install

requirements

DependencyVersionNotes
python3.12+
gitanyUsed for repo identity, hooks
jqanyRequired by capture hooks

one command

$ pip install getflex && flex init

This downloads the embedding model (~87 MB), scans your Claude Code sessions, builds the cell database, installs hooks for live capture, and registers the MCP server.

flags

FlagEffect
--localUse local CPU for embeddings. Skips the Nomic API prompt entirely.
--nomic-key <key>Use Nomic API for faster embeddings (~2 min vs ~20 min on CPU). Get a free key at atlas.nomic.ai.
Non-interactive environments (Docker, CI, piped stdin): flex init auto-detects non-TTY contexts and falls back to local CPU. Pass --local or --nomic-key to be explicit.

priority chain for nomic API key

Flex checks these in order. First match wins:

~/.flex/secrets (saved key)  →  --nomic-key flag  →  NOMIC_API_KEY env  →  --local flag  →  isatty() guard  →  interactive prompt

what happens

flex init runs a complete bootstrap in one pass:

StepWhatTime
1Create ~/.flex/ directory structure<1s
2Download ONNX embedding model (~87 MB)~10s
3Check jq and git on PATH<1s
4Install hooks, slash commands, agent definitions<1s
5Scan sessions from ~/.claude/projects/ (~30 days retained by Claude)1–5 min
6Install views, presets, systemd services<1s
7Embed all chunks (GPU: ~258/s, CPU: ~27/s, Nomic API: ~192/s)2–20 min
8Build knowledge graph — communities, hubs, centrality5–15s
9Register MCP server in ~/.claude.json<1s
Ctrl+C is safe. flex init picks up where it left off — sessions already parsed won't be re-parsed, chunks already embedded won't be re-embedded.

After init completes, restart Claude Code or open a new session. Type /mcp to verify the flex server is connected.

cli

flex init

Full onboarding — model download, session backfill, enrichment, hooks, services, MCP registration.

$ flex init
$ flex init --local
$ flex init --nomic-key nk-abc123

flex index

Re-run the backfill and enrichment pipeline on an existing cell. Same as flex init minus hooks and services.

$ flex index claude-code
$ flex index docpac /path/to/context  # index a documentation corpus

flex search

Query a cell directly from the terminal. Accepts SQL, presets, or vec_ops expressions. Use --cell NAME to target a specific cell (default: claude_code).

# SQL
$ flex search "SELECT COUNT(*) FROM sessions"

# preset
$ flex search "@digest days=7"

# semantic search
$ flex search "SELECT v.id, v.score, m.content FROM vec_ops('_raw_chunks', 'authentication') v JOIN messages m ON v.id = m.id LIMIT 5"

flex sync

Bring everything into parity — presets, views, stubs, services. The "make it current" command.

$ flex sync              # presets + views + services
$ flex sync --full       # also runs enrichment pipeline
$ flex sync --cell NAME  # single cell only

files

Everything lives under ~/.flex/. One directory. Portable. Back it up with rsync.

~/.flex/
├── models/ ONNX model files (downloaded by flex init)
├── registry.db cell catalog — name → UUID → path
├── secrets API keys (Nomic)
├── queue.db event queues (hooks write, worker reads)
├── views/ curated view SQL (user-editable)
│ └── claude_code/ messages.sql, sessions.sql
├── operations/ SQL audit log (timestamped, git-tracked)
└── cells/ your databases
  ├── {uuid}.db the cell — one file, entire knowledge base
  └── {uuid}-history.jsonl query history

~/.claude/
├── hooks/
│ ├── claude-code-capture.sh notifies worker on tool use
│ ├── user-prompt-capture.sh notifies worker on user prompt
│ └── flex-index.sh queues changed .md files for docpac
├── commands/flex/ slash commands (/flex:local, /flex:agent)
├── agents/flx-trace.md retrieval sub-agent definition
└── settings.json hook wiring (patched by flex init)

~/.config/systemd/user/
├── flex-worker.service live capture daemon
└── flex-mcp.service MCP server (HTTP/SSE on port 7134)

how it works

Four components. One direction.

Claude Code tool use
       │
  [hooks]  write session_id to queue
       │
       ▼
  ~/.flex/queue.db
       │
  [worker]  polls every 2s, reads JSONL, embeds, writes to cell
       │
       ▼
  ~/.flex/cells/{uuid}.db
       │
  [MCP server]  exposes cell as read-only SQL surface
       │
       ▼
  Claude writes SQL

hooks

Hooks are notification-only — they write a session ID and timestamp to the queue. No payload, no parsing. The worker reads the actual JSONL file for data.

worker

A systemd user service (flex-worker) that drains the queue every 2 seconds. For each session: parse JSONL, extract chunks with metadata, embed via ONNX, write to cell. Three cycles: queue drain (2s), full enrichment (30 min), and backfill + identity heal (24h).

MCP server

HTTP/SSE server on localhost:7134. Exposes one tool: flex_search. Accepts SQL, preset names, or vec_ops() expressions. Read-only — a SQLite authorizer blocks all writes at the engine level. Claude reads the schema via @orient, then writes its own queries. Works with Claude Code, claude.ai, Cursor, or any MCP client.

enrichment

Offline intelligence, computed automatically. The worker runs the full pipeline every 30 minutes:

LayerWhat it produces
Source graphCentrality, hub status, community membership
File graphFile co-edit relationships across sessions
Delegation graphParent → child agent topology
FingerprintsSession summaries — navigational index per session
Project attributionMaps sessions to repos via 5-tier resolution
Community labelsHuman-readable names for session clusters

All enrichment output is in _enrich_* tables. Safe to wipe. Recomputed automatically.

troubleshooting

flex command not found or runs the wrong binary

Some systems have flex (the lexer generator) installed at /usr/bin/flex. If it shadows the flex CLI:

# check which flex you're running
$ which flex

# if it's /usr/bin/flex (the lexer), fix your PATH
$ export PATH="$HOME/.local/bin:$PATH"

# or add to your shell profile
$ echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc

hdbscan build failure (Arch Linux)

hdbscan requires Cython and numpy headers at build time. On Arch, pipx isolated venvs can't see system Cython.

# create a manual venv instead of pipx
$ python -m venv ~/.local/share/flex-venv
$ source ~/.local/share/flex-venv/bin/activate
$ pip install setuptools wheel cython numpy
$ pip install --no-build-isolation hdbscan
$ pip install getflex

model download fails

The ONNX model (~87 MB) is downloaded from GitHub Releases. If the download fails or the file is corrupt:

# delete and re-download
$ rm -rf ~/.flex/models/
$ flex init

# flex init verifies checksums — corrupt files are deleted and retried

flex init hangs (Docker / CI / piped stdin)

The interactive Nomic API prompt requires a real terminal. In non-interactive environments:

$ flex init --local                     # skip Nomic, use CPU
$ flex init --nomic-key nk-abc123       # pass key directly
$ NOMIC_API_KEY=nk-abc123 flex init      # or via env var

Bare flex init in non-TTY contexts auto-detects and falls back to CPU with a hint.

MCP server not connected

After flex init, restart Claude Code or open a new session. Then:

# verify MCP is registered
$ cat ~/.claude.json | jq '.mcpServers.flex'

# in Claude Code, type:
/mcp

# you should see "flex" with the flex_search tool listed

MCP connection drops mid-session

If Claude stops recognizing the flex tool during a session, the MCP connection may have dropped. Type /mcp in Claude Code to reconnect without restarting the session.

worker not running

The worker is a systemd user service that captures new sessions in real time.

$ systemctl --user status flex-worker    # check status
$ systemctl --user restart flex-worker   # restart
$ journalctl --user -u flex-worker -f    # tail logs

stale data / missing sessions

flex sync is the recovery command. It installs missing views, presets, stubs, and restores systemd services and MCP wiring if absent.

$ flex sync              # views + presets + services
$ flex sync --full       # also re-runs enrichment
$ flex index claude-code # full re-index from JSONL