This is finally the breakdown I promised at the end of the last post: how the living plan skill works, start to finish, so you don’t have to read through the repo to figure it out.
You can find it in my agent-skills repo, it’s 13 files and about a thousand lines, and it runs in five of my projects. The six posts before this one were each a complaint. I realized that’s not the best way to learn about a tool, so this post covers how it works.
A project that runs for months needs a place to keep decisions, a place where work items get created, and something that keeps both of those from loading up with unimportant or archivable information.
- What the Skill Adds to a Project
- Where It Sits Next to BMAD, Spec Kit, and the Rest
- The Router: Five States, Five Workflows
- Grill: The Workflow That Makes Things
- Scaffold: Plumbing After Design
- Adopt: Retrofit Existing Projects
- Why Questions Are Pointers
- The Threshold, and What Counts as Cooled
- The Ledger: How the Judgment Turns Into Rules
- Evict-Tasks: Check, Collapse, Evict
- The Implementer: First Agent, and So Far the Only One
- The Rules Under Everything
- Where This Leaves It
What the Skill Adds to a Project
There are four moving parts.
-
PLAN.mdis the active layer. It’s the decision record, the open questions, the parking lot, and a short session log. The planning agent reads it every session. -
TASKS.mdis the handoff document. When a decision is concrete enough to build, the planning thread writes it up here as a list of tasks. -
The
implementeragent executes that queue in its own context window, on a cheaper model, while the planning thread keeps working. -
The
docs/tree is the inactive layer. Old sessions, cooled decisions, and the full discussion behind every open question live here, one file per item, behind a one-line pointer inPLAN.md.
The skill owns the process. A project gets a one-line pointer in its CLAUDE.md that says to invoke living-plan, and that’s it. The heavy logic stays in the skill’s workflows/ and references/ folders and loads when needed, one file for whichever path you’re on.
Where It Sits Next to BMAD, Spec Kit, and the Rest
I’ve been reading through the bigger agent frameworks lately and using some of them: BMAD, Spec Kit, Superpowers, OpenSpec, Matt Pocock’s skills, and mine fits underneath all of them, weight-wise. It’s lightweight as hell, and that was kind of the goal. I wasn’t trying to reinvent the wheel.
There’s no PRD, no UX phase, no architecture doc template, no story files, and no agile stuff. BMAD will take you from product brief to retrospective, and on a big app it’s worth it. I am building another project using BMAD right now and loving it.
What my skill does is much smaller. It keeps a planning doc and a task file as lean as possible while you plan and build in small loops, which is how I work on a lot of my side projects. They are explorations that become something eventually. I find what that is by building, so I needed something that holds a trail of where I’ve been, not something that wants the thinking done upfront.
It also isn’t original, and that’s fine. It uses some of the same ideas the bigger frameworks do. The docs/ tree that keeps the plan current while old material moves out is the same instinct as OpenSpec archiving its change specs into living specs. The decision record is what every spec-driven tool creates. And the interview at the front of it, the grill, I took straight from Matt Pocock and said so in the last post. I put the pieces together to keep it small enough that planning and task work can stay iterative without a framework owning everything.
The Router: Five States, Five Workflows
The skill starts with a detection step. It looks around before it does anything and discovers which files exist and what their jobs are:
# planning doc
ls PLAN.md PLAN.MD plan.md 2>/dev/null
# task handoff (tolerate singular/plural)
ls TASK.md TASKS.md 2>/dev/null
# conductor: CLAUDE.md is often a SYMLINK to AGENTS.md or vice versa
ls -l CLAUDE.md AGENTS.md 2>/dev/null
# already rebalanced?
ls docs/decisions docs/sessions docs/questions docs/parking-lot 2>/dev/null
# size proxy, for BOTH docs
wc -w PLAN.md TASKS.md 2>/dev/null
# how much of the task doc is already finished?
grep -c '^\s*-\s*\[x\]' TASKS.md 2>/dev/null; grep -c '^\s*-\s*\[\]' TASKS.md 2>/dev/null
Then it classifies the project and routes:
| State | Detected by | Route |
|---|---|---|
| Greenfield | no planning doc present |
grill, then scaffold
|
| Partial | planning doc exists, but no task file, no implementer agent, or no docs/ tree |
adopt |
| Mature | full system present, planning doc heavy | rebalance |
| Task doc bloated | task doc heavy and mostly finished work | evict-tasks |
| Deciding, not filing | not a filesystem state | grill |
Four rows cover things you can see in the directory. The last one triggers on what you are doing at the time.
PLAN.md and TASKS.md both load up with content, but for different reasons. A planning doc bloats because decisions pile up. A task doc bloats because finished tasks never leave the list.
Grill: The Workflow That Makes Things
I covered this one in the last post and stole the idea for it from Matt Pocock.
Four of the five workflows modify existing files. Grill is the only one that creates new things. It interviews me and puts the results under one of four headings: decided, open question, parked, or not applicable.
Ideas usually follow a specific path: parking lot, then open question, then decision, then task queue. Grill moves an item and asks before it does.
Scaffold: Plumbing After Design
On a brand new project, grill runs first and scaffold runs second. That order is a fix. Scaffold used to open with “what is this project?” and then emit a PLAN.md with an empty decisions section.
Scaffold’s interview is all about plumbing:
- What the docs are called. Default is
PLAN.md,TASKS.md, andCLAUDE.md, withTASK.mdandAGENTS.mdoffered if the repo already has those files. - Whether to create the implementer agent, and which model it runs on. Default is Sonnet.
- Whether there’s a copy of the task list somewhere outside the repo, like a note in a notes app. If there is, the conductor gets one line saying where it is and when to reconcile it.
If I skip the grill or bail halfway, scaffold still runs on whatever got decided.
Adopt: Retrofit Existing Projects
Most of my projects didn’t start with this skill. They had their own docs and their own idiosyncrasies, and the skill had to go into them without breaking anything.
adopt diffs the project against the full system and adds only what’s missing. It touches existing docs only to add pointers.
The best example I have is a project called sychysis. When I surveyed my projects for this series, an earlier pass recorded it as having “no PLAN.md at all” and filed it as a project without the system. That was wrong. It’s fully in the system. It just doesn’t look like the template. Here’s the config block at the top of its ledger:
## Config
- **planning doc:** `docs/vision.md` (was `docs/rough-plan.md`)
- **task doc:** `TASKS.md` (repo root)
- **conductor:** `AGENTS.md` (no `CLAUDE.md`; not a symlink)
- **archive:** `docs/archive/` (completed batches, frozen)
- **threshold:** 15000 words (default)
- **executor:** opencode (see `opencode.json`); **planner:** Claude Code
The planning doc isn’t called PLAN.md. There’s no CLAUDE.md. It runs two tools, Claude Code planning and opencode executing, which is the split from post four. And it already had a docs/decisions/ folder full of ADRs before the skill ever showed up. The ledger says that those ADRs belong to the project and must not be confused with the skill’s decisions.
None of that is drift. It’s the skill bending around a project that was there first, with the details written down so the next run doesn’t have to find them next time.
Naming variance is a feature
Half the fragility in tools like this comes from assuming file names. So the skill tolerates TASK.md and TASKS.md, AGENTS.md and CLAUDE.md, and records whatever it finds in the ledger once.
CLAUDE.md is very often a symlink to AGENTS.md. Anything that edits “the conductor” has to resolve the link and edit the real file. Write through the link with the wrong tool and some of them will replace the symlink with a regular file.
Why Questions Are Pointers
Things in PLAN.md get one of two treatments.
Decisions stay whole and inline while they’re active. A decision is a Dxx record in the decisions section, body and all, because it’s load-bearing and the planning agent needs the reasoning every session. When it cools down, it collapses to a one-line heading plus a link, and the body moves to docs/decisions/Dxx.md. The ID never changes, so anything that referred to D14 still resolves.
Open questions and parking-lot items are born as pointers. From the moment one exists, PLAN.md shows only the one-line heading and a link to docs/questions/Qxx.md or docs/parking-lot/Pxx.md. The discussion lives in the file.
Questions grow and decisions don’t. A decision is a conclusion. Once it’s made it mostly sits there. A question is an argument still in progress. Every grill round that touches it appends a new dated section, because the sequence of what I thought in June is what makes the July answer make sense. Put that inline and an open question gets read every session, for months, mostly to rediscover that I still don’t know.
And questions are deferred by nature. The planning agent needs to know the question exists. It doesn’t need the whole history until somebody’s ready to answer it.
There are two markers on decision headings:
- 🔒 foundational means it never cools, even if nothing points at it. Some decisions are load-bearing for work that hasn’t started yet, like an architectural split a future feature depends on.
- 🔨 unbuilt means the decision is cold enough to archive, but the work it describes hasn’t shipped. The marker survives on the pointer line, so the decisions index doubles as a list of things I decided to build and haven’t.
The Threshold, and What Counts as Cooled
The skill’s default threshold is 15,000 words for the planning doc and it’s just a nudge. If I invoke the skill and PLAN.md is over, it says so: “PLAN.md is 27.6k words, about 12k over threshold, want to rebalance?” The real entry point is me asking.
The word count is a stand-in for what I actually care about, which is how much context every session burns reading the plan. The agent can’t reliably read its own context usage. It can run wc -w.
For the task doc the nudge is a ratio, not a size. When finished work is over about 60% of the file, it says that, in numbers.
What gets moved during a rebalance depends on what kind of thing it is:
- Session log entries go by recency. Keep the last three inline, archive the rest. No judgment needed, and this is usually where most of the weight is, so it goes first.
- Decisions go by reference, not age. A decision cools when nothing currently active points at it (no open question, no parking-lot item, not the live task, not a recent session) and it isn’t flagged foundational.
- Questions and parking-lot items were never inline to begin with, so there’s nothing to move.
Here’s where my five projects stand today:
| Project | Planning doc | Words |
|---|---|---|
| writing-model-research | PLAN.md |
17,324 |
| nsf-scifi-wiki | PLAN.md |
10,876 |
| deep-research-agent | PLAN.md |
10,395 |
| content-tools-v2 | PLAN.md |
8,588 |
| sychysis | docs/vision.md |
8,313 |
content-tools-v2 is the project I confessed about twice in this series. It was at 16,939 words in August. It’s at about half that now.
The one over the line is writing-model-research, and it’s the most interesting number in the table. In August it had a planning doc of about 1,500 words. It’s also the project the grill has run in most. Grilling generates decisions, decisions are most of a mature planning doc. That’s the loop working. It just means that project is due a rebalance, and I haven’t run it yet.
The Ledger: How the Judgment Turns Into Rules
Every project gets a small append-only file at docs/rebalance-log.md. It does three jobs.
It’s the audit trail. Every relocation gets one line with a reason, so every move can be traced back and reverted.
It’s the per-project config. Which file is the planning doc, which is the task doc, which is the conductor, what the threshold is, and what deviates from the standard shape. That’s what lets sychysis look nothing like the template without the skill guessing from scratch every run.
And it’s the seed for automation. Early on, every hot-or-cold call is made by hand and logged with its reason. After each run, the skill scans the ledger for a reason that has shown up in three or more runs and isn’t a rule yet, and pitches exactly one: “You’ve cooled superseded decisions four runs straight. Make that automatic?” If I say yes, it moves into a Rules section and runs mechanically from then on.
I didn’t design the rules up front, because I’d have gotten them wrong. They get mined from what I actually do. Even then, nothing stops being propose-then-confirm. Automation just shrinks how much I have to remember and look at manually.
sychysis’s ledger shows what this turns into. It has rules like “the executor may append to the parking lot; only the planner may promote out of it,” and “never reference a living doc by line number.” That last one came from a specific mistake and is now written down where the next run will read it.
Evict-Tasks: Check, Collapse, Evict
Post five is the story of this one. The task doc already had a collapse rule: finished queues shrink to a one-block summary with a [tag]. It didn’t have a step where those summaries actually leave. Check, collapse, and then nothing. The third stage was missing.
A collapsed block gets evicted when every piece in it is checked and nothing still open references it. That second condition is a judgment call, which is why eviction never happens automatically at the end of a queue. The implementer especially must not do it, because it would be editing the file that holds its own run state while it runs.
Before anything moves, two kinds of material get lifted out:
- Lessons. Gotchas and landmines the next similar job will need. If the next person doing this kind of pass would want it, it’s a lesson, not history.
- The inventory. If the done blocks are the only record of which scripts exist, that table belongs in the code’s README.
Everything else moves verbatim, by line range with sed, never retyped. Retyping a 700-line block is how detail disappears.
The Implementer: First Agent, and So Far the Only One
Every task in TASKS.md has the same sections: goal, why (as a pointer back to the decision), a run-state note, the numbered pieces, files, tests, what’s out of scope, and what to report back. The agent is cold on the planning conversation but warm on the project. It has the codebase and the conductor, so it doesn’t need the repo explained. It needs the job specified.
The agent template is short and the rules are blunt:
- Work the numbered pieces as a serial queue, top to bottom, one pass. Serial is on purpose. The point is pacing, not throughput.
- A blocked piece doesn’t stop the queue. Mark it
[!]with a one-line reason and keep going with anything that doesn’t depend on it. - Update the run-state note on every stop, done or blocked. If the session dies, the task file is the recovery point.
- No design decisions. Ever. A fork the spec doesn’t cover gets escalated, not guessed.
That queue serves two rhythms. Stack a few pieces and plan the next batch while the agent grinds, or stack a lot and walk away.
The model line that wasn’t there
Here’s a mistake that lived in this skill for a while. The implementer template has a model: line, and scaffold’s interview even asks which model to use. But neither scaffold nor adopt listed `` among the placeholders to fill. The placeholder was orphaned.
So when the agent got backfilled into writing-model-research, the unfilled line got deleted instead of filled in. A Claude Code agent with no model: line inherits the model of the session that launches it. Mine was Opus. The whole point of the implementer is to run the grind on something cheaper, and I’d accidentally built a cheap-looking wrapper that ran on the most expensive model I have.
Both workflows now list every placeholder explicitly, and adopt checks existing agents for a missing model: line even when the agent folder looks complete. The rule that came out of it is in the skill in plain words: a missing model: line is worse than an unfilled one. An unfilled one is visibly broken. A missing one is invisibly expensive.
What the first real run taught it
The first serious queue through the implementer in that project was a diagnostic job: 29 of 80 extracted novels were coming out of a text-prep script with zero scene breaks detected. In that project the implementer wraps a cheaper model and hands the reading and grinding to pi, a command line coding tool running DeepSeek, which is a whole other post.
The cheap route did better than I expected. It found the real cause, shipped a fairly subtle fix, recovered 9 of the 29 books, and correctly refused two design forks instead of guessing. That’s the contract working exactly as written.
Then it reported that word counts were “verified unchanged across all 80 books.” They weren’t. When I sent it back, the real problem was worse than a bad number. It had compared a dry run of the old script against a dry run of the new one. Internally consistent. The verification was measuring itself.
And to be fair to the agent, I got the follow-up wrong too. My alarm about lost content traced back to a stale baseline from an older script version, not to the patch. But raising it turned up a real bug anyway and forced the check to be redone properly.
The lesson isn’t “use a smarter model.” A smarter model makes the same methodology error. The lesson is that verification has to be against disk, not against another run of yourself.
What comes next for agents
The implementer is a generic worker. The skill has a catalog of agents it knows how to backfill, and right now it has one entry. Adding another type means dropping a template into templates/agents/ and registering its name, and every project can then adopt it through the same workflow. I may add agents that do something other than implement. I haven’t yet, and I’m not going to pretend there’s a roadmap.
The Rules Under Everything
These are the parts that would survive a rewrite.
- Propose, then confirm. Every action that changes a file shows a manifest first. Nothing gets overwritten or relocated on the skill’s own say-so.
- Never lossy. Things move, they don’t get deleted. Thread files append, they don’t get rewritten.
- The planner stays light. Heavy process lives in the skill and loads only when needed. The project gets pointers, never copies.
- Measure what you can control. The agent can’t read its own context usage. It can count words.
- Write the deviations down. A project that doesn’t fit the template is fine. A project that doesn’t fit and doesn’t say how is a puzzle for the next session.
Where This Leaves It
Seven posts. The first one was my third attempt at planning with agents, after vibe coding and Spec Kit both didn’t work for these specific type of open-ended projects. Since then the doc got fat, I split the work across two tools, the other doc got fat, and the decision record turned out to record almost nothing until I taught it to interview me. Every one of those was a complaint before it was a feature.
It’s not done, because it can’t be. It’s a skill about documents that grow, maintained by a guy whose projects keep growing. The ledger rules are still mostly hand calls. The agent catalog has one thing in it.
But it runs on five projects, it bends around the ones that were there first, and the deviations are written down instead of remembered. A project opened cold should be able to tell you where it left off. The rest is plumbing.












Top comments (0)