Install

# One-liner installer
bash <(curl https://raw.githubusercontent.com/atuinsh/atuin/main/install.sh)

# Or via package manager
sudo apt install atuin
brew install atuin
sudo pacman -S atuin

# Or via mise (see /tutorials/mise-polyglot-runtime-versions.html)
mise use -g atuin@latest

atuin --version

Hook into your shell

# bash — install bash-preexec first (atuin needs it)
curl https://raw.githubusercontent.com/rcaloras/bash-preexec/master/bash-preexec.sh \
    -o ~/.bash-preexec.sh
echo '[[ -f ~/.bash-preexec.sh ]] && source ~/.bash-preexec.sh' >> ~/.bashrc
echo 'eval "$(atuin init bash)"' >> ~/.bashrc

# zsh
echo 'eval "$(atuin init zsh)"' >> ~/.zshrc

# fish (see /tutorials/starship-fish-shell-setup.html)
echo 'atuin init fish | source' >> ~/.config/fish/config.fish

# nushell
mkdir -p ~/.config/atuin
atuin init nu > ~/.config/atuin/init.nu
echo 'source ~/.config/atuin/init.nu' >> ~/.config/nushell/config.nu

Reopen the shell. Type echo hello, then hit Ctrl-R: the Atuin TUI appears.

The Ctrl-R interface

By default, Atuin overrides Ctrl-R. You see a list of recent commands; type to fuzzy-filter; arrow-keys to navigate; Enter to select. Per-entry metadata visible: directory + host + exit-code + duration.

Useful keybindings inside the search:

  • Ctrl-R — cycle between filter scopes: global, host, session, directory.
  • Ctrl-S — cycle between sort modes (recent, frequent).
  • Tab — complete to current input.
  • Esc / Ctrl-C — cancel.

By default Atuin shows only the current host's history; Ctrl-R again to expand to "global" (every host you've synced).

Search from anywhere

# Search history from any prompt without entering interactive mode
atuin search "git push"

# Limit by directory
atuin search --cwd ~/projects/myapp "cargo"

# By exit code (find recent failures)
atuin search --exit 1 --before 1h "deploy"

# By host
atuin search --host laptop-01 "ssh"

Sync via Atuin's hosted service

# Register
atuin register --username amir --email amir@example.com

# Sync
atuin sync

# Subsequent shells auto-sync in the background

The default sync target is api.atuin.sh (Atuin's hosted free service). End-to-end encrypted — the server stores ciphertext only; the key is on each of your devices. To set up on a new machine: atuin login, paste the key (printed during registration; store it in a password manager).

Self-host the sync server

For full control, run the Atuin server on your own infrastructure:

# docker-compose.yml
services:
  atuin:
    image: ghcr.io/atuinsh/atuin:latest
    container_name: atuin
    restart: unless-stopped
    ports:
      - "127.0.0.1:8888:8888"
    environment:
      ATUIN_HOST: "0.0.0.0"
      ATUIN_PORT: 8888
      ATUIN_OPEN_REGISTRATION: "true"
      ATUIN_DB_URI: postgres://atuin:${DB_PW}@postgres/atuin
    command: atuin server start
    depends_on: [ postgres ]

  postgres:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: atuin
      POSTGRES_PASSWORD: ${DB_PW}
      POSTGRES_DB: atuin
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:

Reverse-proxy to atuin.example.com over HTTPS. On each device:

# Set the sync URL
atuin set sync.address https://atuin.example.com
atuin register ...   # or login on a known account

Disable open registration after creating your accounts: ATUIN_OPEN_REGISTRATION: "false".

Filtering noise

By default Atuin records every command, which includes mistyped passwords, secrets piped via stdin, etc. Filter at record time:

# ~/.config/atuin/config.toml
[stats]
ignored_commands = ["password", "echo $TOKEN"]

# Ignore commands matching a regex
history_filter = [
    "^secret_command",
    "ssh.*--password",
]

# Ignore commands by working directory
cwd_filter = [
    "~/.secrets",
]

Stats

atuin stats           # daily / weekly summaries
atuin stats day       # commands run today
atuin stats week
atuin stats all       # entire history

# Top commands across all-time
atuin search --cmd-only --count 20 ""

Import existing history

# First-time setup: import from your existing shell history
atuin import auto

# Or specifically
atuin import bash
atuin import zsh
atuin import fish

Your existing thousands of commands become searchable; subsequent commands accumulate alongside them.

Why this beats the default Ctrl-R

  • Real fuzzy search across all of history, not just substring match against the last N lines.
  • Per-directory context: "what did I run last time I was in this repo?"
  • Per-host context: "where did I run this?" The shell that has it isn't always the one you're sitting at.
  • Exit-code awareness: filter to failures only, or successes only.
  • Multi-machine: yesterday's commands from the office laptop are available from the home one.
  • The encrypted sync isolates the privacy issue with cloud history features — it's E2E; the server can't read it.

What it doesn't do

  • It's not a shell — it integrates with your existing shell (bash, zsh, fish, nushell).
  • It doesn't replace your prompt — pair with starship (see that tutorial).
  • It can't undo commands — just search history; the actual filesystem mutations are not reversible by Atuin.