From 6776727f55495647b25aa5b814eca7a19d65fd6d Mon Sep 17 00:00:00 2001 From: pallaoro Date: Fri, 17 Jul 2026 08:55:24 +0200 Subject: [PATCH] feat(commands): add /sidenote to park a thought without derailing the current task A passing thought dropped mid-task reads as a new request, so the agent rushes the big task to get to it. /sidenote reframes it as a parked later-task: log it verbatim to .claude/sidenotes.md, one-line ack, resume with scope and pace unchanged. Bare /sidenote flushes the list. Wired into the installer (copy on install, remove on uninstall) and documented in the README alongside /scalable, including the plain-text SIDENOTE: prefix for agents without slash commands. --- README.md | 18 +++++++++++++++++- bin/install.js | 2 ++ commands/sidenote.md | 21 +++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 commands/sidenote.md diff --git a/README.md b/README.md index 2b356f2..1833354 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ > Built and maintained by [Clawnify](https://clawnify.com) — a managed platform that provisions AI agents with WhatsApp / Telegram / Email and browser capabilities for non-technical users. -A single `CLAUDE.md` file to improve AI coding-agent behavior, derived from [Andrej Karpathy's observations](https://x.com/karpathy/status/2015883857489522876) on LLM coding pitfalls, plus three sections we added for the AI-assisted-coding era. Ships with two runnable [meta-skills](#skills-skillify-dry--mece-resolvers), the [`/scalable`](#the-scalable-command) decision command, and a [one-command installer](#install) that fans it all out to every AI coding agent you use. +A single `CLAUDE.md` file to improve AI coding-agent behavior, derived from [Andrej Karpathy's observations](https://x.com/karpathy/status/2015883857489522876) on LLM coding pitfalls, plus three sections we added for the AI-assisted-coding era. Ships with two runnable [meta-skills](#skills-skillify-dry--mece-resolvers), the [`/scalable`](#the-scalable-command) decision command, the [`/sidenote`](#the-sidenote-command) park-a-thought command, and a [one-command installer](#install) that fans it all out to every AI coding agent you use. ## The Problems @@ -192,6 +192,22 @@ cp commands/scalable.md ~/.claude/commands/ # personal, all projects Then `/scalable` (tests the current direction) or `/scalable `. +## The `/sidenote` command + +You're mid-way through a big task and a passing thought hits — *"the retry logic probably has the same bug", "remind me to check the pricing later"* — something you don't want to forget. Drop it in the chat as-is and the agent reads it as a new request: it rushes the current task to "get to" your note, and the big task pays for it. + +[`commands/sidenote.md`](./commands/sidenote.md) reframes that thought as a **parked later-task, not a now-task**. The agent logs it verbatim to `.claude/sidenotes.md` (durable across compaction and session end), gives a one-line ack, and resumes *exactly* where it was — same scope, same pace, no cutting corners to reach the note. A bare `/sidenote` flushes the list back to you. + +```bash +mkdir -p ~/.claude/commands +cp commands/sidenote.md ~/.claude/commands/ # personal, all projects +# or: .claude/commands/ for one project +``` + +Then `/sidenote ` to park one, or `/sidenote` to see what's parked. The notes land in `.claude/sidenotes.md` — add it to `.gitignore` if you'd rather not track it. + +> **No slash commands?** For agents that read a rule file but have no `/` commands (Cursor, Codex, Copilot…), the same contract works as a plain-text convention: prefix the message with `SIDENOTE:` and the agent parks it instead of acting. Add one line to your rule file so it's honored reliably — see [`commands/sidenote.md`](./commands/sidenote.md) for the exact contract. + ## Install **One command — every agent on your machine:** diff --git a/bin/install.js b/bin/install.js index e63c17b..2d88bf6 100644 --- a/bin/install.js +++ b/bin/install.js @@ -130,12 +130,14 @@ function installClaude(dir, un) { removePath(path.join(dir, 'skills', 'skillify')); removePath(path.join(dir, 'skills', 'check-resolvable')); removePath(path.join(dir, 'commands', 'scalable.md')); + removePath(path.join(dir, 'commands', 'sidenote.md')); return; } fenceInto(path.join(dir, 'CLAUDE.md'), PRINCIPLES); copyDir(path.join(PKG, 'skills', 'skillify'), path.join(dir, 'skills', 'skillify')); copyDir(path.join(PKG, 'skills', 'check-resolvable'), path.join(dir, 'skills', 'check-resolvable')); writeFile(path.join(dir, 'commands', 'scalable.md'), fs.readFileSync(path.join(PKG, 'commands', 'scalable.md'), 'utf8')); + writeFile(path.join(dir, 'commands', 'sidenote.md'), fs.readFileSync(path.join(PKG, 'commands', 'sidenote.md'), 'utf8')); } function applyProvider(p, un) { diff --git a/commands/sidenote.md b/commands/sidenote.md new file mode 100644 index 0000000..1cb6a6d --- /dev/null +++ b/commands/sidenote.md @@ -0,0 +1,21 @@ +--- +description: Park a passing thought as a later-task without derailing the current one — logged, not acted on. +argument-hint: [thought to park — optional] +--- + +Park this thought — **$ARGUMENTS** — as a sidenote. A sidenote is a *later-task*, not a *now-task*. Your job is to record it and keep going, nothing more. + +**The contract — hold it exactly:** + +- **Do not act on it.** Don't investigate it, don't open the files it mentions, don't add it to your current plan, don't answer the question it poses. It is parked, not pending. +- **Do not let it touch the current task.** Its scope, plan, priorities, and *pace* stay exactly as they were. In particular: **do not speed up or cut corners to "get to" the note.** The whole point of parking it is that it costs the current work nothing. +- **Urgency doesn't override the contract.** If the note reads as urgent ("prod is down", "this is broken"), that's the wrong channel — a real emergency is a normal interruption, not a sidenote. Still just log it and resume; the human will escalate directly if they meant to. + +**Persist it so it survives this session** (context gets compacted; memory doesn't count as "logged"): + +1. Append one bullet to `.claude/sidenotes.md` at the project root — create the file (and `.claude/`) if missing. +2. Format: `- [] `. Don't paraphrase or "improve" it — capture what was said. + +Then: **one-line acknowledgement** (e.g. `Parked in .claude/sidenotes.md — continuing.`) and **resume exactly where you left off**, as if the note had never arrived. + +**If `$ARGUMENTS` is empty** (a bare `/sidenote`), there's nothing to park — treat it as a *flush*: read `.claude/sidenotes.md` and list the currently-open sidenotes back to me so I can decide what to pick up. Change nothing, act on nothing, then resume.