#! /bin/sh set -eu ATUIN_NON_INTERACTIVE="no" # Everything but --non-interactive is for `atuin setup`, e.g. `sh -s -- --no-up-arrow --sync off`. for arg in "$@"; do shift case "$arg" in --non-interactive) ATUIN_NON_INTERACTIVE="yes" ;; *) set -- "$@" "$arg" ;; esac done if [ "$ATUIN_NON_INTERACTIVE" != "yes" ]; then ATUIN_NON_INTERACTIVE=yes # In a subshell: without a terminal, `exec`'s failed redirection would end the script. if (exec 3/dev/null; then ATUIN_NON_INTERACTIVE=no fi fi if [ -t 1 ]; then GREEN=$(printf '\033[32m') RESET=$(printf '\033[0m') BACK='\r' else GREEN="" RESET="" BACK='\n' fi if ! command -v curl > /dev/null; then echo "Atuin needs curl to install. Please install it, then try again." exit 1 fi __atuin_install_binary(){ install_script=$(curl --proto '=https' --tlsv1.2 -LsSf https://github.com/atuinsh/atuin/releases/latest/download/atuin-installer.sh) || return echo "$install_script" | sh } ATUIN_BIN="$HOME/.atuin/bin/atuin" ATUIN_INSTALL_LOG=$(mktemp) trap 'rm -f "$ATUIN_INSTALL_LOG"' EXIT printf '\n Installing Atuin...' # What the installer says only matters if it fails. if ! __atuin_install_binary > "$ATUIN_INSTALL_LOG" 2>&1; then printf '\n\n' cat "$ATUIN_INSTALL_LOG" printf '\nAtuin did not install. Please file an issue, or ask on the forum: https://forum.atuin.sh\n' exit 1 fi printf '%b %s✓%s Installed Atuin %s\n' "$BACK" "$GREEN" "$RESET" "$("$ATUIN_BIN" --version | cut -d' ' -f2)" # An `atuin setup` that takes flags does everything below itself: hooks, import and sync. This # script is served from main, but installs the latest release, which may not have it yet. if "$ATUIN_BIN" setup --help 2>/dev/null | grep -q -- "--no-up-arrow"; then if [ "$ATUIN_NON_INTERACTIVE" != "yes" ]; then if ! "$ATUIN_BIN" setup "$@" > "${ZDOTDIR:-$HOME}/.zshrc" fi # Use of single quotes around $() is intentional here # shellcheck disable=SC2016 if ! grep -q "atuin init bash" "$HOME/.bashrc"; then echo 'eval "$(atuin init bash)"' >> "$HOME/.bashrc" fi if [ -f "$HOME/.config/fish/config.fish" ]; then if ! grep -q "atuin init fish" "$HOME/.config/fish/config.fish"; then printf '\nif status is-interactive\n atuin init fish | source\nend\n' >> "$HOME/.config/fish/config.fish" fi fi __atuin_install_agent_hook(){ agent="$1" agent_name="$2" agent_config_dir="$3" shift 3 detected="no" if [ -d "$agent_config_dir" ]; then detected="yes" else for agent_command in "$@"; do if command -v "$agent_command" > /dev/null 2>&1; then detected="yes" break fi done fi if [ "$detected" = "yes" ]; then echo "Detected $agent_name — installing Atuin hooks..." if ! "$ATUIN_BIN" hook install "$agent"; then echo "Failed to install Atuin hooks for $agent_name (this version of Atuin may not support it yet)." fi echo "" fi } __atuin_install_agent_hook "claude-code" "Claude Code" "$HOME/.claude" claude __atuin_install_agent_hook "codex" "Codex" "$HOME/.codex" codex __atuin_install_agent_hook "opencode" "opencode" "${XDG_CONFIG_HOME:-$HOME/.config}/opencode" opencode __atuin_install_agent_hook "pi" "pi" "$HOME/.config/pi" pi echo "" echo "Atuin installed successfully!" echo "" if [ "$ATUIN_NON_INTERACTIVE" != "yes" ]; then printf "Would you like to import your existing shell history into Atuin? [Y/n] " read -r import_answer