* chore(#604): rename get-shit-done/ runtime directory to gsd-core/ Renames the installed runtime directory `get-shit-done/` to `gsd-core/` so the on-disk name matches the package (`@opengsd/gsd-core`), repo, and binary (`gsd-tools`). The npm package name and binary are unchanged; npx/npm consumers are unaffected. Mechanical (bulk, ~90% of the diff): - `git mv get-shit-done gsd-core` - Swept path/identifier references across the repo via `perl -pe 's/get-shit-done(?!-\w)/gsd-core/g'`. The negative lookahead preserves the five legitimate slug variants that are NOT the directory: get-shit-done-{OLD,cc,classic,cli,redux} (old package/repo names). - Build/manifest wiring: package.json (bin, files, coverage globs), tsconfig.build.json (outDir), ~86 .gitignore build-output entries, stryker.config.mjs, scan-ignore files, install.js path strings. - Frozen (not rewritten): CHANGELOG.md history; translated docs (README.<locale>.md and docs/{ja-JP,ko-KR,pt-BR,zh-CN}/). New logic (review here): - src/installer-migrations/003-rename-get-shit-done-to-gsd-core.cts: a proper ADR-0008 installer migration. On upgrade it walks the legacy `~/.claude/get-shit-done/` tree, classifies each file via the prior install manifest, and emits remove-managed / backup-and-remove for managed files while PRESERVING unknown user-added files. Symlink-safe (skips a symlinked root and symlinked entries; bounds-checks every path under configDir). The framework rolls back on install failure. Emptied dirs may remain (framework has no recursive dir-removal primitive) — documented. - scripts/lint-legacy-dir-name.cjs: CI regression guard forbidding the bare `get-shit-done` directory token (split token to avoid self-match; case- insensitive; `(?!-\w)` lookahead allows the slug variants; allowlists CHANGELOG, translated docs, and `gsd-allow-legacy-name` marker lines). Wired into the lint-tests CI job. - Restored scripts/lint-package-identity-drift.cjs detection regexes (the mechanical sweep had wrongly rewritten the old-name patterns it exists to detect) and marked them as intentional legacy references. - TDD tests for the migration and the guard; do.md slash-command guard regex tightened so a `/gsd-core/bin` path segment is not mistaken for a command; changeset + docs/installer-migrations.md row added. Breaking: the installed runtime path moves `~/.claude/get-shit-done/` -> `~/.claude/gsd-core/`. Migration 003 removes the stale legacy dir's managed files (preserving user files) on upgrade. Users with custom hooks/configs hardcoding the old path must update them. Closes #604 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unsweep pending changesets + allowlist injection-example docs CI fixes for the rename PR: - Do not sweep pending .changeset/*.md (ephemeral release-note fragments, like CHANGELOG); reverted those body edits so 5 pre-existing malformed fragments (missing type/pr) no longer enter the PR diff and trip docs-lint. Allowlisted .changeset/ in the legacy-name guard accordingly. - Allowlisted TEST-EXAMPLES.md and docs/explanation/security-model.md in prompt-injection-scan.sh: they contain intentional injection examples / security-model prose; the path-reference rewrites are kept. CodeQL alerts on this PR are pre-existing (alert lines unchanged by this PR; none in the new migration/guard) and are out of scope for the rename. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): resolve CodeQL alerts surfaced on this PR The rename diff touched files carrying pre-existing CodeQL findings; per the no-pre-existing-dismissal rule, fixing every surfaced alert rather than waving them off. All behavior-preserving: - scripts/ci-test-scope.cjs: build the config-path match from string .includes() instead of a RegExp over an arg-derived value (js/regex-injection). - src/profile-output.cts: escape backslashes before pipe-escaping desc/safeName so the table-cell escape is complete (js/incomplete-sanitization). - tests/{bug-2643,bug-2808,docs-parity-live-registry}: two-pass HTML-comment strip so a bare/unclosed `<!--` cannot survive (js/incomplete-multi-character-sanitization). - tests/inline-plan-threshold: drop the no-op `\s`->`\s` identity replace, keep the meaningful POSIX-class conversion (js/identity-replacement). Verified: build:lib green; the touched test files + ci-test-scope + profile-output suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): correctly resolve remaining CodeQL alerts (regex-injection + sanitization) The prior commit's fixes for two alerts were ineffective: - ci-test-scope.cjs js/regex-injection: the alert is the CLI-arg-derived `file` reaching static regex `.test(file)` calls (not the config rule). Removed ALL regex over file/t — startsWith/includes/=== string checks + an isWindowsHint helper — so there is no regex sink for the tainted value. - js/incomplete-multi-character-sanitization (3 test files): a single `.replace(/<!--...-->/g,'')` can let `<!--` re-form. Replaced with a fixpoint loop (replace until stable) plus a final bare-opener strip. Verified: no regex over file/t remains; ci-test-scope + the 3 test suites pass; lint:legacy-name clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): make ci-test-scope + comment-strippers regex-free to clear CodeQL CodeQL flags the regex PATTERNS syntactically (regex-injection on the --files arg split; incomplete-multi-character-sanitization on the <!--...--> replace), so loop fixes do not satisfy it. Made these paths regex-free: - ci-test-scope.cjs splitFiles: char-by-char separator tokenizer (no /[,\\s]+/). - 3 test files: indexOf/slice HTML-comment stripper (no .replace(/<!--/)). Behavior preserved; ci-test-scope + the 3 suites pass; guard clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): unblock security base64 scan on the large rename diff The security job hit its 10m timeout: base64-scan.sh choked on the binary test fixture tests/feat-3594-parser-property-style.test.cjs (embedded NUL/ non-UTF8 bytes -> thousands of bogus blobs + "ignored null byte" warnings), and the ~800-file rename diff is slow to scan regardless. - scripts/base64-scan.sh: skip binary-by-content files (grep -Iq .) — they can't carry base64-obfuscated *text* and feeding NUL bytes through the per-line scanner is pathologically slow. collect_files already filtered binary *extensions*; this catches binary *content* in text extensions. - .github/workflows/security-scan.yml: raise the security job timeout 10m->30m to accommodate very large diffs (the scan itself is unchanged). Verified locally: scan skips the fixture, 0 "ignored null byte" warnings, 0 findings, exit 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): sweep get-shit-done refs introduced by merging next The branch was updated with next (#614/#384/#618 etc.), which reference the get-shit-done/ dir (still named that on next). Swept the stale references in the merged files to gsd-core so the rename stays consistent and lint:legacy-name passes: - commands/gsd/discuss-phase.md (runtime-launcher shim paths) - src/core.cts (getAgentsDir layout comments) - tests/bug-384-agents-runtime-aware.test.cjs (require path to runtime lib) Verified: guard 0 violations; build green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): exclude gsd-core/ path segments from bug-3683 command cross-ref invariant The #614 runtime-launcher shim added to discuss-phase.md references `${_GSD_RUNTIME_ROOT}/gsd-core/bin/...`. bug-3683's REF_PATTERN excluded path-y refs only via lookbehind, but `}` precedes `/gsd-core/` in the shim, so it mis-read the directory path as a dangling `/gsd-core` command ref (same class as the #604 bug-2954 fix). Added a trailing `(?![\w-]*\/)` so `/gsd-<x>/...` path segments are not treated as slash-command references. Verified locally on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22 image) full suite: 0 failures - bug-3683 + bug-2954 pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): lazily resolve findProjectRoot in gsd-tools (harden flaky CI) CI intermittently failed state.test's gsd-tools subprocess with "findProjectRoot is not a function" (flip-flopping across legs; not reproducible on mac full suite, gsd-test linux full suite, test:unit, or state.test x8). findProjectRoot is a re-export from core.cjs (sourced from project-root.cjs); binding it via destructure at module-load can be undefined under a load-ordering edge. Resolve it lazily at call time via a small wrapper so the lookup happens after core.cjs is fully initialized. Verified green on BOTH platforms before pushing: - mac (node 26) full suite: 0 failures - gsd-test-runner (linux, node22) full suite: 0 failures - state.test.cjs: 106/106; gsd-tools loads cleanly. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(#604): allowlist verification-patterns.md placeholder examples in secret scan The rename git-mv'd references/verification-patterns.md into gsd-core/, pulling it into the secret-scan diff. It documents stub/placeholder RED-FLAG env-var examples (illustrative Stripe test-key / database-URL / API-key placeholders) — not real credentials. Added it to .secretscanignore with the strict annotation, mirroring the existing gsd-core/workflows/plan-phase.md exception. Verified locally: secret-scan-lint --strict OK; secret-scan --diff origin/next exits 0 with 0 findings. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
24 KiB
<planning_config>
Configuration options for .planning/ directory behavior.
<config_schema>
"planning": {
"commit_docs": true,
"search_gitignored": false
},
"git": {
"branching_strategy": "none",
"base_branch": null,
"phase_branch_template": "gsd/phase-{phase}-{slug}",
"milestone_branch_template": "gsd/{milestone}-{slug}",
"quick_branch_template": null
},
"manager": {
"flags": {
"discuss": "",
"plan": "",
"execute": ""
}
}
| Option | Default | Description |
|---|---|---|
commit_docs |
true |
Whether to commit planning artifacts to git |
search_gitignored |
false |
Add --no-ignore to broad rg searches |
git.branching_strategy |
"none" |
Git branching approach: "none", "phase", or "milestone" |
git.base_branch |
null (auto-detect) |
Target branch for PRs and merges (e.g. "master", "develop"). When null, auto-detects from git symbolic-ref refs/remotes/origin/HEAD, falling back to "main". |
git.create_tag |
true |
Create git tags on milestone completion |
git.phase_branch_template |
"gsd/phase-{phase}-{slug}" |
Branch template for phase strategy |
git.milestone_branch_template |
"gsd/{milestone}-{slug}" |
Branch template for milestone strategy |
git.quick_branch_template |
null |
Optional branch template for quick-task runs |
workflow.use_worktrees |
true |
Whether executor agents run in isolated git worktrees. Set to false to disable worktrees — agents execute sequentially on the main working tree instead. Recommended for solo developers or when worktree merges cause issues. |
workflow.subagent_timeout |
300000 |
Timeout in milliseconds for parallel subagent tasks (e.g. codebase mapping). Increase for large codebases or slower models. Default: 300000 (5 minutes). |
workflow.inline_plan_threshold |
2 |
Plans with this many tasks or fewer execute inline (Pattern C) instead of spawning a subagent. Avoids ~14K token spawn overhead for small plans. Set to 0 to always spawn subagents. |
manager.flags.discuss |
"" |
Flags passed to /gsd:discuss-phase when dispatched from manager (e.g. "--auto --analyze") |
manager.flags.plan |
"" |
Flags passed to plan workflow when dispatched from manager |
manager.flags.execute |
"" |
Flags passed to execute workflow when dispatched from manager |
response_language |
null |
Language for user-facing questions and prompts across all phases/subagents (e.g. "Portuguese", "Japanese", "Spanish"). When set, all spawned agents include a directive to respond in this language. |
| </config_schema> |
<commit_docs_behavior>
When commit_docs: true (default):
- Planning files committed normally
- SUMMARY.md, STATE.md, ROADMAP.md tracked in git
- Full history of planning decisions preserved
When commit_docs: false:
- Skip all
git add/git commitfor.planning/files - User must add
.planning/to.gitignore - Useful for: OSS contributions, client projects, keeping planning private
Using gsd-tools query (preferred):
# Commit with automatic commit_docs + gitignore checks:
gsd-tools query commit "docs: update state" --files .planning/STATE.md
# Load config via state load (returns JSON):
INIT=$(gsd-tools query state.load)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
# commit_docs is available in the JSON output
# Or use init commands which include commit_docs:
INIT=$(gsd-tools query init.execute-phase "1")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
# commit_docs is included in all init command outputs
Auto-detection: If .planning/ is gitignored, commit_docs is automatically false regardless of config.json. This prevents git errors when users have .planning/ in .gitignore.
Commit via CLI (handles checks automatically):
gsd-tools query commit "docs: update state" --files .planning/STATE.md
The CLI checks commit_docs config and gitignore status internally — no manual conditionals needed.
</commit_docs_behavior>
<search_behavior>
When search_gitignored: false (default):
- Standard rg behavior (respects .gitignore)
- Direct path searches work:
rg "pattern" .planning/finds files - Broad searches skip gitignored:
rg "pattern"skips.planning/
When search_gitignored: true:
- Add
--no-ignoreto broad rg searches that should include.planning/ - Only needed when searching entire repo and expecting
.planning/matches
Note: Most GSD operations use direct file reads or explicit paths, which work regardless of gitignore status.
</search_behavior>
<setup_uncommitted_mode>
To use uncommitted mode:
-
Set config:
"planning": { "commit_docs": false, "search_gitignored": true } -
Add to .gitignore:
.planning/ -
Existing tracked files: If
.planning/was previously tracked:git rm -r --cached .planning/ git commit -m "chore: stop tracking planning docs" -
Branch merges: When using
branching_strategy: phaseormilestone, thecomplete-milestoneworkflow automatically strips.planning/files from staging before merge commits whencommit_docs: false.
</setup_uncommitted_mode>
<branching_strategy_behavior>
Branching Strategies:
| Strategy | When branch created | Branch scope | Merge point |
|---|---|---|---|
none |
Never | N/A | N/A |
phase |
At execute-phase start |
Single phase | User merges after phase |
milestone |
At first execute-phase of milestone |
Entire milestone | At complete-milestone |
When git.branching_strategy: "none" (default):
- All work commits to current branch
- Standard GSD behavior
When git.branching_strategy: "phase":
execute-phasecreates/switches to a branch before execution- Branch name from
phase_branch_template(e.g.,gsd/phase-03-authentication) - All plan commits go to that branch
- User merges branches manually after phase completion
complete-milestoneoffers to merge all phase branches
When git.branching_strategy: "milestone":
- First
execute-phaseof milestone creates the milestone branch - Branch name from
milestone_branch_template(e.g.,gsd/v1.0-mvp) - All phases in milestone commit to same branch
complete-milestoneoffers to merge milestone branch to main
Template variables:
| Variable | Available in | Description |
|---|---|---|
{phase} |
phase_branch_template | Zero-padded phase number (e.g., "03") |
{slug} |
Both | Lowercase, hyphenated name |
{milestone} |
milestone_branch_template | Milestone version (e.g., "v1.0") |
Checking the config:
Use init execute-phase which returns all config as JSON:
INIT=$(gsd-tools query init.execute-phase "1")
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
# JSON output includes: branching_strategy, phase_branch_template, milestone_branch_template
Or use state load for the config values:
INIT=$(gsd-tools query state.load)
if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi
# Parse branching_strategy, phase_branch_template, milestone_branch_template from JSON
Branch creation:
# For phase strategy
if [ "$BRANCHING_STRATEGY" = "phase" ]; then
PHASE_SLUG=$(echo "$PHASE_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
BRANCH_NAME=$(echo "$PHASE_BRANCH_TEMPLATE" | sed "s/{phase}/$PADDED_PHASE/g" | sed "s/{slug}/$PHASE_SLUG/g")
git checkout -b "$BRANCH_NAME" 2>/dev/null || git checkout "$BRANCH_NAME"
fi
# For milestone strategy
if [ "$BRANCHING_STRATEGY" = "milestone" ]; then
MILESTONE_SLUG=$(echo "$MILESTONE_NAME" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//;s/-$//')
BRANCH_NAME=$(echo "$MILESTONE_BRANCH_TEMPLATE" | sed "s/{milestone}/$MILESTONE_VERSION/g" | sed "s/{slug}/$MILESTONE_SLUG/g")
git checkout -b "$BRANCH_NAME" 2>/dev/null || git checkout "$BRANCH_NAME"
fi
Merge options at complete-milestone:
| Option | Git command | Result |
|---|---|---|
| Squash merge (recommended) | git merge --squash |
Single clean commit per branch |
| Merge with history | git merge --no-ff |
Preserves all individual commits |
| Delete without merging | git branch -D |
Discard branch work |
| Keep branches | (none) | Manual handling later |
Squash merge is recommended — keeps main branch history clean while preserving the full development history in the branch (until deleted).
Use cases:
| Strategy | Best for |
|---|---|
none |
Solo development, simple projects |
phase |
Code review per phase, granular rollback, team collaboration |
milestone |
Release branches, staging environments, PR per version |
</branching_strategy_behavior>
<complete_field_reference>
Complete Field Reference
Generated from CONFIG_DEFAULTS (core.cjs) and VALID_CONFIG_KEYS (config.cjs).
Core Fields
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
model_profile |
string | "balanced" |
"quality", "balanced", "budget", "adaptive", "inherit" |
Model selection preset for subagents |
mode |
string | "interactive" |
"interactive", "yolo" |
Operation mode: "interactive" shows gates and confirmations; "yolo" runs autonomously without prompts |
granularity |
string | (none) | "coarse", "standard", "fine" |
Planning depth for phase plans (migrated from deprecated depth) |
commit_docs |
boolean | true |
true, false |
Commit .planning/ artifacts to git (auto-false if .planning/ is gitignored) |
search_gitignored |
boolean | false |
true, false |
Include gitignored paths in broad rg searches via --no-ignore |
phase_naming |
string | "sequential" |
"sequential", "custom" |
Phase numbering: auto-increment or arbitrary string IDs |
project_code |
string|null | null |
Any short string | Prefix for phase dirs (e.g., "CK" produces CK-01-foundation) |
response_language |
string|null | null |
Any language name | Language for user-facing prompts (e.g., "Portuguese", "Japanese") |
context_window |
number | 200000 |
200000, 1000000 |
Context window size; set 1000000 for 1M-context models |
resolve_model_ids |
boolean|string | false |
false, true, "omit" |
Map model aliases to full Claude IDs; "omit" returns empty string |
context |
string|null | null |
"dev", "research", "review" |
Execution context profile that adjusts agent behavior: "dev" for development tasks, "research" for investigation/exploration, "review" for code review workflows |
review.models.<cli> |
string|null | null |
Any model ID string | Per-CLI model override for /gsd:review (e.g., review.models.gemini). Falls back to CLI default when null. |
Workflow Fields
Set via workflow.* namespace in config.json (e.g., "workflow": { "research": true }).
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
workflow.research |
boolean | true |
true, false |
Run research agent before planning |
workflow.plan_check |
boolean | true |
true, false |
Run plan-checker agent to validate plans. Alias: plan_checker is the flat-key form used in CONFIG_DEFAULTS; workflow.plan_check is the canonical namespaced form. |
workflow.verifier |
boolean | true |
true, false |
Run verifier agent after execution |
workflow.nyquist_validation |
boolean | true |
true, false |
Enable Nyquist-inspired validation gates |
workflow.auto_prune_state |
boolean | false |
true, false |
Automatically prune old STATE.md entries on phase completion (keeps 3 most recent phases) |
workflow.auto_advance |
boolean | false |
true, false |
Auto-advance to next phase after completion |
workflow.node_repair |
boolean | true |
true, false |
Attempt automatic repair of failed plan nodes |
workflow.node_repair_budget |
number | 2 |
Any positive integer | Max repair retries per failed node |
workflow.ai_integration_phase |
boolean | true |
true, false |
Run /gsd:ai-integration-phase before planning AI system phases |
workflow.ui_phase |
boolean | true |
true, false |
Generate UI-SPEC.md for frontend phases |
workflow.ui_safety_gate |
boolean | true |
true, false |
Require safety gate approval for UI changes |
workflow.text_mode |
boolean | false |
true, false |
Use plain-text numbered lists instead of AskUserQuestion menus |
workflow.research_before_questions |
boolean | false |
true, false |
Run research before interactive questions in discuss phase |
workflow.discuss_mode |
string | "discuss" |
"discuss", "assumptions" |
Default mode for discuss-phase: "discuss" runs interactive questioning; "assumptions" analyzes codebase and surfaces assumptions instead |
workflow.skip_discuss |
boolean | false |
true, false |
Skip discuss phase entirely |
workflow.use_worktrees |
boolean | true |
true, false |
Run executor agents in isolated git worktrees |
workflow.subagent_timeout |
number | 300000 |
Any positive integer (ms) | Timeout for parallel subagent tasks (default: 5 minutes) |
workflow.inline_plan_threshold |
number | 2 |
0–10 |
Plans with ≤N tasks execute inline instead of spawning a subagent |
workflow.code_review |
boolean | true |
true, false |
Enable built-in code review step in the ship workflow |
workflow.code_review_depth |
string | "standard" |
"light", "standard", "deep" |
Depth level for code review analysis in the ship workflow |
workflow._auto_chain_active |
boolean | false |
true, false |
Internal: tracks whether autonomous chaining is active |
workflow.security_enforcement |
boolean | true |
true, false |
Enable threat-model-anchored security verification via /gsd:secure-phase. When false, security checks are skipped entirely |
workflow.security_asvs_level |
number | 1 |
1, 2, 3 |
OWASP ASVS verification level. Level 1 = opportunistic, Level 2 = standard, Level 3 = comprehensive |
workflow.security_block_on |
string | "high" |
"high", "medium", "low" |
Minimum severity that blocks phase advancement |
workflow.post_planning_gaps |
boolean | true |
true, false |
Post-planning gap report (#2493). After plans are generated, scans REQUIREMENTS.md and CONTEXT.md <decisions> against all PLAN.md files and emits a unified Source | Item | Status table. Non-blocking. Set to false to skip Step 13e of plan-phase. Alias: post_planning_gaps is the flat-key form used in CONFIG_DEFAULTS; workflow.post_planning_gaps is the canonical namespaced form. |
Ship Fields
Set via ship.* namespace in config.json. These fields affect /gsd:ship PRD-style pull request body composition only.
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
ship.pr_body_sections |
array | [] |
Array of section objects | Append-only project-specific PR body sections. Each entry has heading, optional enabled, and one or more of source, template, or fallback. Disabled entries remain in onboarding config but do not render. Core sections remain required and cannot be removed or replaced. |
Git Fields
Set via git.* namespace (e.g., "git": { "branching_strategy": "phase" }).
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
git.branching_strategy |
string | "none" |
"none", "phase", "milestone" |
Git branching approach for phase/milestone isolation |
git.base_branch |
string|null | null (auto-detect) |
Any branch name | Target branch for PRs and merges; auto-detects from origin/HEAD when null |
git.create_tag |
boolean | true |
true, false |
Create git tags on milestone completion |
git.phase_branch_template |
string | "gsd/phase-{phase}-{slug}" |
Template with {phase}, {slug} |
Branch naming template for phase strategy |
git.milestone_branch_template |
string | "gsd/{milestone}-{slug}" |
Template with {milestone}, {slug} |
Branch naming template for milestone strategy |
git.quick_branch_template |
string|null | null |
Template with {slug} |
Optional branch template for quick-task runs |
Search & API Fields
These toggle external search integrations. Auto-detected at project creation when API keys are present.
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
brave_search |
boolean | false |
true, false |
Enable Brave web search for research agent (requires BRAVE_API_KEY) |
firecrawl |
boolean | false |
true, false |
Enable Firecrawl page scraping (requires FIRECRAWL_API_KEY) |
exa_search |
boolean | false |
true, false |
Enable Exa semantic search (requires EXA_API_KEY) |
Features Fields
Set via features.* namespace (e.g., "features": { "thinking_partner": true }).
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
features.thinking_partner |
boolean | false |
true, false |
Enable conditional extended thinking at workflow decision points (used by discuss-phase and plan-phase for architectural tradeoff analysis) |
features.global_learnings |
boolean | false |
true, false |
Enable injection of global learnings from ~/.gsd/learnings/ into agent prompts |
Hook Fields
Set via hooks.* namespace (e.g., "hooks": { "context_warnings": true }).
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
hooks.context_warnings |
boolean | true |
true, false |
Show warnings when context budget is exceeded |
Learnings Fields
Set via learnings.* namespace (e.g., "learnings": { "max_inject": 5 }). Used together with features.global_learnings.
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
learnings.max_inject |
number | 10 |
Any positive integer | Maximum number of global learning entries to inject into agent prompts per session |
Intel Fields
Set via intel.* namespace (e.g., "intel": { "enabled": true }). Controls the queryable codebase intelligence system consumed by /gsd:map-codebase --query.
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
intel.enabled |
boolean | false |
true, false |
Enable queryable codebase intelligence system. When true, /gsd:map-codebase --query builds and queries a JSON index in .planning/intel/. |
Manager Fields
Set via manager.* namespace (e.g., "manager": { "flags": { "discuss": "--auto" } }).
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
manager.flags.discuss |
string | "" |
Any CLI flags string | Flags passed to /gsd:discuss-phase from manager (e.g., "--auto --analyze") |
manager.flags.plan |
string | "" |
Any CLI flags string | Flags passed to plan workflow from manager |
manager.flags.execute |
string | "" |
Any CLI flags string | Flags passed to execute workflow from manager |
Advanced Fields
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
parallelization |
boolean|object | true |
true, false, { "enabled": true } |
Enable parallel wave execution; object form allows additional sub-keys |
model_overrides |
object|null | null |
{ "<agent-type>": "<model-id>" } |
Override model selection per agent type |
agent_skills |
object | {} |
{ "<agent-type>": "<skill-set>" } |
Assign skill sets to specific agent types |
sub_repos |
array | [] |
Array of relative path strings | Child directories with independent .git repos (auto-detected) |
Planning Fields
These can be set at top level or nested under planning.* (e.g., "planning": { "commit_docs": false }). Both forms are equivalent; top-level takes precedence if both exist.
| Key | Type | Default | Allowed Values | Description |
|---|---|---|---|---|
planning.commit_docs |
boolean | true |
true, false |
Alias for top-level commit_docs |
planning.search_gitignored |
boolean | false |
true, false |
Alias for top-level search_gitignored |
Field Interactions
Several config fields affect each other or trigger special behavior:
-
commit_docsauto-detection -- When no explicit value is set in config.json and.planning/is in.gitignore,commit_docsautomatically resolves tofalse. An explicittrueorfalsein config always overrides auto-detection. -
branching_strategycontrols branch templates -- Thephase_branch_templateandmilestone_branch_templatefields are only used whenbranching_strategyis set to"phase"or"milestone"respectively. Whenbranching_strategyis"none", all template fields are ignored. -
context_windowthreshold triggers -- Whencontext_window >= 500000, workflows enable adaptive context enrichment: full-body reads of prior phase SUMMARYs, cross-phase context injection in plan-phase, and deeper read depth for anti-pattern references. Below 500000, only frontmatter and summaries are read. -
parallelizationpolymorphism -- Accepts both a simple boolean and an object with anenabledfield.loadConfig()normalizes either form to a boolean.{ "enabled": true }is equivalent totrue. -
Search API keys and flags --
brave_search,firecrawl, andexa_searchare auto-set totrueduring project creation if the corresponding API key is detected (environment variable or~/.gsd/<name>_api_keyfile). Setting them totruewithout the API key has no effect. -
planning.*and top-level equivalence --planning.commit_docsandcommit_docsare equivalent;planning.search_gitignoredandsearch_gitignoredare equivalent. If both are set, the top-level value takes precedence. -
depthtogranularitymigration -- The deprecateddepthkey (quick/standard/comprehensive) is automatically migrated togranularity(coarse/standard/fine) on config load and persisted back to disk. -
sub_reposauto-sync -- On every config load, GSD scans for child directories with.gitand updates thesub_reposarray if the filesystem has changed. LegacymultiRepo: trueis automatically migrated to a detectedsub_reposarray.
Example Configurations
Minimal -- Solo Developer
{
"model_profile": "balanced",
"commit_docs": true,
"workflow": {
"research": true,
"plan_check": true,
"verifier": true,
"use_worktrees": false
}
}
Team Project with Branching
{
"model_profile": "quality",
"commit_docs": true,
"project_code": "APP",
"git": {
"branching_strategy": "phase",
"base_branch": "develop",
"phase_branch_template": "gsd/phase-{phase}-{slug}"
},
"workflow": {
"research": true,
"plan_check": true,
"verifier": true,
"nyquist_validation": true,
"use_worktrees": true,
"discuss_mode": "discuss"
},
"manager": {
"flags": {
"discuss": "",
"plan": "",
"execute": ""
}
},
"response_language": "English"
}
Large Codebase -- 1M Context with Extended Timeouts
{
"model_profile": "quality",
"context_window": 1000000,
"commit_docs": true,
"project_code": "MEGA",
"phase_naming": "sequential",
"git": {
"branching_strategy": "milestone",
"milestone_branch_template": "gsd/{milestone}-{slug}"
},
"workflow": {
"research": true,
"plan_check": true,
"verifier": true,
"nyquist_validation": true,
"subagent_timeout": 600000,
"use_worktrees": true,
"node_repair": true,
"node_repair_budget": 3,
"auto_advance": true
},
"brave_search": true,
"hooks": {
"context_warnings": true
}
}
</complete_field_reference>
</planning_config>