@sassywares/pi-extensions
A zesty power pack for pi: auto-titled sessions, real web access, clean handoffs, isolated subagents, and ask/work modes.
Package details
Install @sassywares/pi-extensions from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:@sassywares/pi-extensions- Package
@sassywares/pi-extensions- Version
0.3.20- Published
- Oct 22, 2026
- Downloads
- 512/mo · 512/wk
- Author
- thekayshawn
- License
- MIT
- Types
- extension
- Size
- 129.1 KB
- Dependencies
- 0 dependencies · 3 peers
Pi manifest JSON
{
"extensions": [
"./extensions/auto-title.ts",
"./extensions/web-search.ts",
"./extensions/handoff.ts",
"./extensions/subagent/index.ts",
"./extensions/modes/index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
Sassy Pi Extensions
A zesty power pack for pi — auto-titled sessions, real web access, clean handoffs, and isolated subagents. Install once, ship faster.
Sassy Pi Extensions is the Sassywares pi suite. It names each session from its first real turn, gives the agent web_search and web_fetch tools backed by Exa, carries context into a fresh session with /handoff, and runs bounded work in isolated subagents.
The package is @sassywares/pi-extensions; the repo is sassy-pi-extensions.
Contents
- Why this suite
- Quick start
- Extensions
- Configuration
- Security
- Provenance
- Repository layout
- Development
- Releasing
- Repository maintenance
Why this suite
- Zero config where it matters. Exa runs through its public MCP endpoint; titles use the model you are already talking to;
/handoffuses the current session's model. - Native surfaces. Titles use pi's own session name, so they show up in the session picker, footer, and terminal title. Search, fetch, and subagents are ordinary tools the model can call.
- Safe by default.
web_fetchblocks localhost, private network addresses, and URLs with embedded credentials. Subagents run in isolated pi processes with the tools their agent file allows. - Opt out, not opt in. Auto-titling stops with one environment variable. Manual titles always win.
- Composable with
sassy-skills.sassy-cycle,sassy-debug, andsassy-handoffare built around thesubagentand/handoffextensions. - Small. No background servers. Host-provided dependencies only.
Quick start
From a checkout (recommended — this also installs the agent definitions):
git clone https://github.com/sassywares/sassy-pi-extensions.git
./sassy-pi-extensions/scripts/install-agents.sh
pi install ./sassy-pi-extensions
Or install the package only:
pi install git:github.com/sassywares/sassy-pi-extensions@v0.3.0
Or from npm once published:
pi install npm:@sassywares/pi-extensions@0.3.0
A package-only install loads the extensions, but subagent has no agents until you link or copy some into ~/.pi/agent/agents/. Run scripts/install-agents.sh from a checkout to link the Sassy roster.
Reload pi (/reload) and confirm:
web_searchandweb_fetchare available to the model.- The session gets a title after the first assistant turn, and
/titleis registered. /handoffis registered.- The
subagenttool lists the Sassy agents.
To try the package without changing settings:
pi -e ./sassy-pi-extensions
Extensions
| Extension | Surface | What it does |
|---|---|---|
auto-title |
automatic + /title [text] |
Generates a short session title after the first meaningful turn. /title regenerates it; /title <text> sets one manually. |
web-search |
web_search, web_fetch |
Searches the web via Exa and fetches readable page text with local-address protection. |
handoff |
/handoff <goal> |
Summarizes the session into a continuation prompt and opens a fresh session with it in the editor for you to submit. |
subagent |
subagent tool |
Runs single, parallel, or chained tasks in isolated pi processes and returns compact results. |
modes |
alt+m, /ask, /work |
Ask mode removes the write tools and runs bash under an OS-level read-only sandbox. Work mode is pi as usual. |
Auto-title
Runs after the first assistant turn that contains text. It builds a small transcript from the opening turns, asks the current model for a 2–6 word title, and writes it with pi.setSessionName().
- Tries once per session. Use
/titleto retry after a provider failure. - Never overwrites a title you set manually.
- Does not delay the turn; the title arrives when it is ready.
- 15 second timeout, 32 output tokens, low temperature.
- Titles are truncated to 60 characters.
Web search and fetch
web_search uses Exa's public MCP endpoint by default. Set EXA_API_KEY to use the direct Exa API instead (higher limits and your own quota).
web_fetch:
- Accepts absolute
http(s)URLs only. - Follows up to 5 redirects.
- Blocks localhost, private/link-local addresses, and URLs with embedded credentials.
- Accepts HTML and plain text, capped at 2 MB.
- Screens the final URL after redirects, not just the first one.
- Returns readable text, truncated to 50,000 characters (12,000 by default).
Handoff
/handoff <goal> generates a focused prompt for a new session, lets you edit it, then opens that session with the prompt seeded in the editor.
The extension uses the current session's model and the current conversation only. The new session cannot see the old one.
Subagent
The subagent tool spawns a separate pi process per invocation, so each task gets its own context window. Three modes:
- single —
{ agent, task } - parallel —
{ tasks: [{ agent, task }, …] } - chain —
{ chain: [{ agent, task }, …] }, with{previous}replaced by the prior result
Agent definitions are Markdown files under ~/.pi/agent/agents/ and the nearest project .pi/agents/. Project agents override user agents with the same name.
This repo ships the Sassy roster:
| Agent | Role |
|---|---|
scout |
Grounding scout: writes the shared grounding brief other agents read, including matching prior learnings from the project's .sassywares/config.yaml knowledge paths. |
worker |
General-purpose implementation in an isolated context. |
reviewer |
Quality, correctness, security, project-rule, and design-system review, diff-scoped. |
validator |
Checks that the diff matches the plan, independent of review. |
Link them with ./scripts/install-agents.sh. Edit the frontmatter to change each agent's model, thinking level, or tool allowlist.
Every subagent reads the same grounding brief instead of re-exploring the repo. See GROUNDING.md for its location, freshness check, and wait rule.
Parallel dispatch defaults to two concurrent subagents. A three-worker MiniMax M3.1 Flash batch showed stream stalls and request timeouts under load; DeepSeek Flash was fine with four. Raise the limit with PI_SUBAGENT_CONCURRENCY for a DeepSeek-only dispatch.
A watchdog kills a subagent when it emits no output for two minutes, which catches provider streams that hang after a partial response. Completed runs append one JSON line to ~/.pi/agent/subagent-runs.jsonl with model, thinking level, wall time, model time, tool time, turns, error turns, retries, token usage, cost, and the watchdog outcome. Use it to compare models instead of reconstructing runs from session files.
Modes
Two modes, toggled with alt+m or /ask and /work. Ask mode makes it safe to think out loud; work mode is pi as usual.
Ask mode enforces read-only access on two levels:
- Toolset.
edit,write,codemode,subagent, and any other tool that can change files or run arbitrary code are removed from the model's active toolset, so it never sees them. Atool_callgate blocks them anyway, which also covers nested calls made by tools that stay active. - Sandboxed bash.
read,grep,find,ls,bash,web_search, andweb_fetchstay available, because searching and reading is how the model answers honestly. Every bash command, including!input, is wrapped in an OS-level sandbox that denies filesystem writes:- macOS:
sandbox-execwith adeny file-write*profile. - Linux:
bwrapwith--ro-bind / /.
- macOS:
Writes do not fail quietly and they are not matched by pattern. rm, sed -i, tee, > redirection, git checkout, and a nested bash -c all fail at the OS level with Operation not permitted, while git log, git diff, rg, and network calls keep working. /dev and the temp directory stay writable so ordinary tools behave.
A backend is only trusted after it proves both halves of the contract: reads inside the working directory must succeed and a probe write there must fail. A backend that is installed but cannot enforce (for example bubblewrap on a distribution that blocks unprivileged user namespaces) is discarded, and ask mode continues without bash rather than falling back to a command allowlist. The working directory always wins over the temp allowance: if the project itself lives under the temp directory, temp writes are denied too and /modes reports temp dir is read-only.
/modes shows the verdict. While ask mode is active, the footer is replaced by a compact one that draws the badge on the working-directory/session line — ⏸ ask · ro(sandbox-exec) or ⏸ ask · bash off — instead of taking a row of its own; other extension statuses keep their line. Leaving ask mode restores pi's native footer.
--askstarts a session in ask mode; the mode persists across resume.shift+tabis not used, because pi binds it to the thinking level. To match an editor that uses it for modes, bindapp.thinking.cycleto something else in~/.pi/agent/keybindings.jsonand add a shortcut there.- Ask mode is a guardrail for local changes, not a jail. Network access stays open, so a command can still change remote state if it holds a credential. Use pi's containerized setup when the boundary has to hold against a hostile model.
- Windows is unsupported by design. Ask mode needs an OS-level read-only sandbox that Windows does not offer cheaply, so the extension registers nothing there.
/askand/workdo not exist, and every tool behaves as before.
Configuration
| Variable | Default | Effect |
|---|---|---|
PI_AUTO_TITLE |
unset | Set to 0 to disable automatic titles. /title still works. |
EXA_API_KEY |
unset | Use the direct Exa API instead of the public Exa MCP endpoint. |
PI_AGENTS_DIR |
~/.pi/agent/agents |
Target directory for scripts/install-agents.sh. |
PI_MODES_BASH |
auto |
Set to off to skip backend detection. Ask mode then runs without bash. |
PI_MODES_ASK_TOOLS |
unset | Comma-separated extra tool names to allow in ask mode. |
PI_SUBAGENT_CONCURRENCY |
2 |
Maximum parallel subagent processes. DeepSeek Flash handled 4; MiniMax M3.1 Flash stalled with 3. |
PI_SUBAGENT_IDLE_TIMEOUT_MS |
120000 |
Kill a subagent after this many milliseconds with no stdout/stderr events. Set to 0 to disable. |
PI_SUBAGENT_TELEMETRY |
~/.pi/agent/subagent-runs.jsonl |
Telemetry JSONL path, or 0/off to disable. |
Security
Extensions run inside the pi process with the same OS permissions as pi. Review extension source before installing it.
web_fetchis designed for public web pages, not for reaching services on your machine or local network.auto-titlesends a short transcript of the opening turns to the model already selected for the session. Provider terms and data handling apply./handoffsends the conversation and your goal to the current model to generate the continuation prompt.subagentstarts additional pi processes. Their permissions match the tools allowed by their agent file and the pi process that spawned them.modesask mode denies local filesystem writes through the OS sandbox described above. It does not restrict network access, so a sandboxed command can still change remote state if it can authenticate. Work mode has no restrictions.- No credentials are stored by this package.
EXA_API_KEYis read from the environment at call time.
Provenance
handoff and subagent are derived from pi's MIT-licensed examples and documentation, modified for this workflow. See NOTICE.
Repository layout
sassy-pi-extensions/
├── extensions/
│ ├── auto-title.ts
│ ├── handoff.ts
│ ├── web-search.ts
│ ├── modes/
│ │ ├── backends.ts
│ │ └── index.ts
│ └── subagent/
│ ├── agents.ts
│ └── index.ts
├── agents/
│ └── *.md
├── scripts/
│ └── install-agents.sh
├── .github/workflows/
│ └── publish.yml
├── AGENTS.md
├── CONCEPTS.md
├── LICENSE
├── NOTICE
├── README.md
└── package.json
Development
This repo is the source of truth for the extensions and the Sassy agents. Install it locally so pi loads the working tree directly:
./scripts/install-agents.sh
pi install ~/Documents/Workspace/Sassywares/sassy-pi-extensions
Local installs are read in place — no copy, no build step. After changing an extension, run /reload in pi. Agent edits are picked up on the next subagent invocation.
Do not also keep copies under ~/.pi/agent/extensions/; pi would load both and register duplicate tools and commands.
Test the package for one invocation without touching settings:
pi -e ~/Documents/Workspace/Sassywares/sassy-pi-extensions
Manual checks after a change:
web_searchwith and withoutEXA_API_KEY.web_fetchon a normal page, and onhttp://localhost:3000(must be rejected)./title,/title <text>, and automatic naming withPI_AUTO_TITLEunset.PI_AUTO_TITLE=0starts a session without a generated title./handoff <goal>opens an editable prompt.subagentwith a single agent, and a chain using{previous}.
Releasing
Publishing uses npm trusted publishing (OIDC). There is no long-lived npm token and no NPM_TOKEN secret.
A brand-new package cannot publish its first version through OIDC, because npm's trusted-publisher settings only exist after the package exists. Bootstrap once:
npm login, thennpm publish --access publicfrom a clean checkout.- On npmjs.com, open the package → Settings → Trusted publishing → GitHub Actions and set:
- organization:
sassywares - repository:
sassy-pi-extensions - workflow filename:
publish.yml - environment: blank
- allowed actions: enable npm publish (do not leave it stage-only)
- organization:
- Bump
versioninpackage.json, commit, then tag and push. The workflow publishes with OIDC and provenance.
git tag -a v0.3.1 -m v0.3.1
git push origin v0.3.1
The workflow skips publishing if the tag's version is already on npm. A new trusted publisher must complete its first OIDC publish within 2 days of configuration, or npm expires it.
Repository maintenance
- Commit changes under
extensions/andagents/, and updateREADME.mdwhen behavior or configuration changes. - Tag releases (
v0.3.0,v0.3.1, …) so installs can pin a ref. See Releasing. - Bump
versioninpackage.jsonto match the tag before pushing it. AGENTS.mddocuments the workflow for agents working on this repo.CONCEPTS.mdholds the vocabulary.