# Smithers > Deterministic, resumable AI workflow orchestration using JSX. Smithers is a TypeScript framework for building deterministic, resumable AI workflows using JSX. You define your workflow as a tree of React components, and Smithers handles execution ordering, durable state persistence in SQLite, structured output validation, and crash recovery. - Package: `smithers-orchestrator` on npm - Runtime: Bun >= 1.3 (uses Bun's native SQLite driver) - Language: TypeScript with JSX - AI SDK: Vercel AI SDK (`ai` package) for agent abstraction ## Full Documentation For the complete documentation with all code examples, API references, and guides, see: - [llms-full.txt](https://smithers.sh/llms-full.txt): Complete inline documentation (~76k tokens) ## Recommended Models ### Codex (gpt-5.3-codex) -- Primary implementation agent - **Best for**: Writing code, implementing features, fixing bugs, refactoring - **Reasoning effort**: `high` (default). Use `xhigh` for especially complex tasks. - **CLI**: `CodexAgent` -- use if you have a Codex subscription - **AI SDK**: `openai("gpt-5.3-codex")` via `@ai-sdk/openai` -- use if you prefer API billing ### Claude (claude-opus-4-6) -- Planning, review, and tool calling - **Best for**: Research, planning, code review, reporting, tool-calling tasks, orchestration logic - **CLI**: `ClaudeCodeAgent` -- use if you have a Claude Code subscription - **AI SDK**: `anthropic("claude-opus-4-6")` via `@ai-sdk/anthropic` -- use if you prefer API billing ### Claude Sonnet (claude-sonnet-4-5-20250929) -- Simple tasks - **Best for**: Simple tool calling, lightweight reviews, report generation, tasks where a cheaper/faster model suffices - Use Sonnet when the task is straightforward and doesn't need deep reasoning ### When to use which - **Implementing code** → Codex (strongest at code generation) - **Reviewing code** → Claude Opus or Codex (run both in parallel for best results) - **Research & planning** → Claude Opus (strongest at reasoning about architecture) - **Simple tool calls** → Claude Sonnet (fast, cheap, good enough) - **Validation (running tests)** → Codex (good at interpreting build output) ### CLI vs AI SDK Use **CLI agents** (`ClaudeCodeAgent`, `CodexAgent`) when: - You have a subscription and want to use it - You want the agent's native tool ecosystem (file editing, shell, etc.) Use **AI SDK agents** (`ToolLoopAgent` from `ai`) when: - You want API billing instead of subscription - You want sandboxed tools from `smithers-orchestrator/tools` - You need more control over tool definitions ## Quick Start ```bash bun add smithers-orchestrator ai @ai-sdk/anthropic zod ``` ```tsx import { createSmithers, Task, runWorkflow } from "smithers-orchestrator"; import { ToolLoopAgent as Agent } from "ai"; import { anthropic } from "@ai-sdk/anthropic"; import { z } from "zod"; const { Workflow, smithers } = createSmithers({ analysis: z.object({ summary: z.string(), severity: z.enum(["low", "medium", "high"]) }), fix: z.object({ patch: z.string(), explanation: z.string() }), }); const analyst = new Agent({ model: anthropic("claude-sonnet-4-5-20250929"), instructions: "You are a code analyst. Return structured JSON.", }); const fixer = new Agent({ model: anthropic("claude-sonnet-4-5-20250929"), instructions: "You are a senior engineer who writes minimal, correct fixes.", }); export default smithers((ctx) => ( {`Analyze this bug: ${ctx.input.description}`} {`Fix this issue: ${ctx.output("analysis", { nodeId: "analyze" }).summary}`} )); ``` ```bash bunx smithers run workflow.tsx --input '{"description": "Auth tokens expire silently"}' ``` ## Core Concepts - **Workflow**: JSX tree defining the execution graph. Re-renders after each task completes. - **Task**: Single unit of work (AI agent call or static data). Identified by `id` prop. - **Sequence**: Tasks run top-to-bottom. Default behavior inside ``. - **Parallel**: Tasks run concurrently with optional `maxConcurrency`. - **Branch**: Conditional execution based on a boolean (`if`/`then`/`else`). - **Ralph**: Iterative loop with `until` condition and `maxIterations` safety cap. - **Context (`ctx`)**: Access `input`, completed `output` rows, `runId`, `iteration`. - **Resume**: Re-running with same `runId` skips completed tasks automatically. - **Schema Registry**: Zod schemas passed to `createSmithers()` auto-create SQLite tables. ## Key Exports ```ts // Core import { createSmithers, Task, Sequence, Parallel, Branch, Ralph, runWorkflow, renderFrame } from "smithers-orchestrator"; // Tools (sandboxed filesystem + shell) import { read, write, edit, grep, bash, tools } from "smithers-orchestrator/tools"; // CLI Agents import { ClaudeCodeAgent, CodexAgent, GeminiAgent } from "smithers-orchestrator/agents/cli"; // HTTP Server import { startServer } from "smithers-orchestrator/server"; // PI Plugin (HTTP client) import { runWorkflow, resume, approve, deny, streamEvents, getStatus } from "smithers-orchestrator/pi-plugin"; ``` ## TSConfig ```json { "compilerOptions": { "jsx": "react-jsx", "jsxImportSource": "smithers-orchestrator" } } ``` ## Recommended Project Structure For non-trivial workflows, we strongly recommend this file structure with **one component per step**, **MDX prompts**, and **Zod schema files**: ``` scripts/my-workflow/ workflow.tsx # Root workflow -- thin, just composition smithers.ts # createSmithers() + schema registry agents.ts # Agent definitions (CLI + API SDK) config.ts # Shared constants (max iterations, etc.) system-prompt.ts # Build system prompt from MDX + docs preload.ts # MDX plugin registration bunfig.toml # preload = ["./preload.ts"] package.json tsconfig.json run.sh # Shell script to launch workflow components/ index.ts # Re-export all components Discover.tsx # Component Discover.schema.ts # Zod schema for output Discover.mdx # Prompt template (MDX) Implement.tsx Implement.schema.ts Implement.mdx Validate.tsx Validate.schema.ts Validate.mdx Review.tsx Review.schema.ts Review.mdx ReviewFix.tsx ReviewFix.schema.ts ReviewFix.mdx Report.tsx Report.schema.ts Report.mdx TicketPipeline.tsx # Composed pipeline per ticket ValidationLoop.tsx # Ralph loop: implement->validate->review->fix prompts/ system-prompt.mdx # Master system prompt template *.md # Domain-specific context docs ``` ### Why this structure? - **MDX prompts**: Prompts are `.mdx` files with JSX interpolation (`{props.ticketId}`), keeping prompt engineering separate from orchestration logic - **Schema files**: Each step has a `.schema.ts` with a Zod schema, ensuring structured output validation and auto-creating SQLite tables - **One component per step**: Each step (Discover, Implement, Review, etc.) is a React component in its own file, making workflows composable and testable - **Thin workflow.tsx**: The root file just composes components -- all logic lives in components ### Key files explained **`smithers.ts`** -- Schema registry and typed exports: ```ts import { createSmithers } from "smithers"; import { DiscoverOutput } from "./components/Discover.schema"; import { ImplementOutput } from "./components/Implement.schema"; import { ValidateOutput } from "./components/Validate.schema"; import { ReviewOutput } from "./components/Review.schema"; import { ReviewFixOutput } from "./components/ReviewFix.schema"; import { ReportOutput } from "./components/Report.schema"; export const { Workflow, Task, useCtx, smithers, tables } = createSmithers({ discover: DiscoverOutput, implement: ImplementOutput, validate: ValidateOutput, review: ReviewOutput, reviewFix: ReviewFixOutput, report: ReportOutput, }, { dbPath: "./my-workflow.db" }); ``` **`agents.ts`** -- Dual CLI/API agent setup: ```ts import { ToolLoopAgent as Agent, stepCountIs, type ToolSet } from "ai"; import { anthropic } from "@ai-sdk/anthropic"; import { openai } from "@ai-sdk/openai"; import { ClaudeCodeAgent, CodexAgent } from "smithers"; import { tools as smithersTools } from "smithers/tools"; import { SYSTEM_PROMPT } from "./system-prompt"; const tools = smithersTools as ToolSet; const USE_CLI = process.env.USE_CLI_AGENTS !== "0" && process.env.USE_CLI_AGENTS !== "false"; const UNSAFE = process.env.SMITHERS_UNSAFE === "1"; // --- Codex (implementation agent) --- const CODEX_MODEL = process.env.CODEX_MODEL ?? "gpt-5.3-codex"; const codexApi = new Agent({ model: openai(CODEX_MODEL), tools, instructions: SYSTEM_PROMPT, stopWhen: stepCountIs(100), maxOutputTokens: 8192, }); const codexCli = new CodexAgent({ model: CODEX_MODEL, systemPrompt: SYSTEM_PROMPT, yolo: UNSAFE, config: { model_reasoning_effort: "high" }, timeoutMs: 30 * 60 * 1000, }); export const codex = USE_CLI ? codexCli : codexApi; // --- Claude (review/planning agent) --- const CLAUDE_MODEL = process.env.CLAUDE_MODEL ?? "claude-opus-4-6"; const claudeApi = new Agent({ model: anthropic(CLAUDE_MODEL), tools, instructions: SYSTEM_PROMPT, stopWhen: stepCountIs(100), maxOutputTokens: 8192, }); const claudeCli = new ClaudeCodeAgent({ model: CLAUDE_MODEL, systemPrompt: SYSTEM_PROMPT, dangerouslySkipPermissions: UNSAFE, timeoutMs: 30 * 60 * 1000, }); export const claude = USE_CLI ? claudeCli : claudeApi; ``` **`preload.ts`** + **`bunfig.toml`** -- Enable MDX imports: ```ts // preload.ts import { mdxPlugin } from "smithers/mdx-plugin"; mdxPlugin(); ``` ```toml # bunfig.toml preload = ["./preload.ts"] ``` **`system-prompt.ts`** -- Build rich system prompts from MDX with injected docs: ```ts import { readFileSync } from "node:fs"; import { resolve } from "node:path"; import { renderMdx } from "smithers"; import SystemPromptMdx from "./prompts/system-prompt.mdx"; const ROOT = resolve(new URL("../..", import.meta.url).pathname); function readDoc(path: string): string { try { return readFileSync(resolve(ROOT, path), "utf8"); } catch { return `[Could not read ${path}]`; } } const ClaudeMd = () => readDoc("CLAUDE.md"); const Architecture = () => readDoc("docs/architecture.md"); export const SYSTEM_PROMPT = renderMdx(SystemPromptMdx, { components: { ClaudeMd, Architecture }, }); ``` The corresponding `prompts/system-prompt.mdx` uses those components as JSX tags to compose the full system prompt: ```mdx # My Project You are building [project description]. ## Project Conventions ## Architecture ## JSON Output Requirement MUST end response with JSON object in code fence. Format specified in task prompt. ``` This pattern lets you: - Keep domain knowledge in standalone `.md` files (reusable across workflows) - Compose them into a single system prompt via MDX component injection - Share the same system prompt across all agents in the workflow - Add/remove context sections without editing prompt text For per-step prompts (e.g., `Implement.mdx`, `Review.mdx`), use `{props.*}` interpolation to inject dynamic data from the workflow context: ```mdx IMPLEMENTATION -- Ticket: {props.ticketId} {props.ticketDescription} {props.previousAttempt ? `PREVIOUS ATTEMPT FAILED:\n${props.previousAttempt.failingSummary}\nFix the issues above.` : ""} **REQUIRED OUTPUT** -- JSON matching this schema: {props.schema} ``` The `{props.schema}` variable is auto-injected by Smithers with the Zod schema description for the task's output table, so agents know exactly what JSON structure to produce. ## Common Patterns ### Pattern 1: Dynamic Ticket Discovery **For large projects (>20 tasks)**, prefer dynamic ticket discovery over hardcoding a task list. An agent explores the codebase, compares current state to specs, and generates tickets at runtime. This lets the project evolve naturally as tickets are completed. ```tsx // workflow.tsx -- Dynamic discovery export default smithers((ctx) => { const discoverOutput = ctx.latest(tables.discover, "discover-codex"); const unfinishedTickets = ctx .latestArray(discoverOutput?.tickets, Ticket) .filter((t) => !ctx.latest(tables.report, `${t.id}:report`)) as Ticket[]; return ( } /> {unfinishedTickets.map((ticket) => ( ))} ); }); ``` The Discover component runs an agent that analyzes the codebase and generates the next batch of tickets as structured JSON. When all tickets complete, the workflow re-renders, Discover runs again, and finds the next batch. This continues until the agent reports no more work. **For smaller/well-defined projects (<20 tasks)**, hardcoding tasks is fine: ```tsx // Hardcoded task list -- good for focused features const phases = [ { id: "auth-types", name: "Add auth types" }, { id: "auth-middleware", name: "Add auth middleware" }, { id: "auth-routes", name: "Add auth routes" }, { id: "auth-tests", name: "Add auth tests" }, ]; export default smithers((ctx) => ( {phases.map(({ id, name }) => ( {`Implement: ${name}`} {`Validate: run tests for ${name}`} ))} )); ``` ### Pattern 2: Implement-Review Ralph Loop **Strongly recommended.** Wrap implementation in a Ralph loop with validation and review. This catches issues early and forces agents to fix them before moving on. ```tsx // ValidationLoop.tsx import { Ralph, Sequence } from "smithers"; export function ValidationLoop({ ticket }: { ticket: Ticket }) { const ctx = useCtx(); const ticketId = ticket.id; const claudeReview = ctx.latest(tables.review, `${ticketId}:review-claude`) as ReviewOutput | undefined; const codexReview = ctx.latest(tables.review, `${ticketId}:review-codex`) as ReviewOutput | undefined; const allApproved = !!claudeReview?.approved && !!codexReview?.approved; return ( ); } ``` The loop runs: implement → validate (run tests) → review (check quality) → fix (address issues). It repeats until both reviewers approve or `maxIterations` is hit. ### Pattern 3: Parallel Multi-Agent Review Run multiple reviewers in parallel for higher-quality feedback. Use `continueOnFail` so one reviewer timing out doesn't block the other. ```tsx // Review.tsx export function Review({ ticket }: { ticket: Ticket }) { const ctx = useCtx(); const ticketId = ticket.id; const latestValidate = ctx.latest(tables.validate, `${ticketId}:validate`) as ValidateOutput | undefined; if (!latestValidate?.allPassed) return null; // Skip review if tests fail return ( ); } ``` ### Pattern 4: Pipeline per Ticket Compose steps into a per-ticket pipeline, with `skipIf` for completed tickets so resume works correctly. ```tsx // TicketPipeline.tsx export function TicketPipeline({ ticket }: { ticket: Ticket }) { const ctx = useCtx(); const latestReport = ctx.latest(tables.report, `${ticket.id}:report`) as ReportOutput | undefined; const ticketComplete = latestReport != null; return ( ); } ``` ### Pattern 5: MDX Prompt with Props Use MDX files for prompts with interpolated props. This keeps prompts readable and separates prompt engineering from orchestration logic. ``` // Implement.mdx IMPLEMENTATION -- Ticket: {props.ticketId} -- {props.ticketTitle} TICKET DESCRIPTION: {props.ticketDescription} ACCEPTANCE CRITERIA: - {props.acceptanceCriteria} {props.previousImplementation ? `\nPREVIOUS ATTEMPT:\n${props.previousImplementation.whatWasDone}\nFix issues from previous attempt.` : ""} {props.reviewFixes ? `\nREVIEW FIXES NEEDED:\n${props.reviewFixes}` : ""} **REQUIRED OUTPUT** -- JSON matching this schema: {props.schema} ``` The corresponding component imports the MDX and passes props: ```tsx // Implement.tsx import { Task } from "../smithers"; import { codex } from "../agents"; import ImplementPrompt from "./Implement.mdx"; export function Implement({ ticket }: { ticket: Ticket }) { const ctx = useCtx(); const ticketId = ticket.id; const latestValidate = ctx.latest(tables.validate, `${ticketId}:validate`) as ValidateOutput | undefined; return ( ); } ``` ### Pattern 6: Zod Schema per Step Every step gets a dedicated schema file. Schemas auto-create SQLite tables and validate agent output. ```ts // Implement.schema.ts import { z } from "zod"; export const ImplementOutput = z.object({ filesCreated: z.array(z.string()).nullable().describe("Files created"), filesModified: z.array(z.string()).nullable().describe("Files modified"), commitMessages: z.array(z.string()).describe("Git commit messages made"), whatWasDone: z.string().describe("Detailed description of what was implemented"), testsWritten: z.array(z.string()).describe("Test files written"), allTestsPassing: z.boolean().describe("Whether all tests pass"), testOutput: z.string().describe("Output from running tests"), }); export type ImplementOutput = z.infer; ``` ### Pattern 7: Multi-Pass Refinement with Sprint Tracking For very large projects, wrap the entire workflow in a Ralph loop with a pass tracker. Each pass discovers new work, implements it, and advances a counter. ```tsx export default smithers((ctx) => { const passTracker = ctx.latest(tables.output, "sprint-tracker") as { sprintsCompleted?: number } | undefined; const currentSprint = passTracker?.sprintsCompleted ?? 0; const projectComplete = /* check completion condition */; return ( {/* Sprint work here -- discover, implement, test, review */} {{ sprintsCompleted: currentSprint + 1, summary: `Sprint ${currentSprint + 1} complete.` }} ); }); ``` ## Monitoring & Debugging ### SQLite Inspection All workflow state is persisted in SQLite. Query it directly to monitor progress: ```bash # See all completed tasks sqlite3 my-workflow.db "SELECT node_id, status, created_at FROM smithers_attempts ORDER BY created_at DESC" # Check outputs for a specific step sqlite3 my-workflow.db "SELECT * FROM implement WHERE node_id LIKE '%:implement' ORDER BY created_at DESC LIMIT 5" # Count iterations per task (useful for Ralph loops) sqlite3 my-workflow.db "SELECT node_id, COUNT(*) as iterations FROM smithers_attempts WHERE status='completed' GROUP BY node_id" # See review approval status sqlite3 my-workflow.db "SELECT node_id, json_extract(data, '$.approved') as approved, json_extract(data, '$.feedback') as feedback FROM review" ``` ### JJ (Jujutsu) VCS Integration Smithers auto-snapshots the workspace with JJ before each task executes. This enables: - **Reverting** to any previous task's state: `bunx smithers revert --to ` - **Diffing** between task attempts to see what an agent actually changed - **Crash recovery** -- if an agent corrupts the workspace, revert and retry ```bash # See JJ snapshots created by smithers jj log --no-pager | head -40 # Diff what an agent changed during a specific task jj diff -r # Revert workspace to state before a task ran bunx smithers revert --to ``` ### CLI Status Commands ```bash # Check workflow status bunx smithers status workflow.tsx # See execution frames (what the workflow graph looks like at each render) bunx smithers frames workflow.tsx # List all runs bunx smithers list workflow.tsx # Visualize the execution graph bunx smithers graph workflow.tsx ``` ### NDJSON Logs Smithers writes NDJSON event logs to `.smithers/logs/`. Each line is a JSON event: ```bash # Tail live events tail -f .smithers/logs/*.ndjson | jq . # Filter to task completions cat .smithers/logs/*.ndjson | jq 'select(.type == "task:completed")' # See errors cat .smithers/logs/*.ndjson | jq 'select(.type == "task:failed")' ``` ### Programmatic Monitoring Use the `onProgress` callback for real-time monitoring: ```ts await runWorkflow(workflow, { input: {}, onProgress: (event) => { if (event.type === "task:completed") { console.log(`Completed: ${event.nodeId}`); } if (event.type === "task:failed") { console.error(`Failed: ${event.nodeId}`, event.error); } }, }); ``` ## Source Code Reference Raw source files on GitHub for reading implementation details. Use these when docs aren't enough. Base URL: `https://github.com/evmts/smithers/blob/main/` ### Core | File | Description | |------|-------------| | [src/index.ts](https://github.com/evmts/smithers/blob/main/src/index.ts) | Main entry point. `createSmithers()`, `smithers()`, `runWorkflow()`, `renderFrame()` | | [src/types.ts](https://github.com/evmts/smithers/blob/main/src/types.ts) | All core types: `SmithersWorkflow`, `SmithersCtx`, `TaskDescriptor`, `RunOptions`, `RunResult`, `AgentLike`, `GraphSnapshot` | | [src/components.ts](https://github.com/evmts/smithers/blob/main/src/components.ts) | JSX components: `Workflow`, `Task`, `Sequence`, `Parallel`, `Branch`, `Ralph` | | [src/context.ts](https://github.com/evmts/smithers/blob/main/src/context.ts) | `SmithersContext` React context and `useCtx()` hook | | [src/events.ts](https://github.com/evmts/smithers/blob/main/src/events.ts) | Event types and lifecycle event definitions | | [src/jsx-runtime.ts](https://github.com/evmts/smithers/blob/main/src/jsx-runtime.ts) | Custom JSX runtime for `jsxImportSource: "smithers-orchestrator"` | ### Engine | File | Description | |------|-------------| | [src/engine/index.ts](https://github.com/evmts/smithers/blob/main/src/engine/index.ts) | Core execution engine: render-schedule-execute-persist loop, agent invocation, retry logic | | [src/engine/scheduler.ts](https://github.com/evmts/smithers/blob/main/src/engine/scheduler.ts) | Task scheduling: determines which tasks are ready, handles Sequence/Parallel/Ralph ordering | | [src/engine/approvals.ts](https://github.com/evmts/smithers/blob/main/src/engine/approvals.ts) | Human-in-the-loop approval/denial operations | ### DOM / Renderer | File | Description | |------|-------------| | [src/dom/renderer.ts](https://github.com/evmts/smithers/blob/main/src/dom/renderer.ts) | Custom React reconciler: renders JSX workflow tree into `TaskDescriptor[]` and XML snapshots | | [src/dom/extract.ts](https://github.com/evmts/smithers/blob/main/src/dom/extract.ts) | Walks reconciler host nodes to extract `TaskDescriptor[]` for the scheduler | ### Database | File | Description | |------|-------------| | [src/db/adapter.ts](https://github.com/evmts/smithers/blob/main/src/db/adapter.ts) | Drizzle ORM database adapter wrapping Bun SQLite | | [src/db/ensure.ts](https://github.com/evmts/smithers/blob/main/src/db/ensure.ts) | Auto-creates internal tables (`smithers_attempts`, `smithers_cache`, etc.) | | [src/db/snapshot.ts](https://github.com/evmts/smithers/blob/main/src/db/snapshot.ts) | Loads persisted outputs for workflow re-rendering | | [src/db/output.ts](https://github.com/evmts/smithers/blob/main/src/db/output.ts) | Writes task outputs to schema-driven tables | | [src/db/internal-schema.ts](https://github.com/evmts/smithers/blob/main/src/db/internal-schema.ts) | Drizzle schema for internal tables (attempts, cache, tool calls) | | [src/db/input.ts](https://github.com/evmts/smithers/blob/main/src/db/input.ts) | Loads workflow input from database | | [src/db/schema-signature.ts](https://github.com/evmts/smithers/blob/main/src/db/schema-signature.ts) | Schema hashing for cache invalidation | ### Schema Utilities | File | Description | |------|-------------| | [src/zod-to-table.ts](https://github.com/evmts/smithers/blob/main/src/zod-to-table.ts) | Converts Zod schemas to Drizzle table definitions + raw `CREATE TABLE` SQL | | [src/zod-to-example.ts](https://github.com/evmts/smithers/blob/main/src/zod-to-example.ts) | Converts Zod schemas to example JSON (injected as `{props.schema}` in prompts) | ### Agents | File | Description | |------|-------------| | [src/agents/cli.ts](https://github.com/evmts/smithers/blob/main/src/agents/cli.ts) | CLI agent wrappers: `ClaudeCodeAgent`, `CodexAgent`, `GeminiAgent` | ### Tools | File | Description | |------|-------------| | [src/tools/index.ts](https://github.com/evmts/smithers/blob/main/src/tools/index.ts) | Sandboxed tools: `read`, `write`, `edit`, `grep`, `bash` | | [src/tools/context.ts](https://github.com/evmts/smithers/blob/main/src/tools/context.ts) | Tool execution context (rootDir sandboxing, audit logging) | | [src/tools/utils.ts](https://github.com/evmts/smithers/blob/main/src/tools/utils.ts) | Tool utility functions | ### VCS | File | Description | |------|-------------| | [src/vcs/jj.ts](https://github.com/evmts/smithers/blob/main/src/vcs/jj.ts) | Jujutsu VCS adapter: workspace snapshots, diffs, revert operations | ### MDX | File | Description | |------|-------------| | [src/mdx-plugin.ts](https://github.com/evmts/smithers/blob/main/src/mdx-plugin.ts) | Bun preload plugin for `.mdx` imports | | [src/mdx-components.ts](https://github.com/evmts/smithers/blob/main/src/mdx-components.ts) | Default MDX components and `renderMdx()` utility | ### Server & PI Plugin | File | Description | |------|-------------| | [src/server/index.ts](https://github.com/evmts/smithers/blob/main/src/server/index.ts) | HTTP server: REST API for runs, SSE event streaming, approval endpoints | | [src/pi-plugin/index.ts](https://github.com/evmts/smithers/blob/main/src/pi-plugin/index.ts) | Lightweight HTTP client for remote Smithers interaction | ### CLI | File | Description | |------|-------------| | [src/cli/index.ts](https://github.com/evmts/smithers/blob/main/src/cli/index.ts) | CLI binary: `smithers run`, `resume`, `approve`, `deny`, `status`, `frames`, `list`, `graph`, `revert` | ### Revert | File | Description | |------|-------------| | [src/revert.ts](https://github.com/evmts/smithers/blob/main/src/revert.ts) | Workspace revert logic using JJ snapshots | ### Utilities | File | Description | |------|-------------| | [src/utils/errors.ts](https://github.com/evmts/smithers/blob/main/src/utils/errors.ts) | Error types and handling | | [src/utils/hash.ts](https://github.com/evmts/smithers/blob/main/src/utils/hash.ts) | SHA-256 hashing for content-addressed caching | | [src/utils/ids.ts](https://github.com/evmts/smithers/blob/main/src/utils/ids.ts) | Run ID and attempt ID generation | | [src/utils/tree-ids.ts](https://github.com/evmts/smithers/blob/main/src/utils/tree-ids.ts) | Deterministic node ID computation from JSX tree position | | [src/utils/time.ts](https://github.com/evmts/smithers/blob/main/src/utils/time.ts) | Time utilities | | [src/utils/xml.ts](https://github.com/evmts/smithers/blob/main/src/utils/xml.ts) | XML serialization for graph snapshots | ### Tests | File | Description | |------|-------------| | [tests/engine.test.tsx](https://github.com/evmts/smithers/blob/main/tests/engine.test.tsx) | Engine tests: Ralph iteration, Sequence/Parallel execution, resume, skipIf, timeouts, approvals | | [tests/renderer.test.tsx](https://github.com/evmts/smithers/blob/main/tests/renderer.test.tsx) | Renderer tests: reconciler updates, prop changes | | [tests/docs-examples.test.tsx](https://github.com/evmts/smithers/blob/main/tests/docs-examples.test.tsx) | Documentation examples as runnable tests: Branch, Parallel, `createSmithers()`, context API | | [tests/cli.test.ts](https://github.com/evmts/smithers/blob/main/tests/cli.test.ts) | CLI command tests | | [tests/server.test.ts](https://github.com/evmts/smithers/blob/main/tests/server.test.ts) | HTTP server tests | | [tests/tools.test.ts](https://github.com/evmts/smithers/blob/main/tests/tools.test.ts) | Sandboxed tools tests: read, grep, bash, symlink protection | | [tests/pi-plugin.test.ts](https://github.com/evmts/smithers/blob/main/tests/pi-plugin.test.ts) | PI plugin client tests | | [tests/jj-workspace.test.ts](https://github.com/evmts/smithers/blob/main/tests/jj-workspace.test.ts) | JJ VCS workspace integration tests | | [tests/revert.test.ts](https://github.com/evmts/smithers/blob/main/tests/revert.test.ts) | Workflow revert tests | | [tests/helpers.ts](https://github.com/evmts/smithers/blob/main/tests/helpers.ts) | Test utilities: `createTestDb()`, `sleep()` | | [tests/schema.ts](https://github.com/evmts/smithers/blob/main/tests/schema.ts) | Shared test schema and DDL | | [tests/fixtures/test-workflow.tsx](https://github.com/evmts/smithers/blob/main/tests/fixtures/test-workflow.tsx) | Test workflow fixture | | [tests/fixtures/approval-workflow.tsx](https://github.com/evmts/smithers/blob/main/tests/fixtures/approval-workflow.tsx) | Approval workflow test fixture | ### Examples | File | Description | |------|-------------| | [examples/simple-workflow.tsx](https://github.com/evmts/smithers/blob/main/examples/simple-workflow.tsx) | Minimal two-step workflow: research → write article (uses old Drizzle API) | | [examples/code-review-loop.tsx](https://github.com/evmts/smithers/blob/main/examples/code-review-loop.tsx) | Review-fix Ralph loop with sandboxed tools (uses old Drizzle API) | ### Config | File | Description | |------|-------------| | [package.json](https://github.com/evmts/smithers/blob/main/package.json) | Package config, exports map, dependencies | | [tsconfig.json](https://github.com/evmts/smithers/blob/main/tsconfig.json) | TypeScript configuration | ## Docs ### Getting Started - [Introduction](https://smithers.sh/introduction): Overview, architecture, and how the render-execute-persist loop works. - [Installation](https://smithers.sh/installation): Install Smithers, configure TypeScript, verify setup. - [Quickstart](https://smithers.sh/quickstart): Build a two-step research workflow in 5 minutes. ### Core Concepts - [Execution Model](https://smithers.sh/concepts/execution-model): The four-phase render-schedule-execute-persist loop, node states, deterministic ordering. - [Data Model](https://smithers.sh/concepts/data-model): Schema-driven vs manual API, SQLite tables, output validation, internal tables. - [Context API](https://smithers.sh/concepts/context): `SmithersCtx` interface -- `output()`, `outputMaybe()`, `latest()`, `latestArray()`, `iterationCount()`. - [Approvals](https://smithers.sh/concepts/approvals): Human-in-the-loop gates with `needsApproval`, CLI approve/deny, events. - [Caching](https://smithers.sh/concepts/caching): Content-addressed cache with SHA-256 keys, automatic invalidation on schema/prompt/model changes. - [Renderer Internals](https://smithers.sh/concepts/renderer-internals): Custom React reconciler pipeline from JSX to TaskDescriptor[] and XML snapshots. ### Components - [Workflow](https://smithers.sh/components/workflow): Root container with implicit sequencing and optional caching. - [Task](https://smithers.sh/components/task): Agent mode (prompt -> AI -> structured output) or static mode (direct data). - [Sequence](https://smithers.sh/components/sequence): Sequential execution of children. - [Parallel](https://smithers.sh/components/parallel): Concurrent execution with optional `maxConcurrency`. - [Branch](https://smithers.sh/components/branch): Conditional `if`/`then`/`else` routing. - [Ralph](https://smithers.sh/components/ralph): Iterative loop with `until`, `maxIterations`, `onMaxReached`. ### Guides - [Tutorial: Build a Workflow](https://smithers.sh/guides/tutorial-workflow): End-to-end three-step code review workflow. - [Production Project Structure](https://smithers.sh/guides/project-structure): Recommended file layout with MDX prompts, component-per-step, and Zod schemas. - [Model Selection](https://smithers.sh/guides/model-selection): Which models to use (Codex, Claude Opus, Sonnet), CLI vs API agents, dual-agent setup. - [Implement-Review Loop](https://smithers.sh/guides/review-loop): The recommended implement-validate-review-fix Ralph loop pattern. - [Dynamic Tickets](https://smithers.sh/guides/dynamic-tickets): Agent-driven ticket discovery for large projects vs hardcoded task lists. - [MDX Prompts](https://smithers.sh/guides/mdx-prompts): Using MDX for per-step prompts and system prompt composition from docs. - [Structured Output](https://smithers.sh/guides/structured-output): Schema validation flow, auto-retry, outputSchema prop. - [Error Handling](https://smithers.sh/guides/error-handling): Retries, timeouts, continueOnFail, skipIf, Branch fallbacks. - [Workflow Patterns](https://smithers.sh/guides/patterns): Project structure, schema organization, MDX prompts, naming conventions. - [Resumability](https://smithers.sh/guides/resumability): Crash recovery, stale attempt cleanup, deterministic node IDs. - [Debugging](https://smithers.sh/guides/debugging): CLI inspection, NDJSON logs, SQLite queries. - [Monitoring & Logs](https://smithers.sh/guides/monitoring-logs): onProgress callback, NDJSON files, SSE streaming, event types. - [Best Practices](https://smithers.sh/guides/best-practices): Big coherent tasks, measurable stop conditions, structured reports. - [VCS Integration](https://smithers.sh/guides/vcs): JJ (Jujutsu) snapshots for filesystem revert support. ### Runtime API - [runWorkflow](https://smithers.sh/runtime/run-workflow): Execute a workflow programmatically. RunOptions and RunResult types. - [renderFrame](https://smithers.sh/runtime/render-frame): Preview the execution graph without running tasks. - [Events](https://smithers.sh/runtime/events): All 20+ lifecycle event types with full type definitions. - [Revert](https://smithers.sh/runtime/revert): Restore workspace to a previous attempt's state via JJ. ### CLI - [CLI Reference](https://smithers.sh/cli/overview): run, resume, approve, deny, status, frames, list, graph, revert commands. ### Integrations - [Built-in Tools](https://smithers.sh/integrations/tools): Sandboxed read, write, edit, grep, bash tools with security policies. - [CLI Agents](https://smithers.sh/integrations/cli-agents): ClaudeCodeAgent, CodexAgent, GeminiAgent wrappers. - [HTTP Server](https://smithers.sh/integrations/server): REST API for run management, SSE event streaming, approval endpoints. - [PI Plugin Client](https://smithers.sh/integrations/pi-plugin): Lightweight HTTP client for remote Smithers interaction. ### Examples - [Hello World](https://smithers.sh/examples/hello-world): Minimal single-task workflow. - [Dynamic Plan](https://smithers.sh/examples/dynamic-plan): Branch between simple and complex execution paths. - [Ralph Loop](https://smithers.sh/examples/ralph-loop): Write-then-review iterative refinement loop. - [Multi-Agent Review](https://smithers.sh/examples/multi-agent-review): Parallel reviewers with aggregation. - [Approval Gate](https://smithers.sh/examples/approval-gate): Human-in-the-loop publish workflow. - [Tools Agent](https://smithers.sh/examples/tools-agent): Codebase search with sandboxed tools. ### Reference - [Type Reference](https://smithers.sh/reference/types): All exported types including SmithersWorkflow, SmithersCtx, RunOptions, RunResult, TaskDescriptor, SmithersEvent, and component props.