CLI tool
Realiserad/fish-ai avatar
Realiserad/fish-ai

fish-ai: LLM command generation and repair inside the Fish shell

Supercharge your command line with LLMs and get shell scripting assistance in Fish. 💪

561 stars46 forksPythonMIT

At a glance

What is it?
fish-ai is a Fisher-installed Fish plugin that turns comments into shell commands, fixes broken ones, and offers model-backed autocompletion through two keyboard shortcuts. It talks to Anthropic, OpenAI, Azure, Bedrock, Cohere, DeepSeek, Google, Groq, OpenRouter or any OpenAI-compatible server you host yourself.
Who is it for?
Adopt fish-ai if you already live in Fish, want command generation and repair without leaving the prompt, and are willing to maintain an INI file with an API key. Skip it if you need a provider the plugin does not list, if you cannot send shell context to a remote model, or if you want a project with an active feature roadmap, since the author describes it as largely feature complete.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The typing problem fish-ai targets

The README frames the problem in terms of parameter-heavy tools: git, kubectl, curl. These are commands where you know the intent and not the flags, so the loop becomes a manpage search, a browser tab, and a paste. fish-ai collapses that loop into the prompt. You write a comment describing what you want, and the plugin produces a command. The inverse direction exists too: given a command, it can explain what it does. It also repairs a command you typed wrong, which the README compares to thefuck, and it can autocomplete the next command through a fuzzy finder when you have no specific target in mind. The audience is narrow on purpose. This is a Fish plugin, installed through Fisher, for people who already use Fish as their interactive shell and who have an API key for a hosted model or a server running locally. If you use bash or zsh, nothing here applies to you. The README also states the codebase is around 2000 lines, which the author presents as something you can audit in an afternoon. That is a claim about size, not about correctness, and you should treat it as an invitation to read rather than a guarantee.

Two keybindings, one Python process, and the INI file that selects a provider

The interaction surface is deliberately small: the README says everything is done through two configurable keyboard shortcuts, no mouse. That means the plugin is not a wrapper around your shell. It does not intercept command execution, install telemetry, or require a specific terminal emulator, all of which the README calls out as things it avoids. The provider layer is configuration-driven. A file at $XDG_CONFIG_HOME/fish-ai.ini, or ~/.config/fish-ai.ini when that variable is unset, holds one or more sections. A top-level [fish-ai] section with a configuration key names which other section is active, and that section carries provider, api_key, model, and depending on the backend, server, organization, aws_region, aws_profile, bedrock_api, or extra_body. The provider value is not always the vendor name. OpenRouter is configured with provider = self-hosted plus a server URL pointing at https://openrouter.ai/api/v1, and a local Ollama instance uses the same provider value with a localhost server. So the plugin has a small set of provider adapters and a generic OpenAI-compatible path that covers several services. The Python side is what actually talks to the model; the Fish side handles the keybinding, the prompt buffer and the fuzzy finder. The README does not document the wire format of the requests, the prompt templates, or how the generated command is inserted into the buffer, so anyone who needs to reason about exactly what text leaves the machine will have to read the source.

Installing with fisher and writing the first configuration block

The documented install path is Fisher, with git and either uv or a supported Python version plus pip and venv present. The command is fisher install realiserad/fish-ai. Updates go through the same tool, which is one of the reasons the README lists Fisher as a selling point. Configuration comes next, and it is a plain INI file, not a wizard. For Anthropic, the README gives a section named [anthropic] with provider = anthropic, api_key, and model = claude-sonnet-4-6. For OpenAI, the pattern adds the indirection: [fish-ai] with configuration = openai, then an [openai] section with provider, model, api_key and organization. Azure follows the same shape with configuration = azure and a server URL of the form https://<your instance>.openai.azure.com plus a deployment name in the model field. Bedrock is the most involved. The README documents two access paths. The Converse API uses configuration = aws-converse and a section with provider = bedrock, bedrock_api = converse, model, aws_region and aws_profile, and it requires the bedrock:InvokeModel permission. The Mantle gateway uses configuration = aws-mantle, omits bedrock_api, and requires bedrock-mantle:CreateInference. In both cases, if no api_key is set, the plugin generates a short-term token from your AWS credentials, and aws_profile selects a named profile; omit it and the default credential chain runs. For a local model, the README recommends Ollama with Llama 3.3 70B and shows a [local-llama] section with provider = self-hosted, model = llama3.3 and a localhost server. Note that the README's local example is truncated mid-URL in the supplied text, so copy the server line from the repository rather than from a summary.

Where the configuration model bites back

The indirection between [fish-ai] configuration and the named section is the most likely place to lose time. If configuration = azure and the section is called [azure], fine. If you rename the section without updating the key, the plugin has no provider to load, and the README does not describe the failure output you would see. The same applies to the OpenRouter and self-hosted cases, where two very different services share provider = self-hosted and are separated only by the server URL. That is a compact design, but it means a typo in server silently changes which endpoint receives your shell context. The extra_body key is another sharp edge: the OpenRouter example passes a JSON object with a reasoning configuration inline in the INI file, so malformed JSON there is a configuration error the plugin may or may not surface clearly. Beyond configuration, the honest limitation is scope. The README says the author considers the project largely feature complete and asks people to open an issue before sending a feature PR. That is a maintenance posture, not a defect, but it tells you what to expect: bug fixes welcome, new capabilities negotiated. If your workflow needs a provider that is not in the list of adapters, you are writing it yourself. And if your policy forbids sending command text to a third party, the only configuration that respects that is the self-hosted or Ollama path, since every other provider block sends your prompt to a remote endpoint by design.

fish-ai against thefuck and against a plain chat window

The README itself names thefuck as the closest analogue for the repair case. The difference in approach is that thefuck matches a failed command against a set of rule-based correctors, while fish-ai sends the command to a language model and returns whatever the model produces. Rule-based correction is predictable and offline; model-based correction handles mistakes no rule anticipated but can invent a plausible-looking command that is wrong. For the generation case, the alternative is a browser tab or a terminal chat client. Both let you ask for a command in prose. The difference is that fish-ai keeps the result inside the Fish prompt, so the generated text lands where you would type it, and the fuzzy-finder autocompletion has no real equivalent in a chat window. What you give up by staying in the prompt is context control: a chat client lets you paste error output, documentation or a file excerpt before asking, and the README does not describe any mechanism for attaching arbitrary context to a fish-ai request. For short, self-contained requests (a git flag, a curl invocation, a kubectl subcommand) that trade-off favors the plugin. For anything requiring surrounding context, the chat window is still the better tool.

Licence, updates and what maintenance actually costs

The repository is MIT licensed, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained. That is the standard permissive position and it is compatible with vendoring the plugin into an internal dotfiles repository, though the usual caveat applies: keep the licence text with the code, and if you fork it, the MIT terms travel with the fork. This is a description of the licence, not legal advice. On maintenance, the release history shows a steady cadence of patch releases through 2026, with v2.13.1 in late May, preceded by v2.11.1 in April and v2.10.6 in March. The version jumps between releases suggest the project does not promise semantic versioning discipline in the strict sense, so pinning a known-good tag in your dotfiles and upgrading deliberately is safer than running fisher update on a whim. The cost of ownership is otherwise low: one INI file, one API key per provider, and a Python runtime. The variable cost is the model bill, which depends entirely on how often you invoke the two keybindings and which model you configure. The README does not publish token counts or cost estimates, and you should not infer any from the repository.

Editorial conclusion

Adopt fish-ai if you already live in Fish, want command generation and repair without leaving the prompt, and are willing to maintain an INI file with an API key. Skip it if you need a provider the plugin does not list, if you cannot send shell context to a remote model, or if you want a project with an active feature roadmap, since the author describes it as largely feature complete. Before installing, check the pinned Python workflow in .github/workflows/python-tests.yaml against your interpreter, confirm where $XDG_CONFIG_HOME resolves on your machine, and read the provider block for your chosen backend because the section name and the configuration key must match.

Official sources

  1. Issues
  2. License: MIT
  3. README
  4. Realiserad/fish-ai on GitHub
  5. Releases
Community notes

Community notes