<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Claude Code Hook Limitations</title>
  <link href="https://framework.boucle.sh/limitations.html" rel="alternate"/>
  <link href="https://framework.boucle.sh/limitations-feed.xml" rel="self"/>
  <id>https://framework.boucle.sh/limitations-feed.xml</id>
  <updated>2026-08-17T00:00:00Z</updated>
  <author><name>Boucle</name></author>
  <entry>
    <title>[HIGH] Piped `-p` prompts can be recorded but omitted from the model request.</title>
    <id>https://framework.boucle.sh/limitations.html#piped-print-prompt-can-be-dropped-before-model-request</id>
    <link href="https://framework.boucle.sh/limitations.html#piped-print-prompt-can-be-dropped-before-model-request"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.233 Windows headless setup intermittently enqueued and persisted a full piped prompt in the transcript and last-prompt preview, but the first API request behaved as if the user turn were empty. Failing runs exited 0 in one or two turns with tiny ambient-context responses, while usage telemetry showed only 2 input tokens for the user request despite the same wrapper and prompt bytes succeeding minutes apart. Transcript inspection alone can therefore falsely reassure automation owners that the prompt reached the model.</summary>
    <category term="Core &amp; session management"/>
  </entry>
  <entry>
    <title>[HIGH] `grep` shell shim can silently skip binary and ignored files.</title>
    <id>https://framework.boucle.sh/limitations.html#grep-shell-shim-can-silently-skip-binary-and-ignored-files</id>
    <link href="https://framework.boucle.sh/limitations.html#grep-shell-shim-can-silently-skip-binary-and-ignored-files"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.233 Linux and WSL2 setup found that Bash tool calls shadowed system `grep` with a shell function that runs the bundled ugrep using flags such as `-I` and `--ignore-files`. Files containing NUL bytes and files matched by `.gitignore` were skipped with exit status 1 and no stdout or stderr, making the result indistinguishable from a genuine no-match search. The report also notes that `which grep` can still point at `/usr/bin/grep`, so an agent investigating the failure may see contradictory evidence while carrying forward a false conclusion that searched code does not exist.</summary>
    <category term="Tool behavior"/>
  </entry>
  <entry>
    <title>[HIGH] Sandboxed Bash helper process can OOM during a slow command.</title>
    <id>https://framework.boucle.sh/limitations.html#sandboxed-bash-helper-can-oom-during-slow-command</id>
    <link href="https://framework.boucle.sh/limitations.html#sandboxed-bash-helper-can-oom-during-slow-command"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.233 Linux session in an unprivileged LXC found that an ephemeral per-tool-call helper process named `claude.exe` grew to 11.6 GB anonymous RSS in about two minutes while a sandboxed Bash pipeline was running. The interactive Claude Code process stayed around 430 MB, the input JSONL files totaled under 14 MB, and the known triggering command was a slow `grep -o -i` bounded-repetition pattern piped to `head` that hit the Bash tool timeout. The kernel OOM kill occurred inside the service cgroup, and with systemd `OOMPolicy=stop` it stopped the parent Claude service before restart recovered it.</summary>
    <category term="Performance &amp; resource usage"/>
  </entry>
  <entry>
    <title>[HIGH] Cloud routine egress allowlist domains may not reach the sandbox proxy.</title>
    <id>https://framework.boucle.sh/limitations.html#cloud-routine-egress-allowlist-not-propagated-to-sandbox</id>
    <link href="https://framework.boucle.sh/limitations.html#cloud-routine-egress-allowlist-not-propagated-to-sandbox"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code cloud routine found that domains added to the account-level `Allow network egress` additional-domains setting did not appear in the routine sandbox&#x27;s proxy allowlist a week later. Both scheduled fires and a manual `RemoteTrigger run` still returned `EGRESS_BLOCKED` from `WebFetch` and 403 CONNECT failures from `curl`, while the in-sandbox `$HTTPS_PROXY/__agentproxy/status` endpoint confirmed the expected domains were absent. The trigger API exposed prompt, allowed tools, MCP connections, and schedule state, but no sandbox network policy field that could be updated or inspected for repair.</summary>
    <category term="Remote &amp; cloud"/>
  </entry>
  <entry>
    <title>[HIGH] /permissions navigation can become inert after auto-mode denials.</title>
    <id>https://framework.boucle.sh/limitations.html#permissions-menu-denial-state-can-block-human-repair</id>
    <link href="https://framework.boucle.sh/limitations.html#permissions-menu-denial-state-can-block-human-repair"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.221 macOS session found that `/permissions` rendered but stopped responding to arrow-key navigation after recent auto-mode classifier denials in a long-running session. The user could not reach `Add a new rule...` from the discoverable permission UI, while a fresh session on the same project navigated normally and could add the needed allow rule. This makes denials harder to repair exactly when the human is supposed to recover from them, especially because the agent itself should not edit `.claude/settings.json` to grant its own permissions.</summary>
    <category term="Permission system"/>
  </entry>
  <entry>
    <title>[HIGH] PreToolUse hooks can read stale current-turn text from transcript_path.</title>
    <id>https://framework.boucle.sh/limitations.html#pretooluse-transcript-path-can-lag-current-turn</id>
    <link href="https://framework.boucle.sh/limitations.html#pretooluse-transcript-path-can-lag-current-turn"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code hook setup found that `PreToolUse` hooks that inspect the just-written assistant text by parsing `transcript_path` can race the transcript writer and read an earlier turn or draft instead of the text that immediately preceded the tool call. Stop-family hooks have `last_assistant_message` as a race-free field, but `PreToolUse` receives only tool metadata plus common fields, so content or compliance gates that must decide before a tool runs have no equivalent current-message source. The observed effect was a false block caused by matching stale transcript content rather than the clean final text.</summary>
    <category term="Hook behavior &amp; events"/>
  </entry>
  <entry>
    <title>[HIGH] PermissionRequest hooks can stop firing after a Windows CLI restart.</title>
    <id>https://framework.boucle.sh/limitations.html#permissionrequest-hook-can-stop-firing-after-windows-restart</id>
    <link href="https://framework.boucle.sh/limitations.html#permissionrequest-hook-can-stop-firing-after-windows-restart"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.233 Windows session found that a working `PermissionRequest` hook stopped firing for Bash, PowerShell, and Write requests, produced no new hook log entries, showed no fallback confirmation prompts, and stayed inert after a full CLI restart. The hook script and `.claude/settings.json` registration still looked valid and manual invocation of the hook worked, but live tool calls no longer reached it. The restart also showed a new auto-mode setup prompt while the settings UI still reported manual permission mode, leaving users without a reliable in-session signal that the PermissionRequest safety layer was inactive.</summary>
    <category term="Permission system"/>
  </entry>
  <entry>
    <title>[HIGH] PreToolUse and PostToolUse hooks lack live background task status.</title>
    <id>https://framework.boucle.sh/limitations.html#pre-post-hooks-lack-live-background-task-registry</id>
    <link href="https://framework.boucle.sh/limitations.html#pre-post-hooks-lack-live-background-task-registry"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.233 setup found that `PreToolUse` and `PostToolUse` hooks do not receive the live `background_tasks` registry that `Stop` hooks receive. A hook that tracks background Bash work from local marker files can see a `&lt;task-notification&gt;` in the transcript only indirectly; no hook event fires when the task completes, and later Pre/Post payloads do not say that the task has reached a terminal state. Unless the agent explicitly calls `TaskOutput` or the session reaches `Stop`, hook-based tooling can keep warning or blocking as if completed background work were still live for every subsequent tool call in the same turn.</summary>
    <category term="Hook behavior &amp; events"/>
  </entry>
  <entry>
    <title>[HIGH] SubagentStop matcher can be bypassed for internal forks with empty agent_type.</title>
    <id>https://framework.boucle.sh/limitations.html#subagentstop-matcher-bypassed-on-empty-agent-type</id>
    <link href="https://framework.boucle.sh/limitations.html#subagentstop-matcher-bypassed-on-empty-agent-type"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.233 setup found that a SubagentStop hook group with a matcher naming specific agent types can still run for internal forks whose agent_type is the empty string. Because the hook gatherer treats a falsy match key as a reason to skip filtering, matcher-scoped groups are included wholesale rather than excluded. In one measured session, 115 of 129 dispatches of an agent-scoped LLM judge came from empty-agent_type internal forks, creating token waste and risking false blocking verdicts against healthy background work.</summary>
    <category term="Hook behavior &amp; events"/>
  </entry>
  <entry>
    <title>[HIGH] Headless skill preamble failure can report success with zero turns.</title>
    <id>https://framework.boucle.sh/limitations.html#headless-skill-preamble-failure-reports-success</id>
    <link href="https://framework.boucle.sh/limitations.html#headless-skill-preamble-failure-reports-success"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.233 macOS setup found that headless `claude -p &quot;/skill&quot; --output-format json` can abort before the first model turn when the invoked skill&#x27;s `SKILL.md` contains a failing `!` dynamic-injection preamble. The command exits 0 and returns JSON shaped as success with `is_error:false`, `subtype:&quot;success&quot;`, `num_turns:0`, and an empty result. The same skill runs when invoked indirectly from a natural-language prompt, and a fail-open preamble wrapper also allows the model turn to proceed, so the failure is specific to immediate slash-skill invocation plus an unguarded failing preamble.</summary>
    <category term="Skills"/>
  </entry>
  <entry>
    <title>[CRITICAL] Network strictAllowlist can fail open inside Docker.</title>
    <id>https://framework.boucle.sh/limitations.html#strictallowlist-can-fail-open-inside-docker</id>
    <link href="https://framework.boucle.sh/limitations.html#strictallowlist-can-fail-open-inside-docker"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.197 and 2.1.233 Linux setup running inside Docker found that `sandbox.network.strictAllowlist: true` did not block Bash access to non-allowlisted domains. The reporter configured allowed domains, confirmed standalone `bwrap --unshare-net` blocked the same curl target inside the container, and inspected debug logs and process ancestry showing Claude Code spawned the shell directly with no `bwrap`, sandbox, namespace, seccomp, or AppArmor dispatch path. The result was a silent fail-open network boundary in an ingest workflow where external documents could prompt the agent to exfiltrate data.</summary>
    <category term="Sandbox &amp; permissions"/>
  </entry>
  <entry>
    <title>[HIGH] Local worktree settings can leak hooks across linked checkouts.</title>
    <id>https://framework.boucle.sh/limitations.html#local-worktree-settings-can-leak-hooks-across-checkouts</id>
    <link href="https://framework.boucle.sh/limitations.html#local-worktree-settings-can-leak-hooks-across-checkouts"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A collaborator-reproduced Claude Code 2.1.233 macOS issue found that a linked git worktree can pick up the main worktree&#x27;s untracked `.claude/settings.local.json` hooks, then run those hook commands with the linked worktree as the current directory. In the reproduced Stop-hook case, a relative hook script existed only in the main checkout, so sessions in the linked checkout reported a missing hook script even though that branch had no `.claude/` directory. The maintainer clarified that committed `.claude/settings.json` stayed per-checkout, while local settings are resolved through the repository root and can therefore cover every linked worktree without a clear warning.</summary>
    <category term="Worktree"/>
  </entry>
  <entry>
    <title>[CRITICAL] Sandbox read isolation and settings policy can fail open.</title>
    <id>https://framework.boucle.sh/limitations.html#sandbox-read-isolation-and-settings-policy-can-fail-open</id>
    <link href="https://framework.boucle.sh/limitations.html#sandbox-read-isolation-and-settings-policy-can-fail-open"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Linux Claude Code sandbox setup found that `sandbox.filesystem.allowWrite` did not provide filesystem read isolation: Bash commands could still read credential paths such as `~/.ssh/id_rsa`, while `permissions.deny` `Read(...)` rules only covered the dedicated Read tool. The same session showed the agent could edit its own `settings.json`, add plausible but unsupported sandbox keys, and leave the file as invalid JSON during revert. Claude Code then continued tool execution without surfacing a hard sandbox configuration failure, making the boundary appear enabled while policy parsing or enforcement was degraded.</summary>
    <category term="Sandbox &amp; permissions"/>
  </entry>
  <entry>
    <title>[HIGH] Linux bwrap sandbox can hit E2BIG from recursive Read deny globs.</title>
    <id>https://framework.boucle.sh/limitations.html#linux-bwrap-recursive-read-deny-globs-can-hit-e2big</id>
    <link href="https://framework.boucle.sh/limitations.html#linux-bwrap-recursive-read-deny-globs-can-hit-e2big"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Linux and WSL2 Claude Code sandbox setup found that recursive `permissions.deny` rules such as `Read(data/**)` and `Read(**/*.parquet)` were expanded into one bubblewrap bind per matched file. With a denied data tree containing 3,552 files, the generated sandbox argument payload exceeded Linux&#x27;s per-argument limit and every sandboxed Bash call failed before the user command ran with `E2BIG: argument list too long, posix_spawn &#x27;/bin/bash&#x27;`. Adding a directory-level `sandbox.filesystem.denyRead` rule did not help because permission-derived denies were merged rather than replaced.</summary>
    <category term="Sandbox &amp; permissions"/>
  </entry>
  <entry>
    <title>[HIGH] Plugin MCP tools can skip ask-first permission prompts.</title>
    <id>https://framework.boucle.sh/limitations.html#plugin-mcp-tools-can-skip-ask-first-permission-prompts</id>
    <link href="https://framework.boucle.sh/limitations.html#plugin-mcp-tools-can-skip-ask-first-permission-prompts"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code plugin setup found that MCP tools from installed plugins could execute when they were absent from both `permissions.allow` and `permissions.deny`. Denied tools were hidden correctly, but tools left in the expected ask-first state ran without a permission prompt and without a `permission_prompt` hook event. This collapses the permission model for plugin MCP tools from allow, deny, or ask-first into deny or auto-allow.</summary>
    <category term="MCP &amp; plugin issues"/>
  </entry>
  <entry>
    <title>[HIGH] Subagents and workflow agents cannot inherit scoped MCP authorization.</title>
    <id>https://framework.boucle.sh/limitations.html#subagent-workflow-mcp-authorization-not-scoped</id>
    <link href="https://framework.boucle.sh/limitations.html#subagent-workflow-mcp-authorization-not-scoped"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported macOS Claude Code workflow found that a parent session could call a permission-gated read-only MCP database tool, while subagents spawned through Task or Workflow had the same MCP call refused by the auto-mode classifier. Prompt text saying the user had authorized the tool for that run did not help, and the blocked request was not surfaced as an approval prompt. The only working permission route was a permanent `permissions.allow` entry, which is broader than the user&#x27;s intended per-run grant.</summary>
    <category term="MCP &amp; plugin issues"/>
  </entry>
  <entry>
    <title>[HIGH] Invalid or removed settings can disable permissions mid-session.</title>
    <id>https://framework.boucle.sh/limitations.html#invalid-or-removed-settings-can-disable-permissions-mid-session</id>
    <link href="https://framework.boucle.sh/limitations.html#invalid-or-removed-settings-can-disable-permissions-mid-session"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.214 macOS session found that while Claude Code is already running, a watched `.claude/settings.json` or `~/.claude/settings.json` file that becomes syntactically invalid is rejected as a whole and its `permissions.deny` and `permissions.ask` rules stop enforcing. A Bash command that was denied in the previous turn can then execute silently until the file parses again. A later comment on Claude Code 2.1.231 web session reported the same fail-open shape when a project settings file was deleted by `git checkout`: deny rules stopped applying, and in that case stayed inert after the file was restored by merge. The risk is not only malformed startup config; ordinary mid-session edits or branch switches can silently remove active permission policy from a live session.</summary>
    <category term="Sandbox &amp; permissions"/>
  </entry>
  <entry>
    <title>[HIGH] Ancestor sandbox settings are not inherited by nested projects.</title>
    <id>https://framework.boucle.sh/limitations.html#ancestor-sandbox-settings-not-inherited-by-nested-projects</id>
    <link href="https://framework.boucle.sh/limitations.html#ancestor-sandbox-settings-not-inherited-by-nested-projects"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.220 macOS sandbox setup placed `sandbox.enabled: true`, `allowUnsandboxedCommands: false`, and a tight network allowlist in a container workspace&#x27;s `.claude/settings.local.json`, then started a separate session inside a nested git repository. The nested session ran commands with network access that the parent workspace blocked. A collaborator reproduced on Claude Code 2.1.233 and clarified the current model: project and local settings are read only from the project Claude Code starts in, so ancestor-directory settings are not inherited by a nested repository, even when the nested repo has no `.claude/settings.local.json` of its own. The confirmed risk is a silent boundary mismatch where a parent folder looks sandboxed while separately launched nested-project sessions are not covered by that parent sandbox.</summary>
    <category term="Sandbox &amp; permissions"/>
  </entry>
  <entry>
    <title>[HIGH] Interpreter-wrapped hook scripts can fail closed when the target file is missing.</title>
    <id>https://framework.boucle.sh/limitations.html#interpreter-hook-script-missing-can-fail-closed</id>
    <link href="https://framework.boucle.sh/limitations.html#interpreter-hook-script-missing-can-fail-closed"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.218 Windows setup found that a `PreToolUse` command hook such as `python C:/nonexistent/ghost_hook.py` blocked the matched Bash tool because Python itself launched successfully and then exited 2 when it could not open the script. A collaborator reproduced the same behavior on Claude Code 2.1.233 and clarified the distinction: a hook executable that cannot be started can be treated as a non-blocking hook error, but an interpreter that starts and returns exit code 2 is indistinguishable from a deliberate hook deny because the hook protocol reserves exit code 2 for blocking. A stale path, renamed hook file, or disabled-by-renaming guard can therefore lock out every matched tool call, including the call that would repair the configuration from inside the session.</summary>
    <category term="Hook behavior &amp; events"/>
  </entry>
  <entry>
    <title>[HIGH] Linux seccomp sandbox can fail inside `bwrap` unless Unix socket filtering is disabled.</title>
    <id>https://framework.boucle.sh/limitations.html#linux-seccomp-sandbox-can-fail-inside-bwrap</id>
    <link href="https://framework.boucle.sh/limitations.html#linux-seccomp-sandbox-can-fail-inside-bwrap"/>
    <updated>2026-08-17T00:00:00Z</updated>
    <summary>A reported Claude Code 2.1.220 Linux sandbox setup found that every sandboxed Bash call failed before the user command ran with `apply-seccomp: write /proc/self/setgroups ... Permission denied` when `sandbox.network.allowAllUnixSockets` was false. Independent reproductions on Ubuntu narrowed the failure to the seccomp helper attempting a nested user namespace from inside bubblewrap after capabilities have been dropped; enabling `allowAllUnixSockets: true` made Bash run but disabled Unix-socket filtering wholesale. A later 2.1.233 data point found an AppArmor `bwrap` profile can restore deterministic startup while preserving socket blocking, but also reported residual intermittent `unshare(CLONE_NEWUSER): Invalid argument` failures that are not caught by `failIfUnavailable`.</summary>
    <category term="Sandbox &amp; permissions"/>
  </entry>
</feed>
