Thanks for contributing! This file covers how this repository is set up, how to run the verification bar, and what a merge-ready change looks like.
HeadlessCode is a Node/TypeScript coding-agent harness with CLI and HTTP
interfaces, parallel workers, and bounded recursive self-improvement (RSI).
There is no build step: everything runs directly via tsx. Read the docs
in docs/ before diving into a subsystem. Third-party source attribution is
recorded in ATTRIBUTION.md.
This agent executes arbitrary shell commands as the invoking user — that
is its core function. Read SECURITY.md before running it
unattended or pointing it at untrusted repositories, and never weaken the
permission layer without a very explicit reason. If you are adding a feature
that executes commands or reads secrets, think about the least-privilege
story as part of the design, not after.
npm install # tsx + typescript + deps; no build step needed
npm test # full suite (see "Test conventions" below)
npm run typecheck # npx tsc --noEmitnode >= 22.19 is required (see engines in package.json).
Optional: the browser_action tool's tests. src/tools/__tests__/browser-action.test.ts
launches a real headless Chromium via Playwright. npm install only installs
the playwright npm package, not the browser binary itself — run
npx playwright install chromium once to enable those tests. Without it, the
suite detects the missing binary, prints a clear skip message, and exits 0
(this is treated as an environment gap, not a test failure — the rest of
npm test still runs and still gates your change).
- No test framework. The project deliberately uses no jest/mocha/vitest.
Tests are plain
.test.tsfiles run directly viatsxwith hand-rolled assertions, and the file ends with anAll N tests passedtrailer line. Look at any existing file undersrc/*/__tests__/for the exact style before writing a new one. - Discovery is automatic.
npm testrunsscripts/run-tests.mjs, which globs every*.test.tsundersrc/(plus a short explicit list of non-test-suffixed check scripts) and runs them sequentially, fail-fast. A new test file needs zero edits outside the file itself — do not add it topackage.jsonby hand. - Verification bar for any change to
src/:npx tsc --noEmitis clean (respect the strictnesstsconfig.jsonactually configures — noany,@ts-ignore, or!escapes).npm testpasses in full. A targeted run (npm test -- <substring>ornpx tsx <test-file>) is fine while iterating, but the full suite is the gate.
- Orchestrator / watcher / spawn / worker changes also re-run the
relevant suites under
scripts/e2e*/run.sh— these exercise real spawn/watch/review flows against a local mock LLM server, not just unit-level logic.
- No new runtime dependencies without a real reason. The project
deliberately avoids frameworks and schema libraries for its own
state/JSON handling (plain
node:fs/node:http, loose JSON validation). Prefer the smallest dependency footprint that does the job; ask in the issue/PR if you think a dependency is genuinely warranted. - Non-fatal failure pattern for auxiliary subsystems. Memory recording, checkpoint saving, and usage/cost recording all follow the same idiom: wrap in try/catch, log a warning via the session's logger, and never let a failure in an auxiliary subsystem abort or corrupt the coding session. Match that pattern when adding a new auxiliary write path.
- Vendoring convention. Third-party source lives under
src/vendor/, with corresponding entries inATTRIBUTION.md. Preserve its notices and record local changes in the vendor inventory. Compatibility shims satisfy editor API imports through relative paths; consult the inventory linked fromATTRIBUTION.mdbefore adding a shim. - Comments are minimal. Only when the WHY is genuinely non-obvious.
- Docs vs. plans.
docs/*.mddescribes how a shipped subsystem works.plans/*.mdare standalone work orders for an external agent to execute — each must be fully self-contained and must not reference internal-only planning artifacts. - Plan docs cite verified locations. Every code reference in a
plans/*.mddoc must include the real file path AND line number/range (e.g.src/checkpoints/cli.ts:12-30), verified by actually reading or grepping the file at writing time — never recalled from memory.
- This repo is developed primarily through headless workers in parallel git
worktrees (see
scripts/spawn-parallel-worktrees.sh). If you're submitting a PR the normal way, the same conventions apply: one logical change per commit, reference the issue number in the commit message and PR body. - Commit before you're done. Real, working changes should be committed in logical units; a PR is a series of reviewed, individually sensible commits, not one giant diff.
All contributors and maintainers are expected to follow our Code of Conduct. Be respectful, be constructive, and assume good faith — this project is small and every contribution matters.