The strongest argument for CLI tools over MCP servers is arithmetic, and I ran it on my own workflow. A browser form test through an MCP pipeline cost me roughly 114,000 tokens; the same test, scripted through a CLI, about 27,000. A 4x difference, and the CLI run finished faster. The reason is structural, not incidental: MCP servers preload their tool schemas into every session's context whether you use them or not, while a CLI costs nothing until the moment it is invoked, and Claude already knows the common ones from training. That math turned me terminal-first, and my configs prove it: my main project's .mcp.json contains exactly one server, and my Claude Code permission allowlist is a long list of CLI patterns.
These are the ten tools on that allowlist that earn their place daily, with what Claude actually does with each on a real Laravel codebase.

1. gh — GitHub Without Leaving the Session
The GitHub CLI is the single highest-leverage tool on this list. My deploys run through GitHub Actions, and gh run list sits permanently in my allowlist because Claude checks CI after every push, pulls failure logs with gh run view --log-failed, and diagnoses before I have noticed the red X. It also drafts PRs with real descriptions (gh pr create), files issues for bugs it finds mid-task, and reads review comments. An entire MCP server exists for GitHub; gh does all of it with zero standing context cost.
2. php artisan — Your App Already Has a CLI
The most underused "AI tool" in any Laravel project is the framework's own command layer. Claude uses php artisan on my repo for migrations, route listing, cache busting, test runs, and, most powerfully, artisan tinker one-liners to answer questions with data instead of guesses: does this scope return what I think, how many rows match, what does this accessor actually output. Whatever your stack, the equivalent applies: rails, wp-cli (my WordPress client work leans on it heavily), django-admin. Teach Claude your app's CLI before you teach it anything else.
3. vendor/bin/pint — The Formatting Gate
Pint formats PHP to my project's style, and a git pre-commit hook makes it non-negotiable: Pint failures block the commit. The workflow effect is subtle but large. Because Claude knows the gate exists (it is documented in my CLAUDE.md), it runs Pint before finalizing changes rather than shipping diffs that bounce. Deterministic tools enforcing standards beats asking a model to remember style rules, every time.
4. PHPStan — Types as a Tripwire
Static analysis at level 8 catches the class of mistakes AI-generated code is most prone to: plausible calls to methods that do not exist, nullables handled optimistically, wrong return types. Claude runs it after meaningful changes and fixes what it finds. One honest quirk from my repo: composer test runs PHPStan, not PHPUnit, which is exactly the kind of project-specific trap you document once in CLAUDE.md so the agent never trips it again.
5. ripgrep (rg) — How Claude Actually Reads Your Codebase
Fast, gitignore-aware code search is the backbone of every "find where X happens" step. Claude's file-searching is built on exactly this kind of tool, and having rg available means questions like "every template that renders this partial" or "all callers of this service method" get answered in milliseconds across a codebase with hundreds of Blade views. The pagination contrast bug I found during my blog redesign was traced precisely this way: search for the partial, list its includers, notice the forum shell.
6. jq — JSON Surgery in the Pipeline
SEO exports, API responses, backup manifests, composer.json: everything is JSON, and jq lets Claude filter and reshape it without loading entire files into context. During my site's indexation remediation, row backups and status manifests were all JSON, and jq queries ("which posts are still pending?") replaced reading megabytes into the conversation. This is token economy as a habit: process data in the shell, bring only conclusions into context.
7. curl — Verify What Production Actually Serves
Every SEO and caching fix on my site ends with curl -sI against the live URL: is the canonical tag right, did the redirect land, what cache headers are actually being sent. My site's guest-page caching means logged-out visitors can see stale HTML for a while, and curl is how Claude distinguishes "the fix is wrong" from "the cache has not turned over." Trust the wire, not the deploy log.
8. xmllint — Sitemaps That Validate, Not Sitemaps That Probably Work
Niche until it is essential. My sitemap regenerates every five minutes in production, and during my sitemap audit xmllint validated structure and let Claude query URL counts per sitemap with XPath. It is in my allowlist because "the sitemap looks fine" and "the sitemap parses and contains 198 URLs for this tag" are different statements, and only one of them caught real bugs.
9. ssh and scp — Production, Carefully
Claude runs guarded, mostly read-only commands against my Hostinger server over SSH: checking deployed file state, reading logs, verifying cron entries (a check I added after a crontab entry vanished and took my queues with it). Two hard-won specifics: keep destructive patterns out of the allowlist so every write requires explicit approval, and if you ever pipe a file list into a loop that calls SSH, use ssh -n, or the first connection will eat your loop's stdin and process exactly one item. I lost real time to that one.
10. npm run build — The Frontend Truth Test
Vite builds are the verification step for any frontend-touching change: a missing manifest or a broken import fails loudly at build time instead of quietly in production. npm run build is in my allowlist so Claude closes its own loop: edit, build, then screenshot in the browser. Which raises the obvious question about browser automation, so, honestly:
Where MCP Still Wins
The CLI-first rule has exceptions, and they share one property: live state you interact with. Iterating on a page (click, inspect, screenshot, adjust) is genuinely better through the Playwright and Chrome DevTools MCP plugins than through fire-and-forget scripts, though for scripted browser runs the Playwright CLI approach claws back most of the tokens. Database schema introspection through my one standing MCP server (Laravel Boost) beats parsing migrations. My rule from my MCP setup guide: stateful and interactive earns MCP; one-shot commands stay CLI. A fuller list of the servers that pass that bar is in must-have MCPs for Claude Code.
Making Claude Actually Use These
Three steps that turn a list of tools into a faster workflow:
- Allowlist the safe patterns in
.claude/settings.local.json(Bash(gh run list:*),Bash(php artisan:*),Bash(vendor/bin/pint:*)). Every permission prompt you remove is friction and latency gone; mine has grown to dozens of entries, deliberately. - Document the quirks in CLAUDE.md: which command runs what, which flags matter, which traps exist. The agent reads it every session; corrections you write down stop recurring.
- Watch the context budget. Tool output costs tokens too; prefer flags and filters (
--log-failed,jqselectors,-sI) that return conclusions, not dumps. I collected more of these habits in Claude Code token management hacks.
Most of my allowlist patterns, CLAUDE.md fragments, and the exact wordings I use to direct these tools live in my prompt library, which is free to browse and steal from; the CLI workflow entries there pair directly with this list.