diff --git a/README.md b/README.md index 52bc6b2..8d36cdd 100644 --- a/README.md +++ b/README.md @@ -123,6 +123,24 @@ Generate ASCII art from images or text using shape vector rendering. - Adjustable contrast, size, and invert options - Built-in demo mode +### [note](./skills/note) + +Pin a short personal reminder to the Claude Code status line. + +**Use when:** + +- You type `/note ` (e.g. `/note revert the test-only flag before merging`) +- You say "remind me to…", "note to self", "pin a note", "set a reminder" +- You want to clear it: `/note clear` + +**Features:** + +- Synthesizes your input into a terse one-line reminder (strips filler) +- Renders on its own status-line row as a bold black-on-yellow sticky note +- Scoped to the current session — notes don't leak across Claude sessions +- Persists across compactions/restarts until cleared +- Ships an idempotent installer that wires the status line for you + --- ## Installation @@ -136,6 +154,7 @@ npx skills add dupe-com/skills/nomistakes npx skills add dupe-com/skills/ascii-renderer npx skills add dupe-com/skills/reviews npx skills add dupe-com/skills/rebased +npx skills add dupe-com/skills/note ``` This works with Claude Code, OpenCode, Cursor, Windsurf, Cline, Codex, AMP, Copilot, and any agent that supports the [agentskills.io](https://agentskills.io) standard. diff --git a/skills/note/README.md b/skills/note/README.md new file mode 100644 index 0000000..f3d6868 --- /dev/null +++ b/skills/note/README.md @@ -0,0 +1,41 @@ +# note + +Pin a short personal reminder to the Claude Code status line. Type `/note ` and +the agent synthesizes it into a terse line that shows on its own status-line row with a bold +black-on-yellow "sticky note" background. The note is **scoped to the current session** and +persists until you clear it. + +## Use when + +- You type `/note ` (e.g. `/note revert the test-only flag before merging`) +- You say "remind me to…", "note to self…", "pin a note", "set a reminder" +- You want to clear it: `/note clear` (also `done` / `remove` / `delete` / `off` / `x`, or empty) + +## What it does + +- **Set / replace:** synthesizes your input into ≤ ~45 chars (strips "remind me to" filler, + imperative, single line) and writes it to `~/.claude/notes/.txt`. +- **Clear:** deletes this session's note file. +- The status line renders the current session's note on its own line as ` 📌 ` in + bold black-on-yellow. + +## Setup + +The skill wires the status line for you on first use via: + +```bash +bash ~/.claude/skills/note/scripts/install-note-statusline.sh +``` + +This idempotently injects a guarded snippet into `~/.claude/statusline-command.sh` (respecting +`$CLAUDE_CONFIG_DIR`). If you have no status line yet, it creates one and prints the +`settings.json` line to enable it. If you already have a custom status line that doesn't use +the standard `input=$(cat)` stdin capture, the installer won't touch it — it prints the snippet +for you to paste instead. + +## Notes + +- One active note per session; setting a new one replaces it. +- Notes do not leak across sessions — each session reads only its own file. +- Old sessions' note files harmlessly accumulate in `~/.claude/notes/`; only the current + session's is ever displayed. diff --git a/skills/note/SKILL.md b/skills/note/SKILL.md new file mode 100644 index 0000000..854d558 --- /dev/null +++ b/skills/note/SKILL.md @@ -0,0 +1,64 @@ +--- +name: note +description: Pin a short personal reminder to the agent's status line. Use when the user types "/note", or says "remind me", "note to self", "pin a note", "set a reminder", or "clear my note". The note is synthesized into a terse line and shown on its own status-line row with a bold sticky-note background, scoped to the current session, until cleared. +--- + +# /note — status-line reminder (per session) + +Pin a short reminder for the user to the Claude Code status line. A status-line snippet +reads the note for the **current session** from `$CFG/notes/.txt` and renders it +on its own line with a bold black-on-yellow "sticky note" background. The note is scoped to +its session (it does NOT leak into other Claude sessions) and persists until cleared. + +Throughout, `CFG` means `${CLAUDE_CONFIG_DIR:-$HOME/.claude}` — the agent's config dir. The +current session id is in the env var `$CLAUDE_CODE_SESSION_ID` (use it verbatim; never hardcode). + +## First-time setup (run once per machine) + +Before setting the first note, make sure the status line is wired to render it. This is +idempotent — safe to run every time; it no-ops if already installed: + +```bash +bash ~/.claude/skills/note/scripts/install-note-statusline.sh +``` + +(Use wherever this skill is installed.) The installer injects a guarded snippet into +`CFG/statusline-command.sh`. If no status line exists yet it creates one and prints the line +to add to `settings.json` (`"statusLine": { "type": "command", "command": "bash " }`); +relay that to the user. If you see "already installed", stay silent about setup and just set +the note. + +## Behavior + +Look at the argument the user passed after `/note` (or the equivalent natural-language request). + +### 1. Clearing a note +If the argument is empty, or is one of: `clear`, `done`, `remove`, `delete`, `off`, `x` +→ remove this session's note file and confirm: +```bash +rm -f "${CLAUDE_CONFIG_DIR:-$HOME/.claude}/notes/$CLAUDE_CODE_SESSION_ID.txt" +``` +Then reply in one line: `Note cleared.` + +### 2. Setting / replacing a note +Otherwise, **synthesize** the user's input into a single terse reminder line: +- Strip filler ("remind me to", "note to self", "don't forget") — keep only the actionable gist. +- Imperative, present tense. No trailing punctuation. +- **Keep it short — aim for ≤ 45 characters** so it fits the status line. If the source is long, compress to the essential cue, not a full sentence. +- Single line only — strip any newlines. + +Write the synthesized text (no quotes, no markdown, no emoji — the status line adds its own 📌) to this session's file: +```bash +cfg="${CLAUDE_CONFIG_DIR:-$HOME/.claude}"; mkdir -p "$cfg/notes" +printf '%s' 'SYNTHESIZED_NOTE_HERE' > "$cfg/notes/$CLAUDE_CODE_SESSION_ID.txt" +``` +Use `printf '%s'` (not `echo`) so no trailing newline is added. Single-quote the note; if it contains a literal single quote, escape it as `'\''`. + +Then reply in one line showing exactly what was pinned, e.g.: `Pinned: ship the eval on the Mac Studio` + +## Notes +- The note is **per-session** — one active note per Claude session; setting a new one replaces this session's. +- It persists across compactions/restarts of the same session until cleared. +- The status line refreshes on activity, so a freshly pinned note appears on the next render (the next message/tool action), not instantly. +- Old sessions' note files harmlessly remain in `CFG/notes/`; the status line only shows the current session's. +- Do not over-explain; this is a fast utility. One-line confirmation only. diff --git a/skills/note/metadata.json b/skills/note/metadata.json new file mode 100644 index 0000000..b2b2300 --- /dev/null +++ b/skills/note/metadata.json @@ -0,0 +1,19 @@ +{ + "version": "1.0.0", + "organization": "Dupe.com", + "author": "Ramin Bozorgzadeh", + "date": "June 2026", + "abstract": "Pins a short personal reminder to the Claude Code status line. Synthesizes the user's input into a terse single line and renders it on its own status-line row with a bold black-on-yellow sticky-note background. Scoped to the current session (no cross-session leakage) and persists until cleared. Ships an idempotent installer that wires the status line.", + "references": [ + "https://agentskills.io/specification", + "https://code.claude.com/docs/en/statusline" + ], + "compatibility": ["claude-code"], + "tags": [ + "status-line", + "reminder", + "productivity", + "workflow", + "notes" + ] +} diff --git a/skills/note/scripts/install-note-statusline.sh b/skills/note/scripts/install-note-statusline.sh new file mode 100755 index 0000000..5fc4bb0 --- /dev/null +++ b/skills/note/scripts/install-note-statusline.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash +# Idempotently wire the Claude Code status line to render the /note sticky note. +# Safe to run repeatedly — it no-ops once installed. +# +# What it renders: the note for the CURRENT session, read from +# $CFG/notes/.txt +# on its own line, as a bold black-on-yellow sticky note. (Claude Code's status +# line only honors SGR color / OSC 8 link escapes and trims leading whitespace, +# so right-alignment isn't achievable — the note is left-aligned.) +set -euo pipefail + +CFG="${CLAUDE_CONFIG_DIR:-$HOME/.claude}" +SL="$CFG/statusline-command.sh" +START="# >>> note-skill (per-session sticky note) >>>" +END="# <<< note-skill <<<" + +read -r -d '' BLOCK <<'EOF' || true +# >>> note-skill (per-session sticky note) >>> +# Renders this session's pinned note (set via the /note skill) on its own line. +# Assumes the script captured stdin into $input (input=$(cat)). +__cfg="${CLAUDE_CONFIG_DIR:-$HOME/.claude}" +__sid=$(printf '%s' "${input:-}" | jq -r '.session_id // empty' 2>/dev/null || true) +if [ -n "${__sid:-}" ] && [ -s "$__cfg/notes/$__sid.txt" ]; then + __note=$(tr -d '\n' < "$__cfg/notes/$__sid.txt") + if [ -n "$__note" ]; then + printf "\n\033[1;30;103m 📌 %s \033[0m" "$__note" + fi +fi +# <<< note-skill <<< +EOF + +mkdir -p "$CFG/notes" + +# Already installed? +if [ -f "$SL" ] && grep -qF "$START" "$SL"; then + echo "note-skill status line already installed at $SL" + exit 0 +fi + +# Fresh install: create a complete, self-contained status line. +if [ ! -f "$SL" ]; then + { + printf '#!/usr/bin/env bash\n' + printf '# Claude Code status line\n' + printf 'input=$(cat)\n\n' + printf '%s\n' "$BLOCK" + } > "$SL" + chmod +x "$SL" + echo "Created $SL" + echo + echo "Add this to your settings.json (\"$CFG/settings.json\") so Claude Code uses it:" + echo ' "statusLine": { "type": "command", "command": "bash '"$SL"'" }' + exit 0 +fi + +# Existing status line that captures stdin into $input — safe to append our block. +if grep -qE 'input=\$\(cat\)|input="\$\(cat\)"' "$SL"; then + printf '\n%s\n' "$BLOCK" >> "$SL" + echo "Appended note-skill block to existing $SL" + exit 0 +fi + +# Existing custom status line we don't recognize — don't risk mangling it. +echo "A custom status line already exists at $SL and it doesn't use the standard" +echo "'input=\$(cat)' stdin capture, so this installer won't edit it automatically." +echo "Add the following block to it (it needs the raw stdin JSON in a var named \$input):" +echo +printf '%s\n' "$BLOCK" +exit 0