Collaborate with another coding agent on a question or proposed approach: any of Claude Code, Codex and Antigravity (agy) consults another, or a different model in its own CLI (Opus consulting Fable), through a persistent peer session. Use when the user says "consult with <name>", where the name is an agent (Codex, Claude, agy), a vendor or model family (Gemini, GPT), or a model (Fable, Opus, Sonnet); also "consult your counterpart", "compare perspectives", or "work toward consensus". The ori...
Installs into .claude/skills of the current project.
Are you the author of Consult?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/curtisgalloway-consult)
---
name: consult
description: >-
Collaborate with another coding agent on a question or proposed approach:
any of Claude Code, Codex and Antigravity (agy) consults another, or a
different model in its own CLI (Opus consulting Fable), through a persistent
peer session. Use when the user says "consult with <name>", where the name is
an agent (Codex, Claude, agy), a vendor or model family (Gemini, GPT), or a
model (Fable, Opus, Sonnet); also "consult your counterpart", "compare
perspectives", or "work toward consensus". The original agent leads the
exchange and reports the agreed recommendation or unresolved disagreement.
---
<!--
SPDX-FileCopyrightText: 2026 contributors
SPDX-License-Identifier: Apache-2.0
-->
# Consult
Keep leading the user's conversation. Start a dedicated counterpart session,
exchange reasoned follow-ups, and bring the result back to the user. The user
does not need to open another terminal or copy messages. This does not attach to
an existing interactive counterpart session.
## Requirements and scope
- Python 3.9+ on macOS or Linux; standard library only (uses Unix process groups
and `flock`). Windows is not supported.
- The counterpart's CLI on `PATH`, already authenticated: `claude`, `codex` or
`agy`. Normal CLI usage charges/limits apply. The counterpart can be the same
CLI as the original agent when `--model` names a different model (see
"Another model in the same CLI" below).
- For an `agy` counterpart: bubblewrap (`bwrap`) on Linux, or `sandbox-exec` on
macOS, and no MCP servers or plugins configured in agy (see below).
- Permission to launch the counterpart and reach its provider. If the host's
sandbox blocks this, use its normal approval mechanism; do not bypass it.
- A trusted project directory and selected task context. Invocation authorizes
consultation about that task, not forwarding unrelated conversation history
or secrets, changing either agent's configuration, or implementing the result.
The counterpart advises and inspects; the original agent owns implementation.
Both adapters enforce restrictions on every invocation, including resume:
| Counterpart | Inspection controls |
| --- | --- |
| Claude Code | Only `Read`, `Glob`, `Grep`; permission mode `dontAsk`; no MCP servers, hooks, Chrome, or skills; user/project settings excluded |
| Codex | Read-only sandbox, approvals `never`; user config and exec rules excluded; MCP/plugin maps cleared; hooks, multi-agent delegation, and app integrations disabled |
| agy | Runs inside an OS sandbox whose filesystem is read-only except agy's own state directory (`~/.gemini/antigravity-cli`) and a private temp directory; never `--dangerously-skip-permissions`; `--sandbox` (terminal restrictions); slash commands and skills disabled; refused if any MCP server or plugin is configured |
These controls are deliberately different. Claude cannot run shell commands;
Codex can run commands within its read-only sandbox.
agy is enforced from outside because it has no read-only flag. In a live check
(agy 1.2.11, 2026-09-26), `--mode plan` wrote a file into the project with
default settings, no approval and no `--dangerously-skip-permissions`, so plan
mode is never used. Without it, agy's own headless check denied the same write,
but the adapter does not rely on that: bubblewrap mounts `/` read-only, and a
write fails with "Read-only file system". agy has no flag to turn off
configured MCP servers or plugins for one run, and the filesystem sandbox cannot
stop what they do over the network. So `start` refuses unless `agy mcp list`
and `agy plugin list` both report none. If evidence needs a test or
an unavailable tool, gather it in the original session under existing permissions
and share the result. CLI-owned authentication/session writes still occur. This
is not an isolation boundary for hostile projects or compromised CLIs.
Adapter flags were checked against Claude Code 2.1.277 and Codex CLI 0.155.0 on
2026-09-18, and against agy 1.2.11 on Linux on 2026-09-26: a three-turn live
consultation, with the context kept and the write denied. **The macOS
`sandbox-exec` profile for agy has not been run yet.** On first use on a Mac,
run the live check under Validation before relying on it. Older releases may reject flags. Fail visibly rather than removing
restrictions to make a command work. Ground truth: `claude --help`, `codex exec
--help`, and `codex exec resume --help`. See the official
[Claude programmatic guide](https://code.claude.com/docs/en/headless) and
[Codex noninteractive guide](https://developers.openai.com/codex/noninteractive).
## Choose the counterpart from the user's words
Users name the counterpart the way they think of it: "consult with Codex",
"consult with Fable", "consult with Gemini". Turn the name into `--to` and
`--model` before starting:
| The user names | `--to` | `--model` |
| --- | --- | --- |
| An agent or its CLI: Claude, Codex, agy or Antigravity | that CLI | none: its default |
| A model family another CLI serves: Gemini (agy), GPT (Codex) | that CLI | the model, if a specific one is named |
| A model your own CLI serves, such as Fable, Opus or Sonnet from Claude Code | your own CLI | that name |
| A name you don't recognize, such as Astra | the CLI that lists it | its exact ID from that list |
For a name you don't recognize, look it up in every CLI's catalog:
| CLI | Command | What to match |
| --- | --- | --- |
| Codex | `codex debug models` (JSON) | each model's `slug` and `display_name`; skip `"visibility": "hide"` |
| agy | `agy models` | the ID in the first column and the name after it |
| Claude Code | `claude --help`, under `--model` | the aliases (`fable`, `opus`, `sonnet`) or a full ID |
Users say the short name, not the ID, so match it case-insensitively as a whole
word inside the ID or name, not as the entire string. "Astra" matches Codex's
`gpt-6-astra` (display name "GPT-6-Astra"); an exact-string search misses it.
Pass the matched ID, never the user's word, to `--model`.
If exactly one model in one CLI matches, use it. If none match, or several do
(for example two model generations sharing a name), ask the user in one line,
listing the candidates and what you checked. Don't guess a model name: a wrong
one fails the first turn, after the brief has already been sent. If the name is
the model you are running now, say so and ask for another: consulting yourself
only gets you an echo.
Tell the user which CLI and model you picked in the same message that starts
the consultation.
## Conduct the discussion
1. **Frame the question.** Preserve the user's objective, constraints, relevant
files/evidence, and open questions. Record your own current proposal in your
conversation before consulting. Send the counterpart a neutral initial brief
without your preferred answer, unless the user specifically requested a
critique of that answer. Include relevant project instructions explicitly if
they are essential; the restricted peer does not inherit your loaded context.
2. **Get an independent assessment.** Start the opposite CLI. Read the response
and identify actual differences in assumptions, evidence, or recommendations.
Do not treat a peer answer as verified merely because it sounds confident.
3. **Compare and investigate.** Send your proposal, substantive disagreements,
and concrete questions. Relay answers to the counterpart's questions and any
user corrections. Ask for counterexamples or discriminating tests when useful.
Follow up in the same consultation, not a new peer session for every message.
4. **Confirm the exact recommendation.** Once you agree with a proposal, send its
full final text using phase `confirm`. Ask the counterpart to explicitly agree
or identify remaining objections. A response that changes the proposal does
not confirm the original text. Silence, a timeout, or partial agreement is not
consensus. Read and assess the response yourself: the helper checks that a
confirmation turn succeeded, not whether its prose actually agrees.
5. **Close and report.** Record `consensus` only when both agents agree on the same
recommendation. Otherwise record `unresolved` and explain the remaining
disagreement, missing evidence, or user decision. Give the user the conclusion,
the important changes of mind and their reasons, any caveats, and the transcript
location. Consensus is agreement, not proof of correctness.
Default limit: an initial assessment, up to three comparison rounds, and one final
confirmation. Stop earlier if arguments repeat without new evidence, access is
missing, or the problem requires a user decision. Do not spend all rounds just
because they are available. Do not pressure the counterpart to concede.
Neither participant should recursively consult or delegate consultation. Peer
processes receive `CONSULT_PEER=1`; the helper refuses calls from that environment.
If you are already the counterpart, answer directly rather than invoking this skill.
## Drive the helper
Resolve `scripts/consult.py` relative to **this loaded skill**, not a hardcoded
installation directory. In the examples, replace `<skill-dir>` with that directory,
`<project>` with the working project, and `<id>` with the ID returned by `start`.
Message and summary files are UTF-8; `--message-file -` also accepts stdin.
Use files or quoted heredocs, never interpolate prose into shell command strings.
```sh
# If the original agent is Codex; use --from claude for the reverse direction.
python3 <skill-dir>/scripts/consult.py start --from codex \
--project <project> --message-file <brief-file>
# Any direction can name the counterpart; --to is required from agy.
python3 <skill-dir>/scripts/consult.py start --from claude --to agy \
--project <project> --message-file <brief-file>
# A different model in the same CLI: --model is required when --to matches --from.
python3 <skill-dir>/scripts/consult.py start --from claude --to claude \
--model fable --project <project> --message-file <brief-file>
python3 <skill-dir>/scripts/consult.py status <id>
python3 <skill-dir>/scripts/consult.py read <id>
python3 <skill-dir>/scripts/consult.py reply <id> \
--message-file <comparison-file>
python3 <skill-dir>/scripts/consult.py reply <id> --phase confirm \
--message-file <exact-final-proposal-file>
python3 <skill-dir>/scripts/consult.py close <id> --outcome consensus \
--summary-file <agreed-recommendation-file>
python3 <skill-dir>/scripts/consult.py read <id> --all
```
`start` and `reply` return immediately. They launch a detached worker and print JSON
with an ID, status, and state directory. Poll `status` at reasonable intervals
(e.g. 10 seconds), keep the user informed during longer work, and call `read` when
status is `ready`. A successful launch is not a completed consultation.
All public commands print JSON, except `--skill`, which prints these instructions.
Exit codes: 0 = command succeeded (possibly still running), 1 = operational failure
or failed peer turn, 2 = invalid command-line usage. Inspect `status`, not just the
exit code. Peer stdout/stderr and worker errors are retained for diagnosis; do not
paste raw logs into a public report without reviewing them.
`start` accepts `--to claude|codex|agy` (the counterpart; defaults to Codex from
Claude and to Claude from Codex; it may match `--from` when `--model` is given), `--task thinking|coding`, `--rounds N`, `--timeout SECONDS` (per
turn; default 600), and `--model NAME` (the **counterpart's** model).
`--task` sets the counterpart's reasoning effort on every turn, resume included.
The default is `thinking`: design, architecture, review, debugging analysis,
and any other judgment call run at **max** effort, whichever direction the
consultation goes (Codex, or Claude such as Opus 5.5). Pass `--task coding`
only when the counterpart's job is to draft or check code mechanically; it runs
at **medium**. When a consultation mixes the two, use `thinking`. The adapters
pass `--effort <level>` to `claude` and `agy`, and `-c model_reasoning_effort=<level>`
to `codex`. All three accept `max` and `medium` (checked 2026-09-26: `claude --help`
lists `low, medium, high, xhigh, max`; `agy --help` lists `low|medium|high|max`;
the Codex API's list of valid values is `none, minimal, low, medium, high,
xhigh, max`). A Gemini model under agy follows the same rule; name it with
`--model` when a specific one is wanted (`agy models` lists them). Without a model override, its CLI
default applies with the restricted configuration; it need not match the model
in another interactive session. Specify an override only when requested or needed
for the user's stated constraints. There is no cross-provider dollar-budget cap.
### Another model in the same CLI
Pass `--to` equal to `--from` and name the counterpart's model with `--model`,
for example Claude Code on Opus consulting `--model fable`. The model name is
whatever the counterpart CLI's `--model` flag accepts: an alias such as `fable`,
`sonnet` or `opus`, or a full model ID. The helper refuses a same-CLI start
without `--model`, because the CLI's default is most likely the model already
running, which would be an echo, not a second opinion. It cannot see which model
the original agent is running, so choose one that differs from your own. The
counterpart gets the same restrictions as any other peer from that CLI.
A `claude` started from inside Claude Code inherits the parent's session and
appends its turns to the parent's transcript unless told otherwise (Claude Code
2.1.42, 2026-09-26). The helper therefore starts every Claude peer with its own
`--session-id` and fails the turn if the peer reports any other session. Checked
live the same day: Claude on Opus consulting `--model sonnet`, two turns,
context kept, a write attempt denied, and the parent transcript unchanged.
Two models in one CLI share its system prompt, tools and habits, and often
training lineage, so their agreement is weaker evidence than agreement across
vendors. Prefer a different CLI when one is available and the question is
contested; use a different model in the same CLI when only one CLI is signed in,
or when the user asks for that model by name. Say which it was when reporting.
To stop: `close <id> --outcome cancelled`. It returns `closing` while the worker
terminates the peer process group; check `status` until `closed`. For completed
work without agreement, use `--outcome unresolved --summary-file <file>`.
Revisit a successfully closed discussion with `reply <id> --reopen --message-file
<file>`. This retains the peer session and starts a new bounded cycle. Use reopening
for a new user request or genuinely new evidence, not to evade the round limit.
Failed/interrupted turns cannot be blindly resumed: provider-side completion may
be ambiguous. Close them, report the problem, and only start a fresh consultation
when appropriate. There are no automatic retries or permission escalation.
## Local state and privacy
State defaults to `~/.local/state/agent-consult/`; override it with
`CONSULT_STATE_DIR` or global `--state-dir <directory>` **before** the subcommand.
Keep this directory outside the consulted project. In restricted environments,
use an allowed private state directory and pass it consistently on later calls.
Each consultation has its own directory and lock; competing replies cannot run
against the same peer session at once. Different consultations can run concurrently.
State includes the project path, selected messages, peer session ID, answers,
diagnostic logs, and recorded outcome. New consultation directories are private
to the current user. Keep message drafts outside the public repository too.
Native CLI session histories may also retain this material; deleting helper state
does not delete those histories. Do not commit transcripts or authentication data.
## Validation
```sh
python3 -m unittest discover -s <skill-dir>/tests -v
```
The tests use fake CLIs and make no model calls. After adapter changes, also run
a small real consultation in each direction: initial assessment, a follow-up that
depends on initial context, and explicit confirmation of the exact final proposal.
Verify inspection succeeds, mutation is denied, and the session ID stays constant.
For agy, also ask the counterpart to write a file in the project, and confirm
that no file appears.
Record failures honestly; fixture tests alone do not prove live compatibility.