Skip to main content

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

reckon_plans-0.2.0.tar.gz (1.5 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

reckon_plans-0.2.0-py3-none-any.whl (486.2 kB view details)

Uploaded Python 3

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

Hashes for reckon_plans-0.2.0.tar.gz
Algorithm Hash digest
SHA256 0df1d81a67ae2ea6171bd34fcdf5146126c0c722c53321fb8d0695ca4c632680
MD5 14fd1c0c89623235a48425653287f810
BLAKE2b-256 466d5f95f3ecf3389394f197c88db2249e3471597bcbb9a1f94e2d8929424370

See more details on using hashes here.

Provenance

The following attestation bundles were made for reckon_plans-0.2.0.tar.gz:

Publisher: release.yml on Simon-McIntosh/reckon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for reckon_plans-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9a549191e7c5123fdb9b7b3b84625caf62d176eab05e1f1eae06ea48a0d4f20f
MD5 e8a3ed239a8e97e3e1c5f13bae1fa447
BLAKE2b-256 fd408e4575794cbbd135c7b13b90d77ab5eaff5255a0b4ef1a2c1fcd2972e464

See more details on using hashes here.

Provenance

The following attestation bundles were made for reckon_plans-0.2.0-py3-none-any.whl:

Publisher: release.yml on Simon-McIntosh/reckon

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 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