Portable agent peer review for substantial AI-generated work.
Council is a Codex/Claude-compatible skill that asks other local agents to review specs, plans, diffs, incident writeups, migrations, and other decision-driving artifacts before the authoring agent presents final work. Reviewers run from disposable workspaces so cwd-relative edits are discarded, return structured findings, and leave the authoring agent responsible for final judgment.
Council is distributed as a skill zip. The zip contains:
SKILL.mdwith the agent-facing workflow.agents/openai.yamlfor UI metadata.references/council-workflow.mdfor fallback/manual review guidance.evals/with concrete scenarios for testing skill behavior.- A bundled Node.js helper at
scripts/dist/council.mjs. - TypeScript source for auditing the bundled helper.
The helper is bundled so users do not need to run npm install at skill runtime. Source is included so the packaged JavaScript is not an opaque binary.
- The authoring agent drafts an artifact or implementation.
- Council creates an isolated workspace for each available reviewer except the authoring agent.
- Council invokes local reviewer CLIs, currently
codexandclaude. - Reviewers inspect the artifact, repository, and diff as needed.
- Council parses reviewer output into
BLOCKER,SUGGESTION,QUESTION, andPASS. - The authoring agent accepts or rejects findings, revises when needed, and reruns Council if meaningful changes were made.
Council is intentionally smaller than Camelot: no custom UI, no event hub, no persistent coordination protocol, and no long-running service.
- Node.js 20 or newer.
- Git, for the preferred disposable
git worktreeisolation path. - At least one supported reviewer CLI on
PATH:codexclaude
If Git worktrees are unavailable, Council falls back to a temporary directory copy and discloses that fallback in the report. If Node is unavailable, the skill includes manual fallback instructions.
Council is not an OS sandbox. Reviewer CLIs still run as local processes with their own permission modes, so avoid putting absolute paths to the author's source checkout in prompts or artifacts when reviewer tools are broadly permitted.
When Council is launched from a sandboxed Codex shell, reviewer CLIs run as local child processes that need their normal auth/home state and network. Council blocks reviewer launch only when the sandbox has disabled network (CODEX_SANDBOX_NETWORK_DISABLED), since reviewers cannot reach their model backends without it; when network is available reviewers launch and any auth failure surfaces as a reviewer error rather than being guessed from environment variables. In Codex tool calls, the agent should request sandbox_permissions: "require_escalated" for the Council helper command. From a human shell, start Codex with codex --sandbox danger-full-access when you intentionally want reviewer CLIs to run outside the sandbox; --dangerously-bypass-approvals-and-sandbox is broader and should only be used when you understand the risk. --allow-sandboxed-reviewers is an unconditional override.
If a report says no reviewer agents available, treat the artifact as unreviewed. Install the opposite reviewer CLI, correct the author value, or use the manual fallback instructions in references/council-workflow.md.
Review an artifact:
node skill/council/scripts/dist/council.mjs review \
--artifact /path/to/artifact.md \
--cwd /path/to/repo \
--author <codex-or-claude>Replace <codex-or-claude> with codex when running from Codex and claude when running from Claude Code. Council skips the matching reviewer so an agent does not review itself. If you prefer environment configuration, set COUNCIL_AUTHOR_AGENT=codex or COUNCIL_AUTHOR_AGENT=claude; an explicit --author flag wins over the environment variable.
Review the current diff:
node skill/council/scripts/dist/council.mjs review \
--diff \
--cwd /path/to/repo \
--author <codex-or-claude>Review explicit diff targets:
# Dirty working-tree changes only.
node skill/council/scripts/dist/council.mjs review \
--mode local \
--cwd /path/to/repo \
--author <codex-or-claude>
# Branch changes against a base ref, plus dirty changes when present.
node skill/council/scripts/dist/council.mjs review \
--mode branch \
--base origin/main \
--cwd /path/to/repo \
--author <codex-or-claude>
# One committed change.
node skill/council/scripts/dist/council.mjs review \
--commit HEAD \
--cwd /path/to/repo \
--author <codex-or-claude>--commit reviews the diff emitted by git show --format= --binary <ref>. Merge commits may produce no diff with that command shape; review the branch/base range instead when merge-commit content matters.
Limit the reviewer set (unavailable or author-matching reviewers are still skipped with a visible warning):
node skill/council/scripts/dist/council.mjs review \
--mode branch \
--base origin/main \
--reviewers claude \
--cwd /path/to/repo \
--author codexRun a verification command in parallel with reviewer agents and include its proof in the report:
node skill/council/scripts/dist/council.mjs review \
--mode branch \
--base origin/main \
--parallel-tests "npm test" \
--test-timeout-ms 600000 \
--cwd /path/to/repo \
--author <codex-or-claude>Parallel tests run in the author's real working tree, not in reviewer disposable workspaces. Choose commands that are safe for the current checkout, or expect generated files such as coverage/build output. Because reviewer workspaces are prepared from the author's live checkout, avoid parallel commands that create/delete files aggressively during snapshotting. --test-timeout-ms controls the test command budget independently from reviewer --timeout-ms. If no diff is found, Council reports the review as incomplete and skips parallel tests.
Council records the review command in its report. Avoid putting secrets or sensitive one-off paths directly in command-line arguments.
Run a follow-up round:
node skill/council/scripts/dist/council.mjs review \
--artifact /path/to/artifact.md \
--cwd /path/to/repo \
--author <codex-or-claude> \
--round 2 \
--max-rounds 3 \
--change-summary "Addressed rollback and test coverage findings"Emit JSON:
node skill/council/scripts/dist/council.mjs review \
--artifact /path/to/artifact.md \
--cwd /path/to/repo \
--author <codex-or-claude> \
--jsonDownload council-skill.zip from a GitHub Release and upload or install it through your skill library. The zip root contains the council/ skill folder, which can be installed into Codex, Claude Code, or both.
For a local build without GitHub Actions, run:
./scripts/local-release.shThat validates the helper and writes:
skill/council/dist/council-skill.zip
To install the generated zip into both local skill directories:
./scripts/local-release.sh --install-bothThat installs to:
${CODEX_HOME:-$HOME/.codex}/skills/council
$HOME/.claude/skills/council
To install manually into Codex:
SKILLS_DIR="${CODEX_HOME:-$HOME/.codex}/skills"
mkdir -p "$SKILLS_DIR"
rm -rf "$SKILLS_DIR/council"
unzip -q skill/council/dist/council-skill.zip -d "$SKILLS_DIR"To install manually into Claude Code:
SKILLS_DIR="$HOME/.claude/skills"
mkdir -p "$SKILLS_DIR"
rm -rf "$SKILLS_DIR/council"
unzip -q skill/council/dist/council-skill.zip -d "$SKILLS_DIR"Or build and install for one target:
./scripts/local-release.sh --install-codex
./scripts/local-release.sh --install-claude./scripts/local-release.sh --install-local remains supported as a backward-compatible alias for --install-codex.
After installing, start a fresh Codex or Claude Code session or reload skills, then ask for a Council review of a real spec, plan, or diff.
Install dependencies:
cd skill/council/scripts
npm ciRun verification:
npm run typecheck
npm test
npm run check-distPackage the skill zip:
./scripts/local-release.shThe local release command runs npm ci, typecheck, tests, bundle drift check, and packaging. It writes:
skill/council/dist/council-skill.zip
That generated zip is ignored by git. The bundled runtime helper, skill/council/scripts/dist/council.mjs, is tracked for auditability and immediate skill runtime use.
Skill-level evaluation scenarios live in skill/council/evals/. Use them when checking whether the skill triggers, follows the review loop, and falls back correctly when the helper cannot run.
The local release script mirrors the GitHub Actions job for environments where hosted Actions are unavailable:
./scripts/local-release.shTo publish the zip as a GitHub Release asset from your machine:
./scripts/local-release.sh --tag v0.1.0That command creates the tag if needed, pushes it, and creates or updates the release asset with skill/council/dist/council-skill.zip. It requires the GitHub CLI (gh) to be authenticated.
GitHub Actions can still run on pull requests, pushes to main, and tags matching v* when account Actions capacity is available.
- Pull requests and
main: typecheck, test, build, package, and uploadcouncil-skill.zipas a workflow artifact. - Version tags such as
v0.1.0: create a GitHub Release and attachcouncil-skill.zip.
CI also rebuilds skill/council/scripts/dist/council.mjs and fails if the tracked bundle drifts from source.
.
├── SPEC.md
├── .github/workflows/package-skill.yml
├── scripts/local-release.sh
├── skill/council/
│ ├── SKILL.md
│ ├── agents/openai.yaml
│ ├── evals/
│ ├── references/council-workflow.md
│ └── scripts/
│ ├── dist/council.mjs
│ ├── src/
│ ├── test/
│ ├── tools/package-skill.mjs
│ ├── package.json
│ ├── package-lock.json
│ └── tsconfig.json
Portable agent peer-review skill with a bundled TypeScript helper for isolated Council reviews.