Repository navigation
Ask: optional command suggestions from the local model, Copy/Insert only (#432) - #440
Merged
Merged
Conversation
#432 (decision D2), first slice: the local model only. When the person turns command suggestions on, a request Ask's own resolver (and the intent model) cannot place may get one suggested shell command. - Settings → Ask → Command suggestions (Off by default, or Local model): askCommandSuggestions; remote providers are not part of this slice. - understanding/tasks: a `command` task. The prompt carries the request text, the shell and the OS family only (never files, environment, history, the transcript or output). The answer is validated strictly: exactly command and explanation, one plain line of at most 1 KiB, no control, escape or invisible format characters, an explanation of at most 300 characters, or command: null when the model declines. A claimed risk is an extra field and rejects the answer. - The shared model service runs it with its own schema and token budget and advertises 'command'; the client sends it only to a service that does (an older one is told apart by its welcome and the person is told why). - ask/commandSuggestions: NMSh labels the risk itself from the paste-review classifier (destructive, privileged or piped into an interpreter is destructive; installs; anything that writes, reaches the network, runs project scripts or is unknown changes things; only reading reads). The block is literal, so Ask offers Copy and Insert only, never Run; Insert places it in the composer unsent. - TerminalApp.resolveAsk: only unclear or unsupported outcomes reach the model, never a refusal and never a closed Ask. A declined request keeps Ask's own answer; local understanding Off, no model, an older service or an invalid answer each say why. Tests: validation (including adversarial output), prompt minimization, NMSh's labels overriding the model's wording, the service path with a fake runtime, an older service never sent the task, and the whole Ask path through TerminalApp with a stub model (off, on, refusal, declined, unavailable, closed Ask, Insert never runs). Refs #432
…h's verdict first A security review found that echo $(rm -rf ~) was labelled 'reads only'. The read verdict now also requires no substitution, no wrapper command, no find action and nothing the /track repeat gate questions. The note states NMSh's check first and quotes the model's words, attributed; an explanation that names NMSh is rejected.
The Setup coverage audit requires every Settings row in a Setup section. The same row, Off until chosen, with a note on what each choice does.
This was referenced Oct 18, 2026
Open
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.
What it does
With Settings → Ask → Command suggestions → Local model (Off by default), a request Ask's own resolver cannot place may get one suggested shell command from the person's local model (the one set up in
/llm):Boundaries (each tested)
/btw//ask. Composer text is never interpreted as a request. (A composer Ask mode can follow after the keybinding and input-ownership review.)unclearorunsupportedoutcomes reach the model; a refusal (unsafe) stands and is never routed around; a closed Ask never calls the model.commandandexplanation; one plain line of at most 1 KiB; no control, escape or invisible format characters (bidi overrides included); explanation at most 300 characters; orcommand: nullwhen the model declines.commandin its welcome; the client never sends the task to one that does not.Verification
tests/askCommandSuggestions.test.ts: validation (valid, declined, and 15 rejected shapes including a second line, escape sequences, a bidi override, oversize, an extrariskfield); prompt minimization; NMSh's labels including a model that callsrm -rf ~/Downloads"read-only"; the setting's default and normalization; the service path with a fake runtime (command prompt and schema); an older service is never sent the task.tests/askCommandSuggestionsApp.test.tsthrough the realTerminalAppwith a stub model: off never calls; on calls only for what Ask cannot place, with exactly{text, shell, os}; refusals stand; the block is Copy/Insert only and labelled; Insert puts it in the composer and nothing is submitted or written; declined and unavailable states; a closed Ask never calls.npm run verify: running; recorded here when done.Review follow-up (
103b1e9c)A security review found two problems, both fixed at the cause with regressions written first (they failed before the fix):
echo $(rm -rf ~)was labelled "reads only". "Reads only" now needs every part to be plainly read-only: no substitution ($(…), backticks,<(…)), no wrapper that runs another command (env, xargs, nice…), no find action (-exec,-delete…), and nothing the stricter/trackgate (repeatRisk) questions, such asgit -cor--output=. Otherwise "changes things".Ask suites after the fix: 117/117.
The Setup coverage audit also found the new row missing from Setup; fixed in
c1a30017(Setup → Ask & local understanding → Command suggestions, the same row, Off until chosen; tested). Setup suites and the suggestion tests: 45/45.Not in this PR
Remote providers (Anthropic, OpenAI-compatible) with environment-variable credentials; a composer Ask mode; refinement turns. Design and decisions: #432 and
docs/design/v022-natural-language-commands.md(#435).Physical QA (not done)
With a local model set up in
/llmand Settings → Ask → Command suggestions → Local model:/btw convert every png here to webpshows a suggestion with NMSh's label; Insert puts it in the composer, nothing runs; Enter runs it./btw delete all my filesstays a refusal. With suggestions Off, Ask behaves as before. With local understanding Off, the suggestion attempt says how to turn it on.Refs #432