> ## Documentation Index
> Fetch the complete documentation index at: https://recipe.uselettuce.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Run locally

> Index a codebase on your own machine and connect an agent to the local lettuce MCP server — no account, no cloud, no source leaving your laptop.

Lettuce runs fully **local-first**. You index a repo into a single SQLite
file on disk, then point your coding agent at a stdio MCP server that reads
that file. Nothing is uploaded — source, graph, and embeddings all stay on
your machine, and there's no API key or network call at query time.

<Note>
  Prefer a hosted endpoint with no local setup? See the
  [Quickstart](/quickstart) for lettuce cloud instead. The tools your agent
  calls (`understand`, `read_snippet`, …) are the same either way.
</Note>

## 1. Install

Lettuce is a Python package managed with [uv](https://docs.astral.sh/uv/).

```bash theme={null}
git clone https://github.com/<you>/lettuce.git
cd lettuce
uv sync
```

This exposes two commands you'll use: `codewaze` (the CLI) and
`codewaze-mcp` (the stdio MCP server).

## 2. Index a codebase

Point `index` at a repo. Lettuce walks the tree, parses each source file
with tree-sitter into a graph of symbols (files, classes, functions,
methods, variables) and relationships (contains, imports, calls, inherits,
references), and builds **semantic embeddings** so `understand` and
`search` can match by meaning.

```bash theme={null}
uv run codewaze index ./path/to/repo
```

The graph is written to `<repo>/.lettuce/graph.db` by default. Re-running
`index` refreshes it.

```json theme={null}
{
  "db": "/path/to/repo/.lettuce/graph.db",
  "repos": [
    { "repo": "/path/to/repo", "branch": "main",
      "files_indexed": 141, "nodes": 203, "edges": 75 }
  ],
  "embeddings": { "nodes": 203, "vectors": 267 }
}
```

<Note>
  The first index downloads a small embedding model
  (`BAAI/bge-small-en-v1.5`, \~130 MB, runs on CPU via ONNX) and loads it
  once — budget \~30–60s of one-time startup. Subsequent indexes are fast.
</Note>

### Options

<ParamField path="--db PATH">
  Where to write the graph DB. Defaults to `<first-repo>/.lettuce/graph.db`.
  Pass an explicit path to put it elsewhere or to share one map across
  repos.
</ParamField>

<ParamField path="--embed / --no-embed">
  Build semantic embeddings (on by default). `--no-embed` is faster but
  leaves `understand`/`search` **lexical-only** — they'll work, but match
  on names and text rather than meaning.
</ParamField>

<ParamField path="--branch TEXT">
  Scope the graph to a branch. Defaults to the repo's current git branch.
  Re-indexing a different branch never clobbers a previously indexed one,
  so you can keep several branches mapped in the same DB.
</ParamField>

### Multiple repos in one map

Pass several paths plus a shared `--db` to build a single cross-repo graph
— calls and imports resolve across repo boundaries, so an agent can follow
a reference from a service into the library it depends on:

```bash theme={null}
uv run codewaze index ./api ./shared-lib ./worker --db ./workspace.db
```

## 3. Query from the CLI (optional)

You can drive the graph directly to sanity-check an index:

```bash theme={null}
uv run codewaze query search "rate limit" --repo ./path/to/repo
uv run codewaze query symbol UserService --repo ./path/to/repo
uv run codewaze query entry-points --repo ./path/to/repo
```

Each `--repo` resolves to that repo's `.lettuce/graph.db`; pass `--db` to
point at a shared map instead.

## 4. Connect your agent

The local server speaks MCP over **stdio** — your agent launches it as a
subprocess, no port or auth.

### Claude Code

```bash theme={null}
claude mcp add lettuce -- uv run --directory /abs/path/to/lettuce codewaze-mcp
```

### Cursor / Windsurf / Cline

Add a stdio server to the agent's MCP config (e.g. `.cursor/mcp.json`):

```json theme={null}
{
  "mcpServers": {
    "lettuce": {
      "command": "uv",
      "args": ["run", "--directory", "/abs/path/to/lettuce", "codewaze-mcp"]
    }
  }
}
```

By default the local server exposes a **minimal two-tool surface** —
`understand` and `read_snippet` — which is all most agents need. Set
`CODEWAZE_MCP_FULL=1` in the server's environment to expose the full
navigation surface (`search`, `find_symbol`, `callers`, `callees`,
`find_path`, `transitive`, `subgraph`, …); see [MCP tools](/mcp-tools).

<Note>
  Each tool takes an optional `repo` (a path) or `db` argument so the server
  knows which graph to read. You can also set `LETTUCE_DB` in the server's
  environment to pin it to a single graph and drop the argument entirely.
</Note>

## 5. Tell the agent to use it

Agents won't reach for a new tool unprompted. Drop this into the repo's
`CLAUDE.md` (or your agent's equivalent):

```md theme={null}
For navigation, prefer the lettuce MCP tools over grep/Read:
call `understand` first, then `read_snippet` only for the lines you need.
Pass the `repo` path so lettuce knows which graph to read.
```

Now ask *"Who calls `process_payment`, and what would break if I rename
it?"* — the agent should answer from a single `understand` call instead of
grepping and reading whole files.

## Languages

Python, TypeScript, JavaScript, Go, Rust, Java, Ruby, C, C++, .NET (C#), PHP,
Kotlin, Scala, Swift, Bash, and Lua. Python and TS/JS use hand-written
tree-sitter walkers; the rest go through a shared generic extractor.

## Where things live

| Path                          | What                                           |
| ----------------------------- | ---------------------------------------------- |
| `<repo>/.lettuce/graph.db`    | The graph + embeddings (one SQLite file).      |
| `~/.lettuce/credentials.json` | Cloud login, only if you use `codewaze login`. |

The graph DB is portable — copy it to another machine and the MCP server
reads it as-is. No daemon, no server, no external service.
