← Home

GPT-Powered Terminal Error Correction

August 6, 2024

How many times have you copied and pasted a pesky error messgae from the terminal into either Google or ChatGPT? Wouldn't it be nice if your terminal told you directly right there and then what was wrong with that command that didn't work?

This is why I made a simple bash + python script that monitors the stderr for any errors and makes an API call to Gpt to present the solution. It also pastes the correct command at the next prompt if it's able to determine what that might be.

Here is how it looks like:

    The code is a combination of a python script that makes calls to openai and a bash script that goes in your .bashrc or .zshrc, etc.

    Paste this into your .bashrc:

    exec 2> >(tee -a /tmp/term_err.log >&2)
    handle_errors() {
      python ~/handle_errors.py
    }
    handle_nonerrors() {
      echo $BASH_COMMAND > /tmp/term_err.log
    }
    trap handle_errors ERR
    trap handle_nonerrors DEBUG
    

    And save this in your home dir as ~/handle_errors.py:

    import fcntl
    import termios
    import sys, os
    import openai
    
    LIGHT_BLUE = "POST33[38;5;81m"
    RESET = "POST33[0m"
    
    openai.api_key = os.getenv('OPENAI_API_KEY')
    
    input_text = open('/tmp/term_err.log').read()
    messages = [
        {'role': 'system', 'content': 'if it is a simple typo just fix it and only return the cmd plus a new line at the end of your cmd, otherwise explain why this happened very briefly and the last line of your response must be with the correct bash cmd and nothing else, starting with ~ e.g.: ~ls -l'},
        {'role': 'user', 'content': input_text[:400]},
    ]
    
    res = openai.ChatCompletion.create(
      model='gpt-4o',
      messages=messages,
      stream=True
    )
    
    started = False
    sys.stdout.write('  ')
    msg = ''
    for resp in res:
        delta = resp.choices[0].delta
        chunk = delta.content if "content" in delta else ''
        msg += chunk
        for char in chunk:
            if char == '~':
                started = True
            elif started:
                sys.stdout.write('\r')
                fcntl.ioctl(sys.stdin, termios.TIOCSTI, char)
        if not started:
            chunk = chunk.replace('\n', '')
            print(f'{LIGHT_BLUE}{chunk}{RESET}', end='', flush=True)
    
    sys.stdout.write('\r ')
    
    if 'typo' in msg or len(msg) < 4:
        fcntl.ioctl(sys.stdin, termios.TIOCSTI, '\n')
    
    

    Join the Newsletter

    Subscribe to get our latest content by email.




      Other Posts