| Dependency | Version | Notes |
|---|---|---|
python | 3.12+ | |
git | any | Used for repo identity, hooks |
jq | any | Required by capture hooks |
$ 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.
| Flag | Effect |
|---|---|
--local | Use 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. |
flex init auto-detects non-TTY contexts and falls back to local CPU. Pass --local or --nomic-key to be explicit.
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
flex init runs a complete bootstrap in one pass:
| Step | What | Time |
|---|---|---|
| 1 | Create ~/.flex/ directory structure | <1s |
| 2 | Download ONNX embedding model (~87 MB) | ~10s |
| 3 | Check jq and git on PATH | <1s |
| 4 | Install hooks, slash commands, agent definitions | <1s |
| 5 | Scan sessions from ~/.claude/projects/ (~30 days retained by Claude) | 1–5 min |
| 6 | Install views, presets, systemd services | <1s |
| 7 | Embed all chunks (GPU: ~258/s, CPU: ~27/s, Nomic API: ~192/s) | 2–20 min |
| 8 | Build knowledge graph — communities, hubs, centrality | 5–15s |
| 9 | Register MCP server in ~/.claude.json | <1s |
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.
Full onboarding — model download, session backfill, enrichment, hooks, services, MCP registration.
$ flex init
$ flex init --local
$ flex init --nomic-key nk-abc123
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
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"
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
Everything lives under ~/.flex/. One directory. Portable. Back it up with rsync.
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 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.
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).
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.
Offline intelligence, computed automatically. The worker runs the full pipeline every 30 minutes:
| Layer | What it produces |
|---|---|
| Source graph | Centrality, hub status, community membership |
| File graph | File co-edit relationships across sessions |
| Delegation graph | Parent → child agent topology |
| Fingerprints | Session summaries — navigational index per session |
| Project attribution | Maps sessions to repos via 5-tier resolution |
| Community labels | Human-readable names for session clusters |
All enrichment output is in _enrich_* tables. Safe to wipe. Recomputed automatically.
flex command not found or runs the wrong binarySome 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
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.
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
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.
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
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