efficient-token
v1.1.0
Published
Local-first MCP server that returns distilled, faithful code context to cut LLM token usage without degrading reasoning.
Maintainers
Readme
efficient-token
A local-first MCP server that cuts LLM token usage without degrading reasoning.
It does deterministic code work on your machine and returns only distilled, faithful results to the model: real slices, real symbols, a fraction of the tokens.
Install · Verify · Guide the model · Tools · Measure savings
The idea
One principle: anything the model will reason over (source code, document text) is returned losslessly as real slices and real symbols. Savings come from returning less (one symbol instead of a whole file), never from summarizing. The server detects and transforms deterministically; it never makes a judgment the model should make.
For example, to see one function in a 200-line file:
| | Built-in Read | efficient-token code_read |
| ------------ | ----------------------- | ------------------------------------------ |
| Call | Read(file) | code_read(file, symbol) |
| Returns | the whole 200-line file | just that function's real source |
| Tokens | ~2,400 | ~400 |
| Fidelity | full | identical, real source, not a summary |
Same reasoning material, a fraction of the context. Multiply that across a session and the savings compound.
Contents
- What you get
- Requirements
- Install
- Verify it works
- Make the model prefer these tools
- Usage
- Measuring token savings
- Configuration
- Tools
- Language support
- Architecture
- Open-core / premium
- Development
- Contributing & security
- License
What you get
| | |
| --- | --- |
| 47 tools | Reading, searching, git review, editing, and creative/design work. Each returns the real content the model needs, just less of it. |
| Familiar file tools | code_read, code_edit, code_write, code_search, and glob use Claude-compatible Read / Edit / Write / Grep / Glob inputs while remaining standard MCP tools for Codex and other hosts. |
| Measurable | health shows tokens saved this session; npm run toolcost measures the serialized MCP tool records and enforces their CI budget. |
| Safe by construction | Tool-supplied workspace paths stay inside the workspace root with symlink and ADS defenses. File replacements are atomic, edits are syntax-guarded, and runner tools execute captured commands from a validated package.json snapshot. Project scripts retain their normal OS capabilities. |
| Broad language support | tree-sitter via WASM, with no native build step. |
Requirements
- Node.js ≥ 18. ESM and WASM tree-sitter need no native build step. Node 22 or 24 LTS is recommended for production. Node 18 and 20 remain compatibility lanes for this backward-compatible release.
- A local stdio MCP host. Codex and Claude Code are documented below; any standards-compliant stdio host can run the server.
Install
With Codex
For consistent behavior in Codex CLI, the IDE extension, and the desktop app,
create a project-local .codex/config.toml with an explicit absolute root:
[mcp_servers.efficient-token]
command = "npx"
args = ["-y", "efficient-token"]
cwd = "/abs/path/to/project"
tool_timeout_sec = 300
default_tools_approval_mode = "writes"
[mcp_servers.efficient-token.env]
EFFICIENT_TOKEN_ROOT = "/abs/path/to/project"Codex loads project configuration after you trust the project. The explicit root is important for path-dependent MCP tools because Codex surfaces do not all launch stdio servers from the active workspace directory. If you only use Codex CLI, this user-level shortcut also works, but it pins that registration to one project:
codex mcp add efficient-token --env EFFICIENT_TOKEN_ROOT=/abs/path/to/project -- npx -y efficient-tokenCodex CLI, the IDE extension, and the desktop app share Codex configuration on the same host. Keep a separate project-scoped entry for each workspace rather than relying on inherited cwd across surfaces.
See Codex's current MCP configuration guide for server and per-tool options.
With Claude Code
Register the published package with npx. No clone or build is needed:
# available in every project (user scope)
claude mcp add --scope user efficient-token -- npx -y efficient-tokenDrop --scope user to register it for the current project only. To pin the workspace
root used by project/source tool paths, add
--env EFFICIENT_TOKEN_ROOT=/abs/path/to/project. Without that override, Claude
Code supplies its current project directory through CLAUDE_PROJECT_DIR.
Alternative package/source commands
npm i -g efficient-token
claude mcp add --scope user efficient-token -- efficient-tokenFor Codex, use command = "efficient-token" and args = [] in the explicit-root
project table above.
git clone https://github.com/fahomid/Efficient-Token.git
cd Efficient-Token
npm install
npm run build # tsc -> dist/
claude mcp add efficient-token -- node "$(pwd)/dist/index.js"For Codex, use command = "node" and
args = ["/abs/path/to/efficient-token/dist/index.js"] in the explicit-root table.
Skip the build and run the TypeScript directly during development:
claude mcp add efficient-token -- npx tsx "$(pwd)/src/index.ts"For Codex source development, set command = "npx" and
args = ["tsx", "/abs/path/to/efficient-token/src/index.ts"] in that table.
It's a standard stdio MCP server. Point any host at the command
npx -y efficient-token (or node /abs/path/dist/index.js) over stdio.
Optional Claude Code integration
Registering the MCP server is enough to use every tool from Codex or Claude Code.
The following installer is specifically for Claude Code: it manages Claude's
PreToolUse hook and custom statusLine. It does not configure Codex.
From the project root:
npx efficient-token setup # redirect hook + health status line (opt-in, fail-open)
# variants:
npx efficient-token setup --no-hook # status line only (no enforcement)
npx efficient-token setup --no-statusline # enforcement hook only
npx efficient-token setup --scope user # apply to every project (~/.claude)
npx efficient-token uninstall # remove managed settings entries and generated scripts
# from a built source checkout instead of npx:
node dist/index.js setupThis redirects supported bare Bash reads such as rg, cat, head, and
line-range sed to the MCP tools. It fails open, so it never blocks when the
server is down. It also shows live token savings in your status bar with
no API call. See enforcement
and the status line for how each works.
The Claude settings and hook files are opt-in and reversible:
uninstallremoves its managed settings entries and generated scripts. Safety backups remain. The running MCP server separately keeps ephemeral health state in the user's runtime/temp directory; see the status section. Restart Claude Code after setup so it picks up the status line.
Verify it works
MCP servers load when the host session starts, so start (or restart) a session after registering. To confirm it's connected:
In Codex, run
/mcpin the TUI orcodex mcp listin a shell.In Claude Code, run
/mcporclaude mcp list.In the Codex IDE extension or ChatGPT desktop app, open MCP servers in settings and restart the client after changing configuration.
Or, without involving a model, launch the published server in the official Inspector. The current Inspector requires Node.js 22.7.5 or newer; the server itself remains compatible with Node.js 18 and newer.
npx -y @modelcontextprotocol/inspector npx -y efficient-tokenFrom a source checkout, build first; the repository also includes a one-shot health probe:
npm run build npm run health npx -y @modelcontextprotocol/inspector node dist/index.js
health reports the version, workspace root, limits, and the tokens saved so far:
efficient-token: ok
version: 1.1.0
tier: free
root: /abs/path/to/your/project
maxReadTokens: 6000
maxFileBytes: 2000000
savings this session (estimate):
efficient-token read ~0 source tokens and returned ~0 tokens to the MCP host, ~0% fewer tokens (0 read(s))
saved ~0 tokensThe savings ledger is per server process, so a one-shot Inspector or source
npm run healthprobe always reads zero because it is a liveness/config check. To see a live session's savings without the model, runefficient-token status(it reads the running server's heartbeat) or wire up the status command; or ask the model to callhealthin that session.
Make the model prefer these tools
Registering the server already nudges the model toward these tools. It advertises
the preference in its MCP instructions and in every drop-in tool's description.
For a stronger, durable steer, add the following routing rule to a repository's
AGENTS.md for
Codex. Claude Code can share that exact file through a small
CLAUDE.md containing @AGENTS.md.
For personal defaults across repositories, use ~/.codex/AGENTS.md and
~/.claude/CLAUDE.md respectively.
## Tool preference: efficient-token
An `efficient-token` MCP server is available. Its tools return the same real
source and data as reading or grepping files, distilled to far fewer tokens.
**Default to them over native file/shell tools and over reading whole files or raw
git output** whenever one fits the task. As a rule of thumb:
- **Read and locate:** use `code_read` instead of a whole-file read or `cat`,
`code_search` instead of shell `grep`/`rg`, and `glob` instead of `find`/`ls`.
- **Understand code without reading whole files:** `code_outline`, `repo_map`,
`code_context`, `find_references`, `symbol_find`, `call_hierarchy`, `call_sites`,
`import_map`, `type_closure`, `grep_context`, `marker_inventory`, `read_many`
(now reads several symbols at once and a symbol with its callees), `json_query`,
`json_get` (a key plus its sibling metadata).
- **Review changes and history:** `diff_digest`, `review_branch`, `outline_diff`,
`commit_log`, `line_blame`, `symbol_history`, `read_at_rev`, `conflict_digest`,
`change_coverage`, instead of reading changed files or parsing raw `git`.
- **Run checks and chase failures:** `code_check`, `test_run`, `check_locate`,
`trace_locate` (run allowlisted package.json scripts; failures-only output).
- **Edit precisely:** use the efficient-token MCP `apply_patch` for a validated
multi-file batch that checks for stale inputs and safely rolls back its own
completed writes after a later failure. It can also run a package.json check.
Use `code_edit` for one exact replacement, `code_write` for creation or full
rewrites, `json_set` for a key in a large JSON bundle, and `replace_symbol`,
`move_symbol`, or `project_rename` for their specialized cases.
- **Inspect images, design, and media:** `view_image`, `media_info`,
`color_contrast`, `design_tokens`, `font_info`, `svg_digest`, `token_usage`.
Fall back to native tools for formats or operations efficient-token does not cover.Don't feel obliged to copy the whole list: the opening paragraph plus the first bullet (read and locate) is enough on its own. The model discovers the rest from the registered MCP surface. Hosts may expose those definitions eagerly or load them on demand through tool search.
Claude Code enforcement (opt-in)
The soft steer above is usually enough. For hard, automatic enforcement, where a
supported bare Bash reader is actively redirected to the MCP tool, the
server ships an opt-in setup that installs a Claude Code PreToolUse
hook. It is fail-open:
if the server isn't running, isn't installed, or anything errors, your built-in
tools work exactly as normal.
# Run from your project root. This installs both the redirect hook and status line.
npx efficient-token setup # or: node /abs/path/to/dist/index.js setup
npx efficient-token uninstall # removes managed settings entries and generated scripts
# --scope user target ~/.claude/settings.json instead of the project
# --no-hook install only the status line · --no-statusline only the hooksetup writes .claude/settings.local.json, a redirect hook at
.claude/hooks/efficient-token-redirect.mjs, and a status-line script at
.claude/hooks/efficient-token-status.mjs. It sets the statusLine only when you
don't already have one. The installer does not edit Git ignore rules; if your repo
does not already treat Claude's local settings as private, ignore the generated
settings, backup, and efficient-token-*.mjs hook files.
How it works. While the server runs it publishes a fresh, per-process heartbeat
in the user's runtime/temp directory. The hook checks that state on every Bash
call. Only when it is fresh does it deny a supported bare, read-only command:
rg, single-file cat, line-count head, or print-only line-range sed, with no
pipe, chain, redirect, or write flag. It tells the model to use code_search or
code_read instead. Everything else is allowed. This includes grep, whose basic
regular-expression syntax is not equivalent to RE2, pipelines such as
npm test | grep, mutations such as sed -i or cat > f, stale or missing
heartbeats, unparseable input, and commands without an MCP equivalent.
flutter test, git …, and package managers are never blocked.
- Opt-in & reversible.
setupbacks up the Claude settings file, deep-merges idempotently (re-running updates in place, never duplicates), anduninstallremoves only its managed hook, status line, and scripts. - Disable the heartbeat with
EFFICIENT_TOKEN_HEARTBEAT=0; the hook then always fails open. The legacyEFFICIENT_TOKEN_ENFORCE=0name remains accepted.
Health and status (no API call)
Run npx efficient-token status from any supported client environment for the
full health report with version, tier, root, limits, and session savings without a
model turn or API call:
efficient-token: up
version: 1.1.0
tier: free
root: /abs/project
maxReadTokens: 6000
maxFileBytes: 2000000
savings this session (estimate):
efficient-token read ~3100 source tokens and returned ~210 tokens to the MCP host, ~93% fewer tokens (12 read(s))
saved ~2890 tokens
last heartbeat: 4s agoThe source and returned figures are real measurements. The server cannot see a host's full conversation context or billing total.
By default, the state is outside the repository under
$XDG_RUNTIME_DIR/efficient-token when available, otherwise under the operating
system temp directory as efficient-token-<user-id>. Each canonical workspace root
maps to a SHA-256-named directory containing one <pid>.json per live server.
Set EFFICIENT_TOKEN_STATE_DIR to override the base directory. Readers prefer this
runtime state but still accept the old project-local .claude/.efficient-token/
files as a read-only liveness fallback during migration. Legacy workspace files
never supply displayed version, path, tier, or savings data.
When using the optional Claude hook/status line with a custom state directory, run
efficient-token setup with the same absolute EFFICIENT_TOKEN_STATE_DIR value
used by the MCP server; the generated scripts embed that base so they can find
server-only MCP environment state.
--json returns the raw state. EFFICIENT_TOKEN_HEARTBEAT=0 (or the legacy
EFFICIENT_TOKEN_ENFORCE=0) disables state writes and makes status report "not
running". The health MCP tool reports the same details in-conversation.
Claude Code status line
efficient-token setup points Claude Code's
statusLine at a small generated
script that reads the same runtime state and refreshes automatically. Run
efficient-token setup --no-hook when you want only the status line. It never
replaces a status line you set yourself.
The widget renders, for example, efficient-token v1.1.0 (free): up · read ~3.1k
source tokens; returned ~210 tokens to the MCP host (~93% less), or
efficient-token: not running when the server is down. To wire it manually:
// .claude/settings.json
{
"statusLine": { "type": "command", "command": "node /abs/path/to/dist/index.js status --line" }
}This custom command widget is Claude Code-specific. Codex users can call health
or run efficient-token status directly.
Usage
You don't call these tools by hand. The model picks them while it works. A few things worth knowing:
- Workspace root. Project/source tools confine their file operands to one root
(
EFFICIENT_TOKEN_ROOT, then Claude Code'sCLAUDE_PROJECT_DIR, then the server process working directory). Paths are relative to that root. Set the explicit root for Codex so CLI, IDE, and desktop launches agree. Package scripts run with their normal OS permissions. Their validated npm lifecycle is captured before launch and package runs are serialized, which prevents overlapping writes to the same build tree. Heartbeat/status state uses the separate directory described above. - Reads degrade, never dump. A whole-file read over the token budget returns the
first page of real content (like the built-in
Read) with how to continue (offset=…, orcode_outlinefor a map), so a huge file can't blow your context. - Edits are guarded.
code_edit/code_write/apply_patch/replace_symbolrefuse a change that would leave an unclosed token (setvalidate=falseto override) and replace each affected file atomically. Read-modify-write tools also refuse files that changed after planning. Multi-file operations validate every source before the first replacement and roll back only writes they completed. These are coordinated writes, not filesystem-wide atomic transactions. Malformed UTF-8 is rejected by text tools, and the configured file-size limit applies to writes as well as reads. The mutating tools declaredestructiveHint, so your host can confirm them. - Trim what you don't use. If you only do code work, set
EFFICIENT_TOKEN_GROUPS=coreto drop the design/media tools and save their registered metadata cost (see Configuration).
Measuring token savings
Two complementary numbers, both built in.
1. Tokens saved this session with health, status, or the status line. Every
distilled read records two real numbers: the source it read (what a whole-file
Read would have returned) and what it returned to the MCP host. health,
efficient-token status, and the status line all surface the running total:
savings this session (estimate):
efficient-token read ~2455 source tokens and returned ~406 tokens to the MCP host, ~83% fewer tokens (2 read(s))
saved ~2049 tokens [read 1671t/1, outline 379t/1]The source and returned character counts are measured directly, then converted to
token estimates at roughly four characters per token and clamped so savings are
never overstated. Ask the model to call health
in-conversation, run efficient-token status with no API call, or watch the
Claude Code status line.
2. Serialized tool records with npm run toolcost. This opens an in-memory
MCP connection and measures the exact JSON serialization of the tools/list
records, including nested schemas, constraints, descriptions, titles, and
annotations. Protocol framing is excluded, and hosts with tool search may defer
some or all definitions until needed. CI rejects totals above 55,000 characters.
npm run toolcost
# TOTAL 47 tool(s) 53806 chars ~13452 tokUse it to decide which bundles to load. Setting EFFICIENT_TOKEN_GROUPS=core
drops about 1,305 token-equivalent units from this serialization in a pure-code
repo. The realized context saving depends on the host.
Configuration
Server behavior is configured through environment variables (pass them with
--env when registering, or use the client's environment table). Host-side
timeouts and approvals stay in the MCP client's configuration, as in the Codex
example above.
| Variable | Default | Meaning |
| --- | --- | --- |
| EFFICIENT_TOKEN_ROOT | CLAUDE_PROJECT_DIR, then current working directory | Workspace root for project/source tool paths. The explicit setting always wins and is recommended for Codex because its surfaces can launch stdio servers from different directories. Claude Code supplies CLAUDE_PROJECT_DIR. |
| EFFICIENT_TOKEN_MAX_READ_TOKENS | 6000 | Whole-file read budget before code_read returns a first-page preview. |
| EFFICIENT_TOKEN_MAX_FILE_BYTES | 2000000 | Hard UTF-8 byte cap for text reads and writes. Binary inspection tools apply their own smaller bounds. |
| EFFICIENT_TOKEN_GROUPS | (all) | Comma-separated tool bundles to register: core (everything except the design tools) and design (color_contrast, font_info, design_tokens, svg_digest, token_usage, media_info). Unset loads all; core always loads. Example: core in a code-only repo, core,design for UI/video work. |
| EFFICIENT_TOKEN_GENERATED_GLOBS | (none) | Extra comma-separated globs marking generated files to hide by default from code_search / repo_map / diff_digest (added to the built-in defaults like *.min.js, *.g.dart, **/generated/**). Override per call with includeGenerated: true. |
| EFFICIENT_TOKEN_STATE_DIR | user runtime/temp directory | Override the base directory for ephemeral per-workspace heartbeat/status state. No state is written inside the workspace by default. Use the same absolute value when running the optional Claude setup so its generated readers embed the matching base. |
| EFFICIENT_TOKEN_HEARTBEAT | enabled | Set to 0 to disable heartbeat/status state writes. The old EFFICIENT_TOKEN_ENFORCE=0 spelling remains accepted for compatibility. |
Git-aware tools support a parent repository when the configured root is a monorepo
subdirectory. File inputs remain literal and confined to EFFICIENT_TOKEN_ROOT,
and paths and results are scoped and rebased to that root so sibling workspaces do
not appear. A working-tree inspection fails closed when a configured external
clean/process filter applies to the requested files; staged and historical Git
inspection remains available without executing repository-configured helpers.
Tools
47 tools, grouped by what you reach for. Every tool is read-only unless marked (mutating) or (executes). All are free and MIT-licensed.
| Group | Tools | What for | | --- | --- | --- | | Read & navigate | 10 | read symbols/ranges, outline, repo map, keyed JSON | | Search & symbols | 10 | grep, references, call graph, types | | Git & review | 8 | diffs, blame, history, coverage | | Creative & design | 7 | images, media, color, fonts, SVG | | Run & locate | 4 | run checks/tests, jump to failures | | Edit & session | 8 | guarded edits, rename, move, notes |
| Tool | Use it to… |
| --- | --- |
| health | Confirm the server is connected and see tier, workspace, and limits, plus the estimated tokens saved this session by distilled reads. The baseline is exact: whole-file size against what was returned. (read-only) |
| code_outline | List a file's symbols (functions, classes, methods, types) with line ranges and signatures, without the source. (read-only) |
| code_read | Like Claude's Read (same file_path/offset/limit, cat-n output) but leaner: it can also extract one symbol, and a whole-file read over budget returns the first page of content (with how to continue) rather than dumping the file. (read-only) |
| glob | List file paths matching a glob or type, with no content, like Claude's Glob (same pattern/path). Find files without reading directories. Sorted by name for reproducibility rather than by mtime. (read-only) |
| read_many | Read several symbols, ranges, or files in one call, the read-side analog of apply_patch. A target can name several symbols or include same-file callees. Conflicting target forms are rejected, inputs are capped, and output is labeled and budget-bounded. (read-only) |
| code_read (elide) | code_read also takes elideIfUnchanged: a repeat read of a target unchanged since earlier this session returns a short "unchanged" marker instead of the bytes (re-orienting in edit loops). Re-read without the flag to get the source. (read-only) |
| json_query | Extract a value from a JSON file by a dotted or bracket path (scripts.build, items[0].name) instead of reading the whole file. With no query it returns a shallow top-level overview of keys with their types and sizes. Token-bounded. (read-only) |
| json_get | Read one top-level key's value from a JSON object file, plus its sibling metadata key if present (e.g. @key for localization/ARB-style bundles), in one call. (read-only) |
| json_set | Insert or update one top-level key in a JSON object file surgically. It replaces just that key's value span in place (everything else stays byte-for-byte) or appends the key, and can set a sibling metadata key too. Re-validates as JSON before an atomic write. For large keyed JSON (localization bundles, token maps, config). (mutating) |
| read_at_rev | The historical code_read: read one symbol, line range, or whole file as of a git revision, returning a first page with continuation guidance over budget instead of dumping git show <ref>:file. (read-only) |
| repo_map | A token-bounded file tree grouped by directory, with syntax-tree top-level definitions for supported source files. Generated files are hidden by default. Unreadable files and unavailable syntax analysis are labeled instead of being shown as empty. (read-only) |
| Tool | Use it to… |
| --- | --- |
| code_search | Like Claude's Grep (ripgrep), with the same params: output_mode (files_with_matches/content/count), glob/type, -A/-B/-C, -i, -n, -o, head_limit, multiline. Returns matches, not whole files. Generated files (glob list + @generated marker) are skipped by default (count reported); includeGenerated: true to include. (read-only) |
| grep_context | Regex search that returns each match with its enclosing function or class source (deduped, line-numbered, matched lines marked ›). One call replaces a search followed by opening each file. (read-only) |
| find_references | Find syntax-tree definitions and identifier-boundary text mentions of a name. Text mentions can include comments, strings, imports, types, and unrelated same-name bindings, so they are not presented as semantic identity matches. (read-only) |
| symbol_find | Find syntax-tree definitions by exact name or substring, returning file:line, kind, and signature with optional filters. Incomplete read, scan, and parser coverage is disclosed. (read-only) |
| call_sites | Find syntax-tree call lines whose callee name matches. It excludes comments, imports, types, and value-only references, but does not claim receiver, import, or overload identity. (read-only) |
| call_hierarchy | Show one unambiguous function or method definition, syntactic callee names, and same-name caller candidates. Ambiguous definitions are refused, and candidate identity limits are explicit. (read-only) |
| marker_inventory | Inventory code-comment markers (TODO/FIXME/HACK/XXX/BUG, or custom tags) across the workspace, grouped by tag, each as file:line + text. Matches only after a comment leader so prose isn't a false positive. (read-only) |
| import_map | Show static JS/TS imports and importers for one existing file. Syntax-tree extraction ignores import-shaped comments and strings. Relative edges resolve only to a unique existing workspace module; unresolved and ambiguous edges are disclosed. (read-only) |
| type_closure | Return one unambiguous type definition and the verbatim workspace types it references. TypeScript and JavaScript resolution follows parsed type syntax, relative imports, aliases, named and star re-exports, export visibility, and lexical generic scope. Ambiguous or unresolved references are disclosed, and incomplete scans are refused. (read-only) |
| code_context | Show one unambiguous definition with bounded source, syntactic call names and workspace definition candidates, plus identifier-boundary text mentions. Candidate and text identity limits are explicit. (read-only) |
| Tool | Use it to… |
| --- | --- |
| diff_digest | Review git changes as hunks only, or as a --stat summary or file list, scoped by ref/staged/path, instead of reading whole changed files. Generated files are excluded by default (count reported); includeGenerated: true to include. Read-only git. (read-only) |
| review_branch | A semantic change summary: each changed file with the symbols that changed (functions, classes), mapped from the diff to the AST. Review a branch or PR without reading hunks. (read-only) |
| commit_log | Compact commit history, one row per commit (sha date author subject, no bodies or diffs), scoped by path/ref/limit instead of raw git log. (read-only) |
| line_blame | Line provenance via git blame, with contiguous same-commit runs collapsed into ranges (Lstart-Lend sha date author summary). Scope it to a symbol or range; uncommitted lines are marked. (read-only) |
| symbol_history | The history of one symbol or line range via git log -L, as list or hunks, instead of git log plus per-commit git show dragging in whole files. (read-only) |
| outline_diff | A symbol-level delta between two revisions: per changed file, the symbols added, removed, or changed. Rename records preserve both old and new paths. Works on arbitrary revision pairs. (read-only) |
| conflict_digest | Show only the three-way regions of merge-conflicted files (ours, base, theirs, verbatim and line-numbered) instead of reading whole files to find <<<<<<< markers. Extracts only; you decide the resolution. (read-only) |
| change_coverage | Intersect your changed lines with an lcov coverage artifact to answer "did I test my change?". Lists covered against uncovered changed lines with the enclosing symbol. (read-only) |
| Tool | Use it to… |
| --- | --- |
| view_image | See validated raster image files (png/jpg/gif/webp/avif/bmp) directly. Content signatures, dimensions, per-image size, and aggregate size are checked before any image block is returned. (read-only) |
| media_info | Distilled facts about image, video, and audio files: format, dimensions, aspect ratio, byte size, plus duration/fps/codec for A/V when ffprobe is present. Reads metadata without loading the bytes. (read-only) |
| design_tokens | Distill CSS custom properties and JSON design tokens as bounded, verbatim name=value facts. CSS is parsed with PostCSS, so comments, quoted punctuation, selectors, at-rules, and conflicting contextual definitions are handled accurately. DTCG composite values stay intact, $root is preserved, and categories follow declared, inherited, or alias-resolved $type values without guessing. (read-only) |
| color_contrast | Convert CSS Color 4 values to sRGB hex, rgb, and hsl, or calculate WCAG 2.2 contrast. Wide-gamut values use CSS gamut mapping, translucent foregrounds are composited, and translucent backgrounds require an opaque backdrop. (read-only) |
| svg_digest | An SVG's structure: viewBox, intrinsic size, an element histogram, and ids, without path data. A bounded XML scanner validates the root, nesting, attributes, comments, CDATA, and duplicate ids. (read-only) |
| font_info | Inspect TTF, OTF, WOFF, WOFF2, and stylesheet files. It validates bounded font headers, directories, and ranges before reading sfnt family/subfamily names or reporting @font-face declarations; compressed WOFF payload decoding is outside its structural check. (read-only) |
| token_usage | Audit CSS custom properties: which are defined but never referenced via var(), and which are used but never defined, each with a file:line. (read-only) |
| Tool | Use it to… |
| --- | --- |
| code_check | Run one validated package.json script, including its standard npm pre/post hooks, and return a one-line pass or bounded failure output. Execution is bound to the captured manifest, package runs are serialized, and npm's lifecycle code and shell resolve outside the workspace. (executes) |
| check_locate | Like code_check, but on failure it parses file:line from the output and returns the failing source with its enclosing symbol in one call. (executes) |
| trace_locate | Paste a stack trace or error output and get the source at each file:line frame, with context and the enclosing symbol. Frames outside the workspace root are skipped. (read-only) |
| test_run | Run a focused test by forwarding one bounded filter, or set changed: true for a reported, basename-based candidate test set from the working-tree diff. Changed mode is a heuristic, not dependency analysis. Unsafe or oversized launcher arguments are refused, and queued time counts toward the timeout. (executes) |
| Tool | Use it to… |
| --- | --- |
| code_edit | Like Claude's Edit (same file_path/old_string/new_string/replace_all): the match must be verbatim and unique unless replace_all=true, missing or ambiguous matches are refused, and the write is atomic. Tolerates CRLF/LF newline differences. Refuses a change leaving an unclosed token unless validate=false. (mutating) |
| code_write | Like Claude's Write (same file_path/content); creates parent dirs and writes atomically. Carries the same syntax-error guard as code_edit. (mutating) |
| replace_symbol | Replace a whole function/class/method definition by name: pass only the new source, not the old body as a match anchor. Resolves the span via the AST (export/decorator-aware, line-ending and BOM faithful), disambiguates by container/occurrence, syntax-guarded, atomic. (mutating) |
| apply_patch | Apply up to 256 exact edits across one or more files as one validated batch. Each edit is { file_path, old_string, new_string, replace_all? }. It refuses a file that changed after planning. Each replacement is atomic, and a later failure rolls back only transaction-owned changes when the current content is still safe to restore. This is a coordinated batch, not a filesystem-wide atomic transaction. It can run a package.json check after applying; a failed or unavailable check returns an error and states that the edits remain applied. (mutating) |
| move_symbol | Relocate one independent top-level JS or TS definition with stale-input checks and coordinated writes. Parsed named relative imports and re-exports are rewritten across a complete workspace scan, with correct .js, .mjs, and .cjs mapping. It keeps attached documentation and refuses grouped declarations, dependency transfer, unsupported module forms, path aliases, ambiguous modules, and destination conflicts. dryRun reports blocked dependencies without writing. (mutating) |
| project_rename | Rename an identifier across the workspace with stale-input checks and coordinated per-file replacements. It refuses incomplete scans or unreadable candidates, forwards cancellation through validation and commit, and bounds its report. Uses identifier boundaries, supports syntax validation and dryRun, and can be scoped with path or type. The rename is textual. (mutating) |
| note_write / note_read | A persistent scratchpad under .efficient-token/notes/. Appends are serialized across server contexts in the same process. Reads and listings are token-bounded; use offset to continue a large note or list. (write / read) |
Language support
code_read and code_outline use tree-sitter
(via WASM); the language is chosen by file extension.
TypeScript (
.ts .mts .cts), TSX (.tsx), JavaScript (.js .mjs .cjs .jsx), Python (.py), Ruby (.rb), PHP (.php), Go (.go), Rust (.rs), Zig (.zig), C (.c .h), C++ (.cpp .cc .cxx .hpp .hh .hxx), C# (.cs), Objective-C (.m), Java (.java), Kotlin (.kt .kts), Scala (.scala .sc), Swift (.swift), Dart (.dart), OCaml (.ml .mli), ReScript (.res .resi), Emacs Lisp (.el), Lua (.lua), Bash (.sh .bash .zsh), Solidity (.sol), SystemRDL (.rdl), TLA⁺ (.tla)
HTML (
.html .htm), CSS (.css), Vue (.vue), ERB/EJS (.erb .ejs), JSON (.json), TOML (.toml), Elixir (.ex .exs)
Any other file type still works with code_read in range or whole-file mode; only
the symbol-aware features need a grammar.
Architecture
A small kernel that knows nothing about any feature, plus plugins that
receive a shared CoreContext and depend only on it, never on each other.
src/
core/ contract.ts · config.ts · loader.ts · premium.ts · result.ts
read.ts · text.ts · edits.ts · git.ts · run-script.ts
services/ logger.ts · paths.ts · fs.ts · ast.ts · scan.ts
budget.ts · savings.ts · license.ts
plugins/ one folder per tool (47 tools across the groups above)
registry.ts core plugin composition
server.ts build ctx, register plugins, serve over stdio
api.ts side-effect-free package API and contract types
index.ts executable CLI/MCP entry point
scripts/
smoke.ts in-process self-test e2e.ts real-stdio round-trip
package-probe.ts packed npm surface toolcost.ts serialized metadata budget
discover.ts grammar node inspector- stdout is the MCP protocol stream. The server never writes to it; all logs go to stderr.
- Workspace-content access is sandboxed to the configured root, and each file replacement is atomic. Ephemeral heartbeat state is isolated in private user runtime/temp storage.
- Only the loader touches the SDK and gates tools by tier and bundle.
See ARCHITECTURE.md for the full design, conventions, and the
plugin contract.
Open-core / premium
This package is MIT and free, forever. It's also wired for open-core: future
premium plugins ship in a separate, privately-licensed package and are loaded only
when installed and entitled. The core never depends on them, and the free tools are
unaffected. The package exports the plugin contract types so a premium package can
build against it without importing the executable entry point. No premium code is
part of this release. See
ARCHITECTURE.md for the contract.
Development
npm run typecheck # tsc --noEmit (src + scripts)
npm run build # emit dist/
npm test # smoke + stdio E2E + Codex/Claude host compatibility
npm run dev # run the server from source via tsx
npm run health # protocol-level health probe (no model)
npm run toolcost # serialized MCP tool-record measurement and CI budget
npm run package-probe # pack/install CLI, MCP, API, and declarations probeAdding a plugin: create src/plugins/<name>/index.ts exporting a factory that
returns a Plugin, talk only to ctx, set the correct tier, add one entry to the
plugins array in src/registry.ts, and extend scripts/smoke.ts. Update the public
tool inventory and changelog when behavior changes. See
CONTRIBUTING.md for the full workflow.
Contributing & security
CONTRIBUTING.md, dev setup, the plugin contract, the Definition of Done, and the release process.SECURITY.md, the sandbox/security model and how to report a vulnerability privately.CHANGELOG.md, release history.
License
MIT, free for personal and commercial use.
