Skip to content

igorbannicov/read-guard

v1.0.0MIT

Save context by blocking large whole-file reads in Codex shell and file tools.

Read Guard for Codex

A local Node.js hook that keeps large file reads out of Codex's context. No dependencies, service, or API key.

The Claude version intercepts Read. Codex normally uses a shell, so this version intercepts Bash (including exec_command) and recognizes common PowerShell and Unix read commands. It also handles Read, read_file, and MCP tools named mcp__<server>__read_file or mcp__<server>__read_text_file.

For text files over 400 lines, it denies whole reads and sections larger than 400 lines, with a suggestion to search with rg -n and read a bounded section. A small file can still be read whole.

# Blocked for a large file
Get-Content -LiteralPath 'Source/PluginEditor.cpp'

# Allowed
rg -n 'paint' Source/PluginEditor.cpp
Get-Content -LiteralPath 'Source/PluginEditor.cpp' | Select-Object -Skip 100 -First 100
# Blocked for a large file
cat Source/PluginEditor.cpp

# Allowed
sed -n '101,200p' Source/PluginEditor.cpp
head -n 100 Source/PluginEditor.cpp

Install

Requires Node.js 18+ on the PATH and a Codex version with lifecycle hook support. The repository includes .agents/plugins/marketplace.json, pointing to this plugin at the repository root.

  1. Open the read-guard-codex repository as a project in the desktop app.
  2. Open the Plugins directory, select the Read Guard for Codex local marketplace, and install read-guard.
  3. Review and trust its PreToolUse hook in the hook controls, then start a new chat. In the CLI, /hooks opens hook review.

If the local marketplace is not listed, register the repository with a CLI that supports marketplaces:

codex plugin marketplace add C:\Users\bannicov\Projects\read-guard-codex

Then refresh the desktop app's Plugins directory and install from that marketplace. Installation copies the plugin into Codex's cache. After editing the source, refresh/reinstall it to update the installed copy. Installing does not automatically trust hooks. This repository's scripts do not install themselves or change your settings.

Alternatively, use the hook directly: merge the following entry into ~/.codex/hooks.json, preserving existing hooks. Use the absolute path to your checkout; forward slashes also work on Windows.

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "^(Bash|exec_command|shell_command|shell|Read|read_file|mcp__.*__(read_file|read_text_file))$",
        "hooks": [
          {
            "type": "command",
            "command": "node \"C:/Users/bannicov/Projects/read-guard-codex/hooks/read-guard.js\"",
            "timeout": 10,
            "statusMessage": "Checking file read size"
          }
        ]
      }
    ]
  }
}

Use either plugin installation or direct configuration to avoid running the same guard twice. Hook discovery and trust are described in the official OpenAI hook documentation. Package and marketplace formats follow OpenAI's plugin documentation.

Settings and stats

Set environment variables in the environment that launches Codex:

VariableDefaultPurpose
READ_GUARD_LINES400Positive integer limit per read
READ_GUARD_LOG$CODEX_HOME/read-guard/log.jsonlOverride the log file

CODEX_HOME defaults to ~/.codex. Claude's log stays separate. The log contains timestamps, session IDs, absolute file paths, and estimated token counts; file contents are not logged.

From the repository root, run:

node hooks/stats.js

Savings use roughly four characters per token: one denied file per session, minus later attempted bounded reads of that file in that session. Repeated parts count again, and savings are clamped to zero per file/session. Period totals group reads by their first denial date. Bad log lines are ignored. Search output, other tools, failed commands, output truncation, and file changes are not fully accounted for; these estimates are not billing or measured model usage. No savings are claimed for unrecognized commands.

Coverage

Recognizes literal paths with Get-Content/gc/cat/type, head, tail, and numeric sed -n 'A,Bp' reads. Bounds include -TotalCount, -Tail, Select-Object -First/-Last, and -Skip followed by -First. An offset or -Skip alone does not establish a bound; -ReadCount only controls batching. It inspects multiple reads in a shell call and denies the entire call if any recognized read exceeds the limit. It handles literal cd changes and common bash -lc or PowerShell -Command wrappers.

This is an advisory context guard with a small command recognizer, not a shell interpreter or access control. Variables, globs, advanced quoting/escaping, scripts, Python/Node reads, arbitrary aliases, shell functions, input redirection, other MCP schemas, and interactive write_stdin reads can fall outside coverage. Unknown pipeline transforms do not establish a bound. max_output_tokens is not treated as a line bound. Binary files, images, PDFs, notebooks, and unreadable/missing paths pass through. Text is decoded as UTF-8 or BOM-marked UTF-16LE. The hook reads recognized files locally to count lines; large files still incur local I/O.

Development

node --test test/read-guard.test.js

Tests use a temporary log and fixtures, without changing your actual Codex data. They exercise the command recognizer, deny/pass behavior, hook stdin/stdout protocol, and savings accounting. They do not replace an installation and trust review in the desktop app.

MIT; see the repository's LICENSE.