From codex-council
Multi-perspective Codex review via parallel `codex exec` sub-agents. Auto-use ONLY when the user's text contains "codex" alongside a council/panel/agents/team/review intent — e.g. "ask codex council," "codex panel review," "codex agent team," "fan out to codex agents." Do NOT use for bare "agent team," "agents in parallel," "subagents," "council review," "panel review," "multi-angle review," "fan out to agents" — those route to Claude Code's built-in `Agent` tool. Direct invocation: `/codex-council:codex-council`. On invocation, examine context, propose a tailored panel, confirm with the user via AskUserQuestion, then launch.
How this skill is triggered — by the user, by Claude, or both
Slash command
/codex-council:codex-councilThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Fan out a prompt to N parallel `codex exec` sub-agents, each framed
Fan out a prompt to N parallel codex exec sub-agents, each framed
with a role tailored to the work. The script aggregates all responses
into one structured markdown report. Each role keeps its own Codex
thread per project so framings accumulate across calls.
If the trigger phrase that fired this skill does not contain
"codex" (e.g. "agent team," "agents in parallel," "subagents,"
"council review," "panel review," "multi-angle review," "fan out to
agents"), stop. The user meant Claude Code's built-in Agent
tool (subagents spawned with subagent_type like general-purpose,
Plan, Explore, claude-code-guide, code-reviewer) — a
different mechanism (Claude's model with direct tool access, not
OpenAI Codex via codex exec).
Ask one short disambiguation via AskUserQuestion before doing
anything:
Agent subagents, or
codex-council (OpenAI Codex fan-out)?"Only proceed past this gate if the user explicitly picks codex-council.
If the trigger phrase does contain "codex," skip this gate and go to Step 1.
Before proposing a panel, gather signal:
git status --shortgit diff HEAD --statIf the user named a panel in the invocation arguments (e.g.
/codex-council:codex-council 3 agents: ML stability, data quality, bias), trust them — skip to Step 3 with that panel as the proposal.
Re-examine every invocation. Do not silently reuse a prior proposal; the work context can shift in one turn.
Based on Step 1, draft a panel of 2–4 agents (default 3) with concrete role focuses:
| Domain | Suggested panel |
|---|---|
| ML training / inference | ML training stability, data quality, bias |
| Auth / crypto / secrets | security, threat modeling, key management |
| Infrastructure refactor | architect, reviewer, performance |
| API / public surface change | architect, security, reviewer |
| Test infra / coverage | tester, reviewer, simplifier |
| Generic code review / fallback | architect, reviewer, simplifier |
Built-in role IDs (architect, security, tester, performance,
simplifier, reviewer) pass as positional args; custom roles go in
--roles-json. Plan each role's framing instruction now — you need
it for the JSON in Step 4.
Write one short user-facing paragraph that names the domain you inferred (one sentence on why) and the roles you're suggesting.
Then call AskUserQuestion to gate the launch:
multiSelect: falseBranches:
Fallback if AskUserQuestion is unavailable: ask the same
confirmation as one plain-text question and wait for the user's next
turn. Do not fan out without confirmation.
Once you have the user's panel, pipe the gathered context on stdin and
pass roles via --roles-json and/or positional built-in IDs. A council
call takes as long as the slowest role and has no wall-clock cap; use
Bash run_in_background: true and wait for Claude Code's completion
notification instead of sleep-polling.
Custom roles only:
echo "<gathered context>" | python3 ${CLAUDE_PLUGIN_ROOT}/skills/codex-council/scripts/codex_council.py \
--roles-json '[{"id":"ml-training-stability","label":"ML Training Stability","instruction":"Review the context below as an ML training stability reviewer. Surface convergence risks, loss/grad instability, optimizer and LR-schedule issues, mixed-precision pitfalls, and reproducibility gaps. If nothing material, say so clearly. Thoroughness beats speed."}]'
Mix built-in role IDs (positional) with custom roles:
echo "<context>" | python3 ${CLAUDE_PLUGIN_ROOT}/skills/codex-council/scripts/codex_council.py \
architect security \
--roles-json '[{"id":"ml-bias","label":"Bias & Fairness","instruction":"Review the context below as a bias and fairness reviewer. ..."}]'
List built-in roles:
python3 ${CLAUDE_PLUGIN_ROOT}/skills/codex-council/scripts/codex_council.py --list-roles
Calling with no positional roles and no --roles-json exits 2 — a
safety net for accidental invocation. In the normal flow you'll
already have a confirmed panel from Step 3.
Constraints:
id must match ^[a-z0-9_-]+$, ≤32 chars. Kebab-case the user's
description to derive one.label is the human title shown in the report.instruction is a non-empty single-paragraph framing. Keep the
"if nothing material, say so clearly" clause so each role can return
silence honestly.If there are uncommitted changes:
git diff HEAD | python3 ${CLAUDE_PLUGIN_ROOT}/skills/codex-council/scripts/codex_council.py --roles-json '...'
If there are also untracked files that matter, include them (with binary/size guards):
{ git diff HEAD
git ls-files --others --exclude-standard | while IFS= read -r f; do
file --mime "$f" | grep -q 'charset=binary' && continue
[ $(wc -c <"$f") -gt 32768 ] && continue
printf '\n=== %s ===\n' "$f"
cat "$f"
done
} | python3 ${CLAUDE_PLUGIN_ROOT}/skills/codex-council/scripts/codex_council.py --roles-json '...'
If the tree is clean, gather context yourself:
echo "Review this codebase. Key files: ..." | python3 ${CLAUDE_PLUGIN_ROOT}/skills/codex-council/scripts/codex_council.py architect security
Never pipe an empty string. If git diff HEAD would be empty, use
echo with gathered context instead.
One Codex thread per (project, role) pair, stored at
$XDG_STATE_HOME/codex-council/{project-hash}__{role-id}.json.
Follow-up calls resume the per-role thread so each role accumulates its
own framing across Claude Code sessions. Stale resumes restart only the
affected role — siblings are unaffected. Custom role IDs the user
reuses across calls (e.g., ml-training-stability) will continue their
own thread; new IDs start fresh.
Set CODEX_COUNCIL_SESSION_KEY before launching Claude Code to scope a
session away from the project-wide council threads (e.g., per branch or
task ID). The state-file name becomes
{project-hash}-{session-hash}__{role-id}.json.
The output is markdown:
# Codex Council — N/M roles responded (T.Ts)
## Summary
- **ML Training Stability** [ml-training-stability]: ok — 12.3s
- **Data Quality** [data-quality]: ok — 18.7s
- **Bias & Fairness** [bias]: FAILED — 0.4s
## ML Training Stability (ml-training-stability)
<full reply>
## Data Quality (data-quality)
<full reply>
## Bias & Fairness (bias)
_Failed: <error tag and message>_
Reconcile across roles: where they agree, that's a strong signal; where
they conflict, surface the disagreement rather than collapsing it. Then
report your own read — what you accept, what you challenge, what remains
uncertain. Failed-role messages start with a bracket-tagged class
([auth], [retriable:rate-limit], [retriable:5xx],
[orchestrator-exception], [orchestrator-bug]) so the failure mode
is machine-readable.
Multi-turn is available when a reply warrants follow-up; default is single-turn.
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub ehzawad/codex-council --plugin codex-council