From 13a4c9b2452b0b0e8af9cc9dc944be773175e61d Mon Sep 17 00:00:00 2001 From: James Sturtevant Date: Tue, 10 Mar 2026 18:12:00 -0700 Subject: [PATCH] fix(docs): replace ~/.squad/ with platform-specific path references Closes #343 Replaces hardcoded `~/.squad/` references throughout documentation and code comments with platform-aware descriptions. The SDK correctly resolves personal squad paths via `resolveGlobalSquadPath()`: - Linux: `~/.config/squad/` - macOS: `~/Library/Application Support/squad/` - Windows: `%APPDATA%\squad\` However, docs were consistently using `~/.squad/` which doesn't match any platform's actual path. Changed: - personal-squad.md: Added platform table, replaced all hardcoded paths - installation.md: Clarified platform-specific paths in setup instructions - cli.md, config.md, sdk.md: Updated resolution order documentation - api-reference.md: Expanded path examples for all platforms - consult.ts: Updated JSDoc comments to reference the resolver function Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/cli/installation.md | 30 +++++++++----- docs/get-started/installation.md | 2 +- docs/guide/personal-squad.md | 49 ++++++++++++++--------- docs/reference/cli.md | 4 +- docs/reference/config.md | 2 +- docs/reference/sdk.md | 4 +- docs/sdk/api-reference.md | 9 ++++- packages/squad-sdk/src/sharing/consult.ts | 10 ++--- 8 files changed, 68 insertions(+), 42 deletions(-) diff --git a/docs/cli/installation.md b/docs/cli/installation.md index e61302183..7478d5ed6 100644 --- a/docs/cli/installation.md +++ b/docs/cli/installation.md @@ -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 @@ -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 @@ -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 @@ -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 diff --git a/docs/get-started/installation.md b/docs/get-started/installation.md index e1c4fafaa..6a5a17b0d 100644 --- a/docs/get-started/installation.md +++ b/docs/get-started/installation.md @@ -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. --- diff --git a/docs/guide/personal-squad.md b/docs/guide/personal-squad.md index 8d8ee1b0a..1b371c167 100644 --- a/docs/guide/personal-squad.md +++ b/docs/guide/personal-squad.md @@ -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: @@ -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. ``` @@ -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 ``` @@ -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. ``` @@ -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. @@ -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 } ``` @@ -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. @@ -241,7 +250,7 @@ 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. @@ -249,12 +258,12 @@ Over time, your personal squad becomes an opinionated workflow engine. Not becau ## 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 @@ -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) @@ -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. --- diff --git a/docs/reference/cli.md b/docs/reference/cli.md index a91fbdbd0..b9fb6ffbe 100644 --- a/docs/reference/cli.md +++ b/docs/reference/cli.md @@ -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 ` | 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 | @@ -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. diff --git a/docs/reference/config.md b/docs/reference/config.md index 46f3152c5..9e1f18856 100644 --- a/docs/reference/config.md +++ b/docs/reference/config.md @@ -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. diff --git a/docs/reference/sdk.md b/docs/reference/sdk.md index 8ebe178d4..a93a5cc52 100644 --- a/docs/reference/sdk.md +++ b/docs/reference/sdk.md @@ -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 ``` diff --git a/docs/sdk/api-reference.md b/docs/sdk/api-reference.md index 0b4636a6e..0206ba132 100644 --- a/docs/sdk/api-reference.md +++ b/docs/sdk/api-reference.md @@ -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` diff --git a/packages/squad-sdk/src/sharing/consult.ts b/packages/squad-sdk/src/sharing/consult.ts index 01ecca243..d8f278be5 100644 --- a/packages/squad-sdk/src/sharing/consult.ts +++ b/packages/squad-sdk/src/sharing/consult.ts @@ -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 */ @@ -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 @@ -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', ''); @@ -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');