reckon
Repo-agnostic agile planning system. Four surfaces share one repo and one venv:
| Surface | CLI | What it does |
|---|---|---|
| reckon server | reckon serve (reckon service to run it as a daemon) |
HTTP backend on :8765 — serves the SPA, serves shared CSS/JSX, brokers versioned writes to plan HTML semantic elements |
| reckon MCP | reckon mcp |
MCP stdio transport — same writes as the server, callable from Claude Code / Cursor / any MCP client |
| reckon crew | reckon crew dispatch (preflight, observe, resume, attach, list, stop, complete, recover, member, ledger) |
Backend-agnostic worker dispatch — validates the node contract, resolves flight config, holds a wave whose backend has no headroom left, creates its detached worktree, returns JSON describing the spawned run or in-harness directive, and promotes each finished run into the owning repository's committed ledger |
| reckon SPA | (static) | React SPA under docs/ — three-column layout (filters · plans · content), Cmd-K palette, plan reading + radial-fan graph, sprint kanban, critical-path graph tab, prompt generation |
The Python distribution is named reckon-plans; the import package and
console command remain reckon.
Quick start
uv sync
uv run reckon serve # HTTP server on port 8765
uv run reckon serve --port 8766 --mounts /path/to/mounts.json
uv run reckon mcp # stdio MCP transport
uv run reckon crew preflight --project sample --role implement # exits 3 if held
uv run reckon crew dispatch --project sample --plan plan-alpha --section s3 \
--role implement --node docs-readme --goal "Document the crew CLI" \
--done-when "grep -c 'reckon crew' README.md returns 3 or more" \
--write-path README.md --time-budget 20m \
--manifest /tmp/docs-readme-manifest.md --session example
uv run reckon crew observe --run <run-id> --project sample
uv run reckon crew attach --run <run-id> --task <harness-task-id> # in-harness runs only
uv run reckon crew complete --run <run-id> --gate passed --commit <sha>
uv run reckon crew recover # what an interrupted orchestrator left behind
uv run reckon build docs # portable static site under docs/
uv run reckon migrate-layout docs --check # collision-safe migration preview
reckon crew dispatch is the single launch instruction for every configured
backend. It refuses malformed nodes before creating a worktree, then returns
one JSON document whose launch field tells the caller whether a process was
spawned or an in-harness task must be launched and bound with attach. Use the
returned run id with observe; if a worker reports NEEDS-HELP:, answer it in
the same session with resume rather than dispatching a replacement.
A run has two homes over its life. In flight it is a pointer under reckon's
config home — pid, worktree, log, phase — which churns every few seconds and is
never committed. complete promotes the finished record into the owning
repository's ledger at docs/state/<project>/crew.json, committed beside
index.json and version-paired the same way, then deletes the pointer — in that
order, so an interruption leaves a recoverable pointer rather than a lost
record. recover classifies whatever is left: running, completed-but-unpromoted
(with its manifest path), or abandoned. It repairs the record only; it never
force-removes a worktree.
Each promoted record carries whatever headroom its backend reported, which is what
lets preflight decide whether a wave may open without spending anything: a probe
would consume the very resource it measures, and would do so most often when that
resource is scarcest. A wave whose backend is spent is held — no worktree is
created, no node fails, and both preflight and dispatch exit 3 naming the
backend, its utilisation and when it resets. Holds are per-backend, so ready nodes
routed elsewhere still run; and a backend that publishes no headroom reads
unknown, which never holds, because absence of a signal is not evidence of
exhaustion.
Running the server as a service
reckon serve in a terminal dies with the terminal and never comes back on
its own. For a persistent deployment, install it as a systemd user service:
uv run reckon service install # write the unit, enable lingering, start it
uv run reckon service restart # the command to run after changing reckon code
uv run reckon service status # unit state, lingering, effective ExecStart
uv run reckon service logs -f # follow the server's output
install is idempotent, and restarts the service when the rewritten unit
differs from the running one. The unit sets Restart=on-failure, so a crashed
server returns within five seconds, and enabling lingering keeps it alive after
you log out — without it, systemd stops the per-user manager and every unit it
owns at the end of your last login session.
Output is appended to <config-home>/logs/server.log rather than the journal,
because reading a user journal requires a privileged group membership that a
plain account on a managed host does not have. The file is not rotated.
Once the distribution is published, uv tool install reckon-plans installs
the same reckon command. A repository checkout can be installed directly
with uv tool install "git+https://github.com/Simon-McIntosh/reckon".
How it works
Each project keeps typed resources under <repo>/docs/plans/,
docs/research/, docs/evidence/, and docs/sprints/. Stable identity is
project + type + slug, independent of the relative file path. Mixed flat/typed
repositories remain readable; reckon migrate-layout docs moves files only
when invoked explicitly. Plan state (status, decisions, followups, etc.) lives as semantic
HTML inside the plan file:
<meta name="plan-status" content="active">
<meta name="plan-impl" content="0.6">
<!-- inside <main class="plan-doc">: -->
<section data-reckon="decisions" class="r-decisions"> … </section>
<section data-reckon="followups" class="r-followups"> … </section>
The server parses each plan's <meta name="plan-*"> scalars and
data-reckon section elements at request time — there are no per-plan
state JSON sidecars. Project workflow state is independently versioned under
docs/sprints/, docs/milestones/, docs/blockers/, and
docs/state/<project>/timeline.html; project.json is identity/presentation
only. A retained index.json is a frozen compatibility snapshot.
Mounts are configured in ~/docs-server/mounts.json:
{
"reckon": "/home/user/Code/reckon/docs",
"imas-ambix": "/home/user/Code/imas-ambix/docs",
"my-project": "/home/user/Code/my-project/docs"
}
Then open http://localhost:8765/<project>/ in a browser. The SPA reads state
from the server and renders plans, sprint boards, dependency graph, and prompt
generation.
Key endpoints
| Method · path | Purpose |
|---|---|
GET /<project>/ |
SPA shell |
GET /<project>/<type-root>/<slug> |
Canonical typed prose page |
GET /<project>/<slug>.html |
Flat compatibility redirect |
GET /_discover/<project> |
All plans with full parsed state |
GET /plan/<project>/<type-root>/<slug> |
Typed parsed state (incl. version) |
GET /plan/<project>/<slug> |
Compatibility plan-state read |
POST /plan/<project>/<slug> |
Dotted-key patch; requires If-Match: <version> |
GET /state/<project>/index.json |
Composed compatibility view (read-only after migration) |
Frontend
The docs/ directory is the canonical template. Use /reckon-sync (or
reckon sync <docs-path>) to copy docs/_shared/ CSS into a consumer
project’s docs/ and register it in mounts. JSX components are served live
at /_ui/<file> by the reckon server — no per-project copies needed.
For a static deployment, run reckon build <docs-path>. The command copies
the UI and shared assets shipped inside the reckon-plans wheel, writes a
relative-path SPA index and .nojekyll, and writes a derived
projection.json. It never rewrites the frozen migration-source index.
Split a legacy project index explicitly with:
uv run reckon migrate-project-state docs --project <project>
The migration snapshots the source, proves composed parity, installs typed resources, then publishes the distributed-format marker last.
For a host-wide reviewed migration, snapshot the complete active mount registry and select only the repositories whose write scope is authorised:
uv run reckon migrate-fleet \
--run-id 20260729T180000Z \
--apply-project reckon
The command discovers the effective mounts.json at runtime, records its hash,
creates a content-bearing before snapshot for every registered repository, and
writes an incremental machine ledger below the Reckon config home. Unselected,
dirty, detached, conflicting, or otherwise unsafe repositories receive an
explicit terminal deferred row; they are never silently omitted. A selected
repository is migrated in a temporary copy, where capability conversion, typed
layout, distributed state, document/schema/relationship audits, concise MCP
reads, and a static build must all pass before exact files are installed.
Repository commits remain a coordinator responsibility. After committing and pushing a verified row, attach the durable evidence with:
uv run reckon migration-record <ledger.json> <project> <commit> origin/main
Rollback is exact-path only and requires both the content-bearing snapshot and the migration ledger's changed-path list:
uv run reckon migration-rollback <snapshot.zip> <docs-path> \
--path plans/example.html --path example.html
To generate a GitHub Pages workflow in a consumer repository:
uv run reckon sync docs --generate-ci
The generated workflow installs uv and invokes the reckon command from a
pinned git tag with uvx --from. Reckon’s own workflow uses its checked-out
source and lockfile with uv run --frozen reckon build docs.
MCP integration
After uv sync, register in ~/.claude/mcp.json:
{
"mcpServers": {
"reckon": { "command": "reckon", "args": ["mcp"] }
}
}
Then any MCP client can call reckon.read_plan(project, slug),
reckon.edit_plan(...), reckon.roadmap(project), reckon.audit(project), and
reckon.crew(project, view=...). The MCP transport writes to the same semantic
HTML elements as reckon serve — they are two faces of one backend.
Typed reads are progressive. A resource selector defaults to a concise human summary; explicit views reveal current detail, paginated history, lossless storage state, or schema:
read_plan(resource={"project": "sample", "type": "plan", "id": "plan-alpha"})
read_plan(
resource={"project": "sample", "type": "sprint", "id": "S1"},
view="detail",
)
read_plan(
resource={"project": "sample", "type": "plan", "id": "plan-alpha"},
view="raw",
)
audit(project="sample", view="summary")
summary never includes full followup prompts. Use view="detail" with
include_prompts=True when a prompt is specifically needed. history and
large discovery/audit detail responses use cursor plus a bounded limit.
Calls that omit both resource and view preserve the legacy response shape.
Before distributed project-state activation, typed sprint/project reads are
safe projections of the canonical legacy index and identify that source in
their warning/state metadata. Writes continue through slug="index" until the
explicit migration activates independently versioned named resources.
Metadata
Release files for reckon-plans 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| reckon_plans-0.2.0.tar.gz | 1.5 MB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| reckon_plans-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 2.0 MB
Release files / reckon_plans-0.2.0.tar.gz
| Download URL | reckon_plans-0.2.0.tar.gz |
|---|---|
| Size | 1.5 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0df1d81a67ae2ea6171bd34fcdf5146126c0c722c53321fb8d0695ca4c632680
|
|
BLAKE2b-256 checksum How to use checksums |
466d5f95f3ecf3389394f197c88db2249e3471597bcbb9a1f94e2d8929424370
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 24, 2026.
Transparency logRelease files / reckon_plans-0.2.0-py3-none-any.whl
| Download URL | reckon_plans-0.2.0-py3-none-any.whl |
|---|---|
| Size | 486.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
9a549191e7c5123fdb9b7b3b84625caf62d176eab05e1f1eae06ea48a0d4f20f
|
|
BLAKE2b-256 checksum How to use checksums |
fd408e4575794cbbd135c7b13b90d77ab5eaff5255a0b4ef1a2c1fcd2972e464
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
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 Aug 24, 2026.
Transparency logSecurity for reckon-plans 0.2.0
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.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for reckon_plans-0.2.0.tar.gz
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 Aug 24, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.