@yandy0725/pi-todo

pi package providing a minimal todo tool with an editor-overhead widget

Packages

Package details

extension

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_progress per in-flight task, mark done immediately)
  • Feedback on every update: update returns progress, the next task, and the tasks still in flight (✓ #2 写单测 done (2/5 done) · next: #3 修 CI · ◉ still in flight: #4 发布), not a bare OK
  • 3 states: pending → in_progress → done
  • Dependencies: optional blockedBy array, 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 /fork and /resume keep the right todos
  • Reminder when the model goes quiet: if the board has open work and no todo call 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 with items (use at planning time)
  • update — update the task referenced by id (status, title, blockedBy optional)
  • list — return the current list

Task ids

  • The tool owns ids: set assigns 1..n by position and ignores any id present in the items it receives.
  • update's id must match one of those ids exactly (send 3, not #3); blockedBy takes 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 list call.
  • set replaces the whole list, so ids are renumbered — trust the ids echoed by the latest set/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_progress when you dispatch it, done when its result comes back; several items may be in_progress at once
  • next never 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 stale in_progress item is named on the next update instead of being silently dropped
  • set replaces the board and renumbers ids; if items were in flight it appends a ⚠ ids renumbered line 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 /tree and 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 todo call — 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_progress task (or the first unfinished one when nothing is in flight), fills forward, and spends any leftover rows on earlier tasks;
  • ↑ n / ↓ n mark 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 truncated ever 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.