codex-lcm
# codex-lcm
Local, lossless context management for OpenAI Codex CLI.
codex-lcm captures Codex conversation events in SQLite, compacts older context into a hierarchy of summaries without deleting the source messages, restores relevant context when a session starts, and exposes lexical recall through a local MCP server.
> **Meaning of “lossless”:** source content is retained after configured secret redaction. Searchable tool previews are bounded, while complete redacted tool input and output remain available through paged expansion.
## Status and platform
codex-lcm is beta software for macOS. It relies on Codex hooks and POSIX `flock`; Windows and Linux are not currently supported or claimed.
## Features
- **Live capture:** user prompts, assistant responses, and tool activity are captured through Codex hooks.
- **Durable local storage:** SQLite in WAL mode stores raw messages, structured message parts, summaries, and FTS5 indexes.
- **Hierarchical compaction:** older messages become leaf summaries; eligible summary runs can be condensed into deeper DAG nodes. Source rows are never deleted automatically.
- **Context restore:** active summaries and the newest unsummarized messages are injected at session start within a strict size bound.
- **Local recall:** six stdio MCP tools provide lexical search, recent-session lookup, metadata inspection, and paged source expansion.
- **Fail-open hooks:** capture or compaction failures do not block a Codex turn.
- **Safety controls:** secret redaction, per-session compaction locks, atomic message/FTS writes, provider-call reservations, progress checks, and private default file permissions.
## Install from a repository checkout
```bash
python3 -m venv ~/.codex-lcm/venv
~/.codex-lcm/venv/bin/python -m pip install .
~/.codex-lcm/venv/bin/codex-lcm install
~/.codex-lcm/venv/bin/codex-lcm doctor
```
Restart Codex after installation. Use `/hooks` in Codex to inspect and trust the installed hooks.
The installer merges codex-lcm entries into `~/.codex/hooks.json` and `~/.codex/config.toml`. It creates timestamped backups before changing existing files. Running the installer again is idempotent.
A source checkout also includes `scripts/install.sh`, which performs the same isolated installation and verification.
### Optional LLM summarization
On Python 3.11+, the core package has no third-party runtime dependencies. Python 3.10 installs the `tomli` compatibility backport for safe TOML configuration handling. Without an LLM client, compaction uses deterministic head/tail truncation.
To enable OpenAI-compatible summarization, install the optional extra and configure credentials:
```bash
~/.codex-lcm/venv/bin/python -m pip install ".[llm]"
export CODEX_LCM_API_KEY="..."
```
`OPENAI_API_KEY` is also recognized. Use `CODEX_LCM_BASE_URL` or `OPENAI_BASE_URL` for an OpenAI-compatible endpoint. The `CODEX_LCM_*` provider settings are treated as a pair and take precedence as a pair, so a global key is never sent to a scoped endpoint. When `CODEX_LCM_BASE_URL` is set, configure `CODEX_LCM_API_KEY` too.
## CLI
```text
codex-lcm install Wire hooks and the MCP server into Codex
codex-lcm uninstall Remove codex-lcm wiring and keep stored data
codex-lcm status Show database statistics
codex-lcm doctor Verify package, database, hooks, and MCP wiring
codex-lcm compact --session <id> Compact one session synchronously
codex-lcm compact --all Compact every recorded session synchronously
```
Uninstalling does not delete `~/.codex-lcm/` or its database.
## MCP tools
| Tool | Purpose |
|---|---|
| `lcm_status` | Database and active-session statistics |
| `lcm_grep` | Literal and FTS5 lexical search over messages and summaries |
| `lcm_recall` | Ranked lexical recall with bounded result counts |
| `lcm_expand` | Summary-source inspection or paged raw-message recovery |
| `lcm_recent` | Sessions updated inside a UTC look-back window |
| `lcm_describe` | Session or summary metadata |
Recall is lexical, not semantic: there are no embeddings or vector-similarity claims in this release.
## Configuration
Configuration is read from environment variables.
| Variable | Default | Purpose |
|---|---:|---|
| `CODEX_LCM_DB_PATH` | `~/.codex-lcm/codex-lcm.db` | SQLite database path |
| `CODEX_LCM_FRESH_TAIL` | `25` | Newest raw messages protected from compaction |
| `CODEX_LCM_LEAF_CHUNK_TOKENS` | `20000` | Maximum estimated tokens in a leaf chunk |
| `CODEX_LCM_LEAF_MIN_FANOUT` | `3` | Active leaf summaries required for condensation |
| `CODEX_LCM_CONDENSED_MIN_FANOUT` | `3` | Active deeper summaries required for condensation |
| `CODEX_LCM_MAX_ROUNDS` | `5` | Compaction rounds per worker run |
| `CODEX_LCM_MAX_SUMMARY_CALLS` | `12` | Provider attempts allowed per session and call window |
| `CODEX_LCM_SUMMARY_CALL_WINDOW_MS` | `600000` | Provider-attempt accounting window |
| `CODEX_LCM_SUMMARY_TIMEOUT_MS` | `60000` | Provider request timeout |
| `CODEX_LCM_PROGRESS_THRESHOLD` | `0.10` | Marks a compaction run stalled below this savings ratio |
| `CODEX_LCM_ADDITIONAL_CONTEXT_LIMIT` | `5000` | Restore-context budget in estimated tokens |
| `CODEX_LCM_COMPACTION_BACKLOG` | `5` | Extra unsummarized messages allowed before `Stop` starts a worker |
| `CODEX_LCM_COMPACTION_MODEL` | `gpt-4.1-mini` | Leaf summarization model |
| `CODEX_LCM_CONDENSATION_MODEL` | `gpt-4.1` | Condensation model |
| `CODEX_LCM_API_KEY` / `OPENAI_API_KEY` | — | Optional provider credential |
| `CODEX_LCM_BASE_URL` / `OPENAI_BASE_URL` | — | Optional OpenAI-compatible endpoint |
| `CODEX_LCM_CAPTURE_TOOLS` | `1` | Set to `0` to disable tool capture |
| `CODEX_LCM_TOOL_INPUT_MAX_CHARS` | `2000` | Searchable tool-input preview length |
| `CODEX_LCM_TOOL_RESULT_MAX_CHARS` | `2000` | Searchable tool-output preview length |
The default data directory is mode `0700`; the database, WAL sidecars, lock files, and compaction log are mode `0600` on POSIX systems.
## Data and security boundaries
- Redaction occurs before persistence for known API keys, tokens, authorization headers, password/secret assignments, JWTs, and PEM private keys.
- Credential-bearing Git remote URLs are stored without user information, query parameters, or fragments.
- Redaction is defence in depth, not a guarantee that every possible secret format will be recognized.
- Complete redacted tool payloads can still contain private conversation or project data. Protect the local account and database backups accordingly.
- No data is sent to an LLM provider unless the optional client is installed and provider credentials or a base URL are configured.
- Automatic retention and deletion are intentionally absent. The application does not silently discard source history.
## Development
Use a project-local environment; tests never need the live Codex profile or database.
```bash
python3 -m venv .venv
.venv/bin/python -m pip install -e ".[dev]"
.venv/bin/python -m pytest -q
.venv/bin/python tests/smoke_test.py
.venv/bin/python tests/reliability_test.py
.venv/bin/python tests/package_test.py
.venv/bin/ruff check .
.venv/bin/bandit -q -r codex_lcm
```
The package test builds and installs into a throwaway home directory and virtual environment. The smoke and reliability scripts also use temporary databases.
See [DESIGN.md](DESIGN.md) for the storage model, invariants, hook flow, and failure behaviour.
## License
MIT
TDQS
Scored across 6 tools
lcm_grep and lcm_recall are nearly indistinguishable: both are described as lexical FTS5 search with literal substring fallback across messages and summaries. The remaining tools are distinct, but this overlap creates a real risk of misselection.
All tools share the lcm_ prefix and snake_case convention, which is highly predictable. Most names are verb-like, though lcm_recent and lcm_status are descriptive/adjectival rather than action verbs.
Six tools is well-scoped for a memory-database access server, covering expansion, recent activity, metadata, health, and search without excessive surface area.
The retrieval surface is fairly complete for reading and inspecting memory, including expansion and health status. However, there is no visible write/ingest operation, so agents cannot persist or update memories through this server.