Pi coding agent
Human-in-the-loop for pi, in one command.
Pi is a terminal
coding agent. It has no built-in MCP support, so
ping-a-human-pi ships a tiny embedded MCP client that connects
ping-a-human to pi's hooks.
Install
npx ping-a-human-pi This single command:
- installs a pi extension into
~/.pi/agent/extensions/ping-a-human-pi/, - installs the
pahCLI onto your PATH, - seeds
~/.pi/agent/ping-a-human.jsonwith defaults (never overwrites an existing one).
Run /reload in pi (or restart it). Remove everything with
npx ping-a-human-pi uninstall.
First time with ping-a-human? Configure Telegram once with
npx ping-a-human setup.
What you get
- Tools —
notify_humanandask_humanbecome native pi tools the model can call. - Notifications — a Telegram ping with a short summary when each task finishes (pi's
agent_endhook). - Approval — before risky tool calls (pi's
tool_callhook), pi asks viaask_humanand blocks unless you approve. Off by default. /pingcommand — inside pi:/pingor/ping your message.pahCLI — from any terminal, independent of pi.
The pah CLI
pah ping "build finished" # fire-and-forget notification
pah notify "deploy started" # alias for ping
pah ask "ship to prod?" # waits and prints the human's reply
pah help
Because pah ask prints the reply to stdout, you can branch on it
in scripts:
if pah ask "deploy to prod?" | grep -qiE '^(y|yes|ok|approve)'; then
./deploy.sh
fi Configuration
All optional — edit ~/.pi/agent/ping-a-human.json:
| Key | Default | Meaning |
|---|---|---|
command / args | npx -y ping-a-human | how to launch the server |
exposeTools | true | register notify_human / ask_human as model-callable tools |
notify.enabled | true | ping you when a task finishes |
notify.template | ✅ pi finished a task in {cwd}… | message text; {summary} {cwd} substituted |
approval.enabled | false | ask before risky tool calls |
approval.tools | ["bash"] | which pi tools to gate |
approval.patterns | danger regexes | only gate calls whose args match one; empty = gate all |
A reply matching yes/ok/approve/allow/sure/go/lgtm/… approves;
anything else blocks the call, and the reason is sent back to the model.