pi-supacode
Pi extension that reports agent lifecycle hooks to Supacode via Unix domain socket
Package details
Install pi-supacode from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:pi-supacode- Package
pi-supacode- Version
0.1.1- Published
- Apr 17, 2026
- Downloads
- 258/mo · 6/wk
- Author
- dxvapor
- License
- MIT
- Types
- extension
- Size
- 17.5 KB
- Dependencies
- 0 dependencies · 0 peers
Pi manifest JSON
{
"extensions": [
"./index.ts"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
pi-supacode
A Pi extension that integrates with Supacode, reporting agent lifecycle status back to the Supacode macOS app via its Unix domain socket — the same mechanism used by the built-in Claude and Codex integrations.
What it does
When Pi runs inside a Supacode-managed terminal, this extension:
- Shows a busy indicator on the tab while Pi is working
- Fires a notification (bell + macOS system notification) when Pi finishes a turn, including the last assistant message as the notification body
- Clears the busy state on shutdown / session end
All of this happens automatically. If the Supacode environment variables are absent (i.e. Pi is running outside Supacode), the extension is a no-op.
Hook event mapping
| Pi event | Supacode message | Claude / Codex equivalent |
|---|---|---|
agent_start |
busy = 1 |
UserPromptSubmit |
agent_end |
busy = 0 + Stop notification |
Stop |
session_shutdown |
busy = 0 |
SessionEnd |
Prerequisites
- Pi — the coding agent this extension runs inside
- Supacode — the macOS app that manages your agent sessions
- Node.js ≥ 18 — already required by Pi; no extra install needed
- No npm dependencies — uses only
node:netfrom the Node.js standard library
Installation
Pi auto-discovers extensions from ~/.pi/agent/extensions/*/index.ts. The simplest install is a symlink (so you get updates via git pull):
# Clone
git clone https://github.com/DxVapor/pi-supacode.git ~/path/to/pi-supacode
# Symlink into Pi's global extension directory
ln -s ~/path/to/pi-supacode ~/.pi/agent/extensions/pi-supacode
Or copy directly:
cp -r ~/path/to/pi-supacode ~/.pi/agent/extensions/pi-supacode
Restart Pi (or run /reload inside an active session) to pick up the extension.
Alternative: project-local
To enable only for a specific repo, symlink into its .pi/extensions/ directory:
ln -s ~/path/to/pi-supacode /your/repo/.pi/extensions/pi-supacode
Alternative: settings.json
Add to ~/.pi/agent/settings.json:
{
"extensions": ["/absolute/path/to/pi-supacode"]
}
Usage
Open Pi inside a Supacode-managed terminal. The extension activates automatically — no configuration required.
Verify it's working: /supacode
The extension registers a /supacode diagnostic command you can run at any time:
/supacode
This will:
- Print the status of all four required environment variables
- Send a real busy pulse to the socket (watch the tab indicator flicker in Supacode)
- Send a test notification (check the notification bell on the worktree)
Example output when everything is wired up:
── Supacode env ──────────────────────────────────
SUPACODE_SOCKET_PATH ✓ /tmp/supacode-501/pid-12345
SUPACODE_WORKTREE_ID ✓ my-repo%2Ffeature-branch
SUPACODE_TAB_ID ✓ 550e8400-e29b-41d4-a716-446655440000
SUPACODE_SURFACE_ID ✓ 6ba7b810-9dad-11d1-80b4-00c04fd430c8
── Socket test ───────────────────────────────────
Socket send: ✓ (busy pulse sent — watch the tab indicator)
Notification: ✓ (check notification bell in Supacode)
Manual socket test (no Pi required)
From any Supacode terminal you can simulate the hook messages directly:
# Busy = 1
echo "$SUPACODE_WORKTREE_ID $SUPACODE_TAB_ID $SUPACODE_SURFACE_ID 1" \
| /usr/bin/nc -U -w1 "$SUPACODE_SOCKET_PATH"
# Busy = 0 + Stop notification
{ printf '%s pi\n' "$SUPACODE_WORKTREE_ID $SUPACODE_TAB_ID $SUPACODE_SURFACE_ID"
echo '{"hook_event_name":"Stop","last_assistant_message":"manual test"}'; } \
| /usr/bin/nc -U -w1 "$SUPACODE_SOCKET_PATH"
Watch macOS logs
log stream \
--predicate 'subsystem == "app.supabit.supacode" AND category == "AgentHookSocket"' \
--level debug
Supacode app integration (for contributors to Supacode)
The extension's socket messages are already handled transparently by AgentHookSocketServer — the agent string "pi" flows through without any Swift changes. For full first-class UI support (settings toggle, install/uninstall flow) the following additions are needed in the Supacode macOS app:
1. Add SkillAgent.pi
// SupacodeSettingsShared/Models/SkillAgent.swift
public enum SkillAgent: Equatable, Sendable, CaseIterable {
case claude
case codex
case pi // ← add
public var configDirectoryName: String {
switch self {
case .claude: ".claude"
case .codex: ".codex"
case .pi: ".pi"
}
}
}
2. Add PiSettingsClient following the ClaudeSettingsClient / CodexSettingsClient pattern. The "install" action symlinks this extension into ~/.pi/agent/extensions/.
3. No socket changes needed — AgentHookSocketServer already accepts arbitrary agent names.
How it works
Supacode injects four environment variables into every terminal it opens:
| Variable | Purpose |
|---|---|
SUPACODE_SOCKET_PATH |
Unix domain socket path (/tmp/supacode-<uid>/pid-<pid>) |
SUPACODE_WORKTREE_ID |
Percent-encoded worktree path |
SUPACODE_TAB_ID |
UUID of the terminal tab |
SUPACODE_SURFACE_ID |
UUID of the terminal surface |
The extension reads those on startup. If any are missing it returns immediately.
Busy flag wire format — single line, no JSON:
<worktreeID> <tabID> <surfaceID> 1|0\n
Notification wire format — header line + JSON body:
<worktreeID> <tabID> <surfaceID> pi\n
{"hook_event_name":"Stop","last_assistant_message":"..."}\n
These formats match AgentHookSettingsCommand.busyCommand() and AgentHookSettingsCommand.notificationCommand("pi") in the Supacode source, and are parsed by AgentHookSocketServer.parse().
Contributing
Contributions welcome. The codebase is a single TypeScript file with no build step.
git clone https://github.com/DxVapor/pi-supacode.git
cd pi-supacode
Areas to improve:
- Support for the
Notificationhook event (e.g.pi.on("message_end")for mid-session notifications) - Surface the worktree / session name in notification titles
- Tests using a mock Unix socket
Please open an issue before starting significant work so we can discuss approach. For small fixes and typos, PRs are welcome directly.
License
MIT — see LICENSE.