Skip to main content

OpenLynx — persistent semantic memory for Claude Code, Codex CLI and other coding agents. Auto-saves and recalls conversation history across sessions.

Project description

lynx-memory

中文 README

Persistent, semantic, long-term memory for Claude Code. Conversations are auto-saved across sessions and the most relevant snippets are injected into context whenever you start a new prompt — no special syntax, no "remember this" phrasing required.

You      : What can I do tomorrow if the weather's nice — maybe walk the dog?
Claude   : Since you've got Dandan (your golden Border Collie) who needs a lot
           of exercise, try a long walk, frisbee, or a bike ride with him
           tagging along… 🐶
            (you never mentioned Dandan or owning a dog — memory recalled it
             from a past chat)

How it works

Three Claude Code hooks + a small Python service:

Hook What it does
UserPromptSubmit Embeds your prompt and injects the top-K most similar prior turns. When a turn has a summary, the summary is injected instead of the raw prose.
Stop Persists the current user/assistant turn into SQLite + Chroma, then spawns a detached background summarizer that calls the configured API (OpenAI, DeepSeek, or Qwen) to extract long-term memories from the turn.
SessionEnd Calls the configured API to produce a coarse memory summary of the whole session.

Storage:

  • SQLite — source of truth for raw turns, per-turn summaries, and session summaries
  • Chroma — local vector index over turns + summaries
  • Voyage AI (voyage-3) — embeddings
  • OpenAI (gpt-4o-mini, default), DeepSeek (deepseek-chat), or Qwen (qwen-turbo) — per-turn and session summarization (any one of OPENAI_API_KEY, DEEPSEEK_API_KEY, QWEN_API_KEY is enough)

Install

pip install openlynx
lynx-memory init

init will:

  1. Create the shared OpenLynx home at ~/.openlynx/
  2. Prompt for your VOYAGE_API_KEY (get one free at https://www.voyageai.com/)
  3. Write the default .env (MIN_SCORE=0.7, SUMMARY_ENABLED=1, SUMMARY_BACKEND=auto) — set OPENAI_API_KEY, DEEPSEEK_API_KEY, or QWEN_API_KEY to enable per-turn summarization (configurable later via the Web UI ⚙ Settings panel)
  4. Back up your existing ~/.claude/settings.json and add the three hooks
  5. Link shared commands and the OpenLynx skill into supported host directories
  6. Print verification steps

If a legacy ~/.claude/lynx-memory/ store exists and ~/.openlynx/ does not, init migrates it to ~/.openlynx/ before installing hooks. If both exist, OpenLynx uses ~/.openlynx/ and leaves the legacy directory untouched.

The shared home is host-neutral:

~/.openlynx/
  .env
  db/
  commands/
  skills/

Claude Code and Codex keep their own hook configuration files, but reusable OpenLynx files are linked from this shared home into host directories such as ~/.claude/commands/, ~/.claude/skills/, ~/.codex/commands/, and ~/.codex/skills/.

Then open a fresh Claude Code session, chat for a few turns, and run:

lynx-memory status

You should see turns and chroma_turns counters going up.

Codex CLI (cross-host memory)

Same memory store, also wired into Codex CLI:

lynx-memory init --target codex   # or --target all to install both

This writes ~/.codex/hooks.json, sets [features] hooks = true in ~/.codex/config.toml, and registers three hooks (UserPromptSubmit → inject, Stop → persist, SessionStart → summarize the previous session since Codex has no SessionEnd event).

Codex's additionalContext field is fully respected, so retrieved memory is injected exactly like in Claude Code. Restart any running codex process for hooks to take effect — they're loaded at session start.

A turn typed in Claude Code can be recalled inside Codex (and vice versa) because both write to the same SQLite + Chroma store at ~/.openlynx/.

CLI

lynx-memory init           Install hooks, slash commands, and skill links
lynx-memory init-project   Create a .lynx-memory/ marker in cwd to enable
                             project-level storage
lynx-memory status         Show data dir, hook registration, DB stats
lynx-memory doctor         Verify Python, deps, API key, settings.json
lynx-memory merge          Merge memory between the project and global stores
                             (--from / --to is project|global, with --dry-run)
lynx-memory delete         Permanently delete memory for a scope
                             (--scope project|global|both, with double confirm)
lynx-memory uninstall      Remove hooks, slash commands, and skill links (keeps your data)

Slash commands

lynx-memory init also installs five global slash commands into ~/.openlynx/commands/ and links them into host command directories such as ~/.claude/commands/ and ~/.codex/commands/:

Command What it does
/lynx-memory-status Show current scope (project vs global) with stats for both
/lynx-memory-pull-global Merge global memory into the current project (global → proj)
/lynx-memory-push-global Merge current project memory into global (proj → global)
/lynx-memory-delete Delete memory with mandatory double confirm (DELETE + y)
/lynx-memory-history Open a local Web UI to browse, search, tag, and delete turns

Each of these runs lynx-memory status / merge --dry-run first and asks for your approval before any write or destructive action.

Skills

lynx-memory init installs the bundled OpenLynx skill into ~/.openlynx/skills/openlynx/ and links it into supported host skill directories such as ~/.claude/skills/openlynx and ~/.codex/skills/openlynx.

Web UI

OpenLynx Web UI

Type /lynx-memory-history in Claude Code (or run lynx-memory web) to launch a local FastAPI + React UI on 127.0.0.1. The page opens automatically in your browser and lets you:

  • Switch between project and global scopes
  • Page through every saved turn
  • Search by keyword (SQL LIKE) or semantic similarity (Voyage embeddings)
  • Tag turns (e.g. #work, #personal) and filter by tag
  • Delete a single turn (also clears its embedding from Chroma)
  • See the per-turn summary above each turn, with a one-click button to (re)generate it on demand
  • Click the ⚙ gear icon (top-right) to open the Settings panel and configure everything in-browser: API keys, summary backend (OpenAI / DeepSeek / Qwen), model, Top-K, min score, and retrieval scope — changes are saved directly to ~/.openlynx/.env

Usage

# default — listens on http://127.0.0.1:9527 and opens your browser
lynx-memory web

# pick a different port
lynx-memory web --port 8080

# or let the OS assign a free port
lynx-memory web --port 0

# don't auto-open the browser (useful in headless / SSH sessions)
lynx-memory web --no-open
Action What happens on disk
Delete a turn Row removed from SQLite turns and turn_tags; embedding removed from Chroma
Add a tag Inserted into SQLite tags (created on demand) and turn_tags
Remove a tag Row removed from turn_tags; orphaned tag is GC'd from tags
Search (keyword) SQL LIKE over user_msg and assistant_msg — no embedding call
Search (semantic) One Voyage embedding per query, then top-K from Chroma
Regenerate summary One API call (OpenAI, DeepSeek, or Qwen, per SUMMARY_BACKEND); writes summary / summary_model / summary_ts back into the turns row

The server only binds to 127.0.0.1. Press Ctrl+C to stop it.

Project-level vs global

Memory is global by default. Run this in a project root:

cd ~/code/my-project
lynx-memory init-project

It creates a .lynx-memory/ marker. As long as your cwd is inside that project, memory transparently switches to the project-level store at <project>/.lynx-memory/db/, isolated from the global one at ~/.openlynx/.

Use /lynx-memory-status to inspect the active scope, and /lynx-memory-pull-global / /lynx-memory-push-global to move history between the two layers.

Configuration

All optional, set in ~/.openlynx/.env:

Variable Default Purpose
VOYAGE_API_KEY Required for embeddings
TOP_K 5 Max memories injected per prompt
MIN_SCORE 0.7 Cosine similarity floor (0–1)
SUMMARY_ENABLED 1 Set 0/false to disable per-turn summarization
SUMMARY_BACKEND auto auto → first provider with a key set (OpenAI → DeepSeek → Qwen); force with openai, deepseek, or qwen
OPENAI_API_KEY Required when SUMMARY_BACKEND=openai
OPENAI_MODEL gpt-4o-mini OpenAI model used for summarization
OPENAI_BASE_URL https://api.openai.com/v1 Override for OpenAI-compatible endpoints
DEEPSEEK_API_KEY Required when SUMMARY_BACKEND=deepseek
DEEPSEEK_MODEL deepseek-chat DeepSeek model used for summarization
DEEPSEEK_BASE_URL https://api.deepseek.com/v1 Override for the DeepSeek endpoint
QWEN_API_KEY Required when SUMMARY_BACKEND=qwen (DASHSCOPE_API_KEY also accepted)
QWEN_MODEL qwen-turbo Qwen model used for summarization
QWEN_BASE_URL DashScope compatible-mode URL Override for the Qwen/DashScope endpoint
LYNX_MEMORY_DIR ~/.openlynx Where SQLite + Chroma live

Optional: MCP server

You can also expose memory as MCP tools for Claude Code (search_memory, list_recent, stats, forget). Add to ~/.claude.json or .mcp.json:

{
  "mcpServers": {
    "lynx-memory": {
      "command": "lynx-memory-mcp"
    }
  }
}

Uninstall

lynx-memory uninstall                   # remove hooks + slash commands + skill links
lynx-memory delete --scope global       # delete the global store (confirms)
# or
rm -rf ~/.openlynx                       # nuke directly (irreversible)

Privacy

  • All data stays on your machine in ~/.openlynx/.
  • Outbound calls: Voyage AI for embeddings (your prompt text); OpenAI, DeepSeek, or Qwen for per-turn and session summaries (requires an API key — set via .env or the Web UI ⚙ Settings panel).
  • Set SUMMARY_ENABLED=0 if you don't want per-turn summaries to leave the box.
  • Set LYNX_MEMORY_DIR to encrypt at rest with whatever filesystem-level encryption your OS provides.

Roadmap

  • Project-level / global dual-layer storage Global by default; auto-switches to project-level when a .lynx-memory/ marker is found by walking up from cwd, so histories from different projects don't bleed into each other. Run lynx-memory init-project in a project root to create the marker. Search supports scope=auto|project|global|merged (hooks via LYNX_MEMORY_SCOPE env; MCP tools accept a scope argument).

  • Codex CLI — same hooks + shared store; use lynx-memory init --target codex (or --target all). See Codex CLI above.

  • Local Web UI memory browser A local FastAPI + React UI with paging, keyword / semantic search, single-turn deletion, and tagging (e.g. #work, #personal). Launch with /lynx-memory-history (or lynx-memory web); the page exposes both project-level and global histories with a one-click scope toggle.

  • Other CLIs (Cursor, Gemini CLI, …) — not integrated yet. Cursor: blocked until a stable hooks surface ships (we plan to adopt it once available); meanwhile MCP-only workflows remain possible where applicable.

  • Unified multi-client installer A future lynx-memory install --client <name> to write MCP configs in one shot, with rules templates for consistent recall across clients that support them.

  • Import / export & cross-device sync lynx-memory export / import for JSONL backup and restore; place db/ in iCloud / Dropbox / a Git repo, or use a built-in lynx-memory sync subcommand to share memory across machines.

  • Richer automatic tagging (precise vs associative) Stronger auto-labeling for turns, with a switchable precise mode (tight, literal, auditable tags) vs associative mode (broader links and softer clusters to improve semantic recall).

  • Recall modes & tunable ranking Let users steer what gets injected beyond raw similarity — combine signals such as retrieval / hit count, relevance score, and recency (last used or last injected), with presets or manual weighting so priority matches your workflow.

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

openlynx-0.4.0.tar.gz (165.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

openlynx-0.4.0-py3-none-any.whl (172.0 kB view details)

Uploaded Python 3

File details

Details for the file openlynx-0.4.0.tar.gz.

File metadata

  • Download URL: openlynx-0.4.0.tar.gz
  • Upload date:
  • Size: 165.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for openlynx-0.4.0.tar.gz
Algorithm Hash digest
SHA256 b4551be9432f45a7a0ec6d3c5c40353074dfd874f4852d0d60134da3f1aedc62
MD5 d6315c1abf07d7f8828d28d9b1f77fbc
BLAKE2b-256 569b8f8d3a112436728ebf6a7b5dc7c30fa6f3649ef3ff160b459f0bbfbf9127

See more details on using hashes here.

File details

Details for the file openlynx-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: openlynx-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 172.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for openlynx-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 09e3db5264b67187b336a1d8f878a28bf60426ca4a21c57bac94290df685bd55
MD5 4e448e37df55327ff806b63622a919bc
BLAKE2b-256 8fd331dfdc5b9356049859ff3b2468b924663bfe9a50870bed496efee0c681ae

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page