Skip to content

Run an agent-suggested command as a typed line and remember the ?? turn - #116

Merged
tfcace merged 6 commits into
masterfrom
feat/agent-command-as-typed-line
Oct 9, 2026
Merged

tfcace merged 6 commits into
masterfrom
feat/agent-command-as-typed-line

Conversation

@tfcace

@tfcace tfcace commented Oct 9, 2026

Copy link
Copy Markdown
Owner

Why

The command an agent hands back from a ?? turn ran through a side door: not what was shown, not through the typed-line path, and not linked to the question that produced it. One ordinary turn on HEAD showed all three:

❯ ?? use cat to print the file nope.txt
[agent] cat nope.txt
  cmd · [Enter: run] [Tab: edit] [Esc: cancel]

✗ cat:: command not found
  │ did you mean: cat?
❯ ??
[agent] Exit code 127 means the shell can't find the echo command in $PATH ...

The agent replied with the command in backticks; the display stripped them but the executor got a command substitution. The failure then left stale error context, so the bare ?? explained a failure of echo hello that never happened. History held three unrelated rows and the agent-interactions table had never been written.

What changes

  • fix(agent): a one-line reply wrapped in backticks runs as the bare command.
  • fix(shell): a command run or edited from an agent reply takes the same path as a typed line (builtins, history, learning, stderr capture, last-error context). It runs as a shell line even when it contains ??, and an agent-returned exit ends the shell.
  • feat(history): every ?? turn is recorded in agent_interactions, linked to the history id of the command it produced. A command reply counts as accepted only once a command ran.
  • feat(history): the Ctrl+R preview shows the question under a command the agent produced.
  • feat(shell): on Enter, the hint line is replaced by the command on its own input line, so scrollback reads as if the user typed it.
  • feat(shell): a "did you mean: git?" correction becomes ghost text for the corrected line, with the accept footer shown only when a ghost will follow.

After the change, the same turn reads:

❯ ?? use cat to print the file nope.txt
[agent] cat nope.txt
│ cat nope.txt
cat: nope.txt: No such file or directory
❯ ??
[agent] The file nope.txt doesn't exist in the current directory ...

Verification

  • Each commit was written test-first; every commit builds, vets and passes tests on its own.
  • go test ./..., go vet ./... and golangci-lint run ./... are clean at the tip.
  • Three live passes on a rebuilt binary against an isolated data directory confirmed: the backticked reply runs as shown, the bare ?? explains the right command, Ctrl+R shows the question under the command, echo a??b from the agent runs as shell, and echo x&&gti status offers echo x&&git status as ghost text.

Known limits

  • A typo in a line that still exits zero (gti status || true) shows the accept footer but no ghost, since the learning loop only tracks failures.
  • The inline ?? path still dispatches the completed line through the ?? parser (pre-existing).
  • In conversation mode a command produced by a follow-up is linked to that reply, not the original question.

@tfcace
tfcace merged commit b5b8a2d into master Oct 9, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant