labrodev / kalimera
Interactive installer that scaffolds Laravel applications the Labrodev way.
Requires
- php: ^8.4
- laravel/prompts: ^0.3
- symfony/process: ^7.0
Requires (Dev)
- laravel/pint: ^1.20
- mockery/mockery: ^1.6
- pestphp/pest: ^4.0
- phpstan/phpstan: ^2.0
- rector/rector: ^2.0
README
Interactive installer that scaffolds a fresh Laravel application — one
guided CLI flow from laravel new to a fully configured, quality-checked, Sail-running app with all the tools you need.
Instead of a boilerplate — a frozen copy of someone else's choices that goes stale — kalimera
automates the initialization step itself: a fresh, current Laravel application prepared exactly
the way you want it, the same way every time. Your package set is defined once in
kalimera.config.json (the built-in catalog is the Spatie collection — replace it with your
own), Pint + PHPStan + Rector and Sail are wired from the first commit, every choice is made
at once upfront, and the whole run is unattended — driven by you or by your coding agent
through the agent skill. A ready-to-build project in minutes, no manual
setup each time.
Requirements
- PHP 8.4+, Composer, the Laravel installer, Docker, git
Installation
Global (recommended)
Install once, use kalimera from anywhere — same mechanism as the laravel installer.
While the package is not yet on Packagist, register this repo as a path repository in your global composer (the symlink means every local change to the repo is instantly live):
composer global config repositories.kalimera '{"type": "path", "url": "/path/to/laravel-kalimera", "options": {"symlink": true}}'
composer global require labrodev/kalimera:@dev
(:@dev is needed because a path repository has no tagged releases — the package only exists
as dev-main, and composer's default stability is stable.)
Make sure composer's global bin directory (~/.composer/vendor/bin or
~/.config/composer/vendor/bin) is in your PATH — if the laravel command works, it already is.
Once published to Packagist, this becomes simply:
composer global require labrodev/kalimera
Local (no global install)
cd laravel-kalimera && composer install
Then call the binary by its full path from wherever the new app should live:
cd ~/www /path/to/laravel-kalimera/bin/kalimera new
The app is created in the current working directory — don't run kalimera from inside this repo unless you want the app scaffolded into it.
Usage
kalimera new # prompts for everything, creates ./<app-name> kalimera new my-app # skip the name prompt kalimera new ~/www/my-app # a path works too — the app is created exactly there
Options:
| Flag | Effect |
|---|---|
--dry-run |
Print every command without executing anything |
--defaults |
Skip all prompts and accept the preselected answers |
--continue |
Resume into an existing app directory after a failed run — the answers saved in its .kalimera.json are reused, no prompts (the file is written after laravel new and removed when the scaffold completes) |
--config=path |
Load the preselected answers and the additional-packages catalog from a JSON config — see Configuration. kalimera.config.json in the current directory is picked up automatically |
--log[=path] |
Write an append-only transcript of steps, commands and outcomes to a log file (defaults to kalimera.log inside the new application, gitignored there) |
What it does
- Prompts for everything upfront: app name, starter kit (React / Vue / Livewire / Svelte /
none, with optional manual Inertia), ecosystem packages (Horizon, Fortify, Laravel AI,
Nightwatch), Sail services,
PHP version constraint (default
^8.5), quality tools, additional packages, Postmark, GitHub repos for Boost skills, and any extra packages — then shows a summary and one final confirm. laravel newwith Pest and git, no interaction.- Installs Sail with the chosen services, pins the Sail runtime to the chosen PHP version,
remaps any host ports that are already busy (
APP_PORT,FORWARD_DB_PORT, …) so parallel projects never clash, and boots the containers (sail up -d --wait). Everything after this point runs through Sail, so the host PHP version never matters. - Restricts
require.phpin composer.json to the chosen constraint. - Sets up Pint / PHPStan (Larastan + IDE Helper) / Rector with ready-made configs
(
pint.json,phpstan.neon.dist,rector.php) and composer scripts:pint:dry,pint:fix,phpstan,phpstan-clear,ide-helper,rector:dry,rector:fixand the aggregatequality. Generated ide-helper files are gitignored. - Installs the chosen additional packages and publishes their configs/migrations. The
built-in catalog is the Spatie collection (
laravel-data,laravel-view-models,laravel-query-builder,laravel-backup,laravel-permission,laravel-activitylog,laravel-translatable) — replace it with your own via Configuration. - Installs Laravel Boost: you pick the AI agents (Claude Code, Cursor, Codex, Copilot, …)
upfront — kalimera preconfigures
boost.jsonand runsboost:install --guidelines --skills --mcp --no-interaction, fully unattended. (Select no agents to answer Boost's own prompts instead.) Then pulls your skills from GitHub viaboost:add-skill <owner/repo> --all— one run per repository, so you can list several space- or comma-separated at the prompt. - Optionally sets up the Postmark SDK (
wildbit/postmark-php) withpostmark:push/postmark:pullcomposer scripts and aPOSTMARK_API_KEYenv placeholder. - Optionally scaffolds the Core structure:
src/{Domain,Shared,Support,Feature,Infrastructure}with.gitkeepfiles, mapped to a PSR-4 namespace of your choice (Coreby default). - Installs the AI-agent guard: publishes
app/Providers/AgentGuardServiceProvider.phpand registers it last inbootstrap/providers.php, so destructive database commands (db:wipe,migrate:fresh/refresh/reset/rollback) are prohibited whenever an AI agent is driving the app — exactly as they already are in production. Detection comes fromlaravel/pao'sAgentDetector, which ships with new Laravel apps by default and recognizes Claude Code, Cursor, Codex, Copilot, Gemini and others. Registration order matters and the provider must boot afterAppServiceProvider; see TROUBLESHOOTING.md. - Finalizes: migrates,
npm install, formats the fresh skeleton with Pint + Rector, baselines PHPStan if needed socomposer qualitystarts green, and commits.
Configuration
Kalimera works with zero configuration — the built-in setup is the curated Labrodev stack.
To adapt it to your own, drop a kalimera.config.json next to where you run kalimera
(or point at one with --config=path). Everything in it is optional; whatever you omit
keeps the built-in behavior.
{
"$schema": "https://raw.githubusercontent.com/labrodev/laravel-kalimera/main/schema/kalimera.config.schema.json",
"preselected": {
"starterKit": "vue",
"sailServices": ["mysql", "redis", "mailpit"],
"phpConstraint": "^8.4",
"boostSkillRepos": ["acme/boost-skills"],
"coreNamespace": "Acme\\Core"
},
"additionalPackages": [
{
"package": "spatie/laravel-medialibrary",
"label": "medialibrary — file attachments for Eloquent models",
"preselected": true,
"publishProviders": ["Spatie\\MediaLibrary\\MediaLibraryServiceProvider"]
},
{
"package": "barryvdh/laravel-debugbar",
"label": "debugbar — in-browser debug toolbar",
"dev": true
}
]
}
preselected— the pre-chosen answers of every prompt, and exactly what--defaultsinstalls unattended. Keys mirror the prompts:starterKit,installInertia,aroundPackages,sailServices,phpConstraint,qualityTools,installPostmark,coreNamespace(nullskips the Core scaffold),boostAgents,boostSkillRepos,extraPackages,extraDevPackages.additionalPackagesreplaces the built-in Spatie catalog shown by the "additional packages" prompt. Each entry takes a composerpackage(a version constraint likevendor/package:^2.0works), an optional promptlabel,devto require with--dev,preselectedto have it chosen by default, andpublishProvidersto runvendor:publishfor after installation.
The built-in setup itself lives in
schema/kalimera.config.schema.json: each property's
enum lists the available options — what is there — and the default values of preselected
and additionalPackages are the built-in choices — what is chosen. Kalimera reads it on
start, so editing that file changes what the installer offers out of the box (your fork,
your stack), while a kalimera.config.json overrides it per project. Referencing it via
$schema gives your editor completion for every option. Validation happens in kalimera
itself: every loaded file is checked on start and unknown keys or invalid values are
refused with a precise error, so a typo fails before anything is installed, not halfway
through.
Agent skill
The repo ships a ready-made agent skill at skills/laravel-kalimera/
that teaches AI coding agents to drive kalimera end-to-end. The agent becomes the prompt layer:
it re-asks kalimera's full prompt set in its own interface (starter kit, Sail services, ecosystem
and Spatie packages, PHP constraint, quality tools, Core structure, Boost agents, …), encodes the
answers into a config JSON, and runs the installer unattended with --defaults — kalimera's own
prompts would die in the agent's non-TTY shell. It then verifies the result and resumes failed
runs. The skill is plain Markdown in the open Agent Skills format, so
any skills-aware tool can consume it.
-
Claude Code — one symlink and the skill applies to every session on the machine. After the global install above, link through composer's vendor directory — it keeps working once the package is on Packagist, and
composer global updaterefreshes the skill content:ln -s ~/.composer/vendor/labrodev/kalimera/skills/laravel-kalimera ~/.claude/skills/laravel-kalimera
(
~/.config/composer/vendor/...on Linux; linking straight to a cloned repo works too.) -
Cursor, Codex, and friends — they support the same format: copy or symlink
skills/laravel-kalimera/into the tool's skills directory (see its Agent Skills docs), or pasteSKILL.mdinto its global rules/instructions.
Layout
bin/kalimera entry point
src/ installer code (Kalimera\)
KalimeraInstaller.php the orchestrator behind `kalimera new`
Contracts/ interfaces: Pipeline, PortChecker, ProcessRunner
Exceptions/ one exception class per failure mode
Payloads/ immutable data carriers: Argument, InstallerOption
Pipelines/ the installation steps, executed in order
Services/ invokable and multi-op helpers (files, shell, sail, prompts)
schema/ kalimera.config.schema.json — the built-in setup and config file reference
skills/ agent skill that teaches AI agents to drive kalimera (see Agent skill)
templates/ pint.json, phpstan.neon.dist, rector.php shipped into generated apps
tests/ Pest suite (Kalimera\Tests\)
Quality & tests
The package dogfoods the same tooling it installs into new applications:
composer test # the full Pest suite composer quality # rector:dry + pint:dry + phpstan (level 8) + tests
Individual scripts: pint:dry / pint:fix, rector:dry / rector:fix, phpstan,
phpstan-clear and test. The same checks run in CI on PHP 8.4 and 8.5
(.github/workflows/ci.yml).
The suite is split into three Pest test suites:
tests/Unit one test file per src/ class (Services, Pipelines, Payloads)
tests/Feature in-process dry-run snapshot: the exact command sequence `kalimera new
--dry-run --defaults` produces, plus usage/exit-code behavior
tests/Arch architecture rules: strict types, readonly classes, no debug output,
pipeline contract, Services/Payloads layer boundaries
Steps talk to the outside world only through the ProcessRunner, PortChecker and
ExecutableFinder seams, so the whole installer runs in-process against fakes
(tests/Fakes/) — no Docker, network or laravel binary needed to test it.