Naar de inhoud
Recognized byLaravelMatch je projectContact

Je Laravel-project klaarmaken voor ontwikkelen met AI

Een AI-agent is zo goed als de omgeving waarin hij werkt. In een kaal project gokt hij naar je conventies, mist hij fouten die een linter direct had gevonden en roept hij "klaar" zonder dat iemand het heeft gecontroleerd. In een goed ingericht project kent hij de juiste versie van de documentatie, draait hij zelf de checks en ziet hij wat hij heeft gebouwd.

In dit artikel richten we stap voor stap een Laravel-project in voor ontwikkelen met AI. We beginnen bij Laravel Boost en eindigen met een project waarin de agent zijn eigen werk controleert.

Je Laravel-project klaarmaken voor ontwikkelen met AI

Wat je aan het eind hebt

Na dit artikel heeft je project:

  • Laravel Boost, met een MCP-server, slanke guidelines en skills
  • Eén korte AGENTS.md die elke agent leest, ook Claude Code
  • Code die dicht bij Laravel blijft, met projectregels voor de uitzonderingen
  • Skills op één plek, in .agents/skills
  • Checks die de agent zelf draait: Pint, Larastan, Rector, archtests en Pest
  • Browsertests waarmee de agent zijn UI-werk controleert
  • Hooks en permissies die de grenzen bewaken
  • Een werkwijze voor meerdere agents tegelijk
  • Instellingen die tokens besparen

Zo gebruik je dit artikel

Dit is deel 1 van een serie van twee. In deel 2, dat binnenkort verschijnt, gaan we dieper in op hoe je met Laravel en AI gestructureerd features bouwt.

Dit is een lang artikel. Lees het eerst helemaal, zodat je weet waar je naartoe werkt. Daarna kan je het samen met je agent oppakken, stap voor stap:

  1. Geef de agent de link naar dit artikel, of de tekst van één stap.
  2. Laat de agent de stap uitvoeren in jouw project.
  3. Controleer het resultaat en commit.

Deel 1: De basis

In dit deel geef je de agent de juiste kennis: over Laravel, over je packages en over je eigen project.

Stap 1: Laravel Boost installeren

Laravel Boost is de officiële package van Laravel voor AI-agents die aan je code werken. Boost geeft je agent drie dingen:

  • Een MCP-server met tools die je applicatie van binnenuit bekijken
  • Guidelines: korte instructies over Laravel en je packages, altijd geladen
  • Skills: uitgebreide kennis per onderwerp, alleen geladen als de agent ze nodig heeft

Installeer Boost als dev-dependency en draai de installer:

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

De installer stelt een paar vragen:

  • Welke features? Kies guidelines, skills en de MCP-server. Je hebt ze alle drie nodig.
  • Welke third-party guidelines en skills? Hier kies je de package guidelines. Daarover gaat stap 2.
  • Welke agents? Kies elke agent die jij of je team gebruikt, bijvoorbeeld Claude Code, Codex en Cursor. Boost schrijft voor elke agent de juiste bestanden.

Wat de MCP-server de agent geeft

Zonder Boost raadt een agent hoe je applicatie eruitziet. Met Boost kijkt hij. De belangrijkste tools:

  • Search Docs: zoekt in de documentatie van precies de versies die jij gebruikt, van Laravel en van packages als Livewire, Inertia en Pest
  • Database Schema en Database Query: de echte tabellen en data, in plaats van een gok op basis van migraties
  • Last Error en Read Log Entries: de laatste exception en de logs
  • Browser Logs: fouten uit de console van de browser
  • Application Info: de versies van PHP en Laravel, de database-engine en je packages met hun versies

Vooral Search Docs maakt verschil. Een model is getraind op een mix van oude en nieuwe Laravel-versies. Met Search Docs werkt het met de documentatie van jouw versie.

Guidelines en skills

Guidelines staan altijd in de context van de agent. Ze zijn kort en gaan over wat bij elke taak telt. Skills zijn langer en gaan over één onderwerp, zoals testen of Livewire. De agent laadt een skill pas als de taak erom vraagt.

Die verdeling is belangrijk. Alles wat altijd in de context staat, kost bij elke vraag tokens en aandacht. Boost verhuist daarom steeds meer kennis van guidelines naar skills.

boost.json

Je keuzes staan in boost.json. Draai je later php artisan boost:install opnieuw, dan zijn je eerdere keuzes de standaard. Wil je iets wijzigen, zoals een agent toevoegen? Draai de installer dan opnieuw.

Samen met je agent: start na de installatie een nieuwe sessie en vraag: "Welke versies van PHP, Laravel en Pest gebruikt dit project, en hoe ziet de tabel users eruit? Gebruik de Boost-tools." Krijg je een antwoord op basis van de echte database, dan werkt de MCP-server.

Stap 2: Package guidelines en slanke guidelines

Boost levert guidelines en skills voor Laravel en de first-party packages, zoals Livewire, Inertia en Pest. Maar ook andere packages kunnen eigen guidelines en skills meeleveren. Dat zijn de package guidelines.

Package guidelines kiezen

Een package zet zijn guidelines in resources/boost/guidelines en zijn skills in resources/boost/skills. Boost vindt ze vanzelf in je vendor-map. Alleen packages die je zelf in composer.json of package.json hebt staan, tellen mee. Een package die via een andere package binnenkomt, kan geen guidelines toevoegen.

Tijdens boost:install vraagt Boost welke third-party guidelines en skills je wilt installeren. Je keuze staat daarna in boost.json, onder packages.

Een voorbeeld van de website van de DLF zelf: Statamic levert guidelines mee, en spatie/laravel-responsecache een skill. De agent weet zo hoe deze packages werken, zonder dat wij dat hoeven uit te leggen.

Package guidelines zijn waardevol, want ze komen van de makers van de package. Ze beschrijven de API van precies de versie die je gebruikt. Zet ze aan voor de packages die een grote rol spelen in je project.

Minder is meer

Guidelines staan altijd in de context. Elke regel kost tokens, bij elke vraag. En een agent die veel instructies krijgt, volgt de belangrijke minder goed op.

Modellen schrijven steeds beter Laravel. Veel guidelines stammen uit een tijd waarin dat niet zo was. Boost schrapt daarom zelf guidelines die geen effect meer hebben. In Boost 2.10.1 ging er nog 15% af, zonder dat de resultaten in de evals van het Boost-team slechter werden.

Je kunt zelf ook guidelines uitzetten. Publiceer de config van Boost en zet de namen van de guidelines in exclude. De namen staan in de samenvatting van boost:install.

// config/boost.php
'guidelines' => [
    'exclude' => ['herd'], // Herd staat erop, maar je draait de app niet via Herd
],

Twijfel je? Laat de standaard staan. Het Boost-team test zijn guidelines; jij waarschijnlijk niet. Sluit alleen uit wat je echt niet gebruikt.

Eigen guidelines

Wil je de agent iets vertellen dat in geen enkele guideline staat? Zet het in .ai/guidelines. Boost voegt die bestanden toe aan de guidelines. Een bestand met hetzelfde pad als een standaardguideline vervangt die.

Wees hier zuinig mee. Een eigen guideline is alleen zinvol als de agent zonder die regel echt iets anders doet. Voor regels over je eigen applicatie zijn er betere plekken. Daarover gaan stap 4 en 6.

Samen met je agent: vraag: "Welke packages in composer.json leveren Boost-guidelines of -skills mee in resources/boost? Welke heb ik nog niet aangezet in boost.json?" Draai daarna php artisan boost:install en zet de nuttige aan.

Stap 3: Eén AGENTS.md, geen CLAUDE.md meer

Elke agent leest bij de start een instructiebestand. Lange tijd had elke tool een eigen bestand: CLAUDE.md voor Claude Code, .cursorrules voor Cursor, .github/copilot-instructions.md voor Copilot. Wie meerdere agents gebruikte, hield dezelfde tekst op meerdere plekken bij.

AGENTS.md maakt daar een eind aan. Het is een open standaard. Codex, Cursor, Copilot, Junie, OpenCode, Amp en vele andere agents lezen het.

Claude Code was lange tijd de uitzondering. Sinds versie 2.1.277 (september 2026) leest ook Claude Code AGENTS.md. Standaard leest Claude Code AGENTS.md alleen als er geen CLAUDE.md of CLAUDE.local.md is, in je project of in een map erboven. Dat kun je wijzigen onder "Project instructions" in /config.

Boost volgt dezelfde lijn. Sinds Boost 2.10 schrijft Boost de guidelines voor Claude Code naar AGENTS.md. Vanaf 2.10.1 blijft Boost in CLAUDE.md schrijven als je die al hebt.

Overstappen

  1. Staat er in je CLAUDE.md tekst die je zelf hebt geschreven? Verplaats die naar AGENTS.md, buiten het blok van Boost.
  2. Verwijder CLAUDE.md:
git rm CLAUDE.md
  1. Laat Boost de guidelines opnieuw schrijven:
php artisan boost:update

Werk je met een oudere versie van Claude Code, of wil je Claude-specifieke instructies kwijt? Dan kan een CLAUDE.md met één regel die naar AGENTS.md verwijst:

@AGENTS.md

Zet dan ook in config/boost.php dat Boost naar AGENTS.md schrijft. Anders zet Boost zijn blok ook in je CLAUDE.md, en krijgt Claude Code de guidelines dubbel:

'agents' => [
    'claude_code' => [
        'guidelines_path' => 'AGENTS.md',
    ],
],

Samen met je agent: vraag: "Verplaats de eigen instructies uit CLAUDE.md naar AGENTS.md, buiten het blok <laravel-boost-guidelines>. Verwijder daarna CLAUDE.md en draai php artisan boost:update." Start een nieuwe sessie en vraag welke instructies de agent heeft geladen.

Stap 4: Houd AGENTS.md kort

Het is verleidelijk om alles over je project in AGENTS.md te zetten. Doe dat niet.

In 2026 onderzochten ETH Zürich en LogicStar.ai wat contextbestanden als AGENTS.md opleveren. De uitkomst: ze verhogen de kans op een goede oplossing niet of nauwelijks, maar de kosten stijgen gemiddeld met zo'n 20%. Dat gold voor gegenereerde én voor zelfgeschreven bestanden. Wel bleek: agents volgen de instructies goed op. Zinvol zijn vooral regels over afwijkende conventies, en over tools die de agent anders niet zou kennen.

Anthropic adviseert hetzelfde voor Claude Code. Vraag je bij elke regel af: maakt de agent fouten als deze regel weg is? Zo niet, schrap hem.

Wat erin hoort

  • Commando's: hoe de agent test, lint en bouwt. Precies, met de juiste flags.
  • Afwijkingen: wat in jouw project anders gaat dan de agent zou verwachten.
  • Grenzen: wat de agent nooit mag doen, en wat eerst overleg vraagt.

Wat er niet in hoort

  • Een overzicht van je mappen of je architectuur. Die leest de agent zelf uit de code.
  • Regels die je linter of je tests al afdwingen. Die zie je terug in stap 8 en 9.
  • Algemene Laravel-kennis. Die staat al in de guidelines van Boost.

Laat AGENTS.md groeien uit fouten

Begin met een korte AGENTS.md. Voeg pas een regel toe als de agent iets fout doet. Mitchell Hashimoto, de maker van Ghostty, werkt zo: elke regel in een AGENTS.md van Ghostty komt voort uit een fout van een agent. En schrap regels die niets meer veranderen. Modellen worden beter; een regel die vorig jaar nodig was, is dat nu misschien niet meer.

Een voorbeeld

Boost beheert alleen zijn eigen blok, tussen <laravel-boost-guidelines> en </laravel-boost-guidelines>. Wat je daarbuiten schrijft, blijft staan bij elke update. Een eigen deel kan zo kort zijn:

# Project

Deze app draait op https://mijn-project.test. Start geen eigen server.

## Commando's

- `composer check`: draai dit voordat je een taak afrondt
- `vendor/bin/pest --tia`: draait alleen de tests die je wijziging raakt opnieuw; de rest komt uit de cache

## Grenzen

- Wijzig nooit bestaande migraties; maak een nieuwe
- Voeg geen packages toe zonder overleg
- Vraag eerst voordat je iets in `config/` wijzigt

Samen met je agent: vraag: "Lees AGENTS.md. Welke regels buiten het Boost-blok kun je ook zonder deze instructie afleiden uit de code of de tooling? Stel voor welke regels weg kunnen." Beslis zelf wat je schrapt.

Stap 5: Blijf dicht bij Laravel

Dit is misschien de belangrijkste stap, en hij kost niets. Hoe dichter je project bij de conventies van Laravel blijft, hoe beter een agent erin werkt.

Een model kent Laravel uit de documentatie en uit enorm veel bestaande code. Een Form Request, een Eloquent-relatie, een job op de queue: dat herkent het direct.

Een eigen structuur kent het model niet. Onderzoek laat zien hoe groot dat verschil is. In een studie uit 2022 gaven onderzoekers een model dezelfde programmeertaken twee keer. De tweede keer hadden de library en haar functies alleen een andere naam. Bij Codex zakte het percentage goede oplossingen van 19% naar 1,5%. Nieuwere modellen zijn beter, maar het patroon blijft: wat vaak voorkomt in de trainingsdata, gaat goed. Wat zeldzaam of eigen is, gaat vaker mis.

Elke afwijking kost een regel

Bouw je een eigen laag, dan moet je die uitleggen. In AGENTS.md, in een projectregel of in een skill. Elke uitleg kost context, en de agent volgt hem niet altijd. Boost zegt het zelf in de skill die projectregels opstelt: elke map in app/ die niet in het standaard Laravel-skelet zit, is een regel die je waarschijnlijk moet vastleggen. Standaard Laravel kost geen enkele regel.

Een voorbeeld. Je kunt invoer valideren met een eigen DTO-laag:

public function store(Request $request)
{
    $data = CreateProjectData::fromRequest($request);
    // ...
}

Of met een gewone Form Request:

public function store(StoreProjectRequest $request)
{
    $project = Project::create($request->validated());
    // ...
}

De tweede versie hoeft niemand uit te leggen. Elke agent weet hoe hij een Form Request maakt (php artisan make:request), wat erin hoort en hoe hij hem test.

Voor een kleine set regels is ook $request->validate() in de controller prima. Dat staat ook in de best practices van Boost: een Form Request als de validatie groot is of hergebruikt wordt, anders inline.

Afwijken mag

Dit betekent niet dat alles wat niet in de documentatie staat, verboden is. Action classes, DTO's of een package als spatie/laravel-data kunnen goede keuzes zijn, zeker in grote applicaties. Maar maak die keuze bewust, pas hem overal hetzelfde toe en leg hem vast als regel (stap 6). Het grootste risico zit in zelfbedachte abstracties die nergens anders bestaan.

Een bonus voor later

Code die dicht bij Laravel blijft, is ook makkelijker te refactoren en te upgraden. Met AI, en met tools als Rector en Laravel Shift. Die tools kennen de standaard; jouw eigen structuur kennen ze niet.

Samen met je agent: vraag: "Welke structuren in dit project wijken af van een standaard Laravel-applicatie? Geef per afwijking aan of er een goede reden voor lijkt te zijn." Gebruik het antwoord voor stap 6.

Stap 6: Projectregels in .ai/rules

Guidelines en skills leren de agent Laravel. Projectregels leren hem jouw applicatie. Daar horen de afwijkingen uit stap 5 thuis, en beslissingen of valkuilen die niet uit de code blijken.

Boost bewaart projectregels als Markdown in .ai/rules. Elke regel hoort bij een groep bestanden, bijvoorbeeld app/Http/Controllers/**. De agent leest een regel dus alleen als hij in die bestanden werkt. Dat scheelt context. Boost houdt een overzicht bij in .ai/rules/index.md.

Regels vastleggen

Je schrijft regels niet met de hand. De agent legt ze vast met de tool record-rule van Boost, en alleen als jij erom vraagt. Bijvoorbeeld:

"Leg vast als regel: controllers in app/Http/Controllers/Admin controleren altijd de rol admin via een policy."

Wil je beginnen met een bestaand project? Boost heeft een skill die de conventies in je code opspoort, infer-conventions. Die slaat alles over wat standaard Laravel is, of wat Pint en Rector al afdwingen. Wat overblijft, zijn de echte keuzes van jouw project.

Commit je regels

De bestanden die Boost genereert, kun je altijd opnieuw maken. .ai/rules niet. Commit die map, zodat iedereen in je team en elke agent dezelfde regels heeft.

Samen met je agent: vraag: "Gebruik de skill infer-conventions om de conventies van dit project vast te leggen." Lees de regels daarna na. Klopt een regel niet, of is het eigenlijk standaard Laravel? Schrap hem.

Stap 7: Skills op één plek in .agents/skills

Een skill is een map met een SKILL.md: een beschrijving en instructies voor één taak. De agent ziet bij de start alleen de naam en de beschrijving. De rest laadt hij pas als een taak erom vraagt. Zo kun je veel kennis toevoegen zonder je context te vullen.

Eén map voor alle agents

Skills volgen ook een open standaard: Agent Skills. Maar elke agent zoekt ze op een andere plek. Codex, OpenCode, Amp, Zed en Antigravity lezen .agents/skills. Dat is de gedeelde plek aan het worden. Claude Code leest alleen .claude/skills.

De oplossing: zet alle skills in .agents/skills en maak voor Claude Code een symlink.

mkdir -p .agents/skills .claude
ln -s ../.agents/skills .claude/skills

Gebruik je Boost? Laat Boost de skills voor Claude Code dan ook in .agents/skills zetten. Voeg daarvoor een regel toe aan config/boost.php:

'agents' => [
    'claude_code' => [
        'skills_path' => '.agents/skills',
    ],
],

Draai daarna php artisan boost:update. Alle skills staan nu op één plek, en elke agent vindt ze.

Een symlink werkt niet altijd goed op Windows. Werkt iemand in je team op Windows zonder WSL? Laat Boost dan voor elke agent een eigen map vullen.

Eigen skills

Je eigen skills zet je in .ai/skills. Boost linkt ze naar de map van elke agent. Een eigen skill is nuttig voor een workflow die vaak terugkomt, zoals een release voorbereiden of een nieuw type pagina bouwen.

Bestaande skills gebruiken

Voordat je zelf een skill schrijft: misschien bestaat hij al. Op skills.laravel.cloud staan meer dan duizend skills voor Laravel en PHP. Installeren gaat met Boost:

php artisan boost:add-skill eigenaar/repository --skill naam-van-de-skill

Wees wel kritisch:

  • Kijk eerst wat je al hebt. Boost en je packages leveren veel skills mee. Veel populaire skills herhalen basiskennis over Laravel die je agent al heeft.
  • Kies skills van package-auteurs. Een skill van Spatie over hun eigen package is waardevoller dan een algemene "Laravel expert"-skill.
  • Lees een skill voordat je hem installeert. Een skill kan scripts bevatten en je agent instructies geven. In een onderzoek van Snyk naar bijna 4.000 skills van ClawHub en skills.sh had 13% minstens één kritiek beveiligingsprobleem. Boost controleert skills bij installatie, maar lees ze toch zelf.
  • Houd alleen wat het gedrag van de agent verandert. Elke skill kost een beetje context, ook als hij niet gebruikt wordt.

Een goede skill van iemand anders is een prima startpunt. Pas hem aan je project aan. Een korte skill met jouw eigen afspraken werkt vaak beter dan een lange algemene.

Er zijn ook algemene skills die niet over Laravel gaan, maar over je werkwijze: plannen, testen en review. Die bespreken we in deel 2 van deze serie. Ook daarvoor geldt: lees ze eerst en houd alleen wat helpt.

Samen met je agent: vraag: "Zet de skills van dit project in .agents/skills, maak de symlink voor Claude Code en pas config/boost.php aan. Draai daarna boost:update en laat zien welke skills er zijn." Start een nieuwe sessie in Claude Code en vraag welke skills hij ziet.

Deel 2: Feedback die de agent zelf ophaalt

De agent weet nu hoe hij moet werken. In dit deel zorg je dat hij kan controleren of het gelukt is. Dat is het eerste advies in de best practices van Anthropic voor Claude Code: geef de agent een check die hij zelf kan draaien. Zonder die check ben jij de controle.

Stap 8: Automatische checks als vangnet

Drie tools vormen het vangnet: Pint, Larastan en Rector.

Laravel Pint

Pint zet je codestijl recht. Het staat al in elk nieuw Laravel-project. De agent hoeft geen stijlregels te onthouden; Pint lost het op.

Larastan

Larastan is PHPStan voor Laravel. Het vindt fouten zonder de code uit te voeren: een methode die niet bestaat, een verkeerd type, een vergeten null. Precies het soort fout dat een agent maakt.

composer require larastan/larastan --dev
# phpstan.neon
includes:
    - vendor/larastan/larastan/extension.neon

parameters:
    paths:
        - app/
    level: 5

Heeft je project al veel fouten? Maak een baseline met vendor/bin/phpstan analyse --generate-baseline en zet phpstan-baseline.neon onder includes in phpstan.neon. PHPStan negeert dan de fouten die er al zijn. Alleen nieuwe fouten tellen mee. Verhoog het level stap voor stap.

Rector

Rector herschrijft code automatisch. Met rector-laravel, de standaardset Laravel-regels voor Rector, houdt het je code actueel en conventioneel. Rector leest je Laravel-versie uit composer.json en past de regels toe die daarbij horen.

composer require rector/rector driftingly/rector-laravel --dev
// rector.php
use Rector\Config\RectorConfig;

return RectorConfig::configure()
    ->withPaths([__DIR__.'/app', __DIR__.'/tests'])
    ->withComposerBased(laravel: true)
    ->withPreparedSets(deadCode: true, codeQuality: true);

Eén commando voor alles

Geef de agent één commando dat alles controleert. Zet het in composer.json:

"scripts": {
    "fix": [
        "rector",
        "pint --parallel"
    ],
    "check": [
        "pint --test",
        "rector --dry-run",
        "phpstan analyse",
        "pest --parallel"
    ]
}

Noem composer check in je AGENTS.md, en draai precies hetzelfde commando in je CI. Dan weet de agent dat wat lokaal slaagt, ook in CI slaagt.

Compacte output met laravel/pao

De output van deze tools is gemaakt voor mensen: kleuren, voortgangsbalken, lange tabellen. Voor een agent is dat ruis die tokens kost. laravel/pao herkent wanneer een agent een tool draait. Dan geeft Pest, PHPUnit, PHPStan of Rector compacte JSON terug. Voor jou verandert er niets.

Nieuwe Laravel-projecten hebben PAO al. Bij een ouder project installeer je het zo:

composer require laravel/pao --dev

Samen met je agent: vraag: "Installeer Larastan, Rector met rector-laravel en laravel/pao. Maak de scripts fix en check in composer.json, voeg composer check toe aan AGENTS.md en zorg dat composer check slaagt. Maak een PHPStan-baseline als dat nodig is."

Stap 9: Archtests: conventies als test

Een conventie die je test, hoeft niet in AGENTS.md. Pest heeft daarvoor architectuurtests. Ze controleren de structuur van je code, niet het gedrag.

Begin met de presets van Pest:

// tests/Unit/ArchTest.php
arch()->preset()->php();
arch()->preset()->security();
arch()->preset()->laravel();

De laravel-preset controleert de conventies van Laravel, zoals dat controllers alleen in App\Http\Controllers staan en de juiste naam hebben. Hij vangt ook vergeten dd()-aanroepen. De andere presets vangen onder andere dump() en var_dump(), en onveilige functies zoals eval.

Daarna voeg je je eigen regels toe. Bijvoorbeeld voor een afspraak uit stap 6:

arch('Actions zijn invokable classes met de naam van een werkwoord, bijvoorbeeld CreateProject')
    ->expect('App\Actions')
    ->toHaveMethod('__invoke')
    ->toBeFinal();

Foutmeldingen die helpen

Faalt een test, dan leest de agent de foutmelding. Hoe beter die melding, hoe sneller hij het oplost. Zeg daarom in de naam van de test wat de bedoeling is, niet alleen wat er gecontroleerd wordt. "Actions zijn invokable classes met de naam van een werkwoord" helpt meer dan "actions test".

Een regel die je als archtest vastlegt, kun je uit .ai/rules halen. Een test controleert elke keer; een regel is een verzoek.

Samen met je agent: vraag: "Zet de regels uit .ai/rules die je als archtest in Pest kunt controleren om naar archtests. Gebruik testnamen die uitleggen wat de bedoeling is." Kijk daarna welke regels nog nodig zijn.

Stap 10: Snelle tests met Pest TIA

Tests zijn de beste check die er is. Maar een agent draait ze alleen als dat snel gaat. Een testsuite van tien minuten draait niemand na elke wijziging.

Pest 5 heeft daar een oplossing voor: TIA, test impact analysis. Pest houdt bij welke tests welke bestanden raken. Daarna draait het alleen de tests die door je wijziging geraakt worden. De resultaten van de andere tests komen uit de cache.

vendor/bin/pest --tia

De eerste run neemt de afhankelijkheden op. Daarvoor heb je PCOV of Xdebug nodig. Die eerste run is trager dan normaal. Daarna gaat het hard.

Wij maten het op de website van de DLF, met 289 tests:

Run Tijd
Normaal 121 seconden
Parallel (--parallel) 36 seconden
TIA, eerste run 182 seconden
TIA, daarna 0,5 seconde

TIA en --parallel kun je combineren: pest --parallel --tia. Bij een kleine wijziging maakt parallel weinig uit. Bij een grote wijziging, met veel geraakte tests, wel.

Wil je TIA altijd lokaal gebruiken, maar niet in CI? Zet dat in tests/Pest.php:

pest()->tia()->locally();

Dan gebruikt elke lokale pest-run TIA, ook zonder --tia. In CI draait de hele testsuite.

Let op de grenzen. Een wijziging in config/, in .env of in je routes laat alle tests opnieuw draaien. Pest kan daar niet zien welke tests ervan afhangen.

Let op: de testskill van Boost raadt aan PCOV uit te zetten, behalve als je coverage nodig hebt. TIA heeft coverage nodig, dus laat PCOV aan.

Test de tests: mutation testing

Een agent schrijft graag tests. Maar testen ze ook iets? Mutation testing controleert dat. Pest verandert kleine stukjes van je code, bijvoorbeeld een > in een >=. Faalt er dan geen test, dan test je die code niet echt.

Pest muteert alleen code die een test noemt. Zet daarom in je test welke class hij test:

covers(CreateProject::class);

Draai daarna:

vendor/bin/pest --mutate --parallel

Dit is te traag voor elke wijziging. Draai het af en toe, of in CI voor de belangrijke delen van je code.

Samen met je agent: vraag: "Zet Pest TIA aan voor lokaal gebruik en meet de tijd van een normale run en een run met --tia. Pas AGENTS.md aan zodat je tijdens het werk gewoon pest draait."

Stap 11: De agent laten kijken: browser en browsertests

Tests en statische analyse vinden veel. Maar of een pagina er goed uitziet en werkt, zie je pas in een browser. Een agent kan dat ook, op twee manieren.

Een agent-browser om te verkennen

Met een agent-browser opent de agent zelf je applicatie. Hij klikt, vult formulieren in, leest de console en maakt screenshots. Zo controleert hij zijn werk zoals jij dat zou doen.

Twee goede keuzes:

npm install -g @playwright/cli@latest
playwright-cli install --skills

Beide werken met Claude Code, Codex en andere agents. Ze geven de agent een compacte samenvatting van de pagina in plaats van een volledige screenshot. Dat scheelt veel tokens. Microsoft raadt voor coding agents zelf de CLI aan boven de MCP-server van Playwright, om dezelfde reden.

Werk je lokaal met HTTPS op een .test-domein? Beide tools hebben een optie om certificaatfouten te negeren.

Wat er achter de pagina gebeurt: Laravel Debugbar

Een pagina kan er goed uitzien en toch traag zijn. Bijvoorbeeld door dubbele queries, een N+1-probleem of één trage query. Dat zie je niet in de browser.

Veel Laravel-ontwikkelaars gebruiken Laravel Debugbar al. Minder bekend is dat je agent de data van Debugbar nu ook kan lezen. Debugbar bewaart van elke request de queries, exceptions en tijden. De agent zoekt daarin met Artisan:

php artisan debugbar:find --issues
php artisan debugbar:queries latest

--issues toont alleen requests met een probleem: een exception, een foutcode, mislukte, trage of dubbele queries, een N+1-probleem, veel queries, of een trage request. debugbar:queries laat per request zien welke queries dubbel zijn, welke een N+1-probleem vormen en waar ze in je code vandaan komen. Zo zoekt de agent de oorzaak in plaats van te gokken.

Debugbar levert een skill mee die de agent precies dit leert. Gebruik je Boost, dan zet je die aan als package-skill (stap 2). Zonder Boost installeer je hem met php artisan debugbar:install-skill.

Browsertests voor blijvende zekerheid

Een agent die klikt, controleert één keer. Een browsertest controleert elke keer. Pest heeft daar browser testing voor, gebouwd op Playwright.

composer require pestphp/pest-plugin-browser --dev
npm install playwright@latest
npx playwright install
it('toont de homepagina zonder fouten', function () {
    visit('/')
        ->assertSee('Welkom')
        ->assertNoSmoke();
});

assertNoSmoke() controleert dat er geen JavaScript-fouten of consolemeldingen zijn. Er is meer: screenshots vergelijken met assertScreenshotMatches(), testen op mobiel en in dark mode, en controleren op toegankelijkheid.

Pest start je applicatie zelf voor de test. Je lokale domein en HTTPS maken dus niet uit. En TIA werkt ook voor browsertests: een wijziging in je CSS draait alleen de browsertests opnieuw.

Snel iets controleren met pest --agent

Pest 5 heeft een plugin die beide werelden verbindt. Met --agent draait de agent een losse controle met dezelfde API als je tests:

composer require pestphp/pest-plugin-agent --dev
vendor/bin/pest --agent='visit("/")->on()->mobile()->screenshot(filename: "home-mobiel");'

Bevalt de controle? Dan maakt de agent er een echte test van.

Waarom tests beter zijn dan klikken

  • Elke keer hetzelfde resultaat. Het oordeel van een model wisselt; een test niet.
  • Ze draaien in CI, bij elke pull request, zonder model.
  • Ze beschermen later werk. Een fout die terugkomt, valt direct op.
  • Je betaalt één keer. Tokens voor het schrijven van de test, niet voor elke controle.

Gebruik de agent-browser om te verkennen en te debuggen. Leg wat werkt vast in een browsertest.

Samen met je agent: vraag: "Installeer de browserplugin van Pest en schrijf voor de drie belangrijkste pagina's een browsertest met assertNoSmoke(). Voeg aan AGENTS.md toe: elke wijziging aan de UI krijgt een browsertest."

Deel 3: Grenzen

Een instructie in AGENTS.md is een verzoek. De agent volgt het meestal, maar niet altijd. Voor wat altijd moet gebeuren, of nooit mag gebeuren, heb je harde grenzen nodig.

Stap 12: Hooks: checks afdwingen

Een hook is een commando dat de agent automatisch draait op een vast moment. Bijvoorbeeld na elke wijziging aan een bestand, of voordat hij zegt dat hij klaar is. De agent kan een hook niet vergeten of overslaan.

De voorbeelden hieronder zijn voor Claude Code. Andere agents, zoals Codex en Cursor, hebben vergelijkbare hooks.

Pint na elke wijziging

Deze hook draait Pint op elk PHP-bestand dat de agent wijzigt. Zet hem in .claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | grep '\\.php$' | xargs -r \"$CLAUDE_PROJECT_DIR\"/vendor/bin/pint"
          }
        ]
      }
    ]
  }
}

composer check voordat de agent stopt

Deze hook draait composer check als de agent klaar denkt te zijn. Faalt de check, dan krijgt de agent de fouten te zien en werkt hij verder. Maak het script .claude/hooks/check.sh:

#!/bin/bash
INPUT=$(cat)

# Is de agent al eens teruggestuurd? Laat hem dan stoppen, om een lus te voorkomen.
if [ "$(echo "$INPUT" | jq -r '.stop_hook_active')" = "true" ]; then
  exit 0
fi

composer check >&2 || exit 2

Maak het uitvoerbaar met chmod +x .claude/hooks/check.sh en voeg het toe aan hooks in .claude/settings.json, naast PostToolUse:

"Stop": [
  {
    "hooks": [
      {
        "type": "command",
        "command": "\"$CLAUDE_PROJECT_DIR\"/.claude/hooks/check.sh"
      }
    ]
  }
]

Exit code 2 betekent: niet stoppen. Wat het script naar stderr schrijft, krijgt de agent te zien. Met laravel/pao uit stap 8 is dat compacte output.

Is composer check traag? Gebruik in de hook dan pest --tia in plaats van de volledige testsuite.

Samen met je agent: vraag: "Voeg de hooks voor Pint en composer check toe aan .claude/settings.json." Test het daarna: laat de agent een kleine wijziging maken met een opzettelijke fout, en kijk of hij die zelf oplost.

Stap 13: Permissies en secrets

Een agent werkt met jouw rechten. Hij kan je .env lezen, met je productiedatabase praten en met je API-sleutels betalen. Leg daarom vast wat hij wel en niet mag.

Permissies in de repository

In Claude Code zet je permissies in .claude/settings.json. Commit dat bestand, dan geldt het voor iedereen in je team:

{
  "permissions": {
    "allow": [
      "Bash(composer check)",
      "Bash(vendor/bin/pest *)",
      "Bash(php artisan make*)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./.env.*)"
    ]
  }
}

Met allow hoeft de agent niet te vragen voor veilige commando's. Dat scheelt jou klikken en hem wachten. Met deny blokkeer je wat hij nooit mag. Persoonlijke instellingen horen in .claude/settings.local.json; dat bestand commit je niet.

De deny-regels blokkeren de eigen tools van de agent en bekende commando's zoals cat .env. Maar een script of grep -r kan het bestand nog steeds lezen. Wil je zeker weten dat de agent niet bij je secrets kan? Gebruik dan de sandbox van Claude Code, of laat de agent in een container werken.

Secrets

  • Geef de agent alleen test- en sandboxsleutels, nooit sleutels voor productie.
  • Zet een limiet op API-sleutels die geld kosten.
  • Laat een agent die zonder toezicht werkt, altijd in een sandbox of container draaien.

Samen met je agent: vraag: "Maak .claude/settings.json met permissies voor de commando's die je in dit project vaak draait, en blokkeer het lezen van .env." Lees het resultaat na voordat je het commit.

Stap 14: Up-to-date en veilig blijven

Boost bijwerken

Na een composer update kunnen er nieuwe versies van je packages zijn, met nieuwe guidelines. Laat Boost die automatisch bijwerken. Zet dit in composer.json:

"scripts": {
    "post-update-cmd": [
        "@php artisan boost:update --ansi"
    ]
}

boost:update werkt alleen bij wat je al hebt aangezet. Installeer je een nieuwe package met eigen guidelines of skills? Draai dan eenmalig php artisan boost:update --discover.

Packages controleren met laravel/vet

Een agent installeert packages makkelijk. Dat maakt je project kwetsbaarder voor aanvallen via packages: een kwaadaardige nieuwe versie van een populaire package, of een package met een naam die op een bekende package lijkt.

laravel/vet helpt daartegen. Het is nog in bèta. Vet toont wat een composer update in je vendor-map verandert, en laat op jouw verzoek een agent elke nieuwe of gewijzigde package nalezen. Met minimum-release-age installeer je alleen versies die al een paar dagen oud zijn. Een kwaadaardige versie is dan meestal al ontdekt en verwijderd.

composer require laravel/vet --dev
vendor/bin/vet --init --minimum-release-age=7

Vet heeft PHP 8.4 of hoger nodig.

Wat commit je?

Commit Niet committen
AGENTS.md .claude/settings.local.json
boost.json en config/boost.php .env
.ai/ (guidelines, rules, skills)
.agents/skills en de symlink .claude/skills
.claude/settings.json en .claude/hooks/
.mcp.json

Boost kan AGENTS.md, boost.json en .mcp.json altijd opnieuw genereren. Sommige teams zetten ze daarom in .gitignore. Maar staat er eigen tekst in je AGENTS.md, commit hem dan. En met alles in git heeft iedereen in je team, en elke agent, direct dezelfde setup.

Samen met je agent: vraag: "Voeg boost:update toe aan post-update-cmd en controleer of alle bestanden uit de tabel goed in git of in .gitignore staan."

Deel 4: Werkwijze

Stap 15: Eén commando om te starten

Een agent die je applicatie wil testen, moet weten hoe die draait. Maak dat makkelijk:

  • Eén commando om alles te starten. Nieuwe Laravel-projecten hebben composer run dev. Dat start de server, de queue, de logs en Vite in één keer.
  • Of een vaste URL. Gebruik je Laravel Herd of een andere lokale omgeving, dan draait je app al. Zet de URL in AGENTS.md, met de instructie geen eigen server te starten. Zo voorkom je dat de agent een tweede server start.
  • Logs die de agent kan lezen. Laravel schrijft naar storage/logs/laravel.log. Boost leest die met Read Log Entries, en fouten uit de browser met Browser Logs.
  • Realistische testdata. Goede factories en seeders laten de agent testen met data die op productie lijkt. Zonder data test hij lege pagina's.

Stap 16: Meerdere agents tegelijk

Wil je meerdere agents tegelijk laten werken, elk aan een eigen feature? Dat kan met git worktrees: meerdere checkouts van dezelfde repository, elk op een eigen branch.

git worktree add ../mijn-project-zoekfunctie -b zoekfunctie

Maar een worktree alleen is niet genoeg. Twee agents die dezelfde database gebruiken, zitten elkaar in de weg. Elke worktree heeft nodig:

  • een eigen .env
  • een eigen database. Een SQLite-bestand per worktree is de simpelste oplossing.
  • een eigen URL, zodat een agent-browser de juiste versie test

Dan kan elke agent zijn eigen werk controleren, zonder dat van een ander te breken.

Stap 17: Minder tokens verbruiken

Tokens kosten geld en tijd. Je bespaart al veel met een korte AGENTS.md, skills die pas laden als ze nodig zijn, en compacte output van je tools met laravel/pao. Met een paar instellingen bespaar je nog meer, vooral op wat de agent zelf schrijft.

Meet eerst

Kijk eerst waar je tokens heen gaan. In Claude Code zie je dat met /usage en /context. ccusage leest de logs van Claude Code, Codex, OpenCode en andere agents, en toont je verbruik per dag of per sessie:

npx ccusage@latest

Meet opnieuw na elke wijziging. Dan weet je of die echt iets oplevert.

Laat de agent niet harder denken dan nodig

Het denkwerk van een model telt als output. Bij een hoge effort-instelling kost dat per vraag al snel tienduizenden tokens. Zet de standaard op medium, en verhoog hem alleen voor een lastige taak.

In Claude Code zet je dit in ~/.claude/settings.json:

{
  "effortLevel": "medium"
}

In Codex zet je dit in ~/.codex/config.toml:

model_reasoning_effort = "medium"
model_verbosity = "low"

Lager is niet altijd goedkoper. Denkt de agent te weinig, dan heeft hij soms meer beurten nodig.

Kortere antwoorden

Veel output is tekst rond het werk: een inleiding, uitleg over wat de agent gaat doen, een samenvatting achteraf. Claude Code heeft daarvoor de output style Concise. De agent begint dan met het resultaat en laat de rest weg. Het werk zelf doet hij net zo grondig. Foutmeldingen en waarschuwingen blijven volledig.

{
  "outputStyle": "Concise"
}

Gebruik je een andere agent? Vraag hem dan in AGENTS.md om kort te antwoorden.

Misschien ken je Caveman al. Die skill laat de agent praten als een holbewoner, en /caveman-commit schrijft commitberichten van één regel. Code laat hij met rust. Caveman is erg populair, maar de besparing valt tegen. In een test van JetBrains daalde de output met 8,5%, zonder verlies aan kwaliteit. De makers hebben hun eerdere claim van 65% zelf ingetrokken. Een agent schrijft vooral code en roept tools aan, en daar verandert een korte schrijfstijl weinig aan.

Een kleiner model voor subagents

Een subagent doet een deeltaak in een eigen context, zoals zoeken in je code. Alleen zijn samenvatting komt terug in je sessie. Laat subagents in Claude Code een kleiner model gebruiken:

export CLAUDE_CODE_SUBAGENT_MODEL=haiku

Begin elke taak met een schone sessie

Een lange sessie stuurt bij elke vraag de hele geschiedenis mee. Begin daarom een nieuwe taak met /clear.

Geloof de percentages niet

Veel tools beloven grote besparingen. RTK belooft bijvoorbeeld 60 tot 90% minder output van commando's. In een andere test van JetBrains werd een sessie met RTK bij een lage effort juist 7,6% duurder. Voor Pest, PHPStan en Rector doet laravel/pao al hetzelfde. Meet dus altijd zelf.

Samen met je agent: draai npx ccusage@latest en noteer je verbruik. Vraag de agent daarna: "Zet in ~/.claude/settings.json de effort op medium en de output style op Concise." Meet na een week opnieuw.

Controleren en afronden

Na alle stappen ziet je project er zo uit:

mijn-project/
├── .agents/
│   └── skills/          # alle skills, voor elke agent
├── .ai/
│   ├── guidelines/      # eigen guidelines (spaarzaam)
│   ├── rules/           # projectregels
│   └── skills/          # eigen skills
├── .claude/
│   ├── hooks/
│   │   └── check.sh
│   ├── settings.json    # hooks en permissies
│   └── skills -> ../.agents/skills
├── config/boost.php
├── tests/
│   ├── Browser/         # browsertests
│   └── Unit/ArchTest.php
├── AGENTS.md            # kort, met je commando's en grenzen
├── boost.json
├── .mcp.json
├── phpstan.neon
├── rector.php
└── composer.json        # scripts: fix, check, post-update-cmd

Een test voor je setup

Geef de agent een kleine, echte taak:

"Voeg aan de projectenpagina een zoekveld toe. Schrijf er een featuretest en een browsertest bij, en zorg dat composer check slaagt."

Let op wat de agent doet. Zoekt hij de juiste documentatie op met Boost? Maakt hij een Form Request in plaats van een eigen oplossing? Draait hij zelf de checks en lost hij de fouten op? Dan werkt je setup.

Gaat er iets mis? Dat is waardevolle informatie. Leg de oplossing vast: als test, als check, als projectregel of, als laatste redmiddel, als regel in AGENTS.md.

Checklist

  • Laravel Boost geïnstalleerd, met MCP-server, guidelines en skills
  • Package guidelines aangezet voor je belangrijkste packages
  • CLAUDE.md vervangen door één AGENTS.md
  • AGENTS.md kort: commando's, afwijkingen en grenzen
  • Projectregels vastgelegd in .ai/rules
  • Skills in .agents/skills, met een symlink voor Claude Code
  • Pint, Larastan en Rector in één composer check
  • laravel/pao geïnstalleerd
  • Archtests voor je conventies
  • Pest TIA aan voor lokaal gebruik
  • Een agent-browser en browsertests met Pest
  • Laravel Debugbar met de skill voor je agent
  • Hooks voor Pint en composer check
  • Permissies in .claude/settings.json, zonder toegang tot .env
  • boost:update na elke composer update
  • Je tokenverbruik gemeten, met effort op medium en korte antwoorden

Een goed ingericht project is nooit af. Modellen worden beter, tools veranderen en je leert zelf wat werkt. Kijk elke paar maanden opnieuw naar je setup, en schrap wat niet meer nodig is.

Je project is nu klaar. In deel 2, dat binnenkort verschijnt, gaan we dieper in op hoe je er gestructureerd features mee bouwt: met een plan, vastgelegde beslissingen in ADR's, skills als die van Superpowers en Matt Pocock, en een frisse review van het resultaat. We kijken ook naar agentic development environments: tools waarin je met meerdere agents tegelijk aan je project werkt.

Meer lezen

Voor elk project

Werk je vooral met Claude Code?

Werk je vooral met Codex?

Werk je met React?

Laravel en Pest

Over de auteur
Nick Retel

Nick Retel

Freelance developer

Nick Retel is een freelance developer en bestuurslid van de Dutch Laravel Foundation