# Add JSON Output to a Rust CLI from a Linear Issue

Yes. An agent picks up the Linear issue, adds a --json flag to zoxide query that prints path and score, documents it and opens a pull request.

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

## What the agent does

The run starts from the repository URL in `resources`: the agent clones it into its own cloud sandbox and reads the crate the way a new contributor would. In a CLI like `ajeetdsouza/zoxide`, `Cargo.toml` names version 0.10.0, edition 2024, rust-version 1.88.0, and depends on clap 4.3 with the derive feature. Query flags live in `src/cmd/cmd.rs` on the `Query` struct: `--all`, `--interactive`, `--list`, `--score`, `--exclude` and `--base-dir`. There is no `--json` flag today.

Output formatting is plain text. `src/cmd/query.rs` walks a `Stream` of directories and writes paths with `writeln!`; when `--score` is set it uses `dir.display().with_score(now)` from `src/db/dir.rs`, which prints a right-aligned score then the path. The man page `man/man1/zoxide-query.1` documents those flags and does not mention JSON. Shell integrations under `templates/` call `zoxide query` and expect a path on stdout, so the new flag must be opt-in.

The agent adds a `--json` flag on `Query`, serialized through clap, and when it is set prints a JSON array of objects with `path` and `score` for each result (list mode) or a one-element array for the default single match. It reuses the same `score(now)` calculation `Dir` already exposes. Interactive fzf mode refuses `--json` or ignores it with a clear error so a machine-readable stream is never mixed with fzf chrome. `man/man1/zoxide-query.1` gains a `--json` entry.

Proving it means tests beside `tests/completions.rs`. The agent adds a test that seeds a temporary database, runs `zoxide query --json` through `assert_cmd`, and asserts the stdout parses as a JSON array with path and score fields. Then it runs `cargo test` and `cargo clippy`.

## Start it with one API call

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

```json
{
  "agent": "claude",
  "input": "A Linear issue labeled agent says: \"Add JSON Output to a Rust CLI. Add a --json flag to zoxide query so it prints each result with its path and score as a JSON array, documented in the man page.\" Do the work in this repository, add tests for it, run cargo test and cargo clippy, and open a pull request that links back to the issue.",
  "resources": [
    {
      "url": "https://github.com/your-org/your-app"
    }
  ]
}
```

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. Its diff updates `src/cmd/cmd.rs` and `src/cmd/query.rs`, documents `--json` in `man/man1/zoxide-query.1`, and adds a command test. The description quotes the issue and links back to it.

The checks on the pull request run `cargo test` and `cargo clippy`. A reviewer reads the JSON shape for `path` and `score`, confirms default non-JSON output is unchanged for shell init scripts, and confirms the man page lists the flag. No change to `zoxide add` or `zoxide init` is required.

The session read keeps the record behind the pull request: cargo test, clippy and the assert_cmd output. Anyone who questions a score field can see the fixture directory ranks the agent used.

## Run it on every Linear issue labelled agent

The Project's automation turns the label into the run. In the console, add an automation with a Linear trigger on `linear.issue.labeled` filtered to the `agent` label and this prompt; each labelled CLI issue starts its own run in its own sandbox and opens its own pull request.

If the automation is not wanted, a small server can do the same: receive Linear's issue webhook, put the issue text into `input`, and POST to `/o/{org}/sessions` with the zoxide repository in `resources`. A `run.completed` webhook on the API key posts the pull request when cargo test and clippy finish.

## Why run it on Rush?

On a laptop this job needs a Rust toolchain at or above rust-version 1.88.0, and a full `cargo test` cycle that compiles clap derive macros and the askama templates in `build.rs`. Each run on Rush boots its own sandbox with that already in reach, runs test and clippy itself, and keeps every command and its output.

CLI flag requests are easy to defer when local builds are slow. Labelling the issue starts a sandbox that owns the compile, so `--json` work does not block someone mid-edit on shell init templates.

## Frequently asked questions

### Does --json replace --score?

No. `--score` keeps its plain-text layout. `--json` always includes the numeric score inside each object so scripts do not need both flags.

### Will shell cd wrappers break?

Not unless they pass `--json`. Default `zoxide query` output stays a bare path on one line, which is what the init templates expect.

### Is serde already a dependency?

Yes. `Cargo.toml` already depends on serde with derive for the database. The agent reuses it for the query JSON payload instead of printing by hand.

### What about interactive mode?

Interactive mode uses fzf and a custom selection format. The agent keeps `--json` out of that path so a TUI session never emits a partial JSON array.
