Sandbox
Run code in the sandbox: languages and runtimes
Your agent often reads a whole file or a whole log to answer one small question. With ctx_execute, the agent writes a short script, the script runs on your machine, and only what it prints reaches the model. It runs shell, PowerShell, JavaScript, TypeScript, Python or any runtime on your PATH. The script runs as a normal process on your machine: it runs as you, with your files, your network and your own agent permissions in front. The sandbox keeps raw output out of the context. The code runs as your user with your files and network, so keep your agent's permission prompts on.
Free · Local · Private · Forever
Context Mode Engine is source-available under the Elastic License 2.0. Free to use, for all time. It runs on your machine and keeps your data in ~/.context-mode.
Key facts
- What it is
- The
ctx_executetool of Context Mode Engine. It runs code in your project folder and returns only what the code prints, at most 16,384 B. - Who it is for
- Anyone whose agent reads big files, logs or JSON to find one fact.
- Agents
- Claude Code, Codex, Gemini CLI, Qwen Code, Copilot CLI, VS Code, Kiro, ZCode, OpenCode and Pi.
- Measured result
- A 214.0 KB JSON payload of 30 Next.js issues reached the model as 0.8 KB, median of 5 runs, plugin benchmark dated 2026-10-31 in its raw file.
- Scope
- Five named languages plus any runtime on your PATH. Default and maximum timeout 600,000 ms. The code runs as you, with your own agent permissions in front.
One question, one whole file
You ask how many TODO lines are in src. The agent opens every file and reads it into the context. A lint report or a test log goes the same way. The answer is one line, and the context window fills with the rest.
Ask for a short script
Ask the agent to use ctx_execute. The agent writes a few lines of code that find the answer. Context Mode Engine runs the code in your project folder and sends back only what the code prints.
{ "language": "shell", "code": "grep -c TODO -r src" }
The call takes these fields: language, code, and the optional file, intent, timeoutMs and background. With file, the code reads the path from the CTX_FILE variable. With intent, the reply holds the parts of the output that match it, and the full output goes to the index.
Thinking in Code: see it on four jobs
This is Thinking in Code. The agent writes a script, the script reads the whole output, and the model reads only what it prints. The numbers come from the plugin bench.
Try it
Fetch https://jsonplaceholder.typicode.com/photos. Which photo has the longest title (give its id and title), and how many photos have a title that contains the word "est"?
⏺ context-mode - ctx_execute (MCP)(language: "javascript",
code: "const res = await fetch("https://jsonplaceholder.typicode.com/photos");
if (!res.ok) throw new Error("HTTP " + res.status);
const photos = await res.json();
let longest = null;
for (const p of photos) {
if (!longest || p.title.length > longest.title.length) longest = p;
}
const withEst = photos.filter(p => p.title.includes("est")).length;
const ties = photos.filter(p => p.title.length === longest.title.length).map(p => p.id);
console.log(JSON.stringify({ total: photos.length, longest: { id: longest.id, title: longest.title,…
intent: "longest photo title and count of titles containing \"est\"")
⎿ exit 0 · 239 B
{
"total": 5000,
"longest": {
"id": 653,
"title": "temporibus commodi et fugit doloremque reprehenderit exercitationem necessitatibus au…
"length": 86
},
"longestTieIds": [
653
],
"titlesContainingEst": 892
… +1 lines
239 B produced, 254 B returned
⏺ context-mode - ctx_execute (MCP)(language: "javascript",
code: "const photos = await (await fetch("https://jsonplaceholder.typicode.com/photos")).json();
const wholeWord = photos.filter(p => /\best\b/.test(p.title)).length;
console.log(JSON.stringify({ wholeWordEst: wholeWord, substringEst: photos.filter(p => p.title.incl…
intent: "count titles with \"est\" as a whole word vs substring")
⎿ exit 0 · 40 B
{"wholeWordEst":597,"substringEst":892}
40 B produced, 54 B returned99.96% of the bytes stay out of the chat. One live run on 2026-11-02: Claude Code 2.1.312, claude-haiku-5-5, Context Mode 2.0.0-next.26. Produced: what the code printed in the sandbox. Returned: what the agent read. Data and the stream it copies
Here is a Linux syslog sample: https://raw.githubusercontent.com/logpai/loghub/master/Linux/Linux_2k.log. How many authentication failures does it contain, and which 3 remote hosts caused the most?
⏺ context-mode - ctx_execute (MCP)(language: "shell",
code: "d=$(mktemp -d) && cd \"$d\" && curl -sSfL -o Linux_2k.log https://raw.githubusercontent.com/…
intent: "authentication failure counts and top rhost values")
⎿ exit 0 · 273 B
lines: 1999
auth failure lines: 490
--- failure lines with non-empty rhost, top 3 ---
80 rhost=150.183.249.110
23 rhost=n219076184117.netvigator.com
23 rhost=207.243.167.114
--- distinct rhosts among failures ---
48
--- failure lines with empty rhost ---
1
273 B produced, 288 B returned
⏺ context-mode - ctx_execute (MCP)(language: "shell",
code: "cd \"$(ls -td /tmp/tmp.* 2>/dev/null | head -1)\" 2>/dev/null || cd \"$TMPDIR\"; f=$(ls -t *…
⎿ exit 0 · 0 B
0 B produced, 14 B returned
⏺ context-mode - ctx_execute (MCP)(language: "shell",
code: "d=$(mktemp -d) && cd \"$d\" && curl -sSfL -o Linux_2k.log https://raw.githubusercontent.com/…
⎿ 80 rhost=150.183.249.110
23 rhost=n219076184117.netvigator.com
23 rhost=207.243.167.114
20 rhost=60.30.224.116
15 rhost=195.129.24.210
14 rhost=218.188.2.4
168 B produced, 168 B returned99.7% of the bytes stay out of the chat. One live run on 2026-11-02: Claude Code 2.1.312, claude-haiku-5-5, Context Mode 2.0.0-next.26. Produced: what the code printed in the sandbox. Returned: what the agent read. Data and the stream it copies
What are the top 10 stories on the Hacker News front page right now? Give title, points and domain for each.
⏺ context-mode - ctx_execute (MCP)(language: "python",
code: "import subprocess, re, html
out = subprocess.run(["curl","-sL","--max-time","30","https://news.ycombinator.com/"],capture_outpu…
rows = re.findall(r'<tr class="athing[^"]*" id="(\d+)">.*?<span class="titleline"><a href="([^"]+)"…
scores = dict(re.findall(r'<span class="score" id="score_(\d+)"[^>]*>(\d+) points?</span>', out))
for i,(id_,href,title,dom) in enumerate(rows[:10],1):
print(f"{i}. {html.unescape(re.sub('<[^>]+>','',title))} | points: {scores.get(id_,'?')} | doma…
print("rows found:", len(rows))")
⎿ 1. Show HN: Wikihack – HackerTube, but for Wikipedia articles mentioned on HN | points: 93 | domain…
2. Show HN: HackerBooks – HackerTube, but for books mentioned on HN | points: 1305 | domain: hacker…
3. Postgres 19 is late because so many more bugs are being found now | points: 348 | domain: rhaas.…
4. F/OSS Comics #13: BSD Unix, Part 3 – The Beginning of BSD Unix | points: 100 | domain: fosscomic…
5. HackerTube: YouTube built from videos recommended by HN | points: 2512 | domain: karpathy.bearbl…
6. Ask HN: Which TV do you recommend for privacy? | points: 329 | domain: none (HN internal)
7. Mystery of 60-Second Fluctuations in Power Grids Solved | points: 103 | domain: fz-juelich.de
8. Bones may release proteins that slow aging and extend life span | points: 51 | domain: science.o…
9. Trigger.dev customer environment variables exposed | points: 73 | domain: trigger.dev
10. Nibnib: Image compression with extreme decompression speed | points: 135 | domain: github.com/r…
rows found: 28
1,064 B produced, 1,064 B returned95.7% of the bytes stay out of the chat. One live run on 2026-11-02: Claude Code 2.1.312, claude-haiku-5-5, Context Mode 2.0.0-next.26. Produced: what the code printed in the sandbox. Returned: what the agent read. Data and the stream it copies
Which of the last 300 vitejs/vite commits fix the server, and which are v8.3 releases?
⏺ context-mode - ctx_batch (MCP)(commands: ["git shortlog -sn -300 HEAD","git log --stat --format='commit %h %an: %s' -300"],
queries: ["fix(server)","release: v8.3"])
⎿ ## fix(server)
docs/guide/troubleshooting.md | 14 ++++++++++++++
1 file changed, 14 insertions(+)
commit 6894f5c kingmaker: fix(server): handle file watcher errors without crashing (#23503)
packages/vite/CHANGELOG.md | 32 ++++++++++++++++++++++++++++++++
packages/vite/package.json | 2 +-
2 files changed, 33 insertions(+), 1 deletion(-)
commit b28db28 owenn: fix(server): match static aliases on path boundaries (#23643)
packages/vite/CHANGELOG.md | 8 ++++++++
packages/vite/package.json | 2 +-
2 files changed, 9 insertions(+), 1 deletion(-)
commit c3e06f9 翠: fix(server): store ids to `safeModulePaths` rather than URLs (#23656)
… +174 lines
318,426 B produced, 11,688 B returned96.3% of the bytes stay out of the chat. One live run on 2026-11-03: Node MCP client (batch-call.mjs) v26.8.1 over MCP, drawn as Claude Code prints an MCP call, Context Mode 2.0.0-next.34. Produced: what the code printed in the sandbox. Returned: what the agent read. Data and the stream it copies
Read it: the whole output goes into the chat. Write code: the output stays in the sandbox, and the chat gets the answer.
Languages and runtimes
Pick one of five named languages. Each call looks up the runtime on your PATH, so a runtime you install shows up on the next call.
- shell:
sh. On Windows, Git Bash from your Git for Windows install. - powershell:
pwsh,pwsh.exeorpowershell.exe. - javascript and typescript:
node. Node 24.15.0 or later runs the TypeScript file. - python:
python3, thenpython. On Windows,python.exe,py.exe, thenpython. - Any other runtime: pass its name as the language, for example
rubyorbash. Shells such as bash, zsh and fish get the code with-c.
When PATH lacks the runtime, the call returns NO_RUNTIME with the language name. Install the runtime, and the next call finds it.
{ "language": "shell", "code": "grep -c TODO -r src" }Runtime: sh. On Windows, Git Bash.
The agent reads only what the code prints.
{ "language": "powershell", "code": "(Select-String -Path src\* -Pattern TODO).Count" }Runtime: pwsh, pwsh.exe or powershell.exe.
The agent reads only what the code prints.
{ "language": "javascript", "code": "console.log(require('fs').readdirSync('src').length)" }Runtime: node.
The agent reads only what the code prints.
{ "language": "typescript", "code": "const n: number = 42; console.log(n)" }Runtime: node, version 24.15.0 or later.
The agent reads only what the code prints.
{ "language": "python", "code": "import json; print(len(json.load(open('data.json'))))" }Runtime: python3, then python.
The agent reads only what the code prints.
Any other runtime on your PATH works too: pass its name as the language.
What comes back to the model
The reply holds what the code prints, at most 16,384 B, cut on a whole character. When the output is bigger, the reply shows a preview of at most 4,096 B. The Engine keeps the full output in the project index and ends the reply with a ctx_search call, so the agent finds the rest on demand. Colour codes stay off, so the reply holds plain text.
Timeout and long jobs
The default and maximum timeout is 600,000 ms, ten minutes. Set timeoutMs for a shorter run. At the timeout, the Engine stops the whole process tree: the process and every child it started. For a server or a watcher, set background to true. The call then starts the process and returns its process id.
Who runs the code
Runs as you, in your project, with your own agent permissions in front. Only what the code prints reaches the model. Your agent asks you before each tool call, as it does today. Read more on the security page.
What you get
In the plugin benchmark dated 2026-10-31, the agent ran a short script over a JSON payload of 30 Next.js issues. The raw payload was 214.0 KB, and 0.8 KB reached the model. The number is the median of 5 runs on an Apple M1 Pro with Node 26.8.1, and it counts bytes of tool output (row on GitHub). Run it yourself with cd bench && node run.mjs --runs 5 in the plugin repo.
Prompts to give your agent
Paste one into your agent. Each prompt shows in full.
Run the test suite with ctx_execute and print only the names of the tests that need a fix.
Use ctx_execute to count the TODO lines in src and print only the total.