Planning-first, repo-aware AI coding orchestrator CLI
Project description
PLANTOD
Plan, Task, Orchestrate, Deliver — a planning-first, repo-aware AI coding orchestrator CLI.
PLANTOD turns a natural-language request ("add login feature") into a structured
workflow: plan → tasks → scoped execution → test → handoff → escalation → final review.
A strong model plans and reviews; a fast model executes small, scoped tasks. All
decisions and outputs are written to .plantod/ in the repo so the work is auditable.
Install
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
Providers
PLANTOD drives agentic coding CLIs as its backends — one per role. Install the CLI(s) for the providers you pick; each handles its own auth/model config.
| Provider | Binary | Invocation |
|---|---|---|
claude-code |
claude |
claude -p "<prompt>" |
codex |
codex |
codex exec "<prompt>" |
opencode |
opencode |
opencode run "<prompt>" |
plantod login
Set the provider + model for each role (planner / executor / reviewer):
plantod login # interactive wizard (all roles)
plantod login --role executor --provider codex --model o4 # non-interactive, one role
plantod login --role planner --provider claude-code # model optional -> provider default
plantod login ... --project # save to THIS repo instead of global
Config precedence (low → high): defaults < global (~/.config/plantod/config.yaml) < project (.plantod/config.yaml).
login writes the global scope by default so settings carry across repos (NFR-02);
--project overrides for one repo. plantod init inherits the global defaults.
Prerequisites
- Install the CLI for each provider you configure (see table above); each tool manages its own authentication.
.envin the repo root is auto-loaded into the environment (see.env.example) for any provider that reads env vars.- A git repo is required for the scope guard — run
plantod initinside one.
Usage
plantod login # pick provider + model per role (see Providers)
plantod init # detect repo, scaffold .plantod/ (inherits global)
plantod plan "add login feature" # plan + break into tasks + run the default flow
plantod plan "..." --yes --review # approve gated tasks, run final review
plantod tasks # list tasks + status
plantod next # next runnable task
plantod run T001 # run a single task
plantod review R001 # final review for a requirement
plantod status # board summary
plantod resume # where the last session left off
plantod # interactive chat-like session
Why planning-first saves tokens (cost model)
PLANTOD's economics come from routing: a strong, expensive model only plans and reviews (low token volume, high-value reasoning), while a cheap, fast model does the bulk editing (high token volume, low-level work). Most tokens in a coding task are spent reading context and writing edits — so you want those on the cheap model.
Illustrative example — one feature = 1 plan + 4 tasks + 1 review. Token splits below are assumptions to show the shape of the saving, not measurements:
| Stage | Tokens | All-in-one (strong model) | PLANTOD (routed) |
|---|---|---|---|
| Plan + review | ~30K | strong | strong |
| Task execution (×4) | ~200K | strong | cheap executor |
| Total billed as | ~230K | 230K × strong-rate | 30K × strong-rate + 200K × cheap-rate |
If the executor model is ~15× cheaper per token than the planner (a typical fast-model vs frontier-model gap), the routed run costs roughly:
strong_share = 30K
cheap_share = 200K / 15 ≈ 13.3K strong-equivalent tokens
routed_total ≈ 43.3K vs 230K → ~5× cheaper for this mix
The exact multiple depends on your models and the plan/execution token ratio — plug in current per-token prices for your planner and executor to get real numbers.
Honest caveat: these figures are an illustrative model, not a benchmark. PLANTOD does not yet meter real token usage — cost tracking is on the v2 roadmap (PRD §27). The structural saving (route bulk edits to a cheap model, keep reasoning on a strong one) holds regardless; the exact ratio is yours to measure.
Beyond cost, the planning-first flow also reduces wasted tokens: scoped tasks and the scope guard stop the executor from sprawling across the repo and re-generating work, which is where "just let the big model code" runs burn tokens on churn.
How it works
- Adapters (
plantod/adapters/) make backends swappable:claude,opencode,mock. - State machine (
plantod/schemas.py) enforces legal task transitions (pending → ready → in_progress → testing → done → reviewed, plusblocked → needs_planner_review). - Approval gate (
plantod/orchestrator.py) auto-runs only low-risk, small-scope, testable tasks; everything else asks for approval. - Artifacts (
.plantod/):requirements/ plans/ tasks/ handoffs/ reviews/ logs/, markdown + YAML frontmatter;board.json/session.jsonfor state.
Configuration (.plantod/config.yaml)
| Key | Default | Meaning |
|---|---|---|
planner / executor / reviewer |
{provider, model} per role |
backend for each role — set via plantod login |
| default providers | claude-code / opencode / claude-code | planner / executor / reviewer |
auto_run_small_tasks |
true | auto-run low-risk tasks |
require_approval_for_architecture |
true | gate high-risk changes |
test_before_done |
true | run tests before marking done |
enforce_scope |
true | revert executor edits outside files_allowed |
apply_requires_approval |
false | confirm the in-scope diff before keeping it |
exec_timeout_s / test_timeout_s |
900 / 600 | subprocess timeouts |
max_retries |
3 | retry transient backend failures / cap replans |
auto_replan_on_escalation |
true | planner advises + retries an escalated task |
Production notes
- Scope guard — after each executor run, any file changed outside the task's
files_allowed(or matchingfiles_forbidden) is reverted via git and the task is escalated. This is enforced, not just prompted. - State safety —
board.json/session.jsonand all artifacts are written atomically (temp file + rename). A per-project advisory lock (.plantod/.lock) stops concurrent runs from corrupting state. - Escalation loop — a blocked task goes
needs_planner_review; the planner produces guidance and the task retries with narrower scope, capped bymax_retries. - Resilience — backend calls retry with exponential backoff; subprocesses have timeouts; malformed model JSON is parsed defensively.
- Requires a git repo for the scope guard; run
plantod initinside one.
Development
pytest # state machine, artifacts, config, full mock-adapter flow
Layout: src/ package layout, entry point plantod.cli:app.
License
MIT
Project details
Release history Release notifications | RSS feed
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 plantod-0.1.0.tar.gz.
File metadata
- Download URL: plantod-0.1.0.tar.gz
- Upload date:
- Size: 33.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b673874166fda2eb899b5b1771cdb6132e6cc3ca1828b473d6a22aee28cba136
|
|
| MD5 |
517ea38cff0661fb610e6cbde62408e9
|
|
| BLAKE2b-256 |
fe26f783a38ef6d5b479a3e823a087a1406222822d4f1aedc7741744f35b6982
|
Provenance
The following attestation bundles were made for plantod-0.1.0.tar.gz:
Publisher:
publish.yml on wandi1209/plantod
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
plantod-0.1.0.tar.gz -
Subject digest:
b673874166fda2eb899b5b1771cdb6132e6cc3ca1828b473d6a22aee28cba136 - Sigstore transparency entry: 2072235579
- Sigstore integration time:
-
Permalink:
wandi1209/plantod@884ab8ea5a6e2f3ddfe67e45aa87d561d57df6df -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/wandi1209
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@884ab8ea5a6e2f3ddfe67e45aa87d561d57df6df -
Trigger Event:
release
-
Statement type:
File details
Details for the file plantod-0.1.0-py3-none-any.whl.
File metadata
- Download URL: plantod-0.1.0-py3-none-any.whl
- Upload date:
- Size: 35.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
aa2414738e77858e5a3fea587950b400cce708d0937170499e90fcaf4e2910e4
|
|
| MD5 |
c02684b963b8599fc2cac926d08b3d71
|
|
| BLAKE2b-256 |
4f08b1b995b3b7abb629dea695b65b6b1ecb360cc748d19cc0a7e48a391bf72b
|
Provenance
The following attestation bundles were made for plantod-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on wandi1209/plantod
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
plantod-0.1.0-py3-none-any.whl -
Subject digest:
aa2414738e77858e5a3fea587950b400cce708d0937170499e90fcaf4e2910e4 - Sigstore transparency entry: 2072235863
- Sigstore integration time:
-
Permalink:
wandi1209/plantod@884ab8ea5a6e2f3ddfe67e45aa87d561d57df6df -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/wandi1209
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@884ab8ea5a6e2f3ddfe67e45aa87d561d57df6df -
Trigger Event:
release
-
Statement type: