@yandy0725/pi-todo
pi package providing a minimal todo tool with an editor-overhead widget
Package details
Install @yandy0725/pi-todo from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@yandy0725/pi-todo- Package
@yandy0725/pi-todo- Version
0.5.1- Published
- Nov 13, 2026
- Downloads
- 978/mo · 75/wk
- Author
- yandy0725
- License
- MIT
- Types
- extension
- Size
- 45.5 KB
- Dependencies
- 0 dependencies · 3 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-todo
A minimal pi package that adds a single todo tool with an editor-overhead widget for visual task tracking.
Features
- One tool, three actions:
set(plan all tasks),update(change one task),list(review progress) - Update discipline in the prompt: the tool description and guidelines pin down when to update (one
in_progressper in-flight task, markdoneimmediately) - Feedback on every update:
updatereturns progress, the next task, and the tasks still in flight (✓ #2 写单测 done (2/5 done) · next: #3 修 CI · ◉ still in flight: #4 发布), not a bareOK - 3 states:
pending→in_progress→done - Dependencies: optional
blockedByarray, with self-dependency and cycle detection - Compact widget above the editor:
○pending ·◉in_progress ·✓done ·🔒blocked — windowed around the in-flight task when the board grows, with an always-visible progress line - Branch-safe persistence: state is reconstructed from the session branch, so
/forkand/resumekeep the right todos - Reminder when the model goes quiet: if the board has open work and no
todocall has happened for a while, one short reminder is injected into the next request (request-local, never written to the session)
Install
pi install npm:@yandy0725/pi-todo
Or add to ~/.pi/agent/settings.json:
{
"packages": ["npm:@yandy0725/pi-todo"]
}
Tool reference
todo(action: "set" | "update" | "list", items?, id?, status?, title?, blockedBy?)
set— replace the whole list withitems(use at planning time)update— update the task referenced byid(status,title,blockedByoptional)list— return the current list
Task ids
- The tool owns ids:
setassigns1..nby position and ignores anyidpresent in the items it receives. update'sidmust match one of those ids exactly (send3, not#3);blockedBytakes exact ids too.- A wrong id is never guessed at: the error echoes the current board (titles clipped, up to 20 lines) so it can be corrected without an extra
listcall. setreplaces the whole list, so ids are renumbered — trust the ids echoed by the latestset/update.
update returns a single-line ack on success: what changed, the progress, the next task, and any other tasks still in flight.
Parallel work and subagents
The board belongs to one session: a subagent runs its own todo instance and can neither see nor update yours. So keep the parent as the only writer — hand item #2 to a subagent, and mark it yourself.
Parallel dispatch is supported:
- mark an item
in_progresswhen you dispatch it,donewhen its result comes back; several items may bein_progressat once nextnever suggests a task that is already in flight; every ack names the other tasks still in flight (the first two by name, the rest folded into+N, e.g.· ◉ still in flight: #2 修 CI), so a stalein_progressitem is named on the next update instead of being silently droppedsetreplaces the board and renumbers ids; if items were in flight it appends a⚠ ids renumberedline naming them, because your in-hand references just broke
The widget hides automatically when every task is done.
Reminder when the model goes quiet
Prompt rules alone do not keep a board current: in 40 real sessions with these guidelines delivered, 30% never updated after set, 43% set a plan of 3+ tasks and then made fewer than a third as many updates, and 76% of done marks arrived with no in_progress for that task first — the board was written up at the end instead of kept live.
So the extension also nudges. It counts assistant turns since the last todo call and, once the board has open work and the count reaches the threshold, appends one short reminder to the next model request:
<todo-reminder>The pi-todo board has not been updated for 6 turns. Still in_progress: #2 修 CI. When one of them is finished, call todo action "update" with its id and status "done" right away — do not batch completions to the end of the run.</todo-reminder>
Details worth knowing:
- Request-local: the reminder is added to the outgoing request only. It is never persisted, so it cannot pile up into several stale copies that contradict each other, and the session stays clean for
/treeand resume. - Rate-limited: the first reminder comes after 5 turns, and the wait doubles after each one (5 → 10 → 20 → 40). A long run gets a handful of reminders, not one per turn.
- Self-cancelling: any
todocall — including one that fails — resets the clock, so a model that keeps the board current is never interrupted. - Silent when there is nothing to do: no board, an all-done board, and a board whose remaining tasks are all blocked produce no reminder at all.
Widget and full view
The widget above the editor is a compact summary capped at 8 lines. When the board is longer than that budget it renders a window instead of getting truncated:
- the window anchors on the first
in_progresstask (or the first unfinished one when nothing is in flight), fills forward, and spends any leftover rows on earlier tasks; ↑ n/↓ nmark how many tasks are hidden on each side;- the last line is always the overall progress (
✓ 6/18 · ○ 11 · 🔒 1); - every line is clipped to the terminal width with an ellipsis, so nothing wraps and no host-side
widget truncatedever appears.
The widget hides when the list is empty or every task is done. RPC clients get the same window as plain lines (component widgets are TUI-only), so titles are not width-clipped there.
The full view is a command: /todos opens the complete list in an overlay (↑/↓ or j/k to move, g/G for the ends, Esc or q to close); the header carries the progress plus a (current/total) position marker whenever the list is longer than the window. It is read-only — nothing in it changes the board. Outside the TUI the command falls back to a notification carrying the full list: RPC forwards it, while print and JSON modes have no UI and produce no output.