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 CURRENT_CONFIG_VERSION, 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: CURRENT_CONFIG_VERSION = 2).
Rules
| Rule |
Description |
| fundamentals |
HIGH - Config file location, creation, and precedence |
| options-reference |
HIGH - Complete reference for all config options |
| setup |
HIGH - Initial setup flow, secrets, team onboarding |
| auto-copy |
HIGH - File patterns to copy, what to include/exclude |
| team-config |
MEDIUM - Sharing config, documentation, onboarding |
| advanced |
LOW - Multiple sources, secret management integration |
| troubleshooting |
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
CURRENT_CONFIG_VERSION in config-migrations.ts
- Add a migration entry to the
MIGRATIONS array that transforms old configs and sets config.configVersion = <new version>
- Update
types.ts to reflect the new shape
- Update
schemas/gw-config.schema.json — add/remove/rename properties, update "default" on configVersion to 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 git@github.com: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 CURRENT_CONFIG_VERSION |
| 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
defaultBranch first — source must exist before auto-copy works.
- Commit
config.json to version control — team members get it automatically.
- Copy secrets, not dependencies —
.env yes, node_modules/ no.
- Migrations own backwards compat — never add shims in command code.
gw show-init documents your setup — generates a shareable init command from current config.
Related Skills
Resources
1---2name: gw-config-management3description: Configure .gw/config.json for gw-tools repos — auto-copy files, hooks, cleanup thresholds, update strategy, and the config migration system. Use when: setting up gw for a new project, adding or changing a config field, adding a hook, configuring auto-copy patterns, asking what fields gw config supports, running gw init, adding a migration, bumping configVersion, keeping schema.json in sync, or troubleshooting missing env files in worktrees.4license: MIT5---67# gw Configuration Management89Config lives at `.gw/config.json` (committable) and `.gw/config.local.json`10(gitignored, personal overrides). All worktrees in a repo share the same config.1112## MANDATORY: Config-Change Rules1314**Non-negotiable in any gw-tools repo.**1516| Situation | Required action |17| ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------ |18| Adding or renaming a `Config` field in `types.ts` | Add a migration in `config-migrations.ts`, increment `CURRENT_CONFIG_VERSION`, update `gw-config.schema.json`, and update `types.ts` |19| Removing a field from `Config` | Same as above — use a migration to delete it; never just remove from code |20| Old field in existing configs must keep working | Write a migration that renames/transforms it. NEVER add backcompat shims in command code |21| `configVersion` in a committed config | Never edit it manually; gw manages it automatically |22| `gw-config.schema.json` diverges from `Config` | Fix immediately — the schema is `additionalProperties: false` and IDE errors surface in every committed config |2324The canonical migration guide is in the project root `CLAUDE.md` under25"Config Migration System". See also `packages/gw-tool/src/lib/config-migrations.ts`26(current version: `CURRENT_CONFIG_VERSION = 2`).2728## Rules2930| Rule | Description |31| ------------------------------------------------- | --------------------------------------------------------- |32| [fundamentals](./rules/fundamentals.md) | **HIGH** - Config file location, creation, and precedence |33| [options-reference](./rules/options-reference.md) | **HIGH** - Complete reference for all config options |34| [setup](./rules/setup.md) | **HIGH** - Initial setup flow, secrets, team onboarding |35| [auto-copy](./rules/auto-copy.md) | **HIGH** - File patterns to copy, what to include/exclude |36| [team-config](./rules/team-config.md) | **MEDIUM** - Sharing config, documentation, onboarding |37| [advanced](./rules/advanced.md) | **LOW** - Multiple sources, secret management integration |38| [troubleshooting](./rules/troubleshooting.md) | **HIGH** - Common issues and solutions |3940## Complete Config Reference4142```jsonc43{44 // Added automatically by gw init — enables IDE autocompletion/validation45 "$schema": "https://raw.githubusercontent.com/mthines/gw-tools/main/packages/gw-tool/schemas/gw-config.schema.json",4647 // Managed automatically — do not edit manually48 "configVersion": 3,4950 // Branch whose worktree is the source for auto-copy and sync (default: "main")51 // This worktree is protected from auto-clean.52 "defaultBranch": "main",5354 // Files/dirs copied from defaultBranch worktree when gw checkout runs.55 // Paths are relative to repo root. Directories end with /. Non-existent entries are skipped with a warning.56 "autoCopyFiles": [".env", ".env.local", "secrets/"],5758 // Commands run before/after gw checkout. Supports variable substitution (see Hooks below).59 "hooks": {60 "checkout": {61 // Pre-hooks: run before worktree creation. Failure aborts the checkout.62 "pre": ["echo 'Creating: {worktree}'"],63 // Post-hooks: run after successful creation. Failure warns but does NOT roll back.64 "post": ["cd {worktreePath} && pnpm install"],65 },66 },6768 // Days before worktrees are considered stale for gw clean / auto-clean (default: 7)69 "cleanThreshold": 7,7071 // When true, silently prunes stale worktrees after gw checkout / gw list.72 // Never removes defaultBranch. Only removes worktrees with no uncommitted or unpushed changes. (default: false)73 "autoClean": false,7475 // Default strategy for gw update: "merge" (preserves history) or "rebase" (linear). (default: "merge")76 // Override per-command with --merge or --rebase flags.77 "updateStrategy": "merge",7879 // Extra branch names to protect from gw clean and auto-clean.80 // Managed with 'gw protect' / 'gw unprotect'. defaultBranch, main, master,81 // and gw_root are always protected regardless of this list. (default: [])82 "protectedBranches": ["staging", "release/v2"],83}84```8586**Local overrides** — create `.gw/config.local.json` to override any field for your machine only.87It is gitignored automatically and shallow-merged on top of `config.json` (local wins).8889## Hook Variables9091Available for substitution in any hook command string:9293| Variable | Value |94| ---------------- | ----------------------------------------------------- |95| `{worktree}` | Worktree name (e.g. `feat/my-feature`) |96| `{worktreePath}` | Absolute path to the new worktree |97| `{gitRoot}` | Absolute path to the bare git repository root |98| `{branch}` | Branch name (same as worktree name for `gw checkout`) |99100Example using variables:101102```jsonc103{104 "hooks": {105 "checkout": {106 "post": ["cd {worktreePath} && pnpm install", "echo 'Ready at {worktreePath}'"],107 },108 },109}110```111112## Adding a Migration (required when changing `Config`)113114When any field in `packages/gw-tool/src/lib/types.ts`'s `Config` interface is115added, renamed, or removed, follow this checklist — see root `CLAUDE.md` for116the full authoritative process:1171181. Increment `CURRENT_CONFIG_VERSION` in `config-migrations.ts`1192. Add a migration entry to the `MIGRATIONS` array that transforms old configs and sets `config.configVersion = <new version>`1203. Update `types.ts` to reflect the new shape1214. Update `schemas/gw-config.schema.json` — add/remove/rename properties, update `"default"` on `configVersion` to the new version1225. Remove any command-level backcompat code — migrations own backwards compatibility123124Migration skeleton:125126```typescript127{128 version: 3, // next version number129 description: 'Rename oldField to newField',130 migrate: (config) => {131 if (config.oldField !== undefined) {132 config.newField = config.oldField;133 delete config.oldField;134 }135 config.configVersion = 3;136 return config;137 },138}139```140141## Quick Command Reference142143| Task | Command |144| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |145| Initialize config | `gw init` |146| Init with options | `gw init --auto-copy-files .env,secrets/ --post-checkout "pnpm install"` |147| Interactive setup | `gw init --interactive` |148| Clone and initialize | `gw init git@github.com:user/repo.git` |149| Show generated init command | `gw show-init` |150| Sync files to current worktree | `gw sync` |151| Sync to specific worktree | `gw sync feat/branch` |152| Sync specific files | `gw sync feat/branch .env .env.local` |153| 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). |154155## Anti-Patterns156157| Anti-pattern | Correct approach |158| ------------------------------------------------------------ | ---------------------------------------------------------------------------------- |159| Adding a `Config` field without a migration | Always add a migration; bump `CURRENT_CONFIG_VERSION` |160| Handling an old field name in command code | Delete the handling; write a migration instead |161| Editing `configVersion` in a config file by hand | Let gw manage it; never edit manually |162| Updating `types.ts` without updating `gw-config.schema.json` | Both files must stay in sync — the schema is `additionalProperties: false` |163| Listing `node_modules/` or `dist/` in `autoCopyFiles` | Only list secrets and env files that won't regenerate |164| Committing `.gw/config.local.json` | It is gitignored by design; keep machine-specific overrides out of version control |165| Adding absolute paths to `autoCopyFiles` | Paths must be relative to the repo root |166167## Key Principles168169- **Set up secrets in `defaultBranch` first** — source must exist before auto-copy works.170- **Commit `config.json` to version control** — team members get it automatically.171- **Copy secrets, not dependencies** — `.env` yes, `node_modules/` no.172- **Migrations own backwards compat** — never add shims in command code.173- **`gw show-init` documents your setup** — generates a shareable init command from current config.174175## Related Skills176177- [git-worktree-workflows](../git-worktree-workflows/) - Using worktrees effectively (gw checkout, gw cd, gw clean, etc.)178- [autonomous-workflow](https://github.com/mthines/agent-skills#autonomous-workflow) - Autonomous development in isolated worktrees (lives in `mthines/agent-skills`)179180## Resources181182- [Project-Type Guides](./rules/project-types/) - Configuration guides for Next.js, Node.js API, monorepo, React SPA183- [Next.js Setup Example](./references/nextjs-setup.md)184- [Monorepo Setup Example](./references/monorepo-setup.md)185- [Troubleshooting Guide](./references/troubleshooting-config.md)