pi-yancy-ui
Claude Code-style folding of Pi's thinking blocks and tool calls.
Package details
Install pi-yancy-ui from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-yancy-ui- Package
pi-yancy-ui- Version
0.1.0- Published
- Oct 13, 2026
- Downloads
- 395/mo · 5/wk
- Author
- yancyz1
- License
- MIT
- Types
- extension
- Size
- 110.1 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"extensions/yancy-ui/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-yancy-ui
English · 中文
Claude Code–style folding for Pi: thinking blocks and tool output collapse to one line each, and expand again with Pi's own keys.
● read src/injector.ts · 42 lines · 0.3s
● bash npm test · exit 0 · 18 lines · 4.2s
✻ Thought for 3.2s
✻ Worked for 12.3s · 3 tools · thought 4.1s
Each finished tool call is a single status line (compact mode, the default).
/yancyui compact switches back to the two-line layout:
● read src/injector.ts
⎿ 42 lines · 0.3s
12 import { createInjector } from "./injector";
13 return createInjector(options);
14
15 export function bootstrap() {
16 return start();
… 37 more lines (ctrl+o to expand)
● bash npm test
⎿ exit 0 · 18 lines · 4.2s
✓ 18 passed
… 17 earlier lines (ctrl+o to expand)
- Assistant text is never folded. Only thinking blocks and tool results are.
- Nothing is hidden permanently. Every folded row expands with Pi's native
ctrl+o/ctrl+tor a click. No new keybindings are introduced. - Tool execution is untouched. Only rendering changes; the model sees the same output it always did.
Contents
- Requirements
- Install
- First run
- Reading the transcript
- Keys
- Commands
- Configuration
- Turning parts off
- Troubleshooting
- Compatibility and platforms
- Uninstall
- Development
Requirements
- A Pi build with the extension API:
registerToolRenderer,registerEntryRenderer,appendEntry, and thetool_execution_*/agent_*events. Every current Pi release has these. - Thinking folding additionally depends on Pi's
hideThinkingBlocksetting (see First run).
Install
Recommended: install from npm
pi install npm:pi-yancy-ui
pi reads the pi.extensions field in package.json, installs the package, and adds
the extension to your settings, so it loads on every start.
pi list # confirm it is registered
pi update npm:pi-yancy-ui # upgrade to the latest release
pi remove npm:pi-yancy-ui # remove it again
From a git ref or a local checkout
The package also installs straight from the repository, which is useful for testing a branch before it is released:
pi install git:github.com/Yancyz1/pi-yancy-ui # latest main
pi install ./pi-yancy-ui # a local checkout
Alternative: symlink into the extensions folder
macOS / Linux:
ln -s "/path/to/pi-yancy-ui/extensions/yancy-ui" ~/.pi/agent/extensions/yancy-ui
Windows (PowerShell):
New-Item -ItemType SymbolicLink `
-Path "$env:USERPROFILE\.pi\agent\extensions\yancy-ui" `
-Target "C:\path\to\pi-yancy-ui\extensions\yancy-ui"
Copying the extensions/yancy-ui folder there works too; a symlink just keeps it in
sync with this repo.
Try it for one session
pi --no-extensions -e /path/to/pi-yancy-ui/extensions/yancy-ui/index.ts
--no-extensions disables other discovered extensions; explicit -e paths still
load. This is the safest first run because it avoids clashing with another folding
extension — see Troubleshooting.
First run
Start Pi and check that the extension is live:
/yancyui statusYou should see something like
fold: enabled=true tools=true compact=true thinking=true summary=true preview=true/5 turn=true hints=true | patch=yes ….Enable thinking folding once:
/yancyui initPi only collapses thinking blocks when its own
hideThinkingBlocksetting is on, and it reads that setting at startup./yancyui initwrites it to~/.pi/agent/settings.jsonand reloads automatically when the session is idle. Without this step, thinking blocks render in full and the extension leaves them alone.Send a prompt that uses a tool. Results start collapsed.
Reading the transcript
Compact tool line (default)
● read src/injector.ts · 42 lines · 0.3s
- The leading
●is a status light: accent while the tool is running (the line reads● bash npm test · running…), green once it succeeded, red when it failed. - After the tool name comes a short digest of the arguments: the basename for
read/write/edit, the first command line forbash, the pattern forgrep, and so on. - The rest is the same tool-specific summary as the classic mode (see the table below). For a failed shell command the first output line is appended as the failure reason.
- While the tool runs and has not produced any output yet, the same line shows
running…in place of the summary. editis the exception: under the status line it shows a diff preview built from the raw diff — changed lines first (-/+in red/green), one context line on each side, capped topreviewLines + 2rows with a… N more diff lineshint. Unlike Pi's own top-down diff render, the budget is never wasted on leading context.writestays a single line.- Pressing
ctrl+o(or clicking the row) expands to Pi's original call row and complete result, exactly like the classic mode.
Tool call row (classic mode)
● read src/injector.ts
● is the pi-yancy-ui marker. Its colour tracks the tool state: accent while the tool is
running, error red when it failed, muted otherwise. The rest of the line is Pi's own
call renderer, unchanged.
Collapsed result row (classic mode)
⎿ 42 lines · 0.3s
12 import { createInjector } from "./injector";
13 return createInjector(options);
… 37 more lines (ctrl+o to expand)
⎿starts the summary line. It is optional (/yancyui summary).42 linesis the summary, tool-specific — see the table below.0.3sis the tool duration. It only appears for tools that took 1 second or longer.- The indented block is the preview: the first
previewLineslines (5 by default).readpreviews carry real line numbers, starting from the requestedoffset. … 37 more lines (ctrl+o to expand)is the hint.bashsays… 17 earlier linesbecause it previews the tail of its output.ctrl+ois rendered from Pi's keybinding table, so a user who rebindsapp.tools.expandsees their own key.
Pressing ctrl+o (or clicking the row) replaces everything below ● with Pi's
original, complete result — same component Pi would have drawn without the extension.
While expanded, the ● marker itself becomes a ▾ triangle in the same status
colours (red failed, accent running, green done), so the toggle state is visible at
a glance.
Per-tool summary reference
| Tool | Summary | Preview |
|---|---|---|
read |
N lines (plus truncated) |
head, with a line-number gutter from offset |
write |
wrote N lines |
none — the call row already shows the content |
edit |
+added -removed |
none — the call row already shows the diff |
bash, powershell |
exit N · M lines |
tail (the interesting end of the output) |
grep |
N matches / no matches |
head |
find |
N files / no files |
head |
ls |
N entries / empty |
head |
| anything else | its first output line | head |
| any failure | the error text, or exit N for shells |
shells keep their preview |
Notes:
readon an image showsimageand no preview.writecounts the lines it was asked to write, not the result text.- Shell failures keep the useful output visible and hide Pi's trailing
Command exited with code Nline, which is already reflected inexit N. no matches/no files/emptyare recognised as empty results, so no misleading preview line is shown.
Thinking row
✻ Thinking… ← the run is still streaming
✻ Thought for 3.2s ← finished, took at least 0.5s
✻ Thought ← finished, shorter than 0.5s, or restored from a session
The label replaces Pi's Thinking... placeholder while the block is hidden. It is
only computed for runs watched live, so a session you resume never claims a duration
it did not measure.
ctrl+t (Pi's app.thinking.toggle) reveals the full thinking Markdown, exactly as
Pi renders it — the extension leaves the expanded view untouched.
Turn summary
✻ Worked for 12.3s · 3 tools · thought 4.1s
Appended after each turn (in the TUI only). Variants:
Stopped after …when you interrupted the turn.Failed after …when the turn ended in an error.· 3 tools (1 failed)when some tool calls failed.· thought 4.1sonly when thinking took at least 0.5s.
ctrl+o expands it into one line per tool:
✻ Worked for 12.3s · 2 tools
✓ read 1.2s
✗ bash 0.8s
A turn with no tool calls and less than half a second of thinking produces no summary. The entry is session data, not context: it is never sent to the model.
Keys
pi-yancy-ui adds no keybindings. It reuses Pi's:
| Key | Action | Pi action name |
|---|---|---|
ctrl+o |
Expand/collapse tool output and the turn summary | app.tools.expand |
ctrl+t |
Show/hide thinking blocks | app.thinking.toggle |
| click | Toggle a tool row or thinking row | — |
Rebind them in Pi's keybindings as usual; the hints follow your binding.
Commands
Everything lives under /yancyui.
| Command | Effect |
|---|---|
/yancyui |
Toggle folding on/off (same as /yancyui toggle) |
/yancyui on · /yancyui off |
Enable / disable everything |
/yancyui tools |
Toggle tool folding |
/yancyui compact |
Toggle single-line tool rows (● tool args · outcome) |
/yancyui diff |
Toggle the edit diff preview under compact edit rows |
/yancyui thinking |
Toggle thinking folding |
/yancyui summary |
Toggle the ⎿ summary row |
/yancyui preview |
Toggle the truncated preview |
/yancyui turn |
Toggle the per-turn ✻ Worked for … summary |
/yancyui hints |
Toggle the (ctrl+o to expand) hint |
/yancyui init |
Write hideThinkingBlock: true to Pi's settings and reload |
/yancyui status |
Show the current settings and patch state |
Examples:
/yancyui off # temporarily stop folding, keep the extension loaded
/yancyui preview # keep summaries, drop the preview block
/yancyui turn # stop the per-turn footer
/yancyui status # what is on right now?
Changes apply immediately to new rows, and already-rendered rows are repainted
for the part you changed. Settings persist to yancy-ui.json (see below) and survive a
restart. Folding on/off via /yancyui is saved too, so use /yancyui init only for the
one-time hideThinkingBlock setup.
Configuration
yancy-ui.json
/yancyui writes here:
| Platform | Path |
|---|---|
| Default | ~/.pi/agent/yancyui.json |
| Custom agent dir | $PI_CODING_AGENT_DIR/yancyui.json |
The path comes from Pi's own getAgentDir(), so it follows your Pi installation
instead of guessing.
Full field reference:
| Field | Type | Default | Meaning |
|---|---|---|---|
enabled |
boolean | true |
Master switch. false restores Pi's stock rendering completely. |
tools |
boolean | true |
Fold tool results into ⎿ summary rows. |
compact |
boolean | true |
Render each collapsed tool as one ● tool args · outcome line instead of call + summary rows. |
editDiff |
boolean | true |
Show the changed-lines diff preview under compact edit rows. |
thinking |
boolean | true |
Replace the hidden thinking label with ✻ …. |
summary |
boolean | true |
Draw the ⎿ summary line. |
preview |
boolean | true |
Draw the truncated preview under the summary. |
previewLines |
number | 5 |
Preview rows, clamped to 0–50. 0 behaves like preview: false. |
turnSummary |
boolean | true |
Append the ✻ Worked for … entry per turn. |
hints |
boolean | true |
Append (ctrl+o to expand) to truncated rows. |
Unknown keys are ignored, and values of the wrong type fall back to the default, so a hand-edited or stale file can never produce a broken state.
Example:
{
"enabled": true,
"tools": true,
"thinking": true,
"summary": true,
"preview": true,
"previewLines": 3,
"turnSummary": true,
"hints": false
}
The file is read once when the extension loads. Edit it while Pi is stopped, or use
/yancyui to change things live.
hideThinkingBlock
Thinking folding needs Pi to keep thinking blocks collapsed. That is Pi's own
setting, stored in ~/.pi/agent/settings.json:
{ "hideThinkingBlock": true }
/yancyui init sets it for you. ctrl+t toggles the same setting and persists it, so
revealing thinking once will turn folding off until you hide it again.
CLI flag
pi --yancyui # start with folding enabled, overriding yancy-ui.json
There is no --no-fold; a boolean flag cannot be negated from the command line (Pi
reports it as an unknown option). Use /yancyui off or edit yancy-ui.json.
Turning parts off
| I want… | Do this |
|---|---|
| No folding at all, extension still loaded | /yancyui off |
| Folding, but no previews | /yancyui preview |
| Summaries only, no preview and no hint | /yancyui preview + /yancyui hints |
| Tools folded, thinking left alone | /yancyui thinking |
| No per-turn footer | /yancyui turn |
| Thinking folded, tools left alone | /yancyui tools |
/yancyui off keeps the extension loaded and responsive to /yancyui, which makes it easy
to compare against Pi's stock rendering. To remove the extension entirely, see
Uninstall.
Troubleshooting
Thinking blocks are not folded / I see Pi's Thinking....
Run /yancyui init (and reload if asked). Pi must have hideThinkingBlock: true, which
it only reads at startup. ctrl+t also flips this setting, so if you revealed
thinking manually, hide it again.
/yancyui status reports patch=no.
The private hook that decorates thinking labels (AssistantMessageComponent.prototype.updateContent)
is no longer reachable in your Pi build. Thinking falls back to Pi's native rendering
and everything else keeps working. Please open an issue with your Pi version.
Nothing changed after I edited yancy-ui.json.
The file is read at load time. Use /yancyui … for live changes, or restart Pi.
Rows look wrong / flip between two layouts.
Another extension is also registering tool renderers. Most commonly
transcript-blocks.ts: it patches the same assistant renderer and installs its own
tool renderer, and the two wrap each other. Run only one of them.
The preview is cut oddly on a narrow terminal.
Previews are truncated to the visible width, and the summary/hint lines are measured
with visibleWidth, so emoji-width cells stay aligned. If a glyph still misaligns,
please report the terminal and width.
/yancyui init says it could not write settings.
The agent directory is not writable. Fix permissions on ~/.pi/agent, or set
PI_CODING_AGENT_DIR to a writable directory.
Compatibility and platforms
Host APIs. Tool folding and the turn summary use only public extension APIs.
Thinking folding is the single private hook: it wraps
AssistantMessageComponent.prototype.updateContent. That name has left Pi's public
entrypoints before, so the extension resolves it through a small compatibility shim
(host.ts) that fails soft. A missing hook disables thinking folding and nothing
else — the session never breaks.
After a Pi update. Tool folding and the turn summary should keep working
unchanged. If the private hook moves, /yancyui status flips to patch=no and thinking
renders natively.
Platforms. Pure Node APIs, no shell commands and no OS-specific code. The config
directory comes from getAgentDir(), so macOS, Linux, and Windows (including a custom
PI_CODING_AGENT_DIR) all resolve correctly.
Other Pi distributions. The extension imports @earendil-works/pi-coding-agent.
A fork that publishes under a different package name would need a package-resolution
shim, and its private component internals may differ.
Implementation details, the compatibility shim, and the benchmark live in docs/ARCHITECTURE.md.
Uninstall
pi remove npm:pi-yancy-ui
If you installed from a git ref or a local path instead, pass that same source:
pi remove git:github.com/Yancyz1/pi-yancy-ui or pi remove ./pi-yancy-ui.
Or delete the symlink/copy from ~/.pi/agent/extensions/, and remove
~/.pi/agent/yancyui.json. To also restore Pi's defaults for thinking, either run
/yancyui and stop using the extension, or set hideThinkingBlock: false in
~/.pi/agent/settings.json.
Development
npm run typecheck # tsc --noEmit
npm test # 99 assertions: folding, thinking, summary, config (exit 1 on failure)
npm run smoke # human-readable render dump (no TUI, no model)
npm run bench # collapsed-render cost vs native
npm run verify:host # host shim under Pi's real virtualModules loader
The assertions are mutation-tested: reverting a fix (the shell exit-code match, the
write line count, the isPartial short-circuit, the settlement guard, …) makes the
suite fail. The benchmark shows collapsed rows staying flat in cost while Pi's native
expanded rendering grows with output size.
License
MIT — see LICENSE.