Skip to content

feat(agent-mode): ask the agent to fix the last failed command - #1021

Merged
HalFrgrd merged 1 commit into
HalFrgrd:masterfrom
jakob1379:feat/ai-fix-failing-command
Oct 10, 2026
Merged

HalFrgrd merged 1 commit into
HalFrgrd:masterfrom
jakob1379:feat/ai-fix-failing-command

Conversation

@jakob1379

@jakob1379 jakob1379 commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

Summary

A thefuck-style fix built on agent mode: one key sends the failed command and its exit status to the configured agent. The suggestions appear in the existing agent-output picker.

 Alt+Enter
-  always                  -> runAgentMode
+  empty buffer            -> fixLastCommand   # works on legacy terminals
+  otherwise               -> runAgentMode
+Alt+Shift+Enter / Meta+Shift+Enter
+  always                  -> fixLastCommand   # needs extended key codes
fixLastCommand
  agent not configured
    empty buffer -> put last command in buffer   # the setup flow from #1011 keeps it
    show setup dialog
  empty buffer   -> "This Bash command exited with status $?. Fix it:\n<last command>"
  otherwise      -> "Fix this Bash command:\n<buffer, trigger prefix stripped>"
  start_agent_mode(prompt)

The command comes from bash's own history, gated by what this shell just submitted:

on submit (not a PS2 continuation)
  last_command = None
  remember bash's last history entry (pointer)
next prompt
  keep bash's last history line only if
    bash added a new entry            # our command, already !!-expanded and multi-line joined
    or it equals what we submitted    # ignoredups
  otherwise last_command stays None   # ignorespace / HISTIGNORE / set +o history

So anything bash keeps out of history is never sent to the agent. Reading "the last history entry" directly wasn't enough: on the default Bash backend, entries have no session, so it could be yesterday's line from another terminal.

Evidence

  • cargo test --lib: 873 passed. cargo clippy --workspace --all-features -D warnings and cargo fmt --check are clean.
  • Live bash run through tmux with HISTCONTROL=ignoreboth, using a stub agent that records the prompt it receives:
Typed Agent receives
false This Bash command exited with status 1. Fix it:\nfalse
secret-cmd --token=abc (not called)
ls /nope twice (ignoredups) …status 2. Fix it:\nls /nope
for i in 1; do ⏎ false; done …status 1. Fix it:\nfor i in 1; do false; done
true, then secret2 (not called)
echo hi, then !! (a dup under ignoredups) (not called): safe direction, no fix offered
  • There's no automated test for the handler. App can't be built in lib tests, and the docker harness has no agent-mode coverage.

Merge Danger

Door: two-way

Blast Radius: keybindings

  • Alt+Enter on an empty buffer changes meaning. Before, it ran the agent with an empty prompt. Now it fixes the previous command. start_agent_mode has a TODO about empty-buffer UX (maybe opening agent-prompt history search); this change takes that slot. @HalFrgrd, is that OK?
  • Privacy: only commands bash keeps in history are ever sent. check_add_history couldn't be the filter, because it also adds the line to history.
  • After the setup dialog, the fix context is lost. The command comes back in the buffer, but its exit status doesn't, and Alt+Enter on a non-empty buffer sends it as a plain question.

@jakob1379
jakob1379 marked this pull request as ready for review September 30, 2026 10:17
@HalFrgrd

HalFrgrd commented Oct 4, 2026

Copy link
Copy Markdown
Owner

I like this idea!

The main point I'm not confident on is do we really need to bypass HistoryManager and use bash's history vec symbol directly? If the reason to bypass HistoryManager is that in some niche scenarios we might use a command from a previous session / a repeated command, then I don't think it is worth the complexity and we should use HistoryManager.

when the history backend is bash, flyline reads directly from bash's history vec and when the backend is flyline, we first check bash_funcs::check_add_history before appending an entry so if we use HistoryManager, we won't pass the agent any command we have chosen to ignore.

@jakob1379

Copy link
Copy Markdown
Contributor Author

I like this idea!

The main point I'm not confident on is do we really need to bypass HistoryManager and use bash's history vec symbol directly? If the reason to bypass HistoryManager is that in some niche scenarios we might use a command from a previous session / a repeated command, then I don't think it is worth the complexity and we should use HistoryManager.

when the history backend is bash, flyline reads directly from bash's history vec and when the backend is flyline, we first check bash_funcs::check_add_history before appending an entry so if we use HistoryManager, we won't pass the agent any command we have chosen to ignore.

i think bash_funcs::check_add_history is the one i missed! That would reduce this a lot. I 'll implement it and update this as soon as I can get to it

@jakob1379
jakob1379 force-pushed the feat/ai-fix-failing-command branch from abf8259 to 93cc6bf Compare October 5, 2026 07:35
Alt+Shift+Enter (or Alt+Enter on an empty prompt) sends the last command
in flyline's history, plus $?, to the configured agent. Commands excluded
from history never reach the agent. On a non-empty buffer it asks the
agent to fix the buffer text instead.
@jakob1379
jakob1379 force-pushed the feat/ai-fix-failing-command branch from 93cc6bf to 6fb806f Compare October 5, 2026 07:36
@HalFrgrd
HalFrgrd merged commit 7e2c0c0 into HalFrgrd:master Oct 10, 2026
7 checks passed
@jakob1379
jakob1379 deleted the feat/ai-fix-failing-command branch October 11, 2026 15:33
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.

2 participants