Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

pi-extensions

Personal extensions for the pi coding agent. Built from an analysis of my own Claude Code and Codex session history: each one automates something I was demonstrably doing by hand, over and over.

ExtensionOne-linerUse it when
swarmCodex review swarms + parallel worktree fix lanesBefore shipping meaningful changes; when fixing a list of independent issues
probeHeadless-browser screenshots, console errors, failed-request bodiesVerifying UI changes, local-vs-staging parity, debugging 4xx/5xx
jiraJira via REST API token, including card attachment imagesAny card-shaped work: start, review, verify against acceptance criteria
scope-guardBlocks out-of-scope edits and junk commitsAlways on; declare a scope for tightly-bounded tasks
ciPull GitHub Actions failures for the current branchA check fails and you'd otherwise paste the log
devwatchDev servers with captured logs + port managementRunning dev servers the agent should be able to read
shotAttach recent screenshots to a messageQuickly showing the agent what you see

Install

Copy (or run ./install.sh, which does the same) into pi's user extension directory:

cp extensions/*.ts ~/.pi/agent/extensions/

Pi loads them on next start; /reload picks them up in a running session.

Requirements:

  • pi >= 0.82 (the ImageContent shape changed in 0.82 to {type, data, mimeType}; these extensions target the new shape)
  • macOS (uses sips for image downscaling and lsof in devwatch)
  • Codex CLI authenticated (codex on PATH) for swarm
  • GitHub CLI authenticated for ci
  • Chrome, Chromium, Arc, or a Playwright browser cache for probe (it auto-discovers ~/Library/Caches/ms-playwright builds)

No npm installs. Everything runs on Node builtins plus the packages pi already ships (typebox, @earendil-works/pi-ai).


swarm

My own take on pi-subagents + pi-worktree, merged into one pipeline and shaped around a workflow I used to run by hand: fan out independent read-only reviewers over a diff, verify every candidate finding, then fix the confirmed ones in parallel worktrees.

What it does

  • swarm review spawns one read-only codex exec lane per review angle. Eight angle presets: correctness, removed-behavior, cross-file, conventions, efficiency, reuse, simplification, altitude. Each lane reports up to 6 candidates in a strict line format. Candidates are deduped by file:line, then one verifier lane per candidate re-reads the code and returns CONFIRMED, PLAUSIBLE, or REFUTED with a reason. The aggregated report (confirmed first, ranked by severity) comes back as the tool result and is saved to ~/.pi/swarm/<run-id>/report.md.
  • swarm fix takes a list of independent items and creates one git worktree per item in a sibling directory <repo>-swarm/<slug> (branch swarm/<slug>), then runs a workspace-write codex lane in each. Lanes are instructed to stay in scope, commit nothing, and end with STATUS: done|partial|blocked — summary. The report shows each lane's status and git diff --stat; you review the worktree diffs and merge what you like.
  • swarm status / swarm kill / swarm clean inspect the run, kill every lane (including orphans from a crashed session, tracked in ~/.pi/swarm/running.json), and remove all swarm worktrees + branches.

How it works

Lanes are codex exec --json child processes in their own process groups, capped at 4 concurrent (PI_SWARM_CONCURRENCY), logging to ~/.pi/swarm/<run-id>/*.log. A widget above the editor shows lane progress, flags any lane silent for 3+ minutes as stalled, and a 30-minute hard timeout kills runaways. Default model is gpt-5.6-sol (PI_SWARM_MODEL or the model param to override). Reviewers and verifiers run with -s read-only; fix lanes get -s workspace-write scoped to their worktree. No coordination files ever land in the repo.

When to use it

  • /swarm review (optionally with notes) before committing or opening a PR on anything non-trivial. Add scope:'branch' to review the whole branch instead of the uncommitted diff, and pass both repo paths for paired-repo work.
  • /swarm fix after you've agreed on a list of independent fixes; the model derives the items from the conversation. One item per independent concern.
  • Not for single small fixes: the orchestration overhead isn't worth it, just fix it inline.

Commands:/swarm review [notes], /swarm fix [notes], /swarm status, /swarm kill, /swarm clean


probe

Lets the agent look at the running app itself instead of asking me to screenshot, open devtools, or paste network responses. This replaces the highest-volume manual loop in my history: screenshot local, screenshot staging, paste both, repeat.

What it does

  • snap navigates to a route, screenshots it, and returns the image plus console errors and failed requests (with response bodies) from the load.
  • parity captures the same route on local and staging and attaches both screenshots, first local then staging, for direct visual comparison.
  • errors skips the screenshot and just reports console exceptions/errors and failed request bodies, for "why is this 500ing" debugging.
  • config prints the resolved project config with the password redacted.

How it works

Zero dependencies: it launches an installed Chrome/Chromium with --headless=new --remote-debugging-port=0 and speaks the Chrome DevTools Protocol over Node's built-in WebSocket. If no system browser exists it falls back to the newest "Chrome for Testing" build in the Playwright cache. Base URLs, login credentials, and default routes live per project in ~/.pi/probe.json (created chmod 600 by /probe); projects are matched by cwd prefix. Each project gets a persistent Chrome profile under ~/.pi/probe/profiles/, so a login survives between calls, and when a page redirects to the login form the extension fills the configured selectors (with the native-setter trick so React controlled inputs register) and retries. Screenshots over ~1.5MB are downscaled via sips. A full http(s):// URL as route works without any project config.

When to use it

  • After UI changes: probe snap the affected route instead of asking "does it look right?".
  • Local-vs-staging drift: probe parity on the routes that differ.
  • Any browser-side failure (blank page, ChunkLoadError, failing fetch): probe errors reads the console and response bodies directly.

Setup: run /probe once to scaffold ~/.pi/probe.json, fill in URLs + test credentials. Keep real user credentials out of it; use dedicated test accounts.


jira

Jira over the plain REST API with an API token. Exists because the Atlassian MCP kept breaking OAuth and, worse, cannot see images attached to cards; this downloads attachments and hands them to the model as real images.

What it does

  • get pulls a card into context: summary, status, assignee, description (ADF converted to readable text), comments, and attachment images (downloaded with auth, downscaled, attached to the tool result so the model can read screenshots and mockups).
  • search runs a JQL query, comment adds a comment, create makes a new card (optionally under a parent/epic).
  • /jira SXCL-1234 pulls a card into the conversation. /jira start SXCL-1234 also has the agent create the branch off latest main (both repos in a paired-repo workspace). /jira verify [KEY] audits the current branch against the card's acceptance criteria and reports covered / partial / missing; the key defaults to the ticket id in the branch name.

How it works

Config in ~/.pi/jira.json (chmod 600): site URL, account email, API token from https://id.atlassian.com/manage-profile/security/api-tokens. /jira auth prompts for the three values and validates them against /myself before saving. Descriptions and comments arrive as Atlassian Document Format and are converted to markdown-ish text (headings, lists, code blocks, tables, mentions, task lists).

When to use it

  • Any time a ticket id comes up: the model is prompted to fetch cards itself rather than asking for a paste.
  • Start-of-work ritual: /jira start KEY = branch + requirements checklist in one step.
  • Before opening the PR: /jira verify catches the "card asked for three things, branch does two" gap.

scope-guard

Structural enforcement of "only touch what the task is about". Exists because agents (especially delegated workers) kept editing files outside scope and staging junk like .pnpm-store/ into PRs.

What it does

  • Always on: edit/write into node_modules/, .pnpm-store/, or .git/ is blocked outright.
  • After every git add / git commit the staged file list is checked; junk paths (dist/, build/, .next/, .turbo/, coverage/, .DS_Store, *.log, plus the hard list) and out-of-scope files produce a warning appended to the bash tool result, so the model sees it and unstages before committing. You also get a UI notification.
  • With a declared scope, any edit/write outside it is blocked with a reason the model can read, so it has to ask instead of wandering.

How it works

A tool_call handler (blocking) and a tool_result handler (annotating). Scope is session-local state set by the /scope command: either explicit globs (/scope src/pages/** packages/api/**) or /scope branch, which snapshots the files already changed on the branch (vs merge-base with main) plus current dirty files. /scope off clears it; bare /scope shows it. A footer status chip shows when a scope is active.

When to use it

  • Junk protection needs nothing; it's on.
  • Declare a scope at the start of tightly-bounded work ("only the help docs", "only IssuesTracking"), the exact situations where scope creep bit before.

ci

GitHub Actions results for the current branch, in-context. Exists because CI failure logs kept getting copy-pasted by hand.

What it does

  • ci status lists recent workflow runs on the current branch with conclusions and run ids.
  • ci logs fetches the failed-step logs of the latest failed run (or a specific runId), truncated to the last 30KB.
  • /ci asks the model to check the branch, pull failing logs, and identify the root cause before touching anything.

How it works

Thin wrapper over gh run list / gh run view --log-failed executed in the repo cwd. Auth and repo resolution are whatever gh already has.

When to use it

After a push, or the moment anyone says "the check is failing". The model is prompted to reach for it instead of asking for a paste.


devwatch

Dev servers the agent can read, plus port management.

What it does

  • dev tool: start/stop/restart/list/logs for named dev servers. Servers spawn detached with output teed to ~/.pi/dev-logs/<name>.log, so they survive pi exiting and any session (or another tool) can read the same logs. logs supports errorsOnly (error lines plus stack context) and grep, so the agent pulls fresh errors itself instead of me copy-pasting stack traces.
  • ports tool: list TCP listeners with pid, command, and project cwd; kill by port or pid. /ports shows a quick toast.

When to use it

Have the agent start dev servers through dev rather than raw bash, then after changes it checks dev logs errorsOnly:true on its own. ports kill replaces "kill whatever is on 3003".


shot

/shot [n] [message] attaches the n most recent screenshots from the macOS screenshot folder (override with PI_SHOT_DIR) to your message, downscaling anything over ~1.5MB. For the times you want to show the agent something faster than describing it. With probe in place, prefer letting the agent take its own screenshots; /shot covers everything probe can't see (native apps, other windows, your phone photo synced to Desktop).


Notes

  • Secrets: all credentials live outside this repo in ~/.pi/probe.json and ~/.pi/jira.json (0600). Nothing in extensions/ contains a secret.
  • pi 0.82 image gotcha: tool results and user messages take images as {type:"image", data, mimeType}. Older extensions using the Anthropic-style source wrapper fail silently.
  • Verification recipe used for these: typecheck with a tsconfig whose paths map the pi package's dist/*.d.ts (moduleResolution bundler, allowImportingTsExtensions), a harness that loads each extension with a fake ExtensionAPI via node --experimental-strip-types, and a real pi -p load.

About

Personal extensions for the pi coding agent: review swarms, browser probe, Jira, scope guard, CI logs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

pi-extensions

Personal extensions for the pi coding agent. Built from an analysis of my own Claude Code and Codex session history: each one automates something I was demonstrably doing by hand, over and over.

ExtensionOne-linerUse it when
swarmCodex review swarms + parallel worktree fix lanesBefore shipping meaningful changes; when fixing a list of independent issues
probeHeadless-browser screenshots, console errors, failed-request bodiesVerifying UI changes, local-vs-staging parity, debugging 4xx/5xx
jiraJira via REST API token, including card attachment imagesAny card-shaped work: start, review, verify against acceptance criteria
scope-guardBlocks out-of-scope edits and junk commitsAlways on; declare a scope for tightly-bounded tasks
ciPull GitHub Actions failures for the current branchA check fails and you'd otherwise paste the log
devwatchDev servers with captured logs + port managementRunning dev servers the agent should be able to read
shotAttach recent screenshots to a messageQuickly showing the agent what you see

Install

Copy (or run ./install.sh, which does the same) into pi's user extension directory:

cp extensions/*.ts ~/.pi/agent/extensions/

Pi loads them on next start; /reload picks them up in a running session.

Requirements:

  • pi >= 0.82 (the ImageContent shape changed in 0.82 to {type, data, mimeType}; these extensions target the new shape)
  • macOS (uses sips for image downscaling and lsof in devwatch)
  • Codex CLI authenticated (codex on PATH) for swarm
  • GitHub CLI authenticated for ci
  • Chrome, Chromium, Arc, or a Playwright browser cache for probe (it auto-discovers ~/Library/Caches/ms-playwright builds)

No npm installs. Everything runs on Node builtins plus the packages pi already ships (typebox, @earendil-works/pi-ai).


swarm

My own take on pi-subagents + pi-worktree, merged into one pipeline and shaped around a workflow I used to run by hand: fan out independent read-only reviewers over a diff, verify every candidate finding, then fix the confirmed ones in parallel worktrees.

What it does

  • swarm review spawns one read-only codex exec lane per review angle. Eight angle presets: correctness, removed-behavior, cross-file, conventions, efficiency, reuse, simplification, altitude. Each lane reports up to 6 candidates in a strict line format. Candidates are deduped by file:line, then one verifier lane per candidate re-reads the code and returns CONFIRMED, PLAUSIBLE, or REFUTED with a reason. The aggregated report (confirmed first, ranked by severity) comes back as the tool result and is saved to ~/.pi/swarm/<run-id>/report.md.
  • swarm fix takes a list of independent items and creates one git worktree per item in a sibling directory <repo>-swarm/<slug> (branch swarm/<slug>), then runs a workspace-write codex lane in each. Lanes are instructed to stay in scope, commit nothing, and end with STATUS: done|partial|blocked — summary. The report shows each lane's status and git diff --stat; you review the worktree diffs and merge what you like.
  • swarm status / swarm kill / swarm clean inspect the run, kill every lane (including orphans from a crashed session, tracked in ~/.pi/swarm/running.json), and remove all swarm worktrees + branches.

How it works

Lanes are codex exec --json child processes in their own process groups, capped at 4 concurrent (PI_SWARM_CONCURRENCY), logging to ~/.pi/swarm/<run-id>/*.log. A widget above the editor shows lane progress, flags any lane silent for 3+ minutes as stalled, and a 30-minute hard timeout kills runaways. Default model is gpt-5.6-sol (PI_SWARM_MODEL or the model param to override). Reviewers and verifiers run with -s read-only; fix lanes get -s workspace-write scoped to their worktree. No coordination files ever land in the repo.

When to use it

  • /swarm review (optionally with notes) before committing or opening a PR on anything non-trivial. Add scope:'branch' to review the whole branch instead of the uncommitted diff, and pass both repo paths for paired-repo work.
  • /swarm fix after you've agreed on a list of independent fixes; the model derives the items from the conversation. One item per independent concern.
  • Not for single small fixes: the orchestration overhead isn't worth it, just fix it inline.

Commands:/swarm review [notes], /swarm fix [notes], /swarm status, /swarm kill, /swarm clean


probe

Lets the agent look at the running app itself instead of asking me to screenshot, open devtools, or paste network responses. This replaces the highest-volume manual loop in my history: screenshot local, screenshot staging, paste both, repeat.

What it does

  • snap navigates to a route, screenshots it, and returns the image plus console errors and failed requests (with response bodies) from the load.
  • parity captures the same route on local and staging and attaches both screenshots, first local then staging, for direct visual comparison.
  • errors skips the screenshot and just reports console exceptions/errors and failed request bodies, for "why is this 500ing" debugging.
  • config prints the resolved project config with the password redacted.

How it works

Zero dependencies: it launches an installed Chrome/Chromium with --headless=new --remote-debugging-port=0 and speaks the Chrome DevTools Protocol over Node's built-in WebSocket. If no system browser exists it falls back to the newest "Chrome for Testing" build in the Playwright cache. Base URLs, login credentials, and default routes live per project in ~/.pi/probe.json (created chmod 600 by /probe); projects are matched by cwd prefix. Each project gets a persistent Chrome profile under ~/.pi/probe/profiles/, so a login survives between calls, and when a page redirects to the login form the extension fills the configured selectors (with the native-setter trick so React controlled inputs register) and retries. Screenshots over ~1.5MB are downscaled via sips. A full http(s):// URL as route works without any project config.

When to use it

  • After UI changes: probe snap the affected route instead of asking "does it look right?".
  • Local-vs-staging drift: probe parity on the routes that differ.
  • Any browser-side failure (blank page, ChunkLoadError, failing fetch): probe errors reads the console and response bodies directly.

Setup: run /probe once to scaffold ~/.pi/probe.json, fill in URLs + test credentials. Keep real user credentials out of it; use dedicated test accounts.


jira

Jira over the plain REST API with an API token. Exists because the Atlassian MCP kept breaking OAuth and, worse, cannot see images attached to cards; this downloads attachments and hands them to the model as real images.

What it does

  • get pulls a card into context: summary, status, assignee, description (ADF converted to readable text), comments, and attachment images (downloaded with auth, downscaled, attached to the tool result so the model can read screenshots and mockups).
  • search runs a JQL query, comment adds a comment, create makes a new card (optionally under a parent/epic).
  • /jira SXCL-1234 pulls a card into the conversation. /jira start SXCL-1234 also has the agent create the branch off latest main (both repos in a paired-repo workspace). /jira verify [KEY] audits the current branch against the card's acceptance criteria and reports covered / partial / missing; the key defaults to the ticket id in the branch name.

How it works

Config in ~/.pi/jira.json (chmod 600): site URL, account email, API token from https://id.atlassian.com/manage-profile/security/api-tokens. /jira auth prompts for the three values and validates them against /myself before saving. Descriptions and comments arrive as Atlassian Document Format and are converted to markdown-ish text (headings, lists, code blocks, tables, mentions, task lists).

When to use it

  • Any time a ticket id comes up: the model is prompted to fetch cards itself rather than asking for a paste.
  • Start-of-work ritual: /jira start KEY = branch + requirements checklist in one step.
  • Before opening the PR: /jira verify catches the "card asked for three things, branch does two" gap.

scope-guard

Structural enforcement of "only touch what the task is about". Exists because agents (especially delegated workers) kept editing files outside scope and staging junk like .pnpm-store/ into PRs.

What it does

  • Always on: edit/write into node_modules/, .pnpm-store/, or .git/ is blocked outright.
  • After every git add / git commit the staged file list is checked; junk paths (dist/, build/, .next/, .turbo/, coverage/, .DS_Store, *.log, plus the hard list) and out-of-scope files produce a warning appended to the bash tool result, so the model sees it and unstages before committing. You also get a UI notification.
  • With a declared scope, any edit/write outside it is blocked with a reason the model can read, so it has to ask instead of wandering.

How it works

A tool_call handler (blocking) and a tool_result handler (annotating). Scope is session-local state set by the /scope command: either explicit globs (/scope src/pages/** packages/api/**) or /scope branch, which snapshots the files already changed on the branch (vs merge-base with main) plus current dirty files. /scope off clears it; bare /scope shows it. A footer status chip shows when a scope is active.

When to use it

  • Junk protection needs nothing; it's on.
  • Declare a scope at the start of tightly-bounded work ("only the help docs", "only IssuesTracking"), the exact situations where scope creep bit before.

ci

GitHub Actions results for the current branch, in-context. Exists because CI failure logs kept getting copy-pasted by hand.

What it does

  • ci status lists recent workflow runs on the current branch with conclusions and run ids.
  • ci logs fetches the failed-step logs of the latest failed run (or a specific runId), truncated to the last 30KB.
  • /ci asks the model to check the branch, pull failing logs, and identify the root cause before touching anything.

How it works

Thin wrapper over gh run list / gh run view --log-failed executed in the repo cwd. Auth and repo resolution are whatever gh already has.

When to use it

After a push, or the moment anyone says "the check is failing". The model is prompted to reach for it instead of asking for a paste.


devwatch

Dev servers the agent can read, plus port management.

What it does

  • dev tool: start/stop/restart/list/logs for named dev servers. Servers spawn detached with output teed to ~/.pi/dev-logs/<name>.log, so they survive pi exiting and any session (or another tool) can read the same logs. logs supports errorsOnly (error lines plus stack context) and grep, so the agent pulls fresh errors itself instead of me copy-pasting stack traces.
  • ports tool: list TCP listeners with pid, command, and project cwd; kill by port or pid. /ports shows a quick toast.

When to use it

Have the agent start dev servers through dev rather than raw bash, then after changes it checks dev logs errorsOnly:true on its own. ports kill replaces "kill whatever is on 3003".


shot

/shot [n] [message] attaches the n most recent screenshots from the macOS screenshot folder (override with PI_SHOT_DIR) to your message, downscaling anything over ~1.5MB. For the times you want to show the agent something faster than describing it. With probe in place, prefer letting the agent take its own screenshots; /shot covers everything probe can't see (native apps, other windows, your phone photo synced to Desktop).


Notes

  • Secrets: all credentials live outside this repo in ~/.pi/probe.json and ~/.pi/jira.json (0600). Nothing in extensions/ contains a secret.
  • pi 0.82 image gotcha: tool results and user messages take images as {type:"image", data, mimeType}. Older extensions using the Anthropic-style source wrapper fail silently.
  • Verification recipe used for these: typecheck with a tsconfig whose paths map the pi package's dist/*.d.ts (moduleResolution bundler, allowImportingTsExtensions), a harness that loads each extension with a fake ExtensionAPI via node --experimental-strip-types, and a real pi -p load.

About

Personal extensions for the pi coding agent: review swarms, browser probe, Jira, scope guard, CI logs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

pi-extensions

Personal extensions for the pi coding agent. Built from an analysis of my own Claude Code and Codex session history: each one automates something I was demonstrably doing by hand, over and over.

ExtensionOne-linerUse it when
swarmCodex review swarms + parallel worktree fix lanesBefore shipping meaningful changes; when fixing a list of independent issues
probeHeadless-browser screenshots, console errors, failed-request bodiesVerifying UI changes, local-vs-staging parity, debugging 4xx/5xx
jiraJira via REST API token, including card attachment imagesAny card-shaped work: start, review, verify against acceptance criteria
scope-guardBlocks out-of-scope edits and junk commitsAlways on; declare a scope for tightly-bounded tasks
ciPull GitHub Actions failures for the current branchA check fails and you'd otherwise paste the log
devwatchDev servers with captured logs + port managementRunning dev servers the agent should be able to read
shotAttach recent screenshots to a messageQuickly showing the agent what you see

Install

Copy (or run ./install.sh, which does the same) into pi's user extension directory:

cp extensions/*.ts ~/.pi/agent/extensions/

Pi loads them on next start; /reload picks them up in a running session.

Requirements:

  • pi >= 0.82 (the ImageContent shape changed in 0.82 to {type, data, mimeType}; these extensions target the new shape)
  • macOS (uses sips for image downscaling and lsof in devwatch)
  • Codex CLI authenticated (codex on PATH) for swarm
  • GitHub CLI authenticated for ci
  • Chrome, Chromium, Arc, or a Playwright browser cache for probe (it auto-discovers ~/Library/Caches/ms-playwright builds)

No npm installs. Everything runs on Node builtins plus the packages pi already ships (typebox, @earendil-works/pi-ai).


swarm

My own take on pi-subagents + pi-worktree, merged into one pipeline and shaped around a workflow I used to run by hand: fan out independent read-only reviewers over a diff, verify every candidate finding, then fix the confirmed ones in parallel worktrees.

What it does

  • swarm review spawns one read-only codex exec lane per review angle. Eight angle presets: correctness, removed-behavior, cross-file, conventions, efficiency, reuse, simplification, altitude. Each lane reports up to 6 candidates in a strict line format. Candidates are deduped by file:line, then one verifier lane per candidate re-reads the code and returns CONFIRMED, PLAUSIBLE, or REFUTED with a reason. The aggregated report (confirmed first, ranked by severity) comes back as the tool result and is saved to ~/.pi/swarm/<run-id>/report.md.
  • swarm fix takes a list of independent items and creates one git worktree per item in a sibling directory <repo>-swarm/<slug> (branch swarm/<slug>), then runs a workspace-write codex lane in each. Lanes are instructed to stay in scope, commit nothing, and end with STATUS: done|partial|blocked — summary. The report shows each lane's status and git diff --stat; you review the worktree diffs and merge what you like.
  • swarm status / swarm kill / swarm clean inspect the run, kill every lane (including orphans from a crashed session, tracked in ~/.pi/swarm/running.json), and remove all swarm worktrees + branches.

How it works

Lanes are codex exec --json child processes in their own process groups, capped at 4 concurrent (PI_SWARM_CONCURRENCY), logging to ~/.pi/swarm/<run-id>/*.log. A widget above the editor shows lane progress, flags any lane silent for 3+ minutes as stalled, and a 30-minute hard timeout kills runaways. Default model is gpt-5.6-sol (PI_SWARM_MODEL or the model param to override). Reviewers and verifiers run with -s read-only; fix lanes get -s workspace-write scoped to their worktree. No coordination files ever land in the repo.

When to use it

  • /swarm review (optionally with notes) before committing or opening a PR on anything non-trivial. Add scope:'branch' to review the whole branch instead of the uncommitted diff, and pass both repo paths for paired-repo work.
  • /swarm fix after you've agreed on a list of independent fixes; the model derives the items from the conversation. One item per independent concern.
  • Not for single small fixes: the orchestration overhead isn't worth it, just fix it inline.

Commands:/swarm review [notes], /swarm fix [notes], /swarm status, /swarm kill, /swarm clean


probe

Lets the agent look at the running app itself instead of asking me to screenshot, open devtools, or paste network responses. This replaces the highest-volume manual loop in my history: screenshot local, screenshot staging, paste both, repeat.

What it does

  • snap navigates to a route, screenshots it, and returns the image plus console errors and failed requests (with response bodies) from the load.
  • parity captures the same route on local and staging and attaches both screenshots, first local then staging, for direct visual comparison.
  • errors skips the screenshot and just reports console exceptions/errors and failed request bodies, for "why is this 500ing" debugging.
  • config prints the resolved project config with the password redacted.

How it works

Zero dependencies: it launches an installed Chrome/Chromium with --headless=new --remote-debugging-port=0 and speaks the Chrome DevTools Protocol over Node's built-in WebSocket. If no system browser exists it falls back to the newest "Chrome for Testing" build in the Playwright cache. Base URLs, login credentials, and default routes live per project in ~/.pi/probe.json (created chmod 600 by /probe); projects are matched by cwd prefix. Each project gets a persistent Chrome profile under ~/.pi/probe/profiles/, so a login survives between calls, and when a page redirects to the login form the extension fills the configured selectors (with the native-setter trick so React controlled inputs register) and retries. Screenshots over ~1.5MB are downscaled via sips. A full http(s):// URL as route works without any project config.

When to use it

  • After UI changes: probe snap the affected route instead of asking "does it look right?".
  • Local-vs-staging drift: probe parity on the routes that differ.
  • Any browser-side failure (blank page, ChunkLoadError, failing fetch): probe errors reads the console and response bodies directly.

Setup: run /probe once to scaffold ~/.pi/probe.json, fill in URLs + test credentials. Keep real user credentials out of it; use dedicated test accounts.


jira

Jira over the plain REST API with an API token. Exists because the Atlassian MCP kept breaking OAuth and, worse, cannot see images attached to cards; this downloads attachments and hands them to the model as real images.

What it does

  • get pulls a card into context: summary, status, assignee, description (ADF converted to readable text), comments, and attachment images (downloaded with auth, downscaled, attached to the tool result so the model can read screenshots and mockups).
  • search runs a JQL query, comment adds a comment, create makes a new card (optionally under a parent/epic).
  • /jira SXCL-1234 pulls a card into the conversation. /jira start SXCL-1234 also has the agent create the branch off latest main (both repos in a paired-repo workspace). /jira verify [KEY] audits the current branch against the card's acceptance criteria and reports covered / partial / missing; the key defaults to the ticket id in the branch name.

How it works

Config in ~/.pi/jira.json (chmod 600): site URL, account email, API token from https://id.atlassian.com/manage-profile/security/api-tokens. /jira auth prompts for the three values and validates them against /myself before saving. Descriptions and comments arrive as Atlassian Document Format and are converted to markdown-ish text (headings, lists, code blocks, tables, mentions, task lists).

When to use it

  • Any time a ticket id comes up: the model is prompted to fetch cards itself rather than asking for a paste.
  • Start-of-work ritual: /jira start KEY = branch + requirements checklist in one step.
  • Before opening the PR: /jira verify catches the "card asked for three things, branch does two" gap.

scope-guard

Structural enforcement of "only touch what the task is about". Exists because agents (especially delegated workers) kept editing files outside scope and staging junk like .pnpm-store/ into PRs.

What it does

  • Always on: edit/write into node_modules/, .pnpm-store/, or .git/ is blocked outright.
  • After every git add / git commit the staged file list is checked; junk paths (dist/, build/, .next/, .turbo/, coverage/, .DS_Store, *.log, plus the hard list) and out-of-scope files produce a warning appended to the bash tool result, so the model sees it and unstages before committing. You also get a UI notification.
  • With a declared scope, any edit/write outside it is blocked with a reason the model can read, so it has to ask instead of wandering.

How it works

A tool_call handler (blocking) and a tool_result handler (annotating). Scope is session-local state set by the /scope command: either explicit globs (/scope src/pages/** packages/api/**) or /scope branch, which snapshots the files already changed on the branch (vs merge-base with main) plus current dirty files. /scope off clears it; bare /scope shows it. A footer status chip shows when a scope is active.

When to use it

  • Junk protection needs nothing; it's on.
  • Declare a scope at the start of tightly-bounded work ("only the help docs", "only IssuesTracking"), the exact situations where scope creep bit before.

ci

GitHub Actions results for the current branch, in-context. Exists because CI failure logs kept getting copy-pasted by hand.

What it does

  • ci status lists recent workflow runs on the current branch with conclusions and run ids.
  • ci logs fetches the failed-step logs of the latest failed run (or a specific runId), truncated to the last 30KB.
  • /ci asks the model to check the branch, pull failing logs, and identify the root cause before touching anything.

How it works

Thin wrapper over gh run list / gh run view --log-failed executed in the repo cwd. Auth and repo resolution are whatever gh already has.

When to use it

After a push, or the moment anyone says "the check is failing". The model is prompted to reach for it instead of asking for a paste.


devwatch

Dev servers the agent can read, plus port management.

What it does

  • dev tool: start/stop/restart/list/logs for named dev servers. Servers spawn detached with output teed to ~/.pi/dev-logs/<name>.log, so they survive pi exiting and any session (or another tool) can read the same logs. logs supports errorsOnly (error lines plus stack context) and grep, so the agent pulls fresh errors itself instead of me copy-pasting stack traces.
  • ports tool: list TCP listeners with pid, command, and project cwd; kill by port or pid. /ports shows a quick toast.

When to use it

Have the agent start dev servers through dev rather than raw bash, then after changes it checks dev logs errorsOnly:true on its own. ports kill replaces "kill whatever is on 3003".


shot

/shot [n] [message] attaches the n most recent screenshots from the macOS screenshot folder (override with PI_SHOT_DIR) to your message, downscaling anything over ~1.5MB. For the times you want to show the agent something faster than describing it. With probe in place, prefer letting the agent take its own screenshots; /shot covers everything probe can't see (native apps, other windows, your phone photo synced to Desktop).


Notes

  • Secrets: all credentials live outside this repo in ~/.pi/probe.json and ~/.pi/jira.json (0600). Nothing in extensions/ contains a secret.
  • pi 0.82 image gotcha: tool results and user messages take images as {type:"image", data, mimeType}. Older extensions using the Anthropic-style source wrapper fail silently.
  • Verification recipe used for these: typecheck with a tsconfig whose paths map the pi package's dist/*.d.ts (moduleResolution bundler, allowImportingTsExtensions), a harness that loads each extension with a fake ExtensionAPI via node --experimental-strip-types, and a real pi -p load.

About

Personal extensions for the pi coding agent: review swarms, browser probe, Jira, scope guard, CI logs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

pi-extensions

Personal extensions for the pi coding agent. Built from an analysis of my own Claude Code and Codex session history: each one automates something I was demonstrably doing by hand, over and over.

ExtensionOne-linerUse it when
swarmCodex review swarms + parallel worktree fix lanesBefore shipping meaningful changes; when fixing a list of independent issues
probeHeadless-browser screenshots, console errors, failed-request bodiesVerifying UI changes, local-vs-staging parity, debugging 4xx/5xx
jiraJira via REST API token, including card attachment imagesAny card-shaped work: start, review, verify against acceptance criteria
scope-guardBlocks out-of-scope edits and junk commitsAlways on; declare a scope for tightly-bounded tasks
ciPull GitHub Actions failures for the current branchA check fails and you'd otherwise paste the log
devwatchDev servers with captured logs + port managementRunning dev servers the agent should be able to read
shotAttach recent screenshots to a messageQuickly showing the agent what you see

Install

Copy (or run ./install.sh, which does the same) into pi's user extension directory:

cp extensions/*.ts ~/.pi/agent/extensions/

Pi loads them on next start; /reload picks them up in a running session.

Requirements:

  • pi >= 0.82 (the ImageContent shape changed in 0.82 to {type, data, mimeType}; these extensions target the new shape)
  • macOS (uses sips for image downscaling and lsof in devwatch)
  • Codex CLI authenticated (codex on PATH) for swarm
  • GitHub CLI authenticated for ci
  • Chrome, Chromium, Arc, or a Playwright browser cache for probe (it auto-discovers ~/Library/Caches/ms-playwright builds)

No npm installs. Everything runs on Node builtins plus the packages pi already ships (typebox, @earendil-works/pi-ai).


swarm

My own take on pi-subagents + pi-worktree, merged into one pipeline and shaped around a workflow I used to run by hand: fan out independent read-only reviewers over a diff, verify every candidate finding, then fix the confirmed ones in parallel worktrees.

What it does

  • swarm review spawns one read-only codex exec lane per review angle. Eight angle presets: correctness, removed-behavior, cross-file, conventions, efficiency, reuse, simplification, altitude. Each lane reports up to 6 candidates in a strict line format. Candidates are deduped by file:line, then one verifier lane per candidate re-reads the code and returns CONFIRMED, PLAUSIBLE, or REFUTED with a reason. The aggregated report (confirmed first, ranked by severity) comes back as the tool result and is saved to ~/.pi/swarm/<run-id>/report.md.
  • swarm fix takes a list of independent items and creates one git worktree per item in a sibling directory <repo>-swarm/<slug> (branch swarm/<slug>), then runs a workspace-write codex lane in each. Lanes are instructed to stay in scope, commit nothing, and end with STATUS: done|partial|blocked — summary. The report shows each lane's status and git diff --stat; you review the worktree diffs and merge what you like.
  • swarm status / swarm kill / swarm clean inspect the run, kill every lane (including orphans from a crashed session, tracked in ~/.pi/swarm/running.json), and remove all swarm worktrees + branches.

How it works

Lanes are codex exec --json child processes in their own process groups, capped at 4 concurrent (PI_SWARM_CONCURRENCY), logging to ~/.pi/swarm/<run-id>/*.log. A widget above the editor shows lane progress, flags any lane silent for 3+ minutes as stalled, and a 30-minute hard timeout kills runaways. Default model is gpt-5.6-sol (PI_SWARM_MODEL or the model param to override). Reviewers and verifiers run with -s read-only; fix lanes get -s workspace-write scoped to their worktree. No coordination files ever land in the repo.

When to use it

  • /swarm review (optionally with notes) before committing or opening a PR on anything non-trivial. Add scope:'branch' to review the whole branch instead of the uncommitted diff, and pass both repo paths for paired-repo work.
  • /swarm fix after you've agreed on a list of independent fixes; the model derives the items from the conversation. One item per independent concern.
  • Not for single small fixes: the orchestration overhead isn't worth it, just fix it inline.

Commands:/swarm review [notes], /swarm fix [notes], /swarm status, /swarm kill, /swarm clean


probe

Lets the agent look at the running app itself instead of asking me to screenshot, open devtools, or paste network responses. This replaces the highest-volume manual loop in my history: screenshot local, screenshot staging, paste both, repeat.

What it does

  • snap navigates to a route, screenshots it, and returns the image plus console errors and failed requests (with response bodies) from the load.
  • parity captures the same route on local and staging and attaches both screenshots, first local then staging, for direct visual comparison.
  • errors skips the screenshot and just reports console exceptions/errors and failed request bodies, for "why is this 500ing" debugging.
  • config prints the resolved project config with the password redacted.

How it works

Zero dependencies: it launches an installed Chrome/Chromium with --headless=new --remote-debugging-port=0 and speaks the Chrome DevTools Protocol over Node's built-in WebSocket. If no system browser exists it falls back to the newest "Chrome for Testing" build in the Playwright cache. Base URLs, login credentials, and default routes live per project in ~/.pi/probe.json (created chmod 600 by /probe); projects are matched by cwd prefix. Each project gets a persistent Chrome profile under ~/.pi/probe/profiles/, so a login survives between calls, and when a page redirects to the login form the extension fills the configured selectors (with the native-setter trick so React controlled inputs register) and retries. Screenshots over ~1.5MB are downscaled via sips. A full http(s):// URL as route works without any project config.

When to use it

  • After UI changes: probe snap the affected route instead of asking "does it look right?".
  • Local-vs-staging drift: probe parity on the routes that differ.
  • Any browser-side failure (blank page, ChunkLoadError, failing fetch): probe errors reads the console and response bodies directly.

Setup: run /probe once to scaffold ~/.pi/probe.json, fill in URLs + test credentials. Keep real user credentials out of it; use dedicated test accounts.


jira

Jira over the plain REST API with an API token. Exists because the Atlassian MCP kept breaking OAuth and, worse, cannot see images attached to cards; this downloads attachments and hands them to the model as real images.

What it does

  • get pulls a card into context: summary, status, assignee, description (ADF converted to readable text), comments, and attachment images (downloaded with auth, downscaled, attached to the tool result so the model can read screenshots and mockups).
  • search runs a JQL query, comment adds a comment, create makes a new card (optionally under a parent/epic).
  • /jira SXCL-1234 pulls a card into the conversation. /jira start SXCL-1234 also has the agent create the branch off latest main (both repos in a paired-repo workspace). /jira verify [KEY] audits the current branch against the card's acceptance criteria and reports covered / partial / missing; the key defaults to the ticket id in the branch name.

How it works

Config in ~/.pi/jira.json (chmod 600): site URL, account email, API token from https://id.atlassian.com/manage-profile/security/api-tokens. /jira auth prompts for the three values and validates them against /myself before saving. Descriptions and comments arrive as Atlassian Document Format and are converted to markdown-ish text (headings, lists, code blocks, tables, mentions, task lists).

When to use it

  • Any time a ticket id comes up: the model is prompted to fetch cards itself rather than asking for a paste.
  • Start-of-work ritual: /jira start KEY = branch + requirements checklist in one step.
  • Before opening the PR: /jira verify catches the "card asked for three things, branch does two" gap.

scope-guard

Structural enforcement of "only touch what the task is about". Exists because agents (especially delegated workers) kept editing files outside scope and staging junk like .pnpm-store/ into PRs.

What it does

  • Always on: edit/write into node_modules/, .pnpm-store/, or .git/ is blocked outright.
  • After every git add / git commit the staged file list is checked; junk paths (dist/, build/, .next/, .turbo/, coverage/, .DS_Store, *.log, plus the hard list) and out-of-scope files produce a warning appended to the bash tool result, so the model sees it and unstages before committing. You also get a UI notification.
  • With a declared scope, any edit/write outside it is blocked with a reason the model can read, so it has to ask instead of wandering.

How it works

A tool_call handler (blocking) and a tool_result handler (annotating). Scope is session-local state set by the /scope command: either explicit globs (/scope src/pages/** packages/api/**) or /scope branch, which snapshots the files already changed on the branch (vs merge-base with main) plus current dirty files. /scope off clears it; bare /scope shows it. A footer status chip shows when a scope is active.

When to use it

  • Junk protection needs nothing; it's on.
  • Declare a scope at the start of tightly-bounded work ("only the help docs", "only IssuesTracking"), the exact situations where scope creep bit before.

ci

GitHub Actions results for the current branch, in-context. Exists because CI failure logs kept getting copy-pasted by hand.

What it does

  • ci status lists recent workflow runs on the current branch with conclusions and run ids.
  • ci logs fetches the failed-step logs of the latest failed run (or a specific runId), truncated to the last 30KB.
  • /ci asks the model to check the branch, pull failing logs, and identify the root cause before touching anything.

How it works

Thin wrapper over gh run list / gh run view --log-failed executed in the repo cwd. Auth and repo resolution are whatever gh already has.

When to use it

After a push, or the moment anyone says "the check is failing". The model is prompted to reach for it instead of asking for a paste.


devwatch

Dev servers the agent can read, plus port management.

What it does

  • dev tool: start/stop/restart/list/logs for named dev servers. Servers spawn detached with output teed to ~/.pi/dev-logs/<name>.log, so they survive pi exiting and any session (or another tool) can read the same logs. logs supports errorsOnly (error lines plus stack context) and grep, so the agent pulls fresh errors itself instead of me copy-pasting stack traces.
  • ports tool: list TCP listeners with pid, command, and project cwd; kill by port or pid. /ports shows a quick toast.

When to use it

Have the agent start dev servers through dev rather than raw bash, then after changes it checks dev logs errorsOnly:true on its own. ports kill replaces "kill whatever is on 3003".


shot

/shot [n] [message] attaches the n most recent screenshots from the macOS screenshot folder (override with PI_SHOT_DIR) to your message, downscaling anything over ~1.5MB. For the times you want to show the agent something faster than describing it. With probe in place, prefer letting the agent take its own screenshots; /shot covers everything probe can't see (native apps, other windows, your phone photo synced to Desktop).


Notes

  • Secrets: all credentials live outside this repo in ~/.pi/probe.json and ~/.pi/jira.json (0600). Nothing in extensions/ contains a secret.
  • pi 0.82 image gotcha: tool results and user messages take images as {type:"image", data, mimeType}. Older extensions using the Anthropic-style source wrapper fail silently.
  • Verification recipe used for these: typecheck with a tsconfig whose paths map the pi package's dist/*.d.ts (moduleResolution bundler, allowImportingTsExtensions), a harness that loads each extension with a fake ExtensionAPI via node --experimental-strip-types, and a real pi -p load.

About

Personal extensions for the pi coding agent: review swarms, browser probe, Jira, scope guard, CI logs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

pi-extensions

Personal extensions for the pi coding agent. Built from an analysis of my own Claude Code and Codex session history: each one automates something I was demonstrably doing by hand, over and over.

ExtensionOne-linerUse it when
swarmCodex review swarms + parallel worktree fix lanesBefore shipping meaningful changes; when fixing a list of independent issues
probeHeadless-browser screenshots, console errors, failed-request bodiesVerifying UI changes, local-vs-staging parity, debugging 4xx/5xx
jiraJira via REST API token, including card attachment imagesAny card-shaped work: start, review, verify against acceptance criteria
scope-guardBlocks out-of-scope edits and junk commitsAlways on; declare a scope for tightly-bounded tasks
ciPull GitHub Actions failures for the current branchA check fails and you'd otherwise paste the log
devwatchDev servers with captured logs + port managementRunning dev servers the agent should be able to read
shotAttach recent screenshots to a messageQuickly showing the agent what you see

Install

Copy (or run ./install.sh, which does the same) into pi's user extension directory:

cp extensions/*.ts ~/.pi/agent/extensions/

Pi loads them on next start; /reload picks them up in a running session.

Requirements:

  • pi >= 0.82 (the ImageContent shape changed in 0.82 to {type, data, mimeType}; these extensions target the new shape)
  • macOS (uses sips for image downscaling and lsof in devwatch)
  • Codex CLI authenticated (codex on PATH) for swarm
  • GitHub CLI authenticated for ci
  • Chrome, Chromium, Arc, or a Playwright browser cache for probe (it auto-discovers ~/Library/Caches/ms-playwright builds)

No npm installs. Everything runs on Node builtins plus the packages pi already ships (typebox, @earendil-works/pi-ai).


swarm

My own take on pi-subagents + pi-worktree, merged into one pipeline and shaped around a workflow I used to run by hand: fan out independent read-only reviewers over a diff, verify every candidate finding, then fix the confirmed ones in parallel worktrees.

What it does

  • swarm review spawns one read-only codex exec lane per review angle. Eight angle presets: correctness, removed-behavior, cross-file, conventions, efficiency, reuse, simplification, altitude. Each lane reports up to 6 candidates in a strict line format. Candidates are deduped by file:line, then one verifier lane per candidate re-reads the code and returns CONFIRMED, PLAUSIBLE, or REFUTED with a reason. The aggregated report (confirmed first, ranked by severity) comes back as the tool result and is saved to ~/.pi/swarm/<run-id>/report.md.
  • swarm fix takes a list of independent items and creates one git worktree per item in a sibling directory <repo>-swarm/<slug> (branch swarm/<slug>), then runs a workspace-write codex lane in each. Lanes are instructed to stay in scope, commit nothing, and end with STATUS: done|partial|blocked — summary. The report shows each lane's status and git diff --stat; you review the worktree diffs and merge what you like.
  • swarm status / swarm kill / swarm clean inspect the run, kill every lane (including orphans from a crashed session, tracked in ~/.pi/swarm/running.json), and remove all swarm worktrees + branches.

How it works

Lanes are codex exec --json child processes in their own process groups, capped at 4 concurrent (PI_SWARM_CONCURRENCY), logging to ~/.pi/swarm/<run-id>/*.log. A widget above the editor shows lane progress, flags any lane silent for 3+ minutes as stalled, and a 30-minute hard timeout kills runaways. Default model is gpt-5.6-sol (PI_SWARM_MODEL or the model param to override). Reviewers and verifiers run with -s read-only; fix lanes get -s workspace-write scoped to their worktree. No coordination files ever land in the repo.

When to use it

  • /swarm review (optionally with notes) before committing or opening a PR on anything non-trivial. Add scope:'branch' to review the whole branch instead of the uncommitted diff, and pass both repo paths for paired-repo work.
  • /swarm fix after you've agreed on a list of independent fixes; the model derives the items from the conversation. One item per independent concern.
  • Not for single small fixes: the orchestration overhead isn't worth it, just fix it inline.

Commands:/swarm review [notes], /swarm fix [notes], /swarm status, /swarm kill, /swarm clean


probe

Lets the agent look at the running app itself instead of asking me to screenshot, open devtools, or paste network responses. This replaces the highest-volume manual loop in my history: screenshot local, screenshot staging, paste both, repeat.

What it does

  • snap navigates to a route, screenshots it, and returns the image plus console errors and failed requests (with response bodies) from the load.
  • parity captures the same route on local and staging and attaches both screenshots, first local then staging, for direct visual comparison.
  • errors skips the screenshot and just reports console exceptions/errors and failed request bodies, for "why is this 500ing" debugging.
  • config prints the resolved project config with the password redacted.

How it works

Zero dependencies: it launches an installed Chrome/Chromium with --headless=new --remote-debugging-port=0 and speaks the Chrome DevTools Protocol over Node's built-in WebSocket. If no system browser exists it falls back to the newest "Chrome for Testing" build in the Playwright cache. Base URLs, login credentials, and default routes live per project in ~/.pi/probe.json (created chmod 600 by /probe); projects are matched by cwd prefix. Each project gets a persistent Chrome profile under ~/.pi/probe/profiles/, so a login survives between calls, and when a page redirects to the login form the extension fills the configured selectors (with the native-setter trick so React controlled inputs register) and retries. Screenshots over ~1.5MB are downscaled via sips. A full http(s):// URL as route works without any project config.

When to use it

  • After UI changes: probe snap the affected route instead of asking "does it look right?".
  • Local-vs-staging drift: probe parity on the routes that differ.
  • Any browser-side failure (blank page, ChunkLoadError, failing fetch): probe errors reads the console and response bodies directly.

Setup: run /probe once to scaffold ~/.pi/probe.json, fill in URLs + test credentials. Keep real user credentials out of it; use dedicated test accounts.


jira

Jira over the plain REST API with an API token. Exists because the Atlassian MCP kept breaking OAuth and, worse, cannot see images attached to cards; this downloads attachments and hands them to the model as real images.

What it does

  • get pulls a card into context: summary, status, assignee, description (ADF converted to readable text), comments, and attachment images (downloaded with auth, downscaled, attached to the tool result so the model can read screenshots and mockups).
  • search runs a JQL query, comment adds a comment, create makes a new card (optionally under a parent/epic).
  • /jira SXCL-1234 pulls a card into the conversation. /jira start SXCL-1234 also has the agent create the branch off latest main (both repos in a paired-repo workspace). /jira verify [KEY] audits the current branch against the card's acceptance criteria and reports covered / partial / missing; the key defaults to the ticket id in the branch name.

How it works

Config in ~/.pi/jira.json (chmod 600): site URL, account email, API token from https://id.atlassian.com/manage-profile/security/api-tokens. /jira auth prompts for the three values and validates them against /myself before saving. Descriptions and comments arrive as Atlassian Document Format and are converted to markdown-ish text (headings, lists, code blocks, tables, mentions, task lists).

When to use it

  • Any time a ticket id comes up: the model is prompted to fetch cards itself rather than asking for a paste.
  • Start-of-work ritual: /jira start KEY = branch + requirements checklist in one step.
  • Before opening the PR: /jira verify catches the "card asked for three things, branch does two" gap.

scope-guard

Structural enforcement of "only touch what the task is about". Exists because agents (especially delegated workers) kept editing files outside scope and staging junk like .pnpm-store/ into PRs.

What it does

  • Always on: edit/write into node_modules/, .pnpm-store/, or .git/ is blocked outright.
  • After every git add / git commit the staged file list is checked; junk paths (dist/, build/, .next/, .turbo/, coverage/, .DS_Store, *.log, plus the hard list) and out-of-scope files produce a warning appended to the bash tool result, so the model sees it and unstages before committing. You also get a UI notification.
  • With a declared scope, any edit/write outside it is blocked with a reason the model can read, so it has to ask instead of wandering.

How it works

A tool_call handler (blocking) and a tool_result handler (annotating). Scope is session-local state set by the /scope command: either explicit globs (/scope src/pages/** packages/api/**) or /scope branch, which snapshots the files already changed on the branch (vs merge-base with main) plus current dirty files. /scope off clears it; bare /scope shows it. A footer status chip shows when a scope is active.

When to use it

  • Junk protection needs nothing; it's on.
  • Declare a scope at the start of tightly-bounded work ("only the help docs", "only IssuesTracking"), the exact situations where scope creep bit before.

ci

GitHub Actions results for the current branch, in-context. Exists because CI failure logs kept getting copy-pasted by hand.

What it does

  • ci status lists recent workflow runs on the current branch with conclusions and run ids.
  • ci logs fetches the failed-step logs of the latest failed run (or a specific runId), truncated to the last 30KB.
  • /ci asks the model to check the branch, pull failing logs, and identify the root cause before touching anything.

How it works

Thin wrapper over gh run list / gh run view --log-failed executed in the repo cwd. Auth and repo resolution are whatever gh already has.

When to use it

After a push, or the moment anyone says "the check is failing". The model is prompted to reach for it instead of asking for a paste.


devwatch

Dev servers the agent can read, plus port management.

What it does

  • dev tool: start/stop/restart/list/logs for named dev servers. Servers spawn detached with output teed to ~/.pi/dev-logs/<name>.log, so they survive pi exiting and any session (or another tool) can read the same logs. logs supports errorsOnly (error lines plus stack context) and grep, so the agent pulls fresh errors itself instead of me copy-pasting stack traces.
  • ports tool: list TCP listeners with pid, command, and project cwd; kill by port or pid. /ports shows a quick toast.

When to use it

Have the agent start dev servers through dev rather than raw bash, then after changes it checks dev logs errorsOnly:true on its own. ports kill replaces "kill whatever is on 3003".


shot

/shot [n] [message] attaches the n most recent screenshots from the macOS screenshot folder (override with PI_SHOT_DIR) to your message, downscaling anything over ~1.5MB. For the times you want to show the agent something faster than describing it. With probe in place, prefer letting the agent take its own screenshots; /shot covers everything probe can't see (native apps, other windows, your phone photo synced to Desktop).


Notes

  • Secrets: all credentials live outside this repo in ~/.pi/probe.json and ~/.pi/jira.json (0600). Nothing in extensions/ contains a secret.
  • pi 0.82 image gotcha: tool results and user messages take images as {type:"image", data, mimeType}. Older extensions using the Anthropic-style source wrapper fail silently.
  • Verification recipe used for these: typecheck with a tsconfig whose paths map the pi package's dist/*.d.ts (moduleResolution bundler, allowImportingTsExtensions), a harness that loads each extension with a fake ExtensionAPI via node --experimental-strip-types, and a real pi -p load.

About

Personal extensions for the pi coding agent: review swarms, browser probe, Jira, scope guard, CI logs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

pi-extensions

Personal extensions for the pi coding agent. Built from an analysis of my own Claude Code and Codex session history: each one automates something I was demonstrably doing by hand, over and over.

ExtensionOne-linerUse it when
swarmCodex review swarms + parallel worktree fix lanesBefore shipping meaningful changes; when fixing a list of independent issues
probeHeadless-browser screenshots, console errors, failed-request bodiesVerifying UI changes, local-vs-staging parity, debugging 4xx/5xx
jiraJira via REST API token, including card attachment imagesAny card-shaped work: start, review, verify against acceptance criteria
scope-guardBlocks out-of-scope edits and junk commitsAlways on; declare a scope for tightly-bounded tasks
ciPull GitHub Actions failures for the current branchA check fails and you'd otherwise paste the log
devwatchDev servers with captured logs + port managementRunning dev servers the agent should be able to read
shotAttach recent screenshots to a messageQuickly showing the agent what you see

Install

Copy (or run ./install.sh, which does the same) into pi's user extension directory:

cp extensions/*.ts ~/.pi/agent/extensions/

Pi loads them on next start; /reload picks them up in a running session.

Requirements:

  • pi >= 0.82 (the ImageContent shape changed in 0.82 to {type, data, mimeType}; these extensions target the new shape)
  • macOS (uses sips for image downscaling and lsof in devwatch)
  • Codex CLI authenticated (codex on PATH) for swarm
  • GitHub CLI authenticated for ci
  • Chrome, Chromium, Arc, or a Playwright browser cache for probe (it auto-discovers ~/Library/Caches/ms-playwright builds)

No npm installs. Everything runs on Node builtins plus the packages pi already ships (typebox, @earendil-works/pi-ai).


swarm

My own take on pi-subagents + pi-worktree, merged into one pipeline and shaped around a workflow I used to run by hand: fan out independent read-only reviewers over a diff, verify every candidate finding, then fix the confirmed ones in parallel worktrees.

What it does

  • swarm review spawns one read-only codex exec lane per review angle. Eight angle presets: correctness, removed-behavior, cross-file, conventions, efficiency, reuse, simplification, altitude. Each lane reports up to 6 candidates in a strict line format. Candidates are deduped by file:line, then one verifier lane per candidate re-reads the code and returns CONFIRMED, PLAUSIBLE, or REFUTED with a reason. The aggregated report (confirmed first, ranked by severity) comes back as the tool result and is saved to ~/.pi/swarm/<run-id>/report.md.
  • swarm fix takes a list of independent items and creates one git worktree per item in a sibling directory <repo>-swarm/<slug> (branch swarm/<slug>), then runs a workspace-write codex lane in each. Lanes are instructed to stay in scope, commit nothing, and end with STATUS: done|partial|blocked — summary. The report shows each lane's status and git diff --stat; you review the worktree diffs and merge what you like.
  • swarm status / swarm kill / swarm clean inspect the run, kill every lane (including orphans from a crashed session, tracked in ~/.pi/swarm/running.json), and remove all swarm worktrees + branches.

How it works

Lanes are codex exec --json child processes in their own process groups, capped at 4 concurrent (PI_SWARM_CONCURRENCY), logging to ~/.pi/swarm/<run-id>/*.log. A widget above the editor shows lane progress, flags any lane silent for 3+ minutes as stalled, and a 30-minute hard timeout kills runaways. Default model is gpt-5.6-sol (PI_SWARM_MODEL or the model param to override). Reviewers and verifiers run with -s read-only; fix lanes get -s workspace-write scoped to their worktree. No coordination files ever land in the repo.

When to use it

  • /swarm review (optionally with notes) before committing or opening a PR on anything non-trivial. Add scope:'branch' to review the whole branch instead of the uncommitted diff, and pass both repo paths for paired-repo work.
  • /swarm fix after you've agreed on a list of independent fixes; the model derives the items from the conversation. One item per independent concern.
  • Not for single small fixes: the orchestration overhead isn't worth it, just fix it inline.

Commands:/swarm review [notes], /swarm fix [notes], /swarm status, /swarm kill, /swarm clean


probe

Lets the agent look at the running app itself instead of asking me to screenshot, open devtools, or paste network responses. This replaces the highest-volume manual loop in my history: screenshot local, screenshot staging, paste both, repeat.

What it does

  • snap navigates to a route, screenshots it, and returns the image plus console errors and failed requests (with response bodies) from the load.
  • parity captures the same route on local and staging and attaches both screenshots, first local then staging, for direct visual comparison.
  • errors skips the screenshot and just reports console exceptions/errors and failed request bodies, for "why is this 500ing" debugging.
  • config prints the resolved project config with the password redacted.

How it works

Zero dependencies: it launches an installed Chrome/Chromium with --headless=new --remote-debugging-port=0 and speaks the Chrome DevTools Protocol over Node's built-in WebSocket. If no system browser exists it falls back to the newest "Chrome for Testing" build in the Playwright cache. Base URLs, login credentials, and default routes live per project in ~/.pi/probe.json (created chmod 600 by /probe); projects are matched by cwd prefix. Each project gets a persistent Chrome profile under ~/.pi/probe/profiles/, so a login survives between calls, and when a page redirects to the login form the extension fills the configured selectors (with the native-setter trick so React controlled inputs register) and retries. Screenshots over ~1.5MB are downscaled via sips. A full http(s):// URL as route works without any project config.

When to use it

  • After UI changes: probe snap the affected route instead of asking "does it look right?".
  • Local-vs-staging drift: probe parity on the routes that differ.
  • Any browser-side failure (blank page, ChunkLoadError, failing fetch): probe errors reads the console and response bodies directly.

Setup: run /probe once to scaffold ~/.pi/probe.json, fill in URLs + test credentials. Keep real user credentials out of it; use dedicated test accounts.


jira

Jira over the plain REST API with an API token. Exists because the Atlassian MCP kept breaking OAuth and, worse, cannot see images attached to cards; this downloads attachments and hands them to the model as real images.

What it does

  • get pulls a card into context: summary, status, assignee, description (ADF converted to readable text), comments, and attachment images (downloaded with auth, downscaled, attached to the tool result so the model can read screenshots and mockups).
  • search runs a JQL query, comment adds a comment, create makes a new card (optionally under a parent/epic).
  • /jira SXCL-1234 pulls a card into the conversation. /jira start SXCL-1234 also has the agent create the branch off latest main (both repos in a paired-repo workspace). /jira verify [KEY] audits the current branch against the card's acceptance criteria and reports covered / partial / missing; the key defaults to the ticket id in the branch name.

How it works

Config in ~/.pi/jira.json (chmod 600): site URL, account email, API token from https://id.atlassian.com/manage-profile/security/api-tokens. /jira auth prompts for the three values and validates them against /myself before saving. Descriptions and comments arrive as Atlassian Document Format and are converted to markdown-ish text (headings, lists, code blocks, tables, mentions, task lists).

When to use it

  • Any time a ticket id comes up: the model is prompted to fetch cards itself rather than asking for a paste.
  • Start-of-work ritual: /jira start KEY = branch + requirements checklist in one step.
  • Before opening the PR: /jira verify catches the "card asked for three things, branch does two" gap.

scope-guard

Structural enforcement of "only touch what the task is about". Exists because agents (especially delegated workers) kept editing files outside scope and staging junk like .pnpm-store/ into PRs.

What it does

  • Always on: edit/write into node_modules/, .pnpm-store/, or .git/ is blocked outright.
  • After every git add / git commit the staged file list is checked; junk paths (dist/, build/, .next/, .turbo/, coverage/, .DS_Store, *.log, plus the hard list) and out-of-scope files produce a warning appended to the bash tool result, so the model sees it and unstages before committing. You also get a UI notification.
  • With a declared scope, any edit/write outside it is blocked with a reason the model can read, so it has to ask instead of wandering.

How it works

A tool_call handler (blocking) and a tool_result handler (annotating). Scope is session-local state set by the /scope command: either explicit globs (/scope src/pages/** packages/api/**) or /scope branch, which snapshots the files already changed on the branch (vs merge-base with main) plus current dirty files. /scope off clears it; bare /scope shows it. A footer status chip shows when a scope is active.

When to use it

  • Junk protection needs nothing; it's on.
  • Declare a scope at the start of tightly-bounded work ("only the help docs", "only IssuesTracking"), the exact situations where scope creep bit before.

ci

GitHub Actions results for the current branch, in-context. Exists because CI failure logs kept getting copy-pasted by hand.

What it does

  • ci status lists recent workflow runs on the current branch with conclusions and run ids.
  • ci logs fetches the failed-step logs of the latest failed run (or a specific runId), truncated to the last 30KB.
  • /ci asks the model to check the branch, pull failing logs, and identify the root cause before touching anything.

How it works

Thin wrapper over gh run list / gh run view --log-failed executed in the repo cwd. Auth and repo resolution are whatever gh already has.

When to use it

After a push, or the moment anyone says "the check is failing". The model is prompted to reach for it instead of asking for a paste.


devwatch

Dev servers the agent can read, plus port management.

What it does

  • dev tool: start/stop/restart/list/logs for named dev servers. Servers spawn detached with output teed to ~/.pi/dev-logs/<name>.log, so they survive pi exiting and any session (or another tool) can read the same logs. logs supports errorsOnly (error lines plus stack context) and grep, so the agent pulls fresh errors itself instead of me copy-pasting stack traces.
  • ports tool: list TCP listeners with pid, command, and project cwd; kill by port or pid. /ports shows a quick toast.

When to use it

Have the agent start dev servers through dev rather than raw bash, then after changes it checks dev logs errorsOnly:true on its own. ports kill replaces "kill whatever is on 3003".


shot

/shot [n] [message] attaches the n most recent screenshots from the macOS screenshot folder (override with PI_SHOT_DIR) to your message, downscaling anything over ~1.5MB. For the times you want to show the agent something faster than describing it. With probe in place, prefer letting the agent take its own screenshots; /shot covers everything probe can't see (native apps, other windows, your phone photo synced to Desktop).


Notes

  • Secrets: all credentials live outside this repo in ~/.pi/probe.json and ~/.pi/jira.json (0600). Nothing in extensions/ contains a secret.
  • pi 0.82 image gotcha: tool results and user messages take images as {type:"image", data, mimeType}. Older extensions using the Anthropic-style source wrapper fail silently.
  • Verification recipe used for these: typecheck with a tsconfig whose paths map the pi package's dist/*.d.ts (moduleResolution bundler, allowImportingTsExtensions), a harness that loads each extension with a fake ExtensionAPI via node --experimental-strip-types, and a real pi -p load.

About

Personal extensions for the pi coding agent: review swarms, browser probe, Jira, scope guard, CI logs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

pi-extensions

Personal extensions for the pi coding agent. Built from an analysis of my own Claude Code and Codex session history: each one automates something I was demonstrably doing by hand, over and over.

ExtensionOne-linerUse it when
swarmCodex review swarms + parallel worktree fix lanesBefore shipping meaningful changes; when fixing a list of independent issues
probeHeadless-browser screenshots, console errors, failed-request bodiesVerifying UI changes, local-vs-staging parity, debugging 4xx/5xx
jiraJira via REST API token, including card attachment imagesAny card-shaped work: start, review, verify against acceptance criteria
scope-guardBlocks out-of-scope edits and junk commitsAlways on; declare a scope for tightly-bounded tasks
ciPull GitHub Actions failures for the current branchA check fails and you'd otherwise paste the log
devwatchDev servers with captured logs + port managementRunning dev servers the agent should be able to read
shotAttach recent screenshots to a messageQuickly showing the agent what you see

Install

Copy (or run ./install.sh, which does the same) into pi's user extension directory:

cp extensions/*.ts ~/.pi/agent/extensions/

Pi loads them on next start; /reload picks them up in a running session.

Requirements:

  • pi >= 0.82 (the ImageContent shape changed in 0.82 to {type, data, mimeType}; these extensions target the new shape)
  • macOS (uses sips for image downscaling and lsof in devwatch)
  • Codex CLI authenticated (codex on PATH) for swarm
  • GitHub CLI authenticated for ci
  • Chrome, Chromium, Arc, or a Playwright browser cache for probe (it auto-discovers ~/Library/Caches/ms-playwright builds)

No npm installs. Everything runs on Node builtins plus the packages pi already ships (typebox, @earendil-works/pi-ai).


swarm

My own take on pi-subagents + pi-worktree, merged into one pipeline and shaped around a workflow I used to run by hand: fan out independent read-only reviewers over a diff, verify every candidate finding, then fix the confirmed ones in parallel worktrees.

What it does

  • swarm review spawns one read-only codex exec lane per review angle. Eight angle presets: correctness, removed-behavior, cross-file, conventions, efficiency, reuse, simplification, altitude. Each lane reports up to 6 candidates in a strict line format. Candidates are deduped by file:line, then one verifier lane per candidate re-reads the code and returns CONFIRMED, PLAUSIBLE, or REFUTED with a reason. The aggregated report (confirmed first, ranked by severity) comes back as the tool result and is saved to ~/.pi/swarm/<run-id>/report.md.
  • swarm fix takes a list of independent items and creates one git worktree per item in a sibling directory <repo>-swarm/<slug> (branch swarm/<slug>), then runs a workspace-write codex lane in each. Lanes are instructed to stay in scope, commit nothing, and end with STATUS: done|partial|blocked — summary. The report shows each lane's status and git diff --stat; you review the worktree diffs and merge what you like.
  • swarm status / swarm kill / swarm clean inspect the run, kill every lane (including orphans from a crashed session, tracked in ~/.pi/swarm/running.json), and remove all swarm worktrees + branches.

How it works

Lanes are codex exec --json child processes in their own process groups, capped at 4 concurrent (PI_SWARM_CONCURRENCY), logging to ~/.pi/swarm/<run-id>/*.log. A widget above the editor shows lane progress, flags any lane silent for 3+ minutes as stalled, and a 30-minute hard timeout kills runaways. Default model is gpt-5.6-sol (PI_SWARM_MODEL or the model param to override). Reviewers and verifiers run with -s read-only; fix lanes get -s workspace-write scoped to their worktree. No coordination files ever land in the repo.

When to use it

  • /swarm review (optionally with notes) before committing or opening a PR on anything non-trivial. Add scope:'branch' to review the whole branch instead of the uncommitted diff, and pass both repo paths for paired-repo work.
  • /swarm fix after you've agreed on a list of independent fixes; the model derives the items from the conversation. One item per independent concern.
  • Not for single small fixes: the orchestration overhead isn't worth it, just fix it inline.

Commands:/swarm review [notes], /swarm fix [notes], /swarm status, /swarm kill, /swarm clean


probe

Lets the agent look at the running app itself instead of asking me to screenshot, open devtools, or paste network responses. This replaces the highest-volume manual loop in my history: screenshot local, screenshot staging, paste both, repeat.

What it does

  • snap navigates to a route, screenshots it, and returns the image plus console errors and failed requests (with response bodies) from the load.
  • parity captures the same route on local and staging and attaches both screenshots, first local then staging, for direct visual comparison.
  • errors skips the screenshot and just reports console exceptions/errors and failed request bodies, for "why is this 500ing" debugging.
  • config prints the resolved project config with the password redacted.

How it works

Zero dependencies: it launches an installed Chrome/Chromium with --headless=new --remote-debugging-port=0 and speaks the Chrome DevTools Protocol over Node's built-in WebSocket. If no system browser exists it falls back to the newest "Chrome for Testing" build in the Playwright cache. Base URLs, login credentials, and default routes live per project in ~/.pi/probe.json (created chmod 600 by /probe); projects are matched by cwd prefix. Each project gets a persistent Chrome profile under ~/.pi/probe/profiles/, so a login survives between calls, and when a page redirects to the login form the extension fills the configured selectors (with the native-setter trick so React controlled inputs register) and retries. Screenshots over ~1.5MB are downscaled via sips. A full http(s):// URL as route works without any project config.

When to use it

  • After UI changes: probe snap the affected route instead of asking "does it look right?".
  • Local-vs-staging drift: probe parity on the routes that differ.
  • Any browser-side failure (blank page, ChunkLoadError, failing fetch): probe errors reads the console and response bodies directly.

Setup: run /probe once to scaffold ~/.pi/probe.json, fill in URLs + test credentials. Keep real user credentials out of it; use dedicated test accounts.


jira

Jira over the plain REST API with an API token. Exists because the Atlassian MCP kept breaking OAuth and, worse, cannot see images attached to cards; this downloads attachments and hands them to the model as real images.

What it does

  • get pulls a card into context: summary, status, assignee, description (ADF converted to readable text), comments, and attachment images (downloaded with auth, downscaled, attached to the tool result so the model can read screenshots and mockups).
  • search runs a JQL query, comment adds a comment, create makes a new card (optionally under a parent/epic).
  • /jira SXCL-1234 pulls a card into the conversation. /jira start SXCL-1234 also has the agent create the branch off latest main (both repos in a paired-repo workspace). /jira verify [KEY] audits the current branch against the card's acceptance criteria and reports covered / partial / missing; the key defaults to the ticket id in the branch name.

How it works

Config in ~/.pi/jira.json (chmod 600): site URL, account email, API token from https://id.atlassian.com/manage-profile/security/api-tokens. /jira auth prompts for the three values and validates them against /myself before saving. Descriptions and comments arrive as Atlassian Document Format and are converted to markdown-ish text (headings, lists, code blocks, tables, mentions, task lists).

When to use it

  • Any time a ticket id comes up: the model is prompted to fetch cards itself rather than asking for a paste.
  • Start-of-work ritual: /jira start KEY = branch + requirements checklist in one step.
  • Before opening the PR: /jira verify catches the "card asked for three things, branch does two" gap.

scope-guard

Structural enforcement of "only touch what the task is about". Exists because agents (especially delegated workers) kept editing files outside scope and staging junk like .pnpm-store/ into PRs.

What it does

  • Always on: edit/write into node_modules/, .pnpm-store/, or .git/ is blocked outright.
  • After every git add / git commit the staged file list is checked; junk paths (dist/, build/, .next/, .turbo/, coverage/, .DS_Store, *.log, plus the hard list) and out-of-scope files produce a warning appended to the bash tool result, so the model sees it and unstages before committing. You also get a UI notification.
  • With a declared scope, any edit/write outside it is blocked with a reason the model can read, so it has to ask instead of wandering.

How it works

A tool_call handler (blocking) and a tool_result handler (annotating). Scope is session-local state set by the /scope command: either explicit globs (/scope src/pages/** packages/api/**) or /scope branch, which snapshots the files already changed on the branch (vs merge-base with main) plus current dirty files. /scope off clears it; bare /scope shows it. A footer status chip shows when a scope is active.

When to use it

  • Junk protection needs nothing; it's on.
  • Declare a scope at the start of tightly-bounded work ("only the help docs", "only IssuesTracking"), the exact situations where scope creep bit before.

ci

GitHub Actions results for the current branch, in-context. Exists because CI failure logs kept getting copy-pasted by hand.

What it does

  • ci status lists recent workflow runs on the current branch with conclusions and run ids.
  • ci logs fetches the failed-step logs of the latest failed run (or a specific runId), truncated to the last 30KB.
  • /ci asks the model to check the branch, pull failing logs, and identify the root cause before touching anything.

How it works

Thin wrapper over gh run list / gh run view --log-failed executed in the repo cwd. Auth and repo resolution are whatever gh already has.

When to use it

After a push, or the moment anyone says "the check is failing". The model is prompted to reach for it instead of asking for a paste.


devwatch

Dev servers the agent can read, plus port management.

What it does

  • dev tool: start/stop/restart/list/logs for named dev servers. Servers spawn detached with output teed to ~/.pi/dev-logs/<name>.log, so they survive pi exiting and any session (or another tool) can read the same logs. logs supports errorsOnly (error lines plus stack context) and grep, so the agent pulls fresh errors itself instead of me copy-pasting stack traces.
  • ports tool: list TCP listeners with pid, command, and project cwd; kill by port or pid. /ports shows a quick toast.

When to use it

Have the agent start dev servers through dev rather than raw bash, then after changes it checks dev logs errorsOnly:true on its own. ports kill replaces "kill whatever is on 3003".


shot

/shot [n] [message] attaches the n most recent screenshots from the macOS screenshot folder (override with PI_SHOT_DIR) to your message, downscaling anything over ~1.5MB. For the times you want to show the agent something faster than describing it. With probe in place, prefer letting the agent take its own screenshots; /shot covers everything probe can't see (native apps, other windows, your phone photo synced to Desktop).


Notes

  • Secrets: all credentials live outside this repo in ~/.pi/probe.json and ~/.pi/jira.json (0600). Nothing in extensions/ contains a secret.
  • pi 0.82 image gotcha: tool results and user messages take images as {type:"image", data, mimeType}. Older extensions using the Anthropic-style source wrapper fail silently.
  • Verification recipe used for these: typecheck with a tsconfig whose paths map the pi package's dist/*.d.ts (moduleResolution bundler, allowImportingTsExtensions), a harness that loads each extension with a fake ExtensionAPI via node --experimental-strip-types, and a real pi -p load.

About

Personal extensions for the pi coding agent: review swarms, browser probe, Jira, scope guard, CI logs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

pi-extensions

Personal extensions for the pi coding agent. Built from an analysis of my own Claude Code and Codex session history: each one automates something I was demonstrably doing by hand, over and over.

ExtensionOne-linerUse it when
swarmCodex review swarms + parallel worktree fix lanesBefore shipping meaningful changes; when fixing a list of independent issues
probeHeadless-browser screenshots, console errors, failed-request bodiesVerifying UI changes, local-vs-staging parity, debugging 4xx/5xx
jiraJira via REST API token, including card attachment imagesAny card-shaped work: start, review, verify against acceptance criteria
scope-guardBlocks out-of-scope edits and junk commitsAlways on; declare a scope for tightly-bounded tasks
ciPull GitHub Actions failures for the current branchA check fails and you'd otherwise paste the log
devwatchDev servers with captured logs + port managementRunning dev servers the agent should be able to read
shotAttach recent screenshots to a messageQuickly showing the agent what you see

Install

Copy (or run ./install.sh, which does the same) into pi's user extension directory:

cp extensions/*.ts ~/.pi/agent/extensions/

Pi loads them on next start; /reload picks them up in a running session.

Requirements:

  • pi >= 0.82 (the ImageContent shape changed in 0.82 to {type, data, mimeType}; these extensions target the new shape)
  • macOS (uses sips for image downscaling and lsof in devwatch)
  • Codex CLI authenticated (codex on PATH) for swarm
  • GitHub CLI authenticated for ci
  • Chrome, Chromium, Arc, or a Playwright browser cache for probe (it auto-discovers ~/Library/Caches/ms-playwright builds)

No npm installs. Everything runs on Node builtins plus the packages pi already ships (typebox, @earendil-works/pi-ai).


swarm

My own take on pi-subagents + pi-worktree, merged into one pipeline and shaped around a workflow I used to run by hand: fan out independent read-only reviewers over a diff, verify every candidate finding, then fix the confirmed ones in parallel worktrees.

What it does

  • swarm review spawns one read-only codex exec lane per review angle. Eight angle presets: correctness, removed-behavior, cross-file, conventions, efficiency, reuse, simplification, altitude. Each lane reports up to 6 candidates in a strict line format. Candidates are deduped by file:line, then one verifier lane per candidate re-reads the code and returns CONFIRMED, PLAUSIBLE, or REFUTED with a reason. The aggregated report (confirmed first, ranked by severity) comes back as the tool result and is saved to ~/.pi/swarm/<run-id>/report.md.
  • swarm fix takes a list of independent items and creates one git worktree per item in a sibling directory <repo>-swarm/<slug> (branch swarm/<slug>), then runs a workspace-write codex lane in each. Lanes are instructed to stay in scope, commit nothing, and end with STATUS: done|partial|blocked — summary. The report shows each lane's status and git diff --stat; you review the worktree diffs and merge what you like.
  • swarm status / swarm kill / swarm clean inspect the run, kill every lane (including orphans from a crashed session, tracked in ~/.pi/swarm/running.json), and remove all swarm worktrees + branches.

How it works

Lanes are codex exec --json child processes in their own process groups, capped at 4 concurrent (PI_SWARM_CONCURRENCY), logging to ~/.pi/swarm/<run-id>/*.log. A widget above the editor shows lane progress, flags any lane silent for 3+ minutes as stalled, and a 30-minute hard timeout kills runaways. Default model is gpt-5.6-sol (PI_SWARM_MODEL or the model param to override). Reviewers and verifiers run with -s read-only; fix lanes get -s workspace-write scoped to their worktree. No coordination files ever land in the repo.

When to use it

  • /swarm review (optionally with notes) before committing or opening a PR on anything non-trivial. Add scope:'branch' to review the whole branch instead of the uncommitted diff, and pass both repo paths for paired-repo work.
  • /swarm fix after you've agreed on a list of independent fixes; the model derives the items from the conversation. One item per independent concern.
  • Not for single small fixes: the orchestration overhead isn't worth it, just fix it inline.

Commands:/swarm review [notes], /swarm fix [notes], /swarm status, /swarm kill, /swarm clean


probe

Lets the agent look at the running app itself instead of asking me to screenshot, open devtools, or paste network responses. This replaces the highest-volume manual loop in my history: screenshot local, screenshot staging, paste both, repeat.

What it does

  • snap navigates to a route, screenshots it, and returns the image plus console errors and failed requests (with response bodies) from the load.
  • parity captures the same route on local and staging and attaches both screenshots, first local then staging, for direct visual comparison.
  • errors skips the screenshot and just reports console exceptions/errors and failed request bodies, for "why is this 500ing" debugging.
  • config prints the resolved project config with the password redacted.

How it works

Zero dependencies: it launches an installed Chrome/Chromium with --headless=new --remote-debugging-port=0 and speaks the Chrome DevTools Protocol over Node's built-in WebSocket. If no system browser exists it falls back to the newest "Chrome for Testing" build in the Playwright cache. Base URLs, login credentials, and default routes live per project in ~/.pi/probe.json (created chmod 600 by /probe); projects are matched by cwd prefix. Each project gets a persistent Chrome profile under ~/.pi/probe/profiles/, so a login survives between calls, and when a page redirects to the login form the extension fills the configured selectors (with the native-setter trick so React controlled inputs register) and retries. Screenshots over ~1.5MB are downscaled via sips. A full http(s):// URL as route works without any project config.

When to use it

  • After UI changes: probe snap the affected route instead of asking "does it look right?".
  • Local-vs-staging drift: probe parity on the routes that differ.
  • Any browser-side failure (blank page, ChunkLoadError, failing fetch): probe errors reads the console and response bodies directly.

Setup: run /probe once to scaffold ~/.pi/probe.json, fill in URLs + test credentials. Keep real user credentials out of it; use dedicated test accounts.


jira

Jira over the plain REST API with an API token. Exists because the Atlassian MCP kept breaking OAuth and, worse, cannot see images attached to cards; this downloads attachments and hands them to the model as real images.

What it does

  • get pulls a card into context: summary, status, assignee, description (ADF converted to readable text), comments, and attachment images (downloaded with auth, downscaled, attached to the tool result so the model can read screenshots and mockups).
  • search runs a JQL query, comment adds a comment, create makes a new card (optionally under a parent/epic).
  • /jira SXCL-1234 pulls a card into the conversation. /jira start SXCL-1234 also has the agent create the branch off latest main (both repos in a paired-repo workspace). /jira verify [KEY] audits the current branch against the card's acceptance criteria and reports covered / partial / missing; the key defaults to the ticket id in the branch name.

How it works

Config in ~/.pi/jira.json (chmod 600): site URL, account email, API token from https://id.atlassian.com/manage-profile/security/api-tokens. /jira auth prompts for the three values and validates them against /myself before saving. Descriptions and comments arrive as Atlassian Document Format and are converted to markdown-ish text (headings, lists, code blocks, tables, mentions, task lists).

When to use it

  • Any time a ticket id comes up: the model is prompted to fetch cards itself rather than asking for a paste.
  • Start-of-work ritual: /jira start KEY = branch + requirements checklist in one step.
  • Before opening the PR: /jira verify catches the "card asked for three things, branch does two" gap.

scope-guard

Structural enforcement of "only touch what the task is about". Exists because agents (especially delegated workers) kept editing files outside scope and staging junk like .pnpm-store/ into PRs.

What it does

  • Always on: edit/write into node_modules/, .pnpm-store/, or .git/ is blocked outright.
  • After every git add / git commit the staged file list is checked; junk paths (dist/, build/, .next/, .turbo/, coverage/, .DS_Store, *.log, plus the hard list) and out-of-scope files produce a warning appended to the bash tool result, so the model sees it and unstages before committing. You also get a UI notification.
  • With a declared scope, any edit/write outside it is blocked with a reason the model can read, so it has to ask instead of wandering.

How it works

A tool_call handler (blocking) and a tool_result handler (annotating). Scope is session-local state set by the /scope command: either explicit globs (/scope src/pages/** packages/api/**) or /scope branch, which snapshots the files already changed on the branch (vs merge-base with main) plus current dirty files. /scope off clears it; bare /scope shows it. A footer status chip shows when a scope is active.

When to use it

  • Junk protection needs nothing; it's on.
  • Declare a scope at the start of tightly-bounded work ("only the help docs", "only IssuesTracking"), the exact situations where scope creep bit before.

ci

GitHub Actions results for the current branch, in-context. Exists because CI failure logs kept getting copy-pasted by hand.

What it does

  • ci status lists recent workflow runs on the current branch with conclusions and run ids.
  • ci logs fetches the failed-step logs of the latest failed run (or a specific runId), truncated to the last 30KB.
  • /ci asks the model to check the branch, pull failing logs, and identify the root cause before touching anything.

How it works

Thin wrapper over gh run list / gh run view --log-failed executed in the repo cwd. Auth and repo resolution are whatever gh already has.

When to use it

After a push, or the moment anyone says "the check is failing". The model is prompted to reach for it instead of asking for a paste.


devwatch

Dev servers the agent can read, plus port management.

What it does

  • dev tool: start/stop/restart/list/logs for named dev servers. Servers spawn detached with output teed to ~/.pi/dev-logs/<name>.log, so they survive pi exiting and any session (or another tool) can read the same logs. logs supports errorsOnly (error lines plus stack context) and grep, so the agent pulls fresh errors itself instead of me copy-pasting stack traces.
  • ports tool: list TCP listeners with pid, command, and project cwd; kill by port or pid. /ports shows a quick toast.

When to use it

Have the agent start dev servers through dev rather than raw bash, then after changes it checks dev logs errorsOnly:true on its own. ports kill replaces "kill whatever is on 3003".


shot

/shot [n] [message] attaches the n most recent screenshots from the macOS screenshot folder (override with PI_SHOT_DIR) to your message, downscaling anything over ~1.5MB. For the times you want to show the agent something faster than describing it. With probe in place, prefer letting the agent take its own screenshots; /shot covers everything probe can't see (native apps, other windows, your phone photo synced to Desktop).


Notes

  • Secrets: all credentials live outside this repo in ~/.pi/probe.json and ~/.pi/jira.json (0600). Nothing in extensions/ contains a secret.
  • pi 0.82 image gotcha: tool results and user messages take images as {type:"image", data, mimeType}. Older extensions using the Anthropic-style source wrapper fail silently.
  • Verification recipe used for these: typecheck with a tsconfig whose paths map the pi package's dist/*.d.ts (moduleResolution bundler, allowImportingTsExtensions), a harness that loads each extension with a fake ExtensionAPI via node --experimental-strip-types, and a real pi -p load.

About

Personal extensions for the pi coding agent: review swarms, browser probe, Jira, scope guard, CI logs

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages