Capture an idea, task, or issue that surfaces during a GSD session as a structured todo for later work. Enables "thought → capture → continue" flow without losing context. Read all files referenced by the invoking prompt's execution_context before starting. Load todo context: ```bash _GSD_SHIM_NAME="gsd-tools.cjs"; _GSD_RUNTIME_ROOT="${RUNTIME_DIR:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"; GSD_TOOLS="${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}"; _gsd_at() { for _p; do if [ -f "$_p" ]; then GSD_TOOLS="$_p"; return 0; fi; done; return 1; }; if _gsd_at "${_GSD_RUNTIME_ROOT}/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.claude/gsd-core/bin/${_GSD_SHIM_NAME}" "${_GSD_RUNTIME_ROOT}/.codex/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; elif unset -f gsd_run; _G="$(command -v gsd_run)"; then GSD_TOOLS="$_G"; gsd_run() { "$GSD_TOOLS" "$@"; }; elif _gsd_at "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/gsd-core/bin/${_GSD_SHIM_NAME}" "${HERMES_HOME:-$HOME/.hermes}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CURSOR_CONFIG_DIR:-$HOME/.cursor}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEX_HOME:-$HOME/.codex}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GEMINI_CONFIG_DIR:-$HOME/.gemini}/gsd-core/bin/${_GSD_SHIM_NAME}" "${COPILOT_CONFIG_DIR:-$HOME/.copilot}/gsd-core/bin/${_GSD_SHIM_NAME}" "${WINDSURF_CONFIG_DIR:-$HOME/.codeium/windsurf}/gsd-core/bin/${_GSD_SHIM_NAME}" "${AUGMENT_CONFIG_DIR:-$HOME/.augment}/gsd-core/bin/${_GSD_SHIM_NAME}" "${TRAE_CONFIG_DIR:-$HOME/.trae}/gsd-core/bin/${_GSD_SHIM_NAME}" "${QWEN_CONFIG_DIR:-$HOME/.qwen}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CODEBUDDY_CONFIG_DIR:-$HOME/.codebuddy}/gsd-core/bin/${_GSD_SHIM_NAME}" "${CLINE_CONFIG_DIR:-$HOME/.cline}/gsd-core/bin/${_GSD_SHIM_NAME}" "${GROK_AGENTS_HOME:-$HOME/.agents}/gsd-core/bin/${_GSD_SHIM_NAME}" "${ANTIGRAVITY_CONFIG_DIR:-$HOME/.gemini/antigravity}/gsd-core/bin/${_GSD_SHIM_NAME}" "${OPENCODE_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/opencode}/gsd-core/bin/${_GSD_SHIM_NAME}" "${KILO_CONFIG_DIR:-${XDG_CONFIG_HOME:-$HOME/.config}/kilo}/gsd-core/bin/${_GSD_SHIM_NAME}"; then gsd_run() { node "$GSD_TOOLS" "$@"; }; else echo "ERROR: gsd-tools.cjs not found at $GSD_TOOLS and gsd_run is not on PATH. Run: npx -y @opengsd/gsd-core@latest --claude --local" >&2; exit 1; fi; GSD_IDENTITY_STATUS=unverified; case "$(gsd_run runtime-identity --raw 2>/dev/null || true)" in '{"packageName":"@opengsd/gsd-core"'*'}') GSD_IDENTITY_STATUS=ok;; esac; export GSD_IDENTITY_STATUS; [ "$GSD_IDENTITY_STATUS" = ok ] || echo "WARNING: \"$GSD_TOOLS\" did not prove it is @opengsd/gsd-core - it is either a different package or an @opengsd/gsd-core older than the runtime-identity verb. See docs/how-to/diagnose-a-foreign-gsd-tools.md" >&2; if [ -n "${CLAUDE_ENV_FILE:-}" ] && [ -n "${GSD_TOOLS:-}" ]; then printf "export PATH='%s':\"\$PATH\"\n" "${GSD_TOOLS%/*}" >> "$CLAUDE_ENV_FILE" 2>/dev/null || true; fi INIT=$(gsd_run query init.todos) if [[ "$INIT" == @file:* ]]; then INIT=$(cat "${INIT#@file:}"); fi ``` Extract from init JSON: `commit_docs`, `date`, `timestamp`, `todo_count`, `todos`, `pending_dir`, `todos_dir_exists`, `response_language`. **If `response_language` is set:** All user-facing questions, prompts, and explanations in this workflow MUST be presented in `{response_language}`. Technical terms, code, file paths, and subagent prompts stay in English — only user-facing output is translated. Ensure directories exist: ```bash mkdir -p .planning/todos/pending .planning/todos/completed ``` Note existing areas from the todos array for consistency in infer_area step. **With arguments:** Use as the title/focus. - `/gsd-add-todo Add auth token refresh` → title = "Add auth token refresh" **Without arguments:** Analyze recent conversation to extract: - The specific problem, idea, or task discussed - Relevant file paths mentioned - Technical details (error messages, line numbers, constraints) Formulate: - `title`: 3-10 word descriptive title (action verb preferred) - `problem`: What's wrong or why this is needed - `solution`: Approach hints or "TBD" if just an idea - `files`: Relevant paths with line numbers from conversation Infer area from file paths: | Path pattern | Area | |--------------|------| | `src/api/*`, `api/*` | `api` | | `src/components/*`, `src/ui/*` | `ui` | | `src/auth/*`, `auth/*` | `auth` | | `src/db/*`, `database/*` | `database` | | `tests/*`, `__tests__/*` | `testing` | | `docs/*` | `docs` | | `.planning/*` | `planning` | | `scripts/*`, `bin/*` | `tooling` | | No files or unclear | `general` | Use existing area from step 2 if similar match exists. Infer a **suggested** severity from the same blocker/major/minor/cosmetic taxonomy `verify-work.md`'s `severity_inference` uses — then CONFIRM it with the user before writing. Never silently auto-assign: a mis-tagged severity silently corrupts backlog triage, which is exactly the signal this field exists to provide. Suggest from the user's natural-language description: | User says | Suggest | |-----------|---------| | "crashes", "error", "exception", "fails completely", "data loss" | blocker | | "doesn't work", "nothing happens", "wrong behavior" | major | | "works but...", "slow", "weird", "minor issue" | minor | | "color", "spacing", "alignment", "looks off" | cosmetic | Default the suggestion to **major** if unclear. **Text mode (`workflow.text_mode: true` in config or `--text` flag):** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS` OR `text_mode` from init JSON is `true`. When TEXT_MODE is active, replace the `AskUserQuestion` below with a plain-text numbered list of the four options and ask the user to type their choice number. Required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is unavailable. Confirm with AskUserQuestion (present the suggested value first): - header: "Severity?" - question: "Suggested severity: [suggested]. Confirm or change:" - options: - "blocker" — breaks a workflow or loses data; fix first - "major" — wrong behavior with no workaround - "minor" — works, but with a workaround or annoyance - "cosmetic" — visual/polish only Carry the confirmed value into `severity` in the create_file frontmatter. ```bash # Search for key words from title in existing todos grep -l -i "[key words from title]" .planning/todos/pending/*.md 2>/dev/null || true ``` If potential duplicate found: 1. Read the existing todo 2. Compare scope **Text mode (`workflow.text_mode: true` in config or `--text` flag):** Set `TEXT_MODE=true` if `--text` is present in `$ARGUMENTS` OR `text_mode` from init JSON is `true`. When TEXT_MODE is active, replace every `AskUserQuestion` call with a plain-text numbered list and ask the user to type their choice number. This is required for non-Claude runtimes (OpenAI Codex, Gemini CLI, etc.) where `AskUserQuestion` is not available. If overlapping, use AskUserQuestion: - header: "Duplicate?" - question: "Similar todo exists: [title]. What would you like to do?" - options: - "Skip" — keep existing todo - "Replace" — update existing with new context - "Add anyway" — create as separate todo Use values from init context: `timestamp` and `date` are already available. Generate slug for the title: ```bash slug=$(gsd_run query generate-slug "$title" --raw) ``` Write to `.planning/todos/pending/${date}-${slug}.md`: ```markdown --- created: [timestamp] title: [title] area: [area] severity: [blocker|major|minor|cosmetic — confirmed in infer_severity step] files: - [file:lines] --- ## Problem [problem description - enough context for future Claude to understand weeks later] ## Solution [approach hints or "TBD"] ``` If `.planning/STATE.md` exists: 1. Use `todo_count` from init context (or re-run `init todos` if count changed) 2. Update "### Pending Todos" under "## Accumulated Context" Commit the todo and any updated state: ```bash gsd_run query commit "docs: capture todo - [title]" --files .planning/todos/pending/[filename] .planning/STATE.md ``` Tool respects `commit_docs` config and gitignore automatically. Confirm: "Committed: docs: capture todo - [title]" ``` Todo saved: .planning/todos/pending/[filename] [title] Area: [area] Files: [count] referenced --- Would you like to: 1. Continue with current work 2. Add another todo 3. View all todos (/gsd:capture --list) ``` - [ ] Directory structure exists - [ ] Todo file created with valid frontmatter - [ ] Problem section has enough context for future Claude - [ ] No duplicates (checked and resolved) - [ ] Area consistent with existing todos - [ ] STATE.md updated if exists - [ ] Todo and state committed to git