## What
Adds in-memory log buffering for CLI diagnostics so the debug detail
leading up to a failure is available without logging debug during normal
operation. Below-level entries are kept in a slog flight recorder
(`v3.2.0`) and emitted only when a command returns an error. This
implements CLI-4 (connection-log RFC req 13). Depends on the
`cdr.dev/slog/v3` `v3.2.0` bump (already on `main`).
## How
- **Root command** (`cli/root.go`):
- New global `--log-buffer-size` / `CODER_LOG_BUFFER_SIZE` (default
`10`, `0` disables, clamped to `10000`), shared by all commands instead
of duplicated per command.
- `bufferedLoggerMiddleware` runs the invocation logger at `Info` (or
`Debug` with `-v`) with a flight recorder, and on a returned error calls
`Flush` to replay the buffered history to stderr. `Flush` does not add a
duplicate error line; the returned error is still rendered by the normal
formatter.
- Opt-in via an `annotationBufferedLogger` annotation so it does not
clobber the ~17 commands that build their own logger on `inv.Logger`
(which would otherwise double-log). Future commands opt in with one
line.
- `start` / `stop` / `update`: opt into the middleware and just
`client.SetLogger(inv.Logger)` so codersdk request/response debug is
captured and flushed to stderr on failure. They **no longer write
session log files** and dropped their per-command `--log-dir` /
`--log-buffer-size`.
- `ssh`: keeps its own file logger (writing to stderr would corrupt its
stdio stream), now using the global buffer size and the shared
`bufferedLogger` helper. It retains `--log-dir` / `CODER_SSH_LOG_DIR`,
stdio/PID filename handling, and file pruning (50 most recent).
- `restart` is excluded, matching the `client_session_id` opt-in set
(DEVEX-664).
## Default behavior change
`start` / `stop` / `update` now emit buffered diagnostics (recent
below-level entries, e.g. sdk request/response) to **stderr** when they
fail; on success they stay quiet. `coder ssh` continues to write a
per-connection diagnostic file by default under the XDG state dir
(`~/.local/state/coder/logs`), pruned to the 50 most recent. Opt out of
buffering with `--log-buffer-size 0`.
## Review changes (Asher)
- Shared logger construction: the level is computed once and the flight
recorder is always attached, in a single `bufferedLogger` helper used by
ssh and the workspace commands.
- Workspace commands print to normal output instead of a log file, and
the default buffer is `10` to avoid flooding the terminal on failure.
- The buffer lives on the root command / logger (global option +
middleware) rather than being wired into each command.
## Alignment with #29671 (agent)
Same core model: `Info` default with a flight recorder, `-v` for full
debug, and the shared `--log-buffer-size` semantics (`0` disables).
Differences: the agent writes to a file and defaults the buffer to
`1000`, while the CLI prints to stderr and defaults to `10`; both now
rely on slog's auto-flush-on-error (the CLI additionally flushes via the
middleware on a returned error).
> [!NOTE]
> The agent PR (#29671) adds an agent-scoped `--log-buffer-size` /
`CODER_AGENT_LOG_BUFFER_SIZE` on the hidden `coder agent` command. Once
both land, the global `--log-buffer-size` here and the agent's own flag
will need reconciling on `coder agent`. Flagging for whichever merges
second.
## Testing
`cli.TestClampLogBufferSize`, `TestPruneSessionLogs`,
`TestDefaultSessionLogDir`, and `TestBufferedLogger_*` cover clamping,
ssh log retention, the default state dir, buffer-until-error, the
middleware's flush path, and the verbose escape hatch.
`start`/`stop`/`update`/`ssh` command tests pass. Golden `--help` output
and `docs/reference/cli` regenerated. (`TestSSH/Env` is a pre-existing
interactive-PTY test that does not run in all sandboxes; it fails
identically on `main` here.)
<details>
<summary>Rollout context</summary>
Cross-repo sequence: coder/slog flight recorder (released as v3.2.0) ->
go.mod bump in coder/coder (#29600, merged) -> CLIENT-672 (agent,
#29671) and this PR (CLI-4), which are independent consumers and can
merge in any order.
</details>
---
<sub>Opened by Coder Agents on behalf of @aqandrew.</sub>
Reference for the Coder command-line interface, with usage and flags for every command.
./images/icons/terminal.svg
Usage
coder [global-flags] <subcommand>
Description
Coder — A tool for provisioning self-hosted development environments with Terraform.
- Start a Coder server:
$ coder server
- Get started by creating a template from an example:
$ coder templates init
Specify an authentication token. For security reasons setting CODER_SESSION_TOKEN is preferred.
--no-version-warning
Type
bool
Environment
$CODER_NO_VERSION_WARNING
Suppress warning when client and server versions do not match.
--no-feature-warning
Type
bool
Environment
$CODER_NO_FEATURE_WARNING
Suppress warnings about unlicensed features.
--allow-redirects
Type
bool
Environment
$CODER_ALLOW_REDIRECTS
Follow HTTP redirects from the server instead of returning an error. Following redirects may alter the request method and/or drop its body.
--header
Type
string-array
Environment
$CODER_HEADER
Additional HTTP headers added to all requests. Provide as key=value. Can be specified multiple times.
--header-command
Type
string
Environment
$CODER_HEADER_COMMAND
An external command that outputs additional HTTP headers added to all requests. The command must output each header as key=value on its own line. If a header value is a JWT, it will be refreshed based on the value in its exp field.
--force-tty
Type
bool
Environment
$CODER_FORCE_TTY
Force the use of a TTY.
-v, --verbose
Type
bool
Environment
$CODER_VERBOSE
Enable verbose output.
--flight-recorder-size
Type
int
Environment
$CODER_FLIGHT_RECORDER_SIZE
Default
10
Number of log entries below the current log level to keep in memory and emit on errors. Set to 0 to disable the flight recorder.
--disable-direct-connections
Type
bool
Environment
$CODER_DISABLE_DIRECT_CONNECTIONS
Disable direct (P2P) connections to workspaces.
--disable-network-telemetry
Type
bool
Environment
$CODER_DISABLE_NETWORK_TELEMETRY
Disable network telemetry. Network telemetry is collected when connecting to workspaces using the CLI, and is forwarded to the server. If telemetry is also enabled on the server, it may be sent to Coder. Network telemetry is used to measure network quality and detect regressions.
--client-tls-ca-file
Type
string
Environment
$CODER_CLIENT_TLS_CA_FILE
Path to a CA certificate file to trust for API and DERP connections.
--client-tls-cert-file
Type
string
Environment
$CODER_CLIENT_TLS_CERT_FILE
Path to a client certificate file for mTLS authentication with API and DERP. Requires --client-tls-key-file.
--client-tls-key-file
Type
string
Environment
$CODER_CLIENT_TLS_KEY_FILE
Path to a client private key file for mTLS authentication with API and DERP. Requires --client-tls-cert-file.
--use-keyring
Type
bool
Environment
$CODER_USE_KEYRING
Default
true
Store and retrieve session tokens using the operating system keyring. This flag is ignored and file-based storage is used when --global-config is set or keyring usage is not supported on the current platform. Set to false to force file-based storage on supported platforms.