Command Palette

Search for a command to run...

UnylyUnyly
Browse all

Nonna

FreeNot checked

Stop your agent from reinventing the standard library. Example-based structural code search — reuse-before-write via MCP and LSP.

GitHubEmbed

About

Stop your agent from reinventing the standard library. Example-based structural code search — reuse-before-write via MCP and LSP.

README

👵🏻

Stop your agent from reinventing the standard library.

nonna is a structural code-similarity engine for coding agents, built on Opengrep's IL. It hashes each function's resolved control/data-flow graph into a feature set and scores pairs with weighted Jaccard and asymmetric containment. Matching is rename-invariant: variable names, field names, literals and concrete types are ignored by default — two functions match if they compute the same way.

The primary loop is reuse-before-write: an agent drafts a function, asks find_similar, and learns "this already exists in dep X — call it instead", across the workspace, all transitive cargo deps, and std.

Design, decisions and evaluation: DESIGN.md. Looking for v1 (the Python slop detector with the WASM demo)? → nonna-v1.

🏗️ Build

ci

Linux and macOS (on Windows, use WSL — the engine's build is Unix-only). Requires an OCaml 5.3.0 opam switch and bash ≥ 5. From the repo root:

git submodule update --init --recursive   # vendor/opengrep + its grammars
export PATH=/opt/homebrew/bin:$PATH
eval $(opam env --switch=opengrep-5.3.0 --set-switch)
. vendor/opengrep/libs/ocaml-tree-sitter-core/tree-sitter-config.sh
dune build nonna

Binary: _build/default/nonna/cli/main.exe (aliased as nonna below). First build compiles the vendored engine (one-time). Gotcha roundup: the tree-sitter env script is mandatory (C stubs fail without it), and any binary embedding the parser must call Parsing_init.init () (ours do).

🔪 CLI

nonna query <corpus...> -- <draft.rs>      # find fns similar to each fn in draft
nonna dupes <dir> [-t 0.5]                 # intra-corpus clone pairs
#   filters: --metric max|jaccard, --name SUB, --include/--exclude SUB,..,
#            --min-lines/--min-features N, -n LIMIT
nonna features <file>                      # debug: per-fn feature dump
nonna graph <file> --fn NAME [-o DIR]      # DOT per propagation round (+ source)
nonna dump-il <file> [--fn NAME]           # compact IL CFG
nonna corpus <root>                        # cargo deps + std discovery / cache

# benchmarking
nonna mine <paths...> [-o pairs.tsv]       # mine ground-truth pairs (token-level)
nonna eval <pairs.tsv> [-o scores.tsv]     # pairwise recall/FPR
nonna rank <pairs.tsv> <corpus...>         # MRR / recall@k through the pipeline

# servers
nonna lsp                                  # stdio LSP (diagnostics, find-similar)
nonna mcp [root]                           # stdio MCP (per-session)
nonna serve [root] [-p 8976]               # HTTP MCP + duplication explorer UI

# global flags: --profile structural|full, --iters N, --with ch1,ch2

🤖 Agent integration (MCP)

# per-session (cold index each start):
claude mcp add nonna -- /path/to/main.exe mcp /path/to/workspace
# or: one warm daemon shared by all sessions
/path/to/main.exe serve /path/to/workspace &
claude mcp add --transport http nonna http://127.0.0.1:8976/mcp

Tools: find_similar (drafted code → ranked existing fns with source), query_similar (file + line|name), diff_functions (A∩B scores + per-side unique regions by source line — for a bug/fix pair, A−B ≈ bug, B−A ≈ fix), find_duplicates (workspace clone pairs, no query fn — the dedup/refactor view, with threshold/metric/name/include-exclude-path/size filters), status. The server's instructions explain score semantics to the agent (jaccard ≈ 1: same up to renaming; containment ≈ 1: "it does everything yours does, plus more").

The corpus root is indexed at startup (workspace first, then cargo deps + std from per-crate@version caches under ~/.cache/nonna/sigdb — first dep index ~1 min, warm loads < 0.5 s). Check status before trusting empty results.

nonna serve also hosts the duplication explorer at http://127.0.0.1:8976/: all similar pairs in the corpus with a threshold slider, name/file/min-size filters, and a keyboard-navigable side-by-side function diff — both a dedup navigator and a way to eyeball how the engine scores real code.

🧑‍💻 Editor integration (VSCode)

editor/vscode-nonna/ — diagnostics on open/save ("avg is similar to mean (util.rs:1) — jaccard 1.00"), expandable related locations in the Problems panel, lightbulb actions (function-body diff / open-to-the-side), and a "nonna: Find Similar Functions" palette command. Setup: see its README; short version: npm install there, symlink the folder into ~/.vscode/extensions/nonna-dev.nonna-0.0.1, set nonna.serverPath.

🧪 Tests & benchmarks

bash tests/run.sh            # core regressions (fixtures)
bash tests/sanity.sh         # 16 invariant assertions across Rust/Python/JS/Go
bash tests/lsp-smoke.sh      # LSP protocol session
bash tests/mcp-smoke.sh      # MCP stdio + HTTP session (incl. diff algebra)
bash tests/mine-registry.sh  # mine + evaluate against your local cargo registry
bash tests/sweep.sh bench-out/paths.txt   # hyperparameter sweep (MRR/recall@k)
uv run tests/llm_judge.py --pairs ... --scores ...   # LLM-judged pair quality

Current headline numbers (rank MRR through the full pipeline; defaults are tuned per language and need no flags):

benchmark ALL exact renamed evolved MRR / r@5
Rust (crates, 56k units) 0.963 1.000 0.987 0.766 / 0.859
Python (PyPI, 17k units) 0.970 1.000 0.986 0.950 / 0.986
C (Linux v6.10↔v6.16, 103k units) 0.918 1.000 1.000 0.888 / 0.944

"evolved" = the same function edited between two real releases — the hard kind. Full tables, per-language configs, and caveats in DESIGN.md.

📜 License

nonna's code is MIT. The vendored engine (vendor/opengrep, a git submodule — not distributed by this repo) is LGPL-2.1; binaries built from this repo statically link it, and LGPL §6 is satisfied by this repository's public source and build instructions (you can relink against a modified engine). Note: some engine source headers mention a linking exception that the engine's LICENSE file does not actually contain — we conservatively assume plain LGPL-2.1.

🍝 Disclaimer

Vibecoded with love.

from github.com/thebabush/nonna

Installing Nonna

This server has no published package — it is built from source. Open the repository and follow its README.

▸ github.com/thebabush/nonna

FAQ

Is Nonna MCP free?

Yes, Nonna MCP is free — one-click install via Unyly at no cost.

Does Nonna need an API key?

No, Nonna runs without API keys or environment variables.

Is Nonna hosted or self-hosted?

Self-hosted: the server runs locally on your machine via the install command above.

How do I install Nonna in Claude Desktop, Claude Code or Cursor?

Open Nonna on unyly.org, pick your client tab (Claude Desktop, Claude Code, Cursor) and press Install — the config is generated automatically, no JSON editing.

Related MCPs

Compare Nonna with

Not sure what to pick?

Find your stack in 60 seconds

Author?

Embed badge for your README

Browse similar

All development MCPs