What the agent does
The agent reads the manifest and the lock to see what moves together. In filamentphp/demo, composer.json requires filament/filament ^5.0 with three plugins at the same range, the media library, settings and tags plugins, and composer.lock has all four at v5.10.1. Around them sit laravel/framework ^12.0 at v12.69.2, livewire/livewire at v4.4.7, laravel/octane, laravel/sanctum, flowframe/laravel-trend ^0.4.0, spatie/laravel-medialibrary at 11.23.8 and the two squirephp data packages. The dev side has pestphp/pest ^3.0 at v3.8.7, phpunit/phpunit at 11.5.56, larastan/larastan at v3.11.0, laravel/pint, rector/rector ^2.1 and laravel/boost. The post-autoload-dump script runs php artisan filament:upgrade after every install, which is what a Filament bump needs anyway.
Then it reads what passes for green. composer test runs test:pest, which is pest --parallel, and test:phpstan, which is phpstan analyse at level 8 with the Larastan and deprecation-rules extensions from phpstan.neon. phpunit.xml runs the tests/Filament suite only, with the SQLite lines commented out, so the database comes from .env, where .env.example sets DB_CONNECTION=sqlite; tests/Pest.php applies RefreshDatabase and signs in a factory user before each test. The suite covers the three dashboards, fourteen widgets and the resource pages across Blog, HR and Shop with Livewire::test, callAction and TestAction. .github/workflows/tests.yml runs on PHP 8.4 with pdo_sqlite, builds assets with npm ci and npm run build on Node 20, touches database/database.sqlite, and runs composer test:pest; phpstan.yml runs the analysis separately and format.yml runs Pint on push to 5.x.
The repository has turned version bumps from bots off: .github/dependabot.yml lists composer and npm with open-pull-requests-limit: 0, leaving only GitHub Actions updates. So the agent's groups are the policy. Filament and its three plugins move together as one group, since the plugins pin the core version and filament:upgrade runs after. Laravel, Livewire, Octane and Sanctum move as the framework group. The Spatie packages move together. The dev tools move last and separately, because a Pest, PHPStan or Rector bump changes what counts as passing rather than what runs, and a new PHPStan rule at level 8 can fail the analysis on code that did not change. Majors go one at a time with composer why-not consulted first.
Every group runs composer update for its packages with --with-all-dependencies, then composer test:pest, composer test:phpstan and vendor/bin/pint --test. Before the first group the agent copies .env.example to .env, generates a key, touches the SQLite file and runs npm ci && npm run build once so the Vite manifest the Livewire tests render against exists. A group that passes is a commit; a group that fails is reverted and its error kept. The pull request lists each bump with old and new versions from the lock, the skips with their reason, and the three check results.
Start it with one API call
POST https://api.prix.dev/o/{org}/sessions with this body:
{
"agent": "claude",
"input": "Upgrade this Filament app's Composer dependencies in groups: filament/filament and its plugins together, then laravel/framework with livewire, octane and sanctum, then the spatie packages, then the remaining runtime packages, then the dev tools one at a time, and any major on its own. Before the first group copy .env.example to .env, run php artisan key:generate, create the SQLite database file and build assets with npm ci and npm run build. After each group run composer update for that group with --with-all-dependencies, then composer test:pest, composer test:phpstan and vendor/bin/pint --test. Keep a group only if all three pass; 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 from composer.lock, 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 that changes composer.lock, and composer.json only where a constraint had to move for a major, in one commit per group that passed. Published Filament assets under public/ change when the Filament group moved, because filament:upgrade runs on install. No application code changes unless a major required it, and then the description names the file and the line.
The description is one line per bump with the locked versions before and after, a list of upgrades left out with the failing Pest test, PHPStan error or Pint diff that excluded them, and the result lines of composer test:pest, composer test:phpstan and pint --test. The trajectory keeps the full output for every group, including the reverted ones.
Before merging, a reviewer checks that the four Filament packages carry the same version, that a PHPStan failure was fixed by reverting the tool bump rather than by lowering the level, and that a skipped major is not a security release that deserves a code change in its own pull request.
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 to the channel that watches the panel. 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 Filament panel has more moving parts than a plain Laravel app: the core, three plugins and Livewire have to agree, an upgrade publishes assets, and the Pest suite drives every page through Livewire. The repository turned bot pull requests off because a red one is noise. On Rush the agent runs the suite and the static analysis after each group in its own sandbox, reverts what fails, and keeps the output, so the pull request that reaches you is already green and the failures are written down.
Running pest --parallel and PHPStan at level 8 on every group is work a person does once a quarter at best. The record shows each run, and the same request runs on every Filament panel you maintain at once.
Frequently asked questions
Why do the Filament plugins move with the core?
Because each plugin pins the core version it was built against, and composer.lock already shows all four at the same version. Moving one without the others fails composer update or filament:upgrade, so the agent treats them as one group.
Does it need Node?
Once, to build the assets the Livewire tests render against. tests.yml does the same with npm ci and npm run build. The agent does not upgrade npm packages in this run; that is a separate job.
What if PHPStan fails after a Larastan bump?
The dev-tool group is reverted and the new errors are listed in the description, with the files they point at, so you can decide whether to fix the code or raise the tool later. The agent does not lower the level or add a baseline to make the analysis pass.
Will it touch application code?
Only for a major that requires it, in the same commit as the bump, with the change named in the description. Minor and patch groups that need code changes are reverted and reported instead.
Can I pin a package?
Yes. Name it in the prompt and it stays at its locked version with a note in the pull request. A tightened constraint in composer.json works too and is respected.