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": 2,
// 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",
}
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_VERSIONinconfig-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 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 |
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
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 - 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 - Configuration guides for Next.js, Node.js API, monorepo, React SPA
- Next.js Setup Example
- Monorepo Setup Example
- Troubleshooting Guide