Skip to main content
Glama
README.md
# Ember — a warm start for coding agents

**Persistent, queryable memory for your codebase, over MCP.**
Point Ember at a repo once; every coding agent you use (Alan, Claude Code,
Cursor, …) starts warm instead of cold — with semantic-ish search, a repo map,
a mined decision log, and answers that cite `file:line`.

Built at [OpenFire 2026](https://luma.com/2k6cxr0n) (Alan AI's 24h open-source
hackathon). MIT licensed, local-first, zero native dependencies.

## The problem

Coding agents start every session cold. Architecture, conventions, and the
reasons behind past decisions get reconstructed tool call by tool call —
slowly, expensively, and often wrong. Humans carry that context implicitly.

## What Ember does

- `index_repo` — scans a repo, splits code into symbol-aware chunks, embeds
  them, and builds a **pure-TypeScript HNSW** approximate nearest-neighbour
  index. Everything persists in `<repo>/.ember/` — no database, no daemon.
  Re-indexing is incremental: per-file hashes mean unchanged files keep their
  embeddings, only new/changed files are re-embedded, and deleted files drop
  out (`--full` forces a from-scratch rebuild).
- `search_code` — ranked `file:line` hits for natural-language queries.
- `ask` — answers questions with citations. With an OpenAI-compatible chat
  endpoint configured (e.g. open models via OpenRouter) answers are
  synthesized by the model; without one they are extractive (top chunks +
  citations). It never invents an answer source.
- `repo_map` — entry points, hub files (most referenced), key symbols,
  languages. The orientation pass an agent otherwise burns minutes on.
- `decisions` / `recent_changes` — the "why": decision-like commits and
  ADR-style docs, plus recent history.
- `index_status` — freshness and embedder info.
- `save_note` / `recall_notes` — cross-session agent memory: an agent leaves a
  short factual note (decision, gotcha, task state) and any later session —
  including a different agent — recalls it. Notes persist in
  `.ember/notes.jsonl`; recall is deterministic keyword matching.

## Quickstart

```bash
npm install
npm run build

# index any repo
node dist/cli.js index --path /path/to/repo

# search it
node dist/cli.js search "how are neighbors selected in the vector index" --path /path/to/repo

# ask with citations
node dist/cli.js ask "where does scanning decide which files to skip" --path /path/to/repo

# repo orientation
node dist/cli.js map --path /path/to/repo
node dist/cli.js decisions --path /path/to/repo

# leave a note for the next session, and recall notes later
node dist/cli.js note "chose jwt over sessions; see auth.ts" --tags auth --path /path/to/repo
node dist/cli.js notes -q auth --path /path/to/repo

# re-index after edits: only changed files are re-embedded
node dist/cli.js index --path /path/to/repo
```

## Use it from your coding agent (MCP)

Ember speaks MCP over stdio. Add it to your agent's MCP config:

```json
{
  "mcpServers": {
    "ember": {
      "command": "node",
      "args": ["/absolute/path/to/ember/dist/cli.js", "serve", "--path", "/path/to/your/repo"]
    }
  }
}
```

Then ask your agent to call `index_repo` once, and `repo_map` / `search_code`
/ `ask` whenever it would otherwise grope around the tree.

## Honest capability notes

- **Default embedder is lexical, not semantic.** Out of the box Ember uses a
  deterministic hashing embedder (stemmed token overlap). It matches shared
  vocabulary well — code identifiers are meaningful — but it does not
  paraphrase. For true semantic embeddings, point Ember at any
  OpenAI-compatible `/embeddings` endpoint:

  ```bash
  export EMBER_API_BASE=https://openrouter.ai/api/v1
  export EMBER_API_KEY=...
  export EMBER_EMBED_MODEL=<an open embedding model>
  export EMBER_EMBED_DIM=<its dimension>
  node dist/cli.js index --path /path/to/repo   # rebuild with the new embedder
  ```

  _Status: this endpoint path is implemented but not yet live-tested; the
  offline default above is the verified configuration. A configured endpoint
  receives the text it embeds (code chunks and queries)._

- **Answer synthesis needs a chat model.** Set `EMBER_CHAT_BASE`,
  `EMBER_API_KEY` (shared with embeddings), and `EMBER_CHAT_MODEL` (e.g. an
  open model like `qwen/qwen3-coder` or `meta-llama/llama-4-maverick` via
  OpenRouter) to get synthesized answers; otherwise `ask` is extractive.
  Same status as embeddings: implemented, not yet live-tested.
- **HNSW is exact HNSW, not a placeholder.** M=16, efConstruction=200,
  diversity-preserving neighbor selection (paper alg. 4), serialized graph in
  `.ember/`. Tests measure recall@10 vs brute force (>0.9 on clustered data).
- **Incremental indexing is hash-based.** `.ember/files.json` stores a sha1
  per file. Unchanged files keep their chunks and vectors; modified files are
  re-chunked and re-embedded; deleted files are removed. Switching embedders
  (kind or dimension) triggers an automatic full rebuild.
- **Note recall is keyword matching.** `recall_notes` scores by unique
  query-term overlap - predictable and offline, not semantic.
- **Local-first.** The index never leaves your machine; network calls happen
  only when you configure an external endpoint.

## How it fits together

```
src/core/scanner.ts    git-aware file walk (skips deps, build output, binaries)
src/core/chunker.ts    symbol-aware code chunking (falls back to windows)
src/core/embedder.ts   pluggable embedders (offline lexical / HTTP endpoint)
src/core/hnsw.ts       pure-TS HNSW index (cosine, diversity selection)
src/core/store.ts      .ember/ persistence (chunks + vectors + graph + file hashes)
src/core/notes.ts      cross-session agent notes (notes.jsonl)
src/core/engine.ts     load + search
src/core/repomap.ts    structure / entry points / hub files
src/core/decisions.ts  decision log + recent changes from git
src/core/ask.ts        cited answers (model or extractive)
src/mcp/server.ts      MCP server (stdio)
src/cli.ts             CLI
```

## Tests

```bash
npm test   # 17 tests: hnsw recall, chunking, end-to-end index+search,
           # notes persistence, incremental re-index, error paths,
           # and a real MCP stdio session (mutations + restart recall)
```

## License

MIT © 2026 Daksh Patel

---

_Built by Daksh Patel with AI assistance (Instinct agent): code, tests and docs were developed iteratively with an AI pair-programmer; all claims in this README reflect behavior verified by the test suite._

Maintenance

ActivityMaintained
ResponsivenessNo issues