- TypeScript 99.2%
- JavaScript 0.6%
- Nix 0.2%
|
Some checks failed
CI / Check, test, and validate package (push) Failing after 1m9s
- prefix result status headers with the Agent role - update renderer coverage for the clearer completion wording |
||
|---|---|---|
| .forgejo/workflows | ||
| src | ||
| test | ||
| theme | ||
| .gitignore | ||
| consumer.d.ts | ||
| consumer.js | ||
| devenv.lock | ||
| devenv.nix | ||
| devenv.yaml | ||
| LICENSE | ||
| package.json | ||
| pnpm-lock.yaml | ||
| pnpm-workspace.yaml | ||
| README.md | ||
| tsconfig.json | ||
| vite.config.ts | ||
@hayshin/pi-theme
Claude Code-inspired visual identity for Pi, compatible with Pi 0.84.x. Pi loads this extension's TypeScript directly, so the package intentionally publishes its source rather than a compiled build.
Features
- Six dark, light, ANSI, and daltonized Claude Code-inspired themes
- Status line, spinner, and per-request footer
- Claude Code-style rendering and grouping for Pi's built-in and opted-in custom tools
- Unified and split syntax-highlighted diffs
- Collapsible thinking and
❯prompt pointer
Project-owned screenshots are not available yet.
Install
pi install npm:@hayshin/pi-theme
Temporary run:
pi -e npm:@hayshin/pi-theme
Pi packages execute with the user's full system permissions. Review extensions before installing them.
Settings and shortcuts
/theme: configure included theme, tool grouping, extra detail, and status line TPS; also shows spinner configurationalt+t: expand or hide thinkingctrl+shift+o: toggle extra tool detailalt+o: extra-detail fallback for terminals without Kitty keyboard protocol
State and compatibility
Pi owns the selected theme in ~/.pi/agent/settings.json. Extension preferences live in ~/.pi/agent/pi-theme.json:
{
"groupToolCalls": true,
"extraDetail": false,
"showTps": true
}
When corresponding new keys are absent, the extension reads legacy groupToolCalls and ccToolsExtraDetail values from ~/.pi/settings.json. Legacy files are never modified or deleted.
Resumed sessions (/resume) keep the Claude Code tool styling, but grouping is live-only: restored tools render as standalone themed rows (Read N files groups form only for tools executed in the current session).
Tools replaced by another extension keep their execution behavior and standalone renderer unless that extension opts into pi-theme's display adapter. Opted-in tools receive pi-theme renderers without changing execution, schemas, or prompt metadata.
Custom tool display
Tool-owning extensions can opt into the same renderers without depending on extension load order:
import { decorateToolForDisplay } from '@hayshin/pi-theme/consumer';
const tool = {
name: 'doc_read',
// description, parameters, execute, and optional standalone renderers
};
pi.registerTool(
decorateToolForDisplay(tool, {
kind: 'read',
displayName: 'Read',
pathFields: ['path'],
overrideExistingRenderers: true,
}),
);
Supported kinds are read, edit, search, bash, and generic. Adapters may also provide getSummary, getResultText, or getDiff. If pi-theme loads later, the consumer queues the live tool definition and pi-theme decorates it at session start. If pi-theme is absent, the tool remains unchanged.
Pi 0.84 does not expose live definitions through getAllTools(), so custom tools cannot be safely restyled without this small opt-in from their owning extension.
Known external tools are styled automatically
pi-theme recognizes pi-gpt-search's codex-search, codex-research, and web (deprecated alias) and renders them Claude Code-style without any opt-in. Because Pi's getAllTools() does not expose execute, pi-theme substitutes renderers through a guarded, display-only patch on the host's tool component lookup. Consumer API opt-ins for same-named tools take precedence.
pi-subagents integration (automatic, optional)
When the pi-subagents extension is installed, pi-theme styles its tools, steer messages, and widget rows automatically — no configuration needed. The integration activates only when pi-subagents publishes its display provider marker (Symbol.for('pi-subagents.display.provider.v1'), { version: 1 }) and the tool names are active in the current session; otherwise everything keeps Pi's default display. Tool execution, parameters, descriptions, and prompt metadata are never modified.
- Tools:
subagent→Agent(name)with task/fork/skills summary and launch-pane result,subagent_message→Message(name)with delivered/resumed results,subagents_list→Subagentswith count/names, andmessage_orchestrator→Question(orchestrator)with sent/waiting results. Results keep a concise⎿status line visible even when collapsed; expanding adds structured task/message/session/pane metadata. They stay out of read/search grouping and restyle correctly after/resumevia the live display table. - Steer messages: pi-subagents'
subagent_resultandsubagent_pingwrappers delegate dynamically through the theme API below (pi-theme never registers them directly, so nothing goes stale when provider gating changes). They render as a borderless compact status header (all dispositions, elapsed, and summary preserved) plus a⎿body — collapsed to header plus up to 5 summary lines, full session/pane/launch/context metadata when expanded, with an expand hint only when content is genuinely hidden. - Widget: pi-theme publishes
Symbol.for('pi-theme.subagents.display.api.v1')({ version: 1 }withrenderSubagentResult,renderSubagentPing, andrenderSubagentWidget) at extension initialization and removes it identity-safely on session shutdown, so pi-subagents can delegate its widget rows (Subagents · N runningwith status/mm:ss rows) to the themed renderer.
Development
Requirements and setup
devenv shell
pnpm install
Launch Pi with the local source entry point:
pnpm run dev
Run tests once or in watch mode:
pnpm test
pnpm run test:watch
Vite+ provides formatting, linting, strict TypeScript checking, and Vitest:
pnpm check
pnpm exec vp lint
pnpm run fmt
pnpm run test:coverage
Coverage is written to coverage/. Validate the exact npm package contents without publishing:
pnpm run pack:check
The published package includes the source, all six themes, the consumer API, documentation, and license. Pi core packages remain peer dependencies; third-party runtime packages remain regular dependencies.
Publishing
After updating the version and changelog as appropriate, run the full checks and inspect the dry-run package listing:
pnpm check
pnpm run test:coverage
pnpm run pack:check
pnpm publish
publishConfig.access marks the scoped npm package as public. Do not publish generated coverage, local devenv state, or dependencies.
Security
This extension runs inside Pi with the user's full permissions and patches presentation internals for compatible tool rendering. Review changes before installation. Report security issues privately to the repository maintainer rather than opening a public issue with exploit details.
Attribution and license
Based on original work by Demo-0416, with current-maintainer modifications. Distributed under the MIT license; see LICENSE.