↑ ↓ to move · Enter to open · Esc to close Something not working? Troubleshooting
    On this page

    Shell Integration

    Shell integration connects Suvadu to your terminal so that every command you run is automatically recorded with full metadata: working directory, duration, exit code, executor, and, inside a git repository, the branch it started on.

    Zsh Setup

    Add the Suvadu hook to your ~/.zshrc and reload:

    echo 'eval "$(suv init zsh)"' >> ~/.zshrc && source ~/.zshrc

    This appends a single line to your Zsh configuration. The suv init zsh command outputs the shell functions that Suvadu needs; eval loads them into your current session.

    The hook runs under Zsh's default options whatever your own are, so since 0.5.1 OCTAL_ZEROES, SH_WORD_SPLIT, NO_UNSET, or a suv path containing a space no longer break recording, and managed aliases load when the data directory's path contains quotes, $ or backticks.

    Bash Setup

    Add the Suvadu hook to your ~/.bashrc and reload:

    echo 'eval "$(suv init bash)"' >> ~/.bashrc && source ~/.bashrc

    For login shells that only source ~/.bash_profile, add the same line to ~/.bash_profile instead, or make sure your ~/.bash_profile sources ~/.bashrc.

    Since 0.5.1 the Bash hook records the whole line you typed: cd /tmp && ls is stored as typed, and a pipeline as the whole pipeline with its whole duration. Earlier releases stored only the last simple command (ls). An empty Enter no longer re-records a prompt command, lines typed with a leading space are skipped under HISTCONTROL=ignorespace or ignoreboth, and loading the hook keeps an existing multi-line DEBUG trap working.

    What the Hooks Do

    The shell hooks set up two functions that run transparently around every command you execute:

    • Pre-exec hook: Fires just before a command starts. It captures the command text, working directory, timestamp, and which executor is running the command (you, or an AI agent like Claude Code or Cursor).
    • Post-exec hook: Fires after the command finishes. It records the exit code and how long the command took (duration in milliseconds), by running suv add before the next prompt.

    They do not modify your command, its output, or its exit code, and they never see the output: capturing it would mean standing between the program and the terminal. What a prompt pays is one suv add process. On an Apple M4 Max (BENCHMARKS.md), a whole suv add took 13.4 ms p50 and 14.3 ms p95 from inside a repository, nearly all of it starting the process and opening the database; writing the command itself took 207 µs p95 on the 100,000-entry benchmark corpus. Treat these as one machine's order of magnitude, not a guarantee.

    Git Branch Capture

    Since 0.5.1, every command recorded live inside a git repository — by the Zsh or Bash hook, or by an agent integration — keeps the branch checked out in the directory it started in, or the 7-character commit hash of a detached HEAD. Linked worktrees and submodules are followed. Recall's detail pane shows it as a Branch row, and detailed MCP command rows add branch <name>.

    • No git runs at your prompt. The branch is read from the repository's own files: 11–21 µs per lookup on an Apple M4 Max (BENCHMARKS.md), inside the run-to-run noise of a whole suv add.
    • A command that changes directory, like cd ../other, is filed under the branch it was typed on; one that switches branches, under the branch it switched to.
    • The branch is redacted like command text and never stored for an excluded command.

    Turn it off with Record Git Branch in suv settings, or in config.toml; a project's .suvadu.toml can turn it off but not back on:

    [shell]
    capture_git_branch = false

    Up-arrow recall

    In Zsh, Up and Down recall from Suvadu as soon as the hook is loaded; there is nothing else to set up. Up brings back the newest command that starts with what you have typed, then older ones, newest first — the current directory only breaks ties between commands recorded at the same millisecond — and Down walks back towards what you typed. Only commands you typed are recalled: Alt+A shows AI-agent commands too, for that shell.

    • Turn it off with Enable Arrow Key Navigation on the Shell tab of suv settings, or in config.toml. It takes effect in new shells (or after exec zsh), which keep Zsh's own Up/Down and leave Alt+A alone:
      [shell]
      enable_arrow_navigation = false
    • Bash is not covered yet. The Bash hook binds only Ctrl+R; Up and Down keep Bash's own history.
    • Check it in the shell you are using:
      bindkey '^[[A'      # expect  "^[[A" suvadu-up-arrow
      bindkey '^[OA'      # expect  "^[OA" suvadu-up-arrow (the sequence many terminals send)
    • If something else answers Up, a plugin loaded after eval "$(suv init zsh)" rebound it: oh-my-zsh's key bindings, zsh-history-substring-search, zsh-vi-mode, fzf's key bindings, atuin and mcfly all bind Up. Put the eval "$(suv init zsh)" line last in ~/.zshrc, after your plugin manager and plugins, then run exec zsh. A plain setting such as ZSH_AUTOSUGGEST_STRATEGY can still follow it. zsh-vi-mode binds its keys at the first prompt instead, so also set ZVM_INIT_MODE=sourcing before it loads.
    • suv doctor reports it (since 0.5.1). Once per Zsh, at its first prompt — when all of ~/.zshrc has run — the hook checks whether Up is still Suvadu's and notes what took it over; doctor's Up-arrow line names that widget and the fix, and the note is removed when a later Zsh finds Up is Suvadu's again. The check prints nothing, costs about 0.8 ms per shell start on an Apple M4 Max (BENCHMARKS.md), and is skipped when arrow navigation is off.

    Still not working? See Up-arrow shows Zsh's own history.

    zsh-autosuggestions

    Since 0.5.1 the Zsh hook ships a strategy for zsh-autosuggestions that suggests what Up would recall: the newest command starting with what you typed, with AI-agent commands hidden unless Alt+A revealed them. Add this line to ~/.zshrc, after the eval line; history after it falls back to Zsh's own history when Suvadu has nothing:

    ZSH_AUTOSUGGEST_STRATEGY=(suvadu history)

    The hook does not change your strategy setting on its own; suv init --help and the hook's header show the line. Each suggestion is one suv get --prefix lookup, the same one Up makes: 5–8 ms p95 on a 100,000-command history on an Apple M4 Max, about 1–4 ms of it beyond starting the process (BENCHMARKS.md). zsh-autosuggestions 0.7 fetches suggestions asynchronously by default, so this delays the suggestion, not your typing.

    Verify Shell Integration

    After setting up the hooks, run:

    suv status

    You should see output similar to:

    Suvadu Status:
      Recording: enabled in config
      Capture:   most recent record received 4s ago, from this shell session

    Key things to check:

    • Recording — what the configuration says. It is configuration, not evidence that anything was stored.
    • Capture — the evidence: whether a command from this shell session has actually reached the database. Until one has, it says not yet verified and lists the steps to check end to end.

    Try running a few commands, then verify they were recorded:

    suv search

    Your recent commands should appear in the search TUI.

    Terminal Multiplexers

    Suvadu works with tmux, screen, Zellij, and any other terminal multiplexer. Each pane or window gets its own unique session ID, so commands are tracked separately per pane. No extra configuration is needed.

    Pausing and Disabling Recording

    Sometimes you want to stop recording temporarily — for example, when entering sensitive commands.

    Pause (Current Session Only)

    Pause recording for just the current shell session. Other terminal windows and panes continue recording normally:

    suv pause

    Recording resumes automatically when you open a new terminal session, or you can re-source your shell config:

    source ~/.zshrc    # Zsh
    source ~/.bashrc   # Bash

    Disable / Enable (Global)

    Globally disable recording across all sessions:

    suv disable

    To re-enable recording globally:

    suv enable

    When disabled, suv status will show "Recording: disabled". No commands are captured in any terminal until you run suv enable.

    Difference between pause and disable: suv pause only affects the current shell session and is not persistent — a new terminal will record normally. suv disable is a global, persistent setting that stops all recording until you explicitly run suv enable.

    Fish Shell

    Fish shell is not yet supported: suv init generates hooks for Zsh and Bash only. It is on the Suvadu roadmap. If you use Fish, you can track progress on GitHub Issues.

    Troubleshooting

    • "command not found: suv" — The suv binary is not in your PATH. Check your installation and make sure the directory holding suv — /usr/local/bin, ~/.local/bin (install.sh --user), or ~/.cargo/bin — is in your PATH.
    • "no such file or directory" pointing at an old path (e.g. suv:8: no such file or directory: /opt/homebrew/bin/suv) — The shell hook records the absolute path of the suv binary when your session starts. If you later move the binary — switching package managers (for example Homebrew → Cargo), running brew unlink suvadu, or uninstalling and reinstalling elsewhere — already-open shells keep pointing at the old, now-deleted path and print this error on every prompt. Reload the shell to pick up the new location: exec zsh (or exec bash), or just open a new terminal.
    • Recording shows "disabled" after setup — You may have previously run suv disable. Run suv enable to re-enable recording globally.
    • Commands not appearing in search — Make sure you sourced your shell config after adding the eval line. Open a new terminal tab and try again. Run suv status to confirm hooks are active.
    • Duplicate eval lines — If you ran the setup command more than once, you may have multiple eval "$(suv init zsh)" lines in your config. This is harmless but you can remove duplicates. Only one line is needed.