All other .gsd/ state files use uppercase naming (DECISIONS.md, REQUIREMENTS.md, PROJECT.md, etc). This renames the canonical preferences file to PREFERENCES.md while keeping a migration fallback — the loader checks PREFERENCES.md first, then falls back to lowercase preferences.md for existing installations. Closes #2700 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
26 KiB
GSD Preferences Reference
Full documentation for ~/.gsd/PREFERENCES.md (global) and .gsd/PREFERENCES.md (project).
Notes
- Keep this skill-first.
- Prefer explicit skill names or absolute paths.
- Use absolute paths for personal/local skills when you want zero ambiguity.
- These preferences guide which skills GSD should load and follow; they do not override higher-priority instructions in the current conversation.
- For Claude marketplace/plugin import behavior, see
~/.gsd/agent/extensions/gsd/docs/claude-marketplace-import.md.
Semantics
Empty Arrays vs Omitted Fields
Empty arrays ([]) are equivalent to omitting the field entirely. During validation, GSD deletes empty arrays from the preferences object (see validatePreferences() in preferences.ts):
for (const key of [
"always_use_skills",
"prefer_skills",
"avoid_skills",
"custom_instructions",
] as const) {
if (validated[key] && validated[key]!.length === 0) {
delete validated[key];
}
}
These are functionally identical:
# Explicit empty arrays — will be normalized away
prefer_skills: []
avoid_skills: []
skill_rules: []
# Omitted entirely — same result
# (just don't write these fields)
Recommendation: Omit fields you don't need. Empty arrays add noise with no effect.
Global vs Project Preferences
Preferences are loaded from two locations and merged:
- Global:
~/.gsd/PREFERENCES.md— applies to all projects - Project:
.gsd/PREFERENCES.md— applies to the current project only
Merge behavior (see mergePreferences() in preferences.ts):
- Scalar fields (
skill_discovery,budget_ceiling, etc.): Project wins if defined, otherwise global. Uses nullish coalescing (??). - Array fields (
always_use_skills,prefer_skills, etc.): Concatenated viamergeStringLists()(global first, then project). - Object fields (
models,git,auto_supervisor): Shallow merge via spread operator{ ...base, ...override }.
For models, project settings override global at the phase level. If global has planning: opus and project has planning: sonnet, the project wins. But if project omits research, global's research setting is preserved.
Skill Discovery vs Skill Preferences
These are separate concerns:
| Field | What it controls | Code reference |
|---|---|---|
skill_discovery |
Whether GSD looks for relevant skills during research | resolveSkillDiscoveryMode() in preferences.ts |
always_use_skills, prefer_skills, avoid_skills |
Which skills to use when they're found relevant | renderPreferencesForSystemPrompt() in preferences.ts |
Setting prefer_skills: [] does not disable skill discovery — it just means you have no preference overrides. Use skill_discovery: off to disable discovery entirely.
Field Guide
-
version: schema version. Start at1. -
mode: workflow mode —"solo"or"team". Sets sensible defaults for git and project settings based on your workflow. Mode defaults are the lowest priority layer — any explicit preference overrides them. Omit to configure everything manually.Setting soloteamgit.auto_pushtruefalsegit.push_branchesfalsetruegit.pre_merge_checkfalsetruegit.merge_strategy"squash""squash"git.isolation"worktree""worktree"unique_milestone_idsfalsetrueQuick setup:
/gsd mode(global) or/gsd mode project(project-level). -
always_use_skills: skills GSD should use whenever they are relevant. -
prefer_skills: soft defaults GSD should prefer when relevant. -
avoid_skills: skills GSD should avoid unless clearly needed. -
skill_rules: situational rules with a human-readablewhentrigger and one or more ofuse,prefer, oravoid. -
custom_instructions: extra durable instructions related to skill use. For operational project knowledge (recurring rules, gotchas, patterns), use.gsd/KNOWLEDGE.mdinstead — it's injected into every agent prompt automatically and agents can append to it during execution. -
models: per-stage model selection for auto-mode. Keys:research,planning,execution,execution_simple,completion,subagent. Values can be:- Simple string:
"claude-sonnet-4-6"— single model, no fallbacks - Provider-qualified string:
"bedrock/claude-sonnet-4-6"— targets a specific provider when the same model ID exists across multiple providers - Object with fallbacks:
{ model: "claude-opus-4-6", fallbacks: ["glm-5", "minimax-m2.5"] }— tries fallbacks in order if primary fails - Object with provider:
{ model: "claude-opus-4-6", provider: "bedrock" }— explicit provider targeting in object format - Omit a key to use whatever model is currently active. Fallbacks are tried when model switching fails (provider unavailable, rate limited, etc.).
- Simple string:
-
skill_staleness_days: number — skills unused for this many days get deprioritized during discovery. Set to0to disable staleness tracking. Default:60. -
skill_discovery: controls how GSD discovers and applies skills during auto-mode. Valid values:auto— skills are found and applied automatically without prompting.suggest— (default) skills are identified during research but not installed automatically.off— skill discovery is disabled entirely.
-
auto_supervisor: configures the auto-mode supervisor that monitors agent progress and enforces timeouts. Keys:model: model ID to use for the supervisor process (defaults to the currently active model).soft_timeout_minutes: minutes before the supervisor issues a soft warning (default: 20).idle_timeout_minutes: minutes of inactivity before the supervisor intervenes (default: 10).hard_timeout_minutes: minutes before the supervisor forces termination (default: 30).
-
git: configures GSD's git behavior. All fields are optional — omit any to use defaults. Keys:auto_push: boolean — automatically push commits to the remote after committing. Default:false.push_branches: boolean — push the milestone branch to the remote after commits. Default:false.remote: string — git remote name to push to. Default:"origin".snapshots: boolean — create snapshot commits (WIP saves) during long-running tasks. Default:false.pre_merge_check: boolean or"auto"— run pre-merge checks before merging a worktree back to the integration branch.truealways runs,falsenever runs,"auto"runs when CI is detected. Default:false.commit_type: string — override the conventional commit type prefix. Must be one of:feat,fix,refactor,docs,test,chore,perf,ci,build,style. Default: inferred from diff content.main_branch: string — the primary branch name for new git repos (e.g.,"main","master","trunk"). Also used bygetMainBranch()as the preferred branch when auto-detection is ambiguous. Default:"main".merge_strategy:"squash"or"merge"— controls how worktree branches are merged back."squash"combines all commits into one;"merge"preserves individual commits. Default:"squash".isolation:"worktree","branch", or"none"— controls auto-mode git isolation strategy."worktree"creates a milestone worktree for isolated work;"branch"works directly in the project root but creates a milestone branch (useful for submodule-heavy repos);"none"works directly on the current branch with no worktree or milestone branch (ideal for step-mode with hot reloads). Default:"worktree".manage_gitignore: boolean — whenfalse, GSD will not touch.gitignoreat all. Useful when your project has a strictly managed.gitignoreand you don't want GSD adding entries. Default:true.worktree_post_create: string — script to run after a worktree is created (both auto-mode and manual/worktree). ReceivesSOURCE_DIRandWORKTREE_DIRas environment variables. Can be absolute or relative to project root. Runs with 30-second timeout. Failure is non-fatal (logged as warning). Default: none.auto_pr: boolean — automatically create a GitHub pull request after a milestone branch is merged. RequiresghCLI to be installed. Default:false.pr_target_branch: string — branch to target whenauto_pris enabled. Defaults tomain_branchwhen omitted.- Deprecated:
commit_docs— no longer valid;.gsd/is always gitignored. Remove this setting. - Deprecated:
merge_to_main— no longer valid; milestone-level merge is always used. Remove this setting.
-
unique_milestone_ids: boolean — whentrue, generates milestone IDs inM{seq}-{rand6}format (e.g.M001-eh88as) instead of plain sequentialM001. Prevents ID collisions in team workflows where multiple contributors create milestones concurrently. Both formats coexist — existingM001-style milestones remain valid. Default:false. -
budget_ceiling: number — maximum dollar amount to spend on auto-mode. When reached, behavior is controlled bybudget_enforcement. Default: no limit. -
budget_enforcement:"warn","pause", or"halt"— action taken whenbudget_ceilingis reached.warn— log a warning but continue execution.pause— pause auto-mode and wait for user confirmation.halt— stop auto-mode immediately.- Default:
"pause".
-
context_pause_threshold: number (0-100) — context window usage percentage at which auto-mode should pause to suggest checkpointing. Set to0to disable. Default:0(disabled). -
token_profile:"budget","balanced", or"quality"— coordinates model selection, phase skipping, and context compression.budgetskips research/reassessment and uses cheaper models;balanced(default) skips research/reassessment to reduce token burn;qualityprefers higher-quality models. See token-optimization docs. -
phases: fine-grained control over which phases run. Usually set bytoken_profile, but can be overridden. Keys:skip_research: boolean — skip milestone-level research. Default:false.reassess_after_slice: boolean — run roadmap reassessment after each completed slice. Default:false.skip_reassess: boolean — force-disable roadmap reassessment even ifreassess_after_sliceis enabled. Default:false.skip_slice_research: boolean — skip per-slice research. Default:false.
-
remote_questions: route interactive questions to Slack/Discord for headless auto-mode. Keys:channel:"slack"or"discord"— channel type.channel_id: string or number — channel ID.timeout_minutes: number — question timeout in minutes (clamped 1-30).poll_interval_seconds: number — poll interval in seconds (clamped 2-30).
-
notifications: configures desktop notification behavior during auto-mode. Keys:enabled: boolean — master toggle for all notifications. Default:true.on_complete: boolean — notify when a unit completes. Default:true.on_error: boolean — notify on errors. Default:true.on_budget: boolean — notify when budget thresholds are reached. Default:true.on_milestone: boolean — notify when a milestone finishes. Default:true.on_attention: boolean — notify when manual attention is needed. Default:true.
-
cmux: configures cmux terminal integration when GSD is running inside a cmux workspace. Keys:enabled: boolean — master toggle for cmux integration. Default:false.notifications: boolean — route desktop notifications through cmux. Default:truewhen enabled.sidebar: boolean — publish status, progress, and log metadata to the cmux sidebar. Default:truewhen enabled.splits: boolean — run supported subagent work in visible cmux splits. Default:false.browser: boolean — reserve the future browser integration flag. Default:false.
-
dynamic_routing: configures the dynamic model router that adjusts model selection based on task complexity. Keys:enabled: boolean — enable dynamic routing. Default:false.tier_models: object — model overrides per complexity tier. Keys:light,standard,heavy. Values are model ID strings.escalate_on_failure: boolean — escalate to a higher-tier model when the current one fails. Default:true.budget_pressure: boolean — downgrade model tier when budget is under pressure. Default:true.cross_provider: boolean — allow routing across different providers. Default:true.hooks: boolean — enable routing hooks. Default:true.
-
auto_visualize: boolean — show a visualizer hint after each milestone completion in auto-mode. Default:false. -
auto_report: boolean — generate an HTML report snapshot after each milestone completion. Default:true. -
search_provider:"brave","tavily","ollama","native", or"auto"— selects the search backend for research phases."native"forces Anthropic's built-in web search only; provider values force that backend and disable native search;"auto"uses the default heuristic. Default:"auto". -
context_selection:"full"or"smart"— controls how files are inlined into context."full"inlines entire files;"smart"uses semantic chunking to include only the most relevant sections. Default is derived fromtoken_profile. -
parallel: configures parallel orchestration for running multiple slices concurrently. Keys:enabled: boolean — enable parallel execution. Default:false.max_workers: number — maximum concurrent workers (1-4). Default:2.budget_ceiling: number — optional per-parallel-run budget ceiling.merge_strategy:"per-slice"or"per-milestone"— when to merge worktree results back. Default:"per-milestone".auto_merge:"auto","confirm", or"manual"— merge behavior after completion."auto"merges immediately;"confirm"asks first;"manual"leaves branches for you. Default:"confirm".
-
verification_commands: string[] — shell commands to run as verification after task execution (e.g.,["npm test", "npm run lint"]). Commands run in order; if any fails, the task is marked as needing fixes. -
verification_auto_fix: boolean — whentrue, automatically attempt to fix verification failures instead of just reporting them. Default:false. -
verification_max_retries: number — maximum number of fix-and-retry cycles for verification failures. Default:0(no retries). -
uat_dispatch: boolean — whentrue, enables UAT (User Acceptance Testing) dispatch mode. Default:false. -
post_unit_hooks: array — hooks that fire after a unit completes. Each entry has:name: string — unique hook identifier.after: string[] — unit types that trigger this hook (e.g.,["execute-task"]).prompt: string — prompt sent to the LLM. Supports{milestoneId},{sliceId},{taskId}substitutions.max_cycles: number — max times this hook fires per trigger (default: 1, max: 10).model: string — optional model override.artifact: string — expected output file name (relative to task/slice dir). Hook is skipped if file already exists (idempotent).retry_on: string — if this file is produced instead of the artifact, re-run the trigger unit then re-run hooks.agent: string — agent definition file to use for hook execution.enabled: boolean — toggle without removing (default:true).
-
pre_dispatch_hooks: array — hooks that fire before a unit is dispatched. Each entry has:name: string — unique hook identifier.before: string[] — unit types to intercept.action:"modify","skip", or"replace"— what to do with the unit.prepend: string — text prepended to unit prompt (for"modify"action).append: string — text appended to unit prompt (for"modify"action).prompt: string — replacement prompt (for"replace"action; required when action is"replace").unit_type: string — override unit type label (for"replace"action).skip_if: string — for"skip"action: only skip if this file exists (relative to unit dir).model: string — optional model override when this hook fires.enabled: boolean — toggle without removing (default:true).
Action validation:
"modify"requires at least one ofprependorappend."replace"requiresprompt."skip"is valid with no additional fields.
Known unit types for
before/after:research-milestone,plan-milestone,research-slice,plan-slice,execute-task,complete-slice,replan-slice,reassess-roadmap,run-uat. -
experimental: opt-in experimental features. All features here are off by default — you must explicitly set each one totrueto enable it. Features in this block may change or be removed without a deprecation cycle while in experimental status. Keys:rtk: boolean — enable RTK (Real-Time Kompression) shell-command compression. When enabled, GSD wraps shell commands through the RTK binary to reduce token usage during command execution. RTK is downloaded automatically on first use if not already installed. Default:false(opt-in required). SetGSD_RTK_DISABLED=1in the environment to force-disable regardless of this preference.
Best Practices
- Keep
always_use_skillsshort. - Use
skill_rulesfor situational routing, not broad personality preferences. - Prefer skill names for stable built-in skills.
- Prefer absolute paths for local personal skills.
- Omit fields you don't need — empty arrays add noise with no effect.
Workflow Mode Examples
Solo developer — auto-push, simple IDs:
---
version: 1
mode: solo
---
Equivalent to setting git.auto_push: true, git.push_branches: false, git.pre_merge_check: false, git.merge_strategy: squash, git.isolation: worktree, unique_milestone_ids: false.
Team — unique IDs, push branches, pre-merge checks:
---
version: 1
mode: team
---
Equivalent to setting git.auto_push: false, git.push_branches: true, git.pre_merge_check: true, git.merge_strategy: squash, git.isolation: worktree, unique_milestone_ids: true.
Mode with overrides — team mode but with auto-push:
---
version: 1
mode: team
git:
auto_push: true
---
Gets all team defaults except auto_push, which is explicitly overridden to true. Any explicit setting always wins over the mode default.
Minimal Example
The cleanest preferences file only specifies what you actually want:
---
version: 1
always_use_skills:
- debug-like-expert
skill_discovery: suggest
models:
planning: claude-opus-4-6
execution: claude-sonnet-4-6
---
Everything else uses defaults. No prefer_skills: [], no avoid_skills: [], no auto_supervisor: {} — those are just noise.
Models Example
---
version: 1
models:
research: claude-sonnet-4-6
planning: claude-opus-4-6
execution: claude-sonnet-4-6
completion: claude-sonnet-4-6
---
Opus for planning (where architectural decisions matter most), Sonnet for everything else (faster, cheaper). Omit any key to use the currently selected model.
Models with Fallbacks Example
---
version: 1
models:
research:
model: openrouter/deepseek/deepseek-r1
fallbacks:
- openrouter/minimax/minimax-m2.5
planning:
model: claude-opus-4-6
fallbacks:
- openrouter/z-ai/glm-5
- openrouter/moonshotai/kimi-k2.5
execution:
model: openrouter/z-ai/glm-5
fallbacks:
- openrouter/minimax/minimax-m2.5
completion: openrouter/minimax/minimax-m2.5
---
When a model fails to switch (provider unavailable, rate limited, credits exhausted), GSD automatically tries the next model in the fallbacks list. This ensures auto-mode continues even when your preferred provider hits limits.
Provider Targeting
When the same model ID exists across multiple providers (e.g., claude-sonnet-4-6 on both Anthropic and Bedrock), use the provider/model format or the provider field to target a specific one:
---
version: 1
models:
# String format: provider/model
research: bedrock/claude-sonnet-4-6
planning: anthropic/claude-opus-4-6
# Object format: explicit provider field
execution:
model: claude-sonnet-4-6
provider: bedrock
fallbacks:
- anthropic/claude-sonnet-4-6
---
If you use a bare model ID (no provider prefix) and it exists in multiple providers, GSD will warn you and resolve to the first available match. Use provider/model format to avoid ambiguity.
Cost-optimized example — use cheap models with expensive ones as fallback for critical phases:
---
version: 1
models:
research: openrouter/deepseek/deepseek-r1 # $0.28/$0.42 per 1M tokens
planning:
model: claude-opus-4-6 # $5/$25 — best for architecture
fallbacks:
- openrouter/z-ai/glm-5 # $1/$3.20 — strong alternative
execution: openrouter/minimax/minimax-m2.5 # $0.30/$1.20 — cheapest quality
completion: openrouter/minimax/minimax-m2.5
---
Example Variations
Minimal — always load a UAT skill and route Clerk tasks:
---
version: 1
always_use_skills:
- /Users/you/.claude/skills/verify-uat
skill_rules:
- when: finishing implementation and human judgment matters
use:
- /Users/you/.claude/skills/verify-uat
---
Richer routing — prefer cleanup and authentication skills:
---
version: 1
prefer_skills:
- commit-ignore
skill_rules:
- when: task involves Clerk authentication
use:
- clerk
- clerk-setup
- when: the user is looking for installable capability rather than implementation
prefer:
- find-skills
---
Git Preferences Example
---
version: 1
git:
auto_push: true
push_branches: true
remote: origin
snapshots: true
pre_merge_check: auto
commit_type: feat
---
All git fields are optional. Omit any field to use the default behavior. Project-level preferences override global preferences on a per-field basis.
Budget & Cost Control Example
---
version: 1
budget_ceiling: 10.00
budget_enforcement: pause
context_pause_threshold: 80
---
Sets a $10 budget ceiling. Auto-mode pauses when the ceiling is reached. Context window pauses at 80% usage for checkpointing.
Notifications Example
---
version: 1
notifications:
enabled: true
on_complete: false
on_error: true
on_budget: true
on_milestone: true
on_attention: true
---
Disables per-unit completion notifications (noisy in long runs) while keeping error, budget, milestone, and attention notifications enabled.
cmux Example
---
version: 1
cmux:
enabled: true
notifications: true
sidebar: true
splits: true
browser: false
---
Enables cmux-aware notifications, sidebar metadata, and visible subagent splits when GSD is running inside a cmux terminal.
Post-Unit Hooks Example
---
version: 1
post_unit_hooks:
- name: code-review
after:
- execute-task
prompt: "Review the code changes in {sliceId}/{taskId} for quality, security, and test coverage."
max_cycles: 1
artifact: REVIEW.md
---
Runs an automated code review after each task execution. Skips if REVIEW.md already exists (idempotent).
Pre-Dispatch Hooks Examples
Modify — inject instructions before every task:
---
version: 1
pre_dispatch_hooks:
- name: enforce-standards
before:
- execute-task
action: modify
prepend: "Follow our TypeScript coding standards and always run linting."
---
Skip — skip per-slice research when a research file already exists:
---
version: 1
pre_dispatch_hooks:
- name: skip-existing-research
before:
- research-slice
action: skip
skip_if: RESEARCH.md
---
Replace — substitute a custom prompt for task execution:
---
version: 1
pre_dispatch_hooks:
- name: tdd-execute
before:
- execute-task
action: replace
prompt: "Implement the task using strict TDD. Write failing tests first, then implement, then refactor."
model: claude-opus-4-6
---
Token Profile & Phases Example
---
version: 1
token_profile: budget
phases:
skip_research: true
skip_reassess: true
skip_slice_research: false
---
Uses the budget profile to minimize token usage, with explicit override to keep slice-level research enabled.
Remote Questions Example
---
version: 1
remote_questions:
channel: slack
channel_id: "C0123456789"
timeout_minutes: 15
poll_interval_seconds: 10
---
Routes interactive questions to a Slack channel for headless auto-mode sessions. Questions time out after 15 minutes if unanswered.
Dynamic Routing Example
---
version: 1
dynamic_routing:
enabled: true
tier_models:
light: openrouter/minimax/minimax-m2.5
standard: claude-sonnet-4-6
heavy: claude-opus-4-6
escalate_on_failure: true
budget_pressure: true
---
Automatically selects model tier based on task complexity. Simple tasks use the light model, complex tasks escalate to heavy. Under budget pressure, tasks are routed to cheaper tiers.
Parallel Execution Example
---
version: 1
parallel:
enabled: true
max_workers: 3
merge_strategy: per-milestone
auto_merge: confirm
---
Runs up to 3 slices concurrently in separate worktrees. Results are merged per-milestone with user confirmation.
Verification Example
---
version: 1
verification_commands:
- npm test
- npm run lint
- npm run typecheck
verification_auto_fix: true
verification_max_retries: 2
---
Runs test, lint, and typecheck after each task. On failure, auto-fix is attempted up to 2 times before reporting the issue.
Experimental Features Example
---
version: 1
experimental:
rtk: true
---
Opts in to RTK shell-command compression. RTK is downloaded automatically on first use. Set GSD_RTK_DISABLED=1 to force-disable at the environment level regardless of this setting.