Summary
There's no CLI command to read the lifecycle / setup-script log of a Brev workspace. Today the only way to see why a Launchable's setup failed is to wait for the VM to become reachable, then brev shell <name> and dig through /var/log/brev/oncreate-lifecycle-script-*.log (Brev's own logging) and any service log the script writes (e.g. journalctl -u <unit>). That's painful for three common scenarios:
- The setup script failed mid-execution — the VM is up but
brev open lands on something that doesn't work. The operator has to know to brev shell, then know to sudo cat a Brev-managed path that isn't documented.
- The VM never becomes reachable because the script crashed before SSH came up — operators can't
brev shell at all, so the only signal is build_status=CREATE_FAILED with no log surface.
- Agent/CI harnesses — automation that polls for "did the launchable's setup actually succeed?" has to either re-implement the SSH+cat dance or do a deep readiness probe against the service the setup claimed it would start.
This is the third or fourth time recently we've had a launchable setup fail (most recently: glibc 2.39 mismatch on the openshell-gateway binary, where the launchable VM logged the failure but we had to wait for SSH-reachability to read it).
Reproduction
$ brev --help | grep -i log
# (nothing — no `logs` subcommand exists)
$ brev exec my-vm -- sudo cat /var/log/brev/oncreate-lifecycle-script-019e3e9f-cc6c-7041-b186-54a3a6c703da.log
# works, but requires:
# - knowing the exact UUID of the lifecycle-script-instance run
# - knowing the log file lives under /var/log/brev/
# - the VM being SSH-reachable (precluded when the script panics before sshd starts)
# - sudo, since /var/log/brev is root-owned
$ brev exec my-vm -- sudo journalctl -u dex-ui.service -n 200
# same constraints
When the script fails before SSH comes up — which is what happens for any panic in the early apt/install phase — neither of those work. The user is stuck staring at brev ls --json | jq '.workspaces[].statusMessage' which returns one-line summaries with no log content.
What we'd like
A new subcommand:
# Print the latest lifecycle-script log for a workspace, tailing if --follow.
brev logs <workspace-name-or-id>
brev logs <workspace-name-or-id> --follow # -f for live tail
brev logs <workspace-name-or-id> --tail 200 # last N lines
brev logs <workspace-name-or-id> --since 10m # systemd-style window
brev logs <workspace-name-or-id> --json # one log line per JSON object
Behavior:
- Works before SSH is up. Brev's control plane should expose the lifecycle-script-runner's stdout/stderr via the same channel that already populates
build_status and statusMessage. The CLI proxies that stream.
- Independent of whether the script's own log path is conventional.
brev logs shows the lifecycle runner's log — what the runner itself emitted while invoking the user-supplied script. If the user's script writes to its own paths (/var/log/dex-ui-launchable/setup.log), those stay where they are; a future flag could enumerate them but isn't part of this MVP.
- Includes the failure stage, similar to
kubectl logs --previous semantics. If the last attempt failed and a new one is pending, default behavior is to show the failed one; a --current flag swaps to the in-progress run.
- Honors
--workspace-group — for orgs with multiple workspace groups (GCP/AWS/etc.), pull from whichever the workspace lives in. Mostly transparent.
- Output format — plain text by default with one log line per terminal line;
--json for scripts. Don't ANSI-color when piped.
Why this matters
- Debugging the dex-ui launchable above would have been a one-liner:
brev logs dex-ui-launchtest --follow. Instead we waited for SSH, ran sudo cat, found a path, and copy-pasted the GLIBC error.
- Agent harnesses can short-circuit a smoke test the moment the setup fails instead of waiting for a network-level readiness probe to time out.
build_status=CREATE_FAILED records hold zero diagnostic information today — brev logs is the obvious place that information should appear.
Non-goals
- Application logs from arbitrary services on the VM.
brev exec <name> -- journalctl -u foo already works once SSH is up; the gap is specifically the lifecycle-script log when SSH isn't yet available.
- A general "fetch any file from a workspace's filesystem" API. The launchable lifecycle log is a discrete, well-defined surface; broaden later if needed.
Related
Summary
There's no CLI command to read the lifecycle / setup-script log of a Brev workspace. Today the only way to see why a Launchable's setup failed is to wait for the VM to become reachable, then
brev shell <name>and dig through/var/log/brev/oncreate-lifecycle-script-*.log(Brev's own logging) and any service log the script writes (e.g.journalctl -u <unit>). That's painful for three common scenarios:brev openlands on something that doesn't work. The operator has to know tobrev shell, then know tosudo cata Brev-managed path that isn't documented.brev shellat all, so the only signal isbuild_status=CREATE_FAILEDwith no log surface.This is the third or fourth time recently we've had a launchable setup fail (most recently: glibc 2.39 mismatch on the openshell-gateway binary, where the launchable VM logged the failure but we had to wait for SSH-reachability to read it).
Reproduction
When the script fails before SSH comes up — which is what happens for any panic in the early apt/install phase — neither of those work. The user is stuck staring at
brev ls --json | jq '.workspaces[].statusMessage'which returns one-line summaries with no log content.What we'd like
A new subcommand:
Behavior:
build_statusandstatusMessage. The CLI proxies that stream.brev logsshows the lifecycle runner's log — what the runner itself emitted while invoking the user-supplied script. If the user's script writes to its own paths (/var/log/dex-ui-launchable/setup.log), those stay where they are; a future flag could enumerate them but isn't part of this MVP.kubectl logs --previoussemantics. If the last attempt failed and a new one is pending, default behavior is to show the failed one; a--currentflag swaps to the in-progress run.--workspace-group— for orgs with multiple workspace groups (GCP/AWS/etc.), pull from whichever the workspace lives in. Mostly transparent.--jsonfor scripts. Don't ANSI-color when piped.Why this matters
brev logs dex-ui-launchtest --follow. Instead we waited for SSH, ransudo cat, found a path, and copy-pasted the GLIBC error.build_status=CREATE_FAILEDrecords hold zero diagnostic information today —brev logsis the obvious place that information should appear.Non-goals
brev exec <name> -- journalctl -u fooalready works once SSH is up; the gap is specifically the lifecycle-script log when SSH isn't yet available.Related
build_status=CREATE_FAILEDshould expose enough context to debug without SSH