PHP 8.3+
Installation
Docuccino generates OpenAPI documentation from the real shape of your Laravel application. It reads your routes, controllers, form requests, resources, models, and exception handling and produces an accurate document — with no annotations to start.
Requirements
Section titled “Requirements”Laravel 12 or 13
Install
Section titled “Install”-
Install the packages. Where do your docs need to be readable? That’s the only question — pick the tab that matches and paste:
Terminal window composer require docuccino/laravelcomposer require --dev docuccino/inference-phpstanReaders hit
/docs/apion a deployed environment. The adapter ships to production and serves a committed artifact or a warmed cache; the engine stays a dev dependency because analysis belongs wherever you generate, and a production host has no business reading your source.Terminal window composer require --dev docuccino/laravel docuccino/inference-phpstanYou read the docs locally and ship nothing. Everything is dev-only, so
composer install --no-devputs neither package in your productionvendor/— no service provider, no viewer route, no commands. Generate and browse/docs/apion your own machine.Terminal window composer require --dev docuccino/laravel docuccino/inference-phpstanYour docs live on an external host — ReadMe, Bump.sh, Redocly, or anything that takes an OpenAPI file. Export in CI and upload the artifact; your app never serves docs, so both packages stay dev-only. Generating in CI has the job, and
docuccino:export --out=puts the file wherever your upload step wants it.docuccino/inference-phpstangoes underrequire-devin every one of those shapes. It carries a static analyser and runs wherever you generate the document, so a production host has no business installing it.docuccino/laravelis arequire-devpackage too by default — a production dependency only in the first shape, where serving/docs/apifrom the application is its one runtime job.The engine is the same package either way: it runs PHPStan with Larastan’s model and container knowledge to read the real types in your code — a build-time job, like your test suite. It never executes your application; How it works walks the whole pipeline.
If Composer refuses to resolve here, it’s almost always a shared dependency that a framework upgrade moved ahead of Docuccino’s constraint — Dependency conflicts has the fix.
-
Run the installer:
Terminal window php artisan docuccino:installConfig──────Published docuccino.yaml.Published config/docuccino.php.Routes──────"default" documents 23 of the 30 routes this application publishes (include: api/*).Engine──────The inference engine is installed.Response shapes, query parameters and error responses are read from your code.First document──────────────Export one now? (yes/no) [yes]:One command covers the whole first run. It publishes both configuration files, tells you how many of your routes the default
api/*pattern really matches — and which prefixes they sit under when it matches none — reports whether the analysis engine is installed, and offers to write your first document.Out of the box the defaults document every
api/*route in your own application, export todocs/openapi.json, and serve an interactive viewer at/docs/api. They are already active without either published file; the files are there so you can change them.
The installer never replaces a configuration file you already have (pass --force if that’s what
you want), and it decides that per file — an application that already keeps a docuccino.yaml gets
the framework half and nothing else touched — so it is safe to run again. In a provisioning script,
--no-interaction takes the prompt’s default and exports, and --no-export finishes the setup
without one. Prefer to publish the files on their own?
php artisan vendor:publish --tag=docuccino-config writes exactly the same two.
The commands reference has every flag.
That’s it. Open docs/openapi.json, or visit /docs/api in your browser — the bundled viewer is
live in your local environment out of the box, and closed everywhere else until you name a gate.
Your first export walks through what Docuccino read and
what it produced.
What gets added
Section titled “What gets added”Artisan commands
docuccino:install, docuccino:export, docuccino:validate, docuccino:diff,
docuccino:cache, docuccino:clear, docuccino:watch, docuccino:coverage,
docuccino:explain, and docuccino:version-changes. See the
commands reference.
A built-in viewer
An interactive Scalar API reference at /docs/api, its spec at
/docs/api.json, served from your own app — no external CDN required.
Automatic integrations
Support for form requests, API resources, Eloquent models, enums, Spatie Data, Spatie Query Builder, Sanctum, Passport, and more — each activates only when you use it.
Extension points
Register your own logic from any service provider with Docuccino::extend(). Every official
integration is built with the same tools available to you.
Where things live
Section titled “Where things live”- docuccino.yaml everything a build reads — documents, routes, info, security, lint
Directoryconfig/
- docuccino.php what Laravel reads while it boots — the master switch and each viewer
Directorydocs/
- openapi.json your exported document (commit this)
Directorystorage/
Directorydocuccino/ engine scratch files and the fragment cache (add to .gitignore)
- …
Two files, and they do not overlap. Everything that shapes a document lives in docuccino.yaml,
which a command reads once per build — so nothing your application serves ever parses it. What
Laravel needs while it boots stays in config/docuccino.php: the master switch, and each
document’s viewer, whose routes are registered on every boot. Nothing left in the framework file is
merged over the other one — a build setting still sitting there is reported and ignored, never read.
config/docuccino.php is plain data besides — no imports, no class references — so a dev-only
install survives a --no-dev production boot, which loads every file in config/.
Turning it off
Section titled “Turning it off”Set DOCUCCINO_ENABLED=false and Docuccino goes completely dormant: the viewer routes are never
registered and the artisan commands refuse to run. It’s the switch to reach for on a production
host that has no business generating documentation — and one you never need if you installed
everything as a dev dependency, because there’s nothing on that host to turn off.