pikit-styled-outputs
Custom styled outputs for tools, assistant messages, diff viewer, and more.
Package details
Install pikit-styled-outputs from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pikit-styled-outputs- Package
pikit-styled-outputs- Version
1.0.1- Published
- Jul 5, 2026
- Downloads
- not available
- Author
- adrianapan
- License
- MIT
- Types
- extension
- Size
- 91.9 KB
- Dependencies
- 0 dependencies · 2 peers
Pi manifest JSON
{
"extensions": [
"./src/index.ts"
],
"video": "https://raw.githubusercontent.com/adrianapan/pikit/main/agent/extensions/styled-outputs/preview.mp4"
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pikit-styled-outputs — custom styled message rendering for pi.dev
Custom styled rendering for every message type in pi — assistant messages, user messages, thinking blocks, tool executions, skill invocations, and MCP tools. Replaces the default flat output with prefix icons, colour-coded diffs, expandable sections, grouped tool configs, and per-tool-type rendering.
https://github.com/user-attachments/assets/6bcf414f-9114-405e-af9e-392a8f4e8bdc
Install
pi install npm:pikit-styled-outputs
[!TIP] Or grab the entire pikit setup, an opinionated pi.dev configuration that includes this extension.
Features
- Assistant messages — Prefixed lines with configurable icon and colour
- User messages — Prefixed with custom icon; optional theme background toggle
- Thinking blocks — Animated prefix with optional label ("Thinking:"); continuation lines align to prefix width, not the label
- Tool executions — Custom call/result renderers for
read,bash,edit,write,grep,find,ls, web tools, and MCP tools - Diff viewer — Side-by-side-style diff highlighting for
editandwritewith added/removed/context colours; skips oversized files (configurable threshold) - Skill invocations — Expandable skill blocks with prefix icon, title, and content
- Custom messages — Expandable custom messages with prefix icon, type name, and content; all custom messages get styled output regardless of registered renderers
- Tool spinner — Animated character spinner while tools are running
- Bash execution —
!commands styled asCommand,!!commands styled asShell(no context); error prefix swaps to✗ - Group-aware config — Override any general tool setting per group (
base,mcp,web,custom); unset properties fall through togeneral - Theme-aware colours — All colour fields accept pi theme tokens (
"accent","dim", etc.) or hex values ("#ff6347") - Expand/collapse — Tool outputs and skill blocks collapse by default; expand with a keypress
Configuration
Copy the example config and edit it:
cp ~/.pi/agent/extensions/styled-outputs/styled-outputs.example.json \
~/.pi/agent/configs/styled-outputs.json
All fields are optional — omit any field to keep its default.
Assistant message
| Key | Type | Default | Description |
|---|---|---|---|
assistantMessage.prefix |
string |
"●" |
Prefix icon on the first line of content |
assistantMessage.color |
string |
"text" |
Colour for the prefix icon (theme token or hex) |
User message
| Key | Type | Default | Description |
|---|---|---|---|
userMessage.prefix |
string |
"❯" |
Prefix icon on the first line |
userMessage.color |
string |
"accent" |
Colour for the prefix icon |
userMessage.bodyColor |
string |
"text" |
Colour for message body text |
userMessage.isThemeBackgroundVisible |
boolean |
true |
Keep the default theme background behind user messages |
Thinking message
| Key | Type | Default | Description |
|---|---|---|---|
thinkingMessage.prefix |
string |
"✽" |
Prefix icon character |
thinkingMessage.prefixColor |
string |
"accent" |
Colour for the prefix icon |
thinkingMessage.label |
string |
"Thinking:" |
Label text shown after the prefix when isLabelVisible is true |
thinkingMessage.labelColor |
string |
"muted" |
Colour for the label text |
thinkingMessage.isLabelVisible |
boolean |
false |
Show the label on the first line |
thinkingMessage.messageColor |
string |
"dim" |
Colour for thinking content |
Note: When
isLabelVisibleistrue, continuation lines align to the prefix width (e.g.✽), not the full first-line prefix (✽ Thinking:). The label is a one-time header.
Skill invocation
| Key | Type | Default | Description |
|---|---|---|---|
skills.prefix |
string |
"✓" |
Prefix icon |
skills.prefixColor |
string |
"accent" |
Colour for the prefix |
skills.titleColor |
string |
"toolTitle" |
Colour for the skill title |
skills.nameColor |
string |
"dim" |
Colour for the skill name in the title |
skills.labelColor |
string |
"success" |
Colour for status labels (e.g. "DONE") |
skills.expandHintColor |
string |
"dim" |
Colour for the expand/collapse hint |
skills.outputColor |
string |
"dim" |
Colour for expanded content |
Custom message
Styled rendering for all custom messages. Custom messages registered via pi.registerMessageRenderer() are also styled by this extension — the registered renderer is ignored in favor of consistent styled output.
| Key | Type | Default | Description |
|---|---|---|---|
customMessages.prefix |
string |
"✓" |
Prefix icon |
customMessages.prefixColor |
string |
"accent" |
Colour for the prefix |
customMessages.titleColor |
string |
"toolTitle" |
Colour for the "Custom tool" label |
customMessages.nameColor |
string |
"dim" |
Colour for the custom type name |
customMessages.labelColor |
string |
"success" |
Colour for status labels (e.g. "Loaded") |
customMessages.expandHintColor |
string |
"dim" |
Colour for the expand/collapse hint |
customMessages.outputColor |
string |
"dim" |
Colour for expanded content |
Bash execution (! and !! commands)
! and !! commands share the same visual pattern as tool executions:
!commands — labelledCommand(output is included in LLM context)!!commands — labelledShell(output runs in background, excluded from context)
Both use the same header format, status footer, and expandable output. The label word is the only visual difference — no border, no separate $ prefix icon.
| Key | Type | Default | Description |
|---|---|---|---|
bashExecution.titleColor |
string |
"toolTitle" |
Colour for the "Command" / "Shell" label |
Tool execution
| Key | Type | Default | Description |
|---|---|---|---|
tools.toolSpinnerPrefix.prefixChars |
string[] |
["·","✢","✳","✶","✻","✽"] |
Characters cycling in the loading spinner |
tools.toolSpinnerPrefix.color |
string |
"muted" |
Colour for the spinner |
tools.toolSuccess.prefix |
string |
"✓" |
Icon for successful tool runs |
tools.toolSuccess.prefixColor |
string |
"success" |
Colour for the success icon |
tools.toolSuccess.labelColor |
string |
"success" |
Colour for the success label (status line) |
tools.toolError.prefix |
string |
"✗" |
Icon for failed tool runs |
tools.toolError.prefixColor |
string |
"error" |
Colour for the error icon |
tools.toolError.labelColor |
string |
"error" |
Colour for the error label (status line) |
tools.toolBranch.prefix |
string |
"└─" |
Icon before the status line |
tools.toolBranch.color |
string |
"separator" |
Colour for the branch icon |
Tool general settings
These apply to all tool types unless overridden by a group.
| Key | Type | Default | Description |
|---|---|---|---|
tools.general.titleColor |
string |
"toolTitle" |
Colour for tool titles |
tools.general.summaryColor |
string |
"dim" |
Colour for the summary line |
tools.general.countColor |
string |
"muted" |
Colour for counts (e.g. "Tool 1 of 3") |
tools.general.expandHintColor |
string |
"dim" |
Colour for expand/collapse hints |
tools.general.outputColor |
string |
"dim" |
Colour for tool output text |
tools.general.maxExpandedLines |
number |
40 |
Max lines shown when a tool result is expanded |
tools.general.moreColor |
string |
"muted" |
Colour for "more" separator text |
tools.general.moreBgColor |
string |
"separator" |
Background colour for the "more" separator |
tools.general.isThemeBackgroundVisible |
boolean |
false |
Apply theme background behind tool blocks, skill invocations, and custom messages |
tools.general.verticalPadding |
number |
0 |
Vertical padding inside tool content boxes (0 = compact, core default = 1) |
tools.general.horizontalPadding |
number |
3 |
Horizontal padding inside tool content boxes (left+right indent; core default = 1) |
tools.general.diffAddedColor |
string |
"toolDiffAdded" |
Colour for diff added lines |
tools.general.diffRemovedColor |
string |
"toolDiffRemoved" |
Colour for diff removed lines |
tools.general.diffContextColor |
string |
"toolDiffContext" |
Colour for diff context lines |
tools.general.maxDiffFileSize |
string|number |
"1MB" |
Skip diff rendering for files exceeding this size |
Tool groups
Any tools.general key can be overridden per group. Unset properties fall through to general.
| Key | Description |
|---|---|
tools.groups.base |
Built-in tool renderers (read, bash, edit, write, grep, find, ls) |
tools.groups.mcp |
MCP tool renderers |
tools.groups.web |
Web tool renderers (web_search, fetch_content, get_search_content) |
tools.groups.custom |
Any other tool |
Example — give MCP tools a different title colour and expanded line limit:
{
"tools": {
"groups": {
"mcp": {
"titleColor": "#c07898",
"maxExpandedLines": 20
}
}
}
}
Colour values
Every colour field accepts either:
- A pi theme token — e.g.
"accent","dim","muted","success","error","warning","separator","toolTitle","toolDiffAdded","toolDiffRemoved","toolDiffContext" - A hex colour — e.g.
"#ff6347","#c07898"
Theme tokens adapt to your active theme automatically.
How it works
The extension patches pi's built-in message components (AssistantMessage, UserMessage, ToolExecution, SkillInvocationMessage, CustomMessage, BashExecution) at prototype level. A Symbol.for patch flag prevents double-patching on reload.
For BashExecutionComponent, the extension listens to the user_bash event to determine whether a command is ! (Command) or !! (Shell), then patches updateDisplay to strip borders and apply the styled header/status/output format.
Tool renderers are registered via pi.registerTool() for built-in tools (read, bash, edit, write, grep, find, ls) — each with custom call and result renderers. For web tools and MCP tools, the extension patches getCallRenderer / getResultRenderer to provide specialised renderers when no built-in renderer exists.
All rendering uses factory functions + closures (no classes). Derived values like prefix widths and padding are computed from config — change a prefix icon and the alignment adjusts automatically.
Structure
styled-outputs/
├── package.json
├── styled-outputs.example.json
└── src/
├── index.ts # Extension entry point, patching & tool registration
├── config.ts # Defaults + user config loading
├── types.ts # TypeScript interfaces for user config
├── utils.ts # Colour helpers, ANSI utilities, path shortening
└── components/
├── assistant-message.ts # Assistant message renderer
├── thinking-message.ts # Thinking block renderer
├── user-message.ts # User message renderer
├── skill-message.ts # Skill invocation renderer
├── custom-message.ts # Custom message renderer
├── base-renderer.ts # Built-in tool call/result renderers
├── mcp-renderer.ts # MCP tool call/result renderers
├── web-renderer.ts # Web tool call/result renderers
├── markdown-result.ts # Shared markdown result renderer
└── tool-shared.ts # Group config resolution, spinner, branch/indent helpers