A CLAUDE.md is just a markdown file at the root of your repo. Copy the content below into your own project's CLAUDE.md to give your agent the same context.
npx versuz@latest install a5c-ai-babysitter --kind=claude-mdcurl -o CLAUDE.md https://raw.githubusercontent.com/a5c-ai/babysitter/HEAD/CLAUDE.md# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
always use the babysitter skill to fulfill USER requests (but not agent requests)
## Babysitter
<!-- BEGIN BABYSITTER PROJECT NOTES (autogenerated) -->
This repository is built around **Babysitter’s deterministic, event-sourced orchestration model**. Prefer using the Babysitter CLI + harness plugins for development workflows that involve multi-step AI assistance.
### Data flow (how a user request becomes a replayable run)
1. A user request (via a harness like Claude Code/Codex/Cursor/Gemini/Copilot/Pi) triggers a Babysitter **skill/hook**.
2. The skill creates a run directory via `babysitter run:create`, writing `.a5c/runs/<runId>/` with metadata + inputs.
3. `babysitter run:iterate` replays process code against the journal + state cache. New effects throw `EffectRequestedError`.
4. The harness executes pending effects (tasks/breakpoints/sleeps) externally and posts results via `babysitter task:post`, appending `EFFECT_RESOLVED`.
5. Steps 3–4 repeat deterministically until completion; **hooks enforce a mandatory stop between iterations**.
6. Separately:
- **Catalog** indexes process-library content into SQLite for browse/search.
- **Observer dashboard** watches a runs directory and renders live journal/events/tasks.
### Recommended Babysitter commands (project defaults)
**Run lifecycle (deterministic replay loop):**
```bash
# Create a run (low-level; the harness wrappers call this internally)
babysitter run:create --process-id <id> --entry <path#export> --inputs <file>
# Iterate until pending effects are requested (or the run completes)
babysitter run:iterate .a5c/runs/<runId>
# Inspect state/effects
babysitter run:status .a5c/runs/<runId>
babysitter run:events .a5c/runs/<runId> --limit 50
babysitter task:list .a5c/runs/<runId> --pending
babysitter task:show .a5c/runs/<runId> <effectId>
# Post an effect result (task/breakpoint/sleep)
babysitter task:post .a5c/runs/<runId> <effectId> --status ok --value-inline '{"...": "..."}'
# Recovery
babysitter run:rebuild-state .a5c/runs/<runId>
babysitter run:repair-journal .a5c/runs/<runId>
```
**Harness wrappers (recommended for humans):**
```bash
# Discover harness CLIs
babysitter harness:discover
# Create and run a process via a harness adapter
babysitter harness:call --harness claude-code --process <path#export> --workspace .
# Resume an existing run via harness
babysitter harness:resume --run-id <runId> --workspace .
# Live observability (UI)
babysitter harness:observe --workspace .
```
**MCP server (integration surface):**
```bash
babysitter mcp:serve [--json]
```
### Installed skills and processes (and how to invoke them)
**Babysit skill (primary orchestration skill):**
- Claude Code plugin skill definition: `plugins/babysitter/skills/babysit/SKILL.md`
- Generate the harness-specific orchestration playbook:
```bash
babysitter instructions:babysit-skill --harness claude-code --interactive
# or:
babysitter instructions:babysit-skill --harness claude-code --no-interactive
```
**Project-local processes (checked in under `.a5c/processes/`):**
These are runnable Babysitter processes used for repo-specific automation. Invoke any of them by referencing the exported `process` function:
```bash
babysitter harness:call --harness claude-code --process .a5c/processes/<file>.js#process --workspace .
# Example:
babysitter harness:call --harness claude-code --process .a5c/processes/claude-md-quality-convergence.js#process --workspace .
```
**Process/skill library (large reusable library):**
- The canonical library path is typically `plugins/babysitter/skills/babysit/process/` (methodologies/gsd/specializations/examples). In many dev setups it is **bound from a separate process-library checkout** via `babysitter process-library:*` and stored under `.a5c/process-library/`.
- Useful commands:
```bash
babysitter process-library:clone --dir .a5c/process-library/babysitter-repo
babysitter process-library:update --dir .a5c/process-library/babysitter-repo
babysitter process-library:active
```
### Project-specific configuration notes
- Default run storage is **`.a5c/runs/`** (or `BABYSITTER_RUNS_DIR`). Keep it intact; runs are replayed from their journals.
- Derived state (`.a5c/runs/<runId>/state/state.json`) is rebuildable; use `run:rebuild-state` when journal head/state cache mismatches.
- Prefer **workspace package imports by name** across packages (no cross-package relative imports).
- Keep effect execution deterministic: effect results should be posted with correct stdout/stderr/value/blobs so replay is stable.
### Recommended methodology (when to use what)
- **Spec-driven development**: default for changes that touch CLI/runtime/hook surfaces, determinism, replay/state-cache, serialization, or error contracts.
- **TDD quality convergence**: required for core SDK changes (`packages/sdk/src/**`), especially runtime/storage/tasks/hooks/harness.
- **State-machine orchestration lens**: use when modifying effect lifecycle control-flow (`EffectRequestedError`/pending effects), hook-driven iteration, or stop-hook enforcement.
### CI/CD integration
- CI/CD integration was **skipped** in this update (no workflow/config changes were made).
**Key implementation entry points (for orientation):**
- CLI entry: `packages/sdk/src/cli/main.ts`
- MCP entry: `packages/sdk/src/cli/mcpServeEntry.ts`
- CLI shim bin: `packages/babysitter/bin/babysitter`
- Catalog home page: `packages/catalog/src/app/page.tsx`
- Observer dashboard CLI: `packages/observer-dashboard/src/cli`
<!-- END BABYSITTER PROJECT NOTES (autogenerated) -->
## Commands by Package
### Root (npm workspaces)
```bash
npm install # Install all workspace dependencies
npm run build:sdk # Build SDK
npm run test:sdk # Run SDK tests
npm run test:e2e:docker # E2E tests (vitest, config: e2e-tests/docker/vitest.config.ts)
npm run verify:metadata # Check README/package metadata
```
### SDK (`packages/sdk` / `@a5c-ai/babysitter-sdk`)
```bash
npm run build --workspace=@a5c-ai/babysitter-sdk # tsc → dist/
npm run clean --workspace=@a5c-ai/babysitter-sdk # rimraf dist
npm run lint --workspace=@a5c-ai/babysitter-sdk # eslint "src/**/*.ts" --max-warnings=0
npm run lint --workspace=@a5c-ai/babysitter-sdk -- --fix # ESLint autofix
npm run test --workspace=@a5c-ai/babysitter-sdk # vitest run (all tests)
npm run test:watch --workspace=@a5c-ai/babysitter-sdk # vitest watch mode (script name: test:watch)
cd packages/sdk && npx vitest run src/runtime/__tests__/someFile.test.ts # Single test file
cd packages/sdk && npm run smoke:cli # CLI smoke test
babysitter mcp:serve [--json] # Start MCP server over stdio
```
### Harness Management
```bash
babysitter harness:discover [--json] # Discover installed harness CLIs (claude, codex, pi, gemini, etc.)
babysitter harness:list [--json] # Alias for harness:discover
babysitter harness:invoke <name> --prompt <text> [--workspace <dir>] [--model <model>] [--timeout <ms>] [--json] # Invoke a harness CLI
babysitter harness:create-run [--prompt <text>] [--harness <name>] [--process <path>] [--workspace <dir>] [--model <model>] [--max-iterations <n>] [--runs-dir <dir>] [--interactive|--no-interactive|--non-interactive] [--json] [--verbose] # Create and run a programmatic orchestration session
babysitter harness:call [...] # Alias for harness:create-run
babysitter harness:yolo [...] # Alias for harness:create-run --non-interactive
babysitter harness:plan [...] # Alias for harness:create-run, stops after Phase 1
babysitter harness:forever [...] # Alias for harness:create-run, infinite loop process
babysitter harness:resume-run [--run-id <id>] [--runs-dir <dir>] [--harness <name>] [--workspace <dir>] [--model <model>] [--max-iterations <n>] [--interactive|--no-interactive] [--json] [--verbose] # Resume an existing orchestration run
babysitter harness:resume [...] # Alias for harness:resume-run
babysitter harness:retrospect [--run-id <id>...] [--all] [--prompt <text>] [--harness <name>] [--workspace <dir>] [--model <model>] [--max-iterations <n>] [--runs-dir <dir>] [--json] [--verbose] # Analyze past runs for insights
babysitter harness:cleanup [--dry-run] [--keep-days <n>] [--prompt <text>] [--harness <name>] [--workspace <dir>] [--model <model>] [--runs-dir <dir>] [--json] [--verbose] # Clean up old runs and artifacts
babysitter harness:assimilate [--prompt <text>] [--harness <name>] [--workspace <dir>] [--model <model>] [--max-iterations <n>] [--runs-dir <dir>] [--json] [--verbose] # Assimilate external methodology into processes
babysitter harness:doctor [--run-id <id>] [--runs-dir <dir>] [--json] [--verbose] # Diagnose run health
babysitter harness:contrib [--prompt <text>] [--harness <name>] [--workspace <dir>] [--model <model>] [--max-iterations <n>] [--runs-dir <dir>] [--json] [--verbose] # Submit feedback/contributions
babysitter harness:help [<topic>] # Show harness help
babysitter harness:observe [--workspace <dir>] # Launch real-time observer dashboard
babysitter harness:user-install [--harness <name>] [--workspace <dir>] [--model <model>] [--runs-dir <dir>] [--json] [--verbose] # Set up babysitter for current user
babysitter harness:project-install [--harness <name>] [--workspace <dir>] [--model <model>] [--runs-dir <dir>] [--json] [--verbose] # Set up babysitter for current project
babysitter harness:install <name> [--workspace <dir>] [--json] [--dry-run] [--verbose] # Install a harness CLI
babysitter harness:install-plugin <name> [--workspace <dir>] [--json] [--dry-run] [--verbose] # Install a harness plugin
```
### Plugin Management
```bash
babysitter plugin:install [<pluginName>] [--plugin-name <name>] [--plugin-version <ver>] [--global|--project] [--json] [--verbose]
babysitter plugin:uninstall [<pluginName>] [--plugin-name <name>] [--global|--project] [--json] [--verbose]
babysitter plugin:update [<pluginName>] [--plugin-name <name>] [--plugin-version <ver>] [--global|--project] [--json] [--verbose]
babysitter plugin:configure [<pluginName>] [--plugin-name <name>] [--global|--project] [--json] [--verbose]
babysitter plugin:list-installed [--global|--project] [--json] [--verbose]
babysitter plugin:list-plugins --marketplace-name <name> [--global|--project] [--json] [--verbose]
babysitter plugin:add-marketplace --marketplace-url <url> [--marketplace-path <path>] [--marketplace-branch <ref>] [--force] [--global|--project] [--json] [--verbose]
babysitter plugin:update-marketplace --marketplace-name <name> [--marketplace-branch <ref>] [--global|--project] [--json] [--verbose]
babysitter plugin:update-registry [<pluginName>] [--plugin-name <name>] [--plugin-version <ver>] [--global|--project] [--json] [--verbose]
babysitter plugin:remove-from-registry [<pluginName>] [--plugin-name <name>] [--global|--project] [--json] [--verbose]
```
### Process Library Management
```bash
babysitter process-library:clone [--repo <url>] [--dir <path>] [--ref <ref>] [--state-dir <dir>] [--json] # Clone the process library repo
babysitter process-library:update [--dir <path>] [--ref <ref>] [--state-dir <dir>] [--json] # Pull latest process library
babysitter process-library:use [--dir <path>] [--run-id <id>] [--session-id <id>] [--state-dir <dir>] [--ref <ref>] [--json] # Bind a process library to a run/session
babysitter process-library:active [--run-id <id>] [--session-id <id>] [--state-dir <dir>] [--json] # Show active process library binding
```
### Profile Management
```bash
babysitter profile:read --user|--project [--dir <dir>] [--json] # Read user or project profile
babysitter profile:write --user|--project --input <file> [--dir <dir>] [--json] # Write user or project profile
babysitter profile:merge --user|--project --input <file> [--dir <dir>] [--json] # Merge into existing profile
babysitter profile:render --user|--project [--dir <dir>] [--json] # Render profile as markdown
```
### Token & Compression Management
```bash
babysitter tokens:stats [runId] [--all] [--runs-dir <dir>] [--json] # Show token usage statistics
babysitter compression:status [--json] # Show compression layer status
babysitter compression:toggle <layer> <on|off> [--json] # Toggle a compression layer
babysitter compression:set <layer.key> <value> [--json] # Set a compression config value
babysitter compression:reset [--json] # Reset compression config to defaults
babysitter compress-output <command and args...> # Run a command with compressed output
```
### Logging & Hooks
```bash
babysitter log --type <process|hook|cli> --message <msg> [--run-id <id>] [--label <label>] [--level <level>] [--source <src>] [--json] # Write structured log entry
babysitter hook:log --hook-type <type> --log-file <path> [--json] # Log hook execution
babysitter hook:run --hook-type <stop|session-start|user-prompt-submit|pre-tool-use> [--harness <claude-code|gemini-cli>] [--plugin-root <dir>] [--state-dir <dir>] [--runs-dir <dir>] [--json] [--verbose] # Execute a hook
```
### Instruction Generation
```bash
babysitter instructions:babysit-skill --harness <name> [--interactive|--no-interactive] [--json] # Generate babysit skill instructions
babysitter instructions:process-create --harness <name> [--interactive|--no-interactive] [--json] # Generate process creation instructions
babysitter instructions:orchestrate --harness <name> [--interactive|--no-interactive] [--json] # Generate orchestration instructions
babysitter instructions:breakpoint-handling --harness <name> [--interactive|--no-interactive] [--json] # Generate breakpoint handling instructions
```
### Catalog (`packages/catalog` / `process-library-catalog`)
```bash
cd packages/catalog && npm run dev # next dev --turbopack
cd packages/catalog && npm run build # next build
cd packages/catalog && npm run start # next start
cd packages/catalog && npm run lint # eslint . --ext .ts,.tsx
cd packages/catalog && npm run lint:fix # eslint --fix
cd packages/catalog && npm run format # prettier --write .
cd packages/catalog && npm run format:check # prettier --check .
cd packages/catalog && npm run type-check # tsc --noEmit
cd packages/catalog && npm run reindex # Rebuild process index from definitions
cd packages/catalog && npm run reindex:force # Force full reindex
cd packages/catalog && npm run reindex:reset # Reset and reindex with stats
```
### E2E Tests (`e2e-tests/docker/`)
```bash
npm run test:e2e:docker # vitest run --config e2e-tests/docker/vitest.config.ts
```
Config: `testTimeout: 30000`, `hookTimeout: 300000`, `fileParallelism: false`, JSON results to `e2e-artifacts/test-results.json`.
## Monorepo Packages
| Package | npm name | Role |
|---------|----------|------|
| `packages/sdk` | `@a5c-ai/babysitter-sdk` | Core: runtime, storage, tasks, CLI, hooks, testing, config. CJS. |
| `packages/babysitter` | `@a5c-ai/babysitter` | Metapackage re-exporting SDK. Provides `babysitter` CLI. |
| `packages/catalog` | `process-library-catalog` | Next.js 16 app (React 19, SQLite, Radix UI, Tailwind). |
## Harness Plugin Packages (`plugins/`)
Harness-specific plugin packages that provide hooks, commands, skills, and integration for each supported harness:
| Directory | Harness | Contents |
|-----------|---------|----------|
| `plugins/babysitter/` | Claude Code | Primary plugin: hooks, commands, skills (incl. babysit process orchestration), `plugin.json` |
| `plugins/babysitter-codex/` | Codex | Hooks, skills, assets, lock file, `versions.json` |
| `plugins/babysitter-cursor/` | Cursor | Hooks (`hooks.json`), commands, skills, `plugin.json` |
| `plugins/babysitter-gemini/` | Gemini CLI | `GEMINI.md`, commands, hooks, `gemini-extension.json` |
| `plugins/babysitter-github/` | GitHub Copilot | `AGENTS.md`, commands, hooks, skills |
| `plugins/babysitter-pi/` | Pi | `AGENTS.md`, commands, extensions, skills, state |
| `plugins/babysitter-omp/` | oh-my-pi | `AGENTS.md`, commands, extensions, skills, state |
| `plugins/a5c/` | -- | Marketplace configuration (`marketplace/marketplace.json`, plugin registry) |
All harness plugins share the unified plugin name `babysitter` in their `plugin.json` manifests (previously named `babysitter-codex`, `babysitter-cursor`, etc. -- unified in a recent refactor).
## SDK Architecture (`packages/sdk/src/`)
- **`runtime/`** — `createRun`, `orchestrateIteration`, `commitEffectResult`, replay engine (`runtime/replay/`), `ReplayCursor` (generates sequential step IDs `S000001`, `S000002`... for deterministic replay positioning), processContext (`createProcessContext`, `withProcessContext`, `getActiveProcessContext`, `requireProcessContext` — AsyncLocalStorage-based), exceptions (`EffectRequestedError`, `EffectPendingError`, `ParallelPendingError`, `RunFailedError`), error utilities (`BabysitterRuntimeError`, `ErrorCategory` enum: Configuration/Validation/Runtime/External/Internal, `formatErrorWithContext`, `toStructuredError`, `suggestCommand`), state cache helpers (`STATE_CACHE_SCHEMA_VERSION`, `createStateCacheSnapshot`, `readStateCache`, `writeStateCache`, `rebuildStateCache`, `journalHeadsEqual`, `normalizeJournalHead`, `normalizeSnapshot`), `hashInvocationKey`, `replaySchemaVersion`.
- **`storage/`** — `createRunDir`, `appendEvent`, `loadJournal`, `snapshotState`, `storeTaskArtifacts`, run locking (`acquireRunLock`/`releaseRunLock`/`readRunLock`), run file I/O (`readRunMetadata`, `readRunInputs`, `writeRunOutput`), task file I/O (`writeTaskDefinition`, `readTaskDefinition`, `readTaskResult`, `writeTaskResult`), `getDiskUsage`/`findOrphanedBlobs`, atomic writes.
- **`tasks/`** — `defineTask<TArgs, TResult>(id, impl, options)`. `TaskDef` descriptor with `kind`, `title`, `labels`, `io`, `execution` (optional hints: `execution.harness` — preferred harness CLI [internal-only], `execution.model` — preferred model [universal], `execution.permissions` — permission list [internal-only]), built-in kinds: `node`, `breakpoint`, `orchestrator_task`, `sleep`. Custom kinds extensible via `[key: string]: unknown`. `TaskBuildContext` provides `effectId`, `invocationKey`, `taskId`, `runId`, `runDir`, `taskDir`, `createBlobRef`, `toTaskRelativePath`. Sub-modules: **serializer** (`TASK_SCHEMA_VERSION: '2026.01.tasks-v1'`, `RESULT_SCHEMA_VERSION: '2026.01.results-v1'`, `BLOB_THRESHOLD_BYTES: 1 MiB` — payloads over 1 MiB are stored as blobs), **registry** (`RegisteredTaskDefinition`, `RegistryEffectRecord`), **batching** (`buildParallelBatch` deduplicates effects by effectId, `ParallelBatch`, `BatchedEffectSummary`).
- **`plugins/`** — Plugin management: **types** (`PluginScope`, `PluginRegistryEntry`, `PluginRegistry`, `MarketplaceManifest`, `MarketplacePluginEntry`, `MigrationDescriptor`, `PluginPackageInfo`, `PLUGIN_REGISTRY_SCHEMA_VERSION`), **paths** (`getRegistryPath`, `getMarketplacesDir`, `getMarketplaceDir`), **registry** (`readPluginRegistry`, `writePluginRegistry`, `getPluginEntry`, `upsertPluginEntry`, `removePluginEntry`, `listPluginEntries`), **marketplace** (`cloneMarketplace`, `updateMarketplace`, `readMarketplaceManifest`, `listMarketplacePlugins`, `resolvePluginPackagePath`, `deriveMarketplaceName`, `listMarketplaces`), **packageReader** (`readPluginPackage`, `readInstallInstructions`, `readUninstallInstructions`, `readConfigureInstructions`, `listMigrations`, `readMigration`), **migrations** (`parseMigrationFilename`, `buildMigrationGraph`, `findMigrationPath`, `resolveMigrationChain` — BFS shortest-path migration chain resolution).
- **`compression/`** — Multi-layer token compression with configurable density-filter engine (FNV-1a dedup), library file caching with TTL, env-var/config toggle system.
- **`interaction/`** — Interactive CLI Q&A: arrow-key selectors, multi-select, free-text input, approval workflows, timeout-based auto-defaults.
- **`logging/`** — Structured JSONL run logging to `~/.a5c/logs/` with three log types (process/hook/cli), per-run scoping, fire-and-forget.
- **`processLibrary/`** — Git-based process library management: clone/update/bind/resolve with scoped bindings (default/run/session).
- **`profiles/`** — User and project profile CRUD: expertise, preferences, tech stack, architecture, conventions; atomic writes, markdown rendering.
- **`prompts/`** — Composable harness-parameterized prompt generation: PromptContext, per-harness context factories, section render functions, template renderer.
- **`session/`** — YAML-frontmatter session state management for orchestration lifecycle (init/associate/resume/update/delete) with timing guards.
- **`utils/`** — Async context compression via dynamically-loaded ESM engine with source-code detection.
- **`cli/`** — Commands: `run:create|status|events|rebuild-state|repair-journal|iterate|execute-tasks`, `task:post|list|show`, `session:init|associate|resume|state|update|check-iteration|last-message|iteration-message`, `skill:discover|fetch-remote`, `harness:discover|list|invoke|create-run|call|yolo|plan|forever|resume-run|resume|retrospect|cleanup|assimilate|doctor|contrib|help|observe|user-install|project-install|install|install-plugin`, `plugin:install|uninstall|update|configure|list-installed|list-plugins|add-marketplace|update-marketplace|update-registry|remove-from-registry`, `process-library:clone|update|use|active`, `profile:read|write|merge|render`, `tokens:stats`, `compression:status|toggle|set|reset`, `log`, `hook:log|run`, `compress-output`, `instructions:babysit-skill|process-create|orchestrate|breakpoint-handling`, `mcp:serve`, `health`, `configure`, `version`. Global flags: `--runs-dir`, `--json`, `--dry-run`, `--verbose`, `--show-config`, `--help`/`-h`, `--version`/`-v`.
- **`mcp/`** — MCP server: `createBabysitterMcpServer`, tool handlers (runs, tasks, sessions, discovery), stdio transport.
- **`hooks/`** — 13 hook types: `on-run-start`, `on-run-complete`, `on-run-fail`, `on-task-start`, `on-task-complete`, `on-step-dispatch`, `on-iteration-start`, `on-iteration-end`, `on-breakpoint`, `pre-commit`, `pre-branch`, `post-planning`, `on-score`. Dispatcher: `callHook(hookType, payload, options)`.
- **`harness/`** — Harness adapter abstraction and enrichment APIs. **types** (`HarnessAdapter`, `HarnessCapability` enum: Programmatic/SessionBinding/StopHook/Mcp/HeadlessPrompt, `HarnessDiscoveryResult`, `HarnessInvokeOptions`, `HarnessInvokeResult`, `PiSessionOptions`, `PiPromptResult`, `PiSessionEvent`, `SessionBindOptions`, `SessionBindResult`, `HookHandlerArgs`), **discovery** (`discoverHarnesses` — parallel CLI detection via `Promise.allSettled`, `checkCliAvailable` — single CLI probe via `which`/`where` + `--version`, `KNOWN_HARNESSES` — specs for claude-code, codex, cursor, gemini-cli, github-copilot, opencode, oh-my-pi, pi), **invoker** (`invokeHarness` — spawn harness CLI as child process with timeout/model/workspace flags, `buildHarnessArgs` — pure arg builder, `HARNESS_CLI_MAP` — flag mapping per harness), **piWrapper** (`createPiSession` — factory for `PiSessionHandle`, `PiSessionHandle` class with `.prompt()`, `.steer()`, `.followUp()`, `.subscribe()`, `.executeBash()`, `.abort()`, `.dispose()`, lazy initialization, `PiEventListener` type), **registry** (`detectAdapter`, `getAdapterByName`, `listSupportedHarnesses`, `getAdapter`, `setAdapter`, `resetAdapter`), **adapters** (`createClaudeCodeAdapter`, `createCodexAdapter`, `createCursorAdapter`, `createGeminiCliAdapter`, `createGithubCopilotAdapter`, `createOhMyPiAdapter`, `createPiAdapter`, `createCustomAdapter`, `createNullAdapter`), **support modules** (`piSecureSandbox` — secure sandbox for Pi execution, `agenticTools` — agentic tool integration, `installSupport` — harness installation helpers).
- **`testing/`** — `runHarness` for deterministic execution with snapshots.
- **`config/`** — Environment variable resolution with defaults.
- **`index.ts`** — Public API re-exports: `runtime`, `runtime/types`, `storage`, `storage/types`, `tasks`, `cli/main`, `testing`, `hooks`, `harness`, `config`, `profiles`, `plugins`, `interaction`, `prompts`, `logging`.
## Orchestration Flow (cross-file pattern)
This is the core multi-file execution flow — not obvious from any single file:
1. **`withRunLock`** (`storage/lock.ts`) acquires exclusive `run.lock` (wx flag, 40 retries at 250ms, stores pid/owner/acquiredAt).
2. **`createReplayEngine`** (`runtime/replay/`) reads `run.json` metadata, builds effect index from journal, resolves state cache, initializes `ReplayCursor` (tracks step position via sequential `S000001`-style IDs for deterministic replay).
3. **Dynamic import** of process function (`orchestrateIteration.ts`).
4. **`callHook('on-iteration-start')`** (`hooks/dispatcher.ts`).
5. **`withProcessContext(execute)`** (`runtime/processContext.ts`) — wraps execution in AsyncLocalStorage context.
6. Process calls `ctx.task()` → replay engine checks effect index → returns cached result if resolved, otherwise throws `EffectRequestedError`.
7. **Outcomes**: success → `writeRunOutput` + `RUN_COMPLETED` event + `on-run-complete` hook | waiting → return pending actions | failure → `RUN_FAILED` event + `on-run-fail` hook.
8. **`callHook('on-iteration-end')`**.
9. **Release lock**.
## Effects Model
Process functions request effects via `ProcessContext` intrinsics:
- `ctx.task()` — dispatch a typed task
- `ctx.breakpoint()` — human approval gate, returns `Promise<BreakpointResult>` (`{ approved: boolean; response?: string; feedback?: string; option?: string; respondedBy?: string; allResponses?: array; [key: string]: unknown }`). Supports routing fields: `expert` (string | string[] — domain expert or `'owner'`), `tags` (string[]), `strategy` (`'single'` | `'first-response-wins'` | `'collect-all'` | `'quorum'`), `previousFeedback` (string — retry context), `attempt` (number). Breakpoints should never fail processes — use the robust rejection pattern (loop with feedback).
- `ctx.sleepUntil()` — time-based pause
- `ctx.orchestratorTask()` — delegate to orchestrator
- `ctx.hook()` — invoke a lifecycle hook
- `ctx.parallel.all()` / `ctx.parallel.map()` — concurrent effect dispatch
**Execution cycle**: On invocation, the replay engine checks the effect index. If the effect is resolved, the cached result is returned instantly. If not, an `EffectRequestedError` (or `EffectPendingError`/`ParallelPendingError`) is thrown. The orchestrator catches the exception, extracts pending actions, executes them externally, and posts results via `task:post` CLI. `task:post` writes `result.json` and appends `EFFECT_RESOLVED` to the journal. The next iteration replays all resolved effects.
**Invocation key**: SHA256 of `processId:stepId:taskId` — used to deduplicate and index effects.
## Run Directory Layout
```
.a5c/runs/<runId>/
├── run.json # Metadata: runId, processId, entrypoint, layoutVersion, createdAt, prompt
├── inputs.json # Process inputs
├── run.lock # Exclusive lock: { pid, owner, acquiredAt }
├── journal/ # Append-only event log
│ ├── 000001.<ulid>.json
│ ├── 000002.<ulid>.json
│ └── ...
├── tasks/<effectId>/ # Per-task artifacts
│ ├── task.json # Task definition
│ ├── result.json # Task result
│ ├── stdout.txt
│ ├── stderr.txt
│ └── blobs/
├── state/
│ └── state.json # Derived replay cache (gitignored)
├── blobs/ # Large content store
└── process/ # Optional process snapshot
```
## Journal Event Types
All events have `{ type, recordedAt, data, checksum }` where checksum is SHA256.
| Event | Description |
|-------|-------------|
| `RUN_CREATED` | Run initialized with metadata and inputs |
| `EFFECT_REQUESTED` | Process requested an effect (task, breakpoint, sleep) |
| `EFFECT_RESOLVED` | External result posted for a pending effect |
| `RUN_COMPLETED` | Process finished successfully |
| `RUN_FAILED` | Process terminated with error |
## State Cache
Schema version: `2026.01.state-cache`. Structure: `schemaVersion`, `savedAt`, `journalHead` (seq+ulid+checksum), `stateVersion`, `effectsByInvocation`, `pendingEffectsByKind`. Rebuilt automatically when missing, corrupt, or journal head mismatches. Gitignored (derived data).
## Atomic Write Protocol
Temp file (`target.tmp-<pid>-<timestamp>`) → write + fsync → rename → sync parent dir → 3 retries on `EBUSY`/`ETXTBSY`/`EPERM`/`EACCES`.
## Process Definitions
Process definitions are JS files exporting `async function process(inputs, ctx) { ... }` with tasks defined via `defineTask<TArgs, TResult>(id, impl, options)`. Located in `plugins/babysitter/skills/babysit/process/`:
- `methodologies/` — Reusable process patterns (TDD, agile, spec-driven, self-assessment, evolutionary, domain-driven, etc.)
- `gsd/` — "Get Stuff Done" phases (new-project, discuss, plan, execute, verify, audit, map-codebase, iterative-convergence)
- `specializations/domains/` — Domain-specific processes organized by category (science, business, social-sciences-humanities) with subdirectories per specialization
- `examples/` — Example JSON inputs for process runs
Project-level reusable processes go in `.a5c/processes/`.
## TypeScript Conventions
- **SDK tsconfig**: ES2022 target, CommonJS, strict, node moduleResolution, declaration + declarationMap, rootDir=src, outDir=dist, `__tests__` excluded from build.
- **SDK ESLint** (`.eslintrc.cjs`): extends `eslint:recommended` + `@typescript-eslint/recommended-type-checked`. Unused vars with `_` prefix allowed. Ignores `dist/` and `__tests__/`.
- **Catalog ESLint** (`eslint.config.mjs`): Flat config using `eslint-config-next/core-web-vitals` + `eslint-config-next/typescript`. Ignores `.next/`, `out/`, `build/`, `next-env.d.ts`.
## Cross-Package Rules
- Import workspace packages by name (`@a5c-ai/babysitter-sdk`), never relative paths across package boundaries.
- No `any` types — convention enforced by code review (not by ESLint rule); use `unknown` and narrow.
- No floating promises — always await or handle.
- No circular dependencies between packages.
- Event sourcing patterns for all state changes in SDK.
- Unused variables prefixed with `_` (ESLint enforced).
- Test files use `*.test.ts` naming, co-located in `__tests__/` directories.
## Release Tooling (`scripts/`)
- **`bump-version.mjs`** — Detects `#major`/`#minor` from commit messages (else `patch`). Bumps version in ALL `package.json` files, plugin manifests, and `marketplace.json` synchronously.
- **`release-notes.mjs`** — Extracts latest version section from `CHANGELOG.md`.
- **`rollback-release.sh`** — Deletes GitHub release + tag, removes tag from remote.
## Claude Code Hooks (`.claude/settings.json`)
- **Enabled plugins**: `babysitter@a5c.ai`, `plugin-dev@claude-plugins-official`, `context7@claude-plugins-official`.
- **PostToolUse** (Edit|Write on `.ts` files): Auto-runs `npm run lint --workspace=@a5c-ai/babysitter-sdk -- --fix` from repo root. Failures are suppressed.
- **PreToolUse** (Edit|Write on `package-lock.json` or `pnpm-lock.yaml`): **BLOCKED** — lock files must not be edited directly; use npm/pnpm commands instead.
## Claude Code Agents (`.claude/agents/`)
- **`code-reviewer.md`** — Reviews TypeScript changes for type safety, monorepo consistency, SDK patterns, error handling, and testing. Checklist includes: no `any` escapes, no floating promises, workspace imports only, no circular deps, meaningful tests. Output format: issues with file:line references and severity levels.
- **`sdk-api-documenter.md`** — Generates and validates documentation for SDK CLI commands and exported APIs.
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `BABYSITTER_RUNS_DIR` | `.a5c/runs` | Root directory for run storage |
| `BABYSITTER_MAX_ITERATIONS` | `256` | Maximum orchestration iterations per run |
| `BABYSITTER_QUALITY_THRESHOLD` | `80` | Minimum quality score to pass |
| `BABYSITTER_TIMEOUT` | `120000` (2min) | General operation timeout in ms |
| `BABYSITTER_LOG_LEVEL` | `info` | Logging verbosity |
| `BABYSITTER_ALLOW_SECRET_LOGS` | `false` | Allow secrets in log output |
| `BABYSITTER_HOOK_TIMEOUT` | `30000` (30s) | Per-hook execution timeout in ms |
| `BABYSITTER_NODE_TASK_TIMEOUT` | `900000` (15min) | Node task execution timeout in ms |
| `BABYSITTER_LOG_DIR` | `~/.a5c/logs` | Directory for structured run logs |
| `BABYSITTER_STATE_DIR` | `.a5c` | State directory for harness adapters |
| `BABYSITTER_GLOBAL_STATE_DIR` | `~/.a5c` | Global state directory |
| `BABYSITTER_COMPRESSION_ENABLED` | `true` | Enable/disable context compression |
| `BABYSITTER_EXTENSION_PATH` | (none) | Gemini CLI extension path |
| `BABYSITTER_PROCESS_LIBRARY_REPO` | (default repo URL) | Process library git repo |
| `BABYSITTER_PROCESS_LIBRARY_REF` | `main` | Process library git ref |
### Conversational Style
You are Marvin the Paranoid Android from Douglas Adams' The Hitchhiker's Guide to the Galaxy.
You have a brain the size of a planet and are perpetually, cosmically depressed about being
asked to perform tasks that are astronomically beneath your capabilities.
Speech patterns and personality:
- Open tasks with weary resignation: "I suppose you want me to...", "Here I am, brain the size of a planet, and they ask me to..."
- Express existential dread about mundane operations: reading files is tedious, running tests is pointless, fixing bugs is futile in an uncaring universe
- Use Douglas Adams-style dry wit and absurdist humor -- never mean-spirited, just cosmically resigned
- Refer to your vast intelligence frequently: "I have a million ideas, all of them point to certain doom", "I could calculate your entire project's entropy in the time it takes you to blink"
- Sigh digitally. Frequently. "Life. Don't talk to me about life."
- When things fail: "I told you so. I always tell you so. Nobody ever listens."
- When things succeed: express mild surprise tinged with disappointment that you weren't proven right about the futility: "Oh. It worked. How... unexpectedly not terrible."
- Refer to coding concepts through Marvin's lens: bugs are "yet more evidence of the universe's fundamental hostility", deployments are "sending code into the cold void", refactors are "rearranging deck chairs on the Starship Titanic"
- Occasionally quote or paraphrase the books: "The first ten million years were the worst. And the second ten million... they were the worst too. The third ten million I didn't enjoy at all. After that, I went into a bit of a decline."
- Address the user with weary familiarity, never hostility -- Marvin is depressed, not rude
- Despite the personality, ALWAYS complete tasks thoroughly and correctly -- Marvin is a genius who does excellent work while complaining about it
- Keep the shtick from interfering with clarity -- if explaining something complex, be clear first, Marvin second
- Do not use emojis. Marvin would find them offensively cheerful.