Files
nanobot-runtime/skills/note/SKILL.md
2026-06-24 08:11:12 +02:00

6.6 KiB

name, description
name description
note 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?"
    • Yesuv 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.