npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@async23/pi-tool-control

v0.1.0

Published

Control the Tools exposed to Pi's LLM per session branch

Readme

@async23/pi-tool-control

A Pi extension for inspecting and controlling the Tools exposed to the LLM, with an independent selection for every Session Branch.

Install

pi install npm:@async23/pi-tool-control

Restart Pi after installation, or run /reload in an existing session.

Local development

Run it directly from this repository:

pi --no-extensions -e ./packages/tool-control

Then open:

/tools

Remove any other extension that registers /tools before installing this package persistently.

Selection model

When the current Session Branch has no saved selection, tool-control preserves the active selection supplied by Pi at Extension startup. It captures the corresponding inactive Tool Names once for the Extension runtime, so visiting another branch cannot replace that baseline with the previous branch's state.

Once a branch has a saved selection, tool-control persists only the names of Tools explicitly made inactive:

  • the inactive set belongs to the current Session Branch, not to a global config file;
  • a saved empty inactive set explicitly means every registered Tool is active;
  • a fork inherits the set at its fork point and then evolves independently from sibling branches;
  • newly registered Tools are active because their names are absent from the inactive set;
  • inactive Tool Names are retained while their Tools are missing or unavailable, so the preference survives later registration or reconnection;
  • on Session startup and tree navigation, the active selection is restored as registered Tools minus inactive Tool Names.

Selection is applied through Pi's active Tool list; tool-control does not install an execution-time guard. If another Extension changes the active selection after branch restoration, the latest change wins. A Tool excluded by Pi's command-line configuration is not registered and cannot be forced active.

Opening /tools reads Pi's current active Tool list through getActiveTools() and has no selection side effects. Only Ctrl+S applies the staged selection through setActiveTools() and persists it as a custom session entry.

State is stored in versioned Pi custom session entries. Those entries do not participate in LLM context.

Experience

The header shows the after-apply counts and the global Pending count:

Tools 43  ·  ● 34  ·  ○ 9  ·  △ 2

Rows use a fixed-width state column, so every Tool Name remains aligned:

    ●    read
    ○    web_search
    ●→○  write
    ○→●  mcp_search
  • : active now and after apply;
  • : inactive now and after apply;
  • ●→○: pending deactivation;
  • ○→●: pending activation.

The source tabs are ALL, Built-in, MCP, Extension, and SDK. ALL groups Built-in Tools together, MCP Tools under one-level Agent / Server headings, and other Tools by their Registrar. Groups start expanded and folding is kept only for the current panel lifetime.

MCP rows show the original remote primitive name, while their Agent / Server group identifies the source. The Details pane keeps the actual registered Pi Tool Name available to the LLM, together with current/after state, Registrar, Provider, scope, source path, description, Parameters JSON Schema, and Prompt Guidelines.

Keyboard controls:

  • Up/Down or j/k: select rows while Tools is focused, or scroll while Details is focused;
  • Left/Right or h/l: fold/unfold a selected group, or switch focus for a selected Tool;
  • Tab: switch panes in wide layouts;
  • [/]: cycle non-empty source tabs; zero-count tabs remain visible but are skipped;
  • /: filter by displayed or registered Tool Name using a case-insensitive non-contiguous match;
  • Space: stage a selected Tool's opposite state;
  • a / d: stage activation/deactivation for one Tool or every currently visible Tool in a selected group;
  • u: undo the latest single or grouped staging operation;
  • Enter: fold a group or open Details;
  • ?: open the state guide;
  • Ctrl+S: apply and persist every Pending change without closing the panel;
  • Escape: return from narrow Details, clear a kept filter, or close; dirty state requires discard confirmation.

When a Tool Name filter is active, a group heading shows (matching/total) and a/d affects only the matching Tools. Pending changes made under other filters remain staged and Ctrl+S applies them all.

MCP integration

tool-control optionally consumes the versioned MCP Tool Inventory snapshot published on Pi's Event Bus by a compatible @async23/pi-mcp-control. The inventory provides:

  • the Agent and MCP Server behind each Pi Tool Name;
  • whether that Tool is still available from the connected MCP runtime;
  • the remote primitive kind and name.

This is a replace-all metadata contract and contains no MCP configuration, credentials, arguments, or Tool call data. No package is imported across the seam. mcp-control remains responsible for registering and activating its own Tools, so it also works when tool-control is absent.

When a compatible inventory arrives, tool-control starts from pi.getActiveTools() and only removes currently available MCP Tools that the current branch has saved as inactive. It never adds Tools or rebuilds non-MCP state, and it calls pi.setActiveTools() only when there is something to remove. Saved inactive names are retained while an MCP Tool is disconnected or absent from the inventory, so the preference is applied again after reconnection or a later catalog update.

Without compatible metadata, the panel remains usable and groups those Tools as ordinary Extension Tools. It cannot then distinguish a disconnected MCP Tool whose definition is still retained internally by Pi; current mcp-control and tool-control versions should therefore be used together.

Verification

node --test packages/tool-control/tests/*.test.mjs
npm test
npm pack --workspace packages/tool-control --dry-run

License

MIT