If you’ve worked on medium-to-large Laravel projects, you’ve felt the pain.
You run PHPStan.
You wait.
You switch tabs.
You forget what you were fixing.
Static analysis should help developers move faster — but too often, traditional PHP tooling slows teams down. Formatting, linting, and analysis become something you run occasionally instead of continuously.
That’s exactly the problem Mago was built to solve.
What Is Mago?
Mago is a modern, unified PHP toolchain written entirely in Rust.
It replaces multiple tools with a single, ultra-fast binary that performs:
✅ Code formatting (PER-CS compliant)
✅ Linting (style, smells, best practices)
✅ Static analysis (types, null safety, logic issues)
✅ Architecture enforcement (layer boundaries)
Instead of juggling PHPStan, Psalm, PHP-CS-Fixer, and custom scripts, Mago gives you one configuration, one CLI, one mental model.
And yes — it’s fast. Very fast.
Why Mago Is So Fast (And Why It Matters)
Mago isn’t a PHP script running on top of PHP.
It’s written in Rust, designed for:
Native performance
Parallel execution
Low memory overhead
Zero runtime bootstrapping
What this means in practice
ToolLarge Laravel AppPHPStan2–3 minutesPsalm1–2 minutesMago10–20 seconds
Speed isn’t just convenience — it changes how teams work:
You run analysis before every commit
CI pipelines stay fast
Developers stop ignoring quality tools
Installation (Laravel-Friendly)
Recommended: Composer (Per-Project)
composer require --dev carthage-software/magoOr globally (macOS / Linux)
brew install magoVerify installation:
mago --versionProject Setup in Seconds
Inside your Laravel project root:
mago initMago will:
Detect
composer.jsonIdentify Laravel directories
Configure sensible defaults
Generate
mago.toml
No manual wiring. No guessing.
1️⃣ Lightning-Fast Linting (With Auto-Fix)
Mago’s linter detects:
Bad formatting
Inefficient patterns
Missing type hints
Laravel-specific smells
Run linting
mago lintAuto-fix safe issues
mago lint --fixExample: Real Laravel Controller
Before
class UserController extends Controller {
public function index(Request $request) {
$users = User::where('status','active')->get();
if(count($users) > 0){
return response()->json($users);
}
return response()->json([]);
}
}Issues detected
Inconsistent braces
count()on collectionsMissing return type
Unused request parameter
After (Mago-guided)
use Illuminate\Http\JsonResponse;
class UserController extends Controller
{
public function index(): JsonResponse
{
$users = User::where('status', 'active')->get();
if ($users->isEmpty()) {
return response()->json([]);
}
return response()->json($users);
}
}2️⃣ Opinionated Formatter That Ends Style Arguments
Mago’s formatter follows PER-CS, meaning:
No bikeshedding
No team debates
No inconsistent PRs
Format your project
mago formatCI-safe check
mago format --checkOnce formatting is automated, code reviews focus on logic — not whitespace.
3️⃣ Static Analysis That Prevents Production Bugs
This is where Mago really shines.
mago analyzeMago detects:
Null dereferences
Invalid return types
Incorrect assumptions about Eloquent
Unsafe property access
Example: Common Laravel Bug
class ProductService
{
public function discount(Product $product): float
{
return $product->price * 0.1;
}
public function name(int $id): string
{
return Product::find($id)->name;
}
}Problems
$pricecan benullfind()may returnnull
Fixed (With Mago’s Guidance)
class ProductService
{
public function discount(Product $product): float
{
return $product->price !== null
? $product->price * 0.1
: 0.0;
}
public function name(int $id): ?string
{
return Product::find($id)?->name;
}
}These are real production bugs — caught before deployment.
4️⃣ Architecture Guard: Enforce Clean Boundaries
Large Laravel projects rot when architecture rules aren’t enforced.
Mago lets you define rules like:
Controllers → Services only
Services → Repositories
No Models inside Controllers
No cross-module access
Example Rule Concept
[architecture]
controllers_cannot_access_models = true
require_service_layer = true
Now violations fail locally and in CI.
CI/CD Integration (Fast Enough to Matter)
GitHub Actions Example
name: Code Quality
on: [push, pull_request]
jobs:
mago:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Mago
run: curl -fsSL https://mago.carthage.software/install.sh | sh
- name: Run Mago
run: |
mago lint
mago format --check
mago analyzeEven on large projects, this completes in seconds.
VS Code Integration (Instant Feedback)
{
"[php]": {
"editor.defaultFormatter": "mago",
"editor.formatOnSave": true
}
}Now every save:
Formats code
Enforces standards
Reduces review noise
mago.toml – Laravel-Optimized Example
php-version = "8.2"
[paths]
include = ["app", "routes", "config", "tests"]
exclude = ["vendor", "storage", "bootstrap/cache"]
[linter]
level = "strict"
[formatter]
line_width = 120
[analyzer]
level = 5
memory_limit = "2G"Clean. Predictable. Scalable.
Real-World Laravel Use Cases
API Projects
Enforce consistent response types
Catch missing status codes
Prevent null access in services
SaaS Platforms
Keep service boundaries intact
Prevent fat controllers
Maintain long-term code health
Legacy Applications
Generate a baseline
Fix only new issues
Improve gradually
mago analyze --generate-baselineWhy Laravel Teams Should Care
✅ 10x faster feedback
✅ One tool instead of five
✅ Lower memory usage
✅ Better CI pipelines
✅ Cleaner code reviews
Mago doesn’t just replace tools — it changes developer behavior.
Final Thoughts
Mago isn’t hype.
It’s what PHP tooling looks like when performance is treated as a first-class feature.
If you care about:
Developer velocity
Clean architecture
Fast CI pipelines
Fewer production bugs
Then Mago deserves a place in your Laravel workflow.
Getting Started
composer require --dev carthage-software/mago
mago init
mago lint && mago format && mago analyze








