Cut token cost, run the agent safely, and drop your MCP servers.
A portable collection of various Pi coding agent extensions. Repository directories and config files use opl-; established Pi-facing commands and tool names stay compatible.
opl-footerfixed usage refresh from agent_settled to after every turn/toolcall
opl-footeradded an OpenRouter API key's used amount, cap, and percentage.
opl-footeradded ChatGPT Codex subs 5-hour/weekly quota segment with reset countdowns and stale-snapshot fallback.
devDependenciesupdated to>=0.87.0, conforming to latest pi releasev0.99.x; TUI and tests updates
opl-webaccessandopl-browserblock private/link-local hosts by default and cloud metadata always (localhost stays available for dev), fetch redirects are re-checked per hop, screenshots refuse to overwrite existing files, andevaluateno longer crashes onundefined.See CHANGELOG for more details.
Current project state also marked 'SAFE' for pi v1.0.0 release
Install a versioned release from npm or GitHub. Both ship identical content; pick one source per machine, because Pi treats the npm and Git entries as separate packages and installing both loads every extension twice.
pi install npm:@openlines/opl-pi-sht@<version>
pi install git:github.com/linellazatin/opl-pi-sht@<version.tag>Omitting the version on the npm source tracks the latest published release; Git refs stay pinned, so move them with
pi install ...@v<new>.
Pi installs the package under ~/.pi/agent/npm/node_modules/@openlines/opl-pi-sht (npm) or ~/.pi/agent/git/github.com/linellazatin/opl-pi-sht (Git) and runs root npm install, so opl-webaccess and opl-browser runtime dependencies are available. Pi packages do not install optional extension config files; copy only the configs you need from that checkout's configs/ to ~/.pi/agent/configs/.
opl-browser also needs Chromium once after package installation:
cd ~/.pi/agent/npm/node_modules/@openlines/opl-pi-sht # or the git checkout path
npx playwright install chromiumpi install has no per-extension flag like ./install.sh --only. After installing the package, narrow it in ~/.pi/agent/settings.json using the object form (filters are globs relative to the package root and layer on top of the package manifest):
{
"packages": [
{
"source": "npm:@openlines/opl-pi-sht@0.1.18",
"extensions": ["extensions/opl-init/index.ts", "extensions/opl-todo/index.ts"]
}
]
}pi config provides the same control interactively: toggle individual extensions from an installed package without editing globs.
chmod +x install.sh
./install.sh # copy all extensions and configs
./install.sh --link # non-destructive symlinks
./install.sh --only opl-init opl-todo
./install.sh --link --only opl-input # installs the complete UI bundle
PI_AGENT_DIR=/path/to/.pi/agent ./install.sh --linkCopy mode overwrites matching destinations. Link mode skips existing destinations. --only/-o accepts one or more extension names; selecting opl-footer, opl-input, or opl-modes installs all three because they share active-mode state. Use ./install.sh --help for flags. The repository uses standard .json only.
| Extension | Summary | Commands, tools, and configuration |
|---|---|---|
opl-init |
Fingerprinted repository-guide generator with out-of-band model refinement. | /init; no config. |
opl-simplebench |
Auditable provider-aware model benchmark with JSON artifacts and metrics. | /simplebench, simplebench; supports Ollama, OpenAI-compatible providers, and Bedrock; optional opl-simplebench.json. |
opl-webaccess |
Search plus readable URL/PDF retrieval with session recovery. | web_search, fetch_content, get_search_content; opl-webaccess.json. |
opl-browser |
Chromium automation via Playwright with structured extraction of rendered pages; single dispatcher tool replacing the chrome-devtools MCP. | browser (action-based); opl-browser.json. |
opl-ctxtrim |
Trims verbosectx_* tool-schema descriptions on outbound provider requests (~67% smaller schema, ~4,700-6,300 tokens/request). Built specifically for the context-mode extension. |
No commands/tools; no config. |
opl-guardian |
Configurable tool and session safety: dangerous-Bash confirmation, protected paths, destructive-session confirmation, and malformed-call filtering. | No commands/tools; opl-guardian.json. |
opl-todo |
Branch-aware task tool, overlay, and task list. | todo, /todos; opl-todo.json. |
opl-questionnaire |
Interactive structured-choice tool. | questionnaire; no config. |
opl-input |
Configurable replacement editor - enhanced pikit chat-input (because pet is life, and configurable). ![]() |
No commands/tools;opl-input.json. |
opl-modes |
Mode, plan, tool-safety, lazy-tool-loading, and active-appearance manager - highly-modified, configrable and enhanced mode-switcher. | /mode, /chat, /plan, /execute, plan_complete, load_tools; opl-modes.json. |
opl-footer |
Configurable multi-row status footer - highly-specialized, and enhanced pikit footer. | /configure-opl; opl-footer.json. |
Install one, some, or all. The value is grouped by outcome below, not by extension, so you can pick what matters to you.
Two extensions shrink the cached prompt prefix that Pi writes once and re-reads on every turn, so the savings compound across a whole conversation:
opl-ctxtrimtrims verbosectx_*tool-schema descriptions on outbound requests. It is built specifically for the context-mode extension: ~67% smaller schemas, roughly 4,700-6,300 tokens saved per request, on every request.opl-modeslazy tools withhold heavy tool schemas (subagent,browser,simplebench, ...) from the resting prefix until the model callsload_tools. In a measured/initsession this removed ~5,000 tokens from the cold cache write (17.6K to 12.6K) and it repeats every session.
Cold prompt-cache write, measured /init session (opl-modes lazy tools + MCP adapter off)
before ██████████████████████████████████ 17,558 tokens
after █████████████████████████ 12,625 tokens (-28%, ~5K every session)
* token numbers grabbed from my personal setup with ~18 extensions
opl-modeschat and plan modes swap the active toolset for read-only lists and gate Bash to safe inspection patterns per shell segment, socat f && node -e '...',cat x & rm -rf /tmp/x, andecho "$(node -e ...)"can no longer ride the first command's allowance. Destructive checks still fire inside otherwise-safe commands (anchored to command position, sodu -shandfind . -name '*.sh'stay allowed;find -delete,find -fprint,git log --output,sort -o,npm audit fix,git clean,sudo, and quote-obfuscatedr"m"/-del"ete"are blocked;env/printenvare not safe-listed). The plan to execute lifecycle keeps exploration and mutation cleanly separated. Add custom modes (like below) for your workflow needs. Execute-mode auto-exit needs pi >= 0.87.0 (theagent_before_settleboundary).
load_toolsactivation is bounded by the current mode, so a read-only mode cannot be tricked into enabling a write-capable tool.opl-guardiancombines configurable safety checks in one extension: it confirms dangerous Bash commands in the terminal or over RPC, blocks configured protected paths for file tools (including symlink targets), and confirms session clear/switch-with-pending-work/fork actions. Without a UI, configured dangerous commands and session actions block by default. It also removes malformed provider tool calls before persistence or replay and records incidents inerr/guardian.jsonl. Protected-path Bash matching is literal best-effort, not shell sandboxing.
opl-initdeterministically crawls and refinesAGENTS.mdwith a single out-of-band model call (never a synthetic user message), writes it, and reloads context so the session runs on the new guide. A current fingerprint means zero model calls; mid-session invocations wait for the agent to settle instead of interrupting it. Needs pi >= 0.86.0.
opl-browsergives full Chromium automation (navigate, snapshot, extract rendered-page markdown, interact, screenshot, console/network capture, evaluate) through a single tool, with handle+preview output for large results — navigation is http(s)-only, blocks private/link-local hosts by default and cloud metadata always (SSRF guard; localhost is allowed for dev), and screenshots must use.png/.jpg, stay in the project directory, and never overwrite an existing file.opl-webaccessadds provider-backed search plus readable URL and PDF extraction, with session recovery of earlier results, an http(s)-only fetch that blocks private/link-local hosts by default and cloud metadata always, re-checks every redirect hop (SSRF guard; localhost is allowed for dev), a 10 MB response cap, and a 30s timeout.opl-simplebenchbenchmarks models on deterministic closed-answer contracts, instruction-following, and tool-call generation so you pick a model on evidence, not vibes.
opl-todotracks branch-aware tasks that persist across a session and reconstruct from history.
opl-questionnaireturns an ambiguous fork into a structured choice instead of a guess-and-redo cycle.

opl-footersurfaces model, cost, token and cache activity, git state, agent status, per-turn timing, optional exact remaining ChatGPT Codex subscription quota and OpenRouter API-key cap usage. Both usage segments refresh during agent runs after assistant responses and tool completions (30-second floor, coalesced trailing refresh). The OpenRouter segment resolves Pi's active key locally and calls only OpenRouter's key endpoint; keys and response bodies are neither persisted nor logged./configure-opledits and reorders its layout interactively.opl-inputis a configurable editor that reflects the active mode's identity, so you always know which mode you are typing into.
opl-browserreplaces the chrome-devtools MCP server. Together these tools let you drop external MCP servers and the idle schema overhead they add to every prompt.
| If you want to... | Install |
|---|---|
| Cut token cost with minimal change | opl-ctxtrim, opl-modes |
| Run the agent safely on real repos | opl-modes (pulls in the opl-input + opl-footer UI bundle), opl-guardian |
| Research and drive the web | opl-webaccess, opl-browser |
| Choose models with data | opl-simplebench |
| The full, coordinated experience | all eleven |
Selecting opl-footer, opl-input, or opl-modes installs all three, because they share active-mode state.
Installing extensions adds tool schemas (name + description + JSON parameters) to the resting prompt prefix, which Pi writes once per session and then re-reads cheaply from cache on warm turns. Commands and UI-only extensions add little to nothing. The figures below are calibrated against one tool measured directly in a real session (load_tools = 139 tokens); treat them as ±15%.
| Extension | Adds to resting prompt | Est. tokens |
|---|---|---|
opl-browser |
browser tool schema |
~575 |
opl-questionnaire |
questionnaire schema + prompt guidelines |
~532 |
opl-webaccess |
web_search, fetch_content, get_search_content |
~394 |
opl-simplebench |
simplebench schema |
~230 |
opl-modes |
plan_complete + load_tools schemas |
~215 |
opl-todo |
todo schema |
~92 |
opl-init |
command only (no tool) | ~0 |
opl-input |
UI only | ~0 |
opl-footer |
UI only | ~0 |
opl-guardian |
none (tool/session safety; no added tool schemas) | ~0 |
opl-ctxtrim |
none (payload transformer) | net negative |
Command descriptions add roughly another ~120 tokens collectively, and only if your build surfaces them in the prompt or help block.
- All tools active (no
lazyTools): ~1,916 tool-schema tokens + ~101 guidelines + ~120 commands = ~2,140 tokens on every cold prompt-cache write. - With the recommended
lazyToolsconfig (withholdsbrowser+simplebench, keepsload_tools): removing browser (554) and simplebench (230) drops the resting overhead to ~1,356 tokens (-37%).
Full install, cold prompt prefix impact
all tools resting ████████████████████████ ~2,140 tokens
with lazyTools ███████████████ ~1,356 tokens (-37%)
+ opl-ctxtrim (context-mode) saves 4,700-6,300 tokens/request
The fixed cost of a full install is small and paid once per session, then cached. Two extensions pay it back many times over: opl-ctxtrim removes 4,700-6,300 tokens per request for context-mode users, and opl-modes lazy loading keeps the resting number at ~1,356 instead of ~2,140 while also withholding the heavy subagent family (~5K tokens) when present. For a full install, the overhead is modest and one-time-per-session; with context-mode or heavy tools in play, the collection is strongly token-positive.
Copy applicable files from configs/ to ~/.pi/agent/configs/. For a Pi package installation, the source directory is ~/.pi/agent/npm/node_modules/@openlines/opl-pi-sht/configs/ (npm) or ~/.pi/agent/git/github.com/linellazatin/opl-pi-sht/configs/ (Git):
opl-footer.json,opl-input.json,opl-modes.json,opl-todo.json,opl-webaccess.json,opl-guardian.jsonopl-browserhas optional configuration (opl-browser.json); all fields default, so it works without any config file.opl-simplebenchhas optionalopl-simplebench.json; copyconfigs/opl-simplebench.json.sampleto configure DDGS/SearXNG research and llama metadata endpoints.opl-guardianhas an optionalopl-guardian.json; copyconfigs/opl-guardian.json.sampleand manually migrate any old permission-gate or protected-path settings. It does not load legacy files. ConfiguredpermissionGate.patternsreplace the defaults, so copied live patterns do not automatically inherit later default-rule updates.opl-initandopl-questionnairehave no external configuration.- Config files must be valid JSON, with no comments or trailing commas beyond deliberate
_commentkeys. opl-modesowns active-mode appearance. Each mode'sappearance.prefix,prefixColor, andborderColorstyleopl-input;appearance.modeColorstylesopl-footer's unified mode label. Renderers retain hardcoded fallbacks.opl-modes.bashPatternsis the shared read-only Bash policy now applied to every mode by default; a mode overrides it with its own validsafePatterns/destructivePatternsarray, an empty array explicitly removes that policy, orunrestrictedBash: truedisables both gates. Malformed per-mode arrays retain the existing policy.opl-modes.lazyToolswithholds heavy tool schemas (e.g.subagent,browser,simplebench) from the resting prefix and enables them on demand viaload_tools, shrinking the per-session prompt-cache write.
See each extension README for commands, behavior, configuration fields, runtime constraints, and architecture.
All extensions use Pi's normal extension discovery. Pi installs opl-webaccess extraction dependencies and Playwright automatically when installed as an npm or Git package. For the checkout installer, install nested runtime dependencies before using those extensions:
cd extensions/opl-webaccess
npm install
cd ../opl-browser
npm install
npx playwright install chromiumA Pi package (npm or Git) still needs the one-time npx playwright install chromium command shown above.
opl-simplebench writes a full JSON benchmark artifact in Pi's current working directory by default. --test-all additionally writes research.md and page.html beside result.json in a result bundle. /simplebench --sequence[=<name>] runs a named templated multi-run protocol (for example a model warm-up curve) defined in the runSequence.sequences block, with per-iteration tags, optional llama-server/llamagputop metrics, and a configurable pause between iterations; block-level llamaMetrics/pauseMs are defaults a profile can override. Copy configs/opl-simplebench.json.sample to ~/.pi/agent/configs/opl-simplebench.json to configure DDGS/SearXNG research, optional llama-server/llamagputop metadata endpoints, and the run sequence. Use /simplebench --no-artifact or simplebench({ no_artifact: true }) when responses must not be written to disk. Provider credentials remain outside tracked configuration; configure them through Pi provider settings, environment variables, or Pi authentication.
npm testRun one extension suite with npm run test:opl-<name> for browser, footer, guardian, init, input, modes, questionnaire, todo, webaccess, simplebench, or ctxtrim. npm run test:pi-host uses Pi 0.87.0's real extension loader to load every entrypoint and assert no loader errors. Every helper, functional, and selected-entrypoint smoke check uses Bun's named-test reporter; output includes per-test status, timings, and pass/fail totals. Functional tests cover deterministic helpers where practical; smoke tests bundle entrypoints and parse config. They do not test live TUI behavior, provider credentials, network access, or PDF extraction.
