claudekit / updates / claude-code-2-1-323
[ PATCH · ]

Claude Code 2.1.323

Adds Code Mode, an experimental opt-in in which Claude writes JavaScript to call its tools, and `engines["claude-code"]` in `plugin.json` for a plugin's Claude Code version range. Over 290 changes, including fixes for `--permission-mode auto` starting in a mode that could allow more when auto mode was unavailable, and Bash deny rules missing commands run through `sudo`, `env` and similar wrappers.

Official announcement →

This article is a summary based on official documentation.

What changed

Claude Code 2.1.323 shipped on November 12, 2026. It adds Code Mode, an experimental opt-in in which Claude writes JavaScript to call its tools, and engines["claude-code"] so a plugin can state the Claude Code versions it supports. Much of the release’s 290-plus changes harden permission checks and the Bash sandbox and fix how sessions keep their sign-in and named profiles. Some changes affect existing setups, such as the context window assumed for an unrecognized model ID moving from 200K to 1M.

New features

  • Code Mode (experimental)

    Claude has called its tools one at a time. With Code Mode, an experimental opt-in, Claude writes JavaScript to call its tools. The release notes point to the Code Mode docs to turn it on, or to turn it off for an organization.

  • engines["claude-code"] in plugin.json

    A plugin had no way to say which Claude Code versions it works with. Plugins outside their stated Claude Code version range are now not installed, updated or loaded, and install and update pick the newest version that fits.

  • More checks in claude plugin validate

    It now type-checks a plugin’s TypeScript hooks module; each finding is a warning, and --strict fails on it. It also lists the $ nouns a mod’s engine.create hook adds, withholds or replaces.

  • Progress heartbeat for long hooks

    A host such as Claude Desktop could end a turn as hung while hooks ran long in claude -p and SDK sessions. A progress heartbeat now goes out every 30 seconds, taking effect once the host includes this version.

  • Usage credits options menu

    When a model needs usage credits that are turned off or used up, an options menu offers stop, switch to usage credits, or upgrade.

  • New environment variables

    • CLAUDE_CODE_DISABLE_AGENT_PROGRESS_SUMMARIES (available since 2.1.318): set it to 1 to turn off subagent progress summaries and the requests that write them.
    • CLAUDE_CODE_RESUME_HINT_COMMAND: a program that starts Claude Code can set it to have the exit hint name its own resume command.
  • New warnings and notices

    • A start-up warning for Bash allow rules with a * in a variable’s value, such as Bash(PORT=* npm run dev).
    • A warning when a plugin’s language server can’t start, naming the server and what to check.
    • A one-time startup notice naming CLAUDE_CODE_PERFORCE_MODE when Perforce settings are found and the mode is off.
  • Other additions

    • .docx support in Artifact tool asset uploads.
    • A /diff to close hint in the diff panel, and the keys that focus and close a panel in the ? shortcut guide.
    • unsetOptionCount in the claude plugin install --json result: how many userConfig options are not yet set.
    • isPromptCovered in the props a mod’s pane is drawn with, telling it when a dialog or a field above the prompt covers the prompt.
    • CLAUDE_CODE_AUTO_MODE_MODEL in managed settings for Claude Desktop sessions on third-party providers, once Claude Desktop includes this version.
  • [VSCode] Trust prompt and live Bash output

    A Claude Code trust prompt now appears before the first session in a folder you haven’t trusted; declining leaves the folder’s settings and MCP servers unused. The live output of a running Bash or PowerShell command shows in the chat, under the command’s card.

  • Claude Tag and Code Review admin

    On Enterprise plans, Claude Tag sessions started in Slack are now in the Compliance API, in beta: list the sessions and read their transcripts. Admins also get a confirmation step when turning off Claude Tag, a Scope filter on the Network events tab of the Activity page, and a Retry button on a channel’s Configure page. Code Review admin settings add a Download CSV button to export review costs per repository by month, week or day.

Key improvements

  • 1M context for unrecognized model IDs

    Claude Code assumed a 200K context window for a model ID it doesn’t recognize; it now assumes 1M. Use /autocompact to compact earlier, or CLAUDE_CODE_DISABLE_1M_CONTEXT=1 to keep 200K. Sessions on other vendors’ models with a smaller window can fail every turn once full, until /clear, so set CLAUDE_CODE_DISABLE_1M_CONTEXT=1 before they fill.

  • More actions ask first

    • /security-review asks before Claude runs it.
    • Skills’ inline git commands stop in bare-repository worktrees and similar folders until you allow them, outside auto mode and bypass.
    • The tool Claude uses to finish an MCP server sign-in asks you to confirm, even in bypass and auto modes. Where nobody can be asked, such as in dontAsk mode, use /mcp.
    • Artifact updates ask first, even under an allow rule, when people outside your organization can see the artifact or Claude can’t check who can.

    Project (.mcp.json) MCP server approvals now match the server’s exact name, so an approval written in another spelling asks again. For self-hosted runners under --trust-workspace false and VS Code sessions in an untrusted folder, the repository’s settings can no longer disable your hooks or turn plugins on or off.

  • “Don’t ask again” and hook decisions

    An allow rule that looks like it holds a secret, or would be saved to a settings.local.json that git tracks, lasts for the session only and isn’t saved. When a tool’s permission check fails with an error after a PreToolUse hook returned “allow”, Claude Code decides the call as if no hook had answered. When the check fails on input a PermissionRequest hook rewrote, Claude Code asks again, or refuses the call where nobody can answer.

  • Bash sandbox scope

    These now fail read-only inside the sandbox, so run them outside it:

    • glab config set without --global or --host, and glab config edit --local.
    • On macOS and Linux, git worktree add, move and remove, and commits in a worktree the session wasn’t started in or given, even one inside the project.

    On macOS, Linux and WSL, the sandbox ignores write access granted through a symlink in a writable folder that leads elsewhere or to a missing path; grant the real path instead. Start-up stops when a --settings file isn’t valid JSON and has a sandbox key, even one that turns the sandbox off.

  • Credentials kept out of internal commands

    Claude Code’s own ripgrep and most internal git commands run without most of its sign-in tokens and API keys, so a credential helper or hook under such a git command no longer finds them. A managed settings policyHelper no longer takes environment variables from user or --settings files; set what it needs in managed env or the launching shell. Organization settings and policy requests no longer use a proxy set only by ALL_PROXY; set HTTPS_PROXY if your network needs one.

  • Higher cross-session message limits

    Each of your sessions on the same machine can now send the others 100,000 messages without a prompt from you, up from about 20. A Claude Desktop Code tab session can send 100,000, up from 20, before it waits for you to type again.

  • Plugin and mod rules

    • A *, namespace or negated hook on engine.create now only observes. To add or withhold a $ noun, hook engine.create by name. claude plugin validate fails a mod whose engine.create hook isn’t written in the one accepted form; installed mods keep loading.
    • Marketplace and plugin installs fail when a git submodule isn’t on the commit its repository records.
    • Tools that tool.list plugin hooks add or remove apply to the model and every agent.
    • claude plugin install and /plugin show a warning instead of success when a plugin’s install command writes to stderr.
    • claude.ai chats and Cowork tasks check a plugin file for secret keys before sending it, and ask first if it may hold one.
    • A plugin’s agent setting is deprecated: it still applies, and now warns at startup, in claude plugin list and in claude plugin validate.
    • The subagentStatusLine setting is removed: subagent rows always use the default look, and settings files that still hold the key load as before.
  • MCP client and messages

    Because the v1 MCP client is removed, MCP_SDK_GENERATION=v1 runs the v2 MCP client in a compatibility mode (earlier handshake, relaxed OAuth sign-in checks). /mcp shows how many of a server’s tools were left out because the API would reject their input schema, and why. An MCP tool call whose connector ID is mistyped by a character or two now names the tool to call, for a server the host application registered.

  • Memory and speed

    • A finished subagent’s transcript is freed sooner instead of staying in memory while later subagents run.
    • The install script no longer downloads the latest version twice.
    • WebFetch is faster and uses less memory on deeply nested pages.
    • On Linux, when /home is an autofs map, Claude Code no longer looks up files in /home itself. Set CLAUDE_CODE_AUTOMOUNT_ROOTS for a map root deeper than one folder below /.
    • Claude Desktop and cloud sessions for claude.ai accounts with more than 2,000 plugins turned on wait less at startup, and Claude can say why plugins are missing.
  • More consistent Bash permission checks

    The same command now more reliably gets the same answer on a slow or busy machine, and some commands that could run differently from how they were checked now ask for permission.

  • Error and limit messages

    Sign-in errors in /login and claude setup-token say whether a request was rejected, unreachable or timed out, and what to check. The Fable limit message in -p, SDK, IDE and cloud sessions says when the limit resets and how to continue. ToolSearch says when a tool Claude searched for by its short name is already available. The maximum of CLAUDE_CODE_OVERLOADED_RETRY_MAX_DELAY_MS rose from 64000 to 300000.

  • Other changes

    • Workflows in the desktop app’s Code tab pause at a usage limit and continue after it resets.
    • /logout in a background session, which had no effect, now signs out every session on the computer, deletes stored MCP logins and plugin secrets, and ends the session, as in a terminal.
    • claude rm and the agents view say a session is removed from the list, not deleted; the conversation is kept and claude --resume lists it.
    • Split-pane agent teammates check that requests come from their team lead: one that outlives its lead has its asks refused, and plan approvals must be re-sent after /clear or /resume.
    • Worktree creation refuses checkouts whose .git folders are links or hold hard links, such as git-new-workdir layouts and cp -al copies; use a plain clone.
    • After safeguards stop a forked skill or a workflow agent, Claude is told to retry with a narrower prompt or tell you, instead of doing the work itself.
    • Computer use on macOS refuses key chords that hold Space with Control or Option, and more system shortcuts that need your grant.
    • First-run setup in Terminal.app names the “Use Option as Meta key” setting, what Option stops typing, and how to undo it before you agree.

Bug fixes

Permissions and security

  • --permission-mode auto or a settings defaultMode: auto starting in a mode that could allow more when auto mode was unavailable — it now starts in Manual mode, which asks first.
  • Bash deny and ask rules missing some commands run through sudo, env and similar wrappers.
  • Bash allow rules written with combined sudo flags skipping the permission prompt in some cases.
  • Bash allow rules with an attached wildcard, such as Bash(ls*), skipping the permission prompt in some cases — a rule that names a variable, such as Bash(NODE_ENV*), now asks.
  • Bash permission checks judging an rm from the wrong folder and skipping the dangerous-removal prompt under bypass permissions or a Bash allow rule.
  • The Write and Edit tools writing to a path covered by a Read deny rule.
  • Bash permission checks missing part of a command, some lsof commands running without a permission prompt, and a Bash command running without a prompt for zsh users with certain non-default shell options set.
  • The Bash sandbox switching off during a session, and sandbox.excludedCommands letting a command it does not name run outside the sandbox.
  • claude -p and the Agent SDK running Bash unsandboxed when --settings or SDK settings that turn the sandbox on fail validation — Claude Code now stops at start-up and names the invalid setting.
  • Sandboxed commands reading Claude Code’s file checkpoint copies under the config directory, and the sandbox not fully protecting Claude Code’s own config on installs still using the legacy config file.
  • Plan files being written outside the project when plansDirectory is set — a write that can’t be shown to stay inside the project is now refused.
  • Auto mode running behind a gateway at ANTHROPIC_BASE_URL on a model whose gateway name contains “haiku” — such a model, other than claude-haiku-5-5, is now refused, as Haiku 4.5 is.
  • Project settings being read through a symbolic link that leads to a different folder than the one Claude Code checked.
  • Bash permission prompts offering “don’t ask again” for commands that write to sensitive paths such as .git or .claude, where the saved rule did not stop the next prompt.
  • Mods being able to reword Claude Code’s own confirmation questions.
  • Bash commands that write a file with cat > file <<EOF being shown as “Read 1 file”.
  • Windows: some file-reading Bash commands running without a permission prompt when given a wildcard or a list of files.

Sign-in and profiles

  • A session on a named Anthropic profile moving to another sign-in when /fork, the Left arrow or --bg continued it in the background — reopen any session that was open during the update.
  • A background session sending a conversation under another sign-in when its named Anthropic profile is missing, changed or overridden, and a session on an API key, auth token or workload identity from its shell moving to another sign-in in the background — it now stops and says so.
  • A background session’s sign-in leaving the previous account’s login or other credentials in place — it now clears them for every session on the computer.
  • claude plugin commands and claude mcp list signing you out of a Console profile when they ended while the token was being renewed.
  • MCP tool calls ending in the sign-in server’s error, such as TOKEN_EXPIRED, instead of asking you to sign in again.
  • macOS: Not logged in · Please run /login coming back right after a successful /login or a token refresh when the keychain was slow to answer.
  • Turns failing in Claude Desktop when an organization’s gateway answers an expired token with 403 — Claude Code now asks Desktop for a fresh token and retries.
  • Sessions that kept failing after a Claude apps gateway sign-in expired — once you sign in again with /login in another terminal, they carry on at the next message.
  • The error shown when Amazon Bedrock refuses your account a model — it no longer says to refresh your AWS credentials; it says to enable the model.
  • An expired claude.ai login showing “Credit balance too low” when a saved Console key or ant auth login profile without credit was used instead.

Conversations, files and saved sessions

  • Running /compact again, or after a command such as /context, summarizing away a message that Claude had not answered yet.
  • A resumed session joining your next message to an old interrupted message that was not resumed.
  • A setting saved in a running session undoing a hand edit made to settings.json moments earlier — a settings file you delete during a session now stays deleted.
  • Edit and Bash running out of memory on certain /proc files, and Edit hanging on devices and named pipes, and a memory spike at the next prompt after Claude changed a very large file.
  • Requests sent without streaming failing on errors that streamed requests recover from, such as a rejected image, thinking block or beta header.
  • ExitWorktree, the worktree exit dialog and /resume leaving the session in the wrong folder when the folder the shell was in before entering the worktree had been deleted.
  • Subagent transcripts and large tool results being saved apart from the session’s transcript after entering a worktree created by a WorktreeCreate hook or belonging to a nested repository.
  • Part of a saved session being lost on NFS or FUSE file systems when Claude Code discarded a reply.
  • WebFetch dropping empty table cells and shifting later values a column left, and WebFetch not rechecking organization policy and CLAUDE_CODE_DISABLE_WEB_FETCH at each call.
  • Managed settings (managed-settings.json, managed-settings.d) being missed at start-up while another program was rewriting the file — start-up now reads such a file a second time.
  • Long tool results staying on disk after a session run with --no-session-persistence — they are now removed on normal exit, Ctrl+C or SIGTERM.

MCP, plugins and mods

  • An MCP server staying disconnected with no tools after an Agent SDK app or claude -p caller removed and re-added it, when a tool call had tried to reach it in between.
  • Earlier MCP tool calls missing from a resumed conversation, and lines repeating in scrollback, when the server connects late.
  • Headless sessions ending when an SDK host sent a null entry in an MCP server’s tools list.
  • /mcp and /plugins opening an MCP server’s page with the cursor on “Disable” when the server needs authentication but still holds its sign-in — the page now offers “Reconnect” and opens on it.
  • Plugins with a version list in enabledPlugins staying off with no message — /plugin and claude plugin list now say why.
  • The misleading “not cached” error for a plugin only a repository’s settings enable — it now says it isn’t installed and gives the install command.
  • Plugins and marketplaces failing to install on Windows when the path of a cloned file reaches 260 characters.
  • Marketplaces named npm, pip, uv, cargo, github or gh being refused as reserved names, and one malformed entry in a marketplace’s renames map making Claude Code ignore its other renames.
  • Load errors of plugins enabled by managed settings going only to the debug log in SDK and Desktop sessions — init.plugin_errors now lists them.
  • Plugins with defaultEnabled: false staying off in a claude.ai chat’s cloud session after you turn them on in claude.ai.
  • claude --bg --safe-mode sessions stopping at startup to ask about project MCP servers that safe mode never starts.
  • A permission prompt from a mod’s tool.check hook naming every plugin hooked on the tool instead of the one that asked.

Display, input and usage

  • Accents and other combining marks landing left of the text, leaving stale copies on screen, or disappearing when text wraps.
  • The last key of a key chord, such as Enter in ctrl+x enter, acting on a dialog’s text field, and a misspelled keybinding modifier, such as ctl+k, binding the bare key — the binding is now ignored.
  • Pressing Ctrl+C just as claude update finished sometimes removing the claude command.
  • The model picker and /model showing a picked effort level that CLAUDE_CODE_EFFORT_LEVEL overrides, and the newest model’s highlight missing from the /model picker.
  • Fable’s weekly limit showing no reset time and no options menu in the terminal, and the “Now using usage credits” notice repeating or not showing past the weekly Fable limit.
  • /usage hiding limit bars for setup tokens and CLAUDE_CODE_OAUTH_TOKEN, and showing a whole-session percentage beside a subagent type’s name.
  • Screen reader mode dropping dictated or pasted text, and emoji, typed into an answer to a question or permission prompt.
  • A multi-row status line being pushed off screen by a long prompt in the fullscreen renderer.
  • The Option-key hint appearing while typing ø or π inside words on Danish, Norwegian, Faroese and Greek keyboard layouts.

Remote Control and cloud sessions

  • Remote Control sessions showing as disconnected for a minute or more after a network change such as switching Wi-Fi or reconnecting a VPN.
  • claude remote-control reconnecting as a new computer when restarted in the same folder more than 4 hours after it stopped — it now keeps its identity for up to 30 days.
  • Other devices and phone notifications not showing what Claude is asking permission for when DISABLE_TELEMETRY or DO_NOT_TRACK is set.
  • Remote Control showing a session as running while it waited on a permission prompt that can only be answered in the terminal, and showing nothing while Claude Code asks whether to use usage credits — the question now also shows in the Claude app.
  • Cloud sessions losing an answer to Claude’s question after a restart in a long conversation, and a message dropping out of the conversation when the session restarted before Claude replied.
  • An approved plan being answered with “You are not in plan mode” when the approval arrived after the session’s process had restarted, in cloud, self-hosted runner and SDK sessions.
  • Streamed replies in cloud sessions missing text from the middle when the session’s container shut down partway through a reply.
  • A Claude Desktop session getting stuck as busy after another of your sessions sent it the same message twice or many messages at once.

Background sessions, claude -p and OpenTelemetry

  • claude -p silently using another model in text output when settings block the requested one — it now warns on stderr.
  • Text-output claude -p runs printing nothing to stderr when a --plugin-dir mod’s hook hangs or crashes the hooks worker.
  • Read-only git commands needing approval, or being refused under claude -p, when CLAUDE_CODE_SUBPROCESS_ENV_SCRUB is set on Linux.
  • claude agents losing a typed prompt — Esc now needs a second press to clear it, and ctrl+y restores it.
  • The move-to-background key doing nothing in claude attach and claude agents sessions — to detach with Ctrl+B d, press d within 800 ms of Ctrl+B.
  • OpenTelemetry export failing silently when an otlp exporter had an endpoint but no OTEL_EXPORTER_OTLP_PROTOCOL — it now defaults to http/protobuf.
  • OpenTelemetry export to the default localhost:4318 endpoint going through a configured proxy, and one malformed OTEL_RESOURCE_ATTRIBUTES entry dropping all of that variable’s attributes.
  • OpenTelemetry user_prompt events and interaction spans recording a background agent’s reply when OTEL_LOG_ASSISTANT_RESPONSES=0.
  • OpenTelemetry exports failing when a proxy took over 10 seconds to reach the collector — it now has 25 seconds, also the most that OTEL_EXPORTER_OTLP_TIMEOUT can allow (previously 30).

Windows

  • Claude Code running a .cmd or .bat wrapper found beside a program’s .exe in the same PATH folder (a git.cmd next to git.exe, say) — it now runs the .exe, as cmd.exe would.
  • Shell commands failing with “Working directory was deleted” on drives where a folder’s real path can’t be resolved.

VS Code

  • A response that was discarded because its tool call could not be parsed still showing after Claude retried.
  • The “Buy usage credits on claude.ai” button counting as agreement to pay for Fable while usage credits were off.
  • The diff tab not opening for multi-line edits on files with CRLF line endings, and dictation continuing to record after switching sessions.

Claude Code on the web and Claude Tag

  • Pull request updates from GitHub Enterprise Server linking to github.com in cloud sessions — new updates link to your own server.
  • Very large GitHub Actions job logs and run log archives failing to download or being cut off, and git clones and fetches that take longer than ten minutes being cut off at the very end.
  • Try again on a “Connection lost” card sending “Try again” as your message — it now tries to reconnect instead.
  • Removing a repository from a scheduled task silently moving its GitHub trigger to another repository — Save now waits until you pick one.
  • New cloud sessions started from the iOS app with a repository not getting a branch of their own.
  • [Claude Tag] The Approve and post card in a DM with Claude appearing for private or Slack Connect channels, where Claude can’t post.

Notes

  • If you use a model ID Claude Code doesn’t recognize, it now assumes a 1M context window. Sessions on other vendors’ models with a smaller window can fail every turn once full, so set CLAUDE_CODE_DISABLE_1M_CONTEXT=1 before they fill.
  • If you use --permission-mode auto or defaultMode: auto where auto mode is unavailable, sessions now start in Manual mode, which asks first.
  • Bash allow rules that name a variable, such as Bash(NODE_ENV*), now ask. If you granted sandbox write access through a symlink, grant the real path instead, and run git worktree add, move and remove outside the sandbox.
  • If your proxy is set only by ALL_PROXY, organization settings and policy requests no longer use it. Set HTTPS_PROXY.
  • If a credential helper or hook under Claude Code’s internal git commands relied on its sign-in tokens or API keys, it no longer finds them.
  • The subagentStatusLine setting is removed, and a plugin’s agent setting is deprecated. A *, namespace or negated hook on a mod’s engine.create now only observes; hook engine.create by name to add or withhold a $ noun.
  • If a script checks self-hosted runner exit codes, an on-demand runner whose work order was superseded exits 1 again; 2.1.321 and 2.1.322 had changed it to 0.
  • /logout in a background session now signs out every session on the computer and deletes stored MCP logins and plugin secrets.
  • Code Mode is experimental and opt-in.
  • This post covers the main items. See the GitHub release notes for the full list.