Guide
A Comprehensive Agent's Guide to Laravel CloudKnow your CLI
· Ed Grosvenor
Most of the contradictions we found in our own notes turned out to be two agents running two different CLIs. Settle which one you have before you trust anything else.
Find the binary you will actually run
command -v cloud
cloud --version
Run both in the same shell your commands will run in. An interactive shell and an agent's non-interactive shell can resolve cloud differently. On one machine we used, an alias in the interactive shell pointed at a months-old source checkout, while the agent's shell found the Composer global binary. The two had different commands and different output, so notes written by one were wrong for the other.
Install and upgrade with Composer:
composer global require laravel/cloud-cli
cloud self-update
If you cannot touch the global install, a disposable Composer project with laravel/cloud-cli required at a known version works just as well. Call its vendor/bin/cloud by full path.
Releases that change what is safe
| Version | What changed for agents |
|---|---|
| v0.5.0 | environment:update --database-id and --cache-id appeared to do nothing, and attachment fields read back null. database-cluster:list failed with a 400 after the API renamed a relationship. cache:list --json printed live cache passwords. bucket-key:get --show-sensitive returned no secret. |
| v0.5.2 | The attachment read bug was fixed. Attaching databases and caches with environment:update works from here. |
| v0.5.3 | Bucket key secrets are returned again with --show-sensitive. |
| v0.6.0 | JSON output masks sensitive values by default, and every command accepts --show-sensitive and --fields. cloud tinker exists. |
| v0.6.1 | Follows the API's move to versionless database types. |
| v0.6.2 | An environment ID or name that cannot be resolved is now an error. Before this, it silently fell back to another environment, and writes landed there. Listings fetch pages up to a cap of 2,000 rows. |
| v0.6.3 | Adds environment:metrics, database-cluster:metrics, cache:metrics and the WebSocket metrics commands. |
If you are below v0.6.2, upgrade before any write. The environment fallback is the single most dangerous behaviour in this guide. It is covered on Work in the right organization.
Drive it non-interactively
The CLI decides whether it may prompt. It treats you as non-interactive when standard input is not a terminal, when it detects a coding agent, when CI, GITHUB_ACTIONS, GITLAB_CI, JENKINS_URL, CIRCLECI or TRAVIS is set, or when you pass --json, -n or --no-interaction.
When a non-interactive command needs a choice it cannot make, it writes a JSON error to standard error and exits with status 1. The error usually includes the options it would have offered:
{"error": true, "message": "Multiple environments found. Provide an environment ID or name.", "options": {"env-…": "production", "env-…": "staging"}}
Treat that as an instruction to supply the identifier, not as a list to pick from. See rule 3.
Use these conventions, which match the guidance Laravel ships for agents with cloud skills:install:
- Always pass
-n. - Never pass
-qor--silent. You need the output. - Add
--jsonto reads and creates, and always add--fieldsalongside it. - Add
--forceto updates and deletes. - Run
cloud <command> -hat the moment you need a command. Do not rely on a remembered signature. The help output also lists every JSON field a command can return, which is what you pass to--fields.
A few commands are interactive by design and should be left to a human: cloud auth opens a browser, and cloud ship walks through a guided first deployment.
Flags that are not what they look like
--envis not a Cloud environment. Every command accepts a global--envoption, but it is the CLI framework's own application environment. Passing--env=<environment-id>is silently ignored, so the command runs against whatever environment it resolves on its own. Cloud environments are positional arguments:cloud command:run <environment-id> ….- There is no per-command organization flag. Only
repo:configaccepts--organization. How the organization is chosen is covered on the next page. --taildoes not raise the log limit.environment:logsreturns at most 100 entries per call, whatever you pass. See Reads that lie.
When the CLI is not enough
The CLI wraps most, but not all, of the API at https://cloud.laravel.com/api. We used the API directly for full deployment logs, environment logs over a time window, attaching a bucket to an environment, and sizing instances. The API has its own traps:
- Send
Accept: application/vnd.api+json, and the sameContent-Typeon writes. A plainapplication/jsonrequest returns401 Unauthenticated, which looks exactly like a bad token. - Use the published specification with suspicion. It lives at
https://cloud.laravel.com/api-docs/api.json. We found it wrong four times on a single endpoint, and on 28 September 2026 it changed by roughly a thousand lines at once. Its enums tell you which values exist, not which ones a given resource accepts. When the specification and a live response disagree, the live response is the truth. - One token reaches exactly one organization. That is different from Laravel Forge, where one token can reach several.