A pi extension that provides the /context command and its subcommands for visualizing and analyzing the current session's context usage.
Trimmed down from the original repository to keep only the context visualization and details breakdown views, removing /release, skills, publishing helpers, etc.
Load the extension:
pi -e ./pi-context-usage-refine/index.tsOnce in a session, try these commands:
| Command | Action |
|---|---|
/context |
Show the grid visualization + token summary |
/context details |
Expand detailed view: system prompt, tools, conversation breakdown |
/context web |
Generate a fully offline HTML report and open it in the default browser |
/ctx |
Shortcut for /context details |
/ctxw |
Shortcut for /context web |
Both /context details and /context web run a local probe to capture the live system prompt and runtime state (see the "Probe Mechanism" section below). The probe does no model inference and consumes no model quota.
pi-context-usage-refine/
├── index.ts # Extension entry point, registers /context /ctx /ctxw
├── README.md
├── context/
│ ├── index.ts # Main logic: command routing, completions, orchestration
│ ├── breakdown.ts # Turn analysis, tool breakdown, system prompt quantification
│ ├── grid.ts # 11×8 grid rendering
│ ├── tokens.ts # Token calculations, cache reads, cell allocation, symbols
│ ├── web.ts # Offline HTML generation + cross-platform browser launch
│ ├── in-process-probe.ts # Local probe, no model inference / no network
│ └── terminal-compat.ts # Windows terminal compatibility
└── tests/
├── mock-context.ts # In-memory mock tests
├── context-web.ts # HTML escaping / CSP / offline validation
├── in-process-probe.ts # Integration test: launches real pi process to verify probe
├── platform-launch.ts # Cross-platform browser open command tests
├── terminal-compat.ts # Windows glyph substitution tests
└── fixtures/
├── arm-in-process-probe.ts # Mounts the probe inside a real pi process
└── state-marker.ts # Simulates another extension modifying the system prompt
Outputs an 11×8 grid in the terminal. Each cell represents roughly 1.14% of the total context window, with five symbols for different categories:
| Symbol | Meaning | Color |
|---|---|---|
◍ |
System Prompt | accent |
⚙ |
Tools (parameter schemas) | muted |
● |
Messages (conversation history) | success |
· |
Free (remaining capacity) | dim |
○ |
Buffer (reserved for model output) | warning |
The exact token counts and percentages are printed below the grid.
Expands a full session analysis view in the terminal, split into three sections:
System Prompt
- Full text with terminal pagination support
- Token estimate (character count / 4)
Tools
- Every active tool's name, description, and parameter schema, with individual token counts
- Sorted descending by total tokens so the most context-heavy tools appear first
- Reports the combined system prompt + tools token count, and notes when it doesn't match the provider's cached token count (because the provider includes scaffolding and cached context that extensions can't inspect)
Conversation
- Token estimate and cumulative total for each turn
- Tool-heavy turns highlighted in warning color, plain-text turns in success
- Compaction turns prefixed with
Σ - Each message's role and a truncated preview shown
Generates a fully offline HTML file and opens it in the default browser. No web server, no CDN, no remote resources.
HTML features:
- Content-Security-Policy:
default-src 'none'; withstyle-src 'unsafe-inline'andscript-src 'unsafe-inline'for search highlighting and copy functionality (still no external resources) - System Prompt Search: highlights matching paragraphs as you type
- Copy Button: copies the full system prompt to clipboard
- Context Overview: shows estimated system-prompt, active-tool-schema, conversation, and tool-result token counts
- Collapsible Tools: shows name and token count by default, expand to see the full JSON schema
- Tool Activity: groups calls in the current session branch by tool, with call count plus estimated argument and result tokens
- Conversation Table: displays turn number, time, summary, and token count
- Dark Theme: native dark styles, no external stylesheets
Cross-platform browser launcher:
| Environment | Command |
|---|---|
| macOS | open <path> |
| Windows (native) | cmd.exe /c start "" <path> |
| WSL | Converts to Windows path via wslpath, then calls Windows cmd.exe |
| Linux | xdg-open <path> |
The details and web modes rely on a local probe to capture the current session's system prompt and runtime state. The probe makes no network requests, consumes no model quota, and runs entirely within the current process.
Pi's system prompt isn't a static string — it goes through multiple extensions' before_agent_start hooks after a session starts. The loading order of extensions, the state of other extensions, and the current agent phase all affect the final system prompt. Based on observation, the current pi version's ctx.getSystemPrompt() returns the initial value before hooks are applied, so it can't capture dynamic additions from other extensions via before_agent_start.
The probe runs against the same in-process extension instances that are already loaded, so it can read other extensions' in-memory state and produce a system prompt snapshot consistent with what every other extension sees.
- User triggers
details/web - Wait for the agent to be idle
- Wrap the active provider's
stream/streamSimpleimplementation - Send a probe message via
pi.sendUserMessage()withdeliverAs: "followUp" - When pi assembles the request and calls the active provider, the wrapper fires
- The wrapper does not make a network request — it reads
context.systemPrompt,model.provider, andmodel.iddirectly from the arguments - Passes the captured data to the callback; all non-probe requests delegate unchanged to the original provider
- Returns a fake
AssistantMessage(usage all zero, no model quota consumed,stopReason: "stop") - The
agent_settledevent fires, consuming the captured data and rendering the display
- The probe does create one real user/assistant message pair. Don't worry about it — press ESC twice to branch back in the session tree, or delete the two probe messages from the session history. No lasting impact. It's just a snapshot tool; roll it back when you're done.
- Don't submit messages from other entry points while the probe is running, to avoid a concurrent request being captured instead.
- The probe never switches provider or model, and never makes network calls.
- It captures content injected by other extensions through
before_agent_start, since it uses the same in-process extension instances.
- A pending probe is cleared in the
agent_settledcallback, onsession_shutdown, and immediately on startup failure - The provider wrapper remains for the session, but delegates every non-probe request to the original provider unchanged
- Calling
restore()is idempotent
Estimated as Math.ceil(text.length / 4) — roughly 1 token per 4 characters.
For each tool, name + description + JSON.stringify(parameters) total character count, divided by 4.
Uses the pi SDK's estimateTokens(message) function, which accounts for the mixed JSON structure and content strings.
The web report groups tool calls in the active session branch. It estimates the
call argument payload from the tool name and serialized arguments, and estimates
tool-result tokens with estimateTokens(message). Provider usage is reported
for an entire model request, so it cannot be attributed exactly to an individual
tool.
Finds the last non-aborted, non-errored assistant message and reads usage.cacheRead + usage.cacheWrite to get the provider-side cached token count.
Each category's token count is divided by the total context window, rounded to 88 cells. If a category is non-zero but rounds to 0, it gets 1 cell minimum. The array is then padded or trimmed to exactly 88 cells.
Native Windows terminals have rendering issues with certain Unicode characters (e.g. ╭╮╰╯──│▾▸) — some glyphs don't have a display width of exactly 1, causing artifacts or tearing during differential redraws.
When process.platform === "win32", this extension does two things:
- Glyph substitution: replaces all Unicode decorative glyphs with equivalent ASCII characters (e.g.,
╭→+,◍→S,⚙→T) - Overlay disabled: skips differential overlay redraws and uses exclusive custom view mode, eliminating artifacts entirely
On Linux/macOS, it keeps the native Unicode rendering and overlay mode.
# One-time setup for a standalone clone: install the peer dependencies
npm install
# Basic mock test (no pi process needed)
node --experimental-transform-types ./tests/mock-context.ts
# Web report generation and escaping validation
node --experimental-strip-types ./tests/context-web.ts
# Cross-platform browser launch command tests
node --experimental-strip-types ./tests/platform-launch.ts
# Windows terminal compatibility tests
node --experimental-strip-types ./tests/terminal-compat.ts
# In-process probe integration test (requires pi in PATH)
node --experimental-strip-types ./tests/in-process-probe.tsmock-context.ts: verifiescontextis registered,releaseis not, and token math is consistentcontext-web.ts: verifies HTML escaping (<secret>→<secret>), CSP headers, no remote resources, file write and cleanupin-process-probe.ts: launches a real pi process with a native Codex-API fixture provider pointed at a loopback URL, then verifies the probe captures injected state without reaching that providerplatform-launch.ts: verifiesbuildBrowserOpenCommandreturns the correct command structure for Windows, WSL, and Linuxterminal-compat.ts: verifies Unicode-to-ASCII mapping and overlay toggle for Windows