phone-a-friend-paf
Phone a Friend lets Claude Code call other AI coding backends for second opinions, code review, and multi-agent collaboration. It relays you
Open source Open in the app JSON README (API)
About
Phone a Friend lets Claude Code call other AI coding backends for second opinions, code review, and multi-agent collaboration. It relays your prompt and repository context to Codex, Gemini, OpenCode, or local Ollama models, then brings the response back into your Claude session. Includes streaming, structured JSON output, session continuity, multi-agent orchestration with a web dashboard, and an interactive TUI. Useful when you want a different model's perspective without leaving Claude Code.
Details
- Kind
- Plugins
- Topic
- AI, RAG & memory
- Publisher
- freibergergarcia
- Origin
- marketplace
- Category
- ferramentas
- Stars
- 10
- Forks
- 2
- Open pull requests
- 3
- Last push
- 2026-09-01T06:39:18Z
- Repository state
- ativo
- Language
- TypeScript
- License
- Apache-2.0
- Added
- 2026-08-30 01:48:58
- Updated
- 2026-08-30 01:48:58
- Origin id
freibergergarcia/phone-a-friend/phone-a-friend-paf
README
<div align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/freibergergarcia/phone-a-friend/main/assets/logo-dark.svg">
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/freibergergarcia/phone-a-friend/main/assets/logo-light.svg">
<img alt="phone-a-friend" src="https://raw.githubusercontent.com/freibergergarcia/phone-a-friend/main/assets/logo-dark.svg" width="480">
</picture>
<p><em>When your AI needs a second opinion.</em></p>
[](https://www.npmjs.com/package/@freibergergarcia/phone-a-friend)
[](https://github.com/freibergergarcia/phone-a-friend/actions/workflows/ci.yml)
[](LICENSE)

</div>
`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 Antigravity, 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-write` sandbox blocks subprocess access to the macOS Keychain (where Claude stores OAuth tokens) and OAuth refresh network paths (Gemini and Antigravity). With the default sandbox, relays to Claude fail with a misleading `Not logged in` and Google CLI relays can hang 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 `~/.zshrc` or `~/.bashrc`:
> ```bash
> alias codex='codex --sandbox danger-full-access'
> ```
>
> **Option B — Use API keys for API-key backends.** Skips OAuth entirely for Claude/Gemini CLI, works in any sandbox:
> ```bash
> export ANTHROPIC_API_KEY=...
> export GEMINI_API_KEY=...
> ```
>
> A portable-auth path via `claude setup-token` is planned for the Claude side. Antigravity uses `agy` subscription auth, so the current Antigravity-safe path from Codex is Option A or running PaF from a regular terminal.
## Quick Start
**Prerequisites:** Node.js 22.13+ and at least one backend:
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code/setup)
- [Google Antigravity CLI](https://antigravity.google/) (`agy`) for Google AI Pro/Ultra or consumer Google accounts
- [Codex CLI](https://developers.openai.com/codex/quickstart/)
- [Gemini CLI](https://github.com/google-gemini/gemini-cli) for API key, Vertex AI, or enterprise Gemini Code Assist flows
- [Ollama](https://ollama.com/download)
- [OpenCode](https://opencode.ai/docs)
**Install:**
```bash
npm install -g @freibergergarcia/phone-a-friend
phone-a-friend # first run shows a guided menu — choose Setup
```
The 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-marketplace
```
To 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](https://opencode.ai/docs), install the same Phone-a-Friend skills plus thin slash-command shims into your OpenCode config:
```bash
phone-a-friend plugin install --opencode
```
This 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](https://developers.openai.com/codex/quickstart/), 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-marketplace
```
Or via the PaF CLI (does both the marketplace registration AND drops skills into `~/.codex/`):
```bash
phone-a-friend plugin install --codex
```
This 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 add` is sufficient to use `/phone-a-friend`, `/curiosity-engine`, and `/phone-a-team` from inside Codex. For the full CLI (TUI and agentic mode), install via `npm install -g @freibergergarcia/phone-a-friend`. Running `phone-a-friend plugin install --codex` after 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:**
```bash
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 setup
```
Then 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](#host-parity) for which slash commands work in which host).
> [!TIP]
> **Claude Code power-user setup:** Run in [**tmux**](https://formulae.brew.sh/formula/tmux) with [**bypass permissions**](https://docs.anthropic.com/en/docs/claude-code/security) (`⏵⏵`) and [**Agent Teams**](https://docs.anthropic.com/en/docs/claude-code/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:
```bash
phone-a-friend --to codex --prompt "Review this code"
phone-a-friend --to antigravity --prompt "Review this code" --sandbox read-only
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 = true
phone-a-friend --to claude --prompt "Coordinate with the migration session" --peer-messaging accept
```
### Structured output
Request JSON responses matching a schema:
```bash
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. Antigravity, 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:
```bash
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-review
```
Sessions work reliably with Claude, Codex, Gemini, and OpenCode. Ollama replays history (may hit token limits on long conversations). Antigravity is one-shot only in this release, so `--session` is rejected for `--to antigravity`.
### Claude peer messaging
On supported macOS and Linux setups, Claude Code 2.1.224+ can list and message
other live Claude Code sessions on the same machine. PaF exposes that
capability deliberately for Claude relays:
```bash
# Use Claude's native inbound policy while allowing peer discovery/messages (default)
phone-a-friend --to claude --prompt "Ask the payments session for its status" \
--peer-messaging native --session payments-coordinator
# Deliver peer messages to the unattended PaF worker immediately
phone-a-friend --to claude --prompt "Coordinate the migration" \
--peer-messaging accept --session migration-coordinator
# Isolate this relay from peer messaging in both directions
phone-a-friend --to claude --prompt "Review privately" --peer-messaging refuse
```
`native` is the default: PaF makes `ListAgents` and `SendMessage` available but
leaves inbound delivery to Claude Code's own permission-mode rules. `accept`
sets `crossSessionInbound` to `accept`, which is the autonomy-first choice for
unattended workers. `refuse` rejects inbound messages and removes the peer
tools. Peer-visible workers are named from the PaF session label, such as
`paf-migration-coordinator`; one-shot relays use `paf-relay`.
Set your preferred mode once:
```bash
phone-a-friend config set backends.claude.peer_messaging accept
```
### Job tracking
The `--quiet` flag saves the result to a local job store for later retrieval:
```bash
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 job
```
### Review
Context-aware code reviews collect an explicit Git scope so you don't have to paste code:
```bash
phone-a-friend --to claude --review # Committed branch changes (default)
phone-a-friend --to codex --review --review-scope working-tree # Staged, unstaged, and untracked
phone-a-friend --to opencode --review --review-scope all # Branch plus working-tree changes
phone-a-friend --to codex --review --base develop # Use a specific comparison branch
```
| `--review-scope` | Included changes |
|---|---|
| `branch` (default) | Committed changes from the merge base with `--base` through `HEAD` |
| `working-tree` | Staged, unstaged, and non-ignored untracked files relative to `HEAD` |
| `all` | Branch changes plus staged, unstaged, and non-ignored untracked files |
Pass a repository root, linked Git worktree, or any directory inside one through
`--repo <path>`; review mode normalizes it to the containing worktree root before
collecting changes. Before the first commit, `working-tree` and `all` compare
pending files against Git's empty tree. PaF collects and bounds the selected
scope before any native or generic backend call, so the normal diff size limit
always applies. When PaF supplies a generic diff, untracked binary files use a
binary-change marker instead of raw bytes.
If the selected scope is clean, PaF does not invoke a backend. Plain review
returns `No changes found for review scope "<scope>".`; `--verdict-json` returns
a valid `abstain` envelope with no findings. Native review is used only when the
backend supports the selected non-empty scope; otherwise PaF supplies the
deterministic diff through the generic path.
`--include-diff` remains available for normal prompt mode. It cannot be combined with review mode; select `working-tree` or `all` instead. To override a `defaults.include_diff = true` config setting on a normal relay, use `--no-include-diff` (or set `PHONE_A_FRIEND_INCLUDE_DIFF=false` in the environment for older binaries).
> [!TIP]
> Don't paste code into `--prompt` just 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](#agentic-mode) below):
```bash
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 transcript
```
### Ops
```bash
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 $EDITOR
```
`doctor` reports CLI backends, local backends (Ollama), host integration status (Claude / OpenCode / Codex plugin install state), and a summary count. Antigravity and OpenCode CLI are treated as optional: if you don't have `agy` or OpenCode installed, doctor will show them but 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@latest
```
The banner is suppressed automatically when:
- stdout or stderr is not a TTY (piped or redirected output)
- `CI` is set, or `TERM=dumb`
- the command uses `--quiet`, `--schema`, `--verdict-json`, or any subcommand-level `--json` flag
- the same version was already shown within the last 7 days
To disable update checks entirely:
```bash
# One-off
PHONE_A_FRIEND_UPDATE_CHECK=false phone-a-friend ...
# Permanent
phone-a-friend config set defaults.update_check false
```
The 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 |
|---------|------|-----------|
| **Antigravity** | CLI subprocess (`agy`) | No |
| **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 `--model` flag)
Claude configuration via TOML:
```toml
[backends.claude]
peer_messaging = "native" # native (default), accept, or refuse
```
Phone-a-friend environment variables:
- `PHONE_A_FRIEND_INCLUDE_DIFF=false` -- disable diff inclusion globally (equivalent to `--no-include-diff` on every call).
- `PHONE_A_FRIEND_CLAUDE_PEER_MESSAGING=native|accept|refuse` -- override Claude peer messaging for the current process.
- `PHONE_A_FRIEND_HOST=opencode|codex` -- mark the calling process as a specific host for the recursion guard. `opencode` blocks `--to opencode`; `codex` blocks `--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).
Antigravity notes:
- PaF backend name: `antigravity`; executable: `agy`.
- Antigravity is read-only only for now. Plain `--to antigravity` calls resolve
to `read-only`; explicit write sandboxes such as `--sandbox workspace-write`
are rejected.
- `--session` and `--backend-session` are not supported yet.
- If Gemini CLI says individual Google sign-in is no longer supported, use `--to antigravity` for the Google subscription path or use Gemini CLI with an API key/Vertex flow.
OpenCode configuration via TOML:
```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`:
```bash
phone-a-friend --to claude --prompt "Review this code" --stream
```
Streaming 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-team` instead — it does parallel multi-backend rounds with the same iterate-or-ship pattern, just without the persistent session graph. See [AGENTS.md](AGENTS.md) for the agentic architecture.
```bash
# 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](https://freibergergarcia.github.io/phone-a-friend/)**
## Uninstall
**npm install:**
```bash
npm uninstall -g @freibergergarcia/phone-a-friend
```
Automatically 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 -g` deletes `~/.config/phone-a-friend` entirely, 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.db` and any local config in `~/.config/phone-a-friend/config.toml` are wiped along with it.
**Claude Code marketplace:**
```
/plugin uninstall phone-a-friend@phone-a-friend-marketplace
/plugin marketplace remove phone-a-friend-marketplace
```
## Contributing
All changes go through pull requests -- no direct pushes to `main`.
1. **Branch off main** using a recognized prefix (see table below)
2. **Open a PR** against `main` -- a version label is auto-applied from the branch name
3. **CI must pass** before merge (includes label check)
4. PRs are **squash-merged** (one commit per change, clean linear history)
5. Head branches are auto-deleted after merge
6. 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
```bash
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, Antigravity, 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.
## License
Apache-2.0. See [`LICENSE`](LICENSE) and [`NOTICE`](NOTICE).