CLI Support Matrix
Reference of every CLI-specific integration point in CrewRig. Update this file in the same PR as any change that adds, removes, or modifies a CLI-specific feature — drift here is a parity bug.
Supported CLIs
| CLI | Config root | Entry point file | Notes |
|---|---|---|---|
| Claude Code | .claude/ |
CLAUDE.md (re-exports AGENTS.md) |
Plugin-based loading. Components must be declared in a marketplace and installed via the CLI. |
| Gemini CLI | .gemini/ |
.gemini/GEMINI.md (extension form) / GEMINI.md |
Extension-based loading. Settings live in ~/.gemini/settings.json. |
| Copilot CLI | Split: .github/copilot/ (settings + hooks) + .github/skills/ (skills) + .github/agents/ (agents) |
.github/copilot-instructions.md (re-exports AGENTS.md) |
Open Agent Skills standard. No single config root by design — Copilot reads each sibling path independently. @copilot mentions on issues / PRs trigger the coding agent natively. |
Feature matrix
One row per integration point. ✅ = present, ❌ = absent, note when relevant.
| # | Feature / integration point | Source of truth | Claude Code | Gemini CLI | Copilot CLI |
|---|---|---|---|---|---|
| 1 | Workspace config root directory | repo layout | ✅ .claude/ |
✅ .gemini/ |
✅ Split: .github/copilot/ + .github/skills/ + .github/agents/ |
| 2 | Top-level agent-context entry point | repo layout | ✅ CLAUDE.md |
✅ GEMINI.md (in extensions; absent at repo root) |
✅ .github/copilot-instructions.md |
| 3 | Skill definitions directory (built output) — the build is tier-agnostic (globs artifacts/*/); output is routed by tier (ADR-0011, spec 0019): core → committed project tree (paths shown); every non-core tier (library, community, org) → gitignored staging dist/<tier>/.<cli>/skills/<name>/SKILL.md. The init-expertise and init-team guided skills (spec 0021) are core artifact sources and build to all three CLI skill surfaces through this path. |
scripts/build-components.sh build_skills + output_root_for_tier |
✅ core: .claude/skills/<name>/SKILL.md · non-core: dist/<tier>/.claude/skills/<name>/SKILL.md |
✅ core: .gemini/skills/<name>/SKILL.md · non-core: dist/<tier>/.gemini/skills/<name>/SKILL.md |
✅ core: .github/skills/<name>/SKILL.md · non-core: dist/<tier>/.github/skills/<name>/SKILL.md |
| 4 | Agent definitions directory (built output) — same tier routing as row 3 (core → project tree; non-core → dist/<tier>/) |
scripts/build-components.sh build_agents + output_root_for_tier |
✅ .claude/agents/<name>/AGENT.md (directory) |
✅ .gemini/agents/<name>.md (flat file) |
✅ .github/agents/<name>.md (flat file) [GAP-confirmation] — repo-level layout not in the public reference |
| 4b | Agent provenance carrier | scripts/build-components.sh build_agents + gemini_provenance_comment |
✅ YAML metadata.provenance block inside frontmatter (Claude accepts arbitrary frontmatter keys) |
✅ HTML comment <!-- crewrig-provenance: version="…" canonical="…" feedback="…" --> as first line of body — Gemini CLI 0.42.0+ rejects any frontmatter key outside name / description |
⚠️ YAML metadata.provenance block inside frontmatter (parallel with Claude — [GAP-confirmation] — public Copilot reference does not document tolerated frontmatter keys; verify and downgrade to HTML comment if rejected) |
| 5 | Slash-command directory (built output) | scripts/build-components.sh build_commands |
✅ Compiled into .claude/skills/<name>/SKILL.md (commands are wrapped as user-invocable skills) |
✅ .gemini/commands/<name>.toml (native TOML) |
✅ Compiled into .github/skills/<name>/SKILL.md (no first-class slash-command file format — [GAP]) |
| 6 | Settings file in config/ |
config/ |
✅ config/claude/settings.json.template |
✅ config/gemini/settings.json |
✅ config/copilot/settings.json.template |
| 7 | Active workspace settings file | .claude/, .gemini/, .github/copilot/ |
✅ .claude/settings.json |
❌ (loaded from ~/.gemini/settings.json by the CLI; no in-repo workspace file) |
✅ .github/copilot/settings.json |
| 7b | User-level layered context (00–65 priority files) | config/SOUL.md, config/level/, config/ORGANIZATION.md, config/PROFILE.md, config/expertise/, config/teams/, artifacts/core/rules/60-tools.md (priority 60, core), config/TOOLS.md (priority 65, overlay) |
✅ ~/.claude/rules/60-tools.md (core) + ~/.claude/rules/65-org-tools.md (overlay), plus other *.md files — deployed by setup-claude-interactive.sh |
✅ ~/.gemini/60_TOOLS.md (core) + ~/.gemini/65_TOOLS.md (overlay), plus other [0-6][0-9]_*.md files — deployed by setup-gemini-interactive.sh |
✅ ~/.copilot/instructions/60-tools.instructions.md (core) + ~/.copilot/instructions/65-org-tools.instructions.md (overlay), plus other *.instructions.md files — deployed by setup-copilot-interactive.sh |
| 7c | MCP server configuration file | config/ |
✅ User-managed via claude mcp add / ~/.claude/mcp.json (no repo template — managed per-user by the CLI) |
✅ config/gemini/settings.json → ~/.gemini/settings.json (3 servers: GitHub HTTP, MemPalace, SequentialThinking) |
✅ config/copilot/mcp-config.json.template → ~/.copilot/mcp-config.json (3 servers: GitHub HTTP, MemPalace, SequentialThinking; deployed by setup-copilot-interactive.sh) |
| 7d | MemPalace MCP backend | scripts/lib/mempalace-http-wrapper.py + ADR 0006 |
✅ MCP entry → <mempalace-python> scripts/lib/mempalace-http-wrapper.py → HttpClient → chroma run (registered by setup-claude-interactive.sh via claude mcp add) |
✅ Same wrapper invoked from mcpServers.mempalace in ~/.gemini/settings.json; setup script substitutes __CREWRIG_REPO_DIR__ with the repo root at install time |
✅ Same wrapper invoked from mcpServers.mempalace in ~/.copilot/mcp-config.json; setup script substitutes __CREWRIG_REPO_DIR__ with the repo root at install time. Shared ChromaDB HTTP daemon (chroma run) supervised by launchd (macOS) or systemd-user (Linux); replaces concurrent PersistentClient instances (#98) |
| 7e | Org-rules extension delivery (AGENTS.org.md) (spec 0020) |
AGENTS.org.md, AGENTS.md (@ import), scripts/setup-{gemini,copilot}-interactive.sh |
✅ Native recursive @AGENTS.org.md import (CLAUDE.md → @AGENTS.md → @AGENTS.org.md); no setup deployment needed |
✅ Fallback: setup-gemini-interactive.sh deploys AGENTS.org.md → ~/.gemini/66_ORG_RULES.md (priority 66, after 65 org-tools). Gemini resolves @file imports only in GEMINI.md (absent at repo root), so the directive does not resolve — setup copy is the equivalent |
✅ Fallback: setup-copilot-interactive.sh deploys AGENTS.org.md → ~/.copilot/instructions/66-org-rules.instructions.md. Copilot does not resolve @file includes in instruction files and auto-reads only the standard AGENTS.md name. Fallback drift: the deployed copy is taken at setup time; editing AGENTS.org.md requires re-running setup (org rules change rarely; setup is idempotent) |
| 8 | Hook-integration manifest | hooks/ |
✅ hooks/claude-transcript-hooks.json (UserPromptSubmit, PostToolUse, Stop, SessionEnd) |
✅ hooks/gemini-transcript-hooks.json (BeforeAgent, AfterTool, AfterModel, SessionEnd) |
✅ hooks/copilot-transcript-hooks.json — deployed as opt-in by setup-copilot-interactive.sh to: ~/.copilot/hooks/copilot-transcript-hooks.json (user-level, all projects) and .github/copilot/settings.json (workspace-level, rewritten with absolute path). Committed settings.json has "hooks": [] by design. (SessionStart, UserPromptSubmit, PostToolUse, Stop, SessionEnd) |
| 9 | Project-dir env var consumed by hooks | hooks/*-transcript-hooks.json |
✅ $CLAUDE_PROJECT_DIR |
✅ ${GEMINI_PROJECT_DIR} |
❌ No $COPILOT_PROJECT_DIR — [GAP]. Workaround: hook reads workspace path from stdin JSON, falls back to $PWD |
| 10 | Interactive setup script | scripts/ |
✅ scripts/setup-claude-interactive.sh (offers MemPalace auto-install via pipx; installs built artifacts from dist/<tier>/ to ~/.claude/skills+agents — library automatically, community/org per opt-in prompt — ADR-0011, spec 0019) |
✅ scripts/setup-gemini-interactive.sh (same MemPalace offer; installs from dist/<tier>/ to ~/.gemini/skills+agents — library auto, community/org opt-in) |
✅ scripts/setup-copilot-interactive.sh (same MemPalace offer; installs skills from dist/<tier>/.github/skills/ to ~/.copilot/skills — library auto, community/org opt-in; agents skipped, see row 4 [GAP-confirmation]) |
| 11 | Transcript backfill script | scripts/ |
✅ scripts/import-claude-history.sh (reads ~/.claude/projects) |
✅ scripts/import-gemini-history.sh (reads ~/.gemini/tmp) |
✅ scripts/import-copilot-history.sh (reads ~/.copilot/session-state/<session-id>/events.jsonl) |
| 12 | Component-management script | scripts/ |
✅ scripts/manage-claude-component.sh (overlay claude-skills source repointed to the per-tier staging root dist/{community,org}/.claude/skills/ — spec 0019) |
✅ scripts/manage-workspace-component.sh (Gemini target; org tier added as an overlay source fallback alongside community) |
✅ scripts/manage-copilot-component.sh (skills, agents, commands, mcp-servers; artifacts/org/ added to the skill/agent source search) |
| 13 | Plugin / extension build script | scripts/ |
✅ scripts/build-claude-plugin.sh → dist-claude-plugin/.claude-plugin/marketplace.json |
❌ Gemini consumes extensions in-place; no separate build script | ❌ No analog — [GAP] by design (same as Gemini); Copilot consumes .github/ in-place |
| 14 | Plugin / extension install script | scripts/ |
✅ scripts/install-claude-plugin.sh |
❌ (not yet implemented; Gemini auto-discovers extensions) | ❌ No analog — [GAP] by design (same as Gemini) |
| 15 | Build-components target flag | scripts/build-components.sh |
✅ --target claude |
✅ --target gemini |
✅ --target copilot |
| 15b | REPO_DIR build-root override | scripts/build-components.sh |
✅ REPO_DIR env var — redirects the inferred repo root to an arbitrary directory (e.g. a temp dir for test isolation); introduced in spec 0018; CLI-agnostic |
✅ same | ✅ same |
| 16 | Taskfile entries | Taskfile.yml |
✅ setup-claude-interactive, install-claude-workspace, link-claude-workspace, install-claude-component, link-claude-component, build-claude-plugin, install-claude-plugin, import-claude-history, build-components-claude |
✅ setup-gemini-interactive, import-gemini-history, build-components-gemini |
✅ setup-copilot-interactive, import-copilot-history, build-components-copilot |
| 17 | Per-CLI extension manifest | extensions/<tier>/<name>/ |
✅ extension.json (+ CLAUDE.md) |
✅ gemini-extension.json (+ GEMINI.md) |
✅ .github/copilot/extension.json (placeholder) + copilot-instructions.md — [GAP-soft] (no public per-extension manifest spec) |
| 18 | CI workflow targeting the CLI | .github/workflows/ |
✅ claude.yml (anthropics/claude-code-action on @claude mentions) |
❌ No gemini.yml equivalent |
✅ copilot.yml (placeholder — native @copilot mention trigger is set at repo / org level, not via this workflow) |
| 19 | Documentation prose references | README.md, AGENTS.md, CONTRIBUTING.md, DEVELOPMENT.md |
✅ Documented throughout | ✅ Documented throughout | ✅ Documented throughout |
| 20 | .gitignore carve-outs |
.gitignore |
✅ dist-claude-plugin/, .claude/settings.local.json, CLAUDE.local.md |
❌ No Gemini-specific entries | ✅ .github/copilot/settings.local.json, copilot-instructions.local.md |
| 21 | e2e dedicated-account auth flow | scripts/e2e/auth-<cli>.sh, Taskfile.yml → e2e:auth:*, ADR 0002 |
✅ scripts/e2e/auth-claude.sh — interactive claude /login in crewrig/e2e-claude:latest, persists ~/.crewrig-e2e/claude/{.credentials.json,.claude.json} (RW one-shot, RO at scenario time) |
✅ scripts/e2e/auth-gemini.sh — interactive gemini "Login with Google" in crewrig/e2e-gemini:latest. Persists ~/.crewrig-e2e/gemini/ with oauth_creds.json, settings.json, google_accounts.json, google_account_id, installation_id, gemini-credentials.json, extension_integrity.json, trustedFolders.json, acknowledgments/, history/, projects.json, state.json, etc. — full ~/.gemini minus the antigravity* and tmp/ subtrees and backup leftovers (.bak, .ori, .orig). Bundle dir is chmod 0700. Mounted :ro at /run/gemini-creds; a container-side wrapper copies it to /home/agent/.gemini before exec gemini (see issue #147 §5). |
⚠️ scripts/e2e/auth-copilot.sh — guidance-only, no container. Prints PAT setup steps for the test account; scenarios consume $COPILOT_GITHUB_TOKEN at run time via docker run -e. Nothing persisted under ~/.crewrig-e2e/copilot/. [GAP-soft] — empirically justified divergence (see Parity gaps). The e2e runner (#78) consumes this asymmetry first-class via mounts = [] in tests/e2e/defaults.toml [cli.copilot], so no CLI-branching is needed in tests/e2e/run.sh. When local.toml routes Copilot through Ollama Cloud, task e2e:auth:ollama persists an Ed25519 keypair under ~/.crewrig-e2e/ollama/ that is mounted RO into the copilot container (see ADR 0002 Decision 8). |
| 22 | e2e pillar 01 — layered context | tests/e2e/scenarios/01-layered-context/, ADR 0005 |
✅ host-orchestrated probe via claude -p; mounts ${CREWRIG_E2E_HOME}/claude ro; structural + LLM-judge assertions |
✅ host-orchestrated probe via gemini -p; dual :ro mounts — ${CREWRIG_E2E_HOME}/gemini at /run/gemini-creds (auth bundle) and ${HOME}/.gemini at /run/gemini-rules (layered-context rules, [0-6]0_*.md only); container-side bootstrap copies both into /home/agent/.gemini before exec gemini (see issue #148 Decision 5 Revision 2) |
✅ host-orchestrated probe via copilot -p; mounts ${CREWRIG_E2E_HOME}/copilot ro (auth-copilot.sh currently writes nothing here — scenario soft-skips if the dir is absent) |
| 23 | e2e pillar 02 — cross-tool memory | tests/e2e/scenarios/02-cross-tool-memory/, ADR 0005 |
✅ MemPalace sidecar (per-run volume); drawer write + read across two short-lived containers | ✅ same path | ❌ [GAP-soft] — crewrig/e2e-copilot:latest (docker/e2e/copilot.Dockerfile) does not embed the mempalace CLI, and Copilot CLI ships no MemPalace MCP integration in artifacts/community/. Empirical reproduction: docker run --rm crewrig/e2e-copilot:latest which mempalace → exit 1 (binary absent). Scenario excluded via applies_to = ["claude","gemini"] until the Copilot image gains a MemPalace surface. |
| 24 | e2e pillar 03 — skill build | tests/e2e/scenarios/03-skill-build/, ADR 0005 |
✅ runs scripts/build-components.sh --target claude inside the container; asserts .claude/ populated + first SKILL.md has metadata: frontmatter |
✅ same with --target gemini → .gemini/ |
✅ same with --target copilot → .github/ |
| 25 | e2e pillar 04 — harness loop | tests/e2e/scenarios/04-harness-loop/, ADR 0005 |
✅ simulated path (drawer write to wing=harness-friction + curator-style search); MemPalace sidecar; LLM-judge on the friction summary |
✅ same simulated path | ✅ same simulated path. [GAP-soft] — full interactive harness-report skill invocation is not yet driven non-interactively from any CLI; the simulation matches what the curator reads and is parity-equivalent for v1. |
Parity gaps
The following features exist for one CLI but not the other. Each gap is a candidate follow-up issue. Do not fix them in this ticket.
- [GAP] CI workflow — present for Claude Code (
.github/workflows/claude.yml), missing for Gemini CLI. - [GAP] Plugin/extension build script — present for Claude Code (
scripts/build-claude-plugin.sh), missing for Gemini CLI (extensions are consumed in place, but no symmetric packaging path exists). - [GAP] Plugin/extension install script — present for Claude Code (
scripts/install-claude-plugin.sh), missing for Gemini CLI. - [GAP] In-repo workspace settings file — present for Claude Code (
.claude/settings.json), missing for Gemini CLI (settings live only in~/.gemini/settings.json). - [GAP]
.gitignorecarve-outs — Claude-specific entries (dist-claude-plugin/,.claude/settings.local.json,CLAUDE.local.md) have no Gemini equivalents (e.g., a.gemini/settings.local.jsonanalog). - [GAP] Top-level entry point file —
CLAUDE.mdlives at the repo root;GEMINI.mdonly appears inside extensions (no repo-rootGEMINI.md). - [GAP] Slash commands — Copilot CLI has no user-definable slash-command file format. CrewRig commands compile as user-invocable skills under
.github/skills/(same workaround Claude uses). Same trade-off, documented and accepted. - [GAP] Project-dir env var — Copilot does not export a
$COPILOT_PROJECT_DIR.hooks/mempalace-transcript.shextracts the workspace path from the hook stdin JSON payload and falls back to$PWD. - [GAP-confirmation] Repo-level Copilot agent layout — the public Copilot reference only documents the user-level
~/.copilot/agents/directory. CrewRig adopts.github/agents/<name>.mdby parallelism with the skills layout; implementers must verify loading behavior and downgrade to a hard[GAP]if the path is rejected. - [GAP] Plugin / extension build & install — same status as Gemini. Copilot consumes
.github/artifacts in place; no analog toscripts/build-claude-plugin.sh/scripts/install-claude-plugin.shexists. - [GAP-confirmation] Copilot agent provenance carrier — CrewRig currently emits the same
metadata.provenanceYAML block in.github/agents/<name>.mdthat it emits for Claude. Copilot CLI's tolerance for non-standard frontmatter keys is undocumented; if Copilot rejects the block (as Gemini CLI 0.42.0 did, see issue #54), migrate Copilot agents to the same HTML-comment carrier used by Gemini. Follow-up ticket to be filed. - [GAP-soft] Per-extension Copilot manifest — no public spec for a repo-level Copilot extension manifest. CrewRig ships
.github/copilot/extension.jsonas a placeholder convention; revisit when GitHub publishes a spec. - [GAP-soft] e2e pillar 02 (cross-tool memory) for Copilot CLI — the
crewrig/e2e-copilot:latestimage does not embed themempalaceCLI (docker/e2e/copilot.Dockerfileinstalls only Node,gh, and@github/copilot; verified viadocker run --rm crewrig/e2e-copilot:latest which mempalace→ exit 1) and no MemPalace MCP wiring ships inartifacts/community/for Copilot. The scenario excludes Copilot viaapplies_to = ["claude","gemini"]intests/e2e/defaults.toml. Re-evaluate when either the Copilot image gains themempalacebinary or a MemPalace MCP integration appears for Copilot. - [GAP-soft] e2e pillar 04 (harness loop) full interactive leg — the scenario currently uses the simulated path (direct drawer write to
wing=harness-friction, curator-style search) for all three CLIs. The fully interactive path that drives theharness-reportskill end-to-end through the CLI's slash-command surface is not yet supported non-interactively from any CLI. The simulated path is parity-equivalent for v1: it writes the same drawer shape the skill would write and the curator reads the same lane regardless of the writer's identity. - [GAP-soft] e2e auth flow for Copilot CLI —
auth-claude.shandauth-gemini.shpersist on-disk OAuth credentials under~/.crewrig-e2e/<cli>/;auth-copilot.shis guidance-only and relies on an env-var PAT ($COPILOT_GITHUB_TOKEN) at scenario time. Empirical evidence supporting the divergence is captured indocs/adr/0002-e2e-auth-flow.mdDecision 4: thecrewrig/e2e-copilot:latestimage lackslibsecret(verified vialdconfig -p | grep libsecret→ empty), so the upstream desktop-keychain path is unavailable; the documented plaintext-fallback works but adds login-flow friction without scenario-coverage gain in v1. The env-var precedence chain (COPILOT_GITHUB_TOKEN > GITHUB_TOKEN > GH_TOKEN > gh CLI > GITHUB_ASKPASS > OAuth device flow) makes the PAT path strictly simpler. Re-evaluate when the scenario runner (#78) or pillar scenarios (#80) prove the need for an interactive on-disk credential.
Adding a new CLI
Every checklist item below is governed by the Symmetric-script rule
and Gap-acceptance evidence rule in AGENTS.md → CLI Matrix
Maintenance. Unchecking an item requires the evidence the gap rule
demands; it is not a free-form choice.
Use this checklist when onboarding a new CLI. Each item maps to a row in the feature matrix above — leaving one unchecked produces a parity gap.
- [ ] Create the workspace config root (
./.<cli>/). - [ ] Add a top-level agent-context entry point that re-exports
AGENTS.md(analogous toCLAUDE.md). - [ ] Extend
scripts/build-components.shwith a--target <cli>branch and emit skills via the tier-routed output root (output_root_for_tier):core→.<cli>/skills/<name>/SKILL.mdin the project tree; non-core→dist/<tier>/.<cli>/skills/<name>/SKILL.md(or the native form). The build is tier-agnostic — do not hardcode tier names. - [ ] Extend
build_agentsin the same script to emit agents in the CLI's native layout. - [ ] Extend
build_commandsin the same script to emit commands in the CLI's native form. - [ ] Add a per-CLI settings template under
config/<cli>/. - [ ] Decide whether a checked-in workspace settings file at
.<cli>/settings.jsonis required, and add it if so. - [ ] Provide a hook-integration manifest under
hooks/<cli>-transcript-hooks.jsoncovering the CLI's lifecycle events. - [ ] Document the CLI's project-dir env var convention and wire
hooks/mempalace-transcript.shto read it. - [ ] Add an interactive setup script
scripts/setup-<cli>-interactive.sh, including the artifact-install phase that readsdist/<tier>/and routes by tier scope:libraryauto-installed to the user home,community/orgeach behind an opt-in prompt (ADR-0011, spec 0019).coreis never installed here — it ships in the project tree. - [ ] Add a transcript backfill script
scripts/import-<cli>-history.sh. - [ ] Add or extend a component-management script for the CLI.
- [ ] If the CLI requires a build step before install, add
scripts/build-<cli>-plugin.sh(or equivalent). - [ ] If a separate install step is required, add
scripts/install-<cli>-plugin.sh. - [ ] Register
--target <cli>invocations inTaskfile.yml, plussetup-,import-,install-,link-, andbuild-components-task entries. - [ ] Add a per-CLI extension manifest convention to
extension-skeleton/and updateextensions/core/hello-world/with an example. - [ ] Add a CI workflow
.github/workflows/<cli>.ymlif the CLI offers an automation entry point. - [ ] Update prose references in
README.md,AGENTS.md,CONTRIBUTING.md, andDEVELOPMENT.md. - [ ] Add
.gitignorecarve-outs for the CLI's local settings and any generateddist-<cli>-*directories. - [ ] Append a new column to this matrix and re-check every row.