Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Openapi Cli Laravel Package

spatie/laravel-openapi-cli

Turn any OpenAPI spec into dedicated Laravel artisan commands with typed options for path params, query params, and request bodies. Add auth, caching, retries, and error handling, or pair with Laravel Zero to build standalone CLI tools.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package is a thin, opinionated adapter sitting between an OpenAPI document and Laravel's artisan console kernel. It does not own HTTP transport (it wraps Laravel's HTTP client), does not own the spec (it reads local or remote YAML/JSON), and does not own the command surface (it registers commands dynamically from the spec). That is a good architectural shape for us: it is additive, sits at the edge of the app, and can be removed without touching domain code. The one structural commitment it forces is that the OpenAPI spec becomes a runtime dependency of the console kernel — a malformed or unreachable spec at boot time is a console-wide failure mode, not a single-command failure. Registration happens through a facade (OpenApiCli::register(...)) in a service provider, so we control when and how it loads.

Integration feasibility. High for a Laravel shop. The API is a fluent builder: baseUrl(), auth(fn () => ...), banner(), cache(ttl: 600), followRedirects(), yamlOutput(), showHtmlBody(), useOperationIds(), onError(...), retryOn(..., maxRetries: 1). Nothing exotic is required — no DI rewiring, no queue, no migrations, no schema changes. auth() and retryOn() accept closures, so existing token-manager services (OAuth refresh, Vault, AWS Secrets Manager) plug in without a bespoke adapter. The AuthenticationException added in 1.4.0 is the piece that makes this production-shaped rather than demo-shaped: auth failures abort with a friendly message and optional hint before the request is sent, instead of surfacing as a raw 401. Estimated integration effort for a first spec: 0.5–1 engineer-day including auth wiring; each additional spec is closer to hours.

Technical risk. The dominant risk is not code quality — it is adoption signal. 42 stars and 0 dependents means we would be among the first non-Spatie production users. The changelog shows a package still finding its edges: 1.1.0 fixed path-level parameter merging, 1.0.1 fixed query parameters with invalid characters, 1.3.1 fixed options silently dropping when a parameter description spans multiple lines, and 1.5.0 changed non-JSON and HTML body handling in a way the release notes themselves flag as breaking ("If you relied on the old notice appearing in output, that is the breaking bit"). That 1.5.0 change shipped as a minor release. For us that means: pin exact versions, read every changelog, and never let Composer float the package in CI. Secondary risks: derived command names can collide when different endpoints normalize to the same slug (e.g. /books/{id}/reviews and /books/{book_id}/reviews both landing on bookstore:get-books-reviews) — useOperationIds() is the mitigation and should be treated as mandatory, not optional. Spec drift is a third risk: a remote spec change silently changes our CLI surface on the next cache expiry (cache(ttl: 600) means ten minutes of surprise window), unless the spec is vendored.

Key questions.

  • Does a non-2xx response produce a non-zero exit code, or exit 0 with the error printed? This single answer determines whether the tool is usable from shell pipelines and AI agents at all.
  • With auth() being a closure invoked per request, is the token cached anywhere, or do we pay a secrets-store round trip per command invocation?
  • What is the behavior when a $ref resolves to an external document (cross-file refs), and what is the failure message when it can't?
  • If two operations normalize to the same command name, does registration fail loudly at boot or silently drop one?
  • What is the maintenance commitment from Spatie beyond "it's open source"? Is there a paid support path, and is this package in scope for it?
  • What do onError/retryOn do to exit codes and to --output-style machine-readable modes? Retry semantics matter if we build agents on top.

Integration Approach

Stack fit. Native Laravel 11/12/13 (13 support landed in 1.4.1), PHP 8.x, artisan-first. Two distinct deployment shapes, and we should pick one deliberately rather than drift:

  1. In-app console commands. Register specs inside an existing Laravel service provider. Cheap, but the CLI surface ships with the app's release train and inherits the app's secrets, env, and dependency graph.
  2. Standalone CLI via Laravel Zero. A dedicated binary per upstream API — the README's stated intent. Cleaner blast radius, separate release cadence, and the natural home for the "useful for AI agents" use case, since a narrow binary with a fixed command set is far easier to allowlist in an agent sandbox than a general-purpose artisan kernel.

For an internal developer tool, option 1 is fine. For anything agent-facing or externally consumed, option 2.

Migration path. There is no migration — this is greenfield console surface, not a replacement for existing code. The realistic "before" state is hand-rolled HTTP calls in scripts or Postman collections, and there is no forced cutover. Treat adoption as net-new and keep the old path alive until the new commands have been exercised against a non-production tenant.

Compatibility. Three pinning decisions, all cheap and all worth doing on day one:

  • Exact version pin ("spatie/laravel-openapi-cli": "1.5.0") rather than a caret range, given the 1.5.0 precedent.
  • Vendor the OpenAPI spec into the repo rather than fetching remotely. This converts an uncontrolled runtime dependency into a reviewable diff. If remote loading is genuinely required, keep cache() on but treat spec changes as a deploy event.
  • Force useOperationIds(). Derived-from-path naming is unstable across spec edits and collision-prone.

Sequencing.

  1. Week 1 — spike. One spec, one environment, useOperationIds(), JSON/YAML output, banner off. Answer the exit-code question empirically. Deliverable: a written verdict on whether the command surface is machine-consumable.
  2. Week 2 — auth and errors. Wire auth() to the real token manager, throw AuthenticationException on missing credentials, add retryOn() for 401 and onError() for 429 with Retry-After surfaced to the user. This is where the package's value concentrates; a spec-to-CLI generator without auth handling is a toy.
  3. Weeks 3–4 — two more specs, standalone binary. Validate the Laravel Zero shape and the multi-spec registration story before committing to internal standards.
  4. Then — decide on agent exposure, which is a separate approval (sandboxing, allowlisted commands, output contract) and should not be bundled into the initial rollout.

Explicit non-goal for phase 1: no agent integration. Prove the CLI is correct and stable before anything autonomous calls it.

Operational Impact

Maintenance. Low in steady state, spiky around releases. Steady state is: spec changes require a re-pin, a re-vendor, and a smoke test of the affected commands. Spiky state is a Spatie minor release changing output behavior. Budget roughly 2–4 hours per dependency bump for verification, and treat any changelog entry mentioning output formatting as a potential breaking change regardless of the version number. The package itself is a thin layer — EndpointResolver was extracted in 1.2.0 and the codebase reads as small and single-purpose — so there is a credible fork-or-patch escape hatch if Spatie deprioritizes it. That escape hatch is the main reason the 0-dependents risk is tolerable rather than disqualifying.

Support. No commercial SLA. Spatie is a well-known, long-running agency with a paid-products business and a public security policy, but this specific package is community-supported. Internal ownership must be explicit: one named engineer owns the spec-to-command surface, the pinned version, and the smoke tests. Do not let this become everyone's tool and no one's responsibility — that is how pinned versions rot.

Scaling. Scales fine on the dimensions that matter here — number of specs, number of endpoints, command count. It does not scale on the dimension that bites: invocation volume. Every command invocation is a cold PHP process, re-reads or re-fetches the spec (mitigated by cache(ttl: 600)), resolves auth, and issues one HTTP call. That is acceptable for humans and for a handful of agent calls per minute. It is not acceptable as a high-throughput integration path — if a workflow needs thousands of API calls per hour, this is the wrong tool and we should say so early. Also watch artifact size for Laravel Zero builds that bundle large specs.

Failure modes. Ranked by likelihood and blast radius:

  • Spec unreachable or malformed → console-wide boot failure if registered eagerly in a service provider. Mitigate with lazy registration and a cached/vendored spec.
  • Silent command collision → one endpoint's command shadowed by another. Mitigate with useOperationIds(); verify the registered command list in a test.
  • Token expiry mid-run → a 401 surfaced as a raw error. Mitigate with retryOn() and AuthenticationException; test the refresh path, not just the happy path.
  • Output corruption on binary endpoints → the exact class of bug 1.5.0 fixed (a Response is not JSON notice leaking into report.pdf). Re-verify on every bump if we expose download endpoints.
  • Rate limiting → upstream 429s cascading into agent retry storms. Mitigate with onError() reading Retry-After and hard-capping maxRetries at 1.
  • Silent spec drift → remote spec changes, commands appear or vanish, nobody notices. Mitigate by vendoring the spec and diffing it in review.

Ramp-up. Near-zero for anyone who already writes artisan commands — the mental model is "each endpoint is a command, each parameter is an option." Realistic ramp: half a day for a Laravel developer to be productive, mostly spent on auth wiring rather than the package. Two things need to be documented internally before rollout, because neither is discoverable from the README: the exit-code/output contract (what a caller can rely on), and the version-pinning and bump-verification procedure. Without the first, nobody can safely automate against it. Without the second, the first breaks quietly.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log
hsluv/hsluv
seampact/codegen
seampact/hooks
seampact/ir
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table