feat(cli): add pipe support to stop, start, delete, and ls commands#283
feat(cli): add pipe support to stop, start, delete, and ls commands#283
Conversation
Add stdin piping and improved output for CLI composability.
Stop/Start/Delete:
- Accept instance names from stdin (one per line)
- Accept multiple instance names as arguments
- Output instance names when piped for chaining
- Add --all flag to stop command
Ls improvements:
- Add --json flag for JSON output
- Output plain table when piped (for grep/awk)
- Add JSON and pipe support to ls orgs
Examples:
brev ls | awk '/RUNNING/ {print $1}' | brev stop
brev ls | grep "test-" | awk '{print $1}' | brev delete
brev ls --json | jq '.[] | select(.status == "RUNNING")'
brev stop --all
- Extract trackLsAnalytics() in ls.go - Extract runBatchStart() and runSingleStart() in start.go Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Manual QA Results ✅Build & Static Analysis:
Test Plan Verification:
Piping Integration Test:
Notes:
|
- Consolidate duplicate isStdoutPiped() from delete, ls, start, stop - Consolidate duplicate getInstanceNames() from delete, stop - Consolidate duplicate getInstanceNamesFromStdin() from start - Create IsStdoutPiped(), IsStdinPiped(), GetInstanceNames(), GetInstanceNamesWithPipeInfo() - Remove ~108 lines of duplicated code
ea4dba8 to
03b8f8c
Compare
pkg/cmd/start/start.go
Outdated
| }, startStore) | ||
| if err != nil { | ||
| if !piped { | ||
| t.Vprintf("Error starting %s: %s\n", instanceName, err.Error()) |
There was a problem hiding this comment.
this purposely doesn't return the error, just prints it?
pkg/cmd/start/start.go
Outdated
| WorkspaceClass string | ||
| Detached bool | ||
| InstanceType string | ||
| Piped bool // true when stdout is piped to another command |
There was a problem hiding this comment.
is this field ever read?
| stdinPiped := IsStdinPiped() | ||
| if stdinPiped { | ||
| scanner := bufio.NewScanner(os.Stdin) | ||
| for scanner.Scan() { |
There was a problem hiding this comment.
no scanner.err check?
- Return errors from runBatchStart instead of silently swallowing them - Remove unused Piped field from StartOptions - Add scanner.Err() check after stdin scan loop in piping.go
| // Output names for piping to next command | ||
| if piped { | ||
| for _, name := range stoppedNames { | ||
| fmt.Println(name) |
There was a problem hiding this comment.
Interesting -- so this collects the names of the workspaces for which the stop command succeeded, then proceeds with piping to the next command. We have the scenario then of having one or more of the stops having failed, but we will proceed with the piped command on those that succeeded, and then we return an error.
Should we instead be only proceeding with output (or in other words, checking and reacting to the piped flag) after ensuring that allErr is nil?
There was a problem hiding this comment.
I wonder if we should probably exit non zero but still return the workspace names
There was a problem hiding this comment.
Yeah unless we have set -o pipefail then we'll simply continue supplying output to the next command. In the absence of this (which we should assume is possible as we can't control the shell) we can be a good citizen by limiting what we send over stdout to the next possible command.
There was a problem hiding this comment.
Okay decided to go all or nothing.
pkg/cmd/delete/delete.go
Outdated
| } | ||
| fmt.Println("attempting to delete an instance you don't own as admin") | ||
| if !piped { | ||
| fmt.Println("attempting to delete an instance you don't own as admin") |
There was a problem hiding this comment.
Should this go to stderr?
- Add ExitCodeError type to distinguish failure modes - Batch start returns exit code 2 for partial failure, 1 for all failed - main.go propagates custom exit codes from ExitCodeError
Address drewmalin's review: don't send names to stdout when there are partial failures, since the next piped command would act on them even without pipefail. Also send admin delete message to stderr instead of stdout, and remove unused ExitCodeError type.
Summary
Add stdin piping and improved output for CLI composability, enabling Unix-style command chaining.
Changes
Stop/Start/Delete
--allflag to stop commandLs Improvements
--jsonflag for JSON outputbrev ls orgsExamples
Test plan
echo "instance" | brev stopworksbrev stop inst1 inst2works with multiple argsbrev ls --jsonoutputs valid JSONbrev ls | grepworks (plain table when piped)brev stop --allstops all running instancesbrev ls orgs --jsonoutputs valid JSON