Sync and search shell history across machines with atuin
Install atuin, import your existing shell history, search it with Ctrl-R and sync it end-to-end encrypted between machines.
Updated
in short
Install atuin, add atuin init to your shell rc file, run atuin import auto, then atuin register on one machine and atuin login on the others. History is encrypted on your machine before it is uploaded.
atuin stores shell history in a local SQLite database and records the exit code, working directory, hostname, session and duration of each command. It binds Ctrl-R and the up arrow to a full-screen search, and can sync history between machines through a server that only ever sees encrypted data.
This guide covers a local setup first, then sync, key bindings and self-hosting. Sync is optional; everything up to step 5 works offline.
Tools used
Before you start
- zsh, bash, fish, nushell, xonsh or PowerShell
- For bash: ble.sh 0.4+ is recommended; bash-preexec also works with some limits
- An email address and username if you want to use sync
Steps
Step 1: Install atuin
The official install script puts the binary in
~/.atuin/bin, sets up the shell plugin and walks you through import and sync interactively. Package managers install only the binary, so you also need step 2.shcurl --proto '=https' --tlsv1.2 -LsSf https://setup.atuin.sh | shsh# or, with a package manager brew install atuin pacman -S atuin cargo install atuin --lockedStep 2: Load the shell plugin
Add the line for your shell to its rc file, then open a new terminal.
atuin initinstalls the hooks that record each command and the key bindings.In bash, atuin 18.18.0 and newer loads a bundled copy of bash-preexec automatically if neither ble.sh nor bash-preexec is already loaded. ble.sh gives more accurate durations and exit codes.
zsh# ~/.zshrc eval "$(atuin init zsh)"bash# ~/.bashrc eval "$(atuin init bash)"fish# ~/.config/fish/config.fish, inside the is-interactive block atuin init fish | sourceStep 3: Import your existing history
atuin only records new commands through the plugin.
atuin import autoreads your current shell's history file, detected from$SHELL. Name the shell explicitly if detection picks the wrong one, and setHISTFILEto read a non-default file.Imported entries lack exit codes and durations because the old file never stored them. Your old history file is not replaced and keeps being written by the shell.
shatuin import autoshatuin import zsh HISTFILE=~/backup/.zsh_history atuin import zshStep 4: Search with
Ctrl-Rand the up arrowPress
Ctrl-Rand type part of a command. Inside the search UI,Ctrl-Rcycles the filter mode, such as global, host, session or directory,Enterruns the selected command,Tabputs it on the prompt for editing, andAlt-1toAlt-9pick an entry by its number.atuin searchruns the same queries non-interactively, with filters such as exit code and time.sh# successful make commands run after 3pm yesterday atuin search --exit 0 --after "yesterday 3pm" makeStep 5: Change or disable the up-arrow binding
By default the up arrow also opens atuin. To keep
Ctrl-Rbut give the up arrow back to your shell, pass--disable-up-arrowtoatuin init.--disable-ctrl-rdoes the reverse, and settingATUIN_NOBINDbeforeatuin initbinds nothing so you can bind keys yourself.If you want to keep the up arrow but scope it, set
filter_mode_shell_up_key_bindingin~/.config/atuin/config.toml; for exampledirectoryshows only commands run in the current directory.zsh# ~/.zshrc: Ctrl-R only eval "$(atuin init zsh --disable-up-arrow)"zsh# ~/.zshrc: bind keys yourself export ATUIN_NOBIND="true" eval "$(atuin init zsh)" bindkey '^r' atuin-searchtoml# ~/.config/atuin/config.toml filter_mode_shell_up_key_binding = "directory"Step 6: Register and run the first sync
On your first machine, register an account. Leave out
-pand atuin prompts for the password, which keeps it out of your history. Registration generates an encryption key and stores it locally; print it withatuin keyand save it in a password manager. Nobody can recover it for you.After that, sync runs automatically in the background. Run
atuin syncto trigger it by hand.shatuin register -u <USERNAME> -e <EMAIL> atuin key atuin syncStep 7: Log in on your other machines
Install atuin and the shell plugin on the next machine, optionally import its local history, then log in. atuin asks for your password and the key from
atuin key. If entries seem to be missing after the first sync,atuin sync -fforces a full sync.shatuin import auto atuin login -u <USERNAME> atuin syncStep 8: Optional: use a self-hosted server
The server is a separate binary,
atuin-server, backed by PostgreSQL, MySQL or SQLite. It reads~/.config/atuin/server.toml;db_uriis required andopen_registrationdefaults to false, so set it to true while you create accounts. The project recommends tracking tagged releases rather thanmainorlatest.On each client, set
sync_addressto your server before you runatuin registeroratuin login. TheATUIN_SYNC_ADDRESSenvironment variable works too.toml# server: ~/.config/atuin/server.toml host = "0.0.0.0" port = 8888 open_registration = true db_uri = "postgres://user:password@hostname/database"shatuin-server starttoml# client: ~/.config/atuin/config.toml sync_address = "https://atuin.example.com"
Privacy and encryption
- History is encrypted on the client before upload; the server, hosted or self-hosted, stores only ciphertext.
- The key lives in the atuin data directory (
~/.local/share/atuin/keyon Linux and macOS). Losing it means losing access to synced data. secrets_filteris on by default and skips commands that match AWS, GitHub, GitLab, Slack, Stripe and similar token patterns.history_filterandcwd_filterinconfig.tomltake regexes to exclude commands or directories; a leading space also skips a command.- Without sync, the only network call is a version check to
api.atuin.sh, at most once an hour. Setupdate_check = falseto stop it. atuin account deleteremoves your account and synced history from the server. Local data is kept.
Troubleshooting
Ctrl-Rstill shows the old search: the rc file was not reloaded. Open a new terminal or runexec $SHELL.- Another tool such as fzf also binds
Ctrl-R: the binding set last in your rc file wins. Put theatuin initline after it. - Commands from an IDE terminal are not recorded: the IDE starts a non-interactive shell. Configure it to run an interactive one, such as
/bin/bash -i. - Durations or exit codes look wrong in bash: that is a bash-preexec limit. Load ble.sh 0.4+ before
atuin init bash. - Another machine is missing history after login: run
atuin sync -ffor a full sync. - Typing
?opens Atuin AI: recent releases bind it by default. Add--disable-aito theatuin initline.
Also worth a look
- fzfFuzzy Ctrl-R over your shell's existing history file; no database and no sync.
FAQ
- Do I have to use sync?
- No. Without `atuin register` or `atuin login`, history stays in the local SQLite database and nothing is uploaded.
- Does atuin replace my shell's history file?
- No. The shell keeps writing its own history file; atuin records to its own database alongside it.
- I forgot my sync password. Can I reset it?
- There is no password reset. The project's FAQ says that as long as you are still logged in on at least one machine, it is safe to delete the account with `atuin account delete` and register again.