Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 1 addition & 37 deletions .cursorrules
Original file line number Diff line number Diff line change
@@ -1,37 +1 @@
# Cloud CLI Guidelines

## Project Overview

This is a Laravel Zero CLI tool for deploying applications to Laravel Cloud.

## Code Style

- Follow Laravel/PSR-12 conventions
- Run `./vendor/bin/pint --dirty` after modifying PHP files
- Use Laravel Prompts for all user interactions (confirm, select, text, password, info, warning, error)

## Architecture

- Commands live in `app/Commands/`
- `app/Git.php` handles all git and GitHub CLI operations
- `app/ConfigRepository.php` manages user config stored in `~/.config/cloud/config.json`
- `app/ProcessResult.php` wraps command execution results

## Conventions

- Use `gh` CLI for GitHub API interactions rather than direct HTTP calls
- Constructor methods with empty bodies should contain a single empty comment
- Non-public methods/properties should be `protected`, not `private`
- Limit comments to non-obvious code only
- For long command signatures, separate the arguments and concatonate them in the property to make it more readable (leading space)
- Never use the helper methods in `Command`, always use Prompts helper functions

## Dependencies

- Laravel Zero 12.x
- PHP 8.2+
- Requires GitHub CLI (`gh`) to be installed and authenticated

## Cloud API

https://cloud.laravel.com/docs/api/introduction
See CLAUDE.md in the project root for project guidelines, layout, and conventions.
56 changes: 56 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Cloud CLI

Laravel Zero CLI for managing apps on [Laravel Cloud](https://cloud.laravel.com). PHP 8.3+. Run locally with `php cloud <command>`.

## Commands to run

```sh
vendor/bin/pest # tests
vendor/bin/pest --filter=Cache # single test
vendor/bin/pint --dirty # format (run after editing PHP)
vendor/bin/phpstan analyse # static analysis, level 5
```

Point at a local API with `CLOUD_BASE_URL` in `.env`. `LARAVEL_CLOUD_TOKEN` overrides stored tokens.

## Layout

| Path | What |
| --- | --- |
| `app/Commands/` | One class per command, all extend `BaseCommand` |
| `app/Client/` | Saloon SDK for the Cloud API — see `app/Client/README.md` |
| `app/Client/Resources/<Thing>Resource.php` | Method-per-endpoint facade over the request classes |
| `app/Client/Requests/*RequestData.php` | Typed request payloads (spatie/laravel-data) |
| `app/Dto/` | Typed API responses; also drive `--json` output and `--fields` |
| `app/Resolvers/` | Turn a user-supplied ID/name into a DTO, prompting when interactive |
| `app/Prompts/` | Custom Laravel Prompts renderers (tables, monitors, slide-ins) |
| `app/Support/Form.php` | Merges options/arguments with prompts for mixed interactive/flag input |
| `app/Middleware/` | Command middleware (auth, JSON output suppression), registered in `AppServiceProvider` |
| `app/helpers.php` | Global output helpers: `answered()`, `success()`, `dataList()`, `dataTable()`, `codeBlock()` |
| `app/Git.php` | All git and `gh` CLI work |
| `app/ConfigRepository.php` | User config at `~/.config/cloud/config.json` |

## Conventions

- Every command supports `--json`, `--fields`, `--show-sensitive`, and `--no-interaction`. `BaseCommand::wantsJson()` is true when `--json` is passed *or* the run is non-interactive, so a command must work headlessly.
- Set `$jsonDataClass` (and `$jsonDataIsCollection`) on a command so `--json` and the help text know the field list.
- Emit JSON with `outputJsonIfWanted()` (exits) or `writeJsonIfWanted()` (continues) before any human-facing output.
- Never use `Command` output helpers (`$this->info()` etc.) — use Laravel Prompts functions and the helpers in `app/helpers.php`.
- Destructive commands call `confirmDestructive()`; it requires `--force` when non-interactive.
- Fetch through `spin(...)`, resolve arguments through `$this->resolvers()`, prompt through `$this->form()->prompt()`.
- Non-public members are `protected`, never `private`. Empty constructor bodies get a single `//` comment.
- Long signatures go one option per line, indented.
- Comments explain *why*, never *what*.

## Adding a command

1. Request class in `app/Client/Resources/<Thing>/`, payload in `app/Client/Requests/` if it takes a body.
2. Method on the matching `*Resource.php`; DTO in `app/Dto/` for the response.
3. Command in `app/Commands/`; Laravel Zero autoloads it, no registration needed.
4. Test in `tests/Feature/` using Saloon's `MockClient` and `Prompt::fake()` — see `tests/Feature/ApplicationCommandsTest.php` and the fixtures in `tests/Helpers.php`.

## Related docs

- `AI_CLI_DESIGN_PRINCIPLES.md` — why the CLI is shaped for agents as well as people
- `skills/deploying-laravel-cloud/` — the skill `cloud skills:install` ships to users
- API reference: https://cloud.laravel.com/docs/api/introduction