| name | phone-a-friend |
| description | Ask Antigravity, Codex, Gemini, Claude, OpenCode, or Ollama for a second opinion through the phone-a-friend CLI while preserving the user's request in --prompt. |
| argument-hint | ["optional review focus"] |
/phone-a-friend
Use this skill after an assistant reply you want reviewed by another AI.
Goal
Send compact task context + the latest assistant reply to a backend (Antigravity, Codex, Gemini, Claude, OpenCode, or Ollama) using phone-a-friend, then bring the feedback back into the current conversation.
Execution rules
- Preserve the user's actual request in
--prompt. Do not drop it.
- Do not run a bare
phone-a-friend --to <backend> --review unless the user
explicitly asks to review the current diff, branch changes, or staged changes.
- If the user asks for a repo sanity check, architecture opinion, plan critique,
or general second opinion, use normal prompt mode with
--repo "$PWD".
- If the user says not to edit files, keep that instruction in
--prompt.
- From OpenCode, do not select
opencode as the friend backend. Choose
antigravity, codex, gemini, claude, or ollama.
- From Codex, do not select
codex as the friend backend. Choose claude,
antigravity, gemini, opencode, or ollama. PaF enforces this with the same
PHONE_A_FRIEND_HOST recursion guard used for OpenCode.
- Suppress the working-tree diff by default (see "Diff suppression" below);
only include the diff when the user explicitly asked for a
diff/branch/staged review.
- One backend per call. Never pass comma-separated values to
--to (e.g.
phone-a-friend --to codex,gemini). To consult multiple models, run
separate phone-a-friend calls. In Claude Code, the /phone-a-team
slash command orchestrates that for you. In OpenCode, run multiple
separate phone-a-friend invocations yourself; /phone-a-team is not
available in OpenCode (it depends on Claude Agent Teams primitives that
OpenCode does not have).
curiosity-engine is a host slash command / Agent Skill, not a PaF CLI
subcommand. Never run phone-a-friend curiosity-engine. Same shape rule
applies to any other slash command: never invoke them as PaF
subcommands (e.g. phone-a-friend phone-a-team).
--backend is a /phone-a-team skill argument (Claude only), not a PaF
CLI flag. Do not pass --backend to phone-a-friend.
- When running inside OpenCode, always prefix relay invocations with
PHONE_A_FRIEND_HOST=opencode (recursion guard) AND
PHONE_A_FRIEND_INCLUDE_DIFF=false (diff suppression that works on
every shipped binary version). Do NOT use the $PAF_NO_DIFF
probe-and-gate pattern from OpenCode — small host models skip the
probe and inline --no-include-diff literally, which fails on stale
CLIs. The probe-and-gate is reserved for the rich orchestrator path
(Claude Code / capable orchestrators).
- When running inside Codex, prefix relay invocations with
PHONE_A_FRIEND_HOST=codex (recursion guard). Codex ships modern
PaF binaries, so the --no-include-diff flag works directly; the
env-var fallback is also fine if you prefer symmetry with OpenCode.
- When materializing relay commands, write dynamic prompt/context text into
temp files using single-quoted heredocs. Do not splice user text, prior
model output, or conversation context into double-quoted shell arguments.
- Do NOT dump repo files or git output into
--context-file or
--context-text. Repo-aware backends read files via --repo "$PWD"
using their own tools. See "Context hygiene" below.
For example, from OpenCode:
PHONE_A_FRIEND_HOST=opencode PHONE_A_FRIEND_INCLUDE_DIFF=false \
phone-a-friend --to codex --repo "$PWD" \
--prompt "Give a short sanity review of this repo. Do not edit files." \
--timeout 300 --no-stream --fast
Inputs
- Review focus (optional):
$ARGUMENTS
Host awareness
PaF blocks accidental host recursion (e.g.
OpenCode -> phone-a-friend --to opencode -> OpenCode,
Codex -> phone-a-friend --to codex -> Codex) using the
PHONE_A_FRIEND_HOST environment marker.
When running from OpenCode, always set PHONE_A_FRIEND_HOST=opencode on
every relay invocation. From Codex, set PHONE_A_FRIEND_HOST=codex. The
install shims set the marker automatically; be explicit when constructing
commands by hand. From Claude Code, the marker is not needed.
When running from OpenCode, do not select opencode as the friend backend.
Choose antigravity, codex, gemini, claude, or ollama.
When running from Codex, do not select codex as the friend backend. Choose
claude, antigravity, gemini, opencode, or ollama.
Relay mode
command -v phone-a-friend
- If found: set
RELAY_MODE = binary
- If not found: set
RELAY_MODE = direct
No hard abort. The skill continues either way.
Always resolve the binary via command -v phone-a-friend. Never invoke ./phone-a-friend from the current working directory, even when you are working inside the phone-a-friend repository itself. The repo's ./phone-a-friend script is a development entry point that may be out of sync with the user's installed version, and assuming it exists will fail every time you are run from anywhere else. Capture the path once and reuse it:
RELAY_BIN="$(command -v phone-a-friend)"
Codex sandbox awareness (critical when invoked from Codex)
If PHONE_A_FRIEND_HOST=codex, you are running inside Codex's shell-tool sandbox. By default, Codex uses workspace-write mode, which blocks subprocess access to the macOS Keychain and most outbound network, including:
- Claude's OAuth tokens (stored in macOS Keychain under
claude-token-personal / claude-token-work). A relay to Claude under workspace-write returns Not logged in · Please run /login even though the user is fully logged in. Reproducer: codex exec --sandbox workspace-write "claude -p 'hi'" fails; codex exec --sandbox danger-full-access "claude -p 'hi'" succeeds.
- Gemini's OAuth refresh path. A relay to Gemini under workspace-write hangs (until the relay's
--timeout fires) because Gemini cannot reach Google accounts to refresh the token.
- Antigravity's Google auth path. A relay to Antigravity can also time out under workspace-write; PaF prints Codex-specific remediation when this happens.
This is NOT a real auth issue. Telling the user to run claude /login is wrong — it would make things worse.
When you detect Not logged in from a Claude relay OR a Gemini/Antigravity timeout, and the host is Codex, tell the user exactly this:
Codex is sandboxing the relay. Run Codex with codex --sandbox danger-full-access (or codex --full-auto) so subprocess CLIs can reach the keychain and refresh OAuth tokens. Your Claude/Google CLI auth is fine; the sandbox is intercepting it.
Alternatives the user can take:
- Export an API key to skip OAuth entirely:
ANTHROPIC_API_KEY for Claude, GEMINI_API_KEY for Gemini, OPENAI_API_KEY for Codex.
- Approve the specific command escalation when Codex prompts (works for one-shots; tedious for multi-backend fan-outs).
For Codex users running PaF regularly, the cleanest setup is to start Codex with --sandbox danger-full-access for these workflows.
When relays do actually fail
If the relay still fails after the sandbox is opened up, the error is real. Surface the raw error to the user along with the remediation the relay itself printed. Do NOT retry on auth-class failures; the user has to act first.
Direct call reference
When RELAY_MODE = direct, call backend CLIs directly instead of using the
phone-a-friend binary:
| Backend | Direct command |
|---|
| Antigravity | agy --add-dir "$PWD" --print-timeout 300s --sandbox --mode plan --prompt "$(cat "$PROMPT_FILE")" |
| Codex | codex exec -C "$PWD" --skip-git-repo-check --sandbox read-only "$(cat "$PROMPT_FILE")" < /dev/null |
| Gemini | gemini --sandbox --yolo --include-directories "$PWD" --output-format text -m <model> --prompt "$(cat "$PROMPT_FILE")" |
In direct mode, build PROMPT_FILE from prompt + context using this
template and the quoted-heredoc rule:
You are helping another coding agent by reviewing or advising on work in a local repository.
Repository path: <repo-path>
Use the repository files for context when needed.
Respond with concise, actionable feedback.
Request:
<relay-prompt>
Additional Context:
<context-payload>
In direct mode, also verify the backend CLI is available (command -v agy,
command -v codex, or command -v gemini) before calling it. If not found,
tell the user how to install it and stop. If Gemini CLI reports that
individual Google sign-in is no longer supported, switch to
phone-a-friend --to antigravity in binary mode or use Gemini CLI with an
API key/Vertex flow.
Note: do NOT pass PaF flags like --no-include-diff, --fast, or
--session in direct mode. They are CLI flags on the phone-a-friend
binary; the underlying backend CLIs do not accept them.
Context hygiene
Do not generate --context-file or --context-text from repository files,
git show, git diff, git status, or other local file/git output. Do
not create temp files just to pass repo content. For repo-aware backends
(antigravity, codex, gemini, claude, opencode), pass --repo "$PWD" and let the
backend inspect files with its own tools.
--context-file and --context-text are reserved for narrative
context that is not already in the repo — for example: conversation
history that the backend cannot see, your own analysis, user constraints,
prior model output you want reviewed. These remain valid and useful.
Inlining repo content is wasteful, can leak tracked uncommitted edits or
committed secrets into the relay payload, and bypasses the backend's
normal file-access controls.
Backend exception: ollama has localFileAccess: false and cannot read
the repo on its own. For Ollama specifically, ask the user before sending
file content, and send a minimal excerpt rather than bulk-dumping files
or git output.
Diff suppression
PaF reads defaults.include_diff from user config. If a user has
include_diff = true set, every relay would silently leak the working-tree
diff into the prompt. Suppress the diff explicitly on every binary-mode
relay.
The cleanest flag is --no-include-diff, added in phone-a-friend v2.2.0.
Older binaries reject the flag with unknown option '--no-include-diff'.
Probe once at the start of the workflow, then reuse the gate:
if phone-a-friend relay --help 2>/dev/null | grep -q -- '--no-include-diff'; then
PAF_NO_DIFF="--no-include-diff"
else
export PHONE_A_FRIEND_INCLUDE_DIFF=false
PAF_NO_DIFF=""
fi
Append $PAF_NO_DIFF to every binary-mode phone-a-friend invocation. The
env var fallback works in v1.7.2 and later; the explicit flag is preferred
when available.
Only when the user explicitly asked to review the diff, branch changes, or
staged changes, swap $PAF_NO_DIFF for --include-diff (and prefer
phone-a-friend ... --review for branch-level reviews).
Workflow
- Identify:
- The latest relevant user request.
- The most recent assistant reply to review.
- Build relay prompt:
- If
$ARGUMENTS is non-empty: Review this response in context and provide your opinion. Focus: $ARGUMENTS
- Otherwise:
Review this response in context and provide your opinion. Focus on correctness, risks, and missing assumptions.
- Build context payload:
Task Context:
<latest relevant user request>
Assistant Response:
<latest assistant reply>
Review Request:
I'm working on this task and got the above response. Please review it and return:
1) Verdict: agree / partly agree / disagree
2) Corrections or risks
3) A revised concise answer
-
Run:
Binary mode (RELAY_MODE = binary):
RELAY_BIN="$(command -v phone-a-friend)"
PROMPT_FILE="$(mktemp)"
CONTEXT_FILE="$(mktemp)"
trap 'rm -f "$PROMPT_FILE" "$CONTEXT_FILE"' EXIT
cat > "$PROMPT_FILE" <<'PAF_PROMPT_EOF'
PAF_PROMPT_EOF
cat > "$CONTEXT_FILE" <<'PAF_CONTEXT_EOF'
PAF_CONTEXT_EOF
"$RELAY_BIN" --to codex --repo "$PWD" --prompt "$(cat "$PROMPT_FILE")" --context-file "$CONTEXT_FILE" $PAF_NO_DIFF [--fast] [--session ]
Antigravity is read-only and one-shot; do not add --session.
"$RELAY_BIN" --to antigravity --repo "$PWD" --sandbox read-only --prompt "$(cat "$PROMPT_FILE")" --context-file "$CONTEXT_FILE" $PAF_NO_DIFF [--fast]
For gemini, omit --model by default (let auto-routing pick); see "Gemini model selection" below.
Gemini supports --session via native resume (see "Session continuity" below):
"$RELAY_BIN" --to gemini --repo "$PWD" --prompt "$(cat "$PROMPT_FILE")" --context-file "$CONTEXT_FILE" $PAF_NO_DIFF [--fast] [--session ]
Use delimiter names that do not appear in the payload. The quoted heredoc
marker (`<<'PAF_PROMPT_EOF'`) is intentional: it makes shell treat the
body as data, not executable text.
`$PAF_NO_DIFF` comes from the probe in "Diff suppression" above. Swap
for `--include-diff` only when the user explicitly asked to review the
diff, branch changes, or staged changes (and prefer
`phone-a-friend ... --review` for branch-level reviews).
See "Speed optimization" and "Session continuity" below for when to
include `--fast` and `--session`.
**Direct mode** (`RELAY_MODE = direct`):
```bash
# Antigravity:
agy --add-dir "$PWD" --print-timeout 300s --sandbox --mode plan --prompt "$(cat "$PROMPT_FILE")"
# Codex:
codex exec -C "$PWD" --skip-git-repo-check --sandbox read-only "$(cat "$PROMPT_FILE")" < /dev/null
# Gemini (omit -m for auto-routing; pin only when reproducibility/capability is needed):
gemini --sandbox --yolo --include-directories "$PWD" --output-format text --prompt "$(cat "$PROMPT_FILE")"
In direct mode, build PROMPT_FILE from the template in the "Direct call
reference" section using the same quoted-heredoc rule, substituting
<relay-prompt> and <context-payload> into the file body.
Note: --fast, --session, and --no-include-diff are PaF CLI flags
only available in binary mode. Do not append them to direct-mode
invocations of agy, codex, or gemini.
- Return backend feedback in concise review format:
- Critical issues
- Important issues
- Suggested fixes
Speed optimization
When building binary-mode relay commands, add --fast if ALL of these are true:
- The relay prompt is self-contained (all needed context is in
--prompt
and/or --context-text)
- The task does NOT reference project conventions, coding standards, or
CLAUDE.md rules that the backend needs to read
- The task does NOT need MCP tools (GitHub API, Slack, database queries)
--fast maps to --pure for OpenCode, skipping external plugins. It is a
no-op for Antigravity, Claude, Codex, Gemini, and Ollama. Claude intentionally does not
use --bare because bare mode skips OAuth/keychain reads and can break
subscription auth.
Most /phone-a-friend relay calls are self-contained reviews where the
context is already in the prompt. Default to including --fast when the
backend may be OpenCode; it is harmless elsewhere.
Multi-backend parallel
When the user asks more than one backend in the same request (e.g. "ask claude and gemini X", "what does codex and ollama think about Y"), run all relays in parallel, not sequentially. Sequential calls feel slow even when each one is fast, and a single hung backend should not block the others.
Quick-question default: for casual, conversational questions (favourite colour, one-line opinion, sanity check) use --timeout 60. The relay's default is 600s, which is correct for code review and bad for "what's your fav colour" — a hung backend can stall the whole interaction. For longer tasks (code review, refactor advice) the default 600s is right; do not lower it.
Bash pattern (use this exactly when you have two or more backends to query):
RELAY_BIN="$(command -v phone-a-friend)"
PROMPT_FILE="$(mktemp)"
trap 'rm -f "$PROMPT_FILE" "$OUT_DIR"/*; rmdir "$OUT_DIR" 2>/dev/null || true' EXIT
OUT_DIR="$(mktemp -d)"
cat > "$PROMPT_FILE" <<'PAF_PROMPT_EOF'
<relay-prompt>
PAF_PROMPT_EOF
for BACKEND in claude gemini; do
PHONE_A_FRIEND_HOST=<your-host> PHONE_A_FRIEND_INCLUDE_DIFF=false \
"$RELAY_BIN" --to "$BACKEND" --repo "$PWD" \
--prompt "$(cat "$PROMPT_FILE")" \
--no-include-diff --timeout 60 --no-stream \
> "$OUT_DIR/$BACKEND.out" 2> "$OUT_DIR/$BACKEND.err" &
done
wait
After wait returns, every backend has either produced output or timed out at 60s. Read each $OUT_DIR/<backend>.out (or .err if the backend exited non-zero) and present the results as a compact markdown table:
| Backend | Answer |
|---|---|
| Claude | Blue. |
| Gemini | Electric cyan. |
If a backend failed or timed out, surface the error in the table cell so the user sees what happened ("(timed out after 60s)", "(not logged in)") rather than silently dropping that backend.
Host-specific notes:
- From Codex: set
PHONE_A_FRIEND_HOST=codex on every backgrounded call.
- From OpenCode: same with
opencode.
- From Claude: no host marker required, but the parallel-then-table pattern is the same.
- Never select
--to codex from Codex or --to opencode from OpenCode (the recursion guard refuses).
Session continuity
If this relay is a follow-up to a previous /phone-a-friend relay in the
same conversation (e.g., user asked for a review, saw the feedback, and now
wants the same backend to apply fixes or dig deeper), reuse the session:
- On the first relay in a conversation, generate a session ID:
paf-<backend>-<short-slug>-<4-char-random> (e.g.,
paf-codex-auth-review-a3f2). The random suffix prevents collisions
across repos and conversations.
- Add
--session <id> to the relay command.
- On subsequent relays to the same backend in the same
conversation, reuse the same session ID. The backend remembers previous
turns.
- If switching backends (e.g., first call to codex, second to ollama),
generate a new session ID for the new backend. Sessions are
backend-specific.
Benefits: the backend keeps full conversation history, so follow-up prompts
can be shorter (no need to re-send context from previous turns).
Backend-specific behavior:
- Antigravity: no session support yet. Do not add
--session or
--backend-session to Antigravity relay calls.
- Codex, Claude, OpenCode: native session resume. Follow-up prompts
can send deltas only.
- Ollama: replays full history each call. Sessions work but prompt
size grows with each turn. Keep follow-ups concise.
- Gemini: native session resume (same as Codex/Claude/OpenCode).
PaF generates the session UUID client-side, pins it with
--session-id
on the first call, and resumes with --resume later. Follow-up prompts
can send deltas only.
On the FIRST relay under a new session label, PaF prints an informational
stderr line: [phone-a-friend] Session label "..." not found in store. Starting a fresh session under this label. This is expected. The hint
about --backend-session in that line is for advanced use (see below)
and not relevant to the typical /phone-a-friend flow.
Omit --session for one-off relays where no follow-up is expected.
This is the common case. Only add --session when the user explicitly
asks for a follow-up or continuation of a previous relay.
Session continuity is only available in binary mode (RELAY_MODE = binary).
Advanced: --backend-session (raw thread ID adoption)
If the user explicitly provides a Codex/Claude/OpenCode backend thread ID
that PaF did not create (e.g., from another tool or a previous CLI run),
attach to it with --backend-session <id> instead of --session <id>.
Combine with --session <label> to also start tracking under a label.
phone-a-friend --to codex --repo "$PWD" --backend-session <thread-id> --prompt "<...>" $PAF_NO_DIFF
phone-a-friend --to codex --repo "$PWD" --session <label> --backend-session <thread-id> --prompt "<...>" $PAF_NO_DIFF
This is rarely the right move from inside a Claude Code conversation — the
common case is --session <label> with a fresh label. Only use
--backend-session when the user supplied a specific backend thread ID.
Antigravity vs Gemini CLI
Use --to antigravity when the user has the Google Antigravity CLI (agy)
or a consumer Google subscription path. PaF invokes it in read-only plan
mode with --sandbox --mode plan --add-dir "$PWD".
Use --to gemini for Gemini CLI flows that are still valid for the user
(API key, Vertex AI, or enterprise Gemini Code Assist). If Gemini CLI returns
"This client is no longer supported for Gemini Code Assist for individuals",
do not keep retrying Gemini OAuth; suggest Antigravity or API-key/Vertex
Gemini setup.
Gemini model selection
By default, omit --model for --to gemini and let Gemini CLI's
auto-routing pick the model. This mirrors how --to codex and --to claude
work in this skill — the CLI's own default is the right default. Pinning
--model ages docs poorly; auto-routing tracks deployed models for you.
When to pin --model explicitly
Set --model when you need:
- Reproducibility — pinning produces deterministic behavior across runs.
- Capability — choosing a more capable model for a specific task (e.g.,
--model gemini-2.5-pro for a hard review, accepting more 429s).
- Debugging — isolating model behavior from auto-routing changes.
When you do pin and the model returns a strong 404 (ModelNotFoundError),
PaF caches the model as unavailable for 24h at
~/.config/phone-a-friend/gemini-models.json and surfaces a clear error
that includes the cache path, expiry timestamp, and bypass instructions.
PaF does not auto-substitute another model — explicit pins surface
explicit failures so the caller decides whether to retry, switch model,
or omit --model and rely on auto-routing.
To bypass the cache (debugging stale entries or testing recovery):
PHONE_A_FRIEND_GEMINI_DEAD_CACHE=false phone-a-friend --to gemini --model X --prompt "..."
Or delete ~/.config/phone-a-friend/gemini-models.json to clear it.
Cache scope
- Cached (24h): strong 404 (
ModelNotFoundError from gemini-cli's own classifier).
- Not cached: ambiguous 404s (could be a missing project / file, not the model), 429 / RESOURCE_EXHAUSTED, authentication failures, any other error class.
- Not consulted: when
--model is unset (auto-routing), or during session resume (--resume).
Direct Gemini CLI mode (without phone-a-friend --to gemini)
When the orchestrator is calling gemini directly (no PaF wrapper), the
dead-model cache does NOT apply — the orchestrator is responsible for any
retry. In direct mode, retry rules:
- Retry: HTTP 429, 499, 500, 503, 504; RESOURCE_EXHAUSTED; transient/timeout errors.
- Do NOT retry: authentication failures, invalid arguments, permission errors, model-not-found.
- Default: if an error cannot be confidently classified as transient, surface it immediately.
This does NOT apply to --to codex or --to claude.
Notes
- Prefer
--context-text for small narrative payloads.
--context-file and --context-text are mutually exclusive.
- If your narrative context is too large for inline args, write it to a
temp file outside the repo (e.g. under
/tmp). Do NOT use a repo-local
temp file — it muddies git status and risks accidental commit. Repo
content itself does not need a temp file at all; see "Context hygiene"
above.