Rename .pi to .feynman, rename citation agent to verifier, add website, skills, and docs

- Rename project config dir from .pi/ to .feynman/ (Pi supports this via piConfig.configDir)
- Rename citation agent to verifier across all prompts, agents, skills, and docs
- Add website with homepage and 24 doc pages (Astro + Tailwind)
- Add skills for all workflows (deep-research, lit, review, audit, replicate, compare, draft, autoresearch, watch, jobs, session-log, agentcomputer)
- Add Pi-native prompt frontmatter (args, section, topLevelCli) and read at runtime
- Remove sync-docs generation layer — docs are standalone
- Remove metadata/prompts.mjs and metadata/packages.mjs — not needed at runtime
- Rewrite README and homepage copy
- Add environment selection to /replicate before executing
- Add prompts/delegate.md and AGENTS.md

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Advait Paliwal
2026-03-23 17:35:35 -07:00
parent 406d50b3ff
commit f5570b4e5a
98 changed files with 9886 additions and 298 deletions

View File

@@ -128,8 +128,8 @@ export function syncBundledAssets(appRoot: string, agentDir: string): BootstrapS
skipped: [],
};
syncManagedFiles(resolve(appRoot, ".pi", "themes"), resolve(agentDir, "themes"), state, result);
syncManagedFiles(resolve(appRoot, ".pi", "agents"), resolve(agentDir, "agents"), state, result);
syncManagedFiles(resolve(appRoot, ".feynman", "themes"), resolve(agentDir, "themes"), state, result);
syncManagedFiles(resolve(appRoot, ".feynman", "agents"), resolve(agentDir, "agents"), state, result);
writeBootstrapState(statePath, state);
return result;

View File

@@ -28,23 +28,27 @@ import { runDoctor, runStatus } from "./setup/doctor.js";
import { setupPreviewDependencies } from "./setup/preview.js";
import { runSetup } from "./setup/setup.js";
import { printInfo, printPanel, printSection } from "./ui/terminal.js";
import {
cliCommandSections,
formatCliWorkflowUsage,
legacyFlags,
readPromptSpecs,
topLevelCommandNames,
} from "../metadata/commands.mjs";
const TOP_LEVEL_COMMANDS = new Set(["alpha", "chat", "doctor", "help", "model", "search", "setup", "status", "update"]);
const RESEARCH_WORKFLOW_COMMANDS = new Set([
"audit",
"autoresearch",
"compare",
"deepresearch",
"draft",
"jobs",
"lit",
"log",
"replicate",
"review",
"watch",
]);
const TOP_LEVEL_COMMANDS = new Set(topLevelCommandNames);
function printHelpLine(usage: string, description: string): void {
const width = 30;
const padding = Math.max(1, width - usage.length);
printInfo(`${usage}${" ".repeat(padding)}${description}`);
}
function printHelp(appRoot: string): void {
const workflowCommands = readPromptSpecs(appRoot).filter(
(command) => command.section === "Research Workflows" && command.topLevelCli,
);
function printHelp(): void {
printPanel("Feynman", [
"Research-first agent shell built on Pi.",
"Use `feynman setup` first if this is a new machine.",
@@ -58,39 +62,21 @@ function printHelp(): void {
printInfo("feynman search status");
printSection("Commands");
printInfo("feynman chat [prompt] Start chat explicitly, optionally with an initial prompt");
printInfo("feynman setup Run the guided setup");
printInfo("feynman doctor Diagnose config, auth, Pi runtime, and preview deps");
printInfo("feynman status Show the current setup summary");
printInfo("feynman model list Show available models in auth storage");
printInfo("feynman model login [id] Login to a Pi OAuth model provider");
printInfo("feynman model logout [id] Logout from a Pi OAuth model provider");
printInfo("feynman model set <spec> Set the default model");
printInfo("feynman update [package] Update installed packages (or a specific one)");
printInfo("feynman search status Show Pi web-access status and config path");
printInfo("feynman alpha login|logout|status");
for (const section of cliCommandSections) {
for (const command of section.commands) {
printHelpLine(command.usage, command.description);
}
}
printSection("Research Workflows");
printInfo("feynman deepresearch <topic> Start a thorough source-heavy investigation");
printInfo("feynman lit <topic> Start the literature-review workflow");
printInfo("feynman review <artifact> Start the peer-review workflow");
printInfo("feynman audit <item> Start the paper/code audit workflow");
printInfo("feynman replicate <target> Start the replication workflow");
printInfo("feynman draft <topic> Start the paper-style draft workflow");
printInfo("feynman compare <topic> Start the source-comparison workflow");
printInfo("feynman watch <topic> Start the recurring research watch workflow");
for (const command of workflowCommands) {
printHelpLine(formatCliWorkflowUsage(command), command.description);
}
printSection("Legacy Flags");
printInfo('--prompt "<text>" Run one prompt and exit');
printInfo("--alpha-login Sign in to alphaXiv and exit");
printInfo("--alpha-logout Clear alphaXiv auth and exit");
printInfo("--alpha-status Show alphaXiv auth status and exit");
printInfo("--model provider:model Force a specific model");
printInfo("--thinking level off | minimal | low | medium | high | xhigh");
printInfo("--cwd /path/to/workdir Working directory for tools");
printInfo("--session-dir /path Session storage directory");
printInfo("--doctor Alias for `feynman doctor`");
printInfo("--setup-preview Alias for `feynman setup preview`");
for (const flag of legacyFlags) {
printHelpLine(flag.usage, flag.description);
}
printSection("REPL");
printInfo("Inside the REPL, slash workflows come from the live prompt-template and extension command set.");
@@ -201,6 +187,7 @@ export function resolveInitialPrompt(
command: string | undefined,
rest: string[],
oneShotPrompt: string | undefined,
workflowCommands: Set<string>,
): string | undefined {
if (oneShotPrompt) {
return oneShotPrompt;
@@ -211,7 +198,7 @@ export function resolveInitialPrompt(
if (command === "chat") {
return rest.length > 0 ? rest.join(" ") : undefined;
}
if (RESEARCH_WORKFLOW_COMMANDS.has(command)) {
if (workflowCommands.has(command)) {
return [`/${command}`, ...rest].join(" ").trim();
}
if (!TOP_LEVEL_COMMANDS.has(command)) {
@@ -224,7 +211,7 @@ export async function main(): Promise<void> {
const here = dirname(fileURLToPath(import.meta.url));
const appRoot = resolve(here, "..");
const feynmanVersion = loadPackageVersion(appRoot).version;
const bundledSettingsPath = resolve(appRoot, ".pi", "settings.json");
const bundledSettingsPath = resolve(appRoot, ".feynman", "settings.json");
const feynmanHome = getFeynmanHome();
const feynmanAgentDir = getFeynmanAgentDir(feynmanHome);
@@ -251,7 +238,7 @@ export async function main(): Promise<void> {
});
if (values.help) {
printHelp();
printHelp(appRoot);
return;
}
@@ -297,7 +284,7 @@ export async function main(): Promise<void> {
const [command, ...rest] = positionals;
if (command === "help") {
printHelp();
printHelp(appRoot);
return;
}
@@ -374,6 +361,6 @@ export async function main(): Promise<void> {
thinkingLevel,
explicitModelSpec,
oneShotPrompt: values.prompt,
initialPrompt: resolveInitialPrompt(command, rest, values.prompt),
initialPrompt: resolveInitialPrompt(command, rest, values.prompt, new Set(readPromptSpecs(appRoot).filter((s) => s.topLevelCli).map((s) => s.name))),
});
}

View File

@@ -27,8 +27,8 @@ export function resolvePiPaths(appRoot: string) {
promisePolyfillPath: resolve(appRoot, "dist", "system", "promise-polyfill.js"),
researchToolsPath: resolve(appRoot, "extensions", "research-tools.ts"),
promptTemplatePath: resolve(appRoot, "prompts"),
systemPromptPath: resolve(appRoot, ".pi", "SYSTEM.md"),
piWorkspaceNodeModulesPath: resolve(appRoot, ".pi", "npm", "node_modules"),
systemPromptPath: resolve(appRoot, ".feynman", "SYSTEM.md"),
piWorkspaceNodeModulesPath: resolve(appRoot, ".feynman", "npm", "node_modules"),
};
}

View File

@@ -24,7 +24,7 @@ export type PiWebAccessStatus = {
};
export function getPiWebSearchConfigPath(home = process.env.HOME ?? homedir()): string {
return resolve(home, ".pi", "web-search.json");
return resolve(home, ".feynman", "web-search.json");
}
function normalizeProvider(value: unknown): PiWebSearchProvider | undefined {