brainllm 12.7.0 → 12.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,11 +6,11 @@
6
6
 
7
7
  **Give Claude a memory that survives the session.**
8
8
 
9
- A persistent, graph-structured second brain for Claude and any MCP client — built on [TriliumNext Notes](https://github.com/TriliumNext/Trilium), served over the [Model Context Protocol](https://modelcontextprotocol.io).
9
+ Self-hosted memory for LLMs in [TriliumNext Notes](https://github.com/TriliumNext/Trilium), structured by the server and editable by you, served over the [Model Context Protocol](https://modelcontextprotocol.io).
10
10
 
11
- [**brainllm site**](https://miisodev.github.io/BrainLLM/) · [How it works](https://miisodev.github.io/BrainLLM/how-it-works.html) · [Use cases](https://miisodev.github.io/BrainLLM/use-cases.html) · [Docs](https://miisodev.github.io/BrainLLM/docs.html)
11
+ [**Site**](https://miisodev.github.io/BrainLLM/) · [Connect to Claude](https://miisodev.github.io/BrainLLM/connect.html) · [How it works](https://miisodev.github.io/BrainLLM/how-it-works.html) · [Docs](https://miisodev.github.io/BrainLLM/docs.html) · [Privacy](https://miisodev.github.io/BrainLLM/privacy.html)
12
12
 
13
- [![Version](https://img.shields.io/badge/version-12.7.0-f59e0b?style=flat-square)](https://github.com/miisodev/BrainLLM/releases)
13
+ [![Version](https://img.shields.io/badge/version-12.8.0-f59e0b?style=flat-square)](https://github.com/miisodev/BrainLLM/releases)
14
14
  [![CI](https://img.shields.io/github/actions/workflow/status/miisodev/BrainLLM/ci.yml?branch=main&style=flat-square&label=CI&color=f59e0b)](https://github.com/miisodev/BrainLLM/actions/workflows/ci.yml)
15
15
  [![License: MIT](https://img.shields.io/badge/license-MIT-a1a1aa?style=flat-square)](./LICENSE)
16
16
  [![Runtime: Bun](https://img.shields.io/badge/runtime-Bun%20%E2%89%A5%201.0-a1a1aa?style=flat-square&logo=bun&logoColor=white)](https://bun.sh)
@@ -35,7 +35,7 @@ Anyone running an LLM as a long-running collaborator, not a one-shot Q&A tool
35
35
 
36
36
  ### From experiment to open source
37
37
 
38
- BrainLLM began in February 2026 as a personal experiment: could an LLM operate a real, self-hosted second brain reliably enough to be trusted as its own memory — orienting, writing, connecting, and closing sessions without a human doing the filing? Through sustained daily, production use the answer held. The design has settled, the failure modes have been found and fixed, and the project has graduated from experiment to something **efficient and stable enough to share** — so it's now open source. It still runs the author's own sessions every day; what you're reading is the same code, not a demo. It also still carries the shape of one person's daily use — see [Adapting to your environment](#adapting-to-your-environment) for exactly what that means and what to change.
38
+ BrainLLM began in February 2026 as a personal experiment: could an LLM operate a real, self-hosted memory reliably enough to be trusted as its own memory — orienting, writing, connecting, and closing sessions without a human doing the filing? Through sustained daily, production use the answer held. The design has settled, the failure modes have been found and fixed, and the project has graduated from experiment to something **efficient and stable enough to share** — so it's now open source. It still runs the author's own sessions every day; what you're reading is the same code, not a demo. It also still carries the shape of one person's daily use — see [Adapting to your environment](#adapting-to-your-environment) for exactly what that means and what to change.
39
39
 
40
40
  ### The core principle
41
41
 
@@ -199,15 +199,15 @@ The **full mode** tools deliberately break this convention — they are named af
199
199
 
200
200
  ### Tool permissions
201
201
 
202
- Every tool declares whether it reads, writes, or destroys, so your client can group them and you can grant permission per group instead of per call. The current full-mode split is **33 read-only · 38 write · 6 destructive** (core mode is **22 read-only · 20 write · 2 destructive**), which lets reads run unattended while anything that touches your brain still asks.
202
+ Every tool declares whether it reads, writes, or destroys, so your client can group them and you can grant permission per group instead of per call. Every tool also carries a human-readable title ("Edit a note", "Search the brain") for permission prompts and directory listings. The current full-mode split is **34 read-only · 31 write · 13 destructive** (core mode is **23 read-only · 17 write · 5 destructive**); `revise`, `label` and `connect` count as destructive because they can overwrite or remove what was there, which lets reads run unattended while anything that touches your brain still asks.
203
203
 
204
204
  The classification lives in one reviewable table ([`src/annotations.ts`](./src/annotations.ts)) rather than scattered across registrations, and its default is deliberately unsafe-side: a tool missing from the table is treated as a **write**, never a read, and says so at startup. Three are worth knowing because they look like reads and aren't — `start()` creates today's diary and session stubs, `session()` runs the maintenance sweep, and `graph()` writes the rendered graph note.
205
205
 
206
- ### Core — universal verbs (34)
206
+ ### Core — universal verbs (35)
207
207
 
208
208
  | Group | Tools |
209
209
  |---|---|
210
- | Session lifecycle | `start` · `day` · `session` · `remarks` · `close` · `backup` |
210
+ | Session lifecycle | `start` · `day` · `session` · `remarks` · `close` · `backup` · `health` |
211
211
  | Writing | `remember` · `diary` · `revise` · `split` · `resolve` · `withdraw` · `recover` |
212
212
  | Reading & search | `read` · `recall` · `domain` · `brain` · `assembly` · `outline` · `inspect` · `diff` · `template` · `consistency` |
213
213
  | Graph | `connect` · `explore` · `graph` |
@@ -222,7 +222,7 @@ The classification lives in one reviewable table ([`src/annotations.ts`](./src/a
222
222
 
223
223
  The raw ETAPI, one tool per Trilium primitive — notes, attributes, branches, revisions, attachments, calendar, system. Brain-agnostic and guard-free: an edge-case fallback for what core can't express (precise raw queries, code/canvas/mermaid notes, branch surgery, revision recovery).
224
224
 
225
- The complete operational reference is [`skills/brainllm/SKILL.md`](./skills/brainllm/SKILL.md); per-topic deep dives live in [`skills/brainllm/references/`](./skills/brainllm/references/). Beyond that, the **Blueprint** is a from-source architecture reference — every module, every tool's exact behavior and signature, the sweep internals, the full idempotency matrix — kept internally rather than published in this repo; see [Support the project](#support-the-project) for how to get a copy.
225
+ The complete operational reference is [`skills/brainllm/SKILL.md`](./skills/brainllm/SKILL.md); per-topic deep dives live in [`skills/brainllm/references/`](./skills/brainllm/references/). Beyond that, the **architecture reference** explains how BrainLLM is built and why — every module, every tool's behaviour, the sweep internals, the idempotency matrix — and is kept current with each release rather than published in this repo; see [Support the project](#support-the-project) for how to get a copy.
226
226
 
227
227
  ---
228
228
 
@@ -243,7 +243,7 @@ The included [`Dockerfile`](./Dockerfile) builds and runs the HTTP connector (tw
243
243
 
244
244
  ### Branding
245
245
 
246
- In HTTP mode BrainLLM serves its own icons — `/icon.png`, `/icon.svg`, sized variants, and `/favicon.ico` — and advertises them in the MCP handshake, so clients show the BrainLLM mark in your connector list and beside its tool calls.
246
+ In HTTP mode BrainLLM serves its own icons — `/icon.png`, `/icon.svg`, sized variants, and `/favicon.ico` — and advertises them in the MCP handshake together with its title, a one-line description and its website, so clients show the BrainLLM mark in your connector list and beside its tool calls. The handshake also carries short server instructions describing the five areas and the session shape. Everything brand-shaped (name, tagline, description, the mark's geometry) is defined once in [`src/brand.ts`](./src/brand.ts), and a unit test holds `package.json`, `manifest.json` and `server.json` to the same description.
247
247
 
248
248
  Both halves of that are load-bearing. The spec tells clients to **verify icon URIs share the server's origin**, so icons hosted anywhere else are silently dropped. And a host that serves no favicon makes clients fall back to the *registrable domain's* — a BrainLLM at `brain.yourdomain.com` would show `yourdomain.com`'s site logo, which is worse than nothing because it looks intentional.
249
249
 
@@ -253,7 +253,7 @@ To use your own artwork, replace `public/BrainLLM.svg` and run `bun run icons`
253
253
 
254
254
  Claude Code and `mcp-remote` send `MCP_AUTH_TOKEN` as a header and need nothing further. **The hosted Claude surfaces — claude.ai, Claude mobile, Cowork — cannot.** Their custom-connector UI offers OAuth or nothing; there is no field for a bearer token. So BrainLLM ships its own OAuth 2.1 authorization server. It serves **both** registration mechanisms, so every OAuth-capable client works:
255
255
 
256
- - **Client ID Metadata Documents (CIMD)** — the registration-free mechanism MCP's `2026-07-28` revision adopted; this is what Claude selects.
256
+ - **Client ID Metadata Documents (CIMD)** — the registration-free mechanism adopted in the MCP `2025-11-25` specification; this is what Claude selects.
257
257
  - **Dynamic Client Registration (RFC 7591)** — for clients that never grew CIMD support. opencode (MCP TS SDK ≤1.29) is the forcing case: without a `registration_endpoint` it refuses to authenticate at all.
258
258
 
259
259
  Set one variable to turn it on:
@@ -273,9 +273,11 @@ What that turns on:
273
273
  | `/.well-known/oauth-protected-resource` (+ `/mcp` variant) | RFC 9728 — names the authorization server |
274
274
  | `/.well-known/oauth-authorization-server` (+ `/mcp` variant) | RFC 8414 — advertises CIMD support, DCR, and PKCE S256 |
275
275
  | `/authorize` | Validates the client (CIMD document or registered id), shows the consent screen |
276
- | `/token` | PKCE-verified code exchange, with rotating refresh tokens |
276
+ | `/token` | PKCE-verified code exchange, with rotating refresh tokens stored only as SHA-256 hashes |
277
277
  | `/register` | RFC 7591 dynamic client registration — how opencode and other DCR-only clients connect |
278
278
 
279
+ The consent screen names the requesting client and the address it will return to, and warns when that address is your own computer (a loopback redirect, as Claude Code uses). MCP traffic is rate-limited per bearer token, with a looser per-IP bound, so clients that share an egress range (all of Claude's hosted traffic does) never exhaust each other's budget.
280
+
279
281
  Both credentials work simultaneously — a static token from Claude Code and an OAuth token from claude.ai, against the same brain. Access tokens are signed JWTs bound to your server's resource URI, so a token minted for a different MCP server is rejected; the signing secret and refresh tokens persist beside `brainllm.json`, which on a container deploy means **putting `BRAINLLM_CONFIG` on a volume** — otherwise every redeploy invalidates every token.
280
282
 
281
283
  For config persistence across redeploys, mount a volume on the **BrainLLM service** (not the Trilium service) and set `BRAINLLM_CONFIG` to a file path inside it:
@@ -341,12 +343,15 @@ index.ts ─→ tools.ts ─┬→ trilium.ts ETAPI client: bounded/retrying
341
343
  ├→ journal.ts daily Insights log generation (regenerate-in-place)
342
344
  ├→ time.ts timezone-correct now/today (BRAINLLM_TZ)
343
345
  ├→ rate-limit.ts bounded public HTTP budgets
346
+ ├→ brand.ts name, description, mark, icons, server instructions
347
+ ├→ cap.ts the 140k-character result cap
348
+ ├→ diffing.ts block and table-cell diffs
344
349
  ├→ network-security.ts CIMD public-network and redirect checks
345
350
  ├→ bootstrap.ts five-area tree builder
346
351
  └→ tools-*.ts per-area surface reads · full-mode raw ETAPI
347
352
  ```
348
353
 
349
- Key properties: every write is sanitized for Trilium/CKEditor 5 compatibility (mutations reported back as `sanitized[]`); a revision snapshot precedes routine content mutation; every request carries the user's local time so Trilium stamps dates in the right day; core writes are idempotent or duplicate-guarded, while raw full-mode overwrites are explicit.
354
+ Key properties: no tool result exceeds 140,000 characters (a larger one is cut with a note naming the narrower read); every write is sanitized for Trilium/CKEditor 5 compatibility (mutations reported back as `sanitized[]`); a revision snapshot precedes routine content mutation; every request carries the user's local time so Trilium stamps dates in the right day; core writes are idempotent or duplicate-guarded, while raw full-mode overwrites are explicit.
350
355
 
351
356
  ## Development
352
357
 
@@ -355,6 +360,7 @@ bun run dev # hot-reload dev server
355
360
  bun run build # bundle to dist/index.js
356
361
  bun run test:unit # all unit tests (Bun discovery; works on Windows and CI)
357
362
  bun run test:http # local auth/header smoke (no Trilium required)
363
+ BRAINLLM_LIVE_TOKEN=... bun run test:live # read-only smoke against a deployed server, over real MCP
358
364
  bun run test # integration tests (requires a live Trilium instance)
359
365
  bun run validate:manifest # MCPB schema/icon validation
360
366
  bun run init # CLI bootstrap
@@ -392,6 +398,10 @@ Not sure where to start? Issues labeled `good first issue`, doc gaps, and the tr
392
398
 
393
399
  Please do not report suspected vulnerabilities in a public issue. Follow the private reporting process in [`SECURITY.md`](./SECURITY.md); never include ETAPI tokens, OAuth credentials, or private brain content in a report.
394
400
 
401
+ ## Privacy and support
402
+
403
+ BrainLLM collects nothing: no analytics, no telemetry, no account. Your notes stay in your Trilium, and sign-in records stay on your own server. The full [privacy policy](https://miisodev.github.io/BrainLLM/privacy.html) says what is stored where. For help, open a [GitHub issue](https://github.com/miisodev/BrainLLM/issues) or email miisodev@gmail.com.
404
+
395
405
  ---
396
406
 
397
407
  ## Support the project
package/SECURITY.md CHANGED
@@ -6,8 +6,8 @@ Security fixes ship on the latest release line. Older versions may remain useful
6
6
 
7
7
  | Version | Supported |
8
8
  |---|---|
9
- | 12.7.x | ✅ |
10
- | 12.6.x and earlier | ❌ |
9
+ | 12.8.x | ✅ |
10
+ | 12.7.x and earlier | ❌ |
11
11
 
12
12
  ## Reporting a vulnerability
13
13
 
@@ -26,6 +26,8 @@ Please use a private channel until a fix and coordinated disclosure path are agr
26
26
 
27
27
  Run the latest tagged release rather than an unreleased branch or a mutable dependency lock. For an HTTP deployment reachable outside a trusted network, set `MCP_AUTH_TOKEN`; configure `BRAINLLM_OWNER_PASSWORD` only when hosted OAuth clients require it. Keep the Trilium instance, ETAPI token, OAuth store, and `brainllm.json` on protected storage, and restrict network access at the platform edge.
28
28
 
29
+ Since 12.8.0 the OAuth store keeps refresh tokens only as SHA-256 hashes (a token issued earlier is accepted once and replaced by a hashed successor on its next refresh), MCP traffic is rate-limited per bearer token with a looser per-IP bound, and the consent screen shows where an approval will be sent and warns when that is the local machine.
30
+
29
31
  For credential rotation, replace `MCP_AUTH_TOKEN` and the ETAPI token in the provider/Trilium, set a fresh `BRAINLLM_OAUTH_SECRET` (32+ characters) to invalidate existing OAuth tokens, and remove obsolete local `*.oauth.json` / `*.token` files. Never put recovered credentials in a repository, shared context note, Docker context, or release artifact.
30
32
 
31
33
  ## Scope