fix(atuin): use the packaged binary only

~/.atuin/bin held an old standalone atuin (18.19.0) that the shells
prepended to PATH, shadowing pacman's /usr/bin/atuin (18.21.0). The
daemon runs the packaged binary and migrated the history DB, so every
shell command through the old one failed with "migration 20260818000000
was previously applied but is missing in the resolved migrations".

Drop conf.d/atuin.env.fish, the `. ~/.atuin/bin/env` lines in .bashrc
and .zshrc (atuin init is now guarded on `command -v atuin`), the
cargo-dist receipt, and atuin-pick's ~/.atuin/bin fallback. Also drop
`atuin ai init fish`, which 18.21 removed; config.fish already carries
the `?` binding it emitted.
This commit is contained in:
Prad Nukala committed 2026-10-05 11:00:15 -04:00
1 parent 2049f580f0
commit c3828a747c
10 files changed
+23 -45

No files matched your search

+7 -26
View File
@@ -9,38 +9,22 @@ description: Shell history search with a daemon, directory-scoped up-arrow, tmux
| --- | --- | --- |
| `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](/shell/fish#functions)). 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`:
`atuin` is listed in `.chezmoidata/packages.yaml` for pacman and Homebrew, and the shells use that package's binary (`/usr/bin/atuin` on Arch). Each shell runs `atuin init` only if `atuin` is on `PATH`.
- fish: `conf.d/atuin.env.fish` sources `~/.atuin/bin/env.fish`.
- bash and zsh: `. "$HOME/.atuin/bin/env"` just before `atuin 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](https://opensource.axo.dev/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` |
:::note[No standalone install]
An earlier setup also kept atuin's standalone installer layout in `~/.atuin/bin` (with a cargo-dist `atuin-receipt.json` in the repo) and prepended it to `PATH` from `conf.d/atuin.env.fish` and `. "$HOME/.atuin/bin/env"` in `.bashrc`/`.zshrc`. That copy fell behind the package: the daemon, from the newer package, migrated the history database, and every command the shells ran through the old binary failed with `migration 20260818000000 was previously applied but is missing in the resolved migrations`. The standalone install, its receipt, and the `PATH` lines are gone. Do not reinstall atuin with its curl installer on this setup.
:::
## Shell integration
| Shell | Where | What |
| --- | --- | --- |
| fish | `config.fish`, interactive only | `atuin init fish \| source`, `atuin ai init fish \| source`, and the `?` binding |
| fish | `config.fish`, interactive only | `atuin init fish \| source`, and a copy of the `?` binding (atuin 18.21 removed the `atuin ai init` command that used to emit it) |
| fish | `functions/fish_user_key_bindings.fish` | <kbd>ctrl-w</kbd> runs `atuin ai inline` |
| bash | end of `~/.bashrc` | `eval "$(atuin init bash)"` |
| zsh | end of `~/.zshrc` | `eval "$(atuin init zsh)"` |
@@ -61,10 +45,7 @@ Under tmux, atuin's `[tmux]` settings open the search in a tmux popup (80% wide,
## AI inline
Commit `a82921c` ("add Atuin AI inline integration and keybinding") added the <kbd>ctrl-w</kbd> bind to `fish_user_key_bindings.fish` and the following to `config.fish`:
1. `atuin ai init fish | source`, in the interactive block next to `atuin init fish`.
2. A copy of the `_atuin_ai_question_mark` function that `atuin ai init fish` prints, and `bind "?" _atuin_ai_question_mark`.
Commit `a82921c` ("add Atuin AI inline integration and keybinding") added the <kbd>ctrl-w</kbd> bind to `fish_user_key_bindings.fish`, `atuin ai init fish | source` to `config.fish`, and a copy of the `_atuin_ai_question_mark` function that command printed, with `bind "?" _atuin_ai_question_mark`. atuin 18.21 removed `atuin ai init`, so `config.fish` keeps only the copied function and binding; `atuin ai inline --hook` still works.
The config also sets `[ai] enabled = true`.
@@ -84,7 +65,7 @@ The config also sets `[ai] enabled = true`.
`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 <kbd>?</kbd> types a question mark. To ask for a command, press <kbd>Esc</kbd> and then <kbd>?</kbd> on an empty line, or press <kbd>ctrl-w</kbd> from either mode. The <kbd>ctrl-w</kbd> bind calls `atuin ai inline` without `--hook` and replaces fish's default <kbd>ctrl-w</kbd> word deletion.
bash and zsh do not load `atuin ai init`.
bash and zsh have no AI binding.
## Configuration
+2 -2
View File
@@ -34,7 +34,7 @@ Interactive shells only (`[[ $- != *i* ]] && return`). In order:
7. Sources `~/.config/envman/load.sh` if it is non-empty.
8. **Prompt.** `eval "$(starship init bash)"` if starship is installed.
9. **television.** `eval "$(tv init bash)"` if `tv` is installed (the `_tv` completion), then sources `~/.config/bash/keybinds.bash`.
10. **atuin.** Sources `~/.atuin/bin/env`, then `eval "$(atuin init bash)"`. atuin comes after tv, so it keeps <kbd>ctrl-r</kbd> and <kbd>up</kbd>.
10. **atuin.** `eval "$(atuin init bash)"` if atuin is installed (the package's binary; see [atuin](/shell/atuin#installation)). atuin comes after tv, so it keeps <kbd>ctrl-r</kbd> and <kbd>up</kbd>.
## ~/.zshrc
@@ -49,7 +49,7 @@ Interactive shells only (`[[ $- != *i* ]] && return`). In order:
9. `eval "$(starship init zsh)"` if starship is installed.
10. `eval "$(tv init zsh)"` if `tv` is installed (<kbd>ctrl-t</kbd> smart autocomplete).
11. **Syntax highlighting.** Sources the first `zsh-syntax-highlighting.zsh` found in `/usr/share/zsh/plugins/zsh-syntax-highlighting/`, `/opt/homebrew/share/zsh-syntax-highlighting/`, or `/usr/local/share/zsh-syntax-highlighting/`. The comment says this must stay last, because it wraps every zle widget defined before it.
12. **atuin.** Sources `~/.atuin/bin/env` and runs `eval "$(atuin init zsh)"`. These lines come after the syntax-highlighting block, so despite the comment, syntax highlighting is not actually last. atuin loads after tv, so it keeps <kbd>ctrl-r</kbd>.
12. **atuin.** `eval "$(atuin init zsh)"` if atuin is installed. This line comes after the syntax-highlighting block, so despite the comment, syntax highlighting is not actually last. atuin loads after tv, so it keeps <kbd>ctrl-r</kbd>.
## zsh key bindings
+2 -3
View File
@@ -43,7 +43,6 @@ fish sources `conf.d/*.fish` in name order and then `config.fish`. The numbered
| `30-ssh-agent.fish` | One ssh-agent shared across shells |
| `40-tools.fish` | mise, television, starship, zoxide, entire, hishtory, unsloth |
| `50-terminal-title.fish` | tmux/screen window name from `$PWD` |
| `atuin.env.fish` | Sources `~/.atuin/bin/env.fish` (puts atuin's install dir on `PATH`) |
| `inir-env.fish` | `INIR_VENV` and `ILLOGICAL_IMPULSE_VIRTUAL_ENV` → `~/.local/state/quickshell/.venv` |
| `inir-path.fish` | Prepends `~/.local/bin` to `PATH` if missing |
| `nvm.fish` | nvm.fish plugin events and default-version activation |
@@ -169,10 +168,10 @@ The header comment says the file should stay empty, but it holds the following:
2. **Bottom-pinned prompt.** In interactive shells with `FISH_BOTTOM_PROMPT=1`, `tput cup $LINES 0` moves the cursor to the last row. The comment calls `1` the default, but `10-env.fish` sets `0`, so the prompt stays at the top unless you export `FISH_BOTTOM_PROMPT=1`.
3. `fish_add_path ~/.grok/bin` (grok installer block).
4. Sources `~/.config/envman/load.fish` if it is non-empty.
5. **atuin.** Interactive shells run `atuin init fish | source` and `atuin ai init fish | source`. See [atuin](/shell/atuin).
5. **atuin.** Interactive shells run `atuin init fish | source`. See [atuin](/shell/atuin).
6. `fish_add_path ~/.cmux/bin` and `~/.cache/.bun/bin`.
7. Sources the first readable `~/.config/herdr/plugins/github/herdr-automatic-rename-*/shell/hook.fish`. This is herdr's automatic pane-rename hook ([herdr](/terminal/herdr)).
8. A copy of the `_atuin_ai_question_mark` function that `atuin ai init fish` emits, followed by `bind "?" _atuin_ai_question_mark`.
8. A copy of the `_atuin_ai_question_mark` function that `atuin ai init fish` used to emit (atuin 18.21 removed that command), followed by `bind "?" _atuin_ai_question_mark`.
## Key bindings
+1 -1
View File
@@ -68,7 +68,7 @@ atuin-pick
Opens atuin's interactive search (`atuin search -i --filter-mode directory`), limited to history from the current directory. It then `exec`s an interactive `fish`. If you picked a command, the new fish runs `echo '❯ <cmd>'; <cmd>` via `-C` (`--init-command`), so aliases resolve, a `cd` persists, and the prompt appears below the output. Esc starts a plain fish.
It is written for launch contexts where atuin's shell init never ran. It resolves `atuin` from `PATH` or `~/.atuin/bin/atuin`, and seeds `ATUIN_SESSION` from `atuin uuid` if unset.
It is written for launch contexts where atuin's shell init never ran. It runs `atuin` from `PATH` and seeds `ATUIN_SESSION` from `atuin uuid` if unset.
**Launched by:** <kbd>ctrl+shift+p</kbd> in kitty. `kitty.conf` opens it in a horizontal split (`launch_hs atuin-pick`). Under the kitty-tmux profile, `tmux.conf` runs it with `tmux split-window -v -l 25%` in the current pane's directory. See [kitty](/terminal/kitty) and [atuin](/shell/atuin).