@markjaquith/agency 2.68.0 → 2.69.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 CHANGED
@@ -11,7 +11,7 @@ read or write.
11
11
  - Git
12
12
  - [Jujutsu](https://jj-vcs.github.io/jj/) is preferred when available
13
13
  - [GitHub CLI](https://cli.github.com/) for `agency pr`
14
- - OpenCode, Claude Code, or a configured runner for `agency work`
14
+ - OpenCode, Claude Code, or a configured agent for `agency work`
15
15
 
16
16
  ## Installation
17
17
 
@@ -113,7 +113,7 @@ read-only Agency commands, and use explicit Agency CLI permissions to create or
113
113
  update planning structure. Its normal research tools and the complete Agency CLI
114
114
  remain available; managed Agency instructions and reported authority govern each
115
115
  operation.
116
- When the subagent launches work in another agent, it verifies that the runner
116
+ When the subagent launches work in another agent, it verifies that the agent
117
117
  started and returns without waiting for the task to finish.
118
118
  The TUI-only `/agency-debug` command reports TUI companion initialization and
119
119
  whether the server plugin registered writable-checkout skills. It uses a native
@@ -360,23 +360,36 @@ retries checkout creation and the hook rather than reusing an uninitialized
360
360
  checkout. Hook commands should be idempotent so a retry is safe after any
361
361
  external effects the failed invocation may have completed.
362
362
 
363
- ### Agent Runners
363
+ ### Agents
364
364
 
365
- OpenCode (`opencode2` and `opencode`) and Claude Code are built-in runner presets.
366
- Without an explicit runner, Agency uses the first available executable in this
367
- order: `opencode2`, `opencode`, then `claude`. Select a preset or configured
368
- runner with `agency work --runner <name>`. A launch is fresh unless
369
- `AGENCY_SESSION_ID` is already set; resumed launches use the runner's
365
+ OpenCode (`opencode2` and `opencode`), Pi, and Claude Code are built-in agent presets.
366
+ Without an explicit agent, Agency uses the first available executable in this
367
+ order: `opencode2`, `opencode`, `pi`, then `claude`. Select a preset or configured
368
+ agent with `agency work --agent <name>`. To select a built-in agent globally,
369
+ set `agent` in `$XDG_CONFIG_HOME/agency/agency.json` (or
370
+ `~/.config/agency/agency.json`):
371
+
372
+ ```json
373
+ {
374
+ "agent": "pi"
375
+ }
376
+ ```
377
+
378
+ The selection precedence is `--agent` (including the legacy `--opencode` and
379
+ `--claude` aliases), then `AGENCY_AGENT`, then `agent`, then automatic
380
+ detection. Supported global values are `opencode2`, `opencode`, `pi`, and
381
+ `claude`; an unavailable configured agent fails rather than falling back. A launch
382
+ is fresh unless `AGENCY_SESSION_ID` is already set; resumed launches use the agent's
370
383
  `resumeCommand` when configured. The built-in presets use `--continue` only for
371
- resumed launches. By default Agency opens the runner without a prompt. `--auto`
384
+ resumed launches. By default Agency opens the agent without a prompt. `--auto`
372
385
  uses its autonomous command and sends the generated task, phase, or epic prompt.
373
386
 
374
- Custom runners are direct argv commands, never shell snippets:
387
+ Custom agents are direct argv commands, never shell snippets:
375
388
 
376
389
  ```json
377
390
  {
378
391
  "version": 2,
379
- "runners": {
392
+ "agents": {
380
393
  "custom": {
381
394
  "command": ["my-agent"],
382
395
  "autoCommand": ["my-agent", "--prompt", "{prompt}"],
@@ -393,19 +406,19 @@ Available placeholders are `{prompt}`, `{workbase}`, `{target}`, `{task}`,
393
406
  placeholders are empty when they do not apply. `{prompt}` is empty unless
394
407
  `--auto` is set. If `resumeCommand` is omitted, the fresh command is also used
395
408
  for resumed sessions. If `autoResumeCommand` is omitted, `autoCommand` is used;
396
- configured runners without `autoCommand` reject `--auto`.
409
+ configured agents without `autoCommand` reject `--auto`.
397
410
 
398
- Every runner receives the same `AGENCY_RUNNER`, `AGENCY_CLAIMANT`,
411
+ Every agent receives the same `AGENCY_AGENT`, `AGENCY_CLAIMANT`,
399
412
  `AGENCY_SESSION_ID`, `AGENCY_CLAIM_REVISION`, `AGENCY_WORKBASE`, `AGENCY_TARGET`,
400
413
  `AGENCY_TASK_ID`, `AGENCY_PHASE_ID`, and `AGENCY_PROMPT` environment. Configured
401
414
  environment is added without overriding these normalized values.
402
- Execution-unit runners also receive `AGENCY_WRITABLE_CHECKOUT` with the
415
+ Execution-unit agents also receive `AGENCY_WRITABLE_CHECKOUT` with the
403
416
  authoritative writable checkout path.
404
417
  `AGENCY_CLAIM_REVISION` is empty for local `agency work` launches.
405
418
  `AGENCY_PROMPT` is empty unless `--auto` is set.
406
419
  Autonomous prompts begin `Agency worker launch target: <target>.`, carrying the
407
420
  same canonical target as `AGENCY_TARGET`. This is the process-local fallback for
408
- runner clients that attach to a long-lived process and lose launch environment
421
+ agent clients that attach to a long-lived process and lose launch environment
409
422
  variables. A worker must verify either signal against `agency context . --json`
410
423
  before acting; a matching worker performs the task directly and must not invoke
411
424
  `agency work` for the same target. Managed guidance also fails safe for older
@@ -416,7 +429,7 @@ to the receiving OpenCode session, injects an explicit active-worker system
416
429
  instruction, and restores Agency identity for that session's shell environment.
417
430
  This session bridge is necessary because an OpenCode client can attach to a
418
431
  long-lived server process that did not inherit the client's launch environment.
419
- The `opencode2` and `opencode` runners remain rooted in their task or epic
432
+ The `opencode2` and `opencode` agents remain rooted in their task or epic
420
433
  working directory so the workbase `AGENTS.md` and managed OpenCode config are
421
434
  discovered normally.
422
435
  Agency's managed OpenCode plugin grants the active workbase external-directory
@@ -430,7 +443,7 @@ checkout through `agency context`. A multi-phase
430
443
  task root has no single checkout, so launch from its phase directory when using
431
444
  plain OpenCode or Pi. Other checkout-local configuration is not composed.
432
445
  `--print-command` prints the exact cwd and argv plus non-secret environment keys
433
- without launching the runner.
446
+ without launching the agent.
434
447
 
435
448
  ### Custom Chooser Command
436
449
 
@@ -791,7 +804,7 @@ agency task new [id] [--work [--auto]]
791
804
  ```
792
805
 
793
806
  `--work` starts work on the newly created entity. Add `--auto` to pass the
794
- generated context prompt to the selected runner. These launch options are also
807
+ generated context prompt to the selected agent. These launch options are also
795
808
  available on `epic new` and `phase new`; they cannot be combined with `--json`.
796
809
 
797
810
  Create a single-phase task:
@@ -991,7 +1004,7 @@ outcome.
991
1004
 
992
1005
  `delegated` remains readable for existing workbases but cannot be newly assigned.
993
1006
  Delegation is now explicit: the claimant identifies the orchestrator and the
994
- runner identifies the assigned agent.
1007
+ agent identifies the assigned agent.
995
1008
 
996
1009
  Human list output is a compact table with lifecycle, readiness, parent,
997
1010
  repository, branch, recorded PR, and worktree state where applicable. List and
@@ -1007,7 +1020,7 @@ Claim mutations require the SHA-256 revision exposed by `agency context` or
1007
1020
  document lock and atomically replaces the execution document.
1008
1021
 
1009
1022
  ```text
1010
- agency claim <task-id> [phase-id] --claimant <id> --runner <id>
1023
+ agency claim <task-id> [phase-id] --claimant <id> --agent <id>
1011
1024
  --session-id <id> --revision <sha256> [--expires-at <timestamp>] [--json]
1012
1025
  agency release <task-id> [phase-id] --session-id <id>
1013
1026
  --revision <sha256> [--json]
@@ -1027,8 +1040,8 @@ rather than overwriting it. Expired claims may be replaced with a
1027
1040
  revision-guarded claim.
1028
1041
 
1029
1042
  `agency work` does not claim execution units. It refuses active explicit claims,
1030
- marks open execution work `working`, and launches the runner. External
1031
- orchestrators use `agency claim`, launch and monitor their runner separately, and
1043
+ marks open execution work `working`, and launches the agent. External
1044
+ orchestrators use `agency claim`, launch and monitor their agent separately, and
1032
1045
  later call `agency release` or `agency finish`.
1033
1046
 
1034
1047
  ### Archive
@@ -1071,7 +1084,7 @@ until restored.
1071
1084
  ### Work, Publication, and Pull Requests
1072
1085
 
1073
1086
  ```text
1074
- agency work [<directory> | --epic <epic-id>] [--runner <name>] [--auto] [--print-command]
1087
+ agency work [<directory> | --epic <epic-id>] [--agent <name>] [--auto] [--print-command]
1075
1088
  agency work prepare [target] [--evidence <json-or-path>] [--dry-run] [--json]
1076
1089
  agency worktree <list|inspect|prepare|remove|rebuild|repair>
1077
1090
  agency push [--json]
@@ -1084,7 +1097,7 @@ configured external chooser. Pass a directory, including `.` for the current
1084
1097
  directory, to infer its epic, task, or phase. Outside a workbase, Agency first
1085
1098
  presents the registered workbases, then the selected workbase's hierarchy.
1086
1099
 
1087
- Agency automatically uses the first available runner in this order: `opencode2`,
1100
+ Agency automatically uses the first available agent in this order: `opencode2`,
1088
1101
  `opencode`, then `claude`. `--opencode` and `--claude` remain aliases for
1089
1102
  requiring their corresponding built-in presets. Launches are interactive and
1090
1103
  promptless by default; use `--auto` to send Agency's generated context prompt.
package/cli-main.ts CHANGED
@@ -206,7 +206,7 @@ const commands: Record<string, Command> = {
206
206
  taskId: args[0],
207
207
  phaseId: args[1],
208
208
  claimant: options.claimant,
209
- runner: options.runner,
209
+ agent: options.agent,
210
210
  sessionId: options["session-id"],
211
211
  revision: options.revision,
212
212
  expiresAt: options["expires-at"],
@@ -584,7 +584,7 @@ const commands: Record<string, Command> = {
584
584
  verbose: options.verbose,
585
585
  opencode: options.opencode,
586
586
  claude: options.claude,
587
- runner: options.runner,
587
+ agent: options.agent,
588
588
  auto: options.auto,
589
589
  printCommand: options["print-command"],
590
590
  force: options.force,
@@ -28,7 +28,7 @@
28
28
  "ui",
29
29
  "--claimant",
30
30
  "orchestrator-1",
31
- "--runner",
31
+ "--agent",
32
32
  "opencode",
33
33
  "--session-id",
34
34
  "session-123",
@@ -47,7 +47,7 @@
47
47
  "--json"
48
48
  ],
49
49
  ["work", "prepare", "--task", "checkout", "--phase", "ui", "--json"],
50
- ["work", "tasks/checkout/phases/ui", "--runner", "opencode"],
50
+ ["work", "tasks/checkout/phases/ui", "--agent", "opencode"],
51
51
  ["sync", "--dry-run", "--json"],
52
52
  ["sync", "--json"],
53
53
  ["pr", "create", "checkout", "ui", "--json"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@markjaquith/agency",
3
- "version": "2.68.0",
3
+ "version": "2.69.0",
4
4
  "description": "Manage agentic work across repositories with durable workbases",
5
5
  "keywords": [
6
6
  "agents",
@@ -539,7 +539,7 @@
539
539
  "additionalProperties": false,
540
540
  "required": [
541
541
  "claimant",
542
- "runner",
542
+ "agent",
543
543
  "sessionId",
544
544
  "startedAt",
545
545
  "targetRevision",
@@ -547,7 +547,7 @@
547
547
  ],
548
548
  "properties": {
549
549
  "claimant": { "type": "string", "minLength": 1 },
550
- "runner": { "type": "string", "minLength": 1 },
550
+ "agent": { "type": "string", "minLength": 1 },
551
551
  "sessionId": { "type": "string", "minLength": 1 },
552
552
  "startedAt": { "type": "string", "format": "date-time" },
553
553
  "targetRevision": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
@@ -343,7 +343,7 @@ describe("strict CLI parsing", () => {
343
343
  "three",
344
344
  "--claimant",
345
345
  "a",
346
- "--runner",
346
+ "--agent",
347
347
  "r",
348
348
  "--session-id",
349
349
  "s",
@@ -499,7 +499,7 @@ describe("strict CLI parsing", () => {
499
499
  "phase",
500
500
  "--claimant",
501
501
  "orchestrator",
502
- "--runner",
502
+ "--agent",
503
503
  "agent",
504
504
  "--session-id",
505
505
  "job-1",
@@ -699,12 +699,12 @@ describe("strict CLI parsing", () => {
699
699
  expectUsageError(["push", "example"], "agency push")
700
700
  })
701
701
 
702
- test("accepts runner selection and command inspection for work", () => {
702
+ test("accepts agent selection and command inspection for work", () => {
703
703
  expect(
704
704
  parseCli([
705
705
  "work",
706
706
  "example",
707
- "--runner",
707
+ "--agent",
708
708
  "custom",
709
709
  "--auto",
710
710
  "--print-command",
@@ -712,10 +712,10 @@ describe("strict CLI parsing", () => {
712
712
  ).toMatchObject({
713
713
  commandName: "work",
714
714
  args: ["example"],
715
- values: { runner: "custom", auto: true, "print-command": true },
715
+ values: { agent: "custom", auto: true, "print-command": true },
716
716
  })
717
717
  expect(() =>
718
- parseCli(["work", "example", "--runner", "custom", "--claude"]),
718
+ parseCli(["work", "example", "--agent", "custom", "--claude"]),
719
719
  ).toThrow("cannot be combined")
720
720
  expect(() => parseCli(["work", "prepare", "--print-command"])).toThrow(
721
721
  "cannot be combined",
@@ -989,7 +989,7 @@ describe("strict CLI parsing", () => {
989
989
  "release",
990
990
  "--claimant",
991
991
  "agent",
992
- "--runner",
992
+ "--agent",
993
993
  "opencode",
994
994
  "--session-id",
995
995
  "session",
package/src/cli-parser.ts CHANGED
@@ -117,7 +117,7 @@ const mutationOptions = {
117
117
  const claimOptions = {
118
118
  ...outputOptions,
119
119
  claimant: { type: "string" },
120
- runner: { type: "string" },
120
+ agent: { type: "string" },
121
121
  "session-id": { type: "string" },
122
122
  revision: { type: "string" },
123
123
  "expires-at": { type: "string" },
@@ -671,12 +671,12 @@ const commands = {
671
671
  },
672
672
  command: {
673
673
  usage:
674
- "agency claim <task-id> [phase-id] --claimant <id> --runner <id> --session-id <id> --revision <sha256> [--expires-at <timestamp>] [--json]",
674
+ "agency claim <task-id> [phase-id] --claimant <id> --agent <id> --session-id <id> --revision <sha256> [--expires-at <timestamp>] [--json]",
675
675
  minArgs: 1,
676
676
  maxArgs: 2,
677
677
  options: [
678
678
  "claimant",
679
- "runner",
679
+ "agent",
680
680
  "session-id",
681
681
  "revision",
682
682
  "expires-at",
@@ -684,7 +684,7 @@ const commands = {
684
684
  "task",
685
685
  "phase",
686
686
  ],
687
- required: ["claimant", "runner", "session-id", "revision"],
687
+ required: ["claimant", "agent", "session-id", "revision"],
688
688
  },
689
689
  },
690
690
  release: {
@@ -916,13 +916,13 @@ const commands = {
916
916
  },
917
917
  work: {
918
918
  usage:
919
- "agency work [<directory-or-task-id> | --epic <epic-id>] [--runner <name>] [--auto] | agency work prepare [target] [--dry-run] [--json]",
919
+ "agency work [<directory-or-task-id> | --epic <epic-id>] [--agent <name>] [--auto] | agency work prepare [target] [--dry-run] [--json]",
920
920
  options: {
921
921
  ...commonOptions,
922
922
  ...entitySelectorOptions,
923
923
  json: { type: "boolean" },
924
924
  "dry-run": { type: "boolean" },
925
- runner: { type: "string" },
925
+ agent: { type: "string" },
926
926
  auto: { type: "boolean" },
927
927
  "print-command": { type: "boolean" },
928
928
  opencode: { type: "boolean" },
@@ -932,7 +932,7 @@ const commands = {
932
932
  },
933
933
  command: {
934
934
  usage:
935
- "agency work [<directory-or-task-id> | --epic <epic-id>] [--runner <name>] [--auto] | agency work prepare [target] [--dry-run] [--json]",
935
+ "agency work [<directory-or-task-id> | --epic <epic-id>] [--agent <name>] [--auto] | agency work prepare [target] [--dry-run] [--json]",
936
936
  minArgs: 0,
937
937
  maxArgs: 2,
938
938
  options: [
@@ -941,7 +941,7 @@ const commands = {
941
941
  "epic",
942
942
  "task",
943
943
  "phase",
944
- "runner",
944
+ "agent",
945
945
  "auto",
946
946
  "print-command",
947
947
  "opencode",
@@ -951,8 +951,8 @@ const commands = {
951
951
  ],
952
952
  conflicts: [
953
953
  ["opencode", "claude"],
954
- ["runner", "opencode"],
955
- ["runner", "claude"],
954
+ ["agent", "opencode"],
955
+ ["agent", "claude"],
956
956
  ["epic", "$positional"],
957
957
  ],
958
958
  },
@@ -1689,7 +1689,7 @@ export function parseCli(args: readonly string[]): ParsedCli {
1689
1689
  (parsed.values.epic ||
1690
1690
  parsed.values.opencode ||
1691
1691
  parsed.values.claude ||
1692
- parsed.values.runner ||
1692
+ parsed.values.agent ||
1693
1693
  parsed.values.auto ||
1694
1694
  parsed.values["print-command"] ||
1695
1695
  parsed.values.force))
package/src/cli.test.ts CHANGED
@@ -192,7 +192,7 @@ describe("CLI", () => {
192
192
  "claimed",
193
193
  "--claimant",
194
194
  "orchestrator",
195
- "--runner",
195
+ "--agent",
196
196
  "agent",
197
197
  "--session-id",
198
198
  "job-1",
@@ -205,7 +205,7 @@ describe("CLI", () => {
205
205
  )
206
206
  expect(claimed.claim).toMatchObject({
207
207
  claimant: "orchestrator",
208
- runner: "agent",
208
+ agent: "agent",
209
209
  sessionId: "job-1",
210
210
  state: "active",
211
211
  })
@@ -216,7 +216,7 @@ describe("CLI", () => {
216
216
  "claimed",
217
217
  "--claimant",
218
218
  "other",
219
- "--runner",
219
+ "--agent",
220
220
  "other-agent",
221
221
  "--session-id",
222
222
  "job-2",
@@ -232,7 +232,7 @@ describe("CLI", () => {
232
232
  error: {
233
233
  code: "CLAIM_CONFLICT",
234
234
  retryable: true,
235
- fields: { claim: { runner: "agent", sessionId: "job-1" } },
235
+ fields: { claim: { agent: "agent", sessionId: "job-1" } },
236
236
  },
237
237
  })
238
238
 
@@ -274,7 +274,7 @@ describe("CLI", () => {
274
274
  "non-pr",
275
275
  "--claimant",
276
276
  "orchestrator",
277
- "--runner",
277
+ "--agent",
278
278
  "agent",
279
279
  "--session-id",
280
280
  "job-2",
@@ -1014,7 +1014,7 @@ status: open
1014
1014
  `${JSON.stringify(
1015
1015
  {
1016
1016
  ...agencyConfig,
1017
- runners: { noop: { command: ["true"] } },
1017
+ agents: { noop: { command: ["true"] } },
1018
1018
  },
1019
1019
  null,
1020
1020
  2,
@@ -1421,7 +1421,7 @@ status: open
1421
1421
  await runCli(["task", "status", "example", "dropped", "--json"], root),
1422
1422
  )
1423
1423
  const blocked = await runCli(
1424
- ["work", "--task", "example", "--runner", "noop"],
1424
+ ["work", "--task", "example", "--agent", "noop"],
1425
1425
  root,
1426
1426
  )
1427
1427
  expect(blocked.exitCode).toBe(1)
@@ -1432,7 +1432,7 @@ status: open
1432
1432
  ).toBe("dropped")
1433
1433
 
1434
1434
  const resumedTask = await runCli(
1435
- ["work", "--task", "example", "--runner", "noop", "--force"],
1435
+ ["work", "--task", "example", "--agent", "noop", "--force"],
1436
1436
  root,
1437
1437
  )
1438
1438
  expect(resumedTask).toMatchObject({ exitCode: 0, stderr: "" })
@@ -1457,7 +1457,7 @@ status: open
1457
1457
  "pipeline",
1458
1458
  "--phase",
1459
1459
  "build",
1460
- "--runner",
1460
+ "--agent",
1461
1461
  "noop",
1462
1462
  "--force",
1463
1463
  ],
@@ -8,7 +8,7 @@ interface ClaimCommandOptions extends BaseCommandOptions {
8
8
  readonly taskId?: string
9
9
  readonly phaseId?: string
10
10
  readonly claimant?: string
11
- readonly runner?: string
11
+ readonly agent?: string
12
12
  readonly sessionId?: string
13
13
  readonly revision?: string
14
14
  readonly expiresAt?: string
@@ -29,10 +29,10 @@ export const claimCommand = (options: ClaimCommandOptions) =>
29
29
  }
30
30
  if (
31
31
  options.operation === "claim" &&
32
- (!options.claimant || !options.runner)
32
+ (!options.claimant || !options.agent)
33
33
  ) {
34
34
  return yield* Effect.fail(
35
- new Error("Claimant and runner identities are required"),
35
+ new Error("Claimant and agent identities are required"),
36
36
  )
37
37
  }
38
38
  if (options.noPullRequest && !options.summary?.trim()) {
@@ -67,7 +67,7 @@ export const claimCommand = (options: ClaimCommandOptions) =>
67
67
  {
68
68
  ...common,
69
69
  claimant: options.claimant!,
70
- runner: options.runner!,
70
+ agent: options.agent!,
71
71
  ...(options.expiresAt ? { expiresAt: options.expiresAt } : {}),
72
72
  },
73
73
  cwd,
@@ -101,9 +101,9 @@ export const claimCommand = (options: ClaimCommandOptions) =>
101
101
  })
102
102
 
103
103
  export const claimHelp = `
104
- Usage: agency claim <task-id> [phase-id] --claimant <id> --runner <id> --session-id <id> --revision <sha256>
104
+ Usage: agency claim <task-id> [phase-id] --claimant <id> --agent <id> --session-id <id> --revision <sha256>
105
105
 
106
- Claim an execution unit. Use distinct claimant and runner identities for delegated
106
+ Claim an execution unit. Use distinct claimant and agent identities for delegated
107
107
  work. --expires-at accepts an optional future ISO-8601 timestamp.
108
108
  `
109
109
 
@@ -39,7 +39,7 @@ describe("doctor command", () => {
39
39
  "agency.json",
40
40
  JSON.stringify({
41
41
  version: 2,
42
- runners: {
42
+ agents: {
43
43
  missing: {
44
44
  command: ["definitely-not-installed"],
45
45
  autoCommand: ["also-not-installed", "{prompt}"],
@@ -87,12 +87,12 @@ status: open
87
87
  status: "pass",
88
88
  }),
89
89
  expect.objectContaining({
90
- id: "integration.runner.missing",
90
+ id: "integration.agent.missing",
91
91
  level: "error",
92
92
  status: "fail",
93
93
  }),
94
94
  expect.objectContaining({
95
- id: "integration.runner.missing.auto",
95
+ id: "integration.agent.missing.auto",
96
96
  level: "error",
97
97
  status: "fail",
98
98
  }),