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.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file reckon_plans-0.2.0.tar.gz.
File metadata
- Download URL: reckon_plans-0.2.0.tar.gz
- Upload date:
- Size: 1.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0df1d81a67ae2ea6171bd34fcdf5146126c0c722c53321fb8d0695ca4c632680
|
|
| MD5 |
14fd1c0c89623235a48425653287f810
|
|
| BLAKE2b-256 |
466d5f95f3ecf3389394f197c88db2249e3471597bcbb9a1f94e2d8929424370
|
Provenance
The following attestation bundles were made for reckon_plans-0.2.0.tar.gz:
Publisher:
release.yml on Simon-McIntosh/reckon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
reckon_plans-0.2.0.tar.gz -
Subject digest:
0df1d81a67ae2ea6171bd34fcdf5146126c0c722c53321fb8d0695ca4c632680 - Sigstore transparency entry: 2580087438
- Sigstore integration time:
-
Permalink:
Simon-McIntosh/reckon@61bf249488b436900072e5a41f31804f4174a8fb -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Simon-McIntosh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@61bf249488b436900072e5a41f31804f4174a8fb -
Trigger Event:
push
-
Statement type:
File details
Details for the file reckon_plans-0.2.0-py3-none-any.whl.
File metadata
- Download URL: reckon_plans-0.2.0-py3-none-any.whl
- Upload date:
- Size: 486.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9a549191e7c5123fdb9b7b3b84625caf62d176eab05e1f1eae06ea48a0d4f20f
|
|
| MD5 |
e8a3ed239a8e97e3e1c5f13bae1fa447
|
|
| BLAKE2b-256 |
fd408e4575794cbbd135c7b13b90d77ab5eaff5255a0b4ef1a2c1fcd2972e464
|
Provenance
The following attestation bundles were made for reckon_plans-0.2.0-py3-none-any.whl:
Publisher:
release.yml on Simon-McIntosh/reckon
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
reckon_plans-0.2.0-py3-none-any.whl -
Subject digest:
9a549191e7c5123fdb9b7b3b84625caf62d176eab05e1f1eae06ea48a0d4f20f - Sigstore transparency entry: 2580087449
- Sigstore integration time:
-
Permalink:
Simon-McIntosh/reckon@61bf249488b436900072e5a41f31804f4174a8fb -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/Simon-McIntosh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@61bf249488b436900072e5a41f31804f4174a8fb -
Trigger Event:
push
-
Statement type: