Skip to content

Commit 109e513

Browse files
committed
feat(open): output instance names to stdout when piped
Enable chaining with brev open by outputting instance names: brev create my-gpu | brev open cursor | brev exec 'pip install torch' Only outputs when stdout is piped, keeping interactive use clean.
1 parent 43bd7be commit 109e513

2 files changed

Lines changed: 18 additions & 1 deletion

File tree

docs/PRD-composable-cli.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ Make the Brev CLI idiomatic, programmable, and agent-friendly. Users and AI agen
4949
| `brev create` | Instance types (table or JSON) | Instance names ||
5050
| `brev shell` | - | - (interactive) ||
5151
| `brev exec` | Instance names | Command stdout/stderr ||
52-
| `brev open` | Instance names | - ||
52+
| `brev open` | Instance names | Instance names ||
5353

5454
### Exec Command (`brev exec`)
5555

@@ -117,6 +117,13 @@ brev open gpu-1 gpu-2 gpu-3 cursor
117117
brev create my-cluster --count 3 | brev open cursor
118118
```
119119

120+
**Output for chaining**:
121+
Outputs instance names when piped, enabling pipelines:
122+
```bash
123+
# Create, open in editor, then run setup
124+
brev create my-gpu | brev open cursor | brev exec "pip install -r requirements.txt"
125+
```
126+
120127
**Cross-platform support**:
121128
- macOS: Terminal.app, iTerm2
122129
- Linux: Default terminal emulator

pkg/cmd/open/open.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,10 @@ func NewCmdOpen(t *terminal.Terminal, store OpenStore, noLoginStartStore OpenSto
169169
}
170170
return breverrors.WrapAndTrace(err)
171171
}
172+
// Output instance name for chaining (only if stdout is piped)
173+
if isPiped() {
174+
fmt.Println(instanceName)
175+
}
172176
}
173177
if errors != nil {
174178
return breverrors.WrapAndTrace(errors)
@@ -190,6 +194,12 @@ func isEditorType(s string) bool {
190194
return s == EditorVSCode || s == EditorCursor || s == EditorWindsurf || s == EditorTerminal || s == EditorTmux
191195
}
192196

197+
// isPiped returns true if stdout is piped to another command
198+
func isPiped() bool {
199+
stat, _ := os.Stdout.Stat()
200+
return (stat.Mode() & os.ModeCharDevice) == 0
201+
}
202+
193203
// getInstanceNamesAndEditor gets instance names from args/stdin and determines editor type
194204
// editorFlag takes precedence, otherwise last arg may be an editor type (code, cursor, windsurf, tmux)
195205
func getInstanceNamesAndEditor(args []string, editorFlag string) ([]string, string, error) {

0 commit comments

Comments
 (0)