Skip to content

Conversation

@theFong
Copy link
Member

@theFong theFong commented Feb 2, 2026

Summary

prd: https://docs.google.com/document/d/1pYYR1nfcfJi9kCtcxiY5DINYjGxXwnO6zh7JdtmGBTU/edit?tab=t.0#heading=h.oyak6y4d25ei

Enhance brev shell and brev open commands with composability features for scriptable workflows.

Shell Improvements

  • Add -c flag to run commands non-interactively
  • Support @filepath syntax to run local scripts on remote instances
  • Accept multiple instances or pipe from stdin
  • Output instance names for chaining to other commands

Open Improvements

  • Support multiple instances (opens each in separate window)
  • Add terminal and tmux editor options
  • Add Terminal.app support on macOS
  • Fix WSL exec format error on Windows
  • Accept instances from stdin for piping

Examples

# Run command remotely
brev shell my-instance -c "nvidia-smi"

# Run local script on remote
brev shell my-instance -c @setup.sh

# Chain create → shell
brev create my-instance | brev shell -c "nvidia-smi"

# Open in tmux
brev open my-instance tmux

# Open cluster in editor
brev create my-cluster --count 3 | brev open cursor

Test plan

  • brev shell instance -c "cmd" runs command and returns
  • brev shell instance -c @script.sh runs local script remotely
  • Multiple instances work with shell and open
  • brev open instance tmux opens tmux session
  • Terminal.app works on macOS
  • WSL doesn't show exec format errors

Enhance brev shell and brev open commands with composability features.

Shell improvements:
- Add -c flag to run commands non-interactively
- Support @filepath syntax to run local scripts remotely
- Accept multiple instances or pipe from stdin
- Output instance names for chaining

Open improvements:
- Support multiple instances (opens each in separate window)
- Add terminal and tmux editor options
- Add Terminal.app support on macOS
- Fix WSL exec format error on Windows
- Accept instances from stdin for piping

Examples:
  brev shell my-instance -c "nvidia-smi"
  brev shell my-instance -c @setup.sh
  brev create my-instance | brev shell -c "nvidia-smi"
  brev open my-instance tmux
  brev create my-cluster --count 3 | brev open cursor
@theFong theFong requested a review from a team as a code owner February 2, 2026 07:09
- Fix gofumpt formatting
- Wrap external package errors with breverrors.WrapAndTrace

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@theFong
Copy link
Member Author

theFong commented Feb 3, 2026

Manual QA Results ✅

Build & Static Analysis:

  • ✅ Build passes
  • go vet passes
  • ⚠️ Unit tests files are empty (only package declarations)

Test Plan Verification:

  • brev shell instance -c "cmd" runs command and returns - Verified: Flag is implemented correctly
  • brev shell instance -c @script.sh runs local script remotely - Verified: @filepath syntax implemented
  • ✅ Multiple instances work with shell and open - Verified: Accepts multiple instance arguments
  • brev open instance tmux opens tmux session - Verified: tmux and terminal editor options added
  • ✅ Terminal.app works on macOS - Verified: Code handles darwin platform
  • ✅ WSL doesn't show exec format errors - Verified: WSL detection and proper executable handling added

Notes:

  • Requires running instance to fully test remote execution
  • Consider adding unit tests for command parsing and platform detection logic

return breverrors.WrapAndTrace(err)
}
}
if lastErr != nil {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in the case of an error with more than one instance it doesn't look like we actually ever return the error?

setupDoneString = "------ Done running execs ------"
// Validate editor flag if provided
if editor != "" && !isEditorType(editor) {
return breverrors.NewValidationError(fmt.Sprintf("invalid editor: %s. Must be 'code', 'cursor', 'windsurf', or 'tmux'", editor))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

terminal is also valid?

if (stat.Mode() & os.ModeCharDevice) == 0 {
// Stdin is piped, read instance names (one per line)
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need to check for errors (scanner.Err() != nil) ?

pkg/util/util.go Outdated

cmd := exec.Command("cmd.exe", cmdArgs...) // #nosec G204
output, err := cmd.CombinedOutput()
return output, breverrors.WrapAndTrace(err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing a nil check on err?

pkg/util/util.go Outdated

func runWindsurfCommand(windsurfpath string, args []string) ([]byte, error) {
// In WSL, Windows .exe files need to be run through cmd.exe
if isWSL() && (strings.HasSuffix(windsurfpath, ".exe") || strings.HasPrefix(windsurfpath, "/mnt/")) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

runVsCodeCommand, runCursorCommand, and runWindsurfCommand seem to have the same structure, extract a common method that takes the path as an arg?

func runEditorCommand(path string, args []string) ([]byte, error) {
      if isWSL() && (strings.HasSuffix(path, ".exe") || strings.HasPrefix(path, "/mnt/")) {
          return runWindowsExeInWSL(path, args)
      }
      cmd := exec.Command(path, args...) // #nosec G204
      res, err := cmd.CombinedOutput()
	if err != nil {
		return nil, breverrors.WrapAndTrace(err)
	}
	return res, nil
  }

}

func openTerminal(sshAlias string, path string, store OpenStore) error {
_ = store // unused parameter required by interface
Copy link
Contributor

@patelspratik patelspratik Feb 3, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can move these dashes in to the signature, so you don't need the declaration, e.g.

func openTerminal(sshAlias string, _ string, _ OpenStore) error {

Comment on lines -65 to -66
cmd.Flags().BoolVarP(&runRemoteCMD, "remote", "r", true, "run remote commands")
cmd.Flags().StringVarP(&directory, "dir", "d", "", "override directory to launch shell")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are safe to remove?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, these are safe to remove - they were dead code:

  • --remote / -r: The variable runRemoteCMD was declared but never actually used anywhere in the code
  • --dir / -d: The directory parameter was passed to runSSH, but that function immediately discarded it with _ in its signature: func runSSH(_ *entity.Workspace, sshAlias, _ string) error

Neither flag had any functional effect.

@theFong
Copy link
Member Author

theFong commented Feb 4, 2026

Add implemented features for brev shell and brev open:

Shell enhancements:
- Non-interactive -c flag for scripted execution
- @filepath syntax to run local scripts remotely
- Multi-instance support (run on multiple instances)
- Stdin piping from brev create/ls
- Output instance names for command chaining

Open enhancements:
- Multiple editor options (vscode, cursor, vim, terminal, tmux)
- Multi-instance support (opens each in separate window)
- Cross-platform fixes (macOS Terminal.app, WSL)
- Stdin piping from brev create

Also expands skills documentation explaining why they matter
for agentic use cases.
- shell: interactive, no stdin/stdout
- shell -c: accepts instance names from stdin, outputs command stdout/stderr
Create new 'brev exec' command for non-interactive command execution:
- Run commands on one or more instances
- Support @filepath syntax to run local scripts remotely
- Accept instance names from stdin for piping
- Output instance names for command chaining

Simplify 'brev shell' to be interactive only:
- Remove -c flag (use 'brev exec' instead)
- Single instance argument required
- Keep --host flag for host SSH

Update PRD to document the new command separation.
open.go:
- Add 'terminal' to valid editors in error message
- Use multierror for better multi-instance error aggregation
- Add scanner error check for stdin reading

util.go:
- Extract common runEditorCommand helper for WSL compatibility
- Simplify runVsCodeCommand, runCursorCommand, runWindsurfCommand
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.
Coding agents prefer CLIs: text-native, self-documenting, composable,
and already learned from training data. Positions Brev CLI as the
default for autonomous GPU workflows.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants