Skip to content
Closed
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
30 changes: 21 additions & 9 deletions docs/cli/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,10 @@ squad init --global
```

**What happens:**
1. Creates `~/.squad/` (Unix/Mac) or `%USERPROFILE%\.squad\` (Windows)
1. Creates your personal squad directory at a platform-specific path:
- Linux: `~/.config/squad/`
- macOS: `~/Library/Application Support/squad/`
- Windows: `%APPDATA%\squad\`
2. Scaffolds standard team structure
3. Sets up agents that can be inherited by project squads

Expand All @@ -125,13 +128,16 @@ squad init --global
# 1. Set up personal squad (one-time)
squad init --global

# 2. Create a personal upstream practice doc
mkdir ~/.squad/skills/personal-guidelines
echo "# My Python conventions..." > ~/.squad/skills/personal-guidelines/SKILL.md
# 2. Create a personal upstream practice doc (use your actual path)
# Linux: ~/.config/squad/.squad/skills/
# macOS: ~/Library/Application Support/squad/.squad/skills/
# Windows: %APPDATA%\squad\.squad\skills\
mkdir -p "$(squad status | grep 'Global squad:' | cut -d' ' -f3)/.squad/skills/personal-guidelines"
echo "# My Python conventions..." > "$(squad status | grep 'Global squad:' | cut -d' ' -f3)/.squad/skills/personal-guidelines/SKILL.md"

# 3. In a project, inherit from personal squad
cd ~/my-project
squad upstream add ~/.squad --name personal
squad upstream add "$(resolveGlobalSquadPath)" --name personal

# 4. Now all agents in this project inherit from personal squad
squad # launch shell
Expand All @@ -141,25 +147,31 @@ squad # launch shell

### Global vs. Local Squad

| Aspect | Global (`~/.squad/`) | Local (`./.squad/`) |
| Aspect | Global (personal squad) | Local (`./.squad/`) |
|--------|-----|-----|
| **Created by** | `squad init --global` | `squad init` |
| **Location** | Platform-specific (see below) | Project root |
| **Scope** | All projects on this machine | Single project |
| **Inheritance** | Can be upstream for local squads | Can inherit from global |
| **History** | Persistent across projects | Per-project learning |
| **Shared agents** | Yes (optional setup) | No |
| **Used when** | No `.squad/` in project + parents | Found in project hierarchy |

**Platform-specific paths:**
- Linux: `~/.config/squad/`
- macOS: `~/Library/Application Support/squad/`
- Windows: `%APPDATA%\squad\`

### Resolution Order

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 `@bradygaster/squad-cli` default (fallback only)

**First match wins.** If you're in a project with `.squad/`, the global `~/.squad/` is ignored (but can be an upstream).
**First match wins.** If you're in a project with `.squad/`, the global personal squad is ignored (but can be an upstream).

## Commands at a Glance

Expand Down Expand Up @@ -241,7 +253,7 @@ squad init

# Or use global squad:
squad init --global
# Then projects will inherit from ~/.squad/
# Then projects will inherit from your personal squad
```

### "npm ERR! code E403" when installing globally
Expand Down
2 changes: 1 addition & 1 deletion docs/get-started/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ 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 global team root that any project can inherit from. See [Upstream Inheritance](../features/upstream-inheritance.md) for details.

---

Expand Down
49 changes: 29 additions & 20 deletions docs/guide/personal-squad.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ 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 a global directory. Every project you work in can point to it.

What that means in practice:

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

```
✅ Personal squad initialized.
~/.squad/ — your global team root
Your global team root (platform-specific path)
Agents, skills, and casting will be shared across projects.
```

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

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

```
✅ Squad initialized.
.squad/config.json → teamRoot: ~/.squad/
.squad/config.json → teamRoot: {global path}
Team identity inherited from personal squad.
Project-local state (decisions, logs) stays here.
```
Expand All @@ -100,15 +100,24 @@ 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

This is your **team identity**. It contains:
This is your **team identity**. It's stored in a platform-specific location:

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

It contains:

```
~/.squad/
agents/ — your agent charters and histories
casting/ — who's been cast, role assignments
skills/ — accumulated knowledge ("always use Zod", "prefer Tailwind")
{global-path}/
.squad/
agents/ — your agent charters and histories
casting/ — who's been cast, role assignments
skills/ — accumulated knowledge ("always use Zod", "prefer Tailwind")
```

This is the stuff that makes your agents *yours*. It persists across sessions. It grows as you work. It follows you from project to project.
Expand All @@ -120,7 +129,7 @@ Inside each connected project, `.squad/config.json` looks like this:
```json
{
"version": 1,
"teamRoot": "~/.squad/",
"teamRoot": "{platform-specific global squad path}",
"projectKey": null
}
```
Expand All @@ -129,14 +138,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 | global squad directory (platform-specific) |
| 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 global 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 @@ -241,20 +250,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's skills directory. Every project contributes.

After a few weeks:

```
~/.squad/skills/
{global-squad-path}/.squad/skills/
always-use-zod.md
prefer-tailwind.md
cursor-pagination.md
Expand All @@ -281,7 +290,7 @@ What works well today:
- Consistent agent behavior everywhere you work

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 is local to your machine
- Project keys aren't used for anything yet (that `null` in config.json)
- The resolution system is simple — no conflict handling if team identity diverges
- No UI for browsing your global skills or agent histories (it's files for now)
Expand All @@ -293,10 +302,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.
- **Check status anytime.** `squad status` shows your global squad directory and which projects are connected.
- **Commit project `.squad/` but not your personal squad.** 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 path 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 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.
- **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
4 changes: 2 additions & 2 deletions 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 at a platform-specific path | 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. Your 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/reference/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,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/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 path (platform-specific: `~/.config/squad/` on Linux, `~/Library/Application Support/squad/` on macOS, `%APPDATA%\squad\` on Windows) |
| `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(); // '/home/user/.config/squad' (Linux)
const safePath = ensureSquadPath(); // Creates if needed
```

Expand Down
9 changes: 7 additions & 2 deletions docs/sdk/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,18 @@ try {

### `resolveGlobalSquadPath(): string`

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

```typescript
import { resolveGlobalSquadPath } from '@bradygaster/squad-sdk';

const globalSquad = resolveGlobalSquadPath();
// → /home/user/.squad (or C:\Users\user\.squad on Windows)
// → /home/user/.config/squad (on Linux)
// → /Users/user/Library/Application Support/squad (on macOS)
// → C:\Users\user\AppData\Roaming\squad (on Windows)
```

### `ensureSquadPath(startPath?: string): string`
Expand Down
10 changes: 5 additions & 5 deletions packages/squad-sdk/src/sharing/consult.ts
Original file line number Diff line number Diff line change
Expand Up @@ -895,7 +895,7 @@ export interface ExtractionResult {
* Creates the consultations directory if it doesn't exist.
* For new projects, creates a full header; for existing projects, appends session entry.
*
* @param personalSquadRoot - Path to personal squad root (e.g. ~/.config/squad/.squad)
* @param personalSquadRoot - Path to personal squad root (platform-specific via resolveGlobalSquadPath())
* @param result - Extraction result with learnings and metadata
* @returns Path to the consultation log file
*/
Expand Down 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 {personalSquadRoot}/skills/{name}/SKILL.md
* Routes decisions to {personalSquadRoot}/decisions.md (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 {personalSquadRoot}/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 {personalSquadRoot}/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