Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion docs/src/content/docs/get-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,15 @@ Want the same agents across all your projects?
squad init --global
```

This creates `~/.squad/` — a personal team root that any project can inherit from. See [Upstream Inheritance](../features/upstream-inheritance.md) for details.
This creates your personal squad directory — a personal team root that any project can inherit from. See [Upstream Inheritance](../features/upstream-inheritance.md) for details.

**Personal squad location by platform:**

| Platform | Path |
|----------|------|
| Linux | `~/.config/squad/` |
| macOS | `~/Library/Application Support/squad/` |
| Windows | `%APPDATA%\squad\` |

---

Expand Down
38 changes: 23 additions & 15 deletions docs/src/content/docs/guide/personal-squad.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,15 @@ This tutorial walks you through setup, explains what's happening behind the scen

Normally, Squad lives inside a single project — `.squad/` in your repo root. Your agents know that project. They don't know your other ones.

A personal squad flips that. Your team identity — agents, charters, skills, casting history — moves to a global directory (`~/.squad/`). Every project you work in can point to it.
A personal squad flips that. Your team identity — agents, charters, skills, casting history — moves to your personal squad directory. Every project you work in can point to it.

**Personal squad location by platform:**

| Platform | Path |
|----------|------|
| Linux | `~/.config/squad/` |
| macOS | `~/Library/Application Support/squad/` |
| Windows | `%APPDATA%\squad\` |

What that means in practice:

Expand Down Expand Up @@ -51,7 +59,7 @@ You'll see:

```
✅ Personal squad initialized.
~/.squad/ — your global team root
{personal squad directory} — your global team root
Agents, skills, and casting will be shared across projects.
```

Expand All @@ -65,7 +73,7 @@ squad status

```
Squad Status
Global squad: ~/.squad/
Global squad: {personal squad directory}
Agents: 0 (none cast yet — start a session to form your team)
Skills: 0
```
Expand All @@ -85,7 +93,7 @@ Squad detects your global team root and writes a pointer:

```
✅ Squad initialized.
.squad/config.json → teamRoot: ~/.squad/
.squad/config.json → teamRoot: {personal squad directory}
Team identity inherited from personal squad.
Project-local state (decisions, logs) stays here.
```
Expand All @@ -100,12 +108,12 @@ Repeat for any project you want connected.

Two things were created. Understanding the split is the key to personal squads.

### The global directory: `~/.squad/`
### The global directory: your personal squad

This is your **team identity**. It contains:

```
~/.squad/
{personal squad directory}/
agents/ — your agent charters and histories
casting/ — who's been cast, role assignments
skills/ — accumulated knowledge ("always use Zod", "prefer Tailwind")
Expand All @@ -120,7 +128,7 @@ Inside each connected project, `.squad/config.json` looks like this:
```json
{
"version": 1,
"teamRoot": "~/.squad/",
"teamRoot": "{personal squad directory}",
"projectKey": null
}
```
Expand All @@ -129,14 +137,14 @@ That `teamRoot` field is the magic. When Squad's resolution system sees it, the

| | **Local mode** (default) | **Remote mode** (personal squad) |
|---|---|---|
| Team identity | `.squad/` in project | `~/.squad/` (global) |
| Team identity | `.squad/` in project | Personal squad directory (global) |
| Decisions & logs | `.squad/` in project | `.squad/` in project |
| Agents shared? | No — project only | Yes — across all connected projects |
| Skills shared? | No | Yes |

In remote mode:

- **Team identity** (agents, charters, skills, casting) → loaded from `~/.squad/`
- **Team identity** (agents, charters, skills, casting) → loaded from your personal squad directory
- **Project-local state** (decisions, logs, orchestration-log) → stays in this project's `.squad/`

The resolution system walks up directories looking for `.squad/`. When it finds one with a `teamRoot` in `config.json`, it switches to remote mode — pulling team identity from the external path while keeping project state local.
Expand Down Expand Up @@ -251,20 +259,20 @@ Set a directive once:
📌 Captured. Linting required before task completion.
```

That directive is now in `~/.squad/` — every project, every session. Your agents enforce it everywhere. You set the standard once and it sticks.
That directive is now in your personal squad directory — every project, every session. Your agents enforce it everywhere. You set the standard once and it sticks.

Over time, your personal squad becomes an opinionated workflow engine. Not because you configured it that way — because you worked with it and it learned.

---

## 8. Use Case: Skills That Grow Everywhere

Skills accumulate in `~/.squad/skills/`. Every project contributes.
Skills accumulate in your personal squad directory under `skills/`. Every project contributes.

After a few weeks:

```
~/.squad/skills/
{personal squad directory}/skills/
always-use-zod.md
prefer-tailwind.md
cursor-pagination.md
Expand Down Expand Up @@ -292,7 +300,7 @@ What works well today:
- **Consult mode** — bring your team to projects you don't own, invisibly ([docs](../features/consult-mode.md))

What's still rough:
- No sync mechanism between machines yet — `~/.squad/` is local to your machine
- No sync mechanism between machines yet — your personal squad directory is local to your machine
- Project keys aren't used for anything yet (that `null` in config.json)
- No UI for browsing your global skills or agent histories (it's files for now)

Expand All @@ -303,10 +311,10 @@ We're building in the open. If something feels off, [open an issue](https://gith
## Tips

- **Start with one project.** Get comfortable with the personal squad on one repo before connecting others. The value compounds, but so does confusion if something's misconfigured.
- **Commit project `.squad/` but not global `~/.squad/`.** The project-local state (decisions, logs) belongs in version control. Your global identity is personal — keep it out of repos.
- **Commit project `.squad/` but not personal squad directory.** The project-local state (decisions, logs) belongs in version control. Your global identity is personal — keep it out of repos.
- **Check status anytime.** `squad status` shows your global squad directory and which projects are connected.
- **Skills are the payoff.** The more projects you work across, the more skills accumulate. After a month, your agents have a real knowledge base tailored to how *you* build software.
- **It's just files.** `~/.squad/` is a directory on your machine. You can browse it, edit it, back it up, copy it to another machine manually. No magic, no cloud, no lock-in.
- **It's just files.** Your personal squad directory is a folder on your machine. You can browse it, edit it, back it up, copy it to another machine manually. No magic, no cloud, no lock-in.
- **Global install matters.** `npm install -g @bradygaster/squad-cli` gives you the `squad` command everywhere. Without it, you'd need `npx` in each project. Global CLI + global squad = full portability.

---
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/reference/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ const squadPath = resolveSquad('/home/user/project/src');

### `resolveGlobalSquadPath(): string`

Get path to global personal squad (`~/.squad/` on Unix, `%USERPROFILE%\.squad\` on Windows).
Get path to global personal squad. Returns platform-specific path: `~/.config/squad/` on Linux, `~/Library/Application Support/squad/` on macOS, `%APPDATA%\squad\` on Windows.

### `ensureSquadPath(startPath?: string): string`

Expand Down
4 changes: 2 additions & 2 deletions docs/src/content/docs/reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ squad init
|---------|-------------|:------------------:|
| `squad` | Enter interactive shell (no args) | No |
| `squad init` | Initialize Squad in the current repo (idempotent — safe to run multiple times) | No |
| `squad init --global` | Create a personal squad at `~/.squad/` | No |
| `squad init --global` | Create a personal squad in your platform-specific directory | No |
| `squad init --mode remote <path>` | Initialize linked to a remote team root (dual-root mode) | No |
| `squad start [--tunnel] [--port N] [--command cmd]` | Start Copilot with remote phone access via PTY and WebSocket | No |
| `squad status` | Show which squad is active and why | Yes |
Expand Down Expand Up @@ -239,7 +239,7 @@ When Squad starts, it looks for `.squad/` in this order:

1. Current directory (`./.squad/`)
2. Parent directories (walk up to project root)
3. Home directory (`~/.squad/`)
3. Personal squad directory (platform-specific: `~/.config/squad/` on Linux, `~/Library/Application Support/squad/` on macOS, `%APPDATA%\squad\` on Windows)
4. Global CLI default (fallback only)

First match wins.
Expand Down
2 changes: 1 addition & 1 deletion docs/src/content/docs/reference/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ Squad finds `.squad/` by walking up:

1. Current directory (`./.squad/`)
2. Parent directories (up to project root)
3. Home directory (`~/.squad/`)
3. Personal squad directory (platform-specific: `~/.config/squad/` on Linux, `~/Library/Application Support/squad/` on macOS, `%APPDATA%\squad\` on Windows)
4. Global CLI default (fallback)

First match wins.
Expand Down
4 changes: 2 additions & 2 deletions docs/src/content/docs/reference/sdk.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,12 @@ Find `.squad/` directories on disk.
| Function | Description |
|----------|-------------|
| `resolveSquad(startPath?)` | Find `.squad/` walking up from `startPath` (throws if not found) |
| `resolveGlobalSquadPath()` | Get `~/.squad/` path (`%USERPROFILE%\.squad\` on Windows) |
| `resolveGlobalSquadPath()` | Get personal squad directory path (platform-specific) |
| `ensureSquadPath(startPath?)` | Like `resolveSquad`, but creates `.squad/` if missing |

```typescript
const squadPath = resolveSquad(); // '/home/user/project/.squad'
const globalPath = resolveGlobalSquadPath(); // '/home/user/.squad'
const globalPath = resolveGlobalSquadPath(); // Platform-specific: ~/.config/squad/ (Linux), ~/Library/Application Support/squad/ (macOS), %APPDATA%\squad\ (Windows)
const safePath = ensureSquadPath(); // Creates if needed
```

Expand Down
8 changes: 4 additions & 4 deletions packages/squad-sdk/src/sharing/consult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1006,8 +1006,8 @@ function extractSkillName(content: string): string | null {
/**
* Merge staged learnings into personal squad.
*
* Routes skills to ~/.squad/skills/{name}/SKILL.md
* Routes decisions to ~/.squad/decisions.md (with smart merge)
* Routes skills to personal squad directory via resolveGlobalSquadPath() to skills/{name}/SKILL.md
* Routes decisions to decisions.md in personal squad directory (with smart merge)
*
* @param learnings - Staged learnings to merge
* @param personalSquadRoot - Path to personal squad root
Expand Down Expand Up @@ -1035,7 +1035,7 @@ export async function mergeToPersonalSquad(
}
}

// Route skills to ~/.squad/skills/{name}/SKILL.md
// Route skills to personal squad directory (via resolveGlobalSquadPath()) at skills/{name}/SKILL.md
const skillsDir = path.join(personalSquadRoot, 'skills');
for (const skill of skills) {
const skillName = extractSkillName(skill.content) || skill.filename.replace('.md', '');
Expand All @@ -1053,7 +1053,7 @@ export async function mergeToPersonalSquad(
skillsAdded++;
}

// Route decisions to ~/.squad/decisions.md
// Route decisions to personal squad directory at decisions.md
if (decisions.length > 0) {
const decisionsPath = path.join(personalSquadRoot, 'decisions.md');
const newContent = decisions.map(d => d.content.trim()).join('\n\n');
Expand Down
Loading