# Trilium Notes

Hierarchical note tree with attributes and scripting, driven by the ETAPI REST API and an in-repo MCP route.

Trilium is a self-hostable notes app (desktop and server) built around an arbitrarily deep note tree with labels, relations, note versioning, encryption, and scripting. The server ships ETAPI, a documented REST API for notes, branches, attributes, attachments, and calendar notes, and since 2026 an MCP route (apps/server/src/routes/mcp.ts) that exposes the LLM tool registry.

Alternative to: Evernote, Notion, Obsidian

- Capabilities: adaptable, operable
- Vertical: notes-knowledge
- Shape: business-app
- Form factor: web-app
- Execution model: hybrid
- Provenance: mixed (recorded, never ranked)
- Repo: https://github.com/TriliumNext/Trilium (AGPL-3.0), 37683 stars, last commit 2026-09-03
- Last activity: 2026-09-03
- Page: apps/triliumnext--trilium.html
- JSON: apps/triliumnext--trilium.json

## Use it when

- you want a deeply nested personal or team knowledge tree that an agent can populate through a stable REST API
- you outgrew flat markdown folders and want attributes, relations, and saved searches

## Gotchas

- AGPL-3.0
- The desktop app and server versions must match for sync; disable auto-updates on the server when using TriliumDroid
- ETAPI needs a token created in the UI (Options > ETAPI) or from POST /etapi/auth/login with the instance password
- MCP route tool names were not read; they come from the core LLM tool registry (packages/core llm/tools)

## Editions

- Free: Free, open source
  - source: https://github.com/TriliumNext/Trilium
  - binary: https://github.com/TriliumNext/Trilium/releases
  - container: docker compose up -d

## Adaptable: make it yours

Effort: config-only (11 things to edit)

config.ini (from apps/server/src/assets/config-sample.ini) sets instanceName, noAuthentication, noBackup, port, https with certPath and keyPath, trustedReverseProxy, session cookieMaxAge, OAuth multi-factor (oauthBaseUrl, oauthClientId, oauthClientSecret, oauthIssuerBaseUrl), and the security switches backendScriptingEnabled and sqlConsoleEnabled. TRILIUM_DATA_DIR and its siblings relocate data, logs, backups, and the config file. docker-compose.yml is in the repo.

- Env vars: TRILIUM_DATA_DIR, TRILIUM_CONFIG_INI_PATH, TRILIUM_DOCUMENT_PATH, TRILIUM_BACKUP_DIR, TRILIUM_LOG_DIR, TRILIUM_TMP_DIR, TRILIUM_OCR_CACHE_DIR, TRILIUM_ANONYMIZED_DB_DIR
- Config files: config.ini, docker-compose.yml
- Prompt files: .claude/skills/
- Accounts you'll need: an OAuth provider (optional, for multi-factor login)

## Operable: what an agent can drive

Operability: official. Interface: api at https://docs.triliumnotes.org/user-guide/advanced-usage/etapi (published by the builder, local).

### Reach (partial coverage)

- Create, read, update, and delete notes: reachable. ETAPI /notes and /create-note
- Place notes in the tree (branches, clones): reachable. ETAPI /branches
- Labels and relations: reachable. ETAPI /attributes
- Search with Trilium's query language: reachable. ETAPI /notes?search=
- Attachments: reachable. ETAPI /attachments
- Day, week, month, and year calendar notes: reachable. ETAPI /calendar/days, /weeks, /months, /years
- Note revisions and export: reachable. ETAPI /notes/{id}/revision, /notes/{id}/revisions, /notes/{id}/export and /import
- Backup: reachable. ETAPI /backup/{name}
- Scripting and widgets: not reachable. backend scripts run inside the app; ETAPI cannot execute them
- Sync and protected (encrypted) notes: not reachable. sync is app-to-server; protected notes need the session password in the UI

## Code stack

- Languages: TypeScript
- Frameworks: Express, Electron, CKEditor
- Package manager: pnpm
- Database: SQLite
- Hosting target: docker, binary

## Model stack

- Providers: configurable LLM providers for the built-in AI chat
- Models: none
- Keys you need (names only): none
- Prompts live in: .claude/skills/
- Tools: none

## Skills

contributor: Repo tooling for Trilium contributors: client UI, Electron and Capacitor builds, coverage, releases.
- Paths: .claude/skills/*/SKILL.md

## Evidence and confidence

- formFactor: README: server install with Docker with web UI; desktop builds also exist (confidence 0.7)
- executionModel: built-in LLM chat and tool registry (mcp_server.ts imports allToolRegistries from the llm tools); notes work without a model (confidence 0.7)
- operability: docs.triliumnotes.org ETAPI page: token from Options > ETAPI or POST /etapi/auth/login with the password; sent as 'Authorization: &lt;token>', 'Authorization: Bearer &lt;token>' (v0.93+), or Basic with username etapi. OpenAPI spec in repo at apps/server/src/assets/etapi.openapi.yaml (securitySchemes EtapiTokenAuth apiKey + basic); 31 paths incl. /notes, /branches, /attributes, /attachments, /calendar/*, /backup, /metrics. apps/server/src/routes/mcp.ts also present. (confidence 0.95)
- effort: config-sample.ini keys and TRILIUM_* names in apps/server/src/services/data_dir.ts (confidence 0.9)
- editions: AGPL, free; third-party hosting only (confidence 0.95)
- active: pushedAt 2026-09-03
- provenance: CLAUDE.md and .claude/skills in repo; project from 2017 (confidence 0.4)
- reach:  (confidence 0.7)

## Open questions

- Read the MCP tool names from the core LLM tool registry and decide whether the MCP route should replace ETAPI as the stated interface
- Decide whether the MCP route (apps/server/src/routes/mcp.ts) should replace ETAPI as the stated interface once its tool list is read

## Sources

- https://github.com/TriliumNext/Trilium (sourcing:notes-knowledge:github)
- https://github.com/TriliumNext/Trilium/blob/main/apps/server/src/assets/config-sample.ini (analysis)
