# pty-proxy

Atuin pty-proxy is an experimental lightweight PTY proxy, providing new features without needing to replace your existing terminal or shell. It currently supports bash, zsh, fish, and nu. See
[Supported platforms](../support.md) for support tiers.

!!! Note "Previously `atuin hex`"

    `atuin pty-proxy` is a replacement for the old `atuin hex` command. `atuin hex` still works for backward compatibility reasons, but will eventually be removed.

## TUI Rendering

The search TUI exposes a tradeoff: the UI is either in fullscreen alt-screen mode that takes over your terminal, or inline mode that clears your previous output. Neither is great.

With pty-proxy, the Atuin popup renders over the top of your previous output, but when it's closed, pty-proxy restores the output successfully.

!!! tip "Already using tmux?"

    tmux can solve the same problem without pty-proxy: set
    [`[tmux] enabled = true`](../configuration/config.md#tmux) and the search UI
    opens in a popup above your pane, leaving the pane untouched.

## Capturing command output

Because pty-proxy sits between your terminal and your shell, it can also record
what each command printed. It reads the [OSC 133](https://gitlab.freedesktop.org/Per_Bothner/specifications/blob/master/proposals/prompts-data-model.md)
prompt markers that your shell emits, using them to tell where one command's
output ends and the next begins. It then hands each captured block to the
[daemon](daemon.md), which holds it in memory, keyed by the command's Atuin
history ID.

That capture is what lets AI tools see what actually happened, rather than
guessing from the command alone:

- [Atuin AI](../ai/introduction.md) can answer "why did that fail?" by reading
  the real error, via its `AtuinOutput` tool
- External agents such as Claude Code and Cursor can do the same through Atuin's
  [MCP server](../ai/mcp.md)

Output capture needs **both** pty-proxy and the daemon running. Nothing is
captured by default. See [Reading Command Output](../ai/command-output.md) for
setup, retention limits, and privacy.

## Initialization

The simplest way to enable pty-proxy is via your Atuin config (`~/.config/atuin/config.toml`) — no extra shell config needed:

```toml
[pty_proxy]
enabled = true
```

With this set, your existing `atuin init` line starts the proxy automatically.

!!! tip "Startup performance"

    When enabled this way, the proxy starts wherever your `atuin init` line
    sits, and everything sourced *before* that line runs a second time inside
    the proxy. This is harmless, but for the fastest startup keep your
    `atuin init` line as high in your shell config as possible.

Alternatively, you can initialize pty-proxy explicitly in your shell config. Place the init line shown below as high in the document as possible, _before_ your normal `atuin init` call. Both methods can coexist safely — the proxy only starts once.

=== "zsh"

    ```shell
    eval "$(atuin pty-proxy init zsh)"
    ```

=== "bash"

    ```shell
    eval "$(atuin pty-proxy init bash)"
    ```

=== "fish"

    Add

    ```shell
    atuin pty-proxy init fish | source
    ```

    to your `is-interactive` block in your `~/.config/fish/config.fish` file

=== "Nushell"

    Run in *Nushell*:

    ```shell
    mkdir ~/.local/share/atuin/
    atuin pty-proxy init nu | save -f ~/.local/share/atuin/pty-proxy-init.nu
    ```

    Add to `config.nu`, **before** the regular `atuin init`:

    ```shell
    source ~/.local/share/atuin/pty-proxy-init.nu
    ```
    Nushell's `source` command requires a static file path, so you must
    pre-generate the file.

---

If the `atuin` binary isn't in your `PATH` by default, you should initialize pty-proxy as soon as it's set. For example, for a bash user with Atuin installed in `~/.atuin/bin/atuin`, a config file might look like this:

```bash
export PATH=$HOME/.atuin/bin:$PATH
eval "$(atuin pty-proxy init bash)"

# ... other shell configuration ...

eval "$(atuin init bash)"
```
