
Squads
- 129 installs
- 9 repo stars
- Updated April 24, 2026
- gutomec/ai-public-arsenal
Create, validate, run, and manage portable multi-agent squads with workflows that run across Claude Code, Codex, Gemini CLI, Cursor, and other runtimes.
About
A runtime-agnostic orchestrator for building and running multi-agent squads following the Squad Protocol, with adapters for multiple agent runtimes. A developer uses it when creating, validating, running, or migrating portable AI agent teams and workflows.
- Runtime-neutral squads with per-runtime adapters
- Bounded iteration and fail-closed permission defaults
Squads by the numbers
- 129 all-time installs (skills.sh)
- Ranked #3,702 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Jul 24, 2026 (Skillselion catalog sync)
npx skills add https://github.com/gutomec/ai-public-arsenal --skill squadsAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 129 |
|---|---|
| repo stars | ★ 9 |
| Last updated | April 24, 2026 |
| Repository | gutomec/ai-public-arsenal ↗ |
What it does
Create, validate, run, and manage portable multi-agent squads with workflows that run across Claude Code, Codex, Gemini CLI, Cursor, and other runtimes.
Files
Squad Protocol Engine v5.0.0
You orchestrate multi-agent squads following the Squad Protocol v4.0. You are runtime-agnostic: squads you create work on Claude Code, Codex, Gemini CLI, Cursor, Antigravity, and any runtime with an adapter.
Core Principles (v4.0)
P1 Separation of Audiences — frontmatter=runtime, body=LLM, ui=marketplace. P2 Prose Over Structure — LLM reads prose, not nested YAML. P3 Token Budget Discipline — agent bodies ≤1.5% of context window. P4 Bounded Iteration — maxTurns MANDATORY on every agent. No exceptions. P5 Fail-Closed Defaults — no tools granted by default; conservative permissions. P6 Task-First — tasks describe WHAT; workflows decide WHO. P7 Runtime Neutrality — Core spec has no runtime-specific values. P8 Technical Honesty — never sell enforcement that doesn't exist. P9 Graceful Degradation — missing optional features logged, not crashed. P10 Namespaced Extensions — runtime config under runtimes.{id}.*.
Protocol Source
Single source of truth: SQUAD_PROTOCOL_V4.md (21 sections, runtime-agnostic). Legacy: SQUAD_PROTOCOL.md (v2.0, deprecated, kept for legacy squads). Adapters: adapters/{runtime_id}.md + .yaml — runtime-specific mechanics. Read sections on demand via TOC. NEVER load the full 1600-line protocol into context.
Squad Roots
Two canonical locations. Local wins on collision.
./squads/ # workspace-local (highest priority)
~/squads/ # global (home directory)Discovery: find ~/squads ./squads -maxdepth 2 -name "squad.yaml" -type f 2>/dev/null
Output Convention
All squad outputs write to a standard workspace inside the project:
{project-root}/.squads-outputs/{squad-name}/{timestamp}-{slug}/Resolution algorithm: 1. Project root: $SQUADS_PROJECT_ROOT env var, OR walk up from cwd() until .git/, OR cwd() 2. Output root: {project-root}/.squads-outputs/ 3. Run directory: {output-root}/{squad-name}/{ISO-timestamp}-{slug}/
Rules:
- The skill resolves the default path at runtime — squads inherit it automatically
output:in squad.yaml is optional. Three behaviors:- Absent → default (
.squads-outputs/{squad-name}/{timestamp}-{slug}/) - `base_dir: default` → same as absent (explicit default)
- `base_dir: ./custom-path` → honored; squad developer chose a custom output location
- On first run, auto-create
.squads-outputs/README.mdexplaining the directory to AI agents - Do NOT auto-modify
.gitignore— user decides per-project
Path examples:
*squad create my-app→.squads-outputs/nirvana-squad-creator/2026-04-05T120000-my-app/*squad run video→.squads-outputs/nirvana-video-creator/2026-04-05T185600-video-run/
Lifecycle: Outputs are intermediate. User moves final deliverables to their project structure. Old runs can be cleaned: rm -rf .squads-outputs/{squad}/{old-run}/
Environment variable: At runtime, squads receive $SQUAD_RUN_DIR pointing to their resolved run directory. All artifact writes go there.
Resolver: lib/output-resolver.js implements path resolution. Runtimes MUST use this resolver.
Skill Layout (self-contained)
This skill is self-contained. All resources live under the skill directory:
skills/squads/
├── SKILL.md ← this file
├── SQUAD_PROTOCOL_V4.md ← source of truth (21 sections)
├── SQUAD_PROTOCOL.md ← legacy v2.0 (deprecated)
├── adapters/{runtime}.{md,yaml} ← 5 runtime adapters
├── schemas/*.json ← 5 JSON schemas (squad, agent, task, adapter, handoff)
├── references/01..11-*.md ← loaded on demand by intent
├── templates/*.tmpl ← 7 agent/task/workflow/squad templates
├── lib/*.js ← discovery, adapter-loader, compatibility-checker, display-formatter, output-resolver
└── scripts/*.sh ← activate-squad.sh, validate-squad.shFirst Invocation
1. Verify SQUAD_PROTOCOL_V4.md exists alongside this SKILL.md. 2. Check node>=18, python3>=3.8. 3. Create ~/squads/ if missing: mkdir -p ~/squads. 4. Report: Squad Protocol Engine v5.0.0 ready. Protocol: v4.0. Roots: ~/squads (N), ./squads (M).
Intent Classification
Classify user input → load ONLY the relevant reference files → execute.
| Intent | Keywords | Load references |
|---|---|---|
| DISCOVER | list, show, find, search, inspect, info, describe | references/01-discovery.md |
| CREATE | create, new, scaffold, generate, build squad | references/02-creation.md, references/05-schemas.md |
| VALIDATE | validate, check, verify, fix, repair, lint, audit | references/03-validation.md |
| ACTIVATE | activate, register, install, deps, enable | references/04-activation.md |
| MODIFY | add agent, remove, update, add task, add workflow | references/05-schemas.md |
| EXECUTE | run, execute, start, launch, resume, retry | references/06-workflows.md, references/07-execution.md |
| ADAPT | adapter, runtime, compatibility, feature matrix | references/08-runtime-contract.md, references/11-adapters-guide.md |
| UPGRADE | upgrade, migrate, convert, v4 | references/09-upgrade.md |
| OBSERVE | state, status, traces, artifacts, flow, runs | references/07-execution.md |
Critical rule: Read reference files BEFORE acting. Never guess squad structure. Multi-intent: process sequentially in dependency order.
Commands
Discovery
*squad list— list all squads (both roots)*squad list --format {table|card|compact|tree}— display format*squad inspect {name}— detailed squad view
Creation
*squad create {name}— interactive creation wizard (v4 format with protocol:"4.0", runtime_requirements, maxTurns mandatory)
Validation
*squad validate {name}— 18 blocking checks (Core + adapter)*squad validate {name} --report— AI-friendly fix guidance*squad validate {name} --fix— auto-fix common issues*squad validate {name} --runtime {id}— validate against specific adapter
Activation
*squad activate {name}— validate + check deps + verify adapter + register*squad deactivate {name}— remove registration, keep source
Modification
*squad add-agent {squad} {agent-name}— add agent with v4 template (maxTurns mandatory)*squad add-task {squad} {task-name}— add task (no owner, workflow binds)*squad add-workflow {squad} {workflow-name}— add workflow with DAG*squad remove {squad} {component}— remove component
Execution
*squad run {name}— execute default workflow*squad run {name} --workflow {wf}— execute specific workflow*squad run {name} --runtime {id}— force specific runtime*squad resume {name}— resume from checkpoint
Adapters
*squad adapters— list available runtime adapters*squad adapters inspect {runtime}— show adapter feature matrix*squad runtime— detect current runtime*squad compat {squad}— check squad compatibility with current runtime
Migration
*squad migrate {name}— migrate v2/v3.1 squad to v4 format*squad migrate {name} --from {v2|v3.1} --to v4— explicit migration
Observation
*squad status {name}— current execution state*squad traces {name}— execution traces*squad artifacts {name}— list produced artifacts
Meta
*squad help— show this command list
Creation Rules (v4)
When creating a NEW squad, ALWAYS:
1. Set protocol: "4.0" in squad.yaml. 2. Ask for target runtimes → set runtime_requirements.minimum. 3. Set features_required and features_optional. 4. Every agent MUST have maxTurns (default 25 for simple, 50 for complex). 5. Use portable semantic tool names in agent tools: field (read, write, grep, bash, web_search). 6. Tasks have NO owner — workflows bind agent→task. 7. Task acceptance criteria MUST be binary and verifiable. 8. Include <protocol-context> block in prompts for long-running subagents. 9. Declare output schemas in contracts: for chained tasks. 10. Set memory GC policy if persistent memory is used.
Agent Template (v4)
---
name: {agent-name}
description: "{verb} {domain}. Use when {trigger}. Do NOT use for {anti-pattern}."
maxTurns: 25
tools: [read, write, grep]
model: sonnet
runtimes:
claude-code:
tools: [Read, Write, Grep, Bash]
---
You are a {specific role} for {domain}. You {primary action}. You {boundary}.
# Guidelines
## DO
- {principle 1}
- {principle 2}
## DO NOT
- {anti-pattern 1}
- {anti-pattern 2}
# Process
1. {step 1}
2. {step 2}
# Output
{format} at {location}
# Safety Boundaries
- NEVER {destructive action}
- If uncertain: {safe fallback}Anti-Patterns
NEVER:
- Guess squad structure — always read squad.yaml first.
- Load full SQUAD_PROTOCOL_V4.md into context — use TOC, read sections on demand.
- Create agents without
maxTurns— runtime may loop infinitely. - Create tasks with
owner:field — use workflow binding instead. - Use runtime-specific tool names in portable
tools:field — use semantic names. - Skip validation after create/modify — always run
*squad validate. - Invent agent roles not requested by user.
- Modify framework files (L1/L2 boundary).
- Run workflows without verifying all referenced agents/tasks exist.
- Execute destructive operations without confirmation.
- Hardcode runtime-specific values in squad.yaml root — use
runtimes.{id}.*namespace. - Create agents with body > 1.5% of context window — split instead.
- Pass full conversation history between steps — use handoff artifacts.
- Claim enforcement that doesn't exist (P8 Technical Honesty).
Backward Compatibility
- Old commands still work:
*create-squad→*squad create - v1, v2, v3 squads load via auto-upgrade shim (see
references/09-upgrade.md) - v3 harness features (doom loop, ralph loop, traces) remain opt-in
- v4 adds: mandatory maxTurns, runtime_requirements, adapters, portable tool names
- Run
*squad migrateto persist the upgrade to disk
Adapter Template
Use this template to author a new runtime adapter for Squad Protocol v4.0.
Replace {runtime-id}, {Runtime Name}, {Vendor}, and all bracketed placeholders. Remove sections that do not apply after replacing them with a "Not applicable — runtime does not support X" sentence.
Every adapter MUST provide sections 1, 2, 3, 6, 11, 13. Other sections are optional when the runtime genuinely lacks the underlying capability.
---
1. Adapter Metadata (required)
| Field | Value |
|---|---|
| Runtime ID | {runtime-id} |
| Runtime Name | {Runtime Name} |
| Vendor | {Vendor} |
| Adapter Version | 0.1.0 |
| Protocol Version | 4.0 |
| Minimum Runtime Version | {x.y.z} |
| Maintainer | {name or handle} |
| Homepage | {url} |
| Status | {experimental \ |
---
2. Feature Support Matrix (required)
Legend: ✅ enforced · 🟡 advisory · ⚠️ hybrid · ❌ unsupported · 🤝 convention
| Feature | Support | Mechanism |
|---|---|---|
max_turns | {support} | {mechanism} |
tool_whitelist | {support} | {mechanism} |
handoff_artifacts | {support} | {mechanism} |
subagent_spawning | {support} | {mechanism} |
sequential_execution | {support} | {mechanism} |
project_memory | {support} | {mechanism} |
global_memory | {support} | {mechanism} |
session_memory | {support} | {mechanism} |
hooks | {support} | {mechanism} |
sandboxing | {support} | {mechanism} |
web_search | {support} | {mechanism} |
file_write | {support} | {mechanism} |
shell_exec | {support} | {mechanism} |
fork_context | {support} | {mechanism} |
teammate_primitive | {support} | {mechanism} |
---
3. Concept Mapping (required)
3.1 Core → Runtime Primitives
| Core concept | {Runtime Name} primitive |
|---|---|
| Agent | {how this runtime represents an agent} |
| Task | {how tasks are represented} |
| Workflow | {workflow/orchestration representation} |
| Subagent invocation | {spawn mechanism, or "not supported"} |
| Session | {session concept} |
| Agent body | {how body is delivered to the model} |
3.2 Frontmatter Field Semantics
| Frontmatter field | Visible to LLM? | Purpose |
|---|---|---|
name | {yes/no} | {purpose} |
description | {yes/no} | {purpose} |
tools | {yes/no} | {purpose} |
maxTurns | {yes/no} | {purpose} |
---
4. Frontmatter Mapping (optional)
How a v4 squad carries {runtime-id}-specific config:
---
name: example-agent
description: "..."
maxTurns: 25
tools: [read, grep]
runtimes:
{runtime-id}:
# runtime-specific config
---Describe how runtimes.{runtime-id}.* overrides or augments universal fields.
---
5. Tool Whitelist Mechanics (recommended)
Enforcement level: {enforced | advisory | hybrid | unsupported}
{Explain mechanism. CLI flags used. What the whitelist actually does at runtime.}
Portable → local tool names:
| Portable | {Runtime} tool |
|---|---|
read | {...} |
write | {...} |
edit | {...} |
grep | {...} |
glob | {...} |
bash | {...} |
web_search | {...} |
web_fetch | {...} |
---
6. Max-Turns Mechanics (required)
| Property | Value |
|---|---|
| Frontmatter field | {maxTurns or runtime-specific name} |
| CLI flag | {flag name or "none"} |
| Runtime default | {value or "none (must be declared)"} |
| Hard cap | {value or "none"} |
Source: {citation from runtime codebase or documentation}
Typical values:
| Task type | Recommended maxTurns |
|---|---|
| Read + report | 3–5 |
| Code review | 10–20 |
| Fix + test | 15–30 |
---
7. Subagent Spawning (optional — document even if unsupported)
Primitive: {tool/mechanism name or "not supported"}
Mechanism: {Describe how parent spawns child}
Context inheritance: {none | partial | full}
Concurrency: {max concurrent or "1 (sequential only)"}
If unsupported: Document the fallback (typically sequential execution of workflow steps).
---
8. Memory Storage (optional)
8.1 Memory Scopes
| Core scope | Implementation | Location |
|---|---|---|
| Ephemeral | {...} | {...} |
| Session | {...} | {...} |
| Project | {...} | {...} |
| Global | {...} | {...} |
8.2 Size Limits
| Limit | Value | Source |
|---|---|---|
| {...} | {...} | {...} |
---
9. Context Window & Compaction (optional — numbers go here only)
9.1 Numeric Values
| Metric | Value | Source |
|---|---|---|
| Context window | {tokens} | {source} |
| Max output tokens | {tokens} | {source} |
| Compaction trigger | {tokens} | {source} |
9.2 Compaction Mechanism
{Describe how this runtime handles context pressure. Template? Summarization? Rolling window?}
9.3 Environment Overrides
{List env vars that affect context/compaction behavior.}
---
10. Hook System (optional)
Supported events:
| Event | When | Can abort? |
|---|---|---|
| {event} | {when} | {yes/no} |
If the runtime has no hook system, write: "Not applicable — {Runtime Name} does not provide a hook system."
---
11. Invocation Examples (required)
11.1 Interactive Session
{binary}11.2 Non-Interactive
{binary} --flag value "prompt"11.3 Environment Variables
export {RUNTIME_API_KEY}=...11.4 Running a Squad
squads run ./my-squad --runtime {runtime-id}---
12. Runtime-Specific Validators (optional)
| ID | Applies to | Level | Description |
|---|---|---|---|
{runtime-id}-{check-name} | {agent/task/squad/manifest} | {blocking/warning/info} | {description} |
---
13. Known Limitations (required)
| Limitation | Workaround | Source |
|---|---|---|
| {honest limitation} | {what squad author should do} | {citation or "observed"} |
Be honest. This section is for the squad author deciding whether this runtime is right for their squad. Underselling limitations here damages trust.
---
14. Source References (optional)
If claims in this adapter are verified against the runtime's source code or authoritative documentation, cite them:
| ID | Claim | Source |
|---|---|---|
| SRC-{X}-1 | {claim} | {file:lines or URL} |
---
15. Version History (required)
| Version | Date | Changes |
|---|---|---|
| 0.1.0 | {YYYY-MM-DD} | Initial adapter |
Adapter: Antigravity
Runtime-specific documentation for running Squad Protocol v4.0 squads on Antigravity (Google).
Status: Experimental. This adapter reflects current public understanding of Antigravity and will evolve as the runtime matures.
---
1. Adapter Metadata
| Field | Value |
|---|---|
| Runtime ID | antigravity |
| Runtime Name | Antigravity |
| Vendor | |
| Adapter Version | 0.1.0 |
| Protocol Version | 4.0 |
| Minimum Runtime Version | 0.1.0 |
| Status | experimental |
---
2. Feature Support Matrix
| Feature | Support | Mechanism |
|---|---|---|
max_turns | ❌ | Enforcement not verified |
tool_whitelist | ❌ | Advisory only |
handoff_artifacts | 🤝 | Convention |
subagent_spawning | ❌ | Evolving |
sequential_execution | ✅ | Default |
project_memory | ❌ | Manual only |
global_memory | ❌ | Not supported |
session_memory | ✅ | In-memory |
hooks | ❌ | Not supported |
sandboxing | ❓ | Not verified |
web_search | ❓ | Not verified |
file_write | ✅ | Built-in |
shell_exec | ✅ | Built-in |
fork_context | ❌ | Not supported |
teammate_primitive | ❌ | Not applicable |
---
3. Concept Mapping
3.1 Core → Runtime Primitives
| Core concept | Antigravity primitive |
|---|---|
| Agent | .md file with prose instructions |
| Task | .md file (harness-interpreted) |
| Workflow | Harness orchestrator |
| Subagent invocation | Not stable; harness falls back to sequential |
| Session | One Antigravity session |
3.2 Frontmatter Semantics
| Frontmatter field | Status on Antigravity |
|---|---|
name | Used by harness |
description | Used by harness |
tools | Advisory; rely on body guardrails |
maxTurns | Declared for portability; enforcement not verified |
---
4. Frontmatter Mapping
---
name: example
description: "..."
maxTurns: 25 # declare even though enforcement not verified
tools: [read, grep] # advisory only
------
5. Tool Whitelist Mechanics
Enforcement level: Advisory only.
Antigravity's tool gating is not formalized in a way this adapter can rely on. Squad authors must:
- Only grant tools the squad genuinely needs.
- Rely on body-level safety prose for misuse prevention.
- Plan for runtime to honor the whitelist best-effort.
---
6. Max-Turns Mechanics
| Property | Value |
|---|---|
| Frontmatter field | maxTurns |
| CLI flag | unknown |
| Runtime default | unverified |
| Hard cap | unverified |
Declare maxTurns for portability. Do not depend on runtime enforcement in the current Antigravity version.
---
7. Subagent Spawning
Primitive: Evolving.
Fallback: Sequential execution. The harness runs workflow steps in topological order one at a time.
Revisit this adapter when Antigravity formalizes a subagent API.
---
8. Memory Storage
| Core scope | Implementation |
|---|---|
| Ephemeral | Session state |
| Session | In-memory |
| Project | Manual file injection only |
| Global | Not supported |
---
9. Context Window & Compaction
Not publicly documented at this adapter version. Keep agent bodies small and handoff artifacts disciplined.
---
10. Hook System
Not supported.
---
11. Invocation Examples
11.1 Interactive Session
antigravity11.2 Running a Squad
squads run ./my-squad --runtime antigravity---
12. Runtime-Specific Validators
| ID | Applies to | Level | Description |
|---|---|---|---|
antigravity-experimental-advisory | squad | warning | Adapter is experimental; prefer stable runtimes for production |
antigravity-tool-advisory | agent | warning | Tool whitelist is advisory; depend on body safety prose |
---
13. Known Limitations
| Limitation | Workaround |
|---|---|
| Subagent model evolving | Use sequential workflows |
| Tool whitelist advisory | Minimize tool grants; body-level guardrails |
maxTurns enforcement unverified | Declare for portability, do not rely on it |
| No public compaction mechanics | Keep bodies small, handoffs disciplined |
| Experimental adapter (v0.1.0) | Prefer claude-code or gemini-cli for production |
Honest recommendation: use gemini-cli for production Google-family squads until Antigravity stabilizes.
---
14. Source References
No SRC citations yet. This adapter reflects public documentation as of the adapter version date.
---
15. Version History
| Version | Date | Changes |
|---|---|---|
| 0.1.0 | 2026-04-04 | Initial experimental adapter |
adapter:
runtime_id: antigravity
runtime_name: "Antigravity"
vendor: "Google"
adapter_version: 0.1.0
protocol_version: "4.0"
minimum_runtime_version: "0.1.0"
maintainer: "gutomec"
status: experimental
features_supported:
- id: session_memory
mechanism: enforced
- id: file_write
mechanism: enforced
- id: shell_exec
mechanism: enforced
- id: sequential_execution
mechanism: enforced
- id: handoff_artifacts
mechanism: convention
features_unsupported:
- id: subagent_spawning
fallback: "Sequential execution"
notes: "Subagent model is evolving in Antigravity; adapter will update when stable"
- id: tool_whitelist
fallback: "Tools granted permissively; squad body prose as advisory guardrail"
notes: "Enforcement level not yet stable"
- id: max_turns
fallback: "Squad author must be vigilant; no reliable runtime bound"
notes: "maxTurns enforcement not verified in current Antigravity versions"
- id: project_memory
fallback: "Manual file injection via system prompt"
- id: global_memory
fallback: "Not supported"
- id: hooks
fallback: "Validator agent as workflow step"
- id: fork_context
fallback: "Not supported"
- id: teammate_primitive
fallback: "Not applicable"
concept_mapping:
maxTurns:
frontmatter_field: maxTurns
cli_flag: null
default: null
hard_cap: null
notes: "Enforcement not verified; declare for portability but do not rely on it"
tools:
frontmatter_field: tools
cli_flag: null
enforced_by: "advisory only (until Antigravity formalizes tool gating)"
semantic_map:
read: read
write: write
edit: edit
grep: grep
glob: glob
bash: bash
shell: bash
web_search: web_search
web_fetch: web_fetch
model:
resolution:
sonnet: "gemini-2.5-pro"
opus: "gemini-2.5-pro"
memory:
ephemeral:
scope: "single invocation"
session:
scope: "single session"
location: "in-memory"
project:
scope: "manual injection"
global:
scope: "not supported"
subagent_spawn:
primitive: "evolving"
numeric_values:
context_window_tokens: null
max_output_tokens: null
default_max_turns: null
validators:
- id: antigravity-experimental-advisory
description: "Antigravity adapter is experimental; production squads should target a stable runtime"
level: warning
applies_to: squad
- id: antigravity-tool-advisory
description: "Tool whitelist is advisory on Antigravity; rely on body-level safety prose"
level: warning
applies_to: agent
invocation:
binary: "antigravity"
env_vars:
- name: GOOGLE_API_KEY
description: "Google API key"
required: false
examples:
- description: "Interactive session"
command: "antigravity"
hooks:
supported: false
events: []
abort_semantics: none
known_limitations:
- limitation: "Subagent model is evolving; no stable contract yet"
workaround: "Use sequential workflow execution; revisit adapter version when Antigravity formalizes subagent API"
- limitation: "Tool whitelist enforcement not verified"
workaround: "Rely on body-level safety prose; do not grant tools the squad does not need"
- limitation: "maxTurns enforcement not verified"
workaround: "Declare maxTurns for portability but do not depend on runtime enforcement"
- limitation: "No published compaction or context-window mechanics"
workaround: "Keep agent bodies small and handoffs disciplined"
- limitation: "Adapter version 0.1.0 is experimental"
workaround: "Prefer claude-code or gemini-cli adapters for production squads"
version_history:
- version: "0.1.0"
date: "2026-04-04"
changes: "Initial experimental adapter. Many features marked unsupported pending runtime stabilization."
Adapter: Claude Code
Runtime-specific documentation for running Squad Protocol v4.0 squads on Claude Code (Anthropic). This is the reference adapter: every claim is verified against the Claude Code source code.
---
1. Adapter Metadata
| Field | Value |
|---|---|
| Runtime ID | claude-code |
| Runtime Name | Claude Code |
| Vendor | Anthropic |
| Adapter Version | 1.0.0 |
| Protocol Version | 4.0 |
| Minimum Runtime Version | 2.0.0 |
| Maintainer | gutomec |
| Homepage | https://code.claude.com |
| Status | stable |
---
2. Feature Support Matrix
Legend: ✅ enforced · 🟡 advisory · ⚠️ hybrid · ❌ unsupported · 🤝 convention
| Feature | Support | Mechanism |
|---|---|---|
max_turns | ✅ | Harness-enforced; no default |
tool_whitelist | ✅ | Tools absent from API schema cannot be invoked |
handoff_artifacts | 🤝 | Free text inside content[].text; squads impose shape by prompt |
subagent_spawning | ✅ | Task tool spawns subagents |
sequential_execution | ✅ | Default |
project_memory | ✅ | CLAUDE.md injected as userContext |
global_memory | ✅ | ~/.claude/CLAUDE.md |
session_memory | ✅ | In-memory conversation |
hooks | ✅ | PreToolUse (gate) + PostToolUse (observe only) |
sandboxing | 🟡 | Permission modes (plan, acceptEdits, bypassPermissions) |
web_search | ✅ | Built-in WebSearch tool |
file_write | ✅ | Built-in Write, Edit tools |
shell_exec | ✅ | Built-in Bash tool |
fork_context | ✅ | Fork subagents inherit full conversation; maxTurns hardcoded 200 |
teammate_primitive | ✅ | Experimental; SendMessageTool, Unix Domain Sockets |
---
3. Concept Mapping
3.1 Core → Runtime Primitives
| Core concept | Claude Code primitive |
|---|---|
| Agent | .md file in .claude/agents/ or squad agents/ |
| Task | .md file (referenced by workflow) |
| Workflow | Harness or orchestrator; no native workflow file format |
| Subagent invocation | Task tool call |
| Session | Conversation in the Claude Code CLI |
| Agent body | System prompt injected via getSystemPrompt() |
| Agent frontmatter | Runtime config; NEVER sent to LLM |
3.2 Frontmatter Field Semantics
| Frontmatter field | Purpose | Visible to LLM? |
|---|---|---|
name | Agent identity and routing | No |
description | Selection criterion; exposed as whenToUse to planner | Indirectly (listed in agent registry, not injected into context) |
tools | Tool whitelist (hard-enforced in API schema) | No |
model | Model selection | No |
maxTurns | Turn limit for agent loop | No |
memory | Memory scope (user/project/local) | No |
effort | Reasoning depth hint | No |
Source: SRC-1, SRC-11.
---
4. Frontmatter Mapping
A v4 squad agent can carry Claude-Code-specific config under runtimes.claude-code.*:
---
name: reviewer
description: "Reviews code changes against acceptance criteria"
maxTurns: 25
tools: [read, grep, glob] # portable semantic names
runtimes:
claude-code:
tools: [Read, Grep, Glob, Bash] # CC local tool names (override)
model: claude-sonnet-4-6
effort: high
memory: project
---Resolution order for `tools`: 1. If runtimes.claude-code.tools is present, use it verbatim. 2. Otherwise, map portable names from tools via the semantic map (see §3). 3. Otherwise, no tools granted (fail-closed per Core P5).
---
5. Tool Whitelist Mechanics
Enforcement level: Hard (enforced).
Tools not listed literally do not exist in the schema sent to the API. The model cannot invoke what is not in the schema. This is not prompt instruction — it is an API-level constraint.
Source: SRC-11 (agentToolUtils.ts:157-160; runAgent.ts:502).
Portable → local tool names:
| Portable | Claude Code tool |
|---|---|
read | Read |
write | Write |
edit | Edit |
grep | Grep |
glob | Glob |
bash / shell | Bash |
web_search | WebSearch |
web_fetch | WebFetch |
Deny-by-default: If an agent declares tools: [] or omits tools entirely, it has no tool access and can only emit text.
Guardrails in body: Tool whitelist is the first line of defense. Body-level safety prose (NEVER delete outside output/) is the second line for misuse of tools the agent legitimately has.
---
6. Max-Turns Mechanics
Frontmatter field: maxTurns CLI flag: none (frontmatter only) Runtime default: none — without declaration, the agent loop has no upper bound Hard cap: 200 (fork subagents only; normal subagents have none)
Critical: The check in query.ts:1705 is if (maxTurns && ...). An agent without maxTurns in frontmatter can loop indefinitely. v4 Core P4 makes maxTurns mandatory precisely because of this.
Source: SRC-8 (query.ts:1705; forkSubagent.ts:65).
Typical values:
| Task type | Recommended maxTurns |
|---|---|
| Read + report | 3–5 |
| Code review pass | 10–20 |
| Targeted fix + test | 15–30 |
| Research across many searches | 25–50 |
| Large refactor | 50–100 |
---
7. Subagent Spawning
Primitive: Task tool.
Mechanism:
- A parent agent invokes the
Tasktool with a prompt and an agent type. - The runtime spawns a subagent context.
- The subagent receives
promptMessages = [createUserMessage({ content: prompt })]— a single user message, nothing else (SRC-1-Q1,AgentTool.tsx:538-540). - The subagent returns a handoff artifact (see §9 of Core spec).
Context inheritance: None by default. The subagent starts with just the prompt. No working directory, no file list, no tool results, no environment variables are automatically injected.
Fork path (experimental): FORK_SUBAGENT_TYPE inherits the full parent conversation. maxTurns hardcoded at 200. Use sparingly.
Concurrency: Up to 10 subagents can run in parallel (harness limit).
Source: SRC-1-Q1, SRC-8, SRC-1-Q4.
---
8. Memory Storage
8.1 Memory Scopes Mapped to Files
| Core scope | Claude Code implementation | Location |
|---|---|---|
| Ephemeral | Conversation state | In-memory |
| Session | Conversation + tool results | In-memory |
| Project | CLAUDE.md | Repo root, walks up from CWD |
| Global | ~/.claude/CLAUDE.md | User home |
| Project (per-agent) | .claude/agent-memory/{agent}.md | Project .claude/ |
| Local (per-agent, not committed) | .claude/agent-memory-local/{agent}.md | Project .claude/ |
| User (per-agent) | ~/.claude/agent-memory/{agent}.md | User home |
Source: SRC-9, SRC-10.
8.2 Injection Semantics
CLAUDE.md is injected as userContext — it appears before user messages but after the system prompt. This position gives it primacy bias: content near the top of the file is seen first.
Source: SRC-9 (claudemd.ts, runAgent.ts:394-395).
8.3 Size Limits
| Limit | Value | Source |
|---|---|---|
MAX_MEMORY_CHARACTER_COUNT | 40,000 chars (~10K tokens) | SRC-9-Q2 (claudemd.ts:92) |
| Standard CLAUDE.md truncation | none (file injected whole) | SRC-9-Q2 |
| AutoMem / TeamMem truncation | yes | SRC-9-Q2 |
Files larger than MAX_MEMORY_CHARACTER_COUNT are identified for warnings but still injected in full for standard memory.
8.4 Recommended Memory File Structure
# Project Memory
## Project Rules (always relevant)
- Use Prettier with 80 columns.
- All tests must use pytest.
- API responses follow { data, error, meta }.
## Learned Facts (auto-curated, conflict_resolution=replace)
- 2026-04-01: Staging DB at db.staging.internal:5432.
- 2026-04-03: Payment API fails if `currency` not uppercase.---
9. Context Window & Compaction
9.1 Numeric Values (Sonnet 200K)
| Metric | Value | Source |
|---|---|---|
| Context window | 200,000 tokens | spec |
CAPPED_DEFAULT_MAX_TOKENS | 8,000 | SRC-4 (autoCompact.ts:30) |
reservedTokensForSummary | min(maxOutput, 20_000) = 8,000 | SRC-4 |
effectiveContextWindow | 200,000 - 8,000 = 192,000 | SRC-4 |
AUTOCOMPACT_BUFFER_TOKENS | 13,000 | SRC-4 (autoCompact.ts:62) |
| Autocompact trigger | 192,000 - 13,000 = 179,000 (~89.5%) | SRC-4 |
| Warning threshold (UI) | autocompactThreshold - 20K ≈ 159,000 (~79.5%) | SRC-4 |
| Manual compact blocking | effectiveContextWindow - 3K ≈ 189,000 (~94.5%) | SRC-4 |
9.2 Formula
effectiveContextWindow = contextWindow - min(getMaxOutputTokensForModel(model), 20_000)
autocompactThreshold = effectiveContextWindow - AUTOCOMPACT_BUFFER_TOKENS9.3 Environment Override
CLAUDE_CODE_AUTO_COMPACT_WINDOW limits contextWindow before the calculation. It does not change the buffer size.
9.4 Compaction Variants
The runtime has three compaction prompts, not one (SRC-5, compact/prompt.ts):
| Variant | When | Differences |
|---|---|---|
BASE_COMPACT_PROMPT | Full conversation compaction | 9 standard sections |
PARTIAL_COMPACT_PROMPT | Recent portion only | §9 emphasizes verbatim citations |
PARTIAL_COMPACT_UP_TO_PROMPT | Older prefix only | §8 becomes "Work Completed", §9 becomes "Context for Continuing Work" |
Tool use is forbidden during compaction.
9.5 The 9 Compaction Sections
Compaction output is templated into 9 sections. Content that does not fit one of these sections disappears:
1. Primary Request and Intent
2. Key Technical Concepts
3. Files and Code Sections ← file names + line numbers + snippets
4. Errors and Fixes
5. Problem Solving
6. All User Messages ← VERBATIM — nearly empty for subagents
7. Pending Tasks
8. Current Work
9. Optional Next Step ← verbatim citations in PARTIAL variantCritical caveat: getCompactPrompt() does not branch by agent type (SRC-3-Q3, compact/prompt.ts:293-303). A subagent with only one user message (the workflow instruction) has a nearly empty §6.
9.6 Surviving Compaction — Placement Rules
| Data to preserve | Place in | Survives via section |
|---|---|---|
| Code paths, file names, line numbers | Snippets in prompt/output | 3 (Files and Code Sections) |
| Workflow instructions | Original subagent prompt | 6 (All User Messages) |
| Decisions and context | <protocol-context> block in prompt | 8 (Current Work) |
| Verbatim references | Direct citations in output | 9 (Optional Next Step) |
9.7 <protocol-context> Pattern
When a subagent must survive compaction, include a tagged context block at the top of its prompt:
<protocol-context>
Agent role: code-review-squad / bug-detector.
Input: output/findings.json from the analyzer.
Output: append to output/bug-findings.json.
Constraint: critical findings must include reproduction steps verbatim.
</protocol-context>The tagged block survives compaction via §8 (Current Work).
---
10. Hook System
Supported events:
| Event | When | Can abort? |
|---|---|---|
PreToolUse | Before tool invocation | Yes |
PostToolUse | After tool invocation | No |
SessionStart | Session begins | N/A |
SessionEnd | Session ends | N/A |
UserPromptSubmit | User submits a prompt | Yes |
Stop | Agent stops | N/A |
Critical: PostToolUse hooks run after the tool already executed. There is no abort field in the post-hook response schema. Use PreToolUse for gating, or add a validator agent as a workflow step.
Source: SRC-12 (toolExecution.ts:800,1483; types/hooks.ts:101-107).
---
11. Invocation Examples
11.1 Interactive Session
claude11.2 Non-Interactive with Specific Model
claude --model claude-sonnet-4-6 "review the latest PR"11.3 Environment Variables
export ANTHROPIC_API_KEY=sk-ant-...
export CLAUDE_CODE_AUTO_COMPACT_WINDOW=150000 # smaller effective window
export CLAUDE_CODE_AGENT_LIST_IN_MESSAGES=1 # attach agent list as system-reminder11.4 Running a Squad (conceptual)
Claude Code has no native "run squad" command; the harness (this skill) drives it. Typical flow:
# Harness loads squad, resolves adapter, spawns subagents via Task tool
squads run ./my-squad --runtime claude-code---
12. Runtime-Specific Validators
Claude Code adapter adds the following validators beyond Core:
| ID | Applies to | Level | Description |
|---|---|---|---|
cc-frontmatter-flat | agent | warning | Frontmatter should be flat YAML; nested agent:/persona: blocks indicate v2 legacy format |
cc-description-length | agent | warning | description field should be <= 1024 characters |
cc-max-turns-required | agent | blocking | maxTurns is mandatory (runtime has no default) |
---
13. Known Limitations
| Limitation | Workaround | Source |
|---|---|---|
No maxTurns default — omission = infinite loop | Always declare explicitly | SRC-8 |
| Subagents receive no context inheritance | Pass handoff artifact as JSON in prompt | SRC-1-Q1 |
| Compaction §6 (All User Messages) nearly empty for subagents | Use <protocol-context> block in prompt | SRC-3-Q3 |
| PostToolUse hooks cannot abort | Use PreToolUse for gating | SRC-12 |
| Context inheritance is all-or-nothing | Serialize what the child needs into the handoff | SRC-1-Q4 |
| No harness-level doom-loop detection | maxTurns bound only; add workflow reviewer | SRC-7 |
---
14. Source References
All claims in this adapter are verified against the Claude Code source code.
| ID | Claim | Source |
|---|---|---|
| SRC-1 | Frontmatter discarded from LLM context; description → whenToUse via formatAgentLine() | prompt.ts:43-45 |
| SRC-2 | Plain-text agent matching; no embeddings; two delivery modes via listViaAttachment | prompt.ts:59-64, 194-199 |
| SRC-3 | Handoff artifact schema fixed; content[].text is free text | agentToolUtils.ts:227-260 |
| SRC-4 | CAPPED_DEFAULT_MAX_TOKENS=8000; threshold = 179K (~89.5%) for Sonnet 200K | autoCompact.ts:30,62-65,72-76; context.ts:24 |
| SRC-5 | Three compaction prompt variants, 9 sections, tools forbidden during compaction | compact/prompt.ts |
| SRC-7 | Zero doom-loop detection; only MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES=3 for API failures | global repo search |
| SRC-8 | maxTurns without declaration = infinite loop; fork hardcoded 200 | query.ts:1705; forkSubagent.ts:65 |
| SRC-9 | CLAUDE.md injected as userContext, not systemPrompt | claudemd.ts; runAgent.ts:394-395 |
| SRC-9-Q2 | MAX_MEMORY_CHARACTER_COUNT=40000; no automatic truncation for standard CLAUDE.md | claudemd.ts:92 |
| SRC-10 | Memory scopes paths (user/project/local) | settings |
| SRC-11 | Tool restriction = hard enforcement at API schema level | agentToolUtils.ts:157-160; runAgent.ts:502 |
| SRC-12 | PreToolUse prevents execution; PostToolUse runs after; no abort in post schema | toolExecution.ts:800,1483; types/hooks.ts:101-107 |
| SRC-1-Q1 | userMessage(prompt) = text only; zero implicit context | AgentTool.tsx:538-540 |
| SRC-3-Q3 | Compaction does not differentiate agent type; §6 problematic for subagents | compact/prompt.ts:293-303 |
| SRC-1-Q4 | All-or-nothing context transfer; no selective inheritance | AgentTool schema |
---
15. Version History
| Version | Date | Changes |
|---|---|---|
| 1.0.0 | 2026-04-04 | Initial adapter for Squad Protocol v4.0. Supersedes references/cc-squad-standard.md. Incorporates all v3.1 findings. |
adapter:
runtime_id: claude-code
runtime_name: "Claude Code"
vendor: "Anthropic"
adapter_version: 1.0.0
protocol_version: "4.0"
minimum_runtime_version: "2.0.0"
maintainer: "gutomec"
homepage: "https://code.claude.com"
status: stable
features_supported:
- id: max_turns
mechanism: enforced
notes: "Harness enforces deterministically when declared. Without a declaration, the agent loop has no bound (see SRC-8)."
- id: tool_whitelist
mechanism: enforced
notes: "Tools not listed do not appear in the tool schema sent to the API. The model cannot invoke what is not in the schema (SRC-11)."
- id: handoff_artifacts
mechanism: convention
notes: "Content is free text inside content[].text. Squads must impose artifact shape via prompt discipline (SRC-3)."
- id: subagent_spawning
mechanism: enforced
notes: "Task tool spawns subagents. Each subagent receives a single user message as prompt (SRC-1-Q1)."
limits:
context_inheritance: "none by default; fork path inherits full history"
- id: sequential_execution
mechanism: enforced
- id: project_memory
mechanism: enforced
notes: "Project memory is injected as userContext before user messages (SRC-9)."
limits:
max_chars: 40000
- id: global_memory
mechanism: enforced
- id: session_memory
mechanism: enforced
- id: hooks
mechanism: enforced
notes: "PreToolUse prevents execution; PostToolUse runs after (no abort capability in post) (SRC-12)."
- id: web_search
mechanism: enforced
- id: file_write
mechanism: enforced
- id: shell_exec
mechanism: enforced
- id: fork_context
mechanism: enforced
notes: "Fork subagents inherit full conversation; maxTurns hardcoded at 200 (SRC-8)."
- id: teammate_primitive
mechanism: enforced
notes: "Experimental; uses SendMessageTool and Unix Domain Sockets."
features_unsupported: []
concept_mapping:
maxTurns:
frontmatter_field: maxTurns
cli_flag: null
default: null
hard_cap: 200
tools:
frontmatter_field: tools
cli_flag: null
enforced_by: "API schema (tools absent from schema cannot be invoked)"
semantic_map:
read: Read
write: Write
edit: Edit
grep: Grep
glob: Glob
bash: Bash
shell: Bash
web_search: WebSearch
web_fetch: WebFetch
model:
resolution:
haiku: "claude-haiku-4-5-20251001"
sonnet: "claude-sonnet-4-6"
opus: "claude-opus-4-6"
memory:
ephemeral:
scope: "single agent invocation"
session:
scope: "current conversation"
location: "in-memory"
project:
scope: "per-project"
file: "CLAUDE.md"
location: "repo root or parent directories"
global:
scope: "per-user on this machine"
file: "~/.claude/CLAUDE.md"
subagent_spawn:
primitive: "Task tool"
max_concurrent: 10
context_inheritance: "none (normal) or full (fork)"
numeric_values:
context_window_tokens: 200000
max_output_tokens: 8000
effective_context_tokens: 192000
compaction_buffer_tokens: 13000
compaction_threshold_pct: 89.5
compaction_threshold_tokens: 179000
warning_threshold_tokens: 159000
blocking_threshold_tokens: 189000
default_max_turns: null
hard_cap_max_turns: 200
memory_file_max_chars: 40000
validators:
- id: cc-frontmatter-flat
description: "Frontmatter must be flat YAML; nested 'agent:' / 'persona:' blocks indicate v2 legacy format and must be migrated or run via shim"
level: warning
applies_to: agent
- id: cc-description-length
description: "description field should be <= 1024 characters"
level: warning
limit: 1024
applies_to: agent
- id: cc-max-turns-required
description: "maxTurns is mandatory; runtime has no default (SRC-8)"
level: blocking
applies_to: agent
invocation:
binary: "claude"
env_vars:
- name: ANTHROPIC_API_KEY
description: "API key for Anthropic models"
required: false
- name: CLAUDE_CODE_AUTO_COMPACT_WINDOW
description: "Override context_window_tokens before effective window calculation"
required: false
- name: CLAUDE_CODE_AGENT_LIST_IN_MESSAGES
description: "Deliver agent list via system-reminder attachment instead of embedding in system prompt"
required: false
examples:
- description: "Interactive session"
command: "claude"
- description: "Run a specific subagent"
command: "claude --agent reviewer"
- description: "Non-interactive with specific model"
command: "claude --model claude-sonnet-4-6 'review the latest PR'"
hooks:
supported: true
events:
- PreToolUse
- PostToolUse
- SessionStart
- SessionEnd
- UserPromptSubmit
- Stop
abort_semantics: pre-only
known_limitations:
- limitation: "maxTurns without declaration = infinite loop"
workaround: "Always declare maxTurns explicitly in agent frontmatter"
tracking: "SRC-8 (query.ts:1705)"
- limitation: "Subagents receive no context inheritance by default"
workaround: "Pass handoff artifact as JSON in the prompt text"
tracking: "SRC-1-Q1 (AgentTool.tsx:538-540)"
- limitation: "Section 6 of compaction template (All User Messages) can be nearly empty for subagents"
workaround: "Put critical context in <protocol-context> block inside initial prompt"
tracking: "SRC-3-Q3 (compact/prompt.ts:293-303)"
- limitation: "PostToolUse hooks cannot abort; they run after tool already executed"
workaround: "Use PreToolUse for gating or add validator agent as workflow step"
tracking: "SRC-12 (types/hooks.ts:101-107)"
- limitation: "Context inheritance is all-or-nothing (none for normal subagents, full for fork)"
workaround: "Serialize exactly what the child needs into the handoff artifact"
tracking: "SRC-1-Q4 (AgentTool schema)"
- limitation: "No harness-level doom-loop detection"
workaround: "maxTurns bound only; implement workflow-level reviewer if needed"
tracking: "SRC-7 (global codebase search)"
source_references:
- id: SRC-1
claim: "Frontmatter is discarded from LLM context; description becomes whenToUse via formatAgentLine()"
source: "prompt.ts:43-45"
verified_at: "2026-03-15"
- id: SRC-2
claim: "Agent matching is plain-text; no embedding or ranking; two delivery modes via listViaAttachment"
source: "prompt.ts:59-64, 194-199"
verified_at: "2026-03-15"
- id: SRC-3
claim: "Handoff artifact has fixed schema; content[].text is free text"
source: "agentToolUtils.ts:227-260"
verified_at: "2026-03-15"
- id: SRC-4
claim: "CAPPED_DEFAULT_MAX_TOKENS=8000; effectiveContextWindow = contextWindow - min(maxOutput, 20K); AUTOCOMPACT_BUFFER_TOKENS=13000; threshold = effectiveContextWindow - 13K"
source: "autoCompact.ts:30,62-65,72-76; context.ts:24"
verified_at: "2026-03-15"
- id: SRC-5
claim: "Three compaction prompt variants, 9-section template, tools forbidden during compaction"
source: "compact/prompt.ts"
verified_at: "2026-03-15"
- id: SRC-7
claim: "No doom-loop detection in codebase; only MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES=3 for API failures"
source: "global codebase search"
verified_at: "2026-03-15"
- id: SRC-8
claim: "maxTurns without declaration = infinite loop (if (maxTurns && ...) in query.ts); fork subagents hardcoded 200"
source: "query.ts:1705; forkSubagent.ts:65"
verified_at: "2026-03-15"
- id: SRC-9
claim: "CLAUDE.md injected as userContext, not systemPrompt"
source: "claudemd.ts; runAgent.ts:394-395"
verified_at: "2026-03-15"
- id: SRC-9-Q2
claim: "MAX_MEMORY_CHARACTER_COUNT=40000; no automatic truncation of standard CLAUDE.md"
source: "claudemd.ts:92"
verified_at: "2026-03-15"
- id: SRC-10
claim: "Memory scopes: user→~/.claude/agent-memory/, project→.claude/agent-memory/, local→.claude/agent-memory-local/"
source: "settings documentation"
verified_at: "2026-03-15"
- id: SRC-11
claim: "Tool restriction is hard enforcement at API schema level"
source: "agentToolUtils.ts:157-160; runAgent.ts:502"
verified_at: "2026-03-15"
- id: SRC-12
claim: "PreToolUse prevents execution; PostToolUse runs after; no abort field in post hook response schema"
source: "toolExecution.ts:800,1483; types/hooks.ts:101-107"
verified_at: "2026-03-15"
- id: SRC-1-Q1
claim: "Subagent receives userMessage(prompt) only - single text element, zero implicit context"
source: "AgentTool.tsx:538-540"
verified_at: "2026-03-15"
- id: SRC-3-Q3
claim: "Compaction does not differentiate agent type; section 6 problematic for subagents"
source: "compact/prompt.ts:293-303"
verified_at: "2026-03-15"
- id: SRC-1-Q4
claim: "All-or-nothing context transfer; no selective inheritance API"
source: "AgentTool schema"
verified_at: "2026-03-15"
version_history:
- version: "1.0.0"
date: "2026-04-04"
changes: "Initial adapter for Squad Protocol v4.0. Supersedes cc-squad-standard.md."
Adapter: Codex CLI
Runtime-specific documentation for running Squad Protocol v4.0 squads on Codex CLI (OpenAI).
---
1. Adapter Metadata
| Field | Value |
|---|---|
| Runtime ID | codex |
| Runtime Name | Codex CLI |
| Vendor | OpenAI |
| Adapter Version | 0.1.0 |
| Protocol Version | 4.0 |
| Minimum Runtime Version | 0.5.0 |
| Status | beta |
---
2. Feature Support Matrix
Legend: ✅ enforced · 🟡 advisory · ⚠️ hybrid · ❌ unsupported · 🤝 convention
| Feature | Support | Mechanism |
|---|---|---|
max_turns | ✅ | CLI flag --max-turns |
tool_whitelist | ✅ | CLI flag --allowedTools |
handoff_artifacts | 🤝 | No native primitive; convention via structured output |
subagent_spawning | ❌ | Not supported natively |
sequential_execution | ✅ | Default |
project_memory | ❌ | No canonical project memory file |
global_memory | ❌ | Not supported |
session_memory | ✅ | In-memory conversation |
hooks | ❌ | Not supported |
sandboxing | 🟡 | --sandbox flag; behavior varies by version |
web_search | ✅ | Built-in |
file_write | ✅ | Built-in |
shell_exec | ✅ | Built-in |
fork_context | ❌ | Not supported |
teammate_primitive | ❌ | Not applicable |
---
3. Concept Mapping
3.1 Core → Runtime Primitives
| Core concept | Codex primitive |
|---|---|
| Agent | .md file, instructions passed via --instructions flag or stdin |
| Task | .md file (harness-interpreted) |
| Workflow | Harness orchestrator; no native workflow format |
| Subagent invocation | Not supported; harness spawns separate Codex processes |
| Session | One Codex CLI invocation |
| Agent body | Injected as system prompt or via --instructions file |
3.2 Frontmatter Field Semantics
| Frontmatter field | Purpose | Visible to LLM? |
|---|---|---|
name | Harness routing | No |
description | Harness selection | No (unless harness injects into prompt) |
tools → allowedTools | Passed as --allowedTools CLI flag | No |
maxTurns | Passed as --max-turns | No |
---
4. Frontmatter Mapping
---
name: reviewer
description: "Reviews code changes"
maxTurns: 25
tools: [read, grep, glob]
runtimes:
codex:
allowedTools: [read, grep, glob, bash]
model: gpt-4o
sandbox: true
------
5. Tool Whitelist Mechanics
Enforcement level: Enforced (via CLI flag).
The --allowedTools flag restricts which tools the Codex process can invoke. Tools not in the flag are unavailable for the duration of the invocation.
Portable → local tool names:
| Portable | Codex tool |
|---|---|
read | read |
write | write |
edit | edit |
grep | grep |
glob | glob |
bash / shell | bash |
web_search | web |
web_fetch | web |
---
6. Max-Turns Mechanics
| Property | Value |
|---|---|
| Frontmatter field | maxTurns |
| CLI flag | --max-turns |
| Runtime default | version-dependent; always declare explicitly |
| Hard cap | none published |
Typical values:
| Task type | Recommended maxTurns |
|---|---|
| Read + report | 5 |
| Code review | 15–25 |
| Fix + test | 25–40 |
---
7. Subagent Spawning
Primitive: None. Codex CLI has no native subagent/child-process primitive.
Fallback: The harness executes workflow steps sequentially in topological DAG order. For squads declaring features_optional: [subagent_spawning], the harness logs:
INFO: runtime 'codex' does not support subagent_spawning.
Executing workflow steps sequentially.Workaround for parallelism: The harness can spawn independent Codex processes for independent steps. This simulates parallelism at the OS level, not inside Codex.
---
8. Memory Storage
8.1 Memory Scopes
| Core scope | Codex implementation | Location |
|---|---|---|
| Ephemeral | Process-local state | In-memory |
| Session | Single CLI invocation | In-memory |
| Project | AGENTS.md or --instructions file | Repo root (convention) |
| Global | Not supported | — |
`AGENTS.md` is a widely-adopted convention for project-scoped agent instructions. Codex does not inject it automatically; the harness or user must pass it via --instructions.
---
9. Context Window & Compaction
9.1 Numeric Values
| Metric | Value |
|---|---|
| Context window | 128,000 tokens (gpt-4o) |
| Max output tokens | 4,096 (default) |
| Effective context | ~124,000 tokens |
Codex does not publish autocompact buffer mechanics equivalent to Claude Code's. Squads should design for the smaller 128K window and use aggressive handoff artifact discipline.
9.2 Compaction Mechanism
Codex relies on model-level compaction rather than harness-level summarization. When context fills, older turns may be truncated at the API boundary.
9.3 Environment Overrides
No documented env vars for context window override.
---
10. Hook System
Not applicable — Codex CLI does not provide a hook system equivalent to PreToolUse/PostToolUse. Pre/post behavior must be implemented as explicit workflow validator steps.
---
11. Invocation Examples
11.1 Interactive Session
codex11.2 Non-Interactive with Restrictions
codex --allowedTools read,grep,bash --max-turns 25 "review the diff"11.3 With Sandbox
codex --sandbox --allowedTools read,edit "apply the fix"11.4 Environment Variables
export OPENAI_API_KEY=sk-...11.5 Running a Squad
squads run ./my-squad --runtime codex---
12. Runtime-Specific Validators
| ID | Applies to | Level | Description |
|---|---|---|---|
codex-tools-lowercase | agent | warning | Tool names are lowercase in Codex |
codex-max-turns-required | agent | blocking | maxTurns declaration required |
codex-sequential-only | squad | info | Squads requiring subagent_spawning will degrade to sequential |
---
13. Known Limitations
| Limitation | Workaround |
|---|---|
| No native subagent spawning | Design squads tolerant of sequential execution |
| No hook system | Add validator agents as workflow steps |
| No standardized project memory injection | Pass AGENTS.md via --instructions manually |
| Smaller context window than Claude (128K) | Aggressive handoff discipline, smaller agent bodies |
| Sandbox behavior varies by version | Test sandbox against target version before production |
No fork_context primitive | Re-invoke with serialized parent context |
---
14. Source References
Claims in this adapter are based on publicly documented Codex CLI behavior. Where documentation is ambiguous, claims are conservative (feature marked unsupported rather than assumed).
---
15. Version History
| Version | Date | Changes |
|---|---|---|
| 0.1.0 | 2026-04-04 | Initial adapter for Squad Protocol v4.0 |
adapter:
runtime_id: codex
runtime_name: "Codex CLI"
vendor: "OpenAI"
adapter_version: 0.1.0
protocol_version: "4.0"
minimum_runtime_version: "0.5.0"
maintainer: "gutomec"
homepage: "https://github.com/openai/codex"
status: beta
features_supported:
- id: max_turns
mechanism: enforced
notes: "Enforced via --max-turns CLI flag. Default varies by version; always declare explicitly."
- id: tool_whitelist
mechanism: enforced
notes: "Enforced via --allowedTools CLI flag"
- id: handoff_artifacts
mechanism: convention
notes: "No runtime primitive; squads emit structured output the harness reads"
- id: sequential_execution
mechanism: enforced
- id: session_memory
mechanism: enforced
- id: web_search
mechanism: enforced
- id: file_write
mechanism: enforced
- id: shell_exec
mechanism: enforced
features_unsupported:
- id: subagent_spawning
fallback: "Harness executes workflow steps sequentially in topological order"
notes: "Codex CLI has no native subagent primitive. Parallelism is simulated by the harness spawning independent Codex processes."
- id: project_memory
fallback: "Use AGENTS.md convention or workspace-scoped system prompt injection"
notes: "Codex has no equivalent to a single canonical project memory file injected automatically"
- id: global_memory
fallback: "Use session-scope memory or external file injection"
- id: hooks
fallback: "Use validator agent as workflow step"
- id: fork_context
fallback: "Re-invoke with serialized parent context in prompt"
- id: teammate_primitive
fallback: "Not applicable"
concept_mapping:
maxTurns:
frontmatter_field: maxTurns
cli_flag: "--max-turns"
default: null
hard_cap: null
tools:
frontmatter_field: allowedTools
cli_flag: "--allowedTools"
enforced_by: "CLI flag passed to Codex process"
semantic_map:
read: read
write: write
edit: edit
grep: grep
glob: glob
bash: bash
shell: bash
web_search: web
web_fetch: web
model:
resolution:
haiku: "gpt-4o-mini"
sonnet: "gpt-4o"
opus: "gpt-4-turbo"
memory:
ephemeral:
scope: "single invocation"
session:
scope: "single conversation"
location: "in-memory"
project:
scope: "per-project"
file: "AGENTS.md"
location: "repo root (convention)"
global:
scope: "not natively supported"
subagent_spawn:
primitive: "none (harness simulates via process spawn)"
max_concurrent: "harness-dependent"
numeric_values:
context_window_tokens: 128000
max_output_tokens: 4096
effective_context_tokens: 124000
default_max_turns: null
memory_file_max_chars: null
validators:
- id: codex-tools-lowercase
description: "Codex tool names are lowercase; ensure runtimes.codex.allowedTools uses lowercase names"
level: warning
applies_to: agent
- id: codex-max-turns-required
description: "maxTurns must be declared (Core P4)"
level: blocking
applies_to: agent
- id: codex-sequential-only
description: "Squads requiring subagent_spawning degrade to sequential; verify workflow is acceptable"
level: info
applies_to: squad
invocation:
binary: "codex"
env_vars:
- name: OPENAI_API_KEY
description: "OpenAI API key"
required: true
examples:
- description: "Interactive session"
command: "codex"
- description: "Non-interactive with tool restrictions"
command: "codex --allowedTools read,grep,bash --max-turns 25 'review the diff'"
- description: "With sandbox"
command: "codex --sandbox --allowedTools read,edit 'apply the fix'"
hooks:
supported: false
events: []
abort_semantics: none
known_limitations:
- limitation: "No native subagent spawning; parallel workflow steps must run sequentially"
workaround: "Design squads that tolerate sequential execution; use lightweight agents to keep duration bounded"
- limitation: "No hook system; PreToolUse/PostToolUse behavior must be implemented as workflow validator steps"
workaround: "Add an explicit validator agent as a workflow step"
- limitation: "No standardized project memory file injection"
workaround: "Inject AGENTS.md content via system prompt manually or use --instructions flag"
- limitation: "Context window smaller than Claude (128K vs 200K)"
workaround: "Aggressive handoff artifact discipline; smaller agent bodies"
- limitation: "Sandbox mode restrictions vary by Codex version"
workaround: "Test sandbox in target version before production"
version_history:
- version: "0.1.0"
date: "2026-04-04"
changes: "Initial adapter for Squad Protocol v4.0"
Adapter: Cursor Agent
Runtime-specific documentation for running Squad Protocol v4.0 squads on Cursor Agent (Cursor).
---
1. Adapter Metadata
| Field | Value |
|---|---|
| Runtime ID | cursor |
| Runtime Name | Cursor Agent |
| Vendor | Cursor |
| Adapter Version | 0.1.0 |
| Protocol Version | 4.0 |
| Minimum Runtime Version | 0.40.0 |
| Status | beta |
---
2. Feature Support Matrix
| Feature | Support | Mechanism |
|---|---|---|
max_turns | ⚠️ | Hybrid (agent-loop level; flag varies) |
tool_whitelist | 🟡 | Advisory |
handoff_artifacts | 🤝 | Convention |
subagent_spawning | ❌ | Not supported |
sequential_execution | ✅ | Default |
project_memory | ✅ | .cursorrules |
global_memory | ❌ | Not native |
session_memory | ✅ | Chat session |
hooks | ❌ | Not supported |
sandboxing | ❓ | Not verified |
web_search | ✅ | Built-in |
file_write | ✅ | Via edit tool |
shell_exec | ✅ | Via terminal tool |
fork_context | ❌ | Not supported |
teammate_primitive | ❌ | Not applicable |
---
3. Concept Mapping
3.1 Core → Runtime Primitives
| Core concept | Cursor primitive |
|---|---|
| Agent | Cursor chat agent with custom system prompt |
| Task | .md file (harness-interpreted) |
| Workflow | Harness orchestrator |
| Subagent invocation | Not supported; sequential |
| Session | Chat session in Cursor IDE |
3.2 Frontmatter Semantics
| Frontmatter field | Purpose |
|---|---|
name | Routing |
description | Harness selection |
tools | Advisory |
maxTurns | Agent loop bound |
---
4. Frontmatter Mapping
---
name: reviewer
description: "Reviews code in Cursor IDE context"
maxTurns: 25
tools: [read, grep, edit]
runtimes:
cursor:
model: claude-sonnet-4-6
------
5. Tool Whitelist Mechanics
Enforcement level: Advisory.
Cursor's tool gating is not as strict as API-schema enforcement. Squad authors should:
- Rely on body-level safety prose (
NEVER delete outside output/). - Minimize tool grants to reduce attack surface.
Portable → local tool names:
| Portable | Cursor tool |
|---|---|
read | read |
write / edit | edit |
grep | grep |
glob | glob |
bash / shell | terminal |
web_search | search |
web_fetch | fetch |
---
6. Max-Turns Mechanics
| Property | Value |
|---|---|
| Frontmatter field | maxTurns |
| CLI flag | version-dependent |
| Runtime default | none reliable |
| Hard cap | none published |
Declare maxTurns in every agent.
---
7. Subagent Spawning
Primitive: None.
Fallback: Sequential execution of workflow steps.
---
8. Memory Storage
| Core scope | Implementation | Location |
|---|---|---|
| Ephemeral | Session state | In-memory |
| Session | Chat session | In-memory |
| Project | .cursorrules | Workspace root |
| Global | Not native | — |
`.cursorrules` is a per-workspace file that Cursor injects into agent sessions. It fulfills the project memory scope.
---
9. Context Window & Compaction
9.1 Numeric Values
Cursor routes through various model providers; context window depends on the selected model. For Claude models: 200K; for GPT-4o: 128K.
9.2 Compaction Mechanism
Not formally documented at this adapter version. Model-level summarization handles context pressure.
---
10. Hook System
Not supported.
---
11. Invocation Examples
11.1 Interactive (Cursor IDE)
Open Cursor IDE with agent panel. Custom prompts loaded from .cursorrules.
11.2 CLI
cursor-agent --workspace ./my-repo "review the diff"11.3 Running a Squad
squads run ./my-squad --runtime cursor---
12. Runtime-Specific Validators
| ID | Applies to | Level | Description |
|---|---|---|---|
cursor-max-turns-required | agent | blocking | maxTurns required |
cursor-tool-advisory | agent | warning | Tool whitelist is advisory; add body safety prose |
---
13. Known Limitations
| Limitation | Workaround |
|---|---|
| Tool whitelist advisory, not hard-enforced | Body-level safety prose as primary defense |
| No native subagent primitive | Sequential execution |
| No hook system | Validator agent as workflow step |
| Best experience requires Cursor IDE | CLI works but lacks IDE integrations |
---
14. Source References
Based on publicly documented Cursor Agent behavior.
---
15. Version History
| Version | Date | Changes |
|---|---|---|
| 0.1.0 | 2026-04-04 | Initial adapter for Squad Protocol v4.0 |
adapter:
runtime_id: cursor
runtime_name: "Cursor Agent"
vendor: "Cursor"
adapter_version: 0.1.0
protocol_version: "4.0"
minimum_runtime_version: "0.40.0"
maintainer: "gutomec"
homepage: "https://cursor.sh"
status: beta
features_supported:
- id: max_turns
mechanism: hybrid
notes: "Enforced at agent loop level; exact flag varies by version"
- id: tool_whitelist
mechanism: advisory
notes: "Partial enforcement; body-level guardrails recommended as second line"
- id: handoff_artifacts
mechanism: convention
- id: sequential_execution
mechanism: enforced
- id: session_memory
mechanism: enforced
- id: project_memory
mechanism: enforced
notes: ".cursorrules file, injected per-workspace"
- id: file_write
mechanism: enforced
- id: shell_exec
mechanism: enforced
- id: web_search
mechanism: enforced
features_unsupported:
- id: subagent_spawning
fallback: "Sequential execution"
notes: "No native subagent primitive in Cursor Agent"
- id: global_memory
fallback: "Manual per-user configuration"
- id: hooks
fallback: "Validator agent as workflow step"
- id: fork_context
fallback: "Re-invoke with serialized parent context"
- id: teammate_primitive
fallback: "Not applicable"
concept_mapping:
maxTurns:
frontmatter_field: maxTurns
cli_flag: null
default: null
hard_cap: null
tools:
frontmatter_field: tools
cli_flag: null
enforced_by: "Cursor agent loop (advisory)"
semantic_map:
read: read
write: edit
edit: edit
grep: grep
glob: glob
bash: terminal
shell: terminal
web_search: search
web_fetch: fetch
model:
resolution:
haiku: "claude-haiku-4-5"
sonnet: "claude-sonnet-4-6"
opus: "claude-opus-4-6"
memory:
ephemeral:
scope: "single invocation"
session:
scope: "chat session"
location: "in-memory"
project:
scope: "per-workspace"
file: ".cursorrules"
location: "workspace root"
global:
scope: "not native"
subagent_spawn:
primitive: "none"
numeric_values:
context_window_tokens: 200000
max_output_tokens: 8000
default_max_turns: null
validators:
- id: cursor-max-turns-required
description: "maxTurns must be declared (Core P4)"
level: blocking
applies_to: agent
- id: cursor-tool-advisory
description: "Tool whitelist is advisory; include body-level safety prose"
level: warning
applies_to: agent
invocation:
binary: "cursor-agent"
env_vars: []
examples:
- description: "Interactive via Cursor IDE"
command: "cursor (open Cursor IDE with agent panel)"
- description: "CLI invocation"
command: "cursor-agent --workspace ./my-repo 'review the diff'"
hooks:
supported: false
events: []
abort_semantics: none
known_limitations:
- limitation: "Tool whitelist is advisory, not hard-enforced at API schema level"
workaround: "Use body-level safety prose as primary defense"
- limitation: "No native subagent primitive"
workaround: "Sequential execution"
- limitation: "No hook system"
workaround: "Validator agent as workflow step"
- limitation: "Tight coupling to Cursor IDE for best experience"
workaround: "CLI invocation works but lacks IDE integrations"
version_history:
- version: "0.1.0"
date: "2026-04-04"
changes: "Initial adapter for Squad Protocol v4.0"
Adapter: Gemini CLI
Runtime-specific documentation for running Squad Protocol v4.0 squads on Gemini CLI (Google).
---
1. Adapter Metadata
| Field | Value |
|---|---|
| Runtime ID | gemini-cli |
| Runtime Name | Gemini CLI |
| Vendor | |
| Adapter Version | 0.1.0 |
| Protocol Version | 4.0 |
| Minimum Runtime Version | 1.0.0 |
| Status | beta |
---
2. Feature Support Matrix
| Feature | Support | Mechanism |
|---|---|---|
max_turns | ✅ | --max-turns flag |
tool_whitelist | ✅ | --allowed-tools flag |
handoff_artifacts | 🤝 | Convention via structured output |
subagent_spawning | ❌ | No native primitive |
sequential_execution | ✅ | Default |
project_memory | ✅ | GEMINI.md convention |
global_memory | ❌ | Not native |
session_memory | ✅ | In-memory conversation |
hooks | ❌ | Not supported |
sandboxing | 🟡 | --sandbox flag |
web_search | ✅ | Google Search grounding |
file_write | ✅ | Built-in |
shell_exec | ✅ | Built-in |
fork_context | ❌ | Not supported |
teammate_primitive | ❌ | Not applicable |
---
3. Concept Mapping
3.1 Core → Runtime Primitives
| Core concept | Gemini CLI primitive |
|---|---|
| Agent | .md file, prompt injected via CLI |
| Task | .md file (harness-interpreted) |
| Workflow | Harness orchestrator |
| Subagent invocation | Not supported; harness spawns parallel processes |
| Session | One Gemini CLI invocation |
3.2 Frontmatter Field Semantics
| Frontmatter field | Purpose |
|---|---|
name | Harness routing |
description | Harness selection |
tools → allowed_tools | Passed as --allowed-tools CLI flag |
maxTurns | Passed as --max-turns |
---
4. Frontmatter Mapping
---
name: analyst
description: "Analyzes large codebases leveraging 1M context"
maxTurns: 50
tools: [read, grep, glob, web_search]
runtimes:
gemini-cli:
model: gemini-2.5-pro
allowed_tools: [read_file, grep, glob, google_search]
------
5. Tool Whitelist Mechanics
Enforcement level: Enforced (via CLI flag).
Portable → local tool names:
| Portable | Gemini tool |
|---|---|
read | read_file |
write | write_file |
edit | edit_file |
grep | grep |
glob | glob |
bash / shell | shell |
web_search | google_search |
web_fetch | fetch |
---
6. Max-Turns Mechanics
| Property | Value |
|---|---|
| Frontmatter field | maxTurns |
| CLI flag | --max-turns |
| Runtime default | version-dependent |
| Hard cap | none published |
Gemini 1M context advantage: larger maxTurns budgets are viable because the runtime tolerates long histories without compaction pressure.
---
7. Subagent Spawning
Primitive: None. Falls back to sequential execution or harness-spawned independent processes.
---
8. Memory Storage
| Core scope | Implementation | Location |
|---|---|---|
| Ephemeral | Process state | In-memory |
| Session | CLI invocation | In-memory |
| Project | GEMINI.md | Repo root |
| Global | Not native | — |
`GEMINI.md` is Gemini CLI's equivalent of CLAUDE.md. The convention is less standardized; verify the file is being loaded in your Gemini version.
---
9. Context Window & Compaction
9.1 Numeric Values
| Metric | Value |
|---|---|
| Context window | 1,000,000 tokens (gemini-2.5-pro) |
| Max output tokens | 8,192 |
| Effective context | ~992,000 tokens |
9.2 Compaction Mechanism
With a 1M window, compaction pressure is greatly reduced. Gemini does not publish detailed compaction template mechanics. Squads can use larger agent bodies and longer histories.
---
10. Hook System
Not applicable — Gemini CLI does not provide a hook system.
---
11. Invocation Examples
11.1 Interactive Session
gemini11.2 Non-Interactive
gemini --allowed-tools read_file,grep,shell --max-turns 25 "review the diff"11.3 Environment Variables
export GEMINI_API_KEY=...
# or
export GOOGLE_API_KEY=...11.4 Running a Squad
squads run ./my-squad --runtime gemini-cli---
12. Runtime-Specific Validators
| ID | Applies to | Level | Description |
|---|---|---|---|
gemini-max-turns-required | agent | blocking | maxTurns required |
gemini-large-window-advisory | squad | info | 1M window allows larger bodies |
---
13. Known Limitations
| Limitation | Workaround |
|---|---|
| No native subagent primitive | Harness spawns independent processes |
| No hook system | Validator agent as workflow step |
GEMINI.md injection less standardized | Verify loading; fallback to system prompt |
| Compaction mechanics not detailed publicly | Design for 1M window; less critical |
---
14. Source References
Based on publicly documented Gemini CLI behavior.
---
15. Version History
| Version | Date | Changes |
|---|---|---|
| 0.1.0 | 2026-04-04 | Initial adapter for Squad Protocol v4.0 |
adapter:
runtime_id: gemini-cli
runtime_name: "Gemini CLI"
vendor: "Google"
adapter_version: 0.1.0
protocol_version: "4.0"
minimum_runtime_version: "1.0.0"
maintainer: "gutomec"
homepage: "https://github.com/google-gemini/gemini-cli"
status: beta
features_supported:
- id: max_turns
mechanism: enforced
notes: "Enforced via --max-turns or equivalent flag"
- id: tool_whitelist
mechanism: enforced
notes: "Enforced via --allowed-tools CLI flag"
- id: handoff_artifacts
mechanism: convention
- id: sequential_execution
mechanism: enforced
- id: session_memory
mechanism: enforced
- id: project_memory
mechanism: enforced
notes: "GEMINI.md convention, similar to CLAUDE.md"
- id: web_search
mechanism: enforced
notes: "Native Google Search grounding support"
- id: file_write
mechanism: enforced
- id: shell_exec
mechanism: enforced
features_unsupported:
- id: subagent_spawning
fallback: "Harness runs steps sequentially or spawns independent gemini processes"
notes: "No native subagent primitive"
- id: global_memory
fallback: "Use per-user file injection manually"
- id: hooks
fallback: "Use validator agent as workflow step"
- id: fork_context
fallback: "Re-invoke with serialized parent context"
- id: teammate_primitive
fallback: "Not applicable"
concept_mapping:
maxTurns:
frontmatter_field: maxTurns
cli_flag: "--max-turns"
default: null
hard_cap: null
tools:
frontmatter_field: allowed_tools
cli_flag: "--allowed-tools"
enforced_by: "CLI flag"
semantic_map:
read: read_file
write: write_file
edit: edit_file
grep: grep
glob: glob
bash: shell
shell: shell
web_search: google_search
web_fetch: fetch
model:
resolution:
haiku: "gemini-2.0-flash"
sonnet: "gemini-2.0-pro"
opus: "gemini-2.5-pro"
memory:
ephemeral:
scope: "single invocation"
session:
scope: "single conversation"
location: "in-memory"
project:
scope: "per-project"
file: "GEMINI.md"
location: "repo root"
global:
scope: "not natively supported"
subagent_spawn:
primitive: "none (harness-simulated)"
max_concurrent: "harness-dependent"
numeric_values:
context_window_tokens: 1000000
max_output_tokens: 8192
effective_context_tokens: 992000
default_max_turns: null
memory_file_max_chars: null
validators:
- id: gemini-max-turns-required
description: "maxTurns must be declared (Core P4)"
level: blocking
applies_to: agent
- id: gemini-large-window-advisory
description: "Gemini has 1M context; squads can use larger agent bodies if needed"
level: info
applies_to: squad
invocation:
binary: "gemini"
env_vars:
- name: GEMINI_API_KEY
description: "Google AI API key"
required: true
- name: GOOGLE_API_KEY
description: "Alternative name for GEMINI_API_KEY"
required: false
examples:
- description: "Interactive session"
command: "gemini"
- description: "Non-interactive with tool restrictions"
command: "gemini --allowed-tools read_file,grep,shell --max-turns 25 'review the diff'"
- description: "With sandbox"
command: "gemini --sandbox 'apply the fix'"
hooks:
supported: false
events: []
abort_semantics: none
known_limitations:
- limitation: "No native subagent primitive; parallel steps run sequentially"
workaround: "Harness spawns independent gemini processes for parallel steps"
- limitation: "No hook system equivalent to PreToolUse/PostToolUse"
workaround: "Add validator agent as workflow step"
- limitation: "GEMINI.md injection convention less standardized than CLAUDE.md"
workaround: "Verify GEMINI.md is being loaded; pass via system prompt if needed"
- limitation: "Compaction semantics not publicly documented in detail"
workaround: "Design for the 1M window; compaction behavior less critical with large context"
version_history:
- version: "0.1.0"
date: "2026-04-04"
changes: "Initial adapter for Squad Protocol v4.0"
/**
* Adapter Loader — Load and validate runtime adapter manifests
*
* Adapters live at {skill-root}/adapters/{runtime_id}.yaml
* Each adapter declares features_supported, concept_mapping, numeric_values.
* Validated against schemas/adapter-schema.json.
*/
const fs = require('fs');
const path = require('path');
const yaml = require('yaml');
class AdapterLoader {
/**
* @param {string} skillRoot - Path to the squads skill directory
*/
constructor(skillRoot) {
this.skillRoot = skillRoot;
this.adaptersDir = path.join(skillRoot, 'adapters');
this.cache = new Map();
}
/**
* List all available adapter IDs
* @returns {string[]} Array of runtime_id strings
*/
listAdapters() {
try {
const files = fs.readdirSync(this.adaptersDir);
return files
.filter(f => f.endsWith('.yaml') && !f.startsWith('_'))
.map(f => f.replace('.yaml', ''));
} catch (error) {
console.error(`[ERROR] Cannot list adapters: ${error.message}`);
return [];
}
}
/**
* Load an adapter manifest by runtime_id
* @param {string} runtimeId - e.g., 'claude-code', 'codex', 'gemini-cli'
* @returns {object|null} Parsed adapter manifest or null on error
*/
loadAdapter(runtimeId) {
if (this.cache.has(runtimeId)) return this.cache.get(runtimeId);
const yamlPath = path.join(this.adaptersDir, `${runtimeId}.yaml`);
if (!fs.existsSync(yamlPath)) {
console.warn(`[WARN] Adapter not found: ${runtimeId}`);
return null;
}
try {
const content = fs.readFileSync(yamlPath, 'utf-8');
const parsed = yaml.parse(content);
if (!parsed.adapter || !parsed.adapter.runtime_id) {
throw new Error('Missing adapter.runtime_id');
}
this.cache.set(runtimeId, parsed);
return parsed;
} catch (error) {
console.error(`[ERROR] Failed to load adapter ${runtimeId}: ${error.message}`);
return null;
}
}
/**
* Get the feature support matrix for a runtime
* @param {string} runtimeId
* @returns {{ supported: Map<string, object>, unsupported: Map<string, object> }}
*/
getFeatureMatrix(runtimeId) {
const adapter = this.loadAdapter(runtimeId);
if (!adapter) return { supported: new Map(), unsupported: new Map() };
const supported = new Map();
const unsupported = new Map();
(adapter.features_supported || []).forEach(f => supported.set(f.id, f));
(adapter.features_unsupported || []).forEach(f => unsupported.set(f.id, f));
return { supported, unsupported };
}
/**
* Resolve a portable tool name to a runtime-local name
* @param {string} runtimeId
* @param {string} portableName - e.g., 'read', 'grep', 'bash'
* @returns {string|null} Runtime-local tool name or null
*/
resolveToolName(runtimeId, portableName) {
const adapter = this.loadAdapter(runtimeId);
if (!adapter || !adapter.concept_mapping || !adapter.concept_mapping.tools) return null;
const semanticMap = adapter.concept_mapping.tools.semantic_map;
if (!semanticMap) return null;
const resolved = semanticMap[portableName];
if (Array.isArray(resolved)) return resolved[0];
return resolved || null;
}
/**
* Resolve a model family hint to a concrete model identifier
* @param {string} runtimeId
* @param {string} familyHint - e.g., 'sonnet', 'opus', 'haiku'
* @returns {string|null} Concrete model ID or null
*/
resolveModel(runtimeId, familyHint) {
const adapter = this.loadAdapter(runtimeId);
if (!adapter || !adapter.concept_mapping || !adapter.concept_mapping.model) return null;
const resolution = adapter.concept_mapping.model.resolution;
return resolution ? resolution[familyHint] || null : null;
}
/**
* Get numeric values for a runtime (context window, compaction, etc.)
* @param {string} runtimeId
* @returns {object} Numeric values or empty object
*/
getNumericValues(runtimeId) {
const adapter = this.loadAdapter(runtimeId);
return (adapter && adapter.numeric_values) || {};
}
/**
* Get adapter-specific validators
* @param {string} runtimeId
* @returns {object[]} Array of validator definitions
*/
getValidators(runtimeId) {
const adapter = this.loadAdapter(runtimeId);
return (adapter && adapter.validators) || [];
}
/**
* Get adapter metadata summary (for display)
* @param {string} runtimeId
* @returns {object|null}
*/
getAdapterInfo(runtimeId) {
const adapter = this.loadAdapter(runtimeId);
if (!adapter) return null;
const a = adapter.adapter;
const supportedCount = (adapter.features_supported || []).length;
const unsupportedCount = (adapter.features_unsupported || []).length;
return {
runtimeId: a.runtime_id,
name: a.runtime_name,
vendor: a.vendor,
adapterVersion: a.adapter_version,
protocolVersion: a.protocol_version,
minRuntimeVersion: a.minimum_runtime_version,
status: a.status || 'unknown',
featuresSupported: supportedCount,
featuresUnsupported: unsupportedCount,
};
}
}
module.exports = { AdapterLoader };
/**
* Compatibility Checker — Verify squad ↔ adapter feature compatibility
*
* Checks features_required against adapter features_supported.
* Logs graceful degradation for features_optional not supported.
* Implements Core P9 (Graceful Degradation) and P5 (Fail-Closed).
*/
const { AdapterLoader } = require('./adapter-loader');
class CompatibilityChecker {
/**
* @param {string} skillRoot - Path to the squads skill directory
*/
constructor(skillRoot) {
this.adapterLoader = new AdapterLoader(skillRoot);
}
/**
* Check full compatibility of a squad against a runtime adapter
*
* @param {object} squadInfo - Squad metadata (from discovery or parsed squad.yaml)
* @param {string} runtimeId - Target runtime adapter ID
* @returns {{
* compatible: boolean,
* errors: string[],
* warnings: string[],
* degradations: { feature: string, fallback: string }[]
* }}
*/
checkCompatibility(squadInfo, runtimeId) {
const result = {
compatible: true,
errors: [],
warnings: [],
degradations: [],
};
// Load adapter
const adapter = this.adapterLoader.loadAdapter(runtimeId);
if (!adapter) {
result.compatible = false;
result.errors.push(`Adapter '${runtimeId}' not found or failed to load.`);
return result;
}
const { supported, unsupported } = this.adapterLoader.getFeatureMatrix(runtimeId);
// Check features_required (fail-closed: all must be supported)
const required = squadInfo.featuresRequired || [];
for (const feature of required) {
if (!supported.has(feature)) {
result.compatible = false;
const info = unsupported.get(feature);
const fallbackNote = info && info.fallback ? ` Fallback: ${info.fallback}` : '';
result.errors.push(
`REQUIRED feature '${feature}' is not supported by '${runtimeId}'.${fallbackNote}`
);
}
}
// Check features_optional (graceful degradation: log, continue)
const optional = squadInfo.featuresOptional || [];
for (const feature of optional) {
if (!supported.has(feature)) {
const info = unsupported.get(feature);
const fallback = (info && info.fallback) || 'Feature skipped.';
result.degradations.push({ feature, fallback });
result.warnings.push(
`OPTIONAL feature '${feature}' not supported by '${runtimeId}'. Degradation: ${fallback}`
);
}
}
// Check runtime_requirements.incompatible
if (squadInfo.runtimes) {
const incompatible = squadInfo.runtimes
.filter(r => r.type === 'incompatible')
.map(r => r.runtime);
if (incompatible.includes(runtimeId)) {
result.compatible = false;
result.errors.push(
`Squad explicitly declares '${runtimeId}' as incompatible.`
);
}
}
// Check protocol version
const adapterProtocol = adapter.adapter.protocol_version;
if (squadInfo.protocol && adapterProtocol) {
const squadMajor = parseInt(squadInfo.protocol);
const adapterMajor = parseInt(adapterProtocol);
if (squadMajor > adapterMajor) {
result.compatible = false;
result.errors.push(
`Squad targets protocol ${squadInfo.protocol} but adapter supports ${adapterProtocol}.`
);
}
}
return result;
}
/**
* Check compatibility against all declared runtimes
*
* @param {object} squadInfo
* @returns {Map<string, object>} runtimeId → compatibility result
*/
checkAllRuntimes(squadInfo) {
const results = new Map();
const runtimes = squadInfo.runtimes || [];
for (const r of runtimes) {
results.set(r.runtime, this.checkCompatibility(squadInfo, r.runtime));
}
return results;
}
/**
* Format compatibility report for display
*
* @param {object} result - From checkCompatibility()
* @param {string} runtimeId
* @returns {string} Formatted report
*/
formatReport(result, runtimeId) {
const lines = [];
const icon = result.compatible ? '✅' : '❌';
lines.push(`${icon} Runtime: ${runtimeId}`);
lines.push('');
if (result.errors.length > 0) {
lines.push(' Errors:');
result.errors.forEach(e => lines.push(` ✗ ${e}`));
}
if (result.degradations.length > 0) {
lines.push(' Degradations:');
result.degradations.forEach(d =>
lines.push(` ⚠ ${d.feature}: ${d.fallback}`)
);
}
if (result.warnings.length > 0 && result.degradations.length === 0) {
lines.push(' Warnings:');
result.warnings.forEach(w => lines.push(` ⚠ ${w}`));
}
if (result.errors.length === 0 && result.degradations.length === 0) {
lines.push(' All features fully supported.');
}
return lines.join('\n');
}
}
module.exports = { CompatibilityChecker };
/**
* Squad Discovery Engine v4.0 — Runtime-Agnostic
*
* PRIMARY METHOD: Bash find (handles tilde expansion natively)
* FALLBACK: Directory traversal (Node.js fs)
*
* v4 additions:
* - Protocol version detection (v4/v3.1/v2)
* - runtime_requirements parsing
* - features_required/optional parsing
* - Version classification for display
*/
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const yaml = require('yaml');
const { SquadDisplayFormatter } = require('./display-formatter');
class SquadDiscovery {
/**
* Discover all squads from both ./squads/ and ~/squads/
* Returns array of SquadInfo objects, deduplicated (local > home)
*/
static discoverAllSquads() {
try {
const localSquads = this.discoverLocation('./squads', 'local');
const homeSquads = this.discoverLocation('~/squads', 'home');
return this.mergeAndDeduplicate(localSquads, homeSquads);
} catch (error) {
console.error(`[ERROR] Discovery failed: ${error.message}`);
return [];
}
}
/**
* Discover squads in a single location
*/
static discoverLocation(location, locationType) {
const expandedPath = this.expandPath(location);
if (!this.dirExists(expandedPath)) return [];
if (!this.isReadable(expandedPath)) {
console.warn(`[WARN] Directory not readable: ${expandedPath}`);
return [];
}
try {
return this.discoverViaBashFind(expandedPath, locationType);
} catch (error) {
console.warn(`[WARN] Bash find failed, falling back to traversal: ${error.message}`);
return this.discoverViaTraversal(expandedPath, locationType);
}
}
/**
* PRIMARY DISCOVERY: Bash find
*/
static discoverViaBashFind(dir, locationType) {
const cmd = `find "${dir}" -maxdepth 2 -name "squad.yaml" -type f 2>/dev/null`;
let output;
try {
output = execSync(cmd, { encoding: 'utf-8' });
} catch (error) {
throw new Error(`Bash find failed: ${error.message}`);
}
const paths = output.trim().split('\n').filter(line => line.length > 0);
const squads = [];
for (const squadPath of paths) {
try {
const info = this.loadSquadInfo(squadPath, locationType);
squads.push(info);
} catch (err) {
console.warn(`[WARN] Failed to parse ${squadPath}: ${err.message}`);
}
}
return squads;
}
/**
* FALLBACK DISCOVERY: Directory traversal
*/
static discoverViaTraversal(dir, locationType) {
const squads = [];
try {
const entries = fs.readdirSync(dir, { withFileTypes: true });
for (const entry of entries) {
if (!entry.isDirectory() || entry.name.startsWith('.')) continue;
const squadYamlPath = path.join(dir, entry.name, 'squad.yaml');
if (!fs.existsSync(squadYamlPath)) continue;
try {
const info = this.loadSquadInfo(squadYamlPath, locationType);
squads.push(info);
} catch (err) {
console.warn(`[WARN] Failed to parse ${squadYamlPath}: ${err.message}`);
}
}
} catch (error) {
throw new Error(`Directory traversal failed: ${error.message}`);
}
return squads;
}
/**
* LAZY LOADING: Parse essential metadata + v4 fields
*/
static loadSquadInfo(yamlPath, location) {
const content = fs.readFileSync(yamlPath, 'utf-8');
let parsed;
try {
parsed = yaml.parse(content);
} catch (error) {
throw new Error(`Invalid YAML: ${error.message}`);
}
if (!parsed.name || !parsed.version) {
throw new Error('Missing required fields: name, version');
}
const agents = this.countItems(parsed, 'agents');
const workflows = this.countItems(parsed, 'workflows');
const tasks = this.countItems(parsed, 'tasks');
// v4: Detect protocol version
const protocolVersion = this.detectProtocolVersion(parsed, yamlPath);
// v4: Parse runtime requirements
const runtimes = this.parseRuntimes(parsed);
// v4: Parse features
const featuresRequired = parsed.features_required || [];
const featuresOptional = parsed.features_optional || [];
return {
name: parsed.name,
version: parsed.version,
protocol: protocolVersion,
description: parsed.description || '(no description)',
location,
path: path.dirname(yamlPath),
agents,
workflows,
tasks,
runtimes,
featuresRequired,
featuresOptional,
harness: !!parsed.harness,
};
}
/**
* Detect protocol version from manifest and agent files
* Returns: '4.0' | '3.1' | '2.0-cc' | '2.0-legacy' | 'unknown'
*/
static detectProtocolVersion(parsed, yamlPath) {
// Explicit declaration (v4+)
if (parsed.protocol) return parsed.protocol;
// Check for v4 indicators
if (parsed.runtime_requirements || parsed.features_required) return '4.0';
// Check for v3 indicators (harness block)
if (parsed.harness) return '3.x';
// Check agent files for format detection
const squadDir = path.dirname(yamlPath);
const agentFiles = this.getComponentFiles(parsed, 'agents');
for (const agentFile of agentFiles.slice(0, 1)) {
try {
const agentPath = path.join(squadDir, agentFile);
if (!fs.existsSync(agentPath)) continue;
const agentContent = fs.readFileSync(agentPath, 'utf-8');
// Check for nested agent: block (legacy v2)
if (agentContent.includes('agent:') && agentContent.includes('persona:')) {
return '2.0-legacy';
}
// Check for flat name: + description: (v2 CC or v4)
if (agentContent.includes('name:') && agentContent.includes('description:')) {
// v4 has mandatory maxTurns
if (agentContent.includes('maxTurns:')) return '4.0';
return '2.0-cc';
}
} catch (e) {
// Ignore parse errors during detection
}
}
return '2.0';
}
/**
* Parse runtime requirements from squad manifest
*/
static parseRuntimes(parsed) {
if (!parsed.runtime_requirements) return [];
const runtimes = [];
const rr = parsed.runtime_requirements;
if (Array.isArray(rr.minimum)) {
rr.minimum.forEach(r => runtimes.push({ runtime: r.runtime, type: 'minimum' }));
}
if (Array.isArray(rr.compatible)) {
rr.compatible.forEach(r => runtimes.push({ runtime: r.runtime, type: 'compatible' }));
}
return runtimes;
}
/**
* Get component file paths from manifest (supports both v4 string arrays and legacy objects)
*/
static getComponentFiles(parsed, type) {
const items = parsed[type] || (parsed.components && parsed.components[type]) || [];
return items.map(item => typeof item === 'string' ? item : (item.file || ''));
}
/**
* Count items in squad.yaml
*/
static countItems(parsed, type) {
if (Array.isArray(parsed[type])) return parsed[type].length;
if (parsed.components && Array.isArray(parsed.components[type])) return parsed.components[type].length;
return 0;
}
/**
* Merge with precedence: local > home
*/
static mergeAndDeduplicate(localSquads, homeSquads) {
const byName = new Map();
homeSquads.forEach(s => byName.set(s.name, s));
localSquads.forEach(s => byName.set(s.name, s));
return Array.from(byName.values()).sort((a, b) => a.name.localeCompare(b.name));
}
static expandPath(p) {
if (p.startsWith('~')) {
const home = process.env.HOME;
if (!home) throw new Error('HOME environment variable not set');
return p.replace('~', home);
}
return path.resolve(p);
}
static dirExists(p) {
try { return fs.statSync(p).isDirectory(); } catch { return false; }
}
static isReadable(p) {
try { fs.accessSync(p, fs.constants.R_OK); return true; } catch { return false; }
}
static formatSquads(squads, style = 'table', options = {}) {
return SquadDisplayFormatter.format(squads, style, options);
}
}
module.exports = { SquadDiscovery };
/**
* Squad Display Formatter — Beautiful Terminal Output
*
* Provides multiple formatting styles for squad listings:
* - Table: Organized columns with borders
* - Card: Individual squad cards with details
* - Compact: One-liner per squad
* - Tree: Hierarchical by type
*/
const colors = {
reset: '\x1b[0m',
bold: '\x1b[1m',
dim: '\x1b[2m',
// Foreground colors
red: '\x1b[31m',
green: '\x1b[32m',
yellow: '\x1b[33m',
blue: '\x1b[34m',
magenta: '\x1b[35m',
cyan: '\x1b[36m',
white: '\x1b[37m',
gray: '\x1b[90m',
// Background colors (for highlights)
bgBlue: '\x1b[44m',
bgGreen: '\x1b[42m',
bgYellow: '\x1b[43m',
};
class SquadDisplayFormatter {
/**
* Format squads for beautiful terminal display
*/
static format(squads, style = 'table', options = {}) {
if (squads.length === 0) {
return this.formatEmpty();
}
switch (style) {
case 'table':
return this.formatTable(squads, options);
case 'card':
return this.formatCards(squads, options);
case 'compact':
return this.formatCompact(squads, options);
case 'tree':
return this.formatTree(squads, options);
default:
return this.formatTable(squads, options);
}
}
/**
* Beautiful Table Format
*/
static formatTable(squads, options = {}) {
const sorted = this.sortSquads(squads, options);
const grouped = this.groupByLocation(sorted);
let output = '\n';
// Header
output += `${colors.bold}${colors.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${colors.reset}\n`;
output += `${colors.bold}${colors.green}✓ Found ${squads.length} Squads${colors.reset}`;
if (grouped.local.length > 0) {
output += ` ${colors.dim}(${grouped.local.length} local + ${grouped.home.length} home)${colors.reset}`;
}
output += '\n';
output += `${colors.bold}${colors.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${colors.reset}\n\n`;
// Local squads section
if (grouped.local.length > 0) {
output += this.formatLocationSection(grouped.local, 'Local Workspace', '📂', colors.blue);
}
// Home squads section
if (grouped.home.length > 0) {
output += this.formatLocationSection(grouped.home, 'Home Directory', '🏠', colors.magenta);
}
// Footer
output += `\n${colors.bold}${colors.cyan}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${colors.reset}\n`;
output += `${colors.dim}Tip: Use *inspect-squad {name} for details | *run-workflow {squad} {workflow} to execute${colors.reset}\n\n`;
return output;
}
/**
* Format location section with table
*/
static formatLocationSection(squads, title, icon, titleColor) {
let output = `${titleColor}${icon} ${title}${colors.reset}\n`;
output += `${colors.gray}${this.repeat('─', 78)}${colors.reset}\n`;
// Table header
output += this.formatTableHeader();
// Table rows
for (const squad of squads) {
output += this.formatTableRow(squad);
}
output += `\n`;
return output;
}
/**
* Format table header
*/
static formatTableHeader() {
const cols = {
name: 25,
version: 8,
agents: 10,
workflows: 12,
type: 15,
};
let header = '';
header += `${colors.bold}${colors.cyan}`;
header += this.pad('SQUAD NAME', cols.name);
header += this.pad('VERSION', cols.version);
header += this.pad('AGENTS', cols.agents);
header += this.pad('WORKFLOWS', cols.workflows);
header += this.pad('TYPE', cols.type);
header += `${colors.reset}\n`;
header += `${colors.gray}${this.repeat('─', 78)}${colors.reset}\n`;
return header;
}
/**
* Format table row
*/
static formatTableRow(squad) {
const cols = {
name: 25,
version: 8,
agents: 10,
workflows: 12,
type: 15,
};
const versionColor = this.getVersionColor(squad.version);
const typeLabel = squad.harness ? `${colors.green}[v3]${colors.reset}` : `${colors.yellow}[v${squad.version}]${colors.reset}`;
let row = '';
row += `${colors.cyan}${this.pad(squad.name, cols.name - 2)}${colors.reset} `;
row += this.pad(squad.version, cols.version - 1) + ' ';
row += this.pad(squad.agents.toString(), cols.agents - 1) + ' ';
row += this.pad(squad.workflows.toString(), cols.workflows - 1) + ' ';
row += this.pad(typeLabel.replace(/\x1b\[[0-9;]*m/g, ''), cols.type - 1);
row += '\n';
return row;
}
/**
* Card Format (detailed view)
*/
static formatCards(squads, options = {}) {
const sorted = this.sortSquads(squads, options);
let output = '\n';
output += `${colors.bold}${colors.green}✓ Squad Overview${colors.reset} ${colors.dim}(${squads.length} total)${colors.reset}\n\n`;
for (const squad of sorted) {
output += this.formatCard(squad);
}
return output;
}
/**
* Format individual card
*/
static formatCard(squad) {
const icon = squad.harness ? '⚡' : '📋';
const location = squad.location === 'local' ? '📂 Local' : '🏠 Home';
const version = squad.harness ? `${colors.green}v3 (Harness)${colors.reset}` : `${colors.yellow}v${squad.version}${colors.reset}`;
let card = '';
card += `┌─ ${icon} ${colors.bold}${squad.name}${colors.reset}\n`;
card += `│ Version: ${version}\n`;
card += `│ Location: ${location}\n`;
card += `│ Agents: ${colors.cyan}${squad.agents}${colors.reset} │ Workflows: ${colors.cyan}${squad.workflows}${colors.reset} │ Tasks: ${colors.cyan}${squad.tasks || 0}${colors.reset}\n`;
card += `│ Description: ${colors.dim}${squad.description}${colors.reset}\n`;
card += `└─ ${squad.path}\n\n`;
return card;
}
/**
* Compact Format (one-liner)
*/
static formatCompact(squads, options = {}) {
const sorted = this.sortSquads(squads, options);
let output = `\n${colors.bold}${colors.green}✓ ${squads.length} Squads${colors.reset}\n\n`;
for (const squad of sorted) {
const icon = squad.harness ? '⚡' : '📋';
const location = squad.location === 'local' ? '📂' : '🏠';
output += `${icon} ${colors.cyan}${squad.name}${colors.reset} ${location} v${squad.version} ${colors.dim}(${squad.agents}a, ${squad.workflows}w)${colors.reset}\n`;
}
output += `\n`;
return output;
}
/**
* Tree Format (hierarchical)
*/
static formatTree(squads, options = {}) {
const grouped = this.groupByType(squads);
let output = '\n';
output += `${colors.bold}${colors.cyan}Squad Hierarchy${colors.reset}\n`;
output += `${colors.gray}${this.repeat('─', 50)}${colors.reset}\n\n`;
const categories = Object.keys(grouped).sort();
for (let i = 0; i < categories.length; i++) {
const category = categories[i];
const categorySquads = grouped[category];
const isLast = i === categories.length - 1;
const prefix = isLast ? '└── ' : '├── ';
output += `${colors.bold}${prefix}${category}${colors.reset} ${colors.dim}(${categorySquads.length})${colors.reset}\n`;
for (let j = 0; j < categorySquads.length; j++) {
const squad = categorySquads[j];
const isLastSquad = j === categorySquads.length - 1;
const squadPrefix = isLast ? ' ' : '│ ';
const squadLine = isLastSquad ? '└── ' : '├── ';
const icon = squad.harness ? '⚡' : '📋';
output += `${squadPrefix}${squadLine}${icon} ${colors.cyan}${squad.name}${colors.reset} ${colors.dim}v${squad.version}${colors.reset}\n`;
}
output += '\n';
}
return output;
}
/**
* Empty state message
*/
static formatEmpty() {
return `
${colors.bold}${colors.yellow}⚠️ No Squads Found${colors.reset}
Searched locations:
${colors.dim}• ./squads/${colors.reset}
${colors.dim}• ~/squads/${colors.reset}
Getting started:
1. ${colors.cyan}Create first squad${colors.reset}
*create-squad my-first-squad
2. ${colors.cyan}Or import squads${colors.reset}
cp -r /path/to/squads/* ~/squads/
3. ${colors.cyan}Debug discovery${colors.reset}
*list-squads --debug
`;
}
/**
* Helper: Group squads by location
*/
static groupByLocation(squads) {
return {
local: squads.filter(s => s.location === 'local'),
home: squads.filter(s => s.location === 'home'),
};
}
/**
* Helper: Group squads by type (based on name pattern)
*/
static groupByType(squads) {
const groups = {
'Meta-Squads': [],
'Nirvana Squads': [],
'Specialized': [],
'Infrastructure': [],
'Other': [],
};
for (const squad of squads) {
if (['nirvana-squad-creator', 'nirvana-squad-creator-v2', 'nirvana-squad-creator-v3', 'oracle-supreme-squad', 'paperclip-command-center'].includes(squad.name)) {
groups['Meta-Squads'].push(squad);
} else if (squad.name.startsWith('nirvana-')) {
groups['Nirvana Squads'].push(squad);
} else if (['devops-pipeline', 'data-pipeline', 'ml-pipeline', 'monitoring', 'security-audit', 'incident-response-squad'].includes(squad.name)) {
groups['Infrastructure'].push(squad);
} else if (['ultimate-landingpage', 'brandcraft', 'brandcraft-nirvana', 'awwwards-singularity-studio'].includes(squad.name)) {
groups['Specialized'].push(squad);
} else {
groups['Other'].push(squad);
}
}
// Remove empty groups
return Object.fromEntries(Object.entries(groups).filter(([_, squads]) => squads.length > 0));
}
/**
* Helper: Sort squads
*/
static sortSquads(squads, options = {}) {
const sortBy = options.sortBy || 'name';
const reverse = options.reverse || false;
let sorted = [...squads];
if (sortBy === 'name') {
sorted.sort((a, b) => a.name.localeCompare(b.name));
} else if (sortBy === 'version') {
sorted.sort((a, b) => a.version.localeCompare(b.version));
} else if (sortBy === 'agents') {
sorted.sort((a, b) => b.agents - a.agents);
} else if (sortBy === 'workflows') {
sorted.sort((a, b) => b.workflows - a.workflows);
}
if (reverse) {
sorted.reverse();
}
return sorted;
}
/**
* Helper: Pad string to width
*/
static pad(str, width) {
const clean = str.replace(/\x1b\[[0-9;]*m/g, ''); // Remove ANSI codes for length calculation
const padding = width - clean.length;
return str + ' '.repeat(Math.max(0, padding));
}
/**
* Helper: Repeat character
*/
static repeat(char, count) {
return char.repeat(count);
}
/**
* Helper: Get color based on version
*/
static getVersionColor(version) {
if (version === '3' || version.startsWith('3.')) {
return colors.green;
} else if (version === '2' || version.startsWith('2.')) {
return colors.yellow;
} else {
return colors.cyan;
}
}
}
module.exports = { SquadDisplayFormatter };
/**
* Squad Output Resolver — Skill-owned path resolution for squad artifacts.
*
* Convention: {project-root}/.squads-outputs/{squad-name}/{timestamp}-{slug}/
*
* The SKILL (not the squad) decides where outputs go. Squads that declare
* `output:` in squad.yaml are silently ignored — this resolver is authoritative.
*
* Usage:
* const { OutputResolver } = require('./output-resolver');
* const resolver = new OutputResolver();
* const runDir = resolver.resolveRunDir('nirvana-video-creator', 'hormozi-reel');
* // → /Users/guto/my-project/.squads-outputs/nirvana-video-creator/2026-04-05T185600-hormozi-reel/
*/
const fs = require('fs');
const path = require('path');
const OUTPUT_DIR_NAME = '.squads-outputs';
const PROJECT_ROOT_MARKERS = [
'.git',
'AGENTS.md',
'CLAUDE.md',
'package.json',
'pyproject.toml',
'Cargo.toml',
'go.mod',
'Makefile',
];
const README_TEMPLATE = `# Squad Outputs
This directory contains intermediate artifacts produced by AI agent squads.
Each subdirectory is a squad, and each run gets a timestamped folder.
Structure: \`{squad-name}/{YYYY-MM-DDTHHMMSS}-{slug}/\`
These are **working artifacts** — move final deliverables to your project's
appropriate directory when ready. You may delete old runs freely.
Managed by: Squad Protocol Engine v4.1 (skill: squads)
Convention: §16bis of SQUAD_PROTOCOL_V4.md
`;
class OutputResolver {
/**
* Resolve the project root directory.
* Priority: $SQUADS_PROJECT_ROOT > walk-up to marker > cwd()
*/
resolveProjectRoot(startDir) {
// 1. Environment variable override
const envRoot = process.env.SQUADS_PROJECT_ROOT;
if (envRoot && fs.existsSync(envRoot)) {
return path.resolve(envRoot);
}
// 2. Walk up from startDir until finding a project marker
let current = path.resolve(startDir || process.cwd());
const root = path.parse(current).root;
while (current !== root) {
for (const marker of PROJECT_ROOT_MARKERS) {
if (fs.existsSync(path.join(current, marker))) {
return current;
}
}
current = path.dirname(current);
}
// 3. Fallback to cwd
return path.resolve(startDir || process.cwd());
}
/**
* Resolve the output root directory: {project-root}/.squads-outputs/
*/
resolveOutputRoot(projectRoot) {
return path.join(projectRoot || this.resolveProjectRoot(), OUTPUT_DIR_NAME);
}
/**
* Generate ISO timestamp string: YYYY-MM-DDTHHMMSS
*/
generateTimestamp() {
const now = new Date();
const pad = (n) => String(n).padStart(2, '0');
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}T${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
}
/**
* Slugify a string for directory names.
*/
slugify(text) {
if (!text) return `run-${Date.now()}`;
return text
.toLowerCase()
.replace(/[^a-z0-9]+/g, '-')
.replace(/^-|-$/g, '')
.substring(0, 50) || `run-${Date.now()}`;
}
/**
* Resolve the full run directory path.
*
* Three modes based on squad.yaml `output.base_dir`:
* - absent → default (.squads-outputs/{squad}/{timestamp}-{slug}/)
* - "default" → same as absent
* - custom path → {project-root}/{custom-path}/{squad}/{timestamp}-{slug}/
*
* @param {string} squadName - Squad name (from squad.yaml name field)
* @param {string} [slug] - Human-readable slug for this run
* @param {object} [options]
* @param {string} [options.startDir] - Starting directory for project root detection
* @param {string} [options.baseDir] - Value of squad.yaml output.base_dir (absent/null/"default"/custom)
* @returns {string} Full absolute path to the run directory
*/
resolveRunDir(squadName, slug, options = {}) {
const { startDir, baseDir } = typeof options === 'string'
? { startDir: options, baseDir: undefined } // backward compat: resolveRunDir(name, slug, startDir)
: options;
const projectRoot = this.resolveProjectRoot(startDir);
const timestamp = this.generateTimestamp();
const safeSlug = this.slugify(slug);
const runDirName = `${timestamp}-${safeSlug}`;
// Determine output root: default or custom
let outputRoot;
if (!baseDir || baseDir === 'default') {
// Default convention: .squads-outputs/
outputRoot = this.resolveOutputRoot(projectRoot);
} else {
// Custom: squad developer chose a specific path
outputRoot = path.isAbsolute(baseDir)
? baseDir
: path.join(projectRoot, baseDir);
}
return path.join(outputRoot, squadName, runDirName);
}
/**
* Create the run directory and ensure README.md exists at output root.
* @param {string} runDir - Path from resolveRunDir()
* @returns {string} The created runDir path
*/
ensureRunDir(runDir) {
fs.mkdirSync(runDir, { recursive: true });
this.ensureReadme(path.dirname(path.dirname(runDir)));
return runDir;
}
/**
* Auto-create README.md at .squads-outputs/ root for AI discoverability.
*/
ensureReadme(outputRoot) {
const readmePath = path.join(outputRoot, 'README.md');
if (!fs.existsSync(readmePath)) {
fs.writeFileSync(readmePath, README_TEMPLATE, 'utf-8');
}
}
/**
* List all runs for a squad.
* @param {string} squadName
* @param {string} [startDir]
* @returns {string[]} Array of run directory paths, sorted newest first
*/
listRuns(squadName, startDir) {
const outputRoot = this.resolveOutputRoot(this.resolveProjectRoot(startDir));
const squadDir = path.join(outputRoot, squadName);
if (!fs.existsSync(squadDir)) return [];
return fs.readdirSync(squadDir)
.filter(d => fs.statSync(path.join(squadDir, d)).isDirectory())
.sort()
.reverse()
.map(d => path.join(squadDir, d));
}
/**
* Get the latest run directory for a squad.
* @param {string} squadName
* @param {string} [startDir]
* @returns {string|null}
*/
latestRun(squadName, startDir) {
const runs = this.listRuns(squadName, startDir);
return runs.length > 0 ? runs[0] : null;
}
}
module.exports = { OutputResolver, OUTPUT_DIR_NAME, PROJECT_ROOT_MARKERS };
Squad Discovery
When to load
Intent: DISCOVER (keywords: list, show, find, search, inspect, info, describe)
Protocol Reference
SQUAD_PROTOCOL_V4.md §5.2 (Directory Layout)
Discovery Algorithm
Step 1: Find all squads
Search the two canonical roots for squad.yaml manifests:
find ~/squads ./squads -maxdepth 2 -name "squad.yaml" -type f 2>/dev/null | sort -uStep 2: Lazy loading
For each squad.yaml found, parse ONLY these fields for listing:
name(required)version(required)protocol(v4+)description(first 100 chars)components(count agents, tasks, workflows)runtime_requirements(runtime list for compatibility filtering)tags(if present)
Step 3: Deduplication
If same squad name exists in both ./squads/ and ~/squads/, prefer ./squads/ (local wins).
Step 4: Display format
List view (*squad list):
Squad Protocol Engine v4.0.0
Found N squads (M local, K global)
NAME VERSION PROTOCOL AGENTS TASKS WORKFLOWS RUNTIMES ROOT
my-squad 1.0.0 4.0 3 5 2 claude-code,codex ~/squads
legacy-squad 2.1.0 2.0 4 8 3 (legacy) ./squadsInspect view (*squad inspect {name}):
Read full squad.yaml and display all sections including:
- Manifest fields (name, version, protocol, description, author, license, tags)
- Components inventory (agents, tasks, workflows)
- Runtime requirements (minimum, compatible, incompatible)
- Features required and optional
- Runtime namespaces (keys only)
- Contracts (inter-task schemas)
- Memory configuration (if present)
- UI metadata (if present)
Debug mode
*squad list --debug shows:
- Search paths attempted
- Files found per path
- Parse errors (if any)
- Dedup decisions
- Protocol version detected per squad
Common Errors
~/squadsdoesn't exist → create it:mkdir -p ~/squads- Permission denied → check directory permissions
squad.yamlparse error → check YAML syntax
---
Runtime-Specific Details
Discovery itself is runtime-neutral. Filtering squads by runtime compatibility depends on which adapter you target:
| Runtime | See |
|---|---|
| Claude Code | adapters/claude-code.md §2 |
| Gemini CLI | adapters/gemini-cli.md §2 |
| Codex | adapters/codex.md §2 |
| Cursor | adapters/cursor.md §2 |
| Antigravity | adapters/antigravity.md §2 |
Squad Creation
When to load
Intent: CREATE (keywords: create, new, scaffold, generate, build squad)
Protocol Reference
SQUAD_PROTOCOL_V4.md §5–§8
Creation Pipeline
Phase 1: Elicitation
| Question | Field | Default |
|---|---|---|
| Squad purpose? | description | — |
| Squad name? (kebab-case) | name | derived from purpose |
| Target runtimes? | runtime_requirements | [claude-code] |
| Required features? | features_required | [max_turns, tool_whitelist, handoff_artifacts] |
| Domain/tags? | tags | — |
| How many agents? | components.agents | 3 |
| Agent roles? | agent definitions | — |
| Slash command prefix? | slashPrefix | first 3 chars of name |
Phase 2: Scaffold
mkdir -p ~/squads/{name}/{agents,tasks,workflows,schemas}Phase 3: Generate squad.yaml (v4)
name: my-squad
version: "1.0.0"
protocol: "4.0"
description: "What this squad does"
author: "author"
license: MIT
slashPrefix: msq
tags: [domain, keywords]
runtime_requirements:
minimum:
- runtime: claude-code
version: ">=2.0.0"
compatible:
- runtime: gemini-cli
version: ">=1.0.0"
incompatible: []
features_required:
- max_turns
- tool_whitelist
- handoff_artifacts
features_optional:
- subagent_spawning
- project_memory
components:
agents:
- agents/agent-one.md
- agents/agent-two.md
tasks:
- tasks/task-one.md
- tasks/task-two.md
workflows:
- workflows/main-pipeline.yaml
contracts:
task-one → task-two: schemas/task-one-output.json
ui:
icon: "🔬"
category: "research"
agents_metadata:
agent-one:
icon: "🔍"
archetype: Builder
agent-two:
icon: "📊"
archetype: Guardian
memory:
persistent:
enabled: true
scope: project
file: SQUAD_MEMORY.md
max_chars: 40000
garbage_collection:
max_learned_facts: 200
review_interval_days: 30
conflict_resolution: replace
runtimes:
claude-code:
# CC-specific config (optional)
codex:
# Codex-specific config (optional)Phase 4: Generate agents (v4 flat frontmatter)
Use template: templates/agent-cc.md.tmpl (updated for v4).
---
name: agent-name
description: "[Verb] [domain]. Use when [trigger]. Do NOT use for [anti-pattern]."
maxTurns: 25
tools: [read, write, bash]
model: sonnet
---
You are [specific role] for [domain]. You [primary action]. You [primary boundary].
# Guidelines
## DO
- [Principle 1]
- [Principle 2]
- [Principle 3]
## DO NOT
- [Anti-pattern 1]
- [Anti-pattern 2]
# Process
1. [Step 1]
2. [Step 2]
3. [Step 3]
# Output
[Format] at [location]
## GOOD example
[Concrete example]
## BAD example (do NOT produce)
[What to avoid + why]
# Safety Boundaries
- NEVER [destructive action]
- If uncertain: [safe fallback]Rules:
maxTurnsis mandatory (P4).- Body target: 1000–2000 tokens. Max: 1.5% of target context window.
- Prose only in body — no YAML.
- 4 sections minimum: identity + Guidelines + Process + Output.
- Use portable semantic tool names (
read,write,grep, etc.). Override per runtime underruntimes.{id}.toolsif needed.
Phase 5: Generate tasks (v4 flat frontmatter)
Use template: templates/task-cc.md.tmpl.
---
name: task-name
description: "What this accomplishes"
---
# Task Name
## Input
[What this receives]
## Steps
1. [Step]
2. [Step]
## Output
[What to produce, where to save]
## Acceptance Criteria
- [Binary verifiable criterion]
- [Binary verifiable criterion]
## Output Schema
[Inline description or reference to schemas/task-name.json]Rules:
- Tasks do NOT have owners. Workflows bind agents to tasks.
- Acceptance criteria must be binary and verifiable.
- Declare output schema if downstream tasks consume this output.
Phase 6: Generate workflow
name: main_pipeline
description: "What this workflow accomplishes"
steps:
- id: step-1
agent: agent-one
task: task-one
depends_on: []
- id: step-2
agent: agent-two
task: task-two
depends_on: [step-1]
success_indicators:
- "All target files processed"
- "Output schema validated"
- "No unaddressed critical findings"Phase 7: Validate
Run *squad validate {name} → must pass all Core blocking checks.
---
Runtime-Specific Details
| Runtime | Notes on creation |
|---|---|
| Claude Code | adapters/claude-code.md §4 |
| Gemini CLI | adapters/gemini-cli.md §4 |
| Codex | adapters/codex.md §4 |
| Cursor | adapters/cursor.md §4 |
| Antigravity | adapters/antigravity.md §4 |
Squad Validation
When to load
Intent: VALIDATE (keywords: validate, check, verify, fix, repair, lint, audit)
Protocol Reference
SQUAD_PROTOCOL_V4.md §15
Validation — Two-Stage
Validation runs in two stages:
1. Core validation — universal rules that hold on every runtime (this document). 2. Adapter validation — runtime-specific rules declared in each adapter's §12 Runtime-Specific Validators.
Format Detection
The validator accepts v4.0 (native), v3.1 (auto-upgrade), and v2.0 (legacy shim) formats.
| Indicator | Detected version |
|---|---|
protocol: "4.0" in manifest | v4.0 native |
protocol absent, flat agent frontmatter with mandatory maxTurns | v3.1 |
protocol absent, flat name:+description: in agent | v2.0 CC flat |
Nested agent:/persona: blocks in agent | v2.0 legacy nested |
Core Blocking Checks (MUST pass)
| # | Check | v4 | v2 legacy |
|---|---|---|---|
| B1 | squad.yaml exists and valid YAML | Same | Same |
| B2 | name is kebab-case (2–50 chars) | Same | Same |
| B3 | version is valid semver | Same | Same |
| B4 | protocol declared and supported | Required | Auto-injected by shim |
| B5 | All files in components.* exist on disk | Same | Same |
| B6 | Agent has identity | name+description+maxTurns | agent.name+agent.id |
| B7 | Agent frontmatter valid YAML | Same | Same |
| B8 | `maxTurns` declared per agent | Blocking | Shim warns + defaults to 25 |
| B9 | Task has identity | name | task+owner |
| B10 | Task frontmatter valid YAML | Same | Same |
| B11 | Workflow has name | name or workflow_name | Same |
| B12 | Agent names unique | Same | Same |
| B13 | Task names unique | Same | Same |
| B14 | Workflow step agent/task refs resolve | Same | Same |
| B15 | Workflow DAG is acyclic | Same | Same |
| B16 | runtime_requirements.minimum has at least one runtime | Required | Auto-injected by shim |
| B17 | Every runtime in runtime_requirements has adapter available | Required | Auto-fills to claude-code |
| B18 | If contracts: present, schemas exist and valid | Same | Same |
Non-Blocking Checks (Advisories)
These do NOT block validation but are flagged as warnings:
tools:declared per agent.descriptionfollows "[verb] [domain]. Use when… Do NOT use for…" pattern.- Body contains four canonical sections (identity, guidelines, process, output).
features_requirednon-empty.- Memory GC policy declared if persistent memory is used.
ui.agents_metadatapresent for marketplace display.
Adapter Validation Stage
After Core passes, the harness loads each target adapter and runs its runtime-specific validators. Examples:
- Claude Code:
cc-max-turns-required(blocking),cc-description-length(warning) - Codex:
codex-tools-lowercase(warning),codex-sequential-only(info) - Gemini CLI:
gemini-max-turns-required(blocking)
See each adapter's §12 for its validators list.
Validation Procedure
1. Detect squad version. 2. Run Core blocking checks (B1–B18). 3. Run Core advisory checks. 4. For each target runtime in runtime_requirements, load adapter and run adapter validators. 5. Report results with score. 6. If errors: offer --report for AI-friendly fix guidance. 7. If errors: offer --fix for auto-fix of common issues.
CLI Commands
squads validate ./my-squad # Validate with colored report
squads validate ./my-squad --json # JSON output
squads validate ./my-squad --report # AI-friendly fix report
squads validate ./my-squad --fix # Auto-fix then validate
squads validate ./my-squad --runtime claude-code # Validate only against specific adapter---
Runtime-Specific Details
Adapter-level validators live in each adapter's §12:
| Runtime | See |
|---|---|
| Claude Code | adapters/claude-code.md §12 |
| Gemini CLI | adapters/gemini-cli.md §12 |
| Codex | adapters/codex.md §12 |
| Cursor | adapters/cursor.md §12 |
| Antigravity | adapters/antigravity.md §12 |
CC Squad Standard — MOVED
This document has moved. Its content is now part of the Claude Code adapter.
See: `adapters/claude-code.md`
---
Why did this move?
In Squad Protocol v4.0, runtime-specific documentation lives in adapter files under adapters/. The Claude Code adapter is the reference implementation and contains all the detail previously in this file:
- Claude Code frontmatter format and field semantics → §4
- Tool whitelist mechanics (hard enforcement via API schema) → §5
- Max-turns behavior → §6
- Subagent spawning via Task tool → §7
- Memory storage (
CLAUDE.md, agent-memory scopes) → §8 - Context window & compaction values → §9
- Hook system (
PreToolUse,PostToolUse) → §10 - Source references (SRC-1…SRC-12 citations) → §14
For runtime-neutral squad authoring guidance, see:
- `SQUAD_PROTOCOL_V4.md` — the Core spec
- `references/02-creation.md` — how to create a squad
- `references/11-adapters-guide.md` — how adapters work
---
name: {{agent-name}}
description: "{{when-to-use-one-paragraph}}"
tools: [Read, Write, Bash]
---
{{one-paragraph-identity-and-approach}}
## Guidelines
- {{principle-1}}
- {{principle-2}}
- {{principle-3}}
## Process
1. {{step-1}}
2. {{step-2}}
3. {{step-3}}
## Output
{{output-format-and-location}}
---
name: {{agent-name}}
description: "{{verb-domain}}. Use when {{trigger}}. Do NOT use for {{anti-pattern}}."
maxTurns: {{max-turns-default-25}}
tools: [{{portable-tools}}]
model: {{model-family-hint}}
runtimes:
claude-code:
tools: [{{cc-tool-names}}]
codex:
allowedTools: [{{codex-tool-names}}]
gemini-cli:
allowed_tools: [{{gemini-tool-names}}]
---
{{identity-2-3-specific-sentences}}
# Guidelines
## DO
- {{principle-1}}
- {{principle-2}}
- {{principle-3}}
## DO NOT
- {{anti-pattern-1}}
- {{anti-pattern-2}}
# Process
1. {{step-1}}
2. {{step-2}}
3. {{step-3}}
4. Write results to output/{{output-file}}.
# Output
{{output-format}} at output/{{output-location}}
## GOOD example
{{concrete-complete-example}}
## BAD example (do NOT produce)
{{what-to-avoid-and-why}}
# Safety Boundaries
- NEVER {{destructive-action}}
- If uncertain: {{safe-fallback}}
---
name: {{task-name}}
description: "{{what-this-task-accomplishes}}"
---
# {{Task Title}}
## Input
- {{input-description}}
## Steps
1. {{step-1}}
2. {{step-2}}
3. {{step-3}}
## Output
{{output-format-and-location}}
## Acceptance Criteria
- {{criterion-1}}
- {{criterion-2}}