All jobs

Turn Labeled GitHub Issues Into Pull Requests for a Rust CLI

Yes. Label an issue on your Rust CLI and an agent writes the test, makes the change with its man page and completions, runs cargo test and opens a PR.

Run this on RushIn a Project that has your repository.

What the agent does

The run starts with the issue's title and body after the prompt and the repository cloned into its own sandbox. In a CLI shaped like ajeetdsouza/zoxide, the agent reads Cargo.toml first: version 0.10.0, edition 2024, rust-version = "1.88.0", clap 4.3 with derive, askama 0.16, anyhow, glob, bincode for the database file, and assert_cmd, rstest, rstest_reuse and tempfile for tests. Then it reads how a user-visible change is expected to arrive. build.rs regenerates contrib/completions/ from src/cmd/cmd.rs on every build, so a new flag ships with regenerated completion files. man/man1/ holds a page per subcommand and zoxide.1 for the environment variables, and the justfile lints them with mandoc. CHANGELOG.md follows Keep a Changelog with an Unreleased section. README.md documents each _ZO_* variable, and the HelpTemplate in src/cmd/cmd.rs prints the same list in --help.

Take an issue that asks for a new environment variable, _ZO_BASE_DIR, as a default for the --base-dir option of query. The agent traces how the existing ones work: src/config.rs reads each variable with a small function, such as maxage() parsing _ZO_MAXAGE with a context message or exclude_dirs() turning _ZO_EXCLUDE_DIRS into glob patterns and defaulting to the home directory, and data_dir() insisting with ensure! that _ZO_DATA_DIR is absolute. src/cmd/query.rs builds a StreamOptions in get_stream from the Query fields, and src/db/stream.rs applies them in order: keywords, base directory with Path::starts_with, exclude globs, then existence last because it is slow. So the change is a base_dir() reader in config.rs, a fallback in get_stream when the flag is absent, one line each in the HelpTemplate, README.md, man/man1/zoxide.1 and man/man1/zoxide-query.1, and an Unreleased entry.

The test comes before the change, in the shape the module already has. src/db/stream.rs ends in an rstest table of keyword cases, and src/db/mod.rs opens a database in a tempfile::tempdir(), so the base-directory behaviour gets a case there that adds two paths and checks which one a stream with that base directory yields. Behaviour that only shows at the binary level, such as reading the environment, gets an assert_cmd test that runs the built zoxide with _ZO_DATA_DIR pointed at a temporary directory, as src/config.rs requires. The agent runs cargo test and sees the new case fail, then makes the change and runs it green.

Then it runs what ci.yml runs through the justfile, without Nix: cargo clippy --all-features --all-targets -- -Dwarnings, cargo fmt --all --check with a nightly rustfmt because rustfmt.toml uses imports_granularity and group_imports, cargo msrv verify against 1.88.0, and cargo test --all-features --no-fail-fast. The shell template tests in src/shell.rs need their interpreters; for a change that leaves templates/ alone they are unaffected, and the agent says which ran. It builds once more so build.rs rewrites contrib/completions/, commits those files with the change, and opens a pull request whose description says Closes #<issue>, explains the change, and quotes the test and lint output.

Start it with one API call

POST https://api.prix.dev/o/{org}/sessions with this body:

{
  "agent": "claude",
  "input": "Implement the GitHub issue that follows this prompt in this Rust CLI. Read Cargo.toml, the justfile, build.rs, src/cmd/cmd.rs and src/config.rs first to learn how commands, flags and environment variables are defined and documented. Write the test first in the style the module already uses, an rstest case under src/db/ or an assert_cmd test with _ZO_DATA_DIR set to a temporary directory, and confirm it fails. Make the change in the one module it belongs to, update the help template in src/cmd/cmd.rs, README.md, the man page under man/man1 and the Unreleased section of CHANGELOG.md when the change is user-visible, and rebuild so build.rs regenerates contrib/completions, committing those files. Run cargo clippy --all-features --all-targets -- -Dwarnings, cargo fmt --all --check with a nightly rustfmt, cargo msrv verify and cargo test --all-features --no-fail-fast, and say which shell tests ran. Open a pull request whose description says Closes #<issue>, explains the change and quotes the test and lint output.\n\nIssue #1325: new env variable _ZO_BASE_DIR for a default --base-dir. I always want query to search under my projects directory. Add _ZO_BASE_DIR so query uses it when --base-dir is not given, and document it alongside the other _ZO_ variables.",
  "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 whose description says Closes #1325 and explains the change in a few sentences. For a new environment variable the diff touches src/config.rs, src/cmd/query.rs, the HelpTemplate in src/cmd/cmd.rs, README.md, two files under man/man1/, CHANGELOG.md, a test under src/db/ or tests/, and the regenerated files under contrib/completions/. Cargo.toml and Cargo.lock do not change.

A reviewer checks that the test failed before the change, which the session's record shows in order, that the variable's absence leaves query exactly as before, which the existing rstest cases prove, and that the completions diff matches what build.rs generates from the new cmd.rs. Merging closes the issue through GitHub's own Closes keyword.

The session read returns the repository and the pull request, and the transcript holds every command with its output: the failing test, the passing one, clippy, fmt, the MSRV check and the shell tests that ran.

Run it on every GitHub issue labelled agent

In the console, add an automation to the Project with a GitHub trigger on issues.labeled, filtered to the agent label, and this prompt without the issue text; the trigger appends the issue after the prompt itself. Only labels applied by an owner, member or collaborator fire it, so a maintainer decides which issues an agent takes, and each labelled issue starts its own run on its own branch.

The same request can come from your own server with the issue's text after the prompt. Set a webhook_url on the API key and Rush POSTs run.completed when the turn finishes, with the session_url to read the pull request link from and comment it on the issue.

The use case this job follows, with its automation and trigger: Turn a Linear label into a PR.

Why run it on Rush?

A small CLI change is mostly bookkeeping: the test, the help text, the man page, the changelog, the regenerated completions, and four lint commands that each need a toolchain or a nightly. In its own sandbox the agent does all of it for one issue while the maintainer's checkout stays on whatever they were doing, and the record of every command is on the session.

Triage becomes the whole job. Read five feature requests, label the ones that are well specified, and five runs start in five sandboxes, each ending in a pull request that closes its issue with the test and lint output quoted, so the maintainer reviews diffs instead of writing them.

Frequently asked questions

Will it update the man pages and completions?

Yes, when the change is user-visible. build.rs regenerates contrib/completions/ from the clap definitions on every build, so the agent rebuilds and commits those files. The man pages under man/man1/ are hand-written, so it edits the relevant page and runs mandoc -Tlint on it as the justfile does.

Which issues are a good fit?

Ones that name a behaviour and where it lives: a new _ZO_ variable, a flag on query, a keyword-matching rule in src/db/stream.rs. A request that needs a design decision, such as changing how scores age, gets a pull request that states the choice it made and why, or a comment asking for the decision when the issue leaves it open.

Does it need every shell installed?

Only when the change touches templates/ or src/shell.rs, whose tests pipe each rendered template through its interpreter and through shellcheck and shfmt. For a change elsewhere those cases are unaffected, and the pull request says which shell tests ran.

What if the issue cannot be implemented as written?

The agent says so in its final answer with what it found, rather than forcing a change. You can reply with more detail as a follow-up message to the same session once the turn has finished, and it continues in the same sandbox with the build cache intact.