laravel-shift/cli
A command-line interface for Laravel Shift that brings automated Laravel upgrades and code modernization to your terminal. Authenticate, run Shifts, and streamline Laravel project upgrades without leaving your workflow.
laravel-shift/cli installs a global shift binary that wraps Shift's automated "Shift" jobs (linting, fixing, upgrading) so you can run them locally instead of queuing them on shiftservice.com. Day-to-day it acts as a second opinion on top of Pint, PHPStan, and friends.
Install it globally so the binary is on your PATH:
composer global require laravel-shift/cli
Confirm the binary and its command list:
shift --help
shift list
Prerequisites: PHP 8.x and Docker running locally. The CLI shells out to Docker images maintained by Shift, so the first run of any command will pull an image and be slow. Verify Docker with docker info before troubleshooting the tool itself.
Where to look first:
~/.composer/vendor/laravel-shift/cli (or the global vendor dir) — the command classes make the available Shifts and their flags obvious.shift --help for the specific command — most commands mirror a Shift "type" (lint, fix, upgrade).First real use case: on a fresh branch, run the lint task against your project to see what Shift would flag:
git checkout -b shift/lint
shift lint
Treat the output as review material — it produces diffs/patches rather than silently mutating your tree in most modes.
Local pre-review loop. The most common pattern is: develop normally, then run Shift's lint/fix locally as a pre-flight before opening a PR. Because the heavy lifting happens in a Docker container, this keeps your host PHP extensions and version untouched.
shift lint path/to/app # scope a run to a subdirectory
shift fix # apply the suggested corrections, then review with git diff
Always run these on a branch and review git diff before committing — the tool is a helper, not an authority.
Composer script hooks. Wire it into composer.json so the team gets consistent behaviour:
{
"scripts": {
"shift:lint": "shift lint",
"shift:fix": "shift fix"
}
}
Then composer shift:lint. This avoids depending on each developer remembering the CLI name and flags.
CI as an advisory gate. Because it needs Docker, run it on a CI runner that has Docker available (GitHub Actions ubuntu-latest works out of the box). Keep it non-blocking initially — use continue-on-error: true — so you learn its noise level before making it a required check. Pin the version in CI:
- run: composer global require laravel-shift/cli:^1
- run: shift lint
Upgrade dry-runs. For major Laravel bumps, run the upgrade task on a throwaway branch and treat the resulting diff as a checklist of files to review manually. It is useful for surfacing the shape of required changes (imports, provider renames, config keys), not for blindly merging.
Pairing with existing tooling. Use Shift's fix output as input/context when a Pint run keeps failing, and use Shift's lint output to identify rules that your static analysis misses. Do not replace Pint/PHPStan with it — the two ecosystems have different rule sets and you want the union.
Chained maintenance. For a large legacy repo, scope runs per-directory (app/, app/Http/Controllers, etc.) rather than one giant run. Smaller diffs are reviewable and failures are easier to bisect.
laravel-shift/cli:^1) and treat any future Laravel bump as "this tool may no longer understand the codebase." Have a migration plan to Pint + Rector + Larastan for the long term.docker ps first, then the CLI.shift <command> -vvv surfaces the Docker invocation and upstream responses. This is the fastest path from "it failed" to "the daemon was down / the network was blocked."vendor:publish), changes there require a fresh process — no hot reload. Also, because it's a global install, config discovered from the current project may differ from what you expect; run shift from the project root you intend to operate on.How can I help you explore Laravel packages today?