Repository navigation
fix(native-chat): pass saved Claude Arguments to the chat as typed, and refuse what moves the session - #26127
Closed
brennanb2025 wants to merge 4 commits into
Conversation
…nd refuse what moves the session Settings -> Agents -> Arguments is shared by terminal tabs and Claude native chat. The chat squeezed the Arguments into the SDK's one-value-per-option record, so a valid `--mcp-config a.json b.json`, a repeated `--plugin-dir`, or `--tools Bash Edit` refused to start the chat, and a dash-leading value (`--append-system-prompt "- be terse"`) was split. It also silently dropped `--allowedTools`/`--disallowedTools` (one spelling only), the system-prompt options and `--setting-sources`, dropped a prompt typed before the options, and forwarded `--worktree`/`--bg`/`--cloud`, which move the session away from the folder the chat reads. Now every option the chat doesn't own reaches the Claude CLI exactly as typed, after the SDK's own flags, with all its values and repeats; values are read with the CLI's own arity rules. The system-prompt options apply as in a terminal (Orca's initialize sends no prompt of its own). The chat still owns the stream protocol, the session's identity and the permission bypass, which drop quietly; `--permission-mode` drops and tool rules pass, behind one switch pending a product decision. Options that move the session (--worktree, --tmux, --bg, --cloud, --teleport, --remote, --remote-control) and prompts refuse by name; an option the CLI doesn't list is forwarded and left to the CLI. A chat's saved model or effort still replaces the Arguments' own.
…d every CLI option by one table A misspelled or unknown option in saved Arguments (--modle, -x) reached the Claude CLI, which exits with "unknown option '<name>'"; the chat only said Claude stopped before it finished starting. When the CLI's exit carries that exact refusal for an option the user saved, the start now fails as the existing named refusal: "Claude chats can't use --modle from saved Arguments. Remove it from Claude's Arguments in Settings -> Agents." Option arity now comes from one table of every main-command option of the Claude CLI (src/shared/claude-cli-options.ts), which the shared option remover also derives its required-value list from, so hidden options keep their dash-leading values and prompt text after them is still refused. --environment and --pool (cloud sessions) refuse by name, and --inherit-permission-mode drops like --permission-mode: the chat's mode is Agent Permissions'. Tool allow/deny rules are forwarded, each behind one switch. The launch's saved Arguments are required end to end, the SDK contract pin asserts Orca's initialize sends no system prompt of its own (so a saved one stands), and multipleValues is marked as read for older hosts only.
… Arguments are always present
…rguments' into brennanb2025/native-chat-claude-arguments
Closed
6 of 7 tasks
Contributor
Author
Review summaryProblem. In Claude native chat, saved Arguments (Settings → Agents → Arguments, shared with terminal tabs) were only partly applied:
User-facing change.
What review fixed (2 rounds plus the earlier design reviews):
Deferred or follow-ups:
Verified:
Not verified:
Stacking: this targets #26059's branch and will be retargeted to |
This was referenced Oct 8, 2026
Closed
Contributor
Author
|
Closing unmerged. Native chat no longer reads saved Arguments for any agent; they are for terminal launches (#26506). So passing Claude Arguments through to chat isn't needed. Claude chat settings come from Claude's own settings files. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
ELI5
Settings → Agents → Arguments is shared by terminal tabs and native chat. In Claude native chat, saved Arguments were only partly applied:
--disallowedTools,--append-system-prompt,--system-prompt;--mcp-config a.json b.json, stopped the chat from starting with a message blaming the setting.Now Claude chat passes saved Arguments to the Claude CLI exactly as a terminal would. It refuses by name only the flags that would move the session somewhere a chat can't follow.
Stacked on #26059 (the same change for Codex). It reuses that PR's refusal wording and unclosed-quote handling. This PR is retargeted to
mainafter #26059 merges.What Changed
Before (Claude native chat):
--disallowedTools "Bash(rm:*)"was dropped, so denied tools were available in chat. The hyphenated spelling--disallowed-toolswas forwarded, which was inconsistent.--append-system-prompt "..."and--system-promptwere dropped.--mcp-config a.json b.json,--plugin-dirgiven twice, and--tools Bash Editrefused the chat with "Saved Arguments give --mcp-config more than one value."-(--append-system-prompt "- be terse") was split into a fake flag.--worktree,--bg,--cloud,--teleport,--remote-control) were passed through.--worktreewould move Claude away from the folder where Orca reads the conversation.After:
--append-system-prompt,--system-prompt,--mcp-config,--settings,--plugin-dir,--tools,--add-dir, the allowed/disallowed tool rules (both spellings), and unknown options. The Claude CLI is the authority on its own flags. If it rejects a saved option at start with its "unknown option" error, the chat's error card names that option: "Claude couldn't start. Claude chats can't use --modle from saved Arguments. Remove it from Claude's Arguments in Settings → Agents." Any other start failure from the CLI still shows the generic sentence.--model/--effortare left out, as before.--permission-mode,--inherit-permission-modeand the bypass flags in Arguments are dropped quietly in chat, the same rule fix(native-chat): apply or refuse saved Codex Arguments instead of silently dropping them #26059 applies to Codex-s/-a. The tool rules--allowedTools/--disallowedTools(both spellings, all values) are forwarded, as decided. Note that--allowedToolslets the listed tools run without asking, exactly as in a terminal.--print, input/output formats,--resume,--continue,--session-id,--fork-session,--verbose, and the like), plus help/version.--worktree/-w(with the hint "A chat already works in its workspace folder"),--bg,--cloud,--teleport,--remote,--remote-control,--tmux,--environment/--pool, prompt text, a known flag missing its value, and an unclosed quote.-mis no longer turned into--model. The Claude CLI has no-m, so chat now fails the same way a terminal does.--thinking-displayor--setting-sourcesnow wins over Orca's defaults, as it would in a terminal.Mechanism: the parser reads saved Arguments with one Claude option table (
src/shared/claude-cli-options.ts). It holds every main option of the current CLI with its value arity (switch, required, optional, variadic), so the parser knows which tokens are values. The same table now feeds the terminal-side option remover, so there is no second list to drift. It returns them as ordered token groups. Orca's own Claude process spawner appends them after the SDK's arguments. Before, they went through the SDK'sextraArgs, which holds one value per flag. The special--add-dirmapping and the "more than one value" refusal are gone; old hosts can still send the "more than one value" refusal, and clients still read it.configuredArgsis a required field on both launch types, so the type checker guards the whole path from resolver to spawn.Why
The common pattern parses launch arguments into the SDK's extra arguments. That limits each flag to one value and is the root of the "more than one value" refusals. Appending the user's tokens at Orca's own spawn keeps everything the terminal accepts. The system-prompt flags work from the command line because the SDK leaves the system prompt unset in Orca's setup message, and the CLI only overrides when it is set. A contract test pins this: Orca's setup message carries no system prompt. A live real-CLI case also applies a saved
--append-system-promptwhose value starts with a dash.Deviations from the common pattern:
Linked Issue
Follow-up to #25721 and #26059.
Visual Proof
QA ran on Windows (low spec), driven by a non-Claude agent over the DevTools protocol against a hidden window. A stand-in Claude CLI logged its full command line on every start. The box's real agent config files were unchanged at every step.
Repeats, multiple values and dash-leading values survive. Saved

--mcp-config a.json b.json --plugin-dir A --plugin-dir B --append-system-prompt "- be terse" --disallowedTools "Bash(rm:*)"reached the CLI as exactly those 11 tokens, after the SDK's own flags.- be tersestayed one token, andBash(rm:*)stayed intact through the Windows.cmdshim:Permission mode from Arguments is dropped. With Manual plus saved

--permission-mode plan --inherit-permission-mode acceptEdits, the CLI got only the SDK's--permission-mode default:Session-moving flag refused by name (


--worktree feat). Nothing started, and Retry works after editing:A saved option the CLI rejects is named (

--modle opus):Leading prompt text refused:

The chat's model pick wins. After picking Haiku, a new chat with saved


--model opusgot only--model haiku:Testing
tc:node,tc:webandtc:clitypechecks.claude-structured-real-cli*.test.ts, run with the real CLI on the final head 70764b0): 13 passed, 0 skipped, including the new saved--append-system-promptcase.Review
Pending.
Agent skill upstream boundary
docs/reference/agent-skill-sharing-upstream-boundary.mdand copies or mechanically translates no upstream skill-installer source, tests, fixtures, registry entries, path tables, comments, or documentation.Notes
--plugin-dir /a /b) is refused as "Saved Arguments include a prompt." Refusing is right, because the CLI would take/bas a prompt, but the wording could be better.Checklist
N/Awith reasonpnpm lint,pnpm typecheck,pnpm test, andpnpm buildpass (or CI will cover; local preferred)