TokenEconomizer
코딩 에이전트를 위한 경험 기반 블랙박스 비용 제어
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기An orchestrated multi-agent-pipeline where you decide what needs to get done and Planestro helps you get there.
저장소 README에서 가져옴
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Your backlog, shipped by agents — with you at the decision points. Local-first planning and agent orchestration for a solo developer: a web app, an API, anything that lives in a git repository with CI. Write an item in markdown; Claude Code or Codex plans it; Claude Code or the Codex CLI implements it; planestro does everything mechanical in between.
Queue an item and planestro turns it into a plan you approve, an implementation on its own branch and worktree, a pull request, a CI wait, a rebase when the base moves on, a merge and a cleanup. Models do the thinking; deterministic code does git, GitHub and CI. When an agent needs you — a plan to approve, a permission, a question — its session is parked and the item turns red. Answer whenever, even after a restart, and the same conversation resumes.
It is used daily to build Hurricane Harrison, a game on the App Store: several agents in parallel worktrees, every change through a reviewed plan, a pull request and green CI — including features split across two agents, where Codex draws the art and Claude writes the code that uses it.
git clone --branch main https://github.com/gravesisme/planestro && cd planestro
npm install && npm run build
npm run sample # http://127.0.0.1:4310
On a fresh clone the install and build take a few minutes.
sample builds a fictional project (tidepool, a tide-times CLI) with a full
backlog — finished work with its history, a reviewed piece of art, a bug with
repro notes, two epics, an icebox, prompt templates for both agents — and
serves it with the engine in dry-run. Git, GitHub and both agents are the
in-memory fakes the test suite drives, so the whole lifecycle really runs:
Drag a card from NOT YET SUBMITTED to QUEUED. A worktree is "created" and a plan appears; the card turns red: it needs you.
Open it, read the plan, Approve & implement.
Watch it open a PR, wait for CI, merge, clean up and land in Done. The
Console tab shows every Would … the real engine would have run.
For one feature split across two agents, open the Tide chart view epic → plan the breakdown, and follow features split across two agents below.
npm run sample -- --reset rebuilds it from scratch.
Each model in planestro.yml carries a one-line description of what it is
for. Write one epic, and the selected planner proposes the children, routes each
to the model whose description fits, and wires which waits on which. Code
checks the list (known implementers, no cycles) before you ever see it; you
edit it and approve. The children land on the epic's integration branch and
ship as one pull request.
The sample shows the case this was built for, pictures and code: raster art routed to a Codex model that can generate images, the code that uses it to Claude, waiting for the art.
Codex draws in its own worktree and commits. The pull request goes through sync and CI like any other — then, instead of merging, it parks for your eye: before/after thumbnails from git, approve, or send it back to the same Codex thread with a note and a pasted screenshot.
Only when the art has merged do the code children start — their worktrees cut from a branch that already holds the PNGs, their prompts listing exactly which files were delivered. Then the epic lands as one pull request. The walkthrough →
The two agents are trusted differently, and the tool says so: a Claude worker asks before anything unusual (a per-command policy, parked permission requests); a Codex worker runs in a sandbox that confines writes to its worktree and temp and blocks network access. With app-server, a command needing approval parks for your decision; an approval grants that exact command once. Agents →
The interesting part is not that an LLM writes code; it is everything around
it that has to be boring and correct. The rules the codebase is held to (the
full list, with reasons, is in CLAUDE.md):
# Description, # Notes, # Plan, # Activity), a prompt library,
small attachments and an NDJSON journal, in a git-versioned data dir with
meaningful commits (TD-6: approve plan). Readable, greppable and editable
without the tool.engine.mode: dry-run logs Would …
instead of acting, and PAUSE AUTOMATION stops everything new after the
current safe operation, across restarts.{code_repo, data_dir}. The data dir can
live anywhere — for example an orphan branch of the code repo checked out as
a nested worktree, so planning history never touches the code's branches.See Switching providers for continuing paused work in either direction, preserved decisions, token budgets, and a Codex-only setup without Claude installed.
NOT_YET_SUBMITTED → QUEUED → PLAN_IN_PROGRESS → PLAN_READY → IN_PROGRESS → IN_REVIEW → MERGED → FINISHED
(planner) (you approve) (implementer) (rebase, CI, merge) (cleanup)
ICEBOX holds ideas; blocked / awaiting are orthogonal flags, so an item
never loses its phase when it needs you. Epics own a feature/<slug>
integration branch for chained children; items driven by something else
(another agent, a colleague) are watched rather than run. Close as done
finishes an item whose work landed some other way, without a PR.
An orchestrator session (a separate, freely rotated Claude or Codex conversation) wakes on the ambiguous events — a plan to review, a second red CI run, a conflict — and can instruct workers or escalate to you; it never owns state.
npm install && npm run build
npm run planestro -- init ../myproject-planning --repo ../myproject --name "My Project" --prefix MP
npm run planestro -- check ../myproject-planning --preflight
npm start -- ../myproject-planning --open # http://127.0.0.1:4300
Pick the agent once: Claude by default, or add --provider codex to init and Codex plans,
implements and orchestrates, with no Claude installed
(Codex-only setup). Mixing both, item by item,
is set up later in Settings → Models.
Requirements: Node 24, git (with a user.name and user.email), the GitHub CLI
(gh, authenticated), and an agent CLI for each runner your models use: Claude
Code (claude, logged in), the Codex CLI (codex, logged in), or both. check --preflight above checks the ones the project uses on this machine, with no model
call, and prints the repair for anything missing. macOS is where planestro is used
day to day; Linux runs its CI; Windows is untried.
init makes the planning folder a git repository of its own when it is not one
already, and commits the seed files: that history is the audit trail. Keep any
remote you push it to private. If origin/HEAD is not set in your code repo, it
takes the branch checked out and says so; pass --default-branch to choose.
The engine starts in dry-run; once you have watched a dry run against your repo,
set engine.mode to live in Settings, then stop the server (Ctrl+C) and start it
again: the mode is read at startup. Work is real only once the header says Live,
not Dry-run.
planestro is MIT-licensed. npm install — even for the no-login sample — also installs
Anthropic's @anthropic-ai/claude-agent-sdk, which is not MIT: it is © Anthropic PBC under
Anthropic's own terms (see its README and
https://code.claude.com/docs/en/legal-and-compliance), and planestro does not redistribute it.
planestro runs the agents on your own Claude Code or Codex login.
Project rules come from your repo's own CLAUDE.md / AGENTS.md; planestro
adds nothing project-specific.
serve --watch is for working on planestro itself: web source changes rebuild
the UI and open pages reload; server changes restart it between agent turns
(automation is paused until running turns finish, then resumed).
serve runs in the foreground. For a server that should keep running after
the terminal (or the Claude Code session) that started it is gone, use start:
npm run planestro -- start ../myproject-planning --port 4300
npm run planestro -- status
npm run planestro -- stop ../myproject-planning
start [data_dir] [--port N] [--host H] [--watch] runs serve in a
session of its own, logging to <data_dir>/.planestro/serve.log. It returns
once the server answers, after reconciling items against their branches and
worktrees, and prints the URL, the log path and any corrections. A server
started as a Claude Code background task is killed at that task's time cap,
along with the worker turns it is driving. A server from start is not. If
the data dir's own server is already up on that port, start prints it and
exits 0, so a wrapper script can run it every time. It refuses (and says what
holds it) the same data dir on another port, a data dir another planestro
holds, and a port something else listens on. It never stops or takes over
another server. A data-dir lock whose pid now runs something unrelated is stale,
and start removes it.stop <data_dir> | --port N | --all sends SIGTERM to the server's whole
process group (npm, tsx, the server, and a --watch supervisor with whatever
child it last restarted), then SIGKILL after 15 s. With no argument it stops
the data dir in the current directory, and refuses rather than guessing when
there is none. A server started some other way is found by its port or its
data-dir lock and stopped on its own, never by its group, which may be a shell's.
Anything that is not planestro serve is left alone.status [data_dir] lists every running instance on the machine (data
dir, URL, pid and process group, uptime, log) and drops records whose process
has gone.Each instance is recorded in its data dir (.planestro/instance.json), with a
pointer in ~/.planestro/instances/, so several projects can run side by side
on different ports, and stopping one never reaches another. A --watch instance
restarts whenever planestro's own source changes, so editing or pulling the
planestro checkout restarts every instance on the machine that was started from
it with --watch. A restart stays in the same process group, so stop still
catches it.
A consumer repo's scripts can be one line each. From a repo whose backlog is its
planning/ directory, with planestro checked out beside it:
npm --prefix ../planestro run -s planestro -- start "$PWD/planning" --port 4300
npm --prefix ../planestro run -s planestro -- stop "$PWD/planning"
A running server also serves the backlog over MCP at /mcp (streamable HTTP).
It has three read-only tools, and more that write only when the project opts
in:
get_state: the project, engine mode and pause, counts by status, and what
is running, queued, blocked, waiting for you, waiting for review and open as a
PR. It also lists the planestro instances running on the machine, from
planestro start's records.list_items: one summary line per item, filtered by status, epic (its
children), queued or text q.get_item: one item in full.list_notes: the orchestrator's notes about planestro (the Console's
Planestro feedback) and what became of each; open for the ones nothing
was done with.create_item, edit_item and mark_note: with operator_mcp.allow_writes: true in planestro.yml (off by default). create_item files a new item
(title, description, kind, category, priority) to Not yet submitted, marked
created_by: operator_mcp; edit_item changes an item's title, category,
priority, release, epic, dependencies, Description or Notes; mark_note
records the issues a note became, or handled with none. None of them starts,
holds or merges work.operator_mcp.allow_actions: true (a separate opt-in,
off by default, so filing items never grants acting on them): unblock_item (id, message, fresh),
send_message, answer_question (each question to its answer),
answer_decision (an option's label and/or words; an option that carries an
action stays on the board), decide_permission (deny; allow once only with
operator_mcp.allow_permissions, never an allow rule), sync_item,
rerun_ci and file_note (a note filed as an issue in
feedback.issue_repo). Each takes the engine path the board's button does,
and its Activity line says [operator], not [user].operator_mcp.allow_decisions: true (a third opt-in, off by
default): approve_plan (notes, hold), reject_plan, discard_item and
close_as_done, each as the board makes it and recorded as [operator].
Approving an epic-shaped plan as one item and deleting a remote branch on a
discard stay on the board, and merges are always planestro's.Register it once per project, at user scope, under a name of its own.
planestro status prints each instance's MCP URL:
claude mcp add --scope user --transport http planestro-myproject http://127.0.0.1:4300/mcp
codex mcp add planestro-myproject --url http://127.0.0.1:4300/mcp
This is for you and your own sessions, never for planestro's workers, which
never touch planning state. Claude workers and the orchestrator run with
strictMcpConfig, so they load no user-scope or .mcp.json servers, and Codex
workers run with --ignore-user-config. A model whose mcp list names a
server pointing at a running planestro's /mcp is stopped (mcp_missing)
rather than given it. Tests pin all three. Don't add the endpoint to a project's
checked-in .mcp.json: your own sessions in that repo would get it, and
strictMcpConfig is the only thing between it and a worker.
This repository is also a Claude Code plugin marketplace. Its planestro plugin
adds the /planestro skill and registers the operator MCP server above:
claude plugin marketplace add gravesisme/planestro
claude plugin install planestro@planestro
Or, inside Claude Code, /plugin marketplace add gravesisme/planestro and then
/plugin install planestro@planestro.
/planestro (or /planestro status) summarizes the current project's
backlog: what needs you, what's blocked and why, what's waiting for review,
running or queued, and open PRs with their CI. It also lists the other running
instances. Outside a project it summarizes every running instance./planestro start [--port N --host H --watch] and /planestro stop run in
the foreground. Use your repo's start-planestro.sh / stop-planestro.sh
when it has them, else planestro start / stop on its data dir. Without a
wrapper, start needs a port and asks you for one rather than picking one./planestro item <ID> shows one item, from whichever running instance has
that id prefix.The skill runs only when you type it (disable-model-invocation), so it costs
no context until then, and it never changes planestro's state. It finds the data
dir from the current directory (planestro.yml, or planning/planestro.yml in
the repo or its main checkout from a linked worktree), or from PLANESTRO_DATA_DIR.
It runs the CLI from PLANESTRO_DIR, else the checkout the plugin was installed
from, else ../planestro beside the repo. That checkout needs npm install. The registered MCP
server is a small stdio bridge (scripts/mcp-proxy.mjs) to the operator endpoint of
the session's own project: it finds the data dir the same way and reads the URL
from <data dir>/.planestro/instance.json, and refuses a server on that port that
serves another project. So a session in each repo reaches its own backlog, whatever
port it runs on; PLANESTRO_URL, when set, overrides it. Install
the plugin at user scope (the default): workers load project settings, and a
project-scope install would put the skill in front of them too.
If a Claude Code session shows plugin:planestro:planestro as failed (planestro
was down when the session tried it), the tools stay gone for that session until
you run /mcp reconnect plugin:planestro:planestro. serve --watch keeps the
port open across its own restarts, so those no longer cause it.
The web UI has no login on this machine. It binds to
127.0.0.1by default and can start agents that edit and push code. Requests from other websites and DNS-rebinding tricks are refused. With--host 0.0.0.0(orlan_access) another device must be paired first (planestro pair, then/pairon the device), and pairing is plain HTTP: only do that on a network you trust. See SECURITY.md.
planestro is a tool for your own workstation, and it runs on the logins you
already have: Claude sessions use whatever claude is signed in as, Codex turns
whatever codex is. It has no login of its own and never takes a model API key;
ANTHROPIC_API_KEY and the Bedrock/Vertex switches in its environment are
dropped from every session, so usage always comes out of your plans. The dollars it counts are API-price estimates,
a yardstick for budgets, not charges. Access to the machine is the access
control: see SECURITY.md. There is no telemetry; everything that
leaves the machine is listed in What planestro sends.
Claude workers run with a permission policy (packages/server/src/engine/policy.ts):
pushes, PR operations and anything touching the base or release branches are
denied outright — integration is planestro's job, not the agent's — an allow
list covers the routine, and everything else parks as a permission request you
answer in the UI. Codex workers run in the Codex sandbox instead, and cannot
push either. Per-item budgets cap spend (budget_usd_per_item, and turns and
tokens for Codex).
packages/shared schema, item/prompt/release file codecs, ranks, transitions, placeholders
packages/server store (atomic writes, journal, semantic commits), engine (ports,
policy, lifecycle, reconciler, orchestrator, SDK session port),
Hono API + WebSocket, CLI, the sample project
packages/web React + Vite UI: board, item, sessions, releases, prompts, console, settings
docs/ the manual (start at docs/README.md); spike records in docs/notes/
spikes/ the runnable Phase 0 spike
The engine talks to the world only through four ports (git, GitHub, processes,
agents — Claude and Codex behind one contract). Live ports shell out; dry-run ports are an in-memory world. That seam
is why npm test can drive the real lifecycle — CI red then fixed, a rebase
conflict handed to the session, parked questions and permissions, a restart in
the middle of a turn, crash markers left on disk — with no network. The full suite
takes about 4–6 minutes locally and about 7 on CI's hosted runner.
npm test # vitest
npm run typecheck
Hand-edit freely while planestro is not running — it commits your edits as
manual: … at startup. While it runs, planestro is the only writer; worker
sessions never touch the files either: they use the submit_plan, add_note,
append_activity, report_done and report_blocked tools instead. Schema
changes ship as migrations (planestro migrate <data_dir>); an older dir
opens read-only until you run it, a newer one until you upgrade the tool.
A working tool built for one person's workflow, shared as-is. Developed and
used on macOS; Linux runs the test suite in CI; Windows is untried. One project
per server process. The Claude Code and Agent SDK versions it was validated
against are pinned in packages/server/src/compat.ts, and it warns when the
installed CLI has drifted.