@freibergergarcia/phone-a-friend
v4.0.0
Published
CLI relay that lets AI coding agents collaborate
Maintainers
Readme
phone-a-friend is a CLI orchestration layer for AI coding agents.
Relay tasks to any backend, spin up multi-model teams, or run persistent multi-agent sessions.
| Mode | What it does | Best for | |------|-------------|----------| | Relay | One-shot delegation to Codex, Gemini, Ollama, Claude, or OpenCode | Quick second opinions, code reviews, analysis | | Team | Iterative multi-backend refinement over N rounds | Collaborative review, converging on a solution | | Agentic | Persistent multi-agent sessions with @mention routing | Autonomous collaboration, adversarial review, deep analysis |
Host parity
| Feature | Claude Code | OpenCode | Codex |
|---|:---:|:---:|:---:|
| /phone-a-friend (single + parallel multi-backend relay) | ✓ | ✓ | ✓ |
| /curiosity-engine (Q&A rally) | ✓ | ✓ | ✓ |
| /phone-a-team (iterative multi-model team) | ✓ | — | ✓ |
| Plugin marketplace install | ✓ | — | ✓ |
| CLI plugin install (phone-a-friend plugin install --<host>) | ✓ | ✓ | ✓ |
| Skill auto-discovery | ✓ | ✓ | ✓ |
| Recursion guard (PHONE_A_FRIEND_HOST=<host>) | n/a | ✓ | ✓ |
Claude /phone-a-team orchestrates rounds via the Agent Teams primitive (TeamCreate + Task + SendMessage). Codex /phone-a-team is pure Bash orchestration directly from the skill body, with Codex's own model handling the synthesis between rounds. OpenCode has no comparable primitive and replicates /phone-a-team by running repeated /phone-a-friend calls manually.
[!IMPORTANT] Codex users: Codex's default
workspace-writesandbox blocks subprocess access to the macOS Keychain (where Claude stores OAuth tokens) and OAuth refresh network paths (Gemini). With the default sandbox, relays to Claude fail with a misleadingNot logged inand Gemini hangs until the timeout. Two workarounds today, both with tradeoffs:Option A — Lower the sandbox. Per-session (preferred): launch Codex with
codex --sandbox danger-full-access. Persistent (convenient but removes sandbox protections from every Codex session, not just PaF relays): add an alias to~/.zshrcor~/.bashrc:alias codex='codex --sandbox danger-full-access'Option B — Use API keys. Skips OAuth entirely, works in any sandbox:
export ANTHROPIC_API_KEY=... export GEMINI_API_KEY=...A portable-auth path via
claude setup-tokenis planned for the Claude side. Gemini OAuth refresh inside the sandbox is a separate open issue with no planned fix yet — until then, Option B is the only Gemini-safe path that keeps the sandbox intact.
Quick Start
Prerequisites: Node.js 22.13+ and at least one backend:
Install:
npm install -g @freibergergarcia/phone-a-friend
phone-a-friend # first run shows a guided menu — choose SetupThe setup wizard detects your backends, offers to install detected host integrations, and verifies everything works.
Claude Code marketplace (commands and skills only):
/plugin marketplace add freibergergarcia/phone-a-friend
/plugin install phone-a-friend@phone-a-friend-marketplaceTo update: /plugin marketplace update phone-a-friend-marketplace then /plugin update phone-a-friend@phone-a-friend-marketplace.
[!NOTE] Marketplace install ships only the slash commands and skills. For the full CLI (agentic mode and TUI), install via
npm install -g @freibergergarcia/phone-a-friend.
OpenCode commands and skills:
If you use OpenCode, install the same Phone-a-Friend skills plus thin slash-command shims into your OpenCode config:
phone-a-friend plugin install --opencodeThis installs to ~/.config/opencode/skills/ and ~/.config/opencode/commands/ (or $XDG_CONFIG_HOME/opencode/...). From OpenCode, ask naturally, for example:
Ask Codex through phone-a-friend for a short sanity review of this repo; do not edit files.Codex plugin (skills + marketplace registration):
If you use Codex CLI, install the Phone-a-Friend plugin two ways:
Via the Codex marketplace (visible in /plugins like Claude):
codex plugin marketplace add freibergergarcia/phone-a-friend
codex plugin add phone-a-friend@phone-a-friend-marketplaceOr via the PaF CLI (does both the marketplace registration AND drops skills into ~/.codex/):
phone-a-friend plugin install --codexThis installs phone-a-friend, curiosity-engine, and phone-a-team skills into $CODEX_HOME/skills/ (defaulting to ~/.codex/skills/). All three are orchestrated through pure Bash from the skill bodies — no Codex subagent primitive is required.
[!NOTE] Unlike Claude's marketplace, Codex marketplace install ships the skills directly —
codex plugin marketplace add+codex plugin addis sufficient to use/phone-a-friend,/curiosity-engine, and/phone-a-teamfrom inside Codex. For the full CLI (TUI and agentic mode), install vianpm install -g @freibergergarcia/phone-a-friend. Runningphone-a-friend plugin install --codexafter the npm install additionally drops loose-file skills under~/.codex/skills/as a no-marketplace fallback.
From Codex, ask naturally:
Ask Claude and Gemini through phone-a-friend what they think of this code.
Use phone-a-team across Claude and Gemini to converge on a fix for this auth bug. Three rounds max.From source:
git clone https://github.com/freibergergarcia/phone-a-friend.git
cd phone-a-friend
npm install && npm run build
./dist/index.js # first run guides you through setupThen from Claude Code or OpenCode, just talk naturally — the host integration loads the skills automatically:
Ask Gemini to review the error handling in relay.ts
Spin up Codex and Gemini to review the docs.
Then spin another agent to review their reviews and report back.
Build a team with Claude and Ollama. Have them review the website copy,
loop through 3 rounds, and converge on final suggestions.No slash commands needed once the host integration is installed (see Host parity for which slash commands work in which host).
[!TIP] Claude Code power-user setup: Run in tmux with bypass permissions (
⏵⏵) and Agent Teams to watch agents work in parallel split panes. Pair with phone-a-friend agentic mode for fully autonomous sessions.
CLI Usage
Relay
Delegate a task to any backend and get the result back:
phone-a-friend --to codex --prompt "Review this code"
phone-a-friend --to gemini --prompt "Analyze the architecture"
phone-a-friend --to claude --prompt "Refactor this module"
phone-a-friend --to ollama --prompt "Explain this function"
phone-a-friend --to opencode --prompt "Audit this repo" --model qwen3-coder # Local agentic (OpenCode + Ollama)
phone-a-friend --to claude --prompt "Review this code" --stream # Stream tokens live
phone-a-friend --to codex --prompt "Audit the auth module" --quiet # Run silently, save result
phone-a-friend --to opencode --prompt "Explain this" --fast # Skip OpenCode plugins (faster)
phone-a-friend --to codex --prompt "Review my fix" --include-diff # Append `git diff HEAD` to the prompt
phone-a-friend --to codex --prompt "Quick question" --no-include-diff # Override defaults.include_diff = trueStructured output
Request JSON responses matching a schema:
phone-a-friend --to codex --prompt "List files that need refactoring" \
--schema '{"type":"object","properties":{"files":{"type":"array","items":{"type":"string"}}},"required":["files"],"additionalProperties":false}'Claude, Codex, and Ollama enforce the schema through their native structured-output surfaces. Gemini and OpenCode CLI use prompt injection (best-effort), with PaF validating built-in verdict envelopes before returning them.
Sessions
Resume previous relay conversations for multi-turn workflows:
phone-a-friend --to codex --prompt "Review the auth module" --session auth-review
# Later, continue the conversation:
phone-a-friend --to codex --prompt "Now fix those issues" --session auth-reviewSessions work reliably with Claude, Codex, Gemini, and OpenCode. Ollama replays history (may hit token limits on long conversations). (Gemini resumes natively via --session-id/--resume; resume depends on Gemini's session retention.)
Job tracking
The --quiet flag saves the result to a local job store for later retrieval:
phone-a-friend --to codex --prompt "Review this" --quiet # Returns job ID immediately
phone-a-friend job status # List all jobs
phone-a-friend job result <id> # Show stored output
phone-a-friend job cancel <id> # Cancel a pending/running jobReview
Context-aware code reviews — automatically pulls the current git diff so you don't have to paste code:
phone-a-friend --to claude --review # Review current diff
phone-a-friend --to codex --review --base develop # Review against a specific branch
phone-a-friend --to opencode --review # Review with local model (reads repo via tools)--review is the diff-scoped review mode (uses the backend's native review path when available). For ad-hoc prompts where you want the working-tree diff appended, use --include-diff with normal prompt mode. To override a defaults.include_diff = true config setting on a single call, use --no-include-diff (or set PHONE_A_FRIEND_INCLUDE_DIFF=false in the environment for older binaries).
[!TIP] Don't paste code into
--promptjust to review it — the backend can read the repo directly via--repo "$PWD"(default: current working directory). Pasting risks leaking uncommitted edits and burns tokens for content the backend can fetch itself.
Agentic
Spawn multiple agents that collaborate via @mentions (see Agentic Mode below):
phone-a-friend agentic run --agents reviewer:claude,critic:claude --prompt "Review this code"
phone-a-friend agentic logs # View past sessions
phone-a-friend agentic replay --session <id> # Replay transcriptOps
phone-a-friend # Interactive TUI dashboard (TTY only)
phone-a-friend setup # Guided setup wizard
phone-a-friend doctor # Health check all backends + host install status
phone-a-friend plugin install --claude # Install Claude Code plugin
phone-a-friend plugin install --opencode # Install OpenCode commands and skills
phone-a-friend plugin install --codex # Install Codex skills
phone-a-friend config show # Show resolved config
phone-a-friend config edit # Open in $EDITORdoctor reports CLI backends, local backends (Ollama), host integration status (Claude / OpenCode / Codex plugin install state), and a summary count. The OpenCode CLI is treated as optional: if you only use Claude Code and don't have OpenCode installed, doctor will not flag that as a degraded state.
Update notifications
phone-a-friend checks the npm registry for newer stable releases at most once every 24 hours and prints a one-time stderr banner the next time it runs in an interactive terminal. The current invocation is never slowed down: the registry fetch happens in the background, with results applied on the next run.
Sample banner:
↑ phone-a-friend X.Y.Z available (current: A.B.C)
Run: npm install -g @freibergergarcia/phone-a-friend@latestThe banner is suppressed automatically when:
- stdout or stderr is not a TTY (piped or redirected output)
CIis set, orTERM=dumb- the command uses
--quiet,--schema,--verdict-json, or any subcommand-level--jsonflag - the same version was already shown within the last 7 days
To disable update checks entirely:
# One-off
PHONE_A_FRIEND_UPDATE_CHECK=false phone-a-friend ...
# Permanent
phone-a-friend config set defaults.update_check falseThe cache lives at ~/.config/phone-a-friend/update-check.json (or under
$XDG_CONFIG_HOME if set). Run phone-a-friend doctor to inspect the current
state.
Backends
| Backend | Type | Streaming | |---------|------|-----------| | Codex | CLI subprocess | No | | Gemini | CLI subprocess | No | | Ollama | HTTP API | Yes (NDJSON) | | Claude | CLI subprocess | Yes (JSON) | | OpenCode | CLI subprocess | Yes (NDJSON) |
Ollama configuration via environment variables:
OLLAMA_HOST-- custom host (default:http://localhost:11434)OLLAMA_MODEL-- default model (overridden by--modelflag)
Phone-a-friend environment variables:
PHONE_A_FRIEND_INCLUDE_DIFF=false-- disable diff inclusion globally (equivalent to--no-include-diffon every call).PHONE_A_FRIEND_HOST=opencode|codex-- mark the calling process as a specific host for the recursion guard.opencodeblocks--to opencode;codexblocks--to codex. Set automatically by the install shims.CODEX_HOME-- override the Codex config root (default:~/.codex). Honored by the Codex skill installer.PHONE_A_FRIEND_GEMINI_DEAD_CACHE=false-- bypass the Gemini dead-model cache (debugging stale entries).
OpenCode configuration via TOML:
[backends.opencode]
provider = "ollama" # model prefix (default: "ollama")
model = "qwen3-coder" # default model
pure = false # skip OpenCode plugins (maps to --fast)Streaming
Backends that support streaming deliver tokens as they arrive via --stream:
phone-a-friend --to claude --prompt "Review this code" --streamStreaming is enabled by default in the config (defaults.stream = true). Disable with --no-stream or config set defaults.stream false.
Agentic Mode
Let one agent review while another critiques — catching bugs, inconsistencies, and blind spots before you even see the code.
Agentic mode spawns multiple Claude agents that communicate via @mentions within a shared session. An orchestrator routes messages between agents, enforces guardrails, and persists the transcript for logs, replay, and TUI browsing.
Each agent accumulates context through persistent CLI sessions — later responses build on earlier ones, so agents develop genuine understanding of the problem as the session progresses.
[!IMPORTANT] Agentic mode currently supports Claude agents only. Codex, Gemini, OpenCode, and Ollama agents are not yet wired into the orchestrator. If you need multi-host adversarial review today, use
/phone-a-teaminstead — it does parallel multi-backend rounds with the same iterate-or-ship pattern, just without the persistent session graph. See AGENTS.md for the agentic architecture.
# Start an agentic session
phone-a-friend agentic run \
--agents reviewer:claude,critic:claude \
--prompt "Review the auth module"
# View past sessions and replay transcripts
phone-a-friend agentic logs
phone-a-friend agentic replay --session <id>What you get:
- Persistent sessions -- agents accumulate context across turns via UUID-based session resumption
- @mention routing -- agents address each other by name (
@ada.reviewer:), broadcast with@all, or surface findings with@user - Guardrails -- max turns (20), ping-pong detection, session timeout (15 min), turn budget warnings
- Full audit trail -- SQLite-backed transcript persistence for replay, logs, and post-session analysis
- Creative agent naming -- agents get memorable human names so you can follow the conversation
Documentation
Full usage guide, examples, CLI reference, and configuration details:
freibergergarcia.github.io/phone-a-friend
Uninstall
npm install:
npm uninstall -g @freibergergarcia/phone-a-friendAutomatically removes the Claude Code plugin (CLI-installed), OpenCode commands and skills, Codex skills, and the ~/.config/phone-a-friend directory (config, sessions, jobs).
[!WARNING]
npm uninstall -gdeletes~/.config/phone-a-friendentirely, including persisted session labels, the background job store, and agentic transcripts. Back up anything you want to keep before uninstalling. The agentic SQLite database at~/.config/phone-a-friend/agentic.dband any local config in~/.config/phone-a-friend/config.tomlare wiped along with it.
Claude Code marketplace:
/plugin uninstall phone-a-friend@phone-a-friend-marketplace
/plugin marketplace remove phone-a-friend-marketplaceContributing
All changes go through pull requests -- no direct pushes to main.
- Branch off main using a recognized prefix (see table below)
- Open a PR against
main-- a version label is auto-applied from the branch name - CI must pass before merge (includes label check)
- PRs are squash-merged (one commit per change, clean linear history)
- Head branches are auto-deleted after merge
- On merge, version is auto-bumped based on the label
Branch prefixes:
| Prefix | Label |
|--------|-------|
| fix/, bugfix/ | patch |
| chore/, docs/, ci/, refactor/ | patch |
| feat/, feature/ | minor |
| breaking/ | major |
Unrecognized prefixes require adding patch, minor, or major manually.
Development
npm install # Install dependencies
npm run build # Build dist/ (tsup)
npm test # Run tests (vitest)
npm run typecheck # Type check (tsc --noEmit)Privacy
Phone a Friend does not collect, transmit, or store any data on servers operated by this project. There is no telemetry and no analytics.
Prompts and repository context are passed only to backends you have installed and authenticated yourself: the Claude, Codex, Gemini, and OpenCode CLIs, or a local Ollama instance. Each backend is governed by its own provider's privacy policy and terms.
Local state (config, sessions, jobs, and agentic transcripts) is written only to ~/.config/phone-a-friend/ on your machine.
