Task Planning
Overview
TASKS.md at the root of the unit of work you are actively in — usually a
package, or the directory you're working in when there is no package (e.g. a
skill, a hook, a script) — is the durable, committed task ledger for that
work. It survives context resets and new sessions, so both you and the user can
resume mid-task and see exactly what is done, in progress, and pending.
It is distinct from in-session TodoWrite: TodoWrite is ephemeral scratch for the
current turn; TASKS.md is the persistent source of truth that lives in the
repo. Use your judgment about when a task warrants one — err toward creating it.
Never reach for a background task chip (spawn_task) to record a follow-up on
the work you're doing — that follow-up belongs in TASKS.md. Task chips are
only for genuinely separate work that should spin off into its own session.
Projects (registry)
A project is a work-stream — one coherent effort, usually one branch/worktree
— with its own TASKS.md (the ledger) and DESIGN.md (the why: spec +
decisions). All projects are listed in a committed registry so you and any future
session can see everything in flight and resume the right one.
Registry — one entry per project, recording where its docs and PRs live. Its
location is not fixed by this skill: the /dxos:project directive ends with a
BACKEND: line naming the store (by default the file
.agents/projects/registry.yml, overridable via DX_PROJECT_REGISTRY). Obey
that line; a future backend is a service rather than a file, and the schema below
is the shape either way.
projects:
- name: mailbox-research # stable slug
status: active # active | paused | blocked | ended
user: burdon # owner (git/system username, e.g. `whoami`)
host: burdon-mbp-2022 # machine the project lives on (`hostname -s`)
created: 2026-07-05
summary: One line — what this stream delivers.
tasks: path/to/TASKS.md # a package file, or <registry-dir>/<name>/TASKS.md
design: path/to/DESIGN.md # spec + decisions (a REPORT.md counts)
prs: [12163]
resume: 'The single next action.'
ended: []
- The registry records the location of each doc, so an existing effort points
at its package files and a brand-new project defaults to
<registry-dir>/<name>/{TASKS.md,DESIGN.md}. Keep it committed and current.
The /dxos:project command
/dxos:project VERB [ARGS] drives the registry — (bare) | list [all] | tasks | new | end | track | hydrate | resume. The per-verb instructions are not repeated
here. The plugin's hooks/track.sh reads the raw typed text on
UserPromptSubmit and injects the directive for the verb actually given; that
directive is authoritative and arrives whether or not the command expansion does.
Follow it, obey its BACKEND: line, and confirm in one short line.
This file covers what applies without the command — the TASKS.md convention, the registry schema, and the handoff steps below — because the skill loads on "work spans several steps" or "resuming work", when nobody has typed anything.
A lone number in the user's next message after a /dxos:project list table means
"resume the project at that row". With no argument, resume/hydrate fall back
to the single active entry for the current user; if more than one is active,
ask which (list them numbered) — never a guess.
The registry deliberately does not record a branch/worktree. Each session runs in a fresh harness-assigned worktree, and a project's original branch is typically already merged to
main, so there is nothing stable to match. On resume, never warn about a worktree/branch "mismatch" — a fresh worktree is the expected state — and never leave the assigned worktree to chase the project's old one: do notcdinto, edit in, or adopt another worktree or branch as a working directory. If unmerged prior work lives elsewhere, report where it is and ask the user; continuing the work-stream always happens in this session's own worktree.
When to Use
- Work spans 3+ distinct steps, multiple files, or phases.
- The task will likely outlive one session (you'll resume it later).
- The user asks for a plan, roadmap, or to track progress.
- The user uses
/dxos:project track <text>— always record the item, never a task chip. - You are resuming work — read the existing
TASKS.mdfirst to reload state.
When NOT to use:
- Throwaway one-offs (a single edit, a quick answer) — just do them.
- Cross-package chores with no single home — keep those in TodoWrite.
- Duplicating TodoWrite — pick one; don't mirror the same list in both.
Location & Format
One file per unit of work: <root>/TASKS.md, where <root> is the package root
when there is one (e.g. packages/plugins/plugin-magazine/TASKS.md), or
otherwise the directory you're working in (e.g.
tools/claude/plugins/dxos/skills/task-planning/TASKS.md). Match the existing convention:
# <Package> — Tasks
## Phase 2: <goal>
Short paragraph of context — what this phase delivers and why.
### Tasks
- [ ] **Headline task**
- Concrete sub-step with the specific API/file involved.
- Another sub-step.
- [x] **Completed task** — one-line note on what shipped.
### References
- Links to specs, external docs, related PRs.
- Phases are
##; tasks are- [ ]/- [x]; detail as nested bullets. - Keep headlines imperative and specific; put the why in the phase context.
Workflow
- At task start — read the existing
TASKS.md(if any) to reload state; otherwise create one with the phase and its tasks. - As you work — check off
- [x]in the same change that completes the work. Never leave checkboxes stale, and never batch-check everything at the end. - When parking a task — leave a one-line status note on the item (what's blocked, what's next) so it's resumable.
- Before claiming done — reconcile
TASKS.mdagainst reality: every checked item is actually complete, and no completed work is left unchecked. - Commit it —
TASKS.mdis committed alongside the work it tracks. Do not leave it as an uncommitted local edit (see "commit nothing silently").
Project handoff (/dxos:project hydrate / /dxos:project resume)
TASKS.md is the handoff medium — no separate HANDOFF.md (keep plans in the
original doc). The two verbs are the explicit checkpoint/reload actions.
/dxos:project hydrate — checkpoint before stopping or opening a PR
- Reconcile
TASKS.md— check off what's done; add a one-line status note to each in-progress item (what's blocked, what's next). - Refresh the resume pointer — a single italic line under the title:
_Resume: <the one next action>. Uncommitted: <none | files>. Last: <what just landed>._ - Push the why into the design doc (if the work has one —
REPORT.md,DESIGN.md, a spec): decisions and findings live there;TASKS.mdstays the ledger. Save durable, cross-session direction to memory (it auto-loads next session) — not to a doc. - Account for uncommitted work —
git status; commit everything or state plainly in the resume pointer what's left uncommitted. Uncommitted work is the number-one thing a resumed session loses. - Confirm the checkpoint in one short block (done / in-progress / next / uncommitted).
/dxos:project resume — reload at the start of a session
- Stay put — resume continues the work-stream in this session's assigned
worktree; never
cdinto or adopt the project's previous worktree/branch. If unmerged prior work lives elsewhere, report it and ask the user. - Read the active
TASKS.md(and any doc it links); memory is already loaded. - Check the tree —
git status+ recentgit log; surface uncommitted work and the last commits. - Report a concise state: done / in-progress / next action / uncommitted.
- Continue with the next action, or wait for direction if the user gave any.
Viewing
Open TASKS.md directly to see it rendered — Claude Code previews Markdown
files in the Browser pane, so the checklist is visible while you work.
Common Mistakes
| Mistake | Fix |
|---|---|
| Stale checkboxes (work done, box unchecked) | Update TASKS.md in the same edit as the code. |
| Spawning a task chip for an in-scope follow-up | Record it in TASKS.md; chips are only for separate spin-off work. |
TASKS.md in the wrong package/directory or worktree |
Write to the unit of work you're actually editing, in the session's worktree. |
Duplicating TodoWrite and TASKS.md |
TASKS.md = durable/committed; TodoWrite = in-session scratch. Don't mirror. |
Leaving TASKS.md uncommitted |
Commit it with the work; account for it in git status. |
| Batch-checking all items at the very end | Check off incrementally as each task lands. |