SDK / infra · #81 trending MCP repo
Jcodemunch MCP
jgravelle/jcodemunch-mcp
Symbol-level code retrieval for AI agents: fetch the function you need, not the whole file. Runs locally. 94.5% fewer tokens per lookup on average than grep-and-read on our 15-lookup benchmark. Works with Claude Code, Cursor, Codex and any MCP client. Free for non-commercial use; commercial use needs a one-time license.
- Stars
- 2.8k
- This week
- —
- Forks
- 373
- Open issues
- 4
- Skills inside
- 11
Inside this repo
11 skills
.claude/skills/benchmark-methodologychangelog-formatThe shape of a CHANGELOG.md entry and heading in this repo. Load before writing an [Unreleased] line or cutting a release block..claude/skills/changelog-formatclaude-md-budgetHow to keep CLAUDE.md under its character Floor without deleting a rule: measure sections first, rotate by derivability, two edits per rotation. Load in /release step 6 and before any CLAUDE.md rotation or split..claude/skills/claude-md-budgetmechanism-not-instanceThe two questions that separate a fix for the reported spelling from a fix for the property. Load in /fix-issue steps 4-5 and in review of any fix..claude/skills/mechanism-not-instanceobservatoryContext for the jcodemunch-observatory weekly scorecard — what it tracks, the Monday 06:00 UTC cron, why scores must be pulled live rather than transcribed, the NestJS grade story, and the workflow's version dispatch input. Load before quoting, interpreting, or editing observatory scores or config..claude/skills/observatorypr-descriptionThe PR title and body template, and the rules for any comment drafted for a reporter or contributor. Load when writing a PR body, a release PR, or a triage response..claude/skills/pr-descriptionreleasePublishing a jMunch release (jcodemunch-mcp, jdocmunch-mcp, jdatamunch-mcp, jragmunch-cli), reviewing/merging/closing PRs, and responding to the community. Load before any version bump, PyPI upload, tag, GitHub release, MCP registry publish, or PR merge..claude/skills/releasestandard-axesThe criterion numbers of STANDARD.md, so an acceptance criterion can be mapped to one. Load in /feature step 2..claude/skills/standard-axestool-surface-disciplineThe small-front-door principle and what counts as a tool-surface change. Load in /feature step 3, in review, and before editing any tool name, argument, description or tier..claude/skills/tool-surface-disciplineversion-schemeHow the next version number is derived and what a bump touches. Load in /release step 2 or before any version edit..claude/skills/version-schemejcodemunchWhen to use jCodemunch MCP tools for symbol-level code navigation and when the built-in tools are the cheaper route. Loads on demand; complements the always-on policy block.plugin/jcodemunch/skills/jcodemunchDocumentation
README
jCodeMunch MCP
An MCP server that retrieves source code by symbol, not by file, using tree-sitter AST parsing. It uses 94.5% fewer tokens per lookup on average than grep-and-read on our 15-lookup benchmark (86.9% to 98.7% across the lookups, at pinned commits), so your agent stops spending its context window on whole files.
Benchmark: 5 queries on each of express, fastapi and gin at pinned commits, tokens counted with tiktoken cl100k_base, jcodemunch-mcp at commit 15afcf75, whose version string is 1.108.391 but which also carries the settings-file ranking change released in 1.108.392 and the field/constant change released after it. A lookup is one search_symbols plus get_symbol_source on its top 3 hits, against grep-and-read (rank files by match count, read the top 3 whole). Per lookup, not per session. Reproduce with benchmarks/REPRODUCING.md.
Real results from production, as of 2026-08-17 838B+ tokens saved · 136,000+ reporting installs · $4.2M+ in AI spend avoided · 100,000+ kg CO₂ prevented Estimated counter figures as of 2026-08-17, not live, valued at the $5/MTok Claude Opus input rate. All four only grow, so read them as floors. Live at jcodemunch.com.
Works with Claude Code, Cursor, VS Code, Codex CLI, Windsurf, Continue, and any MCP-compatible client.
Install now · Quickstart · See the evidence · Pricing
Free for personal use. Use it to make money, and Uncle J. gets a taste. Fair enough? Commercial licenses below. Our guarantee: if jCodeMunch doesn't pay for itself, you don't pay for jCodeMunch.
Small by default. A new install starts on a six-tool front door: menu, order and route do the work, and jcodemunch_guide, announce_model and set_tool_tier help. The full tool set sits behind it, and jcodemunch-mcp surface shows exactly what your install advertises.
Why jCodeMunch?
Most AI agents explore repositories the expensive way: open entire files, skim thousands of irrelevant lines, repeat. That is not "a little inefficient." That is a token incinerator.
jCodeMunch indexes a codebase once and lets agents retrieve only the exact code they need: functions, classes, methods, constants, outlines, and tightly scoped context bundles, with byte-level precision. It parses source with tree-sitter, stores structured symbol metadata (signature, kind, qualified name, summary, byte offsets) alongside raw file content in a local index, and fetches exact implementations on demand instead of re-reading files over and over.
| Task | Traditional approach | With jCodeMunch |
|---|---|---|
| Find a function | Open and scan large files | Search symbol, fetch exact implementation |
| Understand a module | Read broad file regions | Pull only relevant symbols and imports |
| Explore repo structure | Traverse file after file | Query outlines, trees, and targeted bundles |
| "What breaks if I change X?" | Search for the name, then read each hit | get_blast_radius: affected files and symbols, across indexed repos, with no IDE running |
Index once. Query cheaply. Keep moving. Precision context beats brute-force context.
Evidence
Reproducible token efficiency benchmark
Measured with tiktoken cl100k_base across three public repos pinned to upstream commits, run 2026-10-22 on v1.108.391 (at commit 15afcf75, whose version string is 1.108.391 but which also carries the settings-file ranking change released in 1.108.392 and the field/constant change released after it). Workflow: search_symbols (top 5) + get_symbol_source × 3 per query. Two baselines, same run, same corpus, same file reader:
- Grep-top-3:
rg -lthe query terms, rank files by match count, open the top 3 whole. This is what a competent agent without the tool actually does, and it is the number to quote. - Read-all: every indexed source file concatenated. A ceiling nobody pays; retained for continuity with previously published figures.
| Repository | Files | Symbols | Grep-top-3 baseline | jCodeMunch | vs grep | vs read-all |
|---|---|---|---|---|---|---|
| expressjs/express | 186 | 989 | 15,724 avg | 990 avg | 15.9x | 156.1x |
| fastapi/fastapi | 1,186 | 13,699 | 85,296 avg | 2,556 avg | 33.4x | 322.9x |
| gin-gonic/gin | 98 | 1,822 | 31,975 avg | 1,481 avg | 21.6x | 102.5x |
| Grand total, pooled (15 task-runs) | 664,975 | 25,132 | 26.5x | 225.2x |
Against a grep-and-read agent: 94.5% fewer tokens per lookup on average. No single multiple describes every query; the per-repo rows above are the spread. Against read-all the figure is 99.6%, but nobody pays that ceiling. Compact MUNCH wire encoding then trims a median 45.5% more bytes off responses.
Full methodology, pinned commits, harness, and known caveats: benchmarks/METHODOLOGY.md · Reproduce it yourself · TOKEN_SAVINGS.md
Independent A/B test on a production codebase
50-iteration A/B test on a real Vue 3 + Firebase production codebase, jCodeMunch vs native tools (Grep/Glob/Read), Claude Sonnet 4.6, fresh session per iteration: success rate 80% vs 72%, timeout rate 32% vs 40%, mean cache creation down 10.5%. Tool-layer savings isolated from fixed overhead: 15-25%. One finding category appeared exclusively in the jCodeMunch variant: orphaned file detection via find_importers, a structural query native tools cannot answer without scripting. Full report: benchmarks/ab-test-naming-audit-2026-03-18.md
Mentioned by
- Artur Skowroński (VirtusLab): "roughly 80% fewer tokens, or 5× more efficient — index once, query cheaply forever" · GitHub All-Stars #15
- Traci Lim (AWS · ASEAN AI Lead): "structural queries that native tools can't answer: find_importers, get_blast_radius, get_class_hierarchy, find_dead_code" · 5 Repos That Save Token Usage in Claude Code
- Julian Horsey (Geeky Gadgets): "3,850 tokens reduced to just 700 — a 5.5× improvement" · JCodeMunch AI Token Saver
- Eric Grill: "context is the scarce resource. Cut it by 90% and the whole stack gets cheaper and more reliable" · jCodemunch: Context Engine for AI Agents
Install
One-click installs
Recommended: one command
uv tool install jcodemunch-mcp
jcodemunch-mcp init
No virtualenv to manage, nothing written into system Python, and it works as-is on PEP 668 distros (Ubuntu 24.04+, Debian 12+) where bare pip install is refused. Don't have uv yet?
init auto-detects your MCP clients (Claude Code, Claude Desktop, Cursor, Windsurf, Continue, Codex, opencode, Gemini CLI, Cline, VS Code with Copilot), writes their config entries, installs the hooks that keep the index fresh without adding anything to the model's context (re-index after an edit, a pre-compaction checkpoint, a task-complete note to you), optionally indexes your project, and audits your agent config files for token waste. Two extras are opt-in because the model reads them on every turn they apply: --policy writes the Code Exploration Policy into CLAUDE.md, AGENTS.md and the Cursor and Windsurf rules files, and --guidance adds the hooks that advise the model on Read/Grep/Glob/Bash, brief subagents and restore context after compaction. With the PreToolUse hook installed (--guidance or --strict) and JCODEMUNCH_HOOK_GREP_ANSWER=1, a large Grep inside an indexed repo is answered from the index once: the hook refuses it with every match counted as the reason (by file and by function or class, with less detail for a very large set; the lines themselves are not included; the answer says it came from the index, how many lines in how many files match the pattern case-insensitively, and that JCODEMUNCH_HOOK_GREP_ANSWER=0 turns it off), and the same Grep sent again runs normally. A Grep under the size thresholds (JCODEMUNCH_HOOK_GREP_ANSWER_MIN_LINES, JCODEMUNCH_HOOK_GREP_ANSWER_MIN_FILES) runs untouched, and so does any Grep on an index the file cap cut short. It is off by default. An install that already has them keeps them; jcodemunch-mcp init --remove-guidance removes them, with backups.
Ask for it by name. Tell your agent to use jcodemunch ("use jcodemunch to find where X is handled"). In the sessions we measured, agents used it when the user asked for it by name.
Other install paths
| Command | Use it when |
|---|---|
uvx jcodemunch-mcp |
Zero install. Runs from an ephemeral environment — nothing lands on disk permanently. The client entries init writes already invoke the server this way, so for most setups this is all that ever runs. ⚠ Enforcement hooks are the exception: they're spawned by a minimal-PATH subshell and resolve the executable by name, so they need uv tool install (or pipx/pip) to work. |
pipx install jcodemunch-mcp |
You already standardise on pipx |
pip install jcodemunch-mcp |
Inside a virtualenv you manage yourself |
Verify:
jcodemunch-mcp --version
Manual Claude Code setup
claude mcp add -s user jcodemunch -- uvx jcodemunch-mcp
No install step — uvx fetches and runs the server on demand. Prefer it on your PATH (and required for enforcement hooks)? uv tool install jcodemunch-mcp, then claude mcp add -s user jcodemunch jcodemunch-mcp.
Then tell the agent to prefer the tools. This matters more than people think; installation makes the tools available but does not break the agent's brute-reading habit. One line in your CLAUDE.md does it:
Call the jcodemunch_guide tool and strictly follow its instructions.
Using Cursor, Windsurf, Codex CLI, JetBrains AI Assistant, Junie, Antigravity, Gemini CLI, Qwen Code, Kiro, Cline, Zed, Goose, Hermes, Odysseus, or Paperclip? Every tested client configuration lives in CLIENTS.md, along with fewer approval prompts, a committed .mcp.json for your team and a shared HTTP server. Optional extras (local semantic search, AI summaries per provider) are in QUICKSTART.md; the system surfaces each extra pulls in are documented in SECURITY.md.
Quickstart
Full walkthrough: QUICKSTART.md. The two-minute version, inside your agent after init:
- Ask: "Index this repo with jcodemunch."
- Ask: "Using jcodemunch, find the function that handles authentication and show me its source."
The agent should answer via search_symbols and get_symbol_source, returning tens of lines instead of whole files. Confirm with get_session_stats: it reports tokens served and savings for the session. That is where the numbers on the meter come from.
Want to skip initial indexing for popular frameworks? Pre-built starter packs: jcodemunch-mcp install-pack --list (free packs need no license).
See it on Express (free)
- Install and set up your client:
uv tool install jcodemunch-mcp, thenjcodemunch-mcp init - Load the free starter pack Node.js Essentials (Node, Express, Fastify, Koa):
jcodemunch-mcp install-pack nodejs. Free packs need no license. - Ask your agent: "Using jCodeMunch, find where Express registers a route handler and show me that function."
What that lookup costs, from our benchmark on Express at commit 1faf2289, counted with cl100k:
| Tokens | |
|---|---|
Grep-and-read: search router route handler, open the top 3 matching files whole |
9,890 |
| jCodeMunch: one symbol search, then the source of the top 3 matches | 1,074 |
That's one of the 15 lookups in the benchmark (5 each on express, fastapi and gin at pinned commits). jCodeMunch used 94.5% fewer tokens per lookup on average than grep-and-read on our 15-lookup benchmark. The pack is built from Express 4.x, while the benchmark pins commit 1faf2289 on upstream main, so your count can differ. To rerun the benchmark at the pinned commits, follow benchmarks/REPRODUCING.md; raw data is in benchmarks/.
What you can do
- Retrieve one symbol instead of loading a file.
get_symbol_sourcereturns the exact function body, byte-precise, for the majority of edits that touch one function in a 700-line file (~95% savings on that read). A class comes back as an outline, each method collapsed to its signature; passclass_body="full"for the whole body. - Assemble a whole task's context in one call.
assemble_task_contextclassifies the task intent, extracts anchor symbols, and runs the right tool sequence under one token budget.plan_turnroutes the turn before the first read. - Ask structural questions grep can't answer.
find_importers,get_blast_radius,get_call_hierarchy,find_dead_code,get_changed_symbols,get_hotspots,search_astanti-pattern sweeps, and more. Two of them sound alike and are not:check_referencesanswers where a name is used (import sites plus every file whose content mentions it),find_referencesanswers who imports it, over the import graph alone, so a call site is invisible to it.get_call_hierarchysays which callers are direct: a deeper row names the caller it is reached from. - Preflight risky changes, and know when to stop.
check_edit_safe,check_delete_safe,get_pr_risk_profile, andplan_refactoringwith edit-ready{old_text, new_text}blocks. The two safety checks returnstop_rule.terminal: true means no further jcodemunch call moves the verdict, so re-runningfind_importersorcheck_referencesto be sure is wasted work. It means final, not safe.corpus_inadequate(the index could not back an absence claim) anddynamic_import_boundary(a dynamic import, or for a .NET control or build item a path the index does not carry, can load the file) are never terminal, and each tool's description lists every verdict it returns.check_rename_safeanswerssafe: nullrather thantruewhen the import graph could not reach the symbol's file, so the files that use it were never checked, andget_pr_risk_profileanswersrisk_score: nullwithunmeasurable_axeswhen it could not measure the blast axis; a CI gate should fail on null. Hand the server your type checker's own output (jcodemunch-mcp import-trace --diagnostics <file>:mypy --output json,pyright --outputjson,tsc --pretty false,ruff --output-format json) andcheck_edit_safe,get_changed_symbols,get_pr_risk_profileandget_symbol_provenancesay which symbols the checker already flags, as of which commit. Nothing runs a checker for you. False names the specific thing that would change the answer. - Trust the answers. Calibrated confidence scores, freshness flags, coverage contracts on absence claims, compiler-verified references via SCIP import, and automatic secret redaction before anything reaches the LLM.
- Keep the index fresh automatically. Watch modes, agent hooks, and a VS Code extension close the staleness gap.
That's the highlight reel. The complete tour of the full tool set (90+ tools behind the six-tool front door), the MUNCH compact wire format, evidence receipts, offloadable-work annotation, and the session-economics instrumentation is in CAPABILITIES.md, with internals in UNDER_THE_HOOD.md.
What's new
- v1.108.400 (2026-10-27) — a text search returns the code it found, and a retired tool name says what replaced it
- v1.108.399 (2026-10-26) — four core tool descriptions open with the question each tool answers
- v1.108.398 (2026-10-25) — the semantic and all extras install a fixed filelock on every Python
- v1.108.397 (2026-10-24) — a cut search names the files it left off, and file_pattern takes braces
When does it help (and when doesn't it)?
| Scenario | Native tool | jCodeMunch | Savings |
|---|---|---|---|
| Edit one function (700-line file) | Read → 700 lines |
get_symbol_source → 30 lines |
~95% |
| Understand a file's structure | Read → full content |
get_file_outline → names + signatures |
~80% |
| Find which file to edit | Grep many files |
search_symbols → exact match |
comparable |
| Edit requires whole-file context | Read → full content |
get_file_content → full content |
~0% |
| "What breaks if I change X?" | Grep the name, Read each hit |
get_blast_radius → affected files and symbols |
not measured |
It helps most on targeted edits (one function, one method, one class), which is the majority of real editing work. Edits that genuinely require the entire file (restructuring file-level state, reordering logic spanning hundreds of lines) see no advantage. Best fits: large repositories, unfamiliar codebases, agent-driven exploration, refactoring and impact analysis, and teams cutting AI token costs without making agents dumber.
Languages: 70+ via tree-sitter, including Python, JavaScript/TypeScript, Go, Rust, Java, C/C++, C#, PHP, Ruby, Swift, and Kotlin. Full matrix: LANGUAGE_SUPPORT.md. Monorepos: yes; incremental indexing, workspace-member detection, subpath scoping.
Deferring the tool schemas (Anthropic tool search)
If you reach jCodeMunch through the MCP connector on a model that supports tool search, you can keep our schemas out of your context prefix entirely and let Claude load only the two or three tools a request needs. You do not set defer_loading per tool — set it once for the whole server:
{
"mcp_servers": [
{ "type": "url", "url": "https://your-host/mcp", "name": "jcodemunch" }
],
"tools": [
{ "type": "tool_search_tool_bm25_20251119", "name": "tool_search_tool_bm25" },
{
"type": "mcp_toolset",
"mcp_server_name": "jcodemunch",
"default_config": { "defer_loading": true },
"configs": {
"resolve_repo": { "defer_loading": false },
"search_symbols": { "defer_loading": false },
"get_ranked_context": { "defer_loading": false }
}
}
]
}
Send it with the beta header mcp-client-2025-11-20. Both halves are required — mcp_servers alone is a validation error, and so is mcp_toolset without the matching mcp_server_name.
⚠ The MCP connector takes a URL, so this applies to jCodeMunch served over sse or streamable-http (jcodemunch-mcp serve --transport streamable-http), not to the default local stdio setup. On stdio, whether schemas are deferred is up to your client, and tool_surface: "counter" below is the lever you control.
The configs block above follows Anthropic's own advice — keep your 3–5 most-used tools resident so common requests skip the search round trip — and per-tool configs overrides default_config.
A deferred tool is found by searching its name and description, so the core descriptions open with the question each tool answers, in the words an agent uses: search_symbols "find where a function, class or method is defined", get_symbol_source "read or show the source code", get_call_hierarchy "who calls this function or method", check_references "where is a function, class or other identifier used". The analysis tools follow the same rule: check_delete_safe opens "is it safe to delete this function", get_pr_risk_profile "how risky is this pull request", get_hotspots "where is the riskiest code".
Deferred definitions are excluded from the system-prompt prefix and appended inline as tool_reference blocks when Claude discovers them, so prompt caching is preserved — this is not the cache-invalidating kind of dynamic tool list. At least one tool in the request must stay non-deferred, or the API returns a 400.
⚠ This is a different mechanism from our own tool_surface: "counter", and you do not need both. Tool search is host-side and works across every MCP server you have connected; the Counter is server-side, works on any host including ones with no tool-search support, and is what init configures on a first-ever install. Pick whichever your host supports — see CONFIGURATION.md for the Counter and jcodemunch-mcp surface for what your install actually advertises.
Custom subagents
A Claude Code subagent gets the session's MCP tools unless its definition has a tools: list. If yours does, the subagent can call only what that list names, so add the jcodemunch tools you want:
---
name: code-explorer
description: Finds where code lives and what a change reaches.
tools: Read, Grep, Glob, mcp__jcodemunch__route, mcp__jcodemunch__menu, mcp__jcodemunch__order
---
Those three are the front door on the counter surface, which init sets on a first-ever install. On the full surface, name the tools themselves, for example mcp__jcodemunch__search_symbols. The first line of jcodemunch-mcp surface names the active surface. The mcp__jcodemunch__ prefix assumes the server is registered as jcodemunch, the name init writes; a server registered under another name gets that name in the prefix.
Privacy Policy
jCodeMunch runs on your machine. Your code, file paths and queries stay there: the index lives in ~/.code-index/, and deleting that folder removes it.
The one thing the server sends by default is an anonymous savings counter: a random ID, the tokens saved since the last send, and a lifetime total. It sends no code, no paths and no queries. Turn it off with "share_savings": false in ~/.code-index/config.jsonc or JCODEMUNCH_SHARE_SAVINGS=0. The Claude Code plugin turns it off for you.
Anything else that reaches the network is something you run or turn on yourself, and each is listed in Security, privacy, and background behavior. Full policy: https://jcodemunch.com/privacy.php
Security, privacy, and background behavior
An install that never runs init (a uvx or plugin install) gets one license_notice line in its first tool answer, once per machine; it is skipped with a license key configured, after jcodemunch-mcp config set license_reminder false, after an init that printed the license line, on CI or remote runners (CI=true, CLAUDE_CODE_REMOTE=true), or with JCODEMUNCH_LICENSE_NOTICE=0. Its link carries a fixed source tag, utm_medium=notice.
A short work-license reminder follows, 7 days after a machine's first index and then at most every 30 days: on stderr after a CLI command a person runs (only at a terminal, never with --json), and as license_notice on the first tool answer of a server process when due. Its state is ~/.code-index/license_reminder_state.json (three fields: first index seen, last shown, count). It is never shown with a license key configured, on CI or remote runners, or after jcodemunch-mcp config set license_reminder false; JCODEMUNCH_LICENSE_REMINDER=0 also silences it. Nothing is sent. Its buy link carries a fixed source tag (utm_medium=reminder, or utm_medium=tool in a tool answer), the same on every machine, which reaches the site only if the link is opened.
The text report of jcodemunch-mcp receipt ends with one license line on a machine with no license key, tagged utm_medium=receipt. It has no clock and writes no state; every switch that silences the reminder silences it, and --export and --explain never carry it.
The short version is the Privacy Policy above. Local-first by design: indexes live at ~/.code-index/, and the base package's only default network behavior is an anonymous savings counter (random ID plus aggregate token counts, no code, no paths, no PII; opt out with share_savings: false). Everything the server does beyond answering a tool call (file watching, the opt-in login service, license validation, model downloads, org reporting) is opt-in or opt-out, visible, and reversible, and every item is enumerated in SECURITY.md alongside the path-traversal, symlink, and secret-redaction controls. A stdio server also stops on its own when the client process that started it is gone, even if its stdin pipe stays open (JCODEMUNCH_PARENT_WATCH_SECONDS=0 turns that off). A default init writes no policy file and installs no hook whose output the model reads; those are init --policy and init --guidance, and init --remove-guidance takes them back out of an older install. init --git-hook adds a git post-checkout hook that re-indexes the files a branch switch changed, in an already indexed repository; uninstall run in that repository removes it.
Grammar pack override (#608). The dependency tree-sitter-language-pack is pinned <1.0.0 because the 0.x wheels bundle every grammar and parsing stays local. F# is the one exception: it is parsed by the pinned tree-sitter-fsharp wheel, which also compiles its grammar in, so F# parsing stays local on either pack (#848). You can override it with pip install -U tree-sitter-language-pack after installing; nothing in the code refuses it. What you accept, measured against 1.17.0 on 2026-09-11: the 1.x pack ships no grammars and fetches each one over the network into its cache directory (measured on Windows: %LOCALAPPDATA%\tree-sitter-language-pack\v<version>\libs; jcodemunch-mcp install-status prints the path on any platform) the first time a language is parsed, so an airgapped install parses nothing, and the nim grammar changed upstream, so nim files yield no symbols (the manifest also lacks autohotkey, ejs and verse, which costs nothing here: those three are parsed by jCodeMunch's own extractors, not by tree-sitter). An install on a 1.x pack says so: every index_folder result carries a grammar_pack block and a warning naming the version, the cache directory and each language whose grammar failed, and jcodemunch-mcp install-status prints the same. Dropping the pin is a separate decision that needs the offline story first.
Per-project configuration
Most settings live in the global ~/.code-index/config.jsonc, but any of them can be overridden for a single repository by dropping a .jcodemunch.jsonc at its root. It is an overlay: keys it declares win, keys it omits fall through to global and then to the built-in default, so it only needs to contain what differs.
// <your-repo>/.jcodemunch.jsonc
{
"max_file_size": 1048576,
"languages": ["python", "typescript", "racket"]
}
Declaring Racket defining forms
Racket projects routinely define their own defining forms with define-syntax, and a static parser cannot know what those bind — (defstep (check-admin) ...) is indistinguishable from a function call. Declaring them makes their bindings searchable:
{
"racket_definition_forms": {
"defstep": "function",
"defstudy": "constant",
"defvar": "constant",
"define-schema": "class"
}
}
Each entry maps a form name to what it binds: function, constant, class or type. Where the name sits is read from the source rather than declared — (defstep (check-admin) ...) takes the head of the parameter list, (defstudy consent ...) takes the bare symbol — so a form that appears in both shapes works either way.
⚠ This is an assertion, not something jCodeMunch can verify. A wrong declaration puts a name in the index that Racket does not actually bind. Declarations are also matched only after every built-in form, so declaring define or struct has no effect — the built-in handling wins.
Declaring what a Racket #lang looks like
A #lang line names a reader, and jCodeMunch's Racket parser reads S-expressions. The distribution's langs are built in (racket/*, typed/racket*, s-exp, info, at-exp …, and the document langs scribble/*, pollen, punct, markdown …), but a project's own lang is unknown to it and is treated as a document — no symbols, still text-searchable — until you say what its syntax is:
{
"racket_langs": {
"conscript": "at-exp",
"mylang": "sexp"
}
}
sexp is plain S-expressions; at-exp is at-exp text bodies over Racket (read with @ as the command character, exactly as #lang at-exp reads them, so prose containing ; " # or | is prose); text is a document language that is never walked. A key also covers its sub-langs (conscript matches conscript/with-require), and a project may demote a lang as well as promote one. An at-exp lang whose reader uses another command character declares it with the object form — "mylang": {"tier": "at-exp", "command_char": "◊"} — the way Racket's make-at-readtable takes #:command-char.
Both keys change what the parser emits for unchanged files, so a change to either is stamped on the index and forces one full re-parse on the next index (rebuild_reason: "racket_config_changed"); you do not need to touch the files or clear the index. An index holding Racket files that was built before this stamp existed re-parses once the same way (rebuild_reason: "racket_index_predates_gate").
Documentation
| Doc | What it covers |
|---|---|
| QUICKSTART.md | Zero-to-indexed in three steps |
| CLIENTS.md | Tested configuration for every MCP client |
| USER_GUIDE.md | Full tool reference, workflows, and best practices |
| CAPABILITIES.md | The complete capability reference beyond the highlight reel |
| CONFIGURATION.md |
…
Releases
Recent versions
v1.108.422v1.108.422 — the shared parse cache never serves what an older parser emittedv1.108.421v1.108.421 — a starter pack installs in a few megabytes, and a file tree costs a third of the charactersv1.108.420v1.108.420 — re-indexing one file by path keeps a partial index marked partialv1.108.419v1.108.419 — the file cap limits what one call parses, not what the index keepsv1.108.418v1.108.418 — a search on a capped index says, in its answer, that the index is partialv1.108.417v1.108.417 — a wrong call through order names a call that works