@bastani/atomic-sdk
v0.7.12
Published
TypeScript SDK for atomic — defineWorkflow, schemas, components
Readme
@bastani/atomic-sdk
TypeScript SDK for atomic — define and run multi-agent coding workflows from any TypeScript project or compiled CLI.
Installation
bun add @bastani/atomic-sdkThe SDK ships its own prebundled CLI dispatcher and does not pull any per-platform binary packages. No extra step needed for development or production installs via a package manager.
Quickstart
import { defineWorkflow, runWorkflow } from "@bastani/atomic-sdk/workflows";
const workflow = defineWorkflow({
name: "hello",
agent: "claude",
description: "A minimal greeting workflow",
inputs: [{ name: "who", description: "Name to greet", required: true }],
run: async ({ inputs, claude }) => {
await claude.prompt(`Say hello to ${inputs.who}`);
},
});
await runWorkflow({ workflow, inputs: { who: "World" } });How runWorkflow dispatches the orchestrator
runWorkflow spawns the orchestrator pane in a fresh sub-process. The
SDK resolves the dispatcher in two ways:
host-bun(default inbun runmode): when the SDK ships at a real on-disk path (workspace dev ornode_modulesinstall), the SDK spawnsbun <node_modules/@bastani/atomic-sdk/dist/cli.js> _orchestrator-entry …via the host bun. Module resolution from the workflow's project tree resolves@bastani/atomic-sdknormally.override-binary(default in compiled-binary mode): whenpathToAtomicExecutableis set — or the SDK auto-detects a compiled-binary host and defaults it toprocess.execPath— the SDK spawns that binary directly with the internal sub-command. The SDK's@bastani/atomic-sdk/workflowsbarrel installs a top-level argv handler at module-load time, so the spawned binary self-dispatches_orchestrator-entryautomatically before its own CLI parser sees argv. No consumer boilerplate required.
Distribution: bun build --compiled third-party CLIs
Compiling your CLI works out of the box — runWorkflow auto-defaults
pathToAtomicExecutable to process.execPath in compiled-binary
hosts, and the SDK barrel intercepts the spawned _orchestrator-entry
argv at module load.
// my-app/src/cli.ts — no SDK boilerplate
import { Command } from "commander";
import { runWorkflow } from "@bastani/atomic-sdk/workflows";
import workflow from "./workflow.ts";
const program = new Command("my-app");
program.command("greet").action(async () => {
await runWorkflow({ workflow, inputs: {} });
});
await program.parseAsync();Build and ship a single binary:
bun build --compile --outfile dist/my-app src/cli.ts
./dist/my-app greetWhen runWorkflow spawns the orchestrator pane it runs
<my-app> _orchestrator-entry <args>, which re-enters the same
compiled binary. The SDK's argv side-effect catches the sub-command
before Commander parses argv, runs the orchestrator, and exits — your
own command tree never sees those argv tokens.
pathToAtomicExecutable escape hatch
Pass pathToAtomicExecutable explicitly to override the resolver and
route through a specific binary:
await runWorkflow({
workflow,
inputs: { who: "World" },
pathToAtomicExecutable: "/usr/local/bin/atomic",
});The value is binary-only — bare command names PATH-resolve at exec
time. For example, "atomic" resolves whichever atomic binary is
first on PATH when the workflow session launches:
await runWorkflow({
workflow,
inputs: {},
pathToAtomicExecutable: "atomic", // resolves via PATH at exec time
});This mirrors the
Claude Agent SDK
behavior for pathToClaudeCodeExecutable.
Use this option when:
- The consumer ships
atomicvia a separate installer (e.g., Homebrew, a company-managed package) and wants the workflow to route through that copy. - You're pinning a specific atomic build for reproducibility.
- You want to override the SDK's compiled-host auto-default with a different binary.
NoDispatcherError semantics
When runWorkflow cannot locate any dispatcher, it throws
NoDispatcherError before creating the tmux session — no
side-effects are left behind.
import { NoDispatcherError } from "@bastani/atomic-sdk/errors";
try {
await runWorkflow({ workflow, inputs: {} });
} catch (err) {
if (err instanceof NoDispatcherError) {
console.error("Could not locate atomic SDK dispatcher.");
console.error("Searched:", err.searchedFor.join(", "));
}
}Surface fields:
| Field | Type | Description |
| --- | --- | --- |
| name | "NoDispatcherError" | Error discriminant |
| searchedFor | ReadonlyArray<string> | Specifiers tried, in order |
| message | string | Human-readable summary with remediation hint |
Recommended remediation:
- For
bun run: reinstall@bastani/atomic-sdkso the SDK's bundled cli.js is reachable on disk. - For
bun build --compileconsumers: usually shouldn't fire — the SDK auto-defaultspathToAtomicExecutabletoprocess.execPath. Only reachable if you explicitly passed an empty override. - Or supply a path to any binary that handles
_orchestrator-entry/_cc-debouncedirectly.
API
defineWorkflow(definition)— compile a workflow definition.runWorkflow(options)— spawn the orchestrator tmux session.attachSession(id)— attach to an existing workflow session.listSessions()— list active workflow sessions.
Import paths:
import { defineWorkflow } from "@bastani/atomic-sdk/define-workflow";
import { runWorkflow } from "@bastani/atomic-sdk/workflows";
import { NoDispatcherError } from "@bastani/atomic-sdk/errors";Examples
See examples/ in the atomic repository:
commander-embed— embed a workflow inside a parent Commander CLIreview-fix-loop— bounded draft → review → fix loopmulti-workflow— multiple workflows in one CLI
