singularity-forge/docs/configuration.md
Jeremy McSpadden 30b688bee0 feat: add worktree post-create hook for environment setup (#597) (#617)
* feat: add worktree post-create hook for environment setup (#597)

Add git.worktree_post_create preference — a script path that GSD
runs after creating any worktree (both auto-mode and manual /worktree).
The script receives SOURCE_DIR and WORKTREE_DIR as environment
variables, enabling users to copy .env files, symlink asset
directories, or run other setup commands that git worktrees don't
inherit from the main tree.

Implementation:
- Add worktree_post_create field to GitPreferences interface
- Add validation in validatePreferences (must be non-empty string)
- Add runWorktreePostCreateHook() in auto-worktree.ts — resolves
  relative paths against project root, runs with 30s timeout,
  failure is non-fatal (warning only)
- Integrate hook call in createAutoWorktree() (auto-mode path)
- Integrate hook call in worktree-command.ts (manual /worktree path)
- Update docs/configuration.md with full usage guide and example
  hook script
- Update preferences-reference.md with field documentation

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

Example hook script:
  #!/bin/bash
  cp "$SOURCE_DIR/.env" "$WORKTREE_DIR/.env"
  ln -sf "$SOURCE_DIR/assets" "$WORKTREE_DIR/assets"

Closes #597

* fix: use Node.js scripts in hook tests for Windows compatibility

Replace bash hook scripts with cross-platform Node.js scripts in
worktree-post-create-hook.test.ts. On macOS/Linux, scripts use
#!/usr/bin/env node shebang. On Windows, generates batch files
that invoke node -e. Fixes windows-portability CI failures.

* fix: Windows CI failures in worktree post-create hook tests

- Use path.isAbsolute() instead of startsWith("/") to detect absolute
  paths on Windows (fixes double-path bug like C:\...\C:\...)
- Add .bat extension to hook scripts on Windows so they are recognized
  as executable by cmd.exe
- Extract isWin constant and hookPath() helper for consistent
  platform-aware test setup

Fixes 3 failing tests in windows-portability CI job:
  - executes hook script with correct env vars
  - supports absolute hook paths
  - hook can copy files from source to worktree

* fix: adopt main's help command and error message in commands.ts

The auto-merge missed main's addition of the help handler, showHelp
function, and updated description/subcommands array. Added them
manually and updated the visualizer help text to reflect 7-tab TUI.

* fix: write Windows hook scripts as .bat + companion .js file

The previous approach embedded multi-line JavaScript in a node -e "..."
argument inside the .bat file. cmd.exe splits on newlines, so each JS
line was interpreted as a separate batch command ('const' is not
recognized...).

Now writes the JS code to a companion .js file and the .bat invokes
it with `node "%~dp0<file>.js"`, which works reliably on Windows.

---------

Co-authored-by: TÂCHES <afromanguy@me.com>
2026-03-16 09:50:45 -06:00

14 KiB

Configuration

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

/gsd prefs Commands

Command Description
/gsd prefs Open the global preferences wizard (default)
/gsd prefs global Interactive wizard for global preferences (~/.gsd/preferences.md)
/gsd prefs project Interactive wizard for project preferences (.gsd/preferences.md)
/gsd prefs status Show current preference files, merged values, and skill resolution status
/gsd prefs wizard Alias for /gsd prefs global
/gsd prefs setup Alias for /gsd prefs wizard — creates preferences file if missing

Preferences File Format

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
---

Global vs Project Preferences

Scope Path Applies to
Global ~/.gsd/preferences.md All projects
Project .gsd/preferences.md Current 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

All Settings

models

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

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.

token_profile

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

Values: budget, balanced (default), quality

Profile Behavior
budget Skips research + reassessment phases, uses cheaper models
balanced Default behavior — all phases run, standard model selection
quality All phases run, prefers higher-quality models

phases

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

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

skill_discovery

Controls how GSD finds and applies skills during auto mode.

Value Behavior
auto Skills found and applied automatically
suggest Skills identified during research but not auto-installed (default)
off Skill discovery disabled

auto_supervisor

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

budget_ceiling

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

budget_ceiling: 50.00

budget_enforcement

How the budget ceiling is enforced:

Value Behavior
warn Log a warning but continue
pause Pause auto mode (default when ceiling is set)
halt Stop auto mode entirely

context_pause_threshold

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)

uat_dispatch

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

uat_dispatch: true

unique_milestone_ids

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

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

git

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: false            # WIP snapshot commits during long tasks
  pre_merge_check: false      # 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" or "branch"
  commit_docs: true           # commit .gsd/ artifacts to git (set false to keep local)
  worktree_post_create: .gsd/hooks/post-worktree-create  # script to run after worktree creation
Field Type Default Description
auto_push boolean false Push commits to remote after committing
push_branches boolean false Push milestone branch to remote
remote string "origin" Git remote name
snapshots boolean false WIP snapshot commits during long tasks
pre_merge_check bool/string false Run checks before merge (true/false/"auto")
commit_type string (inferred) Override conventional commit prefix (feat, fix, refactor, docs, test, chore, perf, ci, build, style)
main_branch string "main" Primary branch name
merge_strategy string "squash" How worktree branches merge: "squash" (combine all commits) or "merge" (preserve individual commits)
isolation string "worktree" Auto-mode isolation: "worktree" (separate directory) or "branch" (work in project root — useful for submodule-heavy repos)
commit_docs boolean true Commit .gsd/ planning artifacts to git. Set false to keep local-only
worktree_post_create string (none) Script to run after worktree creation. Receives SOURCE_DIR and WORKTREE_DIR env vars

git.worktree_post_create

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.

notifications

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

remote_questions

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)

post_unit_hooks

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.

pre_dispatch_hooks

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

Skill routing preferences:

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

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

skill_rules

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]

custom_instructions

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>.

dynamic_routing

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

auto_visualize

Show the workflow visualizer automatically after milestone completion:

auto_visualize: true

See Workflow Visualizer.

Full Example

---
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
  commit_docs: true

# Skills
skill_discovery: suggest
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

# Hooks
post_unit_hooks:
  - name: code-review
    after: [execute-task]
    prompt: "Review {sliceId}/{taskId} for quality and security."
    artifact: REVIEW.md
---