diff --git a/docs/shell/atuin.mdx b/docs/shell/atuin.mdx
index 010f4d8..1001221 100644
--- a/docs/shell/atuin.mdx
+++ b/docs/shell/atuin.mdx
@@ -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` | ctrl-w 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 ctrl-w 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 ctrl-w 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 ? 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`.
+bash and zsh have no AI binding.
## Configuration
diff --git a/docs/shell/bash-zsh.mdx b/docs/shell/bash-zsh.mdx
index cad50ea..2df0e32 100644
--- a/docs/shell/bash-zsh.mdx
+++ b/docs/shell/bash-zsh.mdx
@@ -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 ctrl-r and up.
+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 ctrl-r and up.
## ~/.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 (ctrl-t 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 ctrl-r.
+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 ctrl-r.
## zsh key bindings
diff --git a/docs/shell/fish.mdx b/docs/shell/fish.mdx
index a3141c5..9b873c9 100644
--- a/docs/shell/fish.mdx
+++ b/docs/shell/fish.mdx
@@ -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
diff --git a/docs/shell/scripts.mdx b/docs/shell/scripts.mdx
index e04249a..7636fd6 100644
--- a/docs/shell/scripts.mdx
+++ b/docs/shell/scripts.mdx
@@ -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 '❯ '; ` 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:** ctrl+shift+p 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).
diff --git a/dot_bashrc b/dot_bashrc
index f0640e3..4745761 100644
--- a/dot_bashrc
+++ b/dot_bashrc
@@ -65,8 +65,10 @@ command -v tv >/dev/null 2>&1 && eval "$(tv init bash)"
# Readline keybinds — bash ports of fish_user_key_bindings.fish (tv cables)
[ -f "$HOME/.config/bash/keybinds.bash" ] && . "$HOME/.config/bash/keybinds.bash"
-. "$HOME/.atuin/bin/env"
-eval "$(atuin init bash)"
+# atuin comes from the package manager (/usr/bin). No ~/.atuin/bin: an old
+# standalone install there shadowed it on PATH and its older schema rejected
+# the history DB the newer daemon had migrated.
+command -v atuin >/dev/null 2>&1 && eval "$(atuin init bash)"
# >>> termium >>>
case ":$PATH:" in *:'/home/prad/.local/bin':*) ;; *) export PATH='/home/prad/.local/bin':"$PATH" ;; esac
diff --git a/dot_config/atuin/atuin-receipt.json b/dot_config/atuin/atuin-receipt.json
deleted file mode 100644
index 54886ca..0000000
--- a/dot_config/atuin/atuin-receipt.json
+++ /dev/null
@@ -1 +0,0 @@
-{"binaries":["atuin"],"binary_aliases":{},"cdylibs":[],"cstaticlibs":[],"install_layout":"flat","install_prefix":"/home/prad/.atuin/bin","modify_path":true,"provider":{"source":"cargo-dist","version":"0.31.0"},"source":{"app_name":"atuin","name":"atuin","owner":"atuinsh","release_type":"github"},"version":"18.19.0"}
diff --git a/dot_config/fish/conf.d/atuin.env.fish b/dot_config/fish/conf.d/atuin.env.fish
deleted file mode 100644
index d058327..0000000
--- a/dot_config/fish/conf.d/atuin.env.fish
+++ /dev/null
@@ -1,2 +0,0 @@
-
-source "$HOME/.atuin/bin/env.fish"
diff --git a/dot_config/fish/config.fish b/dot_config/fish/config.fish
index 20c49e6..0796692 100644
--- a/dot_config/fish/config.fish
+++ b/dot_config/fish/config.fish
@@ -35,7 +35,8 @@ test -s ~/.config/envman/load.fish; and source ~/.config/envman/load.fish
if status is-interactive
atuin init fish | source
- atuin ai init fish | source
+ # atuin 18.21 dropped `atuin ai init`; the `?` binding it used to emit is
+ # copied below as _atuin_ai_question_mark.
end
# cmux
diff --git a/dot_local/bin/executable_atuin-pick b/dot_local/bin/executable_atuin-pick
index 1708877..df89662 100755
--- a/dot_local/bin/executable_atuin-pick
+++ b/dot_local/bin/executable_atuin-pick
@@ -9,12 +9,11 @@ output in the split, and the prompt drops down below it.
"""
import os
import shlex
-import shutil
import subprocess
-# kitty's launch env has neither ~/.atuin/bin on PATH nor ATUIN_SESSION
-# (atuin's shell init never ran), so resolve and seed both here.
-atuin = shutil.which("atuin") or os.path.expanduser("~/.atuin/bin/atuin")
+# kitty's launch env has no ATUIN_SESSION (atuin's shell init never ran), so
+# seed it here. atuin itself comes from the package manager, on PATH.
+atuin = "atuin"
if "ATUIN_SESSION" not in os.environ:
os.environ["ATUIN_SESSION"] = subprocess.run(
[atuin, "uuid"], stdout=subprocess.PIPE, text=True
diff --git a/dot_zshrc b/dot_zshrc
index a090a3a..f7c790e 100644
--- a/dot_zshrc
+++ b/dot_zshrc
@@ -80,9 +80,8 @@ for _zsh_hl in \
done
unset _zsh_hl
-. "$HOME/.atuin/bin/env"
-
-eval "$(atuin init zsh)"
+# atuin comes from the package manager (/usr/bin); see ~/.bashrc.
+command -v atuin >/dev/null 2>&1 && eval "$(atuin init zsh)"
# >>> termium >>>
case ":$PATH:" in *:'/home/prad/.local/bin':*) ;; *) export PATH='/home/prad/.local/bin':"$PATH" ;; esac