Skip to content

feat: remote squad mode, squad repos, and company of squads#131

Closed
spboyer wants to merge 2 commits intobradygaster:mainfrom
spboyer:feat/remote-squad-mode
Closed

feat: remote squad mode, squad repos, and company of squads#131
spboyer wants to merge 2 commits intobradygaster:mainfrom
spboyer:feat/remote-squad-mode

Conversation

@spboyer
Copy link
Contributor

@spboyer spboyer commented Feb 22, 2026

Summary

This PR adds three new opt-in deployment modes to the Squad CLI, enabling teams to run their squad outside the project repo, from a dedicated squad repo, or as a "company of squads" managing multiple projects from a central hub.

All modes are opt-in. The default local mode (team state inside the project) is completely unchanged. All 102 tests pass (86 existing + 16 new).

Relates to:


What's New

1. Unified Path Resolver (resolveSquadPaths())

Replaces detectSquadDir() with a richer resolver returning dual roots:

┌─────────────────────────────────────────────────────┐
│               resolveSquadPaths(projectDir)          │
│                                                      │
│  Input: project directory (CWD)                      │
│                                                      │
│  ┌──────────────────────┐                            │
│  │ .squad/config.json   │─── exists with teamRoot? ──┤
│  │   exists?            │                     │      │
│  └──────────────────────┘                     │      │
│         │ no                                  │ yes  │
│         ▼                                     ▼      │
│  ┌──────────────┐              ┌──────────────────┐  │
│  │ LOCAL MODE   │              │  REMOTE MODE     │  │
│  │              │              │                  │  │
│  │ projectDir = │              │ projectDir =     │  │
│  │ teamDir =    │              │   .squad/ (local)│  │
│  │   .squad/    │              │ teamDir =        │  │
│  │              │              │   resolve(root)  │  │
│  └──────────────┘              └──────────────────┘  │
│                                                      │
│  Returns: { mode, projectDir, teamDir, config,       │
│             name, isLegacy }                         │
└─────────────────────────────────────────────────────┘

detectSquadDir() is preserved as a thin backward-compatible wrapper.

2. Remote Squad Mode

Run team state outside the project repo. The project keeps a thin .squad/ with a config pointer and project-specific artifacts.

┌──────────────────────────────┐    ┌──────────────────────────────┐
│     PROJECT REPO             │    │    TEAM ROOT (external)      │
│                              │    │                              │
│  .squad/                     │    │  team.md                     │
│  ├── config.json ────────────┼───▶│  routing.md                  │
│  │   { "teamRoot": "../.." } │    │  ceremonies.md               │
│  ├── decisions.md            │    │  agents/                     │
│  ├── decisions/inbox/        │    │  ├── ripley/charter.md       │
│  ├── log/                    │    │  ├── dallas/charter.md       │
│  └── orchestration-log/      │    │  casting/                    │
│                              │    │  ├── registry.json           │
│  (project-specific stays     │    │  skills/                     │
│   local, committed to        │    │  identity/                   │
│   project repo)              │    │  plugins/                    │
│                              │    │                              │
└──────────────────────────────┘    └──────────────────────────────┘

Commands:

  • npx github:bradygaster/squad --mode remote --team-root <path> — init with remote team
  • npx github:bradygaster/squad link --team-root <path> — link existing project to existing team

3. Squad Repo Mode

Specialization of remote mode where the team lives in its own git repo with a manifest tracking managed projects.

┌──────────────────────────────┐    ┌──────────────────────────────┐
│     PROJECT REPO A           │    │      SQUAD REPO              │
│                              │    │                              │
│  .squad/                     │    │  squad-manifest.json         │
│  └── config.json ────────────┼───▶│  ├── projects: [             │
│                              │    │  │   { key: "project-a" },   │
│                              │    │  │   { key: "project-b" }    │
│                              │    │  │ ]                         │
├──────────────────────────────┤    │                              │
│     PROJECT REPO B           │    │  team.md                     │
│                              │    │  agents/                     │
│  .squad/                     │    │  casting/                    │
│  └── config.json ────────────┼───▶│  skills/                     │
│                              │    │  ...                         │
└──────────────────────────────┘    └──────────────────────────────┘

Commands:

  • npx github:bradygaster/squad repo init — create standalone squad repo
  • npx github:bradygaster/squad repo link <path> — two-way link (config in project + manifest entry in squad repo)

4. Company of Squads (Hub Mode)

A hub repo manages multiple independent squads, each dedicated to a different project.

┌─────────────────────────────────────────────────┐
│               HUB REPO                          │
│                                                 │
│  squad-hub.json                                 │
│  ├── name: "Shayne's Company"                   │
│  └── squads: [...]                              │
│                                                 │
│  squads/                                        │
│  ├── project-alpha/          ◀── full team      │
│  │   ├── team.md                 state per      │
│  │   ├── routing.md              project         │
│  │   ├── agents/                                │
│  │   ├── casting/                               │
│  │   └── ...                                    │
│  │                                              │
│  ├── project-beta/           ◀── independent    │
│  │   ├── team.md                 squad with     │
│  │   ├── agents/                 own casting    │
│  │   └── ...                     & universe     │
│  │                                              │
│  └── project-gamma/          ◀── each squad     │
│      ├── team.md                 can be linked  │
│      └── ...                     to a project   │
│                                  repo           │
└─────────────────────────────────────────────────┘

Commands:

  • npx github:bradygaster/squad hub init — create hub with squads/ directory
  • npx github:bradygaster/squad hub add <project-name> — scaffold a new squad
  • npx github:bradygaster/squad hub list — show all managed squads with member counts

5. Doctor Command

Validates setup integrity for any mode:

🩺 Squad Doctor
═══════════════

Mode: remote

✅ .squad/ directory exists
✅ config.json valid (teamRoot: ../my-squad-repo)
✅ Team root resolves to existing directory
✅ team.md found with ## Members header
✅ routing.md found
✅ agents/ directory exists (4 agents)
❌ casting/registry.json — file not found
⚠️  teamRoot uses absolute path (less portable)

Summary: 6 passed, 1 failed, 1 warning

Architecture Decisions

File Ownership Split

The key insight: team identity is team-scoped (portable), while decisions and logs are project-scoped (stay local).

┌───────────────────────────────────────────────┐
│                 FILE OWNERSHIP                │
│                                               │
│  TEAM-SCOPED (lives at teamDir)               │
│  ├── team.md          roster                  │
│  ├── routing.md       work routing            │
│  ├── ceremonies.md    team ceremonies          │
│  ├── agents/          charters + history       │
│  ├── casting/         persistent names         │
│  ├── skills/          learned patterns         │
│  ├── identity/        focus + wisdom           │
│  └── plugins/         marketplace config       │
│                                               │
│  PROJECT-SCOPED (lives at projectDir)          │
│  ├── config.json      pointer to teamDir       │
│  ├── decisions.md     project decisions         │
│  ├── decisions/inbox/ agent decision drops      │
│  ├── log/             session logs              │
│  └── orchestration-log/  agent routing log      │
└───────────────────────────────────────────────┘

No Symlinks

Config pointer uses a JSON file with relative paths instead of symlinks. This avoids Windows admin/dev-mode requirements and works cross-platform without special filesystem permissions.

Backward Compatible

When no config.json exists, resolveSquadPaths() returns projectDir === teamDir — identical to the old detectSquadDir() behavior. Zero changes for existing users.


New CLI Commands

Command Description
--mode remote --team-root <path> Init with remote team state
link --team-root <path> Link existing project to existing team
repo init Create standalone squad repo with manifest
repo link <path> Two-way link project ↔ squad repo
hub init Create company hub
hub add <project-name> Add squad to hub
hub list List all hub squads
doctor Validate setup integrity

Cross-Platform

  • All paths use path.resolve() and path.join() — no string concatenation
  • No symlinks (Windows-safe)
  • Relative paths stored in config.json, resolved at runtime
  • Tested on Windows; uses os.tmpdir() and cross-platform fs APIs in tests

Setup Examples

Remote Squad (team outside project)

# Create team state somewhere
mkdir ~/squads/my-team

# Init project with remote team
cd my-project
npx github:bradygaster/squad --mode remote --team-root ~/squads/my-team

Link existing project to existing team

cd my-project
npx github:bradygaster/squad link --team-root ~/squads/my-team

Squad Repo

# Create squad repo
mkdir my-squad && cd my-squad && git init
npx github:bradygaster/squad repo init

# Link a project
cd ~/my-project
npx github:bradygaster/squad repo link ~/my-squad

Company Hub

mkdir company-hub && cd company-hub && git init
npx github:bradygaster/squad hub init
npx github:bradygaster/squad hub add project-alpha
npx github:bradygaster/squad hub add project-beta
npx github:bradygaster/squad hub list

# Link a project repo to a hub squad
cd ~/project-alpha
npx github:bradygaster/squad link --team-root ~/company-hub/squads/project-alpha

Validate any setup

npx github:bradygaster/squad doctor

Test Coverage

  • 86 existing tests — all pass (zero regressions)
  • 16 new tests in test/remote-mode.test.js:
    • Remote init creates config.json with correct relative teamRoot
    • Remote init creates project-local and team-identity artifacts
    • Link command validates and connects
    • Repo init/link lifecycle
    • Hub init/add/list lifecycle
    • Doctor validates local, remote, and hub modes

What's Deferred

  • Agent.md Coordinator updates (teaching the agent to resolve remote paths)
  • GitHub Actions workflow adaptation for external team state
  • Cross-repo skill sharing between company squads
  • hub upgrade command for batch-upgrading all squads (Automatic Squad update #96)

spboyer and others added 2 commits February 21, 2026 23:12
Add three new capabilities to Squad CLI:

1. Remote Squad Mode: --mode remote --team-root <path> for init,
   plus 'link' subcommand to connect existing projects to external
   team state. Thin .squad/config.json pointer in project, full
   team identity lives elsewhere.

2. Squad Repo: 'repo init' creates standalone squad repos with
   manifest tracking. 'repo link' creates two-way project linking.

3. Company of Squads: 'hub init', 'hub add', 'hub list' for
   managing multiple independent squads via directory convention
   (squads/{project-name}/).

4. Doctor: 'doctor' subcommand validates setup integrity for
   local, remote, and hub modes.

Foundation: resolveSquadPaths() dual-root resolver replaces
detectSquadDir() for all path resolution. Local mode behavior
is completely unchanged (backward compatible).

All 86 existing tests pass.

Relates-to: bradygaster#96, bradygaster#8

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
16 new tests covering:
- Remote init with --mode remote --team-root
- link command for connecting projects to external teams
- repo init and repo link for standalone squad repos
- hub init, hub add, hub list for company of squads
- doctor command validation for local, remote, and hub modes

All 102 tests pass (86 existing + 16 new).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bradygaster added a commit that referenced this pull request Mar 4, 2026
Session: 2026-02-23T0113-pr131-issues-created
Coordinator created 4 GitHub issues (bradygaster/squad-pr #311–#314) from team review of PR #131.

Changes:
- Logged PR #131 review outcome with 4 issues created
- Issues #311 (dual-root resolver), #312 (doctor command), #313 (remote mode CLI), #314 (SDK ensureSquadPath)
- All issues credit @spboyer
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bradygaster added a commit that referenced this pull request Mar 4, 2026
Port features from @spboyer (Shayne Boyer)'s PR #131:

- resolveSquadPaths() dual-root resolver (projectDir / teamDir) (#311)
- squad doctor command — 9-check setup validation (#312)
- squad link + squad init --mode remote (#313)
- ensureSquadPathDual() / ensureSquadPathResolved() (#314)
- Updated squad.agent.md with remote mode coordinator awareness
- Updated CHANGELOG with Shayne credit

Docs cleanup:
- Removed 30 stale internal docs (blog, architecture, test-scripts,
  SquadUI alignment, launch artifacts, completed PRDs/proposals)
- Kept user-facing guides, build tooling, migration docs

42 new tests, all passing.

Co-authored-by: Shayne Boyer <spboyer@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@bradygaster
Copy link
Owner

Thank you so much, Shayne! Your design for Remote Squad Mode has been the foundation that drove our implementation. We've ported the core concepts and features from PR #131 and they're now live in the main branch. Here's the mapping:

Features Implemented


esolveSquadPaths()\ — Unified Dual-Root Resolver
(#311)
The heart of remote mode. Replaces \detectSquadDir()\ with rich path resolution supporting both local and remote team configurations.

\squad doctor\ Command (#312)
Setup validation with 9-check integrity test. Validates config.json, team root resolution, team identity structure, and setup portability.

✅ *\squad link \ & \squad init --mode remote* (#313)
Commands to link projects to external team roots and initialize with remote team state. Users can now run team identity outside the project repo.

Dual-Root Write Guards (#314)
\�nsureSquadPathDual()\ / \�nsureSquadPathResolved()\ — guards ensuring writes go to the right location (project-local vs team-scoped).

Why We're Closing

The team identity separation and remote mode architecture you proposed are now built into the SDK. The fundamental insight — that team state should be portable and separate from project decisions — is now the default pattern.

The implementation has evolved (repo mode and hub mode specialized from your core design), but your contribution is threaded through every feature.

Thanks for thinking ahead about how teams should work. Your work made it easy for us to scale to dedicated squad repos and company hubs. 🙏

@bradygaster
Copy link
Owner

Closing this in favor of the implementation that's now live in main. All the core features are in place and the team is scaling well with the patterns you pioneered.

@bradygaster bradygaster closed this Mar 4, 2026
bradygaster added a commit that referenced this pull request Mar 4, 2026
Session: 20260304T194304Z-community-pr-triage

Changes:
- Logged Keaton's PR #131 review and closure
- Logged Kobayashi's issue #175 and PR #182 closure
- Created session log for community triage
- No decision inbox files to merge

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants