Every Laravel developer knows the ritual. A new idea, a new folder, and then two hours of yak-shaving: the right PHP version, an extension that refuses to compile, a MySQL socket in the wrong place, a Redis instance you installed three projects ago and never upgraded, a mail catcher, a self-signed certificate, an entry in /etc/hosts. By the time you write your first migration, the enthusiasm is gone.

INIT exists to delete that afternoon from your life. It initializes a complete Laravel + Filament working environment on Docker, so the first command you actually care about — the one that creates a model — is also the first command you type.

This article covers what INIT sets up for you, why running your local stack in containers is a stability and security decision rather than a fashion statement, and how Larapilot, which ships with INIT, turns your AI coding agent from an enthusiastic intern into something closer to a delivery team.


What INIT actually does

INIT is a project initializer, not a framework and not a dependency you carry into production. You run it once, at the very beginning, and it leaves you with a project directory containing a working Laravel application, a Filament panel, and a containerized service stack already wired together.

# Bootstrap a new project
curl -fsSL https://init.web.ap.it/go.sh > go.sh && sh go.sh

What you get out of it:

Component Why it's there
Laravel Latest stable release, already installed and configured
Filament Admin panel installed and reachable, not a TODO for next week
MySQL Isolated per project, no shared instance to corrupt
Redis Cache, sessions, and queues behave locally like they do in production
Mailpit Every outbound mail caught in a browser inbox instead of a real one
Reverse proxy + TLS Real HTTPS on a real hostname, so cookies, Secure flags, and OAuth callbacks behave
Wildcard local domains Project URLs that resolve to 127.0.0.1 without touching /etc/hosts

That last point is worth pausing on. Local DNS is one of the pettiest, most persistent annoyances in web development: you either edit a system file with sudo for every project, or you install a DNS resolver you don't understand and hope it survives the next OS update. INIT sidesteps the problem entirely by using a wildcard domain that already resolves to loopback, then terminating TLS in the proxy. No sudo, no resolver, no expired certificate on a Monday morning.


Why Docker is the stability argument

"Works on my machine" is not a joke about developers — it's a description of an environment that nobody wrote down. The moment your local stack lives in compose.yaml next to your code, three things change.

1. The environment becomes reviewable

PHP version, extensions, MySQL version, Redis version, proxy configuration: all of it is text, all of it is in Git, all of it goes through pull requests. When production breaks because of a PHP minor version, you can git log the file that describes it. Homebrew has no changelog for your laptop.

2. Projects stop fighting each other

A legacy client app pinned to PHP 8.1 and a greenfield project on PHP 8.4 can run at the same time, each with its own MySQL, its own Redis, its own extensions. Nothing is global, so nothing is a shared point of failure. Upgrading one project cannot break another — a guarantee you simply cannot make with system-wide packages.

3. Onboarding stops being a document

A new teammate clones the repository and starts containers. There is no wiki page listing seventeen brew install commands, half of which are outdated. Reproducibility is not a nice-to-have here: it is the difference between a bug you can reproduce and a bug you argue about in Slack.

And when a project ends, it ends. You stop the containers, delete the volumes, and your machine is exactly as clean as before. No orphaned database with client data sitting on your SSD for three years.


Why Docker is also the security argument

The stability case for containers is well rehearsed. The security case gets mentioned less often, and it matters more than most developers assume — especially for consultants and freelancers who hold client data on a laptop that travels.

Services are not exposed by default. A MySQL installed with a package manager listens on your machine, often with a password you chose during a project in 2019 and reused ever since. In a compose stack, the database is reachable on a private network by the application container and published to the host only if you explicitly say so. The blast radius of a badly configured service shrinks to a single project.

Client data is compartmentalized. Each project gets its own database in its own volume. A mistaken DB_DATABASE value in a .env file cannot point you at another client's production dump, because that dump isn't in the same server instance to begin with. For anyone working under a DPA or handling personal data, this compartmentalization is not paranoia — it is the difference between an incident and a non-event.

Mail never escapes. Mailpit catches everything. A seeder that generates ten thousand users with real-looking addresses cannot accidentally email ten thousand strangers, because nothing in the stack can reach an SMTP relay on the internet.

Dependencies are pinned and disposable. A compromised or abandoned system package is a problem you carry for years. A compromised image tag is a problem you fix by changing one line and rebuilding. Containers make your runtime supply chain something you can actually audit, roll forward, and roll back.

Local HTTPS is real HTTPS. Developing on plain HTTP and deploying to TLS is how you discover SameSite cookie bugs, mixed-content warnings, and broken OAuth redirects in staging instead of on your laptop. INIT gives you certificates from the first minute, which means the security-relevant parts of your application are exercised from the first minute too.


The part where AI stops guessing: Larapilot

INIT ships with Larapilot, and this is what turns a clean environment into a productive one.

Most AI-assisted development fails the same way: you write a paragraph of prompt, the agent writes four hundred lines of plausible code, and you spend the afternoon working out which of its assumptions you disagree with. The problem isn't the model. The problem is that there is no artifact between "an idea" and "a diff" — no requirements, no acceptance criteria, no plan, nothing to review against.

Larapilot inserts that missing layer. It's a spec-driven workflow built on top of Laravel Boost, exposed as /larapilot-* skills you run directly in your editor — Claude Code, Cursor, VS Code, or any MCP-capable agent.

Three layers

  1. Skills/larapilot-* prompts published through Laravel Boost. You invoke them; the agent follows a defined execution contract instead of improvising.
  2. Artifacts — a .larapilot/ directory committed to your repository: PRD, backlog, specs, plans, review notes. Durable state the agent reloads at every activation, and that your teammates can read in a pull request.
  3. CLIphp artisan larapilot:* commands the skills call under the hood to persist files and enforce status transitions. You rarely type these yourself.

The loop

/larapilot-inception "…"   →  guided product interview, produces a PRD with MoSCoW-tagged requirements
/larapilot-spec            →  maps requirements to user stories in backlog.yaml + specs/US-XXX.yaml
/larapilot-plan US-001     →  technical plan with tasks and test strategy   (TODO → PLANNED)
/larapilot-implement US-001→  Laravel code, Pest tests, one commit per task (PLANNED → REVIEW)
/larapilot-review US-001   →  you approve, or send it back with feedback    (REVIEW → DONE)

The state machine is enforced: you cannot implement before planning, and you cannot reach DONE without passing the human gate. The agent proposes, you approve what ships. If you reject a review, the story returns to TODO with your feedback attached, and the agent replans against it.

For a story that turned out to be four stories, /larapilot-design produces static HTML mockups from a packaged design system — Filament, Laravel Starter Kit, Bootstrap 5, Tailwind, or AdminLTE — before any Blade file is written. On an existing product, /larapilot-feature "…" runs a mini inception for a single capability, and /larapilot-bug "…" triages a defect and routes it to a fix spec or a rework of the story that introduced it.

Why the artifacts matter more than the prompts

Because they are in Git. Six months later, when someone asks why invoices are numbered per fiscal year, the answer is in the PRD, next to the story that implemented it, next to the plan that described the tasks, next to the commits that carry them. Spec-driven development isn't primarily about making the agent smarter — it's about making its output reviewable and its reasoning survivable.

Project modes, because not every project deserves the same ceremony

/larapilot-settings persists five knobs in .larapilot/config.yaml:

  • effortECO, STANDARD, or MAX (how deep the agent goes, how many sub-agents it spawns)
  • backlog granularityLEAN, STANDARD, or GRANULAR (one spec per user journey, per capability, or per requirement)
  • git modeNO_GITFLOW, GITFLOW (feature branches, atomic conventional commits, no automatic push — the default), or GITFLOW_PUSH
  • testingMINIMAL, NORMAL, or BEST (the last one adds browser E2E, viewport matrix, axe, Lighthouse)
  • auto-approve — off by default, because the human gate is the point

A weekend side project and a client ERP rewrite are not the same job, and Larapilot lets you say so once instead of arguing with the agent every session.

When the team is bigger than you

Three integrations exist precisely because real projects have stakeholders who never open a YAML file:

  • Dashboard — a read-only board at /larapilot in your local app: kanban backlog, rendered PRD, spec detail with mockups and internal feedback. Disabled in production by design.
  • Project trackers — mirror the backlog into Linear, Jira, Asana, Trello, ClickUp, or Monday. Stories become issues, plan tasks become native subtasks. Push is authoritative; pull only reports drift until you pass --apply, and a status of DONE is never accepted from a tracker, because DONE is a human review gate.
  • Backstage — publish the repository as a catalog entity with TechDocs generated from the PRD and backlog, for organizations that already run a developer portal.

The rule across all of them is the same: .larapilot/ is the source of truth, and everything else is a window onto it. Scope changes go through inception, feature, or the PRD living document — never through a card someone dragged in a tracker.


Putting it together: a realistic first hour

# 1 — Environment
curl -fsSL https://init.web.ap.it/go.sh > go.sh && sh go.sh
# Laravel + Filament + MySQL + Redis + Mailpit + HTTPS, running

# 2 — AI workflow (bundled with INIT; these are the commands behind it)
composer require andreapollastri/larapilot --dev
php artisan larapilot:install
php artisan boost:install

# 3 — Product
# In your editor:
#   /larapilot-inception "A booking tool for small clinics: patients, appointments, staff"
#   /larapilot-spec
#   /larapilot-plan US-001
#   /larapilot-implement US-001
#   /larapilot-review US-001

Requirements for the Larapilot side: PHP 8.3+, Laravel 12+, Laravel Boost 2.0+, and an MCP-capable editor. Run php artisan larapilot:doctor if anything looks off.

An hour in, you have a running HTTPS application, a database nobody else can reach, a product requirements document your client could actually read, a backlog traced to those requirements, and the first story implemented with Pest tests and reviewed by a human — you.


The through-line

The three pieces solve the same problem at different altitudes.

Docker removes ambiguity from your runtime: what PHP, what MySQL, what network, written down and version-controlled. INIT removes ambiguity from your setup: one command instead of a wiki page, identical on every machine in the team. Larapilot removes ambiguity from your intent: what the software is supposed to do, written before the code and reviewed after it.

None of this makes you a faster typist. It makes the boring parts deterministic, which is the only kind of speed that survives contact with a real project.


Links