The File Read Gate is back, on by default
When Claude Code tries to Read a whole code file that claude-mem already has observations about, the Read is now blocked. Claude gets the file's observation timeline instead, along with cheaper ways to get what it needs:
- Current code:
smart_outlinefor the file's symbols and line numbers, thensmart_unfoldfor the ones it needs. - Past work:
get_observationsfor the observations listed. - Exact lines, for example before an Edit: a targeted
Readwithoffset/limit. Partial reads are always allowed, and they satisfy Edit's read-before-edit rule, so editing never deadlocks.
The block was first built in April, but it never shipped. It broke Edit, so the same day it was softened to "allow + context", and v12.0.0 shipped that version. In July the hook was made asynchronous, and an asynchronous hook can't block anything. This release brings the block back, with the Edit problem solved by letting targeted Reads through. (#4549)
When it blocks. Every one of these must hold:
- It's the Claude Code main session (not Codex, Kimi, Qwen Code or subagents).
- The file is code that
smart_outlineparses (not markdown, YAML, TOML or JSON). - The file is inside the workspace, by the same symlink-aware rule the smart tools use.
- The file is at least 1,500 bytes, and its newest observation is newer than the file.
- The Read would return the whole file.
- The tree-sitter CLI that powers the smart tools is installed.
Turn it off with "CLAUDE_MEM_FILE_READ_GATE_ENABLED": "false" in ~/.claude-mem/settings.json, the env var of the same name, or the viewer's Block full-file reads toggle (Advanced → Save). With the gate off, Reads go through and the timeline is still added as context. CLAUDE_MEM_DISABLE_FILE_CONTEXT=1 turns off the whole hook.
Hook changes:
- The PreToolUse
Readhook is synchronous again (15 s cap, 3 s worker budget). It fails open: a slow or missing worker never blocks a Read. - It no longer answers
allow, so Claude Code's own permission prompts apply as usual.
If smart_outline says "Could not parse" for every file, your install's tree-sitter CLI was never provisioned. Run npx claude-mem repair. Until then the gate stays dormant rather than sending Claude to tools that can't parse.
Proof: npm run eval:read-gate runs real Claude Code against two isolated, seeded workers, one with the gate on and one with it off.
- Gate on: every whole-file Read was denied and no run ever received the whole file. Answers were correct via
smart_outline/smart_unfold, and edits changed only the intended line. - Gate off: Reads went through normally.
- Every verdict passed on both
claude-sonnet-5-5(3 runs per case) andclaude-opus-5-5(2 runs per case).
Also new
- Opt-in worker idle exit: set
CLAUDE_MEM_IDLE_EXIT_SECto have the worker shut down gracefully after that many seconds with no session activity, queued work, host traffic or AI calls. The next hook starts it again. The default,0, keeps today's behavior. (#4524)
Fixes
- Worker: the processing-status broadcast and its log no longer flood when a signed-out observer cycles one batch. (#4525)
- Transcripts:
- Import:
- File context: malformed imported file metadata is isolated. (#4538)
- Context: direct settings counts are validated before querying memory. (#4539)
- Smart read: multiline Go receiver identities and empty-query relevance are preserved. (#4546)
- Work state: state fields named like prototype properties are preserved. (#4535)
- Viewer:
- Docs: the Codex install command uses the valid
--ide codex-cliflag. (#4548)