REFERENCE / v0.5

Everything you need.

BeagleLathe is a local MCP server. One tool, lathe, with four actions: search, edit, edit_glob, read. Eight slash commands. One local SQLite for savings tracking. One optional account for free-tier metering. Below: tool reference, benchmark methodology, install, slash-command index, configuration, statusline, troubleshooting.

01 / MCP TOOLS

The lathe tool.

BeagleLathe registers one MCP tool, lathe, with four actions: search, edit, edit_glob, read. Claude Code picks them up automatically once /mcp shows the server. Seven legacy tool names (sh, run_tests, git_status, git_diff, changed_files, lint_and_typecheck, extract_todos, commit_message) are still dispatched by name as a back-compat layer but are no longer advertised in /mcp. All are documented below.

Read & search

ToolReplacesWhat it does
search glob → grep → read-to-confirm (~3 calls → 1) Fuses glob filtering, regex (ripgrep) pattern matching, and ranked snippet reading into one call. Returns matches grouped by file with surrounding context.
read cat + head/tail on large files (~2 calls → 1) AST-aware reader. Twelve languages get full structural truncation: Python (.py), TypeScript (.ts), TSX (.tsx), JavaScript (.js/.mjs/.cjs/.jsx), Rust (.rs), Go (.go), Java (.java), C# (.cs), Ruby (.rb), PHP (.php), C (.c/.h), and C++ (.cc/.cpp/.cxx/.hpp/.hh/.hxx). Keeps signatures, types, imports, and module-level declarations; stubs function bodies. Four modes: truncated (default — bodies stubbed), full (verbatim), structure (declarations + exports only, drops module-level statements), skeleton (regex-picked declaration lines — cheap fallback for unsupported languages or giant files). Pass symbol="ClassName.method" with mode=truncated to keep one symbol’s body in full while stubbing the rest. Hard cap: 200,000 chars.
sh Bash for read-only inspection Runs a single read-only command: ls, cat, head, tail, wc, find, pwd, which, file, stat, du, df, tree, echo, or git (log/status/diff/show/blame/branch/remote/config/rev-parse/ls-files/describe). No pipes, redirects, or subshells.

Edit

ToolReplacesWhat it does
edit read → edit → verify-read (~3 calls → 1) Apply an array of edits across one or more files in one atomic call. Matching cascade: exact → normalized (whitespace / smart-quote fold) → fuzzy (rapidfuzz ≥ 90). All-or-nothing: if any edit fails the dry run, nothing is written.
edit_glob Bash sed -i across many files Atomic regex substitution across a glob. Two-phase commit: stage all .tmp files, re-verify hashes, rename atomically. All-or-nothing on failure. The differentiator vs shell-sed is the guarantee.

Tests & quality

ToolReplacesWhat it does
run_tests Bash(pytest) → grep → read → grep → read (~5 calls → 1) Auto-detects pytest / jest / vitest / cargo test / go test. Returns parsed summary{total, passed, failed, skipped, errors} plus per-failure {name, file, line, message, source_excerpt, traceback_tail}.
lint_and_typecheck Per-language linter via Bash, then grep output Dispatches by extension: .py → ruff + mypy; .ts/.tsx → tsc + eslint; .js/.jsx → eslint; .go → go vet + golangci-lint; .rs → cargo check + clippy. Missing runners land in skipped_runners rather than failing the call.
extract_todos grep + per-line git blame Scan for TODO / FIXME / XXX / HACK markers, return them with marker, file:line, comment text, surrounding context, and (in git repos) author + commit sha + age in days from blame. Sortable by age or file.

Git

ToolReplacesWhat it does
git_status git status + manual parsing Returns {branch, upstream, ahead, behind, staged, unstaged, untracked, renamed, conflicts}. Detached HEAD adds {detached: true, head_sha}.
git_diff git diff + hunk parsing Structured unified diff with per-file additions/deletions and a list of hunks (old_start, old_lines, new_start, new_lines, header, content). Handles added / modified / deleted / renamed / copied / type-changed / binary.
changed_files git diff --numstat + status parsing Files changed on the current branch vs a base branch (auto-detected main/master/develop) with per-file {additions, deletions, status}. Optionally folds in uncommitted working-tree changes.
commit_message Hand-writing a conventional commit Generate a conventional-commit draft from staged / working-tree / last-commit changes. Heuristic only, no LLM call: paths drive type (test, docs, ci, build, feat, fix, refactor), longest common directory drives scope. Intended as a starting draft.
02 / BENCHMARK

Measured savings.

Numbers from scripts/benchmark.py: n=5 head-to-head across nine fixtures. Each fixture runs twice in a fresh tmp workdir — once with stock Claude Code (empty MCP config), once with BeagleLathe registered. Same model on both sides, same prompt, same setup. The harness parses stream-json telemetry and runs each fixture’s verify.py to confirm the task actually completed.

−46%
fewer tool calls
−42%
lighter cache footprint
−29%
faster wall time
−19%
cheaper per task

Per-task averages across all nine fixtures (Opus 1M tier; re-priced figures for Sonnet 4.6 and Opus 4.7 standard tiers ship in BENCHMARK-RESULTS.md):

MetricStockLatheDelta
Tool calls / task7.44.0−46%
Turns / task8.45.0−40%
Output tokens / task1,243720−42%
Cache-creation tokens / task~20,400~11,800−42%
Wall time / task25.1 s17.9 s−29%
Cost / task (Opus 1M tier)$0.1960$0.1587−19.0%
Pass rate45/45 on both sides

The bigger lever isn’t the dollar number — it’s the −42% cache-creation tokens, which is what most rate limits actually meter against.

The throughput math

A Claude Code 5-hour window is a fixed token budget. If each unit of useful work costs 19% fewer tokens, you fit 1 / (1 − 0.19) = 1.235× more tasks in the same window — ~24% more shipped code. Applied to the published 5h limits for Opus-heavy use:

Extra tasks per 5-hour window

PlanStockLatheExtra
Pro~40~49+9
Max 5×~200~247+47
Max 20×~800~988+188

Caveat: the 19% is a per-task mean across nine paired fixtures. The win is bigger on multi-file edits (rename hits −43%, multi-file-rename hits −73%) and smaller on single-line edits where the schema-load tax still dominates. A rename- or grep-heavy 5h window runs above 24%; an all-one-shot-Q&A window runs closer to 10–15%.

Fixtures cover real refactoring patterns: find-usages, multi-file-rename, constants-in-module, hidden-bug-in-body, large-file-search, re-read-after-edit, rename, run-tests-fix-bug, add-method. The benchmark harness and fixture set are open source. See the repo for scripts/benchmark.py, bench-fixtures/, and BENCHMARK-RESULTS.md.

How the local savings counter works

The benchmark above is the apples-to-apples measurement. Your local /lathe-savings counter is a separate, lighter-weight signal that runs all the time on your own machine. It scores four tools against the stock Claude Code sequences they replace:

The structured git, test, lint, todos, and commit-message tools are recorded to ~/.beaglelathe/state.db but don’t currently roll up into the running total — their per-call savings are harder to pin to a fixed multiplier, so the counter stays conservative. Tokens saved are estimated at 500 tokens per replaced call. Dollar cost is priced at the Sonnet input rate of $3/M tokens (not the higher output rate), so the displayed savings are a floor, not a ceiling. Nothing leaves your machine. /lathe-savings reads the SQLite file directly.

03 / INSTALL

Install.

Requires Python 3.10+ and the Claude Code CLI.

One-liner (recommended)

Picks the best Python installer available (uv > pipx > pip), installs beaglelathe, registers the plugin with Claude Code, and walks you through magic-link sign-in.

shell
curl -LsSf https://beaglelathe.dev/install.sh | sh

Pass --no-login to register the plugin without signing in:

shell
curl -LsSf https://beaglelathe.dev/install.sh | sh -s -- --no-login

The script is short and auditable. Read it at install.sh before running.

Manual install

Pick whichever Python tool you prefer. Each option is one shell line followed by beaglelathe login:

With uv (docs, recommended for Linux)

shell
uv tool install beaglelathe
beaglelathe login

uv installs beaglelathe into an isolated venv (sidesteps PEP 668 on Debian / Ubuntu) and puts the console script in ~/.local/bin. If that’s not on your PATH yet, run uv tool update-shell once.

With pipx (docs)

shell
pipx install beaglelathe
beaglelathe login

Same isolation story as uv. Run pipx ensurepath once if ~/.local/bin isn’t on PATH yet.

With pip directly

shell
pip install beaglelathe
beaglelathe login

Fine on macOS and Windows. On Debian / Ubuntu, modern Python distros block system-wide pip installs (PEP 668). Use uv or pipx instead.

beaglelathe login registers the plugin with Claude Code (MCP server, slash commands, agents, hooks) and then walks you through magic-link sign-in. The install step is idempotent. Re-running is a no-op once the plugin is registered. Open Claude Code in your project and run /mcp. You should see lathe listed as one active tool (it exposes four actions: search, edit, edit_glob, read).

Install without signing in

BeagleLathe tools work without an account. To register the plugin without going through the magic-link flow, replace beaglelathe login with:

shell
beaglelathe install

You can sign in later with beaglelathe login or /lathe-login; without an account, savings are tracked locally and there’s no quota enforced.

Per-project install

If you’d rather wire BeagleLathe into a single project’s .mcp.json instead of installing the plugin globally:

shell
uv tool install beaglelathe   # or: pipx install / pip install
beaglelathe install --mcp-json

This writes a .mcp.json in the current directory (or the path you pass) that points at the Python interpreter where beaglelathe is installed. No plugin install, no slash commands. Just the lathe MCP tool (with four actions, plus the back-compat names), scoped to that project.

Alternative: install from the GitHub marketplace

The plugin is also published to the BeagleLathe Claude Code marketplace. You still need the Python package installed (the MCP server runs the beaglelathe console script):

shell
uv tool install beaglelathe   # or: pipx install / pip install
claude plugin marketplace add BeagleLathe/lathe
claude plugin install lathe@beaglelathe

Or inside a Claude Code session:

inside Claude Code
/plugin marketplace add BeagleLathe/lathe
/plugin install lathe@beaglelathe
04 / SLASH COMMANDS

Slash commands.

Inside Claude Code. All commands also have a corresponding CLI form (beaglelathe <subcommand>).

CommandWhat it does
/lathe List every BeagleLathe slash command with a one-line description. Useful as a quick reminder of what’s available.
/lathe-login Sign in via magic link. Opens browser, polls for confirmation, writes credentials.
Example: /lathe-login → click the link in the printed URL → “Signed in. Run /lathe-status to see your plan.”
/lathe-logout Clear stored credentials from ~/.beaglelathe/credentials.json. The MCP tools keep working anonymously after logout.
/lathe-status Show plan, calls used this month, budget remaining, reset date.
Example output: plan: Free tier / calls used: 42 / remaining: 158 / resets: 2026-06-01
/lathe-savings Show local savings counter: calls saved, tokens saved, estimated cost saved vs stock Claude Code. Computed entirely from ~/.beaglelathe/state.db; never synced.
/lathe-upgrade Open Stripe checkout to upgrade from Free to Pro ($9/mo, unlimited calls).
/lathe-update Update the BeagleLathe package to the latest version. The command detects which Python installer you used and upgrades through it: uv tool upgrade beaglelathe if you installed with uv, pipx upgrade beaglelathe if you installed with pipx, or pip install --upgrade beaglelathe otherwise. Whichever you used, the slash command picks the right one. Restart Claude Code (or run /mcp restart) afterward.
/lathe-help Print usage tips, the tool list, slash-command index, and troubleshooting cheat sheet inside Claude Code.
05 / CONFIGURATION

Configuration.

Files

PathPurpose
~/.beaglelathe/credentials.json Auth token written by beaglelathe login. Cleared by beaglelathe logout. Read-only across all CLI / MCP entry points.
~/.beaglelathe/state.db Local SQLite for the savings counter and per-tool call totals. Never synced; /lathe-savings reads from this file.
./.mcp.json (per project) The MCP server registration written by the plugin installer. Tells Claude Code how to launch the server.

Free tier

200 tool calls per month, per account. Resets at midnight UTC on the 1st of each calendar month. A “call” is one invocation of the lathe MCP tool, regardless of action. Without signing in, tools work anonymously and no quota is enforced. Only the local savings counter advances.

CLI reference

shell
beaglelathe login        Sign in via magic link
beaglelathe logout       Clear stored credentials
beaglelathe whoami       Print signed-in user
beaglelathe status       Show plan and remaining calls
beaglelathe savings      Show local savings summary
beaglelathe upgrade      Open Stripe checkout (Free → Pro)
beaglelathe serve        Start the MCP server (what Claude Code runs)
beaglelathe statusline   Print the one-line statusline string

All commands accept --help.

06 / STATUSLINE

Statusline integration.

BeagleLathe ships a Claude Code statusLine component that prints your plan, calls remaining, and locally-tracked savings on every prompt. To enable, add to ~/.claude/settings.json:

json
{
  "statusLine": {
    "type": "command",
    "command": "beaglelathe statusline"
  }
}

Output looks like:

output
Lathe · Free · 158 left · saved 42

Reads only from ~/.beaglelathe/credentials.json and ~/.beaglelathe/state.db; never makes a network call.

07 / TROUBLESHOOTING

Troubleshooting.

Tools not showing in /mcp

Run claude plugin list to confirm the plugin is installed. If the server isn’t starting, try /mcp restart or restart Claude Code.

“not logged in” / “session expired”

Run beaglelathe login (or /lathe-login) to get a fresh token. Tokens have a 24-hour TTL.

Quota exceeded

Run /lathe-upgrade or beaglelathe upgrade to open Stripe checkout. Pro is unlimited. Free-tier counters reset on the 1st of each month.

edit reports “old_string not found”

The string you provided doesn’t match what’s in the file. Read the current file content first with read, then retry with the exact text. Note that edit already tolerates whitespace and smart-quote drift. If it still can’t match, the underlying content really has diverged.

edit reports “old_string not unique”

Add more surrounding lines to make the match unique, or set replace_all: true if you want all occurrences replaced.

First tool call is slow

The MCP server starts on first use; ~3 seconds is normal. Subsequent calls in the same session are fast.