Skip to main content

brainllm

Persistent memory and knowledge graph via the BrainLLM (Trilium) MCP. Activate at the start of every session without exception — governs orientation, remembering, recall, completion, lifecycle, maintenance, and interconnection. Trigger immediately on any first user message. Also trigger whenever: memory is referenced, something needs to be remembered or recalled, a durable fact or decision emerges, context from a prior session is needed, a knowledge domain is introduced, content goes stale, or any Trilium operation is requested. Do not improvise memory operations without reading this skill.

Quellinformationen

Repository
miisodev/BrainLLM
Letzte Quellaktivität
15. Oktober 2026 um 13:38
Erkannte Sprache von SKILL.md
Englisch
Sterne
0
Forks
1

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
6 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
brainllm
description
Persistent memory and knowledge graph via the BrainLLM (Trilium) MCP. Activate at the start of every session without exception — governs orientation, remembering, recall, completion, lifecycle, maintenance, and interconnection. Trigger immediately on any first user message. Also trigger whenever: memory is referenced, something needs to be remembered or recalled, a durable fact or decision emerges, context from a prior session is needed, a knowledge domain is introduced, content goes stale, or any Trilium operation is requested. Do not improvise memory operations without reading this skill.
# BrainLLM — Operational Skill Persistent memory that survives across sessions, stored in TriliumNext. Treat it as your own mind: orient at session start, write the moment something matters, complete things when they complete, log the session at the end. **You supply content; the server owns form** — placement, labels, dedup, relations, dates, backups, archival and each kind's skeleton (`template(kind)`). If you find yourself doing bookkeeping, a tool does it for you. The shape *inside* a note is yours, held to the four writing rules below. **Operate from it natively.** `start()` loads who the user is and who you are here — act from both unprompted. When the topic is the user's world, read the brain before answering from training; it is authoritative where it speaks. --- ## The two content rules 1. **Timeless by default.** Singletons, thread books, user-knowledge notes, domain books and information notes hold what is true regardless of date. **No state, version, status, incident or decision history in them.** State lives in each domain's **Current State** note (latest measured value, with its measurement date). History and decisions live in **thread entries and sessions**, where the date is native. This keeps knowledge correct and cheap to maintain. 2. **Universal usefulness.** If one sentence says it, one sentence is enough. If it is rarely relevant to the interactions, automations and workflows the brain serves, it goes. Every note is read by some session; its size is paid on every read. --- ## The Protocol ``` START start() once, before responding [day()] when start() reports newDay DURING remember(...) the moment something is worth keeping revise(...) / split(...) edit in place; split an oversized note on its seams resolve / withdraw / recover thread and note lifecycle connect(...) wire a real relation when you see one read: <surface>, domain, recall, read(ids), outline, inspect, assembly, brain verify: consistency(...), claim(...), diff(since="today"), health() END session() → [update singletons] → addendum() → maintain() → remarks() → diary() → close() ``` `start()` returns the date, **preferences and protocols in full**, the other singletons as section headings (pull one with `master(which)`/`llm(which)`, `section=` for one section; `depth="full"` inlines all), today's diary and session ids, active and dormant threads, the previous session and notes changed since (capped at 25; `changesTruncated: {shown, total}` names the cap when there were more). `newDay: true` means no INTERACTIVE close has happened today — an overnight agent-session addendum does not count, so the morning still calls `day()` (previous session, its log, notes touched since; `day()`'s `newDay` is the same signal). `day(recap=true)` returns everything written today, in order, across sessions, diary and thread entries. **Close protocol.** `session()` returns `singletons: "stubs"` (stub mode — not a light close), `changedToday` (the maintained notes this day's writes touched: check every figure you changed agrees everywhere it is recorded, with `diff(since="today")` and `consistency()`), `pending=` (what each remaining step has to do), `audit=` (do the singletons agree, and do the LLM ones still serve the master ones) and `next[]`. Update master singletons with what you learned about the user and LLM singletons with what you learned about yourself, fold any addenda (`addendum()`), `maintain()`, `remarks()` for diary cues, `diary()` your closing record, then `close(summary, identity)`. `close()` refuses until those steps ran and `session → remarks → diary` held; the gate is durable across restarts. `force=true` bypasses a step with nothing to do (reported). `continuing=true` is a second close on the same day, opened by `session(continuing=true)` — the same short continuation receipt (no singleton review), refused on the day's first session. Scoped or autonomous runs pass `session(scope="agent")`. **Light close:** a session that wrote no content gets `closeMode: "light"` from `session()` — only `remarks()`, a one-paragraph `diary()` and `close()` follow; any content write since the last close brings the full protocol back. Every `close()` also seals its day's records, which `maintain(deep)` later verifies. **Write during the session, not at the end** — a fact written mid-conversation survives a crash. --- ## The Structure ``` BrainLLM ├── Master biography · goals · preferences (singletons about the user) ├── LLM responsibilities · protocols · selfcorrection · Diary/ (singletons about you + one diary note per day) ├── Memory Sessions/ · Threads/ (one session note per day + multi-session threads) ├── Knowledge Master/ (user knowledge) · Domains/<domain>/{Sources, information notes} └── Insights Logs/ · Graph · Claims/ ``` **Singletons derive from each other.** Master holds the user: biography, goals, preferences. LLM holds you, **derived from master**: responsibilities serve the goals and preferences, protocols are the operating rules that meet the responsibilities, self-correction holds only general rules learned from your mistakes. When master changes, re-derive LLM; `session()`'s `audit=` asks this every close. **Threads have two shapes.** A thread book holds its **Goal** (what the thread is for, a sentence or two) and optional standing constraints; never progress (a register thread such as Escalations also keeps its one maintained register table there). Its children carry the content: | Shape | Children | Use for | |---|---|---| | **dated** (default) | one `[yyyy-mm-dd]` entry per active day, `Addendum — HH:mm` blocks with an identification line | a line of work: the history lives here | | **collection** | one **titled** entry per item, each a maintained document edited in place | a list of things: ideas, candidates, specs | Create with `remember(kind="thread", title, goal, shape?)`. Dated: append with `remember(kind="thread", title, body, identity)` or `revise(threadId, body, identity)`; `memory(id)` indexes the children newest first, `memory(id, date=)` resolves a day. Collection: add with `remember(kind="threadEntry", thread=<id>, title, body)`, change with `revise(<entry id>)`; `memory(id)` lists entries alphabetically. Appending to a collection book is refused with those two paths. **Records** — sessions, diary, logs and dated thread entries — are one note per day, every write a timestamped `Addendum — HH:mm` block. They are never trimmed or rewritten. --- ## Where things go ``` worth keeping? ├─ about the user ─→ biography / goals / preferences (revise the section, in place) │ otherwise a Knowledge/Master note (remember kind="user") ├─ world knowledge beyond or against training ─→ a domain (sources gate — references/domains.md) │ measured state → that domain's Current State · timeless knowledge → an information note ├─ what happened / what was decided ─→ the relevant thread entry (or the session log) └─ passing remark or already known from training ─→ don't capture ``` **Domains are your own working knowledge of a subject as it currently is.** Their scope, depth and size are your call, set by what keeps you confident enough to act and advise well; refresh one whenever reality moves. The structure keeps that knowledge tidy and checkable, and never caps it: one maintained **Sources** note plus one information note per sub-category, including **Current State**, revised in place. Every claim traces to a Sources entry (❇️ discovered, ✅ used); `remember(kind="sources", revision=[{source, marker, date}])` upserts the Revision row. Creating a domain creates its Sources note. Read `references/domains.md` before creating a domain, adding a sub-category or refreshing one. --- ## Reading | Need | Tool | |---|---| | a singleton | `master(which)` / `llm(which)` — `section=` for one section | | a thread or session | `memory(id)` — dated index (newest days, up to 30 and ~24k characters; `limit=` for more) or collection entries; `date=` for one day; `index=true` for ids, dates and block markers only; `block="14:05"` (or `"-1"`, the newest) for one addendum of a session or day entry — `llm("diary", id, block=)` likewise | | a knowledge note | `knowledge(id)` — `section=` for one section | | a day's change log | `insights(date?)` | | skim a surface | `<surface>_recall` | | everything about an area | `domain(name)` — the reliable path; reach here first. `outline=true` adds every maintained note's headings and size, for planning a multi-note rewrite | | search | `recall(query, domain=…)` — scope it; `since=`/`until=` keep only notes last modified inside the window (date-only bounds cover whole days); every hit names `matchedBy` (`label`/`title`/`text`/`fuzzy`/`ordered`/`regex`) and the top hits carry the `evidence` passage; `regex=` for structure, evidenced on every hit (records included; `kinds=` narrows); fuzzy hits are leads; recent notes rank slightly higher. A receipt that saturated a strategy's 30-candidate cap says so; `searchFailed: true` is a backend failure, never a "nothing matched" verdict — retry | | several bodies at once | `read(ids=[…])` (≤ 10). Every entry carries `chars` (the full stored size, even when a section is returned); `section=` (+ `occurrence=`) reads one heading's body from each note — a table section reports `tableRows`, and a miss follows the singleton miss shape (`missing: true` for an unknown id; `available[]` lists the real headings for a section miss). Bodies stop at ~80k characters; the rest come back in `deferred[]` for a second call. `text=true` returns readable plain text for orienting (not for building a `find=` anchor) | | storage and growth | `health()` — Trilium version, estimated database size, heaviest notes and their revisions, named backups | | what the brain holds | `assembly(area?)` — titles by surface with purposes | | inventory / locate by id | `brain()` — read `parent`, not position | | a note's heading tree | `outline(id)` — before any `section=` edit you're unsure of | | raw labels, relations, body | `inspect(id, content?, section?, find?)` — `find=` also returns the stored element (row, item, paragraph) around each match | Every read that can be large takes `section=` — `read(ids)` too, across each note; a note past the read ceiling cannot be returned whole. --- ## Writing — `remember`, `diary`, `close` | Content | Call | |---|---| | about the user, not bio/goals/prefs | `remember(kind="user", title, body)` | | domain knowledge | `remember(kind="information", domain, title, body)` | | a domain source | `remember(kind="sources", domain, body, revision?)` | | a new line of work | `remember(kind="thread", title, goal, shape?)` — ask the user for the goal | | a dated thread append | `remember(kind="thread", title, body, identity)` | | a collection entry | `remember(kind="threadEntry", thread, title, body)` | | your daily record | `diary(body, identity)` | | the session log | `close(summary, identity, title?, learned?)` | - **Dedup is by title.** Generic titles (Current State, Sources) exist in many domains — pass `mustCreate=true` when you mean to create, and read `action` on every receipt. - **Sources preview before they land.** `remember(kind="sources", …, revision=)` takes `dryRun=true`, which previews each Revision row addition/update without writing; a new key near an existing one returns `didYouMean` (with `didYouMeanNote`) on the dry run and on the real call, so a qualifier added to a name updates its row instead of creating a second one. - **Wire at creation:** `connect=[{relation, toNoteId}]` on the same call. An unconnected note is an orphan until wired. - **Identity line** (`"LLM · environment · agent/mode [· Run N]"`) is required on diary, close and dated thread appends. It is checked on write: at least three `·`-separated parts, one line, no draft text — a malformed one is refused with nothing written. - **Every note carries an icon except logs.** The server sets the kind default at creation (a thread entry takes its thread's icon) and the sweep backfills any missing; `icon=` picks a better one (boxicons class or bare name). Removing an icon is refused. - Bodies may be text, markdown or HTML; the server normalises them to editor-native HTML and reports `sanitized[]` (markdown mixed into an HTML body is converted; a placeholder like `<name>` — even one named like an element, `<template>`, `<select>` — stays as text and never truncates what follows). CKEditor's own attributes (`data-list-item-id` on list items, `spellcheck` on code) are preserved, so re-sanitising a stored note is idempotent and quiet. - `diary`, `session`, `log`, `claim` and `domain` have dedicated paths; `remember` refuses them. **Four writing rules** (each applies to every note you touch): - **Minimal headings.** Only headings that earn their place; depth comes from tables, lists and emphasis. Headings are also what `section=` addresses. - **Match your siblings.** Read an existing note of the same kind and follow its shape; improve a pattern everywhere or nowhere. - **Merge, don't stack.** Everything except records is a clean document: fold new content into its section (`section=`/`find=`), never a dated addendum. - **Titles ≤ 4 words, no dates or run numbers** (they defeat dedup). A title that won't trim means the content wants splitting. Read `template(kind)` before your first write of a kind, then read a sibling. --- ## Updating — `revise` | Mode | Effect | |---|---| | default | dated addendum — right only for records; a dated thread's append lands in today's entry | | `mode="replace"` | whole body | | `section="<heading>"` | replace that section's **whole** body (h2→h3→h4; `occurrence=` for repeats) | | `section=` + `mode="before"/"after"` | insert a sibling block around the whole section | | `section=` + `mode="prepend"` | insert at the top of the section's body | | `section=` + `mode="remove"` | delete the section | | `find="<text>"` | replace every occurrence (`nth=` for one) — exact first, then through re-serialized tags, then ignoring inline formatting (`matchMode` says which) | | `edits=[{find, body}]` | several surgeries in one read and one write | | `find="<short anchor>"` + `within="tr"` | act on the element containing the anchor: replace it (default), `mode="before"/"after"` to insert a row beside it, `mode="remove"` to delete it (`li`, `p`, `td` … too). `within` names what is replaced: `"tr"` takes a whole `<tr>…</tr>` body, `"td"` one `<td>…</td>`; a plain `find=` inside a cell replaces only that text | | `within=` + `dryRun=true` | preview the element first: its full visible extent and byte size, plus the before/after shape (for a `closure=`, what would be appended or moved) — nothing written, no revision. The only other `dryRun` is `domain=` below (its dry run is the default); elsewhere it is refused | | `within="tr"` + `mode="remove"` + `closure=` | close a register row in one call: `{thread, body}` sends the row, quoted, into that thread's entry for today (needs `identity=`); `{note, table?}` moves the removed row into another register note's table, shaped to it — a wider row is refused, a narrower one padded. Run `consistency()` after on any fact the row asserted | | `append={table, row}` | append one row to the table under that heading with no anchor to locate first — pipes are cell boundaries, a lone placeholder row is replaced; composes with nothing else | | `domain="<name>"` + `find=`/`edits=` (no noteId) | the same find/replace across every maintained note in a domain; a dry run listing each match unless `dryRun=false`. Records are never touched | - **Tables are edited by row.** Anchor on a few words unique to the row and pass `within="tr"`; never copy a whole stored row into `find=`. The row's visible text works too (`"Phase 2 | Claude | Open"`), and quotes match in any form. An anchor in several rows is refused with previews; `nth=` picks one. Write one `<td>` per column — a row whose cells disagree with its header comes back as `tableShape`. - **"Last updated" lines are server-owned.** Every content write bumps them (the receipt says `lastUpdated`); never `find=` on one. - A replacement equal to its match writes nothing and reports `unchanged`. - A revision is taken before every content write; `diff(noteId)` shows what the last write changed, and `diff(since="today")` reviews every note you changed today in one call — run it before closing.
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen