@pmelab/gtd 7.11.2 → 8.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/docs/cli.md DELETED
@@ -1,747 +0,0 @@
1
- # CLI reference
2
-
3
- ```
4
- Usage: gtd [command] [options]
5
-
6
- Commands:
7
- (no command), loop
8
- Launch the loop driver (bin/gtd), which repeatedly drives
9
- an agent through gtd next/gtd step calls until the
10
- workflow returns to its initial state again. A bare gtd
11
- invocation and gtd loop both launch it identically
12
- init Scaffold a minimal .gtdrc.json for this repo, seeding the
13
- default variables you are most likely to change (the test
14
- command) and a Prettier formatting suggestion. gtd runs its
15
- built-in workflow by default, so no workflow is written —
16
- add a workflow: key only to customize the machine itself.
17
- Takes no argument. Run once per repo; refuses if a gtd
18
- config already exists. Leaves the file uncommitted for you
19
- to review and commit
20
- step <actor> Authenticate as <actor>, match the resolved rest's
21
- declared patterns against the pending changes, and commit
22
- (or squash) the one resulting transition. Pass
23
- --cost=<n> (optionally --model=<name>) to record the
24
- just-finished invocation's token cost and model on the
25
- turn commit (summed into it.processCost/processCostByModel)
26
- review <commitish>
27
- Start a NEW review process at the workflow's declared
28
- review-entry state (reviewEntry: true), reviewing
29
- <commitish>..HEAD — e.g. a colleague's PR branch. Requires
30
- a clean tree resting at the workflow's initial state
31
- fix Start a NEW process at the workflow's declared fix-entry
32
- state (fixEntry: true) that goes straight into repairing the
33
- current failing tests. Requires a clean tree resting at the
34
- workflow's initial state
35
- abandon End the process currently underway without completing it:
36
- close any open review checkout window, then rewind HEAD to
37
- the commit the process started from, keeping everything it
38
- produced as uncommitted changes. A no-op when no process is
39
- underway
40
- restore Hard-reset HEAD back to the pre-squash tip retained by the
41
- last squash/abandon (refs/worktree/gtd/history), undoing a
42
- squash or bringing back an abandoned process's turns.
43
- Refuses on a dirty working tree, when there is no retained
44
- history, or when HEAD has advanced past the squash with
45
- commits that would be lost
46
- next Print the resolved rest's rendered script/prompt/message
47
- (no mutation)
48
- edit [path] Open <path> (repo-relative) in $VISUAL/$EDITOR, blocking
49
- until the editor exits. With no argument, opens the
50
- resolved rest's declared file (or the repo root if it
51
- declares none). Never reads --no-edit/--edit/GTD_NO_EDIT.
52
- Low-level plumbing — --edit covers the common "force an
53
- edit, then keep driving" case
54
- status Print the resolved rest's state/actor and which declared
55
- pattern (if any) each pending change matches (no mutation)
56
- validate Format and validate the steering file the resolved rest
57
- declares, with its mode's commands (its file:/mode:);
58
- exits non-zero with the findings when it is invalid
59
- lsp Start the LSP server for .gtd/ steering files (stdio)
60
- visualize Serve an interactive diagram of the active workflow on a
61
- local web server (--port <n>, --no-open; --json prints the
62
- model and exits)
63
- version Print version and exit
64
- help Print this help and exit
65
-
66
- Options:
67
- --json Output structured JSON instead of plain text
68
- --port=<n> (gtd visualize only) port to serve on (default: a free port)
69
- --no-open (gtd visualize only) do not open the browser
70
- --cost=<n> (gtd step only) record the invocation's token cost
71
- --model=<name> (gtd step only, with --cost) tag that cost's model
72
- --no-edit (bare gtd or gtd loop only) disable the loop's automatic
73
- editor launching at human gates
74
- --edit, -e (bare gtd or gtd loop only) force the editor open at the
75
- current human gate, overriding --no-edit/GTD_NO_EDIT; a
76
- no-op note (not an error) when not at a human gate
77
- --once (bare gtd or gtd loop only) run exactly one loop beat (one
78
- human gate, one script check+step, or one agent
79
- prompt+step), then exit — combines freely with
80
- --edit/--no-edit
81
- --version, -v Print version and exit
82
- --help, -h Print this help and exit
83
- ```
84
-
85
- `--version` (`-v`) / `gtd version` and `--help` (`-h`) / `gtd help`
86
- short-circuit before any git or repository-state work — they run outside a repo
87
- and in any repo state (the bare subcommands are exact equivalents of their flag
88
- forms). Bare `gtd` (no subcommand) and `gtd loop` both launch the loop driver
89
- (`bin/gtd`) immediately — neither is a usage error. Any other, truly unknown
90
- subcommand remains a usage error: it prints the help text and exits 1 without
91
- touching the repository. Every other (recognized) command must be run from the
92
- **repository root** — gtd derives the workflow, pending changes, and process
93
- history relative to cwd, so it refuses with a clear error if invoked from a
94
- subdirectory.
95
-
96
- `--json`, `--cost=<n>`, and `--model=<name>` (the latter two only for
97
- `gtd step`) are the only long options the compiled bundle recognizes. Any other
98
- `--` option (including a typo like `--jsn`) is rejected with a usage error
99
- rather than silently ignored, so a mistyped flag can never degrade a JSON caller
100
- to plain-text mode. A bare `--cost`/`--model` with no value, a non-numeric or
101
- negative `--cost`, an empty `--model`, `--model` without `--cost`, or either
102
- flag on any command other than `gtd step` are all usage errors.
103
-
104
- `--no-edit`, `--edit`/`-e`, and `--once` are separate, bash-level flags handled
105
- entirely by `bin/gtd` itself, stripped before anything reaches the bundle — see
106
- below.
107
-
108
- ## `--no-edit`, `--edit`, `--once`
109
-
110
- Three flags on the loop driver only (`--edit` also has the short form `-e`),
111
- each recognized bare (`gtd --no-edit`) or immediately after `loop`
112
- (`gtd loop --no-edit`) — the two positions are equivalent, since bare `gtd` and
113
- `gtd loop` are themselves equivalent. All three combine freely with each other,
114
- in any order (e.g. `gtd --edit --once`, `gtd loop --once --edit`), except
115
- `--edit`/`--no-edit` together, which conflict (forcing and suppressing the
116
- editor in the same run is not a coherent request): naming both, in either
117
- position, is rejected right in `bin/gtd` with a dedicated usage error
118
- (`gtd: --edit and --no-edit are mutually exclusive`, exit 2) — it never reaches
119
- the compiled bundle. Any other placement (e.g. `gtd step --once`) or a
120
- duplicated flag (`gtd --once --once`) is still a usage error, but surfaced via
121
- whatever guard the misplaced argument first reaches (the compiled bundle's own
122
- unknown-option/unknown-command rejection for a misplaced flag, or
123
- `gtd: 'loop' takes no arguments` for one misplaced after `loop`) — never
124
- silently ignored or silently resolved one way.
125
-
126
- **`--no-edit`** (or the `GTD_NO_EDIT` environment variable, any non-empty value)
127
- disables the loop's default behavior of launching an editor at human gates,
128
- restoring the halt-and-print-and-exit behavior with no editor involved.
129
-
130
- **`--edit`** (`-e`) is `--no-edit`'s mirror: it forces the editor open at the
131
- current human gate, overriding an ambient `GTD_NO_EDIT`/`--no-edit` default for
132
- this one run. It is only meaningful when the machine currently rests at a human
133
- gate — the honesty caveat: at any other rest, forcing an edit is undefined, so
134
- `bin/gtd` prints a note that it isn't at a human gate yet and simply keeps
135
- driving, rather than pretending to force something. Both flags govern only the
136
- loop's own automatic launching — `gtd edit` invoked directly never reads either
137
- (see [`gtd edit`](#gtd-edit-path) above).
138
-
139
- **`--once`** restricts the loop to exactly one beat — one human gate, one script
140
- check+step, or one agent prompt+step — then exits, instead of driving all the
141
- way back to idle/settled. Precisely: at most one commit/transition is made;
142
- whichever of the three kinds the currently-resolved rest is, that one gets
143
- processed (including any internal `gtd validate` fix-reprompt rounds a producing
144
- agent turn needs — those are all part of finishing the ONE prompt beat, not
145
- separate beats) and the loop exits 0 immediately after, without re-peeking at
146
- what comes next. A clean human gate with nothing to capture (the opening move's
147
- silent capture attempt under `--no-edit`, or a no-op editor session) is not a
148
- beat and falls through to the driver's ordinary halt, same as without `--once`.
149
-
150
- See [Driving the loop](loop.md) and `skills/loop/SKILL.md` for the full
151
- gate-flow description.
152
-
153
- ## `gtd init`
154
-
155
- Scaffolds a **minimal** `.gtdrc.json` at the repository root, plus a `$schema`
156
- link. It writes **no** `workflow:` key — gtd runs the bundled **unified**
157
- workflow as its built-in default, so a state command works out of the box with
158
- no config and no init at all. What `gtd init` seeds is the two things most
159
- projects tune: a `vars: { "testCommand": "npm test" }` entry (the var the
160
- bundled workflow's check script reads) and a ready-to-edit `modes:` block
161
- suggesting a Prettier `format:` for each built-in steering-file mode
162
- (`qa`/`review`). It takes **no argument** — passing one is a usage error
163
- (`gtd init: too many arguments — init takes no argument`).
164
-
165
- The bundled default has four entry points — each behind a green-baseline gate
166
- that runs the suite before starting — into one shared review/squash tail (see
167
- [STATES.md §10](../STATES.md#10-the-bundled-workflow-templates)): creating
168
- `.gtd/TODO.md` starts the simple flow (planning → building → checking), creating
169
- `.gtd/REQUIREMENTS.md` starts the advanced flow (two-phase Q&A planning,
170
- per-package parallel build, agentic spec-review), `gtd review <commitish>`
171
- enters review directly, and `gtd fix` goes straight into repairing failing
172
- tests. A red baseline halts at a `*-start-blocked` gate rather than starting new
173
- work. To CUSTOMIZE that machine, add your own `workflow:` key (a full definition
174
- — there is no `extends`/merge); see
175
- [Configuration](configuration.md#the-workflow-key).
176
-
177
- The file is written **uncommitted**; review and commit it before your first
178
- `gtd step` (an uncommitted `.gtdrc.json` is a pending change the initial state
179
- would otherwise capture). `gtd init` refuses if the repo root already has its
180
- own gtd config (a global/ancestor config, e.g. `~/.gtdrc`, does not count) and
181
- requires the repository root (or a directory outside any repo). `--json` prints
182
- `{"written":".gtdrc.json","inRepo":true}`. See
183
- [Configuration](configuration.md#gtd-init).
184
-
185
- ## `gtd step <actor> [--cost=<n>] [--model=<name>]`
186
-
187
- Authenticates `<actor>` against the resolved rest and performs the ONE resulting
188
- transition. Unlike v2, there is no fixpoint chain to drive: the pattern
189
- machine's `on` edges are direct one-hop transitions, so a single invocation
190
- authors at most one commit (a normal turn) or performs one squash
191
- (§[STATES.md](../STATES.md#8-the-squash-lifecycle)) — never both, never a chain
192
- of several. A caller that wants several transitions issues several invocations.
193
-
194
- `--cost=<n>` records the token cost of the invocation that produced the pending
195
- changes (a non-negative number), and the optional `--model=<name>` tags it with
196
- the model that ran, as a `Gtd-Cost: <n> <model>` trailer on the turn commit —
197
- persisted in the git log, summed across the process into `it.processCost` and
198
- grouped by model into `it.processCostByModel` (see
199
- [Configuration: Token cost](configuration.md#token-cost)). `--model` requires
200
- `--cost`. On a squash they are folded into the process total/breakdown the
201
- `commit:` template renders rather than written as a trailer. Both are orthogonal
202
- to `--json`.
203
-
204
- - **Out-of-turn refusal** — `<actor>` isn't the resolved state's declared actor:
205
- exit non-zero, zero commits.
206
- `gtd step <actor>: out of turn — "<state>" awaits <awaited-actor>`
207
- - **No-match refusal** — the tree is dirty and no declared `on` pattern matches:
208
- exit non-zero, zero commits, naming every declared pattern.
209
- `gtd step <actor>: no declared pattern matches the pending changes at "<state>" — declared patterns: <p1>, <p2>, …`
210
- - **No-op** — the tree is clean and the state declares no `C` pattern: exit
211
- **0**, zero commits. This is the default, silent case a loop driver relies on
212
- (see [Driving the loop](loop.md)).
213
- - **Commit/squash** — a pattern matched: exit 0, one commit (or one squash)
214
- authored.
215
-
216
- Plain-mode output is one line:
217
-
218
- ```
219
- committed: gtd(human): idle → planning
220
- ```
221
-
222
- or, at a no-op:
223
-
224
- ```
225
- nothing to do at "idle"
226
- ```
227
-
228
- `--json` emits `{state, subject}` — `subject` is `null` at a no-op — plus
229
- `cost`/`model` keys echoing what `--cost`/`--model` recorded (each omitted when
230
- not passed):
231
-
232
- ```json
233
- {
234
- "state": "idle",
235
- "subject": "gtd(human): idle → planning",
236
- "cost": 1450,
237
- "model": "claude-opus-4-8"
238
- }
239
- ```
240
-
241
- ## `gtd review <commitish> [--json]`
242
-
243
- Starts a BRAND NEW review process at the active workflow's declared
244
- `reviewEntry: true` state (see
245
- [STATES.md §11](../STATES.md#11-the-review-checkout-window)), reviewing
246
- `<commitish>..HEAD` — e.g. a colleague's PR branch pushed on top of a shared
247
- base, with no gtd process of its own. Reuses the workflow's existing
248
- review/feedback machinery unmodified; there is no separate review-entry command
249
- surface to keep in sync.
250
-
251
- Requires, in order (any failure is a plain refusal — exit non-zero, nothing
252
- written):
253
-
254
- - the machine currently resting at the workflow's **initial state** (a plain
255
- non-gtd branch resolves there via the inert-subject rule — the normal case; a
256
- process already underway refuses — finish it, or
257
- [`gtd abandon`](#gtd-abandon---json) it);
258
- - a **clean working tree**;
259
- - the active workflow declaring a **`reviewEntry: true`** state (otherwise:
260
- `gtd review: the active workflow declares no review entry state`);
261
- - `<commitish>` resolving to a commit, being an **ancestor of HEAD**, and
262
- **differing from HEAD** (nothing to review otherwise).
263
-
264
- On success, writes ONE empty commit, `gtd(human): <review-entry-state>`,
265
- carrying the resolved commit's full hash as a `Gtd-Review-Base: <hash>` trailer
266
- (mirroring how `gtd step --cost` writes its own `Gtd-Cost:` trailer). Everything
267
- downstream that renders a diff — `it.processDiff`, and the review checkout
268
- window opened by a downstream `reviewWindow: true` state — keys off the
269
- process's diff base, and this trailer is exactly how that base gets re-pointed
270
- at `<commitish>..HEAD` (see
271
- [STATES.md §7](../STATES.md#7-retry)/[§11](../STATES.md#11-the-review-checkout-window)).
272
-
273
- Plain-mode output is one line, same shape as `gtd step`:
274
-
275
- ```
276
- committed: gtd(human): review-start-check
277
- ```
278
-
279
- `--json` emits `{state, subject}` — `state` is the entered review-entry state,
280
- `subject` the bare commit subject (the trailer is not echoed).
281
-
282
- Takes exactly one positional argument (`<commitish>`); missing or extra
283
- arguments are usage errors.
284
-
285
- In the bundled unified template the review-entry state is `review-start-check` —
286
- a green-baseline gate that runs the suite and, once green, transitions to
287
- `reviewing`; a red run halts at `review-start-blocked` (see
288
- [STATES.md §10](../STATES.md#10-the-bundled-workflow-template)).
289
-
290
- ## `gtd fix [--json]`
291
-
292
- Starts a BRAND NEW process at the active workflow's declared `fixEntry: true`
293
- state (see [STATES.md §10](../STATES.md#10-the-bundled-workflow-template)) that
294
- goes straight into repairing the current failing tests. It is the standalone
295
- counterpart to the entry gates: the gates refuse to start new work on a red
296
- baseline, and `gtd fix` is the dedicated way to get back to green — repair,
297
- review, and squash a broken baseline into one commit.
298
-
299
- Requires, in order (any failure is a plain refusal — exit non-zero, nothing
300
- written):
301
-
302
- - the machine currently resting at the workflow's **initial state** (a process
303
- already underway refuses — finish it, or [`gtd abandon`](#gtd-abandon---json)
304
- it);
305
- - a **clean working tree**;
306
- - the active workflow declaring a **`fixEntry: true`** state (otherwise:
307
- `gtd fix: the active workflow declares no fix entry state`).
308
-
309
- Takes no positional argument (extra arguments are a usage error). Unlike
310
- `gtd review`, it writes NO `Gtd-Review-Base:` trailer — a fix reviews its own
311
- fixes from the ordinary process start — so on success it writes just one empty
312
- commit, `gtd(human): <fix-entry-state>`:
313
-
314
- ```
315
- committed: gtd(human): fix-check
316
- ```
317
-
318
- `--json` emits `{state, subject}`, same shape as `gtd review`. In the bundled
319
- unified template the fix-entry state is `fix-check`: a red suite drops into the
320
- shared `fixing` loop and out through the review + squash tail; a green suite is
321
- a no-op back to `idle`.
322
-
323
- ## `gtd abandon [--json]`
324
-
325
- Ends the process currently underway **without completing it** — the way out of a
326
- process nobody is going to finish, and the command `gtd review`/`gtd fix` name
327
- when they refuse ("finish it, or run `gtd abandon`, before starting a review").
328
- A workflow's own exit is its squash finale
329
- ([STATES.md §8](../STATES.md#8-the-squash-lifecycle)); this is the human's, and
330
- it targets the same boundary:
331
-
332
- 1. any open **review checkout window** is closed first (the bracket every state
333
- subcommand runs — see
334
- [STATES.md §11](../STATES.md#11-the-review-checkout-window)), so the rewind
335
- starts from the real head, not the rewound base;
336
- 2. HEAD is `git reset --mixed`ed to the commit the process started from (its
337
- start parent — the same target a squash resets to).
338
-
339
- **Nothing is discarded.** Every turn commit the process wrote is dropped, and
340
- everything they carried — the code, the `.gtd/` steering files — stays in the
341
- working tree as uncommitted changes for you to keep, re-commit, or throw away
342
- with ordinary git:
343
-
344
- ```
345
- abandoned the process resting at "await-review" — HEAD is back at 1a2b3c4
346
- ("feat: add calculator"), resting at "idle".
347
- Everything the process produced is kept as uncommitted changes (`git status`);
348
- discard them with `git checkout -- . && git clean -fd .gtd` for a clean tree.
349
- ```
350
-
351
- Takes no positional argument (extra arguments are a usage error). Resting at the
352
- workflow's initial state is a **no-op success**, not a refusal — a recovery
353
- command that fails when there is nothing to recover is a worse tool:
354
-
355
- ```
356
- no gtd process is underway (resting at "idle") — nothing to abandon
357
- ```
358
-
359
- The one refusal is a process whose first commit is the repository's own root
360
- commit: there is no earlier commit to rewind to, so its commits have to be
361
- removed by hand.
362
-
363
- `--json` emits `{state, abandoned, from, head}` — `state` is the initial state
364
- the machine returns to, `abandoned` whether anything was rewound, and (only when
365
- it was) `from` the state the abandoned process rested at plus `head` the full
366
- hash HEAD now points at:
367
-
368
- ```json
369
- {
370
- "state": "idle",
371
- "abandoned": true,
372
- "from": "await-review",
373
- "head": "1a2b3c4…"
374
- }
375
- ```
376
-
377
- The no-op reports `{"state": "idle", "abandoned": false}` and still exits 0.
378
-
379
- ## `gtd restore [--json]`
380
-
381
- Undoes the last squash or `gtd abandon` by hard-resetting HEAD back to the
382
- pre-squash tip that either one retains, before acting, on the per-worktree
383
- `refs/worktree/gtd/history` ref
384
- ([STATES.md §8](../STATES.md#8-the-squash-lifecycle)):
385
-
386
- ```
387
- restored the retained history — HEAD is back at 1a2b3c4 ("gtd(agent): drafting
388
- → working"), resting at "await-review". Resume with the loop, or `git reset`
389
- to any earlier turn to restart from there.
390
- ```
391
-
392
- Refuses on a dirty working tree — commit, stash, or discard your changes first.
393
- Refuses when there is no retained history to restore (nothing has been squashed
394
- or abandoned yet, or a previous `restore` already consumed it). Refuses when
395
- HEAD has advanced past the retained tip with commits that would be discarded by
396
- resetting:
397
-
398
- ```
399
- gtd restore: HEAD has advanced past the squash — restoring would discard
400
- commits built on top of it — HEAD 4d5e6f7 is ahead of the retained tip
401
- 1a2b3c4.
402
- ```
403
-
404
- Takes no positional argument (extra arguments are a usage error).
405
-
406
- `--json` emits `{state, restored, to, from}` — `state` is the resolved rest
407
- after the reset, `restored` always `true` (a refusal exits non-zero instead),
408
- `to` the full hash HEAD was reset to, and `from` the state the machine rested at
409
- before the reset:
410
-
411
- ```json
412
- {
413
- "state": "await-review",
414
- "restored": true,
415
- "to": "1a2b3c4…",
416
- "from": "idle"
417
- }
418
- ```
419
-
420
- ## `gtd next [--json]`
421
-
422
- Pure emitter of the resolved rest's rendered content — it **never mutates** the
423
- repository (no commits, no file writes, no script execution). Resolves HEAD
424
- exactly like `gtd step`, renders that state's declared
425
- `script`/`prompt`/`message` template, and prints it. `kind` is never `"commit"`
426
- here: resolution never rests at a commit state (entering one always ends the
427
- process in the same step that entered it — see
428
- [STATES.md §5](../STATES.md#5-resolution)).
429
-
430
- Plain mode prints the rendered content verbatim (with exactly one trailing
431
- newline) — never the `model`/`memory`/`file`/`mode`/`edges` structured keys,
432
- which are JSON-only. `--json` emits
433
- `{state, actor, kind, content, model?, memory?, file?, mode?, edges?}`:
434
-
435
- ```json
436
- {
437
- "state": "building",
438
- "actor": "agent",
439
- "kind": "prompt",
440
- "content": "You are an autonomous coding agent. ..."
441
- }
442
- ```
443
-
444
- - `state` — the resolved state.
445
- - `actor` — the state's declared actor.
446
- - `kind` — `"script"` | `"prompt"` | `"message"` — the dispatch key a driver
447
- switches on (see [Driving the loop](loop.md)).
448
- - `content` — the fully rendered template.
449
- - `model` — the state's opaque `model:` hint, RENDERED through the same template
450
- context as `content` (see
451
- [Configuration](configuration.md#model--the-opaque-harness-hint-template-rendered)),
452
- present only when the state declares one; **omitted entirely** (never `null`)
453
- when unset.
454
- - `memory` — the state's opaque `memory:` scope label, RENDERED the same way
455
- (see
456
- [Configuration](configuration.md#memory--the-memory-scope-label-template-rendered)).
457
- A memory-aware driver retains an agent's memory across consecutive agent turns
458
- sharing this label and starts fresh when it changes. Present only when the
459
- state declares one; **omitted entirely** (never `null`) when unset.
460
- - `file` — the state's declared steering file, RENDERED the same way; `mode` —
461
- its format's name, verbatim (a built-in `"qa"`/`"review"`, or a
462
- workflow-declared mode) (see
463
- [Configuration](configuration.md#filemode--the-steering-file-association)).
464
- Both present only when the state declares them; **omitted entirely** (never
465
- `null`) otherwise.
466
- - `edges` — the resting state's `on` edges as `[{ pattern, target, describe? }]`
467
- (declaration order) — the same list the content template sees as `it.edges`
468
- (see
469
- [Configuration](configuration.md#on-values--a-target-or-a--to-describe--route-description)).
470
- A driver relaying a human gate's message has the routing (and each edge's
471
- human-readable `describe`) alongside the rendered text. **Omitted entirely**
472
- when the state has no `on` (a commit state); a per-edge `describe` is likewise
473
- omitted when that edge declares none.
474
-
475
- ## `gtd edit [path]`
476
-
477
- Low-level plumbing: for the common case of "force an edit at the current human
478
- gate, then keep driving the loop", use `--edit` (below) instead. `gtd edit`
479
- itself only opens an editor on a path — it never drives anything afterward,
480
- which makes it the right tool for opening a SPECIFIC path (or peeking at the
481
- current rest's file) without starting a loop.
482
-
483
- Handled entirely in `bin/gtd`'s own bash — unlike every other subcommand, it is
484
- **never forwarded** to the compiled bundle (`dist/gtd.bundle.mjs`).
485
-
486
- With `<path>` given (repo-relative), opens it in `${VISUAL:-$EDITOR}` (git's own
487
- precedence — `$VISUAL` first, then `$EDITOR`; no fallback to `vi`), blocking in
488
- the foreground until the editor exits. It creates nothing if `<path>` doesn't
489
- exist — the path is handed straight to the editor command verbatim. The editor's
490
- own exit code is ignored entirely; success is judged from tree state afterward,
491
- not from this command.
492
-
493
- With no argument, it peeks with `gtd next --json` to find the resolved rest's
494
- declared `.file`, and opens that (repo-relative), or the repo directory (`.`)
495
- when the resolved state declares no `file:`. If `gtd next --json` itself fails
496
- (e.g. not in a repo), it prints an error and exits non-zero without attempting
497
- to open an editor:
498
-
499
- ```
500
- gtd edit: could not determine the next step:
501
- <gtd next --json's own error output>
502
- ```
503
-
504
- `gtd edit` **never** reads `--no-edit`/`--edit`/`GTD_NO_EDIT` — those govern
505
- only the loop's own automatic editor launching at human gates (see
506
- [Driving the loop](loop.md) and `skills/loop/SKILL.md`), not this command.
507
- Invoked directly, `gtd edit` always launches, unconditionally.
508
-
509
- If neither `$VISUAL` nor `$EDITOR` is set, no editor is launched:
510
-
511
- ```
512
- gtd: no editor configured — set $EDITOR (or $VISUAL)
513
- ```
514
-
515
- ## Running `script` rests (no `gtd` subcommand)
516
-
517
- There is no `gtd` subcommand that executes a workflow script — gtd never runs a
518
- workflow script itself. When `gtd next` resolves to a `script`-content rest, the
519
- **driver** (`bin/gtd`, or any loop harness) executes the emitted `content`
520
- verbatim via `bash -c` — foreground, inherited stdio, exit code deliberately
521
- ignored (a check script encodes its outcome in the tree, e.g. writing a findings
522
- file, never in its exit status) — then runs `gtd step <actor>` for that state's
523
- own actor to capture the outcome. See [Driving the loop](loop.md).
524
-
525
- ## `gtd status [--json]`
526
-
527
- Pure, read-only dry-run reporter — the same resolution `gtd next` performs, but
528
- reporting the resolved state/actor and, for every pending change, which declared
529
- `on` pattern (if any) matches it — no mutation, and no CONTENT rendering (the
530
- `script`/`prompt`/`message`/`commit` template is never rendered here, unlike
531
- `gtd next`). It DOES render the resolved state's `model:`/`memory:`/`file:`
532
- hints (if declared) through the same `it.vars`-carrying template context
533
- `gtd next` uses — see
534
- [Configuration](configuration.md#model--the-opaque-harness-hint-template-rendered)
535
- — so a templated `model:`/`memory:`/`file:` failing to render fails `gtd status`
536
- too, exactly like it would fail `gtd next`.
537
-
538
- ```
539
- State: working
540
- Awaits: agent
541
- Pending:
542
- A DONE.md -> A DONE.md
543
- A scratch.txt -> (no match)
544
- ```
545
-
546
- or, on a clean tree: `Pending: (clean)`. A `Model: <value>` line appears right
547
- after `Awaits:` when the resolved state declares a `model:` hint, and
548
- `Memory: <value>`/`File: <value>`/`Mode: <value>` lines appear after that (in
549
- that order) when declared — each independently, only when set. A `Cost: <n>`
550
- line appears after those when the current process has accumulated any
551
- `Gtd-Cost:` (see [`gtd step --cost`](#gtd-step-actor---costn-model-name)),
552
- omitted when the running total is `0`; when the breakdown adds information (more
553
- than one model, or a single tagged model), indented ` <model>: <cost>` lines
554
- follow it.
555
-
556
- `--json` emits
557
- `{state, actor, changes: [{status, path, pattern}], model?, memory?, file?, mode?, cost?, costByModel?, edges?}`
558
- — `pattern` is `null` when no declared row matches that change;
559
- `model`/`memory`/`file`/`mode` are present only when the resolved state declares
560
- them; `cost`/`costByModel` (the `[{model, cost}]` breakdown) only when the
561
- running process total is above `0`; and `edges` is the resting state's `on`
562
- edges as `[{ pattern, target, describe? }]` (same as `gtd next --json`), omitted
563
- when the state has no `on` (all omitted entirely, never `null`, otherwise):
564
-
565
- ```json
566
- {
567
- "state": "working",
568
- "actor": "agent",
569
- "changes": [
570
- { "status": "A", "path": "DONE.md", "pattern": "A DONE.md" },
571
- { "status": "A", "path": "scratch.txt", "pattern": null }
572
- ]
573
- }
574
- ```
575
-
576
- `gtd status` takes no arguments — extra positional args are rejected.
577
-
578
- ## `gtd validate [--json]`
579
-
580
- Format **and** validate the steering file the resolved rest declares. It
581
- resolves the current state exactly like `gtd status`, renders that state's
582
- `file:`, formats that file in place, then validates it — both per its `mode:`:
583
-
584
- - **formatting** happens only if the mode declares a `format:` shell command
585
- (see [Configuration](configuration.md#modes--pluggable-steering-file-modes)) —
586
- gtd ships no formatter, so nothing is rewritten until a project plugs one in;
587
- - **validation** runs the mode's `validate:` command when it declares one (its
588
- output becomes the findings), and otherwise, for the built-in `qa`/`review`
589
- names, gtd's own pure parser (`src/OpenQuestions.ts` / `src/ReviewDoc.ts` —
590
- the same parsers the LSP publishes as diagnostics, so there is one source of
591
- truth per format).
592
-
593
- Then:
594
-
595
- - A well-formed file exits `0` (`<file>: valid`, or `{"valid":true, ...}` with
596
- `--json`) — and is left formatted, if the mode formats at all.
597
- - Violations exit **non-zero** with the findings, one per line — the signal a
598
- producing agent, or the driving loop, loops on until the file is well-formed.
599
- - A state that declares no `file:`/`mode:`, or whose file is **absent** (e.g.
600
- `building` deleted `.gtd/TODO.md`, or a human deleted `.gtd/REVIEW.md` to
601
- approve), has nothing to validate and exits `0`
602
- (`nothing to validate at "<state>"`). Nothing is formatted in that case.
603
-
604
- This is how the unified template keeps its steering files well-formed without an
605
- in-machine validation state — and the check runs whoever last touched the file,
606
- agent or human:
607
-
608
- - **The producing agent self-validates.** Plain `gtd next` appends a "run
609
- `gtd validate` and fix all violations" instruction to a `prompt` rest that
610
- declares `file:`+`mode:`; `gtd next --json` withholds it and the driving loop
611
- runs `gtd validate` after the turn instead (see `bin/gtd` /
612
- [STATES.md §12](../STATES.md#12-steering-file-validation-gtd-validate)).
613
- - **`gtd step` enforces the same gate.** Capturing a turn out of a state that
614
- declares `file:`+`mode:` formats that file in place and validates it first
615
- (with the very same mode commands), and **refuses the step** (committing
616
- nothing) when it is invalid — so a human's edit at a gate (answering at
617
- `adv-grilling-answer`, reviewing at `await-review`) is formatted and checked
618
- exactly like an agent's draft, and a malformed steering file is never
619
- committed.
620
-
621
- `gtd validate` takes no arguments.
622
-
623
- ## `gtd lsp`
624
-
625
- Starts an LSP server over stdio for `.gtd/` steering files — document symbols
626
- for a `qa`-mode file's open questions and, for a `review`-mode file, one symbol
627
- per chunk that still has an unchecked hunk (the outline lists only the packages
628
- left to review, with no hunk children), code actions to check/uncheck a hunk or
629
- a whole chunk, go-to-definition (`textDocument/definition`) from a `review`-mode
630
- hunk pointer line into the file it points at (at its 1-based `#line`, or the top
631
- of the file for a bare `./path`; the `./`-relative path resolves against the
632
- repo's git toplevel), and diagnostics publishing the same parser findings
633
- `gtd validate` reports (see `src/OpenQuestions.ts` / `src/ReviewDoc.ts` and
634
- [STATES.md §12](../STATES.md#12-steering-file-validation-gtd-validate)).
635
-
636
- **Config-driven** (see
637
- [docs/design/state-file-association.md](design/state-file-association.md)): the
638
- server locates the active gtd config the same way the CLI does, from the
639
- `initialize` request's workspace root (falling back to the open document's own
640
- directory), renders every state's `file:` into an absolute-path → `mode` map,
641
- and dispatches on it — first declaring state wins a path conflict. A path the
642
- map doesn't cover (or no config at all) falls back to the basename dispatch
643
- (`TODO.md` → `qa`, `REVIEW.md` → `review`), so the server still works standalone
644
- with no `.gtdrc` in sight. Also registers an `executeCommand`,
645
- `gtd.openSteeringFile`: resolves the current state exactly like `gtd status`
646
- (config + git HEAD) and asks the client to show its `file:`
647
- (`window/showDocument`); a state with no `file:` gets an informational message
648
- naming the state instead — bind it to an editor keybinding for a "jump to the
649
- active steering file" command.
650
-
651
- Dispatched before the repository-root guard and the config-reading path — the
652
- server needs no git/workflow state of its own (like `gtd init`, it needs no
653
- config to run). Rejects `--json` (exit 1, `gtd lsp does not accept --json`) and
654
- extra positional arguments — it's a long-running server, not a state command.
655
- Runs until the client disconnects (the LSP `exit` notification), then exits
656
- cleanly.
657
-
658
- ## `gtd visualize [--port=<n>] [--no-open] [--json]`
659
-
660
- Serve an interactive diagram of the ACTIVE workflow on a local web server: the
661
- main flow as a graph (each sub-machine invocation collapsed into a single opaque
662
- black-box node — click it to jump to that sub-machine's own diagram, rendered
663
- separately below with its true member states/shapes/colours and a muted ghost
664
- node for any edge leaving the group; every diagram supports scroll-to-zoom,
665
- drag-to-pan, and a corner `+`/`−`/fit control cluster), a click-through
666
- inspector with each state's actor, content kind, its own raw
667
- prompt/message/script text, model/memory, steering file+mode, retry, flags, and
668
- outgoing/incoming edges, and — read ONCE at page load, never polled — a "Current
669
- state" panel showing where the active process rests, its pending changes, and
670
- which `on` pattern (or retry redirect) currently leads where, with the resting
671
- node highlighted in the diagrams. This is the replacement for the removed
672
- `gtd mermaid` — a live viewer instead of a static diagram dump.
673
-
674
- ```
675
- $ gtd visualize
676
- gtd visualize running at http://127.0.0.1:53017 — Ctrl-C to stop
677
- ```
678
-
679
- The server serves three routes: `/` (the self-contained HTML page),
680
- `/workflow.json` (the model the page renders), and `/state.json` (the current
681
- process's resting state, or `{}` when there isn't one — not a repo, no commits,
682
- or an older server; the browser tolerates either). It runs until interrupted
683
- (Ctrl-C), then closes cleanly. Options (orthogonal, `gtd visualize` only):
684
-
685
- - `--port=<n>` (or `--port <n>`) — serve on a specific port (0–65535); the
686
- default is a free ephemeral port, printed on start.
687
- - `--no-open` — do not open the default browser (the URL is always printed).
688
- - `--json` — print the workflow model to stdout and exit WITHOUT starting a
689
- server (unchanged shape — live state is a server-only concern). The model is
690
- `{ states, initial, groups, vars }`; each state carries its
691
- `actor`/`kind`/`content`/`model`/`memory`/`file`/`mode`/`retry`/`flags`
692
- (`content` is the state's own raw script/prompt/message text, omitted for a
693
- commit state), its `on` edges, its computed `incoming` edges, and its
694
- sub-machine `group`. `groups` lists each sub-machine invocation and the
695
- concrete states it produced.
696
-
697
- Dispatched before the repository-root guard and the config-reading path's review
698
- window — it reads the active workflow (the built-in default when none is
699
- configured) but touches no git/HEAD/review-window state ITSELF; the
700
- `/state.json` route best-effort reads git state per request instead (any failure
701
- — not a repo, no commits — serves `{}`), preferring the review checkout window's
702
- saved head over HEAD so a request landing mid-window still reports the state the
703
- process actually rests at. The diagram is rendered with Mermaid loaded from a
704
- CDN, so the graph needs network access the first time a browser loads the page;
705
- the inspector and current-state panel work offline regardless. Rejects unknown
706
- options and unexpected positional arguments.
707
-
708
- ## Error envelope
709
-
710
- Every command, in `--json` mode, reports a failure as a machine-readable
711
- envelope on **stdout**, and still exits 1:
712
-
713
- ```json
714
- { "state": "error", "prompt": "<message>" }
715
- ```
716
-
717
- A human-readable `gtd: <message>` line is still written to **stderr** regardless
718
- of `--json` — the envelope adds a structured stdout channel, it does not replace
719
- the plain-text one.
720
-
721
- ## Repository requirements
722
-
723
- - **Single writer, linear branch.** A process's history is walked via
724
- **first-parent** commits only.
725
- - **Test/build artifacts must be gitignored.** This is **load-bearing**, not a
726
- style preference: every step decision detects "clean" via
727
- `git diff --name-status HEAD` (tracked changes) unioned with
728
- `git ls-files --others --exclude-standard` (untracked files), which silently
729
- omits anything matched by `.gitignore`. If a `script` state's command (or the
730
- build it triggers) writes tracked-but-untracked output — a `dist/`, a coverage
731
- report, a log file — into the working tree, the tree never goes clean after a
732
- green run, and the check's `"C"` pattern never fires. Gitignore every path
733
- your scripts write before wiring gtd into a repo.
734
- - **Repository root invocation.** Every state subcommand (`step`/`review`/
735
- `next`/`status`) must run from the git repository root — the workflow, pending
736
- changes, and process history are resolved against the process cwd.
737
- `--help`/`--version` (and the `help`/`version` subcommands), `lsp`, and
738
- `visualize` skip this guard entirely (`visualize` still reads the `.gtdrc`
739
- workflow, but needs no git state).
740
- - **Linked worktrees are independent.** N `git worktree` worktrees of one
741
- repository (sharing a single `.git`) each run their own gtd process: state is
742
- derived from that worktree's own HEAD, and the review checkout window's refs
743
- live in git's per-worktree `refs/worktree/gtd/*` namespace, so a review
744
- resting in one worktree neither blocks nor rewrites any other
745
- ([STATES.md §11](../STATES.md#11-the-review-checkout-window)). This holds from
746
- 7.2 on; gtd ≤ 7.1 kept the window under the shared `refs/gtd/*` refs, where
747
- the first worktree to open one clobbered every sibling's branch.