No description
  • TypeScript 99.2%
  • JavaScript 0.6%
  • Nix 0.2%
Find a file
hayshin b0f495c55e
Some checks failed
CI / Check, test, and validate package (push) Failing after 1m9s
fix(subagents): label completed agents explicitly
- prefix result status headers with the Agent role
- update renderer coverage for the clearer completion wording
2026-09-21 15:02:14 +05:00
.forgejo/workflows chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00
src fix(subagents): label completed agents explicitly 2026-09-21 15:02:14 +05:00
test fix(subagents): label completed agents explicitly 2026-09-21 15:02:14 +05:00
theme fix(theme): 全量逐键审计——修正两个 ANSI 主题的 7 处色值偏差 2026-08-19 16:21:38 +08:00
.gitignore chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00
consumer.d.ts chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00
consumer.js chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00
devenv.lock chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00
devenv.nix chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00
devenv.yaml chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00
LICENSE docs(license): attribute upstream better-claude-code-ui source 2026-09-11 12:43:46 +05:00
package.json chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00
pnpm-lock.yaml chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00
pnpm-workspace.yaml chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00
README.md feat(subagents): add custom subagent design 2026-09-21 14:58:00 +05:00
tsconfig.json chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00
vite.config.ts chore(tooling): adopt extension template 2026-09-10 19:04:33 +05:00

@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 configuration
  • alt+t: expand or hide thinking
  • ctrl+shift+o: toggle extra tool detail
  • alt+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: subagentAgent(name) with task/fork/skills summary and launch-pane result, subagent_messageMessage(name) with delivered/resumed results, subagents_listSubagents with count/names, and message_orchestratorQuestion(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 /resume via the live display table.
  • Steer messages: pi-subagents' subagent_result and subagent_ping wrappers 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 } with renderSubagentResult, renderSubagentPing, and renderSubagentWidget) at extension initialization and removes it identity-safely on session shutdown, so pi-subagents can delegate its widget rows (Subagents · N running with status/mm:ss rows) to the themed renderer.

Development

Requirements and setup

  • Nix with flakes enabled
  • devenv
  • Pi for interactive testing
  • pnpm (pinned by the packageManager field)
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.