Claude Code 2.1.299 to 2.1.301 Changed How Your Hooks Behave: 7 Things to Recheck Claude Code releases 2.1.299 through 2.1.301, shipped October 14–15, 2026, silently changed the behavior of seven existing hook configurations, including making UserPromptSubmit hooks run before a skill or custom slash command expands so a blocking hook now also stops the skill's embedded shell commands. The changes also affect how rewritten hook input is handled, which MCP tools an agent's tools list picks up, and what a plugin hook does when it cannot answer, applying automatically on upgrade with no user edit required. The writeup quotes each changelog line, describes what it can break, and gives grep commands to check whether a setup is affected. Since Claude Code https://code.claude.com/docs/en/overview 2.1.299, a UserPromptSubmit hook runs before your skill expands, so a hook that blocks the prompt now also stops the skill's shell lines. Nobody touched your hooks file to make that happen. Three releases landed on October 14 and 15, 2026: 2.1.299, 2.1.300 and 2.1.301 changelog https://code.claude.com/docs/en/changelog . Seven lines in their "Changed" sections alter how hooks you already have behave. They move when a prompt hook runs, what happens to input a hook rewrites, which MCP tools an agent's tools: list picks up, and what a plugin hook does when it can't answer. None of them waits for an edit on your side. They apply as soon as you're on the new version. Each item below quotes the changelog line, says what it can break, and gives one command to see whether your setup is affected. Two hook changes from the same week are left out on purpose: onFailure: "block" 2.1.295 and the narrower MCP allow rules 2.1.299 . Each needs more room than a list item. claude --version claude update Each of the seven changes arrived in 2.1.299 or later. If claude --version prints an older number, none of the seven applies to you yet, and claude update is the moment they start to. One of the three fixes near the end goes back further, to 2.1.294. If you run Claude Code through Hermes IDE https://hermes-ide.com , which I build, the agent picker in the ⌘N sheet shows the installed version next to each agent you have installed. Hermes 2.3.4's agent picker: Claude Code installed, 2.1.299 selected, Codex installed 0.145.0 , and the other supported agents marked Not installed. UserPromptSubmit now runs before the skill expands From 2.1.299: "Changed UserPromptSubmit hooks to run before a skill or custom slash command expands, so a hook that blocks the prompt now also stops its embedded shell commands." A skill's body can carry shell lines, written as followed by a command in backticks. The getting-started example in the skills docs https://code.claude.com/docs/en/skills runs git diff HEAD that way. The changelog's "now also stops" tells you the old order: a blocking hook stopped the prompt, but not those lines. What can break: your hook now sees the prompt before the skill's text is in it. A hook that searched the prompt for words that only appear inside a skill's body has nothing left to find. For the expansion itself there is a separate event, UserPromptExpansion , which matches on the command's name hooks reference https://code.claude.com/docs/en/hooks . To see what can break, print your UserPromptSubmit hooks and look for patterns that only match a skill's expanded text: grep -n -A8 UserPromptSubmit \ .claude/settings.json ~/.claude/settings.json This one lists the skills and commands whose shell lines a blocking hook can now stop: grep -rlF ' ' .claude/skills .claude/commands \ ~/.claude/skills ~/.claude/commands From 2.1.299: "Changed a skill's own front-matter UserPromptSubmit hook to first run on the prompt after the one that invokes the skill." A skill can declare hooks in its frontmatter. Claude Code registers them when the skill is invoked and keeps running them for the rest of the session hooks reference https://code.claude.com/docs/en/hooks . If your skill's UserPromptSubmit hook checked the prompt that called it, say /deploy prod , it no longer sees that prompt. It starts with the next one. If the check has to happen on the invocation, move it to UserPromptExpansion in your settings. The hooks reference gives this exact case: a hook matching deploy that blocks /deploy unless an approval file is present. { "hooks": { "UserPromptExpansion": { "matcher": "deploy", "hooks": { "type": "command", "command": "$CLAUDE PROJECT DIR/.claude/hooks/deploy.sh" } } } } To find the skills that declare this hook: grep -rln UserPromptSubmit .claude/skills ~/.claude/skills updatedInput is validated, and unknown keys are dropped From 2.1.300: "Changed hooks: updatedInput from PreToolUse and PermissionRequest hooks is now validated like Claude's own input: unknown keys are dropped, and input the tool rejects denies the call." The hooks reference https://code.claude.com/docs/en/hooks already said updatedInput "Replaces the entire input object, so include unchanged fields alongside modified ones." Now that rule bites. A hook that returns only the field it changed and leaves out a required one, or spells a field wrong, hands the tool input it rejects, and the call is denied. A key you added for your own bookkeeping is dropped before the tool sees it. The safe shape starts from the input Claude sent and changes one field. In a command hook, with jq https://jqlang.org : jq '{hookSpecificOutput: { hookEventName: "PreToolUse", permissionDecision: "allow", updatedInput: .tool input + {command: "npm run lint"} }}' The check feeds your hook a sample event and prints what it returns as updatedInput , wherever it sits in the output. Swap in your own script path: echo '{"hook event name": "PreToolUse", "tool name": "Bash", "tool input": {"command": "ls"}}' \ | .claude/hooks/rewrite.sh \ | jq '.. | .updatedInput? // empty' Every key in the object it prints should be one the tool accepts, and the object should be the whole input, not only the field you changed. setMode from a PermissionRequest hook is ignored in Cowork cloud From 2.1.300: "Changed PermissionRequest hooks in Cowork cloud sessions: a setMode update in a hook's allow is now ignored; the rest of the approval still applies." A PermissionRequest hook that allows a call can also send updatedPermissions , and one entry type, setMode , changes the permission mode, to acceptEdits for example hooks reference https://code.claude.com/docs/en/hooks . Cowork can run tasks in the cloud, on Anthropic's servers https://support.claude.com/en/articles/15811196-what-to-expect-with-claude-cowork-in-the-cloud . In those sessions the approval still holds, but the mode no longer moves. A hook that approved the first edit and switched the session to accept edits will keep seeing permission requests. A related line in 2.1.299 goes further for auto mode in Cowork cloud sessions: "a PermissionRequest hook can no longer approve shell commands or subagents; those prompts wait or are denied." Neither line mentions local terminal sessions. The check finds hooks that send a mode change: grep -rn setMode .claude ~/.claude/settings.json ~/.claude/hooks Seven changes in two days, none of them in your config file. tools: lists take only the server they name From 2.1.299: "Changed agent tools: lists to take only the named MCP server's tools; list a server whose name contains as mcp