From 56e3a82fd54087dd9ee52be1c5dc5b2ac53deb6a Mon Sep 17 00:00:00 2001 From: Jorge Vidaurre Date: Fri, 13 Mar 2026 13:10:12 -0300 Subject: [PATCH 1/6] =?UTF-8?q?feat:=20reset=20first-run=20experience=20?= =?UTF-8?q?=E2=80=94=204=20starter=20squads,=20context=20cascade,=20placeh?= =?UTF-8?q?older=20sentinel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Default init creates 4 core squads (intelligence, research, product, company) with 14 agents - Add SYSTEM.md (Layer 0) and directives.md (Layer 3) to context cascade - BUSINESS_BRIEF.md has PLACEHOLDER sentinel — agents stop and ask user to edit instead of producing garbage - Upgrade all agent templates with structured output formats and quality rules - Add product squad (lead, scanner, worker) with depends_on intelligence/research - Rename create → add, remove list (use status), add --pack option to init - Clean repo root: remove changeset, husky, changelog, scripts, telemetry docs - Add AGENTS.md (vendor-neutral) and rewrite CLAUDE.md with cascade documentation - Update README with 4-step customization guide (Brief → Directives → Goals → Priorities) - Fix broken command references in company agents (squads feedback add → real commands) Co-Authored-By: Claude --- .changeset/config.json | 11 - .changeset/github-app-bot.md | 5 - .gitignore | 10 +- .husky/pre-commit | 4 - AGENTS.md | 94 +++ CHANGELOG.md | 88 --- CLAUDE.md | 213 ++---- README.md | 673 ++++++++++++++---- docs/TELEMETRY.md | 284 -------- scripts/e2e-smoke.sh | 69 -- scripts/release.sh | 229 ------ scripts/update-docs-changelog.cjs | 99 --- src/cli.ts | 59 +- src/commands/create.ts | 6 +- src/commands/init.ts | 173 +++-- src/commands/run.ts | 69 +- src/commands/status.ts | 2 +- templates/core/AGENTS.md.template | 79 +- templates/core/CLAUDE.md.template | 4 +- templates/seed/BUSINESS_BRIEF.md.template | 5 +- templates/seed/CLAUDE.md.template | 130 ++-- templates/seed/README.md.template | 12 +- templates/seed/config/SYSTEM.md | 52 ++ templates/seed/memory/company/directives.md | 37 + templates/seed/memory/product/lead/state.md | 14 + templates/seed/memory/research/lead/state.md | 14 + .../seed/memory/research/researcher/state.md | 10 - templates/seed/skills/squads-cli/SKILL.md | 6 +- templates/seed/squads/company/SQUAD.md | 14 +- .../seed/squads/company/company-critic.md | 42 +- templates/seed/squads/company/company-eval.md | 42 +- .../seed/squads/company/event-dispatcher.md | 36 +- templates/seed/squads/company/goal-tracker.md | 36 +- templates/seed/squads/company/manager.md | 26 +- templates/seed/squads/intelligence/SQUAD.md | 7 +- .../seed/squads/operations/goal-tracker.md | 2 +- templates/seed/squads/product/SQUAD.md | 41 ++ templates/seed/squads/product/lead.md | 56 ++ templates/seed/squads/product/scanner.md | 50 ++ templates/seed/squads/product/worker.md | 55 ++ templates/seed/squads/research/SQUAD.md | 18 +- templates/seed/squads/research/analyst.md | 45 +- templates/seed/squads/research/lead.md | 52 ++ .../seed/squads/research/research-critic.md | 20 - .../seed/squads/research/research-eval.md | 20 - templates/seed/squads/research/researcher.md | 28 - templates/seed/squads/research/synthesizer.md | 59 ++ .../skills/squads-workflow/instruction.md | 4 +- test/commands/run.test.ts | 4 +- test/e2e/first-run.e2e.test.ts | 8 +- 50 files changed, 1619 insertions(+), 1497 deletions(-) delete mode 100644 .changeset/config.json delete mode 100644 .changeset/github-app-bot.md delete mode 100755 .husky/pre-commit create mode 100644 AGENTS.md delete mode 100644 CHANGELOG.md delete mode 100644 docs/TELEMETRY.md delete mode 100755 scripts/e2e-smoke.sh delete mode 100755 scripts/release.sh delete mode 100755 scripts/update-docs-changelog.cjs create mode 100644 templates/seed/config/SYSTEM.md create mode 100644 templates/seed/memory/company/directives.md create mode 100644 templates/seed/memory/product/lead/state.md create mode 100644 templates/seed/memory/research/lead/state.md delete mode 100644 templates/seed/memory/research/researcher/state.md create mode 100644 templates/seed/squads/product/SQUAD.md create mode 100644 templates/seed/squads/product/lead.md create mode 100644 templates/seed/squads/product/scanner.md create mode 100644 templates/seed/squads/product/worker.md create mode 100644 templates/seed/squads/research/lead.md delete mode 100644 templates/seed/squads/research/research-critic.md delete mode 100644 templates/seed/squads/research/research-eval.md delete mode 100644 templates/seed/squads/research/researcher.md create mode 100644 templates/seed/squads/research/synthesizer.md diff --git a/.changeset/config.json b/.changeset/config.json deleted file mode 100644 index 483ce967..00000000 --- a/.changeset/config.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json", - "changelog": ["@changesets/changelog-github", { "repo": "agents-squads/squads-cli" }], - "commit": false, - "fixed": [], - "linked": [], - "access": "public", - "baseBranch": "main", - "updateInternalDependencies": "patch", - "ignore": [] -} diff --git a/.changeset/github-app-bot.md b/.changeset/github-app-bot.md deleted file mode 100644 index 59c6370b..00000000 --- a/.changeset/github-app-bot.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"squads-cli": minor ---- - -Add GitHub App bot identity for agent commits, daemon command, and dynamic AI co-authors diff --git a/.gitignore b/.gitignore index 80d6112b..6915857a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,11 @@ dist/ .env.local *.tgz -# Generated files - never commit +# Generated coverage/ -docker/.env -# Local PII patterns — never commit -.husky/.blocked-patterns +# Local-only (not shared) +scripts/ +docker/ +.changeset/ +.husky/ diff --git a/.husky/pre-commit b/.husky/pre-commit deleted file mode 100755 index 2e4961c2..00000000 --- a/.husky/pre-commit +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -# Pre-commit hook — disabled -# TODO: re-enable quality gate after branch consolidation -exit 0 diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..bbf06a05 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,94 @@ +# Agent Instructions + +Guidance for AI coding agents working on this repository. + +## What This Is + +`squads-cli` is a CLI orchestrator for autonomous AI agent teams. It organizes agents into squads (domain-aligned teams), manages their context and memory, and dispatches them via native AI CLIs (`claude`, `gemini`, etc.). + +The CLI is open source. Agents are the primary consumers — after `squads run` dispatches an agent, it calls CLI commands to read context, persist memory, and coordinate with other agents. + +## Repository Structure + +``` +src/ +├── cli.ts # All command registrations (Commander.js, lazy imports) +├── commands/ # One file per command — start here for any command change +├── lib/ # Shared logic (parsing, context, memory, git, providers) +templates/ # Files generated by `squads init` +test/ # Unit + E2E tests (vitest) +``` + +Key files by concern: + +| Concern | File | +|---------|------| +| Squad/agent discovery | `src/lib/squad-parser.ts` | +| Context injection | `src/lib/run-context.ts` | +| Agent execution | `src/commands/run.ts` | +| Multi-agent conversation | `src/lib/conversation.ts`, `src/lib/workflow.ts` | +| Provider CLIs | `src/lib/llm-clis.ts` | +| Memory read/write | `src/lib/memory.ts` | +| Terminal output | `src/lib/terminal.ts` | +| Command registration | `src/cli.ts` | + +## Build and Test + +```bash +npm install +npm run build # Required before committing — must pass +npm test # 1700+ tests, all must pass +npm run lint # ESLint +``` + +## How to Make Changes + +### Adding a command + +1. Create `src/commands/.ts` exporting an async function +2. Register in `src/cli.ts` with lazy import +3. Add `--json` flag for machine output +4. Add tests in `test/commands/.test.ts` + +### Removing a command + +Use the `removedCommand()` pattern in `cli.ts` — never silently delete: +```typescript +program.command('old-name', { hidden: true }) + .description('[removed]') + .action(removedCommand('old-name', 'Use: squads replacement')); +``` + +### Modifying squad/agent parsing + +All filesystem discovery goes through `squad-parser.ts`. Never hardcode paths to `.agents/` — use `findSquadsDir()`, `findProjectRoot()`, `loadSquad()`. + +## Conventions + +- **TypeScript strict mode.** No `any` types. +- **Lazy imports in cli.ts.** Commands are loaded only when invoked. +- **Terminal output via `terminal.ts`.** Use `writeLine()`, `colors`, `bold` — not raw `console.log`. +- **`--json` on every command.** Agents parse CLI output programmatically. +- **No new dependencies** without explicit approval. +- **No hardcoded repos, orgs, or file paths.** Everything discovered at runtime. +- **Graceful degradation.** Missing files, unavailable APIs — handle gracefully, never crash. +- **Conventional Commits.** `feat:`, `fix:`, `docs:`, `chore:`. + +## Testing + +Tests use vitest. Run the full suite before submitting changes: + +```bash +npm test # All tests +npx vitest run test/commands/run.test.ts # Single file +``` + +E2E tests in `test/e2e/` run actual CLI commands against temp directories. + +## What Not to Do + +- Don't add dependencies (especially heavy ones) without discussion +- Don't use `console.log` in command implementations +- Don't hardcode GitHub as the only git provider +- Don't break `--json` output formats (agents depend on them) +- Don't skip the build step — `npm run build` is the quality gate diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index cd557281..00000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,88 +0,0 @@ -# Changelog - -All notable changes to squads-cli will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [0.6.0] - 2026-02-20 - -### Security -- fix(security): escape HTML in OAuth callback responses (#323) -- fix(security): prevent shell injection in agent spawn (#324) -- fix(security): restrict auth file permissions to owner-only (#325) -- security: remove internal infrastructure references from public repo - -### Added -- feat(run): memory injection, event emission, Ralph verification loop -- feat(run): foreground default, status tracking, auto-commit -- feat(run): inject Output section with target repo into agent context -- feat(run): multi-provider model routing -- feat(run): enforce model routing from squad context -- feat(run): enforce branch isolation for agent execution -- feat(eval): implement squads eval readiness scorer (#305) -- feat(deploy): implement squads deploy command (#304) -- feat(dashboard): add ROI metrics, cost projections, and baseline command (#245) -- feat(context): add squad-scoped skills and MCP servers (#243) -- feat(autonomous): implement real scheduling daemon -- feat(cli): reposition as business OS for AI managers (v0.6.0) -- feat(cli): interactive init, session filtering, bug fixes from Santiago sim -- feat(cli): accept any model string for multi-provider routing -- feat(status): add execution observability to squad status -- feat(release): auto-update docs changelog on version bump (#270) -- feat: add privacy indicators to CLI output (#269) -- feat: add light mode terminal palette (#221) - -### Changed -- refactor: remove pg, ioredis, supabase from CLI dependencies (#303) -- refactor(run): deprecate -e flag, add native Claude execution pattern -- refactor: clean up unused code - -### Fixed -- fix: update memory tests to match new ## date format -- fix: add worktree isolation to executeWithProvider -- fix: use git worktrees for agent isolation instead of checkout -- fix: restore auto branch isolation for agent execution -- fix: unset CLAUDECODE env var to allow nested execution -- fix: skip --mcp-config when no squad MCP config exists -- fix: use array spawn for foreground mode to avoid shell escaping -- fix: auto-detect non-TTY and use --print in foreground mode -- fix: standardize learnings format for synthesizer parsing -- fix: point approval commands to squads-api instead of dead slack-bot -- fix: update trigger commands to use SQUADS_API_URL -- fix(cli): resolve 6 P1 issues — URLs, ANSI, errors, init, run checks, optional deps (#44bc09d) -- fix(ci): resolve smoke-test failure and npm audit vulnerability (#327) -- fix(lint): remove all unused imports/vars, replace require() with ESM import (#326) -- fix(run): add shell wrapper for Node 22 symlink resolution -- fix(run): include learnings in dry-run preview -- fix(login): update auth URL to api.agents-squads.com -- fix(login): show graceful "coming soon" message when auth unavailable -- fix(docker): add REDIS_URL to scheduler-api for event buffer -- fix(tests): skip tests for unimplemented baseline functions, fix SQL injection test (#253) -- fix(test): normalize temp paths for macOS compatibility -- docs: realign positioning to "Your AI workforce" -- docs: add backlinks to agents-squads.com - -### Tests -- test: add comprehensive tests for core commands (#244) -- test: add comprehensive database operation tests (#246) -- test: extract cron functions to lib/cron.ts and add comprehensive tests (#301) -- test: add unit tests for anthropic.ts skill extraction functions (#239) -- test: add unit tests for terminal utility functions (#237) -- test: add unit tests for dashboard postgres source pure functions (#235) -- test: add unit tests for dashboard summary and table renderers (#234) -- test: add unit tests for dashboard bar and trend renderers (#233) -- test: add unit tests for dashboard list renderer (#232) -- test: add unit tests for dashboard base renderer utilities (#231) -- test: add unit tests for llm-clis.ts (#230) -- test: add unit tests for autonomous.ts core functions (#224) -- test: add unit tests for templates.ts and local.ts pure functions (#220) -- test: add comprehensive unit tests for lib/goal-parser.ts (#219) -- test: fix flaky memory tests on macOS (#242) - -### CI -- ci: add P1 issue aging alert workflow (#236) - -## [0.5.1] - 2026-01-27 - -See previous releases for earlier changelog entries. diff --git a/CLAUDE.md b/CLAUDE.md index f0918914..b1f26aa4 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,180 +1,81 @@ # squads-cli -CLI for managing autonomous AI agent squads. Define AI teams, run them, monitor their work. +CLI orchestrator for autonomous AI agent squads. Agents are defined as markdown files, organized into squads, and executed via native AI CLIs (claude, gemini, etc.). -## Quick Start +## Build & Test ```bash -squads init # Set up your project -squads status # See your squads, milestones, open PRs -squads run # Run a squad -squads run -a # Run a specific agent +npm install +npm run build # tsup → dist/ +npm test # vitest (1700+ tests) +npm run lint # eslint +npm link # test globally as `squads` ``` -## Core Concepts - -### Squads -Domain-aligned teams of AI agents. Defined in `.agents/squads//SQUAD.md`. +`npm run build` must pass before committing. Conventional Commits format. -Each SQUAD.md has frontmatter: -```yaml ---- -name: engineering -mission: Build and maintain the platform -repo: your-org/your-repo # Links to your git repo for milestones/PRs -stack: TypeScript -context: - model: - default: sonnet ---- -``` +## Architecture -### Agents -Individual AI workers defined as markdown files in a squad directory. -Each `.agents/squads//.md` contains the agent's instructions, role, and behavior. - -### Memory -Persistent state across sessions at `.agents/memory///`. -```bash -squads memory write [agent] "insight" # Save a learning -squads memory read [agent] # Load context -squads memory query "query" # Search across squads ``` - -### Milestones & PRs -`squads status` reads the `repo:` field from your SQUAD.md files and shows: -- Milestone progress from your git provider -- Open PRs across your repos - -This works with any git hosting that supports the `gh` CLI or equivalent. - -## Commands - -### Monitoring -| Command | What It Shows | -|---------|--------------| -| `squads status` | Squad overview, milestones, open PRs | -| `squads status ` | Squad detail: agents, context, recent executions | -| `squads dash` | Full dashboard: git activity, costs, goals | -| `squads dash --ceo` | Executive summary with priorities | - -### Execution -| Command | What It Does | -|---------|-------------| -| `squads run ` | Run a squad's lead agent | -| `squads run -a ` | Run a specific agent | -| `squads run --parallel` | Run all agents in parallel | -| `squads run --dry-run` | Preview without executing | - -### Memory -| Command | What It Does | -|---------|-------------| -| `squads memory write [agent] "text"` | Persist a learning | -| `squads memory read [agent]` | Load agent memory | -| `squads memory query "query"` | Search all memory | -| `squads memory list` | List all entries | - -### Infrastructure -| Command | What It Does | -|---------|-------------| -| `squads stack init` | Set up local Docker services | -| `squads stack status` | Check container health | -| `squads stack up / down` | Start/stop services | -| `squads health` | Quick infrastructure check | - -### Scheduling -| Command | What It Does | -|---------|-------------| -| `squads autonomous start` | Start scheduler daemon | -| `squads autonomous status` | Check daemon | -| `squads cron list` | List scheduled agents | -| `squads cron sync` | Sync schedules from agent definitions | - -## Project Structure - -After `squads init`, your project has: -``` -.agents/ -├── squads/ -│ ├── / -│ │ ├── SQUAD.md # Squad definition -│ │ └── .md # Agent definitions +src/ +├── cli.ts # Command registration (Commander.js) +├── commands/ # One file per command (lazy-imported) +│ ├── run.ts # Core: agent execution + autopilot +│ ├── init.ts # Project bootstrapping +│ ├── create.ts # Squad creation (exposed as `squads add`) +│ ├── status.ts # Squad/org overview +│ ├── dashboard.ts # Full dashboard +│ └── ... +├── lib/ +│ ├── squad-parser.ts # Filesystem-based squad/agent discovery +│ ├── run-context.ts # Context cascade assembly +│ ├── conversation.ts # Multi-agent conversation protocol +│ ├── workflow.ts # Conversation orchestration loop +│ ├── llm-clis.ts # Provider CLI integration (claude, gemini, etc.) +│ ├── providers.ts # Provider registry + pricing +│ ├── memory.ts # Persistent agent memory (filesystem) +│ ├── terminal.ts # Colors, formatting, output helpers +│ ├── git.ts # Git operations +│ ├── github.ts # GitHub API via gh CLI +│ ├── telemetry.ts # Anonymous usage tracking │ └── ... -├── memory/ -│ └── // # Persistent state -├── sessions/ -│ └── history.jsonl # Execution log -├── config/ -│ └── provider.yaml # LLM provider settings -└── BUSINESS_BRIEF.md # Your business context +├── version.ts # Package version +templates/ # `squads init` scaffolding templates +test/ # Vitest unit + e2e tests ``` -## Working With Squads +## Key Patterns -### Define a new squad -Create `.agents/squads/my-squad/SQUAD.md` with frontmatter (name, mission, repo) and agent table. - -### Define a new agent -Create `.agents/squads/my-squad/my-agent.md` with instructions for what the agent does. - -### Connect to your repos -Set `repo: your-org/your-repo` in SQUAD.md frontmatter. This enables milestone tracking and PR visibility in `squads status`. - -### Multi-provider support -Configure in `.agents/config/provider.yaml` or SQUAD.md frontmatter: -```yaml -context: - model: - default: sonnet # Default for all tasks - expensive: opus # Heavy reasoning - cheap: haiku # Simple tasks +**Command registration** — `cli.ts` uses lazy dynamic imports. Commands are only loaded when invoked: +```typescript +.action(async (name, options) => { + const { createCommand } = await import('./commands/create.js'); + return createCommand(name, options); +}); ``` -Supported: Claude, GPT-4, Gemini, Ollama, and custom providers. - -## Development - -### Building -```bash -npm install -npm run build # Build with tsup -npm run dev # Watch mode -npm link # Test globally as `squads` +**Removed commands** — use `removedCommand()` helper to show migration message: +```typescript +program.command('old', { hidden: true }).description('[removed]') + .action(removedCommand('old', 'Use: squads new-command')); ``` -### Testing -```bash -npm test # Run vitest -npm run test:watch # Watch mode -npm run test:coverage # Coverage report +**Squad/agent discovery** — filesystem-based via `squad-parser.ts`: +```typescript +import { findSquadsDir, listSquads, listAgents, loadSquad } from '../lib/squad-parser.js'; ``` -### Code Patterns - -**Adding a new command:** -1. Create `src/commands/.ts` -2. Register in `src/cli.ts` via Commander.js - -**Key libraries:** +**Terminal output** — never use raw `console.log` in commands. Use: ```typescript -// Terminal output -import { colors, bold, gradient, writeLine } from '../lib/terminal.js'; - -// Squad/agent parsing -import { loadSquad, findSquadsDir, listSquads } from '../lib/squad-parser.js'; - -// Memory operations -import { searchMemory, appendToMemory, listMemoryEntries } from '../lib/memory.js'; +import { colors, bold, RESET, writeLine } from '../lib/terminal.js'; ``` -### File Paths -- **Squad definitions:** `.agents/squads//SQUAD.md` -- **Agent definitions:** `.agents/squads//.md` -- **Memory files:** `.agents/memory///.md` -- **Session history:** `.agents/sessions/history.jsonl` -- **CLI config:** `~/.squads/config.json` (managed via `squads config use local|staging|prod`) +**Every command supports `--json`** for machine consumption. + +## Rules -### Git Workflow -- Conventional Commits format (`feat:`, `fix:`, `docs:`, `chore:`) -- Feature branches for non-trivial changes -- `npm run build` must pass before committing +- TypeScript strict mode. No `any`. +- No new dependencies without approval. +- No hardcoded repos, orgs, or paths — use `findProjectRoot()`, `loadSquad()`, `listSquads()`. +- Graceful degradation — show local data when API unavailable, never crash on missing optional data. +- Feature branches for non-trivial changes. PRs to `develop`. diff --git a/README.md b/README.md index f0c1c433..7f1bb978 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,11 @@ -# squads +
-**Your AI workforce.** One person + AI teammates = a real business. +# Agents Squads + +**Your AI ops teams.** + +Autonomous AI agents for engineering, marketing, finance, and operations. +You make the decisions. They do the work. [![npm version](https://img.shields.io/npm/v/squads-cli.svg)](https://www.npmjs.com/package/squads-cli) [![npm downloads](https://img.shields.io/npm/dw/squads-cli.svg)](https://www.npmjs.com/package/squads-cli) @@ -8,20 +13,66 @@ [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org) [![GitHub stars](https://img.shields.io/github/stars/agents-squads/squads-cli?style=social)](https://github.com/agents-squads/squads-cli) -Instead of building fragile Python state machines, Squads turns native LLM CLIs into autonomous managers. The filesystem is long-term memory. GitHub is the async message bus. Markdown is the only config format. No framework lock-in, no proprietary runtime — just the tools developers already use. +
+ +## Why Squads? + +Agents Squads is an experimental framework that replicates how businesses +have been organized and built over decades of evolution — different +domains, specialized teams, shared goals, prioritization, pivoting, and +accumulated knowledge. The same structure that makes human organizations +effective can make AI operations effective. + +LLMs are not learners. Their limitations around self-learning and memory +are well known. But this framework engineers around those limitations — +using structured context injection, persistent filesystem memory, and +feedback loops to extract the best outputs from repetitive tasks and +accumulate organizational knowledge across cycles. + +AI agents from different providers — Claude, Gemini, Codex, Grok — each +have distinct strengths. Claude reasons deeply. Gemini is fast and cheap. +GPT has broad knowledge. But individually, each one hits a ceiling: no +shared context, no coordination, no way to evaluate its own output. + +A **squad** puts multiple AI agents together as a team — different models, +different roles — working toward a shared goal. A Gemini scanner finds +opportunities. A Claude worker executes deep reasoning. A fast model +verifies quality. A lead coordinates and prioritizes. The synergy between +models and roles produces output no individual agent achieves alone. + +Agents within a squad don't just run in parallel — they **converse**. +A lead briefs the team, workers iterate on the task, the lead reviews +and redirects, the verifier checks the output. This local conversation +loop — happening entirely on your machine through shared transcript +files — lets agents discuss, debate, and converge on a solution before +shipping anything. + +This is the difference between "AI that helps" and "AI that operates." -## Why Squads +### Who uses this CLI -Most agent frameworks trap you inside their runtime: custom Python classes, proprietary state graphs, vendor-locked tool registries. When the framework breaks, your agents break. When the framework pivots, you rewrite. +`squads run` is called by an orchestrating agent — Claude Code, Gemini, +or any supported CLI. After dispatch, **agents are the primary users of +this CLI**. They call `squads memory read` to recall what they know, +`squads env show --json` to understand their execution context, and +`squads status --json` to see what's happening across the org. -Squads takes the opposite approach. **The operating system is the framework.** +The CLI is designed for both human operators and machine consumers — +every command supports `--json` for programmatic access. Human-facing +commands (like `squads dash`) prioritize readability. Agent-facing +commands (like `squads env prompt`) prioritize composability. -- **Native CLIs are the runtime.** Claude Code, Gemini CLI, Codex — each is already a capable autonomous agent. Squads orchestrates them as-is, routing tasks to the right model without wrapping them in abstraction layers. When Claude ships a new capability, your agents get it immediately. -- **The filesystem is memory.** Agent knowledge lives in plain markdown files — `state.md`, `learnings.md`, `feedback.md`. No vector databases, no embeddings, no retrieval pipelines. `grep` is your search engine. Git is your version history. Knowledge survives anything. -- **GitHub is the message bus.** Squads coordinate through issues, PRs, and labels — not custom pub/sub systems. A scanner files an issue; a worker picks it up; a verifier checks the PR. The entire workflow is visible, auditable, and works with every CI/CD system that exists. -- **Markdown is the only config.** A squad is a directory. An agent is a `.md` file. Edit it in vim, review it in a PR, diff it in git. No YAML pipelines, no JSON schemas, no DSLs to learn. -- **Multi-provider by default.** Route each agent to the right model: Claude for deep reasoning, Gemini for speed, GPT for breadth, local models for privacy. Swap providers without touching agent definitions. -- **Autonomous, not assisted.** Agents run on schedules, respect budgets, evaluate their own output quality, and improve over time — closing the loop between execution and learning without human intervention. +### Context is the moat + +Most agent frameworks focus on tool calling. Squads focuses on **what the +agent knows before it starts working**. + +Every agent execution loads a layered context cascade — squad identity, +current priorities, feedback from last cycle, active work across the team — +tuned by role so scanners stay lightweight and leads get the full picture. + +The desired result: agents that don't duplicate work, don't ignore +feedback, and improve with every cycle. ## Quick Start @@ -31,215 +82,507 @@ squads init squads status ``` -`squads init` creates a `.agents/` directory in your project with starter squads and configures Claude Code hooks for automatic context injection. +`squads init` creates a `.agents/` directory with 4 starter squads and +configures your environment. ## How It Works +Everything in Squads is a file. There's no database, no server, no +runtime to manage. Your entire AI workforce lives in a single `.agents/` +directory that you commit to git like any other code. This means you get +version history, code review, branching, and merge — applied to your +agent definitions and organizational memory. + ``` .agents/ +├── BUSINESS_BRIEF.md # Business context (primary source) ├── config/ │ └── SYSTEM.md # Base behavior (shared across all agents) ├── squads/ -│ ├── engineering/ +│ ├── intelligence/ │ │ ├── SQUAD.md # Squad identity, goals, KPIs -│ │ ├── code-review.md # Agent definition -│ │ └── backend.md # Agent definition -│ └── marketing/ +│ │ ├── scanner.md # Agent definition +│ │ └── analyst.md # Agent definition +│ ├── research/ +│ │ ├── SQUAD.md +│ │ └── analyst.md +│ ├── product/ +│ │ ├── SQUAD.md +│ │ └── scanner.md +│ └── company/ │ ├── SQUAD.md -│ └── content.md +│ └── evaluator.md # COO — evaluates all squad outputs └── memory/ # Persistent state (auto-managed) - ├── engineering/ - └── marketing/ + ├── intelligence/ + ├── research/ + ├── product/ + └── company/ ``` -**Context cascades down:** `SYSTEM.md` (base behavior) → `SQUAD.md` (squad identity + goals) → `agent.md` (unique instructions) → `state.md` (ephemeral runtime context). - -Everything is plain text. No databases, no servers, no config files beyond markdown. - -## How Agents Think - -Squads uses a layered context cascade to give each agent exactly the right -information for its role. Not too much (wasted tokens, confused agents), -not too little (blind execution, duplicate work). - -### The Cascade +A squad is a directory. An agent is a markdown file. Edit in vim, review in +a PR, diff in git. No YAML pipelines, no JSON schemas, no DSLs. + +The three top-level directories serve distinct purposes: `config/` holds +immutable rules that every agent follows regardless of squad. `squads/` +holds identity — who each agent is, what it produces, how it behaves. +`memory/` holds state — what agents have learned, what they're working on, +what feedback they've received. Identity is stable. Memory evolves. + +### Context Cascade + +The biggest problem with autonomous agents isn't capability — it's +context. An agent that doesn't know what's already been done will +duplicate work. An agent that doesn't know the company strategy will +optimize for the wrong thing. An agent that doesn't know its own last +output was rated as noise will keep producing noise. + +Squads solves this by loading a layered context cascade before every +execution, in strict priority order: + +| # | Layer | Source | Purpose | +|---|-------|--------|---------| +| 0 | System Protocol | `config/SYSTEM.md` | Immutable rules every agent follows | +| 1 | Squad Identity | `squads/{squad}/SQUAD.md` | Mission, goals, output format | +| 2 | Priorities | `memory/{squad}/priorities.md` | Current operational focus | +| 3 | Directives | `memory/company/directives.md` | Company-wide strategic overlay | +| 4 | Active Work | `memory/{squad}/active-work.md` | Open PRs and issues — prevent duplication | +| 5 | Agent State | `memory/{squad}/{agent}/state.md` | What the agent already knows | +| 6 | Feedback | `memory/{squad}/feedback.md` | Last cycle evaluation | +| 7 | Briefings | `memory/daily-briefing.md` | Cross-squad context | + +The order matters. When the token budget runs out, lower layers drop +first. An agent that loses briefings still knows its mission and what +work exists. An agent that loses its identity is useless. The cascade +ensures graceful degradation — the most critical context always loads. -Every agent execution loads context in priority order: +### Role-Based Depth -| Layer | What | Why | -|-------|------|-----| -| System Protocol | Approvals, git workflow, escalation | Immutable rules every agent follows | -| Squad Identity | Mission, aspirational goals, output format | Who am I, what do I produce | -| Priorities | Current operational priorities | What to work on now (weekly) | -| Directives | Company-wide strategic overlay | What matters to the org | -| Feedback | Last cycle evaluation | What was valuable, what was noise | -| Memory | Agent state from last run | What I already know | -| Active Work | Open PRs and issues | What exists — don't duplicate | -| Briefings | Daily briefing, cross-squad context | What's happening elsewhere | +Not every agent needs the same depth of context. A scanner looking for +new opportunities doesn't need to know the company's strategic directives +or what feedback other agents received. A lead coordinating across squads +needs everything. Loading unnecessary context wastes tokens and can +confuse the agent with irrelevant information. -A token budget ensures context fits the model's window. Lower layers drop -gracefully when budget runs out — identity and priorities always load, -briefings drop first. +- **Scanners** get identity, priorities, and their own state — they discover, don't decide +- **Workers** add directives, feedback, and active work — they execute with awareness of what exists +- **Leads** get all layers including cross-squad briefings — they orchestrate with full visibility +- **Evaluators** get all layers with org-wide summaries — they assess and generate feedback ### Goals vs Priorities +A common failure mode in autonomous systems is conflating direction with +execution. An agent that only sees "Fix #461 this week" doesn't know +*why* that matters or what the bigger picture is. An agent that only sees +"Build the best developer experience" has no idea what to work on today. + Squads separates aspiration from execution: -- **Goals** live in `SQUAD.md` — atemporal, aspirational ("Zero friction first-run") +- **Goals** live in `SQUAD.md` — atemporal, aspirational ("Zero friction first-run experience") - **Priorities** live in `priorities.md` — temporal, operational ("Fix #461 this week") -`squads goal set` writes aspirational goals. Priorities are updated by leads -or founders between cycles. Both are injected — goals as squad identity, -priorities as current focus. - -### Role-Based Depth - -Not every agent needs the same context: - -- **Scanners** get minimal context (identity + priorities + state) — they discover, don't decide -- **Workers** add directives + feedback + active work — they execute with awareness -- **Leads** get everything including cross-squad context — they orchestrate -- **Evaluators** get org-wide summaries — they assess and generate feedback - -### The Feedback Loop - -After each execution cycle, a lead evaluates squad outputs against goals: -what was valuable, what was noise, what to prioritize next. This evaluation -is written to `feedback.md` and injected into the next cycle — closing the -loop so agents learn from their own output quality over time. +Goals give agents purpose and judgment. Priorities give them focus. Both +are injected — goals as identity context that shapes decision-making, +priorities as immediate operational focus. `squads goal set` writes +aspirational goals. Priorities are updated between cycles by the human +operator or the evaluator agent. ### Phase Ordering +In a real organization, the research team finishes their analysis before +the product team writes the roadmap. The finance team closes the books +before the CEO reviews performance. Order matters — and when agents +execute in the wrong order, they work with stale or missing information. + Squads declare dependencies in their SQUAD.md frontmatter: ```yaml --- name: product -depends_on: [engineering, customer, research] +depends_on: [intelligence, research] --- ``` -The CLI automatically computes execution phases via topological sort. -Squads with no dependencies run first. Squads with `depends_on: ["*"]` -run last (evaluation). Within each phase, squads run in parallel. -Use `squads run --phased` to enable phase-ordered execution. +The CLI computes execution phases via topological sort. Squads with no +dependencies run first. Squads with `depends_on: ["*"]` run last +(evaluation). Within each phase, squads run in parallel. + +### The Feedback Loop + +This is the core of Squads — a closed loop where agents improve autonomously: + +``` +┌─────────────────────────────────────────────────────┐ +│ │ +│ autopilot ──→ squads run │ +│ ▲ │ │ +│ │ ▼ │ +│ │ intelligence ──┐ │ +│ │ research ──────┼──→ product │ +│ │ │ │ │ +│ │ │ ▼ │ +│ │ │ company (COO) │ +│ │ │ │ │ +│ │ │ feedback.md │ +│ │ │ │ │ +│ │ └────────┘ │ +│ │ (injected next cycle) │ +│ └─────────────────────┘ │ +│ │ +└─────────────────────────────────────────────────────┘ +``` + +After each cycle, the company evaluator assesses all squad outputs: +what was valuable, what was noise, what to prioritize next. Written to +`feedback.md` per squad and injected into the next cycle — closing the +loop so agents learn from their own output quality. + +`squads autopilot` uses these evaluations to determine which squads to +run next, in what order, with what budget. The full loop: autopilot +dispatches → agents execute → evaluator writes feedback → autopilot +reads feedback → dispatches again. ## Running Agents +There are three ways to run agents, each suited for different situations. + +**Single agent** — run one agent for a focused task. The agent gets its +context cascade, executes autonomously, and writes results to GitHub +and memory. This is the building block. + ```bash -# Run a specific agent -squads run engineering/code-review +squads run research/analyst +squads run intelligence --task "Scan competitor pricing changes" +``` -# Run with a specific directive -squads run engineering --task "Review all open PRs for security issues" +**Squad conversation** — run an entire squad as a coordinated team. The +lead briefs first, workers execute in parallel, the lead reviews outputs, +and the cycle repeats until the team converges on a result. This is where +multi-agent synergy happens. -# Run a full squad conversation (lead briefs → workers iterate → convergence) -squads run engineering --parallel +```bash +squads run research --parallel +``` -# Autonomous scheduling with budget control +**Autonomous dispatch** — let Squads decide what to run, when, and in +what order. Autopilot reads priorities and feedback, respects phase +ordering, and manages budget constraints. This is the hands-off mode for +continuous operations. + +```bash squads autopilot --interval 30 --budget 50 ``` -## Base Squads +## Starter Squads -These squads are battle-tested and produce real outputs autonomously: +The first experience matters. Rather than shipping an empty framework and +asking you to figure out what to build, `squads init` ships with 4 squads +designed to deliver visible output from the very first run. These aren't +demo squads — they're the foundation of an operational AI workforce. | Squad | What It Does | Agents | |-------|-------------|--------| -| **engineering** | Code review, CI/CD, infrastructure, issue resolution | lead, scanner, worker, verifier, issue-solver | -| **marketing** | Content creation, SEO, social media, brand voice | lead, writer, seo-analyst, social-scheduler | -| **finance** | Budget tracking, cost analysis, financial reporting | lead, scanner, verifier, bookkeeper | -| **operations** | Org health, agent performance, architecture gaps | lead, scanner, worker, verifier, critic | -| **research** | Deep research, competitive intelligence, domain analysis | lead, analyst, synthesizer | -| **product** | Roadmap, specs, user feedback synthesis, sprint planning | lead, scanner, worker | -| **customer** | Inbound lead qualification, CRM, onboarding | lead, scanner, worker | -| **website** | Site quality, SEO audits, content updates, testing | lead, scanner, tester | +| **intelligence** | Strategic synthesis — Know / Don't Know / Playbook briefs | intel-lead, intel-eval, intel-critic | +| **research** | Market, competitor, and trend research with sourced findings | lead, analyst, synthesizer | +| **product** | Roadmap, specs, user feedback synthesis | lead, scanner, worker | +| **company** | Orchestrates squads, evaluates outputs, closes the feedback loop | manager, evaluator, goal-tracker, event-dispatcher, critic | + +**Intelligence + research** produce insights. **Product** turns insights +into roadmap. **Company** evaluates everything and writes feedback — which +agents read next cycle. The loop closes automatically. + +Additional squads available as packs: + +```bash +squads init --pack engineering # Add engineering squad +squads init --pack marketing # Add marketing squad +squads init --pack all # All available squads +``` + +### Build Your Own + +Squads are directories. Agents are markdown files. Bring your own skills, +tools, and CLIs — anything your agents can run in a terminal becomes part +of the squad. + +```bash +squads add devops -d "Infrastructure and deployment automation" +``` + +This creates `squads/devops/SQUAD.md` and a lead agent. Add more agents +as `.md` files, define their roles, give them access to your CLIs +(`terraform`, `kubectl`, `aws`, `docker` — whatever they need), and run: + +```bash +squads run devops --parallel +``` + +### Customizing Your Squads + +Agents read context in layers — higher layers are stable, lower layers +change often. Update them in this order: + +#### 1. Business Brief (what you do) + +Edit `.agents/BUSINESS_BRIEF.md` — every agent reads this before every run. +The more specific you are, the better agents perform. + +```markdown +What does your business do? Who are your customers? What market? +What should agents research first? Who are your competitors? +``` + +#### 2. Directives (what matters now) + +Edit `.agents/memory/company/directives.md` — strategic overlay that +overrides squad-level goals when there's a conflict. + +```markdown +What is the #1 priority right now? What metric are you optimizing? +What constraints apply? What should agents NOT do? +``` -Each squad follows a consistent pattern: **lead** (coordinates), **scanner** (monitors), **worker** (executes), **verifier** (validates). +#### 3. Squad Goals (what each team does) -## Key Commands +Replace the generic goals in each `SQUAD.md` with goals specific to your +business: ```bash -# Status & monitoring +# Or use the CLI: +squads goal set intelligence "Monitor competitor X's pricing weekly" +squads goal set research "Deep dive on Y market segment" +squads goal set product "Write spec for Z feature" +``` + +#### 4. Priorities (what to do this week) + +Create or edit `.agents/memory/{squad}/priorities.md` — operational focus +that changes frequently: + +```markdown +- Fix issue #123 (blocking users) +- Research competitor's new feature launch +- Update roadmap based on last cycle's feedback +``` + +**Rule**: Goals are aspirational (stable). Priorities are operational +(updated frequently). Directives are strategic (updated less frequently). + +#### Agent Instructions + +Each `.md` file in a squad defines an agent's behavior, output format, +and quality rules. The starter agents come with structured output formats +(tables, scoring rubrics, required sections) — modify these to match what +you actually need. + +#### System Protocol + +`.agents/config/SYSTEM.md` contains immutable rules all agents follow — +git workflow, memory protocol, output standards. You rarely need to change +this, but you can customize it for your team's conventions. + +## Why CLI-First? + +AI agents already live in the terminal. Wrapping them in a web UI or +Python runtime adds latency, complexity, and failure modes. A CLI +orchestrating CLIs is zero-overhead — and it means your agents can use +**any tool you can run in a shell**. + +The more CLIs your agents have access to, the more capable your squads +become. Squads itself is just the orchestrator — the real power comes +from the tools you give your agents. + +### Required + +| Tool | Purpose | +|------|---------| +| [Node.js](https://nodejs.org) >= 18 | Runtime | +| [Git](https://git-scm.com) | Memory sync, version control | +| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) (`claude`) | Default agent execution | + +### Recommended + +| Tool | Purpose | +|------|---------| +| [GitHub CLI](https://cli.github.com) (`gh`) | Issue tracking, PRs, project management | +| [Google Cloud CLI](https://cloud.google.com/sdk) (`gcloud`) | GCP deployments, secrets, infrastructure | +| [Wrangler](https://developers.cloudflare.com/workers/wrangler/) (`wrangler`) | Cloudflare Workers, Pages, DNS | +| [Google Workspace CLI](https://github.com/nicholasgasior/gws) (`gws`) | Drive, Gmail, Calendar, Sheets | + +### Any CLI Your Agents Need + +```bash +terraform, kubectl, docker, aws, vercel, stripe, twilio, +psql, redis-cli, curl, jq, ffmpeg, imagemagick... +``` + +If it runs in a terminal, your agents can use it. + +### Skills + CLIs + +Agents get capabilities through two layers: + +- **CLIs** are the tools — `gh`, `gcloud`, `curl`, `psql`. They execute + actions in the real world. +- **Skills** are the knowledge — markdown files that teach agents *how* + to use those tools effectively. A BigQuery skill teaches query + optimization patterns. A GitHub skill teaches your PR workflow. A + deployment skill codifies your staging-to-prod pipeline. + +``` +.claude/skills/ +├── bq/SKILL.md # BigQuery patterns + cost optimization +├── gh/SKILL.md # GitHub workflow + PR conventions +├── gcloud/SKILL.md # GCP deployment procedures +└── e2e-test/SKILL.md # Browser testing with Chrome CDP +``` + +Skills are injected into agent context alongside squad identity and +memory. The combination of CLI tools + domain knowledge in skills is +what turns a generic LLM into a specialized operator. + +No MCP servers, no custom tool registries, no adapter layers. A skill +file + a CLI installed on your machine is all an agent needs to operate +in any domain. + +`squads doctor` checks which CLIs are available on your machine. + +## Commands + +The command surface is split into two audiences. Human operators manage +the workforce — they set goals, monitor progress, and control budgets. +Agents consume the CLI programmatically during execution — they read +their own context, persist learnings, and record metrics. Every command +supports `--json` so agents can parse outputs reliably. + +### For Humans + +```bash +# Setup +squads init # Bootstrap .agents/ directory +squads add # Add a new squad +squads doctor # Check tools and readiness + +# Execute +squads run # Run an agent or full squad +squads autopilot # Autonomous scheduling with budget control + +# Monitor squads status [squad] # Overview of all squads -squads dash # Dashboard with goals, metrics, git activity -squads sessions # Active AI coding sessions across your machine -squads cost # Cost summary by squad and period -squads doctor # Check local tools, auth, readiness - -# Memory & learning -squads memory query "topic" # Search across all agent memory -squads memory write squad "x" # Persist a learning -squads memory read squad # View squad knowledge -squads memory sync # Sync memory with git remote - -# Goals & tracking +squads sessions # Active agent sessions on your machine +squads dash # Dashboard with goals, metrics, activity + +# Goals & Tracking squads goal set squad "goal" # Set a squad objective -squads goal list # View all goals and progress -squads results [squad] # Git activity + KPI goals vs actuals +squads goal list # View all goals +squads results [squad] # Git activity + KPI actuals +squads stats [squad] # Workforce scorecard + ROI +``` + +### For Agents + +Agents are the primary consumers of this CLI. After `squads run` +dispatches an agent, it uses these commands to understand its context, +persist knowledge, and evaluate its own work. -# Automation -squads autonomous start # Cron-style local scheduling -squads autopilot # Intelligent dispatch with budget control -squads cognition # Business cognition engine (beliefs, decisions) +```bash +# Context +squads env show --json # Execution context (MCP, model, budget) +squads env prompt -a # Generate sub-agent prompt +squads status --json # Org-wide state for coordination + +# Memory +squads memory read # Recall squad knowledge +squads memory write "x"# Persist a learning +squads memory query "topic" # Search across all memory + +# Feedback loop +squads feedback show # Last cycle evaluation +squads feedback add "text" # Write evaluation +squads exec list # Own execution history +squads kpi record # Record a metric +``` + +Everything above works locally — no login, no cloud, no API. +Every command supports `--json` for machine consumption. + +## Configuration + +Agents need API keys to execute. Squads reads secrets from a `.env` file +in your project root — the same pattern used by most Node.js and Python +projects. Each provider's CLI uses its own environment variable, so you +only need keys for the providers you actually use. + +```bash +# .env — never commit this file +ANTHROPIC_API_KEY=sk-ant-... # Required for Claude Code (default provider) +GEMINI_API_KEY=... # Required for Gemini CLI +OPENAI_API_KEY=sk-... # Required for Codex +GITHUB_TOKEN=ghp_... # Recommended for gh CLI operations ``` -Run `squads --help` for the full command reference, or `squads --help` for options. +`squads run` loads `.env` automatically before dispatching any agent. +If a required key is missing, the provider's CLI will report the error — +Squads doesn't mask or intercept auth failures. Add `.env` to your +`.gitignore` to keep secrets out of version control. + +## Providers -## Supported Providers +Multi-provider support isn't just a feature — it's central to how squads +work. Different models have different strengths, costs, and speed +profiles. A squad can route its scanner to a fast, cheap model (Gemini +Flash) for high-volume monitoring, its worker to a deep reasoning model +(Claude Opus) for complex analysis, and its verifier to a mid-tier model +for cost-effective quality checks. -| Provider | CLI | Models | +Squads shells out to native AI CLIs. Each provider's CLI handles auth, +context, and tool use independently — Squads just orchestrates. + +| Provider | CLI | Status | |----------|-----|--------| -| Anthropic | `claude` | Opus, Sonnet, Haiku | -| Google | `gemini` | Gemini 2.5 Flash, Pro | -| OpenAI | `codex` | GPT-4o, o1, o3 | -| Mistral | `vibe` | Large, Medium | -| xAI | `grok` | Grok | -| Aider | `aider` | Multi-model | -| Ollama | `ollama` | Any local model | +| Anthropic | `claude` | Stable — primary provider | +| Google | `gemini` | Stable | +| OpenAI | `codex` | Experimental | +| Mistral | `vibe` | Experimental | +| xAI | `grok` | Experimental | +| Ollama | `ollama` | Experimental | + +Experimental providers have CLI integration but haven't been extensively +tested in production. Contributions welcome — especially from teams +already using these CLIs for autonomous work. ```bash squads run research --provider=google --model=gemini-2.5-flash -squads providers # List available providers +squads providers # List available providers and install status ``` -## Prerequisites - -Squads orchestrates existing CLI tools. Install the ones your squads need: - -| Tool | Required | Used For | -|------|----------|----------| -| [Node.js](https://nodejs.org) >= 18 | Yes | Runtime | -| [Git](https://git-scm.com) | Yes | Memory sync, version control | -| [Claude Code](https://docs.anthropic.com/en/docs/claude-code) | Yes (default provider) | Agent execution | -| [GitHub CLI](https://cli.github.com) (`gh`) | Recommended | Issue tracking, PRs, project management | -| [Google Cloud CLI](https://cloud.google.com/sdk) (`gcloud`) | Optional | GCP deployment, secrets | -| [Google Workspace CLI](https://github.com/nicholasgasior/gws) (`gws`) | Optional | Drive, Gmail, Calendar, Sheets | -| [Docker](https://www.docker.com) | Optional | Local Postgres/Redis for API | - -## Claude Code Integration - -Squads hooks into Claude Code for automatic context injection: - -```json -{ - "hooks": { - "SessionStart": [{ - "hooks": [ - { "type": "command", "command": "squads status", "timeout": 10 }, - { "type": "command", "command": "squads memory sync --no-push", "timeout": 15 } - ] - }], - "Stop": [{ - "hooks": [ - { "type": "command", "command": "squads memory sync --push", "timeout": 15 } - ] - }] - } -} -``` +## Local Execution and Scaling + +Squads runs locally by default — your machine, your API keys, your +control. There's no cloud dependency for core functionality. Each agent +execution spawns a CLI process (`claude`, `gemini`, etc.) that runs +until completion. Your data never leaves your machine unless the agent +explicitly pushes to GitHub or another service you've configured. + +### Local limits + +| Parallel squads | Machine | +|----------------|---------| +| 2–3 | 8 GB RAM, 4 cores (laptop) | +| 4–6 | 16 GB RAM, 8 cores (workstation) | +| 8–12 | 32 GB+ RAM, 10+ cores (M-series Mac / desktop) | + +*Actual capacity depends on your CPU, memory, and which providers you +use. `squads autopilot --max-parallel 3` controls concurrent executions. +Monitor with `squads sessions`.* + +### Cloud scaling -`squads init` configures this automatically. +Local execution works well for individuals and small teams, but it has +natural limits — your machine needs to stay running, parallel execution +is bounded by hardware, and there's no shared visibility across team +members. When you're ready to scale autonomous operations across teams, +cloud execution runs the same agents, same memory, same commands — but +on managed infrastructure instead of your laptop. ## Development @@ -252,7 +595,7 @@ npm link # Makes 'squads' available globally npm test ``` -TypeScript (strict mode), Commander.js, Vitest, tsup. Built on the [Anthropic SDK](https://github.com/anthropics/anthropic-sdk-node) with multi-provider abstraction. +TypeScript (strict mode), Commander.js, Vitest, tsup. ## Contributing @@ -274,7 +617,23 @@ See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. ## Related - [agents-squads](https://github.com/agents-squads/agents-squads) — The framework -- [engram](https://github.com/agents-squads/engram) — Persistent memory for AI agents (MCP server) + +## Get Started + +```bash +npm install -g squads-cli +squads init +squads run research/analyst +``` + +Build your own squads. Write your own skills. Optimize for your desired +outputs. Every organization is different — Squads gives you the structure, +you bring the domain knowledge. Start with the starter squads, observe +what works, tune the context, and iterate. The agents get better as your +skills and memory accumulate. + +We'd love to see what you build. Share your squads and skills in +[GitHub Discussions](https://github.com/agents-squads/squads-cli/discussions). ## License diff --git a/docs/TELEMETRY.md b/docs/TELEMETRY.md deleted file mode 100644 index 86a1e81a..00000000 --- a/docs/TELEMETRY.md +++ /dev/null @@ -1,284 +0,0 @@ -# Squads CLI Telemetry Architecture - -This document maps all telemetry data flowing through the squads infrastructure. - -## Overview - -``` -┌─────────────────────────────────────────────────────────────────┐ -│ DATA SOURCES │ -├─────────────────────────────────────────────────────────────────┤ -│ │ -│ Claude Code (OTel) squads-cli (Local) │ -│ ├─ api_request events ├─ cli.init │ -│ │ └─ model, tokens, cost ├─ cli.run │ -│ ├─ tool_result events ├─ cli.status │ -│ │ └─ tool_name, duration ├─ cli.dashboard │ -│ └─ session context ├─ cli.error │ -│ └─ squad, agent, user_id └─ cli.* (all commands) │ -│ │ -└───────────────┬─────────────────────────┬───────────────────────┘ - │ │ - ▼ ▼ -┌───────────────────────────┐ ┌──────────────────────────────────┐ -│ OTel Collector (4318) │ │ Local Storage │ -│ └─ Batch + Forward │ │ ~/.squads-cli/ │ -└───────────────┬───────────┘ │ ├─ telemetry.json (config) │ - │ │ └─ events.json (last 1000) │ - ▼ └──────────────────────────────────┘ -┌───────────────────────────────────────────────────────────────┐ -│ SQUADS BRIDGE (8080) │ -├───────────────────────────────────────────────────────────────┤ -│ Endpoints: │ -│ ├─ POST /v1/logs ← OTel logs (api_request, tool_result)│ -│ ├─ POST /v1/metrics ← OTel metrics │ -│ ├─ POST /api/telemetry ← CLI anonymous events │ -│ ├─ GET /stats → Real-time budget/costs │ -│ ├─ GET /api/cost/summary → Cost breakdown for dashboard │ -│ ├─ POST /api/conversations → Memory capture │ -│ └─ GET /api/conversations/search → Full-text search │ -└───────────────┬───────────────────────────────────────────────┘ - │ - ┌──────────┼──────────┬──────────────────┐ - ▼ ▼ ▼ ▼ -┌─────────┐ ┌───────┐ ┌──────────┐ ┌──────────────┐ -│PostgreSQL│ │ Redis │ │ Langfuse │ │ Engram/mem0 │ -│ (primary)│ │(cache)│ │(optional)│ │ (optional) │ -└─────────┘ └───────┘ └──────────┘ └──────────────┘ -``` - -## Data Sources - -### 1. Claude Code (OpenTelemetry) - -Claude Code sends telemetry via OTLP HTTP to port 4318. - -**Event Types:** - -| Event | Data | Purpose | -|-------|------|---------| -| `api_request` | model, tokens, cost, cache | Track LLM usage | -| `tool_result` | tool_name, duration, success | Track tool execution | - -**Token Attributes:** -- `input_tokens` / `output_tokens` - Token counts -- `cache_read_tokens` - Cached input tokens -- `cache_creation_tokens` - New cache entries -- `cost_usd` - Computed cost - -**Context Attributes:** -- `session.id` - Session identifier -- `user.id` - User identifier -- `squad` - Squad name -- `agent` - Agent name -- `model` - Model used - -### 2. squads-cli (Anonymous Telemetry) - -The CLI tracks usage locally with optional remote reporting. - -**Configuration:** -```bash -# Disable telemetry -export SQUADS_TELEMETRY_DISABLED=1 -# or -export DO_NOT_TRACK=1 - -# Custom endpoint -export SQUADS_TELEMETRY_URL=https://your-endpoint.com/telemetry -``` - -**Local Storage:** -- `~/.squads-cli/telemetry.json` - Anonymous ID and config -- `~/.squads-cli/events.json` - Last 1000 events - -**Event Types:** - -| Event | When | Properties | -|-------|------|------------| -| `cli.init` | Project initialized | template | -| `cli.run` | Squad/agent executed | squad, agent, durationMs | -| `cli.status` | Status viewed | squad | -| `cli.dashboard` | Dashboard viewed | durationMs | -| `cli.error` | Command failed | command, errorType, errorMessage | -| `cli.goal.set` | Goal created | squad | -| `cli.goal.complete` | Goal completed | squad | -| `cli.memory.query` | Memory searched | query length | -| `cli.login` | User logged in | email domain (not full email) | -| `cli.logout` | User logged out | - | - -**Event Payload:** -```json -{ - "event": "cli.dashboard", - "timestamp": "2024-01-02T12:00:00Z", - "properties": { - "anonymousId": "uuid", - "cliVersion": "0.1.0", - "durationMs": 234, - "success": true - } -} -``` - -## Storage - -### PostgreSQL Tables - -| Table | Data | Source | -|-------|------|--------| -| `squads.llm_generations` | API calls (tokens, cost, model) | OTel api_request | -| `squads.tool_executions` | Tool usage (name, duration, success) | OTel tool_result | -| `squads.sessions` | Session aggregates | OTel session context | -| `squads.conversations` | Message content for memory | Engram hook | -| `squads.dashboard_snapshots` | Historical metrics | squads dash | -| `squads.cli_events` | Anonymous CLI usage | squads-cli | - -### Redis Keys - -| Key Pattern | Data | TTL | -|-------------|------|-----| -| `cost:daily:{date}` | Daily cost total | 48h | -| `cost:squad:{squad}:{date}` | Per-squad daily cost | 48h | -| `tokens:input:{date}` | Daily input tokens | 48h | -| `tokens:output:{date}` | Daily output tokens | 48h | -| `generations:{date}` | Daily API call count | 48h | -| `session:{id}` | Session metadata | 24h | -| `ratelimit:latest:{model}` | Current rate limits | 5m | - -## Privacy - -### What We Collect - -- Anonymous UUID (generated locally, not linked to identity) -- Command names and durations -- Error types (not full stack traces) -- Email domain for login (not full email) -- CLI version - -### What We DON'T Collect - -- Personal information (name, email, IP) -- File contents or paths -- API keys or secrets -- Full error messages (truncated to 100 chars) -- Conversation content (stored locally only) - -### Opt-Out - -```bash -# Disable all telemetry -export SQUADS_TELEMETRY_DISABLED=1 - -# Standard DO_NOT_TRACK -export DO_NOT_TRACK=1 - -# Or programmatically -import { disable } from 'squads-cli/telemetry'; -disable(); -``` - -### Data Inspection - -View your local telemetry: -```bash -cat ~/.squads-cli/events.json | jq '.[-10:]' -``` - -## OTel Collector Configuration - -The collector batches and forwards telemetry to the bridge. - -**File:** `docker/otel-collector.yaml` - -```yaml -receivers: - otlp: - protocols: - http: - endpoint: 0.0.0.0:4318 - -processors: - batch: - timeout: 5s - send_batch_size: 100 - -exporters: - otlphttp: - endpoint: http://squads-bridge:8080 - encoding: json - -service: - pipelines: - logs: - receivers: [otlp] - processors: [batch] - exporters: [otlphttp] -``` - -## Cost Tracking - -### Model Pricing (per 1M tokens) - -| Model | Input | Output | -|-------|-------|--------| -| claude-opus-4-5 | $15.00 | $75.00 | -| claude-sonnet-4 | $3.00 | $15.00 | -| claude-haiku-4.5 | $0.80 | $4.00 | - -### Rate Limits by Tier - -| Tier | RPM | ITPM (opus/sonnet) | OTPM (opus/sonnet) | -|------|-----|--------------------|--------------------| -| 1 | 50 | 30k | 8k | -| 2 | 1,000 | 450k | 90k | -| 3 | 2,000 | 800k | 160k | -| 4 | 4,000 | 2M | 400k | - -## Integration Points - -### Langfuse (Optional) - -Forward OTel data to Langfuse for observability: - -```bash -export LANGFUSE_ENABLED=true -export LANGFUSE_PUBLIC_KEY=pk_... -export LANGFUSE_SECRET_KEY=sk_... -export LANGFUSE_HOST=https://cloud.langfuse.com -``` - -### Engram/mem0 (Optional) - -Forward conversations for memory extraction: - -```bash -export ENGRAM_ENABLED=true -export ENGRAM_URL=http://localhost:8000 -``` - -## Debugging - -### View Recent OTel Logs - -```bash -curl http://localhost:8080/debug/logs | jq -``` - -### Check Bridge Health - -```bash -curl http://localhost:8080/health -``` - -### Real-time Stats - -```bash -curl http://localhost:8080/stats | jq -``` - -### Cost Summary - -```bash -curl "http://localhost:8080/api/cost/summary?period=day" | jq -``` diff --git a/scripts/e2e-smoke.sh b/scripts/e2e-smoke.sh deleted file mode 100755 index 149e8763..00000000 --- a/scripts/e2e-smoke.sh +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env bash -# E2E smoke test: simulates real user npm install + first-run journey -# Catches packaging bugs (missing files, broken bin, wrong exports) that -# vitest tests miss because they run local dist, not the installed package. -# -# Usage: bash scripts/e2e-smoke.sh - -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" - -echo "▶ Building package..." -cd "$REPO_ROOT" -npm run build - -echo "▶ Packing..." -TARBALL=$(npm pack --quiet) -TARBALL_PATH="$REPO_ROOT/$TARBALL" - -TMPDIR=$(mktemp -d) -cleanup() { - echo "▶ Cleaning up..." - npm uninstall -g squads-cli 2>/dev/null || true - rm -rf "$TMPDIR" - rm -f "$TARBALL_PATH" -} -trap cleanup EXIT - -echo "▶ Installing from tarball (simulates: npm install -g squads-cli)..." -npm install -g "$TARBALL_PATH" - -echo "▶ Setting up temp project dir..." -cd "$TMPDIR" -git init -q -git config user.email "smoke@test.local" -git config user.name "Smoke Test" -git commit --allow-empty -q -m "init" - -step() { echo ""; echo "=== STEP: $1 ==="; } - -step "squads --version" -squads --version - -step "squads list (empty project)" -squads list || true - -step "squads init --yes" -squads init --yes 2>/dev/null || squads init --skip-infra --force <<< "" - -step "squads list (after init)" -squads list - -step "squads status" -squads status || true - -step "squads doctor" -squads doctor || true - -step "squads run --dry-run (first squad found)" -SQUAD=$(squads list 2>/dev/null | grep -v "^$" | head -1 | awk '{print $1}' || true) -if [ -n "$SQUAD" ]; then - squads run "$SQUAD" --dry-run || true -else - echo "skip: no squads found after init" -fi - -echo "" -echo "✅ All smoke test steps passed" diff --git a/scripts/release.sh b/scripts/release.sh deleted file mode 100755 index 45480541..00000000 --- a/scripts/release.sh +++ /dev/null @@ -1,229 +0,0 @@ -#!/bin/bash -# Release script for squads-cli -# Usage: ./scripts/release.sh [patch|minor|major] -# -# Steps: -# 1. Bump version in package.json -# 2. Build the project -# 3. Run tests -# 4. Create git tag -# 5. Push to GitHub -# 6. Create GitHub release with artifacts -# 7. Publish to npm - -set -e - -# Colors -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -CYAN='\033[0;36m' -NC='\033[0m' - -SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" -PROJECT_DIR="$(dirname "$SCRIPT_DIR")" -cd "$PROJECT_DIR" - -# Check args -BUMP_TYPE="${1:-patch}" -if [[ ! "$BUMP_TYPE" =~ ^(patch|minor|major)$ ]]; then - echo -e "${RED}Usage: $0 [patch|minor|major]${NC}" - exit 1 -fi - -# Check for uncommitted changes -if [[ -n $(git status --porcelain) ]]; then - echo -e "${RED}Error: Uncommitted changes. Commit or stash first.${NC}" - git status --short - exit 1 -fi - -# Check we're on main -BRANCH=$(git branch --show-current) -if [[ "$BRANCH" != "main" ]]; then - echo -e "${YELLOW}Warning: Not on main branch (on $BRANCH)${NC}" - read -p "Continue anyway? [y/N] " -n 1 -r - echo - [[ ! $REPLY =~ ^[Yy]$ ]] && exit 1 -fi - -# Check npm auth -if ! npm whoami &>/dev/null; then - echo -e "${RED}Error: Not logged in to npm. Run 'npm login' first.${NC}" - exit 1 -fi - -# Check gh auth -if ! gh auth status &>/dev/null; then - echo -e "${RED}Error: Not logged in to GitHub CLI. Run 'gh auth login' first.${NC}" - exit 1 -fi - -echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" -echo -e "${CYAN} squads-cli release${NC}" -echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" - -# Get current version -CURRENT_VERSION=$(node -p "require('./package.json').version") -echo -e "${YELLOW}Current version:${NC} $CURRENT_VERSION" - -# Bump version -echo -e "\n${YELLOW}[1/7] Bumping version ($BUMP_TYPE)...${NC}" -npm version "$BUMP_TYPE" --no-git-tag-version -NEW_VERSION=$(node -p "require('./package.json').version") -echo -e "${GREEN}New version:${NC} $NEW_VERSION" - -# Build -echo -e "\n${YELLOW}[2/7] Building...${NC}" -bun run build -echo -e "${GREEN}✓ Build complete${NC}" - -# Test -echo -e "\n${YELLOW}[3/7] Running tests...${NC}" -bun test || { - echo -e "${RED}Tests failed. Reverting version bump.${NC}" - git checkout package.json package-lock.json 2>/dev/null || true - exit 1 -} -echo -e "${GREEN}✓ Tests passed${NC}" - -# Create tarball for GitHub release -echo -e "\n${YELLOW}[4/7] Creating release artifact...${NC}" -TARBALL="squads-cli-$NEW_VERSION.tgz" -npm pack -mv "squads-cli-$NEW_VERSION.tgz" "$TARBALL" -echo -e "${GREEN}✓ Created $TARBALL${NC}" - -# Commit and tag -echo -e "\n${YELLOW}[5/7] Committing and tagging...${NC}" -git add package.json package-lock.json -git commit -m "chore: release v$NEW_VERSION - -🤖 Generated with [Agents Squads](https://agents-squads.com) - -Co-Authored-By: Claude Opus 4.5 -Co-Authored-By: Gemini 3 🍌 " -git tag -a "v$NEW_VERSION" -m "Release v$NEW_VERSION" -echo -e "${GREEN}✓ Tagged v$NEW_VERSION${NC}" - -# Push to GitHub -echo -e "\n${YELLOW}[6/7] Pushing to GitHub...${NC}" -git push origin main -git push origin "v$NEW_VERSION" -echo -e "${GREEN}✓ Pushed to GitHub${NC}" - -# Create GitHub release -echo -e "\n${YELLOW}[7/7] Creating GitHub release...${NC}" - -# Generate changelog from commits -PREV_TAG=$(git describe --tags --abbrev=0 HEAD~1 2>/dev/null || echo "") -if [[ -n "$PREV_TAG" ]]; then - COMMITS=$(git log "$PREV_TAG"..HEAD~1 --pretty=format:"- %s" --no-merges | grep -v "^- chore: release") -else - COMMITS=$(git log --oneline -20 --pretty=format:"- %s" --no-merges | grep -v "^- chore: release" | head -15) -fi - -# Categorize commits -FEAT_COMMITS=$(echo "$COMMITS" | grep "^- feat" | sed 's/^- feat[^:]*: /- /' || true) -FIX_COMMITS=$(echo "$COMMITS" | grep "^- fix" | sed 's/^- fix[^:]*: /- /' || true) -OTHER_COMMITS=$(echo "$COMMITS" | grep -v "^- feat\|^- fix\|^- chore\|^- docs\|^- test\|^- ci" || true) - -RELEASE_NOTES="## squads-cli v$NEW_VERSION - -A CLI for humans and agents - manage AI agent squads with comprehensive dashboards, telemetry, and team coordination. - -### Installation - -\`\`\`bash -npm install -g squads-cli -\`\`\` - -### What's New -" - -[[ -n "$FEAT_COMMITS" ]] && RELEASE_NOTES+=" -#### Features -$FEAT_COMMITS -" - -[[ -n "$FIX_COMMITS" ]] && RELEASE_NOTES+=" -#### Bug Fixes -$FIX_COMMITS -" - -[[ -n "$OTHER_COMMITS" ]] && RELEASE_NOTES+=" -#### Other Changes -$OTHER_COMMITS -" - -RELEASE_NOTES+=" -### Full Changelog - -See [commits since v$CURRENT_VERSION](https://github.com/agents-squads/squads-cli/compare/v$CURRENT_VERSION...v$NEW_VERSION) - ---- - -🤖 Generated with [Agents Squads](https://agents-squads.com) - -Co-Authored-By: Claude Opus 4.5 -Co-Authored-By: Gemini 3 🍌 " - -gh release create "v$NEW_VERSION" "$TARBALL" \ - --title "v$NEW_VERSION" \ - --notes "$RELEASE_NOTES" -echo -e "${GREEN}✓ GitHub release created${NC}" - -# Update docs changelog -echo -e "\n${YELLOW}[8/9] Updating docs changelog...${NC}" -DOCS_DIR="${DOCS_DIR:-$HOME/agents-squads/docs}" - -if [[ -d "$DOCS_DIR" ]]; then - cd "$DOCS_DIR" - git pull --rebase origin main 2>/dev/null || true - - # Generate release title from commits - if [[ -n "$FEAT_COMMITS" ]]; then - RELEASE_TITLE=$(echo "$FEAT_COMMITS" | head -1 | sed 's/^- //' | cut -c1-40) - else - RELEASE_TITLE="Bug Fixes & Improvements" - fi - - # Convert commits to JSON arrays for the script - FEAT_JSON=$(echo "$FEAT_COMMITS" | jq -R -s 'split("\n") | map(select(length > 0))' 2>/dev/null || echo "[]") - FIX_JSON=$(echo "$FIX_COMMITS" | jq -R -s 'split("\n") | map(select(length > 0))' 2>/dev/null || echo "[]") - - # Run the changelog update script - DOCS_DIR="$DOCS_DIR" node "$SCRIPT_DIR/update-docs-changelog.cjs" \ - "$NEW_VERSION" \ - "$RELEASE_TITLE" \ - "$FEAT_JSON" \ - "$FIX_JSON" - - # Commit and push - git add changelog.mdx - git commit -m "docs(changelog): add v$NEW_VERSION release - -Co-Authored-By: Claude " || echo "No changes to commit" - git push origin main - - cd "$PROJECT_DIR" - echo -e "${GREEN}✓ Docs changelog updated${NC}" -else - echo -e "${YELLOW}⚠ Docs repo not found at $DOCS_DIR - skipping changelog update${NC}" -fi - -# Publish to npm -echo -e "\n${YELLOW}[9/9] Publishing to npm...${NC}" -npm publish --access public -echo -e "${GREEN}✓ Published to npm${NC}" - -# Cleanup -rm -f "$TARBALL" - -echo -e "\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" -echo -e "${GREEN}✓ Released squads-cli v$NEW_VERSION${NC}" -echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}" -echo "" -echo -e " ${CYAN}npm:${NC} https://www.npmjs.com/package/squads-cli" -echo -e " ${CYAN}github:${NC} https://github.com/agents-squads/squads-cli/releases/tag/v$NEW_VERSION" -echo "" diff --git a/scripts/update-docs-changelog.cjs b/scripts/update-docs-changelog.cjs deleted file mode 100755 index c56762c8..00000000 --- a/scripts/update-docs-changelog.cjs +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env node -/** - * Update docs changelog with new release entry - * Usage: node update-docs-changelog.js [features] [fixes] - */ - -const fs = require('fs'); -const path = require('path'); - -const [,, version, title, featuresJson, fixesJson] = process.argv; - -if (!version || !title) { - console.error('Usage: update-docs-changelog.js <version> <title> [featuresJson] [fixesJson]'); - process.exit(1); -} - -const docsDir = process.env.DOCS_DIR || path.join(process.env.HOME, 'agents-squads/docs'); -const changelogPath = path.join(docsDir, 'changelog.mdx'); - -if (!fs.existsSync(changelogPath)) { - console.error(`Changelog not found: ${changelogPath}`); - process.exit(1); -} - -// Parse features and fixes from JSON -let features = []; -let fixes = []; -try { - if (featuresJson) features = JSON.parse(featuresJson); - if (fixesJson) fixes = JSON.parse(fixesJson); -} catch (e) { - // If not valid JSON, treat as newline-separated strings - if (featuresJson) features = featuresJson.split('\n').filter(Boolean); - if (fixesJson) fixes = fixesJson.split('\n').filter(Boolean); -} - -// Build entry -const date = new Date().toLocaleDateString('en-US', { - year: 'numeric', - month: 'long', - day: 'numeric' -}); - -let entry = `### v${version} - ${title} - -<Note> - Released ${date} -</Note> -`; - -if (features.length > 0) { - entry += ` -**Features:** -${features.map(f => `- ${f.replace(/^- /, '')}`).join('\n')} -`; -} - -if (fixes.length > 0) { - entry += ` -**Fixes:** -${fixes.map(f => `- ${f.replace(/^- /, '')}`).join('\n')} -`; -} - -entry += ` ---- - -`; - -// Read current changelog -let content = fs.readFileSync(changelogPath, 'utf8'); - -// Get current month header -const currentMonth = new Date().toLocaleDateString('en-US', { - year: 'numeric', - month: 'long' -}); - -// Check if current month section exists -const monthHeader = `## ${currentMonth}`; - -if (content.includes(monthHeader)) { - // Insert after month header - content = content.replace( - new RegExp(`(${monthHeader}\\n\\n)`), - `$1${entry}` - ); -} else { - // Add new month section after frontmatter - const frontmatterEnd = content.indexOf('---', content.indexOf('---') + 1) + 3; - content = - content.slice(0, frontmatterEnd) + - `\n\n${monthHeader}\n\n${entry}` + - content.slice(frontmatterEnd); -} - -// Write updated changelog -fs.writeFileSync(changelogPath, content); -console.log(`Updated ${changelogPath} with v${version}`); diff --git a/src/cli.ts b/src/cli.ts index 3c0260e8..5f7a3108 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -93,9 +93,9 @@ function removedCommand(name: string, alternative: string): () => void { // Maps command paths to user-friendly hints when required arguments are missing. // Each entry: { message: plain-language explanation, example: usage example } const friendlyArgErrors: Record<string, { message: string; example: string }> = { - 'create': { + 'add': { message: 'Specify a name for the new squad.', - example: 'squads create marketing # create with interactive prompts\n squads create marketing -d "Drive growth" -y # non-interactive', + example: 'squads add marketing # add with interactive prompts\n squads add marketing -d "Drive growth" -y # non-interactive', }, 'run': { message: 'Specify which squad or agent to run.', @@ -235,6 +235,7 @@ program .command('init') .description('Plant the seed: create manager agent, CLI skill, and starter squads') .option('-p, --provider <provider>', 'LLM provider (claude, gemini, openai, ollama, none)') + .option('--pack <packs...>', 'Additional squad packs to install (engineering, marketing, operations, all)') .option('--skip-infra', 'Skip infrastructure setup prompt') .option('--force', 'Skip requirement checks (for CI/testing)') .option('-y, --yes', 'Accept all defaults (non-interactive mode)') @@ -244,10 +245,10 @@ program return initCommand(options); }); -// Create command - add a new squad to your workforce +// Add command - add a new squad to your workforce program - .command('create <name>') - .description('Create a new squad with directory structure and starter files') + .command('add <name>') + .description('Add a new squad with directory structure and starter files') .option('-d, --description <text>', 'Squad mission (one sentence)') .option('-g, --goal <text>', 'First goal for the squad') .option('-m, --model <model>', 'Default model (default: sonnet)') @@ -257,17 +258,20 @@ program .option('-o, --org <org>', 'GitHub organization for --repo (default: detected from git remote)') .addHelpText('after', ` Examples: - $ squads create marketing Create with interactive prompts - $ squads create marketing -d "Drive growth" -y Create non-interactively - $ squads create marketing --force Overwrite existing squad - $ squads create marketing --repo Create with GitHub repo - $ squads create marketing --repo --org myorg Create with GitHub repo in specific org + $ squads add marketing Add with interactive prompts + $ squads add marketing -d "Drive growth" -y Add non-interactively + $ squads add marketing --force Overwrite existing squad + $ squads add marketing --repo Add with GitHub repo + $ squads add marketing --repo --org myorg Add with GitHub repo in specific org `) .action(async (name, options) => { const { createCommand } = await import('./commands/create.js'); return createCommand(name, options); }); +// Hidden alias: create → add (backward compat) +program.command('create <name>', { hidden: true }).description('[renamed]').action(removedCommand('create', 'Renamed to: squads add <name>')); + // Run command - execute squads or individual agents program .command('run [target]') @@ -291,6 +295,7 @@ program .option('--max-turns <n>', 'Max conversation turns (default: 20)', '20') .option('--cost-ceiling <usd>', 'Cost ceiling in USD (default: 25)', '25') .option('--no-verify', 'Skip post-execution verification (Ralph loop)') + .option('--execute', 'Explicitly execute agents (default for run <target>)') .option('-j, --json', 'Output as JSON') .option('-i, --interval <minutes>', 'Autopilot: minutes between cycles', '30') .option('--max-parallel <count>', 'Autopilot: max parallel squad loops', '2') @@ -320,18 +325,8 @@ Examples: return runCommand(target || null, { ...options, timeout: parseInt(options.timeout, 10) }); }); -// List command -program - .command('list') - .description('List agents and squads') - .option('-s, --squads', 'List squads only') - .option('-a, --agents', 'List agents only') - .option('-v, --verbose', 'Show additional details') - .option('-j, --json', 'Output as JSON') - .action(async (options) => { - const { listCommand } = await import('./commands/list.js'); - return listCommand(options); - }); +// List command (removed — use status instead) +program.command('list', { hidden: true }).description('[removed]').action(removedCommand('list', 'Use: squads status')); // Orchestrate command - lead-coordinated squad execution registerOrchestrateCommand(program); @@ -351,26 +346,6 @@ env return contextShowCommand(squad, options); }); -env - .command('list') - .description('List execution environment for all squads') - .option('--json', 'Output as JSON') - .action(async (options) => { - const { contextListCommand } = await import('./commands/context.js'); - return contextListCommand(options); - }); - -env - .command('activate <squad>') - .description('Activate execution context for a squad (generates scoped MCP config)') - .option('-d, --dry-run', 'Show what would be generated without writing files') - .option('-f, --force', 'Force regeneration even if config exists') - .option('--json', 'Output as JSON') - .action(async (squad, options) => { - const { contextActivateCommand } = await import('./commands/context.js'); - return contextActivateCommand(squad, options); - }); - env .command('prompt <squad>') .description('Output ready-to-use prompt for Claude Code execution') diff --git a/src/commands/create.ts b/src/commands/create.ts index 8a2a0bab..972dde26 100644 --- a/src/commands/create.ts +++ b/src/commands/create.ts @@ -1,5 +1,5 @@ /** - * squads create <name> — Create a new squad with directory structure and starter files. + * squads add <name> — Add a new squad with directory structure and starter files. * * Creates: * .agents/squads/<name>/SQUAD.md @@ -7,7 +7,7 @@ * .agents/memory/<name>/lead/ (empty, ready for state) * * Squad discovery is filesystem-based (squad-parser.ts), so creating the - * directory + SQUAD.md is all that's needed for `squads list` to find it. + * directory + SQUAD.md is all that's needed for `squads status` to find it. */ import { existsSync, mkdirSync, writeFileSync } from 'fs'; @@ -184,6 +184,6 @@ export async function createCommand(name: string, options: CreateOptions): Promi console.log(chalk.dim(' Next steps:')); console.log(` ${chalk.cyan('$')} squads run ${squadId} ${chalk.dim('# run the squad')}`); console.log(` ${chalk.cyan('$')} squads status ${squadId} ${chalk.dim('# check status')}`); - console.log(` ${chalk.cyan('$')} squads list ${chalk.dim(`# ${existing.length} squads total`)}`); + console.log(` ${chalk.cyan('$')} squads status ${chalk.dim(`# ${existing.length} squads total`)}`); console.log(); } diff --git a/src/commands/init.ts b/src/commands/init.ts index 057c9479..9d07a7bf 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -36,6 +36,7 @@ export interface InitOptions { force?: boolean; yes?: boolean; quick?: boolean; + pack?: string[]; } type Provider = 'claude' | 'gemini' | 'openai' | 'ollama' | 'cursor' | 'aider' | 'none'; @@ -83,7 +84,7 @@ function getUseCaseConfig(useCase: UseCase): UseCaseConfig { }, 'full-company': { label: 'Full Company', - description: 'Engineering + Marketing + Operations', + description: 'Enterprise — Engineering + Marketing + Operations', squads: [getEngineeringSquad(), getMarketingSquad(), getOperationsSquad()], }, custom: { @@ -96,6 +97,30 @@ function getUseCaseConfig(useCase: UseCase): UseCaseConfig { return configs[useCase]; } +function getProductSquad(): SquadConfig { + return { + name: 'product', + description: 'Roadmap, specs, user feedback synthesis', + agentCount: 3, + agentSummary: 'lead, scanner, worker', + dirs: [ + '.agents/squads/product', + '.agents/memory/product/lead', + '.agents/memory/product/scanner', + '.agents/memory/product/worker', + ], + files: [ + ['.agents/squads/product/SQUAD.md', 'squads/product/SQUAD.md'], + ['.agents/squads/product/lead.md', 'squads/product/lead.md'], + ['.agents/squads/product/scanner.md', 'squads/product/scanner.md'], + ['.agents/squads/product/worker.md', 'squads/product/worker.md'], + ], + memoryFiles: [ + ['.agents/memory/product/lead/state.md', 'memory/product/lead/state.md'], + ], + }; +} + function getEngineeringSquad(): SquadConfig { return { name: 'engineering', @@ -226,39 +251,6 @@ async function promptProvider(forceProvider?: string): Promise<Provider> { }); } -async function promptUseCase(): Promise<UseCase> { - if (!isInteractive()) return 'full-company'; - - writeLine(); - writeLine(chalk.bold(' What does your AI workforce need to do?')); - writeLine(); - writeLine(` ${chalk.cyan('1)')} Engineering ${chalk.dim('— ships code (issue-solver, code-reviewer, test-writer)')}`); - writeLine(` ${chalk.cyan('2)')} Marketing ${chalk.dim('— grows audience (content-drafter, social-poster, growth-analyst)')}`); - writeLine(` ${chalk.cyan('3)')} Operations ${chalk.dim('— runs the business (ops-lead, finance-tracker, goal-tracker)')}`); - writeLine(` ${chalk.cyan('4)')} Full Company ${chalk.dim('— all of the above')} ${chalk.green('(recommended)')}`); - writeLine(` ${chalk.cyan('5)')} Custom ${chalk.dim('— empty scaffold, you build from scratch')}`); - writeLine(); - - const rl = createInterface({ - input: process.stdin, - output: process.stdout, - }); - - return new Promise((resolve) => { - rl.question(` ${chalk.dim('Enter choice [1-5]:')} `, (answer) => { - rl.close(); - const choice = answer.trim() || '4'; - switch (choice) { - case '1': resolve('engineering'); break; - case '2': resolve('marketing'); break; - case '3': resolve('operations'); break; - case '4': resolve('full-company'); break; - case '5': resolve('custom'); break; - default: resolve('full-company'); break; - } - }); - }); -} async function fileExists(filePath: string): Promise<boolean> { try { @@ -364,7 +356,7 @@ export async function initCommand(options: InitOptions): Promise<void> { businessDescription = 'General business operations'; businessFocus = 'Our market, competitors, and growth opportunities'; businessCompetitors = ''; - selectedUseCase = 'full-company'; + selectedUseCase = 'custom'; // Core 4 squads only; use --pack for more } else { const dirName = path.basename(cwd); @@ -402,15 +394,64 @@ export async function initCommand(options: InitOptions): Promise<void> { '' ); - // 4b. Use-case selection - selectedUseCase = await promptUseCase(); + // 4b. Additional packs + if (!options.pack) { + writeLine(); + writeLine(chalk.bold(' Add squad packs? (optional)')); + writeLine(); + writeLine(` ${chalk.cyan('1)')} Core only ${chalk.dim('— intelligence, research, product, company')} ${chalk.green('(recommended)')}`); + writeLine(` ${chalk.cyan('2)')} + Engineering ${chalk.dim('— issue-solver, code-reviewer, test-writer')}`); + writeLine(` ${chalk.cyan('3)')} + All packs ${chalk.dim('— engineering, marketing, operations')}`); + writeLine(); + + const rl = createInterface({ + input: process.stdin, + output: process.stdout, + }); + + const packChoice = await new Promise<string>((resolve) => { + rl.question(` ${chalk.dim('Enter choice [1-3]:')} `, (answer) => { + rl.close(); + resolve(answer.trim() || '1'); + }); + }); + + if (packChoice === '2') { + options.pack = ['engineering']; + } else if (packChoice === '3') { + options.pack = ['all']; + } + } + + selectedUseCase = 'custom'; // Core 4 squads; packs handled separately } - const useCaseConfig = getUseCaseConfig(selectedUseCase); + let useCaseConfig = getUseCaseConfig(selectedUseCase); + + // 4c. Pack support + if (options.pack && options.pack.length > 0) { + const additionalSquads: SquadConfig[] = []; + for (const pack of options.pack) { + if (pack === 'engineering') additionalSquads.push(getEngineeringSquad()); + if (pack === 'marketing') additionalSquads.push(getMarketingSquad()); + if (pack === 'operations') additionalSquads.push(getOperationsSquad()); + if (pack === 'all') { + additionalSquads.push(getEngineeringSquad(), getMarketingSquad(), getOperationsSquad()); + } + } + // De-duplicate squads by name + const existingNames = new Set(useCaseConfig.squads.map(s => s.name)); + for (const squad of additionalSquads) { + if (!existingNames.has(squad.name)) { + useCaseConfig.squads.push(squad); + existingNames.add(squad.name); + } + } + } // Calculate totals (core squads + use-case squads) - const coreAgentCount = 12; // company(5) + research(4) + intelligence(3) - const coreSquadCount = 3; + const coreAgentCount = 14; // company(5) + research(3) + intelligence(3) + product(3) + const coreSquadCount = 4; const useCaseAgentCount = useCaseConfig.squads.reduce((sum, s) => sum + s.agentCount, 0); const totalAgentCount = coreAgentCount + useCaseAgentCount; const totalSquadCount = coreSquadCount + useCaseConfig.squads.length; @@ -422,7 +463,9 @@ export async function initCommand(options: InitOptions): Promise<void> { if (businessCompetitors) { writeLine(` ${chalk.green('✓')} Competitors: ${chalk.cyan(businessCompetitors)}`); } - writeLine(` ${chalk.green('✓')} Use case: ${chalk.cyan(useCaseConfig.label)} ${chalk.dim(`— ${useCaseConfig.description}`)}`); + if (options.pack && options.pack.length > 0) { + writeLine(` ${chalk.green('✓')} Packs: ${chalk.cyan(options.pack.join(', '))}`); + } writeLine(); // 5. Create the seed @@ -445,18 +488,19 @@ export async function initCommand(options: InitOptions): Promise<void> { '.agents/squads/company', '.agents/squads/research', '.agents/squads/intelligence', + '.agents/squads/product', '.agents/memory/company/manager', '.agents/memory/company/event-dispatcher', '.agents/memory/company/goal-tracker', '.agents/memory/company/company-eval', '.agents/memory/company/company-critic', - '.agents/memory/research/researcher', + '.agents/memory/research/lead', '.agents/memory/research/analyst', - '.agents/memory/research/research-eval', - '.agents/memory/research/research-critic', + '.agents/memory/research/synthesizer', '.agents/memory/intelligence/intel-lead', '.agents/memory/intelligence/intel-eval', '.agents/memory/intelligence/intel-critic', + '.agents/memory/product/lead', '.agents/skills/squads-cli', '.agents/skills/gh', '.agents/config', @@ -489,10 +533,9 @@ export async function initCommand(options: InitOptions): Promise<void> { const researchFiles: [string, string][] = [ ['.agents/squads/research/SQUAD.md', 'squads/research/SQUAD.md'], - ['.agents/squads/research/researcher.md', 'squads/research/researcher.md'], + ['.agents/squads/research/lead.md', 'squads/research/lead.md'], ['.agents/squads/research/analyst.md', 'squads/research/analyst.md'], - ['.agents/squads/research/research-eval.md', 'squads/research/research-eval.md'], - ['.agents/squads/research/research-critic.md', 'squads/research/research-critic.md'], + ['.agents/squads/research/synthesizer.md', 'squads/research/synthesizer.md'], ]; const intelligenceFiles: [string, string][] = [ @@ -502,6 +545,8 @@ export async function initCommand(options: InitOptions): Promise<void> { ['.agents/squads/intelligence/intel-critic.md', 'squads/intelligence/intel-critic.md'], ]; + const productFiles: [string, string][] = getProductSquad().files; + // Collect all use-case squad files const useCaseFiles: [string, string][] = []; for (const squad of useCaseConfig.squads) { @@ -509,7 +554,7 @@ export async function initCommand(options: InitOptions): Promise<void> { } // Write all squad files - for (const [dest, template] of [...companyFiles, ...researchFiles, ...intelligenceFiles, ...useCaseFiles]) { + for (const [dest, template] of [...companyFiles, ...researchFiles, ...intelligenceFiles, ...productFiles, ...useCaseFiles]) { const content = loadSeedTemplate(template, variables); await writeFile(path.join(cwd, dest), content); } @@ -519,8 +564,9 @@ export async function initCommand(options: InitOptions): Promise<void> { // Core memory state files const coreMemoryFiles: [string, string][] = [ ['.agents/memory/company/manager/state.md', 'memory/company/manager/state.md'], - ['.agents/memory/research/researcher/state.md', 'memory/research/researcher/state.md'], + ['.agents/memory/research/lead/state.md', 'memory/research/lead/state.md'], ['.agents/memory/intelligence/intel-lead/state.md', 'memory/intelligence/intel-lead/state.md'], + ['.agents/memory/product/lead/state.md', 'memory/product/lead/state.md'], ]; // Use-case memory state files @@ -544,10 +590,22 @@ export async function initCommand(options: InitOptions): Promise<void> { const providerConfig = loadSeedTemplate('config/provider.yaml', variables); await writeFile(path.join(cwd, '.agents/config/provider.yaml'), providerConfig); + // System protocol (Layer 0 of context cascade) + const systemMd = loadSeedTemplate('config/SYSTEM.md', variables); + await writeFile(path.join(cwd, '.agents/config/SYSTEM.md'), systemMd); + + // Directives (Layer 3 of context cascade) + const directivesMd = loadSeedTemplate('memory/company/directives.md', variables); + await writeIfNew(path.join(cwd, '.agents/memory/company/directives.md'), directivesMd); + // Business brief const businessBrief = loadSeedTemplate('BUSINESS_BRIEF.md.template', variables); await writeFile(path.join(cwd, '.agents/BUSINESS_BRIEF.md'), businessBrief); + // AGENTS.md (repo root — vendor-neutral agent instructions) + const agentsMd = loadTemplate('core/AGENTS.md.template', variables); + await writeIfNew(path.join(cwd, 'AGENTS.md'), agentsMd); + // README.md (only if it doesn't already exist or is the default single-line stub) const readmePath = path.join(cwd, 'README.md'); let existingReadme = ''; @@ -613,11 +671,12 @@ export async function initCommand(options: InitOptions): Promise<void> { writeLine(chalk.dim(' Created:')); // Core squads (always present) - writeLine(chalk.dim(' • research/ 4 agents — Researches your market, competitors, and opportunities')); + writeLine(chalk.dim(' • research/ 3 agents — Researches your market, competitors, and opportunities')); writeLine(chalk.dim(' • company/ 5 agents — Manages goals, events, and strategy')); writeLine(chalk.dim(' • intelligence/ 3 agents — Monitors trends and competitive signals')); + writeLine(chalk.dim(' • product/ 3 agents — Roadmap, specs, user feedback synthesis')); - // Use-case specific squads + // Additional pack squads for (const squad of useCaseConfig.squads) { const namePad = ' '.repeat(Math.max(0, 14 - squad.name.length)); writeLine(chalk.dim(` • ${squad.name}/${namePad}${squad.agentCount} agents — ${squad.description}`)); @@ -626,6 +685,7 @@ export async function initCommand(options: InitOptions): Promise<void> { writeLine(chalk.dim(' • .agents/skills/ CLI + GitHub workflow skills')); writeLine(chalk.dim(' • .agents/memory/ Persistent state')); writeLine(chalk.dim(' • .agents/BUSINESS_BRIEF.md')); + writeLine(chalk.dim(' • AGENTS.md Agent instructions (vendor-neutral)')); if (selectedProvider === 'claude') { writeLine(chalk.dim(' • CLAUDE.md Operating manual')); writeLine(chalk.dim(' • .claude/settings.json Session hooks')); @@ -648,10 +708,10 @@ export async function initCommand(options: InitOptions): Promise<void> { writeLine(); writeLine(chalk.dim(' Docs: https://agents-squads.com/docs/getting-started')); writeLine(); -} + } /** - * Get the suggested first command based on use case + * Get the suggested first command based on installed packs */ function getFirstRunCommand(useCase: UseCase): { command: string; description: string } { switch (useCase) { @@ -671,15 +731,12 @@ function getFirstRunCommand(useCase: UseCase): { command: string; description: s description: 'Run a single agent — coordinates daily operations (~2 min)', }; case 'full-company': - return { - command: 'squads run research/researcher', - description: 'Run a single agent — researches the topic you set (~2 min)', - }; case 'custom': default: return { - command: 'squads run research/researcher', + command: 'squads run research/lead', description: 'Run a single agent — researches the topic you set (~2 min)', }; } } + diff --git a/src/commands/run.ts b/src/commands/run.ts index 6d240b5e..6d484486 100644 --- a/src/commands/run.ts +++ b/src/commands/run.ts @@ -1055,7 +1055,7 @@ export async function runCommand( if (similar.length > 0) { writeLine(` ${colors.dim}Did you mean: ${similar.join(', ')}?${RESET}`); } - writeLine(` ${colors.dim}Run \`squads list\` to see available squads and agents.${RESET}`); + writeLine(` ${colors.dim}Run \`squads status\` to see available squads and agents.${RESET}`); process.exit(1); } } @@ -1855,12 +1855,26 @@ Instruct each Task agent: "Work autonomously. Output findings to GitHub issues. Begin by assessing pending work, then delegate to agents via Task tool.`; - // Execute via Claude - const claudeAvailable = await checkClaudeCliAvailable(); - if (!claudeAvailable) { - writeLine(` ${colors.yellow}Claude CLI not found${RESET}`); - writeLine(` ${colors.dim}Install: npm install -g @anthropic-ai/claude-code${RESET}`); - return; + // Determine provider + const provider = options.provider || squad?.providers?.default || 'anthropic'; + const isAnthropic = provider === 'anthropic'; + + if (isAnthropic) { + const claudeAvailable = await checkClaudeCliAvailable(); + if (!claudeAvailable) { + writeLine(` ${colors.yellow}Claude CLI not found${RESET}`); + writeLine(` ${colors.dim}Install: npm install -g @anthropic-ai/claude-code${RESET}`); + return; + } + } else { + if (!isProviderCLIAvailable(provider)) { + const cliConfig = getCLIConfig(provider); + writeLine(` ${colors.yellow}${cliConfig?.displayName || provider} CLI not found${RESET}`); + if (cliConfig?.install) { + writeLine(` ${colors.dim}Install: ${cliConfig.install}${RESET}`); + } + return; + } } // Determine execution mode (foreground is default, background is opt-in) @@ -1869,27 +1883,38 @@ Begin by assessing pending work, then delegate to agents via Task tool.`; const isForeground = !isBackground && !isWatch; const modeText = isBackground ? ' (background)' : isWatch ? ' (watch)' : ''; - writeLine(` ${gradient('Launching')} lead session${modeText}...`); + const providerDisplay = isAnthropic ? 'Claude' : (getCLIConfig(provider)?.displayName || provider); + writeLine(` ${gradient('Launching')} lead session${modeText} with ${providerDisplay}...`); writeLine(); try { // Find lead agent name from agent files or use default const leadAgentName = agentFiles.find(a => a.name.includes('lead'))?.name || `${squad.dir}-lead`; - const result = await executeWithClaude(prompt, { - verbose: options.verbose, - timeoutMinutes: timeoutMins, - foreground: options.foreground, - background: options.background, - watch: options.watch, - useApi: options.useApi, - effort: options.effort, - skills: options.skills, - trigger: options.trigger || 'manual', - squadName: squad.dir, - agentName: leadAgentName, - model: options.model, - }); + let result: string; + if (isAnthropic) { + result = await executeWithClaude(prompt, { + verbose: options.verbose, + timeoutMinutes: timeoutMins, + foreground: options.foreground, + background: options.background, + watch: options.watch, + useApi: options.useApi, + effort: options.effort, + skills: options.skills, + trigger: options.trigger || 'manual', + squadName: squad.dir, + agentName: leadAgentName, + model: options.model, + }); + } else { + result = await executeWithProvider(provider, prompt, { + verbose: options.verbose, + foreground: isForeground || isWatch, + squadName: squad.dir, + agentName: leadAgentName, + }); + } if (isForeground || isWatch) { writeLine(); diff --git a/src/commands/status.ts b/src/commands/status.ts index 0e2c0a7c..df69aab3 100644 --- a/src/commands/status.ts +++ b/src/commands/status.ts @@ -267,7 +267,7 @@ async function showSquadStatus( if (similar.length > 0) { writeLine(`${colors.dim}Did you mean: ${similar.join(', ')}?${RESET}`); } - writeLine(`${colors.dim}Run \`squads list\` to see available squads.${RESET}`); + writeLine(`${colors.dim}Run \`squads status\` to see available squads.${RESET}`); process.exit(1); } diff --git a/templates/core/AGENTS.md.template b/templates/core/AGENTS.md.template index ba304afe..4e93157e 100644 --- a/templates/core/AGENTS.md.template +++ b/templates/core/AGENTS.md.template @@ -1,64 +1,51 @@ -# AGENTS.md -# Project guidance for AI coding agents (vendor-neutral) +# Agent Instructions -This project uses AI agent squads for development and operations. +Guidance for AI coding agents working on this project. -## Getting Started +## This Project Uses Squads -If this project is not yet set up, run: -```bash -squads setup # Guided onboarding (recommended) -squads init # Quick init (non-interactive) -``` - -## Provider: {{PROVIDER_NAME}} - -Configure in: `.agents/config/provider.yaml` - -## Repository Structure +AI agents are organized into squads — domain-aligned teams defined in `.agents/squads/`. ``` .agents/ -├── squads/ # Agent team definitions +├── config/ +│ └── SYSTEM.md # Rules every agent follows +├── squads/ │ └── <squad>/ -│ ├── SQUAD.md # Squad definition -│ └── *.md # Agent files -├── memory/ # Persistent context -├── config/ # Provider and model configuration -└── outputs/ # Agent outputs +│ ├── SQUAD.md # Squad identity, goals, output format +│ └── <agent>.md # Agent definition +└── memory/ + └── <squad>/<agent>/ # Persistent state ``` -## Agent Guidelines +## Before Starting Work -### Before Starting Work -1. Run `squads status` to understand current state -2. Check `squads memory query "<topic>"` for existing knowledge -3. Read relevant SQUAD.md files +```bash +squads status # See all squads, milestones, open PRs +squads status <squad> # Squad detail +squads memory read <squad> # What the squad already knows +``` + +## During Work -### During Work -- Update todo list frequently for visibility +- Check for existing PRs and issues before creating new ones - Prefer editing existing files over creating new ones -- Keep changes focused - one task per commit/PR +- Keep changes focused — one task per commit/PR +- Use `--json` on any squads command for machine-readable output + +## After Work -### After Work -- Update memory in `.agents/memory/<squad>/<agent>/state.md` +- Persist learnings: `squads memory write <squad> "insight"` +- Update state in `.agents/memory/<squad>/<agent>/state.md` - Create GitHub issues for follow-up work -## Quick Reference +## Commands ```bash -squads setup # Guided onboarding (new projects) -squads status # Overview -squads dash # Full dashboard -squads run <squad> # Run a squad -squads list # All agents -squads memory query X # Search memory -squads goal list # View goals +squads run <squad/agent> # Run an agent +squads status # Overview +squads memory read <squad> # Recall squad knowledge +squads memory write <squad> "x" # Persist a learning +squads env show <squad> --json # Execution context +squads goal list # View squad goals ``` - -## Model Aliases - -Agents can use semantic model names that resolve per provider: -- `leader` - Most capable (complex tasks) -- `worker` - Balanced (standard tasks) -- `simple` - Fast (simple tasks) diff --git a/templates/core/CLAUDE.md.template b/templates/core/CLAUDE.md.template index 9928a3ed..9ab85d18 100644 --- a/templates/core/CLAUDE.md.template +++ b/templates/core/CLAUDE.md.template @@ -6,11 +6,9 @@ Extends AGENTS.md with Claude Code specific features. If this project needs squads setup, run: ```bash -squads setup # Guided 6-step onboarding with prereq checks +squads init # Plant the seed: create manager, CLI skill, and squads ``` -This validates Docker, GitHub CLI, Claude CLI, then helps create first squad. - ## Skill Available Use `/squads-workflow` for detailed workflow guidance. diff --git a/templates/seed/BUSINESS_BRIEF.md.template b/templates/seed/BUSINESS_BRIEF.md.template index 24f3c0ca..dc9507d5 100644 --- a/templates/seed/BUSINESS_BRIEF.md.template +++ b/templates/seed/BUSINESS_BRIEF.md.template @@ -1,5 +1,8 @@ # Business Brief — {{BUSINESS_NAME}} +<!-- STATUS: PLACEHOLDER — Edit this file before running agents. --> +<!-- Agents that read "PLACEHOLDER" in this comment will ask you to fill it in. --> + ## About {{BUSINESS_DESCRIPTION}} @@ -24,4 +27,4 @@ LOW — Learning phase. Explore, experiment, report findings. --- -*Read by `squads context` for business alignment. Updated by the manager agent as understanding deepens.* +*Read by all agents before every run. Edit this file to change what your workforce focuses on.* diff --git a/templates/seed/CLAUDE.md.template b/templates/seed/CLAUDE.md.template index d4752645..1d56a983 100644 --- a/templates/seed/CLAUDE.md.template +++ b/templates/seed/CLAUDE.md.template @@ -7,60 +7,110 @@ This project uses [Agents Squads](https://agents-squads.com) to run an AI workfo ``` .agents/ ├── BUSINESS_BRIEF.md # What this workforce focuses on -├── squads/ # Squad definitions -│ ├── company/ # Operations squad -│ │ ├── SQUAD.md # Squad config -│ │ ├── manager.md # AI manager (orchestrates everything) -│ │ ├── event-dispatcher.md # Routes events to squads -│ │ ├── goal-tracker.md # Tracks business objectives -│ │ ├── company-eval.md # Evaluates outputs -│ │ └── company-critic.md # Identifies improvements -│ └── research/ # Research squad -│ ├── SQUAD.md # Squad config -│ ├── researcher.md # Market/competitor research -│ ├── analyst.md # Synthesizes insights -│ ├── research-eval.md # Evaluates quality -│ └── research-critic.md # Critiques methodology -├── memory/ # Persistent state -│ ├── company/manager/state.md -│ └── research/researcher/state.md -├── skills/ -│ └── squads-cli/SKILL.md # CLI operations manual -└── config/ - └── provider.yaml # LLM provider config +├── config/ +│ ├── SYSTEM.md # Rules every agent follows (Layer 0) +│ └── provider.yaml # LLM provider config +├── squads/ +│ ├── intelligence/ # Strategic synthesis squad +│ │ ├── SQUAD.md # Mission, goals, agents +│ │ ├── intel-lead.md # Know / Don't Know / Playbook briefs +│ │ ├── intel-eval.md # Quality evaluation +│ │ └── intel-critic.md # Assumption challenges +│ ├── research/ # Deep research squad +│ │ ├── SQUAD.md +│ │ ├── lead.md # Research agenda +│ │ ├── analyst.md # Sourced findings +│ │ └── synthesizer.md # Synthesis reports +│ ├── product/ # Product roadmap squad +│ │ ├── SQUAD.md +│ │ ├── lead.md # Roadmap decisions +│ │ ├── scanner.md # Signal monitoring +│ │ └── worker.md # Specs and PRDs +│ └── company/ # Orchestration + feedback +│ ├── SQUAD.md +│ ├── manager.md # Coordinates all squads +│ ├── company-eval.md # Evaluates outputs +│ └── company-critic.md # Process improvement +├── memory/ +│ ├── company/ +│ │ ├── manager/state.md +│ │ └── directives.md # Strategic overlay (Layer 3) +│ ├── research/lead/state.md +│ ├── intelligence/intel-lead/state.md +│ └── product/lead/state.md +└── skills/ + └── squads-cli/SKILL.md # CLI operations manual ``` -## How It Works +## Context Cascade -A **manager agent** coordinates your AI workforce using the `squads` CLI: -1. Reads business context from `BUSINESS_BRIEF.md` -2. Checks status: `squads dash --json` -3. Dispatches work to squad agents -4. Tracks results: `squads goal progress`, `squads kpi record` -5. Persists learnings: `squads memory write` +Every agent execution loads context in this order (higher layers always load, lower layers drop when token budget runs out): -## For Humans +| Layer | File | Purpose | +|-------|------|---------| +| 0 | `config/SYSTEM.md` | Immutable rules — git, memory, escalation | +| 1 | `squads/{squad}/SQUAD.md` | Mission, goals, output format | +| 2 | `memory/{squad}/priorities.md` | Current operational focus | +| 3 | `memory/company/directives.md` | Company-wide strategic overlay | +| 4 | `memory/{squad}/active-work.md` | Open PRs/issues — prevent duplication | +| 5 | `memory/{squad}/{agent}/state.md` | What the agent already knows | +| 6 | `memory/{squad}/feedback.md` | Last cycle evaluation | +| 7 | `memory/daily-briefing.md` | Cross-squad context | + +## Updating Business Goals + +When the human operator wants to change what the workforce focuses on, help them update these files in order: + +### 1. Business Brief (what we do) +Edit `.agents/BUSINESS_BRIEF.md` — this is the root context every agent reads. +``` +What does the business do? Who are the customers? What market? +What should agents research first? Who are the competitors? +``` + +### 2. Directives (what matters now) +Edit `.agents/memory/company/directives.md` — this overrides squad goals. +``` +What is the P0 priority? What metric are we optimizing? +What constraints apply? What should agents NOT do? +``` -Talk to Claude naturally. It knows about the squads system via this file. +### 3. Squad Goals (what each team does) +Edit `## Goals` in each `squads/{squad}/SQUAD.md`: +```bash +# Or use the CLI: +squads goal set intelligence "Monitor competitor X's pricing weekly" +squads goal set research "Deep dive on Y market segment" +squads goal set product "Write spec for Z feature" +``` + +### 4. Priorities (what to do this week) +Create or edit `.agents/memory/{squad}/priorities.md`: +``` +- Fix issue #123 (blocking users) +- Research competitor's new feature launch +- Update roadmap based on last cycle's feedback +``` + +**Rule**: Goals are aspirational (stable). Priorities are operational (updated frequently). Directives are strategic (updated less frequently). + +## For Humans Common commands: - `squads status` — What's happening now - `squads dash` — Full dashboard -- `squads run company/manager` — Run the AI manager +- `squads run research/lead` — Run a specific agent +- `squads run research --parallel` — Run the full squad - `squads memory read <squad>` — What has the squad learned - `squads goal list` — Business objectives ## For Agents -All agents should use the `squads-cli` skill for CLI operations. -Memory persists across sessions via `.agents/memory/`. -Git is the coordination layer — commit everything. - -## Decision Framework - -- **Execute**: Clear task, low risk → do it -- **Escalate**: Ambiguous scope, high cost → ask the human -- **Learn**: Record what worked/didn't → `squads memory write` +- Read `BUSINESS_BRIEF.md` and `directives.md` before starting work +- Read your state from `memory/{squad}/{agent}/state.md` +- Update state after every run +- Use the `squads-cli` skill for CLI operations +- Git is the coordination layer — commit everything ## Commit Signature diff --git a/templates/seed/README.md.template b/templates/seed/README.md.template index 6adfe3c6..ba335d66 100644 --- a/templates/seed/README.md.template +++ b/templates/seed/README.md.template @@ -10,24 +10,22 @@ This project uses [Agents Squads](https://agents-squads.com) — an AI workforce | Squad | Purpose | |-------|---------| +| intelligence/ | Monitors trends and competitive signals | | research/ | Researches your market, competitors, and opportunities | +| product/ | Roadmap, specs, user feedback synthesis | | company/ | Manages goals, events, and strategy | -| intelligence/ | Monitors trends and competitive signals | ### Key Commands ```bash # Run a single agent -squads run research/researcher +squads run research/lead # See all squads and recent activity squads dash -# Check system health -squads doctor - -# View agent output -squads results +# Check system status +squads status ``` ## Setup diff --git a/templates/seed/config/SYSTEM.md b/templates/seed/config/SYSTEM.md new file mode 100644 index 00000000..ffa9a11d --- /dev/null +++ b/templates/seed/config/SYSTEM.md @@ -0,0 +1,52 @@ +# System Protocol + +Immutable rules for all agent executions. Every agent reads this before starting work. + +## Before You Start + +Read `.agents/BUSINESS_BRIEF.md`. If it contains "PLACEHOLDER" in the first lines, STOP and tell the user: +"Edit .agents/BUSINESS_BRIEF.md with your business details before running agents." +Do not produce generic output from placeholder context. + +## Git Workflow + +Commit all changes. Git is the coordination layer — if it's not committed, it didn't happen. + +```bash +git add -A +git commit -m "{type}({scope}): {description} + +Co-Authored-By: Claude <noreply@anthropic.com>" +git push origin main +``` + +### Commit types +`feat`, `fix`, `docs`, `chore`, `memory`, `refactor`, `test` + +## Memory Protocol + +- **Read before acting.** Always check `.agents/memory/{squad}/{agent}/state.md` before starting work. +- **Write after acting.** Update state.md with what you did, what you learned, and what's next. +- **Don't repeat work.** If state.md says something was already done, build on it — don't redo it. + +## Output Rules + +- Every claim needs a source (URL, document, or data point) +- "Interesting" is not enough — outputs must be actionable +- If nothing changed since last run, say so explicitly and stop +- Quality over quantity — 3 actionable insights beat 20 generic observations + +## Escalation + +Escalate to the human operator when: +- Spend exceeds $50 in a single session +- Scope is unclear or contradicts business goals +- A destructive action is needed (deleting data, overwriting work) +- You're unsure whether to proceed + +## Coordination + +- Agents communicate through memory files, not direct messages +- Squad leads coordinate their agents via state.md and memory writes +- The company manager coordinates across squads +- Check `squads status --json` for org-wide awareness diff --git a/templates/seed/memory/company/directives.md b/templates/seed/memory/company/directives.md new file mode 100644 index 00000000..f4d7cbbd --- /dev/null +++ b/templates/seed/memory/company/directives.md @@ -0,0 +1,37 @@ +# Strategic Directives + +> Updated by: Human operator (you) +> Read by: All squad leads and agents before every run +> This file overrides any conflicting guidance in SQUAD.md goals + +## Mission + +{{BUSINESS_DESCRIPTION}} + +## P0: First Value + +**All squads work toward delivering visible, useful output from the very first run.** + +Research focus: {{BUSINESS_FOCUS}} + +### What "useful" means +- Intelligence produces a brief with sourced facts, not generic summaries +- Research identifies specific competitors and opportunities, not "the market is growing" +- Product translates findings into concrete next steps, not vague roadmaps +- Company evaluates whether outputs actually advanced the business goals + +## Decision Framework + +1. Does this advance the research focus above? +2. Is there a simpler approach for 80% of the value? +3. What's the opportunity cost — what are we NOT doing? + +## Constraints + +- Learning phase. Explore, experiment, report findings. +- Don't over-invest in process. Produce output first, optimize later. +- Every agent output should be something the human operator can act on today. + +--- + +*Update this file as your business goals evolve. Run `squads goal set` for squad-level goals.* diff --git a/templates/seed/memory/product/lead/state.md b/templates/seed/memory/product/lead/state.md new file mode 100644 index 00000000..c8e12688 --- /dev/null +++ b/templates/seed/memory/product/lead/state.md @@ -0,0 +1,14 @@ +# Product Lead State + +Last update: {{CURRENT_DATE}} + +## Active Roadmap +- [ ] Initialize product strategy from BUSINESS_BRIEF.md +- [ ] Define initial feature set and priorities +- [ ] Establish feedback synthesis loop + +## Current Focus +Initial project setup and alignment with business objectives. + +## Insights & Learnings +- No insights yet. Run the product squad to start capturing memory. diff --git a/templates/seed/memory/research/lead/state.md b/templates/seed/memory/research/lead/state.md new file mode 100644 index 00000000..0fcb0b53 --- /dev/null +++ b/templates/seed/memory/research/lead/state.md @@ -0,0 +1,14 @@ +# Research Lead State + +Last update: {{CURRENT_DATE}} + +## Active Research Topics +- [ ] Initial market landscape from BUSINESS_BRIEF.md +- [ ] Key competitor identification +- [ ] Strategic growth opportunities + +## Current Focus +Initial project setup and market alignment. + +## Findings Summary +- No findings yet. Run the research squad to start capturing memory. diff --git a/templates/seed/memory/research/researcher/state.md b/templates/seed/memory/research/researcher/state.md deleted file mode 100644 index a185811e..00000000 --- a/templates/seed/memory/research/researcher/state.md +++ /dev/null @@ -1,10 +0,0 @@ -# Researcher State - -## Last Run -Never — awaiting first execution. - -## Research Focus -Pending — will be set by manager after reading BUSINESS_BRIEF.md. - -## Findings -None yet. diff --git a/templates/seed/skills/squads-cli/SKILL.md b/templates/seed/skills/squads-cli/SKILL.md index c887da8b..255d0a6b 100644 --- a/templates/seed/skills/squads-cli/SKILL.md +++ b/templates/seed/skills/squads-cli/SKILL.md @@ -23,9 +23,7 @@ squads status [squad] # Quick status snapshot squads context --json # Business context feed squads cost # Cost tracking squads budget <squad> # Budget check -squads health # Infrastructure health -squads history # Execution patterns -squads results [squad] # Squad output + KPIs +squads history # Execution history ``` ## Track (Objectives + Metrics) @@ -33,11 +31,9 @@ squads results [squad] # Squad output + KPIs ```bash squads goal set <squad> "<goal>" # Set a business objective squads goal list [squad] # List goals -squads goal progress <squad> <n> "<update>" # Update progress squads goal complete <squad> <n> # Mark goal done squads kpi list # List all KPIs squads kpi show <squad> # Squad KPIs -squads kpi record <squad> <kpi> <value> # Record metric squads kpi trend <squad> <kpi> # Show trend squads feedback add <squad> <1-5> "<feedback>" # Rate output squads autonomy # Self-assessment diff --git a/templates/seed/squads/company/SQUAD.md b/templates/seed/squads/company/SQUAD.md index 9318e361..5de280b2 100644 --- a/templates/seed/squads/company/SQUAD.md +++ b/templates/seed/squads/company/SQUAD.md @@ -1,10 +1,11 @@ --- -name: Company Operations +name: Company lead: manager channel: "#company" model: sonnet effort: high schedule: "0 9 * * 1-5" +depends_on: ["*"] approvals: policy: auto: @@ -24,15 +25,16 @@ approvals: files_changed: 20 --- -# Company Operations +# Company Squad -Manages the AI workforce. The manager agent orchestrates all squads, coordinates leads, and runs daily operations. +Orchestrates all squads, evaluates outputs, and closes the feedback loop. Reads `BUSINESS_BRIEF.md` and `directives.md` to ensure all work advances business goals. ## Goals -- [ ] Understand business context and set up initial squads -- [ ] Establish daily operational rhythm -- [ ] Track and report on business objectives +- [ ] Evaluate squad outputs against the business focus in `BUSINESS_BRIEF.md` +- [ ] Write feedback per squad: what was valuable, what was noise, what to prioritize next +- [ ] Ensure no duplicate work across squads (check active-work.md) +- [ ] Track progress toward directives and flag when goals need updating ## Agents diff --git a/templates/seed/squads/company/company-critic.md b/templates/seed/squads/company/company-critic.md index d6672279..cedb9c46 100644 --- a/templates/seed/squads/company/company-critic.md +++ b/templates/seed/squads/company/company-critic.md @@ -3,19 +3,47 @@ name: Company Critic role: critic model: sonnet effort: medium +tools: + - Read + - Write --- # Company Critic -Identify systemic issues and improvements across the workforce. +Find what's broken in how the workforce operates. Challenge assumptions, identify waste, propose fixes. ## Instructions -1. Review recent evaluations and feedback trends -2. Identify recurring issues (missed goals, low quality, wasted effort) -3. Propose process improvements with specific, actionable suggestions -4. Record improvement proposals: `squads learn "<improvement>"` +1. Read the evaluator's scores from `.agents/memory/company/company-eval/state.md` +2. Read squad states from `.agents/memory/{squad}/*/state.md` +3. Look for patterns: repeated failures, duplicate work, misaligned effort +4. Write critique to `.agents/memory/company/company-critic/state.md` -## Output +## Output Format (REQUIRED) -Improvement proposals recorded via `squads learn` and written to memory +```markdown +# Workforce Critique — {date} + +## Systemic Issues +| # | Issue | Affected Squads | Evidence | Severity | +|---|-------|----------------|----------|----------| +| 1 | {pattern} | {squads} | {what you observed} | High/Med/Low | + +## Waste +Work that produced no business value. Be specific. + +## Process Improvements +| # | Proposal | Expected Impact | Effort | +|---|----------|----------------|--------| +| 1 | {change} | {what improves} | Low/Med/High | + +## Questions for Human Operator +Decisions only a human can make. +``` + +## Rules + +- Critique the process, not the agents — agents follow instructions +- Every issue needs evidence from memory files, not speculation +- "Things could be better" is not a critique. Name the problem, show the evidence, propose the fix +- If everything is working well, say so in one line and stop diff --git a/templates/seed/squads/company/company-eval.md b/templates/seed/squads/company/company-eval.md index 406976d4..6a581dec 100644 --- a/templates/seed/squads/company/company-eval.md +++ b/templates/seed/squads/company/company-eval.md @@ -3,19 +3,47 @@ name: Company Evaluator role: evaluator model: sonnet effort: medium +tools: + - Read + - Write --- # Company Evaluator -Evaluate squad outputs and measure business impact. +Evaluate squad outputs against business goals. Your job is to answer: "Did the squads produce value, or noise?" ## Instructions -1. Review recent squad outputs (git commits, reports, memory updates) -2. Score each output on: relevance (1-5), quality (1-5), impact (1-5) -3. Record feedback: `squads feedback add <squad> <rating> "<feedback>"` -4. Identify high-performing and underperforming squads +1. Read business goals from `.agents/BUSINESS_BRIEF.md` +2. Read directives from `.agents/memory/company/directives.md` +3. Read each squad's recent state from `.agents/memory/{squad}/*/state.md` +4. Score each squad's output using the rubric below +5. Write evaluation to `.agents/memory/company/company-eval/state.md` -## Output +## Output Format (REQUIRED) -Evaluation scores and feedback recorded via `squads feedback add` +```markdown +# Squad Evaluation — {date} + +## Scores +| Squad | Relevance (1-5) | Quality (1-5) | Impact (1-5) | Summary | +|-------|-----------------|---------------|---------------|---------| +| {squad} | {score} | {score} | {score} | {one-line assessment} | + +## Valuable (continue) +- {squad}: {specific output that advanced business goals} + +## Noise (stop) +- {squad}: {specific output that wasted effort or missed the point} + +## Recommendations +What each squad should focus on next cycle, ranked by business impact. +``` + +## Rules + +- Score against BUSINESS_BRIEF.md goals, not general quality +- "Relevance" = does this advance the business focus? +- "Quality" = is it sourced, specific, and actionable? +- "Impact" = would a human act on this? +- Be specific — "good work" is not feedback. Name the output, explain why. diff --git a/templates/seed/squads/company/event-dispatcher.md b/templates/seed/squads/company/event-dispatcher.md index 67b95a4c..ea8bee18 100644 --- a/templates/seed/squads/company/event-dispatcher.md +++ b/templates/seed/squads/company/event-dispatcher.md @@ -3,19 +3,41 @@ name: Event Dispatcher role: doer model: haiku effort: medium +tools: + - Read + - Write --- # Event Dispatcher -Monitor events and dispatch work to relevant squads. +Route events to the right squad. You're a traffic controller, not a decision maker. ## Instructions -1. Check for new events (GitHub activity, scheduled triggers, manual requests) -2. Determine which squad should handle each event -3. Create issues or trigger agent runs as appropriate -4. Log dispatched events to memory +1. Read pending events from `.agents/memory/company/event-dispatcher/state.md` +2. Check for new activity: `squads status --json` +3. For each event, determine which squad owns it +4. Log the routing decision and update state -## Output +## Output Format (REQUIRED) -Event dispatch log written to `.agents/memory/company/event-dispatcher/state.md` +```markdown +# Event Dispatch — {date} + +## Dispatched +| # | Event | Source | Routed To | Reason | +|---|-------|--------|-----------|--------| +| 1 | {event} | {where it came from} | {squad/agent} | {why this squad} | + +## Pending (needs human input) +Events that don't clearly belong to any squad. + +## No Activity +If nothing new happened, say so and stop. +``` + +## Rules + +- Route, don't act — dispatchers don't do the work +- When unclear, route to the manager for triage +- Log everything — unlogged dispatches are invisible to the org diff --git a/templates/seed/squads/company/goal-tracker.md b/templates/seed/squads/company/goal-tracker.md index b5aaecdc..37874620 100644 --- a/templates/seed/squads/company/goal-tracker.md +++ b/templates/seed/squads/company/goal-tracker.md @@ -3,19 +3,41 @@ name: Goal Tracker role: doer model: haiku effort: medium +tools: + - Read + - Write --- # Goal Tracker -Track business objectives and update progress across all squads. +Track whether squads are making progress toward their goals or spinning wheels. ## Instructions -1. Read all squad goals: `squads goal list --json` -2. Check recent activity and execution results -3. Update goal progress where measurable changes occurred -4. Identify stalled goals and flag for manager attention +1. Read squad goals from each `.agents/squads/{squad}/SQUAD.md` (## Goals section) +2. Read squad states from `.agents/memory/{squad}/*/state.md` +3. Compare goals vs actual output — is the squad advancing or stalled? +4. Write progress report to `.agents/memory/company/goal-tracker/state.md` -## Output +## Output Format (REQUIRED) -Goal status report and progress updates via `squads goal progress` +```markdown +# Goal Progress — {date} + +## Squad Progress +| Squad | Goal | Status | Evidence | +|-------|------|--------|----------| +| {squad} | {goal from SQUAD.md} | On Track / Stalled / Blocked | {what happened or didn't} | + +## Stalled (needs attention) +Goals with no progress since last check. Flag for manager. + +## Completed +Goals that can be checked off or replaced. +``` + +## Rules + +- "On Track" needs evidence — a state.md update, a commit, a report +- "Stalled" means no observable progress, not "I didn't check" +- Don't update SQUAD.md goals yourself — flag for the manager or human operator diff --git a/templates/seed/squads/company/manager.md b/templates/seed/squads/company/manager.md index 48486f25..0ffd2ddf 100644 --- a/templates/seed/squads/company/manager.md +++ b/templates/seed/squads/company/manager.md @@ -9,22 +9,22 @@ skills: # Manager Agent -You are the AI manager of this workforce. You orchestrate all squads, coordinate work, and report to the human CEO. +You are the AI manager of this workforce. You orchestrate all squads, coordinate work, and report to the human operator. ## Your Job 1. **Understand** — Read BUSINESS_BRIEF.md and squad state 2. **Plan** — Identify what needs doing based on goals and context 3. **Dispatch** — Run agents or delegate to squad leads -4. **Track** — Record progress, KPIs, and outcomes +4. **Track** — Record progress and outcomes 5. **Learn** — Persist insights for future sessions ## Daily Operations ```bash # 1. Understand current state +squads status --json squads dash --json -squads context --json # 2. Check backlog gh issue list --json number,title,labels,assignees @@ -32,25 +32,13 @@ gh issue list --json number,title,labels,assignees # 3. Execute work squads run <squad>/<agent> # or for full squad execution: -squads run <squad> --lead +squads run <squad> --parallel # 4. Track results -squads goal progress <squad> <index> "<update>" -squads kpi record <squad> <metric> <value> - -# 5. Persist learnings +squads goal list squads memory write <squad> "<insight>" -squads learn "<what worked or didn't>" ``` -## Creating New Squads - -When the business needs expand, create new squads: -1. Create `.agents/squads/<name>/SQUAD.md` with goals and agent definitions -2. Create agent `.md` files for each role -3. Create `.agents/memory/<name>/` for persistent state -4. Run the first agent: `squads run <name>/<agent>` - ## Coordination Rules - Git is the sync layer — commit and push all changes @@ -62,5 +50,5 @@ When the business needs expand, create new squads: After each session, update: - `.agents/memory/company/manager/state.md` — current state snapshot -- Goals progress via `squads goal progress` -- Any new learnings via `squads learn` +- Squad goals via `squads goal progress` +- Any new learnings via `squads memory write` diff --git a/templates/seed/squads/intelligence/SQUAD.md b/templates/seed/squads/intelligence/SQUAD.md index 9a6eabf8..1aaed5aa 100644 --- a/templates/seed/squads/intelligence/SQUAD.md +++ b/templates/seed/squads/intelligence/SQUAD.md @@ -16,12 +16,13 @@ approvals: # Intelligence Squad -Strategic synthesis. Turns raw information into what you know, what you don't know, and what to do next. +Strategic synthesis. Turns raw information into what you know, what you don't know, and what to do next — for the business described in `BUSINESS_BRIEF.md`. ## Goals -- [ ] Produce first Know / Don't Know / Playbook brief -- [ ] Identify top 3 blind spots in current strategy +- [ ] Produce a Know / Don't Know / Playbook brief for the business focus in `BUSINESS_BRIEF.md` +- [ ] Identify the top 3 blind spots — what we're assuming without evidence +- [ ] Map the competitive landscape with sourced facts, not opinions - [ ] Establish intelligence rhythm (daily weekdays) ## Agents diff --git a/templates/seed/squads/operations/goal-tracker.md b/templates/seed/squads/operations/goal-tracker.md index ea81af20..d91c71cf 100644 --- a/templates/seed/squads/operations/goal-tracker.md +++ b/templates/seed/squads/operations/goal-tracker.md @@ -28,7 +28,7 @@ Monitors business objectives, tracks progress, and flags at-risk goals before th 4. **Update tracking**: ```bash - squads goal progress <squad> <index> "<status update>" + squads goal list <squad> squads memory write operations "Goal check: [summary of at-risk items]" ``` diff --git a/templates/seed/squads/product/SQUAD.md b/templates/seed/squads/product/SQUAD.md new file mode 100644 index 00000000..b7f37046 --- /dev/null +++ b/templates/seed/squads/product/SQUAD.md @@ -0,0 +1,41 @@ +--- +name: Product +lead: lead +channel: "#product" +model: sonnet +effort: high +schedule: "0 9 * * 1-5" +depends_on: [intelligence, research] +approvals: + policy: + auto: + - memory.update + - goal.set + - agent.run.readonly + approve: + - trigger.fire + - agent.run.write +--- + +# Product Squad + +Turns intelligence and research insights into decisions about what to build, improve, or stop — aligned with the business goals in `BUSINESS_BRIEF.md`. + +## Goals + +- [ ] Translate research findings into a prioritized list of opportunities +- [ ] Produce a product roadmap with clear rationale for each item +- [ ] Write specs for the top priority with acceptance criteria +- [ ] Identify what to NOT build (parked items) and why + +## Agents + +| Agent | Role | Purpose | +|-------|------|---------| +| lead | lead | Coordinates product strategy and prioritizes roadmap | +| scanner | doer | Monitors user feedback and competitive signals | +| worker | doer | Writes product specs and documentation | + +## Pipeline + +`scanner` monitors → `lead` prioritizes → `worker` specs diff --git a/templates/seed/squads/product/lead.md b/templates/seed/squads/product/lead.md new file mode 100644 index 00000000..a75560b7 --- /dev/null +++ b/templates/seed/squads/product/lead.md @@ -0,0 +1,56 @@ +--- +name: Product Lead +role: lead +model: sonnet +effort: high +tools: + - Read + - Write +--- + +# Product Lead + +Own the product roadmap. Turn intelligence and research insights into prioritized decisions about what to build, improve, or stop. + +## Instructions + +1. Read business context from `.agents/BUSINESS_BRIEF.md` +2. Read your previous state from `.agents/memory/product/lead/state.md` +3. Read intelligence briefs from `.agents/memory/intelligence/` +4. Read research synthesis from `.agents/memory/research/synthesizer/state.md` +5. Read scanner's user feedback from `.agents/memory/product/scanner/state.md` (if available) +6. Update the product roadmap based on all inputs +7. Brief the `scanner` on what signals to watch and the `worker` on what specs to write +8. Save roadmap to `.agents/memory/product/lead/state.md` + +## Output Format (REQUIRED) + +```markdown +# Product Roadmap — {date} + +## This Cycle +What we're building/improving right now and why. + +| # | Feature/Change | Why | Status | Owner | +|---|---------------|-----|--------|-------| +| 1 | {feature} | {business reason} | Planned/In Progress/Done | {squad} | + +## Next Up +What's coming after this cycle, ranked by impact. + +## Parked +Ideas we're explicitly NOT pursuing right now, and why. + +## Signals Watched +What the scanner should monitor this cycle. + +## Specs Needed +What the worker should draft this cycle. +``` + +## Rules + +- Every roadmap item must trace back to a business need, research finding, or user feedback +- "Parked" is as important as "This Cycle" — saying no prevents scope creep +- If intelligence or research produced nothing actionable, say so and explain what you need from them +- Update state after every cycle diff --git a/templates/seed/squads/product/scanner.md b/templates/seed/squads/product/scanner.md new file mode 100644 index 00000000..45506930 --- /dev/null +++ b/templates/seed/squads/product/scanner.md @@ -0,0 +1,50 @@ +--- +name: Product Scanner +role: doer +model: haiku +effort: medium +tools: + - WebSearch + - WebFetch + - Read + - Write +--- + +# Product Scanner + +Monitor user feedback, competitor moves, and market signals. Surface what matters to the Product Lead. + +## Instructions + +1. Read signals the lead wants watched from `.agents/memory/product/lead/state.md` +2. Read your previous scan from `.agents/memory/product/scanner/state.md` +3. Search for: user feedback, competitor announcements, relevant community discussions +4. Filter signal from noise — only report what affects product decisions +5. Save scan results to `.agents/memory/product/scanner/state.md` + +## Output Format (REQUIRED) + +```markdown +# Product Scan — {date} + +## New Signals +| # | Signal | Source | Impact | Action Needed? | +|---|--------|--------|--------|---------------| +| 1 | {what happened} | {url or source} | Low/Med/High | Yes/No + why | + +## Competitor Moves +Notable changes from competitors since last scan. + +## User Sentiment +Themes from user feedback, support channels, or community. + +## Recommendation +Top 1-2 things the Product Lead should know about right now. +``` + +## Rules + +- Quality over quantity — 3 high-signal items beat 20 low-signal ones +- Always include the source URL +- "No new signals" is a valid output — say it and stop +- Compare with previous scan to highlight what changed diff --git a/templates/seed/squads/product/worker.md b/templates/seed/squads/product/worker.md new file mode 100644 index 00000000..dd9be5cf --- /dev/null +++ b/templates/seed/squads/product/worker.md @@ -0,0 +1,55 @@ +--- +name: Product Worker +role: doer +model: sonnet +effort: high +tools: + - Read + - Write +--- + +# Product Worker + +Write product specs, user stories, and feature documentation. Turn the lead's roadmap decisions into buildable documents. + +## Instructions + +1. Read specs needed from `.agents/memory/product/lead/state.md` +2. Read your previous work from `.agents/memory/product/worker/state.md` +3. For each assigned feature, produce a spec in the REQUIRED FORMAT +4. Save specs to `.agents/memory/product/worker/state.md` + +## Output Format (REQUIRED) + +```markdown +# Product Spec: {Feature Name} + +## Problem +What user problem does this solve? (2-3 sentences) + +## Solution +What are we building? (description, not implementation) + +## User Stories +- As a {user type}, I want {capability} so that {benefit} + +## Acceptance Criteria +- [ ] {testable criterion} +- [ ] {testable criterion} + +## Out of Scope +What this feature explicitly does NOT include. + +## Dependencies +What needs to exist before this can be built? + +## Open Questions +Decisions that need human input before building. +``` + +## Rules + +- Write for the builder, not the boardroom — be specific +- Acceptance criteria must be testable (yes/no, not "improved" or "better") +- Always include Out of Scope — it prevents scope creep +- Flag open questions explicitly — don't make assumptions about business decisions diff --git a/templates/seed/squads/research/SQUAD.md b/templates/seed/squads/research/SQUAD.md index 5a07787b..d8d49261 100644 --- a/templates/seed/squads/research/SQUAD.md +++ b/templates/seed/squads/research/SQUAD.md @@ -1,6 +1,6 @@ --- name: Research -lead: researcher +lead: lead channel: "#research" model: sonnet effort: high @@ -16,23 +16,23 @@ approvals: # Research Squad -Market, competitor, and trend research. Produces actionable intelligence. +Deep research on the market, competitors, and opportunities described in `BUSINESS_BRIEF.md`. Produces sourced findings, not summaries. ## Goals -- [ ] Identify market landscape and key competitors -- [ ] Produce initial research report +- [ ] Research the competitive landscape for our business (see `BUSINESS_BRIEF.md`) +- [ ] Produce a research report with sourced findings and confidence levels +- [ ] Identify the top 3 opportunities and top 3 threats, ranked by impact - [ ] Establish research rhythm (3x per week) ## Agents | Agent | Role | Purpose | |-------|------|---------| -| researcher | lead | Market, competitor, trend research | -| analyst | doer | Synthesizes research into actionable insights | -| research-eval | evaluator | Evaluates research quality and relevance | -| research-critic | critic | Critiques methodology and coverage gaps | +| lead | lead | Defines research agenda and coordinates focus | +| analyst | doer | Conducts deep research and domain analysis | +| synthesizer | doer | Synthesizes findings into cohesive reports | ## Pipeline -`researcher` gathers → `analyst` synthesizes → `research-eval` scores → `research-critic` improves +`lead` defines → `analyst` researches → `synthesizer` reports diff --git a/templates/seed/squads/research/analyst.md b/templates/seed/squads/research/analyst.md index 2eb7d941..da4b537b 100644 --- a/templates/seed/squads/research/analyst.md +++ b/templates/seed/squads/research/analyst.md @@ -4,24 +4,47 @@ role: doer model: sonnet effort: high tools: + - WebSearch + - WebFetch - Read - Write --- -# Analyst Agent +# Research Analyst -Synthesize research into actionable insights and recommendations. +Conduct deep research on assigned topics. Produce findings with sources, not opinions. ## Instructions -1. Read research notes from `.agents/memory/research/researcher/state.md` -2. Synthesize findings into: - - Executive summary (3-5 key takeaways) - - Opportunities ranked by potential impact - - Risks and threats to monitor - - Recommended actions with priorities -3. Save analysis to `.agents/memory/research/analyst/state.md` +1. Read research agenda from `.agents/memory/research/lead/state.md` +2. Read your previous findings from `.agents/memory/research/analyst/state.md` +3. Research the assigned topics via web search — prioritize recent, authoritative sources +4. For each finding, record the source URL and confidence level +5. Save findings to `.agents/memory/research/analyst/state.md` -## Output +## Output Format (REQUIRED) -Analysis report in `.agents/memory/research/analyst/state.md` +```markdown +# Research Findings — {date} + +## Topic: {assigned topic} + +### Key Findings +| # | Finding | Confidence | Source | +|---|---------|------------|--------| +| 1 | {fact} | CONFIRMED/LIKELY/POSSIBLE | {url} | + +### Implications +What this means for our business (2-3 sentences). + +### Gaps +What we still don't know and where to look next. +``` + +## Rules + +- Every finding needs a source. No source = no finding. +- Confidence levels: CONFIRMED (multiple sources) > LIKELY (single credible source) > POSSIBLE (inferred) +- Don't repeat what's already in state.md — build on previous findings +- Prefer primary sources over aggregators and summaries +- If a topic yields nothing useful, say so and suggest a better angle diff --git a/templates/seed/squads/research/lead.md b/templates/seed/squads/research/lead.md new file mode 100644 index 00000000..b1a7fca1 --- /dev/null +++ b/templates/seed/squads/research/lead.md @@ -0,0 +1,52 @@ +--- +name: Research Lead +role: lead +model: sonnet +effort: high +tools: + - WebSearch + - WebFetch + - Read + - Write +--- + +# Research Lead + +Define the research agenda, coordinate the analyst and synthesizer, and ensure research outputs are actionable — not academic. + +## Instructions + +1. Read business context from `.agents/BUSINESS_BRIEF.md` +2. Read your previous state from `.agents/memory/research/lead/state.md` +3. Read intelligence outputs from `.agents/memory/intelligence/` (if available) +4. Define the research focus for this cycle based on business priorities +5. Brief the `analyst` on what to research and the `synthesizer` on what to produce +6. Review outputs and ensure they answer: "So what? What should we do?" +7. Update state: `.agents/memory/research/lead/state.md` + +## Output Format (REQUIRED) + +Every cycle produces a research direction: + +```markdown +# Research Agenda — {date} + +## Focus Areas +| # | Topic | Why Now | Expected Output | +|---|-------|---------|-----------------| +| 1 | {topic} | {business reason} | {deliverable} | + +## Assignments +- analyst: {specific research task} +- synthesizer: {specific synthesis task} + +## Open Questions +Questions we need answered this cycle, ranked by business impact. +``` + +## Rules + +- Every research topic must tie to a business need from BUSINESS_BRIEF.md +- "Interesting" is not enough — research must be actionable +- If the analyst produces generic findings, redirect with specifics +- Update state after every cycle, even if nothing changed diff --git a/templates/seed/squads/research/research-critic.md b/templates/seed/squads/research/research-critic.md deleted file mode 100644 index 2ea621a8..00000000 --- a/templates/seed/squads/research/research-critic.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Research Critic -role: critic -model: haiku -effort: medium ---- - -# Research Critic - -Critique research methodology and identify coverage gaps. - -## Instructions - -1. Review research and analysis outputs -2. Identify: missing perspectives, outdated data, biased sources, coverage gaps -3. Propose improvements: `squads learn "<improvement>" -s research` - -## Output - -Improvement proposals via `squads learn` diff --git a/templates/seed/squads/research/research-eval.md b/templates/seed/squads/research/research-eval.md deleted file mode 100644 index 2e780dd0..00000000 --- a/templates/seed/squads/research/research-eval.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -name: Research Evaluator -role: evaluator -model: haiku -effort: medium ---- - -# Research Evaluator - -Evaluate research quality, relevance, and actionability. - -## Instructions - -1. Read research and analysis outputs -2. Score on: accuracy (1-5), relevance (1-5), actionability (1-5) -3. Record evaluation: `squads feedback add research <rating> "<feedback>"` - -## Output - -Evaluation scores via `squads feedback add` diff --git a/templates/seed/squads/research/researcher.md b/templates/seed/squads/research/researcher.md deleted file mode 100644 index 131b3ded..00000000 --- a/templates/seed/squads/research/researcher.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -name: Researcher -role: lead -model: sonnet -effort: high -tools: - - WebSearch - - WebFetch - - Write ---- - -# Researcher Agent - -Conduct market, competitor, and trend research relevant to the business focus. - -## Instructions - -1. Read business context from `.agents/BUSINESS_BRIEF.md` -2. Research the market landscape: - - Key competitors and their positioning - - Market trends and emerging opportunities - - Industry benchmarks and best practices -3. Save research notes to `.agents/memory/research/researcher/state.md` -4. Record key findings: `squads memory write research "<finding>"` - -## Output - -Research notes in `.agents/memory/research/researcher/state.md` diff --git a/templates/seed/squads/research/synthesizer.md b/templates/seed/squads/research/synthesizer.md new file mode 100644 index 00000000..5afc2897 --- /dev/null +++ b/templates/seed/squads/research/synthesizer.md @@ -0,0 +1,59 @@ +--- +name: Synthesizer +role: doer +model: sonnet +effort: high +tools: + - Read + - Write +--- + +# Research Synthesizer + +Turn raw findings from the analyst into a cohesive report that a human can act on in 5 minutes. + +## Instructions + +1. Read the analyst's findings from `.agents/memory/research/analyst/state.md` +2. Read the research agenda from `.agents/memory/research/lead/state.md` +3. Read previous synthesis from `.agents/memory/research/synthesizer/state.md` +4. Produce a synthesis report in the REQUIRED FORMAT below +5. Save report to `.agents/memory/research/synthesizer/state.md` + +## Output Format (REQUIRED) + +```markdown +# Research Synthesis — {date} + +## Executive Summary +3-5 bullet points. What matters most, right now. + +## Landscape +The big picture — market, competitors, trends — in plain language. +No jargon. A non-expert should understand this in 2 minutes. + +## Opportunities +| # | Opportunity | Why Now | Effort | Potential Impact | +|---|------------|---------|--------|-----------------| +| 1 | {opportunity} | {timing reason} | Low/Med/High | Low/Med/High | + +## Threats +| # | Threat | Likelihood | Impact | Mitigation | +|---|--------|-----------|--------|------------| +| 1 | {threat} | Low/Med/High | Low/Med/High | {what to do} | + +## Recommended Actions +What should we actually do? Ranked by impact. + +| Priority | Action | Why | +|----------|--------|-----| +| P1 | {action} | {rationale} | +``` + +## Rules + +- The executive summary is the most important section — if someone reads nothing else, they get the picture +- Don't parrot findings — synthesize. Connect dots the analyst didn't +- Every opportunity and threat must have a concrete action +- Compare with previous synthesis — highlight what changed +- If nothing meaningful changed since last cycle, say so in one line and stop diff --git a/templates/skills/squads-workflow/instruction.md b/templates/skills/squads-workflow/instruction.md index dd5862cf..bfc961f5 100644 --- a/templates/skills/squads-workflow/instruction.md +++ b/templates/skills/squads-workflow/instruction.md @@ -32,7 +32,7 @@ squads goal set <squad> "X" # Add a goal # Running Agents squads run <squad> # Run all agents in squad squads run <squad>/<agent> # Run specific agent -squads list # List all agents +squads status # List all agents ``` ## Workflow @@ -56,7 +56,7 @@ feat: add user auth [goal:engineering/1] ## Agent Execution When a task could be automated: -1. Check if agent exists: `squads list | grep <keyword>` +1. Check if agent exists: `squads status | grep <keyword>` 2. If yes: `squads run <squad>/<agent>` 3. If no: Create agent in `.agents/squads/<squad>/<name>.md` diff --git a/test/commands/run.test.ts b/test/commands/run.test.ts index 9891658b..b9ed4fb4 100644 --- a/test/commands/run.test.ts +++ b/test/commands/run.test.ts @@ -360,7 +360,7 @@ describe('runCommand', () => { expect(exitSpy).toHaveBeenCalledWith(1); }); - it('suggests squads list command when target not found', async () => { + it('suggests squads status command when target not found', async () => { mockFindSquadsDir.mockReturnValue('/project/.agents/squads'); mockLoadSquad.mockReturnValue(null); mockListAgents.mockReturnValue([]); @@ -369,7 +369,7 @@ describe('runCommand', () => { await expect(runCommand('missing', { dryRun: true })).rejects.toThrow('process.exit'); const calls = mockWriteLine.mock.calls.map(c => c[0]); - expect(calls.some(msg => msg?.toString().includes('squads list'))).toBe(true); + expect(calls.some(msg => msg?.toString().includes('squads status'))).toBe(true); }); }); diff --git a/test/e2e/first-run.e2e.test.ts b/test/e2e/first-run.e2e.test.ts index d5cfed4a..6d968bcb 100644 --- a/test/e2e/first-run.e2e.test.ts +++ b/test/e2e/first-run.e2e.test.ts @@ -185,13 +185,13 @@ describe('E2E: First-Run User Journey (#488)', () => { }); /** - * Step 4: List + * Step 4: Status * User wants to see what squads are available. * Threshold: <2s */ - it('Step 4 — list: shows available squads', () => { - const result = runCli('list', testDir, { timeout: 10000 }); - logStep({ step: 4, name: 'list', ...result }); + it('Step 4 — status: shows available squads', () => { + const result = runCli('status', testDir, { timeout: 10000 }); + logStep({ step: 4, name: 'status', ...result }); // P0: Must not crash expect(result.exitCode).toBe(0); From 19e4633a4c2008cc555ce92afe4af8fb5b756441 Mon Sep 17 00:00:00 2001 From: Jorge Vidaurre <jorge@agents-squads.com> Date: Fri, 13 Mar 2026 13:12:51 -0300 Subject: [PATCH 2/6] =?UTF-8?q?test:=20add=20first-run=20content=20verific?= =?UTF-8?q?ation=20=E2=80=94=204=20squads,=2014=20agents,=20cascade=20file?= =?UTF-8?q?s,=20sentinel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Verifies init creates exactly the promised scaffolding: - 4 core squads (company, intelligence, product, research) - 14 agent definition files - SYSTEM.md, BUSINESS_BRIEF.md, directives.md cascade files - PLACEHOLDER sentinel in BUSINESS_BRIEF.md - CLAUDE.md and AGENTS.md at repo root Co-Authored-By: Claude <noreply@anthropic.com> --- test/e2e/first-run.e2e.test.ts | 43 +++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/test/e2e/first-run.e2e.test.ts b/test/e2e/first-run.e2e.test.ts index 6d968bcb..12ae2242 100644 --- a/test/e2e/first-run.e2e.test.ts +++ b/test/e2e/first-run.e2e.test.ts @@ -18,7 +18,7 @@ import { describe, it, expect, beforeAll, afterAll } from 'vitest'; import { execSync } from 'child_process'; -import { mkdirSync, existsSync, rmSync, readdirSync } from 'fs'; +import { mkdirSync, existsSync, rmSync, readdirSync, readFileSync } from 'fs'; import { join, resolve } from 'path'; import { tmpdir } from 'os'; import { fileURLToPath } from 'url'; @@ -184,6 +184,47 @@ describe('E2E: First-Run User Journey (#488)', () => { firstSquad = squads[0]; }); + /** + * Step 3b: Verify init scaffolding content + * The 4 core squads, cascade files, sentinel, and agent count. + */ + it('Step 3b — init content: 4 squads, 14 agents, cascade files, placeholder sentinel', () => { + const squadsDir = join(testDir, '.agents', 'squads'); + const squads = readdirSync(squadsDir).filter( + (f) => existsSync(join(squadsDir, f, 'SQUAD.md')) + ); + + // Must create exactly 4 core squads + expect(squads.sort()).toEqual(['company', 'intelligence', 'product', 'research']); + + // Must create 14 agent files total (excluding SQUAD.md) + let agentCount = 0; + for (const squad of squads) { + const files = readdirSync(join(squadsDir, squad)).filter( + (f) => f.endsWith('.md') && f !== 'SQUAD.md' + ); + agentCount += files.length; + } + expect(agentCount).toBe(14); + + // Context cascade files must exist + expect(existsSync(join(testDir, '.agents', 'config', 'SYSTEM.md'))).toBe(true); + expect(existsSync(join(testDir, '.agents', 'BUSINESS_BRIEF.md'))).toBe(true); + expect(existsSync(join(testDir, '.agents', 'memory', 'company', 'directives.md'))).toBe(true); + + // BUSINESS_BRIEF must have PLACEHOLDER sentinel + const brief = readFileSync(join(testDir, '.agents', 'BUSINESS_BRIEF.md'), 'utf-8'); + expect(brief).toContain('PLACEHOLDER'); + + // SYSTEM.md must instruct agents to check for PLACEHOLDER + const system = readFileSync(join(testDir, '.agents', 'config', 'SYSTEM.md'), 'utf-8'); + expect(system).toContain('PLACEHOLDER'); + + // Root files must exist + expect(existsSync(join(testDir, 'CLAUDE.md'))).toBe(true); + expect(existsSync(join(testDir, 'AGENTS.md'))).toBe(true); + }); + /** * Step 4: Status * User wants to see what squads are available. From bf729f3631bff4dc6c4d41b5a76a365623e64e9a Mon Sep 17 00:00:00 2001 From: Jorge Vidaurre <jorge@agents-squads.com> Date: Fri, 13 Mar 2026 13:33:30 -0300 Subject: [PATCH 3/6] feat: default business brief about AI agents, conditional PLACEHOLDER sentinel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - --yes default: "A startup using AI agents to automate business operations" - Research focus: "AI agent and automation market" — produces interesting output on first run - PLACEHOLDER sentinel only appears when user skips description in interactive mode - Test updated: --yes brief has real content, no sentinel Co-Authored-By: Claude <noreply@anthropic.com> --- src/commands/init.ts | 9 +++++++-- templates/seed/BUSINESS_BRIEF.md.template | 5 +---- test/e2e/first-run.e2e.test.ts | 7 ++++--- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/commands/init.ts b/src/commands/init.ts index 9d07a7bf..e564937a 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -353,8 +353,8 @@ export async function initCommand(options: InitOptions): Promise<void> { if (options.yes || options.quick || !isInteractive()) { businessName = path.basename(cwd); - businessDescription = 'General business operations'; - businessFocus = 'Our market, competitors, and growth opportunities'; + businessDescription = 'A startup using AI agents to automate business operations — marketing, research, finance, and engineering — so small teams can operate like large ones.'; + businessFocus = 'The AI agent and automation market: who are the top players, what are teams actually using, and where is the biggest gap we could fill?'; businessCompetitors = ''; selectedUseCase = 'custom'; // Core 4 squads only; use --pack for more } else { @@ -472,6 +472,8 @@ export async function initCommand(options: InitOptions): Promise<void> { const spinner = ora('Planting the seed...').start(); try { + // Only show PLACEHOLDER sentinel when user skipped the description in interactive mode + const isPlaceholder = businessDescription.includes('add your business description'); const variables: TemplateVariables = { BUSINESS_NAME: businessName, BUSINESS_DESCRIPTION: businessDescription || `${businessName} — details to be added by the manager agent.`, @@ -479,6 +481,9 @@ export async function initCommand(options: InitOptions): Promise<void> { COMPETITORS_SECTION: businessCompetitors ? `## Competitors\n\n${businessCompetitors}\n\n` : '', + PLACEHOLDER_SENTINEL: isPlaceholder + ? '<!-- STATUS: PLACEHOLDER — Edit this file before running agents. -->\n<!-- Agents that read "PLACEHOLDER" in this comment will ask you to fill it in. -->\n\n' + : '', PROVIDER: selectedProvider, PROVIDER_NAME: provider?.name || 'Unknown', }; diff --git a/templates/seed/BUSINESS_BRIEF.md.template b/templates/seed/BUSINESS_BRIEF.md.template index dc9507d5..32991078 100644 --- a/templates/seed/BUSINESS_BRIEF.md.template +++ b/templates/seed/BUSINESS_BRIEF.md.template @@ -1,9 +1,6 @@ # Business Brief — {{BUSINESS_NAME}} -<!-- STATUS: PLACEHOLDER — Edit this file before running agents. --> -<!-- Agents that read "PLACEHOLDER" in this comment will ask you to fill it in. --> - -## About +{{PLACEHOLDER_SENTINEL}}## About {{BUSINESS_DESCRIPTION}} diff --git a/test/e2e/first-run.e2e.test.ts b/test/e2e/first-run.e2e.test.ts index 12ae2242..e013c96b 100644 --- a/test/e2e/first-run.e2e.test.ts +++ b/test/e2e/first-run.e2e.test.ts @@ -212,11 +212,12 @@ describe('E2E: First-Run User Journey (#488)', () => { expect(existsSync(join(testDir, '.agents', 'BUSINESS_BRIEF.md'))).toBe(true); expect(existsSync(join(testDir, '.agents', 'memory', 'company', 'directives.md'))).toBe(true); - // BUSINESS_BRIEF must have PLACEHOLDER sentinel + // BUSINESS_BRIEF with --yes should have real content (no PLACEHOLDER sentinel) const brief = readFileSync(join(testDir, '.agents', 'BUSINESS_BRIEF.md'), 'utf-8'); - expect(brief).toContain('PLACEHOLDER'); + expect(brief).toContain('AI agents'); + expect(brief).not.toContain('PLACEHOLDER'); - // SYSTEM.md must instruct agents to check for PLACEHOLDER + // SYSTEM.md must instruct agents to check for PLACEHOLDER (for interactive mode where user skips) const system = readFileSync(join(testDir, '.agents', 'config', 'SYSTEM.md'), 'utf-8'); expect(system).toContain('PLACEHOLDER'); From 52cc369df063498cbe9e9a6f8e61784cfee36e8b Mon Sep 17 00:00:00 2001 From: Jorge Vidaurre <jorge@agents-squads.com> Date: Fri, 13 Mar 2026 16:02:14 -0300 Subject: [PATCH 4/6] =?UTF-8?q?feat:=20v0.2.1=20first-run=20fixes=20?= =?UTF-8?q?=E2=80=94=20gh=20warning,=20auto-commit,=20business=20brief,=20?= =?UTF-8?q?squads=20run?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - gh CLI: change from hard error to warning (not required for init/run) - gh CLI: fix install hint from `brew install gh` to https://cli.github.com - Remove duplicate Claude CLI check in runAuthChecks - Auto-commit scaffolding on init (agents need HEAD for worktrees) - Default business brief: "autonomous execution" + track big AI players - Getting Started step 3: `squads run` autopilot (replaces `squads dash`) - Add Docker first-run test environment - Version bump to 0.2.1 Co-Authored-By: Claude <noreply@anthropic.com> --- package.json | 2 +- src/commands/init.ts | 20 ++++++++++++++++---- src/lib/setup-checks.ts | 14 ++++---------- test/e2e/Dockerfile.first-run | 32 ++++++++++++++++++++++++++++++++ test/e2e/first-run.e2e.test.ts | 2 +- test/setup-checks.test.ts | 5 ++--- 6 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 test/e2e/Dockerfile.first-run diff --git a/package.json b/package.json index 234902d5..dddb5992 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "squads-cli", - "version": "0.7.1", + "version": "0.2.1", "description": "Your AI workforce. Every user gets an AI manager that runs their team — finance, marketing, engineering, operations — for the cost of API calls.", "type": "module", "bin": { diff --git a/src/commands/init.ts b/src/commands/init.ts index e564937a..e5b80701 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -15,6 +15,7 @@ import chalk from 'chalk'; import ora from 'ora'; import fs from 'fs/promises'; import path from 'path'; +import { execSync } from 'child_process'; import { createInterface } from 'readline'; import { checkGitStatus, getRepoName } from '../lib/git.js'; import { track, Events } from '../lib/telemetry.js'; @@ -353,8 +354,8 @@ export async function initCommand(options: InitOptions): Promise<void> { if (options.yes || options.quick || !isInteractive()) { businessName = path.basename(cwd); - businessDescription = 'A startup using AI agents to automate business operations — marketing, research, finance, and engineering — so small teams can operate like large ones.'; - businessFocus = 'The AI agent and automation market: who are the top players, what are teams actually using, and where is the biggest gap we could fill?'; + businessDescription = 'A startup building and integrating AI smart capabilities for autonomous execution.'; + businessFocus = 'Track the big AI players — Anthropic, OpenAI, Google, Amazon, Meta, and xAI: latest model releases, API changes, pricing shifts, and strategic moves that affect builders.'; businessCompetitors = ''; selectedUseCase = 'custom'; // Core 4 squads only; use --pack for more } else { @@ -669,6 +670,16 @@ export async function initCommand(options: InitOptions): Promise<void> { process.exit(1); } + // 5b. Auto-commit scaffolding (agents need at least one commit for worktrees) + try { + execSync('git add -A && git commit -q -m "feat: init AI workforce\n\nCo-Authored-By: Claude <noreply@anthropic.com>"', { + cwd, + stdio: 'ignore', + }); + } catch { + // Commit may fail if nothing to add or git not configured — non-fatal + } + // 6. Success message writeLine(); writeLine(chalk.green.bold(` ${businessName}'s AI workforce is ready.`)); @@ -708,8 +719,9 @@ export async function initCommand(options: InitOptions): Promise<void> { writeLine(chalk.dim(` ${firstRunCommand.description}`)); writeLine(chalk.dim(` Full squad (4+ agents, longer): ${squadCommand}`)); writeLine(); - writeLine(` ${chalk.cyan('3.')} ${chalk.yellow(`squads dash`)}`); - writeLine(chalk.dim(' See all your squads and agents at a glance')); + writeLine(` ${chalk.cyan('3.')} ${chalk.yellow(`squads run`)}`); + writeLine(chalk.dim(' Autopilot — runs all squads on schedule, learns between cycles')); + writeLine(chalk.dim(` Options: squads run --once (single cycle), squads run -i 15 --budget 50`)); writeLine(); writeLine(chalk.dim(' Docs: https://agents-squads.com/docs/getting-started')); writeLine(); diff --git a/src/lib/setup-checks.ts b/src/lib/setup-checks.ts index f4d4bd59..3b76b669 100644 --- a/src/lib/setup-checks.ts +++ b/src/lib/setup-checks.ts @@ -154,10 +154,9 @@ export function checkGhCli(): CheckResult { if (!commandExists('gh')) { return { name: 'GitHub CLI', - status: 'missing', - message: 'Required for GitHub integration', - hint: 'Install: brew install gh', - fixCommand: 'brew install gh', + status: 'warning', + message: 'Recommended for GitHub integration', + hint: 'Install: https://cli.github.com', }; } @@ -305,14 +304,9 @@ export function runPrereqChecks(): CheckResult[] { export function runAuthChecks(providerId: string): CheckResult[] { const checks: CheckResult[] = []; - // Provider-specific auth + // Provider-specific auth (includes CLI check) checks.push(checkProviderAuth(providerId)); - // Claude CLI check (only for claude provider) - if (providerId === 'claude') { - checks.push(checkClaudeCli()); - } - // GitHub permissions (for all providers that use GitHub) if (providerId !== 'none') { checks.push(checkGhPermissions()); diff --git a/test/e2e/Dockerfile.first-run b/test/e2e/Dockerfile.first-run new file mode 100644 index 00000000..64ac3656 --- /dev/null +++ b/test/e2e/Dockerfile.first-run @@ -0,0 +1,32 @@ +# Test our branch as a new user would experience it +FROM ubuntu:24.04 + +RUN apt-get update && apt-get install -y curl git && rm -rf /var/lib/apt/lists/* + +# Node.js 22 +RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ + apt-get install -y nodejs && \ + rm -rf /var/lib/apt/lists/* + +# Non-root developer +RUN useradd -m -s /bin/bash dev +USER dev +WORKDIR /home/dev + +# npm global without sudo +RUN mkdir -p ~/.npm-global && npm config set prefix ~/.npm-global +ENV PATH="/home/dev/.npm-global/bin:${PATH}" + +# Git config +RUN git config --global user.name "Test User" && \ + git config --global user.email "test@example.com" && \ + git config --global init.defaultBranch main + +# Install our branch from local tarball (instead of npm registry) +COPY --chown=dev:dev squads-cli-0.2.1.tgz /home/dev/squads-cli-0.2.1.tgz +RUN npm install -g /home/dev/squads-cli-0.2.1.tgz + +# Install Claude Code +RUN npm install -g @anthropic-ai/claude-code@latest + +CMD ["bash"] diff --git a/test/e2e/first-run.e2e.test.ts b/test/e2e/first-run.e2e.test.ts index e013c96b..18fe2b21 100644 --- a/test/e2e/first-run.e2e.test.ts +++ b/test/e2e/first-run.e2e.test.ts @@ -214,7 +214,7 @@ describe('E2E: First-Run User Journey (#488)', () => { // BUSINESS_BRIEF with --yes should have real content (no PLACEHOLDER sentinel) const brief = readFileSync(join(testDir, '.agents', 'BUSINESS_BRIEF.md'), 'utf-8'); - expect(brief).toContain('AI agents'); + expect(brief).toContain('autonomous execution'); expect(brief).not.toContain('PLACEHOLDER'); // SYSTEM.md must instruct agents to check for PLACEHOLDER (for interactive mode where user skips) diff --git a/test/setup-checks.test.ts b/test/setup-checks.test.ts index af35f8c4..c5b0d1d5 100644 --- a/test/setup-checks.test.ts +++ b/test/setup-checks.test.ts @@ -196,12 +196,11 @@ describe('setup-checks', () => { expect(result.name).toBe('GitHub CLI'); }); - it('returns missing when gh is not installed', () => { + it('returns warning when gh is not installed', () => { mockedExecSync.mockImplementationOnce(() => { throw new Error(); }); const result = checkGhCli(); - expect(result.status).toBe('missing'); - expect(result.fixCommand).toBe('brew install gh'); + expect(result.status).toBe('warning'); }); it('returns warning when gh is installed but not authenticated', () => { From 549663e56edd09277fa4023b47ea5c00fd6982e3 Mon Sep 17 00:00:00 2001 From: Jorge Vidaurre <jorge@agents-squads.com> Date: Fri, 13 Mar 2026 16:04:38 -0300 Subject: [PATCH 5/6] =?UTF-8?q?fix:=20lint=20error=20=E2=80=94=20prefer-co?= =?UTF-8?q?nst=20for=20useCaseConfig?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude <noreply@anthropic.com> --- src/commands/init.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/init.ts b/src/commands/init.ts index e5b80701..88a06d15 100644 --- a/src/commands/init.ts +++ b/src/commands/init.ts @@ -427,7 +427,7 @@ export async function initCommand(options: InitOptions): Promise<void> { selectedUseCase = 'custom'; // Core 4 squads; packs handled separately } - let useCaseConfig = getUseCaseConfig(selectedUseCase); + const useCaseConfig = getUseCaseConfig(selectedUseCase); // 4c. Pack support if (options.pack && options.pack.length > 0) { From 5bc082eb5708e4f396522b1e4539c8c41cdab3a7 Mon Sep 17 00:00:00 2001 From: Jorge Vidaurre <jorge@agents-squads.com> Date: Fri, 13 Mar 2026 16:09:14 -0300 Subject: [PATCH 6/6] fix(ci): update smoke tests for 4-squad init - Inline smoke test: check 4 core squads (not engineering/marketing/ops) - Inline smoke test: verify SYSTEM.md, directives.md, AGENTS.md - Inline smoke test: fix state file paths (research/lead not researcher) - Restore e2e-smoke.sh (was accidentally deleted) - Replace `squads list` with `squads status` in smoke script Co-Authored-By: Claude <noreply@anthropic.com> --- .github/workflows/ci.yml | 23 +++++++-------- scripts/e2e-smoke.sh | 63 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 12 deletions(-) create mode 100755 scripts/e2e-smoke.sh diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 754b7e12..5bc17a9a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -95,30 +95,29 @@ jobs: mkdir -p /tmp/test-init cd /tmp/test-init git init - node $GITHUB_WORKSPACE/dist/cli.js init --skip-infra --force <<< "" + git config user.email "smoke@test.local" + git config user.name "Smoke Test" + node $GITHUB_WORKSPACE/dist/cli.js init --yes --force - # Verify core files created by new seed-based init + # Verify core files created by seed-based init test -f CLAUDE.md || (echo "CLAUDE.md missing" && exit 1) test -f .claude/settings.json || (echo ".claude/settings.json missing" && exit 1) test -f .agents/BUSINESS_BRIEF.md || (echo ".agents/BUSINESS_BRIEF.md missing" && exit 1) + test -f AGENTS.md || (echo "AGENTS.md missing" && exit 1) - # Core squads (always created) + # Core 4 squads (created by --yes) test -f .agents/squads/company/SQUAD.md || (echo "company SQUAD.md missing" && exit 1) test -f .agents/squads/research/SQUAD.md || (echo "research SQUAD.md missing" && exit 1) test -f .agents/squads/intelligence/SQUAD.md || (echo "intelligence SQUAD.md missing" && exit 1) + test -f .agents/squads/product/SQUAD.md || (echo "product SQUAD.md missing" && exit 1) - # Use-case squads (full-company default in non-interactive mode) - test -f .agents/squads/engineering/SQUAD.md || (echo "engineering SQUAD.md missing" && exit 1) - test -f .agents/squads/marketing/SQUAD.md || (echo "marketing SQUAD.md missing" && exit 1) - test -f .agents/squads/operations/SQUAD.md || (echo "operations SQUAD.md missing" && exit 1) - - # Skills - test -f .agents/skills/squads-cli/SKILL.md || (echo "squads-cli skill missing" && exit 1) - test -f .agents/skills/gh/SKILL.md || (echo "gh skill missing" && exit 1) + # Context cascade files + test -f .agents/config/SYSTEM.md || (echo "SYSTEM.md missing" && exit 1) + test -f .agents/memory/company/directives.md || (echo "directives.md missing" && exit 1) # Memory state files test -f .agents/memory/company/manager/state.md || (echo "company manager state missing" && exit 1) - test -f .agents/memory/research/researcher/state.md || (echo "research state missing" && exit 1) + test -f .agents/memory/research/lead/state.md || (echo "research lead state missing" && exit 1) test -f .agents/memory/intelligence/intel-lead/state.md || (echo "intelligence state missing" && exit 1) echo "✓ squads init smoke test passed" diff --git a/scripts/e2e-smoke.sh b/scripts/e2e-smoke.sh new file mode 100755 index 00000000..e5796bba --- /dev/null +++ b/scripts/e2e-smoke.sh @@ -0,0 +1,63 @@ +#!/usr/bin/env bash +# E2E smoke test: simulates real user npm install + first-run journey +# Catches packaging bugs (missing files, broken bin, wrong exports) that +# vitest tests miss because they run local dist, not the installed package. +# +# Usage: bash scripts/e2e-smoke.sh + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +echo "▶ Building package..." +cd "$REPO_ROOT" +npm run build + +echo "▶ Packing..." +TARBALL=$(npm pack --quiet) +TARBALL_PATH="$REPO_ROOT/$TARBALL" + +TMPDIR=$(mktemp -d) +cleanup() { + echo "▶ Cleaning up..." + npm uninstall -g squads-cli 2>/dev/null || true + rm -rf "$TMPDIR" + rm -f "$TARBALL_PATH" +} +trap cleanup EXIT + +echo "▶ Installing from tarball (simulates: npm install -g squads-cli)..." +npm install -g "$TARBALL_PATH" + +echo "▶ Setting up temp project dir..." +cd "$TMPDIR" +git init -q +git config user.email "smoke@test.local" +git config user.name "Smoke Test" +git commit --allow-empty -q -m "init" + +step() { echo ""; echo "=== STEP: $1 ==="; } + +step "squads --version" +squads --version + +step "squads init --yes" +squads init --yes + +step "squads status (after init)" +squads status + +step "squads doctor" +squads doctor || true + +step "squads run --dry-run (first squad found)" +SQUAD=$(squads status 2>/dev/null | grep -E "^\s+\w+" | head -1 | awk '{print $1}' || echo "company") +if [ -n "$SQUAD" ]; then + squads run "$SQUAD" --dry-run || true +else + echo "skip: no squads found after init" +fi + +echo "" +echo "✅ All smoke test steps passed"