# 🧠 Lemma

[![npm version](https://img.shields.io/npm/v/@nxuss/lemma.svg?color=orange&style=flat-square)](https://www.npmjs.com/package/@nxuss/lemma)
[![License](https://img.shields.io/npm/l/@nxuss/lemma.svg?color=blue&style=flat-square)](https://github.com/Nxusbets/lemma/blob/main/LICENSE)
[![MCP Tools](https://img.shields.io/badge/MCP%20tools-110-ff69b4?style=flat-square)](https://github.com/Nxusbets/lemma)
[![Security](https://img.shields.io/badge/privacy-firewall%20active-blueviolet?style=flat-square)](https://github.com/Nxusbets/lemma)
[![Caching](https://img.shields.io/badge/semantic%20memory-enabled-success?style=flat-square)](https://github.com/Nxusbets/lemma)
[![Tests](https://img.shields.io/badge/tests-1003%20passing-00c853?style=flat-square)](https://github.com/Nxusbets/lemma)

```text
    __
   / /   ___  ____ ___  ____ ___  ____ _
  / /   / _ \/ __ `__ \/ __ `__ \/ __ `/
 / /___/  __/ / / / / / / / / / / /_/ /
/_____/\___/_/ /_/ /_/_/ /_/ /_/\__,_/
```

> **The Intelligent local-first AI Gateway — Privacy, Performance, Static Code Intelligence, and Infrastructure Command Center for the Agentic Era.**

Lemma sits between your development environment and LLM providers as an MCP server / local proxy.
It cuts what actually enters the model's context — repeated reads, unfiltered command output, tool
schemas the project can't use — while keeping every answer verifiable: a cache hit is disclosed as
a cache hit, a compressed file is never what the user sees, and a savings number always traces back
to an auditable ledger, never an estimate.

## 🚀 Quick start

```bash
npm install -g @nxuss/lemma
lemma init      # auto-configures MCP for your IDE (Muse, Claude Code, Cursor, Codex, Windsurf, Kiro, OpenCode)
lemma start     # gateway + dashboard on http://localhost:8081
```

> **Muse** — no setup needed. This repo is already Muse-compatible zero-config: clone and open with `muse` — the skill at `.agents/skills/lemma/SKILL.md` auto-loads and `lemma call` works via `bash`. See [MCP integration](#-mcp-integration).
>
> **🆕 v1.22.0 — Lemma auto-activates in every LLM client.** `npm i -g @nxuss/lemma` registers the skill in your **user** catalog (auto-loads in every `muse` session, any project) and `lemma init` wires each project for Muse, Claude Code, Cursor, Codex, Windsurf, Kiro and OpenCode. Health check: `lemma doctor`.
>
> **🆕 v1.32.0 — what a command can see and reach.** `run_workspace_command` no longer hands the
> child the host's whole environment (tokens, API keys, the license key): it gets a short allowlist,
> extendable via `mcp.commandEnv.allow`. `cat`, `ls`, `grep`, `find`, `sed`… must keep their paths
> inside the workspace, and on Windows a backslash executable path no longer passes as a bare name.
> New and opt-in: `mcp.sandbox.mode: "docker"` runs each command in a throwaway container with only
> the workspace, no network, no host environment and a read-only root, and fails closed if Docker is
> unavailable. **Behavior change:** a command that relied on an inherited variable now needs it allowed
> by name (or `mcp.commandEnv.mode: "inherit"`). Also fixed: options a tool advertised and ignored
> (`generate_pr_workflow.autoApprove`, `jenkins_generate_pipeline`, `TaskLifecycle.cleanup`), now guarded
> by a test. See the [changelog](CHANGELOG.md).
>
> **🆕 v1.31.1 — secrets, symlinks and stale fixes.** A second round of dogfooding (rounds 11-20)
> found that `run_workspace_command` handed `.env` secrets to the model in clear (`cat .env`,
> `grep -r PASSWORD .`) while `read_workspace_file` masked them — command output is now scrubbed too.
> Also closed: writes escaping the workspace through a dangling symlink, an allowlist that accepted
> `./git` and `env sh -c`, a compressor that cut code at `//` inside strings, a scrubber that masked
> code as secrets, `brain_trash purge` wiping the whole trash on an invalid `olderThanDays`, and
> `local_semantic_autofix` presenting a stale fix as a clean zero-token hit (it now says `STALE`, or
> that the fix is not anchored to any file). Patches keep your CRLF line endings and tab/space
> indentation, and `list_workspace_dir` caps huge directories. See the [changelog](CHANGELOG.md).
>
> **🆕 v1.31.0 — tools that said "success" without doing the job, fixed.** Dogfooding with a small
> project driven only through Lemma's own tools found a pattern: several tools answered cleanly
> without having done what was asked. `validate_patch_sandbox` approved *every* patch (it ran `npx tsc`
> in an empty temp dir, which resolves a different package); `surgical_ast_insert` ignored an unknown
> parameter, appended code outside the class and reported success (it now refuses syntax-breaking
> patches); `get_ast_hologram` ignored `filePath` and scanned the whole repo (212K chars);
> `search_workspace` could not find its own source file (two stray NUL bytes made it look binary).
> Also fixed: `type_coverage_report` counting inferred types as missing, `affected_tests` using the root
> runner for nested packages, lockfiles and changelogs ranking as "risk 100" in `git_heatmap_risk` /
> `precrime_static`, `review_diff` flagging missing tests that already exist, and `brain_export`
> being annotated read-only while it writes a file.
> New: every result now says when an **argument was ignored** (`⚠️ Lemma ignored unknown argument …
> Valid: …`, also on failures), and when a **newer build exists than the running MCP process** — a
> rebuild never reaches a process that is already running, so reconnect it (Claude Code: `/mcp` →
> lemma). `get_symbol_surgical_context` now resolves methods (`Class.method`).
> **Behavior change:** the extra "Proceed?" confirmation on `run_workspace_command`,
> `apply_workspace_patch` and `forget_memory` is now **off by default** (the allowlist and path checks
> are unchanged); set `"mcp": { "confirmActions": true }` in `lemma.config.json` to get it back.
>
> **🆕 v1.30.1 — `lemma init` now really installs the Brain's hooks, and big search results stop eating
> your context.** Dogfooding found that `lemma init` finished "successfully" without installing the
> git hooks (`post-commit`, `post-merge`, `post-checkout`) or the Claude Code / Codex / Cursor /
> OpenCode tool hooks that v1.28–v1.30 advertised — so commits never became memories. Fixed
> (idempotent, merge-only, `--no-hooks` to skip); re-run `lemma init` after updating.
> `search_workspace` also had a match cap but no size cap: one hit inside a minified bundle returned
> the whole line (~75k tokens reproduced). Lines are now a 240-char window around the hit and the
> result is capped at ~8k tokens, with what was dropped disclosed. Plus 10% smaller tool schemas
> (−938 tokens per session).
>
> **🆕 v1.30.0 — the Brain speaks through your agent's own tools, for zero tokens.** Agents read,
> edit and test with their native tools, so the Brain used to stay silent unless the model
> remembered `search_memory`. Now a post-tool hook answers at the three moments a memory is worth
> the most: reading a file the Brain has notes on (their ids), editing code where an approach
> already **failed**, and a test/build/lint failing with an error the Brain has a recorded **fix**
> for. Local BM25 + hashes, no model tokens; ids and one line only (~35 tokens), and silent by
> default — no match, a stale fix, or a note already given this session says nothing. `lemma init`
> wires it for **Claude Code, Codex, Cursor and OpenCode**. Also fixes `store()`'s dedup leaking
> across projects (the same fix in a second repo was dropped as a "duplicate").
>
> **🆕 v1.29.0 — the dashboard shows what the Brain knows.** `lemma start` now opens with a
> 🧠 Brain panel: how many files of your codebase it carries evidence about, how many times a
> memory reached an agent's context, growth this week, how much of it is verifiable against the
> code, where memories come from (manual, red → green fixes, tests, commits, team), and the most
> recalled ones. Token savings stay as a footnote — the Brain's value is agents not re-discovering
> context. Same numbers in `brain_stats` and at `GET /api/brain/stats`.
>
> **🆕 v1.28.0 — the Brain goes team-wide through git, and fills itself.** `brain_team push`
> writes your verified memories into the repo (`.lemma-brain/memories/`, one reviewable JSON file
> each, paths relative to the repo root); `brain_team pull` — automatic on merge/checkout once
> `lemma init` installs the hooks — imports a teammate's memories rebased onto *your* checkout. A
> memory about a file that is byte-identical on your machine arrives **fresh**; one whose file has
> moved on arrives **stale**, never silently trusted. And memories no longer depend on the model
> remembering `store_memory`: a test/build/lint command that goes **red → green** is captured as
> `fix: <the error>` + the files and diff that fixed it — searchable by the exact error message next
> time — whether it ran through `run_workspace_command` or the agent's own shell (Claude Code
> `PostToolUse` hook). Commits become memories anchored to their own blobs. Also fixes
> `lemma-brain-ingest` silently dropping everything it ingested.
>
> **🆕 v1.26.0 — a memory without evidence is no longer sold as a verified hit, and the Brain
> repairs it on the spot.** `search_memory` now splits its results into three buckets — `fresh`
> (tracked + verified, the only ones credited `tokensSaved`/`hits`), `stale`, and `UNTRACKED`
> (no files/symbols to re-check: flagged with ⚠️ and its remedy, never "from cache"). On the
> maintenance side, `brain_upkeep` auto-anchors those evidence-free memories when their body
> names real repo files — corpus snapshot first (`auto-anchor`), reversible via
> `brain_trash restore-snapshot`; `autoAnchor:false` keeps the old read-only pass.
>
> **🆕 v1.24.0 — the Brain stops crediting what it can't verify.** `smarter_cache` no longer
> presents a stale hit as a clean one (`stale:true`/`tokensSaved:0` + why, instead of a silent
> guess); `store_memory` derives evidence by default from files/symbols the session already
> touched instead of depending on the caller to pass them; every "tokens saved" figure now cites
> the `hits` that earned it. See [`CHANGELOG.md`](CHANGELOG.md) for the full list.

---

## ✨ What Lemma actually does

- **Shared Semantic Memory ("The Brain")** — a zero-dependency local index (BM25 + Jaccard, no
  ChromaDB/Ollama required) that persists solutions, fixes, and decisions across every project and
  every session, with claim- and symbol-level freshness so a stale answer can't hide behind a fresh
  one. Memories can depend on other memories (`derivedFrom`) and inherit their staleness
  transitively; `verify_memory` batch-revalidates a set of ids by hash-compare alone, no search
  round trip; `semanticDiff` tells a comment/formatting-only edit apart from a real one so
  reformatting a file doesn't falsely invalidate what was learned about it. Write tools
  (`surgical_ast_insert`, `apply_workspace_patch`, `write_workspace_file`) warn proactively when
  the code they're about to touch has dependent memories — including a documented failed
  attempt — instead of only finding out on the next search. Ranking factors in
  real usage (`hits`), explicit negative feedback (`downvote_memory`), and `cognitive_map` domain
  tags; a command that goes red → green auto-captures the fix (see below); two memories
  about the same symbol that disagree on outcome are flagged, not silently both suggested.
  Every hit explains itself (`whyShown` ranking signals + cited `evidence` files/symbols), and
  every reuse books its savings onto the memory itself — `brain_stats` and `brain_upkeep` name
  which memories actually pay for the Brain (`totalTokensSaved` alongside the `hits` that earned
  it, never one without the other). `store_memory` derives `filePaths`/`symbols` by default from
  whatever the session already read, wrote, or patched when the caller doesn't pass them —
  flagged as auto-derived in the response, correctable, but no longer opt-in.
- **A Brain that speaks up on its own, through the host's tools** — a post-tool hook
  (`lemma-brain-ingest --hook-result --host=claude|codex|cursor|opencode`) points at memories when
  the agent reads a file they're about to matter for, warns when an edit touches a documented
  failed attempt, and names the recorded fix when a verdict command fails with an error already
  fixed in *this* project (term overlap between error headlines decides "the same failure", not
  BM25 rank). No model tokens to compute, ids instead of bodies, deduped per host session, and a
  pointer never counts as reuse. Codex's shell reads (`cat`, `sed -n`, …) and `apply_patch` edits
  are recovered from the command; OpenCode gets a plugin, since it has no hook protocol.
  Windsurf/Devin post-hooks can't inject context, and Kiro's hooks spend tokens by design, so
  neither is wired.
- **A team Brain, shared through git** — `brain_team push` writes this project's fresh, tracked
  memories to `.lemma-brain/memories/<id>.json`: one sorted-key JSON file per memory, so two people
  sharing at once never conflict, every shared memory goes through code review, and deleting one is
  a `git rm`. Evidence is stored relative to the repo root and rebased onto each clone on `pull`,
  hashes untouched — a teammate's memory is verified against *your* files, fresh only if they are
  byte-identical. Never shared: conversation checkpoints, commit memories (each clone derives its
  own), untracked or stale memories, evidence outside the repo, or anything derived from a memory
  that isn't shared. A pulled path that is absolute or escapes the repo is rejected; a memory a
  teammate deletes leaves your clone into `brain_trash` (restorable), and one you wrote yourself is
  never removed. Pushing is always explicit; pulling is a no-op when nothing changed, so it runs on
  every merge/checkout. `brain_team status` shows both sides; `dryRun:true` previews either.
- **Memories that write themselves** — a verdict command (jest, vitest, pytest, tsc, eslint, `go
  test`, `cargo test`, `npm test`/`build`/`lint`, …) that fails and later passes stores
  `fix: <headline error>` with the failure signature, the files whose content changed between the
  two runs, and their diff — tracked against those files, tagged `confirmed`, source `auto-fix`.
  A pass with nothing changed since the failure is treated as flaky and stores nothing; a "fix" over
  15 files is a refactor and stores nothing. It sees `run_workspace_command`, `test_oracle`, and — via
  `lemma-brain-ingest --hook-result` — the agent's own Bash tool. Commits are ingested with each
  touched file anchored to its blob *in that commit* (`git show sha:path`), not to the working copy.
  `lemma init` installs the `post-commit`, `post-merge` and `post-checkout` hooks that drive this
  (appended to existing hooks, idempotent, never touches a versioned `core.hooksPath` like husky).
- **A memory that maintains itself** — `brain_upkeep` revalidates the most-reused memories,
  surfaces exact duplicates and merge candidates, dead weight, and savings, each finding with its
  fix. Since v1.26.0 it also **auto-anchors** evidence-free memories whose body names real repo
  files — snapshot first (`auto-anchor`), then re-anchored to those paths so they become
  verifiable; `autoAnchor:false` keeps the pass read-only, and everything is reversible via
  `brain_trash restore-snapshot`. `brain_merge` folds near-duplicate fragments into one
  canonical entry (fragments survive as evidence-carrying claims). `forget_memory` moves to a
  trash (`brain_trash`: list/restore/purge) instead of destroying, automatic snapshots roll
  back every forget/import/clear/merge, and `brain_import dryRun:true` previews a bundle —
  counts plus opposite-outcome conflicts — before a byte is written. Session onboarding
  re-checks freshness of the memories it lists, so a day-one answer never starts stale.
- **Integrity and encryption at rest** — the corpus carries a sha256 sidecar with `.prev`
  backup rotation: a half-written or rotted file serves its intact lines, falls back to the
  backup on total loss, and quarantines (never deletes) the bad bytes, with the incident
  surfaced in `brain_stats`. `LEMMA_BRAIN_ENCRYPT=1` (or `LEMMA_BRAIN_KEY`) stores the
  corpus AES-256-GCM encrypted under a local 0600 key; secrets never reach disk at all —
  scrub-on-store redacts credentials one-way before indexing or persisting.
- **Verifiable caching, not marketing numbers** — `state_hash_cache` only hits when the files an
  answer depends on are byte-identical, and reading a file it already tracks an answer for
  surfaces that proactively, the same way a Brain memory does. A `smarter_cache` hit on a memory
  whose evidence changed comes back `stale:true`/`tokensSaved:0` with a warning instead of
  looking like a clean hit. `token_receipt` gives a real per-session breakdown of how each answer
  was produced instead of an invented "% saved."
- **Privacy Firewall** — API keys, credentials, and PII are scrubbed automatically from every file
  read and workspace search, before anything leaves your machine.
- **Zero-token static intelligence** — dependency graphs, entropy/coupling/risk scores, and an AST
  symbol index, computed locally with the TypeScript Compiler API. No LLM calls, no tokens.
- **Command output distillation** — a failing `npm test`/`tsc` run is parsed by deterministic
  per-format rules (jest, tsc, eslint) down to the failures that matter; the full output is never
  lost, just stored and retrievable on demand.
- **Surgical, AST-based patching** — `surgical_ast_insert` and `refactor` edit or rename by
  compiler-verified AST location instead of asking the model to output a full-file rewrite.
- **Infrastructure Command Center** — 22 free tools for Jenkins, OKD/OpenShift, and Terraform:
  discover, connect, deploy, diagnose, and detect drift, all via MCP.
- **Scoped tool surface** — of the 110 registered tools, only the ones your project shows evidence
  of needing are advertised to the model each turn; the rest stay one `lemma_toolbox` call away.

See [`CHANGELOG.md`](CHANGELOG.md) for the full, per-version history.

---

## 💎 Free vs Pro

60 of the 110 registered tools work with no license; 50 require Pro. Enforced by one allowlist in
code (`FREE_TOOLS` in `src/mcp/tools.ts`, including all 22 infrastructure tools), not by narrative.
A session without a license doesn't even advertise the Pro tools — they stay registered and
discoverable via `lemma_toolbox`.

| | Free (60) | Pro (50) |
| :--- | :--- | :--- |
| **Caching & memory** | `smarter_cache`, `state_hash_cache`, `token_receipt`, `search_memory`, `list_memories`, `store_memory`, `downvote_memory`, `verify_memory`, `token_budget`, `brain_upkeep`, `brain_trash`, `brain_merge`, `brain_team` | `get_telepathic_hints`, `query_hybrid_consensus`, `semantic_dedup_guard`, `local_semantic_autofix` |
| **Reading & context** | `read_workspace_file`, `scrub_privacy`, `import_tree_context`, `bulk_file_digest`, `auto_context_bundle`, `git_blame_heat`, `type_coverage_report` | `get_ast_hologram`, `smart_file_slice`, `get_symbol_surgical_context`, `diff_only` |
| **Writing & workspace** | — | `write_workspace_file`, `apply_workspace_patch`, `multi_file_patch`, `search_workspace`, `run_workspace_command`, `validate_patch_sandbox`, `surgical_ast_insert` |
| **Static analysis** | — | `entropy_score`, `coupling_radar`, `pattern_fossil`, `precrime_static`, `dead_export_necromancer`, `depgraph`, `refactor`, `ast_flow_visualizer`, `cognitive_map` |
| **Infrastructure** | All 22: `infra_*`, `jenkins_*`, `okd_*`, `terraform_*` | — |
| **Automation & PR review** | `conversation_checkpoint`, `test_autofix_interceptor`, `prompt_pattern_cache` | `review_diff`, `review_pr`, `pr_status`, `test_oracle`, `auto_heal`, AutoPilot, Silent Patch Watcher |

Get Pro: `lemma activate <key>` → [lemma.nxus.studio/upgrade](https://lemma.nxus.studio/upgrade)

Full per-tool listing: `lemma_toolbox { "action": "list" }`.

---

## 🎚️ Tool profiles

Every advertised tool schema is re-sent on **every request** of the session — advertising all 110
costs ~11,900 tokens/turn. Lemma advertises a scoped surface instead: core tools always, situational
groups (e.g. infrastructure) only when the repo shows evidence for them. Nothing is removed —
everything stays registered and reachable via `lemma_toolbox`.

```jsonc
// lemma.config.json
{ "mcp": { "toolProfile": "full" } }   // "auto" (default) | "core" | "full"
```

```jsonc
lemma_toolbox { "action": "list",   "query": "terraform drift" }   // what exists
lemma_toolbox { "action": "schema", "tool":  "terraform_drift" }   // its inputs
lemma_toolbox { "action": "call",   "tool":  "terraform_drift", "args": {} }
```

`token_budget` reports the profile in use and what the advertised schemas actually cost this session.

---

## 🛠️ CLI reference

| Command | Action |
| :--- | :--- |
| `lemma init` | Bootstraps config, auto-configures MCP for OpenCode, Claude Desktop, Cursor, Windsurf, Kiro, VS Code, and installs the hooks that feed the Brain: git hooks, plus the tool hooks for Claude Code, Codex, Cursor and OpenCode (`--no-hooks` to skip). |
| `lemma start` | Launches proxy, cache engine, and dashboard at `http://localhost:8081` (gateway savings + Brain knowledge panel). |
| `lemma stop` / `lemma status` / `lemma stats` | Stop, health check, and net token/cost report (reports `NET COST` when a session is underwater). |
| `lemma mcp` | Starts the stdin/stdout MCP server for IDE integration. |
| `lemma heal` / `lemma autopilot` / `lemma watch` | Diagnose+repair the last crash / toggle autonomous fix-apply / silent patch-only watcher. |
| `lemma patches` / `lemma apply <id>` / `lemma discard <id>` | List, apply, or discard a pending Silent Patch Watcher fix. |
| `lemma activate <key>` | Activate a Pro license. |
| `lemma-checkpoint [projectRoot]` | Derive a session checkpoint from repo state (branch, changed files, commits) with no assistant call. |
| `lemma-brain-ingest [projectRoot] [--changelog] [--team-pull]` | Feed The Brain from git commits and `CHANGELOG.md`, incrementally; `--team-pull` imports the repo's `.lemma-brain/`. |
| `lemma-brain-ingest --hook-result [--host=claude\|codex\|cursor\|opencode]` | Read a host post-tool payload on stdin: capture red → green fixes from the agent's own shell, and reply with a Brain note (memory ids, failed attempts, known fixes) in that host's format — or nothing. |

Wire the standalone bins into hooks so memory doesn't depend on the assistant remembering to call a tool:

```jsonc
// ~/.claude/settings.json
{ "hooks": { "SessionEnd": [{ "hooks": [{ "type": "command",
  "command": "lemma-checkpoint \"${CLAUDE_PROJECT_DIR:-$PWD}\"" }] }] } }
```

```jsonc
// .claude/settings.local.json — what `lemma init` writes: fixes from Claude Code's own Bash
// become memories, and native Read/Edit/Bash get Brain notes back
{ "hooks": { "PostToolUse": [{ "matcher": "Bash|Read|Edit|MultiEdit|Write|NotebookEdit",
  "hooks": [{ "type": "command", "command": "lemma-brain-ingest --hook-result" }] }] } }
```

Codex (`~/.codex/hooks.json`, `--host=codex`), Cursor (`~/.cursor/hooks.json`, `postToolUse` +
`postToolUseFailure`, `--host=cursor`) and OpenCode (a plugin in `~/.config/opencode/plugins/`) are
wired the same way by `lemma init` when their config directory exists. Existing hooks are kept;
a file that isn't valid JSON is left alone and the snippet printed instead.

The git side needs nothing by hand either: `lemma init` installs `post-commit` (commit → memory) and
`post-merge`/`post-checkout` (pull the team's `.lemma-brain/`). With a versioned hooks dir
(`core.hooksPath`, e.g. husky) it prints the lines to add instead of editing team files.

Customize via `lemma.config.json`:

```json
{
  "system": { "clipboardWatcher": { "disabled": false } },
  "mcp": { "allowedCommandPrefixes": ["npm", "git", "tsc", "your-custom-tool"] }
}
```

---

## 🔌 MCP integration

| Client | Setup |
| :--- | :--- |
| **Muse** (`muse` CLI · Muse Spark) | `lemma init` installs the skill into your **user** catalog (`muse skills install --scope user`, auto-loads in every session) + project skill; `npm i -g @nxuss/lemma` also registers it via postinstall. `lemma call` wrapper via `bash` (no MCP native needed). Health check: `lemma doctor`. |
| OpenCode | `lemma init` — registers itself in `~/.opencode.json`, zero config. |
| Cursor / Windsurf / Kiro / Antigravity | Settings → MCP → add server, command `lemma mcp`. |
| Claude Desktop | Add to `mcpServers`: `{ "lemma": { "command": "npx", "args": ["-y", "@nxuss/lemma", "mcp"] } }` |
| Claude Code / Codex CLI | `lemma init` — auto-configures MCP + sets gateway (`ANTHROPIC_BASE_URL`/`OPENAI_BASE_URL` → `http://localhost:8081`). |

Once connected, Lemma auto-injects its TurboMode system prompt on handshake — states the goal
(reduce what enters context without ever costing a correct answer) and enforces it: a tool call
must save more than its own round-trip, `smarter_cache` hits are disclosed as cached and
re-verified before being acted on, `store_memory` only fires after a solution is verified, and
compression is always for the model's own context — the user gets the real file.

---

## 📡 MCP resources

| Resource URI | Description |
| :--- | :--- |
| `lemma://runtime/context` | Live application errors, stack traces, and runtime state. |
| `lemma://stats/usage` | Current token savings, cost report, and cache hit metrics. |
| `lemma://project/context` | Active project metadata, tech stack, memory count. |
| `lemma://project/onboarding` | Dynamic project architecture guide. |
| `lemma://multiverse/timeline` | Chronological AST diff timeline of recent snapshots. |

---

## 🔒 Security

**Network binding.** Binds only to `127.0.0.1` by default — not network-accessible unless you set
`LEMMA_BIND_HOST=0.0.0.0` and enable `AUTH_ENABLED`/`AUTH_REQUIRE_API_KEY`/`AUTH_ALLOWED_ORIGINS`.

**Command allowlist.** `run_workspace_command` is deny-by-default, with defaults covering normal
JS/TS, Python, Go, Rust, Ruby, JVM, `make`, git/gh, read-only shell utilities, and container/infra
CLIs. Extend via `lemma.config.json` → `mcp.allowedCommandPrefixes`. See
[`.env.security.example`](.env.security.example) for every security-related env var.

**What commands can reach.** Two guards apply by default, on macOS, Linux and Windows:

- *Environment.* Commands no longer inherit the host's whole environment (tokens, API keys, the
  license key). They get `PATH`, home/temp dirs, locale, terminal and toolchain-location variables
  only. If a command needs more (for example `HTTPS_PROXY`), allow it by name, or restore the old
  behavior:

  ```json
  { "mcp": { "commandEnv": { "allow": ["HTTPS_PROXY"] } } }
  { "mcp": { "commandEnv": { "mode": "inherit" } } }
  ```

- *Paths.* `cat`, `head`, `tail`, `ls`, `find`, `grep`, `rg`, `sed`, `awk`, `diff`, `sort`, `wc` and
  similar must keep their file operands inside the workspace: absolute paths, `~`, `..` that climb
  out, environment variables in a path, and symlinks pointing outside are refused.

Those two are guards, not a sandbox: commands that run code (`node -e`, `python -c`, `npm run`,
`git -C …`) can still reach anything the user can. For real isolation, opt in to the Docker sandbox
(Docker is the one layer that works the same on macOS, Linux and Windows):

```json
{ "mcp": { "sandbox": { "mode": "docker", "image": "node:22-bookworm", "network": "none" } } }
```

Each validated command then runs in a throwaway container that sees only the workspace (mounted at
`/workspace`), with no network (`"network": "bridge"` allows it, for `npm install` or `git fetch`),
none of the host's environment, no capabilities, a read-only root filesystem, and bounded memory,
CPUs and processes (`memory`, `cpus`, `pidsLimit`). Files it creates belong to you, not to root.
It fails closed: if Docker is down or the image is missing, the command is **not** run on the host.

The image must contain the toolchain your commands use (`node:22-bookworm` has node, npm, git,
python3, make and gcc; there is no `cargo` or `go`). Run `docker pull <image>` once beforehand,
since a first download counts against the command's timeout.

**Confirmations.** `run_workspace_command`, `apply_workspace_patch` and `forget_memory` no longer
ask the host for a second "Proceed?" by default — the allowlist, the rejection of shell chaining and
the workspace-root path checks are what protect you, and your host has its own permission layer. To
require the extra prompt: `{ "mcp": { "confirmActions": true } }` in `lemma.config.json`.

**Brain at rest.** Secrets are redacted one-way before a memory is indexed or persisted
(scrub-on-store, same patterns as the traffic firewall — the token map is discarded, there is
no unmask step). `LEMMA_BRAIN_ENCRYPT=1` additionally stores the corpus AES-256-GCM encrypted
under `<brainDir>/.brain.key` (0600, auto-generated); `LEMMA_BRAIN_KEY` (64 hex chars or base64
of 32 bytes) overrides it for teams sharing one key. A malformed key fails loud at startup;
a wrong key flows into the integrity fallback (backup → quarantine → fresh start), never an
exception, never half a corpus.

---

## 🦜 SDK integrations & proxy mode

```typescript
import { LemmaCrewAIProvider } from '@nxuss/lemma/crewai';
const crew = new LemmaCrewAIProvider({ agents: [...] });
```

Point any OpenAI-compatible tool at `http://localhost:8081/v1` for transparent caching and privacy
(Cursor: Settings → Models → Override Base URL; VS Code/Continue: `apiBase`).

---

MIT © Nxus Studio | [Upgrade to Lemma Pro](https://lemma.nxus.studio/upgrade)
