Repository navigation
chore: release 0.5.0 - #223
Conversation
AGENTS.md and the commit policy named release/0.3.0. A bugfix/<name> cut from a release/<semver> now merges back into that same branch, and its merge commit is pre-approved for every release.
A Sidebar plugin can set its own `cap`; Todo sets 8 so a typical plan shows whole, and every other list section keeps the shared 4. An empty list draws a bare `Todo:` title and one muted `no tasks yet` row instead of `0/0`. Update the live checks, MEMORY.md and the all-expanded render (`◐` glyph, Todo uncapped). Refs: #215
While the Sidebar is docked with Todo on, the TaskCreate and TaskUpdate
hooks answer main-loop calls from ctui's own `$.tool.call` with
`{ result }` alone, so Claude Code's list stays closed. `dockColumns`
resets to 0 whenever the Sidebar isn't drawn docked.
Refs: #217
…der Task tools For reference only, not for merge. On 2.1.292 with Opus 5.5 the tools reached the prompt, but Claude made no task list in 0 of 18 live runs. Refs: #216
With Task tools on, a pure prompt.compose hook appends the ctui:todo section when the request offers TaskCreate or TodoWrite. With the pin, Opus 5.5 keeps a list for multi-step work and none for one-step work. The setting's description, the README, MEMORY.md and the live checks say what this costs and that a change fully reaches Claude from the next /clear, since Claude Code keeps a conversation's first prompt. Refs: #216
Bump plugin.json and ctui/package.json to 0.5.0 and add the tested-versions row: ctui 0.5.0 with Claude Code 2.1.292. Refs: #214
The task in progress draws a ⠴⠦⠖⠲ spinner, one frame every 100 ms in warning, through a new spinner.tsx Client that turns on its surface's own frame clock, so the Sidebar doesn't redraw. Waiting tasks draw ⠶ in faint. Sidebar plugins get the terminal/desktop table (SidebarUi), so a view draws a Client without a cast; tests draw views through clientsAsTrees, which gains a spinner.tsx stub. MEMORY.md, docs/configuration.md, the live checks and the design render follow the new glyphs. Refs: #222
Done tasks draw , waiting tasks , and the task in progress a circle filling up through … at 100 ms, all Nerd Font Material icons that fill more of their cell than ✓, ⠶ and the braille spinner. Roles stay as they were. Like the git header, there is no fallback without a Nerd Font. MEMORY.md, docs/configuration.md, the live checks and the design render follow the new glyphs. Refs: #225
fix: draw the Todo icons with Nerd Font Material circles
Color readers that reset per line report painted rows as unpainted wherever a row opens in the color the row above ended with. Refs: #233
docs: record that capture-pane -e carries SGR across lines
A live session per small ticket costs too many tokens. Fix and diagnosis tickets now work from code, vendored types and tests, and only a release's pull request runs the live checklist. Refs: #228
The engine keeps the ring's index through the redraw and the re-open Esc makes, and autoFocus doesn't move it, so the bold label and the ring split. Focus the row just left after the re-open. Refs: #238
The ring keeps the Themes row's index into the Themes screen, where index 1 is inherit, and the filter's autoFocus doesn't move it, so typed keys went to the prompt. Focus the filter after the pick. Refs: #239
From 2.1.292 a background agent reads waiting in the agent list while it waits on its own background shell, then running again. The poll read every word but running as an end, so the row turned ✗, dropped 8 s later, and left its shell at the top level. End a held agent only on completed, failed or killed; any other word is live. Refs: #246
chore: write the live-check skill's scenarios, checks and report
Slice 3 of docs/spec/live-checks.md. docs/testing/live-checks.md loses its 133 rows and keeps the operator's half: how to run the live-check skill, how to read the report it writes, and ctui's promise that the cold-cache cost row arrives within 2 s. CONTEXT.md defines a live check as one an agent drives through the pty harness. MEMORY.md's "Tests cover real usage" carries the three mechanisms, the placement rule, the three conversion rules and the 2-minute ceiling on node scripts/check.ts, and points at CONTRIBUTING.md for the procedure rather than restating it. CONTRIBUTING.md gains the ceiling pointer, the rewritten Live checks paragraph, an Evals paragraph with the suite's one command, and a Reports paragraph saying which pull request attaches which report. The pull request template swaps its seven section checkboxes for one Reports block taking a whole report or N/A. Refs: #282
Slice 5 converted six rows, not seven: the `resets in` countdown is already asserted in full in usage.test.tsx, which advances mock.clock 30 s and then 60 s, so it moves to that slice's not-converted list with its reason. Scenario 6 is not the only scenario that spends model turns — the rule-gutter and ctrl+o checks, the fresh-110 docking check and the main-screen toast check each need one too, about five a run — so the spec keeps scenario 6's two explicit turns and the no-skip rule and leaves the count to the report's version block. Scenario 7 drives the harness's `once` rather than a fifo session, because its arrival check is timed from the session's own start and a first `send` would add its own latency. And themes/omarchy-mix copies the operator's own ~/.claude/themes/omarchy.json into the scenario's config dir and picks custom:omarchy instead of running `omarchy theme set`, which HARNESS.md forbids. Refs: #266
docs: cut the live checks to an operator page
The five converted tests cited rows of docs/testing/live-checks.md by line number, and this release deleted those rows. Each comment now names the live check that covers the behaviour (todo/spinner-focused, docking/width-42-at-150 and its 170-column twin), or the sibling test it builds on by its title, or says that no live check reaches it. The engine's one-step swap of the session id and the live cost is cited where it lives, in MEMORY.md's engine-pinned expectations. docs/spec/live-checks.md loses the same numbering: the check-id table drops its Row column, and slice 5's table and its not-converted list name each row by its subject. Refs: #266
The harness needs @types/node and allowImportingTsExtensions; ctui does not. Adding both to the root project put Node globals in scope for ctui/hooks, ctui/plugins and ctui/tests, which run in the engine and have no Node. The harness now has its own tsconfig.json carrying them, the root config is back to what it was, and node scripts/check.ts runs tsc over both projects so the port still does not inherit scripts/*.ts's missing type check. ctui's own code type-checks with no Node globals in scope, so nothing there depended on one. MEMORY.md's pin entry and the spec's slice 1 record the two projects. Refs: #266
…alves
fixtures/mcp-server.ts was built and documented, and no scenario started it:
config.ts wrote mcpServers: {}, so layout/no-child-processes could only assert
an absence and the "only MCP servers and short git runs" half of the check was
unobservable. `seed --mcp` now writes the stub into the seeded .claude.json at
local scope, where the engine starts it with no approval, and SKILL.md's
scenario 1 seeds with it. It stays a stub: two named tools, no network.
HARNESS.md also counts five modules, which is what its table lists.
Refs: #266
screen.ts coalesced a row twice, once for dumpbg and once for runs, and built
the `fg=… bg=… b=… u=…` string in two places. Both go through one `attrs(cell)`
and one `rowRuns(term, y, key)`; the step output is unchanged. Its `flag`
helper, which has nothing to do with a command-line flag, is now `bit`.
steps.ts split "on the first separator" by hand four times and `arg.split(' ')`
three times inside `anim`; `splitFirst` does it once.
harness.ts names `once`'s steps file and `serve`'s fifo and output file instead
of a fourth and a fifth argument, and its argv-consuming helpers say so:
`takeFlag` and `takeSwitch`. `--plugin-key` and the repeatable `--env` are gone
with the `LaunchOptions` and `Session` fields behind them: no scenario passed
either, and `setopt` always writes under `ctui@inline`, now a constant in
steps.ts.
Refs: #266
themes/omarchy-mix copied ~/.claude/themes/omarchy.json out of the operator's home, so scenario 4 could not run on a machine without Omarchy and the report's always-complete promise broke there. The theme is now a committed fixture beside the MCP stub, harness/fixtures/theme.json, carrying Everforest's #2d353b background and #d3c6aa foreground so the expected flat colour stays #373e42. Every seeded config dir gets it as themes/fixture.json, which /theme lists as Live Check Fixture and ctui reads as custom:fixture. The check measures ctui's own rule — the background mixed 6% toward the foreground — which a fixture with known values measures better than a file whose contents vary by desktop. Its id keeps its name: the rule exists for Omarchy's template, which writes a theme's background to inverseText. The glass-flat step now rewrites that seeded file rather than an unnamed "/theme file", HARNESS.md's care list forbids reading a theme out of the operator's home as well as running `omarchy theme set`, and the theme-list check says the fixture is not one of the 22 ctui Themes. Nothing else in the skill, the harness or the operator page needs an Omarchy desktop. Refs: #266
02-big allows Write, because the job writes calc.test.ts, and grades `after: Edit`, because tool_order names one tool per side — so a Write-first run scores as if no list were missed. The case file now says so and why it stands: the medium case avoids it by dropping Write, which this job cannot, and restructuring the case would change what the #220 job measures. Refs: #266
…oval MEMORY.md's own rule is to point at CONTRIBUTING.md for the procedure rather than restate it, and the eval entry restated the command, the flags and the 18-session arithmetic verbatim. It now points, and keeps what CONTRIBUTING.md does not carry: the case-file schema facts, the empty sandbox that makes --scaffold necessary, the path-versus-name trap, the --max-cost-usd 0 load check, and why each case keeps its own copy of scaffold.sh. "Sonnet at medium effort" now lives in CONTRIBUTING.md with its reason, and the operator page and SKILL.md point at it. The 20-40 minutes a run takes stays on the operator page, which SKILL.md no longer repeats. The node-pty approval stays in CONTRIBUTING.md's Setup, which HARNESS.md and SKILL.md now point at instead of spelling out the commands again. HARNESS.md's file table also lists the theme fixture and the harness tsconfig, and drops the count that kept going stale. Refs: #266
fix: the live-checks review findings, and no Omarchy machine required
ctui live checks — PARTIAL: 14 PASS, 2 FAIL, 14 NOT RUN (14/30 passed)Scenarios 1, 2, 5 and 6 only, as scoped for this run. Scenarios 3, 4 and 7 were not driven, so their 14 checks are listed as NOT RUN rather than left out. plugin ctui 0.5.0 (27f7afd) Sidebar docking
Sidebar layout and scroll
Render-site rewrites
Toasts
Themes
The /ctui menu
Todo
Cost
Kept config dirsscenario default-150: /tmp/ctui-live-check-default-150-BsvqpS Run notes
|
The eval's guard case failed in the with-plugin arm: on "Fix the bug in add in calc.ts" the section made the model start a task list in 3 of 3 runs, at 12-14 turns against 4 with the plugin off. Its skip clause came last and asked for a list for "2 or more distinct steps", which a one-line fix meets once read, edit and check are counted as steps. The section now denies the list before it asks for one, calls the unit a piece of work rather than a step, and says that reading, searching, editing and checking the same piece are not separate steps. MEMORY.md names the models each earlier result was measured on, and carries this one beside them. Refs: #294
fix: hold the task list back from one-piece work
The first live-check run failed both. Neither was a ctui regression. The frame check demanded the dock's rule in subtle #505050. That cell is the engine's: under inherit it draws with the default foreground on the #262626 dock, and a mod can set neither the glyph nor its colour, which #99 already settled. It joins the engine-pinned expectations as frame-rule-colour, and the check now reads the colour instead of requiring one. The gutter check demanded a last text column of exactly 105. paddingRight 2 is a ceiling, not a target: the run measured 102 for the prompt panel inside its border, 104 for a truncated Bash row and 103 for a reply, none of them spilling. The check now asserts that nothing reaches the rule's neighbour and forces one reply row to the ceiling with an unbroken token, so the reservation can fail if it ever stops being made. CONTRIBUTING gains --trust-plugin, without which the eval stops at the trust prompt, and says the non-zero exit at the default threshold of 1.0 is not the result. Refs: #251
…ions fix: make the frame and gutter checks assert what ctui controls
|
Re-run of scenario 1 only, on the expectations #296 corrected. The other 22 checks were not run. ctui live checks — scenario 1 only: 7 PASS, 1 FAIL, 22 NOT RUN (of 30)plugin ctui 0.5.0 (3fab9b4), package.json carries an uncommitted Sidebar docking
Sidebar layout and scroll
Render-site rewrites
NOT RUN: docking 3 of 6, toasts, themes, menu, todo, cost (22 checks). scenario default-150: /tmp/ctui-live-check-default-150-oB6lPw |
…ter row The scenario-1 re-run passed the corrected frame check and failed the gutter one on both halves of its expectation. The ceiling was off by one in the same direction twice. With the rule at 107 the text region is columns 0-106, and paddingRight 2 takes 105 and 106, so the last text column is 104 - which is what MEMORY.md's gutter entry has recorded since #102. The run measured the forced 200-character token wrapping at 104 with 105 and 106 blank, the prompt panel at 102 and the Bash row at 104: the reservation held and the check asked for the wrong number. The arithmetic now sits in that entry beside the measurement. The check also asked for the column a gutter row reaches, which the docked view never draws: the engine summarises a result inline there, and those rows exist only in the ctrl+o transcript, where the Sidebar is hidden and rewrites/ctrl-o-transcript already reads them. The control is now the prompt box's own border rule, a row ctui does not pad. The frame check's #505050 is explained too: it belongs to the separator inside the footer's own text, not to the frame rule. Refs: #251
fix: the gutter ceiling is column 104, and the docked view has no gutter row
tool_order names one tool per side, and the big case named Edit while granting Write. On 2026-10-13 all six runs of both arms rewrote calc.ts whole with Write, so Edit was never called and the grader failed on its own naming: 0.00 against 0.00, where the captured traces show TaskCreate before the first Write in all three with-plugin runs and no TaskCreate at all without. Graded against Write, that is 1.00 against 0.00 - the case has been under-reporting the nudge since it was written, and the 0.33 it scored before was one run happening to reach for Edit. The grader now names Write, the write this job cannot avoid because it must create calc.test.ts. The remaining gap is narrower and runs the other way: a run that edited calc.ts before starting its list and only then wrote the test file would still pass. MEMORY.md carries the rule for choosing the after tool, and the re-run's numbers. Refs: #251
fix: grade the big eval case against the write it cannot avoid
The live-check harness loads node-pty's native binding, and the manual `npm install-scripts approve node-pty` wrote this `allowScripts` entry per checkout. Committing the entry builds the binding everywhere `npm ci` runs, CI included, so the three places that told an operator to approve it by hand have no step left to name.
build: install node-pty's binding from npm ci
ctui evals — the task-list nudge18 sessions, 2 arms × 3 cases × 3 runs, no judge turn. plugin ctui 0.5.0, suite as merged at b13c1f7 (before #298 renamed the big case's grader)
medium — the job that hides its steps and asks for brevity. Every with-plugin run opened a task list before touching the file ( big — the grader failed on its own naming, not on what the arms did: it asked for one-line — the over-trigger guard, and the one number this release moved. Before #295 the with-plugin arm made 3 task lists for a one-line fix and took 12–14 turns against 4. After the reword it is 1.00 in both arms at 4 turns each: no list, no cost. The command exits non-zero at the default threshold of 1.0 because the big case scored 0 as graded. That exit is not the result; the per-case deltas above are. Known gaps on the record: the re-graded big case would still pass if a run edited |
|
Amendment to the scenario-1 re-run above, no new boot. The one FAIL in that run was #297 corrected both in the check. That row reads PASS on the evidence already gathered, so the scenario-1 heading is: ctui live checks — scenario 1 only: 8 PASS, 0 FAIL, 22 NOT RUN (of 30)The 22 NOT RUN stand: scenarios 3, 4 and 7 were never driven this release, so all ten |
What changed
ctui 0.5.0, from the map "Map: ctui 0.5.0 Todo list" (#205) and its spec (#214). It follows the release bullets of MEMORY.md "Publish to Anthropic's plugin directory and to npm".
Task toolson, TaskCreate, TaskUpdate and TodoWrite stay in Claude's prompt (not deferred), and a short system-prompt section tells Claude to keep a task list for work of 2 or more steps. A toggle fully reaches Claude from the next/clearor new session (Keep the task tools and a task-list instruction in Claude's prompt under Task tools #216, feat: keep the task tools and a task-list instruction in Claude's prompt under Task tools #221).Todo:title andno tasks yet(Todo section: 8-row cap and empty-list row #215, feat: cap Todo at 8 rows and showno tasks yetfor an empty list #218). The task in progress gets a spinner and waiting tasks⠶; that fix lands through a bugfix pull request into this branch (Animate the Todo task in progress with a spinner #222).plugin.jsonandctui/package.jsonmove from 0.4.0 to 0.5.0, andctui/COMPATIBILITY.mdgets0.5.0 | 2.1.292.After merging, tag the merge commit
v0.5.0.Closes #205
Closes #214
Reports
Both reports ride on this pull request, pasted whole in the comments:
themes/checks and bothcost/checks are unmeasured for 0.5.0, and Run 0.5.0's full live-check pass #251 stays open for the full pass.claude-haiku-5-5, $4.17. medium +1.00, big +1.00 once re-graded against the write the job cannot avoid (fix: grade the big eval case against the write it cannot avoid #298), one-line 0.00 by design — the over-trigger the first run found is fixed (The task-list nudge over-triggers on one-piece work #294/fix: hold the task list back from one-piece work #295) and the guard now reads 1.00 in both arms at 4 turns each.Both ran against the pin, 2.1.292.
Appendix: the 2026-10-12 manual run, superseded
The run that produced this release's fix list, before the live checks became an agent-driven skill. It covered three of the old document's sections at
de576d7: Sidebar docking 7/7; Sidebar layout and scroll 55 pass, 4 fail, 14 not run; the/ctuimenu 19 pass, 7 fail. Its eleven failures each became a diagnosis and a fix under #228, and all of them are closed (#229–#246): the menu ring's index, the Themes filter's focus, the Monthly cost cursor, the engine-drawn markers' decision, the user-prompt background under Catppuccin Latte, the/clearlag, teammate and Workflow rows, and the background agent's row ending while it waited on its own shell.The numbers above are kept for the record only. The agent-driven reports in the comments are this release's result.