Stu Mason
Stu Mason
Guide

My CLAUDE.md Setup for Laravel Projects (With Real Examples)

Stuart Mason11 min read

A detailed walkthrough of my actual CLAUDE.md configuration for Laravel projects — global settings, project-level rules, and the sections that make the biggest difference.

I've been using Claude Code daily for months now. Early on, my interactions were fine but generic — Claude would give me textbook Laravel answers that missed how I actually work. It would spell out full commands I have aliases for, suggest patterns that didn't match my project's conventions, and ignore the tooling I'd already set up.

The fix was CLAUDE.md. Once I configured it properly, Claude stopped being a generic Laravel assistant and started working like a developer who actually knows my codebase. The difference is night and day.

This is a walkthrough of my actual configuration — the global file, the project-level file, and the specific sections that made the biggest impact.

Two Levels of Configuration

Claude Code reads CLAUDE.md files from two locations:

  1. Global~/.claude/CLAUDE.md applies to every project and every session
  2. ProjectCLAUDE.md in your project root applies only to that project

Global handles your personal environment — your tools, your shell, your preferences. Project handles everything specific to the codebase — architecture decisions, conventions, deployment, commands.

Both load automatically. No import statements, no config flags. Just drop the files in place and Claude reads them.

My Global CLAUDE.md

This is ~/.claude/CLAUDE.md. It's short on purpose — under 20 lines. Everything here applies regardless of what project I'm working on.

# Stu Mason - Dev Environment

## Stack
PHP (Laravel/Herd) | Node (nvm) | Python (pyenv) | Editor: VS Code

## Shell Aliases
`ga` git add | `gc` checkout | `nah` reset hard | `gamend` amend | `fuckit` WIP push
`art` php artisan | `master`/`main`/`develop` checkout+pull
`sso-devops` AWS login | `ecr-login` Docker ECR | `sam-build` SAM

## Tools ~/Code/tools/
`./hue recording|nightlights|daylights|off` | `make invoice` | `make review URL=<yt>`

## Prefs
Concise. Use existing aliases. Minimal changes. Don't over-engineer.

Why the Stack Line Matters

Declaring PHP (Laravel/Herd) up front means Claude never suggests Docker-based setups, never asks if I'm using Valet vs Sail, and never recommends php -S for local development. It knows I'm on Herd. That saves time on every single interaction.

Same with Node (nvm) — Claude uses nvm use instead of assuming a global Node installation.

Shell Aliases Are the Secret Weapon

This section changed how Claude generates commands for me. Before adding it, Claude would suggest:

php artisan make:model Post -mfc
git checkout -b feature/new-thing
git add . && git commit --amend --no-edit

After adding aliases:

art make:model Post -mfc
gc -b feature/new-thing
gamend

It's a small thing, but when you're reading dozens of commands per session, shorter is better. Claude uses the aliases naturally in its suggestions because I told it they exist.

The Preferences Line

Concise. Use existing aliases. Minimal changes. Don't over-engineer.

Four instructions, massive impact. Without this, Claude tends toward verbose explanations, comprehensive refactors, and architecturally impressive but unnecessarily complex solutions. With it, Claude gives me what I asked for and stops. No unsolicited redesigns. No paragraph-long explanations of things I already understand.

My Project CLAUDE.md

This is where the real value lives. Here's my project-level CLAUDE.md for a Laravel 12 + Inertia v2 + React 19 application, broken down section by section.

Git Flow Rules

## Development Workflow

### Git Flow

Never commit directly to main. Always:
1. Create a feature branch (`feature/phase-x-description`)
2. Do the work
3. PR
4. Review
5. Merge

This prevents Claude from ever running git commit on main. Before I added this, Claude would happily commit directly to whatever branch was checked out. Now it refuses and reminds me to create a feature branch first.

Deployment Context

### Deployment

Pushing/merging to `main` automatically triggers a deployment to production via Coolify webhook. No need to manually trigger deploys.

This one line gives Claude critical context. It knows that pushing to main isn't just a git operation — it's a production deployment. So when I ask Claude to help with a merge or push, it treats main with the appropriate level of caution. It warns me. It double-checks.

Without this line, Claude has no idea what your deployment pipeline looks like. With it, Claude becomes deployment-aware.

Working in Slices

### Working in Slices

Work in small, isolated vertical slices. One feature at a time, fully working and tested before moving on.

- Each slice = branch, PR, review, merge
- No half-baked migrations or models sitting around
- Test everything before moving to the next feature
- Keep the PRD todo updated as work progresses

This shapes how Claude approaches larger tasks. When I ask for a feature that involves a model, migration, controller, page, and tests, Claude doesn't try to build everything at once. It works through it methodically — one piece at a time, tested before moving to the next.

Generator Commands

## Generator Commands

Use these commands instead of writing boilerplate manually:

php artisan make:action User/UpdateProfile
php artisan make:action Order/ApproveOrder

php artisan make:dto UserProfile --properties=id:int,name:string,email:string
php artisan make:dto OrderData --properties=id:int,total:int,status:string --model=Order

php artisan types:generate

This is one of the highest-value sections. My project uses custom Action and DTO classes with artisan generators I've built. Without this section, Claude would create action classes by hand with whatever structure it thinks is right. With it, Claude runs art make:action and gets the exact boilerplate my project expects.

The types:generate command is equally important — it tells Claude that after creating or modifying DTOs, it needs to regenerate TypeScript interfaces. Claude remembers to run this because the docs say to.

Test Commands

## Running Tests

Use this command to run tests (avoids environment variable conflicts):

env -u APP_ENV -u DB_CONNECTION -u DB_DATABASE -u DB_HOST -u DB_PORT -u DB_USERNAME -u DB_PASSWORD -u SESSION_DRIVER -u CACHE_STORE -u QUEUE_CONNECTION php artisan test

This is project-specific and non-obvious. My local environment has shell variables that conflict with the test environment. The env -u flags unset them before running tests. Without this in CLAUDE.md, every test run Claude triggers would fail with database connection errors, and Claude would spend time debugging a problem that isn't a problem — it's just environment config.

Coding Standards References

## Coding Standards

Before writing any code, review the coding standards in `docs/standards/`:

- general.md - Core principles, type hints, imports
- backend.md - Laravel patterns: models, migrations, controllers, Actions, DTOs
- frontend.md - Inertia + React + Tailwind patterns
- testing.md - Pest v4 testing patterns

I maintain a docs/standards/ directory with detailed coding conventions. Pointing Claude to these files means it reads them before writing code. The result: Claude's output matches my project's style from the first attempt instead of requiring multiple rounds of corrections.

The Third Layer: Laravel Boost

There's a third piece that dramatically improves Claude's Laravel knowledge, and it's the one most people underestimate. Laravel Boost is an official MCP server built by the Laravel maintainers. It does two distinct things: it gives Claude tools to interact with your running application, and it auto-generates guidelines that get injected into your CLAUDE.md.

Installing Boost

composer require laravel/boost --dev
php artisan boost:install

The install command generates your .mcp.json, injects guidelines into CLAUDE.md, creates agent skill files in .ai/skills/, and sets up a boost.json config. You can add the generated files to .gitignore — they regenerate automatically.

The MCP Tools

Boost gives Claude 15 tools for interacting with your actual application:

ToolWhat It Does
Database QueryExecute read queries against your database
Database SchemaInspect your table structures
Database ConnectionsCheck available database connections
Search DocsQuery 17,000+ pieces of version-specific Laravel documentation
TinkerExecute PHP in your application context
List Artisan CommandsInspect available artisan commands with arguments
List RoutesInspect application routes with middleware
Application InfoRead PHP/Laravel versions, packages, Eloquent models
Get ConfigRead configuration values using dot notation
List Available Config KeysDiscover all config keys
List Available Env VarsDiscover all environment variable keys
Read Log EntriesRead the last N entries from your application log
Last ErrorPull the most recent error from logs
Browser LogsRead browser console logs and errors
Get Absolute URLConvert relative URIs to full URLs

The Search Docs tool is the game-changer. It automatically passes your installed packages and their exact versions to a documentation API with 17,000+ indexed pieces across Laravel, Inertia, Pest, Tailwind, Livewire, Filament, Nova, and more. When Claude needs to check how deferred props work in Inertia v2, it gets back the right answer for your exact version. No hallucinated APIs. No outdated patterns.

The Database Schema and Database Query tools mean Claude can inspect your actual tables before writing migrations or queries. It stops guessing column names and starts knowing them.

Auto-Generated Guidelines

When you run boost:install, Boost scans your composer.json and package.json, detects which Laravel ecosystem packages you're using, and generates version-specific coding guidelines. These get injected directly into your CLAUDE.md.

Guidelines exist for 25+ packages including Laravel (with version-specific rules for 10.x/11.x/12.x), Inertia (React, Vue, Svelte), Pest (3.x, 4.x), Tailwind (3.x, 4.x), Livewire, Fortify, Wayfinder, Pint, and more.

The injected rules cover things like:

  • Use Model::query() instead of DB:: facades
  • Write Pest tests with datasets for validation rules
  • Use Tailwind v4's CSS-first @theme configuration instead of tailwind.config.js
  • Use Inertia v2's <Form> component and deferred props
  • Run vendor/bin/pint --dirty before committing
  • Use constructor property promotion in PHP 8

You don't write any of this. Boost generates it based on what's actually installed. When you update packages, run php artisan boost:update and the guidelines update too.

Agent Skills

Boost also includes on-demand skills — domain-specific knowledge that Claude loads only when relevant, keeping your context window clean. There are 14 built-in skills covering things like Livewire development, Pest testing, Tailwind CSS, Wayfinder routing, and MCP server development.

You can create custom skills too by adding SKILL.md files to .ai/skills/. I have one for my project's Action pattern that explains when and how to use make:action.

Why This Matters for CLAUDE.md

The key insight: your hand-written CLAUDE.md and Boost's auto-generated guidelines work together. You write the project-specific stuff — git flow, deployment pipeline, custom generators, test commands. Boost handles the framework-specific best practices. Neither replaces the other.

Tips That Made the Biggest Difference

Be Specific About What You Don't Want

Don't over-engineer and Minimal changes do more work than most positive instructions. Claude's default tendency is to be thorough and comprehensive. Sometimes that means refactoring three files when you asked it to change one line. Telling it what to avoid is as important as telling it what to do.

Include Real Commands, Not Just Descriptions

Don't write "use the artisan command to generate actions." Write the actual command:

php artisan make:action User/UpdateProfile

Claude is literal. If you give it the exact command, it uses the exact command. If you give it a description, it interprets — and sometimes interprets wrong.

Keep It Under 500 Lines

More isn't better. Every line of CLAUDE.md consumes context window tokens. A 1000-line CLAUDE.md eats into the space available for your actual conversation. My global file is under 20 lines. My project file is around 80 lines before Boost's additions. Be ruthless about what earns a spot.

Update It As Your Project Evolves

CLAUDE.md isn't write-once. When I add a new generator command, I add it to the file. When I change my deployment pipeline, I update the deployment section. When I notice Claude making the same mistake twice, I add a rule to prevent it. It's a living document.

Use the GitHub CLI Section

### GitHub Interactions

Always use `gh` CLI for GitHub interactions instead of web fetching:

gh pr view 123
gh pr view 123 --comments --json comments
gh issue view 123

This prevents Claude from trying to web-fetch GitHub URLs (which often fails with authentication issues) and instead uses the gh CLI that's already authenticated on your machine.

Before and After

Before CLAUDE.md: Claude gives me textbook Laravel. Full php artisan commands instead of art. Commits to whatever branch is checked out. Writes action classes by hand with its own structure. Runs tests without unsetting environment variables. Suggests Docker when I'm on Herd.

After CLAUDE.md: Claude uses my aliases. Creates feature branches. Runs my generators. Tests with the correct command. Knows that pushing to main means production. Matches my coding standards from the first attempt.

The time investment is maybe an hour to set up both files, then a few minutes here and there to keep them current. The return is every single Claude Code session being more productive, more accurate, and less frustrating.

If you're using Claude Code without CLAUDE.md, you're leaving most of its value on the table.

Get the Friday email

What I shipped this week, what I learned, one useful thing.

No spam. Unsubscribe anytime. Privacy policy.