@bastani/atomic 0.6.4 → 0.6.5
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/.agents/skills/create-spec/SKILL.md +6 -3
- package/.agents/skills/tdd/SKILL.md +107 -0
- package/.agents/skills/tdd/deep-modules.md +33 -0
- package/.agents/skills/tdd/interface-design.md +31 -0
- package/.agents/skills/tdd/mocking.md +59 -0
- package/.agents/skills/tdd/refactoring.md +10 -0
- package/.agents/skills/tdd/tests.md +61 -0
- package/.agents/skills/workflow-creator/SKILL.md +550 -0
- package/.agents/skills/workflow-creator/references/agent-sessions.md +891 -0
- package/.agents/skills/workflow-creator/references/agent-setup-recipe.md +266 -0
- package/.agents/skills/workflow-creator/references/computation-and-validation.md +201 -0
- package/.agents/skills/workflow-creator/references/control-flow.md +470 -0
- package/.agents/skills/workflow-creator/references/failure-modes.md +1014 -0
- package/.agents/skills/workflow-creator/references/getting-started.md +392 -0
- package/.agents/skills/workflow-creator/references/registry-and-validation.md +141 -0
- package/.agents/skills/workflow-creator/references/running-workflows.md +418 -0
- package/.agents/skills/workflow-creator/references/session-config.md +384 -0
- package/.agents/skills/workflow-creator/references/state-and-data-flow.md +356 -0
- package/.agents/skills/workflow-creator/references/user-input.md +234 -0
- package/.agents/skills/workflow-creator/references/workflow-inputs.md +392 -0
- package/.claude/agents/debugger.md +2 -2
- package/.claude/agents/reviewer.md +1 -1
- package/.claude/agents/worker.md +2 -2
- package/.github/agents/debugger.md +1 -1
- package/.github/agents/worker.md +1 -1
- package/.mcp.json +5 -1
- package/.opencode/agents/debugger.md +1 -1
- package/.opencode/agents/worker.md +1 -1
- package/README.md +236 -201
- package/dist/sdk/define-workflow.d.ts +11 -6
- package/dist/sdk/define-workflow.d.ts.map +1 -1
- package/dist/sdk/errors.d.ts +10 -0
- package/dist/sdk/errors.d.ts.map +1 -1
- package/dist/sdk/index.d.ts +21 -9
- package/dist/sdk/index.d.ts.map +1 -1
- package/dist/sdk/primitives/inputs.d.ts +36 -0
- package/dist/sdk/primitives/inputs.d.ts.map +1 -0
- package/dist/sdk/primitives/metadata.d.ts +40 -0
- package/dist/sdk/primitives/metadata.d.ts.map +1 -0
- package/dist/sdk/primitives/run.d.ts +57 -0
- package/dist/sdk/primitives/run.d.ts.map +1 -0
- package/dist/sdk/primitives/sessions.d.ts +128 -0
- package/dist/sdk/primitives/sessions.d.ts.map +1 -0
- package/dist/sdk/runtime/executor.d.ts +24 -56
- package/dist/sdk/runtime/executor.d.ts.map +1 -1
- package/dist/sdk/runtime/orchestrator-entry.d.ts +26 -0
- package/dist/sdk/runtime/orchestrator-entry.d.ts.map +1 -0
- package/dist/sdk/runtime/tmux.d.ts +20 -0
- package/dist/sdk/runtime/tmux.d.ts.map +1 -1
- package/dist/sdk/types.d.ts +26 -86
- package/dist/sdk/types.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/claude/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/copilot/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/deep-research-codebase/opencode/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/open-claude-design/claude/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/open-claude-design/copilot/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/open-claude-design/opencode/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/ralph/claude/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/ralph/copilot/index.d.ts.map +1 -1
- package/dist/sdk/workflows/builtin/ralph/opencode/index.d.ts.map +1 -1
- package/dist/sdk/workflows/index.d.ts +20 -12
- package/dist/sdk/workflows/index.d.ts.map +1 -1
- package/dist/services/config/additional-instructions.d.ts +1 -1
- package/dist/services/config/additional-instructions.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/cli.ts +39 -56
- package/src/commands/builtin-registry.ts +37 -0
- package/src/commands/cli/chat/index.ts +1 -3
- package/src/{sdk → commands/cli}/management-commands.ts +15 -55
- package/src/commands/cli/session.ts +1 -1
- package/src/commands/cli/workflow-command.test.ts +250 -16
- package/src/commands/cli/workflow-inputs.test.ts +1 -0
- package/src/commands/cli/workflow-inputs.ts +13 -3
- package/src/commands/cli/workflow-list.test.ts +1 -0
- package/src/commands/cli/workflow-list.ts +0 -0
- package/src/commands/cli/workflow-status.ts +1 -1
- package/src/commands/cli/workflow.ts +191 -11
- package/src/sdk/define-workflow.test.ts +47 -16
- package/src/sdk/define-workflow.ts +24 -6
- package/src/sdk/errors.test.ts +11 -0
- package/src/sdk/errors.ts +13 -0
- package/src/sdk/index.test.ts +92 -0
- package/src/sdk/index.ts +71 -15
- package/src/sdk/primitives/inputs.ts +48 -0
- package/src/sdk/primitives/metadata.ts +63 -0
- package/src/sdk/primitives/run.ts +81 -0
- package/src/sdk/primitives/sessions.test.ts +594 -0
- package/src/sdk/primitives/sessions.ts +328 -0
- package/src/sdk/runtime/executor.ts +36 -115
- package/src/sdk/runtime/orchestrator-entry.ts +110 -0
- package/src/sdk/runtime/tmux.ts +33 -0
- package/src/sdk/types.ts +26 -91
- package/src/sdk/workflows/builtin/deep-research-codebase/claude/index.ts +1 -0
- package/src/sdk/workflows/builtin/deep-research-codebase/copilot/index.ts +1 -0
- package/src/sdk/workflows/builtin/deep-research-codebase/opencode/index.ts +1 -0
- package/src/sdk/workflows/builtin/open-claude-design/claude/index.ts +1 -0
- package/src/sdk/workflows/builtin/open-claude-design/copilot/index.ts +1 -0
- package/src/sdk/workflows/builtin/open-claude-design/opencode/index.ts +1 -0
- package/src/sdk/workflows/builtin/ralph/claude/index.ts +1 -0
- package/src/sdk/workflows/builtin/ralph/copilot/index.ts +1 -0
- package/src/sdk/workflows/builtin/ralph/opencode/index.ts +1 -0
- package/src/sdk/workflows/index.ts +68 -51
- package/src/services/config/additional-instructions.ts +1 -1
- package/.agents/skills/test-driven-development/SKILL.md +0 -371
- package/.agents/skills/test-driven-development/testing-anti-patterns.md +0 -299
- package/dist/commands/cli/session.d.ts +0 -67
- package/dist/commands/cli/session.d.ts.map +0 -1
- package/dist/commands/cli/workflow-status.d.ts +0 -63
- package/dist/commands/cli/workflow-status.d.ts.map +0 -1
- package/dist/sdk/commander.d.ts +0 -74
- package/dist/sdk/commander.d.ts.map +0 -1
- package/dist/sdk/management-commands.d.ts +0 -42
- package/dist/sdk/management-commands.d.ts.map +0 -1
- package/dist/sdk/workflow-cli.d.ts +0 -103
- package/dist/sdk/workflow-cli.d.ts.map +0 -1
- package/dist/sdk/workflows/builtin-registry.d.ts +0 -113
- package/dist/sdk/workflows/builtin-registry.d.ts.map +0 -1
- package/src/sdk/commander.ts +0 -161
- package/src/sdk/workflow-cli.ts +0 -409
- package/src/sdk/workflows/builtin-registry.ts +0 -23
package/README.md
CHANGED
|
@@ -9,27 +9,21 @@
|
|
|
9
9
|
[](./package.json)
|
|
10
10
|
[](./LICENSE)
|
|
11
11
|
|
|
12
|
-
**
|
|
12
|
+
**Turn coding agents into reliable engineering workflows.** Atomic is an open-source CLI and TypeScript SDK for Claude Code, OpenCode, and GitHub Copilot CLI. Define the steps, guardrails, review gates, and execution environment your agent should follow, then run the workflow as TypeScript your whole team can review and reuse.
|
|
13
13
|
|
|
14
|
-
>
|
|
14
|
+
> Build the workflow once. Run it across agents, repos, and teams — with GitHub, Azure DevOps (ADO), or Sapling.
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
-
##
|
|
19
|
-
|
|
20
|
-
Atomic ships **two** things that share one orchestrator runtime. You can use either on its own or both together:
|
|
18
|
+
## Why Atomic
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
24
|
-
| **What it is** | Global `atomic` binary | `@bastani/atomic/workflows` TypeScript library |
|
|
25
|
-
| **Install** | `bun install -g @bastani/atomic` (or `install.sh` / `install.ps1`) | `bun add @bastani/atomic` inside your project |
|
|
26
|
-
| **Entrypoint** | `atomic <command>` | `bun run src/<agent>-worker.ts` |
|
|
27
|
-
| **Code required?** | No — everything is pre-built | Yes — you write `defineWorkflow(...)` + a 3-line composition root |
|
|
28
|
-
| **What you get** | `atomic chat` (agent REPL), three autonomous builtins (`ralph`, `deep-research-codebase`, `open-claude-design`), session management, the live orchestrator panel, Atomic skills (`/init`, `/research-codebase`, `/create-spec`, …) | `defineWorkflow`, `createWorkflowCli`, `createRegistry`, `ctx.stage`, `s.save` / `s.transcript`, headless stages, the Commander adapter (`toCommand`, `runCli`) |
|
|
29
|
-
| **When to reach for** | You want autonomous execution of a standard pattern out of the box, or interactive chat with your agent's full toolset | You want to encode **your** team's process — review flows, deployment gates, custom research pipelines — as TypeScript every teammate runs identically |
|
|
30
|
-
| **Read next** | [Quick Start](#quick-start) (steps 1–3) | [Quick Start step 4](#4-build-your-own-workflow--sdk) and [Building your own atomic-powered app](#building-your-own-atomic-powered-app) |
|
|
20
|
+
Coding agents are great inside a single session. They can inspect code, use tools, make edits, and explain their work. The trouble starts when the task is ambiguous/complex, tied to specific outcomes/exit criteria, long-running, or tied to a large codebase: you end up reminding the agent of the process, moving output between sessions, checking whether it followed the right steps, and deciding when a human needs to review the work. Atomic turns that process into code. A workflow can branch, retry, run stages in parallel, isolate sessions, pass only the right transcript forward, pause for human approval, and run inside a devcontainer so the agent is not loose on your host machine.
|
|
31
21
|
|
|
32
|
-
|
|
22
|
+
- **Start with your own process.** Automate the repetitive parts of research, product feedback, debugging, review, migrations, or PR prep. One TypeScript file, versioned with the repo.
|
|
23
|
+
- **Scale to your team.** Encode review gates, quality checks, and approvals so every teammate runs the same workflow instead of manually steering an agent.
|
|
24
|
+
- **Keep the coding agent.** Atomic adds structure around Claude Code, OpenCode, and Copilot CLI without rebuilding their file editing, tool use, MCP setup, hooks, or context handling from scratch.
|
|
25
|
+
- **Use natural language to get started.** Ask the `workflow-creator` skill to turn a workflow description into `defineWorkflow()` code, or let an agent use the skill when a complex task needs a repeatable workflow.
|
|
26
|
+
- **Control the outer loop.** Instead of trusting a black-box harness to improvise process, Atomic makes the orchestration inspectable: the agent stil uses it's harness with its native tools and context management, but the workflow, gates, handoffs, and execution graph are TypeScript you can read, edit, and version. This allows you to enhance your existing coding agent's capabilities.
|
|
33
27
|
|
|
34
28
|
---
|
|
35
29
|
|
|
@@ -39,7 +33,7 @@ Install, generate context, try Ralph, then write your own workflow — four step
|
|
|
39
33
|
|
|
40
34
|
### Prerequisites
|
|
41
35
|
|
|
42
|
-
Atomic doesn't replace your coding agent or terminal — it
|
|
36
|
+
Atomic doesn't replace your coding agent or terminal — it gives them a workflow to follow. Three things have to exist on the host before a workflow can run:
|
|
43
37
|
|
|
44
38
|
- **[Bun](https://bun.sh/)** as the JavaScript runtime — Atomic and the SDK ship source that relies on `Bun.spawn`, native pty handling, and Bun-specific module resolution. **They do not run on Node.js.** The bootstrap installer below installs Bun for you; if you install `@bastani/atomic` manually, install Bun first.
|
|
45
39
|
- **A terminal multiplexer** — every stage runs inside a detachable session on a dedicated `atomic` socket (your personal tmux is untouched). That's how workflows survive terminal disconnects, how `-d/--detach` puts a run in the background, and how `atomic session connect` reattaches later from any shell.
|
|
@@ -51,7 +45,7 @@ Atomic doesn't replace your coding agent or terminal — it orchestrates them. T
|
|
|
51
45
|
- [GitHub Copilot CLI](https://github.com/features/copilot/cli) — run `copilot` and authenticate
|
|
52
46
|
- **Windows only:** PowerShell 7+ ([install guide](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell-on-windows))
|
|
53
47
|
|
|
54
|
-
> The bootstrap installer below installs Bun and Atomic but **does not** install tmux/psmux or the coding agents. Install those separately before running any workflow — `bun run src/claude-worker.ts
|
|
48
|
+
> The bootstrap installer below installs Bun and Atomic but **does not** install tmux/psmux or the coding agents. Install those separately before running any workflow — `bun run src/claude-worker.ts` will fail loudly at stage spawn if either is missing. Using a [devcontainer](#alternative-devcontainer-recommended-for-autonomous-workflows) short-circuits all of this: the atomic feature bundles Bun + tmux + the agent CLI into the container image.
|
|
55
49
|
|
|
56
50
|
### 1. Install — CLI + SDK share the same package
|
|
57
51
|
|
|
@@ -233,22 +227,52 @@ export default defineWorkflow({
|
|
|
233
227
|
.compile();
|
|
234
228
|
```
|
|
235
229
|
|
|
236
|
-
Wire it to a CLI in `src/claude-worker.ts
|
|
230
|
+
Wire it to a CLI in `src/claude-worker.ts`. The SDK ships pure
|
|
231
|
+
primitives — no wrapper to opt into. Compose with your CLI library of
|
|
232
|
+
choice (Commander, citty, yargs, …) and call `runWorkflow`. Catch the
|
|
233
|
+
SDK's typed errors (`MissingDependencyError`, `SessionNotFoundError`,
|
|
234
|
+
…) for friendly CLI output:
|
|
237
235
|
|
|
238
236
|
```ts
|
|
239
|
-
import {
|
|
237
|
+
import { Command } from "@commander-js/extra-typings";
|
|
238
|
+
import {
|
|
239
|
+
getInputSchema,
|
|
240
|
+
runWorkflow,
|
|
241
|
+
MissingDependencyError,
|
|
242
|
+
} from "@bastani/atomic/workflows";
|
|
240
243
|
import workflow from "./workflows/review-to-merge/claude.ts";
|
|
241
244
|
|
|
242
|
-
|
|
245
|
+
const program = new Command();
|
|
246
|
+
for (const input of getInputSchema(workflow)) {
|
|
247
|
+
program.option(`--${input.name} <value>`, input.description ?? "");
|
|
248
|
+
}
|
|
249
|
+
program.action(async (rawOpts) => {
|
|
250
|
+
try {
|
|
251
|
+
await runWorkflow({ workflow, inputs: rawOpts as Record<string, string> });
|
|
252
|
+
} catch (err) {
|
|
253
|
+
if (err instanceof MissingDependencyError) {
|
|
254
|
+
console.error(`Missing dependency: ${err.dependency}. Install it and retry.`);
|
|
255
|
+
process.exit(1);
|
|
256
|
+
}
|
|
257
|
+
throw err;
|
|
258
|
+
}
|
|
259
|
+
});
|
|
260
|
+
await program.parseAsync();
|
|
243
261
|
```
|
|
244
262
|
|
|
245
263
|
Run it:
|
|
246
264
|
|
|
247
265
|
```bash
|
|
248
|
-
bun run src/claude-worker.ts
|
|
266
|
+
bun run src/claude-worker.ts --target_branch=main
|
|
249
267
|
```
|
|
250
268
|
|
|
251
|
-
That's the full shape — one workflow file, one
|
|
269
|
+
That's the full shape — one workflow file, one composition root. The
|
|
270
|
+
SDK exposes primitives (`runWorkflow`, `getInputSchema`, `listWorkflows`,
|
|
271
|
+
`getName`, `getAgent`, `validateInputs`, `listSessions`, …) and the
|
|
272
|
+
developer composes them into whatever CLI shape they prefer. See
|
|
273
|
+
[Workflow SDK](#workflow-sdk--build-reliable-engineering-workflows) for
|
|
274
|
+
parallel stages, input schemas, headless stages, and the full API
|
|
275
|
+
reference.
|
|
252
276
|
|
|
253
277
|
### Managing sessions
|
|
254
278
|
|
|
@@ -270,42 +294,42 @@ atomic workflow -n ralph -a claude -d "build the auth module" # returns immedi
|
|
|
270
294
|
atomic workflow session connect atomic-wf-claude-ralph-<id> # attach later
|
|
271
295
|
```
|
|
272
296
|
|
|
273
|
-
Detached mode is what you want for scripted / CI automation and long-running tasks — the
|
|
297
|
+
Detached mode is what you want for scripted / CI automation and long-running tasks — the workflow keeps running on the atomic tmux socket regardless of your terminal.
|
|
274
298
|
|
|
275
299
|
---
|
|
276
300
|
|
|
277
|
-
##
|
|
301
|
+
## Two surfaces: CLI and SDK
|
|
278
302
|
|
|
279
|
-
|
|
303
|
+
Atomic ships **two** things that share one workflow runtime. You can use either on its own or both together:
|
|
280
304
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
305
|
+
| | Atomic CLI | Atomic SDK |
|
|
306
|
+
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
307
|
+
| **What it is** | Global `atomic` binary | `@bastani/atomic/workflows` TypeScript library |
|
|
308
|
+
| **Install** | `bun install -g @bastani/atomic` (or `install.sh` / `install.ps1`) | `bun add @bastani/atomic` inside your project |
|
|
309
|
+
| **Entrypoint** | `atomic <command>` | `bun run src/<agent>-worker.ts` |
|
|
310
|
+
| **Code required?** | No — everything is pre-built. You can also ask the agent inside `atomic chat` to use the `workflow-creator` skill, decide when a complex task needs its own workflow, and build/run that workflow on the fly. | No to start — describe the workflow in natural language and use the `workflow-creator` skill to generate it. Then refine it in natural language or edit the TypeScript workflow and composition root directly, with full visibility into exactly what will run. |
|
|
311
|
+
| **What you get** | `atomic chat` (agent REPL), three autonomous built-in workflows (`ralph`, `deep-research-codebase`, `open-claude-design`), session management, the live workflow panel, Atomic skills (`/init`, `/research-codebase`, `/create-spec`, …) | `defineWorkflow`, `createRegistry`, `runWorkflow`, metadata accessors (`getName`, `getInputSchema`, …), session primitives (`listSessions`, `getSessionStatus`, `attachSession` / `detachSession`, `nextWindow` / `previousWindow` / `gotoOrchestrator`), typed errors (`MissingDependencyError`, `SessionNotFoundError`, …), `ctx.stage`, `s.save` / `s.transcript`, headless stages |
|
|
312
|
+
| **When to reach for** | You want autonomous execution of a standard pattern out of the box, interactive chat with your agent's full toolset, or a CLI agent that can create a purpose-built workflow before doing complex work. | You want to control the outer loop yourself — review flows, deployment gates, custom research pipelines — with full visibility into the TypeScript your team will run identically. |
|
|
313
|
+
| **Read next** | [Quick Start](#quick-start) (steps 1–3) | [Quick Start step 4](#4-build-your-own-workflow--sdk) and [Building your own atomic-powered app](#building-your-own-atomic-powered-app) |
|
|
284
314
|
|
|
285
|
-
|
|
315
|
+
Both surfaces call the same runtime underneath (tmux/psmux session graph, provider SDKs, detach/reattach) — they're two entry points, not two products. Neither depends on the other: you can `bun add @bastani/atomic` in a project without ever installing the global binary, and you can use `atomic chat` and the built-in workflows without writing any TypeScript.
|
|
286
316
|
|
|
287
|
-
|
|
317
|
+
## Example use cases
|
|
288
318
|
|
|
289
|
-
|
|
319
|
+
These are workflows you'd author with `defineWorkflow` and run from your own `src/<agent>-worker.ts` — see [step 4 of Quick Start](#4-build-your-own-workflow--sdk) for the three-line entrypoint. Atomic ships three built-in workflows (`ralph`, `deep-research-codebase`, `open-claude-design`); everything else is yours to define.
|
|
290
320
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
**
|
|
296
|
-
|
|
297
|
-
```bash
|
|
298
|
-
bun run src/claude-worker.ts -n ux-personas -a claude --personas=50
|
|
299
|
-
```
|
|
300
|
-
|
|
301
|
-
**Review-to-merge pipeline.** The workflow from [step 4](#4-build-your-own-workflow) above — reviews code, runs CI in parallel, opens a PR, notifies Slack, waits for approval, merges.
|
|
321
|
+
- **Review-to-merge pipeline.** Review code, run CI in parallel, open a PR, notify Slack, wait for approval, merge.
|
|
322
|
+
- **Support ticket to draft PR.** Reproduce the issue, find the root cause, try a fix in a sandbox, run tests, pause for review.
|
|
323
|
+
- **Production alert investigation.** Pull the failing trace, inspect recent commits, rank likely causes, then draft a fix or page the on-call with evidence.
|
|
324
|
+
- **Parallel UX testing.** Run many persona-specific agents against the same feature, aggregate structured feedback, and turn selected issues into tasks.
|
|
325
|
+
- **Large migration or refactor.** Research the codebase, split the work into safe batches, run implementation and review passes, and keep artifacts for later runs.
|
|
302
326
|
|
|
303
327
|
---
|
|
304
328
|
|
|
305
329
|
## Table of Contents
|
|
306
330
|
|
|
307
331
|
- [Atomic](#atomic)
|
|
308
|
-
- [
|
|
332
|
+
- [Why Atomic](#why-atomic)
|
|
309
333
|
- [Quick Start](#quick-start)
|
|
310
334
|
- [Prerequisites](#prerequisites)
|
|
311
335
|
- [1. Install — CLI + SDK share the same package](#1-install--cli--sdk-share-the-same-package)
|
|
@@ -313,16 +337,16 @@ bun run src/claude-worker.ts -n ux-personas -a claude --personas=50
|
|
|
313
337
|
- [3. Try Ralph — CLI (autonomous coding)](#3-try-ralph--cli-autonomous-coding)
|
|
314
338
|
- [4. Build your own workflow — SDK](#4-build-your-own-workflow--sdk)
|
|
315
339
|
- [Managing sessions](#managing-sessions)
|
|
316
|
-
- [
|
|
317
|
-
|
|
340
|
+
- [Two surfaces: CLI and SDK](#two-surfaces-cli-and-sdk)
|
|
341
|
+
- [Example use cases](#example-use-cases)
|
|
318
342
|
- [Table of Contents](#table-of-contents)
|
|
319
343
|
- [Security: Workflow Permissions Model](#security-workflow-permissions-model)
|
|
320
344
|
- [Core Features](#core-features)
|
|
321
345
|
- [Multi-Agent Support](#multi-agent-support)
|
|
322
|
-
- [Workflow SDK — Build
|
|
346
|
+
- [Workflow SDK — Build Reliable Engineering Workflows](#workflow-sdk--build-reliable-engineering-workflows)
|
|
323
347
|
- [Runnable examples shipped with the repo](#runnable-examples-shipped-with-the-repo)
|
|
324
348
|
- [Builder API](#builder-api)
|
|
325
|
-
- [WorkflowContext (`ctx`) — top-level
|
|
349
|
+
- [WorkflowContext (`ctx`) — top-level workflow context](#workflowcontext-ctx--top-level-workflow-context)
|
|
326
350
|
- [SessionContext (`s`) — inside each session callback](#sessioncontext-s--inside-each-session-callback)
|
|
327
351
|
- [Session Options (`SessionRunOptions`)](#session-options-sessionrunoptions)
|
|
328
352
|
- [Saving Transcripts](#saving-transcripts)
|
|
@@ -334,7 +358,7 @@ bun run src/claude-worker.ts -n ux-personas -a claude --personas=50
|
|
|
334
358
|
- [Containerized Execution](#containerized-execution)
|
|
335
359
|
- [Specialized Sub-Agents](#specialized-sub-agents)
|
|
336
360
|
- [Built-in Skills](#built-in-skills)
|
|
337
|
-
- [Workflow
|
|
361
|
+
- [Workflow Panel](#workflow-panel)
|
|
338
362
|
- [Commands Reference](#commands-reference)
|
|
339
363
|
- [CLI Commands](#cli-commands)
|
|
340
364
|
- [Global Flags](#global-flags)
|
|
@@ -346,8 +370,8 @@ bun run src/claude-worker.ts -n ux-personas -a claude --personas=50
|
|
|
346
370
|
- [Building your own atomic-powered app](#building-your-own-atomic-powered-app)
|
|
347
371
|
- [One factory, three input shapes](#one-factory-three-input-shapes)
|
|
348
372
|
- [One method: `run()`](#one-method-run)
|
|
349
|
-
- [Embedding under a parent CLI — `
|
|
350
|
-
- [`entry` — for bundled apps and
|
|
373
|
+
- [Embedding under a parent CLI — `runWorkflow` inside any Commander tree](#embedding-under-a-parent-cli--runworkflow-inside-any-commander-tree)
|
|
374
|
+
- [`entry` — for bundled apps and tests](#entry--for-bundled-apps-and-tests)
|
|
351
375
|
- [Registry rules](#registry-rules)
|
|
352
376
|
- [Input precedence](#input-precedence)
|
|
353
377
|
- [Builtin workflows via the `atomic` CLI](#builtin-workflows-via-the-atomic-cli)
|
|
@@ -395,21 +419,23 @@ Atomic works across **three production coding agents** — switch with a flag an
|
|
|
395
419
|
|
|
396
420
|
Each agent gets its own configuration directory (`.claude/`, `.opencode/`, `.github/`), skills, and context files — all managed by Atomic.
|
|
397
421
|
|
|
398
|
-
### Workflow SDK — Build
|
|
422
|
+
### Workflow SDK — Build Reliable Engineering Workflows
|
|
399
423
|
|
|
400
|
-
The Workflow SDK (`@bastani/atomic/workflows`) lets you encode your team's process as TypeScript — spawn agent sessions dynamically with native control flow (`for`, `if`, `Promise.all()`), and watch
|
|
424
|
+
The Workflow SDK (`@bastani/atomic/workflows`) lets you encode your team's process as TypeScript — spawn agent sessions dynamically with native control flow (`for`, `if`, `Promise.all()`), pass state explicitly, and watch each stage appear in a live graph as it runs.
|
|
401
425
|
|
|
402
|
-
Set up a workflow project (`bun init && bun add @bastani/atomic`), define your workflow with `defineWorkflow`, then
|
|
426
|
+
Set up a workflow project (`bun init && bun add @bastani/atomic`), define your workflow with `defineWorkflow`, then call `runWorkflow({ workflow, inputs })` from inside whatever CLI library you prefer (Commander, citty, yargs, an OpenTUI app, …). The SDK ships pure primitives — no opinionated wrapper:
|
|
403
427
|
|
|
404
428
|
```bash
|
|
405
|
-
bun run src/claude-worker.ts
|
|
429
|
+
bun run src/claude-worker.ts --prompt="describe this project"
|
|
406
430
|
```
|
|
407
431
|
|
|
408
|
-
See [step 4 of Quick Start](#4-build-your-own-workflow) for a complete review-to-merge example. More examples and the full API reference below.
|
|
432
|
+
See [step 4 of Quick Start](#4-build-your-own-workflow--sdk) for a complete review-to-merge example. More examples and the full API reference below.
|
|
409
433
|
|
|
410
434
|
#### Runnable examples shipped with the repo
|
|
411
435
|
|
|
412
|
-
The [`examples/`](./examples) directory contains small, complete user apps you can run directly. Most subdirectories ship `claude/`, `copilot/`, and `opencode/` variants plus one agent-scoped worker file per agent — `claude-worker.ts`, `copilot-worker.ts`, `opencode-worker.ts` — each a
|
|
436
|
+
The [`examples/`](./examples) directory contains small, complete user apps you can run directly. Most subdirectories ship `claude/`, `copilot/`, and `opencode/` variants plus one agent-scoped worker file per agent — `claude-worker.ts`, `copilot-worker.ts`, `opencode-worker.ts` — each a small Commander entrypoint that calls `runWorkflow({ workflow, inputs })`. `multi-workflow/` and `commander-embed/` use a single `cli.ts` instead, to demonstrate multi-workflow dispatch and Commander embedding respectively.
|
|
437
|
+
|
|
438
|
+
**Design principle — when does `-a/--agent` belong on your CLI?** Each agent-scoped worker file imports a single workflow pinned to one agent (`import workflow from "./claude/index.ts"`), so there's nothing to disambiguate — no `-a` flag. Only reach for `-a/--agent` when one CLI dispatches across workflows that exist in multiple agent variants — e.g. a `cli.ts` that registers `hello` for claude *and* copilot. The atomic CLI itself uses `-a` for exactly that reason: its builtin registry has cross-agent variants of `ralph`, `deep-research-codebase`, and `open-claude-design`.
|
|
413
439
|
|
|
414
440
|
| Example | What it demonstrates |
|
|
415
441
|
| ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
@@ -421,29 +447,28 @@ The [`examples/`](./examples) directory contains small, complete user apps you c
|
|
|
421
447
|
| `hil-favorite-color-headless` | HIL pause inside a headless stage |
|
|
422
448
|
| `structured-output-demo` | Per-SDK structured output (JSON-schema validation, Zod) |
|
|
423
449
|
| `reviewer-tool-test` | Custom reviewer tool wiring (Copilot — copilot-worker.ts only) |
|
|
424
|
-
| `review-fix-loop` | Draft → loop(review → fix) with bounded iterations and early exit on a `CLEAN` verdict —
|
|
425
|
-
| `multi-workflow` | Two Claude workflows under one `cli.ts` —
|
|
426
|
-
| `commander-embed` | Mount an atomic workflow under a parent Commander CLI
|
|
450
|
+
| `review-fix-loop` | Draft → loop(review → fix) with bounded iterations and early exit on a `CLEAN` verdict — a reliable review gate showing how a stage's return value (`handle.result`) drives TypeScript control flow |
|
|
451
|
+
| `multi-workflow` | Two Claude workflows under one `cli.ts` — uses `listWorkflows(registry)` to register one Commander subcommand per workflow with each workflow's declared inputs as `--<flag>` options. |
|
|
452
|
+
| `commander-embed` | Mount an atomic workflow under a parent Commander CLI by calling `runWorkflow({ workflow, inputs })` inside a Commander action, alongside a plain Commander sibling command. No re-entry boilerplate — the SDK ships its own orchestrator entry script. |
|
|
453
|
+
| `pane-navigation` | Driver CLI for the SDK pane-navigation primitives (`nextWindow`, `previousWindow`, `gotoOrchestrator`, `attachSession`, `detachSession`). Spawns a 3-stage workflow detached and exposes `start / list / status / next / prev / home / attach / stop` subcommands. Catches `SessionNotFoundError` for friendly errors. |
|
|
427
454
|
|
|
428
455
|
Run any of them with:
|
|
429
456
|
|
|
430
457
|
```bash
|
|
431
|
-
# Single-workflow
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
bun run examples/
|
|
436
|
-
bun run examples/
|
|
437
|
-
bun run examples/
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
bun run examples/multi-workflow/cli.ts
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
# Commander embedding — workflow mounted as a subcommand under a parent CLI
|
|
446
|
-
bun run examples/commander-embed/cli.ts greet -n greet -a claude --who=Alex
|
|
458
|
+
# Single-workflow workers — agent is pinned by which file you run, so no `-a` flag.
|
|
459
|
+
# Inputs map to `--<input>=<value>` flags; if the workflow declares no inputs,
|
|
460
|
+
# trailing positional tokens become the prompt.
|
|
461
|
+
bun run examples/hello-world/claude-worker.ts --greeting="Hello" --style=casual
|
|
462
|
+
bun run examples/sequential-describe-summarize/claude-worker.ts --topic="Bun"
|
|
463
|
+
bun run examples/review-fix-loop/claude-worker.ts --topic="adopting Bun" --max_iterations=3
|
|
464
|
+
bun run examples/headless-test/copilot-worker.ts --prompt="TypeScript"
|
|
465
|
+
|
|
466
|
+
# Multi-workflow CLI — one cli.ts, one Commander subcommand per registered workflow.
|
|
467
|
+
bun run examples/multi-workflow/cli.ts hello --who=Alex
|
|
468
|
+
bun run examples/multi-workflow/cli.ts goodbye --tone=melodramatic
|
|
469
|
+
|
|
470
|
+
# Commander embedding — atomic workflow mounted as `greet` alongside plain Commander commands.
|
|
471
|
+
bun run examples/commander-embed/cli.ts greet --who=Alex
|
|
447
472
|
bun run examples/commander-embed/cli.ts status # sibling Commander command
|
|
448
473
|
bun run examples/commander-embed/cli.ts --help # all commands
|
|
449
474
|
```
|
|
@@ -583,13 +608,11 @@ export default defineWorkflow({
|
|
|
583
608
|
.compile();
|
|
584
609
|
```
|
|
585
610
|
|
|
586
|
-
Wire it into `src/claude-worker.ts` (three lines — see [step 4 of Quick Start](#4-build-your-own-workflow)) and run it:
|
|
611
|
+
Wire it into `src/claude-worker.ts` (three lines — see [step 4 of Quick Start](#4-build-your-own-workflow--sdk)) and run it:
|
|
587
612
|
|
|
588
613
|
```bash
|
|
589
614
|
# Scriptable; CI-friendly
|
|
590
615
|
bun run src/claude-worker.ts \
|
|
591
|
-
-n gen-spec \
|
|
592
|
-
-a claude \
|
|
593
616
|
--research_doc=research/docs/2026-04-11-auth.md \
|
|
594
617
|
--focus=standard
|
|
595
618
|
```
|
|
@@ -662,15 +685,17 @@ The graph shows `seed → merge` — headless stages are transparent to the topo
|
|
|
662
685
|
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
663
686
|
| **Dynamic session spawning** | `ctx.stage()` spawns sessions at runtime — each gets its own tmux window and graph node |
|
|
664
687
|
| **Native TypeScript control flow** | Use `for`, `if/else`, `Promise.all()`, `try/catch` — no framework DSL |
|
|
688
|
+
| **Review gates and approvals** | Pause for human input, run structured review stages, and decide whether the next stage should continue |
|
|
665
689
|
| **Session return values** | Session callbacks can return data: `const h = await ctx.stage(...); h.result` |
|
|
666
690
|
| **Transcript passing** | Access prior output via handle (`s.transcript(handle)`) or name (`s.transcript("name")`) |
|
|
667
691
|
| **Declared input schemas** | Add an `inputs: [...]` array and the CLI materialises `--<field>=<value>` flags with built-in validation |
|
|
668
|
-
| **Interactive picker** | `atomic workflow -a <agent>` is the explicit no-`-n` discovery path; direct runs use `-n <name>`
|
|
692
|
+
| **Interactive picker** | `atomic workflow -a <agent>` is the explicit no-`-n` discovery path; direct runs use `-n <name>` |
|
|
669
693
|
| **Nested sub-sessions** | `s.stage()` inside a callback spawns child sessions — visible as nested graph nodes |
|
|
670
694
|
| **Auto-inferred graph** | Topology derived from `await` / `Promise.all` patterns — no annotations |
|
|
671
695
|
| **Provider-agnostic** | Write raw SDK code for Claude, Copilot, or OpenCode inside each callback |
|
|
672
696
|
| **Live graph visualization** | Sessions appear in the TUI graph as they spawn — loops and conditionals visible in real time |
|
|
673
697
|
| **Background (headless) stages** | `headless: true` runs in-process without a tmux window — invisible in graph, tracked by statusline counter, identical callback API |
|
|
698
|
+
| **Token-aware handoffs** | Save transcripts to disk and pass paths or distilled outputs forward instead of stuffing every stage with the full history |
|
|
674
699
|
|
|
675
700
|
**Deterministic execution guarantees:**
|
|
676
701
|
|
|
@@ -682,7 +707,7 @@ Workflows are deterministic by design — the same definition produces the same
|
|
|
682
707
|
- **Isolated context windows** — Each session runs in its own tmux pane with a fresh context. Data flows only through explicit `ctx.transcript()` / `ctx.getMessages()` calls.
|
|
683
708
|
- **Persisted artifacts** — Every session writes messages, transcript, and metadata to disk — a complete, inspectable execution record.
|
|
684
709
|
|
|
685
|
-
Variance comes
|
|
710
|
+
Variance comes from the LLM's responses, not from a changing workflow.
|
|
686
711
|
|
|
687
712
|
> Ask Atomic to build workflows for you: `Use your workflow-creator skill to create a workflow that plans, implements, and reviews a feature.`
|
|
688
713
|
|
|
@@ -697,7 +722,7 @@ Variance comes only from the LLM's responses, not from the harness.
|
|
|
697
722
|
| `.run(async (ctx) => { ... })` | Set the workflow's entry point — `ctx` is a `WorkflowContext` |
|
|
698
723
|
| `.compile()` | **Required** — terminal method that seals the workflow definition |
|
|
699
724
|
|
|
700
|
-
#### WorkflowContext (`ctx`) — top-level
|
|
725
|
+
#### WorkflowContext (`ctx`) — top-level workflow context
|
|
701
726
|
|
|
702
727
|
| Property | Type | Description |
|
|
703
728
|
| ---------------------------------------------- | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
@@ -759,7 +784,7 @@ The runtime auto-creates `s.client` and `s.session` — use them directly inside
|
|
|
759
784
|
2. Session names must be unique within a workflow run
|
|
760
785
|
3. `transcript()` / `getMessages()` only access completed sessions (callback returned + saves flushed)
|
|
761
786
|
4. Each session runs in its own tmux window with the chosen agent
|
|
762
|
-
5.
|
|
787
|
+
5. Run a workflow by calling `runWorkflow({ workflow, inputs })` from inside any CLI library (Commander, citty, yargs, …). Use `listWorkflows(registry)` to iterate when registering multiple workflows.
|
|
763
788
|
6. Set up your workflow project with `bun init && bun add @bastani/atomic`
|
|
764
789
|
7. Background (headless) stages use the same callback API — `s.client`, `s.session`, `s.save()`, return values all work identically
|
|
765
790
|
|
|
@@ -818,7 +843,7 @@ The [Ralph Method](https://ghuntley.com/ralph/) enables **multi-hour autonomous
|
|
|
818
843
|
**How Ralph works:**
|
|
819
844
|
|
|
820
845
|
1. **Task Decomposition** — A `planner` sub-agent breaks your spec into a task list with dependency tracking, stored in SQLite (WAL mode for parallel access).
|
|
821
|
-
2. **
|
|
846
|
+
2. **Execution** — An `orchestrator` retrieves the task list, validates the dependency graph, and dispatches `worker` sub-agents for ready tasks.
|
|
822
847
|
3. **Review & Debug** — A `reviewer` audits the implementation with structured JSON output; if P0–P2 findings exist, a `debugger` investigates root causes and feeds back to the planner on the next iteration.
|
|
823
848
|
|
|
824
849
|
**Loop config:** Up to **10 iterations**. Exits early after **2 consecutive clean reviews** (zero actionable findings). P3 (minor) findings are non-actionable.
|
|
@@ -917,16 +942,16 @@ Skills are structured capability modules that give agents best practices and reu
|
|
|
917
942
|
<details>
|
|
918
943
|
<summary><b>Development workflows</b></summary>
|
|
919
944
|
|
|
920
|
-
| Skill
|
|
921
|
-
|
|
|
922
|
-
| `init`
|
|
923
|
-
| `research-codebase`
|
|
924
|
-
| `create-spec`
|
|
925
|
-
| `workflow-creator`
|
|
926
|
-
| `explain-code`
|
|
927
|
-
| `find-skills`
|
|
928
|
-
| `
|
|
929
|
-
| `prompt-engineer`
|
|
945
|
+
| Skill | Description |
|
|
946
|
+
| ------------------- | --------------------------------------------------------------------------- |
|
|
947
|
+
| `init` | Generate `CLAUDE.md` and `AGENTS.md` by exploring the codebase |
|
|
948
|
+
| `research-codebase` | Analyze codebase with parallel sub-agents and document findings |
|
|
949
|
+
| `create-spec` | Create detailed execution plans from research documents |
|
|
950
|
+
| `workflow-creator` | Create multi-agent workflows using the session-based `defineWorkflow()` API |
|
|
951
|
+
| `explain-code` | Explain code functionality in detail using DeepWiki |
|
|
952
|
+
| `find-skills` | Discover and install agent skills from the community |
|
|
953
|
+
| `tdd` | Write tests first; includes a testing anti-patterns guide |
|
|
954
|
+
| `prompt-engineer` | Create, improve, and optimize prompts using best practices |
|
|
930
955
|
|
|
931
956
|
</details>
|
|
932
957
|
|
|
@@ -1025,9 +1050,9 @@ Skills are structured capability modules that give agents best practices and reu
|
|
|
1025
1050
|
|
|
1026
1051
|
Skills are auto-invoked when relevant. Run `ls .agents/skills/` for the complete, current list on disk.
|
|
1027
1052
|
|
|
1028
|
-
### Workflow
|
|
1053
|
+
### Workflow Panel
|
|
1029
1054
|
|
|
1030
|
-
During `atomic workflow` execution, Atomic renders a live
|
|
1055
|
+
During `atomic workflow` execution, Atomic renders a live workflow panel built on [OpenTUI](https://github.com/anomalyco/opentui) over the workflow's tmux session graph. It shows:
|
|
1031
1056
|
|
|
1032
1057
|
- **Session graph** — Nodes per `.stage()` with status (pending / running / completed / failed) and edges for sequential / parallel dependencies
|
|
1033
1058
|
- **Task list tracking** — Ralph's decomposed task list with dependency arrows, updated in real time
|
|
@@ -1038,7 +1063,7 @@ During `atomic chat`, there is no Atomic-owned TUI — `atomic chat -a <agent>`
|
|
|
1038
1063
|
|
|
1039
1064
|
| Context | UI provider |
|
|
1040
1065
|
| -------------------------------------- | ----------------------------------------------------------- |
|
|
1041
|
-
| `atomic workflow -n <name> -a <agent>` | Atomic (
|
|
1066
|
+
| `atomic workflow -n <name> -a <agent>` | Atomic (workflow panel + tmux session graph) |
|
|
1042
1067
|
| `atomic chat -a <agent>` | The native agent CLI (Claude Code / OpenCode / Copilot CLI) |
|
|
1043
1068
|
|
|
1044
1069
|
---
|
|
@@ -1047,16 +1072,16 @@ During `atomic chat`, there is no Atomic-owned TUI — `atomic chat -a <agent>`
|
|
|
1047
1072
|
|
|
1048
1073
|
### CLI Commands
|
|
1049
1074
|
|
|
1050
|
-
| Command | Description
|
|
1051
|
-
| ------------------------------- |
|
|
1052
|
-
| `atomic chat` | Spawn the native agent CLI inside a tmux session
|
|
1053
|
-
| `atomic workflow` | Run a named multi-session workflow with the Atomic
|
|
1054
|
-
| `atomic workflow list` | List available workflows, grouped by source
|
|
1055
|
-
| `atomic session list` | List all running sessions on the atomic tmux socket
|
|
1056
|
-
| `atomic session connect [name]` | Attach to a session (interactive picker when no name given)
|
|
1057
|
-
| `atomic session kill [name]` | Kill a session by name, or all sessions when no name is given
|
|
1058
|
-
| `atomic completions <shell>` | Output shell completion script (bash, zsh, fish, powershell)
|
|
1059
|
-
| `atomic config set <k> <v>` | Set configuration values (supports `telemetry` and `scm`)
|
|
1075
|
+
| Command | Description |
|
|
1076
|
+
| ------------------------------- | ----------------------------------------------------------------- |
|
|
1077
|
+
| `atomic chat` | Spawn the native agent CLI inside a tmux session |
|
|
1078
|
+
| `atomic workflow` | Run a named multi-session workflow with the Atomic workflow panel |
|
|
1079
|
+
| `atomic workflow list` | List available workflows, grouped by source |
|
|
1080
|
+
| `atomic session list` | List all running sessions on the atomic tmux socket |
|
|
1081
|
+
| `atomic session connect [name]` | Attach to a session (interactive picker when no name given) |
|
|
1082
|
+
| `atomic session kill [name]` | Kill a session by name, or all sessions when no name is given |
|
|
1083
|
+
| `atomic completions <shell>` | Output shell completion script (bash, zsh, fish, powershell) |
|
|
1084
|
+
| `atomic config set <k> <v>` | Set configuration values (supports `telemetry` and `scm`) |
|
|
1060
1085
|
|
|
1061
1086
|
#### Global Flags
|
|
1062
1087
|
|
|
@@ -1113,7 +1138,7 @@ atomic chat -a claude --verbose # forward --verbose to claude
|
|
|
1113
1138
|
|
|
1114
1139
|
| Flag | Description |
|
|
1115
1140
|
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
1116
|
-
| `-n, --name <name>` | Workflow name (required for direct runs; omit only for the interactive picker)
|
|
1141
|
+
| `-n, --name <name>` | Workflow name (required for direct runs; omit only for the interactive picker) |
|
|
1117
1142
|
| `-a, --agent <name>` | Agent: `claude`, `opencode`, `copilot` |
|
|
1118
1143
|
| `-d, --detach` | Start the workflow in the background without attaching — ideal for scripted / CI runs; attach later with `atomic workflow session connect <name>` |
|
|
1119
1144
|
| `--<field>=<value>` | Structured input for workflows that declare an `inputs` schema (also accepts `--<field> <value>`) |
|
|
@@ -1137,7 +1162,7 @@ atomic workflow -n open-claude-design -a claude \
|
|
|
1137
1162
|
--prompt="a dashboard for monitoring API latency" \
|
|
1138
1163
|
--output-type=prototype
|
|
1139
1164
|
|
|
1140
|
-
# 5. Run detached —
|
|
1165
|
+
# 5. Run detached — workflow runs in the background; prints the session name
|
|
1141
1166
|
# and returns immediately. Attach any time with `atomic workflow session connect`.
|
|
1142
1167
|
atomic workflow -n ralph -a claude -d "build a REST API for user management"
|
|
1143
1168
|
```
|
|
@@ -1212,150 +1237,160 @@ Native slash commands (`/help`, `/clear`, `/compact`, `/model`, `/theme`, `/agen
|
|
|
1212
1237
|
|
|
1213
1238
|
`@bastani/atomic/workflows` is a library, not just a CLI. Use it directly to build your own TypeScript app that runs your team's workflows.
|
|
1214
1239
|
|
|
1215
|
-
> **SDK-only users:** you don't need the global `atomic` binary, but you still need the runtime prerequisites — **[Bun](https://bun.sh/) (the SDK does not run on Node.js)**, a terminal multiplexer (tmux on macOS/Linux, psmux on Windows), and at least one authenticated coding agent CLI (`claude`, `opencode`, or `copilot`). See [Prerequisites](#prerequisites) for the "why" and install commands. The SDK spawns the agent CLI at each stage and wraps it in a detachable multiplexer session
|
|
1240
|
+
> **SDK-only users:** you don't need the global `atomic` binary, but you still need the runtime prerequisites — **[Bun](https://bun.sh/) (the SDK does not run on Node.js)**, a terminal multiplexer (tmux on macOS/Linux, psmux on Windows), and at least one authenticated coding agent CLI (`claude`, `opencode`, or `copilot`). See [Prerequisites](#prerequisites) for the "why" and install commands. The SDK spawns the agent CLI at each stage and wraps it in a detachable multiplexer session.
|
|
1216
1241
|
>
|
|
1217
|
-
> **
|
|
1242
|
+
> **Session management primitives.** The SDK exposes `listSessions`, `getSession`, `stopSession`, `attachSession`, `detachSession`, `getSessionStatus`, `getSessionTranscript`, plus pane-navigation verbs `nextWindow` / `previousWindow` / `gotoOrchestrator` — wire them into your CLI's `session list`, `status`, etc. subcommands as you see fit. Sessions live on the shared `atomic` tmux socket, so a worker CLI built on the primitives, the global `atomic` binary, and `bunx atomic` all see the same runtime state.
|
|
1243
|
+
>
|
|
1244
|
+
> **Typed errors.** Every error path the SDK throws — missing tmux/psmux/bun, unknown session id, missing `.compile()`, invalid workflow file, `minSDKVersion` mismatch — is a typed class (`MissingDependencyError`, `SessionNotFoundError`, `WorkflowNotCompiledError`, `InvalidWorkflowError`, `IncompatibleSDKError`). Catch them with `instanceof` to render friendly CLI output without parsing message text. See `examples/pane-navigation/cli.ts` for a worked example.
|
|
1218
1245
|
|
|
1219
|
-
###
|
|
1246
|
+
### Primitives, not a wrapper
|
|
1220
1247
|
|
|
1221
|
-
|
|
1248
|
+
The SDK ships pure functions you compose into whatever CLI shape you want:
|
|
1222
1249
|
|
|
1223
|
-
|
|
|
1224
|
-
|
|
|
1225
|
-
| `
|
|
1226
|
-
| `
|
|
1227
|
-
| `
|
|
1250
|
+
| Primitive | Purpose |
|
|
1251
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
1252
|
+
| `defineWorkflow` | Author a workflow with `.for(agent).run(...).compile()`. Pass `source: import.meta.path`. |
|
|
1253
|
+
| `createRegistry` | Build an immutable registry of workflows for iteration / lookup. |
|
|
1254
|
+
| `listWorkflows(reg)` | Snapshot every workflow in a registry. |
|
|
1255
|
+
| `getWorkflow(reg, …)` | Resolve `(agent, name)` → workflow. |
|
|
1256
|
+
| `getName / getAgent / getInputSchema / getDescription / getSource / getMinSDKVersion` | Read workflow metadata. |
|
|
1257
|
+
| `validateInputs(wf, raw)` | Run the same validation pipeline atomic uses (required, defaults, enum, integer). |
|
|
1258
|
+
| `runWorkflow({ workflow, inputs, detach? })` | Spawn the orchestrator tmux session and (optionally) attach. Resolves with `{ id, tmuxSessionName }`. |
|
|
1259
|
+
| `listSessions / getSession / stopSession / attachSession / detachSession` | Manage running tmux sessions on the shared atomic socket. |
|
|
1260
|
+
| `getSessionStatus / getSessionTranscript` | Read the orchestrator-written status snapshot or per-session messages from disk. |
|
|
1261
|
+
| `nextWindow / previousWindow / gotoOrchestrator` | **Pane navigation** — pure tmux verbs that update the session's current-window pointer. Never auto-attach; an attached client sees the change live, otherwise a subsequent `attachSession` lands on the new window. |
|
|
1262
|
+
| `MissingDependencyError / SessionNotFoundError / WorkflowNotCompiledError / InvalidWorkflowError / IncompatibleSDKError` | **Typed errors** thrown by the primitives above. Catch with `instanceof` to render friendly CLI messages without parsing message text. |
|
|
1228
1263
|
|
|
1229
|
-
**Single workflow (most common)
|
|
1264
|
+
**Single workflow (most common):**
|
|
1230
1265
|
|
|
1231
1266
|
```ts
|
|
1232
1267
|
// src/claude-worker.ts
|
|
1233
|
-
import {
|
|
1268
|
+
import { Command } from "@commander-js/extra-typings";
|
|
1269
|
+
import { getInputSchema, runWorkflow } from "@bastani/atomic/workflows";
|
|
1234
1270
|
import workflow from "./workflows/review-to-merge/claude.ts";
|
|
1235
1271
|
|
|
1236
|
-
|
|
1237
|
-
|
|
1272
|
+
const program = new Command();
|
|
1273
|
+
for (const input of getInputSchema(workflow)) {
|
|
1274
|
+
program.option(`--${input.name} <value>`, input.description ?? "");
|
|
1275
|
+
}
|
|
1276
|
+
program.action(async (rawOpts) => {
|
|
1277
|
+
const inputs = rawOpts as Record<string, string>;
|
|
1278
|
+
await runWorkflow({ workflow, inputs });
|
|
1279
|
+
});
|
|
1280
|
+
await program.parseAsync();
|
|
1238
1281
|
```
|
|
1239
1282
|
|
|
1240
1283
|
Run it:
|
|
1241
1284
|
|
|
1242
1285
|
```bash
|
|
1243
|
-
bun run src/claude-worker.ts
|
|
1286
|
+
bun run src/claude-worker.ts --target_branch=release/v2
|
|
1244
1287
|
```
|
|
1245
1288
|
|
|
1246
|
-
**Multiple workflows —
|
|
1289
|
+
**Multiple workflows — iterate a registry:**
|
|
1247
1290
|
|
|
1248
1291
|
```ts
|
|
1249
1292
|
// src/cli.ts
|
|
1250
|
-
import {
|
|
1293
|
+
import { Command } from "@commander-js/extra-typings";
|
|
1294
|
+
import {
|
|
1295
|
+
createRegistry,
|
|
1296
|
+
getInputSchema,
|
|
1297
|
+
getName,
|
|
1298
|
+
listWorkflows,
|
|
1299
|
+
runWorkflow,
|
|
1300
|
+
} from "@bastani/atomic/workflows";
|
|
1251
1301
|
import reviewToMerge from "./workflows/review-to-merge/claude.ts";
|
|
1252
1302
|
import genSpec from "./workflows/gen-spec/claude.ts";
|
|
1253
1303
|
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
Run it:
|
|
1258
|
-
|
|
1259
|
-
```bash
|
|
1260
|
-
bun run src/cli.ts -n review-to-merge -a claude
|
|
1261
|
-
bun run src/cli.ts -a claude # interactive picker (TTY)
|
|
1262
|
-
```
|
|
1263
|
-
|
|
1264
|
-
See [`examples/multi-workflow/`](./examples/multi-workflow) for a complete runnable version — two Claude workflows (`hello`, `goodbye`) registered under one `cli.ts`, with the `createRegistry()` variant shown side by side in a comment.
|
|
1265
|
-
|
|
1266
|
-
**Dynamic composition — `createRegistry`:**
|
|
1304
|
+
const registry = createRegistry().register(reviewToMerge).register(genSpec);
|
|
1305
|
+
const program = new Command("my-app");
|
|
1267
1306
|
|
|
1268
|
-
|
|
1269
|
-
|
|
1307
|
+
for (const wf of listWorkflows(registry)) {
|
|
1308
|
+
const sub = program.command(getName(wf)).description(wf.description);
|
|
1309
|
+
for (const input of getInputSchema(wf)) {
|
|
1310
|
+
sub.option(`--${input.name} <value>`, input.description ?? "");
|
|
1311
|
+
}
|
|
1312
|
+
sub.action(async (rawOpts) => {
|
|
1313
|
+
await runWorkflow({ workflow: wf, inputs: rawOpts as Record<string, string> });
|
|
1314
|
+
});
|
|
1315
|
+
}
|
|
1270
1316
|
|
|
1271
|
-
|
|
1272
|
-
await createWorkflowCli(registry).run();
|
|
1317
|
+
await program.parseAsync();
|
|
1273
1318
|
```
|
|
1274
1319
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
### One method: `run()`
|
|
1320
|
+
See [`examples/multi-workflow/`](./examples/multi-workflow) for a complete runnable version — two Claude workflows (`hello`, `goodbye`) registered under one `cli.ts`.
|
|
1278
1321
|
|
|
1279
|
-
|
|
1322
|
+
### Programmatic invocation
|
|
1280
1323
|
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
Example — programmatic invocation without argv:
|
|
1324
|
+
`runWorkflow({ workflow, inputs })` is a plain async function — you don't need a CLI at all:
|
|
1284
1325
|
|
|
1285
1326
|
```ts
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
argv: false,
|
|
1289
|
-
name: "review-to-merge",
|
|
1290
|
-
agent: "claude",
|
|
1291
|
-
inputs: { target_branch: "main" },
|
|
1292
|
-
});
|
|
1327
|
+
import { runWorkflow } from "@bastani/atomic/workflows";
|
|
1328
|
+
import workflow from "./workflows/review-to-merge/claude.ts";
|
|
1293
1329
|
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
argv: false,
|
|
1297
|
-
name: "review-to-merge",
|
|
1298
|
-
agent: "claude",
|
|
1330
|
+
const { id, tmuxSessionName } = await runWorkflow({
|
|
1331
|
+
workflow,
|
|
1299
1332
|
inputs: { target_branch: "main" },
|
|
1333
|
+
detach: true,
|
|
1300
1334
|
});
|
|
1301
1335
|
```
|
|
1302
1336
|
|
|
1303
|
-
|
|
1337
|
+
Combine with `getSessionStatus(tmuxSessionName)` and `attachSession(id)` to build your own monitoring UI on top of the SDK.
|
|
1338
|
+
|
|
1339
|
+
### Embedding under a parent CLI — `runWorkflow` inside any Commander tree
|
|
1304
1340
|
|
|
1305
|
-
|
|
1341
|
+
The SDK no longer ships a Commander adapter — it doesn't need one. Just call `runWorkflow` from inside any Commander action:
|
|
1306
1342
|
|
|
1307
1343
|
```ts
|
|
1308
|
-
import { createWorkflowCli } from "@bastani/atomic/workflows";
|
|
1309
|
-
import { toCommand, runCli } from "@bastani/atomic/workflows/commander";
|
|
1310
1344
|
import { Command } from "@commander-js/extra-typings";
|
|
1345
|
+
import { getInputSchema, runWorkflow } from "@bastani/atomic/workflows";
|
|
1311
1346
|
import workflow from "./workflows/deploy/claude.ts";
|
|
1312
1347
|
|
|
1313
|
-
const cli = createWorkflowCli(workflow);
|
|
1314
|
-
|
|
1315
1348
|
const program = new Command("my-app");
|
|
1316
|
-
|
|
1349
|
+
|
|
1350
|
+
const deploy = program.command("deploy").description(workflow.description);
|
|
1351
|
+
for (const input of getInputSchema(workflow)) {
|
|
1352
|
+
deploy.option(`--${input.name} <value>`, input.description ?? "");
|
|
1353
|
+
}
|
|
1354
|
+
deploy.action(async (rawOpts) => {
|
|
1355
|
+
await runWorkflow({ workflow, inputs: rawOpts as Record<string, string> });
|
|
1356
|
+
});
|
|
1357
|
+
|
|
1317
1358
|
program.command("hello").action(() => console.log("hi"));
|
|
1318
1359
|
|
|
1319
|
-
|
|
1320
|
-
// re-entry — when the process is a tmux-spawned orchestrator, it drives
|
|
1321
|
-
// runOrchestrator; otherwise it invokes your callback (argv parse + any
|
|
1322
|
-
// bootstrap you want). PyTorch's init_process_group for rank-zero
|
|
1323
|
-
// dispatch — no guards, no env-var checks in user code.
|
|
1324
|
-
await runCli(cli, () => program.parseAsync());
|
|
1360
|
+
await program.parseAsync();
|
|
1325
1361
|
```
|
|
1326
1362
|
|
|
1327
|
-
|
|
1363
|
+
There's no re-entry boilerplate — the SDK ships its own internal orchestrator entry script and re-execs *that* with positional args (`workflowSource`, `agent`, base64-encoded inputs). Your CLI is never re-imported, so there's nothing to guard against orchestrator-mode env vars.
|
|
1328
1364
|
|
|
1329
|
-
### `
|
|
1365
|
+
### `WorkflowPicker` component
|
|
1330
1366
|
|
|
1331
|
-
|
|
1367
|
+
The interactive picker (the same one `atomic workflow -a claude` opens) is exposed as a component:
|
|
1332
1368
|
|
|
1333
1369
|
```ts
|
|
1334
|
-
|
|
1370
|
+
import { WorkflowPicker } from "@bastani/atomic/workflows/components";
|
|
1335
1371
|
```
|
|
1336
1372
|
|
|
1373
|
+
Mount it inside your own OpenTUI app or imperatively via `WorkflowPickerPanel.create({ agent, registry })`.
|
|
1374
|
+
|
|
1337
1375
|
### Registry rules
|
|
1338
1376
|
|
|
1339
1377
|
- `createRegistry()` returns an **immutable** registry. Each `.register(wf)` call returns a **new** registry — the original is unchanged. Chain calls to accumulate workflows.
|
|
1340
1378
|
- Each workflow is keyed by `${agent}/${name}` — the `(agent, name)` pair must be unique. Registering a duplicate throws immediately.
|
|
1341
|
-
- `createWorkflowCli(registry)` inspects every registered workflow and builds a union of their declared inputs. Same-name / same-type flags are shared; same-name / different-type conflicts throw at construction time so ambiguity never reaches runtime.
|
|
1342
1379
|
- Builtin workflows (`ralph`, `deep-research-codebase`, `open-claude-design`) are managed by `atomic`'s internal `createBuiltinRegistry()`. They are reserved — user-registered workflows with the same name will not shadow builtins when running the `atomic` CLI.
|
|
1343
1380
|
|
|
1344
1381
|
### Input precedence
|
|
1345
1382
|
|
|
1346
|
-
|
|
1383
|
+
`runWorkflow({ workflow, inputs })` runs `validateInputs(workflow, inputs)` for you, applying:
|
|
1347
1384
|
|
|
1348
|
-
1. `defineWorkflow` default values (on each `WorkflowInput`)
|
|
1349
|
-
2.
|
|
1350
|
-
|
|
1351
|
-
- `createWorkflowCli(registry, { inputs })` / `cli.run({ inputs })` for the multi-workflow shape
|
|
1352
|
-
3. CLI flags — `--<field>=<value>` passed at runtime
|
|
1385
|
+
1. `defineWorkflow` default values (on each `WorkflowInput`) when no value is provided
|
|
1386
|
+
2. The first declared enum value when `required: true` and no value is provided
|
|
1387
|
+
3. Whatever you pass in `inputs`
|
|
1353
1388
|
|
|
1354
|
-
|
|
1389
|
+
CLI flags compose entirely at the calling-CLI layer — the SDK only sees the final `inputs` map.
|
|
1355
1390
|
|
|
1356
1391
|
### Builtin workflows via the `atomic` CLI
|
|
1357
1392
|
|
|
1358
|
-
The `atomic workflow` command
|
|
1393
|
+
The `atomic workflow` command runs the built-in registry via the same primitives:
|
|
1359
1394
|
|
|
1360
1395
|
```bash
|
|
1361
1396
|
atomic workflow -n ralph -a claude "Build the auth module"
|
|
@@ -1365,19 +1400,14 @@ atomic workflow -n open-claude-design -a claude
|
|
|
1365
1400
|
|
|
1366
1401
|
These are not affected by your own `createRegistry()` — they are separate.
|
|
1367
1402
|
|
|
1368
|
-
### Migration from 0.x (directory-scanning)
|
|
1369
|
-
|
|
1370
|
-
> This is a breaking change. The SDK no longer scans `.atomic/workflows/` directories.
|
|
1403
|
+
### Migration from 0.x (directory-scanning) and the `createWorkflowCli` wrapper
|
|
1371
1404
|
|
|
1372
|
-
|
|
1373
|
-
2. **Create one entrypoint file per agent**, e.g. `src/claude-worker.ts`:
|
|
1374
|
-
```ts
|
|
1375
|
-
import { createWorkflowCli } from "@bastani/atomic/workflows";
|
|
1376
|
-
import workflow from "./workflows/my-workflow/claude.ts";
|
|
1405
|
+
> Two breaking changes: workflows must declare `source: import.meta.path`, and the `createWorkflowCli` / `toCommand` / `runCli` wrappers were removed in favour of primitives.
|
|
1377
1406
|
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
3. **
|
|
1407
|
+
1. **Add `source: import.meta.path`** to every `defineWorkflow({ ... })` call. The SDK uses it to import the workflow module inside the orchestrator child process.
|
|
1408
|
+
2. **Replace `createWorkflowCli(workflow).run()`** with a small Commander (or citty / yargs) entrypoint that calls `runWorkflow({ workflow, inputs })` — see the snippets above. The SDK no longer ships a CLI wrapper.
|
|
1409
|
+
3. **Remove `handleOrchestratorReentry` / `runCli` calls** — the SDK ships its own orchestrator entry script and the dev's CLI is never re-execed.
|
|
1410
|
+
4. **Update invocations**: replace `atomic workflow -n foo -a claude` with `bun run src/claude-worker.ts --<input>=<value>` for your custom workflows. For the Atomic builtin set (`ralph`, `deep-research-codebase`, `open-claude-design`) keep using `atomic workflow -n <name> -a <agent>`.
|
|
1381
1411
|
|
|
1382
1412
|
---
|
|
1383
1413
|
|
|
@@ -1481,6 +1511,11 @@ Ensure the agent CLI is in your PATH. Atomic uses `Bun.which()`, which handles `
|
|
|
1481
1511
|
|
|
1482
1512
|
## FAQ
|
|
1483
1513
|
|
|
1514
|
+
<details>
|
|
1515
|
+
<summary><b>Why not markdown, a coding agent alone, or a general agent framework?</b></summary>
|
|
1516
|
+
Markdown is great for guidance: conventions, commands, repo notes, and checklists. Use Claude Code, OpenCode, or Copilot CLI directly for normal single-session coding. Atomic is for the point where the work needs branching, retries, parallel sessions, state, human approval, sandboxed execution, or reliable handoff between stages. General agent frameworks can do some of this, but you often rebuild coding-agent basics yourself: file editing, terminal interaction, MCP setup, hooks, session handling, and repo-specific context. Atomic starts from production coding agents and adds the workflow layer around them.
|
|
1517
|
+
</details>
|
|
1518
|
+
|
|
1484
1519
|
<details>
|
|
1485
1520
|
<summary><b>How does Atomic differ from Spec-Kit?</b></summary>
|
|
1486
1521
|
|
|
@@ -1507,9 +1542,9 @@ Ensure the agent CLI is in your PATH. Atomic uses `Bun.which()`, which handles `
|
|
|
1507
1542
|
<details>
|
|
1508
1543
|
<summary><b>How does Atomic differ from DeerFlow?</b></summary>
|
|
1509
1544
|
|
|
1510
|
-
[DeerFlow](https://github.com/bytedance/deer-flow) is ByteDance's agent
|
|
1545
|
+
[DeerFlow](https://github.com/bytedance/deer-flow) is ByteDance's agent runtime built on LangGraph/LangChain. Both can run multi-agent work, but take different approaches:
|
|
1511
1546
|
|
|
1512
|
-
**In short:** DeerFlow is a general-purpose agent
|
|
1547
|
+
**In short:** DeerFlow is a general-purpose agent system with a web UI. Atomic is narrowly focused on coding workflows. The key difference is that Atomic runs on top of production coding agents (Claude Code, OpenCode, Copilot CLI) rather than reimplementing coding tools through a generic API — you get each agent's native file editing, permissions, MCP integrations, and hooks out of the box. Atomic also gives you deterministic execution, which matters when encoding a team's dev process.
|
|
1513
1548
|
|
|
1514
1549
|
| Aspect | DeerFlow | Atomic |
|
|
1515
1550
|
| ----------------------- | ----------------------------------------------- | --------------------------------------------------------------------------------------------- |
|
|
@@ -1531,9 +1566,9 @@ Ensure the agent CLI is in your PATH. Atomic uses `Bun.which()`, which handles `
|
|
|
1531
1566
|
<details>
|
|
1532
1567
|
<summary><b>How does Atomic differ from Hermes Agent?</b></summary>
|
|
1533
1568
|
|
|
1534
|
-
[Hermes Agent](https://github.com/NousResearch/hermes-agent) is Nous Research's general-purpose AI agent with a self-improving learning loop. Both are open
|
|
1569
|
+
[Hermes Agent](https://github.com/NousResearch/hermes-agent) is Nous Research's general-purpose AI agent with a self-improving learning loop. Both are open source agent projects, but serve different use cases:
|
|
1535
1570
|
|
|
1536
|
-
**In short:** Hermes is a broad AI assistant that learns across sessions and connects to messaging platforms. Atomic is
|
|
1571
|
+
**In short:** Hermes is a broad AI assistant that learns across sessions and connects to messaging platforms. Atomic is coding-specific workflow software for engineering teams. It lets you encode your development process as deterministic TypeScript workflows that run identically across team members, machines, and CI. Atomic inherits production-hardened tools from Claude Code, OpenCode, and Copilot CLI — including their permission systems, MCP integrations, and hooks — giving you two independent security boundaries (devcontainer isolation + agent permissions). Fresh context per session keeps output sharp over multi-hour tasks. Developer-authored skills don't drift the way auto-generated ones can.
|
|
1537
1572
|
|
|
1538
1573
|
| Aspect | Hermes Agent | Atomic |
|
|
1539
1574
|
| ------------------------- | -------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
|