@companion-ai/feynman 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/.env.example +8 -0
  2. package/.feynman/SYSTEM.md +62 -0
  3. package/.feynman/agents/researcher.md +63 -0
  4. package/.feynman/agents/reviewer.md +84 -0
  5. package/.feynman/agents/verifier.md +38 -0
  6. package/.feynman/agents/writer.md +51 -0
  7. package/.feynman/settings.json +20 -0
  8. package/.feynman/themes/feynman.json +85 -0
  9. package/AGENTS.md +53 -0
  10. package/README.md +99 -0
  11. package/bin/feynman.js +2 -0
  12. package/dist/bootstrap/sync.js +98 -0
  13. package/dist/cli.js +297 -0
  14. package/dist/config/commands.js +71 -0
  15. package/dist/config/feynman-config.js +42 -0
  16. package/dist/config/paths.js +32 -0
  17. package/dist/feynman-prompt.js +63 -0
  18. package/dist/index.js +5 -0
  19. package/dist/model/catalog.js +238 -0
  20. package/dist/model/commands.js +165 -0
  21. package/dist/pi/launch.js +31 -0
  22. package/dist/pi/runtime.js +70 -0
  23. package/dist/pi/settings.js +101 -0
  24. package/dist/pi/web-access.js +74 -0
  25. package/dist/search/commands.js +12 -0
  26. package/dist/setup/doctor.js +126 -0
  27. package/dist/setup/preview.js +20 -0
  28. package/dist/setup/prompts.js +29 -0
  29. package/dist/setup/setup.js +119 -0
  30. package/dist/system/executables.js +38 -0
  31. package/dist/system/promise-polyfill.js +12 -0
  32. package/dist/ui/terminal.js +53 -0
  33. package/dist/web-search.js +1 -0
  34. package/extensions/research-tools/alpha.ts +212 -0
  35. package/extensions/research-tools/header.ts +379 -0
  36. package/extensions/research-tools/help.ts +93 -0
  37. package/extensions/research-tools/preview.ts +233 -0
  38. package/extensions/research-tools/project.ts +116 -0
  39. package/extensions/research-tools/session-search.ts +223 -0
  40. package/extensions/research-tools/shared.ts +46 -0
  41. package/extensions/research-tools.ts +25 -0
  42. package/metadata/commands.d.mts +46 -0
  43. package/metadata/commands.mjs +133 -0
  44. package/package.json +71 -0
  45. package/prompts/audit.md +15 -0
  46. package/prompts/autoresearch.md +63 -0
  47. package/prompts/compare.md +16 -0
  48. package/prompts/deepresearch.md +167 -0
  49. package/prompts/delegate.md +21 -0
  50. package/prompts/draft.md +16 -0
  51. package/prompts/jobs.md +16 -0
  52. package/prompts/lit.md +16 -0
  53. package/prompts/log.md +14 -0
  54. package/prompts/replicate.md +22 -0
  55. package/prompts/review.md +15 -0
  56. package/prompts/watch.md +14 -0
  57. package/scripts/patch-embedded-pi.mjs +319 -0
  58. package/skills/agentcomputer/SKILL.md +108 -0
  59. package/skills/agentcomputer/references/acp-flow.md +23 -0
  60. package/skills/agentcomputer/references/cli-cheatsheet.md +68 -0
  61. package/skills/autoresearch/SKILL.md +12 -0
  62. package/skills/deep-research/SKILL.md +12 -0
  63. package/skills/docker/SKILL.md +84 -0
  64. package/skills/jobs/SKILL.md +10 -0
  65. package/skills/literature-review/SKILL.md +12 -0
  66. package/skills/paper-code-audit/SKILL.md +12 -0
  67. package/skills/paper-writing/SKILL.md +12 -0
  68. package/skills/peer-review/SKILL.md +12 -0
  69. package/skills/replication/SKILL.md +14 -0
  70. package/skills/session-log/SKILL.md +10 -0
  71. package/skills/source-comparison/SKILL.md +12 -0
  72. package/skills/watch/SKILL.md +12 -0
@@ -0,0 +1,319 @@
1
+ import { spawnSync } from "node:child_process";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { dirname, resolve } from "node:path";
4
+ import { fileURLToPath } from "node:url";
5
+
6
+ const here = dirname(fileURLToPath(import.meta.url));
7
+ const appRoot = resolve(here, "..");
8
+ const piPackageRoot = resolve(appRoot, "node_modules", "@mariozechner", "pi-coding-agent");
9
+ const packageJsonPath = resolve(piPackageRoot, "package.json");
10
+ const cliPath = resolve(piPackageRoot, "dist", "cli.js");
11
+ const bunCliPath = resolve(piPackageRoot, "dist", "bun", "cli.js");
12
+ const interactiveModePath = resolve(piPackageRoot, "dist", "modes", "interactive", "interactive-mode.js");
13
+ const interactiveThemePath = resolve(piPackageRoot, "dist", "modes", "interactive", "theme", "theme.js");
14
+ const piTuiRoot = resolve(appRoot, "node_modules", "@mariozechner", "pi-tui");
15
+ const editorPath = resolve(piTuiRoot, "dist", "components", "editor.js");
16
+ const workspaceRoot = resolve(appRoot, ".feynman", "npm", "node_modules");
17
+ const webAccessPath = resolve(workspaceRoot, "pi-web-access", "index.ts");
18
+ const sessionSearchIndexerPath = resolve(
19
+ workspaceRoot,
20
+ "@kaiserlich-dev",
21
+ "pi-session-search",
22
+ "extensions",
23
+ "indexer.ts",
24
+ );
25
+ const piMemoryPath = resolve(workspaceRoot, "@samfp", "pi-memory", "src", "index.ts");
26
+ const settingsPath = resolve(appRoot, ".feynman", "settings.json");
27
+ const workspaceDir = resolve(appRoot, ".feynman", "npm");
28
+ const workspacePackageJsonPath = resolve(workspaceDir, "package.json");
29
+
30
+ function ensurePackageWorkspace() {
31
+ if (!existsSync(settingsPath)) {
32
+ return;
33
+ }
34
+
35
+ const settings = JSON.parse(readFileSync(settingsPath, "utf8"));
36
+ const packageSpecs = Array.isArray(settings.packages)
37
+ ? settings.packages
38
+ .filter((value) => typeof value === "string" && value.startsWith("npm:"))
39
+ .map((value) => value.slice(4))
40
+ : [];
41
+
42
+ if (packageSpecs.length === 0) {
43
+ return;
44
+ }
45
+
46
+ mkdirSync(workspaceDir, { recursive: true });
47
+
48
+ writeFileSync(
49
+ workspacePackageJsonPath,
50
+ JSON.stringify(
51
+ {
52
+ name: "pi-extensions",
53
+ private: true,
54
+ dependencies: Object.fromEntries(packageSpecs.map((spec) => [spec, "latest"])),
55
+ },
56
+ null,
57
+ 2,
58
+ ) + "\n",
59
+ "utf8",
60
+ );
61
+
62
+ const npmExec = process.env.npm_execpath;
63
+ const install = npmExec
64
+ ? spawnSync(process.execPath, [npmExec, "install", "--prefix", workspaceDir, ...packageSpecs], {
65
+ stdio: "inherit",
66
+ })
67
+ : spawnSync("npm", ["install", "--prefix", workspaceDir, ...packageSpecs], {
68
+ stdio: "inherit",
69
+ });
70
+
71
+ if (install.status !== 0) {
72
+ console.warn("[feynman] warning: failed to preinstall default Pi packages into .feynman/npm");
73
+ }
74
+ }
75
+
76
+ ensurePackageWorkspace();
77
+
78
+ if (existsSync(packageJsonPath)) {
79
+ const pkg = JSON.parse(readFileSync(packageJsonPath, "utf8"));
80
+ if (pkg.piConfig?.name !== "feynman" || pkg.piConfig?.configDir !== ".feynman") {
81
+ pkg.piConfig = {
82
+ ...(pkg.piConfig || {}),
83
+ name: "feynman",
84
+ configDir: ".feynman",
85
+ };
86
+ writeFileSync(packageJsonPath, JSON.stringify(pkg, null, "\t") + "\n", "utf8");
87
+ }
88
+ }
89
+
90
+ for (const entryPath of [cliPath, bunCliPath]) {
91
+ if (!existsSync(entryPath)) {
92
+ continue;
93
+ }
94
+
95
+ const cliSource = readFileSync(entryPath, "utf8");
96
+ if (cliSource.includes('process.title = "pi";')) {
97
+ writeFileSync(entryPath, cliSource.replace('process.title = "pi";', 'process.title = "feynman";'), "utf8");
98
+ }
99
+ }
100
+
101
+ if (existsSync(interactiveModePath)) {
102
+ const interactiveModeSource = readFileSync(interactiveModePath, "utf8");
103
+ if (interactiveModeSource.includes("`π - ${sessionName} - ${cwdBasename}`")) {
104
+ writeFileSync(
105
+ interactiveModePath,
106
+ interactiveModeSource
107
+ .replace("`π - ${sessionName} - ${cwdBasename}`", "`feynman - ${sessionName} - ${cwdBasename}`")
108
+ .replace("`π - ${cwdBasename}`", "`feynman - ${cwdBasename}`"),
109
+ "utf8",
110
+ );
111
+ }
112
+ }
113
+
114
+ if (existsSync(interactiveThemePath)) {
115
+ let themeSource = readFileSync(interactiveThemePath, "utf8");
116
+ const desiredGetEditorTheme = [
117
+ "export function getEditorTheme() {",
118
+ " return {",
119
+ ' borderColor: (text) => " ".repeat(text.length),',
120
+ ' bgColor: (text) => theme.bg("userMessageBg", text),',
121
+ ' placeholderText: "Type your message or /help for commands",',
122
+ ' placeholder: (text) => theme.fg("dim", text),',
123
+ " selectList: getSelectListTheme(),",
124
+ " };",
125
+ "}",
126
+ ].join("\n");
127
+ themeSource = themeSource.replace(
128
+ /export function getEditorTheme\(\) \{[\s\S]*?\n\}\nexport function getSettingsListTheme\(\) \{/m,
129
+ `${desiredGetEditorTheme}\nexport function getSettingsListTheme() {`,
130
+ );
131
+ writeFileSync(interactiveThemePath, themeSource, "utf8");
132
+ }
133
+
134
+ if (existsSync(editorPath)) {
135
+ let editorSource = readFileSync(editorPath, "utf8");
136
+ const importOriginal =
137
+ 'import { getSegmenter, isPunctuationChar, isWhitespaceChar, truncateToWidth, visibleWidth } from "../utils.js";';
138
+ const importReplacement =
139
+ 'import { applyBackgroundToLine, getSegmenter, isPunctuationChar, isWhitespaceChar, truncateToWidth, visibleWidth } from "../utils.js";';
140
+ if (editorSource.includes(importOriginal)) {
141
+ editorSource = editorSource.replace(importOriginal, importReplacement);
142
+ }
143
+ const desiredRender = [
144
+ " render(width) {",
145
+ " const maxPadding = Math.max(0, Math.floor((width - 1) / 2));",
146
+ " const paddingX = Math.min(this.paddingX, maxPadding);",
147
+ " const contentWidth = Math.max(1, width - paddingX * 2);",
148
+ " // Layout width: with padding the cursor can overflow into it,",
149
+ " // without padding we reserve 1 column for the cursor.",
150
+ " const layoutWidth = Math.max(1, contentWidth - (paddingX ? 0 : 1));",
151
+ " // Store for cursor navigation (must match wrapping width)",
152
+ " this.lastWidth = layoutWidth;",
153
+ ' const horizontal = this.borderColor("─");',
154
+ " const bgColor = this.theme.bgColor;",
155
+ " // Layout the text",
156
+ " const layoutLines = this.layoutText(layoutWidth);",
157
+ " // Calculate max visible lines: 30% of terminal height, minimum 5 lines",
158
+ " const terminalRows = this.tui.terminal.rows;",
159
+ " const maxVisibleLines = Math.max(5, Math.floor(terminalRows * 0.3));",
160
+ " // Find the cursor line index in layoutLines",
161
+ " let cursorLineIndex = layoutLines.findIndex((line) => line.hasCursor);",
162
+ " if (cursorLineIndex === -1)",
163
+ " cursorLineIndex = 0;",
164
+ " // Adjust scroll offset to keep cursor visible",
165
+ " if (cursorLineIndex < this.scrollOffset) {",
166
+ " this.scrollOffset = cursorLineIndex;",
167
+ " }",
168
+ " else if (cursorLineIndex >= this.scrollOffset + maxVisibleLines) {",
169
+ " this.scrollOffset = cursorLineIndex - maxVisibleLines + 1;",
170
+ " }",
171
+ " // Clamp scroll offset to valid range",
172
+ " const maxScrollOffset = Math.max(0, layoutLines.length - maxVisibleLines);",
173
+ " this.scrollOffset = Math.max(0, Math.min(this.scrollOffset, maxScrollOffset));",
174
+ " // Get visible lines slice",
175
+ " const visibleLines = layoutLines.slice(this.scrollOffset, this.scrollOffset + maxVisibleLines);",
176
+ " const result = [];",
177
+ ' const leftPadding = " ".repeat(paddingX);',
178
+ " const rightPadding = leftPadding;",
179
+ " const renderBorderLine = (indicator) => {",
180
+ " const remaining = width - visibleWidth(indicator);",
181
+ " if (remaining >= 0) {",
182
+ ' return this.borderColor(indicator + "─".repeat(remaining));',
183
+ " }",
184
+ " return this.borderColor(truncateToWidth(indicator, width));",
185
+ " };",
186
+ " // Render top padding row. When background fill is active, mimic the user-message block",
187
+ " // instead of the stock editor chrome.",
188
+ " if (bgColor) {",
189
+ " if (this.scrollOffset > 0) {",
190
+ " const indicator = ` ↑ ${this.scrollOffset} more`;",
191
+ " result.push(applyBackgroundToLine(indicator, width, bgColor));",
192
+ " }",
193
+ " else {",
194
+ ' result.push(applyBackgroundToLine("", width, bgColor));',
195
+ " }",
196
+ " }",
197
+ " else if (this.scrollOffset > 0) {",
198
+ " const indicator = `─── ↑ ${this.scrollOffset} more `;",
199
+ " result.push(renderBorderLine(indicator));",
200
+ " }",
201
+ " else {",
202
+ " result.push(horizontal.repeat(width));",
203
+ " }",
204
+ " // Render each visible layout line",
205
+ " // Emit hardware cursor marker only when focused and not showing autocomplete",
206
+ " const emitCursorMarker = this.focused && !this.autocompleteState;",
207
+ " const showPlaceholder = this.state.lines.length === 1 &&",
208
+ ' this.state.lines[0] === "" &&',
209
+ ' typeof this.theme.placeholderText === "string" &&',
210
+ " this.theme.placeholderText.length > 0;",
211
+ " for (let visibleIndex = 0; visibleIndex < visibleLines.length; visibleIndex++) {",
212
+ " const layoutLine = visibleLines[visibleIndex];",
213
+ " const isFirstLayoutLine = this.scrollOffset + visibleIndex === 0;",
214
+ " let displayText = layoutLine.text;",
215
+ " let lineVisibleWidth = visibleWidth(layoutLine.text);",
216
+ " const isPlaceholderLine = showPlaceholder && isFirstLayoutLine;",
217
+ " if (isPlaceholderLine) {",
218
+ " const marker = emitCursorMarker ? CURSOR_MARKER : \"\";",
219
+ " const rawPlaceholder = this.theme.placeholderText;",
220
+ ' const styledPlaceholder = typeof this.theme.placeholder === "function"',
221
+ " ? this.theme.placeholder(rawPlaceholder)",
222
+ " : rawPlaceholder;",
223
+ " displayText = marker + styledPlaceholder;",
224
+ " lineVisibleWidth = visibleWidth(rawPlaceholder);",
225
+ " }",
226
+ " else if (layoutLine.hasCursor && layoutLine.cursorPos !== undefined) {",
227
+ ' const marker = emitCursorMarker ? CURSOR_MARKER : "";',
228
+ " const before = displayText.slice(0, layoutLine.cursorPos);",
229
+ " const after = displayText.slice(layoutLine.cursorPos);",
230
+ " displayText = before + marker + after;",
231
+ " }",
232
+ " // Calculate padding based on actual visible width",
233
+ ' const padding = " ".repeat(Math.max(0, contentWidth - lineVisibleWidth));',
234
+ " const renderedLine = `${leftPadding}${displayText}${padding}${rightPadding}`;",
235
+ " result.push(bgColor ? applyBackgroundToLine(renderedLine, width, bgColor) : renderedLine);",
236
+ " }",
237
+ " // Render bottom padding row. When background fill is active, mimic the user-message block",
238
+ " // instead of the stock editor chrome.",
239
+ " const linesBelow = layoutLines.length - (this.scrollOffset + visibleLines.length);",
240
+ " if (bgColor) {",
241
+ " if (linesBelow > 0) {",
242
+ " const indicator = ` ↓ ${linesBelow} more`;",
243
+ " result.push(applyBackgroundToLine(indicator, width, bgColor));",
244
+ " }",
245
+ " else {",
246
+ ' result.push(applyBackgroundToLine("", width, bgColor));',
247
+ " }",
248
+ " }",
249
+ " else if (linesBelow > 0) {",
250
+ " const indicator = `─── ↓ ${linesBelow} more `;",
251
+ " const bottomLine = renderBorderLine(indicator);",
252
+ " result.push(bottomLine);",
253
+ " }",
254
+ " else {",
255
+ " const bottomLine = horizontal.repeat(width);",
256
+ " result.push(bottomLine);",
257
+ " }",
258
+ " // Add autocomplete list if active",
259
+ " if (this.autocompleteState && this.autocompleteList) {",
260
+ " const autocompleteResult = this.autocompleteList.render(contentWidth);",
261
+ " for (const line of autocompleteResult) {",
262
+ " const lineWidth = visibleWidth(line);",
263
+ ' const linePadding = " ".repeat(Math.max(0, contentWidth - lineWidth));',
264
+ " const autocompleteLine = `${leftPadding}${line}${linePadding}${rightPadding}`;",
265
+ " result.push(bgColor ? applyBackgroundToLine(autocompleteLine, width, bgColor) : autocompleteLine);",
266
+ " }",
267
+ " }",
268
+ " return result;",
269
+ " }",
270
+ ].join("\n");
271
+ editorSource = editorSource.replace(
272
+ / render\(width\) \{[\s\S]*?\n handleInput\(data\) \{/m,
273
+ `${desiredRender}\n handleInput(data) {`,
274
+ );
275
+ writeFileSync(editorPath, editorSource, "utf8");
276
+ }
277
+
278
+ if (existsSync(webAccessPath)) {
279
+ const source = readFileSync(webAccessPath, "utf8");
280
+ if (source.includes('pi.registerCommand("search",')) {
281
+ writeFileSync(
282
+ webAccessPath,
283
+ source.replace('pi.registerCommand("search",', 'pi.registerCommand("web-results",'),
284
+ "utf8",
285
+ );
286
+ }
287
+ }
288
+
289
+ if (existsSync(sessionSearchIndexerPath)) {
290
+ const source = readFileSync(sessionSearchIndexerPath, "utf8");
291
+ const original = 'const sessionsDir = path.join(os.homedir(), ".pi", "agent", "sessions");';
292
+ const replacement =
293
+ 'const sessionsDir = process.env.FEYNMAN_SESSION_DIR ?? process.env.PI_SESSION_DIR ?? path.join(os.homedir(), ".pi", "agent", "sessions");';
294
+ if (source.includes(original)) {
295
+ writeFileSync(sessionSearchIndexerPath, source.replace(original, replacement), "utf8");
296
+ }
297
+ }
298
+
299
+ if (existsSync(piMemoryPath)) {
300
+ let source = readFileSync(piMemoryPath, "utf8");
301
+ const memoryOriginal = 'const MEMORY_DIR = join(homedir(), ".pi", "memory");';
302
+ const memoryReplacement =
303
+ 'const MEMORY_DIR = process.env.FEYNMAN_MEMORY_DIR ?? process.env.PI_MEMORY_DIR ?? join(homedir(), ".pi", "memory");';
304
+ if (source.includes(memoryOriginal)) {
305
+ source = source.replace(memoryOriginal, memoryReplacement);
306
+ }
307
+ const execOriginal = 'const result = await pi.exec("pi", ["-p", prompt, "--print"], {';
308
+ const execReplacement = [
309
+ 'const execBinary = process.env.FEYNMAN_NODE_EXECUTABLE || process.env.FEYNMAN_EXECUTABLE || "pi";',
310
+ ' const execArgs = process.env.FEYNMAN_BIN_PATH',
311
+ ' ? [process.env.FEYNMAN_BIN_PATH, "--prompt", prompt]',
312
+ ' : ["-p", prompt, "--print"];',
313
+ ' const result = await pi.exec(execBinary, execArgs, {',
314
+ ].join("\n");
315
+ if (source.includes(execOriginal)) {
316
+ source = source.replace(execOriginal, execReplacement);
317
+ }
318
+ writeFileSync(piMemoryPath, source, "utf8");
319
+ }
@@ -0,0 +1,108 @@
1
+ ---
2
+ name: agentcomputer
3
+ description: Delegate research tasks to remote Agent Computer machines for cloud execution. Manages machine discovery, remote agent sessions, task delegation, progress monitoring, result retrieval, and ACP bridging via the aicomputer CLI.
4
+ allowed-tools: Bash(npm:*), Bash(npx aicomputer@latest:*), Bash(aicomputer:*), Bash(computer:*)
5
+ ---
6
+
7
+ # Agent Computer
8
+
9
+ Use Agent Computer to run Feynman research workflows on remote cloud machines when local compute is insufficient or when tasks should run unattended.
10
+
11
+ ## When to use
12
+
13
+ - A research task needs GPU, large memory, or long-running compute
14
+ - `/autoresearch` or `/deepresearch` should run unattended in the cloud
15
+ - The user explicitly asks to delegate work to a remote machine
16
+ - An experiment loop would take hours and should not block the local session
17
+
18
+ ## Prerequisites
19
+
20
+ The `aicomputer` CLI must be installed and authenticated:
21
+
22
+ ```bash
23
+ if command -v computer >/dev/null 2>&1; then
24
+ COMPUTER=computer
25
+ elif command -v aicomputer >/dev/null 2>&1; then
26
+ COMPUTER=aicomputer
27
+ else
28
+ npm install -g aicomputer
29
+ COMPUTER=computer
30
+ fi
31
+ $COMPUTER whoami || $COMPUTER login
32
+ ```
33
+
34
+ ## Fleet control
35
+
36
+ ### Discover machines and agents
37
+
38
+ ```bash
39
+ $COMPUTER ls --json
40
+ $COMPUTER agent agents <machine> --json
41
+ ```
42
+
43
+ ### Sessions
44
+
45
+ Create, reuse, and manage named sessions on a machine:
46
+
47
+ ```bash
48
+ $COMPUTER agent sessions new <machine> --agent claude --name research --json
49
+ $COMPUTER agent sessions list <machine> --json
50
+ $COMPUTER agent status <machine> --session <session_id> --json
51
+ ```
52
+
53
+ ### Prompting and monitoring
54
+
55
+ ```bash
56
+ $COMPUTER agent prompt <machine> "<task>" --agent claude --name research
57
+ $COMPUTER agent watch <machine> --session <session_id>
58
+ ```
59
+
60
+ ### Stopping and cleanup
61
+
62
+ ```bash
63
+ $COMPUTER agent cancel <machine> --session <session_id> --json
64
+ $COMPUTER agent interrupt <machine> --session <session_id> --json
65
+ $COMPUTER agent close <machine> --session <session_id>
66
+ ```
67
+
68
+ ## Research delegation workflow
69
+
70
+ 1. Pick a machine: `$COMPUTER ls --json`
71
+ 2. Create a session: `$COMPUTER agent sessions new <machine> --agent claude --name research --json`
72
+ 3. Send a self-contained research prompt:
73
+
74
+ ```bash
75
+ $COMPUTER agent prompt <machine> \
76
+ "Run a deep research workflow on <topic>. Write all outputs to /workspace/outputs/. When done, write a summary to /workspace/outputs/summary.md." \
77
+ --agent claude --name research
78
+ ```
79
+
80
+ 4. Monitor: `$COMPUTER agent watch <machine> --session <session_id>`
81
+ 5. Retrieve: `$COMPUTER agent prompt <machine> "cat /workspace/outputs/summary.md" --session <session_id>`
82
+ 6. Clean up: `$COMPUTER agent close <machine> --session <session_id>`
83
+
84
+ ## ACP bridge
85
+
86
+ Expose a remote machine agent as a local ACP-compatible stdio process:
87
+
88
+ ```bash
89
+ $COMPUTER acp serve <machine> --agent claude --name research
90
+ ```
91
+
92
+ This lets local ACP clients (including Feynman's subagents) talk to a remote agent as if it were local. Keep the bridge process running; reconnect by restarting the command with the same session name.
93
+
94
+ ## Session naming
95
+
96
+ Use short stable names that match the task:
97
+
98
+ - `research` — general research delegation
99
+ - `experiment` — autoresearch loops
100
+ - `review` — verification passes
101
+ - `literature` — literature sweeps
102
+
103
+ Reuse the same name when continuing the same line of work.
104
+
105
+ ## References
106
+
107
+ - [CLI cheatsheet](references/cli-cheatsheet.md) — full command reference
108
+ - [ACP flow](references/acp-flow.md) — protocol details for the ACP bridge
@@ -0,0 +1,23 @@
1
+ # ACP Flow
2
+
3
+ The `computer acp serve` bridge makes a remote machine agent look like a local ACP server over stdio.
4
+
5
+ ## Basic shape
6
+
7
+ 1. The local client starts `computer acp serve <machine> --agent <agent> --name <session>`.
8
+ 2. The bridge handles ACP initialization on stdin/stdout.
9
+ 3. The bridge maps ACP session operations onto Agent Computer session APIs.
10
+ 4. Remote session updates are streamed back as ACP `session/update` notifications.
11
+
12
+ ## Good commands
13
+
14
+ ```bash
15
+ computer acp serve my-box --agent claude --name research
16
+ computer acp serve gpu-worker --agent claude --name experiment
17
+ ```
18
+
19
+ ## Recommended client behavior
20
+
21
+ - Reuse a stable session name when reconnecting.
22
+ - Treat the bridge as the single local command for remote-agent interaction.
23
+ - Use the normal `computer agent ...` commands outside ACP when you need manual inspection or cleanup.
@@ -0,0 +1,68 @@
1
+ # CLI Cheatsheet
2
+
3
+ ## Authentication
4
+
5
+ ```bash
6
+ computer whoami
7
+ computer login
8
+ computer claude-login # install Claude credentials on a machine
9
+ computer codex-login # install Codex credentials on a machine
10
+ ```
11
+
12
+ ## Machine discovery
13
+
14
+ ```bash
15
+ computer ls --json
16
+ computer fleet status --json
17
+ ```
18
+
19
+ ## Agent discovery
20
+
21
+ ```bash
22
+ computer agent agents <machine> --json
23
+ ```
24
+
25
+ ## Sessions
26
+
27
+ ```bash
28
+ computer agent sessions list <machine> --json
29
+ computer agent sessions new <machine> --agent claude --name research --json
30
+ computer agent status <machine> --session <session_id> --json
31
+ ```
32
+
33
+ ## Prompting
34
+
35
+ ```bash
36
+ computer agent prompt <machine> "run the experiment" --agent claude --name research
37
+ computer agent prompt <machine> "continue" --session <session_id>
38
+ ```
39
+
40
+ ## Streaming and control
41
+
42
+ ```bash
43
+ computer agent watch <machine> --session <session_id>
44
+ computer agent cancel <machine> --session <session_id> --json
45
+ computer agent interrupt <machine> --session <session_id> --json
46
+ computer agent close <machine> --session <session_id>
47
+ ```
48
+
49
+ ## ACP bridge
50
+
51
+ ```bash
52
+ computer acp serve <machine> --agent claude --name research
53
+ ```
54
+
55
+ ## Machine lifecycle
56
+
57
+ ```bash
58
+ computer create my-box
59
+ computer open my-box
60
+ computer open my-box --terminal
61
+ computer ssh my-box
62
+ ```
63
+
64
+ ## Good defaults
65
+
66
+ - Prefer machine handles over machine ids when both are available.
67
+ - Prefer `--name` for human-meaningful persistent sessions.
68
+ - Prefer `--json` when another program or agent needs to read the result.
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: autoresearch
3
+ description: Autonomous experiment loop that tries ideas, measures results, keeps what works, and discards what doesn't. Use when the user asks to optimize a metric, run an experiment loop, improve performance iteratively, or automate benchmarking.
4
+ ---
5
+
6
+ # Autoresearch
7
+
8
+ Run the `/autoresearch` workflow. Read the prompt template at `prompts/autoresearch.md` for the full procedure.
9
+
10
+ Tools used: `init_experiment`, `run_experiment`, `log_experiment` (from pi-autoresearch)
11
+
12
+ Session files: `autoresearch.md`, `autoresearch.sh`, `autoresearch.jsonl`
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: deep-research
3
+ description: Run a thorough, source-heavy investigation on any topic. Use when the user asks for deep research, a comprehensive analysis, an in-depth report, or a multi-source investigation. Produces a cited research brief with provenance tracking.
4
+ ---
5
+
6
+ # Deep Research
7
+
8
+ Run the `/deepresearch` workflow. Read the prompt template at `prompts/deepresearch.md` for the full procedure.
9
+
10
+ Agents used: `researcher`, `verifier`, `reviewer`
11
+
12
+ Output: cited brief in `outputs/` with `.provenance.md` sidecar.
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: docker
3
+ description: Execute research code inside isolated Docker containers for safe replication, experiments, and benchmarks. Use when the user selects Docker as the execution environment or asks to run code safely, in isolation, or in a sandbox.
4
+ allowed-tools: Bash(docker:*)
5
+ ---
6
+
7
+ # Docker Sandbox
8
+
9
+ Run research code inside Docker containers while Feynman stays on the host. The container gets the project files, runs the commands, and results sync back.
10
+
11
+ ## When to use
12
+
13
+ - User selects "Docker Sandbox" as the execution environment in `/replicate` or `/autoresearch`
14
+ - Running untrusted code from a paper's repository
15
+ - Experiments that install packages or modify system state
16
+ - Any time the user asks to run something "safely" or "isolated"
17
+
18
+ ## How it works
19
+
20
+ 1. Build or pull an appropriate base image for the research code
21
+ 2. Mount the project directory into the container
22
+ 3. Run experiment commands inside the container
23
+ 4. Results write back to the mounted directory
24
+
25
+ ## Running commands in a container
26
+
27
+ For Python research code (most common):
28
+
29
+ ```bash
30
+ docker run --rm -v "$(pwd)":/workspace -w /workspace python:3.11 bash -c "
31
+ pip install -r requirements.txt &&
32
+ python train.py
33
+ "
34
+ ```
35
+
36
+ For projects with a Dockerfile:
37
+
38
+ ```bash
39
+ docker build -t feynman-experiment .
40
+ docker run --rm -v "$(pwd)/results":/workspace/results feynman-experiment
41
+ ```
42
+
43
+ For GPU workloads:
44
+
45
+ ```bash
46
+ docker run --rm --gpus all -v "$(pwd)":/workspace -w /workspace pytorch/pytorch:latest bash -c "
47
+ pip install -r requirements.txt &&
48
+ python train.py
49
+ "
50
+ ```
51
+
52
+ ## Choosing the base image
53
+
54
+ | Research type | Base image |
55
+ | --- | --- |
56
+ | Python ML/DL | `pytorch/pytorch:latest` or `tensorflow/tensorflow:latest-gpu` |
57
+ | Python general | `python:3.11` |
58
+ | Node.js | `node:20` |
59
+ | R / statistics | `rocker/r-ver:4` |
60
+ | Julia | `julia:1.10` |
61
+ | Multi-language | `ubuntu:24.04` with manual installs |
62
+
63
+ ## Persistent containers
64
+
65
+ For iterative experiments (like `/autoresearch`), create a named container instead of `--rm`. Choose a descriptive name based on the experiment:
66
+
67
+ ```bash
68
+ docker create --name <name> -v "$(pwd)":/workspace -w /workspace python:3.11 tail -f /dev/null
69
+ docker start <name>
70
+ docker exec <name> bash -c "pip install -r requirements.txt"
71
+ docker exec <name> bash -c "python train.py"
72
+ ```
73
+
74
+ This preserves installed packages across iterations. Clean up with:
75
+
76
+ ```bash
77
+ docker stop <name> && docker rm <name>
78
+ ```
79
+
80
+ ## Notes
81
+
82
+ - The mounted workspace syncs results back to the host automatically
83
+ - Containers are network-enabled by default — add `--network none` for full isolation
84
+ - For GPU access, Docker must be configured with the NVIDIA Container Toolkit
@@ -0,0 +1,10 @@
1
+ ---
2
+ name: jobs
3
+ description: Inspect active background research work including running processes, scheduled follow-ups, and pending tasks. Use when the user asks what's running, checks on background work, or wants to see scheduled jobs.
4
+ ---
5
+
6
+ # Jobs
7
+
8
+ Run the `/jobs` workflow. Read the prompt template at `prompts/jobs.md` for the full procedure.
9
+
10
+ Shows active `pi-processes`, scheduled `pi-schedule-prompt` entries, and running subagent tasks.
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: literature-review
3
+ description: Run a literature review using paper search and primary-source synthesis. Use when the user asks for a lit review, paper survey, state of the art, or academic landscape summary on a research topic.
4
+ ---
5
+
6
+ # Literature Review
7
+
8
+ Run the `/lit` workflow. Read the prompt template at `prompts/lit.md` for the full procedure.
9
+
10
+ Agents used: `researcher`, `verifier`, `reviewer`
11
+
12
+ Output: literature review in `outputs/` with `.provenance.md` sidecar.
@@ -0,0 +1,12 @@
1
+ ---
2
+ name: paper-code-audit
3
+ description: Compare a paper's claims against its public codebase. Use when the user asks to audit a paper, check code-claim consistency, verify reproducibility of a specific paper, or find mismatches between a paper and its implementation.
4
+ ---
5
+
6
+ # Paper-Code Audit
7
+
8
+ Run the `/audit` workflow. Read the prompt template at `prompts/audit.md` for the full procedure.
9
+
10
+ Agents used: `researcher`, `verifier`
11
+
12
+ Output: audit report in `outputs/`.