Skip to content
Open
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
6 changes: 3 additions & 3 deletions docs/reference/commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@
| `lerd about` | Show version, build info, and project URL |
| `lerd man [page]` | Browse the built-in documentation in the terminal; pass a page name to jump directly (e.g. `lerd man sites`) |
| `lerd tui` | Open a btop-style terminal dashboard with live site / service / worker status, per-site detail pane, inline domain and version editing, shell drop-in, log tailing, filter + sort, and global settings |
| `lerd check` | Validate `.lerd.yaml` syntax, services, and PHP version before setup |
| `lerd doctor` | Full environment diagnostic: podman, systemd, DNS, ports, PHP images, config validity; also reports how much podman disk is reclaimable. Add `--fix` to apply the safe automatic repairs (confirming each; `--yes` to skip prompts, `--dry-run` to preview); privileged and external-state findings are left for you to run. `--json` emits the findings, each tagged with a fix tier, for tooling |
| `lerd site:doctor [domain]` | App-level health checks for a single site (env file, services the site declares that this machine has never installed, which `--fix` and the dashboard's *Install the missing services* button install, ones that are installed but stopped, which the *Start the stopped services* button starts, services picked in `.lerd.yaml` that the site's env file does not point at, a key the env file sets more than once, env drift, application key, a configured database that is missing (a SQLite file that is absent or empty, or a MySQL/Postgres schema that does not exist on the service), composer/node dependency install + lock, `composer audit`/`npm audit`, PHP version range, an nginx vhost that no longer matches what lerd would write for the site, routes running well above the site's typical response time, plus the framework's own checks). A broken database suppresses the framework migration check so the remedy isn't repeated. Defaults to the site in the current directory; pass a domain to target another. Add `--json` for machine-readable output, or `--fix` to apply the findings lerd can resolve on its own and re-check |
| `lerd check` | Deprecated alias for `lerd site:doctor`, which validates `.lerd.yaml` as one check inside the site's health report |
| `lerd doctor` | Full environment diagnostic: podman, systemd, DNS, ports, PHP images, config validity; also reports how much podman disk is reclaimable, and finishes by sweeping every linked site through the cheap half of `site:doctor`, one summary line each with `lerd site:doctor <domain>` for the detail (the audits and the timing lookup stay on the per-site command). Add `--fix` to apply the safe automatic repairs (confirming each; `--yes` to skip prompts, `--dry-run` to preview) and to offer the disk reclaim it reported; privileged and external-state findings are left for you to run. `--json` emits the findings, each tagged with a fix tier, for tooling |
| `lerd site:doctor [domain]` | App-level health checks for a single site (`.lerd.yaml` validity: PHP version, workers, services, container block, commands, database service, env file, services the site declares that this machine has never installed, which `--fix` and the dashboard's *Install the missing services* button install, ones that are installed but stopped, which the *Start the stopped services* button starts, services picked in `.lerd.yaml` that the site's env file does not point at, a key the env file sets more than once, env drift, application key, a configured database that is missing (a SQLite file that is absent or empty, or a MySQL/Postgres schema that does not exist on the service), composer/node dependency install + lock, `composer audit`/`npm audit`, PHP version range, an nginx vhost that no longer matches what lerd would write for the site, routes running well above the site's typical response time, plus the framework's own checks). A broken database suppresses the framework migration check so the remedy isn't repeated. Defaults to the site in the current directory; pass a domain to target another. Add `--json` for machine-readable output, or `--fix` to apply the findings lerd can resolve on its own and re-check |
| `lerd cleanup` | Reclaim podman disk from orphaned lerd images (old PHP build and base images a rebuild left behind), unused service images no installed service references any more (e.g. an old `mysql:8.0` after upgrading, keeping each service's current image and its one-back rollback target), and dangling untagged images. Previews the list and confirms before removing. Never touches a tagged image in use, your databases, or volumes |
| `lerd cleanup --dry-run` | Show what would be reclaimed and the approximate size, remove nothing |
| `lerd cleanup --safe` | Only reclaim images provably built by lerd, leave unused service and dangling images alone |
Expand Down
10 changes: 9 additions & 1 deletion docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,20 @@
When something isn't working, start with the built-in diagnostics:

```bash
lerd doctor # full check: podman, systemd, DNS, ports, images, config
lerd doctor # full check: podman, systemd, DNS, ports, images, config, sites
lerd status # quick health snapshot of all running services
```

`lerd doctor` reports OK/FAIL/WARN for each check with a hint for every failure.

It finishes with a `[Sites]` section, one line per linked site, so the broad command is actually broad: an environment that passes everything else while three sites are down is not a healthy machine. Each site runs the cheap half of [`lerd site:doctor`](reference/commands.md), the file-and-config checks, and the line names the command to run for the detail:

```bash
lerd site:doctor acme.test
```

The expensive checks, `composer audit`, `npm audit`, and the response-time lookup, only run there, so the sweep stays quick however many sites you have. `lerd site:doctor` also validates the project's `.lerd.yaml`, which is what `lerd check` used to do on its own; `check` still works as a deprecated alias for it.

## Repairing findings automatically

`lerd doctor --fix` runs the same diagnostic and then offers to repair the findings it safely can. It confirms each fix before applying it, so you can pick and choose:
Expand Down
2 changes: 1 addition & 1 deletion docs/usage/custom-containers.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ container:
ssl: true
```

Nginx will use `proxy_pass https://` and skip certificate verification (`proxy_ssl_verify off`) since the container cert is self-signed. Run `lerd check` to confirm the setting is recognised.
Nginx will use `proxy_pass https://` and skip certificate verification (`proxy_ssl_verify off`) since the container cert is self-signed. Run `lerd site:doctor` to confirm the setting is recognised.

## Hot reload

Expand Down
8 changes: 4 additions & 4 deletions docs/usage/framework-commands.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ The merge rules are:
- A project entry with a new `name` is **appended** after the framework set.
- Framework entries whose `check:` rule fails are dropped before the merge.

Validation runs as part of `lerd check`. Invalid `output:` values, unknown icons, duplicate names, and missing commands all surface there.
Validation runs as part of `lerd site:doctor`. Invalid `output:` values, unknown icons, duplicate names, and missing commands all surface there.

Because a `.lerd.yaml` `commands:` entry comes from the project (an untrusted cloned repo), lerd asks before running one on your host: the first run via `lerd run` or the dashboard shows the exact command and prompts, and the approval is remembered per site so later runs don't re-prompt. `lerd run --yes` bypasses the prompt, and `host_commands.skip_confirmation: true` (or `host_commands.disabled: true` to refuse them) in the global config changes the default. Framework-provided commands (store, built-in, user overlay) run without this prompt.

Expand All @@ -84,9 +84,9 @@ commands:
# `disabled: true` is only meaningful in .lerd.yaml; ignored in framework yamls
```

**Known icons**: `broom`, `database`, `refresh`, `link`, `check`, `list`, `key`, `edit`, `arrow-down`, `arrow-up`, `play`, `terminal`. An unknown icon falls back to a generic glyph; `lerd check` warns.
**Known icons**: `broom`, `database`, `refresh`, `link`, `check`, `list`, `key`, `edit`, `arrow-down`, `arrow-up`, `play`, `terminal`. An unknown icon falls back to a generic glyph; `lerd site:doctor` warns.

**Output values:** invalid values fail `lerd check`. Defaults to `text`.
**Output values:** invalid values fail `lerd site:doctor`. Defaults to `text`.

**Check rules**: reuse `FrameworkRule`. The two common forms are `composer: <package>` (the package must be in `composer.json`) and `file: <path>` (the file must exist relative to the project root).

Expand All @@ -99,7 +99,7 @@ When the lerd MCP server is registered, an AI assistant can:
- `command_add(site, name, command, ...)`: write a new entry into `.lerd.yaml`'s `commands:` block. Same `name` as a framework default replaces it. Use `disabled: true` to suppress a framework default
- `command_remove(site, name)`: delete a project entry

Agents should prefer `commands_run` over invoking `php artisan` / `drush` / `wp` directly so per-project overrides are honored, and `command_add` over hand-editing yaml so the entry passes the same validation `lerd check` runs.
Agents should prefer `commands_run` over invoking `php artisan` / `drush` / `wp` directly so per-project overrides are honored, and `command_add` over hand-editing yaml so the entry passes the same validation `lerd site:doctor` runs.

## CLI

Expand Down
4 changes: 2 additions & 2 deletions docs/usage/framework-definitions.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ The `commands:` list is the framework's own verbs: the things you would otherwis

`broom`, `database`, `refresh`, `link`, `check`, `list`, `key`, `edit`, `arrow-down`, `arrow-up`, `play`, `terminal`

`lerd check` validates a definition's commands, and it is the fastest way to catch a typo: an unknown `output` is an error, and an unknown `icon` is a warning.
`lerd site:doctor` validates a definition's commands, and it is the fastest way to catch a typo: an unknown `output` is an error, and an unknown `icon` is a warning.

## Declining a warning

Expand All @@ -407,7 +407,7 @@ The repeated-query warning is the case that needs it. On a content management sy

## Doctor checks

The `doctor:` section adds framework-specific health checks to the ones every site gets for free (env file present, every picked service wired into it, dependencies installed and locked, audit clean, PHP version in range, nginx vhost current). They run on `lerd site:doctor` and in the dashboard's doctor panel. Keeping them declarative is what stops the doctor from growing a Go branch per framework.
The `doctor:` section adds framework-specific health checks to the ones every site gets for free (a valid `.lerd.yaml`, env file present, every picked service wired into it, dependencies installed and locked, audit clean, PHP version in range, nginx vhost current). They run on `lerd site:doctor` and in the dashboard's doctor panel. Keeping them declarative is what stops the doctor from growing a Go branch per framework.

The section also takes a `migrate_command`, naming whichever of the framework's own `commands:` applies the schema. The universal database checks offer it as their fix, so an empty or missing database is reported with the button that fills it. Every framework spells it differently (Laravel `migrate`, Symfony `doctrine:migrations:migrate`, Drupal `updb`), so nothing but the definition can say; a framework that declares none, or names a command it does not have, gets a finding with no fix rather than a button that maps to nothing.

Expand Down
2 changes: 1 addition & 1 deletion docs/usage/host-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Lerd starts the dev server, generates the proxy vhost, and serves the domain. Op

## Configuration

The `proxy` section in `.lerd.yaml` is mutually exclusive with `container:` (a site is one or the other, and `lerd check` rejects setting both).
The `proxy` section in `.lerd.yaml` is mutually exclusive with `container:` (a site is one or the other, and `lerd site:doctor` rejects setting both).

| Field | Required | Default | Description |
|-------|----------|---------|-------------|
Expand Down
2 changes: 1 addition & 1 deletion docs/usage/sites.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ When `lerd link` runs and workers are configured but not yet running, it prompts

Toggling workers from the CLI (`lerd queue:start`, `lerd schedule:stop`, etc.) or the web UI syncs the running state back to `.lerd.yaml` when the file exists.

`lerd check` validates that listed workers are valid for the detected framework.
`lerd site:doctor` validates that listed workers are valid for the detected framework.

`lerd status` includes a Workers section showing all active, restarting, or failed workers across sites. In the web UI, failing workers show a pulsing red toggle and their log tab appears with a "!" indicator.

Expand Down
Loading
Loading