LTM-SPEC-0001 · 2026-04-21

Portable understanding
for AI work sessions.

Ship intent between machines and models — not configuration. A one-file, one-verb protocol. Self-hosted. Model-agnostic. Open.

Protocol
ltm — long-term memory for AI sessions
Version
0.1 (draft)
Status
draft — call for comment
Editors
Dennis de Vulder · Thijs Herman
Reference
github.com/dennisdevulder/ltm
License
Apache-2.0
sh
          
$ curl -fsSL https://ltm-cli.dev/install | sh
# ~180 lines of spec. ~1,900 lines of Go. that is the whole thing.

§ 1. Abstract

Why this exists.

You hit a wall on your Mac. The GPU story doesn't work. You pivot to a Fedora box, spin up a new agent, and spend an hour re-explaining what you've tried, what you ruled out, and why. The model makes the same mistakes you already solved for.

ltm fixes exactly that. And nothing else.

§ 2. Protocol

Three verbs. That is the spec.

verbdescriptionexample
writeAgent emits a Core Memory Packet at session end.$ ltm write --from .agent/session.json
push Packet is pushed to any ltm-compatible server. $ ltm push 01JDMB4W1YNJ…
pull A new session on any machine pulls it back. $ ltm pull 01JDMB4W1YNJ…

HTTPS transport with bearer-token auth. SQLite storage. ULID-keyed packets. Nothing exotic; nothing reinvented.

§ 3. Design principles

Four invariants.

REQ-01

Intent, not configuration

Your CLAUDE.md, skills, and tool setup stay yours. Only the understanding of what you are doing travels.

REQ-02

Self-host or nothing

No enterprise tier. No hosted-only features. If it does not run on a $5 VPS, it is not done.

REQ-03

Model-agnostic

A packet written by Claude is readable by GPT, Gemini, or the next thing.

REQ-04

Spec first

The protocol is public and versioned. The CLI and server are reference implementations — not the whole product.

§ 4. Core Memory Packet

A single JSON object.

Five required fields. Six recommended. Forward-compatible. Every field earns its byte.

01JDMB4W1YNJZQR7K8F3A2H5P9.json 1543 B · ltm v0.1
          
1{
2 "ltm_version": "0.1",
3 "id": "01JDMB4W1YNJZQR7K8F3A2H5P9",
4 "created_at": "2026-04-18T22:41:03Z",
5 "provenance": {
6 "agent": "claude-code",
7 "model": "claude-sonnet-4-5",
8 "host": "darwin-arm64"
9 },
10 "goal": "Get llama.cpp inference running on a local GPU for a Rust side-project; benchmark tok/s vs. CPU.",
11 "decisions": [
12 {
13 "what": "Abandon Metal backend on M2",
14 "why": "Kernel compile fails with Xcode 16.2; not worth diagnosing further.",
15 "locked": true
16 },
17 {
18 "what": "Continue on Fedora 40 + RTX 4070 (CUDA 12.4)",
19 "why": "Known-working GPU path; matches target deployment hardware.",
20 "locked": true
21 },
22 {
23 "what": "Pin llama.cpp to b3821",
24 "why": "Newer builds regress on sm_89; b3821 bench-verified.",
25 "locked": false
26 }
27 ],
28 "attempts": [
29 {
30 "tried": "brew install llama.cpp",
31 "outcome": "builds, but MPS allocator OOMs on 13B Q4",
32 "learned": "MPS path has a hard ceiling well below VRAM — not a tuning issue."
33 },
34 {
35 "tried": "GGML_METAL=1 make -j",
36 "outcome": "link error: _ggml_metal_graph_compute undefined",
37 "learned": "Metal symbols moved; would need a Xcode 15 toolchain — out of scope."
38 }
39 ],
40 "open_questions": [
41 "Is flash-attn worth enabling on sm_89 for <14B?",
42 "Does llama-bench reflect real inference? Need an e2e harness."
43 ],
44 "next_step": "On the Fedora box: clone llama.cpp@b3821, build with -DLLAMA_CUDA=ON, run llama-bench -m qwen2.5-7b-q4_k_m.gguf -ngl 99."
45}
SIZE
1543 bytes
FIELDS
5 required 6 recommended
OMITS
paths, secrets, transcripts
IDENTITY
ULID per packet
[ full schema → ]

§ 5. Scope

In scope / out of scope.

IN SCOPE
  • +Developers using AI agents across multiple machines
  • +Small teams sharing context without sharing setup
  • +Self-hosters who want their memory on their own box
OUT OF SCOPE
  • People looking for a managed memory SaaS
  • Teams that want a single-vendor Claude/Cursor/Codex stack
  • Anything that needs enterprise SSO on day one

§ 6. Reference implementation

Install the CLI.

sh · client
          
$ curl -fsSL https://ltm-cli.dev/install | sh
$ ltm auth https://your-server.dev <token>
$ ltm pull <packet-id>
# session restored. your agent takes it from here.

Self-hosting the server is two commands:

sh · server
          
$ ltm server init
$ ltm server --addr :8080
# sqlite on disk. bearer tokens. done.