SKILL.md
gw Configuration Management
Config lives at .gw/config.json (committable) and .gw/config.local.json (gitignored, personal overrides). All worktrees in a repo share the same config.
MANDATORY: Config-Change Rules
Non-negotiable in any gw-tools repo.
| Situation | Required action |
|---|---|
Adding or renaming a Config field in types.ts |
Add a migration in config-migrations.ts, increment CURRENTCONFIGVERSION, update gw-config.schema.json, and update types.ts |
Removing a field from Config |
Same as above — use a migration to delete it; never just remove from code |
| Old field in existing configs must keep working | Write a migration that renames/transforms it. NEVER add backcompat shims in command code |
configVersion in a committed config |
Never edit it manually; gw manages it automatically |
gw-config.schema.json diverges from Config |
Fix immediately — the schema is additionalProperties: false and IDE errors surface in every committed config |
The canonical migration guide is in the project root CLAUDE.md under "Config Migration System". See also packages/gw-tool/src/lib/config-migrations.ts (current version: CURRENTCONFIGVERSION = 2).
Rules
| Rule | Description |
|---|---|
| [fundamentals](./rules/fundamentals.md) | HIGH - Config file location, creation, and precedence |
| [options-reference](./rules/options-reference.md) | HIGH - Complete reference for all config options |
| [setup](./rules/setup.md) | HIGH - Initial setup flow, secrets, team onboarding |
| [auto-copy](./rules/auto-copy.md) | HIGH - File patterns to copy, what to include/exclude |
| [team-config](./rules/team-config.md) | MEDIUM - Sharing config, documentation, onboarding |
| [advanced](./rules/advanced.md) | LOW - Multiple sources, secret management integration |
| [troubleshooting](./rules/troubleshooting.md) | HIGH - Common issues and solutions |
Complete Config Reference
{
// Added automatically by gw init — enables IDE autocompletion/validation
"$schema": "https://raw.githubusercontent.com/mthines/gw-tools/main/packages/gw-tool/schemas/gw-config.schema.json",
// Managed automatically — do not edit manually
"configVersion": 3,
// Branch whose worktree is the source for auto-copy and sync (default: "main")
// This worktree is protected from auto-clean.
"defaultBranch": "main",
// Files/dirs copied from defaultBranch worktree when gw checkout runs.
// Paths are relative to repo root. Directories end with /. Non-existent entries are skipped with a warning.
"autoCopyFiles": [".env", ".env.local", "secrets/"],
// Commands run before/after gw checkout. Supports variable substitution (see Hooks below).
"hooks": {
"checkout": {
// Pre-hooks: run before worktree creation. Failure aborts the checkout.
"pre": ["echo 'Creating: {worktree}'"],
// Post-hooks: run after successful creation. Failure warns but does NOT roll back.
"post": ["cd {worktreePath} && pnpm install"],
},
},
// Days before worktrees are considered stale for gw clean / auto-clean (default: 7)
"cleanThreshold": 7,
// When true, silently prunes stale worktrees after gw checkout / gw list.
// Never removes defaultBranch. Only removes worktrees with no uncommitted or unpushed changes. (default: false)
"autoClean": false,
// Default strategy for gw update: "merge" (preserves history) or "rebase" (linear). (default: "merge")
// Override per-command with --merge or --rebase flags.
"updateStrategy": "merge",
// Extra branch names to protect from gw clean and auto-clean.
// Managed with 'gw protect' / 'gw unprotect'. defaultBranch, main, master,
// and gw_root are always protected regardless of this list. (default: [])
"protectedBranches": ["staging", "release/v2"],
}
Local overrides — create .gw/config.local.json to override any field for your machine only. It is gitignored automatically and shallow-merged on top of config.json (local wins).
Hook Variables
Available for substitution in any hook command string:
| Variable | Value |
|---|---|
{worktree} |
Worktree name (e.g. feat/my-feature) |
{worktreePath} |
Absolute path to the new worktree |
{gitRoot} |
Absolute path to the bare git repository root |
{branch} |
Branch name (same as worktree name for gw checkout) |
Example using variables:
{
"hooks": {
"checkout": {
"post": ["cd {worktreePath} && pnpm install", "echo 'Ready at {worktreePath}'"],
},
},
}
Adding a Migration (required when changing Config)
When any field in packages/gw-tool/src/lib/types.ts's Config interface is added, renamed, or removed, follow this checklist — see root CLAUDE.md for the full authoritative process:
- Increment
CURRENTCONFIGVERSIONinconfig-migrations.ts - Add a migration entry to the
MIGRATIONSarray that transforms old configs and setsconfig.configVersion = <new version> - Update
types.tsto reflect the new shape - Update
schemas/gw-config.schema.json— add/remove/rename properties, update"default"onconfigVersionto the new version - Remove any command-level backcompat code — migrations own backwards compatibility
Migration skeleton:
{
version: 3, // next version number
description: 'Rename oldField to newField',
migrate: (config) => {
if (config.oldField !== undefined) {
config.newField = config.oldField;
delete config.oldField;
}
config.configVersion = 3;
return config;
},
}
Quick Command Reference
| Task | Command |
|---|---|
| Initialize config | gw init |
| Init with options | gw init --auto-copy-files .env,secrets/ --post-checkout "pnpm install" |
| Interactive setup | gw init --interactive |
| Clone and initialize | gw init [email protected]:user/repo.git |
| Show generated init command | gw show-init |
| Sync files to current worktree | gw sync |
| Sync to specific worktree | gw sync feat/branch |
| Sync specific files | gw sync feat/branch .env .env.local |
| Add file to autoCopyFiles (VS Code) | Command palette → gw: Add to Auto-Copy Files, or right-click a file in the Explorer or editor tab. Supports multi-file selection. Requires .gw/config.json to exist (gw init first). |
Anti-Patterns
| Anti-pattern | Correct approach |
|---|---|
Adding a Config field without a migration |
Always add a migration; bump CURRENTCONFIGVERSION |
| Handling an old field name in command code | Delete the handling; write a migration instead |
Editing configVersion in a config file by hand |
Let gw manage it; never edit manually |
Updating types.ts without updating gw-config.schema.json |
Both files must stay in sync — the schema is additionalProperties: false |
Listing node_modules/ or dist/ in autoCopyFiles |
Only list secrets and env files that won't regenerate |
Committing .gw/config.local.json |
It is gitignored by design; keep machine-specific overrides out of version control |
Adding absolute paths to autoCopyFiles |
Paths must be relative to the repo root |
Key Principles
- Set up secrets in
defaultBranchfirst — source must exist before auto-copy works. - Commit
config.jsonto version control — team members get it automatically. - Copy secrets, not dependencies —
.envyes,node_modules/no. - Migrations own backwards compat — never add shims in command code.
gw show-initdocuments your setup — generates a shareable init command from current config.
Related Skills
- [git-worktree-workflows](../git-worktree-workflows/) - Using worktrees effectively (gw checkout, gw cd, gw clean, etc.)
- autonomous-workflow - Autonomous development in isolated worktrees (lives in
mthines/agent-skills)
Resources
- [Project-Type Guides](./rules/project-types/) - Configuration guides for Next.js, Node.js API, monorepo, React SPA
- [Next.js Setup Example](./references/nextjs-setup.md)
- [Monorepo Setup Example](./references/monorepo-setup.md)
- [Troubleshooting Guide](./references/troubleshooting-config.md)