Skip to content

decipher2k/fixlast

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

fixlast

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.

Components

  • 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 ~/.local or $PREFIX.
  • uninstall.sh: Removes installed files.

Installation

./install.sh

If ~/.local/bin is not in PATH:

export PATH="$HOME/.local/bin:$PATH"

Bash Integration

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.

Zsh Integration

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.

Fish Integration

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.

Example Usage

make test
fixlast

fixlast 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 --yes

Only show the prompt:

fixlast --preview

Edit the prompt in an editor before sending:

fixlast --edit

Codex CLI

By 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 fixlast

This 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"' fixlast

FIXLAST_CODEX_COMMAND is executed with sh -c and should only come from trusted configuration.

Troubleshooting

Diagnostics:

fixlast doctor

Common 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: codex is not in PATH; set FIXLAST_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_preexec is not executed for syntax errors.

Security

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 --edit

Disable redaction:

fixlast --no-redact

Raw 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 --logs

Logging Details

The 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=1

After that, fixlast can still capture the command and status in the future, but it cannot capture output reliably.

Uninstallation

./uninstall.sh

Then remove the source line from ~/.bashrc, ~/.zshrc, or ~/.config/fish/config.fish.

Local logs are intentionally kept. Delete them first with:

fixlast clean --logs

About

Uses ChatGPT Codex to fix the last error that appeared on the Linux shell.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages