Skip to main content

millstone logo

CI Quality Coverage Docs Release PyPI version Python versions License

Coding agents produce dramatically better results when they plan before they code, and when their output is reviewed by a second agent — ideally from a different model provider. The catch: manually running that cycle (design → review → revise → approve → plan → review → revise → implement → review → revise → commit) across multiple agents is extremely time-consuming.

millstone automates that end to end. It wraps any combination of coding CLIs (Claude Code, Codex, Gemini, OpenCode) in a deterministic build-review loop: one agent authors, a second reviews, feedback cycles until the reviewer approves, then the change is committed. The same loop governs designs, plans, and code — with optional autonomous outer loops that discover opportunities, generate designs, and break them into tasks without human prompting.

Documentation | Getting Started | Meta Invoke | Contributing | Changelog

Quick Start

Before installing millstone, install and authenticate at least one supported coding agent CLI. See Supported Agents.

# 1) Install
pipx install millstone

# 2) Move into the repo you want to run on
cd /path/to/your/project

# 3) Recommended: give your coding agent an operator prompt
# @docs/prompts/execute.md  (run a tasklist)
# @docs/prompts/design.md   (design + plan a new feature)

Common pattern: hand millstone a short list of features and let it design, plan, and implement each one. Write them as a roadmap:

<!-- docs/roadmap.md -->
- [ ] Add a logout button to the header
- [ ] Show toast notifications on form errors
- [ ] Rate-limit the /api/search endpoint

Then run:

# Local roadmap file
millstone --cycle --roadmap docs/roadmap.md

For each goal, millstone designs a solution, breaks it into atomic tasks, implements them through a build-review loop, and commits. The local roadmap path reads goals directly from the file; the remote path runs analysis to discover and select from provider-backed opportunities. Approval gates pause between stages for human review; add --no-approve for fully autonomous operation. When a run hits a high-risk task, eval regression, or critical remote effect, millstone now saves a decision gate in .millstone/state.json and resumes only through an explicit follow-up command instead of waiting on stdin.

Other starting points:

# One task now (no setup required)
millstone --task "add retry logic to API client"

# Design, plan, and execute one objective end-to-end
millstone --deliver "Add retry logic to API client"

# Full autonomous loop — analyze codebase for improvements, then implement
millstone --cycle

# Existing local backlog file -> migrate once, then execute
millstone --migrate-tasklist backlog.md && millstone

# New app / fresh repo
millstone --init
millstone --deliver "Build a CLI app for release note generation"

millstone reads from .millstone/tasklist.md by default.

Highlights

  • Deterministic inner loop: Builder -> Sanity -> Reviewer -> Sanity -> Fix -> Commit.
  • Autonomous outer loops: analyze, design, plan, cycle — every authoring step is write/review gated.
  • --max-cycles governs both inner build-review iterations and outer-loop authoring loops.
  • --required-approvals N runs N independent reviewer rounds per task, each with up to --max-cycles fix loops.
  • Parallel execution via git worktree — run multiple tasks concurrently with isolated checkouts and a serialized merge queue.
  • Primary operating mode is coding-agent-invoked execution (docs/prompts/execute.md).
  • Built-in evaluation flow with result capture and regression comparison.
  • Multi-provider CLI routing per role (claude, codex, gemini, opencode).
  • Stateful runs with logs, evals, and recovery under .millstone/.

Usage Patterns

Goal Command
Coding agent mediated execution (recommended) Give your coding agent docs/prompts/execute.md
Execute next tasks from tasklist millstone
Limit to one task millstone -n 1
Run custom one-off task millstone --task "..."
Migrate an existing local backlog to tasklist format millstone --migrate-tasklist backlog.md
Design, plan, and execute one scoped objective millstone --deliver "..."
Claude code as author, codex as reviewer, one task, max of 6 write/review cycles millstone --cli claude --cli-reviewer codex -n 1 --max-cycles 6
Require two independent reviewer approvals per task millstone --required-approvals 2
Run 4 tasks in parallel (worktree mode) millstone --worktrees --concurrency 4
Dry-run prompt flow without invoking agents millstone --dry-run
Scan codebase for opportunities millstone --analyze
Generate a design doc millstone --design "Add caching layer"
Turn design into atomic tasks millstone --plan .millstone/designs/foo.md
Analyze through planning, stop before execute millstone --analyze --through plan
Design, plan, and execute from text millstone --design "Add caching" --through execute
Plan and execute from existing design millstone --plan .millstone/designs/foo.md --through execute
Execute roadmap goals without analyze millstone --cycle --roadmap docs/roadmap.md
Run autonomous cycle end-to-end millstone --cycle
Resume an interrupted run millstone --continue
Approve a saved high-risk task gate millstone --continue --approve-high-risk
Approve saved critical effect gates millstone --continue --approve-effects
Resolve a saved eval regression by rollback millstone --continue --on-eval-regression=rollback
Resolve a saved eval regression without rollback millstone --continue --on-eval-regression=ignore

How It Works

Inner loop (delivery):

Builder -> Sanity Check -> Reviewer -> Sanity Check -> Fix Loop -> Commit

Outer loop (self-direction) — a composable pipeline of typed stages:

Analyze -> Design -> Plan -> [Inner Loop] -> Eval -> (repeat)

Each stage transforms one artifact type into another (Opportunity → Design → Worklist). --through controls where the pipeline stops: --analyze --through plan runs analysis, design, and planning but skips execution. --cycle resolves which pipeline to build based on pending tasks, roadmap goals, or analysis results.

Every authoring step (analyze, design, plan) is write/review gated: a reviewer agent checks the output and requests revisions until it approves or --max-cycles is exhausted.

Installation Options

# PyPI (recommended when release is available)
pipx install millstone

# GitHub latest
pipx install git+https://github.com/wittekin/millstone.git

# Contributor install
pip install -e .[dev]

Optional extras:

pip install -e .[test]      # pytest + coverage
pip install -e .[quality]   # ruff + mypy
pip install -e .[security]  # pip-audit
pip install -e .[release]   # build + twine
pip install -e .[docs]      # mkdocs
pip install -e .[dev]       # contributor setup: tests, quality, docs, build, pre-commit

Local CI Before Push

Install the repo hooks once:

pre-commit install --hook-type pre-commit --hook-type pre-push

The pre-push hook runs a local CI subset that mirrors the most failure-prone required checks: lint, format, type check, dead-code scan, unit tests, coverage, package build, docs build, and an isolated wheel smoke test.

You can run the same gate manually:

python -m millstone.devtools.local_ci

It does not try to reproduce GitHub-only checks such as CodeQL, dependency review, or the macOS runner itself, but it catches most avoidable CI failures before you push.

Minimal Tasklist Format

# Tasklist

- [ ] First task to implement
- [ ] Second task
- [x] Already completed task

millstone executes the first unchecked - [ ] task.

Configuration Snapshot

Create .millstone/config.toml in the target repo:

max_cycles = 3
required_approvals = 1
max_tasks = 5
tasklist = ".millstone/tasklist.md"
roadmap = "docs/roadmap.md" # optional: used by `--cycle` when tasklist is empty

cli = "claude"
cli_builder = "codex"
cli_reviewer = "claude"

eval_on_commit = false
approve_opportunities = true
approve_designs = true
approve_plans = true

Multi-maintainer setup

By default, artifact files (tasklist, designs, opportunities) are written under .millstone/ and are gitignored — suitable for single-maintainer or local-only workflows.

To commit artifacts to the repo and share them with teammates, opt in per artifact type:

commit_tasklist = true       # stores at docs/tasklist.md
commit_designs = true        # stores at designs/
commit_opportunities = true  # stores at opportunities.md

For full multi-maintainer collaboration, use an external artifact provider (Jira, Linear, GitHub Issues, or beads) instead of file-backed defaults.

Tasklist filter contract

All tasklist providers (Jira, Linear, GitHub Issues) respect a provider-agnostic [tasklist_filter] section in .millstone/config.toml:

[tasklist_filter]
labels    = ["sprint-1"]        # AND – task must carry ALL listed labels
assignees = ["alice", "bob"]    # OR  – task assigned to ANY of these users
statuses  = ["Todo", "In Progress"]  # OR  – task in ANY of these statuses

Omit any key (or leave the list empty) to skip filtering on that dimension. The filter is applied when the outer loop fetches the next task from the remote provider. An explicit filter key inside [tasklist_provider_options] takes precedence over this section.

Scoping remote backlogs

When using a remote tasklist provider (Jira, Linear, or GitHub Issues), the default scope is the full open-issue set for the configured project/team/repo. Use [millstone.tasklist_filter] to restrict millstone to a specific subset without modifying provider options.

When to use local tasklist vs remote filters

Situation Recommendation
Personal project or solo maintainer Local .millstone/tasklist.md
Team with shared backlog in Jira/Linear/GitHub Remote provider + [millstone.tasklist_filter]
Ad-hoc spike or one-off work millstone --task "..."
Sprint-scoped automation on a shared board Remote provider + label/cycle/milestone filter

Quick examples by backend

Jira — current sprint label:

[tasklist_provider_options]
type = "jira"
project = "PROJ"

[millstone.tasklist_filter]
label = "sprint-1"
assignee = "john.doe"

Linear — active cycle for a team:

[tasklist_provider_options]
type = "linear"
team_id = "<uuid>"

[millstone.tasklist_filter]
cycles = ["Cycle 5"]
label  = "millstone"

GitHub Issues — label + milestone:

[tasklist_provider_options]
type  = "github"
owner = "myorg"
repo  = "myrepo"

[millstone.tasklist_filter]
label     = "sprint-1"
milestone = "v1.2"

See full filter option reference in the per-backend docs under docs/providers/.

See full config and CLI options with:

millstone --help

Project Signals

  • Canonical loop ontology: docs/architecture/ontology.md
  • Scope and safety boundaries: docs/architecture/scope.md
  • Parallel execution with worktrees: docs/worktrees.md
  • CLI providers: docs/cli-providers/
  • Artifact providers: docs/providers/
  • Release checklist: docs/maintainer/release_checklist.md

Build and Release Workflows

This repository ships with CI, quality, docs, release, security, CodeQL, dependency review, and weekly maintenance workflows in .github/workflows/.

Tag release flow:

git tag -a vX.Y.Z -m "Release vX.Y.Z"
git push origin vX.Y.Z

Star History

Planned after initial public release and first community adoption.

Working Directory

Creates .millstone/ in your repo containing:

  • runs/ - Timestamped logs of each run
  • evals/ - JSON eval results for comparison
  • cycles/ - Logs of autonomous cycle decisions
  • state.json - Saved state for --continue, including inner-loop halts, outer-loop stage checkpoints, and explicit decision gates
  • config.toml - Per-repo configuration
  • STOP.md - Created by sanity check to halt

This directory is auto-added to .gitignore.

Safety Checks

Mechanical:

  • No changes detected -> Warn (proceeds to review)
  • Too many lines changed -> Halt for human review
  • Sensitive files (.env, credentials) -> Halt for human review
  • New test failures (with --eval-on-commit) -> Halt with explicit eval-regression policy
  • High-risk tasks / critical remote effects -> Halt with explicit decision gate unless approved or --no-approve

Judgment (via LLM):

  • Builder output is gibberish -> Create STOP.md -> Halt
  • Reviewer feedback is nonsensical -> Create STOP.md -> Halt

Exit Codes

  • 0 - Success
  • 1 - Halted (needs human intervention)
  • 2 - Decision gate saved; resume with --continue plus the required explicit approval/policy flag

Expected Runtime

Depending on cycles, tasks, and your agent provider / model, millstone can run for minutes or hours.

Requirements

  • Python 3.10+
  • claude CLI installed and authenticated (default), or
  • codex CLI installed and authenticated (if using --cli codex), or
  • gemini CLI installed and authenticated (if using --cli gemini), or
  • opencode CLI installed and authenticated (if using --cli opencode)

Open Source Project Files

Release files for millstone 0.6.11

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for millstone 0.6.11
File Size Uploaded
millstone-0.6.11.tar.gz 425.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for millstone 0.6.11
File Interpreter ABI Platform
millstone-0.6.11-py3-none-any.whl Python 3 none any Details

Total release size: 691.1 kB

Release files / millstone-0.6.11.tar.gz

Download URL millstone-0.6.11.tar.gz
Size 425.4 kB
Tags Source
SHA-256 checksum
How to use checksums
8c76cc08a84dd286dca0b6fcebb7f0c3e68410cc9fe12d9197640be3e936488d
BLAKE2b-256 checksum
How to use checksums
b1e0313a9e6c1eac42d49c8234a847ecbac08060d6911c005c10000265e28c61
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 26, 2026.

Transparency log

Release files / millstone-0.6.11-py3-none-any.whl

Download URL millstone-0.6.11-py3-none-any.whl
Size 265.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7b1ab54030ad231b06cf1e15c6a6580ab070ed241bb28882522af85e51942978
BLAKE2b-256 checksum
How to use checksums
90ba7073014d5c5be4d1697924b746dab848587138ea3afc55c2247b8e0a37bd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Apr 26, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.6.11 This release

2 release files

0.6.10

2 release files

0.6.9

2 release files

0.6.8

2 release files

0.6.7

2 release files

0.6.6

2 release files

0.6.5

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.9

2 release files

0.5.8

2 release files

0.5.7

2 release files

0.5.6

2 release files

0.5.5

2 release files

0.5.4

2 release files

0.5.3

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page