You point Observer at a Laravel repo and it scans. Easy. But here's the thing I kept getting asked:
"Which engine actually found what? And what changes if I install Semgrep or PHPStan?"
Good question. In v0.6.0 the dashboard answers both, right in the scan history. Every past scan now shows an Engines column — a pill for each engine that ran (Semgrep, PHPStan, Bandit, gosec, ESLint), or a plain Built-in badge when you scanned with no local engines installed. There's a legend too, and scans are sorted newest-first so the comparison you care about is always at the top.
No flags. Observer auto-detects whatever you have installed and runs it. Install more → deeper scan. Uninstall → still works, just faster and built-in only.
The demo: one Laravel app, two scans
I scanned the same project twice — FinDocAnalyzer, a Laravel + MySQL app (582 files). First with zero local engines, then again with Semgrep and PHPStan installed. Same code, same machine, just a different toolchain.
Scan 1 — Built-in only (no engines installed)
- 58 issues — 31 high, 2 medium, 25 low
- Security 79 / C, Health 99 / A
- Took 39.9s
- Dashboard shows: Built-in
This is the "no setup" path. Observer runs its own offline rules — secrets in commits, raw SQL concatenation, APP_DEBUG=true in prod, unguarded eval, that kind of thing. Fast, zero dependencies, catches the scary patterns.
Scan 2 — With Semgrep + PHPStan installed
- 348 issues — 26 high, 297 medium, 25 low
- Security 81 / B, Health 66 / D
- Took 52.3s
- Dashboard shows: Semgrep · PHPStan
The moment PHPStan and Semgrep are on PATH, Observer picks them up and runs them — no config, no switches. Now the same 582 files get type-aware analysis: PHPStan's argument.type / return.type / mass-assignment findings, Semgrep's taint and framework-specific rules. The issue count jumps from 58 to 348 mostly because of medium findings that only a real type-checker can see.
So which one should you run?
Neither is "wrong." They're a speed-vs-depth tradeoff you now control:
| Built-in | With engines | |
|---|---|---|
| Setup | none | install Semgrep + PHPStan |
| Issues | 58 | 348 |
| High | 31 | 26 |
| Medium | 2 | 297 |
| Health | 99 / A | 66 / D |
| Time | 39.9s | 52.3s |
Notice the built-in scan flagged more "high" findings (31 vs 26). That's not because it's smarter — it's because without type context it can't downgrade a pattern that PHPStan proves is safe. Installing engines doesn't just add findings, it adds judgement: fewer false highs, way more real mediums worth fixing.
My rule of thumb:
- CI on every push → built-in. Fast, no extra deps, still catches the worst stuff.
- Pre-release / deep audit → install the engines once, get the type-aware pass.
And because the dashboard records the engine set per scan, you can literally watch the "Change" column flip from -290 (the built-in scan, 290 fewer than the deep one) to +291 (the deep scan, 291 more than the one before it) as you add tooling. The history tells the story.
How to try it
bash
# free, no engines needed
observer serve
# open http://127.0.0.1:7777, paste your project path, hit Scan
# want the deeper pass? just install the engines — Observer finds them:
composer global require phpstan/phpstan
pip install semgrep
# re-scan the same project — the Engines column now shows the pills



Top comments (0)