152 lines
6.6 KiB
Markdown
152 lines
6.6 KiB
Markdown
---
|
|
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]: <content> [#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 <id>`, `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 <display-id>`
|
|
- 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 <display-id>`
|
|
- 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.
|