Files
summercms/docs/console/introduction.md
Jakub Zych 9c89705747 fix(summer): give delegated commands the terminal and keep their stderr apart
- appStreams hands the app binary summer's own stdout and stderr on a
  terminal, so it asks the production question, prints styled summaries
  and animates its widgets
- off a terminal the binary's stdout goes through summer's Output and its
  stderr to summer's stderr, so --json and -q output carry no log lines
- newAppCmd (unexported) takes the two writers; docs say the streams stay
  apart (CR-03)
2026-10-22 02:19:01 +02:00

158 lines
8.8 KiB
Markdown

---
title: Console introduction
description: The two command-line programs of SummerCMS, the summer developer tool and the application binary, and how summer delegates runtime commands.
section: console
order: 10
---
# Console introduction
WinterCMS has one console entry point, `php artisan`. SummerCMS has two programs, because the developer tooling and the running application are separate binaries:
| Program | Where it comes from | What it does |
|---------|---------------------|--------------|
| `summer` | Installed once, by the `curl -fsSL https://summercms.io/new \| bash -s -- <name>` one-liner or from a framework checkout with `go install ./cmd/summer`. | Creates, builds and watches applications, scaffolds plugins and their parts, records API parity fixtures and builds these docs. |
| The application binary, for example `./bin/acme` | Written by `summer build` into the application's `bin/` directory. | Runs the application: the HTTP server, migrations, workers, the scheduler, admin accounts and every command its plugins add. |
The application binary is what you deploy, so everything that must run in production, such as migrations and workers, is a command of the binary rather than of `summer`.
Run with no arguments, the binary prints the list of every command it has, the framework's and those its plugins add, the way `php artisan` does; `--help` and `list` print the same:
```sh
./bin/acme
./bin/acme --help
./bin/acme list
```
```text
SummerCMS acme v1.4.0 (framework v0.3.2)
Usage:
bin/acme <command> [options] [arguments]
Options:
-h, --help Display help for the given command
-q, --quiet Do not output any message
-v|vv|vvv Increase verbosity
--ansi|no-ansi Force (or disable) ANSI output
-n, --no-interaction Do not ask any interactive question
--env The environment the command runs under
Available commands:
help Display help for a command
list List commands
migrate Run plugin migrations in dependency order
serve Serve the application HTTP API
admin
admin:create Create an activated backend administrator
admin:reset-password Reset a backend administrator password and revoke existing tokens
admin:token:create Create a personal API token for a backend administrator
migrate
migrate:rollback Roll back the last migration of a plugin
migrate:status Show per-plugin migration history
queue
queue:work Run background job workers in the foreground
```
The header names the application, its version and the framework version it was built against (`local` when the framework comes from a local checkout). Commands without a namespace come first, then one block per namespace, the part of the name before the first colon. `summer` with no arguments prints its own list in the same layout.
## Getting help
Both programs list their commands with no arguments, with `--help` and with `list`, and every command accepts `--help` for its arguments and flags:
```sh
summer
summer make:model --help
summer help migrate
./bin/acme --help
./bin/acme migrate:rollback --help
./bin/acme help migrate:rollback
./bin/acme list --all
./bin/acme list --format=json
```
A command's help shows its description, usage, arguments, options with their defaults, the global options, the long help and examples. `list --all` includes hidden commands, and `list --format=json` prints every command with its arguments, options and examples for scripts and agents.
A command that `summer` delegates to the application binary, such as `summer serve`, answers `--help` with the binary's own help, so run it inside an application directory. Asking the help command of `summer` about a delegated command instead prints a short description and its common flags without running the binary.
### Global options
Every command of both programs accepts these options, before or after the command name:
| Option | Effect |
|--------|--------|
| `-v`, `-vv`, `-vvv` (`--verbose`) | More output: `-v` shows info logs of every component, `-vv` debug logs, `-vvv` also source locations and SQL traces. |
| `-q`, `--quiet` | Hides info and success lines, spinners and progress, and shows only warnings and errors in the console log; data a command prints (tokens, keys, JSON) and errors still appear. Implies `-n`. |
| `--ansi`, `--no-ansi` | Forces or turns off colors and styling; `--no-ansi` also stops animations. The last one given wins. Without either, colors follow the terminal, `NO_COLOR` and `FORCE_COLOR`. |
| `-n`, `--no-interaction` | Asks no questions: prompts take their defaults, and a password prompt reads piped stdin or fails with a hint. |
| `--env` | The configuration environment, as `SUMMER_ENV` would set it: `--env staging` or `--env=staging`. |
The application binary reads these options before it loads `config/` and starts plugins, so `--env` picks the configuration and `-vv` applies from the first log line:
```sh
./bin/acme -vv migrate
./bin/acme migrate:status --env staging
```
### Exit codes
| Code | Meaning |
|------|---------|
| `0` | The command succeeded. |
| `1` | The command failed; the error is printed on stderr. |
| `2` | The command was called wrongly: an unknown command or flag, or a wrong number of arguments. |
## Commands that summer delegates
During development you often work from the application directory with `summer` alone. These `summer` commands find the application's `summer.yaml`, build `bin/<binary>` when it does not exist yet, and run the same command of the binary with the same arguments:
| summer command | Runs |
|----------------|------|
| `summer migrate` | `./bin/acme migrate` |
| `summer migrate:rollback` | `./bin/acme migrate:rollback` |
| `summer migrate:status` | `./bin/acme migrate:status` |
| `summer serve` | `./bin/acme serve` |
| `summer queue:work` | `./bin/acme queue:work` |
| `summer queue:clear` | `./bin/acme queue:clear` |
| `summer schedule:run` | `./bin/acme schedule:run` |
| `summer route:list` | `./bin/acme route:list` |
| `summer key:generate` | `./bin/acme key:generate` |
| `summer admin:create` | `./bin/acme admin:create` |
| `summer admin:reset-password` | `./bin/acme admin:reset-password` |
| `summer admin:token:create` | `./bin/acme admin:token:create` |
| `summer admin:token:list` | `./bin/acme admin:token:list` |
| `summer admin:token:revoke` | `./bin/acme admin:token:revoke` |
| `summer admin:token:scopes` | `./bin/acme admin:token:scopes` |
`summer` parses no flags of these commands: every flag and argument, including `--help`, goes to the binary unchanged, and the binary's input is your terminal, so the password prompts of `admin:create` and `admin:reset-password` work as usual:
```sh
summer serve --addr 127.0.0.1:8123
summer serve --help
summer migrate:rollback --plugin acme.blog
summer admin:create --email admin@example.com --superuser
```
One leading `--` is ignored, so `summer serve -- --addr 127.0.0.1:8123` behaves the same as `summer serve --addr 127.0.0.1:8123`.
The global options go to the binary too, wherever you put them: `summer -v migrate --pretend` runs `./bin/acme -v migrate --pretend`, and `summer -q key:generate` prints only the key. `summer help migrate` shows each delegate's examples; the binary's own help, with every flag, is `summer migrate --help`:
```sh
summer -v migrate --pretend
summer admin:token:create jane --scope journal.posts --json
```
The binary writes to your terminal directly, so it asks the production question, prints its styled startup summary and animates its spinners as if you had run it yourself. Its error stream stays separate from its output: `summer route:list --json > routes.json` captures only the JSON, while warnings and log lines still reach the terminal on stderr.
When the binary fails, `summer` exits with the binary's exit code (a usage error stays `2`) and prints nothing more: the binary has already printed its error. A binary killed by a signal gets an error block from `summer` and exit code `1`.
When `summer` receives SIGINT or SIGTERM while the binary runs, it passes the signal on and waits for the binary to shut down, so stopping `summer serve` with Ctrl+C or `kill` frees its port.
`summer` does not rebuild an existing binary before it delegates. Run `summer build` after you change code, or keep `summer dev` running. Every other runtime command, such as `deferred:purge` or the commands your plugins add, is run on the binary directly.
## The sections of this chapter
- [Setup and maintenance](setup-and-maintenance.md) lists every command of the application binary.
- [Scaffolding](scaffolding.md) covers `summer new`, `summer build`, `summer dev` and the `make:` commands.
- [Writing commands](writing-commands.md) shows how a plugin adds its own commands.
- [Utilities](utilities.md) covers the parity and documentation commands of `summer`.