Skip to content

learncoder4848/devmate

Repository files navigation

devmate

A local, offline AI dev assistant for any repo and any language — exposed as a single MCP server. It pairs a local LLM (the brain) with codebase-grounded retrieval (cocoindex + code-specialized embeddings) so its answers are based on your actual code.

Works with Claude Code, Cursor, Windsurf, and Claude Desktop. Fully offline once set up — no cloud API, no code leaves your machine.

Tools

All four are grounded in the indexed repository via retrieval.

Tool What it does
develop Write a feature / refactor / fix — including tests, docstrings, and small accompanying changes — matching repo conventions, and writes the files to disk
review Review code against the repo's conventions, for bugs/security, PRs, or pasted changes
explain Explain how something works, or brainstorm an approach — grounded in real files
search Semantic code search over the repo (re-ranked to favor implementation over tests/docs); returns raw chunks for the host model to read

develop refuses to run when retrieval returns no chunks (avoids silent FastAPI/Flask guesses). Root README.md is demoted when AGENTS.md exists at repo root. API/endpoint tasks pull core/** implementation first, demote OpenAPI skill templates, and block writes to .cursor/ / SKILL.md.

Architecture

   Claude Code / Cursor / Claude Desktop
              │  (one registered MCP server)
              ▼
        ┌─ devmate ───────────────────────────┐
        │  develop · review · explain · search │
        │                                      │
        │  retrieval ──► ccc (cocoindex)       │  ← backend, not a separate MCP
        │  inference ──► local LLM (Ollama)    │
        └──────────────────────────────────────┘
                          │
            cocoindex daemon → jina code embeddings → local SQLite index
  • Brain (reasoning): a local model via Ollama (default codestral:22b), or vLLM on a shared GPU.
  • Apply model: a small, fast model (default Kortix FastApply-7B) that merges develop's lazy edit sketches into full files — the two-model split. Pulled by setup.sh; see How develop edits files.
  • Retrieval (RAG): cocoindex-code with jinaai/jina-embeddings-v2-base-code embeddings, indexed per-repo into local SQLite. setup.sh patches index settings so .cursor/rules, .claude/skills, and invariants are searchable (default ccc init excludes all dot-dirs via **/.*). Retrieval uses multiple passes — agent knowledge → implementation (core/** by default) → data layer (models/repositories on write tasks) → broad — and re-ranks so rules beat tests/docs. On develop, a sibling-test pass also derives name stems from the task (e.g. StatementBuilderstatement_builder) and pins the matching test file(s) into context so generated code follows the repo's test conventions — these chunks are additive and exempt from the tests/* demotion.
  • One MCP server — cocoindex runs as devmate's backend, not a separate server.

Quick Setup (recommended)

One command does everything — installs Ollama + a model, installs cocoindex with the code-embedding model, indexes your repo, and registers the MCP server:

git clone https://github.com/learncoder4848/devmate
cd devmate
./setup.sh /path/to/your-repo      # or run with no arg to use the current dir

What setup.sh does (6 steps, idempotent — safe to re-run):

1/6  Ollama          install + start (skips if present)
2/6  Model picker     choose a reasoning model + pull the apply model
3/6  cocoindex-code   install on Python 3.12 (the retrieval backend)
4/6  Embeddings       pin known-good deps + set jina code embeddings
5/6  Index repo       ccc init + ccc index the target repo
6/6  Register         build + register the devmate MCP (with REPO_ROOT)

Then restart your IDE and use the tools naturally:

"develop a retry-with-backoff wrapper for the ledger client"
"review this diff against our conventions"
"explain how interest is computed here"
"search for where SCRA adjustments are posted"

Adding another repo (same command)

setup.sh is dual-mode. To point the assistant at a different repo later, just run it again with that path — it skips everything already installed and only indexes + re-points devmate at the new repo:

./setup.sh /path/to/other-repo

Indexing is fast and one-time per repo (~10s for a small service, ~1–2 min for a large one; incremental re-index after that is near-instant). First run also downloads the jina embedding model (~160 MB) once.

Requirements the script checks for: macOS, Homebrew, Node.js, and Python 3.12 (cocoindex's deps don't support 3.13+). It installs Ollama, pipx, and cocoindex-code for you.

How develop edits files

develop uses a two-model split so a local model can safely modify existing files, not just create new ones:

  1. The reasoning model plans the change and emits change blocks:
    • ### FILE: <path> — a brand-new file, with its full content in a fence.
    • ### EDIT: <path> — an existing file, as a lazy sketch: only the changed regions, with ... existing code ... markers standing in for everything else.
  2. For each ### EDIT:, the apply model merges the sketch into the full original file (it is purpose-built for this and avoids the anchor/diff-boundary failures of making one model emit exact diffs).

Safety guarantees (a bad edit never silently corrupts a file):

  • New files are only created, never overwrite an existing file; ### EDIT: only touches files that exist.
  • A merge that would drop an existing top-level def/class/function (GUARD_SYMBOL_LOSS) or a top-level import (GUARD_IMPORT_LOSS) is rejected (imports are repaired when possible), as is a merge that looks truncated or that leaks an unexpanded ... existing code ... marker (GUARD_MARKER_LEAK).
  • develop never writes to .cursor/, .claude/, .agents/, or SKILL.md.
  • Every change in a run is revertible, which powers the verify loop below.

Verify-and-retry loop (optional). Set VERIFY_CMD (e.g. poetry run pytest -x -q or make lint) and develop runs it after writing. On failure it reverts the changes and re-prompts the model with the error output, up to DEVELOP_MAX_ATTEMPTS (default 3 when VERIFY_CMD is set, else single-shot). If the final attempt still fails, the last attempt is kept on disk so you can inspect and fix it (set REVERT_ON_FINAL_FAILURE=true to revert to a clean repo instead). Either way, every mid-loop attempt is reverted before the next retry so attempts never stack.

Live progress. Because MCP is request/response (a tool call can't stream while it runs), develop writes a step-by-step log to .devmate/progress.log and opens it in your editor at the start — retrieval, each file written, each verify attempt and result — so you can watch it work instead of staring at a silent foreground. Toggle with PROGRESS_ENABLED / PROGRESS_FILE.

Editor open. Created/edited files are opened in your editor (cursor by default) so you see them immediately. Toggle with OPEN_EDITED / EDITOR_CMD.

Configuration

All configuration is via the env block of the devmate entry in your MCP host config (written by setup.sh):

Variable Default Description
LLM_BASE_URL http://localhost:11434/v1 Ollama or vLLM endpoint (reasoning model)
LLM_MODEL codestral:22b Reasoning model (plans changes, emits edit sketches)
LLM_TEMPERATURE 0.1 Sampling temperature (low = deterministic, convention-following)
LLM_NUM_CTX 32768 Context window (Ollama num_ctx); must hold CONTEXT + prompt. 0 = server default
LLM_TIMEOUT 180 Reasoning request timeout (seconds)
LLM_MAX_TOKENS 4096 Max tokens per reasoning response
REPO_ROOT (set by setup) Repo the tools operate on & retrieve from
CCC_BIN ~/.local/bin/ccc Path to the cocoindex CLI
Apply model (merges develop edit sketches into files)
APPLY_MODEL hf.co/QuantFactory/FastApply-7B-v1.0-GGUF:Q4_K_M Apply model name
APPLY_BASE_URL (= LLM_BASE_URL) Apply model endpoint
APPLY_TEMPERATURE 0 Apply temperature (0 = deterministic merge)
APPLY_NUM_CTX 32768 Apply context window; must hold full file + sketch
APPLY_TIMEOUT 300 Apply merge timeout (seconds)
APPLY_MAX_TOKENS 16384 Max tokens for a merged file (apply re-emits the whole file; too low → merge truncated & the file skipped). Raise for very large files
Retrieval
RETRIEVAL_K 12 Chunks of grounding context per query
RETRIEVAL_AGENT_K 3 Max chunks from .cursor / .claude / docs/dev per query
RETRIEVAL_IMPL_GLOB core/** Implementation-biased pass; set empty to disable
RETRIEVAL_RELATED_GLOBS core/models/**,core/repositories/** Data-layer pass on write tasks (comma-separated)
RETRIEVAL_RELATED_K 4 Chunks per data-layer glob
RETRIEVAL_TEST_GLOBS tests/**,**/tests/**,**/test_*.py,**/*_test.py,**/*.test.*,**/*.spec.*,**/*_test.go Globs for the sibling-test pass (develop only, comma-separated)
RETRIEVAL_TEST_K 3 Reserved, additive chunks of sibling-test context pinned into develop runs (0 disables)
Edit safety / loop
GUARD_SYMBOL_LOSS true Reject a merge that drops an existing def/class/function
GUARD_IMPORT_LOSS true Repair (or reject) a merge that drops a top-level import
GUARD_MARKER_LEAK true Reject a merge whose output still contains an unexpanded ... existing code ... marker (corrupts the file)
VERIFY_CMD (empty) Command run after a write; failure reverts + re-prompts
VERIFY_TIMEOUT 300 Verify command timeout (seconds)
DEVELOP_MAX_ATTEMPTS 3 if VERIFY_CMD set, else 1 Max develop attempts
REVERT_ON_FINAL_FAILURE false On the final failed verify attempt: false keeps the last attempt on disk for inspection; true reverts to a clean repo. Mid-loop attempts always revert before retrying
PROGRESS_ENABLED true Write a live step-by-step progress log during develop and open it in the editor (watch it work — MCP can't stream inside one tool call)
PROGRESS_FILE .devmate/progress.log Repo-relative path for the live progress log (auto-gitignored)
OPEN_EDITED true Open created/edited files in the editor
EDITOR_CMD cursor Editor CLI used to open files (e.g. code -r)

Switching repos = change REPO_ROOT (or re-run setup.sh <repo>) and restart the host. devmate drives cocoindex with that path, so retrieval and file-writing follow automatically.

Moving to a shared GPU (vLLM) — change two values, no code changes:

"env": {
  "LLM_BASE_URL": "http://gpu-server.internal:8000/v1",
  "LLM_MODEL": "Qwen/Qwen2.5-Coder-32B-Instruct"
}

Manual MCP registration

If you'd rather not use setup.sh, register the built server yourself:

claude mcp add devmate \
  -e LLM_BASE_URL=http://localhost:11434/v1 \
  -e LLM_MODEL=codestral:22b \
  -e APPLY_MODEL=hf.co/QuantFactory/FastApply-7B-v1.0-GGUF:Q4_K_M \
  -e REPO_ROOT=/path/to/your-repo \
  -e CCC_BIN=$HOME/.local/bin/ccc \
  -- node /path/to/devmate/dist/index.js

(You still need cocoindex installed and the repo indexed, and both models pulled (ollama pull codestral:22b and the apply model) — see the steps in setup.sh.)

Project structure

src/
├── index.ts      # MCP server: develop / review / explain / search (+ verify loop)
├── retrieval.ts  # cocoindex multi-pass retrieval + language-agnostic re-rank
├── grounding.ts  # grounding guards (abort/warn when no repo context)
├── writer.ts     # parses FILE/EDIT blocks, merges sketches, write guards, revert
├── verify.ts     # runs VERIFY_CMD after a write (drives the retry loop)
├── editor.ts     # opens created/edited files in the editor
├── llm.ts        # OpenAI-compatible clients: reasoning (complete) + apply (applyMerge)
├── config.ts     # env-based configuration
└── prompts.ts    # system prompts per tool
templates/        # cocoindex settings template applied to target repos
scripts/          # settings patcher + manual test harness
setup.sh          # one-command, idempotent setup / add-a-repo
dist/             # compiled JS (npm run build)
eval/             # retrieval + model evaluation harness and scorecards

About

No description, website, or topics provided.

Resources

Contributing

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages