Turnpack
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Turnpack rename getUser to fetchUser across the repo and run the tests"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Try the demo · See an example · Set it up · The three tools · What it saves · Safety · FAQ
AI coding agents work in round trips: the model asks for something, waits, reads the result, and asks again. Each trip is a full model turn, a wait for the first token and then the tokens themselves. Today's apps already run independent reads side by side, so the trips that are left are the ones that depend on each other. A search has to come back before the agent knows which files to open. An edit has to land before the tests can run. And when the tests fail at the end, your repo is left half-edited while the agent spends more turns backing out.
Turnpack is a small local MCP server that gives the agent three tools to fold those trips together:
Tool | One call does | So that |
| A regex search with the code around each hit, several files (whole, by line range, or just one function), glob listings and git status | The agent gets its context in one turn. Replies are size-capped, and |
| Edits across any number of files, then your test command | Either everything passes and stays, or every file is restored byte-for-byte and the agent gets the failing output. None of the four apps we checked does this on its own. |
| A short read-only script over the repo | "Which of these 40 files export X?" costs one turn and a ten-line answer instead of 40 reads. |
It runs entirely on your machine: no API keys, no account, no telemetry, no network calls, and zero runtime dependencies. It works with Claude Code and Claude Desktop, Codex CLI and the ChatGPT desktop app, OMP, Grok Build, Cursor, Gemini CLI, OpenCode and anything else that speaks MCP over stdio.
Try it in 10 seconds
npx turnpack demoThis builds a throwaway repo in your temp folder, runs all three tools against it, and deletes it. Nothing in your own projects or AI app config is touched.
The recording is generated from the real output of those two commands (scripts/render-assets.py), so it cannot drift from what the tool does. doctor is run on a temporary home directory in which init has just set up five apps, which is why it lists them.
Want to run it straight from this repository instead of npm? npx github:OnlyTerp/turnpack demo
Related MCP server: Sippion
What it looks like
A rename that misses a call site is the classic way an agent breaks a build. Here is that mistake going through ship. The agent renames a function but forgets the file that imports it:
{
"edits": [
{
"path": "src/tax.js",
"search": "export function calculateTax(amount)",
"replace": "export function computeTax(amount)"
}
],
"verify": "npm test"
}FAILED_AND_ROLLED_BACK: verify "npm test" failed (exit code 1).
Restored 1 file(s) to byte-exact pre-edit snapshots. The workspace is unchanged; fix the edit and ship again.
$ npm test
> test
> node test/invoice.test.js
file:///home/you/shop/src/invoice.js:1
import { calculateTax } from "./tax.js";
^^^^^^^^^^^^
SyntaxError: The requested module './tax.js' does not provide an export named 'calculateTax'The repo is exactly as it was, and the agent has the error that tells it what it missed. It ships again with both files:
{
"edits": [
{
"path": "src/tax.js",
"search": "export function calculateTax(amount)",
"replace": "export function computeTax(amount)"
},
{
"path": "src/invoice.js",
"search": "calculateTax",
"replace": "computeTax",
"replace_all": true
}
],
"verify": "npm test"
}SHIPPED_AND_VERIFIED in 170ms: 2 file(s) changed (src/tax.js, src/invoice.js).
$ npm test (passed)
> test
> node test/invoice.test.js
ok - invoice total includes taxTwo turns, and at no point was the working tree broken. Both replies are real output, with Node's internal stack frames cut from the first and the project path shortened.
{
"query": "calculateTax",
"files": ["src/tax.js", { "path": "src/invoice.js", "symbol": "invoiceTotal" }, ".env"],
"git_status": true
}## GIT STATUS
## master
## SEARCH "calculateTax" (3 hits, engine=rg)
src/invoice.js:1: import { calculateTax } from "./tax.js";
src/invoice.js:4: return Number((subtotal + calculateTax(subtotal)).toFixed(2));
src/tax.js:3: export function calculateTax(amount) {
## FILES (3)
### FILE: src/tax.js (L1-6/6)
1 | export const TAX_RATE = 0.08;
2 |
3 | export function calculateTax(amount) {
4 | return Number((amount * TAX_RATE).toFixed(2));
5 | }
6 |
### SYMBOL: src/invoice.js :: function invoiceTotal (L3-5/6)
3 | export function invoiceTotal(subtotal) {
4 | return Number((subtotal + calculateTax(subtotal)).toFixed(2));
5 | }
### FILE: .env
[REDACTED SECRET FILE: .env — pass allow_secrets: true if intentional]Set it up
You need Node.js 22 or newer. Then:
npx turnpack initnpx turnpack doctorinit finds the AI apps you have installed, shows you exactly what it would change, and asks before writing. By default that is Claude Code, Claude Desktop, Codex (the CLI and the ChatGPT desktop app share one config), OMP and Grok Build.
The entry it writes starts a file on your machine, with an absolute path to Node. That starts in tens of milliseconds, works offline, cannot change version without you, and does not depend on the
PATHa desktop app happens to be given. If you raninitthroughnpx, the server's files are first copied to~/.turnpack/versions/<version>, because thenpxcache gets cleaned. Prefer a portable entry?init --npxwritesnpx -y turnpack@<version> serveinstead, pinned to the version.It then starts the server with that exact command and tells you whether it answered. An entry in a config file and an entry that works are different things.
It is careful with your files. Every file it edits gets a
.turnpack.bakcopy, anything you added to an existing entry is kept, a config it cannot parse is left untouched, and the file's own indentation and line endings are preserved. It never adds rules to yourCLAUDE.mdorAGENTS.md.npx turnpack uninstallremoves only whatinitadded.It leaves room for slow tests. Codex and Grok Build give an MCP tool 60 seconds by default, which is also
ship's default verify timeout.initsets the app's limit for Turnpack to 10 minutes so a long test run is not cut off by the app.
doctor checks the fences and then every app: it reads each app's config and starts the server exactly as that app would, so a stale path shows up as a failure there instead of as tools silently missing in a session. Restart your AI apps after init so they load the server.
Claude Desktop without a terminal. Each release carries turnpack.mcpb. Open it and Claude Desktop shows an install dialog and asks, with a folder picker, which project folder Turnpack may work in. It runs on the Node that ships inside Claude Desktop.
Claude Code — one command:
claude mcp add --scope user turnpack -- npx -y turnpack serveor add this to ~/.claude.json (this is what init writes):
{
"mcpServers": {
"turnpack": { "command": "npx", "args": ["-y", "turnpack", "serve"] }
}
}Codex CLI — ~/.codex/config.toml:
[mcp_servers.turnpack]
command = "npx"
args = ["-y", "turnpack", "serve"]The ChatGPT desktop app reads the same file. Add tool_timeout_sec = 600 to the block so a test run longer than a minute is not cut off.
Claude Desktop — claude_desktop_config.json (Settings → Developer → Edit Config). A chat has no project folder, so name one:
{
"mcpServers": {
"turnpack": {
"command": "npx",
"args": ["-y", "turnpack", "serve"],
"env": { "TURNPACK_ROOT": "/path/to/your/project" }
}
}
}or let init write it: npx turnpack init --client claude-desktop --root /path/to/your/project
OMP (oh-my-pi) — ~/.omp/agent/mcp.json, plus an optional status-line extension:
npx turnpack init --client omp --yesGrok Build — ~/.grok/config.toml, the same [mcp_servers.turnpack] block as Codex.
Cursor, Gemini CLI, OpenCode — init writes only the MCP server entry for these, and only when you name them:
npx turnpack init --client cursor --yesnpx turnpack init --experimental --yesOn Windows, npx is a batch file, and many apps cannot start one directly. Use "command": "cmd" with "args": ["/c", "npx", "-y", "turnpack", "serve"] in the snippets above. init avoids the problem by writing Node's own path.
Config paths, where each app gets its workspace from, and inline size caps are in docs/harness-matrix.md.
Turnpack tells the agent when to use its tools through the MCP instructions field: about 230 tokens, the same on every session in a project. In Claude Code, which hides MCP tools behind a search step by default, Turnpack asks for its three tools to be loaded with the session, so the model can call them straight away. If your agent still reaches for one-file-at-a-time tools, docs/steering.md has an optional snippet for your rules file, an optional Claude Code hook, and a one-line way to log which tools were called.
The three tools
pack: gather context in one call
Argument | What it does |
| Search the repo with a regex, or plain text. Uses ripgrep when installed, a built-in search otherwise. |
| Lines of code to return around each hit (up to 30), grouped by file with the hits marked. This is the trip parallel reads cannot save: without it the agent has to see the search result before it knows what to open. |
|
|
| List matching paths, for example |
| Include |
| Reply size cap (4,000–44,000 bytes, set per app by default). What fits is returned inline; overflow goes to private files outside your repo that the agent reads only if it needs them. |
ship: edit, test, and undo if it fails
Argument | What it does |
| Search-and-replace. Each |
| The same change as one patch, in the |
| Create, replace, rename or delete whole files. A moved file can be edited under its new name in the same call. |
| Commands that must each exit 0, for example |
| Defaults to |
Every edit is checked before anything is written: a problem in file five means files one to four are never touched. All the problems come back in one reply, each with the closest text in the file, its line numbers and the first line that differs, so the next attempt needs no re-read:
ABORTED_BEFORE_WRITE: src/invoice.js (edits[1]): search text not found. The closest text is lines 3-5 (2 of 3 line(s) identical apart from indentation):
3 | export function invoiceTotal(subtotal) {
4 | return Number((subtotal + calculateTax(subtotal)).toFixed(2));
5 | }
First difference, at line 4:
search has: " return subtotal + calculateTax(subtotal);"
file has: " return Number((subtotal + calculateTax(subtotal)).toFixed(2));"
Nothing was written.If the server finds your project's check command (a test or typecheck script in package.json, cargo check, go test, pytest, a make test target), it tells the model at the start of the session, so verify is not left out for want of knowing what to run.
The reply always starts with what is true on disk now:
SHIPPED_AND_VERIFIED · APPLIED_NO_VERIFY · ABORTED_BEFORE_WRITE · FAILED_AND_ROLLED_BACK · FAILED_ROLLBACK_PARTIAL · FAILED_KEPT_ON_DISK
When verify fails, the agent gets the beginning and the end of the output, because test failures are reported at the end. When it passes, it gets a few lines, because nobody needs 800 lines of green.
batch: one script instead of forty reads
// Which source files still import the old module, and how many functions does each have?
const hits = await ctx.grep("from \"./legacy", { literal: true });
const files = [...new Set(hits.map((h) => h.relPath))];
return files.map((f) => ({ file: f, functions: ctx.outline(f).length }));The script gets ctx.files(glob), ctx.read(path, start, end), ctx.outline(path), await ctx.grep(pattern) and await ctx.gitStatus(). It cannot write files, start processes, or see your environment variables. See Safety for how that is enforced.
How much does it save?
First, what your app already does. We read the source and documentation of Claude Code, Codex, OMP and Grok Build (docs/baselines.md). All four run independent calls in parallel, so none of them makes one tool call per round trip, and pack saves less than a naive count would suggest. Codex and OMP can already edit several files in one call. What none of the four has is a step that edits, runs the check, and puts every file back when the check fails. That is ship.
Then, a measurement. One task (rename a function used in five files, then make the tests pass), run through Claude Code 2.1.280 with Claude Sonnet 5, three times per arm, with nothing in the prompt about Turnpack:
Solved | Model round trips | Tool calls | Time | Output tokens | Cost | |
Built-in tools | 3/3 | 6 | 13 | 23.4 s | 2,044 | $0.131 |
Built-in tools, asked to batch | 3/3 | 5 | 13 | 23.9 s | 2,063 | $0.121 |
With Turnpack | 3/3 | 3 | 2 | 12.7 s | 873 | $0.084 |
Each figure is the median of three runs; the per-run numbers are in bench/results/2026-11-13-claude-code.json, and the charts on this page are drawn from that file. With Turnpack every run was the same three round trips: one pack (a search with three lines of context), one ship that made nine edits in five files and ran npm test, one closing message. The model chose those tools unprompted in all three runs.
Read it with these in mind:
It is one small task, one model, three runs per arm. It shows the direction and that the model reaches for the tools. It is not a benchmark of your work. Bigger tasks have more round trips of thinking that no tool removes.
The built-in arm was already batching. Its 13 tool calls took 6 round trips, with up to 9 calls in one. Asking it to batch harder changed nothing. The saving came from the dependent steps: search then read, and edit then test.
Other apps: less evidence. In Codex CLI 0.166, three runs out of three used
packand then oneshipcarrying all five edits and the test. We have no Codex comparison without Turnpack: on the test machine its shell sandbox could not start processes in the scratch directory, so that arm could not run the tests at all. OMP and Grok Build were not measured.
Run it on your own setup. It costs a few cents per run:
npm run bench:agents -- --agents claude,codex --arms native,turnpack --runs 3bench/agent-bench.mjs builds a throwaway project for every run, hands Turnpack to the CLI through a flag, and leaves your own configs alone. If your result differs, including "no gain", please open an issue with it.
A way to estimate your own case
time saved per task = round trips avoided × (time to first token + tokens per turn ÷ tokens per second)The chart models one scenario, a task that would take 16 round trips done in 4, across five latency profiles. That scenario is an agent that makes one tool call per round trip. None of the apps above works that way by default, so treat it as the upper end and put your own round-trip counts into the calculator:
Latency profile | One turn | 16 turns | 4 turns |
Local GPU, warm cache | 0.5s to first token + 330 tokens at 30/s = 11.5s | 3m 04s | 46s |
Fast cloud API | 2s + 225 tokens at 45/s = 7s | 1m 52s | 28s |
Frontier reasoning model | 6s + 360 tokens at 30/s = 18s | 4m 48s | 1m 12s |
Busy or cold-cache API | 15s + 400 tokens at 20/s = 35s | 9m 20s | 2m 20s |
Read it with these in mind:
The turn counts are an assumption, not a measurement. Agents that already issue tool calls in parallel make fewer round trips for reads to begin with: 6 rather than 13 in the run above. With those, expect less from
packand most of the gain fromship, because no built-in tool edits, tests and rolls back in one turn.The latency numbers are examples. Yours are easy to measure, and both the CLI and the interactive calculator take them as input:
npx turnpack estimate --ttft 2 --tok-per-turn 300 --tps 40It does not count the turns an agent spends repairing a half-applied edit, which is the cost
shipexists to remove.
The formula and every default are written out in docs/time-calculator.md. The benchmark protocol (native tools, native tools plus a batching prompt, and native tools plus Turnpack, on the same model and task) and how to read its output are in bench/README.md.
What Turnpack itself costs
These are measured, by npm run bench and npx turnpack doctor --json on Linux x64 with Node 22.23:
Measured | Notes | |
Tool schema in your context | 5,090 bytes, about 1,270 tokens | All three tools, plus about 230 tokens of instructions. In Claude Code they load with the session by design; in apps that defer MCP tools (OMP, Grok Build) only the names and instructions load until the first call. |
Server start and handshake | 50–60 ms | Local stdio, no network |
| about 8 ms | Median of 5 runs on a 42-file fixture |
| about 35 ms | Dominated by starting the verify command |
| about 80 ms | Most of it is starting the isolated process |
Safety
An agent that can edit files and run commands deserves fences. These are the ones Turnpack puts up, and where each one ends.
Fence | What it does | Where it ends |
Workspace jail | The workspace is fixed by the server, not by the model: | Some desktop apps start the server in your home directory or their own install folder and name no project. Turnpack never treats those as a workspace. There, each call has to name its project folder, the call is confined to that folder, and home, drive roots, system folders and credential folders are refused. That is the one case where the model picks the folder. Set |
Secret shield |
| It matches file names, not contents, and the agent can pass |
Read-only | The script runs in a separate process started under Node's permission model: no file writes, no child processes, no workers, reads limited to the workspace. It is handed no host objects and none of your environment variables, and it is killed at its time limit. | Node's permission model does not restrict network access on Node 22. |
Protected paths |
| |
Verify allowlist | Optional. With | The command runs your project's code, and |
Rollback | Byte-exact snapshots taken before the first write, restored when verify fails or times out, and when the server receives SIGINT or SIGTERM mid-verify. New files and the directories created for them are removed. A file that something else changed while verify was running (you saved it in your editor) is left as it is and reported, never overwritten. | Snapshots live in memory, so |
Zero dependencies |
|
Each fence has tests that attack it: sandbox escapes, path traversal, symlink escapes, Windows path aliases, allowlist smuggling, argument injection, runaway regexes, rollback under a kill signal, a save made while the tests run. They are in test/, and npx turnpack doctor re-checks the main ones on your machine. The full threat model is in SECURITY.md.
When you don't need it
A one-line fix in a file the agent already has open. One edit is one edit; there is nothing to fold.
Pasting a whole repository into a chat window. That is what Repomix is for. Turnpack is for an agent working inside a repo, a slice at a time.
A project with no fast check.
shipearns its keep when a test, type check or build takes seconds. Without averifyit is a multi-file edit with validation and nothing more.
FAQ
My agent already reads several files in parallel. What does pack add?
Less than it would for an agent that does not, and all four apps in docs/baselines.md do. Parallel calls remove round trips for reads the model already knows it wants. What they cannot remove is the trip between a search and the reads it leads to, which pack folds into one call with context. It also caps the reply size, redacts secrets, and behaves the same in apps and with models that do not parallelize. If your agent batches reads well, you will mostly notice ship.
Codex and OMP can already edit several files in one call. What does ship add there?
The test run in the same call, and putting every file back when it fails or when a write fails part-way. ship takes Codex's own patch format, so the model does not have to change how it writes edits to get that.
Will the model actually use these tools?
In the runs we measured, yes: Claude Code with Sonnet 5 and Codex CLI each chose pack and ship in three runs out of three, with nothing in the prompt about them. That is two apps, one task and default settings, so it is evidence and not a guarantee. An install with other tools or rules that push the model elsewhere may behave differently; one heavily customised OMP setup we tried solved the task without touching Turnpack. TURNPACK_LOG tells you what your own agent does, and docs/steering.md covers the optional ways to push harder.
Why not git stash or git checkout to roll back?
ship works without git, never touches your index, staging area or unrelated uncommitted changes, restores only the files it changed, and removes the files it created.
Is batch a sandbox?
It is two layers. The script gets a tiny API and no host objects, and it runs in a process that Node itself refuses to let write, spawn or read outside the workspace. Node documents its permission model as a safety net against trusted code doing something unintended rather than a defence against deliberately malicious code, and we describe ours the same way. SECURITY.md says exactly what is and is not blocked.
Does it send anything anywhere?
No. There is no network code in the server. ship runs the verify command you or the agent names, and that command can do whatever your shell can.
Does it work on Windows?
Yes, natively. CI runs the full suite on Windows, macOS and Linux. Timed-out verify commands are stopped with taskkill /T, and paths are checked across drive letters.
Prior art
Turnpack builds on ideas from Anthropic's programmatic tool calling, Cloudflare's Code Mode, context-mode, Repomix and Serena. Its own angle is narrow: three tools, a small schema, and edits that are tested before they are allowed to stay.
More
Recipes: multi-file rename, verify allowlist, native Windows, when not to use it
What Claude Code, Codex, OMP and Grok Build already do without Turnpack
License
Apache License 2.0. You may use, change and redistribute Turnpack, including in commercial products. If you redistribute it, with or without changes, keep the license and the NOTICE file with it and say which files you changed. The license grants no right to use the Turnpack name or logo, beyond saying where the software came from.
Available Tools
3 toolsbatchARead-only
Run a short read-only JS script over the repo to answer a question that would otherwise take many reads (count usages, outline every file, filter files by content). The script gets ctx.files(glob), ctx.read(path, start, end), ctx.outline(path), await ctx.grep(pattern), await ctx.gitStatus(). Return a compact summary, not raw file contents. It cannot write files or run commands.
Inputs: code (required), root, timeout_ms, allow_secrets.
packARead-only
Read and search the project in ONE call instead of several: a regex search (with the lines around each hit if you ask), any number of files (whole, a line range, or one function), glob listings and git status together. Use it whenever you need 2+ files, or a search plus what it finds. Output is size-capped; .env files and keys are redacted.
Inputs: root, files, globs, query, +7 more.
shipADestructive
Edit files and run the tests in ONE call. Applies search/replace edits or a patch, new files, moves and deletes across any number of files, then runs your verify command(s). If verify fails, every file is restored byte-for-byte and you get the failing output. If an edit cannot be applied, nothing is written and the reply shows the nearest text. Prefer it over separate edit calls (or apply_patch) plus a test run whenever a change spans files or must pass a check.
Inputs: root, edits, moves, patch, +6 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 3 tools
ship is clearly distinct (writes + verify with rollback), but pack and batch both read/search the repo — pack does regex search plus files/glob/git status, while batch does ctx.grep/ctx.read/ctx.outline/ctx.gitStatus. The descriptions offer heuristics ('2+ files' vs 'a question that would take many reads'), but the boundary between a multi-file read and a scripted read is fuzzy and an agent could easily pick either.
All three names are single lowercase words in a consistent, terse style with no case or separator mixing. The only weakness is that the words are metaphors (pack/ship/batch) that don't encode read vs. write vs. script, so the pattern is consistent but not self-describing.
Three tools is minimal but each is a deliberate composite covering a real workflow (read-many, write-and-verify, scripted analysis), so nothing feels redundant or padded. The count is slightly thin, since some actions only exist as sub-operations of a larger tool.
Reading, editing, file creation/move/delete, and running verification commands are covered, which handles core edit loops. Notable gaps remain: no standalone command execution (without an edit), no diff or log inspection beyond git status, and no git commit/branch/stage operations, which will force agents to leave the server for common repo tasks.
Maintenance
Related MCP Connectors
Git-backed platform for skills, tools, and context for AI agents
Codebase intelligence for agents: 152 structured artifacts across 21 programs, one call.
Persistent cloud workspaces for AI agents: run commands, edit files, use git and a browser.
Plain-English git for agents: 22 tools to branch, commit, push and tag. Free tier.
Related MCP Servers
- FlicenseNot gradedqualityBmaintenanceEnables AI agents to safely inspect, edit, and test code within a bounded repository environment to solve software engineering tasks and verify fixes.-
- FlicenseNot gradedqualityBmaintenanceEnables AI coding agents to retrieve focused, bounded repository context locally and read-only, reducing token usage while never modifying the repository or executing its code.-
- AlicenseNot gradedqualityCmaintenanceEnables MCP-capable coding agents to perform batched, token-efficient file and search operations with tolerant, automatically verified edits and diffs. It supports sandboxed workspace access, optional command execution, caching, and post-edit syntax/import checks.MIT
- AlicenseAqualityBmaintenanceEnables AI agents to perform exact-match, transactional multi-file edits with atomic writes, dry-run diffs, and self-correcting error diagnostics that reduce token usage.11MIT