# Claude Code v2.1.195

> Claude Code v2.1.195, released 26 Jun 2026 (2026-06-26). 16 entries read out of the shipped bundle. Unofficial, and not affiliated with Anthropic.

Web version: https://changelogs.core-directive.com/v/2.1.195

This release is headlined by an interactive cloud gateway login flow with full OAuth device-code authentication and TLS certificate pinning, and a new WebSocket source mode for the Monitor tool. It also ships a substantially richer model catalog with six new or updated model entries, per-organization effort-level enforcement, and better tooling for MCP hook matchers and tool schema normalization.

## New Features

### Cloud Gateway OAuth Login

**What**

Users can now authenticate with an enterprise cloud gateway directly from Claude Code using a browser-based device code OAuth flow, complete with TLS certificate pinning.

**Usage**

`claude login # opens the /login flow; gateway URL is provisioned via managed settings (forceLoginGatewayUrl) /login # same, from inside a session` **Details** - The gateway URL must use `https://` (plain `http://` is only allowed for localhost in development). - On first connection, Claude Code shows the gateway's SHA-256 certificate fingerprint and prompts "You haven't connected to this gateway before. Once trusted, it can push settings to this machine that execute commands and change your environment. Only continue if this is your organization's gateway." - If the certificate changes after a previous trust, a warning is shown: "The TLS certificate for this gateway has changed since you last connected. Only continue if your administrator has confirmed a certificate rotation." - DNS resolution is validated to confirm the gateway host resolves to private-network addresses only. Direct IPs, dual-stack hostnames with a public AAAA record, and HTTP proxy hosts on public networks are all flagged with specific error messages. - The token is persisted via secure storage after the browser flow completes. - If `NODE_EXTRA_CA_CERTS` is needed for a private CA or self-signed certificate, a help message now explains exactly how to set it (both as an environment variable and via `env.NODE_EXTRA_CA_CERTS` in `~/.claude/settings.json`). **Evidence** Full browser-based OAuth flow (search for `"Connecting to gateway…"`, `"Certificate fingerprint (SHA-256):"`, `"Gateway URL must use https://"`)

### Monitor Tool WebSocket Support

**What**

The Monitor tool now accepts a `ws` source that opens a WebSocket and streams each incoming text frame as a notification event — no shell process, no polling needed.

**Usage**

`Monitor({ ws: { url: 'wss://events.example.com/stream', protocols: ['v1'] }, description: 'deploy events', })` **Details** - Each text frame becomes one notification; multiline frames stay as one event. - Binary frames are reported as `[binary frame, N bytes]` rather than passed through. - Socket close ends the watch; close code and optional reason are surfaced. - WebSocket errors appear before close as `[WebSocket error: ...]`. - Same rate-limiting as bash monitor — a firehose is suppressed and eventually stopped. - Blocks connections to private/link-local/cloud-metadata IP ranges (SSRF protection) and respects `sandbox.network.deniedDomains` and `allowManagedDomainsOnly`. - Compliance taint disables arbitrary-URL WebSocket egress with a clear message: "Monitor cannot open a WebSocket: arbitrary-URL egress is disabled by your organization's compliance policy." - Cannot be combined with `command`. **Evidence** New `MonitorWsTask` and `MonitorWsPreconditionError` types (search for `"MonitorWsTask"`, `"MonitorWsPreconditionError"`, `"ws source"`)

### Model Catalog: New and Updated Models

**What**

The model catalog has been reworked into a structured, versioned manifest (`schema_version: 1`) covering all current models. Several new models are now registered.

**Details**

- New model entries added: `claude-sonnet-4-6` (Sonnet 4.6, knowledge cutoff August 2025), `claude-opus-4-6` (Opus 4.6, knowledge cutoff May 2025 with `fast_mode`), `claude-opus-4-7` (Opus 4.7, native 1M context, `xhigh_effort`, knowledge cutoff January 2026, default effort `xhigh`), `claude-opus-4-8` (Opus 4.8, native 1M context, `lean_prompt`, `mid_conv_system`, default effort `high`), `claude-fable-5` (Fable 5, native 1M context, `rejects_disabled_thinking`, `fable_5_mitigations`).
- Family aliases updated: `opus` → `claude-opus-4-8`, `sonnet` → `claude-sonnet-4-6`, `fable` → `claude-fable-5`.
- All models include provider IDs for first_party, bedrock, vertex, foundry, anthropic_aws, mantle, and gateway.
- Capability flags now include `effort`, `max_effort`, `xhigh_effort`, `adaptive_thinking`, `context_management`, `fast_mode`, `lean_prompt`, and `mid_conv_system`.

**Evidence**

New model catalog object with `schema_version: 1` (search for `"Generated by \`bun run generate:model-catalog\`"`, `"claude-sonnet-4-6"`, `"claude-fable-5"`)

### Vertex 1M Context Warning for Unsupported Models

**What**

A warning is emitted when requesting the 1M context beta (`[1m]` model suffix) on Vertex for models that do not support it.

**Details**

- The check fires at startup when the resolved gateway configuration includes a vertex upstream that serves `claude-sonnet-4-5` or `claude-sonnet-4` models (identified internally as `sonnet45` / `sonnet40`).
- If the gateway config sets `auto_include_builtin_models: true`, the built-in `claude-sonnet-4-5` model is automatically added to the warning list even when no explicit upstream model mapping covers it.
- The emitted message names the specific model IDs that triggered it: `"vertex upstream serves <model-list>: Sonnet 4.5/Sonnet 4 do not support 1M context on Vertex — requests with the context-1m beta (the [1m] model suffix) for these models will be rejected with a 400. Vertex 1M lineup: Opus 4.6+/Sonnet 4.6."`
- Emitted as a `warn`-level log via `gu("warn", …)` during gateway config validation; does not block startup or abort the request.
- Only vertex-provider upstreams are checked; other providers (bedrock, foundry, etc.) are unaffected by this warning.

**Evidence**

Vertex 1M limitation notice (search for `"Sonnet 4.5/Sonnet 4 do not support 1M context on Vertex"`, `u5c`, `auto_include_builtin_models`)

## Improvements

### Effort Levels Now Enforced Per-Organization

**What**

If your organization's gateway has set a maximum effort level for a given model, `/effort` will silently cap selections above that limit and show an explanatory message.

**Details**

- When you pick an effort level that exceeds the organization cap, Claude Code automatically uses the highest allowed level (or the model's own floor, whichever applies) and logs a message like: "Effort 'xhigh' exceeds your organization's limit for claude-sonnet-4-6; using 'high'."
- The `/effort` picker displays a "Higher effort levels are restricted by your organization." notice when some effort levels are blocked.
- The `Usage: /effort [...]` help text now dynamically lists only the effort levels actually available for the current model and session.

**Evidence**

Effort capping logic (search for `"exceeds your organization's limit for"`, `"Higher effort levels are restricted by your organization."`)

### Remote Session Progress Display

**What**

When starting or resuming a cloud session, a structured progress view now shows each setup step (provision, clone, setup_script, start_cc) with live status, elapsed time, and detail lines.

**Details**

- Steps shown: "Setting up a cloud container", "Cloning repository", "Running setup script", "Starting Claude Code" (and resume variants: "Resuming your cloud container", "Refreshed repository", etc.).
- Elapsed time is shown per step once it exceeds 5 seconds.
- Messages queued during setup are listed: "N messages queued · sends once the session is ready" or "You can start typing — messages send once the session is ready".
- Final summary: "Remote session ready in Xs" (or "resumed in Xs").

**Evidence**

Progress step renderer (search for `"Setting up a cloud container"`, `"Cloning repository"`, `"You can start typing — messages send once the session is ready"`)

### Hook Matcher Warnings for MCP Server Patterns

**What**

Claude Code now warns at startup if a hook matcher like `mcp__my_server` matches no known tool, because hook matchers are compared as exact strings — the correct pattern to match all tools from a server is `mcp__my_server__.*`.

**Details**

- Warning message: "Hook matcher `mcp__server` matches no tool (it is compared as an exact string). To match all tools from this server, use `mcp__server__.*`. See CHANGELOG v2.1.195."
- Only fires once per distinct matcher pattern per session.

**Evidence**

Hook matcher warning (search for `"matches no tool (it is compared as an exact string). To match all tools from this server, use \`"`)

### MCP Tool Schema Normalization

**What**

MCP tools whose input schemas use top-level `anyOf`, `oneOf`, or `allOf` can now be normalized into a flat object schema, making them usable in Claude Code without being dropped.

**Details**

- Controlled by the `tengu_mcp_normalize_root_combinators` feature flag. Set to `["*"]` for all MCP servers, or a list of hostnames to target specific ones. Hostname entries support subdomain matching: `"example.com"` also matches `api.example.com`.
- Only URL-based MCP servers (those with a `url` property) are eligible. stdio and sdk-type servers have no `url` and are never normalized regardless of flag value.
- The injected note in the tool description differs by combinator type:
- `allOf` only: `"Input constraint: all listed parameters apply together (flattened from a JSON Schema allOf)."`
- `oneOf`: `"Input constraint: Provide parameters for exactly one of: (param_a, param_b) or (param_c)."`
- `anyOf`: `"Input constraint: Provide parameters for at least one of: (param_a, param_b) or (param_c)."`
- If parameter groups cannot be extracted from the schema branches, the note falls back to: `"Input constraint: Provide parameters for exactly one of the documented parameter groups (flattened from a JSON Schema oneOf)."`
- Only property names matching `/^[a-zA-Z0-9_.-]{1,64}$/` are included in the flattened schema; others are silently excluded.
- Top-level schema fields preserved through normalization: `$defs`, `definitions`, `$schema`, `additionalProperties`, `description`, `title`.
- If normalization fails for any reason, the tool is dropped with a logged reason (e.g., `"input schema has top-level anyOf that is not an array"`) rather than silently accepted with a broken schema.

**Evidence**

Schema normalization (search for `"Input constraint: all listed parameters apply together"`, `"Provide parameters for exactly one of"`, `"Provide parameters for at least one of"`, `Mxp`, `tengu_mcp_normalize_root_combinators`)

- Flag `tengu_mcp_normalize_root_combinators`: Not enough to say (read for one account on one subscription tier against v2.1.195; this account: no value returned, anonymous baseline: no value returned, compiled default: not a boolean we can read) These values were read against a different version of Claude Code, so treat them as the nearest reading available instead of one taken on this release.

### Code Review Workflow Improved Verification

**What**

The built-in `/code-review` workflow now deduplicates candidates before verification — each distinct (file, line) location gets exactly one independent verifier, rather than one verifier per raw candidate.

**Details**

- Old description: "one independent verifier for every candidate"
- New description: "one independent verifier for every distinct (file, line) location across the pooled candidates"
- Findings from all finder agents are pooled first, then verified — this reduces duplicate work when multiple finders identify the same location.

**Evidence**

Updated code review description constant (search for `"one independent verifier for every distinct (file, line) location across the pooled candidates"`)

### /config Inline Key=Value Shortcut

**What**

The `/config` command now accepts `key=value` arguments to set panel settings inline without opening the interactive panel.

**Usage**

`/config model=claude-opus-4-8 /config theme=dark` **Details** - Supported settings include model, theme, verbose, and output style. - User-facing tip: "/config key=value sets panel settings (model, theme, verbose, output style, …) inline — no need to open the panel." **Evidence** New /config inline setting tip (search for `"/config key=value sets panel settings"`)

### MCP Login from CLI with --no-browser

**What**

MCP servers that require authentication can now be authenticated from the command line, with a `--no-browser` flag for SSH/headless environments where the browser cannot open.

**Usage**

`claude mcp login <server-name> claude mcp login <server-name> --no-browser` **Details** - `--no-browser` prints the callback URL for manual pasting rather than attempting to open a browser. - Tip: "`claude mcp login <name>` authenticates an MCP server from the CLI — add --no-browser to paste the callback URL manually over SSH." **Evidence** New CLI tip (search for `"claude mcp login <name> --no-browser"`)

### Deny/Ask Rules for Tool Input Parameters

**What**

Permission rules now support matching on a specific tool input parameter value, allowing fine-grained auto-handling without a blanket allow.

**Details**

- Example rules: `deny Agent(model:opus)` or `ask Bash(run_in_background:true)`.
- Tip: "Deny and ask rules can match a tool input parameter — e.g., deny Agent(model:opus) or ask Bash(run_in_background:true) — so that specific pattern is auto-handled without prompting each time."
- The `/permissions` panel guidance also updated to reference this syntax.

**Evidence**

New permissions tip (search for `"Deny and ask rules can match a tool input parameter"`, `"/permissions, then add a Tool(param:value) deny or ask rule"`)

### Skill Override Lookup Extended to Local Settings

**What**

Skill enable/disable overrides (`skillOverrides`) are now checked in local project settings (`localSettings`) in addition to project and user settings, with local settings taking the highest priority.

**Details**

- The resolution order is two-phase: (1) look up by fully-qualified `cmdName` in `projectSettings`, then `userSettings`; (2) if nothing found, look up by `unqualifiedName` in `localSettings`, then `projectSettings`, then `userSettings`. `localSettings` is therefore checked only for the unqualified name, not for the full command name.
- Valid override values and their effects: `"on"` (default — fully visible to model and typeable); `"name-only"` (lists the skill without its description); `"user-invocable-only"` (hidden from model invocation, but still typeable as `/name`); `"off"` (hidden from both the model and the `/name` prompt).
- When a skill's `lockSource` is `"author"`, any resolved override value other than `"off"` is silently capped to `"user-invocable-only"`. This means authors can prevent a skill from being fully exposed, but individual users cannot grant it full `"on"` status.
- The `/skills` panel writes overrides to `localSettings` (not projectSettings), so panel changes are local to the machine and do not affect teammates sharing the same project settings file.
- Attempting to invoke a skill whose effective state is `"off"` or `"user-invocable-only"` via the model produces the error: `"Skill '<name>' is disabled via skillOverrides. Re-enable it in /skills or remove the override from your settings to run it."`

**Evidence**

Updated skill override resolver (search for `Mjl`, `"localSettings"` in context of `skillOverrides`, `"user-invocable-only"`, `"Skill.*disabled via skillOverrides"`)

### Interrupted Response Recovery Improved

**What**

When a response was interrupted mid-generation, the resume hint now escapes angle brackets inside the fence (HTML-entity-escaped) to avoid parse ambiguities. The prior-partial-output fence boundary is also validated more carefully.

**Details**

- New message: "Your previous response was interrupted mid-generation. Your prior partial output follows this reminder, fenced as <interrupted-output> (angle brackets inside the fence are HTML-entity-escaped). It is..."
- Logs `[reply-on-resume] prefill boundary mismatch` if the boundary doesn't match what was expected.

**Evidence**

Interrupted output handling (search for `"[reply-on-resume] partial-hint"`, `"[reply-on-resume] prefill boundary mismatch"`)

## Bug Fixes

- Adoption (workflow handoff) now retries on `EPERM`/`EBUSY`/`EACCES` errors up to 3 times with 50ms delay before giving up, reducing failures on Windows and network paths (search for `"ebusy_retry"`)

- `system-reminder` tags are now stripped from both the leading AND trailing end of assistant text blocks, not just from the start — preventing stale reminders from leaking into prefill boundaries (search for `"</system-reminder>"` in the Cur function)

- Daemon error messages and stack traces now have hex session IDs replaced with `cc-daemon-*` before logging, preventing log pollution with session-specific noise (search for `"cc-daemon-*"`)

- Monitor stopped message now shows the count of excess output bytes as a number rather than a raw string fragment, and the restart advice is no longer appended (search for `"[Monitor stopped — too much output ("`)

- Voice stream now handles mid-stream errors by salvaging partial audio rather than silently failing (search for `"[voice] mid-stream error: salvaging"`)

- MCP server re-authentication notifications are now namespaced with a prefix (`mcp-needs-reauth-`) to avoid colliding with other notification IDs (search for `"mcp-needs-reauth-"`)

## Notes

Hook matchers for MCP servers have changed behavior (or rather, an existing behavior is now surfaced as a warning): `mcp__server_name` is an exact-string match that will never match any real tool. The correct form to match all tools from a server is `mcp__server_name__.*`. If you see the warning "Hook matcher `mcp__server` matches no tool", update your hook rules in `.claude/settings.json` to use the `__.*` suffix.
