@odradekk/vera-theme

Vera unified theme package: Obsidian-toned palette plus Kylin-inspired chrome (banner, status line, spinner, thinking cycle).

Packages

Package details

extension

Install @odradekk/vera-theme from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:@odradekk/vera-theme
Package
@odradekk/vera-theme
Version
0.4.0
Published
Jun 12, 2026
Downloads
236/mo · 180/wk
Author
odradekk
License
MIT
Types
extension
Size
279.6 KB
Dependencies
1 dependency · 4 peers
Pi manifest JSON
{
  "extensions": [
    "./src/index.ts"
  ]
}

Security note

Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.

README

vera-theme

Purpose

Unified visual identity package for Vera. Combines the previous vera-ui session chrome (banner, status line, thinking shortcut) with Kylin-inspired design-language elements (braille spinner, vertical-bar separators in the status line, chevron label for collapsed thinking blocks). Pairs with the bundled vera theme JSON (Obsidian palette).

Non-goals

  • Replacing Pi's chat-message renderer; Vera leaves chat messages to the SDK-owned renderer.
  • Web/search/data retrieval tools, compaction, prompt-rule assembly, or any non-presentation concerns.

Registered surface

Commands

  • /thinking — cycle thinking level, or set directly (e.g. /thinking high).
  • /statusline — toggle status line placement; or set directly (/statusline below, /statusline embed).
  • /framebg — show or set frame background fill (off, status, uniform).

Shortcuts

  • Configurable thinking-cycle shortcut from vera-theme.json (default alt+t).
  • Configurable status-line toggle shortcut (default alt+s).
  • Configurable frame-background cycle shortcut (default alt+g).

Hooks / UI integration

  • session_start — loads config; installs banner, status line, working spinner, hidden-thinking label, and KylinEditor when the SDK exposes editor-component replacement.
  • turn_start / turn_end — refreshes status line and git snapshot.
  • tool_execution_start / tool_execution_end — updates editor run-state indicator around tool calls.
  • message_update — switches the editor run-state indicator during thinking spans.
  • model_select — syncs current model and refreshes status line.

Theme

  • agent/themes/vera.json — Obsidian-toned palette tuned for Vera. Set via settings.json ("theme": "vera") or the /theme picker.

Editor chrome

Rounded box around the input area (╭─╮│ │╰─╯). Vera installs KylinEditor opportunistically through ui.setEditorComponent(...); older SDKs without that API silently fall back to Pi's stock editor.

Top edge — run-state indicator

Embedded on the right as a static state chip. Pi's built-in working indicator supplies motion elsewhere. States:

  • idle (no history yet) — nothing rendered
  • idle_done (after first turn) — ✓ done
  • streamingstreaming…
  • thinkingthinking… (color follows thinkingHigh)
  • tool⚙ <toolName>

Driven by Pi events: turn_start, turn_end, tool_execution_start, tool_execution_end, and message_update.thinking_start/end.

Bottom edge

Two appearances, controlled by the status-line mode:

  • below (default) — plain closed border ╰─────╯. The full status line lives in the footer line below the editor.
  • embed — status line rendered into the bottom edge ╰─ project · model · thinking · gauge · tokens ───╯. The footer line is hidden.

Toggle with /statusline or alt+s. When the autocomplete suggestion list is open the chrome stays applied; the stock internal divider between input and suggestions is upgraded to ├─┤ so the box reads as a paneled view. Disable via editorChrome.enabled = false.

Status line fields (preserved from vera-ui, restyled)

  1. Project context (cwd basename + git branch + dirty markers)
  2. Model identity (current model name)
  3. Thinking level (color-coded by level)
  4. Context-window gauge (16-cell bar + percent)
  5. Token stats (input · output · cache · hit-rate)

Outer separators between sections use (Kylin-style); inner separators within a section use ·. Width-adaptive collapse is preserved: when the terminal is narrow, lower-priority sections drop in order tokens → gauge → identity-only.

Hash-anchored edits (Hashline)

Optional override of Pi's built-in read and edit tools, off by default (hashline.enabled). When on, every read line is tagged with a LINE#ID| anchor — ID is a whitespace-insensitive 2-character content hash of that line. The edit tool then references lines by those anchors instead of reproducing text:

  • replacepos, plus optional end for an inclusive range; lines: null or [] deletes.
  • insert_after / insert_beforepos, lines.

Each anchor is re-validated against a fresh read before any write: if a line no longer hashes to its ID, the whole batch is rejected and the model is told to re-read. Edits apply by line index (bottom-up), so identical lines never collide; the actual write, line-ending/BOM handling, and diff are delegated to Pi's native edit. Installed at session_start; the same pair is also installed in subagent sessions (via vera-subagents), keeping anchors consistent across main and delegated agents.

Config

Looked up in this order (first hit wins):

  1. Project: .pi/config/vera-theme.json
  2. Agent: agent/config/vera-theme.json
  3. Built-in defaults

Schema

{
  "banner": { "enabled": true },
  "statusLine": { "enabled": true, "mode": "below", "shortcut": "alt+s" },
  "frameBackground": { "enabled": true, "mode": "off", "shortcut": "alt+g" },
  "spinner": { "enabled": true },
  "editorChrome": { "enabled": true },
  "builtinChrome": { "enabled": true },
  "hashline": { "enabled": false },
  "messageChrome": { "enabled": true },
  "thinkingCycle": {
    "enabled": true,
    "shortcut": "alt+t",
    "default": ["low", "medium", "high", "xhigh"],
    "profiles": {
      "exampleProfile": {
        "match": ["*haiku*", "*flash*"],
        "levels": ["off", "minimal", "low"]
      }
    }
  }
}

builtinChrome.enabled controls Vera's wrappers around Pi built-in tools, installed during session_start when enabled.

hashline.enabled (default off) replaces Pi's built-in read/edit with the hash-anchored pair — see Hash-anchored edits (Hashline).

messageChrome.enabled controls Kylin styling for Pi's compaction-summary and skill-invocation messages. When enabled, both render with the same ┌─ name ──── ✓ ─┐ │ ... │ └──────┘ chrome as Vera's tool frames, with the expanded body rendered through pi-tui's Markdown component so prose reflows on terminal resize. Pi exposes no extension point for these components, so this is delivered via an idempotent prototype patch installed during session_start; disabling reverts to Pi's native [compaction] / [skill] rendering once the agent is restarted.

Loaded through

Loaded through a local path entry in settings.json or by npm install.