zsh-autosuggestions: a cat of nine files, three strategies in a fixed order, and a color default that hides itself
Fish-like autosuggestions for zsh
At a glance
- What is it?
- zsh-autosuggestions proposes commands from your history and from the completion engine, and almost every surprise users report traces back to one of its configuration variables: the strategy array short-circuits instead of ranking, the history ignore pattern skips the completion strategy, and the default highlight color can be invisible on a matching background. The last push was June 24, 2025 and the repository publishes no releases.
- Who is it for?
- zsh-autosuggestions is worth the small setup cost if you type repeated commands and want them proposed in gray instead of retyped, and the widget and strategy arrays are the right places to adjust it. Skip it if you rely on history deduplication and want match_prev_cmd to keep working, or if you need history filtering to also cover completions.
- 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?
- Probably not. The repository last received commits 15 months ago, on June 24, 2025.
- What is it written in?
- Mainly Shell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The plugin you install is nine files concatenated by cat
There is no single source file. The Makefile treats src as the source of truth and assembles one artifact from it: the header files, DESCRIPTION, URL, VERSION, and LICENSE, piped through sed so every line becomes a comment, then the nine source files appended in a fixed order. The whole rule is two lines:
$(PLUGIN_TARGET): $(HEADER_FILES) $(SRC_FILES)
cat $(HEADER_FILES) | sed -e 's/^/# /g' > $@
cat $(SRC_FILES) >> $@That order is load order, running config, util, bind, highlight, widgets, strategies, fetch, async, start. Reorder it and the plugin fails somewhere other than where you edited. It also means the large zsh-autosuggestions.zsh in the repository root is generated, so reading it shows you what shipped rather than what is maintained. The clean target removes that artifact with a plain rm and no force flag, so a clean tree makes the target fail instead of succeeding quietly. There is no install target at all, which is why installation lives in its own INSTALL.md file: the Makefile is for contributors.
Strategy order is the whole policy, and match_prev_cmd needs history order
ZSH_AUTOSUGGEST_STRATEGY is an array of strategies tried in order until one returns something, and three are built in. history takes the most recent match. completion takes what tab completion would suggest and needs the zpty module, which has shipped with zsh since 4.0.1. match_prev_cmd takes the most recent match whose preceding history entry equals the command you last ran. Setting `ZSH_AUTOSUGGEST_STRATEGY=(history completion)` therefore does not prefer history, it short-circuits it: any history hit ends the chain and the completion engine never runs, so the second entry is a fallback for when history has nothing to say rather than a tiebreaker between two candidates.
The third strategy carries a sharper requirement, because it reads the relative order of your history. It is documented as not working as expected with HIST_IGNORE_ALL_DUPS or HIST_EXPIRE_DUPS_FIRST, since both deduplicate and rewrite history order as they run. Enable history deduplication for tidiness and match_prev_cmd quietly becomes a different strategy, with no error to tell you that it happened.
The history ignore pattern never reaches the completion strategy
ZSH_AUTOSUGGEST_HISTORY_IGNORE takes a glob pattern and blocks history entries matching it, with the given examples being "cd *" so that no cd command is ever proposed and "?(#c50,)" so that nothing 50 characters or longer is. The scope is stated in a single line: it only affects the history and match_prev_cmd strategies.
That limit is what to check before relying on it. If your reason for setting the pattern is keeping a secret, an access token, or an internal host name off your screen, the completion strategy is untouched and can still propose something, because it answers from what the completion engine would offer rather than from history. The option narrows one of your three sources and leaves the others alone. The second example also uses zsh's extended glob quantifier form, while the option is described only as taking a glob pattern, so that style of pattern also depends on your extended glob setting being enabled.
Invisible suggestions in iTerm2 are a color collision
The proposal is drawn after the cursor in a muted gray, and the default style is fg=8, which is color 8 of the 256-color palette, meaning ANSI bright black. If your terminal background is the same color as the text, the suggestion is rendered correctly and cannot be seen, and the plugin is doing its job. This has been reported by iTerm2 users, and the fix is a setting rather than a patch: open the profile > colors pane and make sure that Basic Colors > Background and ANSI Colors > Bright Black hold different values.
Terminals limited to 8 colors are the other half of the problem, since fg=8 does not exist in that palette, and the documented workaround is a number between 0 and 7. Anything richer goes through ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE, and the given example combines a hex foreground, a background color, and two attributes: `ZSH_AUTOSUGGEST_HIGHLIGHT_STYLE="fg=#ff00ff,bg=cyan,bold,underline"`. The styling syntax is not invented locally, it follows the character highlighting section of the zsh manual, reachable as man zshzle. So when suggestions seem broken, check colors before you check history.
Async is on by default, so disabling it means unsetting a variable
Suggestions are fetched asynchronously in zsh 5.0.8 and later, and the switch runs in opposite directions depending on your zsh. On a modern shell the variable is already set and the behavior is asynchronous, so the way to turn that off is to remove it after the plugin is sourced:
unset ZSH_AUTOSUGGEST_USE_ASYNCAn assignment placed in your configuration before sourcing changes nothing on a modern shell, because the plugin default already applies. Below zsh 5.0.8 the default is synchronous, and setting the variable after sourcing turns asynchronous fetching on, with any value accepted.
That older path carries a known defect: in zsh below 5.0.8, pressing ctrl after an asynchronous fetch fails to reset the prompt immediately, leaving the line in a state you clear by hand. The ordering rule is the same in both directions. The variable is read at source time, so the unset or the assignment has to come after the plugin line rather than before it.
Manual rebind moves widget updates onto you, with no error when you forget
The plugin does not watch for widget changes. It re-binds on every precmd, meaning before each prompt, and ZSH_AUTOSUGGEST_MANUAL_REBIND turns that off, with any value accepted. The stated payoff is a large performance improvement, since the rebind stops running on every single prompt.
The stated cost is that rebinding becomes your job. If any of the five widget lists changes, or if you or another plugin wraps one of the autosuggest widgets, you have to trigger it yourself by running `_zsh_autosuggest_bind_widgets`. That is easy to miss, because nothing errors. The plugin keeps accepting and fetching exactly as before, the keys still work, and the only symptom is that a new entry in ZSH_AUTOSUGGEST_ACCEPT_WIDGETS never takes effect. Widgets that modify the buffer and appear in none of the five arrays still cause a fresh suggestion to be fetched, so a third-party widget that edits your line quietly adds work on every keystroke even with the rebind turned off.
Ruby 2.5.3 on Alpine, a mandatory build argument, and no release since June 24, 2025
The test container shows what contributing costs. It starts from ruby:2.5.3-alpine, takes a build argument naming the zsh version under test, and refuses to proceed without it:
ARG TEST_ZSH_VERSION
RUN : "${TEST_ZSH_VERSION:?}"The colon question mark expansion exits when the value is missing, so the build fails loudly rather than testing whatever zsh the base image happens to carry. After that it installs autoconf, libtool, libcap-dev, pcre-dev, curl, build-base, ncurses-dev, and tmux, runs install_test_zsh.sh to compile that zsh from source, and ends with bundle install. The Makefile test target then runs bundle exec rspec against the spec directory, with rubocop configured at the root. For users none of that applies, since the artifact is one sourced file. For the project's own state the dates do: the last push was June 24, 2025, there are no published releases, and a CHANGELOG.md and VERSION file sit at the root with nothing publishing the latter as a downloadable build.
Editorial conclusion
zsh-autosuggestions is worth the small setup cost if you type repeated commands and want them proposed in gray instead of retyped, and the widget and strategy arrays are the right places to adjust it. Skip it if you rely on history deduplication and want match_prev_cmd to keep working, or if you need history filtering to also cover completions. Before you tune anything, confirm your terminal background differs from ANSI bright black so you are not debugging an invisible color, and remember the last push to this repository was June 24, 2025 with no tagged release to pin.
Frequently asked questions
How do I install zsh-autosuggestions?
The Installation section of the README contains no commands at all and points to INSTALL.md instead, so that file is where the steps live. The one stated requirement is zsh 4.3.11 or later, and what you source is the single generated zsh-autosuggestions.zsh file, which the Makefile assembles from the files under src by concatenating the header files as comments and then the source in a fixed order.
How do I install oh my zsh autosuggestions?
The repository itself gives no Oh My Zsh steps. It mentions Oh My Zsh once, to say where configuration belongs: in a file inside the $ZSH_CUSTOM directory, with a link to Oh My Zsh's own notes on overriding internals. A zsh-autosuggestions.plugin.zsh file sits at the repository root, which is the shape Oh My Zsh expects from a plugin, but the installation sequence comes from INSTALL.md and from your framework, not from here.
What does zsh autosuggestions do?
It suggests commands as you type, based on your history and on completions, and shows the proposal after the cursor in a muted gray. Pressing the right arrow or End, the forward-char and end-of-line widgets, accepts the whole suggestion when the cursor is at the end of the buffer, while the forward-word widget accepts it only up to the point the cursor moves to.
Is zsh autosuggestions safe?
Nothing in the described behavior sends data anywhere, since proposals come from your local history and from the completion engine. What it does do is read your history and wrap your line editor's widgets through five configurable arrays, so the source file is the thing to review before you source it. The requirement is zsh 4.3.11 or later, and the repository publishes no releases, so there is no signed artifact to verify.