larapilot.v2.4.2

From product idea to reviewed Laravel code.

Spec-driven workflow for Laravel — integrated with Laravel Boost. Thirty personas, fifteen skills, apps and packages — install, enable MCP, run /larapilot-* in your editor.

The agent proposes. You approve what ships. Human-in-the-loop, always.

Install in 3 commands

Add Larapilot to your Laravel app, scaffold the .larapilot/ workspace, and publish the /larapilot-* skills via Laravel Boost.

Terminal
  1. composer require andreapollastri/larapilot --dev
  2. php artisan larapilot:install
  3. php artisan boost:install
After install — code quality gate (v2.3.1+)
  1. php artisan larapilot:quality

Requires: PHP 8.3+ · Laravel 12+ · Laravel Boost 2.0+ (bundled) · MCP-capable editor/agent (Claude Code, VS Code, Cursor, etc.)

larapilot:install also scaffolds Larastan (level 5+) and Laravel Pintphpstan.neon.dist, pint.json, Composer scripts, and dev dependencies. Run php artisan larapilot:quality before merge; see Code quality.

Already on Boost without a fresh install? Run php artisan boost:update --discover once to pick up new skills.

Upgrade

After a new Larapilot release — pull the package with Composer, then refresh project assets with Artisan. Details: Upgrade.

Terminal
  1. composer update andreapollastri/larapilot
  2. php artisan larapilot:update

Verify with php artisan larapilot:doctor. Runtime-only refresh (skip Boost republish): php artisan larapilot:update --skip-boost.

First run

/larapilot-inception "your idea". Full walkthrough: new product example.

How to use

Run /larapilot-* skills in your editor. Each skill orchestrates the conversation; artifacts land in .larapilot/ and status transitions are enforced automatically.

Greenfield — repeat steps 3–5 per story
/larapilot-inception "…" /larapilot-spec /larapilot-plan US-XXX /larapilot-implement US-XXX /larapilot-review US-XXX

Optional: /larapilot-design before plan · /larapilot-ship when all MVP stories are DONE · /larapilot-autopilot to batch plan+implement · /larapilot-settings for project modes · /larapilot-usage for Lucille time/token reports · /larapilot-backstage to publish into a developer portal · /larapilot-tracker to mirror the backlog into a project tracker.

Project modes via /larapilot-settings: effort, backlog, git mode, testing, auto-approve, lucille, optional github / gitlab / bitbucket and notifications — persisted in .larapilot/config.yaml. Default Gitflow is without auto-push; Playwright/E2E only when testing is BEST. Lucille is ON by default (OFF automatically on ECO). Settings · Usage · Integrations · Branch conventions.

When Start with
New product, site, app, PHP/Laravel package, pivot, or legacy rewrite /larapilot-inception
One new capability on existing product /larapilot-feature "…"
Defect or regression /larapilot-bug "…"
Time/token spend, deadlines, Gantt /larapilot-usage

MCP: Laravel Boost (docs, schema, Tinker) + Larapilot (workflow). Walkthroughs: seven examples. Squad: 30 personas.

Use cases

New product

/larapilot-inception

Laravel 13 greenfield — task board with registration, projects, assignable tasks. One sentence in, PRD + backlog + code out.

Your editor
/larapilot-inception "I want a simple team task board: registration, projects, and assignable tasks."

Mark runs 3 AskQuestion rounds (max 3 questions each, skippable).

💎 Mark: Let's shape the MVP — who is this for and what kind of product is it?

AskQuestion — Round 1 (product kind)
  1. Project Kind: Application · Website · Personal · Package
  2. Audience: Small dev teams · Agencies · Solo founders
  3. Competitors in mind: Trello/Asana · Linear · None — greenfield

You pick: Application, Small dev teams (2–10), Trello/Asana.

AskQuestion — Round 2 (MVP scope)
  1. MVP features: Register + projects + tasks · + Kanban view · + Notifications
  2. Auth: Email + password · + Magic link · SSO later
  3. Delivery target: MVP · V1 Complete · Full Product

You pick: Register + projects + tasks, Email + password (no SSO for now), MVP.

AskQuestion — Round 3 (topology, stack & panel)
  1. Frontend Topology: Laravel-coupled · SPA-in-Laravel · API + external frontend
  2. Authenticated UI (in this repo): Laravel Starter Kit · Filament · AdminLTE · Bootstrap 5 · Tailwind CSS · Custom
  3. Budget sensitivity: Tracked · Relaxed

You pick: Laravel-coupled, Laravel Starter Kit, Tracked.

📐 John + ✨ Joe: Coupled Blade/Inertia UI in this repo — Starter Kit + session auth fits Laravel 13 out of the box. Filament stays a Future Phase option for ops.

💎 Mark: Drafting the PRD — each functional requirement gets a MoSCoW tag.

PRD.md (excerpt)
**Project Kind:** Application
**Delivery Target:** MVP
**Frontend Topology:** Laravel-coupled
**Stack:** Laravel 13 · Laravel Starter Kit · Pest

### FR-001: User registration with email and password
**MoSCoW:** Must

### FR-002: Project CRUD for team members
**MoSCoW:** Must

### FR-003: Task assignment within projects
**MoSCoW:** Must

### FR-004: SSO via Google Workspace
**MoSCoW:** Won't
Your editor
/larapilot-spec

Tom maps Must FRs to MVP stories; Won't skipped.

backlog.yaml (excerpt)
specs:
  - code: US-001
    title: User Registration
    status: TODO
  - code: US-002
    title: Project Management
    status: TODO
  - code: US-003
    title: Task Assignment
    status: TODO
Your editor — optional
/larapilot-design US-001

Static HTML mockup from the PRD-chosen packaged design system (design-systems/filament/, starter-kit/, bootstrap-5/, tailwind/, or adminlte/). Preview at /mockups/US-001 — and in the dashboard on the US detail page (embedded preview + screen links).

Your editor — US-001
/larapilot-plan US-001
/larapilot-implement US-001
/larapilot-review US-001
Prompt Status change What lands
/larapilot-plan US-001 TODOPLANNED plans/US-001-plan.yaml
/larapilot-implement US-001 PLANNEDREVIEW User model, RegisterController, Blade view, Pest tests
/larapilot-review US-001 REVIEWDONE You approve — or send back with feedback
Laravel 13 app (US-001)
database/migrations/xxxx_create_users_table.php
app/Models/User.php
app/Http/Controllers/RegisterController.php
app/Http/Requests/RegisterRequest.php
resources/views/auth/register.blade.php
routes/web.php
tests/Feature/RegistrationTest.php
Story Prompts What gets implemented
US-002 Projects planimplementreview Project model, CRUD, policies, Pest tests
US-003 Tasks planimplementreview Task model, assignment, board view, tests
Your editor — optional batch
/larapilot-autopilot US-002 US-003

Chains plan + implement — you still run /larapilot-review per spec.

Your editor — when all MVP stories are DONE
/larapilot-ship
You do
Answer wizard rounds; run spec loop per story; approve reviews
Agent does
PRD → backlog → plans → Laravel code + tests under .larapilot/
Next step
Repeat for US-002, US-003 — then /larapilot-ship

Laravel package

/larapilot-inception · Project Kind Package

First-class Composer package workflow — provider, public API, Pest matrix, CI, semver, Packagist/Satis. UI mockups stay off unless the package ships Blade/Livewire/Filament.

Your editor
/larapilot-inception "Laravel package that adds signed webhook delivery with retries and a publishable config."

💎 Mark: Package kind — greenfield or wrapping existing code?

AskQuestion — Package origin & delivery
  1. Project Kind: Application · Website · Personal · Package
  2. Package Origin: New · Existing local · Existing git
  3. Delivery target: MVP · V1 Complete · Full Product

You pick: Package, New, MVP.

👾 Andrew + 📐 John: Namespace, Service Provider, config publish, and public API surface before backlog.

🗄️ Mike: Optional migrations only if the package owns schema; otherwise document host-app tables.

⌨️ Sarah: CI matrix (PHP/Laravel) + release scripts; Artisan doctor/publish commands when useful.

📒 Lucille: Any Packagist / demo deadline? (skippable)

PRD.md (excerpt)
**Project Kind:** Package
**Package Origin:** New
**Delivery Target:** MVP

### Package
**Name:** acme/webhooks
**Distribution:** Packagist
**Consumer install:** composer require acme/webhooks

### FR-001: Publishable config + Service Provider
**MoSCoW:** Must

### FR-002: Signed outbound webhook client with retries
**MoSCoW:** Must

### FR-003: Pest feature tests + GitHub Actions matrix
**MoSCoW:** Must

Then the same loop: /larapilot-spec (package-surface stories first) → plan → implement → review → /larapilot-ship with Packagist/semver checklist. Skip /larapilot-design unless the package ships UI.

You do
Confirm origin, name, distribution, and consumer install mode
Agent does
Package layout, tests, CI YAML (Sarah), docs (Albert), optional migrations (Mike)
Next step
/larapilot-ship — tag, CHANGELOG, publish notes

Legacy porting

/larapilot-inception

15-year PHP ERP in .larapilot/legacy/ — rewrite on Laravel 12 + Filament, zero feature/data loss, phased cutover.

Prep — before inception
.larapilot/legacy/
  SOURCE.md              # repo URL + tag
  schema.sql             # sanitized dump
  app/                   # legacy PHP codebase snapshot
Your editor
/larapilot-inception "Rewrite our legacy ERP to Laravel — keep customers, orders, warehouse, and e-invoicing"

Mark + Sabrine scan legacy/ first, then ask about rewrite approach and scope.

💎 Mark: I see a legacy ERP snapshot in .larapilot/legacy/. Before we dive into architecture — how should we treat it?

AskQuestion — Round 1 (project origin)
  1. Approach: Legacy rewrite · Legacy port · Partial modules only · Reference only · Decide later
  2. Cutover style: Big-bang · Phased by module · Parallel run · Unsure
  3. Data in scope: Full history · Last 24 months · Master data only · Decide in chat

You pick: Legacy rewrite, Phased by module, Full history (orders, invoices, stock movements must migrate).

🔄 Sabrine: I mapped five modules — anagrafica, ordini, magazzino, fatturazione, report. Warehouse and e-invoicing touch 40+ legacy tables and ~12k uploaded PDF/XML files.

AskQuestion — Round 2 (scope & delivery)
  1. Project Kind: Application · Website · Personal · Package
  2. Phase 1 modules: Customers + orders · + Warehouse · + E-invoicing · All five
  3. Delivery target: MVP · V1 Complete · Full Product · Enterprise

You pick: Application, Customers + orders (warehouse and e-invoicing in Phase 2), MVP.

AskQuestion — Round 3 (admin & stack)
  1. Admin panel: Filament · AdminLTE · Laravel Starter Kit · Bootstrap 5 · Custom panel
  2. Multi-tenancy: Single company · Multi-company (row-level) · DB per tenant
  3. Budget sensitivity: Tracked · Relaxed

You pick: Filament, Multi-company (row-level), Tracked.

📐 John: Row-level tenancy fits the legacy company_id pattern. Matt will ETL from MySQL; Sabrine owns assets under /uploads/fatture/.

PRD records Project Origin: Legacy rewrite + parity matrix. Migration specs come first on /larapilot-spec.

PRD.md (excerpt)
**Project Origin:** Legacy rewrite
**Delivery Target:** MVP
**Project Kind:** Application

### In Scope (Phase 1 — MVP)
- FR-001: Customer master data (parity with legacy anagrafica)
- FR-002: Sales orders — create, edit, status workflow
- FR-003: Multi-company access (row-level, legacy company_id)

### Future Phases
- FR-010: Warehouse / stock (legacy magazzino — Phase 2)
- FR-011: Italian e-invoicing SDI (legacy fatturazione — Phase 2)
- FR-012: Accounting reports (legacy report — Phase 3)

### Legacy parity
- Matrix: `.larapilot/research/legacy-parity.md`
- Assets: migrate `/uploads/fatture/` in Phase 2 with e-invoicing
.larapilot/research/legacy-parity.md (excerpt)
| Legacy module | Current impl | New impl | Migration | Status |
| --- | --- | --- | --- | --- |
| Anagrafica clienti | PHP forms + `clienti` table | Filament CustomerResource | ETL `clienti` → `customers` | preserve |
| Ordini vendita | Custom MVC + 8 status codes | Order model + Filament | Map statuses 1:1 | preserve |
| Magazzino | Stock tables + manual adjustments | — | Phase 2 | defer |
| Fatturazione SDI | XML + PDF generation | — | Phase 2 + assets port | defer |

On /larapilot-spec, Tom bootstraps migration specs first.

specs/US-001.yaml (excerpt — first story)
code: US-001
title: "Legacy schema analysis and ETL plan"
priority: HIGH
status: TODO
body: |
  #### US-001: Legacy schema analysis and ETL plan

  **Epic:** EP-001 Legacy migration | **Priority:** HIGH | **Points:** 5
  **Type:** Migration | **Traces to:** Legacy parity (anagrafica + ordini)

  **User Story**
  As a developer,
  I want a documented ETL plan from legacy MySQL to Laravel,
  so that customer and order data migrates without loss.

  **Acceptance Criteria**
  - [ ] Field-level mapping `clienti` → `customers`, `ordini` → `orders`
  - [ ] Idempotent import command with dry-run
  - [ ] Parity matrix rows updated with test evidence
  - [ ] Sabrine signs off before US-002 (CustomerResource UI)
You do
Drop legacy snapshot in .larapilot/legacy/; invoke inception; answer origin + scope rounds
Agent does
Writes PRD + legacy-parity.md; /larapilot-spec with migration specs first
Next step
/larapilot-plan US-001 → implement → /larapilot-review (Sabrine checks parity)

New feature

/larapilot-feature

Invoicing SaaS shipped — stakeholder wants PDF export on invoice detail.

Your editor
/larapilot-feature "Add PDF export for invoices"

Mark + Tom read PRD/backlog, confirm no duplicate, run 3 AskQuestion rounds.

💎 Mark: Got it — PDF export for invoices from the detail page. Let's align scope and priority.

AskQuestion — Round 1 (scope & priority)
  1. MoSCoW: Should · Must · Could
  2. Traces to: New FR-011 · Extends FR-004 (Invoicing) · Standalone enhancement
  3. Persona: Freelancer · Accountant · Admin

You pick: Should, Extends FR-004, Freelancer.

AskQuestion — Round 2 (delivery shape)
  1. Complexity: Small (1 spec) · Medium · Large (split epics)
  2. Mockup first? Yes — /larapilot-design · No — plan directly · Already have mockups
  3. Legacy touch? No · Maps to legacy parity · Needs scraping/porting

You pick: Small, No — plan directly, No.

AskQuestion — Round 3 (backlog placement)
  1. Priority: HIGH · MEDIUM · LOW · CRITICAL
  2. Epic: EP-002 Invoicing · New epic · Other
  3. Blocked by: None · US-004 (Invoice detail UI)

You pick: MEDIUM (Should), EP-002 Invoicing, US-004.

🔎 Tom: Acceptance criteria — can you confirm before I write the spec?

  • Download PDF from invoice detail (happy path)
  • 403 when user lacks permission on that invoice
  • PDF includes line items, tax breakdown, company logo from tenant settings

Mark adds FR-011 to PRD, then agent creates US-011.

specs/US-011.yaml (excerpt)
code: US-011
title: "Export invoice as PDF"
priority: MEDIUM
status: TODO
body: |
  #### US-011: Export invoice as PDF

  **Epic:** EP-002 | **Priority:** MEDIUM | **Points:** 3 | **Status:** TODO
  **Blocked by:** US-004
  **Type:** Feature | Evolutiva
  **Traces to:** FR-011 (MoSCoW: Should), extends FR-004

  **User Story**
  As a freelancer,
  I want to download a PDF of an invoice from its detail page,
  so that I can archive or send it to clients offline.

  **Acceptance Criteria**
  - [ ] PDF download from invoice detail for authorized users
  - [ ] 403 when the user cannot view the invoice
  - [ ] PDF contains line items, tax breakdown, and tenant logo
You do
Invoke with a one-line description; answer 3 wizard rounds; confirm AC
Agent does
Validates and persists US-011 spec; updates PRD with FR-011 when needed
Next step
/larapilot-plan US-011

Bug resolution

/larapilot-bug

SSO works in Chrome, fails in Safari — maps to done story US-003.

Your editor
/larapilot-bug "SSO login fails on Safari"

Sophia triages with AskQuestion, logs to support/intake.md. Because the environment is Production (or staging) and the report mentions login errors, she pulls a diagnostics snapshot before routing — status, health checks, and a redacted log tail. Secrets never land in chat or intake.

🎧 Sophia: Report received — SSO works on Chrome, fails on Safari. Let's classify and route.

AskQuestion — Round 1 (severity & environment)
  1. Severity: Critical · High · Medium · Low
  2. Environment: Production · Staging · Local · Unknown
  3. Security-related? Yes · No · Unsure

You pick: High, Production, Unsure (auth boundary — Lars will review).

🎧 Sophia: Production auth failure — pulling diagnostics (redacted logs) before we route.

Agent — diagnostics (any of these)
php artisan larapilot:diagnostics --lines=80
# or MCP diagnostics tool
# or GET /larapilot/api/diagnostics?lines=80   (dev/staging only)

🎧 Sophia: Checks look healthy (database / storage_writable ok). Log tail shows OAuth callback noise — cookies/state look suspicious; no secrets in the redacted lines. Citing that in intake.

AskQuestion — Round 2 (reproduction)
  1. Reproducible? Always · Sometimes · Once · Not yet tried
  2. Affected area: Auth / SSO · Billing · Other · Unknown
  3. Maps to existing spec? Yes — US-003 · No — new fix spec · Unsure

You pick: Always (Safari 17+), Auth / SSO, Yes — US-003.

AskQuestion — Round 3 (routing)
  1. Preferred path: Rework existing spec · New fix spec · Log only
  2. Urgency: Hotfix now · Next sprint · Backlog

You pick: Rework existing spec, Next sprint (High but not Critical — no hotfix/* branch).

🔎 Tom: Steps to reproduce documented for the rework payload.

GET /larapilot/api/diagnostics?lines=80 (excerpt)
{
  "collected_at": "2026-07-15T09:12:00+00:00",
  "app": { "env": "local", "laravel_version": "13.x", "…" : "…" },
  "checks": {
    "storage_writable": { "ok": true, "detail": "…" },
    "database": { "ok": true, "detail": "…" },
    "…" : "…"
  },
  "healthy": true,
  "logs": {
    "redacted": true,
    "entries": [
      "[2026-07-15] local.ERROR: Socialite callback failed … cookie=… [REDACTED]",
      "[2026-07-15] local.WARNING: OAuth state mismatch for Safari UA …"
    ]
  }
}

Same payload via php artisan larapilot:diagnostics (CLI envelope) or the MCP diagnostics tool. API only where the dashboard is browsable — never in production; use CLI/MCP against a staging/local app that can reproduce, or export logs carefully. Toggle with LARAPILOT_DIAGNOSTICS_ENABLED. Full reference: Diagnostics.

Sophia appends a normalized entry to the support log (including a short diagnostics note):

.larapilot/docs/support/intake.md (excerpt)
## BUG-20260715-sso-safari

- **Reported:** 2026-07-15
- **Severity:** High
- **Environment:** Production
- **Summary:** SSO login fails on Safari; works on Chrome
- **Diagnostics:** healthy=true; log tail (redacted) shows OAuth state/cookie mismatch on Safari UA
- **Steps to reproduce:**
  1. Open app in Safari 17+
  2. Click "Sign in with Google"
  3. Complete OAuth — redirect returns to /login with error
- **Expected / Actual:** Expected dashboard · Actual login error
- **Affected spec:** US-003
- **Routed to:** rework on US-003 via /larapilot-bug
- **Security:** unsure — Lars/Oliver tagged

Maps to US-003 — skill sends it back to TODO with rework feedback. PRD update only if requirement gap (e.g. Safari never specified).

Rework feedback (attached to US-003)
## Bug report — 2026-07-15
**Severity:** High
**Steps to reproduce:** Safari 17+ → Sign in with Google → redirect error
**Expected / Actual:** Dashboard vs login error
**Diagnostics note:** redacted log tail pointed at OAuth state / SameSite cookie on Safari

**Additional acceptance criteria:**
- [ ] SSO login succeeds on Safari 17+ (macOS and iOS)
- [ ] SameSite / session cookie behaviour verified for OAuth callback
- [ ] Regression test covers Safari user-agent (Anne)
- [ ] Lars/Oliver review if cookie or state token issue confirmed

New fix spec instead?

No matching story → new US-XXX with Type: Fix. Critical production → Jack's hotfix/* note.

You do
Describe the defect; answer triage wizard; allow diagnostics on staging/local when asked
Agent does
Runs diagnostics (CLI / MCP / API); cites redacted evidence in support/intake.md; routes rework or fix spec
Next step
/larapilot-plan US-003 (rework) or /larapilot-plan US-012 (new fix)

External frontend repo

/larapilot-inception/larapilot-spec/larapilot-implement

Booking SaaS: Laravel API + React SPA in another folder. Laravel is the only Larapilot cockpit — the React repo is a linked write target. Reference: External frontend repo.

1 · Inception (Laravel)

Laravel editor
/larapilot-inception "Clinic booking API — React SPA in /Users/dev/clinic-web"

John + Joe ask Frontend Topology → you pick API + external frontend, React, absolute path /Users/dev/clinic-web. Filament for ops admin on Laravel. PRD records API + OpenAPI as Must.

2 · Link + scan (Laravel)

Laravel terminal
php artisan larapilot:frontend-set --path=/Users/dev/clinic-web --stack=React
php artisan larapilot:frontend-scan

frontend-set saves the path in .larapilot/config.yaml. frontend-scan detects Vite, src/, entrypoints — specs start from existing code.

3 · Deliver (Laravel only)

Laravel editor
/larapilot-spec
/larapilot-plan US-003
/larapilot-implement US-003

API stories touch Laravel. UI stories use plan tasks with repo: frontend — implement writes src/… under data.frontend.repo_path, runs npm test, commits with git -C /Users/dev/clinic-web …. Mockups stay in Laravel .larapilot/mockups/.

You do
Work only in the Laravel workspace — set path, spec, plan, implement
Agent does
Scans FE · plans BE + FE tasks · writes both repos from Laravel
Next step
/larapilot-spec → implement Must stories

PRD living document

Selective PRD updates with ## PRD Revision History — bugs stay in specs + intake unless they reveal a requirement gap.

Change type Update PRD? Where it lives
Legacy rewrite (/larapilot-inception) Yes — full PRD + Project Origin + parity section PRD + research/legacy-parity.md + migration specs first
New feature (/larapilot-feature) Yes — new FR-XXX or MoSCoW / scope change PRD + spec + revision history
Routine bug No support/intake.md + fix spec or rework
Bug reveals missing requirement (e.g. Safari SSO) Yes — clarify parent FR, not a “fix FR” PRD bullet under FR-003 + revision history + rework
Review rework No /larapilot-review feedback only
Hotfix production No Spec + app CHANGELOG.md
PRD.md — revision history (after post-inception edits)
## PRD Revision History

| Date | Trigger | Summary |
| --- | --- | --- |
| 2026-07-01 | larapilot-inception | Initial PRD |
| 2026-07-15 | larapilot-feature US-011 | Added FR-011 Export PDF (MoSCoW: Should) |
| 2026-07-15 | larapilot-bug → FR-003 gap | SSO must work on Safari 17+ (macOS/iOS) |
| 2026-07-24 | larapilot-inception | Frontend Topology: API + external frontend (React companion) |

Unclear? Default: spec only — safer than polluting the PRD.

Feature vs bug — at a glance

Step /larapilot-feature /larapilot-bug
1. Invoke /larapilot-feature "Add PDF export for invoices" /larapilot-bug "SSO login fails on Safari"
2. Interview Mark + Tom — MoSCoW, FR, mockup, epic (3 rounds) Sophia + Tom — severity, env, security, routing (3 rounds); diagnostics when prod/staging/logs
3. Persist US-011 spec; PRD if new FR-011 + revision history intake.md + rework or fix spec; PRD only on requirement gap
4. Implement /larapilot-plan/larapilot-implement/larapilot-review

Tracker sync

/larapilot-tracker

Invoicing SaaS, already in delivery: 12 specs in the backlog, four of them planned. The client's PM runs everything from Linear and will never open backlog.yaml. You mirror the backlog into their team so they can follow progress, and read status back before standup. Full reference: Project trackers.

1 · Point Larapilot at the tracker

Editor
/larapilot-tracker

🔗 Matt: No provider configured yet — 12 specs, 0 linked. Let's pick the destination first.

AskQuestion — Project tracker
  1. Where should the backlog be mirrored: Linear · Jira · Asana · ClickUp · Trello · Monday

You pick: Linear — issues on a team, plan tasks as sub-issues.

🔐 Lars: I need a personal API key (Linear → Settings → API) and the team key — the short prefix on your issues, e.g. ENG. The key goes in .env, never in .larapilot/: that directory is committed.

You paste: the key and ENG.

.env
LARAPILOT_TRACKER_ENABLED=true
LARAPILOT_TRACKER_PROVIDER=linear
LARAPILOT_LINEAR_API_KEY=lin_api_xxxxxxxxxxxxxxxxxxxx
LARAPILOT_LINEAR_TEAM=ENG
Terminal — verify before touching anything
php artisan larapilot:tracker-status --ping
Envelope (excerpt)
{
  "kind": "tracker-status",
  "data": {
    "provider": "linear",
    "ready": true,
    "missing_config": [],
    "sync_tasks": true,
    "status_map": { "TODO": "Todo", "PLANNED": "Todo", "IN PROGRESS": "In Progress",
                    "REVIEW": "In Review", "DONE": "Done" },
    "specs": { "total": 12, "linked": 0, "unlinked": ["US-001", "US-002", "…"] },
    "connection": { "ok": true, "detail": "Connected to Linear team ENG.", "target": "Engineering" }
  }
}

2 · Dry-run first — and hit the status map

On a backlog that has never been synced, always dry-run. It reports what would change without calling the provider at all.

Terminal
php artisan larapilot:tracker-push --dry-run
Envelope (excerpt)
"dry_run": true,
"stories": [ { "code": "US-001", "action": "created", "ref": null,
               "tasks": { "created": 4, "updated": 0, "removed": 0, "unchanged": 0 } }, … ],
"summary": { "created": 12, "updated": 0, "unchanged": 0, "tasks_created": 17, … }

The real push then fails — and this is the common first-run outcome, not an edge case:

Terminal
php artisan larapilot:tracker-push   # exit code 3
Envelope (excerpt)
{
  "kind": "error",
  "error": {
    "code": "E_CONNECTOR",
    "message": "12 of 12 stories failed to sync.",
    "details": {
      "errors": [{
        "code": "US-001",
        "message": "Linear team ENG has no workflow state named \"Todo\". Existing states: Backlog, In Progress, In Review, Done. Rename the state or adjust larapilot.tracker.providers.linear.status_map."
      }, … ]
    }
  }
}

🔗 Matt: The client's team calls its first column Backlog, not Todo. Larapilot will not create a column in someone else's tracker — two ways out: rename the state in Linear, or point the map at what already exists. I'd take the second: it's their board.

config/larapilot.php
'linear' => [
    'api_key' => env('LARAPILOT_LINEAR_API_KEY'),
    'team' => env('LARAPILOT_LINEAR_TEAM'),
    'status_map' => [
        'TODO' => 'Backlog',        // was 'Todo'
        'PLANNED' => 'Backlog',     // same column — not drift
        'IN PROGRESS' => 'In Progress',
        'REVIEW' => 'In Review',
        'DONE' => 'Done',
    ],
],

3 · Push

Terminal
php artisan larapilot:tracker-push
Envelope (excerpt)
"stories": [
  { "code": "US-001", "action": "created", "ref": "ENG-42",
    "url": "https://linear.app/acme/issue/ENG-42",
    "tasks": { "created": 4, "updated": 0, "removed": 0, "unchanged": 0 } }, … ],
"summary": { "created": 12, "updated": 0, "unchanged": 0, "tasks_created": 17, … },
"errors": [],
"link_file": ".larapilot/tracker.yaml"

In Linear the client now sees ENG-42 — US-001 — Staff can issue an invoice, sitting in Backlog, carrying the spec body, priority, points as the estimate, and the epic — with four sub-issues, one per plan task. Larapilot writes the mapping to disk:

.larapilot/tracker.yaml — commit this
providers:
  linear:
    US-001:
      id: 9f2c1a4e-7b30-4d1e-9c55-2a6f81b0c3d7
      key: ENG-42
      url: https://linear.app/acme/issue/ENG-42
      fingerprint: 6b1f0c2d…
      pushed_at: '2026-07-27T11:04:12+00:00'
      tasks:
        TASK-01:
          id: 3ad5b9c1-…
          url: https://linear.app/acme/issue/ENG-43
          fingerprint: 8c02e5a7…
provider: linear
updated_at: '2026-07-27T11:04:12+00:00'
Commit tracker.yaml. It is how the team shares one mapping — without it, your colleague's first push creates a second ENG-… for every story. It holds identifiers only, never the API key.

4 · Normal delivery — the push is cheap

You keep working as usual: /larapilot-plan, /larapilot-implement, /larapilot-review. Re-push whenever you like — unchanged stories are fingerprinted and skipped without an API call.

Terminal — after planning US-005 and finishing two tasks on US-003
php artisan larapilot:tracker-push
Envelope (excerpt)
"summary": { "created": 0, "updated": 2, "unchanged": 10,
             "tasks_created": 5, "tasks_updated": 2, "tasks_removed": 1 }

The removed subtask is a plan task that disappeared when you re-planned US-005 — the matching sub-issue is deleted rather than left orphaned in the client's board.

5 · Before standup — read the drift

Overnight the PM dragged two cards. tracker-pull with no flags changes nothing — it reports.

Terminal
php artisan larapilot:tracker-pull
Envelope (excerpt)
"apply": false,
"stories": [
  { "code": "US-003", "ref": "ENG-44", "local_status": "IN PROGRESS",
    "remote_status": "In Review", "suggested_status": "REVIEW",
    "drift": true, "applied": false, "blocked": null },
  { "code": "US-007", "ref": "ENG-48", "local_status": "REVIEW",
    "remote_status": "Done", "suggested_status": "DONE",
    "drift": true, "applied": false,
    "blocked": "Remote status maps to DONE. Approve through /larapilot-review or larapilot:spec-approve so the merge commit is recorded." },
  { "code": "US-002", "ref": "ENG-43", "local_status": "PLANNED",
    "remote_status": "Backlog", "drift": false, "applied": false } ],
"summary": { "checked": 12, "in_sync": 10, "drifted": 2, "applied": 0, "missing": 0 },
"hint": "2 stories drifted. Re-run with --apply to write the mapped statuses into the backlog."

🔗 Matt: Two drifts. US-003 genuinely moved to review — safe to apply. US-007 the PM marked Done, which Larapilot will not accept from a tracker.

💎 Mark: Note US-002: local PLANNED, remote Backlog. Both TODO and PLANNED map to that column, so it is in sync, not drift — you won't get a false alarm every morning.

Terminal
php artisan larapilot:tracker-pull --apply
Envelope (excerpt)
"summary": { "checked": 12, "in_sync": 10, "drifted": 2, "applied": 1, … },
"hint": "Statuses that map to DONE were left alone — approve them through /larapilot-review."

US-003 is now REVIEW in backlog.yaml. US-007 is untouched — you finish it the normal way:

Editor
/larapilot-review US-007

What pull will never do

Change made in Linear Effect on .larapilot/ Why
Card moved to In Review Applied with --apply Status is the one thing the tracker legitimately observes
Card moved to Done Reported, never applied DONE is a human gate that records the merge commit — spec-approve owns it
Issue title or description edited Ignored, overwritten on the next push Spec text is owned by .larapilot/; the card footer says so
Card moved to a state outside the map Drift with no suggestion Better a visible unknown than a guessed status
Issue deleted Flagged missing; next push recreates it The link is stale, not the spec
Comment added Imported once as non-blocking internal feedback Opt-in via LARAPILOT_TRACKER_PULL_COMMENTS=true

6 · Keep it fresh (optional)

.github/workflows/tracker.yml (excerpt)
- name: Sync backlog to Linear
  run: php artisan larapilot:tracker-push
  env:
    LARAPILOT_TRACKER_ENABLED: true
    LARAPILOT_TRACKER_PROVIDER: linear
    LARAPILOT_LINEAR_API_KEY: ${{ secrets.LARAPILOT_LINEAR_API_KEY }}
    LARAPILOT_LINEAR_TEAM: ENG

Run it on the default branch after merges. Because unchanged stories cost no API call, a push on every merge is cheap.

The tracker is a window, not a second workflow. Scope still changes through /larapilot-feature and the PRD, plans through /larapilot-plan, and acceptance through /larapilot-review. What the client gets is visibility in the tool they already use — not a second place to run delivery from.

Reference

Skills, settings, personas, workflow, artifacts, usage, integrations, surfaces, CLI, dashboard, and API — how every layer fits together.

What's new in v2.4.2

Polish on Project tracking — shorter settings label and a couple of cleanups.

  • Settings label — Lucille key reads Project tracking (was Lucille · Project tracking)
  • PHPStan / tests — quieter Gantt assignee analysis; UsageTest imports tightened

Also in v2.4.1: epics with objectives & deadlines, dependency-aware Gantt, Zoey vs Lucille panel, usage UX (hours / K tokens, paginated ledger). In v2.4.0: 30 personas (Mike, Lucille, Sarah), Project Kind Package, optional forges + chat notifications.

How it works

Three layers: skills orchestrate the conversation, artifacts in git are the source of truth, and Artisan CLI persists state under the hood.

1 · Skills

/larapilot-* prompts published via Laravel Boost. You invoke them in the editor; the agent reads SKILL.md and follows the execution contract.

2 · Artifacts

PRD, backlog, specs, plans, and review notes live under .larapilot/ in git — durable state the agent reloads on every skill activation.

3 · CLI (under the hood)

Skills call php artisan larapilot:* to persist files and enforce status transitions. You rarely run these directly — see Artisan CLI. After a package upgrade, run Composer + larapilot:update to refresh shared runtime and Boost skills.

Upgrade

Larapilot ships as a Composer package. Updating is two steps: pull the new version, then refresh the files Larapilot publishes into your project — without touching your workflow data in .larapilot/config.yaml, specs, plans, or PRD.

Terminal — after each release
  1. composer update andreapollastri/larapilot
  2. php artisan larapilot:update

What each step does

Command Updates Leaves untouched
composer update andreapollastri/larapilot PHP package in vendor/ — services, CLI, dashboard, design-system packages, Boost resources bundled with Larapilot Your .larapilot/ project config and workflow artifacts
php artisan larapilot:update .larapilot/shared-runtime.md, .larapilot/task-templates.md, packaged .larapilot/design-systems/ references; missing phpstan.neon.dist / pint.json and Composer quality entries; re-runs boost:update to republish guidelines and /larapilot-* skills .larapilot/config.yaml, PRD, backlog, specs, plans, mockups, and other project-owned files

Options & checks

  • php artisan larapilot:update --skip-boost — refresh shared runtime and design-system copies only; run php artisan boost:update yourself when you want new skills/guidelines
  • php artisan larapilot:doctor — verify install health after an upgrade (includes Larastan/Pint gate)
  • php artisan boost:update --discover — one-time if Boost was installed before Larapilot and skills are missing

Automate with Composer (optional)

Add a post-update-cmd hook so larapilot:update runs whenever Larapilot is updated via Composer:

composer.json — scripts
"scripts": {
    "post-update-cmd": [
        "@php artisan larapilot:update --skip-boost"
    ]
}

Omit --skip-boost if you always want Boost guidelines and skills republished on every Composer update. Run php artisan boost:update manually when you use --skip-boost in the hook.

Do not re-run larapilot:install on an existing project unless you intend to scaffold from scratch (--force). Use larapilot:update for routine upgrades.

Skills

Fifteen editor-native skills cover the full product lifecycle — discovery, delivery, ship, settings, usage (Lucille), Backstage, trackers, and frontend companion. Each is a SKILL.md file with a name, description, persona roster, execution steps, and allowed CLI calls. Laravel Boost publishes them on php artisan boost:install; coding guidelines ship alongside (not a skill).

When you type /larapilot-plan US-001, the agent:

  1. Loads the skill instructions and .larapilot/shared-runtime.md
  2. Reads current artifacts (PRD, spec, backlog status)
  3. Runs the guided conversation with the right personas
  4. Persists output via Artisan commands defined in the skill — never inventing its own file writes
discovery

/larapilot-inception

Guided product interview → PRD.md with MoSCoW-tagged functional requirements.

  • Mark opens with Project Kind (Personal · Website · Application · Package)
  • Package branch: origin (new / local / git), distribution, consumer install, CI/docs
  • John + Joe ask Frontend Topology when there is a UI; Mike on data stores; Lucille on deadlines (skippable)
  • AskQuestion rounds (max 3 questions each, skippable)
  • Reads client-materials/ and legacy/ when present; snapshots choices via choices-set

CLI: larapilot:prd-write · larapilot:validate-prd · larapilot:choices-set · larapilot:schedule-set.

shortcut

/larapilot-feature "…"

Mini-inception for one evolutiva on a shipped product → new US-XXX spec (+ optional PRD FR).

CLI: larapilot:spec-add · larapilot:validate-spec — optionally prd-write when a new FR is added.

shortcut

/larapilot-bug "…"

Sophia-led triage → fix spec or rework route. PRD updated only on requirement gaps. When the report mentions production/staging errors or logs, agents pull diagnostics (redacted).

CLI: larapilot:spec-add or larapilot:spec-request-changes — plus larapilot:diagnostics for runtime evidence.

companion

/larapilot-frontend-companion

For API + external frontend: link the FE absolute path, scan existing code. All delivery stays on Laravel via repo: frontend tasks. External frontend repo.

  • larapilot:frontend-set --path=/abs/fe/repo
  • larapilot:frontend-scan

CLI: frontend-set · frontend-scan.

backlog

/larapilot-spec

Maps PRD Must/Should FRs to user stories. Writes backlog.yaml + specs/US-XXX.yaml.

CLI: larapilot:spec-add · larapilot:validate-spec · larapilot:spec-list.

optional

/larapilot-design US-XXX

Static HTML mockups in mockups/{spec}/, styled from packaged references — Filament, Starter Kit, Bootstrap 5, Tailwind, or AdminLTE per PRD. Preview at /mockups/{spec} (non-production) and on the dashboard spec page when HTML exists.

CLI: larapilot:config-show — resolve paths.mockups and paths.design_systems.

plan

/larapilot-plan US-XXX

Technical plan with tasks, test strategy, Git deliverables → plans/US-XXX-plan.yaml. Status → PLANNED.

CLI: larapilot:validate-plan · larapilot:spec-plan — validate then persist the plan.

implement

/larapilot-implement US-XXX

Executes the plan: Laravel code, Pest tests, per-task commits. Runs larapilot:quality (Pint + Larastan level 5+) on backend tasks before task-done. Status → REVIEW when all tasks complete.

CLI: larapilot:spec-start · larapilot:quality (--fix) · larapilot:task-done · larapilot:spec-review.

review

/larapilot-review US-XXX

Human gate. You approve → DONE, or send back with feedback → TODO.

CLI: larapilot:spec-approve or larapilot:spec-request-changes.

optional

/larapilot-ship

OWASP security gate + multi-platform deploy runbook when all MVP stories are DONE.

CLI: larapilot:config-show · larapilot:metrics — paths and DONE coverage before release checks.

batch

/larapilot-autopilot US-XXX …

Chains plan + implement for multiple specs. By default you still run /larapilot-review per story; with auto_approve: YES it may spec-approve after implement.

CLI: same as plan/implement; plus larapilot:spec-approve when auto-approve is on.

config

/larapilot-settings

AskQuestion for persistent project settings — effort, backlog, git mode, testing, auto-approve, lucille, GitHub / GitLab / Bitbucket, and notification channels. Written to .larapilot/config.yaml. Full tables in Settings.

CLI: larapilot:settings-set — write settings; larapilot:config-show — read data.settings.

ops

/larapilot-usage

Lucille interrogates the committed time/token ledger and schedule — overview, filters by category/user/skill/spec/date, deadline drift, and Markdown resoconto export. Read-only while settings.lucille is NO. Full reference: Usage & Lucille.

CLI: larapilot:usage-report · larapilot:usage-log · larapilot:schedule-set.

portal

/larapilot-backstage

Publishes the repo into a Backstage developer portal — catalog entity (catalog-info.yaml) plus TechDocs generated from PRD and backlog. Asks for owner, system, and lifecycle, then generates. Full reference: Backstage portal.

CLI: larapilot:backstage-export (preview) · --write to generate.

tracker

/larapilot-tracker

Mirrors the backlog into Linear, Asana, Jira, Trello, ClickUp, or Monday over an API key. Stories become issues, plan tasks become native subtasks, and remote status comes back as a drift report. Full reference: Project trackers.

CLI: larapilot:tracker-status · larapilot:tracker-push · larapilot:tracker-pull.

Project settings

Persistent modes for effort, backlog granularity, Git, testing, auto-approve, Lucille, and optional GitHub / GitLab / Bitbucket + Slack / Discord / Telegram (forges and chat OFF by default). Configure with /larapilot-settings (AskQuestion). Values live under settings: in .larapilot/config.yaml. Every skill reads and honors them via config-show.

CLI: php artisan larapilot:settings-set --effort=… --backlog=… --git-mode=… --testing=… --auto-approve=… --lucille=… --github=… --gitlab=… --bitbucket=… --notifications=… --notify-slack=… persists one or more keys. php artisan larapilot:config-show returns data.settings (YES/NO for booleans; YAML stores booleans).

Defaults when unset: effort: STANDARD · backlog: STANDARD · git_mode: GITFLOW · testing: NORMAL · auto_approve: NO · lucille: YES · github|gitlab|bitbucket: NO · notifications: NO · notify_*: NO.

Effort

Value Behavior
ECO Token economy — never spawn sub-agents; disables Lucille automatically (re-enable via settings-set --lucille=YES without leaving ECO); defer docs theater (README/PDF/diagrams) but still update OpenAPI when APIs change; skip deep reviews and E2E planning
STANDARD Normal Larapilot behavior (default)
MAX Deep mode on every flow — fuller persona rounds, always run explore/review sub-agents when available, richer plans and residual-risk notes

Backlog granularity

Value Behavior
LEAN Fewest specs — one per end-to-end user journey, related FRs merged (each cited as Traces to: FR-XXX); technical seams, admin entities, and i18n locales are always plan tasks; ≤ 5 epics per product
STANDARD One spec per demonstrable user capability (default) — closely related FRs may share a spec; Laravel seams (models, controllers, policies, UI, API resources) become plan tasks; reuse existing epics
GRANULAR Fine-grained — one spec per FR allowed; seam / Filament per-entity / i18n per-locale splits allowed; multi-epic backlog expected. For large teams or spec-per-PR workflows

Granularity changes spec cardinality only — never coverage: merged scope stays traceable via FR-XXX citations in spec bodies and plan tasks. Epics are always consolidated: reuse existing EP-XXX before proposing a new one.

Git mode

Value Behavior
NO_GITFLOW No Gitflow ceremony — work on the current branch; no mandatory feature branch / internal PR
GITFLOW Feature branches + atomic commits + PR prepared locally — no automatic push (default
GITFLOW_PUSH Full Gitflow with push and open/update of the internal PR toward develop after each task

Push is never implied by GITFLOW alone. See also Git workflow.

Remote forges opt-in

settings.github, gitlab, and bitbucket (all default NO) are orthogonal to git_mode. Enable the forge matching origin:

  • GitHubgh CLI; probe larapilot:github-status
  • GitLabglab CLI (MR); probe larapilot:gitlab-status
  • Bitbucket Cloud — REST API with access token or app password; probe larapilot:bitbucket-status

When ON, skills open/update the PR/MR, always print the URL, and can notify pr_opened / pr_updated. Full setup: Forges & notifications · .larapilot/integrations.md.

Notifications opt-in

Master switch settings.notifications plus notify_slack / notify_discord / notify_telegram (all default NO). Secrets stay in .env. Fan-out via php artisan larapilot:notify. Hard hooks: task-donetask_done, spec-approvespec_done. Full event list: Forges & notifications.

Testing

Value Behavior
MINIMAL Critical-path Pest/PHPUnit only — no Playwright, Dusk, browser E2E, or viewport matrix
NORMAL Standard feature/unit/policy/API tests (default) — still no Playwright/Dusk/E2E
BEST Full bar — integrations, primary-journey E2E, Playwright or Dusk / Pest browser, viewport matrix (375 / 768 / 1280), axe, Lighthouse when applicable

Auto-approve

Value Behavior
NO Human gate required (default) — specs stop at REVIEW; only you Approve via /larapilot-review
YES After implement reaches REVIEW, /larapilot-autopilot may present a short checklist and call spec-approve without waiting — opt-out of the usual human-in-the-loop DONE gate

Lucille

settings.lucille controls the silent usage ledger and schedule interviews. Missing key = ON. Exclusion is opt-out only.

Value Behavior
YES Default — log tokens/time at skill end, ask deadlines at inception, surface schedule drift, honor /larapilot-usage
NO Excluded — no usage-log, no Lucille interview rounds; /larapilot-usage may still read historical ledger. Set automatically when switching effort to ECO (unless you pass --lucille=YES in the same call)

Re-enable anytime with php artisan larapilot:settings-set --lucille=YES without leaving ECO. Details: Usage & Lucille.

CLI — persist settings
php artisan larapilot:settings-set \
  --effort=STANDARD \
  --backlog=STANDARD \
  --git-mode=GITFLOW \
  --testing=NORMAL \
  --auto-approve=NO \
  --lucille=YES \
  --github=NO \
  --gitlab=NO \
  --bitbucket=NO \
  --notifications=NO \
  --notify-slack=NO \
  --notify-discord=NO \
  --notify-telegram=NO

Personas

30 personas are lenses, not costumes. Each skill activates a subset of the squad — they speak in chat as 💎 Mark:, 📐 John:, etc., applying a specific kind of scrutiny to the work at hand. Zoey (AI Guru) is active in every skill; Lucille is active quietly by default (usage ledger); Mike, Sarah, and Lucille joined in v2.4.0.

Discovery

Zoey sharpens user intent and flags session-budget risks. Lucille asks for delivery deadlines (skippable) and starts the ledger. Mark drives scope and MoSCoW. Jennifer and Benjamin frame market context. John and Aurora co-own architecture — John designs with SOLID and N+1-aware query shape; Aurora brings SaaS economics. Mike owns data architecture (SQL/NoSQL, tree patterns, search, migrations) when persistence is non-trivial. Sabrine leads legacy parity when legacy/ has content. Elise and Joe co-own the design system. Emma, Lauren join for public surfaces; Ricky for mobile apps; Albert scopes documentation; Sarah joins when CLI/Git/CI/Linux surfaces appear.

Planning

Zoey recommends sub-agent vs inline passes. Tom sharpens acceptance criteria. John designs the technical approach; Mike designs schema and query plans. Anne defines test strategy. Andrew enforces Laravel conventions. Albert plans baseline docs on every spec and extended deliverables when approved. Alex plans FE/BE integration with Andrew, Joe, and Jack. Sarah plans CLI, Git mechanics (conflicts/rebase), forge automation, CI pipeline scripts, and Linux/server shell tasks when those surfaces appear. Optional sub-agents explore the codebase in readonly mode.

Implementation

Alex writes SOLID, N+1-free code; Mike guides migrations and data access. Anne ships Pest tests and documents manual tests. Robert checks plan adherence, Gitflow, and the quality bar — involves Sabrine on refactoring/porting. Joe enforces design-system consistency. Lars runs OWASP-aligned security review. Sarah leads Git conflict/rebase resolution and implements pipeline YAML, forge automation, and server shell scripts. Ricky, Marika, Matt, and Albert join when mobile, copy, integrations, or docs are in scope. Lucille logs the session quietly at the end.

Review

Robert presents the human gate — including SOLID and N+1 checks — with Sabrine on refactoring/porting specs. Joe checks design-system compliance. Marika and Emily verify typos and translation consistency. Anne attaches automated evidence and manual test recommendations. Mike reviews schema/migration risk when data tasks shipped.

Ship & support

Jack owns CI/CD gates and deploy orchestration; Sarah owns pipeline scripts and server-side shell those runbooks invoke. Oliver red-teams before launch. Albert ships client manuals and API docs. Sophia routes bugs. Violet and Emily cover compliance and localization. Lucille reports schedule drift vs deadlines via /larapilot-usage.

Output economy varies by phase: concise status lines during implement/review; full artifacts and code stay complete. See .larapilot/shared-runtime.md for brevity rules.

💎
Mark
Product Manager
🧭
Jennifer
Business Strategist
🏢
Benjamin
Business Consultant
💡
Sebastian
Innovator
🔎
Tom
Requirements Analyst
📐
John
Architect
🗄️
Mike
Database Expert
🔧
Alex
Full-Stack Developer
🧪
Anne
Test Architect
🛡️
Robert
Code Reviewer
🔐
Lars
Security Expert
🚀
Jack
DevOps Engineer
⌨️
Sarah
CLI, Git & Linux
📒
Lucille
Account
💰
Aurora
FinOps Expert
⚖️
Violet
Legal Expert
📈
Emma
SEO & Web Performance
💬
Lauren
Social Media Manager
🎨
Elise
UX Designer
Joe
Frontend Expert
📱
Ricky
App Developer
📝
Albert
Tech Writer
🤖
Zoey
AI Guru
✍️
Marika
Copywriter
🔄
Sabrine
Legacy Porting & Migration
👾
Andrew
Laravel Expert
🔗
Matt
Integration Manager
🎯
Oliver
Ethical Hacker
🎧
Sophia
Support Manager
🌍
Emily
Translator

Workflow

Every user story moves through a strict state machine on a Gitflow branch model. Skills drive transitions; invalid jumps are blocked automatically. After inception and backlog creation, you repeat the per-story loop until the MVP is shipped.

Greenfield — repeat per story
/larapilot-inception "…" /larapilot-spec /larapilot-plan US-XXX /larapilot-implement US-XXX /larapilot-review US-XXX

Optional: /larapilot-design before plan · /larapilot-ship when all MVP stories are DONE · /larapilot-autopilot to batch plan+implement · /larapilot-settings · /larapilot-usage · /larapilot-feature or /larapilot-bug on existing products · Package kind skips UI mockups unless the package ships UI.

Git workflow — Gitflow

Git behavior is gated by settings.git_mode (set via /larapilot-settings). Default is GITFLOW without automatic push. Choose GITFLOW_PUSH for push-after-each-task, or NO_GITFLOW to skip branch/PR ceremony. Jack proposes the workflow at inception; Sarah owns Git mechanics (conflicts, rebase), forge automation, and CI pipeline scripts; Robert enforces the active mode.

Branch Purpose
main Production-ready; tagged releases only
develop Integration branch for the next release
feature/US-XXX-short-desc One user story or cohesive feature; branch from develop
release/x.y.z Release prep — version bump, changelog, final QA; merge → main + back-merge → develop
hotfix/x.y.z Urgent production fix; branch from main; merge → main + develop

In Gitflow modes: no direct commits to main or develop; one atomic Conventional Commit per plan task. Push and remote PR updates run only when git_mode is GITFLOW_PUSH (or the user asks). Critical production defects route through hotfix/* via /larapilot-bug. Mode table: Git mode settings.

Status machine

Status Meaning Skill to advance
TODO Spec exists in backlog, not yet planned /larapilot-plan US-XXX
PLANNED Technical plan written and validated /larapilot-implement US-XXX
IN PROGRESS Implementation underway — tasks ticking off Skill completes tasks → auto REVIEW
REVIEW Code delivered, awaiting acceptance /larapilot-review US-XXX — or autopilot spec-approve when auto_approve: YES
DONE Approved — spec is shipped Next US-XXX or /larapilot-ship

Transition guards

The workflow engine rejects invalid state changes — for example, you cannot implement before planning, or approve before review. When you reject a review, the spec returns to TODO with your feedback attached so the agent can replan and reimplement.

Human-in-the-loop

Discovery interviews use AskQuestion wizards. By default, review is yours — the agent proposes, you approve or send back. No spec reaches DONE without explicit acceptance unless you set auto_approve: YES in project settings (opt-in for /larapilot-autopilot).

Artifacts

Everything the workflow produces lives in .larapilot/ inside your repo. Skills read and write these files; they survive across editor sessions and give every agent the same ground truth.

.larapilot/ ├── config.yaml # connector, paths, settings (effort / git / lucille / forges…) ├── integrations.md # optional GitHub/GitLab/Bitbucket + Slack/Discord/Telegram ├── choices.yaml # inception/settings snapshot (choices-set) ├── shared-runtime.md # rules every skill reads at activation ├── task-templates.md # plan/implement task body shapes ├── backlog.yaml # spec index + statuses ├── usage/ # Lucille ledger + schedule (committed) │ ├── ledger.jsonl │ └── schedule.yaml ├── docs/ │ ├── PRD.md # living product contract (includes Frontend Topology) │ ├── test-results/ # per-spec test evidence │ ├── review/ # Robert/Lars findings │ ├── security/ # OWASP assessments │ ├── launch/ # SEO/social launch checks │ └── support/ # bug intake, triage notes ├── specs/US-XXX.yaml # user story + acceptance criteria ├── plans/US-XXX-plan.yaml # tasks, deliverables, test strategy ├── mockups/{spec}/ # HTML mockups (optional) ├── internal-feedback/ # PM/dev comments per spec (append-only) ├── client-materials/ # drop client docs before inception ├── legacy/ # legacy snapshot for rewrite/port ├── research/ # deepsearch, parity matrices └── design-systems/ # Filament / Starter Kit / Bootstrap / Tailwind / AdminLTE
Artifact Written by Purpose
config.yamlsettings /larapilot-settings effort, backlog, git_mode, testing, auto_approve, lucille, github, gitlab, bitbucket, notifications, notify_* — see Settings
PRD.md /larapilot-inception, /larapilot-feature Vision, personas, MoSCoW FRs, architecture including Frontend Topology — updated selectively on scope changes. Mirrored to an external FE via /larapilot-frontend-companion when topology is split.
backlog.yaml /larapilot-spec Ordered list of specs with status, priority, and traceability to FRs
specs/US-XXX.yaml /larapilot-spec, shortcuts User story body, acceptance criteria, epic link, priority
plans/US-XXX-plan.yaml /larapilot-plan Task breakdown with Git deliverables, test data, and dependencies
mockups/{spec}/ /larapilot-design Static HTML previews at /mockups/{spec} (dev/staging); linked in the dashboard and JSON API when present
internal-feedback/{code}.md Dashboard · larapilot:spec-comment Append-only PM/dev notes until the spec is DONE; blocking comments flagged with [blocks-merge]
design-systems/ larapilot:install · larapilot:update Packaged mockup references + optional custom folders — see design systems
usage/ skills (Lucille) · /larapilot-usage ledger.jsonl + schedule.yaml — tokens, minutes, deadlines; see Usage
choices.yaml inception · larapilot:choices-set Snapshot of Project Kind, topology, data-store/CLI choices, and current settings
integrations.md larapilot:install · larapilot:update Setup guide for optional forges + chat notifications
Laravel app code /larapilot-implement Models, controllers, views, migrations, Pest tests — outside .larapilot/

JSON responses from CLI commands use schema larapilot/v1 — skills parse these envelopes to confirm writes and status changes. Inspect artifacts visually via the dashboard or programmatically via the API.

Usage & Lucille

Lucille keeps a committed ledger of AI tokens and wall-clock time, plus delivery deadlines. Every skill may append an entry at session end; /larapilot-usage interrogates the data. Dashboard Usage mirrors charts, Gantt, and a Markdown download.

Categories

analysis · planning · implementation · support · feature · review · ship · other.

Commands

Log · report · schedule
php artisan larapilot:usage-log --category=implementation --tokens=12000 --minutes=45 --skill=implement --spec=US-001
php artisan larapilot:usage-report --format=json --insights
php artisan larapilot:usage-report --format=md --output=.larapilot/usage/report.md --insights --from=2026-08-01 --to=2026-08-31
php artisan larapilot:schedule-set --deadline=2026-09-15 --label="MVP go-live" --status=on_track

Report filters: --category= · --user= · --skill= · --spec= · --from= · --to= · --limit= · --insights. Formats: json · md · human.

When Lucille is OFF

usage-log refuses writes. /larapilot-usage states she is excluded and may still run a read-only report on historical data. Re-enable: php artisan larapilot:settings-set --lucille=YES. ECO switches set lucille: NO automatically unless you pass --lucille=YES together with --effort=ECO.

Dashboard: /larapilot/usage · download /larapilot/usage/report.md (dev/staging only). MCP RunArtisanTool allows larapilot:usage-report.

Forges & notifications

Optional remote forges and chat fan-out — all OFF by default, orthogonal to git_mode. Full install steps live in .larapilot/integrations.md (published on install/update). Toggle via /larapilot-settings or larapilot:settings-set.

Remote forges

Setting Tooling Probe
github gh CLI larapilot:github-status
gitlab glab CLI (MR) larapilot:gitlab-status
bitbucket Bitbucket Cloud REST (access token or app password) larapilot:bitbucket-status

When ON, skills open/update the PR/MR (still respecting git_mode), always print the URL, and may emit pr_opened / pr_updated notifications. Secrets stay in .env — never in config.yaml.

Chat notifications

Master switch settings.notifications plus notify_slack / notify_discord / notify_telegram. Fan-out: php artisan larapilot:notify.

  • Hard hooks: task-donetask_done, spec-approvespec_done
  • Skill events: PR/MR opened/updated, review, ship, schedule drift
  • Env: LARAPILOT_SLACK_WEBHOOK_URL, LARAPILOT_DISCORD_WEBHOOK_URL, LARAPILOT_TELEGRAM_BOT_TOKEN, LARAPILOT_TELEGRAM_CHAT_ID; Bitbucket BITBUCKET_ACCESS_TOKEN or username + app password

Settings tables: Remote forges · Notifications.

Design systems

Five packaged visual references ship in .larapilot/design-systems/ on larapilot:install and refresh on larapilot:update. /larapilot-design picks the folder that matches the PRD stack choice — Elise and Joe enforce token and component consistency through implement and review.

System Path When to use Contents
Filament design-systems/filament/ Admin/control panel mockups when the PRD records Filament tokens.css, components.md, figma-sources.md, 17 HTML screens — v3 light sidebar; slate primary (v1.8.1)
Laravel Starter Kits design-systems/starter-kit/ Authenticated app UI when the PRD records a Starter Kit variant (livewire, react, vue, svelte) tokens.css (shadcn oklch), components.md, 7 HTML screens
Bootstrap 5 design-systems/bootstrap-5/ Marketing or app UI when the PRD records Bootstrap 5 (without Filament or a Starter Kit) tokens.css, components.md, 6 HTML screens (landing, dashboard, login, settings, components)
Tailwind CSS design-systems/tailwind/ Marketing or custom app UI when the PRD records Tailwind CSS without Filament, Starter Kit, or Bootstrap tokens.css, components.md, 6 utility-first HTML screens
AdminLTE design-systems/adminlte/ Admin/control panel mockups when the PRD records AdminLTE 4 tokens.css, components.md, 6 HTML screens (dashboard, resource list, login, settings, components)

Open each folder's html/index.html locally as a visual catalog. Skills resolve paths via php artisan larapilot:config-showpaths.design_systems.

Custom design systems & templates

You can add your own design system or UI template under .larapilot/design-systems/{your-name}/ and use it for mockups (/larapilot-design) and implementation — not only the five packaged references.

  • Drop tokens, component notes, HTML starters, and brand assets in that folder (same shape as the packaged ones helps: README.md, tokens.css, components.md, optional html/).
  • Record the choice in the PRD (or tell the agent during inception/design) so Elise, Joe, and Alex treat it as the source of truth for mockups and shipped UI.
  • larapilot:update refreshes only the packaged systems — your custom folder is never overwritten.

External frontend repo

Laravel is the only Larapilot cockpit. When topology is API + external frontend, the SPA lives in another folder on disk. Larapilot links that path and implements UI there via repo: frontend tasks. The FE repo holds application code only — no mirrored PRD.

Topology choices

Topology UI location Split repo?
Laravel-coupled Blade / Livewire / Inertia in Laravel No
SPA-in-Laravel Vite SPA inside Laravel No
API + external frontend Separate folder; Laravel is API (+ optional admin) Yes

PRD fields

Technical Architecture
**Frontend Topology:** API + external frontend
**Frontend stack (in-repo):** N/A
**External frontend repo:** /Users/dev/acme-web
**External frontend stack:** React

Three CLI commands (all from Laravel)

Command When
larapilot:frontend-set --path=… Once — persist absolute FE path in config.yaml (data.frontend on config-show)
larapilot:frontend-scan Before plan on an existing FE codebase — stack, tooling, entrypoints

Delivery

  • Laravel — PRD, backlog, plans, mockups, workflow. All /larapilot-* skills.
  • Frontend folder — application code from larapilot-implement tasks with repo: frontend. No Larapilot workflow here.
  • Mockups — always in Laravel .larapilot/mockups/; Joe implements in the FE folder.

End-to-end

Walkthrough: External frontend repo example.

  1. Inception → API + external frontend + absolute path → frontend-set
  2. frontend-scan when the FE already has code
  3. /larapilot-spec → plan → implement (BE + FE tasks from Laravel)
PRD edits happen on Laravel only. The FE repo never holds a mirrored PRD.

Code quality

Every Larapilot project stays compatible with Larastan (PHPStan level 5+) and Laravel Pint. Introduced in v2.3.1 — not optional after install.

What install scaffolds

Artifact Purpose
phpstan.neon.dist Larastan extension, level: 5, paths app/ · bootstrap/ · config/ · database/ · routes/ · tests/
pint.json Laravel preset — code style linter/formatter
composer.json require-dev: larastan/larastan, laravel/pint; scripts lint, lint:check, analyse

Run the gate

Check-only (CI / before merge)
php artisan larapilot:quality
Apply Pint formatting, then Larastan
php artisan larapilot:quality --fix

Equivalent Composer shortcuts after composer install:

composer.json scripts
composer lint:check   # pint --test
composer analyse      # phpstan analyse --memory-limit=1G

When to run

  • Implement/larapilot-implement runs larapilot:quality on Laravel tasks before each task-done
  • CI — add php artisan larapilot:quality (or composer lint:check && composer analyse) on every PR; failing Pint or Larastan blocks merge
  • Health checklarapilot:doctor reports quality_pint, quality_larastan, and quality_packages; install is not healthy when the gate is missing

Rules

  • Minimum level 5 — never lower level in phpstan.neon(.dist) without an explicit human waiver
  • Legacy codebases — generate a baseline with vendor/bin/phpstan analyse --generate-baseline (see Larastan docs); do not drop below level 5 for new code
  • larapilot:install --skip-composer — write config files only; run composer require --dev larastan/larastan laravel/pint yourself
Andrew + Jack own the gate — Pint for style, Larastan for static analysis. Robert flags regressions at review when quality was skipped.

Backstage portal

Larapilot is repo-level; Backstage is org-level. The integration publishes .larapilot/ into the developer portal — a catalog entity, a TechDocs site built from the PRD and backlog, and a live delivery snapshot. The direction is one-way: the workspace stays the source of truth, and workflow state never changes from the portal.

When it is worth it

Situation Recommendation
No Backstage in the organization Skip it — the dashboard already covers a single repo
Backstage exists, one Laravel repo Catalog entity + TechDocs — the PRD and backlog become discoverable next to every other service
Backstage with several Larapilot repos The real payoff — an entity provider polling /backstage gives one org-wide view of delivery state

Generate

Editor
/larapilot-backstage

The skill asks for owner, system, and lifecycle, persists them to .env, then generates. Equivalent CLI:

Terminal
php artisan larapilot:backstage-export           # preview the bundle — writes nothing
php artisan larapilot:backstage-export --write   # generate catalog + TechDocs
php artisan larapilot:backstage-export --write --force        # overwrite existing files
php artisan larapilot:backstage-export --write --no-techdocs  # catalog entity only
Generated Contents Overwritten?
catalog-info.yaml (repo root) Component entity, plus one API entity per OpenAPI contract found (storage/api-docs/api-docs.json, openapi.json, docs/openapi.json, .larapilot/openapi-product.json) Only with --force
mkdocs.yml (repo root) TechDocs config — docs_dir: .larapilot/techdocs, plugin techdocs-core, nav over PRD and backlog Only with --force
.larapilot/techdocs/ index.md (delivery snapshot), prd.md, backlog/index.md, backlog/US-XXX.md (spec body, plan, task checklist) Always — pages for deleted specs are pruned

The two root files may already belong to the project (an existing catalog entry, an existing MkDocs site), so Larapilot keeps them unless you pass --force; the envelope's data.hint names what was kept. Everything under .larapilot/techdocs/ is generated output — fix the PRD or the spec and regenerate rather than editing a page.

Catalog entity

catalog-info.yaml
apiVersion: backstage.io/v1alpha1
kind: Component
metadata:
  name: acme-shop
  namespace: default
  title: 'Acme Shop'
  description: 'A thing.'          # PRD elevator pitch, when present
  annotations:
    backstage.io/techdocs-ref: 'dir:.'
    larapilot.io/version: 2.2.0
    larapilot.io/workspace: .larapilot
    larapilot.io/prd: .larapilot/docs/PRD.md
    larapilot.io/board-url: 'https://staging.acme.test/larapilot'
    larapilot.io/api-url: 'https://staging.acme.test/larapilot/api'
  tags: [laravel, larapilot]
spec:
  type: service
  lifecycle: production
  owner: 'group:default/platform'
  system: commerce
  providesApis:
    - acme-shop-api
---
apiVersion: backstage.io/v1alpha1
kind: API
metadata:
  name: acme-shop-api
  title: 'Acme Shop API'
spec:
  type: openapi
  lifecycle: production
  owner: 'group:default/platform'
  definition:
    $text: ./openapi.json          # resolved by Backstage relative to this file

The name defaults to a slug of app.name, the description to the PRD Elevator Pitch (falling back to the composer description), and the larapilot.io/* annotations let a plugin locate the board and API for this entity.

Catalog identity

Identity describes the org catalog, not the delivery workflow — so it lives in Laravel config and .env, not in .larapilot/config.yaml. Never set it with larapilot:settings-set.

Env var Default Purpose
LARAPILOT_BACKSTAGE_ENABLED true Master switch — false also hides the API endpoints
LARAPILOT_BACKSTAGE_OWNER guests Set this. Backstage Group/User that owns the entity (platform or group:default/payments); unresolvable owners show as dangling refs
LARAPILOT_BACKSTAGE_SYSTEM Parent System entity, when your org models them
LARAPILOT_BACKSTAGE_LIFECYCLE experimental experimental · production · deprecated
LARAPILOT_BACKSTAGE_COMPONENT_TYPE service service · website · library
LARAPILOT_BACKSTAGE_NAME slug of app.name Entity name override (also _TITLE, _DESCRIPTION, _NAMESPACE)
LARAPILOT_BACKSTAGE_BASE_URL app.url Base URL for catalog links and annotations — non-production only
LARAPILOT_BACKSTAGE_TECHDOCS true Generate the TechDocs site alongside the catalog entity
LARAPILOT_BACKSTAGE_WORKFLOW_API false Also register the dev-only Larapilot API as its own API entity — tooling, not a product contract

php artisan larapilot:config-show reports the resolved mapping under data.backstage (entity ref, owner, system, lifecycle, TechDocs paths, whether the catalog file exists).

TechDocs

MkDocs config and sources are generated together, so Backstage builds the docs site straight from the repository:

mkdocs.yml
site_name: 'Acme Shop'
site_description: 'A thing.'
docs_dir: .larapilot/techdocs
plugins:
  - techdocs-core
nav:
  - Overview: index.md
  - 'Product Requirements': prd.md
  - Backlog:
      - Overview: backlog/index.md
      - 'US-001 — Login': backlog/US-001.md

Specs and plans are YAML on disk, so each story page is rendered to Markdown: status/priority/points/epic table, task progress, internal-feedback counts, then the spec body, the technical plan, and the task checklist. Internal feedback bodies stay in the repo — only counts are published.

Live delivery data

For a Backstage frontend plugin or entity provider, two endpoints share the API gate (dev/staging only):

Endpoint Use
GET /larapilot/api/backstage Entities, rendered YAML, TechDocs metadata, and snapshot — metrics, per-status counts, blocking feedback, and a story list without spec bodies or plan text, so a portal can poll many repos cheaply
GET /larapilot/api/backstage/catalog-info.yaml The same entities as a YAML descriptor, consumable as a Backstage url location
GET /larapilot/api/backstage → data.snapshot (excerpt)
{
  "entity_ref": "component:default/acme-shop",
  "metrics": { "total": 12, "done": 5, "completion_rate": 41.7, "total_tasks": 61, "done_tasks": 40 },
  "counts_by_status": { "TODO": 5, "PLANNED": 2, "IN PROGRESS": 1, "REVIEW": 1, "DONE": 3 },
  "blocking_feedback": { "count": 1, "specs": ["US-003"] },
  "stories": [
    {
      "code": "US-001", "title": "Login", "status": "PLANNED", "priority": "HIGH", "points": 3,
      "tasks": { "total": 2, "done": 0 }, "blocking_feedback": 0,
      "techdocs_path": "backlog/US-001.md"
    }
  ],
  "links": { "board": "https://staging.acme.test/larapilot", "api": "https://staging.acme.test/larapilot/api" }
}
Proxy the API, never expose it. Call these endpoints through the Backstage backend proxy so LARAPILOT_API_TOKEN stays server-side — never from browser code, and never against a production host (the API returns 404 there by design). If the portal cannot reach a dev/staging environment, ship the committed catalog-info.yaml and TechDocs instead of the live endpoints.

Register & keep fresh

  • Commit catalog-info.yaml, mkdocs.yml, and .larapilot/techdocs/ on the default branch.
  • In Backstage: Create → Register existing component → paste the repo URL of catalog-info.yaml. Orgs with catalog discovery configured skip this step.
  • TechDocs builds from mkdocs.yml; the backstage.io/techdocs-ref: dir:. annotation is already set.
  • Regenerate after PRD, backlog, or plan changes — a CI job on the default branch running --write --force and committing the diff keeps the portal from drifting.

Personas & boundaries

  • Matt — owns the catalog mapping: owner, system, lifecycle, which APIs get registered
  • Jack — CI regeneration and environment reachability
  • Albert — TechDocs nav and readability
  • Lars — token/proxy boundary; the portal is never pointed at production
The portal renders; it does not drive. Backstage is a read surface over .larapilot/. Scope changes still go through /larapilot-inception, /larapilot-feature, or the PRD living document, and status still moves only through skills and Artisan.

Project trackers

Optional, API-key based sync between the backlog and the tool the rest of the organisation already lives in — Linear, Asana, Jira, Trello, ClickUp, or Monday. A PM or a client follows delivery without ever opening backlog.yaml. The workspace stays the source of truth; the tracker is a window, not a second workflow.

When it is worth it

Situation Recommendation
Solo dev, no external stakeholders Skip it — the dashboard at /larapilot already shows the board
Client or PM tracks work in their own tool Push the backlog so they see progress where they already look
Team runs sprints in Jira/Linear alongside the code Push after planning, pull before standup to catch drift
You want the tracker to drive the workflow Not supported by design — status moves through skills and Artisan

Setup

/larapilot-tracker

The skill picks the provider, tells you where to generate the API key, writes it to .env, validates the status map against the real board, dry-runs, then pushes. By hand:

php artisan larapilot:tracker-status --ping   # credentials + target board
php artisan larapilot:tracker-push --dry-run  # what would change, no API calls
php artisan larapilot:tracker-push            # backlog → tracker
php artisan larapilot:tracker-pull            # tracker → drift report (read-only)
php artisan larapilot:tracker-pull --apply    # write mapped statuses back

What gets mirrored

Provider Auth Destination Plan tasks become Status maps to
Linear personal API key team key (ENG) sub-issues workflow state
Jira (Cloud, REST v2) email + API token project key subtasks status, via a workflow transition
Asana personal access token project gid subtasks section (DONE also marks complete)
Trello key + token board id checklist items list (board column)
ClickUp personal token pk_… list id subtasks list status
Monday API token board id subitems status-column label

A user story becomes an issue titled US-XXX — Title carrying the spec body, priority, points, and epic. Plan tasks are mirrored as native subtasks, not a checklist buried in the description. One provider is active at a time, but links are stored per provider — switching tools, or switching back, never loses the mapping.

Push writes, pull reports

The direction is deliberately asymmetric. Push is authoritative: .larapilot/ decides what a story says and which column it sits in, and unchanged stories are skipped without an API call. Pull is a report — it lists drift and changes nothing until you pass --apply.

  • DONE is never applied from a tracker. DONE is a human review gate that records the merge commit — it stays with /larapilot-review and larapilot:spec-approve.
  • Spec text is never read back. Titles, bodies, and acceptance criteria are owned by .larapilot/; the card description says so, and edits made in the tracker are overwritten on the next push.
  • TODO and PLANNED sharing one column is normal and is not drift — a story is in sync when its forward mapping matches the remote label.
  • A remote status outside the map is reported as drift with no suggestion, never guessed at.

Set LARAPILOT_TRACKER_PULL_COMMENTS=true to import tracker comments as internal feedback — non-blocking, and imported once each.

Configuration

Env var Default Purpose
LARAPILOT_TRACKER_ENABLED false Master switch for the integration
LARAPILOT_TRACKER_PROVIDER linear · asana · jira · trello · clickup · monday
LARAPILOT_TRACKER_SYNC_TASKS true Mirror plan tasks as native subtasks
LARAPILOT_TRACKER_PULL_COMMENTS false Import remote comments as internal feedback
LARAPILOT_MONDAY_DESCRIPTION_COLUMN Monday items have no description field — point this at a long-text column

Per-provider credentials follow the same shape: LARAPILOT_LINEAR_API_KEY / _TEAM, LARAPILOT_JIRA_BASE_URL / _EMAIL / _API_TOKEN / _PROJECT, LARAPILOT_ASANA_TOKEN / _PROJECT, LARAPILOT_TRELLO_KEY / _TOKEN / _BOARD, LARAPILOT_CLICKUP_TOKEN / _LIST, LARAPILOT_MONDAY_TOKEN / _BOARD. Status maps live in config/larapilot.phptracker.providers.{provider}.status_map. If a mapped column does not exist, the push fails and names the columns that do — Larapilot never creates columns in your tracker.

Personas & boundaries

  • Matt — provider choice, status mapping, link hygiene
  • Mark — what non-developers should see on the board
  • Jack — the CI push step on the default branch
  • Lars — the credential boundary: API keys live in .env, never in .larapilot/
Credentials never enter the repo. The tracker key is write-capable on a third-party workspace — a tighter boundary than the read-only Larapilot API. It belongs in .env and CI secrets. config-show and tracker-status report whether a credential is present, never its value. .larapilot/tracker.yaml is committed on purpose — it holds the spec → remote-id map so the team shares one mapping instead of each machine creating duplicate cards, and it contains identifiers only.

Artisan CLI

Optional and under the hood. Skills call these commands — you do not need to memorize them. They persist artifacts, validate YAML/Markdown, enforce workflow guards, and return structured JSON for the agent to parse.

You interact via skills. The CLI is the persistence layer agents use internally. Run commands manually only for debugging, scripting, or CI — e.g. php artisan larapilot:doctor to verify install health.

JSON envelope

stdout — every command
{
  "schema": "larapilot/v1",
  "kind": "plan_result",
  "data": { "code": "US-001", "task_count": 4 }
}

Errors return "kind": "error" with code, message, and optional hint. Skills never invent persistence — they always go through these commands.

Command reference

Category Commands Used by
Setup larapilot:install · larapilot:update · larapilot:doctor · larapilot:config-show · larapilot:settings-set · larapilot:github-status · larapilot:gitlab-status · larapilot:bitbucket-status · larapilot:notify · larapilot:quality (--fix) Install, upgrades, health check, code quality, project settings, optional forges/notifications
Runtime larapilot:diagnostics (--lines=, --no-logs) /larapilot-bug, local triage — see Diagnostics
PRD larapilot:frontend-set · larapilot:frontend-scan /larapilot-inception, /larapilot-feature, /larapilot-frontend-companion
Backlog larapilot:spec-list · larapilot:spec-add · larapilot:spec-show · larapilot:spec-next · larapilot:spec-delete · larapilot:validate-spec · larapilot:spec-comment /larapilot-spec, shortcuts, dashboard comments
Planning larapilot:spec-plan · larapilot:validate-plan /larapilot-plan
Execution larapilot:spec-start · larapilot:quality (--fix) · larapilot:task-done · larapilot:spec-review /larapilot-implement — see Code quality
Review larapilot:spec-approve · larapilot:spec-request-changes (--include-feedback) /larapilot-review
Metrics larapilot:metrics Dashboard, progress reporting
Usage (Lucille) larapilot:usage-log · larapilot:usage-report (--insights · larapilot:schedule-set · larapilot:choices-set /larapilot-usage, inception deadlines — see Usage
Developer portal larapilot:backstage-export (--write, --force, --no-techdocs, --file=, --api-base=) /larapilot-backstage, CI catalog refresh — see Backstage portal
Project tracker larapilot:tracker-status (--ping) · larapilot:tracker-push (--dry-run, --spec=, --force) · larapilot:tracker-pull (--apply) /larapilot-tracker, CI backlog sync — see Project trackers

MCP exposes backlog, spec, and diagnostics tools — larapilot server alongside laravel-boost. Skills prefer CLI for writes; MCP is for read/query during conversation (including larapilot:diagnostics, larapilot:quality, larapilot:usage-report, and larapilot:backstage-export via RunArtisanTool).

Dashboard

Read-only web UI over the artifacts in .larapilot/. Review backlog progress, read the PRD, inspect settings/choices, and Lucille usage — then drill into spec detail between skill sessions. You can also post internal feedback comments from the spec page (dev/staging only) — workflow state still changes only via skills/CLI.

Activation

The dashboard is on by default after php artisan larapilot:install. Routes register automatically when the package boots. All of the following must be true:

  • LARAPILOT_ENABLED=true (default) — master switch in config/larapilot.php
  • LARAPILOT_DASHBOARD_ROUTE=true (default) — dashboard route toggle
  • App environment is not production
  • Environment is in the allowlist: local, development, testing, or staging

Start your Laravel app (php artisan serve, Sail, Herd, etc.) and open /larapilot. If routes 404, check APP_ENV and the flags above.

config/larapilot.php — dashboard_route
'dashboard_route' => [
    'enabled' => env('LARAPILOT_DASHBOARD_ROUTE', true),
    'prefix' => 'larapilot',           // change to customize URL prefix
    'middleware' => ['web'],
    'environments' => ['local', 'development', 'testing', 'staging'],
],

Pages

Tab URL What you see
Board /larapilot Kanban backlog — specs grouped by workflow status (TODODONE)
PRD /larapilot/prd Rendered PRD.md with a section table of contents
Settings /larapilot/settings Current settings.* + allowed options; visual summary of inception choices.yaml
Usage /larapilot/usage Lucille charts (tokens/time by category), living Gantt (specs + milestones), download /larapilot/usage/report.md
API docs /larapilot/api/docs Interactive OpenAPI browser for the workflow JSON API

Board

Summary metrics at the top: total specs, done count, completion rate, and WIP. Each workflow column lists spec cards — code, title, epic, story points, priority, subtask progress bar, mockup indicator when HTML exists, pill badges for comment and blocking counts when feedback exists, and merge-request link when the story is DONE.

PRD

The living product document from /larapilot-inception (and later /larapilot-feature or /larapilot-bug updates). Headings become anchor links in the sidebar; the body is rendered Markdown — the same file skills write to .larapilot/docs/PRD.md.

Settings & Usage

Settings shows the live project modes (effort, backlog, git, testing, auto-approve, lucille, forges, notifications) and the inception choices snapshot. Usage is Lucille's surface — category breakdowns, schedule Gantt, and a one-click Markdown resoconto. Same data as larapilot:usage-report --insights / /larapilot-usage.

Spec detail

Click any card to open /larapilot/specs/{code}:

  • User story — acceptance criteria and narrative from the spec YAML
  • Mockups — when /larapilot-design created HTML in .larapilot/mockups/{code}/, an embedded preview and screen links appear (served via /mockups/{code} in dev/staging)
  • Internal feedback — accordion list of PM/dev comments (author, date, status, preview); blocking items show a Needs rework badge. Post new comments with a Markdown toolbar and compact footer (blocking checkbox, log path) until the story is DONE. Toggle globally with LARAPILOT_COMMENTS_ENABLED.
  • Technical plan — plan Markdown once /larapilot-plan has run
  • Tasks — expandable subtasks with status, type, body, and commit SHA when marked done

Status badge, story points, and merge commit appear in the header. The dashboard mirrors repo state — skills remain the only way to change it.

API

JSON API over the same artifacts as the dashboard. Read endpoints for scripts, CI dashboards, external frontend repo setup, bug-triage diagnostics, or tooling; POST /specs/{code}/comments appends internal feedback when enabled. Workflow state still changes only via skills/CLI.

Activation

API routes share the dashboard gate: enabled when dashboard activation conditions are met. Base path: /{prefix}/api (default /larapilot/api). Returns 404 in production or when disabled.

Authentication

Set LARAPILOT_API_TOKEN to require a shared token on every API request — send it as Authorization: Bearer <token> or an X-Larapilot-Token header. Strongly recommended on shared staging hosts. Without a token configured, read endpoints stay open in the allowed environments, but write endpoints (POST /comments) are refused outside local/development/testing.

Endpoints

Method Path Returns
GET /larapilot/api/board Metrics, status order, and specs grouped by workflow column — each spec includes mockups.screens (absolute preview URLs) and a counts-only feedback summary
GET /larapilot/api/specs All specs with task progress, mockup screens, and counts-only feedback summaries; optional ?status=TODO filter
GET /larapilot/api/specs/{code} Single spec with plan body, tasks, workdir, task progress; each spec embeds mockups.screens (absolute preview URLs) and feedback.entries
POST /larapilot/api/specs/{code}/comments Append internal feedback — JSON body: author, message, optional blocks_merge. Returns 201 with updated feedback snapshot.
GET /larapilot/api/prd PRD Markdown content and parsed heading index
GET /larapilot/api/backstage Backstage catalog entities, rendered catalog-info.yaml, TechDocs metadata, and a lean delivery snapshot for a portal plugin. Full guide: Backstage portal.
GET /larapilot/api/backstage/catalog-info.yaml The same entities as a multi-document YAML descriptor — consumable as a Backstage url location
GET /larapilot/api/diagnostics Read-only runtime snapshot for bug triage — see Diagnostics
GET /larapilot/api/openapi.json Machine-readable OpenAPI 3 document (auto-generated)
GET /larapilot/api/docs Swagger UI — try requests in the browser

Diagnostics

Read-only app status for /larapilot-bug and local debugging. Same dashboard gate as the rest of the API (never in production). Disable with LARAPILOT_DIAGNOSTICS_ENABLED=false (returns 404).

Surface Usage
API GET /larapilot/api/diagnostics — optional ?lines=100, ?no_logs=1
CLI php artisan larapilot:diagnostics--lines=, --no-logs
MCP Larapilot diagnostics tool, or RunArtisanToollarapilot:diagnostics

Checks: storage_writable, cache, database, queue, log_file. healthy is true when critical checks (storage + database) pass. Log lines redact secrets ([REDACTED]). Defaults: LARAPILOT_DIAGNOSTICS_LOG_LINES=100, LARAPILOT_DIAGNOSTICS_MAX_LOG_LINES=500.

GET /larapilot/api/diagnostics?no_logs=1
{
  "collected_at": "2026-07-24T16:00:00+00:00",
  "app": {
    "name": "My App",
    "env": "local",
    "debug": true,
    "laravel_version": "13.x",
    "php_version": "8.4.0"
  },
  "checks": {
    "storage_writable": { "ok": true, "detail": "…" },
    "cache": { "ok": true, "detail": "…" },
    "database": { "ok": true, "detail": "…" },
    "queue": { "ok": true, "detail": "…" },
    "log_file": { "ok": true, "detail": "…" }
  },
  "healthy": true
}

Response shape

Plain JSON — not the larapilot/v1 CLI envelope. Example from /larapilot/api/board:

GET /larapilot/api/board
{
  "metrics": { "total": 3, "done": 1, "completion_rate": 33.3, "wip": 1 },
  "status_order": ["TODO", "PLANNED", "IN PROGRESS", "REVIEW", "DONE"],
  "columns": {
    "TODO": [{
      "code": "US-002",
      "title": "Project Management",
      "task_progress": { "total": 0, "done": 0 },
      "mockups": { "available": false, "screen_count": 0, "screens": [] },
      "feedback": { "enabled": true, "available": false, "entry_count": 0, "blocking_count": 0, "writable": true, "entries": [] }
    }],
    "DONE": [{
      "code": "US-001",
      "title": "User Registration",
      "task_progress": { "total": 4, "done": 4 },
      "mockups": {
        "available": true,
        "screen_count": 2,
        "entry_url": "https://app.test/mockups/US-001",
        "screens": [
          { "file": "index.html", "label": "Index", "url": "https://app.test/mockups/US-001" },
          { "file": "desktop.html", "label": "Desktop", "url": "https://app.test/mockups/US-001/desktop.html" }
        ]
      },
      "feedback": {
        "enabled": true,
        "entry_count": 1,
        "blocking_count": 0,
        "writable": true,
        "entries": [
          { "at": "2026-07-15 17:00", "author": "PM", "status": "REVIEW", "body": "Looks good.", "blocks_merge": false }
        ]
      }
    }]
  },
  "workflow": { "todo": "TODO", "planned": "PLANNED", "in_progress": "IN PROGRESS", "review": "REVIEW", "done": "DONE" }
}

No authentication is built in — the API is intended for local/dev use behind your existing app middleware. Do not expose it in production (routes are not registered there). Mockup preview URLs are absolute in API responses when the mockup route is browsable. Comment writes honor LARAPILOT_COMMENTS_ENABLED and reject DONE specs with 422. Diagnostics honor LARAPILOT_DIAGNOSTICS_ENABLED and redact secrets in log tails.

Ready to ship with AI?

Install Larapilot and give your agent a real product process.

Get started →