Skip to content

Configuration

GSD preferences live in ~/.gsd/PREFERENCES.md (global) or .gsd/PREFERENCES.md (project-local). Manage interactively with /gsd prefs.

CommandDescription
/gsd prefsOpen the global preferences wizard (default)
/gsd prefs globalInteractive wizard for global preferences (~/.gsd/PREFERENCES.md)
/gsd prefs projectInteractive wizard for project preferences (.gsd/PREFERENCES.md)
/gsd prefs statusShow current preference files, merged values, and skill resolution status
/gsd prefs wizardAlias for /gsd prefs global
/gsd prefs setupAlias for /gsd prefs wizard — creates preferences file if missing
/gsd prefs import-claudeImport Claude marketplace plugins and skills as namespaced GSD components
/gsd prefs import-claude globalImport to global scope
/gsd prefs import-claude projectImport to project scope

Preferences use YAML frontmatter in a markdown file:

---
version: 1
models:
research: claude-sonnet-4-6
planning: claude-opus-4-6
execution: claude-sonnet-4-6
completion: claude-sonnet-4-6
skill_discovery: suggest
auto_supervisor:
soft_timeout_minutes: 20
idle_timeout_minutes: 10
hard_timeout_minutes: 30
budget_ceiling: 50.00
token_profile: balanced
---
ScopePathApplies to
Global~/.gsd/PREFERENCES.mdAll projects
Project.gsd/PREFERENCES.mdCurrent project only

Merge behavior:

  • Scalar fields (skill_discovery, budget_ceiling): project wins if defined
  • Array fields (always_use_skills, etc.): concatenated (global first, then project)
  • Object fields (models, git, auto_supervisor): shallow-merged, project overrides per-key

Tool API keys are stored globally in ~/.gsd/agent/auth.json and apply to all projects automatically. Set them once with /gsd config — no need to configure per-project .env files.

Terminal window
/gsd config

This opens an interactive wizard showing which keys are configured and which are missing. Select a tool to enter its key.

ToolEnvironment VariablePurposeGet a key
Tavily SearchTAVILY_API_KEYWeb search for non-Anthropic modelstavily.com/app/api-keys
Brave SearchBRAVE_API_KEYWeb search for non-Anthropic modelsbrave.com/search/api
Context7 DocsCONTEXT7_API_KEYLibrary documentation lookupcontext7.com/dashboard
  1. /gsd config saves keys to ~/.gsd/agent/auth.json
  2. On every session start, loadToolApiKeys() reads the file and sets environment variables
  3. Keys apply to all projects — no per-project setup required
  4. Environment variables (export BRAVE_API_KEY=...) take precedence over saved keys
  5. Anthropic models don’t need Brave/Tavily — they have built-in web search

GSD can connect to external MCP servers configured in project files. This is useful for local tools, internal APIs, self-hosted services, or integrations that aren’t built in as native GSD extensions.

GSD reads MCP client configuration from these project-local paths:

  • .mcp.json
  • .gsd/mcp.json

If both files exist, server names are merged and the first definition found wins. Use:

  • .mcp.json for repo-shared MCP configuration you may want to commit
  • .gsd/mcp.json for local-only MCP configuration you do not want to share
TransportConfig shapeUse when
stdiocommand + optional args, env, cwdLaunching a local MCP server process
httpurlConnecting to an already-running MCP server over HTTP
{
"mcpServers": {
"my-server": {
"type": "stdio",
"command": "/absolute/path/to/python3",
"args": ["/absolute/path/to/server.py"],
"env": {
"API_URL": "http://localhost:8000"
}
}
}
}
{
"mcpServers": {
"my-http-server": {
"url": "http://localhost:8080/mcp"
}
}
}

After adding config, verify it from a GSD session:

mcp_servers
mcp_discover(server="my-server")
mcp_call(server="my-server", tool="<tool_name>", args={...})

Recommended verification order:

  1. mcp_servers — confirms GSD can see the config file and parse the server entry
  2. mcp_discover — confirms the server process starts and responds to tools/list
  3. mcp_call — confirms at least one real tool invocation works
  • Use absolute paths for local executables and scripts when possible.
  • For stdio servers, prefer setting required environment variables directly in the MCP config instead of relying on an interactive shell profile.
  • If a server is team-shared and safe to commit, .mcp.json is usually the better home.
  • If a server depends on machine-local paths, personal services, or local-only secrets, prefer .gsd/mcp.json.
VariableDefaultDescription
GSD_HOME~/.gsdGlobal GSD directory. All paths derive from this unless individually overridden. Affects preferences, skills, sessions, and per-project state. (v2.39)
GSD_PROJECT_ID(auto-hash)Override the automatic project identity hash. Per-project state goes to $GSD_HOME/projects/<GSD_PROJECT_ID>/ instead of the computed hash. Useful for CI/CD or sharing state across clones of the same repo. (v2.39)
GSD_STATE_DIR$GSD_HOMEPer-project state root. Controls where projects/<repo-hash>/ directories are created. Takes precedence over GSD_HOME for project state.
GSD_CODING_AGENT_DIR$GSD_HOME/agentAgent directory containing managed resources, extensions, and auth. Takes precedence over GSD_HOME for agent paths.
GSD_ALLOWED_COMMAND_PREFIXES(built-in list)Comma-separated command prefixes allowed for !command value resolution. Overrides allowedCommandPrefixes in settings.json. See Custom Models — Command Allowlist.
GSD_FETCH_ALLOWED_URLS(none)Comma-separated hostnames exempted from fetch_page URL blocking. Overrides fetchAllowedUrls in settings.json. See URL Blocking.

Per-phase model selection. Each key accepts a model string or an object with fallbacks.

models:
research: claude-sonnet-4-6
planning:
model: claude-opus-4-6
fallbacks:
- openrouter/z-ai/glm-5
execution: claude-sonnet-4-6
execution_simple: claude-haiku-4-5-20250414
completion: claude-sonnet-4-6
subagent: claude-sonnet-4-6

Phases: research, planning, execution, execution_simple, completion, subagent

  • execution_simple — used for tasks classified as “simple” by the complexity router
  • subagent — model for delegated subagent tasks (scout, researcher, worker)
  • Provider targeting: use provider/model format (e.g., bedrock/claude-sonnet-4-6) or the provider field in object format
  • Omit a key to use whatever model is currently active

Define custom models and providers in ~/.gsd/agent/models.json. This lets you add models not included in the default registry — useful for self-hosted endpoints (Ollama, vLLM, LM Studio), fine-tuned models, proxies, or new provider releases.

GSD resolves models.json with fallback logic:

  1. ~/.gsd/agent/models.json — primary (GSD)
  2. ~/.pi/agent/models.json — fallback (Pi)
  3. If neither exists, creates ~/.gsd/agent/models.json

Quick example for local models (Ollama):

{
"providers": {
"ollama": {
"baseUrl": "http://localhost:11434/v1",
"api": "openai-completions",
"apiKey": "ollama",
"models": [
{ "id": "llama3.1:8b" },
{ "id": "qwen2.5-coder:7b" }
]
}
}
}

The file reloads each time you open /model — no restart needed.

For full documentation including provider configuration, model overrides, OpenAI compatibility settings, and advanced examples, see the Custom Models Guide.

With fallbacks:

models:
planning:
model: claude-opus-4-6
fallbacks:
- openrouter/z-ai/glm-5
- openrouter/moonshotai/kimi-k2.5
provider: bedrock # optional: target a specific provider

When a model fails to switch (provider unavailable, rate limited, credits exhausted), GSD automatically tries the next model in the fallbacks list.

For providers not built into GSD, community extensions can add full provider support with proper model definitions, thinking format configuration, and interactive API key setup.

ExtensionProviderModelsInstall
pi-dashscopeAlibaba DashScope (ModelStudio)Qwen3, GLM-5, MiniMax M2.5, Kimi K2.5gsd install npm:pi-dashscope

Community extensions are recommended over the built-in alibaba-coding-plan provider for DashScope models — they use the correct OpenAI-compatible endpoint and include per-model compatibility flags for thinking mode.

Coordinates model selection, phase skipping, and context compression. See Token Optimization.

Values: budget, balanced (default), quality

ProfileBehavior
budgetSkips research + reassessment phases, uses cheaper models
balancedDefault behavior — all phases run, standard model selection
qualityAll phases run, prefers higher-quality models

Fine-grained control over which phases run in auto mode:

phases:
skip_research: false # skip milestone-level research
skip_reassess: false # skip roadmap reassessment after each slice
skip_slice_research: true # skip per-slice research
reassess_after_slice: true # enable roadmap reassessment after each slice (required for reassessment)
require_slice_discussion: false # pause auto-mode before each slice for discussion

These are usually set automatically by token_profile, but can be overridden explicitly.

Note: Roadmap reassessment requires reassess_after_slice: true to be set explicitly. Without it, reassessment is skipped regardless of skip_reassess.

Controls how GSD finds and applies skills during auto mode.

ValueBehavior
autoSkills found and applied automatically
suggestSkills identified during research but not auto-installed (default)
offSkill discovery disabled

Timeout thresholds for auto mode supervision:

auto_supervisor:
model: claude-sonnet-4-6 # optional: model for supervisor (defaults to active model)
soft_timeout_minutes: 20 # warn LLM to wrap up
idle_timeout_minutes: 10 # detect stalls
hard_timeout_minutes: 30 # pause auto mode

Maximum USD to spend during auto mode. No $ sign — just the number.

budget_ceiling: 50.00

How the budget ceiling is enforced:

ValueBehavior
warnLog a warning but continue
pausePause auto mode (default when ceiling is set)
haltStop auto mode entirely

Context window usage percentage (0-100) at which auto mode pauses for checkpointing. Set to 0 to disable.

context_pause_threshold: 80 # pause at 80% context usage

Default: 0 (disabled)

Enable automatic UAT (User Acceptance Test) runs after slice completion:

uat_dispatch: true

Configure shell commands that run automatically after every task execution. Failures trigger auto-fix retries before advancing.

verification_commands:
- npm run lint
- npm run test
verification_auto_fix: true # auto-retry on failure (default: true)
verification_max_retries: 2 # max retry attempts (default: 2)
FieldTypeDefaultDescription
verification_commandsstring[][]Shell commands to run after task execution
verification_auto_fixbooleantrueAuto-retry when verification fails
verification_max_retriesnumber2Maximum auto-fix retry attempts

The fetch_page tool blocks requests to private and internal network addresses to prevent server-side request forgery (SSRF). This protects against the agent being tricked into accessing internal services, cloud metadata endpoints, or local files.

Blocked by default:

CategoryExamples
Private IP ranges10.x.x.x, 172.16-31.x.x, 192.168.x.x, 127.x.x.x
Link-local / cloud metadata169.254.x.x (AWS/GCP instance metadata)
Cloud metadata hostnamesmetadata.google.internal, instance-data
Localhostlocalhost (any port)
Non-HTTP protocolsfile://, ftp://
IPv6 private ranges::1, fc00:, fd, fe80:

Public URLs (https://example.com, http://8.8.8.8) are not affected.

Allowing specific internal hosts:

If you need the agent to fetch from internal URLs (self-hosted docs, internal APIs behind a VPN), add their hostnames to fetchAllowedUrls in global settings (~/.gsd/agent/settings.json):

{
"fetchAllowedUrls": ["internal-docs.company.com", "192.168.1.50"]
}

Alternatively, set the GSD_FETCH_ALLOWED_URLS environment variable (comma-separated). The env var takes precedence over settings.json:

Terminal window
export GSD_FETCH_ALLOWED_URLS="internal-docs.company.com,192.168.1.50"

Allowed hostnames bypass the blocklist checks. The protocol restriction (HTTP/HTTPS only) still applies — file:// and ftp:// cannot be allowlisted.

Note: This setting is global-only. Project-level settings.json cannot override the URL allowlist — this prevents a cloned repo from directing fetch_page at internal infrastructure.

Auto-generate HTML reports after milestone completion:

auto_report: true # default: true

Reports are written to .gsd/reports/ as self-contained HTML files with embedded CSS/JS.

Generate milestone IDs with a random suffix to avoid collisions in team workflows:

unique_milestone_ids: true
# Produces: M001-eh88as instead of M001

Git behavior configuration. All fields optional:

git:
auto_push: false # push commits to remote after committing
push_branches: false # push milestone branch to remote
remote: origin # git remote name
snapshots: true # WIP snapshot commits during long tasks
pre_merge_check: auto # run checks before worktree merge (true/false/"auto")
commit_type: feat # override conventional commit prefix
main_branch: main # primary branch name
merge_strategy: squash # how worktree branches merge: "squash" or "merge"
isolation: worktree # git isolation: "worktree", "branch", or "none"
commit_docs: true # commit .gsd/ artifacts to git (set false to keep local)
manage_gitignore: true # set false to prevent GSD from modifying .gitignore
worktree_post_create: .gsd/hooks/post-worktree-create # script to run after worktree creation
auto_pr: false # create a PR on milestone completion (requires push_branches)
pr_target_branch: develop # target branch for auto-created PRs (default: main branch)
FieldTypeDefaultDescription
auto_pushbooleanfalsePush commits to remote after committing
push_branchesbooleanfalsePush milestone branch to remote
remotestring"origin"Git remote name
snapshotsbooleantrueWIP snapshot commits during long tasks
pre_merge_checkbool/string"auto"Run checks before merge (true/false/"auto")
commit_typestring(inferred)Override conventional commit prefix (feat, fix, refactor, docs, test, chore, perf, ci, build, style)
main_branchstring"main"Primary branch name
merge_strategystring"squash"How worktree branches merge: "squash" (combine all commits) or "merge" (preserve individual commits)
isolationstring"worktree"Auto-mode isolation: "worktree" (separate directory), "branch" (work in project root — useful for submodule-heavy repos), or "none" (no isolation — commits on current branch, no worktree or milestone branch)
commit_docsbooleantrueCommit .gsd/ planning artifacts to git. Set false to keep local-only
manage_gitignorebooleantrueWhen false, GSD will not modify .gitignore at all — no baseline patterns, no self-healing. Use if you manage your own .gitignore
worktree_post_createstring(none)Script to run after worktree creation. Receives SOURCE_DIR and WORKTREE_DIR env vars
auto_prbooleanfalseAutomatically create a pull request when a milestone completes. Requires auto_push: true and gh CLI installed and authenticated
pr_target_branchstring(main branch)Target branch for auto-created PRs (e.g. develop, qa). Defaults to main_branch if not set

Script to run after a worktree is created (both auto-mode and manual /worktree). Useful for copying .env files, symlinking asset directories, or running setup commands that worktrees don’t inherit from the main tree.

git:
worktree_post_create: .gsd/hooks/post-worktree-create

The script receives two environment variables:

  • SOURCE_DIR — the original project root
  • WORKTREE_DIR — the newly created worktree path

Example hook script (.gsd/hooks/post-worktree-create):

#!/bin/bash
# Copy environment files and symlink assets into the new worktree
cp "$SOURCE_DIR/.env" "$WORKTREE_DIR/.env"
cp "$SOURCE_DIR/.env.local" "$WORKTREE_DIR/.env.local" 2>/dev/null || true
ln -sf "$SOURCE_DIR/assets" "$WORKTREE_DIR/assets"

The path can be absolute or relative to the project root. The script runs with a 30-second timeout. Failure is non-fatal — GSD logs a warning and continues.

Automatically create a pull request when a milestone completes. Designed for teams using Gitflow or branch-based workflows where work should go through PR review before merging to a target branch.

git:
auto_push: true
auto_pr: true
pr_target_branch: develop # or qa, staging, etc.

Requirements:

  • auto_push: true — the milestone branch must be pushed before a PR can be created
  • gh CLI installed and authenticated (gh auth login)

How it works:

  1. Milestone completes → GSD squash-merges the worktree to the main branch
  2. Pushes the main branch to remote (if auto_push: true)
  3. Pushes the milestone branch to remote
  4. Creates a PR from the milestone branch to pr_target_branch via gh pr create

If pr_target_branch is not set, the PR targets the main_branch (or auto-detected main branch). PR creation failure is non-fatal — GSD logs and continues.

GitHub sync configuration. When enabled, GSD auto-syncs milestones, slices, and tasks to GitHub Issues, PRs, and Milestones.

github:
enabled: true
repo: "owner/repo" # auto-detected from git remote if omitted
labels: [gsd, auto-generated] # labels applied to created issues/PRs
project: "Project ID" # optional GitHub Project board
FieldTypeDefaultDescription
enabledbooleanfalseEnable GitHub sync
repostring(auto-detected)GitHub repository in owner/repo format
labelsstring[][]Labels to apply to created issues and PRs
projectstring(none)GitHub Project ID for project board integration

Requirements:

  • gh CLI installed and authenticated (gh auth login)
  • Sync mapping is persisted in .gsd/.github-sync.json
  • Rate-limit aware — skips sync when GitHub API rate limit is low

Commands:

  • /github-sync bootstrap — initial setup and sync
  • /github-sync status — show sync mapping counts

Control what notifications GSD sends during auto mode:

notifications:
enabled: true
on_complete: true # notify on unit completion
on_error: true # notify on errors
on_budget: true # notify on budget thresholds
on_milestone: true # notify when milestone finishes
on_attention: true # notify when manual attention needed

macOS delivery: GSD uses terminal-notifier when available, falling back to osascript. We recommend installing terminal-notifier for reliable notification delivery:

Terminal window
brew install terminal-notifier

Why: osascript display notification is attributed to your terminal app (Ghostty, iTerm2, etc.), which may not have notification permissions in System Settings → Notifications. terminal-notifier registers as its own app and prompts for permission on first use. See Troubleshooting: Notifications not appearing on macOS if notifications aren’t working.

Route interactive questions to Slack or Discord for headless auto mode:

remote_questions:
channel: slack # or discord
channel_id: "C1234567890"
timeout_minutes: 15 # question timeout (1-30 minutes)
poll_interval_seconds: 10 # poll interval (2-30 seconds)

Custom hooks that fire after specific unit types complete:

post_unit_hooks:
- name: code-review
after: [execute-task]
prompt: "Review the code changes for quality and security issues."
model: claude-opus-4-6 # optional: model override
max_cycles: 1 # max fires per trigger (1-10, default: 1)
artifact: REVIEW.md # optional: skip if this file exists
retry_on: NEEDS-REWORK.md # optional: re-run trigger unit if this file appears
agent: review-agent # optional: agent definition to use
enabled: true # optional: disable without removing

Known unit types for after: research-milestone, plan-milestone, research-slice, plan-slice, execute-task, complete-slice, replan-slice, reassess-roadmap, run-uat

Prompt substitutions: {milestoneId}, {sliceId}, {taskId} are replaced with current context values.

Hooks that intercept units before dispatch. Three actions available:

Modify — prepend/append text to the unit prompt:

pre_dispatch_hooks:
- name: add-standards
before: [execute-task]
action: modify
prepend: "Follow our coding standards document."
append: "Run linting after changes."

Skip — skip the unit entirely:

pre_dispatch_hooks:
- name: skip-research
before: [research-slice]
action: skip
skip_if: RESEARCH.md # optional: only skip if this file exists

Replace — replace the unit prompt entirely:

pre_dispatch_hooks:
- name: custom-execute
before: [execute-task]
action: replace
prompt: "Execute the task using TDD methodology."
unit_type: execute-task-tdd # optional: override unit type label
model: claude-opus-4-6 # optional: model override

All pre-dispatch hooks support enabled: true/false to toggle without removing.

always_use_skills / prefer_skills / avoid_skills

Section titled “always_use_skills / prefer_skills / avoid_skills”

Skill routing preferences:

always_use_skills:
- debug-like-expert
prefer_skills:
- frontend-design
avoid_skills: []

Skills can be bare names (looked up in ~/.agents/skills/ and .agents/skills/) or absolute paths.

Situational skill routing with human-readable triggers:

skill_rules:
- when: task involves authentication
use: [clerk]
- when: frontend styling work
prefer: [frontend-design]
- when: working with legacy code
avoid: [aggressive-refactor]

Durable instructions appended to every session:

custom_instructions:
- "Always use TypeScript strict mode"
- "Prefer functional patterns over classes"

For project-specific knowledge (patterns, gotchas, lessons learned), use .gsd/KNOWLEDGE.md instead — it’s injected into every agent prompt automatically. Add entries with /gsd knowledge rule|pattern|lesson <description>.

Declare project-level runtime context in .gsd/RUNTIME.md. This file is inlined into task execution prompts, giving the agent accurate information about your runtime environment without relying on hallucinated paths or URLs.

Location: .gsd/RUNTIME.md

Example:

# Runtime Context
## API Endpoints
- Main API: https://api.example.com
- Cache: redis://localhost:6379
## Environment Variables
- DEPLOYMENT_ENV: staging
- DB_POOL_SIZE: 20
## Local Services
- PostgreSQL: localhost:5432
- Redis: localhost:6379

Use this for information that the agent needs during execution but that doesn’t belong in DECISIONS.md (architectural) or KNOWLEDGE.md (patterns/rules). Common examples: API base URLs, service ports, deployment targets, and environment-specific configuration.

Complexity-based model routing. See Dynamic Model Routing.

dynamic_routing:
enabled: true
tier_models:
light: claude-haiku-4-5
standard: claude-sonnet-4-6
heavy: claude-opus-4-6
escalate_on_failure: true
budget_pressure: true
cross_provider: true

OpenAI service tier preference for supported models. Toggle with /gsd fast.

ValueBehavior
"priority"Priority tier — 2x cost, faster responses
"flex"Flex tier — 0.5x cost, slower responses
(unset)Default tier
service_tier: priority

Opt-in: search existing issues and PRs before filing from /gsd forensics. Uses additional AI tokens.

forensics_dedup: true # default: false

Opt-in: show per-prompt and cumulative session token cost in the footer.

show_token_cost: true # default: false

Show the workflow visualizer automatically after milestone completion:

auto_visualize: true

See Workflow Visualizer.

Run multiple milestones simultaneously. Disabled by default.

parallel:
enabled: false # Master toggle
max_workers: 2 # Concurrent workers (1-4)
budget_ceiling: 50.00 # Aggregate cost limit in USD
merge_strategy: "per-milestone" # "per-slice" or "per-milestone"
auto_merge: "confirm" # "auto", "confirm", or "manual"

See Parallel Orchestration for full documentation.

---
version: 1
# Model selection
models:
research: openrouter/deepseek/deepseek-r1
planning:
model: claude-opus-4-6
fallbacks:
- openrouter/z-ai/glm-5
execution: claude-sonnet-4-6
execution_simple: claude-haiku-4-5-20250414
completion: claude-sonnet-4-6
# Token optimization
token_profile: balanced
# Dynamic model routing
dynamic_routing:
enabled: true
escalate_on_failure: true
budget_pressure: true
# Budget
budget_ceiling: 25.00
budget_enforcement: pause
context_pause_threshold: 80
# Supervision
auto_supervisor:
soft_timeout_minutes: 15
hard_timeout_minutes: 25
# Git
git:
auto_push: true
merge_strategy: squash
isolation: worktree # "worktree", "branch", or "none"
commit_docs: true
# Skills
skill_discovery: suggest
skill_staleness_days: 60 # Skills unused for N days get deprioritized (0 = disabled)
always_use_skills:
- debug-like-expert
skill_rules:
- when: task involves authentication
use: [clerk]
# Notifications
notifications:
on_complete: false
on_milestone: true
on_attention: true
# Visualizer
auto_visualize: true
# Service tier
service_tier: priority # "priority" or "flex" (for /gsd fast)
# Diagnostics
forensics_dedup: true # deduplicate before filing forensics issues
show_token_cost: true # show per-prompt cost in footer
# Hooks
post_unit_hooks:
- name: code-review
after: [execute-task]
prompt: "Review {sliceId}/{taskId} for quality and security."
artifact: REVIEW.md
---