@agentworkforce/cli 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.
package/README.md ADDED
@@ -0,0 +1,382 @@
1
+ # agent-workforce CLI
2
+
3
+ A thin command-line front end for the workload-router. Spawns the harness CLI
4
+ (`claude`, `codex`, `opencode`) configured by a selected **persona** — either a
5
+ built-in one from `/personas/`, or a user-local one that extends a built-in.
6
+
7
+ ```
8
+ agent-workforce agent <persona>[@<tier>] [task...]
9
+ ```
10
+
11
+ - No `task` → drops you into an interactive session with the harness.
12
+ - `task...` given → runs one-shot (via `usePersona().sendMessage()`) and streams
13
+ output to stdout/stderr.
14
+
15
+ ## Install
16
+
17
+ The CLI ships as a `bin` in `@agentworkforce/cli` (which depends on
18
+ `@agentworkforce/workload-router` via the pnpm workspace). From the repo
19
+ checkout:
20
+
21
+ ```sh
22
+ corepack pnpm -r build
23
+ corepack pnpm --filter @agentworkforce/cli link --global
24
+ ```
25
+
26
+ That puts `agent-workforce` on your PATH.
27
+
28
+ ## Selectors
29
+
30
+ ```
31
+ agent-workforce agent <persona>[@<tier>] [task...]
32
+ ```
33
+
34
+ - `<persona>` — matches, in order:
35
+ 1. A **pwd-local** id (files in `<cwd>/.agent-workforce/*.json`)
36
+ 2. A **home-local** id (files in `~/.agent-workforce/*.json`)
37
+ 3. A **library** persona — by intent first (e.g. `review`), then by id
38
+ (e.g. `code-reviewer`)
39
+ - `<tier>` — `best` | `best-value` | `minimum`. Defaults to `best-value`.
40
+
41
+ Unknown persona prints the full catalog with each entry's origin.
42
+
43
+ ### Examples
44
+
45
+ ```sh
46
+ # One-shot against the built-in code reviewer
47
+ agent-workforce agent review@best-value "look at the diff on this branch"
48
+
49
+ # Interactive PostHog session (library persona, needs POSTHOG_API_KEY)
50
+ agent-workforce agent posthog@best
51
+
52
+ # Interactive against a local override
53
+ agent-workforce agent my-posthog@best
54
+ ```
55
+
56
+ ## Personas
57
+
58
+ A persona is a JSON object describing *what harness runs, which model, with
59
+ what system prompt, what skills to install, what env vars to inject, and which
60
+ MCP servers to attach*. Full library shape:
61
+
62
+ ```jsonc
63
+ {
64
+ "id": "posthog",
65
+ "intent": "posthog",
66
+ "description": "…",
67
+ "skills": [],
68
+ "env": { "POSTHOG_API_KEY": "$POSTHOG_API_KEY" },
69
+ "mcpServers": {
70
+ "posthog": {
71
+ "type": "http",
72
+ "url": "https://mcp.posthog.com/mcp",
73
+ "headers": { "Authorization": "Bearer ${POSTHOG_API_KEY}" }
74
+ }
75
+ },
76
+ "tiers": {
77
+ "best": { "harness": "claude", "model": "claude-opus-4-6", "systemPrompt": "…", "harnessSettings": { "reasoning": "high", "timeoutSeconds": 900 } },
78
+ "best-value": { "harness": "claude", "model": "claude-sonnet-4-6", "systemPrompt": "…", "harnessSettings": { "reasoning": "medium", "timeoutSeconds": 600 } },
79
+ "minimum": { "harness": "claude", "model": "claude-haiku-4-5-20251001", "systemPrompt": "…", "harnessSettings": { "reasoning": "low", "timeoutSeconds": 300 } }
80
+ }
81
+ }
82
+ ```
83
+
84
+ See `/personas/*.json` for all built-ins.
85
+
86
+ ## Local personas & the cascade
87
+
88
+ Local persona files layer on top of the library. Resolution precedence (highest
89
+ wins):
90
+
91
+ 1. `<cwd>/.agent-workforce/*.json` — **pwd**
92
+ 2. `~/.agent-workforce/*.json` — **home** (override path via
93
+ `AGENT_WORKFORCE_CONFIG_DIR`)
94
+ 3. Built-in personas in `/personas/` — **library**
95
+
96
+ Local files are **partial overlays**: only the fields you set replace the
97
+ inherited value. Everything else cascades through from below.
98
+
99
+ ### Minimal override: add your API key
100
+
101
+ `~/.agent-workforce/my-posthog.json`:
102
+
103
+ ```json
104
+ {
105
+ "id": "my-posthog",
106
+ "extends": "posthog",
107
+ "env": { "POSTHOG_API_KEY": "$POSTHOG_API_KEY" }
108
+ }
109
+ ```
110
+
111
+ That inherits every field from the library `posthog` persona, then layers your
112
+ `env` on top. `agent-workforce agent my-posthog@best` now works as long as
113
+ `POSTHOG_API_KEY` is exported in your shell.
114
+
115
+ ### Same-id override (implicit extends)
116
+
117
+ If your file's `id` matches a persona in a lower layer and you omit `extends`,
118
+ the loader implicitly inherits from that same-id base:
119
+
120
+ `<cwd>/.agent-workforce/posthog.json`:
121
+
122
+ ```json
123
+ {
124
+ "id": "posthog",
125
+ "env": { "POSTHOG_API_KEY": "$POSTHOG_API_KEY" }
126
+ }
127
+ ```
128
+
129
+ Resolving `posthog` now hits this pwd override first; it inherits the rest
130
+ (MCP, tiers, description, etc.) from the library `posthog`.
131
+
132
+ ### Cascade chain
133
+
134
+ A pwd file can extend a home file, which extends the library:
135
+
136
+ ```
137
+ ~/.agent-workforce/ph-base.json:
138
+ { "id": "ph-base", "extends": "posthog", "env": { "POSTHOG_ORG": "acme" } }
139
+
140
+ <cwd>/.agent-workforce/ph-prod.json:
141
+ { "id": "ph-prod", "extends": "ph-base", "env": { "POSTHOG_API_KEY": "$PROD_KEY" } }
142
+ ```
143
+
144
+ Resolving `ph-prod`:
145
+
146
+ - Start with library `posthog` (MCP, tiers, prompt, …)
147
+ - Layer home `ph-base` on top (adds `POSTHOG_ORG=acme`)
148
+ - Layer pwd `ph-prod` on top (adds `POSTHOG_API_KEY`)
149
+
150
+ `extends` is resolved **strictly against lower layers** — pwd extends home or
151
+ library, home extends library, library has no `extends`.
152
+
153
+ ### Override shape (all fields except `id` optional)
154
+
155
+ ```jsonc
156
+ {
157
+ "id": "my-agent", // required
158
+ "extends": "posthog", // optional; implicit same-id if omitted
159
+ "description": "…", // replaces base description
160
+ "skills": [ … ], // replaces entire skills array
161
+ "env": { … }, // union, local wins per key
162
+ "mcpServers": { … }, // union by server name, local wins per key
163
+ "permissions": { // allow/deny union (dedup), mode replaces
164
+ "allow": ["…"], "deny": ["…"], "mode": "default"
165
+ },
166
+ "systemPrompt": "…", // replaces systemPrompt on every inherited tier
167
+ "tiers": { // per-tier partial override
168
+ "best": { "model": "claude-sonnet-4-6" }
169
+ // other tiers inherited untouched
170
+ }
171
+ }
172
+ ```
173
+
174
+ **Per-tier partial merge.** If you set `tiers.best.model`, only `model`
175
+ changes — `systemPrompt`, `harness`, and `harnessSettings` still come from the
176
+ base. Use top-level `systemPrompt` if you want to replace the prompt
177
+ uniformly across all tiers.
178
+
179
+ ## Env references & secrets
180
+
181
+ Any `env` value or `mcpServers.*.{headers,env,args,url,command}` value can be
182
+ either a literal string or an env reference. Two forms:
183
+
184
+ | Form | Meaning | Example |
185
+ | ---- | ------- | ------- |
186
+ | `"$VAR"` | Whole-string reference — the entire value is the env var. | `"POSTHOG_API_KEY": "$POSTHOG_API_KEY"` |
187
+ | `"prefix ${VAR}"` | Braced interpolation — each `${VAR}` is replaced in place, anywhere in the string. | `"Authorization": "Bearer ${POSTHOG_API_KEY}"` |
188
+
189
+ - Both forms resolve against the shell `process.env` at **spawn time** (not
190
+ load time).
191
+ - **Unbraced `$VAR` mid-string stays literal** — `"prefix-$FOO"` is NOT
192
+ interpolated. Use `${FOO}` if you want interpolation there. This prevents a
193
+ stray `$` in a JSON string from accidentally getting eaten.
194
+ - An unset or empty referenced var is a **warning, not a fatal error**. The
195
+ CLI drops the referring entry and proceeds. So a persona that references
196
+ `$POSTHOG_API_KEY` in both `env` and an `Authorization` header will, if the
197
+ var isn't set, launch without either — and the agent can still authenticate
198
+ interactively (e.g. via Claude Code's MCP OAuth flow). Example warning:
199
+
200
+ ```
201
+ warning: env.POSTHOG_API_KEY dropped (env var POSTHOG_API_KEY is not set).
202
+ warning: mcpServers.posthog.headers.Authorization dropped (env var POSTHOG_API_KEY is not set).
203
+ (referenced env vars were not set — proceeding without those values;
204
+ if the agent relies on them it may need to authenticate
205
+ interactively, e.g. via OAuth.)
206
+ ```
207
+
208
+ - An MCP server whose **structural** field (`url`, `command`, or any `arg`)
209
+ references a missing var is dropped entirely, since the server couldn't be
210
+ launched without that value. The warning names the server and the refs that
211
+ were unset.
212
+
213
+ Secrets therefore stay in your shell/keychain, not in files on disk — local
214
+ persona JSON remains commit-safe as long as you only use references.
215
+
216
+ ## Permissions
217
+
218
+ A persona can declare which tool calls the harness should auto-approve, block,
219
+ or gate via a permission mode. Skip the approval prompts for trusted tools
220
+ (e.g. a persona's own MCP server); keep them on for anything you want to
221
+ eyeball.
222
+
223
+ ```jsonc
224
+ {
225
+ "permissions": {
226
+ "allow": ["mcp__posthog", "Bash(git *)"], // auto-approve
227
+ "deny": ["Bash(rm -rf *)"], // always block
228
+ "mode": "default" // default | acceptEdits | bypassPermissions | plan
229
+ }
230
+ }
231
+ ```
232
+
233
+ - **Tool patterns** are passed through verbatim; use the harness's native
234
+ grammar. For Claude Code: `Bash(<pattern>)`, `Edit(<glob>)`,
235
+ `mcp__<server>` (all tools from that server), `mcp__<server>__<tool>`
236
+ (specific tool).
237
+ - **Harness support today:** only `claude` is wired (flags: `--allowedTools`,
238
+ `--disallowedTools`, `--permission-mode`). codex and opencode emit a
239
+ warning and fall back to their defaults when `permissions` is set.
240
+ - **Cascade merge:** `allow` and `deny` are unions across layers (deduped on
241
+ merge); `mode` is replaced by the topmost layer that sets it. So the
242
+ library can declare the minimum-viable allow list, home can layer on
243
+ project-wide denies, and pwd can add per-project patterns — they all
244
+ compose.
245
+
246
+ ### Example: PostHog with auto-approve
247
+
248
+ The built-in `posthog` persona declares `permissions.allow = ["mcp__posthog"]`
249
+ so that once you've authenticated (either by passing `POSTHOG_API_KEY` up
250
+ front or via Claude's OAuth flow), subsequent analytics tool calls don't
251
+ prompt. To narrow the auto-approval to read-only tools, override in a local
252
+ persona:
253
+
254
+ ```json
255
+ {
256
+ "id": "my-posthog",
257
+ "extends": "posthog",
258
+ "permissions": {
259
+ "allow": [
260
+ "mcp__posthog__projects-get",
261
+ "mcp__posthog__insights-list",
262
+ "mcp__posthog__events-query"
263
+ ]
264
+ }
265
+ }
266
+ ```
267
+
268
+ Because `allow` is a union, the base's `"mcp__posthog"` would still be in the
269
+ merged list. If you want to *shrink* the allow list in a local override,
270
+ include a comment explaining why — there's currently no "replace" knob, only
271
+ union. (File an issue if you need one.)
272
+
273
+ ## MCP servers
274
+
275
+ The `mcpServers` block mirrors Claude Code's `--mcp-config` JSON shape
276
+ verbatim. Three transport types:
277
+
278
+ ```jsonc
279
+ // Remote HTTP / streamable-http
280
+ { "type": "http", "url": "https://…", "headers": { "Authorization": "Bearer ${TOKEN}" } }
281
+
282
+ // Remote SSE (deprecated by most servers but still supported)
283
+ { "type": "sse", "url": "https://…", "headers": { … } }
284
+
285
+ // Stdio — long-running local MCP server
286
+ { "type": "stdio", "command": "npx", "args": ["-y", "…"], "env": { "API_KEY": "$API_KEY" } }
287
+ ```
288
+
289
+ ### Harness support
290
+
291
+ | Harness | Interactive MCP | One-shot MCP |
292
+ | -------- | --------------- | ------------ |
293
+ | claude | yes (via `--mcp-config` + `--strict-mcp-config`) | not yet — SDK workflow path doesn't thread MCP |
294
+ | codex | not yet — warns and proceeds without MCP | not yet |
295
+ | opencode | not yet — warns and proceeds without MCP | not yet |
296
+
297
+ For a persona that needs MCP today, pick `claude` as the harness on every tier
298
+ and use interactive mode.
299
+
300
+ ### MCP isolation
301
+
302
+ For the `claude` harness the CLI always spawns with `--strict-mcp-config`,
303
+ paired with an explicit `--mcp-config` payload (the persona's `mcpServers`, or
304
+ `{"mcpServers":{}}` if none). That means **only the servers declared on the
305
+ persona are loaded** — your user-level `~/.claude.json` MCPs and any
306
+ project-level MCP sources are ignored inside the session. This keeps each
307
+ persona session self-contained and prevents cross-contamination with the
308
+ agents you normally run. If you need one of your personal MCPs inside a
309
+ persona session, add it to the persona's `mcpServers` block.
310
+
311
+ ## Interactive vs one-shot
312
+
313
+ ### Interactive
314
+
315
+ ```sh
316
+ agent-workforce agent <persona>[@<tier>]
317
+ ```
318
+
319
+ 1. Resolves the persona, walks the cascade, resolves `$VAR` refs.
320
+ 2. Runs skill install (`prpm install …`) if the persona declares any skills.
321
+ 3. Execs the harness binary with stdio inherited:
322
+ - `claude`: `claude --model <model> --append-system-prompt <prompt>
323
+ --mcp-config '<json>' --strict-mcp-config`. Both flags are always passed
324
+ so the session only sees the persona's declared MCP servers — see
325
+ **MCP isolation** above.
326
+ - `codex`: `codex -m <model>` with the system prompt as the initial
327
+ positional `[PROMPT]`. (codex has no `--system-prompt` flag today.)
328
+ - `opencode`: `opencode --model <model>` with the system prompt as the
329
+ initial argument.
330
+ 4. Runs the skill cleanup command on exit, regardless of exit status.
331
+ 5. Propagates the harness's exit code.
332
+
333
+ Signals (SIGINT, SIGTERM) are forwarded to the child.
334
+
335
+ ### One-shot
336
+
337
+ ```sh
338
+ agent-workforce agent <persona>[@<tier>] "<task…>"
339
+ ```
340
+
341
+ Non-interactive. Delegates to `usePersona(intent, { tier }).sendMessage(task)`
342
+ from the workload-router SDK, which spawns an ad-hoc single-step workflow:
343
+ install skills → run agent → cleanup. Stdout/stderr stream live; exit code
344
+ matches the agent's.
345
+
346
+ Env from the persona is passed through via `ExecuteOptions.env`. `mcpServers`
347
+ is currently **ignored with a warning** in one-shot mode — the SDK workflow
348
+ path doesn't thread MCP config yet.
349
+
350
+ ## Selecting a harness per tier
351
+
352
+ A persona's three tiers can use different harnesses. The built-in
353
+ `npm-provenance-publisher` has `best` on codex and `best-value` on opencode,
354
+ for example.
355
+
356
+ If a persona uses MCP, keep every tier on `claude` — only the claude harness
357
+ wires MCP at spawn time today.
358
+
359
+ ## Troubleshooting
360
+
361
+ - **`Unknown persona "X".`** — The CLI prints the full catalog. If your local
362
+ file should be listed, check for a warning on the preceding line — parse
363
+ errors and bad `extends` references are reported but non-fatal.
364
+
365
+ - **`warning: <field> dropped (env var X is not set)`** — Informational. The
366
+ CLI skipped that value and is launching without it. Export the variable if
367
+ you want the agent to have it up-front; otherwise the harness may handle
368
+ auth interactively (e.g. Claude Code's MCP OAuth flow).
369
+
370
+ - **`Failed to spawn "claude": binary not found on PATH.`** — Install the
371
+ harness CLI (`claude`, `codex`, or `opencode`) and ensure it's on your PATH.
372
+
373
+ - **`warning: persona declares mcpServers but the codex harness is not yet
374
+ wired …`** — Either switch the tier's `harness` to `claude`, or drop the MCP
375
+ requirement.
376
+
377
+ - **`extends cycle detected through …`** — A local persona extends itself
378
+ transitively. Break the chain or point one link at the library directly.
379
+
380
+ - **Local file silently missing from the list** — Scroll up for a
381
+ `warning: [layer] file.json: …` line. Common causes: invalid JSON, `id`
382
+ missing, or `extends` pointing at something that isn't in a lower layer.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js ADDED
@@ -0,0 +1,249 @@
1
+ #!/usr/bin/env node
2
+ import { spawn, spawnSync } from 'node:child_process';
3
+ import { constants } from 'node:os';
4
+ import { PERSONA_TIERS, personaCatalog, useSelection } from '@agentworkforce/workload-router';
5
+ import { buildInteractiveSpec, formatDropWarnings, resolveMcpServersLenient, resolveStringMapLenient } from '@agentworkforce/harness-kit';
6
+ import { loadLocalPersonas } from './local-personas.js';
7
+ const USAGE = `Usage: agent-workforce agent <persona>[@<tier>] [task...]
8
+
9
+ <persona> repo persona id, repo intent, or local persona id
10
+ <tier> ${PERSONA_TIERS.join(' | ')} (default: best-value)
11
+ [task] if provided, runs one-shot non-interactively;
12
+ otherwise drops into an interactive harness session
13
+
14
+ Local personas cascade: <cwd>/.agent-workforce/*.json → ~/.agent-workforce/*.json → repo library.
15
+ Each layer only needs to specify fields it overrides; everything else inherits
16
+ from the next lower layer. "extends" explicitly names a base; omit it and the
17
+ loader implicitly inherits from the same-id persona below. (Override the home
18
+ layer path via AGENT_WORKFORCE_CONFIG_DIR.)
19
+
20
+ Examples:
21
+ agent-workforce agent npm-provenance-publisher@best
22
+ agent-workforce agent my-posthog@best
23
+ agent-workforce agent review@best-value "look at the diff on this branch"
24
+ `;
25
+ function die(msg, withUsage = true) {
26
+ process.stderr.write(`${msg}\n`);
27
+ if (withUsage)
28
+ process.stderr.write(`\n${USAGE}`);
29
+ process.exit(1);
30
+ }
31
+ const local = loadLocalPersonas();
32
+ for (const warning of local.warnings) {
33
+ process.stderr.write(`warning: ${warning}\n`);
34
+ }
35
+ function resolveSpec(key) {
36
+ const localSpec = local.byId.get(key);
37
+ if (localSpec)
38
+ return localSpec;
39
+ const catalogAsIntent = personaCatalog[key];
40
+ if (catalogAsIntent)
41
+ return catalogAsIntent;
42
+ const byId = Object.values(personaCatalog).find((p) => p.id === key);
43
+ if (byId)
44
+ return byId;
45
+ const repoListing = Object.values(personaCatalog)
46
+ .slice()
47
+ .sort((a, b) => a.id.localeCompare(b.id))
48
+ .map((p) => ` ${p.id} (intent: ${p.intent})`);
49
+ const localListing = [...local.byId.values()]
50
+ .sort((a, b) => a.id.localeCompare(b.id))
51
+ .map((p) => ` ${p.id} (${local.sources.get(p.id) ?? 'local'})`);
52
+ const listing = [...repoListing, ...localListing].join('\n');
53
+ return { error: `Unknown persona "${key}". Known personas:\n${listing}` };
54
+ }
55
+ function parseSelector(sel) {
56
+ const at = sel.indexOf('@');
57
+ const key = at === -1 ? sel : sel.slice(0, at);
58
+ const tierRaw = at === -1 ? undefined : sel.slice(at + 1);
59
+ if (!key)
60
+ die('Missing persona name before "@"');
61
+ const tier = (tierRaw ?? 'best-value');
62
+ if (tierRaw !== undefined && !PERSONA_TIERS.includes(tier)) {
63
+ die(`Invalid tier "${tierRaw}". Must be one of: ${PERSONA_TIERS.join(', ')}`);
64
+ }
65
+ const result = resolveSpec(key);
66
+ if ('error' in result)
67
+ die(result.error, false);
68
+ const kind = local.byId.has(key) ? 'local' : 'repo';
69
+ return { kind, spec: result, tier };
70
+ }
71
+ function buildSelection(spec, tier, kind) {
72
+ return {
73
+ personaId: spec.id,
74
+ tier,
75
+ runtime: spec.tiers[tier],
76
+ skills: spec.skills,
77
+ rationale: kind === 'local' ? `local-override: ${spec.id}` : `cli-tier-override: ${tier}`,
78
+ ...(spec.env ? { env: spec.env } : {}),
79
+ ...(spec.mcpServers ? { mcpServers: spec.mcpServers } : {}),
80
+ ...(spec.permissions ? { permissions: spec.permissions } : {})
81
+ };
82
+ }
83
+ function emitDropWarnings(lines) {
84
+ if (lines.length === 0)
85
+ return;
86
+ for (const line of lines)
87
+ process.stderr.write(`warning: ${line}\n`);
88
+ process.stderr.write(` (referenced env vars were not set — proceeding without those values; if the agent relies on them it may need to authenticate interactively, e.g. via OAuth.)\n`);
89
+ }
90
+ async function runOneShot(selection, task) {
91
+ const { runtime } = selection;
92
+ process.stderr.write(`→ ${selection.personaId} [${selection.tier}] via ${runtime.harness} (${runtime.model})\n`);
93
+ const envResolution = resolveStringMapLenient(selection.env, process.env, 'env');
94
+ emitDropWarnings(formatDropWarnings(envResolution.dropped, [], []));
95
+ if (selection.mcpServers && Object.keys(selection.mcpServers).length > 0) {
96
+ process.stderr.write(`warning: mcpServers are not yet wired through the one-shot (sendMessage) path; the agent will run without MCP. Use interactive mode for MCP access.\n`);
97
+ }
98
+ const ctx = useSelection(selection);
99
+ const execution = ctx.sendMessage(task, {
100
+ env: envResolution.value,
101
+ onProgress: ({ stream, text }) => {
102
+ (stream === 'stderr' ? process.stderr : process.stdout).write(text);
103
+ }
104
+ });
105
+ try {
106
+ const result = await execution;
107
+ process.exit(result.exitCode ?? 0);
108
+ }
109
+ catch (err) {
110
+ const typed = err;
111
+ const status = typed.result?.status ?? 'failed';
112
+ process.stderr.write(`\n[${status}] ${typed.message}\n`);
113
+ process.exit(typed.result?.exitCode ?? 1);
114
+ }
115
+ }
116
+ function signalExitCode(signal) {
117
+ if (!signal)
118
+ return 0;
119
+ const num = constants.signals[signal];
120
+ return 128 + (num ?? 1);
121
+ }
122
+ function runInstall(command, label) {
123
+ const [bin, ...args] = command;
124
+ if (!bin)
125
+ return;
126
+ process.stderr.write(`• ${label}\n`);
127
+ const res = spawnSync(bin, args, { stdio: 'inherit', shell: false });
128
+ if (res.status !== 0) {
129
+ const code = res.status ?? 1;
130
+ process.stderr.write(`${label} failed (exit ${code}). Aborting.\n`);
131
+ process.exit(code);
132
+ }
133
+ }
134
+ function runCleanup(command, commandString) {
135
+ if (commandString === ':')
136
+ return;
137
+ const [bin, ...args] = command;
138
+ if (!bin)
139
+ return;
140
+ spawnSync(bin, args, { stdio: 'inherit', shell: false });
141
+ }
142
+ function runInteractive(selection) {
143
+ const ctx = useSelection(selection);
144
+ const { runtime, personaId, tier } = selection;
145
+ const { install } = ctx;
146
+ process.stderr.write(`→ ${personaId} [${tier}] via ${runtime.harness} (${runtime.model})\n`);
147
+ const envResolution = resolveStringMapLenient(selection.env, process.env, 'env');
148
+ const mcpResolution = resolveMcpServersLenient(selection.mcpServers, process.env);
149
+ emitDropWarnings(formatDropWarnings(envResolution.dropped, mcpResolution.dropped, mcpResolution.droppedServers));
150
+ const resolvedEnv = envResolution.value;
151
+ const resolvedMcp = mcpResolution.servers;
152
+ if (install.plan.installs.length > 0) {
153
+ const skillIds = install.plan.installs.map((i) => i.skillId).join(', ');
154
+ runInstall(install.command, `Installing skills: ${skillIds}`);
155
+ }
156
+ const spec = buildInteractiveSpec({
157
+ harness: runtime.harness,
158
+ model: runtime.model,
159
+ systemPrompt: runtime.systemPrompt,
160
+ mcpServers: resolvedMcp,
161
+ permissions: selection.permissions
162
+ });
163
+ for (const w of spec.warnings)
164
+ process.stderr.write(`warning: ${w}\n`);
165
+ const finalArgs = spec.initialPrompt ? [...spec.args, spec.initialPrompt] : [...spec.args];
166
+ // Print a sanitized summary rather than raw argv: spec.args for the claude
167
+ // harness contains the resolved --mcp-config JSON and the full system
168
+ // prompt, either of which can carry secrets (Bearer tokens, API keys) once
169
+ // env refs are interpolated. We show the bin, model, and the *names* of
170
+ // the servers / permission fields so the user can verify the shape without
171
+ // leaking credentials to stderr or CI logs.
172
+ const summary = [`model=${runtime.model}`];
173
+ if (runtime.harness === 'claude') {
174
+ const servers = Object.keys(resolvedMcp ?? {});
175
+ summary.push(`mcp-strict=${servers.length ? servers.join(',') : '(none)'}`);
176
+ if (selection.permissions?.allow?.length) {
177
+ summary.push(`allow=${selection.permissions.allow.length} rule(s)`);
178
+ }
179
+ if (selection.permissions?.deny?.length) {
180
+ summary.push(`deny=${selection.permissions.deny.length} rule(s)`);
181
+ }
182
+ if (selection.permissions?.mode) {
183
+ summary.push(`mode=${selection.permissions.mode}`);
184
+ }
185
+ }
186
+ if (spec.initialPrompt)
187
+ summary.push('initial-prompt=<systemPrompt>');
188
+ process.stderr.write(`• spawning ${spec.bin} (${summary.join(', ')})\n`);
189
+ return new Promise((resolve) => {
190
+ let settled = false;
191
+ const finish = (code) => {
192
+ if (settled)
193
+ return;
194
+ settled = true;
195
+ runCleanup(install.cleanupCommand, install.cleanupCommandString);
196
+ resolve(code);
197
+ };
198
+ const child = spawn(spec.bin, finalArgs, {
199
+ stdio: 'inherit',
200
+ env: resolvedEnv ? { ...process.env, ...resolvedEnv } : process.env
201
+ });
202
+ const forward = (signal) => {
203
+ if (!child.killed)
204
+ child.kill(signal);
205
+ };
206
+ process.on('SIGINT', () => forward('SIGINT'));
207
+ process.on('SIGTERM', () => forward('SIGTERM'));
208
+ child.on('exit', (code, signal) => {
209
+ finish(code ?? signalExitCode(signal));
210
+ });
211
+ child.on('error', (err) => {
212
+ if (err.code === 'ENOENT') {
213
+ process.stderr.write(`Failed to spawn "${spec.bin}": binary not found on PATH. Install the ${runtime.harness} CLI and retry.\n`);
214
+ }
215
+ else {
216
+ process.stderr.write(`Failed to spawn "${spec.bin}": ${err.message}\n`);
217
+ }
218
+ finish(127);
219
+ });
220
+ });
221
+ }
222
+ async function main() {
223
+ const argv = process.argv.slice(2);
224
+ const [subcommand, ...rest] = argv;
225
+ if (!subcommand || subcommand === '-h' || subcommand === '--help') {
226
+ process.stdout.write(USAGE);
227
+ process.exit(subcommand ? 0 : 1);
228
+ }
229
+ if (subcommand !== 'agent') {
230
+ die(`Unknown subcommand "${subcommand}".`);
231
+ }
232
+ const [selector, ...taskParts] = rest;
233
+ if (!selector)
234
+ die('agent: missing persona selector.');
235
+ const target = parseSelector(selector);
236
+ const selection = buildSelection(target.spec, target.tier, target.kind);
237
+ if (taskParts.length > 0) {
238
+ await runOneShot(selection, taskParts.join(' '));
239
+ }
240
+ else {
241
+ const code = await runInteractive(selection);
242
+ process.exit(code);
243
+ }
244
+ }
245
+ main().catch((err) => {
246
+ process.stderr.write(`${err?.stack ?? String(err)}\n`);
247
+ process.exit(1);
248
+ });
249
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}