# AI command generation in the fish shell

URL: https://joaocosta.dev/blog/16
Published: 2025-05-28 · 2 min read

I want to share a cool little fish function that I started using to suggest/improve the commands I'm writting.

## Why not just use github copilot cli

So, I tried using [Github's copilot cli](https://docs.github.com/en/copilot/using-github-copilot/using-github-copilot-in-the-command-line), but it just felt slow/cumbersome. Even when using aliases, it just broke my workflow.

```bash
alias cop="gh copilot suggest -t shell"
alias copg="gh copilot suggest -t git"
alias cope="gh copilot explain"
```

## What I came up with

A friend at work complained that VSCode started annoying him with copilot stuff in the terminal, so I went to check it out. Basically, Microsoft started showing a prompt to open copilot in Code's terminal with a ctrl+i keybind. This gave me the idea to do something similar.

In [fish](https://fishshell.com/) we have access to a `commandline` built-in that allows manipulating the content of the prompt. I already used, for example, to prepend `sudo` to a command when I forget it:

```fish
# pipe bindings
# append | less and execute
bind \el -M insert 'commandline -a "| less" && commandline -f execute'
# prefix yes | and execute
bind \ey -M insert 'commandline -C 0 && commandline -i "yes | " && commandline -f execute'
# prefix sudo
bind \es -M insert 'commandline -C 0 && commandline -i "sudo "'
```

So I wrote this function. This gets the current content of the command line, generates an AI based suggestion, and replaces it with the result:

```fish
function ai_cmd_suggest
    set -l base_prompt
    if test (count $argv) -ge 1
        set base_prompt "$argv[1]"
    else
        return 1
    end

    set -l current_content (commandline)

    set -l prompt "Only provide a single fish shell command as your response. Do not include any explanations, markdown formatting (like ```), or extra text. $base_prompt\n```fish\n$current_content\n```"
    set -l new_cmd (echo "$prompt" | ask | string trim)

    # Replace the current commandline content with the AI's suggestion
    set -l cmd_line "# $current_content
$new_cmd"
    commandline "$cmd_line"
    commandline --cursor (string length "$cmd_line") # Move cursor to end
end
```

The `ask` command is just an alias/script that I use to wrap-around [simonw's llm tool](https://llm.datasette.io/en/stable/). I use it to interact with Google's Gemini models:

```bash
#!/bin/sh

cat | llm -m 'gemini-2.0-flash' "$@"
```

### How to use it

I set 2 keybindings for the script. These keybindings contain the actual prompt.

```fish
bind \ei -M insert 'ai_cmd_suggest "Suggest a command for the following description:"'
bind \eI -M insert 'ai_cmd_suggest "Improve and/or fix the following command:"'
```

With this, I can:

- Write the description for a command and then press `alt+i` to replace it with a command.
- Write a command and then press `alt+I` to replace it with a fixed/improved version of the original.

## Conclusion

This has been working pretty well and seems to be faster than Github's copilot tool. Although the processing is pretty fast, a loading spinner would be cool, but for now this is good enough.
Stay safe :P
