atuin
Shell history search with a daemon, directory-scoped up-arrow, tmux popups, a cyberdream theme, and the atuin AI inline command generator.
atuin replaces shell history search in fish, bash, and zsh. It also provides atuin ai inline, a natural-language command generator that the fish config binds to keys.
| Source (repo) | Target | Notes |
|---|---|---|
dot_config/atuin/private_config.toml |
~/.config/atuin/config.toml |
private_: written as a regular 0600 file, not a symlink |
dot_config/atuin/themes/cyberdream.toml |
~/.config/atuin/themes/cyberdream.toml |
symlink |
dot_config/atuin/atuin-receipt.json |
~/.config/atuin/atuin-receipt.json |
symlink |
chezmoi runs in symlink mode, but private_ files are written as real files, so edits to ~/.config/atuin/config.toml do not reach the repo on their own. Copy them back with chezmoi re-add (or czs, see fish). None of the files are templates, and they apply on every role.
Installation
atuin is listed in .chezmoidata/packages.yaml for pacman and Homebrew. The shells also expect atuin’s standalone installer layout in ~/.atuin/bin:
- fish:
conf.d/atuin.env.fishsources~/.atuin/bin/env.fish. - bash and zsh:
. "$HOME/.atuin/bin/env"just beforeatuin init.
Neither line checks that the file exists, so a machine without ~/.atuin/bin prints a sourcing error at shell start.
atuin-receipt.json
The receipt that atuin’s cargo-dist installer writes. It records how atuin was installed, which the self-updater (atuin update) needs:
| Field | Value |
|---|---|
binaries |
["atuin"] |
install_prefix |
~/.atuin/bin (stored as an absolute path under /home/prad) |
install_layout |
flat |
modify_path |
true |
provider |
cargo-dist 0.31.0 |
source |
GitHub release atuinsh/atuin |
version |
18.19.0 |
Shell integration
| Shell | Where | What |
|---|---|---|
| fish | config.fish, interactive only |
atuin init fish | source, atuin ai init fish | source, and the ? binding |
| fish | functions/fish_user_key_bindings.fish |
ctrl-w runs atuin ai inline |
| bash | end of ~/.bashrc |
eval "$(atuin init bash)" |
| zsh | end of ~/.zshrc |
eval "$(atuin init zsh)" |
In fish, 40-tools.fish sources hishtory before atuin, but atuin’s init runs later in config.fish and takes ctrl-r. zsh also loads suv init zsh (suvadu) if installed.
Key bindings
| Key | Shells | Action |
|---|---|---|
| ctrl-r | all | Interactive search (_atuin_search) |
| up | all | Search opened from the up arrow. filter_mode_shell_up_key_binding = "directory" limits it to history from the current directory |
| ? | fish, vi normal mode | On an empty buffer, runs atuin ai inline --hook |
| ctrl-w | fish, insert and normal mode | atuin ai inline, then repaint |
| ctrl+shift+p | kitty | atuin-pick: directory-filtered search in a split, running the pick in a fresh fish |
Under tmux, atuin’s [tmux] settings open the search in a tmux popup (80% wide, 60% tall) instead of inline.
AI inline
Commit a82921c (“add Atuin AI inline integration and keybinding”) added the ctrl-w bind to fish_user_key_bindings.fish and the following to config.fish:
atuin ai init fish | source, in the interactive block next toatuin init fish.- A copy of the
_atuin_ai_question_markfunction thatatuin ai init fishprints, andbind "?" _atuin_ai_question_mark.
The config also sets [ai] enabled = true.
_atuin_ai_question_mark works like this:
-
Buffer empty (or just
?): clears the line, prints OSC133;Cto/dev/ttyto close the terminal’s semantic prompt zone (so shell-integrated terminals do not erase the TUI during a prompt reflow), then runsatuin ai inline --hookwith stdout and stderr swapped. The TUI draws on the terminal, and the result comes back tagged:Output prefix Effect __atuin_ai_print__:Print the text, repaint __atuin_ai_cancel__Repaint only __atuin_ai_execute__:Put the command on the line and execute it __atuin_ai_insert__:Put the command on the line for editing anything else, non-empty Put it on the line for editing -
Buffer not empty: inserts a literal
?under emacs bindings. Under vi or hybrid bindings, which this config uses, it does nothing.
bind "?" in config.fish has no -M flag, so it applies to fish’s default mode, which is vi normal mode here. In insert mode ? types a question mark. To ask for a command, press Esc and then ? on an empty line, or press ctrl-w from either mode. The ctrl-w bind calls atuin ai inline without --hook and replaces fish’s default ctrl-w word deletion.
bash and zsh do not load atuin ai init.
Configuration
config.toml is atuin’s generated sample with a few keys set. The rest are commented-out defaults. The settings that take effect:
| Key | Value | Effect |
|---|---|---|
filter_mode_shell_up_key_binding |
"directory" |
Up-arrow search shows only the current directory’s history |
dotfiles.enabled |
true |
Enables atuin’s dotfiles feature (aliases and vars managed by atuin) |
daemon.enabled |
true |
Uses the background daemon |
daemon.autostart |
true |
atuin starts and manages the daemon itself |
pty_proxy.enabled |
false |
atuin init does not re-exec the shell inside atuin pty-proxy |
theme.name |
"cyberdream" |
Loads themes/cyberdream.toml |
tmux.enabled |
true |
Search opens in a tmux popup when inside tmux (tmux 3.2+) |
tmux.width / tmux.height |
"80%" / "60%" |
Popup size |
ai.enabled |
true |
Enables atuin ai |
No sync server, key, or session is configured in the repo. atuin keeps its encryption key and session under ~/.local/share/atuin, outside chezmoi, and uses the default sync server.
Theme
themes/cyberdream.toml defines a theme named cyberdream, using the palette shared with fish and Starship:
| Key | Color |
|---|---|
AlertInfo |
#5ef1ff |
AlertWarn |
#f1ff5e |
AlertError |
#ff6e5e |
Annotation |
#7b8496 |
Guidance |
#5ea1ff |
Important |
#ff5ef1 |
Title |
#5ef1ff |
Muted |
#7b8496 |
SyntaxCommand |
#5ea1ff |
SyntaxFlag |
#5ef1ff |
SyntaxString |
#5eff6c |
SyntaxVariable |
#ff5ef1 |
SyntaxOperator |
#ff5ea0 |
SyntaxComment |
#7b8496 |