From Phone a Friend
Sends the current assistant reply and user request to another AI (Codex, Gemini, Claude, or Ollama) for a second opinion, then brings the feedback back into the conversation.
How this skill is triggered — by the user, by Claude, or both
Slash command
/phone-a-friend:phone-a-friendThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Use this skill after an assistant reply you want reviewed by another AI.
Use this skill after an assistant reply you want reviewed by another AI.
Send compact task context + the latest assistant reply to a backend (Codex, Gemini, or Ollama) using phone-a-friend, then bring the feedback back into the current conversation.
--prompt. Do not drop it.phone-a-friend --to <backend> --review unless the user
explicitly asks to review the current diff, branch changes, or staged changes.--repo "$PWD".--prompt.opencode as the friend backend. Choose codex,
gemini, claude, or ollama.codex as the friend backend. Choose claude,
gemini, opencode, or ollama. PaF enforces this with the same
PHONE_A_FRIEND_HOST recursion guard used for OpenCode.--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.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).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.--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
$ARGUMENTSPaF 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 codex, gemini, claude, or ollama.
When running from Codex, do not select codex as the friend backend. Choose
claude, gemini, opencode, or ollama.
command -v phone-a-friend
RELAY_MODE = binaryRELAY_MODE = directNo 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)"
# Then every relay invocation uses "$RELAY_BIN" ... — never plain "phone-a-friend"
# from PATH lookup and never "./phone-a-friend".
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-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.--timeout fires) because Gemini cannot reach Google accounts to refresh the token.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 timeout, and the host is Codex, tell the user exactly this:
Codex is sandboxing the relay. Run Codex with
codex --sandbox danger-full-access(orcodex --full-auto) so subprocess CLIs can reach the keychain and refresh OAuth tokens. Your Claude/Gemini auth is fine; the sandbox is intercepting it.
Alternatives the user can take:
ANTHROPIC_API_KEY for Claude, GEMINI_API_KEY for Gemini, OPENAI_API_KEY for Codex.For Codex users running PaF regularly, the cleanest setup is to start Codex with --sandbox danger-full-access for these workflows.
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.
When RELAY_MODE = direct, call backend CLIs directly instead of using the
phone-a-friend binary:
| Backend | Direct command |
|---|---|
| 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 codex or
command -v gemini) before calling it. If not found, tell the user how to
install it and stop.
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.
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
(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.
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).
$ARGUMENTS is non-empty: Review this response in context and provide your opinion. Focus: $ARGUMENTSReview this response in context and provide your opinion. Focus on correctness, risks, and missing assumptions.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'
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 ]
"$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
# 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 codex or gemini.
When building binary-mode relay commands, add --fast if ALL of these are true:
--prompt
and/or --context-text)--fast maps to --pure for OpenCode, skipping external plugins. It is a
no-op for 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.
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
# Fire each backend in the background, writing stdout to a per-backend file.
# Apply --no-include-diff for casual questions (no diff payload needed).
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:
PHONE_A_FRIEND_HOST=codex on every backgrounded call.opencode.--to codex from Codex or --to opencode from OpenCode (the recursion guard refuses).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:
paf-<backend>-<short-slug>-<4-char-random> (e.g.,
paf-codex-auth-review-a3f2). The random suffix prevents collisions
across repos and conversations.--session <id> to the relay command.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:
--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).
--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.
# Resume a raw backend thread once (no PaF persistence):
phone-a-friend --to codex --repo "$PWD" --backend-session <thread-id> --prompt "<...>" $PAF_NO_DIFF
# Adopt: resume AND start tracking under a PaF label going forward:
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.
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.
--model explicitlySet --model when you need:
--model gemini-2.5-pro for a hard review, accepting more 429s).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.
ModelNotFoundError from gemini-cli's own classifier).--model is unset (auto-routing), or during session resume (--resume).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:
This does NOT apply to --to codex or --to claude.
--context-text for small narrative payloads.--context-file and --context-text are mutually exclusive./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.Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub freibergergarcia/phone-a-friend