diff --git a/.changeset/fix-squad-slash-command.md b/.changeset/fix-squad-slash-command.md new file mode 100644 index 000000000..dc4e364d6 --- /dev/null +++ b/.changeset/fix-squad-slash-command.md @@ -0,0 +1,76 @@ +--- +"@bradygaster/squad-sdk": minor +"@bradygaster/squad-cli": minor +--- + +Make `/squad` a real slash command — rename `squad-commands` skill to `squad` with `user-invocable: true` + +## What this enables + +Users can type `/squad` in any Copilot CLI session in a squad-initialized project and get the categorized command catalog (Install & Upgrade, Team Management, Issues & PRs, Plugins & Skills, Model & Cost, Sessions & State). This is what users naturally expect — Squad ships an in-chat command surface, and the slash key is the muscle memory. + +## Verified mechanism (Copilot CLI 1.0.62-2) + +Decompiling `~/.copilot/pkg/win32-x64/1.0.62-2/sdk/index.js` line 2618: + +```js +getLoadedSkills().filter(e => e.userInvocable) + .map(e => ({name: `/${eF(e)}`, isSkill: true, skill: e})) +``` + +Any skill with frontmatter `user-invocable: true` is auto-registered by Copilot CLI as a slash command at `/`. The built-in `customize-cloud-agent` skill shipped with Copilot CLI uses this exact pattern with `user-invocable: false`; setting it to `true` makes the skill appear in `/skills` AND as a slash keystroke. + +The previous skill `squad-commands` had no `user-invocable` field (Copilot CLI defaults to false), so `/squad-commands` did not exist. Users either typed natural language ("squad commands", "what can squad do") or never discovered the menu. + +## Changes + +1. **Renamed** the `squad-commands` skill to `squad` (canonical source in `.squad/skills/squad/`). +2. **Frontmatter rewritten** to match Copilot CLI's actual schema (verified against decompiled source): + - `name: squad` (was `squad-commands` — `/squad` is shorter, intuitive, and matches the agent name without colliding because slash commands and skill lookups are separate namespaces) + - `user-invocable: true` ← **the load-bearing change** + - `description:` rewritten to be self-explanatory so natural-language match also still works + - `allowedTools: []` (matches Copilot CLI's schema) + - Removed unused fields: `domain:`, `confidence:`, `source:`, `triggers:` (all silently ignored by Copilot CLI) +3. **Body text** updated to reference `/squad` as the primary invocation path. +4. **`MANIFEST_SKILL_NAMES`** in `packages/squad-sdk/src/config/init.ts`: `'squad-commands'` → `'squad'`. +5. **`TEMPLATE_MANIFEST`** in `packages/squad-cli/src/cli/core/templates.ts`: updated `source` + `destination` + `description` to reflect the rename. +6. **Removed** stale `packages/{squad-cli,squad-sdk}/templates/skills/squad-commands/` directories. + +## Test coverage + +New `test/init.test.ts > should install the squad slash-command skill with user-invocable: true`: +- Asserts `.copilot/skills/squad/SKILL.md` exists after `initSquad()` +- Asserts frontmatter contains `user-invocable: true` (load-bearing — without this, no slash command) +- Asserts frontmatter `name: squad` (load-bearing — slash command is `/`) +- Asserts the menu presentation rules are still in the body + +26/26 init tests pass; `npm run lint` clean. + +## How users will experience this + +After `squad init` + opening Copilot CLI in the project: + +``` +> /squad +📋 Squad Commands — pick a category: + 1. Install & Upgrade + 2. Team Management + 3. Issues & PRs + 4. Plugins & Skills + 5. Model & Cost + 6. Sessions & State +``` + +## Composability with other open PRs + +- **Disjoint from #1292** (skills bundling, 4 new entries). Both modify `MANIFEST_SKILL_NAMES` but `squad-commands → squad` is a rename, not an add. Merge order doesn't matter — the renamer wins. +- **Disjoint from #1302** (`squad-help` disambiguation skill). `squad-help` covers the `skill(Squad)` misdirect case; this PR covers the `/squad` slash command UX. They're complementary. + +## Out of scope (future, mentioned in user request) + +The user wants to eventually install the `squad` skill **machine-wide** (e.g., `~/.copilot/skills/squad/`) so `/squad init` works in any folder even before `squad` is initialized in that project. That's a separate piece of work because: +1. It requires a `squad install --global-skill` command or similar (none exists today) +2. The `/squad` menu currently calls into `squad` CLI subcommands that assume `.squad/` exists in cwd — the menu would need a "Init Mode" branch for the "no `.squad/` yet" case +3. Copilot CLI's `~/.copilot/skills/` is a personal scope, so it'd need to be opt-in per-user + +Will file a follow-up issue tracking that work after this lands. diff --git a/.github/agents/squad.agent.md b/.github/agents/squad.agent.md index 0ae5901a6..75517c273 100644 --- a/.github/agents/squad.agent.md +++ b/.github/agents/squad.agent.md @@ -298,7 +298,7 @@ The routing table determines **WHO** handles work. After routing, use Response M | PRD intake ("here's the PRD", "read the PRD at X", pastes spec) | Follow PRD Mode (see that section) | | Human member management ("add {name} as PM", routes to human) | Follow Human Team Members (see that section) | | Ralph commands ("Ralph, go", "keep working", "Ralph, status", "Ralph, idle") | Follow Ralph — Work Monitor (see that section) | -| "squad commands", "what can squad do", "show me squad options", "slash commands", "what commands are available" | Read `.copilot/skills/squad-commands/SKILL.md`, present categorized menu (see squad-commands skill) | +| "squad commands", "what can squad do", "show me squad options", "slash commands", "what commands are available" | Read `.copilot/skills/squad/SKILL.md`, present categorized menu (see squad skill). Users can also invoke this directly via `/squad`. | | "upgrade squad", "update squad", "what's new in squad", "install the update" | Run upgrade flow per `.squad/templates/session-init-reference.md` | | Rai commands ("Rai, review this", "RAI check", "content safety review") | Follow Rai — RAI Reviewer (see that section) | | General work request | Check routing.md, spawn best match + any anticipatory agents | diff --git a/.squad-templates/squad.agent.md b/.squad-templates/squad.agent.md index 0ad38f813..d17c63553 100644 --- a/.squad-templates/squad.agent.md +++ b/.squad-templates/squad.agent.md @@ -329,7 +329,7 @@ The routing table determines **WHO** handles work. After routing, use Response M | PRD intake ("here's the PRD", "read the PRD at X", pastes spec) | Follow PRD Mode (see that section) | | Human member management ("add {name} as PM", routes to human) | Follow Human Team Members (see that section) | | Ralph commands ("Ralph, go", "keep working", "Ralph, status", "Ralph, idle") | Follow Ralph — Work Monitor (see that section) | -| "squad commands", "what can squad do", "show me squad options", "slash commands", "what commands are available" | Read `.copilot/skills/squad-commands/SKILL.md`, present categorized menu (see squad-commands skill) | +| "squad commands", "what can squad do", "show me squad options", "slash commands", "what commands are available" | Read `.copilot/skills/squad/SKILL.md`, present categorized menu (see squad skill). Users can also invoke this directly via `/squad`. | | "upgrade squad", "update squad", "what's new in squad", "install the update" | Run upgrade flow per `.squad/templates/session-init-reference.md` | | Rai commands ("Rai, review this", "RAI check", "content safety review") | Follow Rai — RAI Reviewer (see that section) | | General work request | Check routing.md, spawn best match + any anticipatory agents | diff --git a/packages/squad-cli/templates/skills/squad-commands/SKILL.md b/.squad/skills/squad/SKILL.md similarity index 94% rename from packages/squad-cli/templates/skills/squad-commands/SKILL.md rename to .squad/skills/squad/SKILL.md index 046dde513..d9caa13f4 100644 --- a/packages/squad-cli/templates/skills/squad-commands/SKILL.md +++ b/.squad/skills/squad/SKILL.md @@ -1,18 +1,14 @@ --- -name: squad-commands -description: > - Categorized catalog of common Squad operations. Coordinator reads this - file and presents it as an interactive menu when the user asks for - available commands or help. -domain: squad-operations -confidence: high -source: first-party -triggers: ["squad commands", "what can squad do", "show me squad options", "slash commands"] +name: squad +description: >- + Squad's command catalog and interactive menu. Invoke via /squad (slash command) or natural language ("squad commands", "what can squad do", "show me squad options"). Presents categorized operations (Install & Upgrade, Team Management, Issues & PRs, Plugins & Skills, Model & Cost, Sessions & State) as an interactive picker. Routes to the right squad CLI command or the Squad coordinator agent. +user-invocable: true +allowedTools: [] --- ## Menu Presentation Rules -When the user triggers this skill ("squad commands", "help", "what can squad do", etc.): +When the user triggers this skill (via `/squad` slash command, "squad commands", "help", "what can squad do", etc.): 1. **Category-level menu first.** Present category names as an `ask_user` choice list: ``` diff --git a/packages/squad-cli/src/cli/core/templates.ts b/packages/squad-cli/src/cli/core/templates.ts index 8223d5552..5c20d92df 100644 --- a/packages/squad-cli/src/cli/core/templates.ts +++ b/packages/squad-cli/src/cli/core/templates.ts @@ -252,10 +252,10 @@ export const TEMPLATE_MANIFEST: TemplateFile[] = [ description: 'Multi-agent collaboration and handoff patterns', }, { - source: 'skills/squad-commands/SKILL.md', - destination: '../.copilot/skills/squad-commands/SKILL.md', + source: 'skills/squad/SKILL.md', + destination: '../.copilot/skills/squad/SKILL.md', overwriteOnUpgrade: true, - description: 'In-chat command discovery — categorized menu of Squad operations', + description: 'Squad command catalog — invokable via /squad slash command', }, { source: 'skills/squad-version-check/SKILL.md', diff --git a/packages/squad-cli/templates/skills/squad/SKILL.md b/packages/squad-cli/templates/skills/squad/SKILL.md new file mode 100644 index 000000000..d9caa13f4 --- /dev/null +++ b/packages/squad-cli/templates/skills/squad/SKILL.md @@ -0,0 +1,299 @@ +--- +name: squad +description: >- + Squad's command catalog and interactive menu. Invoke via /squad (slash command) or natural language ("squad commands", "what can squad do", "show me squad options"). Presents categorized operations (Install & Upgrade, Team Management, Issues & PRs, Plugins & Skills, Model & Cost, Sessions & State) as an interactive picker. Routes to the right squad CLI command or the Squad coordinator agent. +user-invocable: true +allowedTools: [] +--- + +## Menu Presentation Rules + +When the user triggers this skill (via `/squad` slash command, "squad commands", "help", "what can squad do", etc.): + +1. **Category-level menu first.** Present category names as an `ask_user` choice list: + ``` + 📋 Squad Commands — pick a category: + 1. Install & Upgrade + 2. Team Management + 3. Issues & PRs + 4. Plugins & Skills + 5. Model & Cost + 6. Sessions & State + ``` +2. **Drill-down.** After selection, show operation titles in that category as a second `ask_user` list. +3. **Direct match skips the menu.** If the user says "how do I upgrade with state backend," match to the specific entry and go straight to argument collection. +4. **Compact fallback.** If `ask_user` is unavailable, render as a markdown table instead. +5. **Back / Cancel.** Include "← Back to categories" in sub-menus. Include "Cancel" in confirmation prompts. Respect "never mind" / "cancel" at any point. + +**Argument collection:** For entries with `args`, iterate the list sequentially. Use `ask_user` with choices when `choices` is provided; free-text prompt otherwise. If the user says "just do it" or "defaults are fine," skip remaining args and use their defaults. + +**Confirmation template:** +``` +⚠️ This will {action-description}. +{what will change} +Proceed? (yes / no) +``` + +--- + +## Install & Upgrade + +### Upgrade Squad CLI + +- **intent:** upgrade squad, update squad, install latest version, get new version +- **summary:** Upgrade Squad CLI to the latest version for your channel +- **action:** shell +- **command:** squad upgrade +- **args:** + - `state-backend`: Which state backend? | choices: {worktree, git-notes, orphan, two-layer} | default: (keep current) +- **confirm:** false +- **platform_caveats:** Requires terminal. In VS Code, open the integrated terminal and run the command directly. + +### Initialize Squad + +- **intent:** set up squad, initialize squad, create team, start squad in this project +- **summary:** Scaffold Squad in the current directory (idempotent) +- **action:** shell +- **command:** squad init +- **args:** (none) +- **confirm:** false +- **platform_caveats:** Requires terminal. Recommend a standalone terminal for best results. + +### Switch State Backend + +- **intent:** switch state backend, change state storage, use git-notes, use orphan branch +- **summary:** Change where Squad stores mutable state (config.json) +- **action:** file-edit +- **command:** .squad/config.json → stateBackend +- **args:** + - `stateBackend`: Which state backend? | choices: {worktree, git-notes, orphan, two-layer} | default: (keep current) +- **confirm:** true +- **platform_caveats:** May require migration if switching away from worktree. Show current value and new value before confirming. + +--- + +## Team Management + +### Add Team Member + +- **intent:** add team member, hire agent, add agent, add developer, recruit +- **summary:** Add a new agent to the team roster +- **action:** coordinator +- **command:** Add Team Member flow (Init Mode / Team Mode) +- **args:** + - `role`: What role should this agent fill? (e.g., Frontend Dev, Backend Dev, QA Engineer) + - `name`: Preferred name or casting universe? | default: (auto-cast from active universe) +- **confirm:** false + +### Remove Team Member + +- **intent:** remove team member, fire agent, delete agent, remove developer +- **summary:** Remove an agent and delete their charter and history files +- **action:** coordinator +- **command:** Remove Team Member flow +- **args:** + - `member`: Which team member to remove? (name or role) +- **confirm:** true + +### Reassign Roles + +- **intent:** reassign role, change role, swap roles, update team member role +- **summary:** Update a team member's role in team.md and their charter +- **action:** coordinator +- **command:** Update team.md roster + charter.md +- **args:** + - `member`: Which team member? + - `newRole`: New role? +- **confirm:** false + +### Show Roster + +- **intent:** show roster, who is on the team, list team members, show team, capability profile +- **summary:** Display the current team roster and capability profile +- **action:** coordinator +- **command:** Direct Mode — read team.md, answer +- **args:** (none) +- **confirm:** false + +--- + +## Issues & PRs + +### Connect GitHub Repo + +- **intent:** connect github, enable issues, set up issues, link repository, github issues mode +- **summary:** Connect this project to GitHub Issues via gh auth +- **action:** coordinator +- **command:** GitHub Issues Mode (connection flow) +- **args:** (none) +- **confirm:** false +- **platform_caveats:** Requires `gh auth login` to have been run in the terminal. + +### Triage Issues + +- **intent:** triage issues, review issues, assign issues, label issues +- **summary:** Run the Lead triage flow on open GitHub issues +- **action:** coordinator +- **command:** GitHub Issues Mode → Lead triage +- **args:** (none) +- **confirm:** false + +### Activate Ralph + +- **intent:** activate ralph, start ralph, ralph go, start work monitor, start auto-work +- **summary:** Activate Ralph — Work Monitor — to pick up and run queued issues +- **action:** coordinator +- **command:** Ralph — Work Monitor triggers +- **args:** (none) +- **confirm:** false + +### Set Ralph Polling Interval + +- **intent:** set ralph interval, change ralph timing, how often does ralph check, ralph every N minutes +- **summary:** Tell Ralph how frequently to poll for new work +- **action:** coordinator +- **command:** Ralph trigger: "Ralph, check every N minutes" +- **args:** + - `interval`: How often should Ralph poll? (in minutes) | default: 10 +- **confirm:** false + +### Start Squad Watch + +- **intent:** start watch, squad watch, monitor issues, watch for issues, auto-triage +- **summary:** Start squad watch to continuously poll and triage issues +- **action:** shell +- **command:** squad watch +- **args:** + - `interval`: Poll interval in minutes | default: 10 +- **confirm:** false +- **platform_caveats:** CLI-only — long-running foreground process. Not viable in VS Code without an integrated terminal. Run: `squad watch --interval {n}` in your terminal. + +--- + +## Plugins & Skills + +### Browse Plugin Marketplace + +- **intent:** browse plugins, explore plugins, what plugins are available, plugin marketplace +- **summary:** Browse available plugins in the Squad marketplace +- **action:** shell +- **command:** squad plugin marketplace browse +- **args:** + - `name`: Plugin name to search for | default: (browse all) +- **confirm:** false + +### Add Marketplace Plugin + +- **intent:** add plugin, install plugin, get plugin from marketplace +- **summary:** Add a plugin from the marketplace to this Squad +- **action:** shell +- **command:** squad plugin marketplace add +- **args:** + - `plugin`: Plugin owner/repo (e.g., owner/plugin-name) +- **confirm:** false + +### Remove Marketplace Plugin + +- **intent:** remove plugin, uninstall plugin, delete plugin +- **summary:** Remove an installed marketplace plugin +- **action:** shell +- **command:** squad plugin marketplace remove +- **args:** + - `name`: Plugin name to remove +- **confirm:** true + +### List Marketplace Plugins + +- **intent:** list plugins, show installed plugins, what plugins do I have +- **summary:** List all plugins registered in this Squad +- **action:** shell +- **command:** squad plugin marketplace list +- **args:** (none) +- **confirm:** false + +### List Installed Skills + +- **intent:** list skills, show skills, what skills are installed, skill catalog +- **summary:** List all skills installed in .squad/skills/ and .copilot/skills/ +- **action:** coordinator +- **command:** Direct Mode — list .squad/skills/ and .copilot/skills/ directories +- **args:** (none) +- **confirm:** false + +--- + +## Model & Cost + +### Set Default Model + +- **intent:** set default model, change model, use gpt-4, use claude, switch model +- **summary:** Set the default model for all agents in config.json +- **action:** file-edit +- **command:** .squad/config.json → defaultModel +- **args:** + - `model`: Model name (e.g., gpt-4o, claude-sonnet-4.5, o3) +- **confirm:** false + +### Override Per-Agent Model + +- **intent:** set model for agent, agent model override, use different model for one agent +- **summary:** Set a model override for a specific agent in config.json +- **action:** file-edit +- **command:** .squad/config.json → agentModelOverrides.{agentName} +- **args:** + - `agent`: Agent name (must match name in team.md) + - `model`: Model name (e.g., gpt-4o, claude-sonnet-4.5) +- **confirm:** false + +### Clear Model Preference + +- **intent:** clear model, reset model, remove model preference, use default model +- **summary:** Remove a model override from config.json (reverts to system default) +- **action:** file-edit +- **command:** .squad/config.json → remove defaultModel or agentModelOverrides.{agentName} +- **args:** + - `scope`: Clear default or a specific agent? | choices: {default model, specific agent} | default: default model + - `agent`: Agent name (only if scope = specific agent) +- **confirm:** false + +--- + +## Sessions & State + +### Catch-Up Summary + +- **intent:** catch me up, what happened, status, what did the team do, session summary +- **summary:** Summarize recent agent activity and key decisions +- **action:** coordinator +- **command:** Session catch-up flow (lazy scan) +- **args:** (none) +- **confirm:** false + +### Show Recent Decisions + +- **intent:** show decisions, recent decisions, what decisions were made, decision log +- **summary:** Display recent entries from .squad/decisions.md +- **action:** coordinator +- **command:** Direct Mode — read decisions.md, answer +- **args:** (none) +- **confirm:** false + +### Archive Old Decisions + +- **intent:** archive decisions, clean up decisions, move old decisions, compact decisions +- **summary:** Move old decisions from decisions.md to decisions-archive.md +- **action:** coordinator +- **command:** Move entries older than threshold from .squad/decisions.md → .squad/decisions-archive.md +- **args:** + - `olderThan`: Archive decisions older than how many days? | default: 30 +- **confirm:** true + +### Summarize Agent History + +- **intent:** summarize history, what did agent do, agent history, compress history +- **summary:** Spawn an agent to summarize and compress a team member's history file +- **action:** coordinator +- **command:** Spawn agent with history.md summarization task +- **args:** + - `member`: Which team member's history to summarize? +- **confirm:** false diff --git a/packages/squad-cli/templates/squad.agent.md.template b/packages/squad-cli/templates/squad.agent.md.template index 0ad38f813..d17c63553 100644 --- a/packages/squad-cli/templates/squad.agent.md.template +++ b/packages/squad-cli/templates/squad.agent.md.template @@ -329,7 +329,7 @@ The routing table determines **WHO** handles work. After routing, use Response M | PRD intake ("here's the PRD", "read the PRD at X", pastes spec) | Follow PRD Mode (see that section) | | Human member management ("add {name} as PM", routes to human) | Follow Human Team Members (see that section) | | Ralph commands ("Ralph, go", "keep working", "Ralph, status", "Ralph, idle") | Follow Ralph — Work Monitor (see that section) | -| "squad commands", "what can squad do", "show me squad options", "slash commands", "what commands are available" | Read `.copilot/skills/squad-commands/SKILL.md`, present categorized menu (see squad-commands skill) | +| "squad commands", "what can squad do", "show me squad options", "slash commands", "what commands are available" | Read `.copilot/skills/squad/SKILL.md`, present categorized menu (see squad skill). Users can also invoke this directly via `/squad`. | | "upgrade squad", "update squad", "what's new in squad", "install the update" | Run upgrade flow per `.squad/templates/session-init-reference.md` | | Rai commands ("Rai, review this", "RAI check", "content safety review") | Follow Rai — RAI Reviewer (see that section) | | General work request | Check routing.md, spawn best match + any anticipatory agents | diff --git a/packages/squad-sdk/src/config/init.ts b/packages/squad-sdk/src/config/init.ts index 173ee04b4..ab1d2ee28 100644 --- a/packages/squad-sdk/src/config/init.ts +++ b/packages/squad-sdk/src/config/init.ts @@ -37,7 +37,7 @@ const MANIFEST_SKILL_NAMES = [ 'reviewer-protocol', 'test-discipline', 'agent-collaboration', - 'squad-commands', + 'squad', 'squad-version-check', 'squad-help', ] as const; diff --git a/packages/squad-sdk/templates/skills/squad/SKILL.md b/packages/squad-sdk/templates/skills/squad/SKILL.md new file mode 100644 index 000000000..d9caa13f4 --- /dev/null +++ b/packages/squad-sdk/templates/skills/squad/SKILL.md @@ -0,0 +1,299 @@ +--- +name: squad +description: >- + Squad's command catalog and interactive menu. Invoke via /squad (slash command) or natural language ("squad commands", "what can squad do", "show me squad options"). Presents categorized operations (Install & Upgrade, Team Management, Issues & PRs, Plugins & Skills, Model & Cost, Sessions & State) as an interactive picker. Routes to the right squad CLI command or the Squad coordinator agent. +user-invocable: true +allowedTools: [] +--- + +## Menu Presentation Rules + +When the user triggers this skill (via `/squad` slash command, "squad commands", "help", "what can squad do", etc.): + +1. **Category-level menu first.** Present category names as an `ask_user` choice list: + ``` + 📋 Squad Commands — pick a category: + 1. Install & Upgrade + 2. Team Management + 3. Issues & PRs + 4. Plugins & Skills + 5. Model & Cost + 6. Sessions & State + ``` +2. **Drill-down.** After selection, show operation titles in that category as a second `ask_user` list. +3. **Direct match skips the menu.** If the user says "how do I upgrade with state backend," match to the specific entry and go straight to argument collection. +4. **Compact fallback.** If `ask_user` is unavailable, render as a markdown table instead. +5. **Back / Cancel.** Include "← Back to categories" in sub-menus. Include "Cancel" in confirmation prompts. Respect "never mind" / "cancel" at any point. + +**Argument collection:** For entries with `args`, iterate the list sequentially. Use `ask_user` with choices when `choices` is provided; free-text prompt otherwise. If the user says "just do it" or "defaults are fine," skip remaining args and use their defaults. + +**Confirmation template:** +``` +⚠️ This will {action-description}. +{what will change} +Proceed? (yes / no) +``` + +--- + +## Install & Upgrade + +### Upgrade Squad CLI + +- **intent:** upgrade squad, update squad, install latest version, get new version +- **summary:** Upgrade Squad CLI to the latest version for your channel +- **action:** shell +- **command:** squad upgrade +- **args:** + - `state-backend`: Which state backend? | choices: {worktree, git-notes, orphan, two-layer} | default: (keep current) +- **confirm:** false +- **platform_caveats:** Requires terminal. In VS Code, open the integrated terminal and run the command directly. + +### Initialize Squad + +- **intent:** set up squad, initialize squad, create team, start squad in this project +- **summary:** Scaffold Squad in the current directory (idempotent) +- **action:** shell +- **command:** squad init +- **args:** (none) +- **confirm:** false +- **platform_caveats:** Requires terminal. Recommend a standalone terminal for best results. + +### Switch State Backend + +- **intent:** switch state backend, change state storage, use git-notes, use orphan branch +- **summary:** Change where Squad stores mutable state (config.json) +- **action:** file-edit +- **command:** .squad/config.json → stateBackend +- **args:** + - `stateBackend`: Which state backend? | choices: {worktree, git-notes, orphan, two-layer} | default: (keep current) +- **confirm:** true +- **platform_caveats:** May require migration if switching away from worktree. Show current value and new value before confirming. + +--- + +## Team Management + +### Add Team Member + +- **intent:** add team member, hire agent, add agent, add developer, recruit +- **summary:** Add a new agent to the team roster +- **action:** coordinator +- **command:** Add Team Member flow (Init Mode / Team Mode) +- **args:** + - `role`: What role should this agent fill? (e.g., Frontend Dev, Backend Dev, QA Engineer) + - `name`: Preferred name or casting universe? | default: (auto-cast from active universe) +- **confirm:** false + +### Remove Team Member + +- **intent:** remove team member, fire agent, delete agent, remove developer +- **summary:** Remove an agent and delete their charter and history files +- **action:** coordinator +- **command:** Remove Team Member flow +- **args:** + - `member`: Which team member to remove? (name or role) +- **confirm:** true + +### Reassign Roles + +- **intent:** reassign role, change role, swap roles, update team member role +- **summary:** Update a team member's role in team.md and their charter +- **action:** coordinator +- **command:** Update team.md roster + charter.md +- **args:** + - `member`: Which team member? + - `newRole`: New role? +- **confirm:** false + +### Show Roster + +- **intent:** show roster, who is on the team, list team members, show team, capability profile +- **summary:** Display the current team roster and capability profile +- **action:** coordinator +- **command:** Direct Mode — read team.md, answer +- **args:** (none) +- **confirm:** false + +--- + +## Issues & PRs + +### Connect GitHub Repo + +- **intent:** connect github, enable issues, set up issues, link repository, github issues mode +- **summary:** Connect this project to GitHub Issues via gh auth +- **action:** coordinator +- **command:** GitHub Issues Mode (connection flow) +- **args:** (none) +- **confirm:** false +- **platform_caveats:** Requires `gh auth login` to have been run in the terminal. + +### Triage Issues + +- **intent:** triage issues, review issues, assign issues, label issues +- **summary:** Run the Lead triage flow on open GitHub issues +- **action:** coordinator +- **command:** GitHub Issues Mode → Lead triage +- **args:** (none) +- **confirm:** false + +### Activate Ralph + +- **intent:** activate ralph, start ralph, ralph go, start work monitor, start auto-work +- **summary:** Activate Ralph — Work Monitor — to pick up and run queued issues +- **action:** coordinator +- **command:** Ralph — Work Monitor triggers +- **args:** (none) +- **confirm:** false + +### Set Ralph Polling Interval + +- **intent:** set ralph interval, change ralph timing, how often does ralph check, ralph every N minutes +- **summary:** Tell Ralph how frequently to poll for new work +- **action:** coordinator +- **command:** Ralph trigger: "Ralph, check every N minutes" +- **args:** + - `interval`: How often should Ralph poll? (in minutes) | default: 10 +- **confirm:** false + +### Start Squad Watch + +- **intent:** start watch, squad watch, monitor issues, watch for issues, auto-triage +- **summary:** Start squad watch to continuously poll and triage issues +- **action:** shell +- **command:** squad watch +- **args:** + - `interval`: Poll interval in minutes | default: 10 +- **confirm:** false +- **platform_caveats:** CLI-only — long-running foreground process. Not viable in VS Code without an integrated terminal. Run: `squad watch --interval {n}` in your terminal. + +--- + +## Plugins & Skills + +### Browse Plugin Marketplace + +- **intent:** browse plugins, explore plugins, what plugins are available, plugin marketplace +- **summary:** Browse available plugins in the Squad marketplace +- **action:** shell +- **command:** squad plugin marketplace browse +- **args:** + - `name`: Plugin name to search for | default: (browse all) +- **confirm:** false + +### Add Marketplace Plugin + +- **intent:** add plugin, install plugin, get plugin from marketplace +- **summary:** Add a plugin from the marketplace to this Squad +- **action:** shell +- **command:** squad plugin marketplace add +- **args:** + - `plugin`: Plugin owner/repo (e.g., owner/plugin-name) +- **confirm:** false + +### Remove Marketplace Plugin + +- **intent:** remove plugin, uninstall plugin, delete plugin +- **summary:** Remove an installed marketplace plugin +- **action:** shell +- **command:** squad plugin marketplace remove +- **args:** + - `name`: Plugin name to remove +- **confirm:** true + +### List Marketplace Plugins + +- **intent:** list plugins, show installed plugins, what plugins do I have +- **summary:** List all plugins registered in this Squad +- **action:** shell +- **command:** squad plugin marketplace list +- **args:** (none) +- **confirm:** false + +### List Installed Skills + +- **intent:** list skills, show skills, what skills are installed, skill catalog +- **summary:** List all skills installed in .squad/skills/ and .copilot/skills/ +- **action:** coordinator +- **command:** Direct Mode — list .squad/skills/ and .copilot/skills/ directories +- **args:** (none) +- **confirm:** false + +--- + +## Model & Cost + +### Set Default Model + +- **intent:** set default model, change model, use gpt-4, use claude, switch model +- **summary:** Set the default model for all agents in config.json +- **action:** file-edit +- **command:** .squad/config.json → defaultModel +- **args:** + - `model`: Model name (e.g., gpt-4o, claude-sonnet-4.5, o3) +- **confirm:** false + +### Override Per-Agent Model + +- **intent:** set model for agent, agent model override, use different model for one agent +- **summary:** Set a model override for a specific agent in config.json +- **action:** file-edit +- **command:** .squad/config.json → agentModelOverrides.{agentName} +- **args:** + - `agent`: Agent name (must match name in team.md) + - `model`: Model name (e.g., gpt-4o, claude-sonnet-4.5) +- **confirm:** false + +### Clear Model Preference + +- **intent:** clear model, reset model, remove model preference, use default model +- **summary:** Remove a model override from config.json (reverts to system default) +- **action:** file-edit +- **command:** .squad/config.json → remove defaultModel or agentModelOverrides.{agentName} +- **args:** + - `scope`: Clear default or a specific agent? | choices: {default model, specific agent} | default: default model + - `agent`: Agent name (only if scope = specific agent) +- **confirm:** false + +--- + +## Sessions & State + +### Catch-Up Summary + +- **intent:** catch me up, what happened, status, what did the team do, session summary +- **summary:** Summarize recent agent activity and key decisions +- **action:** coordinator +- **command:** Session catch-up flow (lazy scan) +- **args:** (none) +- **confirm:** false + +### Show Recent Decisions + +- **intent:** show decisions, recent decisions, what decisions were made, decision log +- **summary:** Display recent entries from .squad/decisions.md +- **action:** coordinator +- **command:** Direct Mode — read decisions.md, answer +- **args:** (none) +- **confirm:** false + +### Archive Old Decisions + +- **intent:** archive decisions, clean up decisions, move old decisions, compact decisions +- **summary:** Move old decisions from decisions.md to decisions-archive.md +- **action:** coordinator +- **command:** Move entries older than threshold from .squad/decisions.md → .squad/decisions-archive.md +- **args:** + - `olderThan`: Archive decisions older than how many days? | default: 30 +- **confirm:** true + +### Summarize Agent History + +- **intent:** summarize history, what did agent do, agent history, compress history +- **summary:** Spawn an agent to summarize and compress a team member's history file +- **action:** coordinator +- **command:** Spawn agent with history.md summarization task +- **args:** + - `member`: Which team member's history to summarize? +- **confirm:** false diff --git a/packages/squad-sdk/templates/squad.agent.md.template b/packages/squad-sdk/templates/squad.agent.md.template index 0ad38f813..d17c63553 100644 --- a/packages/squad-sdk/templates/squad.agent.md.template +++ b/packages/squad-sdk/templates/squad.agent.md.template @@ -329,7 +329,7 @@ The routing table determines **WHO** handles work. After routing, use Response M | PRD intake ("here's the PRD", "read the PRD at X", pastes spec) | Follow PRD Mode (see that section) | | Human member management ("add {name} as PM", routes to human) | Follow Human Team Members (see that section) | | Ralph commands ("Ralph, go", "keep working", "Ralph, status", "Ralph, idle") | Follow Ralph — Work Monitor (see that section) | -| "squad commands", "what can squad do", "show me squad options", "slash commands", "what commands are available" | Read `.copilot/skills/squad-commands/SKILL.md`, present categorized menu (see squad-commands skill) | +| "squad commands", "what can squad do", "show me squad options", "slash commands", "what commands are available" | Read `.copilot/skills/squad/SKILL.md`, present categorized menu (see squad skill). Users can also invoke this directly via `/squad`. | | "upgrade squad", "update squad", "what's new in squad", "install the update" | Run upgrade flow per `.squad/templates/session-init-reference.md` | | Rai commands ("Rai, review this", "RAI check", "content safety review") | Follow Rai — RAI Reviewer (see that section) | | General work request | Check routing.md, spawn best match + any anticipatory agents | diff --git a/templates/squad.agent.md.template b/templates/squad.agent.md.template index 0ad38f813..d17c63553 100644 --- a/templates/squad.agent.md.template +++ b/templates/squad.agent.md.template @@ -329,7 +329,7 @@ The routing table determines **WHO** handles work. After routing, use Response M | PRD intake ("here's the PRD", "read the PRD at X", pastes spec) | Follow PRD Mode (see that section) | | Human member management ("add {name} as PM", routes to human) | Follow Human Team Members (see that section) | | Ralph commands ("Ralph, go", "keep working", "Ralph, status", "Ralph, idle") | Follow Ralph — Work Monitor (see that section) | -| "squad commands", "what can squad do", "show me squad options", "slash commands", "what commands are available" | Read `.copilot/skills/squad-commands/SKILL.md`, present categorized menu (see squad-commands skill) | +| "squad commands", "what can squad do", "show me squad options", "slash commands", "what commands are available" | Read `.copilot/skills/squad/SKILL.md`, present categorized menu (see squad skill). Users can also invoke this directly via `/squad`. | | "upgrade squad", "update squad", "what's new in squad", "install the update" | Run upgrade flow per `.squad/templates/session-init-reference.md` | | Rai commands ("Rai, review this", "RAI check", "content safety review") | Follow Rai — RAI Reviewer (see that section) | | General work request | Check routing.md, spawn best match + any anticipatory agents | diff --git a/test/init.test.ts b/test/init.test.ts index 93ebf54ce..dcd0ef19a 100644 --- a/test/init.test.ts +++ b/test/init.test.ts @@ -252,17 +252,10 @@ describe('Squad Initialization', () => { it('should install the squad-help disambiguation skill (regression: #1297 / supersedes squad name collision)', async () => { // The Squad framework registers a Copilot CLI agent named "Squad" at // .github/agents/squad.agent.md. Coding models sometimes confuse that - // with a skill and call skill(Squad), which fails because: - // (a) Copilot CLI's skill loader uses {name, description} — the - // triggers field in our SKILL.md frontmatter is ignored - // (b) A skill named "squad" would collide with the agent name and - // hide the skill from /skills output - // - // Fix: name the disambiguation skill "squad-help" instead, which - // - avoids the agent-name collision (so /skills lists it) - // - is discoverable via natural-language match on its description - // - // Supersedes the original PR #1297 which used the colliding name. + // with a skill and call skill(Squad), which fails. Fix: name the + // disambiguation skill "squad-help" instead — avoids the agent-name + // collision (so /skills lists it) and is discoverable via natural- + // language match on its description. const agents: InitAgentSpec[] = [{ name: 'lead', role: 'lead' }]; const options: InitOptions = { teamRoot: TEST_ROOT, @@ -275,13 +268,36 @@ describe('Squad Initialization', () => { const skillPath = join(TEST_ROOT, '.copilot', 'skills', 'squad-help', 'SKILL.md'); expect(existsSync(skillPath)).toBe(true); const content = await readFile(skillPath, 'utf-8'); - // The skill must NOT be named "squad" (collides with the agent named "Squad") expect(content).toContain('name: "squad-help"'); expect(content).not.toMatch(/^name:\s*"?squad"?\s*$/m); - // Must explain the agent-vs-skill distinction and route to task tool. - expect(content).toContain("agent_type=\"Squad\""); + expect(content).toContain('agent_type="Squad"'); expect(content).toContain('custom agent'); - expect(content).toContain('squad-commands'); + }); + + it('should install the squad slash-command skill with user-invocable: true (regression: /squad must appear)', async () => { + // Users want to type /squad in Copilot CLI to see Squad's command + // catalog. Copilot CLI auto-registers any skill with frontmatter + // user-invocable: true as a slash command using the skill's name. + // Verified against Copilot CLI 1.0.62-2 sdk/index.js, function Y_n: + // getLoadedSkills().filter(e => e.userInvocable).map(... + // ({name: `/${eF(e)}`, isSkill: true, skill: e})) + // Renamed from 'squad-commands' to 'squad' + set user-invocable: true + // so /squad shows the command catalog. Composes with squad-help. + const agents: InitAgentSpec[] = [{ name: 'lead', role: 'lead' }]; + const options: InitOptions = { + teamRoot: TEST_ROOT, + projectName: 'Test Project', + agents + }; + + await initSquad(options); + + const skillPath = join(TEST_ROOT, '.copilot', 'skills', 'squad', 'SKILL.md'); + expect(existsSync(skillPath)).toBe(true); + const content = await readFile(skillPath, 'utf-8'); + expect(content).toMatch(/^user-invocable:\s*true\s*$/m); + expect(content).toMatch(/^name:\s*"?squad"?\s*$/m); + expect(content).toContain('Menu Presentation Rules'); }); it('should create initial decisions.md', async () => {