# Fix Rust CLI Errors from Sentry Alerts

Yes. An agent reads the Sentry event from your Rust CLI, reproduces the wrong command or shell behavior with a test, fixes the cause and opens a pull request.

[Run this on Rush](https://cloud.getrush.ai/run/fix-sentry-errors/rust-cli/), in a Project that has your repository.

## What the agent does

The agent reads the alert payload after the prompt, then opens the issue and its latest event through the Sentry connection. For a command-line tool the event carries a panic message with its frames, or an error the tool reported itself, plus whatever the CLI attached as tags: the subcommand and arguments, the shell, the operating system. It keeps the frame's file and line and the command line as the two facts the test must reproduce.

Then it reads the crate. In ajeetdsouza/zoxide, `Cargo.toml` names version 0.10.0, edition 2024 and `rust-version` 1.88.0, with `anyhow` for errors, `clap` 4.3 with `derive` for the commands in `src/cmd/cmd.rs`, `askama` 0.16 for the shell templates under `templates/`, `bincode` 1.3 for the database file, `glob` for exclude patterns and `ouroboros` for the self-referential database; dev-dependencies are `assert_cmd`, `rstest`, `rstest_reuse` and `tempfile`. `src/main.rs` is 35 lines: it removes `RUST_BACKTRACE`, runs `Cmd::parse().run()`, turns a `SilentExit` into its exit code and prints anything else as `zoxide: {e:?}` to stderr. Errors are `anyhow` contexts such as `_ZO_DATA_DIR must be an absolute path` in `src/config.rs`, `not a directory: {path}` in `src/cmd/add.rs` and `could not write to stdout` from the `BrokenPipeHandler` in `src/error.rs`, so an event message usually points straight at the line.

The agent picks the test shape from the module. A ranking or matching bug lives in `src/db/`: `src/db/dir.rs` scores an entry at rank times 4, 2, 0.5 or 0.25 depending on whether it was used within the hour, the day, the week or longer ago, and `src/db/stream.rs` filters by base directory, exclude globs, existence (with `symlink_metadata` when symlinks are resolved) and keywords, where the last keyword must match inside the last path component. Those modules already have tests: `mod tests` in `src/db/mod.rs` opens a database in a `tempfile::tempdir()` at epoch 946684800 and checks `add` and `remove`, and `src/db/stream.rs` has an `rstest` table of keyword cases such as `["foo", "/"]` against `/foo/bar`. The agent adds a case with the path and keywords from the event. A shell integration bug lives in `templates/posix.txt` and its siblings, where `__zoxide_z` falls through to `zoxide query --exclude "$(__zoxide_pwd)" -- "$@"`; `src/shell.rs` renders each template under an `rstest` template over the `cmd`, `hook`, `echo` and `resolve_symlinks` options and runs it through `bash`, `dash`, `shellcheck`, `shfmt`, `fish`, `nu`, `pwsh`, `zsh` and `xonsh`, so a new case there proves a fix in the template.

With the test failing for the same reason the event shows, the agent changes the one function or template and runs what `justfile` runs in CI: `cargo clippy --all-features --all-targets -- -Dwarnings`, `cargo fmt --all --check`, `cargo msrv verify` against 1.88.0, and the tests with `cargo nextest run --all-features --no-fail-fast --workspace`, or `cargo test` where nextest is unavailable. The shell tests need the shells installed, and the repository runs them inside `nix-shell`, so the agent installs the shells the failing case needs and says in the description which ones ran.

## Start it with one API call

`POST https://api.prix.dev/o/{org}/sessions`

```json
{
  "agent": "claude",
  "input": "A Sentry alert fired for this Rust CLI; its payload follows this prompt. Use the Sentry connection to read the issue, its latest event, the panic or error message, the frames with their file and line, and the tags that carry the command line and the shell. In a crate shaped like ajeetdsouza/zoxide, find the function the frames point at under src/cmd/, src/db/, src/config.rs or src/util.rs, or the shell template under templates/ when the shell integration misbehaved. Write a test in the style the module already has: an rstest case in src/db/stream.rs or src/shell.rs, a tempdir-based test in src/db/mod.rs, or an assert_cmd test against the built binary with _ZO_DATA_DIR pointed at a temporary directory. Confirm it fails with the same message as the event, then fix the cause in that one function or template without catching the panic or hiding the error. Run cargo clippy --all-features --all-targets -- -Dwarnings, cargo fmt --all --check, cargo msrv verify and cargo test --all-features --no-fail-fast, installing any shell a new shell test needs. Open a pull request that links the Sentry issue, quotes the message and frames and the failing test output, and explains the cause. If it does not reproduce, stop and report what you tried.\n\nAlert payload:\n{payload}",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ],
  "connections": [
    "sentry"
  ]
}
```

1. **Get an API key.** In the console, open Settings, then API keys, and create a key for your org. Send it in the Authorization header as a Bearer token.
2. **Send the request.** POST the body in request.json to https://api.prix.dev/o/{org}/sessions, with your repository as the resources URL. The run starts in its own cloud sandbox.
3. **Read what came back.** Follow the run on its live stream or wait for the run.completed webhook, then read the result and its trajectory.

## What comes back

What comes back is a pull request that changes one function under `src/` or one template under `templates/` and adds a test case beside the existing ones. Its description links the Sentry issue, quotes the message and the frames or the command line, shows the new case failing before the change and passing after, and gives the `cargo test`, clippy, fmt and `cargo msrv verify` results, naming which shells were installed for a shell test. `Cargo.toml` and `Cargo.lock` do not change.

Before merging, a reviewer checks that a scoring or matching change keeps the existing `rstest` cases green, since those encode what users expect from `z foo`, that a template change passes `shellcheck` and `shfmt` the way `src/shell.rs` demands, and that the fix changes the decision rather than wrapping it in a fallback. If the event came from a release older than `main` and the line already changed, the description says so and the test pins the current behavior.

## Run it on every Sentry issue alert

Create an alert rule in the Sentry project for the CLI with a webhook action pointed at a handler on your server; Sentry signs its own requests and cannot add the `Authorization: Bearer` header a Rush `webhook` trigger needs. The handler places the alert JSON after the prompt and sends this request with the Sentry issue id as `Idempotency-Key`, so the same issue redelivered returns the run already started.

Set a webhook URL on the API key and Rush POSTs `run.completed` with `session_url` when the turn ends; the handler can comment the pull request link on the issue. A CLI reports the same crash from many machines, and Sentry folds those into one issue, so one issue is one run; the handler can also skip issues that already have an open pull request.

## Why run it on Rush?

A CLI bug depends on a shell, a data directory, a symlink or a pipe, and a laptop has one shell configured one way. On Rush the agent sets those conditions in a test in its own sandbox, installs `fish` or `nu` or `pwsh` when the case needs it, points `_ZO_DATA_DIR` at a temporary directory so no real database is touched, and runs the one test that matters before the whole suite.

The pull request carries its own proof: the Sentry event the agent read, the case failing with the event's message and passing after the change, and the exact clippy, fmt and MSRV output in the transcript. Several alerts are several sandboxes at once, and a reviewer judges a diff instead of reconstructing someone else's terminal.

## Frequently asked questions

### A terminal tool reporting to Sentry? What is in the event?

Whatever your CLI's Sentry setup sends: the panic message and frames from the panic integration, and the tags you attach, such as the subcommand, the arguments and the shell. The agent uses the frames to find the function and the tags to build the input; a CLI that only sends the message still gives it the line through `anyhow`'s context text.

### Will the tests touch my real zoxide database?

No. The existing tests open the database in a `tempfile::tempdir()`, and a binary-level test sets `_ZO_DATA_DIR` to a temporary directory, which `src/config.rs` requires to be absolute. The sandbox has no user data in any case.

### Does it need every shell installed?

Only the shells the failing case runs through. `src/shell.rs` tests each template with its own interpreter plus `shellcheck` and `shfmt`, and the repository runs them in `nix-shell`; the agent installs what the new case needs and lists in the description which shell tests ran.

### What about cargo msrv verify and udeps?

`cargo msrv verify` checks the crate still builds on `rust-version` 1.88.0 and the agent runs it; `cargo udeps` needs a nightly toolchain and is run when the fix touched `Cargo.toml`, which a Sentry fix normally does not. The description names which lint steps ran.

### What if the fix is in the fzf interaction?

`src/util.rs` wraps `fzf` in the `Fzf` and `FzfChild` types, and `query_interactive` in `src/cmd/query.rs` reads the selection from it. The agent installs `fzf` in the sandbox, writes a test that feeds it a known list, and if the behavior depends on a specific `fzf` version it says so and pins the version in the test.
