trailmem 0.1.0__tar.gz

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.
@@ -0,0 +1,26 @@
1
+ # Python packaging and local environments
2
+ .venv/
3
+ __pycache__/
4
+ *.py[cod]
5
+ build/
6
+ dist/
7
+ *.egg-info/
8
+
9
+ # Local Trailmem runtime data
10
+ .trailmem/
11
+
12
+ # Regeneratable Graphify output
13
+ graphify-out/
14
+
15
+ # Editor and OS files
16
+ .vscode/
17
+ .idea/
18
+ .DS_Store
19
+
20
+ # OpenKnowledge local runtime data
21
+ .ok/*.db
22
+ .ok/local/
23
+
24
+ # Claude Code local settings
25
+ .claude/settings.local.json
26
+ .claude/
trailmem-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Amit Kushwaha
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.4
2
+ Name: trailmem
3
+ Version: 0.1.0
4
+ Summary: Local-first, graph-linked persistent memory for AI coding agents (MCP server + CLI)
5
+ Project-URL: Homepage, https://github.com/amit/trailmem
6
+ Author-email: Amit Kushwaha <amitkushwaha2805@gmail.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE
9
+ Keywords: ai-agents,knowledge-graph,mcp,memory,sqlite
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Software Development :: Libraries
14
+ Requires-Python: >=3.10
15
+ Requires-Dist: mcp
16
+ Requires-Dist: numpy
17
+ Requires-Dist: onnxruntime
18
+ Requires-Dist: orjson
19
+ Requires-Dist: sqlite-vec<0.2.0
20
+ Requires-Dist: tokenizers
21
+ Description-Content-Type: text/markdown
22
+
23
+ # trailmem
24
+
25
+ **Persistent, local-first graph memory for AI coding agents.**
26
+
27
+ Trailmem gives agents durable cross-session memory without provider lock-in: a local SQLite knowledge graph, typed relationships, explicit knowledge evolution, and token-disciplined briefings. It is designed for multiple local agents—Claude, Kiro, Codex, OpenCode, Kilo, and Gemini—to share useful project knowledge without silently creating junk memories.
28
+
29
+ ## Quick start
30
+
31
+ Same commands on Windows, macOS, and Linux (pure Python; wheels ship for all three). On some systems use `pip3` or `python -m pip` instead of `pip`.
32
+
33
+ ```bash
34
+ pip install trailmem
35
+ trailmem setup # creates ~/.trailmem/, inits DB, downloads the default embedding model
36
+ trailmem doctor # health check
37
+
38
+ # Register the MCP server with your agent host(s):
39
+ trailmem integrate # detects installed agent hosts, asks before writing any config
40
+ ```
41
+
42
+ `trailmem integrate` auto-detects nine hosts: **Claude Code, Codex, Kiro, Kilo, OpenCode, Antigravity, Zed, Cursor, Windsurf**. It shows what it found, asks once (y/N), backs up every config it touches (`.bak-trailmem`), skips hosts that are already registered, and never rewrites a config it can't parse losslessly (JSONC with comments gets the manual entry printed instead).
43
+
44
+ Prefer manual registration? Each host has its own mechanism:
45
+
46
+ | Host | Manual registration |
47
+ |------|--------------------|
48
+ | Claude Code | `claude mcp add trailmem -- trailmem-mcp` |
49
+ | Codex | add an `[mcp_servers.trailmem]` table to `~/.codex/config.toml` |
50
+ | Kiro | add `trailmem` under `mcpServers` in `~/.kiro/settings/mcp.json` |
51
+ | Kilo | add `trailmem` under `mcpServers` in `~/.config/kilo/kilo.jsonc` |
52
+ | OpenCode | add `trailmem` under `mcp` in `~/.config/opencode/opencode.json` |
53
+ | Antigravity | add `trailmem` under `mcpServers` in `~/.gemini/config/mcp_config.json` |
54
+ | Zed | add `trailmem` under `context_servers` in `~/.config/zed/settings.json` |
55
+ | Cursor | add `trailmem` under `mcpServers` in `~/.cursor/mcp.json` |
56
+ | Windsurf | add `trailmem` under `mcpServers` in `~/.codeium/windsurf/mcp_config.json` |
57
+
58
+ ### Any other MCP agent
59
+
60
+ Trailmem works with **any agent that speaks MCP** — Cursor, Windsurf, Cline, Zed, Gemini CLI, or anything newer. `trailmem integrate` only automates the hosts above; for everything else, register it yourself. You need exactly three facts:
61
+
62
+ 1. **Transport:** stdio (no URL, no port, no HTTP).
63
+ 2. **Command:** `trailmem-mcp` — no arguments, no environment variables required.
64
+ 3. **Server name:** `trailmem` (any name works; tool names don't depend on it).
65
+
66
+ Most agents use a JSON block shaped like this (key name varies — `mcpServers`, `mcp`, `servers`):
67
+
68
+ ```json
69
+ {
70
+ "mcpServers": {
71
+ "trailmem": {
72
+ "command": "trailmem-mcp",
73
+ "args": []
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ If the agent can't find the command, use the absolute path — print it with:
80
+
81
+ ```bash
82
+ which trailmem-mcp # Windows: where trailmem-mcp
83
+ ```
84
+
85
+ Then restart the agent and check the wiring: the agent should see six `trailmem_*` tools, and calling `trailmem_welcome` should return a briefing. `trailmem doctor` verifies the database side.
86
+
87
+ ### Updating
88
+
89
+ ```bash
90
+ pip install --upgrade trailmem
91
+ ```
92
+
93
+ There is no in-app "update available" notice — trailmem sends no telemetry, by design. Watch the GitHub Releases page instead.
94
+
95
+ The agent then gets six tools: `trailmem_welcome` (once-per-session briefing), `trailmem_store`, `trailmem_query`, `trailmem_show`, `trailmem_edit`, `trailmem_link`. Everything is also available to humans via the `trailmem` CLI (`store`, `query`, `show`, `list`, `stats`, `link`, `archive`, ...).
96
+
97
+ Try it from the CLI (note: `content` is positional; `--agent user` for your own notes):
98
+
99
+ ```bash
100
+ trailmem store --title "First note" --type lesson --agent user "Something worth remembering."
101
+ trailmem query "what did I note earlier"
102
+ trailmem list
103
+ trailmem help # or: trailmem <command> --help
104
+ ```
105
+
106
+ ## Why
107
+
108
+ - **Local-first.** One SQLite file (`~/.trailmem/trailmem.db`), WAL mode, no cloud, no daemon. Embeddings run locally via ONNX (default: bge-small-en-v1.5, user-swappable with `trailmem model use`).
109
+ - **A graph, not a list.** Typed edges (`related`, `supersedes`, `evolves`, `contradicts`, `derived_from`), orphan warnings at store time, supersede chains instead of destructive overwrites.
110
+ - **Token discipline.** Context is injected exactly once per session (welcome, ~600–800 tokens). No per-turn injection, ever. Repeat welcomes return a short form.
111
+ - **No junk memories.** 4-band duplicate detection (exact hash reject → >0.92 block → 0.85–0.92 warn → accept), mandatory titles, hard-reject on unattributed stores, no auto-store lifecycle hooks.
112
+ - **No telemetry.** The server writes only what the user needs (e.g. a local `hooks.log` diagnostic); it never emits analytics — a deliberate anti-goal, not an oversight.
113
+
114
+ ## Status
115
+
116
+ Core implemented and tested (schema, store/dedup, query/show, welcome, MCP server, CLI, hooks, model management, loopback dashboard, host integration). Not yet published to PyPI. The design contract lives in [`docs/`](docs/index.md) — schema, welcome lifecycle, duplicate policy, evolution rules, CLI/MCP surfaces, hooks, seeding playbook, and the dashboard contract.
117
+
118
+ ## License
119
+
120
+ MIT
@@ -0,0 +1,98 @@
1
+ # trailmem
2
+
3
+ **Persistent, local-first graph memory for AI coding agents.**
4
+
5
+ Trailmem gives agents durable cross-session memory without provider lock-in: a local SQLite knowledge graph, typed relationships, explicit knowledge evolution, and token-disciplined briefings. It is designed for multiple local agents—Claude, Kiro, Codex, OpenCode, Kilo, and Gemini—to share useful project knowledge without silently creating junk memories.
6
+
7
+ ## Quick start
8
+
9
+ Same commands on Windows, macOS, and Linux (pure Python; wheels ship for all three). On some systems use `pip3` or `python -m pip` instead of `pip`.
10
+
11
+ ```bash
12
+ pip install trailmem
13
+ trailmem setup # creates ~/.trailmem/, inits DB, downloads the default embedding model
14
+ trailmem doctor # health check
15
+
16
+ # Register the MCP server with your agent host(s):
17
+ trailmem integrate # detects installed agent hosts, asks before writing any config
18
+ ```
19
+
20
+ `trailmem integrate` auto-detects nine hosts: **Claude Code, Codex, Kiro, Kilo, OpenCode, Antigravity, Zed, Cursor, Windsurf**. It shows what it found, asks once (y/N), backs up every config it touches (`.bak-trailmem`), skips hosts that are already registered, and never rewrites a config it can't parse losslessly (JSONC with comments gets the manual entry printed instead).
21
+
22
+ Prefer manual registration? Each host has its own mechanism:
23
+
24
+ | Host | Manual registration |
25
+ |------|--------------------|
26
+ | Claude Code | `claude mcp add trailmem -- trailmem-mcp` |
27
+ | Codex | add an `[mcp_servers.trailmem]` table to `~/.codex/config.toml` |
28
+ | Kiro | add `trailmem` under `mcpServers` in `~/.kiro/settings/mcp.json` |
29
+ | Kilo | add `trailmem` under `mcpServers` in `~/.config/kilo/kilo.jsonc` |
30
+ | OpenCode | add `trailmem` under `mcp` in `~/.config/opencode/opencode.json` |
31
+ | Antigravity | add `trailmem` under `mcpServers` in `~/.gemini/config/mcp_config.json` |
32
+ | Zed | add `trailmem` under `context_servers` in `~/.config/zed/settings.json` |
33
+ | Cursor | add `trailmem` under `mcpServers` in `~/.cursor/mcp.json` |
34
+ | Windsurf | add `trailmem` under `mcpServers` in `~/.codeium/windsurf/mcp_config.json` |
35
+
36
+ ### Any other MCP agent
37
+
38
+ Trailmem works with **any agent that speaks MCP** — Cursor, Windsurf, Cline, Zed, Gemini CLI, or anything newer. `trailmem integrate` only automates the hosts above; for everything else, register it yourself. You need exactly three facts:
39
+
40
+ 1. **Transport:** stdio (no URL, no port, no HTTP).
41
+ 2. **Command:** `trailmem-mcp` — no arguments, no environment variables required.
42
+ 3. **Server name:** `trailmem` (any name works; tool names don't depend on it).
43
+
44
+ Most agents use a JSON block shaped like this (key name varies — `mcpServers`, `mcp`, `servers`):
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "trailmem": {
50
+ "command": "trailmem-mcp",
51
+ "args": []
52
+ }
53
+ }
54
+ }
55
+ ```
56
+
57
+ If the agent can't find the command, use the absolute path — print it with:
58
+
59
+ ```bash
60
+ which trailmem-mcp # Windows: where trailmem-mcp
61
+ ```
62
+
63
+ Then restart the agent and check the wiring: the agent should see six `trailmem_*` tools, and calling `trailmem_welcome` should return a briefing. `trailmem doctor` verifies the database side.
64
+
65
+ ### Updating
66
+
67
+ ```bash
68
+ pip install --upgrade trailmem
69
+ ```
70
+
71
+ There is no in-app "update available" notice — trailmem sends no telemetry, by design. Watch the GitHub Releases page instead.
72
+
73
+ The agent then gets six tools: `trailmem_welcome` (once-per-session briefing), `trailmem_store`, `trailmem_query`, `trailmem_show`, `trailmem_edit`, `trailmem_link`. Everything is also available to humans via the `trailmem` CLI (`store`, `query`, `show`, `list`, `stats`, `link`, `archive`, ...).
74
+
75
+ Try it from the CLI (note: `content` is positional; `--agent user` for your own notes):
76
+
77
+ ```bash
78
+ trailmem store --title "First note" --type lesson --agent user "Something worth remembering."
79
+ trailmem query "what did I note earlier"
80
+ trailmem list
81
+ trailmem help # or: trailmem <command> --help
82
+ ```
83
+
84
+ ## Why
85
+
86
+ - **Local-first.** One SQLite file (`~/.trailmem/trailmem.db`), WAL mode, no cloud, no daemon. Embeddings run locally via ONNX (default: bge-small-en-v1.5, user-swappable with `trailmem model use`).
87
+ - **A graph, not a list.** Typed edges (`related`, `supersedes`, `evolves`, `contradicts`, `derived_from`), orphan warnings at store time, supersede chains instead of destructive overwrites.
88
+ - **Token discipline.** Context is injected exactly once per session (welcome, ~600–800 tokens). No per-turn injection, ever. Repeat welcomes return a short form.
89
+ - **No junk memories.** 4-band duplicate detection (exact hash reject → >0.92 block → 0.85–0.92 warn → accept), mandatory titles, hard-reject on unattributed stores, no auto-store lifecycle hooks.
90
+ - **No telemetry.** The server writes only what the user needs (e.g. a local `hooks.log` diagnostic); it never emits analytics — a deliberate anti-goal, not an oversight.
91
+
92
+ ## Status
93
+
94
+ Core implemented and tested (schema, store/dedup, query/show, welcome, MCP server, CLI, hooks, model management, loopback dashboard, host integration). Not yet published to PyPI. The design contract lives in [`docs/`](docs/index.md) — schema, welcome lifecycle, duplicate policy, evolution rules, CLI/MCP surfaces, hooks, seeding playbook, and the dashboard contract.
95
+
96
+ ## License
97
+
98
+ MIT
@@ -0,0 +1,242 @@
1
+ # trailmem — CLI Reference
2
+
3
+ ## Overview
4
+
5
+ `trailmem` is the command-line interface for managing agent memory. All operations available via MCP tools are also available via CLI.
6
+
7
+ **Installation:** `pip install trailmem`
8
+ **Binary:** `trailmem`
9
+ **Help:** `trailmem` (no args), `trailmem help`, or `trailmem --help` all print top-level help with usage examples and exit 0; `trailmem <command> --help` shows per-command flags.
10
+
11
+ ---
12
+
13
+ ## Commands
14
+
15
+ ### WRITE Operations
16
+
17
+ ```bash
18
+ # Store a new memory
19
+ trailmem store "content here" \
20
+ --title "Short Title" \
21
+ --type decision \
22
+ --agent kiro \
23
+ --pin \
24
+ --link-to mem-abc123 \
25
+ --edge-type related \
26
+ --work-type code-written \
27
+ --source "file:docs/apps/jarvis-play.md"
28
+ # Also: --supersedes <ref> --archive-reason "why (min 20 chars)" for one-call supersede,
29
+ # --modified-files "a.py,b.py", --force to bypass the >0.92 near-dup block (exit 4)
30
+
31
+ # Edit existing memory
32
+ trailmem edit <ref> --content "updated content"
33
+ trailmem edit <ref> --title "new title"
34
+ trailmem edit <ref> --type lesson
35
+ trailmem edit <ref> --pin # or --no-pin
36
+ trailmem edit <ref> --status archived --reason "why (min 20 chars)" --link-to <ref>
37
+
38
+ # Archive (primary way to "remove" — preserves knowledge trail)
39
+ trailmem archive <ref> --reason "replaced by QTcpSocket approach" --link-to <ref>
40
+
41
+ # Link two memories
42
+ trailmem link <source-ref> <target-ref> --type related --reason "both about aria2"
43
+
44
+ # Remove a link
45
+ trailmem unlink <edge-id>
46
+
47
+ # Pin/unpin
48
+ trailmem pin <ref>
49
+ trailmem unpin <ref>
50
+ ```
51
+
52
+ ### READ Operations
53
+
54
+ ```bash
55
+ # Show single memory (full detail + edges)
56
+ trailmem show <ref>
57
+ # Output: #id [node_id] title, type, agent, status, content, all edges
58
+
59
+ # Search memories
60
+ trailmem query "wayfire compositor"
61
+ trailmem query "aria2" --type lesson
62
+ trailmem query "build" --agent claude
63
+ trailmem query "aria2" --limit 10 --format json # default limit 5, text output
64
+
65
+ # Session briefing (same as MCP welcome)
66
+ trailmem welcome
67
+
68
+ # Check near-duplicates before storing
69
+ trailmem similar "content to check"
70
+ # Shows: band (exact/0.92+/0.85+/low) + matching memory
71
+ ```
72
+
73
+ ### LIST Operations (filterable)
74
+
75
+ ```bash
76
+ trailmem list # all active memories
77
+ trailmem list --recent # last 10, newest first
78
+ trailmem list --orphans # zero-edge memories
79
+ trailmem list --pinned # pinned + constraints
80
+ trailmem list --tasks # open tasks
81
+ trailmem list --timeline # grouped by day
82
+ trailmem list --archived # archived/superseded
83
+ trailmem list --by-agent claude # filter by agent
84
+ trailmem list --project /path # filter by project
85
+ trailmem list --global # only global (project=NULL)
86
+ ```
87
+
88
+ ### ADMIN Operations
89
+
90
+ ```bash
91
+ # Statistics
92
+ trailmem stats
93
+ # Output: memory count, edge count, orphans, DB size, per-type breakdown
94
+
95
+ # Maintenance (DRY-RUN by default — report only)
96
+ trailmem maintain
97
+ # Output: what would be cleaned (old sessions, orphan report)
98
+ # Does NOT delete/archive anything without --apply
99
+
100
+ trailmem maintain --apply
101
+ # DESTRUCTIVE: purge sessions >90 days, report orphans
102
+ # Confirmation prompt before execution
103
+ # NEVER auto-archives/deletes memories
104
+
105
+ # Backup & Restore
106
+ trailmem export [output.json] # full DB dump
107
+ trailmem import <file.json> --merge # add without overwriting existing
108
+ trailmem import <file.json> --replace # full overwrite (DOUBLE confirmation!)
109
+
110
+ # Web Dashboard
111
+ trailmem dashboard
112
+ # Starts web UI at http://127.0.0.1:3800 (loopback-only, Ctrl-C to stop)
113
+ # Flags: --port N | --project <path|global> | --agent <default attribution for UI-created memories>
114
+
115
+ # Setup (first-time) — identical on Windows / macOS / Linux (pure-Python package)
116
+ trailmem setup
117
+ # Creates ~/.trailmem/, downloads the default embedding model, prints MCP registration hint.
118
+ # Note: some systems use `pip3` or `python -m pip` instead of `pip`.
119
+
120
+ # Integrate with agent hosts (auto-detect, permission-gated)
121
+ trailmem integrate
122
+ # Detects 9 hosts (Claude Code via `claude` on PATH; Codex / Kiro / Kilo / OpenCode /
123
+ # Antigravity / Zed / Cursor / Windsurf
124
+ # via their MCP config files) and, ONLY after an explicit y/N prompt, writes each host's
125
+ # own MCP config. Per-host config differs: Claude Code uses `claude mcp add`; others get
126
+ # their JSON config patched. No silent changes. (Manual fallback: `claude mcp add trailmem -- trailmem-mcp`.)
127
+ # ANY other MCP agent works manually: stdio transport, command `trailmem-mcp`, no args/env.
128
+ # README has the generic guide ("Any other MCP agent") with the common JSON shape + `which trailmem-mcp` for the absolute path.
129
+
130
+ # Update to a newer release
131
+ pip install --upgrade trailmem
132
+ # No in-app "update available" notice (no telemetry, by design). Track GitHub Releases.
133
+
134
+ # Health check
135
+ trailmem doctor
136
+ # Verifies: home + config presence, DB tables, sqlite-vec extension, embedding model
137
+ ```
138
+
139
+ ### MODEL Management (embedding model is user-configurable)
140
+
141
+ ```bash
142
+ # List available + installed models
143
+ trailmem model list
144
+
145
+ # Install a supported model (checksum-verified download, NOT bundled in wheel)
146
+ trailmem model install bge-small # default (384-dim, good balance)
147
+ trailmem model install minilm # lighter (~200MB RAM)
148
+ trailmem model install nomic # better quality (768-dim, ~500MB RAM)
149
+ trailmem model install --path /path/to/model.onnx # custom ONNX; dims auto-detected at install and saved as dims.txt, no manual config edit
150
+
151
+ # Switch active model
152
+ trailmem model use nomic
153
+ # Config updated. Dimensions may change → reindex required (see below).
154
+
155
+ # Disable embeddings entirely → FTS5-only mode
156
+ trailmem model disable
157
+ # WARNING printed: semantic search OFF + near-duplicate detection OFF (exact-hash only)
158
+
159
+ # Re-embed all memories with the current model
160
+ # REQUIRED after `model use` when dimensions change (drops + recreates memories_vec)
161
+ trailmem reindex
162
+ # Also re-validates dedup bands against the new model's cosine distribution
163
+ ```
164
+
165
+ Model config lives in `~/.trailmem/config.json`. Dedup thresholds (0.85/0.92) are per-model — swapping without `reindex` leaves stale bands. See [[schema]] embedding section and [[dedup]].
166
+
167
+ ### HIDDEN Commands (rare, destructive)
168
+
169
+ ```bash
170
+ # Hard delete — permanent removal (NOT recommended, use archive instead)
171
+ trailmem delete <ref> --hard --confirm
172
+ # Warning: edges CASCADE delete, knowledge trail lost
173
+ # Only for genuine junk/test data
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Reference Resolution
179
+
180
+ `<ref>` accepts both formats:
181
+ - `4` or `#4` → lookup by memory ID
182
+ - `mem-abc123` → lookup by node_id
183
+
184
+ ```bash
185
+ trailmem show 4 # by ID
186
+ trailmem show mem-abc123 # by node_id
187
+ trailmem edit #4 --title "new" # # prefix optional
188
+ ```
189
+
190
+ ---
191
+
192
+ ## Output Format
193
+
194
+ Default: plain text (human + agent readable)
195
+ ```bash
196
+ trailmem query "aria2"
197
+ # #12 [mem-abc123] [decision] [claude] QTcpSocket for aria2 Communication
198
+ # Use QTcpSocket direct connection for aria2 JSON-RPC...
199
+ # #7 [mem-def456] [lesson] [archived] Qt WebSocket Failed
200
+ # Connection drops under load, protocol mismatch...
201
+ ```
202
+
203
+ JSON output (for dashboard/scripts):
204
+ ```bash
205
+ trailmem list --format json
206
+ trailmem export --format json
207
+ ```
208
+
209
+ ---
210
+
211
+ ## Environment Variables
212
+
213
+ | Variable | Purpose | Auto-fill |
214
+ |----------|---------|-----------|
215
+ | `TRAILMEM_AGENT_TYPE` | Default agent_type | Auto-detects from CLAUDE_CODE_SESSION_ID etc |
216
+ | `CLAUDE_CODE_SESSION_ID` | Session tracking | Claude Code sets this |
217
+ | `KIRO_SESSION_ID` | Session tracking | Kiro sets this |
218
+ | `TRAILMEM_DB` | Custom DB path | Default: ~/.trailmem/trailmem.db |
219
+ | `TRAILMEM_HOME` | Custom home dir (config, models, DB, hooks.log) | Default: ~/.trailmem |
220
+ | `TRAILMEM_PROJECT` | Override project detection (value global stores NULL for cross-project scope) | Default: cwd |
221
+
222
+ ---
223
+
224
+ ## Exit Codes
225
+
226
+ | Code | Meaning |
227
+ |------|---------|
228
+ | 0 | Success |
229
+ | 1 | General error |
230
+ | 2 | Validation error (content too short, missing title, etc) |
231
+ | 3 | Duplicate detected (exact hash match) |
232
+ | 4 | Near-duplicate blocked (>0.92 similarity, use --force) |
233
+
234
+ ---
235
+
236
+ ## Related specs
237
+
238
+ - [[mcp]] — the six MCP tools that share this CLI's validation/storage paths.
239
+ - [[schema]] — data contracts; `model`/`reindex` commands map to the embedding config.
240
+ - [[dedup]] — `similar` command + exit codes 3/4 behavior.
241
+ - [[hooks]] — `trailmem hook session-start/session-stop` host integration.
242
+ - [[migration]] — one-time seed runbook built on `store`/`link`.
@@ -0,0 +1,141 @@
1
+ # trailmem — Dashboard Specification
2
+
3
+ **Status: built (2026-07-17), REVIEWED + HARDENED (2026-07-17, commit 4d862c6).** An initial `trailmem/dashboard.py` exists (authored by Amit, wired into cli.py). Audit + fresh-install functional test PASS: loopback-only bind, shared store/ops service layer (no direct SQLite writes), zero CDN/external assets, trigger-based revisioned SSE with Last-Event-ID replay + reset-on-gap, core validation on all write flows, no hard-delete in UI. Hardening added during review: Host/Origin loopback validation on every request (blocks DNS rebinding + cross-site CSRF), scope check on edge removal, clean port-in-use error. The dashboard is a first-party local feature, not a replacement for the six stdio MCP tools.
4
+
5
+ ## Product Goal
6
+
7
+ `trailmem dashboard` should make a memory graph easy and comfortable to inspect, navigate, and maintain for long sessions. It must feel quiet while the data changes: a user reading a memory must never lose their scroll position, selected item, graph camera, layout, filter, or unfinished form because another agent stored a memory.
8
+
9
+ The existing Omega dashboard is only a UX reference. Its five-second full polling and graph rebuild are explicitly rejected.
10
+
11
+ ## Boundary and Safety
12
+
13
+ ```bash
14
+ trailmem dashboard
15
+ # Local UI: http://127.0.0.1:3800
16
+ ```
17
+
18
+ - Bind to loopback only by default; no public network listener in v1.
19
+ - MCP remains **stdio-only**. The dashboard's loopback HTTP/SSE channel is an internal UI transport, not an HTTP MCP server or shared remote API.
20
+ - The dashboard calls Trailmem's shared application/service layer. It must **never** write SQLite rows directly or duplicate store/edit/archive/link rules.
21
+ - All dashboard writes use the same transactions, validation, model handling, deduplication, FTS/vector synchronization, archive rules, and orphan checks specified in [[schema]], [[dedup]], and [[evolution]].
22
+ - Ship required frontend assets locally. The dashboard must remain usable offline and must not load analytics, fonts, scripts, or graph libraries from third-party CDNs.
23
+
24
+ ## Quiet Live-Update Contract
25
+
26
+ ### Initial data and revisions
27
+
28
+ The first load receives a compact graph snapshot with a monotonic `revision`. Full content is fetched only for the selected memory. Each later write increases the revision after its database transaction commits.
29
+
30
+ The UI subscribes to a local SSE stream. The server emits small change events, never a periodic full snapshot:
31
+
32
+ ```text
33
+ id: 418
34
+ event: memory.updated
35
+ data: {"revision":418,"node_id":"mem-a1b2c3d4","changed":["title","status"]}
36
+ ```
37
+
38
+ Required event kinds:
39
+
40
+ | Event | Client action |
41
+ |---|---|
42
+ | `memory.created` | Add one node/list row without resetting the view. |
43
+ | `memory.updated` | Patch that memory's summary; refresh its inspector only when it is not being edited. |
44
+ | `memory.archived` | Patch status and dim the node; retain it in graph/search according to active filters. |
45
+ | `memory.deleted` | Remove the node and its connected edges; show a quiet notice if it was selected. |
46
+ | `edge.created` / `edge.deleted` | Patch only the affected edge counts, graph edge, and inspector links. |
47
+ | `stats.updated` | Patch health/stat counters. |
48
+ | `reset` | Request one fresh snapshot only when the client missed revisions or server history is unavailable. |
49
+
50
+ Reconnect uses `Last-Event-ID`/`since_revision`. If the server cannot supply a complete event gap, it emits `reset`; this is the only permitted automatic full reload.
51
+
52
+ ### State that updates must preserve
53
+
54
+ On every ordinary patch, preserve:
55
+
56
+ - selected memory and inspector scroll position;
57
+ - search text, filters, sort, active mode, and list scroll position;
58
+ - graph zoom/pan camera and current in-browser node positions;
59
+ - open dialogs and unsaved drafts;
60
+ - keyboard focus and accessibility context.
61
+
62
+ A tiny non-blocking “Synced” indicator may update; no toast, animation, or focus change is allowed for routine changes. If another agent edits the memory currently open in an unsaved form, show a passive conflict banner with explicit **Reload** and **Keep editing** choices. Never overwrite the user's draft.
63
+
64
+ ## Default Experience
65
+
66
+ ### Desktop layout
67
+
68
+ Use a dense but breathable three-region workspace:
69
+
70
+ 1. **Top bar** — product name, project scope, search, connection state, and clickable health counters.
71
+ 2. **Graph canvas** — pan/zoom graph with readable labels only at useful zoom levels; visible type/status/edge meaning; keyboard-accessible selection.
72
+ 3. **Inspector** — full selected-memory content, metadata, archive/supersession context, and all inbound/outbound relationships.
73
+
74
+ The inspector is the reading surface, not a cramped card list. Use comfortable line length, clear hierarchy, durable whitespace, selectable text, and obvious status contrast. Archived/superseded knowledge stays readable but visually subdued, never hidden by default.
75
+
76
+ ### Navigation and discoverability
77
+
78
+ - Clicking a node selects it, centers it only when the user requests it, and opens its inspector.
79
+ - Every relationship in the inspector is a clickable chip showing direction, type, `#id`, title, and optional reason. Clicking one selects and reveals that linked memory immediately.
80
+ - Selecting a memory highlights its direct neighborhood without dimming the entire graph so heavily that labels become unreadable.
81
+ - Search supports title/content/ID/node ID; filters include type, status, agent, project/global scope, pinned, and orphan state.
82
+ - Health counters are actionable: clicking orphans, stale tasks, or contradictions applies the matching filter and explains the remediation path.
83
+ - List/search results always show `#id`, `node_id` (or copy affordance), type, status, agent, edge count, and a restrained preview.
84
+
85
+ ### Graph behavior
86
+
87
+ - Node color encodes type; shape, border, or badge distinguishes pinned/constraint, project/global scope, and archived/superseded status. Do not rely on color alone.
88
+ - Edge styling differentiates relationship type and direction. Hover/focus reveals its reason/metadata.
89
+ - New nodes appear without restarting the force simulation or moving existing nodes. Changed nodes preserve coordinates.
90
+ - Provide an explicit **Re-layout graph** action with a confirmation/explanation. Automatic re-layout is prohibited.
91
+ - The graph is an exploration aid, not the only way to work: an accessible list/inspector route remains fully usable without it.
92
+
93
+ ## Write Flows
94
+
95
+ All mutations are explicit, validated, and reversible where the core supports it.
96
+
97
+ - **Create:** requires title, English-oriented content check (soft warning), type, scope, attribution, and at least one meaningful link before final completion. The form surfaces duplicate/near-duplicate outcomes from [[dedup]] with links to the candidate record.
98
+ - **Edit:** uses the core edit path and identifies fields changed by another writer before submit.
99
+ - **Archive/supersede:** requires the reason and required relationship; ordinary UI does not offer hard delete.
100
+ - **Link/unlink:** provides type, direction explanation, reason, duplicate prevention, and an orphan warning before an unlink creates one.
101
+ - **Hard delete:** absent from normal dashboard UI; only the existing explicit CLI safety path may expose it.
102
+
103
+ ## Health and Feedback
104
+
105
+ The dashboard must surface—not silently repair—data problems:
106
+
107
+ - orphan memories;
108
+ - stale open tasks;
109
+ - unresolved contradiction edges;
110
+ - model unavailable / FTS-only mode, including the loss of semantic search and near-duplicate detection;
111
+ - database or event-stream connectivity problems.
112
+
113
+ Errors are contextual and actionable. Successful routine saves update the affected UI in place; they do not trigger a full refresh.
114
+
115
+ ## Accessibility and Visual Quality
116
+
117
+ - Support keyboard navigation, focus states, semantic controls, and screen-reader labels for graph/list/inspector actions.
118
+ - Meet readable contrast in both light and dark themes; honor reduced-motion preferences.
119
+ - Do not use attention-seeking animations. Motion is reserved for intentional navigation and must be subtle.
120
+ - Responsive layouts may collapse the inspector into a focused view, but must preserve full-content reading and linked-memory navigation.
121
+
122
+ ## Implementation Gate and Open Decisions
123
+
124
+ Before implementation, explicitly confirm these items rather than silently treating them as locked:
125
+
126
+ 1. **Position persistence:** v1 must preserve layout during a live session. Persisting node positions across browser restart (for example in local storage or a dedicated local table) is still an open choice.
127
+ 2. **Timeline mode:** graph + list/inspector are required; a dedicated timeline mode is deferred until approved.
128
+ 3. **Exact loopback API schema:** this document locks revision/SSE behavior and service-layer ownership, but endpoint names and payload fields need an implementation review against the final core model.
129
+ 4. **Authentication policy for non-loopback use:** v1 is loopback-only. Any LAN/remote mode requires a separate security design and explicit approval.
130
+
131
+ ## Acceptance Criteria
132
+
133
+ Before dashboard release, demonstrate that:
134
+
135
+ 1. A second agent stores, edits, archives, links, and unlinks memories while a user reads another memory; the reader's state remains intact.
136
+ 2. No normal event calls a full graph render, restarts the simulation, or resets the graph camera.
137
+ 3. A dropped SSE connection catches up by revision or performs one controlled `reset` reload.
138
+ 4. All writes pass the same core validations as CLI/MCP, including archive and orphan rules.
139
+ 5. Every visible relationship is keyboard-accessible and clickable to its connected memory.
140
+ 6. The dashboard works offline with no third-party runtime requests.
141
+ 7. Graph-disabled or assistive-technology users can search, inspect, and maintain memories through the list/inspector workflow.