shahghasiadil / laravel-bruno-generator
Generate Bruno API collections from Laravel routes with automatic request body inference and environment support
Package info
github.com/shahghasiadil/laravel-bruno-generator
pkg:composer/shahghasiadil/laravel-bruno-generator
Requires
- php: ^8.3
- illuminate/console: ^10.0|^11.0|^12.0|^13.0
- illuminate/contracts: ^10.0|^11.0|^12.0|^13.0
- illuminate/filesystem: ^10.0|^11.0|^12.0|^13.0
- illuminate/routing: ^10.0|^11.0|^12.0|^13.0
- illuminate/support: ^10.0|^11.0|^12.0|^13.0
- symfony/yaml: ^6.0|^7.0
Requires (Dev)
- larastan/larastan: ^2.9|^3.0
- laravel/pint: ^1.14
- mockery/mockery: ^1.6
- nunomaduro/collision: ^7.10|^8.0
- orchestra/testbench: ^8.0|^9.0|^10.0|^11.0
- pestphp/pest: ^2.34|^3.0|^4.0
- pestphp/pest-plugin-arch: ^2.7|^3.0|^4.0
- pestphp/pest-plugin-laravel: ^2.4|^3.0|^4.0
- phpstan/extension-installer: ^1.3
- phpstan/phpstan-deprecation-rules: ^1.1|^2.0
- phpstan/phpstan-phpunit: ^1.3|^2.0
- phpstan/phpstan-strict-rules: ^1.5|^2.0
This package is auto-updated.
Last update: 2026-08-19 11:34:55 UTC
README
Generate Bruno API collections from Laravel routes.
This package analyzes your Laravel application's routes and generates a ready-to-use Bruno collection, complete with request bodies inferred from FormRequests, authentication configuration, environment files, and more.
Installation
You can install the package via composer:
composer require shahghasiadil/laravel-bruno-generator --dev
Publish the config file:
php artisan vendor:publish --tag=bruno-generator-config
Quick Start
Generate a collection:
php artisan bruno:generate
Default output:
bruno/collections/Laravel-API/
Open that folder in Bruno using Open Collection.
Features
- One-command generation from Laravel routes
- FormRequest body inference
- Route filtering (middleware, prefix, include/exclude)
- Multiple organization strategies (
prefix,controller,tag,none) - Auth support (
none,bearer,basic,oauth2), with protected routes pointing at a shared collection-level auth block (auth: inherit) - Real Bruno path parameters (
:id+params:path) and query parameters inferred from FormRequest rules, with example values informed bywhere()route constraints when present - Multi-environment generation (
Local,Staging,Productionby default) - Optional docs, tests, and scripts generation
.bruand OpenCollection YAML (.yml) output support- Deterministic, git-friendly generated files
bruno:checkdrift detection for CI — regenerates in memory and exits non-zero if the committed collection is out of date
Usage
Common commands
Generate with default settings:
php artisan bruno:generate
Generate YAML output:
php artisan bruno:generate --format=yaml
Generate only API routes protected by Sanctum:
php artisan bruno:generate --api-only --middleware=auth:sanctum
Generate with docs and tests:
php artisan bruno:generate --with-docs --with-tests
Preview without writing files:
php artisan bruno:generate --dry-run
Overwrite existing output:
php artisan bruno:generate --force
Clear generated collection:
php artisan bruno:clear
Clear a custom path:
php artisan bruno:clear path/to/collection --force
Check whether the committed collection has drifted from what your routes currently produce (regenerates in memory, writes nothing, exits non-zero on drift — useful as a CI gate):
php artisan bruno:check
bruno:check accepts the same filtering/format options as bruno:generate
(--format, --output, --name, --api-only, --prefix,
--exclude-prefix, --middleware, --exclude-middleware, --group-by) so
you can check the same slice of routes you'd generate. Add --verbose to
list which files would be added, changed, or are orphaned on disk.
All generate options
php artisan bruno:generate \ --format=bru|yaml \ --output=path/to/output \ --name="My API" \ --api-only \ --prefix=api/v1 \ --exclude-prefix=admin \ --middleware=auth:sanctum \ --exclude-middleware=web \ --group-by=prefix|controller|tag|none \ --with-body-inference \ --with-tests \ --with-scripts \ --with-docs \ --force \ --dry-run
Configuration
You can control most behavior through .env:
BRUNO_OUTPUT_PATH=bruno/collections BRUNO_COLLECTION_NAME="Laravel API" BRUNO_OUTPUT_FORMAT=bru BRUNO_GROUP_BY=prefix BRUNO_INFER_BODY=true BRUNO_AUTH_MODE=bearer APP_URL=http://localhost:8000 STAGING_URL=https://staging.example.com PRODUCTION_URL=https://api.example.com
After publishing, full options are available in config/bruno-generator.php.
Key config sections
output_path,collection_name,output_formatroute_discoveryfor include/exclude rulesorganizationfor grouping and sortingrequest_generationfor body/query/header behaviorauthfor mode and auth middleware detectionenvironmentsfor generated Bruno environmentsadvancedfor docs length, tests, scripts, YAML options, request settings
FormRequest Body Inference
When enabled, request bodies are generated from your FormRequest rules.
Example FormRequest rules:
public function rules(): array { return [ 'name' => 'required|string|max:255', 'email' => 'required|email', 'age' => 'integer|min:18', 'is_active' => 'boolean', 'tags' => 'array', 'tags.*' => 'string', ]; }
Example generated body:
{
"name": "Name",
"email": "user@example.com",
"age": 18,
"is_active": true,
"tags": [""]
}
Nested rules like user.name and user.email are also supported.
Other rules that shape the generated example:
in:draft,published,archiveduses the first listed value (draft)between:5,20on an integer/numeric field uses the lower bound (5), same asmin:- A
fileorimagerule on any field switches the whole request to amultipart-formbody instead of JSON
Output Formats
Both output formats are supported:
bru(default)yaml
Use command flag:
php artisan bruno:generate --format=yaml
Or environment variable:
BRUNO_OUTPUT_FORMAT=yaml
Environments
By default, the package generates:
LocalStagingProduction
Each environment contains values like baseUrl and authToken and can be switched in Bruno.
You can add custom environments (for example Development, QA, UAT) in config/bruno-generator.php.
Secret variables
Variable names listed in secrets.variable_names (authToken by default)
are never written to the generated environment file — Bruno manages their
real value separately (OS keychain, or AES256 as a fallback), and you set it
through Bruno's environment UI after opening the collection. In .bru
output this looks like a name-only vars:secret [...] block; in YAML output
the variable gets secret: true and an empty value.
Use the array shape to mark a custom variable as secret, or add a description:
'environments' => [ 'Staging' => [ 'baseUrl' => env('STAGING_URL', 'https://staging.example.com'), 'apiKey' => [ 'value' => env('STAGING_API_KEY', ''), 'description' => 'API key issued by the staging gateway', 'secret' => true, ], ], ],
Descriptions are a Bruno 4 addition; set bruno_compatibility to v3 to
omit them if your collection needs to open in an older Bruno.
Generated Structure
Typical output:
bruno/collections/Laravel-API/
bruno.json
environments/
Local.bru
Staging.bru
Production.bru
api/
...requests and folders...
Best Practices
- Use
--dry-runbefore first full generation - Keep route filters explicit in larger projects
- Commit generated collections to track API changes
- Keep environment URLs in
.env - Let
authToken(and other secrets) stay a secret variable rather than disablingsecret: false— its real value never gets written to disk - Run
php artisan bruno:checkin CI to catch a committed collection that's drifted from the routes it was generated from
Testing
Run tests:
composer test
Run static analysis:
composer analyse
Format code:
composer format
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
If you discover any security-related issues, please email adil.shahghasi@gmail.com.
Credits
License
The MIT License (MIT). Please see License File for more information.