name: gsd-note description: "Zero-friction idea capture. Append, list, or promote notes to todos." argument-hint: "<text> | list | promote <N> [--global]" allowed-tools:
- Read
- Write
- Glob
- Grep
<objective> Zero-friction idea capture — one Write call, one confirmation line.
Three subcommands:
- append (default): Save a timestamped note file. No questions, no formatting.
- list: Show all notes from project and global scopes.
- promote: Convert a note into a structured todo.
Runs inline — no Task, no AskUserQuestion, no Bash. </objective>
<!-- Workflow content (was: note.md) --> <purpose> Zero-friction idea capture. One Write call, one confirmation line. No questions, no prompts. Runs inline — no Task, no AskUserQuestion, no Bash. </purpose><required_reading> Read the skill content below before starting. </required_reading>
<process> <step name="storage_format"> **Note storage format.**Notes are stored as individual markdown files:
- Project scope:
.planning/notes/{YYYY-MM-DD}-{slug}.md— used when.planning/exists in cwd - Global scope:
$HOME/.claude/notes/{YYYY-MM-DD}-{slug}.md— fallback when no.planning/, or when--globalflag is present
Each note file:
---
date: "YYYY-MM-DD HH:mm"
promoted: false
---
{note text verbatim}
--global flag: Strip --global from anywhere in $ARGUMENTS before parsing. When present, force global scope regardless of whether .planning/ exists.
Important: Do NOT create .planning/ if it doesn't exist. Fall back to global scope silently.
</step>
| Condition | Subcommand |
|---|---|
Arguments are exactly list (case-insensitive) | list |
Arguments are exactly promote <N> where N is a number | promote |
| Arguments are empty (no text at all) | list |
| Anything else | append (the text IS the note) |
Critical: list is only a subcommand when it's the ENTIRE argument. /gsd-note list of groceries saves a note with text "list of groceries". Same for promote — only a subcommand when followed by exactly one number.
</step>
- Determine scope (project or global) per storage format above
- Ensure the notes directory exists (
.planning/notes/or$HOME/.claude/notes/) - Generate slug: first ~4 meaningful words of the note text, lowercase, hyphen-separated (strip articles/prepositions from the start)
- Generate filename:
{YYYY-MM-DD}-{slug}.md- If a file with that name already exists, append
-2,-3, etc.
- If a file with that name already exists, append
- Write the file with frontmatter and note text (see storage format)
- Confirm with exactly one line:
Noted ({scope}): {note text}- Where
{scope}is "project" or "global"
- Where
Constraints:
- Never modify the note text — capture verbatim, including typos
- Never ask questions — just write and confirm
- Timestamp format: Use local time,
YYYY-MM-DD HH:mm(24-hour, no seconds) </step>
- Glob
.planning/notes/*.md(if directory exists) — project notes - Glob
$HOME/.claude/notes/*.md(if directory exists) — global notes - For each file, read frontmatter to get
dateandpromotedstatus - Exclude files where
promoted: truefrom active counts (but still show them, dimmed) - Sort by date, number all active entries sequentially starting at 1
- If total active entries > 20, show only the last 10 with a note about how many were omitted
Display format:
Notes:
Project (.planning/notes/):
1. [2026-02-08 14:32] refactor the hook system to support async validators
2. [promoted] [2026-02-08 14:40] add rate limiting to the API endpoints
3. [2026-02-08 15:10] consider adding a --dry-run flag to build
Global ($HOME/.claude/notes/):
4. [2026-02-08 10:00] cross-project idea about shared config
{count} active note(s). Use `/gsd-note promote <N>` to convert to a todo.
If a scope has no directory or no entries, show: (no notes)
</step>
- Run the list logic to build the numbered index (both scopes)
- Find entry N from the numbered list
- If N is invalid or refers to an already-promoted note, tell the user and stop
- Requires
.planning/directory — if it doesn't exist, warn: "Todos require a GSD project. Run/gsd-new-projectto initialize one." - Ensure
.planning/todos/pending/directory exists - Generate todo ID:
{NNN}-{slug}where NNN is the next sequential number (scan both.planning/todos/pending/and.planning/todos/completed/for the highest existing number, increment by 1, zero-pad to 3 digits) and slug is the first ~4 meaningful words of the note text - Extract the note text from the source file (body after frontmatter)
- Create
.planning/todos/pending/{id}.md:
---
title: "{note text}"
status: pending
priority: P2
source: "promoted from /gsd-note"
created: {YYYY-MM-DD}
theme: general
---
## Goal
{note text}
## Context
Promoted from quick note captured on {original date}.
## Acceptance Criteria
- [ ] {primary criterion derived from note text}
- Mark the source note file as promoted: update its frontmatter to
promoted: true - Confirm:
Promoted note {N} to todo {id}: {note text}</step>
<edge_cases>
- "list" as note text:
/gsd-note list of thingssaves note "list of things" (subcommand only whenlistis the entire arg) - No
.planning/: Falls back to global$HOME/.claude/notes/— works in any directory - Promote without project: Warns that todos require
.planning/, suggests/gsd-new-project - Large files:
listshows last 10 when >20 active entries - Duplicate slugs: Append
-2,-3etc. to filename if slug already used on same date --globalposition: Stripped from anywhere —--global my ideaandmy idea --globalboth save "my idea" globally- Promote already-promoted: Tell user "Note {N} is already promoted" and stop
- Empty note text after stripping flags: Treat as
listsubcommand </edge_cases>
<success_criteria>
- Append: Note file written with correct frontmatter and verbatim text
- Append: No questions asked — instant capture
- List: Both scopes shown with sequential numbering
- List: Promoted notes shown but dimmed
- Promote: Todo created with correct format
- Promote: Source note marked as promoted
- Global fallback: Works when no
.planning/exists </success_criteria>