TechQuant Blog

atuinに乗り換えて半年。シェル履歴がSQLiteになって生活が変わった話

7分で読める

水曜の深夜、本番のVPSで「3週間前にやったあのワンライナー、なんだっけ」を5分間思い出せなかった。history | grepを打っても出てこない。~/.bash_historyがどうやら途中で潰れていたらしい。あの瞬間に、atuinを入れた。

あれから半年経った。Ctrl+Rの体験はもう戻れない。

この記事は、atuinを毎日3台のマシン(Mac / Raspberry Pi 5 / VPS)で使い込んだ自分が、本当に効いた使い方とハマったポイントだけを書く。公式READMEの和訳ではなく、現場で気付いたものを中心に。

atuin とは何か(普通のhistoryと何が違うのか)

atuinは Ellie Huxtable 氏が Rust で書いた、シェル履歴の置き換えツールだ。bash / zsh / fish / nushell に対応している。

普通のシェル履歴と決定的に違うのは、保存先がプレーンテキストではなくSQLiteな点。これが効く。

  • コマンドだけでなく、実行ディレクトリ・終了コード・所要時間・ホスト名も一緒に記録される
  • 重複は自動でマージ、古い履歴も上限なしで残せる
  • セッション単位の履歴ロストが起きない(zshで複数ターミナル開いてた時のあれ、もう発生しない)
  • サーバー連携でE2E暗号化済みの履歴を別マシンと同期できる

「ふーん、grep でええやん」と思った人。半年前の自分もそう思っていた。一週間使うと、たぶん戻れなくなる。

インストールと最低限のセットアップ

ワンライナーで入る。Mac でも Linux でも Raspberry Pi (arm64) でも同じ。

curl --proto '=https' --tlsv1.2 -LsSf https://setup.atuin.sh | sh

Homebrew 派ならbrew install atuinでも入る。cargo install atuinもある。Rust ツールチェーンがあるなら速い。

その後シェルへの組み込み。zshの場合は.zshrcに1行。

eval "$(atuin init zsh)"

bash の場合は~/.bashrcに同じ要領で書く。bash-preexec.shを読み込む形になるが、インストーラが面倒見てくれる。

ここまでで Ctrl+R が atuin の検索画面に変わる。早速触ってみると、見た目からして違う。実行時刻・ディレクトリ・終了コードがその場で見える。

既存のhistoryを取り込む

これを忘れがち。新規インストール直後はatuinの履歴ゼロなので、まず吸い上げる。

atuin import auto

これでbashなら.bash_history、zshなら.zsh_historyを読み込んでSQLiteに突っ込んでくれる。10年分の.zsh_history(自分の場合、約42,000行)も数秒で食べてくれた。タイムスタンプも保持される、これは正直うれしい。

Ctrl+Rで生活が変わる5つの操作

キーバインドは色々あるが、毎日使うのは結局この5つだけだった。

1. ファジー検索 + フィルタモード切替

Ctrl+R を押した検索画面で、Ctrl+Rをもう一度押すと検索モードが切り替わる。Global / Host / Session / Directory の4段階。

  • Global: 全マシン全期間の履歴(同期している場合)
  • Host: 今のマシンだけ
  • Session: 今開いているターミナルセッションだけ
  • Directory: 今いるディレクトリで実行した履歴だけ ← 個人的に最強

「このプロジェクトでよくやってる作業をもう一度」というケースで、Directory モードが圧倒的に効く。同じnpm runでも、案件ごとに異なるサブコマンドを使い分けている人は刺さるはず。

2. 終了コードでフィルタ

失敗したコマンドだけを除外できる。検索フィールドの先頭でTabを押してフィルタを開き、Exit code: 0 onlyに切り替えると、過去にちゃんと通ったコマンドだけが出てくる。

これが効く場面はいくつかあって、たとえば「ffmpegのオプションが正しかった時のフルコマンドを出したい」みたいな状況。タイポ含む失敗履歴に埋もれず、正解だけ呼び出せる。

3. 直前のコマンドを別マシンに飛ばす(Workspace固有)

これはちょっと裏技。同期サーバーを使っていると、Mac で打ったコマンドが数秒で Raspberry Pi 5 のCtrl+Rで出てくる。

自分の場合、Mac でローカルに作って動作確認したシェルスクリプトのワンライナーを、SSH先のRaspberry Piに「再入力なしで」貼れる。Raspberry Pi 5 のホームサーバー運用をしていると、こういう細かい摩擦の積み重ねが地味に効いてくる。

4. 統計を見る

「自分が一番打ってるコマンドって何だっけ」を可視化できる。

atuin stats

自分の場合、トップはgit status(月3,200回)、次がls、3位がcd、4位がvim、5位がpythonだった。git statusの数字を見たとき、さすがに何か対策を取るべきと思って、lazygitに乗り換えたのはこの直後だ。

5. 履歴の削除

うっかりexport AWS_SECRET=...を打ってしまった時。atuin searchで該当コマンドを見つけ、Ctrl+Dで削除できる。SQLiteから物理的に消える。これはhistory -dより使いやすい。

セルフホスト同期サーバー(プライバシーを担保しつつ複数マシン運用)

atuinの真価は、履歴をE2E暗号化して同期できるところにある。公式が無料の同期サーバーを提供しているが、自分は自前のVPSで立てている。理由は単純で、自分のシェル履歴は他人(運営含む)に渡したくないからだ。

セルフホストはDocker一発で立つ。

version: "3"
services:
  atuin:
    image: ghcr.io/atuinsh/atuin:latest
    command: server start
    volumes:
      - "./config:/config"
    ports:
      - 8888:8888
    environment:
      ATUIN_HOST: "0.0.0.0"
      ATUIN_OPEN_REGISTRATION: "false"
      ATUIN_DB_URI: postgres://user:pass@postgres/atuin
  postgres:
    image: postgres:14
    restart: unless-stopped
    volumes:
      - "./database:/var/lib/postgresql/data/"
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: atuin

あとはCaddyのリバースプロキシでHTTPS化して終わり。クライアント側は~/.config/atuin/config.tomlに同期先を書くだけ。

sync_address = "https://atuin.example.com"

登録はatuin register -u USER -e EMAIL、ログインはatuin login -u USER -p PASS -k KEYkeyは復元用の暗号化キーで、これをなくすと既存の暗号化履歴は二度と復号できない。これは絶対にパスワードマネージャに入れておくべき値だ。自分は1度ロストしかけて、汗をかいた。

ちなみにVPSはお名前.comの高性能VPSのいちばん安いプランで動かしている。atuinサーバー自体は数十MBのメモリしか食わないので、月数百円のプランで十分間に合う。

半年使って気付いた地味なハマりどころ

べた褒めばかりじゃ嘘になるので、ハマったポイントも正直に書く。

  • SSH先で履歴が分離される問題: 当然と言えば当然だが、SSHした先のマシンにもatuinが入っていないと、ローカルの履歴と統合されない。サーバー全部に入れるか、Hostフィルタを使い分けるかの二択。自分はTailscaleで繋いだホスト群には全部入れている。
  • 同期競合は基本起きないが、巨大履歴の初回同期は遅い: 4万行の初回pushが約2分かかった。Wi-Fiが弱い環境ではコーヒーを淹れる時間。
  • シェルの起動が体感数十ms遅くなる: 計測すると約30-50ms。チューニングしたい人はatuin init zsh --disable-up-arrow等のフラグで無駄な機能を切ると軽くなる。
  • 自動補完(atuin shellと別)との衝突: fzfCtrl+Rと被ると、どちらかしか使えない。自分はfzfのCtrl+Rを一旦無効にしてatuinに統一した。fzfは別キー(Alt+R)で残してある。

あ、もう一つ。atuin initを入れた状態で別のシェル設定を弄ると、稀にプロンプトが二重に描画される。これはpreexec hookの登録順問題で、初期化の位置を一番下にすると直る。

誰におすすめか、誰にいらないか

正直に言うと、シングルマシンで完結している人にはあまり刺さらない。HISTSIZE=999999HISTFILESIZE=999999で十分という人もいる。それは正しい判断だ。

逆に、以下のどれかに当てはまる人にはたぶん刺さる。

  • 複数マシン(ノートPC + デスクトップ + サーバー)で同じシェル作業をしている
  • 過去の履歴を「いつ・どこのディレクトリで・成功したか」で絞り込みたい
  • シェル履歴ファイルを過去に1度でもロストしたことがある
  • 普段からhistory | grepを多用していて、地味にストレスを感じている

自分は最後の3つ全部に当てはまった。たぶん、エンジニアの大半はそうだと思う。

導入リスクは低い、戻りも数秒で済む

atuinは Ctrl+R を奪うだけで、bash や zsh の設定そのものは壊さない。.bashrcからeval "$(atuin init bash)"を消せば、即座に元の Ctrl+R に戻る。SQLiteのファイルは~/.local/share/atuin/history.dbに残るので、後で気が向いたら再開できる。

合わなければやめればいい。インストールが2分、削除が30秒。これくらいの軽さなら、試さない理由がない。

普段のターミナル環境を底上げするツール群は、まとめてDevToolsコレクションでも紹介している。気になる人はあわせて見てほしい。

半年前、本番VPSの深夜デバッグであのワンライナーを思い出せなかった自分は、もう存在しない。Ctrl+R を打って、ディレクトリで絞り込んで、終了コード0でフィルタする、それだけのことなのに、毎日の摩擦が減る。

その差は、たぶん想像より大きい。