Task Progress Reporter
Why
The user supervises many agent sessions at once (tabs, worktrees) and glances at each for seconds. They need: what is this session doing, how far along, is it stuck, what did it touch. A fixed visual language answers that at a glance and separates processes when scrolling. Every output token also costs the user money and reading time, so the format is built to carry maximum status in minimum tokens. Same symbols, same places, every time; do not improvise.
When
Code rule (no judgment call): any task that creates, modifies or deletes source code uses this skill, whatever its size, including when a question turns into "ok, fix it". The agent never waives this rule; only the user can (see opt-out). If some code edits were reported and others not, a missing report would stop meaning "nothing was touched".
- Code task, 2+ steps: full format.
- Code task, single step: compact form (below).
- Non-code task: full format if it has 3+ steps, changes files, or runs long.
- Never: chat, questions, explanations, opinions, reading/reviewing code without changing it, trivial single-step non-code edits.
If a conversation becomes a task midway, start the format at that moment.
Per-prompt opt-out
If the prompt for the current task says the user does not want progress shown, in whatever language they write ("no progress", "without showing progress", "skip the progress report", "sin mostrar progreso", "no quiero progreso", "no progreso", "sem progresso"), do not use this skill for that task: no delimiters, no plan, no ticks, no tpr.py call. Work as if the skill were not installed. This outranks the code rule, because the rule exists to serve the user and they have just said what serves them.
- Scope: that task only. Do not store it and do not carry it into the next task; the next prompt without the phrase gets normal reporting. Persistent silence is what "reports off" is for (see Modes).
- It must be about your reporting, not about the software. "Add an upload without showing progress" or "remove the progress bar from the installer" describe a feature; the skill applies as usual. If a phrase could be read either way, treat it as a feature description and report normally: an unwanted report costs a few tokens, an unreported code change costs the user their audit trail.
- It does not license hiding problems. With or without this skill, failures, blockers and questions for the user are still stated, in the agent's ordinary style.
Modes
Same process model in every mode (numbered processes, weighted points, computed percent); what changes is how much is shown.
| Mode | What it shows | Spec |
|---|---|---|
| normal | Everything in this file. Default. | this file |
| eco | ASCII only, top-level plan, progress every 20%, files once at the end | references/eco-mode.md |
| colorful | Richest rendering: progress bars, emojis, linked files, a precise explanation per task, detailed closing summary. Token cost is not a concern. | references/colorful-mode.md |
| explain | Normal mode plus a technical explanation, 10 lines at most, of each completed step | references/explain-mode.md |
| off | Nothing. Work as if this skill were not installed. | none |
Read a mode's spec file only when that mode is active.
Which mode applies
In order of precedence:
- A mode command in this session.
/task-progress-reporter:eco,/task-progress-reporter:colorful,/task-progress-reporter:explain,/task-progress-reporter:normal,/task-progress-reporter:off, or the spoken equivalents in any language ("eco mode", "colorful mode", "explain mode", "normal mode", "reports off").explain <step id>(or "explain step 2.2") is a one-off: it explains that step and changes no mode. In agents without slash commands the user may type the command as plain text; treat it the same. Scope is this session only: remember it from the conversation, do not store it. If the user addsall("/task-progress-reporter:eco all", "eco mode in all sessions"), also store it withpython3 scripts/tpr.py set-mode <mode>so every session picks it up. Acknowledge a mode command in one line; if a process is running, switch from the next report onward. - A stored mode. At the first activation in a session, and at the start of each later full-format process, run
python3 scripts/tpr.py status(path relative to this skill's directory). It prints e.g.usage=82 window=five_hour mode=unset. Ifmodeis set, the user already chose for all sessions: use it, do not ask. If off, say so once per session in one line, then stay silent. - The plan-usage question. If
mode=unsetandusageis 75 or more, ask the question below before the plan and store the answer withset-mode. It is shared by all sessions and expires when the quota window resets, so the user is asked once, not once per tab. - Otherwise normal:
usageunder 75,usage=unknown, script missing or failing. No question.
Never state a usage percentage you did not read from the script. Most environments do not expose plan usage to the agent; unknown is the expected answer there, not an error.
The question, in the user's language, through the environment's question tool if it has one:
You are at <usage>% of your plan. How should tasks be reported?
- Eco mode (recommended): no emojis, top-level plan only, progress every 20% instead of 5%, file list once at the end. Blockers and plan changes still shown.
- No reports: no plan, progress or file lists; the agent works as if this skill were not installed.
- Normal: full reports. Highest token cost.
Colorful and explain are never offered here: they are the most expensive modes and the user is near their limit. They can still ask for it explicitly.
Writing rules (token economy)
These apply to everything you output during a process in normal and eco modes, not only the structured lines. Colorful mode replaces them with its own.
- Facts only: what was done, what was found, numbers, paths, identifiers.
- No preamble, acknowledgment, or restating the request. The opening delimiter is your first output, before any tool call.
- Do not announce what you are about to do; the plan already says it.
- No adjectives, hedging, enthusiasm, apologies, or filler ("successfully", "I've gone ahead and", "great news").
- No narration between reports, including transitions ("Now the API.", "Next, tests."); the next report line says it. No closing recap; the end line is the recap.
- Result notes: 10 words max, only when they add a fact ("14 refs in 6 files", "42 passing").
- After the end line: only actionable follow-ups, 2 lines max, or nothing.
- Use only the symbols and delimiters defined here. No other emojis, separators (
=== plan ===) or decoration. Bold only the title. - Brevity never hides bad news. Failures, skipped tasks, failing tests, risks and anything the user must decide are always stated, in as few words as it takes to be unambiguous.
Language
Write in the user's language, including fixed labels. Spanish: CHECKPOINT, BLOQUEO, DESBLOQUEADO, EN ESPERA, "tarea nueva agregada", "No planificado", "detenido". Symbols never change.
Format
Plain Markdown, no code fences. One element per line; use list items where shown so line breaks survive every renderer.
Open
Number processes sequentially per session. Title: 3-7 words, bold, names the outcome.
Open first, plan second. Print the opening line before your first tool call, with a provisional title taken from the prompt. Minutes of silent setup (creating a worktree, installing, reading an issue) look exactly like a skill that is not running. If you must investigate before you can plan, say what you are reading in a discovery line, then publish the plan as soon as you can. Discovery carries no points. If it changes what the task is, use the better title in the close line; the process number is the identity.
========== ▶ #1 **Migrate sessions to JWT** ==========
⏳ Discovery: issue #212, session usage in src/auth
A question for the user during discovery goes after the opening line as a ⏸️ WAITING: line, never before it.
Plan
Before any work: every task and subtask, in execution order, each weighted. 🟢 simple (mechanical, low risk) · 🟠 moderate (several files or some reasoning) · 🔴 complex (architectural, cross-cutting, uncertain). Weigh honestly; when unsure, pick higher.
1. 🟢 Audit current session usage
2. 🟠 Create token service
- 2.1 🟢 Generation and signing
- 2.2 🟠 Refresh and revocation
3. 🔴 Replace auth middleware
- 3.1 🟠 Token validation middleware
- 3.2 🟠 Swap it into API routes
- 3.3 🟢 Swap it into admin routes
4. 🟠 Update tests
5. 🟢 Update documentation
= 12 pts
Granularity: progress can only move when a leaf completes, so coarse leaves mean long silences. Two rules keep leaves small:
- If a task's description lists parts (parentheses, "+", "and": "classifier + two routes + tests"), those parts are its subtasks. List them.
- No 🟠 or 🔴 leaf may be worth more than 20% of the total points. Split it. 🟢 leaves are exempt.
End the plan with the total (= 12 pts), taken from the script below, never added by hand.
Progress
Computed, never guessed, never time-based. Percent moves only when something verifiable completes.
- Points. Leaf tasks score 🟢=1 🟠=2 🔴=3. A leaf is a task with no subtasks. A parent's emoji is a label for the reader and has no points of its own: a 🟠 parent with a 🟢 and a 🟠 child is worth 3, not 2.
- The script does the arithmetic. Models reliably miscount here (adding parents, carrying a wrong running total), so do not add by hand. Right after writing the plan, run once, passing leaves only, in execution order:
python3 scripts/tpr.py plan 1:1 2.1:1 2.2:2 3.1:2 3.2:2 3.3:1 4:2 5:1It prints the total and the exact prefix each leaf must use when it completes:total=12 now=[0% 0/12] 1=[8% 1/12] 2.1=[17% 2/12] 2.2=[33% 4/12] ...Copy those prefixes verbatim into the leaf lines. If the plan changes or you execute leaves in a different order, run it again with the new list and--done 1,2.1,...;now=is the value for thePLAN+line. If the script cannot run, compute the same way by hand: sum of completed leaves / sum of all leaves. - Acts. A leaf is often worth more than 5% of the plan (in a 12-point plan a 🟢 is 8%, a 🟠 17%), so leaf completions alone cannot give a 5% cadence. When you start a leaf worth more than 5%, split it into its acts: the concrete, verifiable actions it consists of (a function written, a file edited, a command that passed). Each act gets an equal share of the leaf's points. Aim for acts of 5% or less.
- Leaf start. When you start a leaf worth more than 5%, emit
⏳ <id> <name> · <n> acts. It tells the user what is in progress right now and commits you to the act count the ticks are computed from. If the count changes, restate it. - Tick lines. A tick's percent lies between two script anchors: previous anchor + (this leaf's span × acts done / acts in the leaf). Write the tick as soon as the act completes, before your next tool call; ticks saved for later are the main way cadence is lost. Every time an act completes and progress has advanced since the last report, emit
<percent>% - <act, 10 words max>. Show the real computed percent (4%, 13%), not a rounded-to-5 label. Consecutive reports must never be more than 5 points apart, with one exception below. - Leaf lines. When a leaf completes, emit
[33% 4/12] ✅ <leaf id> ...with its file changes. Only leaves get these lines: a parent task never gets a line of its own, and there are no "partial" leaf lines (unfinished work is a tick). Showing points makes the number checkable (3/12 is 25%, not 33%). This line is the report for that moment; do not add a tick for the same act. When the leaf completes its parent, append→ <parent number> ✅(e.g.→ 2 ✅means task 2 is now complete; it is the parent's number, not a count of subtasks). - Start at 0%. Right after the plan, before the first action, emit the start line: planning is over, work has begun.
- Never fabricate. If an act is truly indivisible and worth more than 5% (small plans: a 4-step task moves in 25% steps), report the real jump. Do not invent intermediate ticks or split one action into fake halves; a wrong percentage is worse than a big step.
- Report as things complete, not at the end of the parent task or of the turn. Never per tool call; an act is the unit.
To the user, silence is indistinguishable from stuck. The ticks are the heartbeat; the leaf lines are the record.
[0% 0/12] ⏳ 1. Audit current session usage · 2 acts
4% - found 14 `req.session` refs via grep
[8% 1/12] ✅ 1. Audit current session usage: 14 refs in 6 files
13% - `sign()` and `verify()` written
Keep the user informed while you work
Around 20 seconds of silence is when a user starts wondering whether the session died. You have no clock, and you cannot speak while a tool is running, so handle it at the edges:
- Announce slow commands before you run them. Test suites, builds, installs, migrations, deploys, anything you expect to take more than about 20 seconds: one line first, with a rough duration if you know it.
⏳ running the full test suite (~2 min). Said before, it explains the silence; said after, it is too late. - Say you are still on it. If you have made several tool calls since your last visible line and nothing has completed (you are reading, searching, debugging), write one still-working line:
⏳ 3.2: tracing where the session cookie is set. What you are doing, not a percent: progress moves only when an act completes, and an honest "still reading" beats an invented tick. - Some environments show this notice for you from a hook. If you see one, do not repeat it.
These lines are the one exception to "no narration between reports": they carry information the user cannot get otherwise. Keep them to one line and never stack two in a row.
File changes
Under the task that made them, one line per file: A added, M modified, D deleted (git convention), then the path relative to the repo root. For source code, add the classes/methods/functions touched; "M auth.ts" alone does not tell a reviewer where to look. Write the path bare as path:line; terminals and IDEs make it clickable, and a Markdown link would spend the path twice. Only switch to Markdown links if the user says paths are not clickable in their environment.
[33% 4/12] ✅ 2.2 Refresh and revocation → 2 ✅
- M src/auth/token.service.ts:48 `TokenService`: `refresh()`, `revoke()`
- M src/config/auth.ts:12 `authConfig`
- D src/auth/legacy-session.ts
Non-code files: path plus a few words on what changed.
Checkpoint
The first time progress reaches or passes 50%, re-list top-level tasks with status; expand subtasks only for the task in progress. ✅ done · ⏳ in progress · ⬜ pending · ⚠️ blocked · ⏭️ skipped (state why). Once per process; add one at 75% if the plan has more than 10 tasks.
--- CHECKPOINT 50% 6/12 ---
1. ✅ Audit current session usage
2. ✅ Create token service
3. ⏳ Replace auth middleware
- 3.1 ✅ Token validation middleware
- 3.2 ⏳ Swap it into API routes
- 3.3 ⬜ Swap it into admin routes
4. ⬜ Update tests
5. ⬜ Update documentation
Plan change
Never absorb unplanned work silently. One line per new task with the explicit label, and the recomputed percent and points (it may drop; that is honest). Keep the label on that task wherever it reappears.
PLAN+ 3.4 🟠 Adapter for legacy routes (new task added) 50% 6/12 → 43% 6/14
Blocked / waiting
Raise a blocker when something fails twice or an assumption proves wrong, not after giving up. State cause and next action.
⚠️ BLOCKED 3.2: 4 legacy routes read `req.session` directly. Next: adapter.
✅ UNBLOCKED 3.2: adapter in place.
If you cannot continue without the user, make it the last line of the message so it sits at the bottom of the tab:
⏸️ WAITING: keep cookie sessions on legacy routes, or migrate them too?
Close
Always close, even when stopping early. Same number and title as the opening, tasks done, file counts.
========== ■ #1 **Migrate sessions to JWT** 5/5 ✅ · A3 M5 D1 ==========
Unplanned: 3.4
Stopped early: ========== ■ #1 **Title** 3/5 ⚠️ stopped: <reason> · A2 M1 D0 ========== followed by the remaining task numbers.
Compact form (single-step code change)
========== ▶ #3 **Rename usrCnt to userCount** 🟢 ==========
- M src/utils/stats.ts:14 `computeStats()`
========== ■ #3 ✅ ==========
If it turns out to need more steps, publish a plan and continue in full format under the same number.
Other tools
If the environment has a todo/plan tool, keep using it; it must agree with what you report here.
Full process example with blocker and plan change: references/full-example.md.