@juancrg90/todo-widget
Persistent accordion-style todo list widget for pi — display agent task groups from markdown and update state from the agent.
Package details
Install @juancrg90/todo-widget from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@juancrg90/todo-widget- Package
@juancrg90/todo-widget- Version
0.1.1- Published
- Oct 3, 2026
- Downloads
- 200/mo · 184/wk
- Author
- juancrg90
- License
- MIT
- Types
- extension
- Size
- 49 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
@juancrg90/todo-widget
Persistent accordion-style todo list widget for pi. Display task groups from a markdown checklist and update task state as the agent works.
Install
pi install npm:@juancrg90/todo-widget
Usage
The agent loads a markdown checklist with the LoadTodoList tool, then updates individual tasks with UpdateTodoTask. The widget appears in the TUI and persists state across pi restarts for the current project.
Markdown format
# Project: Turnstile integration
## Task 1: Setup
- [ ] Confirmar Wrangler canónico
- [x] Ejecutar auth probe
- [/] Verificar dashboard
## Task 2: Verify
- [ ] Probar rechazo de token
- [ ] Implementar helper
- First
#heading is the project title. - Second-level
##headings are task groups. - Task markers:
- [ ]not-started- [/]in-progress- [x]done
Task IDs
Task IDs are stable and derived from the markdown text: <group-slug>:<item-slug>. For example, a task under ## Task 1: Setup with item - [ ] Confirm env gets ID task-1-setup:confirm-env. The LoadTodoList and ListTodoTasks tools return the exact IDs for each task. Use those exact IDs in UpdateTodoTask; passing an unknown ID returns an error.
Tools
- LoadTodoList — load a markdown task list into the widget.
- ListTodoTasks — return the current list with exact task IDs.
- UpdateTodoTask — mark a task as
not-started,in-progress, ordone. Use the IDs returned byLoadTodoListorListTodoTasks. - ClearTodoList — clear the widget and delete persisted state. Only call this when the user explicitly asks to clear the list; do not call it automatically when a plan finishes.
Keyboard shortcuts
| Shortcut | Action |
|---|---|
ctrl+shift+l |
Toggle widget visibility |
ctrl+shift+o |
Expand all groups |
ctrl+shift+c |
Collapse all groups |
ctrl+shift+[ / ctrl+shift+] |
Focus previous / next group |
ctrl+shift+return |
Toggle focused group |
Slash commands
/toggle-todo-widget/expand-todo-groups/collapse-todo-groups/clear-todo-list(asks for confirmation)
Known limitation: no mouse support
Clicking a group header to expand/collapse is not supported. Pi does not currently dispatch mouse events to extensions or widgets: the TUI's viewport layer consumes all mouse input for scrolling, text selection, and scrollbar drags, and extension input listeners never see mouse sequences. Widget components only receive keyboard input. This is tracked upstream as earendil-works/pi#7683; once pi exposes mouse events to components, the widget can be wired for click-to-toggle.
Until then, use the keyboard shortcuts or slash commands above.
Persistence
State is saved in .pi/todo-widget-state.json inside the current project. Group and task titles, task states, and collapsed groups are restored automatically when pi starts a session in the same project. Loading a markdown list with a different # project title resets persisted task state so progress from an unrelated plan does not leak across lists.
Keeping the widget in sync
The widget is TUI-only, so agents can forget to update it. This extension enforces sync on three layers:
- Status in context — while a list is loaded, a compact
[TodoWidget]block with pending/in-progress tasks and their exact IDs is injected into every LLM call. The model always sees what is left and what IDs to use. - Completion nudge — when an agent run settles with unfinished tasks, a work tool was used, the final message sounds complete, and no
UpdateTodoTaskwas called, the extension injects a follow-up message that forces a reconciliation turn (ListTodoTasks+UpdateTodoTask). Loop-guarded: follow-up runs are never re-nudged, and runs that already updated the widget are skipped. - Prompt guidelines —
UpdateTodoTask,LoadTodoList, andListTodoTaskscarry imperative guidelines that name each tool explicitly.
The nudge can be disabled with the TODO_WIDGET_NO_NUDGE=1 environment variable; the status-in-context layer stays on.
Development
pnpm install
pnpm --filter @juancrg90/todo-widget test
pnpm --filter @juancrg90/todo-widget typecheck
License
MIT © JuanCrg90