pi-tbox

List, toggle, group, and focus tools from any Pi extension in one place. Choices persist in chat state, and you can see the context cost of what's active.

Packages

Package details

extension

Install pi-tbox from npm and Pi will load the resources declared by the package manifest.

$ pi install npm:pi-tbox
Package
pi-tbox
Version
0.1.1
Published
Jul 29, 2026
Downloads
282/mo · 282/wk
Author
sofuego
License
AGPL-3.0-or-later
Types
extension
Size
155.3 KB
Dependencies
1 dependency · 3 peers
Pi manifest JSON
{
  "extensions": [
    "./index.ts"
  ],
  "image": "https://raw.githubusercontent.com/coreyryanhanson/pi-tbox/main/assets/tbox-dino.webp"
}

Security note

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

README


The problem

Every Pi extension you install brings tools. Install a browser, a search index, a code lens, a few MCP bridges — and suddenly the model has dozens of tools active at once, each one eating context budget, whether or not you're using it. Pi has no unified way to see or shape that population: each plugin is its own world, and turning tools off means digging into each one individually.

pi-tbox is the one surface that sits across all of them. It lists every tool from every extension, lets you toggle whole toolsets at the level their authors declared them, curate named groups of them, and focus the model down to just the ones a task needs — with the choice persisting across reloads and resume.

What it gives you

A natural progression — each step is the next thing you'd want once you have the one before it:

  1. See them. /tbox list enumerates every tool across every installed extension, grouped by the toolset it belongs to. Tools unclaimed by any toolset are grouped per-source, so a plugin that only registers tools shows up as one focusable unit just like one that declares toolsets.
  2. Toggle them. /tbox +<toolset> on / off flips whole toolsets at the level their author declared them — the natural addressability boundary, not individual tools. /tbox all on|off hits everything at once.
  3. Group them. /tbox group <name> edit opens a keyboard-driven picker to curate a named collection of toolsets, saved globally so it's usable from any directory. Dependency (requires) closures are auto-maintained both directions — a group is always a coherent closed set, so /tbox research on enables exactly what's visible, no hidden cascades.
  4. Focus on a subset. /tbox focus <group> (or focus +<toolset>) restricts the model to Pi's builtins plus that one unit, and the choice persists in chat state — it survives reloads and resume, and survives installing new extensions without drifting. focus off restores defaults.
  5. Glance at the cost. A status-bar slot shows masking and focus state at a glance; /tbox status reports a serialized character count split into a core floor (builtins — immutable overhead) and an extension budget (what you can actually move with /tbox), so the number becomes a decision tool rather than a trivia fact.

Quick start

pi install npm:pi-tbox

Then in any Pi session:

/tbox            # show current state + brief help
/tbox list       # every tool, grouped by toolset
/tbox status     # toolsets, groups, focus, and char-count split

The status slot appears in your bar automatically and updates live as you toggle. Its four states:

Glyph State Meaning
○ tbox pristine all defaults — nothing toggled, nothing masked
● tbox n masked count exclusion mode, n extension tools turned off
● focus:<unit> (n) focus deliberately constrained to one group/toolset; n active extension tools
● focus:∅ focus-empty focus is on but the allowlist left nothing active — broken

Commands

All commands live under the /tbox shortcut. Two addressability rules keep the surface unambiguous: a + prefix means a toolset, a bare name means a group, so +find is always the toolset and find is always the group even if they share a name. Reserved words (status, focus, all, list, group, on, off, edit, remove, chars) are rejected at group creation, so bare /tbox <group> on|off always works.

Command Effect
/tbox current state (slot mirror + brief help)
/tbox list [view] [filter] enumerate tools (see views & filters below)
/tbox chars budget view: toolsets ranked by +chars descending
/tbox <group> on / off enable / disable every toolset in a group
/tbox +<toolset> on / off enable / disable a single toolset directly
/tbox +<toolset> describe the toolset (members, state)
/tbox group <name> edit curate a group in the keyboard-driven picker
/tbox group <name> remove delete the group
/tbox group <name> describe a single group
/tbox group list list every group with its toolsets
/tbox focus <group> / focus +<toolset> enter focus on a group or toolset
/tbox focus off exit focus → restore defaults
/tbox all on / off enable all / disable all non-builtin toolsets
/tbox status full status: toolsets, groups, focus, char-count split

/tbox list views and filters

/tbox list [--flat] [--active|--inactive]
  --flat      one row per tool, no grouping
  --active    show only active tools
  --inactive  show only inactive tools

The default grouped view resolves overlapping toolsets by smallest-toolset-wins: each tool appears once under its most specific containing toolset, no duplication. --active / --inactive let you focus on only the enabled or disabled tools.

/tbox chars — budget view

/tbox chars

Flat, ranked list of toolsets sorted by serialized character count descending (most expensive first). Builtins are excluded — they are the non-togglable floor. Toolsets with no active members (charging +0 chars) are omitted — they're not consuming budget, so there's nothing to save. No flags. Each line reports the toolset's active/inactive split and its +chars cost.

Concepts

Toolsets are the unit extensions declare (or that tbox auto-registers for plugins that only register tools). A toolset is the addressability boundary — tbox toggles whole toolsets, not individual members, because that's the granularity state persists at. Toolsets from any installed extension are visible to tbox automatically.

Groups are your named collections of toolsets, stored in tbox's own config ({ toolsets: string[] } — whole toolsets only). The library never knows what a group is; tbox resolves a group to its toolsets at actuation time. Curating a group in the picker auto-maintains requires closures in both directions, so a group is always a closed set under the dependency graph. Groups are global/user-scoped — defined once, usable from any directory.

Focus is a stronger constraint than toggling: it flips the underlying library into inclusion mode so that only the focused unit's allowlist (plus Pi's builtins) is active, and unknown toolsets default off. That means a focus snapshot survives new-extension installs without re-applying. While focus is active, the actuation commands (all on|off, <group> on|off, +<toolset> on|off) are refused — the slot advertises a known working set, and toggling underneath it would make that promise a lie. Use focus off first.

Drift, honestly. /tbox <group> on|off writes per-toolset state at the moment it runs, so editing a group later doesn't retroactively change past sessions — only the resulting per-toolset state was stored, and you re-adjust with /tbox commands. Focus is the exception: inclusion mode makes it drift-free by design. If you want a choice that holds, use focus; if you want a one-off toggle, use on/off.

What tbox won't touch. Pi's builtin tools are always-on and outside tbox's scope — they're never registered into a toolset, so no group, focus, or all off can reach them. Tools injected by a host embedding Pi via customTools (the sdk source) are likewise out of scope: their presence is controlled by the host, not the extension system, so persisting toggle state for them would be semantically broken. They appear as read-only rows in /tbox list --flat so you can see they exist.

Picker keyboard shortcuts

/tbox group <name> edit requires interactive (tui) mode. All keys are remappable through your user keybindings:

Key Action
/ navigate
Enter toggle the focused row
Ctrl+A enable all (filtered set if search is active)
Ctrl+X clear all (filtered set if search is active)
Ctrl+S save to config
Esc / Ctrl+C cancel (clears search first if a filter is active)

The list is windowed (8 rows) with a fuzzy search input, so it never exceeds the viewport regardless of how many toolsets exist. Inline footer cues report auto-checked dependencies (auto-checked: portal.web (required by selection)) and auto-unchecked dependents as you toggle.

How state persists

tbox is the user-facing layer; the persistence machinery lives in its dependency pi-tool-masking, which owns per-toolset on/off memory, the requires cascade, and the inclusion/exclusion default-resolution mode that makes focus drift-free. tbox operates entirely through that library's events, so it layers on top of any installed extension without disrupting the event flow those extensions already depend on — toggles survive reloads and resume, focus survives new installs, and nothing reaches into extension internals.

Config

Groups are stored as user data in ~/.pi/agent/pi-tbox/groups.json — the groups table directly, no wrapper key. A group defined in one directory is usable from any other. (Per-project actuation defaults — which groups auto-on in a given checkout — are a future concern and would name global groups in .pi/settings.json rather than redeclare them.)

License

AGPL-3.0-or-later.