What the agent does
The agent reads go.mod to see what moves together. In charmbracelet/glow, module charm.land/glow/v3, the go directive is 1.26.7 and there are two dozen direct requirements. Four are the Charm v2 libraries on the charm.land path: bubbles/v2 v2.1.1, bubbletea/v2 v2.0.8, glamour/v2 v2.0.1 and lipgloss/v2 v2.0.6, which share internals and move as a set. Beside them are spf13/cobra v1.10.2 and spf13/viper v1.21.0, charmbracelet/log v0.4.2, caarlos0/env/v11, fsnotify, go-runewidth, uniseg, sahilm/fuzzy, mvdan.cc/sh/v3, and the golang.org/x modules sys, term and text. The indirect block carries pseudo-versions that matter: charmbracelet/ultraviolet at a dated v0.0.0 and the old charmbracelet/lipgloss at a v1.1.1-0 pre-release, both pulled in by the v2 libraries, so a Charm bump can move them to a tagged release or to a newer pseudo-version.
Then it reads what the repository already does about upgrades, so the run agrees with it. .github/dependabot.yml groups all gomod updates into one monthly pull request and ignores bubbletea/v2 at v2.0.0-beta1, and dependabot-sync.yml refreshes that config weekly from charmbracelet/meta. Taskfile.yaml defines test as go test ./... and lint as golangci-lint run. .github/workflows/coverage.yml runs go test -race -covermode atomic -coverprofile=profile.cov ./..., build.yml reuses the shared build, snapshot, govulncheck, semgrep and ruleguard workflows, and lint.yml runs golangci-lint with --issues-exit-code=0, so lint is advisory there. The tests are glow_test.go, url_test.go with its network cases skipped, ui/pager_test.go, ui/ui_test.go, ui/rawpaint_test.go and utils/textsize_test.go.
The groups follow the module graph. The Charm set moves first and together, with go get naming all four, followed by go mod tidy and a check of what happened to ultraviolet and the old lipgloss in the indirect block; a Bubble Tea or Lip Gloss release that changes an API the ui/ package uses shows up as a compile error and sends the group back. Cobra, Viper and pflag move as the second group, since a Viper change can alter how glow.yml keys bind to flags in main.go. The golang.org/x modules move as the third, and everything else as the fourth. The go directive stays at 1.26.7 unless a required module demands a newer one, and then the pull request says which module and why. Ignore rules from dependabot.yml are respected, so a version Dependabot is told to skip is skipped here too.
After each group the agent runs go build ./..., go vet ./..., go test -race ./..., govulncheck ./... and golangci-lint run, and renders a README through the built binary with --style notty into a file to see that output still appears. A group that passes is a commit; a group that fails is reverted with the error kept. The pull request lists each bump with old and new versions, including indirect modules that moved, the skips with their reason, and the five check results.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "Upgrade this Go CLI's modules in groups: the charm.land v2 libraries together, then spf13/cobra, spf13/viper and spf13/pflag, then the golang.org/x modules, then everything else, each with go get followed by go mod tidy. Respect the ignore rules in .github/dependabot.yml and keep the go directive unless a module requires a newer one, and say which. After each group run go build ./..., go vet ./..., go test -race ./..., govulncheck ./... and golangci-lint run, and render README.md through the built binary with --style notty to a file. Keep a group only if everything passes; otherwise revert it and record the error. Open one pull request with one commit per group, one line per bump with old and new versions including indirect modules that moved, and every upgrade left out with the reason.",
"resources": [
{
"url": "https://github.com/your-org/your-app"
}
]
}- 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.
- 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.
- 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 on a new branch that changes go.mod and go.sum, in one commit per group that passed, with a source change only where a major required it and the file named in the description. The go directive is unchanged unless the description says which module moved it.
The description is one line per bump with old and new versions, the indirect modules that moved with them, a list of upgrades left out with the compile error, test failure or vulnerability report that excluded them, and the result lines of go build, go vet, go test -race, govulncheck and golangci-lint run. The trajectory keeps the full output for every group, including the reverted ones, and the rendered README.
Before merging, a reviewer checks that the four Charm v2 libraries moved together, that the ultraviolet and old lipgloss pseudo-versions in the indirect block landed on versions the Charm release expects, and that a left-out bump is not the one govulncheck wanted.
Run it on every Monday morning
Create an automation in the Project with this prompt and a schedule trigger (cron 0 9 * * 1 in your timezone). Each week the run opens one pull request with that week's bumps, or none when nothing moved. Because each group is its own commit, dropping a bump before merge is a revert of one commit.
To have the link reach your server, start the weekly run from your own scheduler instead, with POST /o/{org}/sessions and an API key that has a webhook URL: Rush then POSTs run.completed with the session_url when the turn ends, and a handler on your side can post the pull request link where the maintainers read. A run that ends with no safe group opens no pull request and says why in its result.
The use case this job follows, with its automation and trigger: Upgrade dependencies weekly.
Why run it on Rush?
A grouped bot pull request on a Go CLI is all or nothing: one Bubble Tea release that changes a view API turns the whole month red and the other bumps wait with it. On Rush the agent tries the groups one at a time in a sandbox, builds and tests with the race detector after each, reverts the one that fails, and keeps the output, so the pull request that reaches you carries everything that passed and names the one that did not.
Running govulncheck and a real render of the binary after every group is the kind of check a person skips when the suite is green. The record shows each run, and the same request runs on every Go tool you maintain at the same time.
Frequently asked questions
Dependabot already groups gomod updates here. Why this?
Dependabot opens the group and CI reports red or green for the whole thing. This run splits the group by module family, keeps the parts that pass, reverts the part that fails, and explains why in the description, so a single breaking release does not block the rest for a month.
What about the pseudo-versions in the indirect block?
They are reported, not chased. When the Charm group moves, go mod tidy resolves ultraviolet and the old lipgloss to whatever the new releases require, and the pull request lists the before and after. The agent does not pin them by hand.
Will it move the go directive?
Only if a module in a passing group requires a newer Go, and then the description names the module. Otherwise go 1.26.7 stays and the toolchain the sandbox uses matches it.
How does it check the TUI still works?
The ui/ tests run under the race detector, and the rendering path is exercised by piping a README through the built binary with --style notty. Interactive behavior in the Bubble Tea program is not covered by that and the pull request says so; a UI change in a Charm release is a reason to try the binary by hand before merging.
Can I exclude a module?
Yes. Name it in the prompt or add it to the ignore list in .github/dependabot.yml, which the agent reads and respects. It stays at its current version with a line in the pull request saying so.