Skip to content
Projects

Milestoner

Autonomous-run engine for coding agents. A milestone state machine launches one fresh headless session per milestone, grades what each session claims against evidence on disk, and refuses to spend a retry on a usage limit. On npm, MIT.

Year
2026
Role
Design, engineering, release
Stack
TypeScript, Node.js, Claude Code, tsup, Server-Sent Events
Get it on npmSource
Milestoner

Coding agents can already run for hours. What they cannot do is tell you, truthfully, what they got done. A session that reports “all tests pass” at three in the morning has said exactly that many times before, and nothing in the exit code separates the times it was true.

Milestoner is the layer around that. You decompose the work into milestones with acceptance criteria written before the run starts. The engine launches one fresh headless agent session per milestone, reads the small result file the session leaves behind, and grades the claim against what is actually on disk: a passing test, a diff, a commit. A milestone marked done with no evidence line per criterion is downgraded to incomplete and retried. Blocked has to arrive with a diagnosis: the exact symptom, everything tried, and the single clearest action for a person.

The hours of execution go to the agent. The design, the decomposition and the acceptance criteria stay yours, which is the point: the evidence gate only means something when a person wrote the criteria.

What the engine refuses to count

Infrastructure is not failure. A session that dies in seconds, hits a usage limit, or crashes leaving a near-empty transcript does not consume an attempt, and an announced reset time is parsed and waited out. Liveness comes from side signals, watched source directories, test-result files and tool logs, never from the transcript, which sits still through a long generation and grows while an agent narrates a retry loop.

Supervising and steering

A bundled Claude Code skill turns a second session into a supervisor that wakes every ten minutes, reads the run and applies a bounded playbook: healthy, environment stalled, session hung, waiting out a limit, runner dead, blocked for real. Its entire write surface is killing a hung session, running the environment adapter, relaunching the runner and appending a log line. It never edits project code and never clears a block; that stays a human decision. A second skill, the planner, interviews you and proposes the milestone breakdown for approval before writing a single prompt.

Steering corrects a run in flight without killing it. Every session launched afterwards gets the text inlined as an override on its milestone prompt, and every attempt records the steering that was in force. A local web panel, loopback only with a one-time key in the URL, shows the same state the CLI does and calls the same functions, so there is one audit trail rather than two.

Shipping it

Milestoner logo: a mountain peak inside a circle, split between a light upper half and a dark lower half

On npm since August 2026 under the MIT license. It runs on Windows, macOS and Linux and CI exercises all three; the platform-specific parts, killing a whole process tree and launching through an npm shim under cmd.exe, live inside the engine. It requires Node 20 or newer and an agent CLI on PATH, Claude Code by default.

The default configuration runs the agent with permission prompts skipped, because a headless session cannot answer one. The README says so in bold and tells you to commit first. The protocol template tags every green milestone, which is what makes git reset --hard <tag> a real rollback.

Technology

  • TypeScript compiled with tsup, shipped as a single CLI binary with zero runtime dependencies. Everything it needs is in Node’s standard library.
  • A file-based state machine. The engine owns state.json; each session writes only a small result.json drop box that gets graded, merged and archived. State never lives in a conversation, so every session starts with clean context.
  • Process supervision built on child processes: one headless agent session per milestone, a process-tree kill on Windows via taskkill /T and via POSIX process groups elsewhere, and a registry at ~/.milestoner/runs.json that every runner joins on start and leaves on exit, so a runner that died overnight is the one still listed.
  • Liveness by mtime. Watched source directories, test-result files and tool logs are polled for modification time; the transcript is deliberately never a signal, only a source for the transcript command, which renders it as prose.
  • A local HTTP server on Node’s http module, no framework, streaming updates over Server-Sent Events. Loopback only, with a one-time key in the URL, and the same functions behind every button that the CLI calls.
  • Self-contained HTML reports, one file per run, with no external assets.
  • Tests on Node’s built-in runner (node:test), covering the grader, the runner’s gate, steering, the registry, the lint pass and the HTTP API. GitHub Actions runs the matrix on Ubuntu, macOS and Windows across Node 20, 22 and 24.
  • Bundled Claude Code skills for the supervisor and the planner, installed into .claude/skills/ by the binary itself so they never ship apart from the engine they call.