Context Mode: Put the Note on the Agent's Desk, Not the File
context-mode processes an agent's raw tool output in a separate process and hands back only the result. On a 484 KB PHP log it returned 809 bytes; but search does not count, the savings meter flatters itself, and its "sandbox" is not an OS sandbox.
This post is also available in Turkish →
Think of an agent's context window as a desk. However big the desk, if you empty every folder from the archive onto it, the page you actually need ends up at the bottom. A good clerk leaves the folder in the archive and brings a three-line note to the desk: "29 fatals, all from line 27 of the same file."
When I wrote up my PHP 8.5 upgrade, 568 deprecation lines piled up in half an hour, every one of them the same sentence. Had I handed that log to an agent with "have a look", all 568 lines would have landed on the desk. This week's radar entry, context-mode, wants to be that clerk. This time I actually installed it, measured it against a PHP-FPM style log, and found two things I did not expect.
What is context-mode?#
In one sentence: an MCP server plus a set of hooks that processes a coding agent's raw tool output (logs, test runs, API responses, web pages) in a separate subprocess, sends the model only what that process prints, and puts large outputs into a searchable SQLite FTS5 index.
It is not tied to one agent. According to the README it supports eighteen clients, including Anthropic's Claude Code, OpenAI's Codex CLI, Google's Gemini CLI and Antigravity, Cursor, GitHub Copilot, OpenCode and Zed. The depth of that support varies, and we will get there.
How it works: bring back the answer, not the output#
The core idea is what the project calls "Think-in-Code": instead of reading a 500 KB file and counting in its head, the agent writes the code that counts, and only sees the result. There are eleven MCP tools for this; three do the heavy lifting:
ctx_execute: runs the given code (JavaScript, Python, PHP, shell and more) in a separate process and returns only stdout.ctx_execute_file: loads a file into aFILE_CONTENTvariable and runs your code over it.ctx_search: BM25 search over large outputs that have been indexed.
The hooks step in when the agent reaches for a large output through its own tools (a shell command, a web request) and route it to these tools instead.
I tried it: a 484 KB PHP log#
In Claude Code the install is a couple of slash commands; in Codex it is one CLI line (for hooks, the README also asks for plugin_hooks = true and hooks = true under [features] in config.toml):
# Inside Claude Code
/plugin marketplace add mksglu/context-mode
/plugin install context-mode@context-mode
/context-mode:ctx-doctor
# Codex CLI
codex plugin marketplace add mksglu/context-mode
# MCP only, no hooks (Claude Code example)
claude mcp add context-mode -- npx -y context-mode
I did not measure from inside an agent. I installed v1.0.169 from npm (Node 22, PHP 8.3 CLI) and called the MCP server directly with a small JSON-RPC client. So I measured what the tools return, not how well the hooks steer an agent.
The test data is synthetic: a 3,000-line, 495,838-byte PHP-FPM error log generated with a fixed seed. It includes that familiar "Using null as an array offset" line from the PHP 8.5 piece. I asked the same question four ways: "What is in here, and where do the fatals come from?"
| Route | Returned to the model | What it saw |
|---|---|---|
| Reading the file directly | 495,838 bytes | Everything |
ctx_execute_file + a PHP summary |
809 bytes (203 ms) | Five sources, 29 fatals, exact counts |
ctx_execute + intent ("PHP Fatal error PDOException") |
1,561 bytes | 5 previews, two of them fatals |
ctx_execute without intent |
268 bytes | Only "indexed" |
Here is the body I sent to ctx_execute_file (the tool fills FILE_CONTENT; to run it from the command line, prepend <?php and $FILE_CONTENT = file_get_contents($argv[1]);. It passes php -l):
$satirlar = explode("\n", trim($FILE_CONTENT));
$say = [];
foreach ($satirlar as $s) {
if (preg_match("/\] (PHP [A-Za-z ]+?):\s+(.+?) in (\S+?)(?: on line |:)(\d+)/", $s, $m)) {
$anahtar = $m[1] . " | " . basename($m[3]) . ":" . $m[4];
$say[$anahtar] = ($say[$anahtar] ?? 0) + 1;
}
}
arsort($say);
echo count($satirlar), " satir, ", count($say), " farkli kaynak\n";
foreach ($say as $k => $n) { echo str_pad((string)$n, 6, " ", STR_PAD_LEFT), " ", $k, "\n"; }
The note that reached the desk (output kept as it ran, "satir" is "lines", "farkli kaynak" is "distinct sources"):
3000 satir, 5 farkli kaynak
2065 PHP Deprecated | Memo.php:88
548 PHP Warning | Liste.php:41
281 PHP Notice | Csv.php:112
77 PHP Warning | Servis.php:54
29 PHP Fatal error | Baglanti.php:27
From 495,838 bytes to 809. But the real hero of that number is not the tool, it is those eleven lines of PHP. The clerk writes the right note only when you ask the right question.
When does it help, and when does it not?#
Fact: long test output, large JSON responses, server logs, documentation pages. The gap grows with the session, because every byte that never reaches the desk does not take up space in later steps either. If you run the 4,096-token window I described in the local LLM chapter, you will feel it even more.
Fact: it does not help with a file you are about to edit. The agent needs the exact text to change it, and the tool's own description says so.
Hard Truth 1, search does not count: on the intent route, BM25 gave me five previews: two fatals, two deprecations, one notice. It did not tell me how many fatals there were, and it cannot. Counting, grouping and totals belong in code. Search answers "where does it appear", not "how many".
Hard Truth 2, the silent index: produce a large output without an intent and the model sees only "Indexed 1 sections, use ctx_search to query". If the agent does not think to search, the information never reaches the desk.
Hard Truth 3, the meter writes its own timesheet: after four calls, ctx_stats told me "974 KB saved, 99.5% reduction, ~$1.24 saved (Opus)". There was one 484 KB file in play; the meter adds up each call separately as "what would have arrived without me". Do not treat that figure as your evidence; measure your own sessions. The README's "315 KB becomes 5.4 KB, 98%" is also the project's own number.
Watch the word "sandbox": the README's security section says it plainly: ctx_execute runs arbitrary code and inherits the process's filesystem access; it is not a full OS sandbox. CLIs such as gh and aws inherit their credentials too. ctx_execute_file refuses reads outside the project root, but that applies to the file-reading tool only. Treat approving an execution tool as approving arbitrary code.
No hook, just a polite request: it uses hooks in Cursor, Codex and Claude Code, but not to the same depth. Codex's PreToolUse hook currently supports deny rules only and cannot rewrite input. Cursor's validator rejects the sessionStart hook, so there is no session restore there. Zed and the Antigravity IDE have no hooks at all; routing relies on instructions in AGENTS.md or GEMINI.md, and the README puts that at "~60% compliance". In Vibe Coder #4.2 I wrote that a rule file is context and the hook is what guards the door; that percentage is the same sentence written as a number.
Maintenance and who built it#
| Item | Status (13 October 2026) |
|---|---|
| Licence | Elastic License 2.0 (ELv2); not on the OSI list of approved licenses |
| Latest release | v1.0.169 (npm, 29 June 2026) |
| Development | last commit on the next branch 28 September 2026; main only gets automated stats commits |
| Stars | about 26.9k |
| Open issues / PRs | 173 / 174 |
| Requirements | Node.js 22.5 or later (or Bun); Linux below 22.5 is unsupported |
| Data | README says "no telemetry"; if you configure platform.json for the team dashboard, every event is sent to that endpoint |
The project is built and maintained by Mert Köseoğlu, and the copyright in LICENSE is his. ELv2 lets you use, modify and redistribute it in your own work, but not offer it to third parties as a hosted or managed service. The source is available, but it does not meet the open source definition; if it goes into a client project, that distinction matters. A hosted analytics dashboard for teams (Insight) is also offered.
Quick comparison with the alternatives#
| Tool | Layer | Licence | Latest release |
|---|---|---|---|
| context-mode | MCP + hooks; runs code in a separate process, indexes large output | ELv2 | v1.0.169 (29.06.2026) |
| RTK | Rust CLI proxy that rewrites shell commands and filters their output | Apache-2.0 | v0.51.0 (02.10.2026) |
| Headroom | Library, proxy and MCP; compresses tool output, keeps the original locally | Apache-2.0 | v0.40.0 (05.10.2026) |
| claude-mem | Cross-session memory (hooks, SQLite, vector search) | Apache-2.0 | v13.37.0 (12.10.2026) |
My call: if your problem is noise from commands like git, composer and phpunit, RTK is narrower and ships as a single binary. If your problem is the agent reading large data and doing the maths in its head, context-mode's "write the code, bring back the answer" approach fits that job exactly. If licensing matters to you, all three alternatives are Apache-2.0.
In the field: where would it fit in my work?#
My daily material is exactly what this tool likes: PHP-FPM logs, MariaDB's ANALYZE FORMAT=JSON output, long PHPUnit runs. If I tried it, log reading would come first, because that is where a wrong summary costs the most. On two conditions: execution tools stay off auto-approve, and I trust my own measurements over the meter.
A clerk is worth exactly as much as the accuracy of the note. Just remember you also handed them the keys to the archive.
Comments
0 comments
Leave a comment