@amenophis1er/foreman 0.1.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 (65) hide show
  1. package/DESIGN.md +408 -0
  2. package/LICENSE +15 -0
  3. package/README.md +133 -0
  4. package/bin/foreman.mjs +58 -0
  5. package/package.json +68 -0
  6. package/scripts/prepare.mjs +48 -0
  7. package/skills/director/SKILL.md +65 -0
  8. package/src/anthropic-models.ts +54 -0
  9. package/src/ask.test.ts +88 -0
  10. package/src/ask.ts +95 -0
  11. package/src/attachments.test.ts +33 -0
  12. package/src/attachments.ts +60 -0
  13. package/src/cli.test.ts +27 -0
  14. package/src/cli.ts +297 -0
  15. package/src/codex.test.ts +328 -0
  16. package/src/codex.ts +196 -0
  17. package/src/cost-basis.test.ts +76 -0
  18. package/src/deck.test.ts +402 -0
  19. package/src/deck.ts +892 -0
  20. package/src/fork.test.ts +31 -0
  21. package/src/gateway/ledger.cjs +326 -0
  22. package/src/gateway/ledger.test.ts +255 -0
  23. package/src/gateway/llm-gateway.cjs +1411 -0
  24. package/src/gateway/llm-gateway.test.ts +478 -0
  25. package/src/gateway.test.ts +226 -0
  26. package/src/gateway.ts +309 -0
  27. package/src/instance.ts +124 -0
  28. package/src/models.test.ts +147 -0
  29. package/src/models.ts +158 -0
  30. package/src/notify/commands.test.ts +28 -0
  31. package/src/notify/commands.ts +73 -0
  32. package/src/notify/telegram.ts +259 -0
  33. package/src/notify.test.ts +343 -0
  34. package/src/notify.ts +495 -0
  35. package/src/ollama.test.ts +49 -0
  36. package/src/ollama.ts +49 -0
  37. package/src/openai-prices.test.ts +58 -0
  38. package/src/openai-prices.ts +106 -0
  39. package/src/orchestrator.test.ts +1147 -0
  40. package/src/orchestrator.ts +2325 -0
  41. package/src/planner.test.ts +60 -0
  42. package/src/planner.ts +505 -0
  43. package/src/policy.test.ts +411 -0
  44. package/src/policy.ts +599 -0
  45. package/src/preflight.ts +348 -0
  46. package/src/prices.test.ts +69 -0
  47. package/src/prices.ts +90 -0
  48. package/src/provider.test.ts +366 -0
  49. package/src/provider.ts +502 -0
  50. package/src/secrets.test.ts +143 -0
  51. package/src/secrets.ts +66 -0
  52. package/src/server.ts +1992 -0
  53. package/src/services.test.ts +53 -0
  54. package/src/services.ts +102 -0
  55. package/src/sse-events.test.ts +83 -0
  56. package/src/store.test.ts +119 -0
  57. package/src/store.ts +346 -0
  58. package/src/tailscale.test.ts +32 -0
  59. package/src/tailscale.ts +79 -0
  60. package/src/title.ts +138 -0
  61. package/src/types.ts +442 -0
  62. package/ui/dist/assets/index-LAj0Dy9p.css +1 -0
  63. package/ui/dist/assets/index-lcBy-uRZ.js +65 -0
  64. package/ui/dist/favicon.svg +8 -0
  65. package/ui/dist/index.html +14 -0
package/DESIGN.md ADDED
@@ -0,0 +1,408 @@
1
+ # Foreman — design concept
2
+
3
+ > **Working name: Foreman.** A foreman runs a crew on a job site. Here the job
4
+ > site is a folder on your machine, the crew is Claude agents, and you hand it
5
+ > a mission instead of a checklist. Rename freely (alternates: Overseer, Helm,
6
+ > Conductor, Steward, Skipper).
7
+
8
+ **One line:** an autonomous mission runner. You pick a project folder, type a
9
+ mission, and Foreman plans it, spawns Claude agents to do the work in that
10
+ folder, steers them, answers their questions, approves their tools, verifies
11
+ the result, and reports back — from a single UI, with no terminal.
12
+
13
+ Status: **concept only.** No code yet. This document captures the idea and the
14
+ architecture while the lessons from `claude-golden-eye`'s director mode are
15
+ fresh.
16
+
17
+ ---
18
+
19
+ ## 1. Where this comes from
20
+
21
+ Foreman is the standalone, terminal-free evolution of **director mode**, which
22
+ we built and proved inside the `claude-golden-eye` plugin. There, one Claude
23
+ Code *session* (the director) autonomously ran a mission across other Claude
24
+ Code *sessions* (workers), observed and steered through golden-eye's hooks,
25
+ channel, and MCP tools. It works: in a soak test, a single mission prompt
26
+ produced a correct, tested CLI with the human touching nothing.
27
+
28
+ But director mode is bound to Claude Code **running in terminals**. That forces
29
+ two panes (director + worker), a channels research-preview flag on every
30
+ session, and manual session lifecycle. The friction is structural, not a bug.
31
+
32
+ **The pivot:** stop driving terminals. Use the **Claude Agent SDK** — the same
33
+ Claude Code engine, embeddable in an application — so Foreman *is* the program
34
+ that spawns and drives agents, with the UI as the only surface. Everything we
35
+ learned about director↔worker orchestration carries over; only the substrate
36
+ changes (SDK processes instead of terminal sessions).
37
+
38
+ ### What carries over from director mode (hard-won, keep it)
39
+
40
+ - **Plan-first into a tracking doc.** The director always wrote `MISSION.md`
41
+ (mission, DONE-when, budget, checklist, log, decisions) and re-read it every
42
+ wake. The doc — not the context window — is the mission's source of truth, so
43
+ it survives compaction/restart. Keep this verbatim.
44
+ - **The blocked-question protocol.** Terminal question dialogs can't be answered
45
+ remotely, so workers were told: never ask interactively; when you need a
46
+ decision, report "blocked" with the question and end your turn. Foreman keeps
47
+ this shape (the SDK equivalent is a worker signalling the orchestrator), and
48
+ it's cleaner here because the SDK has real permission callbacks.
49
+ - **Verify DONE independently.** The director never trusted a worker's "done" —
50
+ it read the files and ran the tests itself. Non-negotiable.
51
+ - **The escalation contract.** Anything irreversible, out of scope, over
52
+ budget, or looping → escalate to the human, don't power through.
53
+ - **Never let an agent modify its own oversight infrastructure.** A director
54
+ once tried to patch and restart golden-eye's server to unblock itself. Hard
55
+ rule: tooling failure is always an escalation, never a self-repair.
56
+ - **Deterministic loop guards.** The director's own events never woke it;
57
+ action echoes weren't wake events. Any event-driven design needs the same.
58
+
59
+ ---
60
+
61
+ ## 2. Core concept
62
+
63
+ - **Folder-linked.** A Foreman run is bound to one directory on the system. That
64
+ path becomes the `cwd` of every agent it spawns; all work happens there and in
65
+ its subtree. Picking the folder in the UI is the entire "setup."
66
+ - **UI is the I/O surface.** Not a terminal. The UI: pick folder → state mission
67
+ → watch live → answer the few things only a human should → get the result. The
68
+ dashboard we already designed for golden-eye (agent tree, live transcripts,
69
+ plan board, approve/deny cards) is the right starting shape.
70
+ - **Real agents, not headless one-shots.** Each worker is a full Agent-SDK
71
+ agentic loop (tools, edits, bash, MCP, subagents) — the same Claude Code
72
+ behavior, just embedded and streamed to the UI instead of a TTY.
73
+ - **A director drives workers.** The director role from golden-eye becomes an
74
+ orchestration layer (see §4 for the key open decision on where its
75
+ intelligence lives).
76
+
77
+ ---
78
+
79
+ ## 3. How it differs from golden-eye (and why it's a separate product)
80
+
81
+ | | golden-eye (keep as is) | Foreman (new) |
82
+ |---|---|---|
83
+ | What it is | Claude Code **plugin**: observes real terminal sessions | Standalone **app** that runs agents |
84
+ | Substrate | Claude Code CLI in terminals | Claude Agent SDK, embedded |
85
+ | Dependencies | zero runtime deps (a point of pride) | depends on the Agent SDK + tree |
86
+ | Spends tokens? | never — pure observer | yes — it *is* the agent runtime |
87
+ | Auth | none needed | Anthropic **API key** (see §9) |
88
+ | Surface | dashboard observes; terminals drive | dashboard **is** the driver |
89
+ | Lifecycle | humans open/close sessions | Foreman starts/kills/resumes agents |
90
+
91
+ These are different enough to be **two products sharing UI DNA**, not one. The
92
+ recommendation is to keep golden-eye exactly as it is (clean, zero-dep, ships
93
+ as v0.1.0) and grow Foreman independently, reusing dashboard patterns and the
94
+ director's charter wisdom. Do not rewrite golden-eye into this.
95
+
96
+ ---
97
+
98
+ ## 4. Architecture (draft)
99
+
100
+ ```
101
+ ┌─────────────────────────── UI (control plane) ───────────────────────────┐
102
+ │ pick folder · state mission · live transcripts · plan board · │
103
+ │ approve/deny cards · pause/kill · cost meter │
104
+ └───────────────▲───────────────────────────────────┬──────────────────────┘
105
+ │ SSE/ws (stream out) │ HTTP (commands in)
106
+ ┌───────────────┴───────────────────────────────────▼──────────────────────┐
107
+ │ Orchestrator (Node service) │
108
+ │ • owns runs: {folder, mission, budget, status} │
109
+ │ • spawns/streams/kills SDK agents; routes canUseTool → UI cards │
110
+ │ • persists MISSION.md + run state; enforces budgets & guardrails │
111
+ └───────────────┬───────────────────────────────────────────────────────────┘
112
+ │ Agent SDK (query() / ClaudeSDKClient), cwd = the folder
113
+ ┌────────────▼───────────┐ ┌──────────────────────────────┐
114
+ │ Director agent │ ───▶ │ Worker agent(s) │
115
+ │ (strong model, thinking)│ │ (build/edit/test in cwd) │
116
+ │ plans, steers, verifies │ │ report blocked → director │
117
+ └─────────────────────────┘ └──────────────────────────────┘
118
+ ```
119
+
120
+ **SDK grounding (verified against current docs):**
121
+
122
+ - Package `@anthropic-ai/claude-agent-sdk` (TS) / `claude-agent-sdk` (Py);
123
+ entry `query()` returns an async iterator of messages. Multi-turn
124
+ continuity: Python has `ClaudeSDKClient`; TS has **no client class** — it
125
+ uses streaming input (`AsyncIterable<SDKUserMessage>`) plus the
126
+ `resume`/`continue` options. We stream `AssistantMessage` / `UserMessage` /
127
+ `ResultMessage` to the UI.
128
+ - `cwd` option pins the agent to the chosen folder.
129
+ - `canUseTool(toolName, input, ctx)` callback → `Allow(updated_input?)` or
130
+ `Deny(message)` — note deny takes **no `interrupt` flag**; mid-run
131
+ interruption is done via the query/client's own `interrupt()` method.
132
+ This is how UI approve/deny cards work —
133
+ natively, no channels relay. Precedence: hooks → deny rules → ask rules →
134
+ permission mode → allow rules → canUseTool.
135
+ - Permission modes: `default`, `acceptEdits`, `plan`, `dontAsk`, `auto`,
136
+ `bypassPermissions`. Foreman would run workers in `default`/`acceptEdits`
137
+ with a `canUseTool` gate, never blanket `bypassPermissions`.
138
+ - Hooks (`PreToolUse`/`PostToolUse`/`Stop`/`SubagentStop`/…) run **in the
139
+ orchestrator process, no context cost** — perfect for feeding the same
140
+ observability the golden-eye dashboard renders.
141
+ - `mcpServers` option → agents can use MCP tools (`mcp__<server>__<tool>`).
142
+ - Subagents via the `Agent`/`Task` tool; `agents={...}` defines them with
143
+ per-agent model + tool restrictions + `max_turns`.
144
+ - Sessions: capture `session_id` from `ResultMessage`; `resume` / `continue` /
145
+ `fork_session`; persisted under `~/.claude/projects/<cwd>/<id>.jsonl`, or a
146
+ custom `session_store` for our own backend.
147
+
148
+ ### The one decision that shapes everything: where does the director live?
149
+
150
+ - **Option A — Director is an SDK agent too.** Orchestrator spawns a director
151
+ agent (strong model + extended thinking) whose *tools* are "spawn worker",
152
+ "message worker", "answer worker", "read MISSION.md". Workers are separate SDK
153
+ agents (or its subagents). Keeps intelligence in a model, mirrors what we
154
+ proved. Most faithful to director mode.
155
+ - **Option B — Director is orchestrator code calling a model.** The Node
156
+ service holds the loop and calls the model for judgment at each decision
157
+ point. Simpler infra, but drifts back toward "intelligence in the server,"
158
+ which we deliberately rejected in golden-eye.
159
+ - **Option C — No separate director; one agent with subagents.** A single SDK
160
+ agent runs the mission and uses the SDK's own subagents as its crew. Simplest,
161
+ but loses the cross-agent supervision that makes this distinctive — it's
162
+ really just normal delegation with a tracking doc.
163
+
164
+ **Leaning: A.** It preserves the director/worker separation and the
165
+ observability story; the orchestrator stays "dumb pipes + guardrails."
166
+ Workers as separate SDK sessions (not subagents) keep them independently
167
+ observable and resumable, matching golden-eye's model.
168
+
169
+ ### The director's wake loop (the hardest part of Option A — design before spike 2)
170
+
171
+ In golden-eye, the channel and hooks defined *when* the director woke and
172
+ *what* it saw. In Foreman that becomes: how does the director learn a worker
173
+ finished, blocked, or went quiet? Under Option A the orchestrator must inject
174
+ events into the director's streaming input, and every director-mode question
175
+ returns:
176
+
177
+ - **Which events wake it.** Wake granularity drives cost: a strong-model
178
+ director woken on every worker turn burns tokens fast. Default should be
179
+ coarse — worker *blocked*, worker *done*, milestone reached, budget
180
+ threshold, silence timeout — not per-turn.
181
+ - **Echo filtering.** The director's own actions (messages it sent, workers it
182
+ spawned) must never wake it. Same deterministic loop guards as golden-eye.
183
+ - **Turn coalescing.** Events arriving while the director is mid-turn queue
184
+ and coalesce into one wake, never interleave.
185
+
186
+ Also worth naming: the director's tools ("spawn worker", "message worker",
187
+ "answer worker", "read mission doc") are **custom in-process MCP tools** the
188
+ orchestrator implements via `createSdkMcpServer` — a real chunk of the
189
+ phase-2 work.
190
+
191
+ ---
192
+
193
+ ## 5. Mission model
194
+
195
+ Unchanged from director mode. On start, the director writes the mission doc at
196
+ `.foreman/MISSION.md` inside the target folder (gitignored by default —
197
+ polluting a real repo's root with an agent artifact is the wrong default):
198
+
199
+ ```markdown
200
+ # MISSION: <one line>
201
+ DONE WHEN: <verifiable criteria>
202
+ BUDGET: max <N> turns · <$X> · escalate at <T>
203
+ ## Plan
204
+ - [ ] 1. <verifiable milestone>
205
+ ## Log
206
+ ## Decisions
207
+ ```
208
+
209
+ The UI renders this as the plan board and reads it as run state. It is the
210
+ durable record; a Foreman run can be killed and resumed from it. That includes
211
+ **orchestrator crash recovery**: if the Node service dies mid-run, the mission
212
+ doc plus persisted SDK sessions (`sessionStore` + `resume`) are enough to
213
+ reconstruct and continue the run.
214
+
215
+ ---
216
+
217
+ ## 6. Safety & guardrails (first-class, not bolted on)
218
+
219
+ An autonomous agent runtime with shell access and a wallet is a different risk
220
+ class than an observer. Non-negotiables:
221
+
222
+ - **Bounded runs.** `max_turns` and `max_budget_usd` per run (the SDK enforces
223
+ both; `error_max_budget_usd` stops subagents and refuses new spawns). Surface
224
+ a live cost meter (`ResultMessage.total_cost_usd`) and a hard cap in the UI.
225
+ - **`canUseTool` gate, deny-by-default for danger.** Auto-allow in-folder,
226
+ reversible operations; route anything irreversible or out-of-scope to a UI
227
+ approve/deny card; hard-deny known-destructive patterns.
228
+ - **Folder confinement — policy-enforced, not sandboxed.** `cwd` pins where
229
+ the agent works; it does **not** sandbox anything — Bash can write anywhere,
230
+ and `canUseTool` path-inspection of shell commands is best-effort (paths
231
+ hide inside scripts, redirects, `cd`). Policy: auto-allow only clearly
232
+ in-folder writes, route the rest to approval. OS-level sandboxing (or
233
+ containerized workers, see open questions) is the hardening path if
234
+ policy-only proves too leaky.
235
+ - **Escalation contract** (from director mode): irreversible / out-of-scope /
236
+ over-budget / looping → stop and ask the human.
237
+ - **No self-modification of Foreman itself.** The infra rule, carried over.
238
+ - **Pause / kill switch** always available in the UI; the orchestrator
239
+ interrupts a running agent via the SDK's `interrupt()` on the query/client
240
+ (deny responses carry no interrupt flag).
241
+
242
+ ---
243
+
244
+ ## 7. Observability
245
+
246
+ Reuse golden-eye's dashboard patterns wholesale: agent tree, full-height live
247
+ transcripts, plan board, timeline, cost/token meters. Because SDK hooks run in
248
+ the orchestrator process, we get the event stream for free without tailing
249
+ JSONL. This is where Foreman and golden-eye visibly share DNA.
250
+
251
+ ---
252
+
253
+ ## 8. Worker senses: browser tooling & visual verification
254
+
255
+ Workers (and the director) shouldn't have to trust "tests pass" — they should
256
+ be able to *look at* the running app. This is mostly free via `mcpServers`,
257
+ but the choice of tool matters:
258
+
259
+ - **Playwright MCP (`@playwright/mcp`) is the default.** Given to workers via
260
+ `mcpServers`, it launches a **headless, disposable** browser: navigate,
261
+ click, fill forms, read console errors, take screenshots. Agents genuinely
262
+ *see* — the Read tool renders images, so a worker screenshots the page and
263
+ visually inspects the result. The director uses the same to verify DONE
264
+ against the real app, not just the test suite.
265
+ - **Ruled out as defaults:** tools that drive the human's real Chrome
266
+ (claude-in-chrome style — your logged-in sessions and cookies under an
267
+ unattended agent) and full **computer use** (desktop control — hands the
268
+ whole machine to an agent whose story is "confined to a folder"). Keep the
269
+ browser headless and disposable.
270
+ - **Guardrails compose.** Browser MCP tools flow through the same
271
+ `canUseTool` gate as everything else: auto-allow navigation to
272
+ `localhost`, route external URLs to an approval card.
273
+ - **Docker synergy:** a Playwright-enabled base image gives the browser
274
+ story and the isolation story in one artifact (see §12 on containerized
275
+ workers).
276
+
277
+ ---
278
+
279
+ ## 9. Auth & billing (the real gate)
280
+
281
+ > **Superseded in part.** This section predates instance pinning. Foreman now
282
+ > points at an *installed* Claude Code and uses whatever that install is logged
283
+ > into, which is how a personal Foreman rides a subscription without any third
284
+ > party minting tokens. The generalisation of that idea — Codex installs, local
285
+ > Ollama, OpenAI-compatible endpoints — is designed in
286
+ > [docs/provider-model.md](docs/provider-model.md). The last bullet below still
287
+ > governs everything.
288
+
289
+ - **API key only.** SDK apps authenticate via `ANTHROPIC_API_KEY` (or a cloud
290
+ provider: Bedrock/Vertex/Foundry). Anthropic does **not** permit third-party
291
+ SDK apps to offer claude.ai login to end users — so a distributed Foreman
292
+ can't ride users' subscriptions; each install brings its own key. For
293
+ **personal use this is fine** (your key, your machine).
294
+ - **Foreman spends money autonomously.** Every run bills the key. Budgets and
295
+ the cost meter aren't nice-to-haves; they're the safety floor.
296
+
297
+ ---
298
+
299
+ ## 10. Phased build (when we start)
300
+
301
+ > **Status (2026-09-03).** Phases 1–3 are built and verified, plus several
302
+ > items beyond the original plan:
303
+ > phase 1 spike (one worker, SSE transcript, approve/deny) ✅ ·
304
+ > phase 2 director (MISSION.md, spawn/message workers, ask_human, budgets,
305
+ > independent verification) ✅ · phase 3 dashboard (React + design system,
306
+ > agent tree, transcript, plan board) ✅ · persistence (append-only event
307
+ > logs, atomic meta, orphan sweep, history replay) ✅ · **fleet** (multi-
308
+ > project home, zoomable project views, composer, concurrent missions —
309
+ > one per project) ✅ · per-mission model selection (director/workers) ✅ ·
310
+ > resume of interrupted runs via director session restore ✅.
311
+ > Parallel workers already occur naturally (the director issues parallel
312
+ > spawn_worker tool calls); phase 4 below remains for the *management*
313
+ > around them (wake loop, steering, conflict policy).
314
+
315
+ 1. **Spike:** orchestrator spawns ONE SDK worker in a chosen folder, streams its
316
+ transcript to a minimal UI, `canUseTool` → an approve/deny card. Prove the
317
+ substrate end to end.
318
+ 2. **Mission + director (Option A):** director agent plans `MISSION.md`, spawns
319
+ one worker, steers via tools, verifies DONE, respects budgets. This is
320
+ director-mode reborn without terminals.
321
+ 3. **Dashboard parity:** port golden-eye's tree/transcript/plan/timeline views.
322
+ 4. **Multi-worker:** director runs N workers for one mission. N workers
323
+ sharing one `cwd` will trample each other's edits — per-worker git
324
+ worktrees (or serialized write access) is the likely answer.
325
+ 5. **Polish:** pause/resume/kill, run history, cost caps, guardrail tuning.
326
+
327
+ ---
328
+
329
+ ## 11. Non-goals
330
+
331
+ **What Foreman is:** a governance layer — goal doc + budget + policy +
332
+ escalation — around autonomous work, on your own machine, in your own folders.
333
+ Coding was the first capability plugged in; the browser was the second.
334
+
335
+ The boundaries below exist because the alternative to each is a real, working
336
+ product that already occupies that ground. Every one of them is a bet, and
337
+ crossing it does not make Foreman more capable — it makes Foreman a lesser
338
+ copy of something else. They are permanent, not "at least at first".
339
+
340
+ ### The mission is the unit of work
341
+
342
+ - **Conversation produces missions; it never does the work.** The planner is
343
+ read-only — Read, Grep, Glob, and nothing else — permanently. Not "read-only
344
+ until a small edit would be convenient". If it needs doing, it becomes a
345
+ mission the human starts, with a budget and DONE WHEN criteria. The day the
346
+ planner writes a file, Foreman is a chat client with a cost meter.
347
+ - **Not chat-first.** The project view's centre of gravity is the mission and
348
+ its verification, not the transcript. Talking is the cheap step before
349
+ committing, not the product.
350
+ - **No unverified completion.** The director reads the files and runs the
351
+ checks itself. A worker's "done" is evidence, never a result.
352
+
353
+ ### The desk shows the work; it is not a workstation
354
+
355
+ - **No terminal in the UI.** Foreman runs on your machine and you already have
356
+ one. An unrestricted shell in the panel is a hole straight through
357
+ `canUseTool`, which is the entire safety floor.
358
+ - **The deck is diff and artifacts**, not a file manager and not an editor.
359
+ Its job is to show what this mission changed, which is something your editor
360
+ cannot tell you and Foreman can.
361
+
362
+ ### It runs in your real folders, as you
363
+
364
+ - **No containers, no isolation layer.** The agent edits the actual repository.
365
+ That is the bet: policy plus budgets plus an audit trail, rather than a
366
+ sandbox you then have to sync back.
367
+ - **Never mint credentials.** Foreman reads what a first-party CLI already put
368
+ there (`~/.claude`, `~/.codex`); it does not reimplement anyone's OAuth flow
369
+ to obtain tokens itself. See [docs/provider-model.md](docs/provider-model.md).
370
+ - **Not blanket `bypassPermissions`.** Autonomy comes from good `canUseTool`
371
+ policy + budgets, never from removing the floor.
372
+
373
+ ### Single-user, single-purpose
374
+
375
+ - Not a hosted or multi-tenant service.
376
+ - No embeddable widget, no plugin marketplace, no agent-as-a-product surface.
377
+ - Not a replacement for golden-eye — the observer plugin stays its own thing.
378
+
379
+ ---
380
+
381
+ ## 12. Open questions
382
+
383
+ - Director substrate: confirm Option A vs C after the spike.
384
+ - Workers as separate SDK sessions vs subagents (observability & resume vs
385
+ simplicity).
386
+ - How much of golden-eye's server/UI can be literally reused vs forked.
387
+ - Do we ever need a human-in-the-loop "review before commit/push" stage as a
388
+ built-in mission phase?
389
+ - Containerized workers (Docker): worth it for isolation/"full unleash" runs,
390
+ or is policy + budgets enough for personal use?
391
+ - Mission shapes (the super-agent direction): keep the MISSION.md *invariant*
392
+ (goal, success criteria, decisions, log — externalized outside the context
393
+ window; it is what makes runs resumable, auditable, steerable) but free the
394
+ *format*. Proportionality is now in the charter (a 3-line doc is valid for
395
+ a small task); next is shape-awareness — **build** (deliverable, DONE WHEN:
396
+ today's checklist), **research/decide** (deliverable is an answer + a
397
+ recommendation), **assist/monitor** (ongoing goal, "until told to stop",
398
+ per-period budgets, Notifier as heartbeat). The doc skeleton should follow
399
+ the declared shape. Foreman's long-term identity: a governance layer
400
+ (goal doc + budget + policy + escalation) around any capable agent — coding
401
+ was just the first capability plugged in; the browser (below) is the second.
402
+ - Unattended operation: a "Trust this run" pre-grant toggle, plus human
403
+ notification channels (Telegram/Slack/webhook behind a Notifier interface)
404
+ with an availability policy (quiet hours, severity threshold) and an
405
+ escalation ladder — question unanswered for N minutes → notify; still
406
+ unanswered → director takes the conservative path and records it in
407
+ Decisions, or parks the milestone. Cards never expire today; missions
408
+ stall politely until answered.
package/LICENSE ADDED
@@ -0,0 +1,15 @@
1
+ ISC License
2
+
3
+ Copyright (c) 2026 Amen AMOUZOU
4
+
5
+ Permission to use, copy, modify, and/or distribute this software for any
6
+ purpose with or without fee is hereby granted, provided that the above
7
+ copyright notice and this permission notice appear in all copies.
8
+
9
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
10
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
12
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
14
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,133 @@
1
+ # Foreman
2
+
3
+ An autonomous mission runner on the [Claude Agent SDK]. You link project
4
+ folders, write a mission, and Foreman's **director** agent plans it into
5
+ `.foreman/MISSION.md`, delegates implementation to **worker** sessions,
6
+ answers or escalates their questions, verifies the result independently, and
7
+ reports back — all from one browser dashboard, no terminal.
8
+
9
+ Foreman is the standalone evolution of [claude-golden-eye]'s director mode:
10
+ same director/worker doctrine, but the agents are embedded SDK sessions
11
+ driven by this app instead of terminal sessions observed by a plugin.
12
+ (Golden-eye still observes Foreman's agents for free — they are real Claude
13
+ Code sessions.)
14
+
15
+ ## Install
16
+
17
+ Foreman needs Node 20 or newer and a Claude Code login (or an API key) on the
18
+ machine it runs on. Then:
19
+
20
+ ```sh
21
+ npx @amenophis1er/foreman # try it — starts the server, serves http://localhost:4177
22
+ npm install -g @amenophis1er/foreman # keep it — then `foreman` from any shell
23
+ ```
24
+
25
+ ```sh
26
+ foreman doctor # what this machine can run, what is missing, how to fix it
27
+ foreman # start in this terminal (Ctrl+C stops it)
28
+ foreman up # …or in the background; foreman down stops it, foreman status asks
29
+ foreman open # the dashboard, in your browser
30
+ foreman service install # keep it running for good: start at login, restart if it dies
31
+ foreman --help # the rest, and the environment variables
32
+ ```
33
+
34
+ `foreman doctor` prints the same checklist the server prints on start —
35
+ credentials and which account pays, the Claude Code install, Ollama and Codex
36
+ if present, the browser missions will use, the port, Tailscale, the data
37
+ directory — and exits. Nothing blocks unless it says so.
38
+
39
+ **On the move.** If the machine is on a [Tailscale] tailnet, Foreman listens
40
+ on the tailnet address too (never on every interface — there is no login),
41
+ and the links it sends to your phone use the tailnet name. Link the Telegram
42
+ bot in Settings → Notifications and the phone can answer asks, plan and start
43
+ missions, and open what the crew built. `foreman service install` is what
44
+ keeps the server up while the lid is closed.
45
+
46
+ **Platforms.** macOS is where Foreman is developed and tested. Linux is
47
+ verified on Debian with Node 22: install, `foreman doctor`, `foreman up` /
48
+ `status` / `down` and the dashboard all work; `foreman service install` needs
49
+ a systemd user session (a desktop, or `loginctl enable-linger`), and browser
50
+ missions need Google Chrome or `npx playwright install chromium` with
51
+ `FOREMAN_BROWSER=chromium`. Windows is not yet tested natively — use WSL2 for
52
+ now; `foreman service` has no Windows implementation, `foreman up` works.
53
+
54
+ **From a checkout** (contributing):
55
+
56
+ ```sh
57
+ npm ci && npm run setup # dependencies, then the dashboard build
58
+ npm start # serves http://localhost:4177
59
+ npm test · npm run typecheck · npm run dev # tests · both tsconfigs · API + Vite together
60
+ ```
61
+
62
+ [Tailscale]: https://tailscale.com
63
+
64
+ ### Which account pays
65
+
66
+ The SDK spawns your local Claude Code engine, so missions run on whatever that
67
+ install is logged in with — a Claude subscription or an `ANTHROPIC_API_KEY`.
68
+ Both report real per-run cost, so budgets bind either way.
69
+
70
+ A machine can hold more than one login, and `CLAUDE_CONFIG_DIR` inherited from
71
+ the launching shell silently decides which one is used. So startup prints the
72
+ account it resolved to, and the dashboard shows it beside every place a mission
73
+ can be started:
74
+
75
+ ```
76
+ ✓ Credentials Claude subscription — you@example.com · Your Org
77
+ ✓ Claude Code /Users/you/.claude · bundled executable
78
+ ```
79
+
80
+ Pin it explicitly with `FOREMAN_CLAUDE_CONFIG_DIR`, and assert the mode you
81
+ intend with `FOREMAN_AUTH_MODE=api-key|subscription` so an unset key fails at
82
+ startup instead of quietly billing the other account. A project can pin its own
83
+ install, and choose whether it inherits the server's billing or uses that
84
+ install's own login — which is what makes personal and work projects coexist on
85
+ one server.
86
+
87
+ Dev loop: `npm run dev` (API + Vite, proxied to :4177) · `npm test` ·
88
+ `npm run typecheck` · `scripts/dev-restart.sh` (restarts the server only when
89
+ no run, ask or planner turn would be lost).
90
+
91
+ ## Using it
92
+
93
+ 1. **Fleet** (`/`): link a folder as a project. Cards show status, live
94
+ mission cost, and a pulsing **needs you** strip when approvals or
95
+ questions wait.
96
+ 2. **Project view**: write the mission in the composer (say what DONE looks
97
+ like; flag decisions the director must ask you about), set a budget cap
98
+ and optional director/worker models, Start.
99
+ 3. While running: approve/deny tool cards (or **Always** per tool per run),
100
+ answer director questions, watch the plan board tick as MISSION.md
101
+ updates. Interrupt anytime.
102
+ 4. Every run persists (`~/.foreman/`): refresh-proof, browsable history with
103
+ full replay, and a **⟳ Resume** button on interrupted runs that restores
104
+ the director's session and re-verifies state before continuing.
105
+
106
+ Missions in real repositories are fine: `.foreman/` git-ignores itself, the
107
+ repo's `CLAUDE.md` loads into workers, and git operations go through your
108
+ approval cards.
109
+
110
+ ## Architecture
111
+
112
+ ```
113
+ ui/ React 19 + Vite dashboard (design tokens in src/design/)
114
+ src/server.ts HTTP + SSE wiring only
115
+ src/orchestrator.ts MissionRun: director + workers + budget + escalation
116
+ src/policy.ts permission policy (what auto-allows vs. asks you)
117
+ src/store.ts ~/.foreman persistence: append-only event logs, atomic meta
118
+ src/types.ts shared contracts
119
+ ```
120
+
121
+ - **One active mission per project; many across projects.** SSE frames carry
122
+ `{runId, projectId}` envelopes; persisted logs are replayed through the
123
+ same reducer that renders live events.
124
+ - The director's tools (`spawn_worker`, `message_worker`, `ask_human`) are
125
+ in-process MCP tools; worker calls block inside the director's tool call,
126
+ so reports land in its context as ordinary tool results.
127
+ - Budgets are enforced before any new worker work; guarded asks (e.g. writes
128
+ outside the folder) always prompt, even after "Always".
129
+
130
+ Design history and roadmap: [DESIGN.md](DESIGN.md).
131
+
132
+ [Claude Agent SDK]: https://code.claude.com/docs/en/agent-sdk
133
+ [claude-golden-eye]: ../claude-golden-eye
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * The `foreman` command.
4
+ *
5
+ * Everything resolves from this file's own location rather than the working
6
+ * directory, so the server can be started from anywhere — which is the whole
7
+ * point of having a bin. `src/` ships as TypeScript, so tsx is registered as a
8
+ * loader here rather than requiring a build step before first run.
9
+ *
10
+ * npx @amenophis1er/foreman start, right now, from nothing
11
+ * npm i -g @amenophis1er/foreman then `foreman` from any shell
12
+ */
13
+ import { readFileSync } from 'node:fs';
14
+ import { register } from 'tsx/esm/api';
15
+
16
+ const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
17
+
18
+ const USAGE = `foreman ${pkg.version}
19
+
20
+ foreman Start in this terminal (same as "start"); Ctrl+C stops it
21
+ foreman up Start in the background; logs to ~/.foreman/logs/server.log
22
+ foreman down Stop a background server started with "up"
23
+ foreman status Is a server up? Which port, which pid?
24
+ foreman doctor Check credentials, providers, browser, port, Tailscale — and exit
25
+ foreman open Open the dashboard in your browser
26
+ foreman service install Keep Foreman running: start at login, restart if it dies
27
+ foreman service uninstall Remove that
28
+ foreman service status Is the service registered and running?
29
+ foreman service logs Tail the service's log
30
+ foreman --version | --help
31
+
32
+ Environment:
33
+ PORT Listen port (default 4177)
34
+ FOREMAN_HOME State directory (default ~/.foreman)
35
+ FOREMAN_BIND auto (loopback + Tailscale, default) | local | all
36
+ FOREMAN_BROWSER Browser for missions: chrome (default), chromium, msedge, firefox
37
+ FOREMAN_CLAUDE_CONFIG_DIR Claude Code install missions run under
38
+ FOREMAN_CLAUDE_EXECUTABLE Claude Code executable (default: bundled)
39
+ FOREMAN_AUTH_MODE Assert 'api-key' or 'subscription'; fail on mismatch
40
+ `;
41
+
42
+ const [command = 'start', ...rest] = process.argv.slice(2);
43
+
44
+ if (command === '--help' || command === '-h' || command === 'help') {
45
+ process.stdout.write(USAGE);
46
+ } else if (command === '--version' || command === '-v' || command === 'version') {
47
+ process.stdout.write(`${pkg.version}\n`);
48
+ } else if (command === 'start') {
49
+ register();
50
+ await import(new URL('../src/server.ts', import.meta.url).href);
51
+ } else if (['doctor', 'open', 'service', 'up', 'down', 'status'].includes(command)) {
52
+ register();
53
+ const { runCli } = await import(new URL('../src/cli.ts', import.meta.url).href);
54
+ process.exitCode = await runCli(command, rest, { version: pkg.version, bin: new URL(import.meta.url) });
55
+ } else {
56
+ process.stderr.write(`foreman: unknown command "${command}"\n\n${USAGE}`);
57
+ process.exit(1);
58
+ }