Local-first, graph-linked persistent memory for AI coding agents (MCP server + CLI)
trailmem has well-structured tool definitions with complete schemas and descriptions for all 6 tools. Naming follows verb_noun convention (welcome, store, query, show, edit, link). Descriptions are detailed (100-250 chars) and explain WHEN to use each tool. Parameters are typed and mostly described. However, several parameters lack descriptions (e.g., session_id, session_context appear in all tools but are never explained), and output schemas are not documented, LLMs cannot predict what fields to expect. Error handling is mentioned in docstrings but not formalized in tool definitions. The trailmem_store tool has complex interdependencies (code_files/doc_files required, supersedes needs archive_reason) that are documented in description text but not enforced via schema constraints.
Update a memory's content/title/type/pin, or close it (status='completed'/'cancelled' for finished/dropped tasks, 'archived' for wrong/outdated info, 'superseded' when replaced — all need archive_reason >=20 chars AND >=1 edge). `project` rescopes a misfiled memory (absolute path or 'global') — content, hash and embedding stay untouched. Content edits refresh hash + embedding + search index automatically.
Create (action='add': source, target, edge_type) or remove (action='remove': edge_id from trailmem_show) a typed edge between memories. Types: related / derived_from / supersedes / contradicts / evolves.
Search memories (semantic + keyword). Returns #id, type, status, edge count [↔N] and a 200-char preview per hit. Use trailmem_show(ref) for full content + edges.
Fetch one memory in full: content, all edges (with [eN] ids), supersede chain. The only tool that returns edges — edge ids here are what link remove needs.
Save a new memory (decision/lesson/task/constraint/...) with optional linking. Store the ENGLISH version of the content; title 3-60 chars, content 50+ chars. code_files and doc_files are REQUIRED: comma-separated paths (code_files = source/config files this memory touches, doc_files = docs/spec pages), or the literal 'none' if this memory touches no files of that kind. Duplicates are rejected/blocked with the existing #id — edit that instead.
Output schemas not documented. Tool descriptions mention what is returned (e.g., '#id, type, status, edge count, 200-char preview' for trailmem_query) but no formal schema is provided. LLMs cannot predict field names, types, or structure for downstream tool chaining.
session_id and session_context parameters appear in all 6 tools but are never described. LLMs cannot determine what values to pass, when they are required, or what format they expect.
trailmem_store has undocumented parameter interdependencies: code_files and doc_files are marked required but can be 'none'; supersedes requires archive_reason (>=20 chars) AND >=1 edge. These constraints are in the docstring but not enforced in schema, LLMs may pass invalid combinations.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | D | 59 | 2026-07-28+ | v2 |
Session-start briefing: pinned rules, recent activity, open tasks, stats. Call once at session start; repeat calls return the short form unless force=true.
Error handling is described in docstrings (e.g., 'Duplicates are rejected/blocked with the existing #id') but not formalized in tool definitions. LLMs cannot predict error categories (retryable, user-fixable, fatal) or recovery steps.
trailmem_link action parameter accepts 'add' or 'remove' but has no enum constraint in schema. source, target, edge_type are conditionally required (only for action='add') but marked required=false with no conditional logic documented.