Galvo Memory
Graph-native memory layer for AI coding agents. Two shipping paths from one substrate:
- Personal-use today — replaces flat-file
MEMORY.md / CLAUDE.md / AGENTS.md with a typed knowledge graph queryable across Claude Code, Codex, and VS Code.
- Galvo productization — same substrate, customer-deployable as a memory service for Lucidity's agent platform.
Canonical design: docs/MEMORY-LAYER-DESIGN.md. Read that first.
Phase 2 plan + acceptance gates: docs/PHASE-2-PLAN.md.
Status
Phase 2 cycle 1 — feature-complete. Six acceptance gates verified by
examples/sidecar_demo.sh:
- 12-label custom ontology (
Decision, Pattern, Convention, Constraint, Task, Session, Mistake, Commit, Failure, Artifact, Test, Belief) layered on neo4j-agent-memory==0.2.1.
- FastAPI sidecar on
:7575 owning the MemoryClient + the MiniLM-L6-v2 384-dim embedder warmup.
- 3-tier scope partitioning (
project:<id> / personal / universal) with in-cypher filtering.
- REST CRUD over all 12 labels + semantic search via the library's vector index.
- 4 Claude Code lifecycle hooks (
SessionStart, UserPromptSubmit, PostToolUse, SessionEnd).
AGENTS.md / CLAUDE.md file watcher → Convention writer.
python -m memory.cli promote — pin a graph node back into a markdown file.
- D5 SessionEnd utility scorer — 4-signal feedback writer on
RETRIEVED_IN edges.
Cycle 2 parking lot (explicit deferrals — out of scope here):
- Qwen3-Embedding swap (currently MiniLM-L6-v2 / 384-dim; swap requires vector-index migration recipe).
- Consolidation service ("dream-state" rollups, Belief supersession orchestration).
- Codex / VS Code hook adapters (cycle 1 only ships Claude Code).
- Embedding-cosine re-query detection in the scorer (cycle 1 uses Jaccard word-overlap).
GET /api/node/{id} one-shot label+props lookup (cycle 1 walks per-label routes; acceptable on loopback).
Layout
memory/
├── docker/ # docker-compose.yml — Neo4j Community + sidecar
├── sidecar/ # FastAPI bridge on :7575 — REST CRUD + scoring + health
├── ontology/ # Custom 12-label mapping + adoption driver
├── scope/ # Project marker (.galvo-mem/project.toml) + scope detector
├── hooks/claude_code/ # 4 lifecycle hooks (SessionStart / UserPromptSubmit / PostToolUse / SessionEnd)
├── watcher/ # AGENTS.md / CLAUDE.md file watcher → Convention writer
├── cli/ # `python -m memory.cli promote ...`
├── examples/ # End-to-end demo + operator README
├── tests/ # 330 unit + integration tests (uv run --extra dev --extra sidecar --extra watcher pytest)
└── docs/ # Design brief + Phase 1 spike findings + Phase 2 plan
Quick start
# 1. Bring up Neo4j + sidecar.
cd memory/docker
docker compose up -d
# 2. Verify both healthy (first boot warms the MiniLM embedder; ~10-30s).
curl -fsS http://localhost:7575/health
# Expect: {"status":"ok","neo4j":"ok","embedder":"all-MiniLM-L6-v2",...}
# 3. Run the end-to-end smoke — 6 acceptance gates.
bash memory/examples/sidecar_demo.sh
# Exit code 0 = all gates passed.
If you'd rather have the script own the stack lifecycle:
GALVO_MEMORY_DEMO_STARTUP=1 bash memory/examples/sidecar_demo.sh
Scope: mark a project
Memory writes are tagged with a stable scope so queries from one project don't surface another's notes. Mark a project once at the repo root:
mkdir .galvo-mem
cat > .galvo-mem/project.toml <<'EOF'
[project]
id = "myproj"
name = "My Project"
[scope]
default = "project:myproj"
EOF
The marker file survives renames, moves, and worktrees. Sessions opened anywhere under that tree (including subdirectories and git worktree add paths) inherit scope=project:myproj. Without a marker, the scope detector falls back to personal for the current user.
Source: scope/marker.py, scope/detector.py.
Install on Claude Desktop
Claude Desktop supports MCP servers but not lifecycle hooks. That means the auto-capture story (SessionStart top-of-mind, PostToolUse logging commits and edits, SessionEnd scoring) is Claude Code only. In Claude Desktop, the memory layer surfaces as MCP tools (memory_store, memory_search, etc.) that the model calls when it decides recall is relevant.
Setup is one config edit plus a restart:
- Make sure the substrate is running (Neo4j on
:7687):
cd docker && docker compose up -d neo4j
- Edit Claude Desktop's MCP config. Location is OS-specific:
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
- Windows:
%APPDATA%\Claude\claude_desktop_config.json
- Linux:
~/.config/Claude/claude_desktop_config.json