@bastani/atomic 0.6.4 → 0.6.5-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 (120) hide show
  1. package/.agents/skills/create-spec/SKILL.md +6 -3
  2. package/.agents/skills/tdd/SKILL.md +107 -0
  3. package/.agents/skills/tdd/deep-modules.md +33 -0
  4. package/.agents/skills/tdd/interface-design.md +31 -0
  5. package/.agents/skills/tdd/mocking.md +59 -0
  6. package/.agents/skills/tdd/refactoring.md +10 -0
  7. package/.agents/skills/tdd/tests.md +61 -0
  8. package/.agents/skills/workflow-creator/SKILL.md +550 -0
  9. package/.agents/skills/workflow-creator/references/agent-sessions.md +891 -0
  10. package/.agents/skills/workflow-creator/references/agent-setup-recipe.md +266 -0
  11. package/.agents/skills/workflow-creator/references/computation-and-validation.md +201 -0
  12. package/.agents/skills/workflow-creator/references/control-flow.md +470 -0
  13. package/.agents/skills/workflow-creator/references/failure-modes.md +1014 -0
  14. package/.agents/skills/workflow-creator/references/getting-started.md +392 -0
  15. package/.agents/skills/workflow-creator/references/registry-and-validation.md +141 -0
  16. package/.agents/skills/workflow-creator/references/running-workflows.md +418 -0
  17. package/.agents/skills/workflow-creator/references/session-config.md +384 -0
  18. package/.agents/skills/workflow-creator/references/state-and-data-flow.md +356 -0
  19. package/.agents/skills/workflow-creator/references/user-input.md +234 -0
  20. package/.agents/skills/workflow-creator/references/workflow-inputs.md +392 -0
  21. package/.claude/agents/debugger.md +2 -2
  22. package/.claude/agents/reviewer.md +1 -1
  23. package/.claude/agents/worker.md +2 -2
  24. package/.github/agents/debugger.md +1 -1
  25. package/.github/agents/worker.md +1 -1
  26. package/.mcp.json +5 -1
  27. package/.opencode/agents/debugger.md +1 -1
  28. package/.opencode/agents/worker.md +1 -1
  29. package/README.md +236 -201
  30. package/dist/sdk/define-workflow.d.ts +11 -6
  31. package/dist/sdk/define-workflow.d.ts.map +1 -1
  32. package/dist/sdk/errors.d.ts +10 -0
  33. package/dist/sdk/errors.d.ts.map +1 -1
  34. package/dist/sdk/index.d.ts +21 -9
  35. package/dist/sdk/index.d.ts.map +1 -1
  36. package/dist/sdk/primitives/inputs.d.ts +36 -0
  37. package/dist/sdk/primitives/inputs.d.ts.map +1 -0
  38. package/dist/sdk/primitives/metadata.d.ts +40 -0
  39. package/dist/sdk/primitives/metadata.d.ts.map +1 -0
  40. package/dist/sdk/primitives/run.d.ts +57 -0
  41. package/dist/sdk/primitives/run.d.ts.map +1 -0
  42. package/dist/sdk/primitives/sessions.d.ts +128 -0
  43. package/dist/sdk/primitives/sessions.d.ts.map +1 -0
  44. package/dist/sdk/runtime/executor.d.ts +24 -56
  45. package/dist/sdk/runtime/executor.d.ts.map +1 -1
  46. package/dist/sdk/runtime/orchestrator-entry.d.ts +26 -0
  47. package/dist/sdk/runtime/orchestrator-entry.d.ts.map +1 -0
  48. package/dist/sdk/runtime/tmux.d.ts +20 -0
  49. package/dist/sdk/runtime/tmux.d.ts.map +1 -1
  50. package/dist/sdk/types.d.ts +26 -86
  51. package/dist/sdk/types.d.ts.map +1 -1
  52. package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts.map +1 -1
  53. package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts.map +1 -1
  54. package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts.map +1 -1
  55. package/dist/sdk/workflows/builtin/open-claude-design/claude/index.d.ts.map +1 -1
  56. package/dist/sdk/workflows/builtin/open-claude-design/copilot/index.d.ts.map +1 -1
  57. package/dist/sdk/workflows/builtin/open-claude-design/opencode/index.d.ts.map +1 -1
  58. package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts.map +1 -1
  59. package/dist/sdk/workflows/builtin/ralph/copilot/index.d.ts.map +1 -1
  60. package/dist/sdk/workflows/builtin/ralph/opencode/index.d.ts.map +1 -1
  61. package/dist/sdk/workflows/index.d.ts +20 -12
  62. package/dist/sdk/workflows/index.d.ts.map +1 -1
  63. package/dist/services/config/additional-instructions.d.ts +1 -1
  64. package/dist/services/config/additional-instructions.d.ts.map +1 -1
  65. package/package.json +4 -4
  66. package/src/cli.ts +39 -56
  67. package/src/commands/builtin-registry.ts +37 -0
  68. package/src/commands/cli/chat/index.ts +1 -3
  69. package/src/{sdk → commands/cli}/management-commands.ts +15 -55
  70. package/src/commands/cli/session.ts +1 -1
  71. package/src/commands/cli/workflow-command.test.ts +250 -16
  72. package/src/commands/cli/workflow-inputs.test.ts +1 -0
  73. package/src/commands/cli/workflow-inputs.ts +13 -3
  74. package/src/commands/cli/workflow-list.test.ts +1 -0
  75. package/src/commands/cli/workflow-list.ts +0 -0
  76. package/src/commands/cli/workflow-status.ts +1 -1
  77. package/src/commands/cli/workflow.ts +191 -11
  78. package/src/sdk/define-workflow.test.ts +47 -16
  79. package/src/sdk/define-workflow.ts +24 -6
  80. package/src/sdk/errors.test.ts +11 -0
  81. package/src/sdk/errors.ts +13 -0
  82. package/src/sdk/index.test.ts +92 -0
  83. package/src/sdk/index.ts +71 -15
  84. package/src/sdk/primitives/inputs.ts +48 -0
  85. package/src/sdk/primitives/metadata.ts +63 -0
  86. package/src/sdk/primitives/run.ts +81 -0
  87. package/src/sdk/primitives/sessions.test.ts +594 -0
  88. package/src/sdk/primitives/sessions.ts +328 -0
  89. package/src/sdk/runtime/executor.ts +36 -115
  90. package/src/sdk/runtime/orchestrator-entry.ts +110 -0
  91. package/src/sdk/runtime/tmux.ts +33 -0
  92. package/src/sdk/types.ts +26 -91
  93. package/src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts +1 -0
  94. package/src/sdk/workflows/builtin/deep-research-codebase/copilot/index.ts +1 -0
  95. package/src/sdk/workflows/builtin/deep-research-codebase/opencode/index.ts +1 -0
  96. package/src/sdk/workflows/builtin/open-claude-design/claude/index.ts +1 -0
  97. package/src/sdk/workflows/builtin/open-claude-design/copilot/index.ts +1 -0
  98. package/src/sdk/workflows/builtin/open-claude-design/opencode/index.ts +1 -0
  99. package/src/sdk/workflows/builtin/ralph/claude/index.ts +1 -0
  100. package/src/sdk/workflows/builtin/ralph/copilot/index.ts +1 -0
  101. package/src/sdk/workflows/builtin/ralph/opencode/index.ts +1 -0
  102. package/src/sdk/workflows/index.ts +68 -51
  103. package/src/services/config/additional-instructions.ts +1 -1
  104. package/.agents/skills/test-driven-development/SKILL.md +0 -371
  105. package/.agents/skills/test-driven-development/testing-anti-patterns.md +0 -299
  106. package/dist/commands/cli/session.d.ts +0 -67
  107. package/dist/commands/cli/session.d.ts.map +0 -1
  108. package/dist/commands/cli/workflow-status.d.ts +0 -63
  109. package/dist/commands/cli/workflow-status.d.ts.map +0 -1
  110. package/dist/sdk/commander.d.ts +0 -74
  111. package/dist/sdk/commander.d.ts.map +0 -1
  112. package/dist/sdk/management-commands.d.ts +0 -42
  113. package/dist/sdk/management-commands.d.ts.map +0 -1
  114. package/dist/sdk/workflow-cli.d.ts +0 -103
  115. package/dist/sdk/workflow-cli.d.ts.map +0 -1
  116. package/dist/sdk/workflows/builtin-registry.d.ts +0 -113
  117. package/dist/sdk/workflows/builtin-registry.d.ts.map +0 -1
  118. package/src/sdk/commander.ts +0 -161
  119. package/src/sdk/workflow-cli.ts +0 -409
  120. package/src/sdk/workflows/builtin-registry.ts +0 -23
@@ -0,0 +1,418 @@
1
+ # Running a Workflow on Behalf of the User
2
+
3
+ When the user asks you to **run** (or "kick off" / "start" / "execute") a
4
+ workflow — *not* author one — your job is to translate their request into the
5
+ correct invocation and run it. This is the playbook for that flow. It is
6
+ different from the authoring playbook in `SKILL.md`: the workflow already
7
+ exists in a registry; you just need to invoke it correctly.
8
+
9
+ **This playbook works from any context.** Whether you're running in a fresh terminal, inside `atomic chat -a <agent>`, or from a CI script, the decision tree below is the same — atomic builtins, repo examples, and user SDK workflows are all discoverable and invokable. If the user is chatting with you through `atomic chat` and says "start my hello-world workflow", walk the same three paths; the shared tmux socket means the workflow you spawn will be visible to every monitoring surface (the worker CLI's own `status` / `session` subcommands, `atomic workflow status`, and `bunx atomic …`) regardless of which path you used to start it.
10
+
11
+ ## Three invocation paths
12
+
13
+ **Path A — user's own app.** The user wrote one or more composition
14
+ roots. Two shapes exist — pick based on what the file calls:
15
+
16
+ - **Single-workflow worker** (`runWorkflow({ workflow, inputs })`) —
17
+ one file per agent, bound to one `WorkflowDefinition`. The dev wires
18
+ `--<input>` Commander options for each declared input using
19
+ `getInputSchema(wf)`. Typical name: `claude-worker.ts`.
20
+
21
+ ```bash
22
+ bun run src/claude-worker.ts --<field>=<value> # structured inputs
23
+ bun run src/claude-worker.ts "<prompt>" # positional (if the worker wired [prompt...])
24
+ ```
25
+
26
+ For detached runs, the dev passes `detach: true` to `runWorkflow` or
27
+ wires their own `--detach` Commander option. There are no built-in
28
+ `-n`/`-a`/`-d` flags on user-app workers.
29
+
30
+ - **Multi-workflow CLI** (`createRegistry()` + `listWorkflows`) —
31
+ a single file that registers many workflows and mounts one Commander
32
+ subcommand per workflow. The subcommand name is the workflow name; each
33
+ subcommand's options are the workflow's declared inputs.
34
+
35
+ ```bash
36
+ bun run src/cli.ts <workflow-name> --<field>=<value>
37
+ bun run src/cli.ts <workflow-name> "<prompt>" # if the subcommand wires [prompt...]
38
+ ```
39
+
40
+ **Path B — repo-shipped examples.** Inside the Atomic repo each example
41
+ directory ships one worker file per agent (`claude-worker.ts`,
42
+ `copilot-worker.ts`, `opencode-worker.ts`). Each is a Commander entrypoint
43
+ built with `getInputSchema(wf)`:
44
+
45
+ ```bash
46
+ bun run examples/<name>/claude-worker.ts --<field>=<value>
47
+ bun run examples/<name>/copilot-worker.ts "<prompt>" # if the worker wires [prompt...]
48
+ ```
49
+
50
+ Available examples: `hello-world`, `parallel-hello-world`, `headless-test`,
51
+ `hil-favorite-color`, `hil-favorite-color-headless`, `structured-output-demo`,
52
+ `reviewer-tool-test` (copilot only). Use these to demonstrate a specific SDK
53
+ feature or as a copy-paste starting point.
54
+
55
+ **Path C — atomic builtins.** Workflows shipped inside `@bastani/atomic`
56
+ and registered via `createBuiltinRegistry()` inside the `atomic` CLI:
57
+
58
+ ```bash
59
+ atomic workflow -n <name> -a <agent> [inputs...]
60
+ atomic workflow list
61
+ ```
62
+
63
+ Builtin names: `ralph`, `deep-research-codebase`, `open-claude-design`.
64
+
65
+ Direct `atomic workflow` runs should always include `-n <name>` and
66
+ `-a <agent>`. Use `-d` when launching from an agent or script and you want
67
+ the command to return after spawning the workflow.
68
+
69
+ **Identify the path before anything else.** Decision order:
70
+
71
+ 1. Is the name one of the three builtins (`ralph`, `deep-research-codebase`,
72
+ `open-claude-design`)? → **Path C** (`atomic workflow`).
73
+ 2. Does `examples/<name>/<agent>-worker.ts` exist in the current repo? →
74
+ **Path B** (`bun run examples/<name>/<agent>-worker.ts`).
75
+ 3. Does a composition root exist in `src/` (single-workflow
76
+ `runWorkflow({ workflow })` file, or a cli `createRegistry()` + `listWorkflows`
77
+ file)? → **Path A**.
78
+ 4. None of the above → the workflow doesn't exist. Offer to author it
79
+ (see below).
80
+
81
+ ## Always list first
82
+
83
+ **Before running, list available workflows.** This is a cheap, read-only
84
+ call that confirms whether the named workflow actually exists:
85
+
86
+ ```bash
87
+ # Atomic builtins
88
+ atomic workflow list
89
+
90
+ # Repo-shipped examples (when inside the atomic repo)
91
+ bun run examples/<name>/<agent>-worker.ts --help
92
+
93
+ # User's own app with an explicit list/help command
94
+ bun run src/cli.ts list
95
+ ```
96
+
97
+ If the user app has no read-only list/help command, inspect its composition
98
+ root instead of running `-n <name> -a <agent>` as a probe — that would start
99
+ the workflow when the name is valid.
100
+
101
+ The list/help output or source inspection tells you:
102
+ - Whether the workflow the user named actually exists.
103
+ - What other workflows are available (close matches for typos).
104
+
105
+ Skipping this step is how you end up with a `workflow not found` error you
106
+ could have predicted.
107
+
108
+ If the request is ambiguous ("run the research one"), show the list to the
109
+ user and ask with AskUserQuestion.
110
+
111
+ ## If the workflow doesn't exist: offer to create it
112
+
113
+ When the listed workflows don't include what the user asked for:
114
+
115
+ 1. **Tell the user explicitly** — "I don't see a `<name>` workflow registered.
116
+ Available: \<short list>."
117
+ 2. **Check for typos first** — if one of the listed names is a close match,
118
+ surface it via AskUserQuestion ("Did you mean `<close-match>`?") before
119
+ offering to author anything.
120
+ 3. **Offer to create it** — ask with AskUserQuestion: "Want me to create a
121
+ `<name>` workflow first?" with choices `Yes, create it` / `No, pick from
122
+ the list` / `No, cancel`.
123
+ 4. **If yes → switch modes** — hand off to the authoring flow in SKILL.md.
124
+ Interview the user for intent, write the workflow definition, register it
125
+ in the composition root, typecheck it, *then* come back here and invoke.
126
+ Do not skip the typecheck.
127
+ 5. **If no → stop** — don't fabricate a command that will fail. Let the user
128
+ redirect you.
129
+
130
+ Never invent a workflow name or silently fall back to a different workflow.
131
+
132
+ ## Collecting inputs with AskUserQuestion
133
+
134
+ Once you've confirmed the workflow exists, you need to know two things about
135
+ its invocation shape:
136
+
137
+ 1. **Does it declare a `prompt` input?** If so, it's free-form — you pass a
138
+ positional string.
139
+ 2. **Does it declare structured inputs?** If so, you pass `--<field>=<value>`
140
+ flags, one per required field.
141
+
142
+ **Use `atomic workflow inputs <name> -a <agent>` to get the schema for atomic builtins.** This prints a JSON envelope with every field's `name`, `type`, `required`, `default`, `description`, and (for enums) `values` — exactly what AskUserQuestion needs. The `freeform: true` flag tells you whether the workflow takes a positional prompt vs. structured flags, with a synthetic `prompt` field included so the JSON shape is uniform either way.
143
+
144
+ ```bash
145
+ atomic workflow inputs gen-spec -a claude
146
+ # {"workflow":"gen-spec","agent":"claude","freeform":false,
147
+ # "inputs":[{"name":"research_doc","type":"string","required":true,...},
148
+ # {"name":"focus","type":"enum","values":["minimal","standard","exhaustive"],"default":"standard"}]}
149
+ ```
150
+
151
+ For user apps, read the workflow definition's `inputs` array directly or
152
+ inspect the TypeScript source — the schema is inline in `defineWorkflow({
153
+ inputs: [...] })`. Reading the source is always in sync because `defineWorkflow`
154
+ validates the schema at definition time.
155
+
156
+ `atomic workflow inputs` is a builtin-only command — it queries the
157
+ internal builtin registry and is not available for user apps. For user
158
+ app workflows, always read the `defineWorkflow` source directly.
159
+
160
+ Once you have the schema, use the **AskUserQuestion tool** to collect any
161
+ values the user hasn't already provided in their message. One question per
162
+ missing input field. For enum fields, pass the declared `values` as
163
+ multiple-choice options so the user sees exactly what's allowed. Keep
164
+ questions tight and purposeful — if the user's message already answers a
165
+ question, don't ask it again.
166
+
167
+ Skip AskUserQuestion entirely when:
168
+ - The user already supplied every required value in their message
169
+ ("run ralph on 'add OAuth to the API'" — the prompt is right there).
170
+ - The workflow declares no required inputs and needs no prompt.
171
+
172
+ ## End-to-end recipe
173
+
174
+ 1. **Identify the invocation path** — atomic builtin (`atomic workflow`),
175
+ repo-shipped example (`bun run examples/<name>/<agent>-worker.ts`), or
176
+ the user's own app (single-workflow `src/<agent>-worker.ts` or
177
+ multi-workflow `src/cli.ts`)?
178
+ 2. **List available workflows** — run the list command for the chosen path.
179
+ This is your ground truth.
180
+ 3. **Resolve the target**:
181
+ - Exact match in the list → continue.
182
+ - Close match → confirm via AskUserQuestion before proceeding.
183
+ - No match → tell the user what's available and offer to author it (see
184
+ previous section). If they decline, stop.
185
+ 4. **Discover the inputs schema** — for builtins use `atomic workflow inputs
186
+ <name> -a <agent>`; for user apps inspect the `defineWorkflow` source.
187
+ 5. **Ask for missing inputs** — use AskUserQuestion, one question per
188
+ unanswered required field. Enums become multiple-choice.
189
+ 6. **Invoke** — build one of these commands:
190
+
191
+ User's own app — single-workflow worker:
192
+ - Free-form: `bun run src/<agent>-worker.ts "<prompt>"` (only if the worker wires `[prompt...]`)
193
+ - Structured: `bun run src/<agent>-worker.ts --field1=val1`
194
+ - Detached: pass `detach: true` to `runWorkflow` or use the dev's own `--detach` option
195
+
196
+ User's own app — multi-workflow CLI:
197
+ - Free-form: `bun run src/cli.ts <workflow-name> "<prompt>"` (only if wired)
198
+ - Structured: `bun run src/cli.ts <workflow-name> --field1=val1`
199
+ - Detached: same as above (dev-wired `--detach` or `detach: true`)
200
+
201
+ Repo-shipped example (inside atomic repo):
202
+ - Free-form: `bun run examples/<name>/<agent>-worker.ts "<prompt>"` (only if wired)
203
+ - Structured: `bun run examples/<name>/<agent>-worker.ts --field1=val1`
204
+
205
+ Atomic builtins:
206
+ - Free-form: `atomic workflow -n <name> -a <agent> "<prompt>"`
207
+ - Structured: `atomic workflow -n <name> -a <agent> --<field1>=<value1>`
208
+ - Detached: add `-d`
209
+
210
+ 7. **Report the session name** the CLI printed and tell the user: "attach any
211
+ time with `atomic workflow session connect <session>` — or
212
+ `atomic workflow session list` to see what's running."
213
+
214
+ ## Monitoring a running workflow
215
+
216
+ All three invocation paths (Path A, B, C) spawn sessions on the same `atomic`
217
+ tmux socket. Two surfaces expose monitoring commands:
218
+
219
+ 1. **The global `atomic` binary (recommended for all paths).** Session
220
+ management lives under `atomic session …` and `atomic workflow status`:
221
+ ```bash
222
+ atomic session list
223
+ atomic workflow status <session-id>
224
+ atomic session connect <session-id>
225
+ atomic session kill <session-id> -y
226
+ ```
227
+ 2. **SDK-only fallback — `bunx atomic`.** Any project with `@bastani/atomic`
228
+ as a dep ships the full `atomic` binary at `node_modules/.bin/atomic`. Use
229
+ this when the global binary is not installed.
230
+
231
+ `runWorkflow` does **not** auto-register `session` or `status` subcommands on
232
+ user-app worker files. If the dev wants those commands inside their own CLI,
233
+ they wire them explicitly using the SDK session primitives:
234
+
235
+ ```ts
236
+ import {
237
+ listSessions,
238
+ stopSession,
239
+ attachSession,
240
+ getSessionStatus,
241
+ } from "@bastani/atomic/workflows";
242
+ ```
243
+
244
+ Because every workflow lands on the same atomic tmux socket regardless of
245
+ which path spawned it, the `atomic` CLI commands work for Path A and B
246
+ workflows just as well as for atomic builtins.
247
+
248
+ Detached workflows return immediately with a session name; the actual work
249
+ runs in the background. Use `status` to check whether the workflow is still
250
+ running, has completed, errored out, or paused for human input — without
251
+ attaching to its TUI.
252
+
253
+ ```bash
254
+ # Via the global `atomic` CLI:
255
+ atomic workflow status atomic-wf-claude-gen-spec-a1b2c3d4
256
+
257
+ # Via bunx atomic (SDK-only, no global install):
258
+ bunx atomic workflow status atomic-wf-claude-gen-spec-a1b2c3d4
259
+
260
+ # Output:
261
+ # {"id":"atomic-wf-claude-gen-spec-a1b2c3d4","overall":"in_progress","alive":true,
262
+ # "sessions":[{"name":"orchestrator","status":"running",...}],...}
263
+ ```
264
+
265
+ Four overall states the agent must handle distinctly:
266
+
267
+ | Status | Meaning | What you should do |
268
+ |---|---|---|
269
+ | `in_progress` | The orchestrator is running and no stage is paused | Wait, or report progress to the user |
270
+ | `needs_review` | At least one stage is paused for human input (HIL) — Copilot `ask_user`, OpenCode `question.asked`, Copilot/MCP elicitation | **Surface this to the user immediately** — they need to attach with `atomic workflow session connect <id>` to respond, otherwise the workflow stalls indefinitely |
271
+ | `completed` | Workflow finished successfully | Report success and summarize the output |
272
+ | `error` | Fatal error or a stage failed | Report the `fatalError` field and offer to investigate logs |
273
+
274
+ `needs_review` outranks `completed` so a HIL pause near the end is never
275
+ reported as done while still waiting on a human. A dead orchestrator with a
276
+ stale snapshot is automatically downgraded to `error`.
277
+
278
+ Omit the id to list every running workflow at once: `atomic workflow status`.
279
+ Useful when checking on multiple parallel runs, or when the user just asks
280
+ "what's running?".
281
+
282
+ ## Cleaning up sessions
283
+
284
+ When the user is done with a workflow — or you launched one detached and it's
285
+ no longer needed — tear it down with `-y` so no confirmation prompt blocks you:
286
+
287
+ ```bash
288
+ # Via the global atomic binary (works for all three paths — same tmux socket):
289
+ atomic session kill atomic-wf-claude-gen-spec-a1b2c3d4 -y
290
+
291
+ # Via bunx atomic (SDK-only, no global install):
292
+ bunx atomic session kill atomic-wf-claude-gen-spec-a1b2c3d4 -y
293
+ ```
294
+
295
+ The `-y` flag is mandatory for agent use. Without it, the CLI calls
296
+ `@clack/prompts confirm`, which expects a TTY and will hang indefinitely in a
297
+ non-interactive context. Same flag works for `atomic workflow session kill`
298
+ and `atomic chat session kill`. Without an id, `kill -y` tears down every
299
+ in-scope session — only do that when the user has asked to stop everything.
300
+
301
+ ## Worked examples
302
+
303
+ **Example A — atomic builtin, structured inputs**
304
+
305
+ > **User:** "run gen-spec on research/docs/2026-04-11-auth.md"
306
+
307
+ *(Note: `gen-spec` is a hypothetical builtin used here for pedagogical purposes. Real atomic builtins are `ralph`, `deep-research-codebase`, and `open-claude-design`.)*
308
+
309
+ 1. Path C (atomic builtin). Run `atomic workflow list`. Output includes `gen-spec`. Good.
310
+ 2. Target resolved exactly: `gen-spec`.
311
+ 3. Run `atomic workflow inputs gen-spec -a claude`. Parse the JSON:
312
+ `research_doc` (required string — already given), `focus` (required enum
313
+ of `minimal|standard|exhaustive`, default `standard`), `notes`
314
+ (optional text).
315
+ 4. Ask via AskUserQuestion once: "What focus level for the spec?" with
316
+ choices `minimal`, `standard`, `exhaustive`. User picks `standard`. Skip
317
+ `notes` since it's optional.
318
+ 5. Run: `atomic workflow -n gen-spec -a claude --research_doc=research/docs/2026-04-11-auth.md --focus=standard`
319
+ 6. The CLI prints a session name like `atomic-wf-claude-gen-spec-a1b2c3d4`.
320
+ Tell the user: "Started in the background. Attach with
321
+ `atomic workflow session connect atomic-wf-claude-gen-spec-a1b2c3d4`,
322
+ check progress with `atomic workflow status atomic-wf-claude-gen-spec-a1b2c3d4`,
323
+ or stop it with `atomic session kill atomic-wf-claude-gen-spec-a1b2c3d4 -y`."
324
+
325
+ **Example B — user app, free-form prompt**
326
+
327
+ > **User:** "run the summarize-pr workflow on 'add OAuth to the API'"
328
+
329
+ 1. Path A. `src/claude-worker.ts` exists and calls `runWorkflow(summarizePrClaude)`.
330
+ (If instead the user had a `src/cli.ts` with `createRegistry()` + `listWorkflows`,
331
+ run `bun run src/cli.ts --help` to see the registered subcommands and confirm `summarize-pr`.)
332
+ 2. Target resolved exactly: `summarize-pr`, agent `claude`.
333
+ 3. Prompt already given in user's message. No AskUserQuestion needed. Check
334
+ `defineWorkflow` source to confirm `prompt` is a declared input.
335
+ 4. Run: `bun run src/claude-worker.ts --prompt="add OAuth to the API"`.
336
+ (If the worker was built with a `[prompt...]` Commander argument, the positional
337
+ form `bun run src/claude-worker.ts "add OAuth to the API"` works too.)
338
+ The runtime prints a session name like `atomic-wf-claude-summarize-pr-a1b2c3d4`.
339
+ For a detached run, the worker must wire `detach: true` to `runWorkflow` or
340
+ expose its own `--detach` Commander option — there is no built-in `-d` on
341
+ user-app workers.
342
+ 5. Report monitoring commands using the global `atomic` CLI (recommended — no
343
+ extra setup, works for all three paths):
344
+ - "Attach: `atomic session connect atomic-wf-claude-summarize-pr-a1b2c3d4`"
345
+ - "Status: `atomic workflow status atomic-wf-claude-summarize-pr-a1b2c3d4`"
346
+ - "Stop: `atomic session kill atomic-wf-claude-summarize-pr-a1b2c3d4 -y`"
347
+ 6. `bunx atomic …` is equivalent if the global binary is not installed. Both
348
+ talk to the same atomic tmux socket regardless of which path spawned the
349
+ workflow.
350
+
351
+ **Example B1b — repo-shipped example, structured inputs**
352
+
353
+ > **User:** "run the hello-world example with a formal greeting"
354
+
355
+ 1. Not a builtin name. Check `examples/hello-world/claude-worker.ts` — it exists.
356
+ Path B.
357
+ 2. Target resolved: `hello-world`, via `examples/hello-world/claude-worker.ts`.
358
+ 3. Read `examples/hello-world/claude/index.ts` for the input schema:
359
+ `greeting` (string, required), `style` (enum: formal/casual/robotic,
360
+ default casual), `notes` (text, optional).
361
+ 4. Ask via AskUserQuestion: "What should the greeting text be?" User
362
+ supplies `"Hello there"`. `style=formal` is implied by the message.
363
+ 5. Run: `bun run examples/hello-world/claude-worker.ts --greeting="Hello there" --style=formal`
364
+ 6. Report the session name.
365
+
366
+ **Example B2 — atomic builtin, free-form prompt**
367
+
368
+ > **User:** "run ralph on 'add OAuth to the API'"
369
+
370
+ 1. Path C (atomic builtin — `ralph` is shipped inside `@bastani/atomic`).
371
+ Run `atomic workflow list`. Confirms `ralph` is registered.
372
+ 2. Target resolved exactly: `ralph`, agent `claude`.
373
+ 3. Prompt already given in user's message. No AskUserQuestion needed.
374
+ 4. Run: `atomic workflow -n ralph -a claude "add OAuth to the API"`.
375
+ 5. Report the session name.
376
+
377
+ **Example C — workflow does not exist**
378
+
379
+ > **User:** "run the security-audit workflow on src/auth"
380
+
381
+ 1. This sounds like a user app workflow. Run `bun run src/cli.ts --help` to
382
+ list available subcommands. Output shows: `summarize-pr`, `triage-pr`. No `security-audit`.
383
+ 2. Tell the user: "I don't see a `security-audit` workflow registered. Available: summarize-pr, triage-pr."
384
+ 3. Ask via AskUserQuestion: "Want me to create a `security-audit` workflow
385
+ first?" with choices `Yes, create it`, `No, use one of the existing
386
+ workflows`, `No, cancel`.
387
+ 4. If **Yes**: switch to SKILL.md's Authoring Process — interview the user
388
+ for what the workflow should do, write the definition, register it in the
389
+ composition root, typecheck, *then* return here and invoke.
390
+ 5. If **No, use existing**: ask which one via AskUserQuestion, then continue.
391
+ 6. If **Cancel**: stop, no command runs.
392
+
393
+ ## Common mistakes to avoid
394
+
395
+ - **Not identifying the invocation path** — using `atomic workflow` for a
396
+ user app, or `bun run src/worker.ts` for a builtin or a repo-shipped
397
+ example, leads to "not found". Check the three paths in order (builtin
398
+ → examples/ → user app) first.
399
+ - **Skipping the list command** — leads to guessing and `workflow not found`
400
+ errors. Always list first.
401
+ - **Using `-n`/`-a`/`-d` on user-app workers** — these flags only exist on
402
+ the `atomic` binary for builtins. User-app workers expose per-input `--<flag>`
403
+ options and (optionally) a positional `[prompt...]` argument. There is no
404
+ `-n`, `-a`, or `-d` built into user-app workers.
405
+ - **Inventing a workflow name** — if it's not in the list, it doesn't exist.
406
+ Say so and offer to author it.
407
+ - **For builtins: reading the source to discover inputs** — use
408
+ `atomic workflow inputs <name> -a <agent>` instead. JSON, always in sync.
409
+ - **Asking everything at once** — let AskUserQuestion drive one question per
410
+ field. Enum fields are multiple-choice, not free text.
411
+ - **Re-asking what the user already said** — read their message first.
412
+ - **Forgetting to report the session name** — the user needs it to reattach
413
+ and to query status later.
414
+ - **Leaving `needs_review` unreported** — when `atomic workflow status`
415
+ returns `needs_review`, surface it to the user right away. The workflow is
416
+ blocked on human input and will sit forever otherwise.
417
+ - **Calling `session kill` without `-y`** — the prompt hangs in a
418
+ non-interactive context. Always pass `-y` from an agent.