fixlast reads the last interactive shell command and its logged output, then
sends a prompt built from both to the Codex CLI which tries to fix the error.
Important: on Linux, the output of an already finished shell command cannot be
reliably recovered after the fact. Terminal scrollback belongs to the terminal,
not the shell, and stdout/stderr from past processes are not persisted
automatically. For that reason, fixlast installs shell hooks and starts the
interactive shell under script(1) by default, so future commands are logged
while they run.
bin/fixlast: Main script.share/fixlast/bash.sh: Bash integration.share/fixlast/zsh.zsh: Zsh integration.share/fixlast/fish.fish: Fish integration.install.sh: Installs to~/.localor$PREFIX.uninstall.sh: Removes installed files.
./install.shIf ~/.local/bin is not in PATH:
export PATH="$HOME/.local/bin:$PATH"Near the top of ~/.bashrc:
[ -r "$HOME/.local/share/fixlast/bash.sh" ] && . "$HOME/.local/share/fixlast/bash.sh"Then start a new Bash shell.
The Bash integration uses PS0 and requires Bash 4.4 or newer. The command is
read from Bash history. Commands that are intentionally not written to history,
for example through HISTCONTROL=ignorespace, are not captured as plaintext
commands. This is safer than accidentally sending secret history-bypass input.
Near the top of ~/.zshrc:
[ -r "$HOME/.local/share/fixlast/zsh.zsh" ] && . "$HOME/.local/share/fixlast/zsh.zsh"Then start a new Zsh shell.
The Zsh integration uses native preexec and precmd hooks and captures the
full command as entered.
Near the top of ~/.config/fish/config.fish:
test -r "$HOME/.local/share/fixlast/fish.fish"; and source "$HOME/.local/share/fixlast/fish.fish"Then start a new Fish shell.
The Fish integration uses native fish_preexec and fish_postexec events. The
full command as entered is passed directly by the event. Syntax errors are
captured via fish_posterror with at least the command and status; for those
cases there is no reliable output boundary because fish_preexec does not run.
The source line should be placed near the top of the relevant rc file. On first
load, the integration replaces the shell with a script(1) PTY session; after
that, the rc file is read again in the inner shell. If the line is placed near
the bottom, earlier rc side effects may run twice.
make test
fixlastfixlast then generates roughly:
The last executed shell command was:
make test
The output was:
<output from make test>
Please analyze the error and suggest a concrete fix.
Before sending, fixlast asks interactively. During that step, the prompt can
be displayed or edited.
Send directly:
fixlast --yesOnly show the prompt:
fixlast --previewEdit the prompt in an editor before sending:
fixlast --editBy default, the tool uses the robust stdin variant:
codex exec --skip-git-repo-check -C "$COMMAND_CWD" - < "$PROMPT_FILE"This works better for long prompts with the locally installed Codex CLI than a
plain argument string. --skip-git-repo-check is set because fixlast is often
started from arbitrary working directories, not only from Git repositories.
Interactive Codex UI:
FIXLAST_CODEX_MODE=interactive fixlastThis corresponds to:
codex -C "$COMMAND_CWD" "$PROMPT"Configurable variants:
FIXLAST_CODEX_BIN=/usr/local/bin/codex fixlast
FIXLAST_CODEX_MODE=args fixlast
FIXLAST_CODEX_COMMAND='codex exec --skip-git-repo-check -C "$FIXLAST_COMMAND_CWD" - < "$FIXLAST_PROMPT_FILE"' fixlastFIXLAST_CODEX_COMMAND is executed with sh -c and should only come from
trusted configuration.
Diagnostics:
fixlast doctorCommon cases:
no captured command found: the shell integration is not loaded, or the current shell was started before installation.- No output in the prompt: the command was silent, the log was deleted, or the
shell was not running under
script(1). Codex binary not found:codexis not inPATH; setFIXLAST_CODEX_BIN.- Bash reports that transparent capture is missing: Bash is older than 4.4.
- Fish captures syntax errors without output: this is expected behavior because
fish_preexecis not executed for syntax errors.
fixlast redacts common secret patterns by default, including:
Authorization: Bearer ...password=...,token=...,api_key=...,secret=...- OpenAI keys with
sk-... - GitHub tokens with
ghp_...,gho_...,ghu_...,ghs_...,ghr_... - AWS Access Key IDs with
AKIA... - Passwords in URLs such as
https://user:pass@example.com
This redaction is intentionally conservative, but it cannot be proven complete. For sensitive error output, use:
fixlast --preview
fixlast --editDisable redaction:
fixlast --no-redactRaw logs are stored locally with restrictive permissions under:
${XDG_STATE_HOME:-$HOME/.local/state}/fixlast
Prompts and temporary files are stored under:
${XDG_CACHE_HOME:-$HOME/.cache}/fixlast
Delete logs and cache:
fixlast clean --logsThe shell integration starts the interactive shell under script(1) by default.
This is more robust than exec > >(tee ...) because programs still see a PTY.
Colors, interactive programs, and TTY detection therefore behave much closer to
normal terminal behavior.
Disable the script(1) wrapper:
export FIXLAST_NO_SCRIPT=1After that, fixlast can still capture the command and status in the future,
but it cannot capture output reliably.
./uninstall.shThen remove the source line from ~/.bashrc, ~/.zshrc, or
~/.config/fish/config.fish.
Local logs are intentionally kept. Delete them first with:
fixlast clean --logs