This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
pnpm test # run all tests (vitest)
pnpm test -- tests/harness.test.ts # run a single test file
pnpm test -- -t "node name" # run tests matching a pattern
pnpm typecheck # tsgo --noEmit (strict, uses native TS preview)
pnpm lint # oxlint across src/ contracts/ tests/ blueprints/
pnpm harness run --blueprint self-build --repo . --intent "..." --spec docs/product-specs/foo.md
pnpm harness dry-run --blueprint self-build # preview blueprint nodes
pnpm harness list # list available blueprintsTypecheck uses tsgo (the native TypeScript preview compiler), not tsc. Always get full output — never tail.
See docs/ARCHITECTURE.md for full philosophy, invariants, and directory conventions.
This is a harness engineering system: an orchestrator that turns intent into working code via autonomous agent loops running in isolated sandboxes. The codebase follows the Phoenix Architecture — specs, tests, and contracts are durable; src/ is regenerable.
CLI (citty) → runHarness() → createSandbox() → executeBlueprint() → push+PR
| Layer | Location | Role |
|---|---|---|
| Contracts | contracts/types.ts |
Shared types: RunContext, NodeResult, RunReport, ExecOptions |
| Blueprints | blueprints/*.ts |
Named sequences of nodes (preflight → deterministic → agentic → validate) |
| Blueprint DSL | src/blueprint/dsl.ts |
Builder functions: blueprint(), preflight(), deterministic(), agentic(), validate() |
| Blueprint Engine | src/blueprint/engine.ts |
Executes nodes sequentially; validate nodes retry with onFailure agentic loops |
| Agent Drivers | src/agents/{claude-code,pi,codex}.ts |
Spawn CLI agents in sandbox; parse output for token usage |
| Sandbox | src/sandbox/{local,daytona}.ts |
Isolation: local uses git worktrees in tmpdir; Daytona uses remote devboxes |
| Reporter | src/reporter/{console,json}.ts |
Emit events: nodeStart, nodeOutput, nodeComplete, runComplete |
| CLI | src/cli.ts |
citty-based CLI with run, list, dry-run subcommands |
- preflight — checks prerequisites (tools, auth, spec file exists)
- deterministic — exact commands (install, lint, commit)
- agentic — dispatches to an agent driver (claude-code, pi, codex) with a prompt function
- validate — composite: runs deterministic steps, on failure invokes an onFailure agentic node, retries up to maxRetries
Sandbox (src/sandbox/types.ts) is the isolation abstraction: exec(), uploadFiles(), snapshot(), teardown(), optional pushBranch() and defaultBranch(). All commands go through sandbox.exec() as argv arrays — no shell strings. Path confinement is enforced via assertPathConfined().
@contracts/*→./contracts/*@src/*→./src/*
Vitest resolves these via vitest.config.ts aliases. TSConfig uses paths.
- ESM-only (
"type": "module"); all local imports use.jsextensions - Strict TypeScript:
noUncheckedIndexedAccess,noUnusedLocals,noUnusedParameters - Commands passed as
argv: string[]arrays, never shell strings —shell: falseis enforced - Output truncation via
truncate()fromsrc/util/sanitize.tswithMAX_OUTPUT_BYTES - Path traversal protection via
assertPathConfined()fromsrc/util/path.ts - Tests live in
tests/(flat), named*.test.ts; integration tests use*.integration.test.ts - Product specs in
docs/product-specs/; architecture indocs/ARCHITECTURE.md - Learnings captured in
docs/solutions/with YAML frontmatter
- Enter plan mode for ANY non-trivial task (3+ steps or architectural decisions)
- If something goes sideways, STOP and re-plan immediately — don't keep pushing
- Use plan mode for verification steps, not just building
- Write detailed specs upfront to reduce ambiguity
- Use subagents liberally to keep main context window clean
- Offload research, exploration, and parallel analysis to subagents
- For complex problems, throw more compute at it via subagents
- One task per subagent for focused execution
- After ANY correction from the user: update
tasks/lessons.mdwith the pattern - Write rules for yourself that prevent the same mistake
- Ruthlessly iterate on these lessons until mistake rate drops
- Review lessons at session start for relevant project
- Never mark a task complete without proving it works
- Diff behavior between main and your changes when relevant
- Ask yourself: "Would a staff engineer approve this?"
- Run tests, check logs, demonstrate correctness
- Run /compound-engineering:workflows:review
- For non-trivial changes: pause and ask "is there a more elegant way?"
- If a fix feels hacky: "Knowing everything I know now, implement the elegant solution"
- Skip this for simple, obvious fixes — don't over-engineer
- Challenge your own work before presenting it
- When given a bug report: just fix it. Don't ask for hand-holding
- Point at logs, errors, failing tests — then resolve them
- Zero context switching required from the user
- Go fix failing CI tests without being told how
- Plan First: Write plan to
tasks/todo.mdwith checkable items - Verify Plan: Check in before starting implementation. Required to pass to the /codex-review skill
- Track Progress: Mark items complete as you go
- Explain Changes: High-level summary at each step
- Document Results: Add review section to
tasks/todo.md - Capture Lessons: Update
tasks/lessons.mdafter corrections. Required to pass to the /compound-docs skill too
- Simplicity First: Make every change as simple as possible. Impact minimal code.
- No Laziness: Find root causes. No temporary fixes. Senior developer standards.
- Minimal Impact: Changes should only touch what's necessary. Avoid introducing bugs.
| Variable | Purpose |
|---|---|
GITHUB_TOKEN |
Clone/push + PR creation |
DAYTONA_API_KEY |
Daytona sandbox provisioning |
DAYTONA_API_URL |
Daytona endpoint override |
DAYTONA_TARGET |
Daytona target region |