Catalog npm
PACKAGE EXPLORERView in registry

@0xkahi/pi-qol

npm

quality of life pi extensions

pi-extensionpi-package
Versions collected22
Direct dependencies11From release 1.4.0
Last observed21 Oct, 09:00 UTC

README

Current package documentation

pi-qol

Quality-of-life extensions for pi.

A small collection of opt-in extensions that smooth out everyday pi usage. Today it ships auto_session_name — automatic, opencode-style session titling, model_select — an interactive model picker, and custom_footer — a compact configurable interactive footer.

Installation

Install the package from npm:

pi install npm:@0xkahi/pi-qol

Then register it in your pi configuration so pi loads ./src/index.ts as an extension (see the pi.extensions field in package.json).

Features

auto_session_name

Automatically generates a short, human-readable title for a brand-new session from its first user prompt or whitelisted custom message, using a cheap model call that runs in the background and never blocks your turn (Pi >=1.2).

  • Non-blocking — titles are generated asynchronously while the agent responds.
  • Fires once, early — only until the session branch contains a user message or whitelisted custom message with text (image-only/blank messages don't count).
  • Custom triggers — opt in to custom message types with custom_message_whitelist; only messages sent with triggerTurn: true can trigger naming. The default empty list allows only user prompts.
  • Smart guards — skips sessions that already have a name, forked/child sessions, and empty prompts.
  • Model-flexible — use a configured cheap model, or fall back to the active session model automatically.
  • Safe output — strips <think> blocks, unwraps quotes, and truncates titles to 100 characters.

model_select

Adds /select-model, an interactive model picker with fuzzy search, permanent Favourites, ordered custom group tabs, provider filtering, and inline or overlay layouts.

  • quick access to listed favourite models and user-defined favourite subsets
  • shared filtering across Favourites, group, and Search tabs
  • bidirectional tab navigation with Tab and Shift+Tab
  • provider filtering for Search without removing models from favourite tabs
  • sections: opens on Select Model; Ctrl+L switches to the next section and Ctrl+H to the previous (both wrap). Ctrl+H needs a terminal that reports it distinctly (Kitty, CSI-u, or modifyOtherKeys); otherwise it acts as Backspace. Ctrl+L works everywhere. Tab/Shift+Tab stay within the active section.
  • Usage: [Claude] [Codex] [OC-GO] tabs show every subscription rate window, separated by blank lines, with a progress bar, used percentage, reset time, pace, and data freshness. Fixed provider colors match the custom footer. Missing credentials and request failures are shown explicitly. Usage shares the footer cache and fetches only when visited; press r to refresh the active provider. Navigate rows with j/k, arrows, gg/G; q or Esc closes without changing the model. In Select Model, q still types in the filter.

allow keybindings with pi-vim-keys with eventId of pi.vimKeys.event:pi-qol.model_select

Replaces pi's built-in interactive footer with the same three-line layout, but shows the current directory as an icon plus basename, supports hex color overrides, can hide token/cache clusters, and adds a subscription-usage progress bar for supported providers (Anthropic, OpenAI Codex, and OpenCode Go via model provider opencode-go, not OpenCode Zen opencode). Usage colors are fixed: Claude #D97706, Codex #10B981, and OC-GO #00ADD8; former usage-color overrides are ignored. OpenCode Go shows 5h, Week, and Month windows and requires an opencode-go entry of type api_key in ~/.pi/agent/auth.json, with the secret in key; OPENCODE_API_KEY alone is not used. Claude and Codex require OAuth entries.

  • Directory line — optional inverse-styled agent badge followed by the directory icon + basename, with optional git branch and session name. The badge is disabled by default.
  • Stats line — cumulative input/output tokens, cache read/write/hit cluster, session cost (or (sub) when on a subscription), context-window usage, and the right-aligned model name (with provider prefix when multiple providers are available).
  • Subscription usage — a colored progress bar plus percentage and reset time for the active subscription provider. Usage is fetched lazily and cached, refreshing at most once every 60 seconds per provider; auth/network failures simply hide the segment.

Known difference from pi's built-in footer: the (auto) compaction suffix is omitted because extensions do not expose reliable live state for it.

Configuration

pi-qol reads a JSON config file named config.json from two locations and merges them (project overrides global):

ScopePath
Global<agent-dir>/extensions/pi-qol/config.json
Project<cwd>/.pi/extensions/pi-qol/config.json (trusted projects only)

Project config is only loaded when the project is trusted.

Example

{
  "$schema": "https://raw.githubusercontent.com/0xKahi/pi-qol/main/assets/config.schema.json",
  "auto_session_name": {
    "enabled": true,
    "custom_message_whitelist": [],
    "model": {
      "provider": "opencode",
      "modelId": "gpt-5-nano",
      "reasoning": "low"
    }
  },
  "model_select": {
    "enabled": true,
    "layout": "overlay",
    "favourite_label": "Pinned",
    "provider_filter": ["anthropic", "openai"],
    "groups": ["work", "fast"],
    "favourite": [
      {
        "provider": "anthropic",
        "modelId": "claude-sonnet-4-5",
        "groups": ["work", "fast"]
      }
    ],
    "hide_tabs": { "groups": false, "search": false }
  },
  "context_view": {
    "enabled": true,
    "layout": "inline"
  },
  "custom_footer": {
    "enabled": true,
    "colors": {
      "directory": "#A78BFA",
      "modelName": "#60A5FA",
      "agentName": "#FBBF24"
    },
    "display": {
      "tokens": true,
      "cache": true,
      "agentName": true
    },
    "defaultAgentName": "DEFAULT"
  }
}

Options

auto_session_name

KeyTypeDefaultDescription
enabledbooleanfalseTurn the auto session naming feature on.
custom_message_whiteliststring[][]Allowed customType values for pi.sendMessage(..., { triggerTurn: true }) runs. Empty means only user prompts.
modelobject—Optional model used to generate titles. Falls back to the session model if omitted.

model

KeyTypeDescription
providerstringModel provider id (e.g. anthropic, openai).
modelIdstringModel identifier as registered in pi's model registry.
reasoningenumOne of off, minimal, low, medium, high, xhigh.

When model is set but cannot be found or authenticated, pi-qol automatically falls back to the active session model and surfaces a warning notification.

model_select

KeyTypeDefaultDescription
enabledbooleanfalseTurn the model picker on.
layoutenuminlinePicker layout: inline or overlay.
favourite_labelstringFavouritesNon-empty label for the permanent first tab.
provider_filterstring[][]Restrict Search models to these providers; favourite tabs are unaffected.
groupsstring[][]Ordered custom group tabs. Exact duplicate names use their first occurrence.
favouriteobject[][]Favourite models (provider, modelId, optional groups).
favourite[].groupsstring[][]Exact, case-sensitive group memberships for a favourite. Unknown names are ignored.
hide_tabs.groupsbooleanfalseHide all custom group tabs.
hide_tabs.searchbooleanfalseHide the Search tab. Favourites cannot be hidden.

The favourites tab is always first, even when empty, and uses favourite_label as its display label. Unique groups follow in configured order, and Search is last when visible. Use Tab to cycle forward and Shift+Tab to cycle backward through visible tabs. A favourite can belong to multiple groups; group tabs contain only resolved, authenticated favourites and preserve favourite order. Duplicate favourite declarations remain first-entry-wins.

context_view

KeyTypeDefaultDescription
enabledbooleanfalseEnable the Context View capture and interface.
layoutenuminlineContext View presentation: inline or centered overlay.

Context View

Context View is a fork of Dmitry Makarov's pi-context-view, adapted into one unified tabbed interface with Vim-friendly keybindings. Enable it, then run /context-view with no arguments. The Usage tab opens first; Tab and Shift+Tab switch between Usage and Injections. Use j/k or arrows to move, Ctrl+u/Ctrl+d to move by a page, gg/G to jump to the beginning/end, Enter to preview, and Esc or q to return or close. By default it opens inline; set context_view.layout to overlay for a centered overlay. Other extensions can open the same view by emitting pi.vimKeys.event:pi-qol.context_view.

KeyTypeDefaultDescription
enabledbooleanfalseReplace pi's built-in interactive footer.
display.tokensbooleantrueShow cumulative input/output token counts.
display.cachebooleantrueShow the custom cache read/write/hit cluster.
display.agentNamebooleanfalsePrefix the first line with a padded bold inverse agent badge.
defaultAgentNamestringDEFAULTAgent name restored at the start of each session.
colors.directoryhex—Color the directory icon and basename.
colors.modelNamehex—Color the right-aligned model name.
colors.agentNamehex—Agent badge foreground color before inversion.
icons.directorystringnerd fontGlyph shown before the directory basename.
icons.cachestringnerd fontGlyph for the cache cluster.
icons.cacheReadstringnerd fontGlyph for cache-read tokens.
icons.cacheWritestringnerd fontGlyph for cache-write tokens.
icons.refreshstringnerd fontGlyph shown before the subscription reset time.

When enabled, the badge has no brackets, uses bold and inverse styling, and adds one styled padding space on each side of the name. One normal, unstyled space separates the trailing badge padding from the directory. Names are trimmed and sanitized. Names wider than ten terminal columns are rendered as their first ten visible columns plus ...; badge padding does not count toward that limit, and wide Unicode characters are never split. Badge color precedence is a valid event color, colors.agentName, then pi's accent theme color. Event-selected names and colors are session-scoped: every session_start restores defaultAgentName and clears the event color.

Other extensions can update the current identity through pi's event bus:

pi.events.emit('pi.qol.event:set-agent-name', {
  agentName: 'Reviewer',
  color: '#FFFFFF', // optional; must be #RRGGBB
});

Invalid or empty names are ignored. A missing or invalid event color clears any previous event color and uses the normal fallback precedence.

Project config shallow-merges each top-level section over global config. Arrays replace lower-precedence arrays, so project model_select.favourite or model_select.groups replaces the corresponding global array. Nested objects are also replaced as values during that section merge; for example, a project hide_tabs object replaces the global one, then omitted groups or search fields receive their default of false.

How it works

On before_agent_start, the auto_session_name extension checks a series of guards before doing any work. It only proceeds when all of the following hold:

  1. The feature is enabled in config.
  2. The run starts with a non-empty user prompt, or a custom message whose customType is in custom_message_whitelist and whose text is non-empty (image blocks are ignored).
  3. The session does not already have a name and is not a fork/child session.
  4. The branch has no prior user messages or whitelisted custom messages with non-whitespace text. Blank or image-only messages are ignored, using the same text rule as step 2, so they never block a later message from naming the session.

Pi >=1.2 emits this event for both user and custom runs, before appending the starting message to the branch. Non-whitelisted custom runs are skipped before session guards and their messages do not block later naming.

If those pass, it resolves a model, generates a title via a dedicated title-generation prompt, cleans the result, and persists it with pi.setSessionName(). The work runs in a cancellable background task that is aborted on session shutdown.

Development

This project uses Bun and Biome.

bun install        # install dependencies
bun run check      # biome fix + type-check
bun test           # run tests
bun run buildSchema # regenerate assets/config.schema.json from the zod schemas

Project structure

src/
  index.ts                       # extension entry — lifecycle wiring only
  config-loader.ts               # loads + merges global/project config
  constants.ts                   # EXTENSION_ID
  schemas/                       # zod config schemas (full + partial)
  utils/                         # path + model-resolution helpers
  extensions/
    auto-session-name/           # the auto_session_name feature
    model-select/                # the model_select feature
    custom-footer/               # the custom_footer feature
scripts/                         # JSON schema generation
assets/config.schema.json        # generated config schema

License

See repository for license details.

Author

0xKahi

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 22

Collected releases
VersionPublishedDirect dependenciesOpen version
1.4.0Registry latest17 Oct 202611
1.3.015 Oct 202611
1.2.01 Oct 202611
1.1.324 Sept 202611
1.1.224 Sept 202611
1.1.121 Sept 202611
1.1.020 Sept 202611
1.0.65 Sept 202612
1.0.529 Aug 202611
1.0.412 Aug 202611
1.0.38 Aug 202611
1.0.24 Aug 202611
1.0.14 Aug 202611
1.0.01 Aug 202611
0.1.129 Jul 202611
0.1.017 Jul 202611
0.0.614 Jul 202611
0.0.57 Jul 202610
0.0.419 Jun 202610
0.0.317 Jun 202610

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
0xkahi/pi-qol

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 21 Oct, 08:58 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:cc9efee52f3e5a6ba84eabe9930f48e16738bb0c414546556d6d17ea895431cd