Approve, reject, or correct your AI coding agent's actions from your phone — a remote-approval relay for Claude Code's PreToolUse hook.
Project description
🛞 steerd
Approve, reject — or correct — your AI coding agent's actions from your phone.
Claude Code keeps asking for permission, so you either babysit the terminal or approve everything blindly. steerd lets you hold the reins from your phone: when the agent wants to run a tool, you get a push notification, tap a link, and Approve, Reject with a correction, or even edit the command — then it keeps going.
No native app. No forking Claude Code. It plugs into Claude Code's built-in
PreToolUse hook and relays the decision through a tiny self-hosted server.
⚠️ Alpha / work in progress. Core scaffold is in place; see HANDOFF.md for status and the build plan.
How it works
Claude Code (laptop)
└─ PreToolUse hook → steerd relay → push to your phone
└─ you tap: ✅ Approve · ❌ Reject (+ correction) · ✏️ Edit command
└─ decision returns to Claude → it proceeds, stops, or adjusts
- Approve → the tool runs.
- Reject + correction → blocked, and your note is fed back to Claude as guidance.
- Edit input → rewrites the command before it runs (
updatedInput). - Auto-allow read-only tools (Read/Glob/Grep) so you're only pinged for the risky stuff.
Quickstart (local loop)
# Recommended: install globally with pipx (isolated deps, command on PATH)
pipx install steerd # or: pip install --user steerd
# 1. run the relay
steerd-relay
# 2. register the hook in ~/.claude/settings.json (see examples/)
# ⚠️ use the ABSOLUTE path to the hook — see note below
# 3. get phone pushes via ntfy (free, no account):
export STEERD_NTFY_TOPIC="your-unique-topic-name"
# install the "ntfy" app and subscribe to that topic
Use the absolute path for the hook command in
settings.json. The Claude Desktop app spawns hooks with a limitedPATH, so a baresteerd-hookcan fail to resolve there. Find the real path withwhich steerd-hook(e.g.~/.local/bin/steerd-hookafter a pipx install) and use that exact path in the hook'scommand.
Now run Claude Code — when it wants to run a tool, your phone buzzes; tap the link and decide.
📱 Using a real phone (not localhost)? See DEPLOY.md for exposing the relay via Tailscale / Cloudflare Tunnel / ngrok — and always set
STEERD_TOKENwhen you do.
Config (env vars)
| Var | Default | Purpose |
|---|---|---|
STEERD_TOKEN |
— | shared secret protecting the relay — set this before exposing the relay beyond localhost |
STEERD_RELAY_URL |
http://127.0.0.1:8787 |
where the hook reaches the relay |
STEERD_PUBLIC_URL |
= relay url | public link used in the push (use a tunnel/VPS for a remote phone) |
STEERD_TIMEOUT |
300 |
seconds to wait for a decision (keep < hook's 600s) |
STEERD_ON_TIMEOUT |
deny |
fallback if no answer: deny or allow |
STEERD_NTFY_TOPIC |
— | ntfy topic for push |
STEERD_TELEGRAM_BOT_TOKEN / _CHAT_ID |
— | Telegram backend (alt to ntfy) |
STEERD_AUTO_ALLOW |
Read,Glob,Grep,LS |
tools approved without pinging the phone |
Where to enable it (scope)
Install once, run one relay — then where you register the hook decides what it guards. It plugs into Claude Code's PreToolUse hook and works with both the Claude Desktop app and the CLI (both read these settings).
| Put the hook in… | Guards | Use for |
|---|---|---|
~/.claude/settings.json (global) |
every session, every project | supervise all agent shell commands |
<project>/.claude/settings.json (project) |
only sessions opened in that project | guard one repo (prod / infra / trading) |
<project>/.claude/settings.local.json (local) |
that project, just you (uncommitted) | personal, per-repo |
- A session loads hooks at startup, and only from its project root — not subfolders. Open the session in the folder whose settings has the hook, and restart after editing settings.
- Only Bash is gated by the example matcher; read-only tools are auto-approved — so you're pinged for shell commands, not every file read.
- Recommended: per-project on sensitive repos for day-to-day work; global when you're letting an agent run on its own.
Gotchas
- Long-running servers block. Approving
npm run devmakes Claude's terminal wait on a process that never exits — that's normal, not steerd. Ask Claude to start servers in the background. - Keep the relay up. If it's down, gated commands fall back to Claude's normal in-app prompt (graceful, not broken). For always-on, run the relay as a service — see DEPLOY.md.
Why not just…
--dangerously-skip-permissions? That approves everything, blind. This keeps you in control of the risky calls only.- Allowlists in settings.json? Great for known-safe commands — use both. steerd covers the unpredictable calls you can't pre-list, while away from the keyboard.
- A mobile app? Unnecessary — a push + web page does the job and stays installable in seconds.
Status & roadmap
Core relay + hook are scaffolded. Next: tests + CI, a remote-tunnel guide, an auth token on the relay, and a demo. See HANDOFF.md.
- End-to-end tested in Claude Code with phone approval
- Auth token on relay endpoints
- Tunnel/VPS guide for remote phones
- Demo GIF
- Support more agents (Cursor, Cline) via the same relay
License
MIT © Kannan Dharmalingam
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file steerd-0.1.0.tar.gz.
File metadata
- Download URL: steerd-0.1.0.tar.gz
- Upload date:
- Size: 16.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
12edf489ab6733ea8f7df3b5a57ae1d1f74cad071610b4bab68a5d57905fb29c
|
|
| MD5 |
5339c9f8f8d3c9c3e58f28b0102fb4a0
|
|
| BLAKE2b-256 |
bcad363cb8b4f79f549e7f19c738d82d0fc116a75085e67c91d640beea593cec
|
File details
Details for the file steerd-0.1.0-py3-none-any.whl.
File metadata
- Download URL: steerd-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42c171463d90144aeba89a3ad61614b0476d2fa5923b265e804ad48c445b69dc
|
|
| MD5 |
1ab4ca0433aae7a67cef3d3c86e81e12
|
|
| BLAKE2b-256 |
c7f5488facb377af3e31deb11fe81fa68a5ea216d2725b98157edeb20ad2670a
|