--- name: note description: > Explicit notes. Use when user says "note X", "note it". --- # Note Explicit note store backed by SQLite. User says "note X" → take only explicitly-typed tags, reformulate content, store via `note.py add`. Delete only on explicit user request. Notes are stored to sqlite db. ## Backend `skills/note/scripts/note.py` — CLI wrapper around `db/note.sqlite`. Operation log: `log/note.log` (append-only, all write operations). ## Tag protocol Tags are the **first token** right after the trigger — comma-separated, no spaces: ``` /note arch explanation of the architecture decision → tags: [arch] /note hw,linux interesting article about kernel → tags: [hw, linux] /note this is a note without tags → tags: [] ``` Rules: - **Tags come *only* from the first token the user actually typed. Never derive, infer, or invent tags from the note's content, topic, or meaning.** If the user did not type a tag, the note has no tags — full stop. - Lowercase only; multi-word tags use `-`: `cli`, `soft-delete`, `task-queue` - If user writes `#tag`, strip `#` before passing to the script - If no tag is given — that is fine, use no tags; never force tags Tags must be **registered before use**. There is no auto-creation: the database holds a registry of known tags, and `add` rejects any tag that is not in it (exit 2). A new tag is born only via the explicit `tag-add` command (see Tag management). Still only pass tags the user typed — registration does not license inventing them. ## Write protocol 1. Take inline tags from the first token only (see Tag protocol above). If that token is not a tag the user typed, the tags field stays empty — never fill it from the content. 2. Reformulate the remaining text into a terse fact. One concept per entry — split if too complex; omit context that is not itself a fact. Preserve input language; never translate. Drop filler. - Input: "poznamenej si, glow zobrazuje markdown v terminálu #cli" - Run: `uv run skills/note/scripts/note.py add "glow displays markdown in terminal" --tags cli` 3. **Unknown tag (`add` exits 2, prints `Unknown tag(s): …`):** the note was NOT stored. For each unknown tag, ask the user (in their language): "Tag #X doesn't exist — create it?" - **Yes** → `uv run skills/note/scripts/note.py tag-add X`, then re-run `add` with the original tags. - **No** → re-run `add` without that tag (keep the known ones). If nothing remains, store with no tags. 4. Echo: `Noted [#1]: [#tag1 #tag2]` (tags omitted if none). `#1` is the display ID of the new note — use it to delete immediately if needed. No dedup. No MEMORY.md lookup. Blind append. ## Tag management Tags are created and listed explicitly — never as a side effect of adding a note. Trigger (create): `/note tag add X`, "create tag X", "register tag X". 1. Run: `uv run skills/note/scripts/note.py tag-add X` 2. Echo the result. Already-existing tag → script reports it and exits 0 (no error). 3. No tag name given → ask which tag to create; do not guess. Trigger (list): `/note tags`, "what tags are there?", "list tags". 1. Run: `uv run skills/note/scripts/note.py tag-list` 2. Echo output. Empty → "No tags." Tags are referenced by name everywhere (no display ID). There is no tag deletion. ## List protocol Trigger: `/note list`, `show notes`, `what notes do you have?` 1. Run: `uv run skills/note/scripts/note.py list [--limit N] [--tag TAG [TAG ...]]` 2. Echo output. If empty → respond "No notes." `--tag` accepts one or more tags; OR logic (notes with at least one matching tag). The number before each note (`1.`, `2.`, …) is the **display ID** — sequential among active notes, newest first. Renumbers after every deletion. Never change, renumber, or drop it. ### URLs in a note The script already lays out each URL (with its inline label, if any) on its own indented bullet line. **Echo the output verbatim** — keep the bullets and line breaks, keep URLs bare. Never collapse the bullets back onto one line and never wrap a URL in `[text](url)`: this chat UI merges two adjacent inline links into one block, hides the second URL, and overlays the list number. Bare URLs on their own lines autolink correctly and stay separate. ## Show protocol Trigger: `/note show `, `show note N`, `read note N`, `what does note N say`. 1. Display IDs are the same as in `list`/`delete` — sequential among active notes, newest first, renumbered after every deletion. If unsure, run `list` first. 2. Run: `uv run skills/note/scripts/note.py show ` - Exit 0 → **output the script's stdout verbatim — print every line exactly as emitted.** Do not summarize, shorten, rewrap, or drop any part of the `content` field, including URLs and links. The `show` command exists precisely to surface the note in full; brevity directives do not apply here. - Exit 1 → display ID out of range; respond accordingly. 3. `show` is read-only — it never deletes or modifies anything. The block contains every stored field: display ID, internal DB id, creation timestamp, tags, and full untruncated content. ## Delete protocol Trigger: `/note delete`, `delete a note`, `remove a note`. 1. If the user has not specified an ID, run `list` first to show current notes. 2. Run: `uv run skills/note/scripts/note.py delete ` - Exit 0 → confirm deletion. - Exit 1 → display ID out of range; respond accordingly. 3. Nothing is deleted automatically. Only this explicit protocol deletes. Display IDs renumber after every deletion (e.g., after deleting #3, the old #4 becomes #3). Always run `list` first if unsure of current IDs. ## Edge cases - `/note` with no content → ask "What should I note?" - Vague input → ask for the concrete fact; do not store a placeholder. - `/note tag add` with no name → ask which tag to create; never guess. - `/note show` with no ID → run `list` first, then ask which display ID. - `/note delete` with no ID → run `list` first, then ask which display ID. - Multi-line input → collapse to one line; one entry = one row. ## Rules - Never store verbatim input. Always reformulate. Preserve input language. - Do not store smalltalk or meta-commentary about the note skill itself. - **No auto-load:** `note.sqlite` is never referenced in bootstrap files. - **No auto-delete / no compaction.** Only explicit delete marks an entry. - **Delete is soft** — the entry is marked with a timestamp, not removed from the database. The operation log (`log/note.log`) is the primary audit trail. - Separate from `/keep`, `MEMORY.md`, Dream — never cross-write or cross-read.