Skip to content

Make CLI cleanup cross-platform#3620

Open
dipeshbabu wants to merge 1 commit intosimstudioai:mainfrom
dipeshbabu:fix/cli-cross-platform-cleanup
Open

Make CLI cleanup cross-platform#3620
dipeshbabu wants to merge 1 commit intosimstudioai:mainfrom
dipeshbabu:fix/cli-cross-platform-cleanup

Conversation

@dipeshbabu
Copy link

Summary

Replace shell-specific cleanup commands with cross-platform spawn() calls.

Problem

stopAndRemoveContainer() currently shells out with:

  • docker stop <name> 2>/dev/null || true
  • docker rm <name> 2>/dev/null || true

That syntax is shell-dependent and can fail on Windows.

Changes

  • add runCommandQuiet() using spawn()
  • use it for container stop/remove cleanup
  • preserve the current "ignore missing container" behavior without shell redirection

Validation

  • cd packages/cli && bun run type-check
  • test startup + Ctrl+C cleanup on macOS/Linux
  • test startup + cleanup on Windows PowerShell or CMD

@cursor
Copy link

cursor bot commented Mar 17, 2026

PR Summary

Low Risk
Low risk: only changes the CLI’s container cleanup to avoid shell-specific redirection, keeping behavior of ignoring stop/rm failures for missing containers.

Overview
Updates the CLI’s container cleanup to be cross-platform by replacing shell-based docker stop/rm invocations (with redirection/|| true) with a new runCommandQuiet() helper that runs spawn() with output suppressed.

stopAndRemoveContainer() now uses this quiet spawn-based execution to preserve “ignore missing container” behavior while working on Windows shells.

Written by Cursor Bugbot for commit c603c9f. This will update automatically on new commits. Configure here.

@vercel
Copy link

vercel bot commented Mar 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
docs Skipped Skipped Mar 17, 2026 4:21am

Request Review

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 17, 2026

Greptile Summary

This PR replaces the shell-specific execSync('docker stop … 2>/dev/null || true') calls inside stopAndRemoveContainer with a new runCommandQuiet() helper that uses spawn() with stdio: 'ignore', making container cleanup work correctly on Windows (where 2>/dev/null || true shell syntax is unavailable). The behavioral semantics are preserved — errors and non-zero exit codes are silently ignored, matching the original "container might not exist" intent.

Key observations:

  • The fix is targeted and correct for the problem it describes.
  • runCommandQuiet is an almost exact duplicate of the pre-existing runCommand function; the only difference is stdio: 'ignore' vs stdio: 'inherit'. These two functions should be unified with a parameter to avoid divergence over time.
  • Both runCommand and runCommandQuiet assign the child process to a variable named process, shadowing Node.js's built-in process global for the duration of each function body — a latent footgun if either function is extended.
  • Other execSync calls in the file (docker network ls, docker exec … pg_isready) do not use shell-specific redirection operators, so they are not a cross-platform concern in the same way.

Confidence Score: 4/5

  • Safe to merge — the cross-platform fix is correct and the issues found are minor style concerns that don't affect runtime behavior.
  • The core change is a straightforward and correct replacement of shell-dependent syntax with a portable spawn() call. The two flagged issues (code duplication and process variable shadowing) are style-level concerns with no impact on current functionality. No logic regressions were introduced.
  • No files require special attention beyond the minor style suggestions in packages/cli/src/index.ts.

Important Files Changed

Filename Overview
packages/cli/src/index.ts Replaces shell-specific execSync invocations in stopAndRemoveContainer with a new runCommandQuiet helper that uses spawn(). The logic is correct and achieves the cross-platform goal, but the new helper is a near-duplicate of the existing runCommand function and both shadow the global process object with a local variable of the same name.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[stopAndRemoveContainer] --> B[runCommandQuiet docker stop name]
    B --> C{spawn exits}
    C -- code 0 --> D[success: true]
    C -- code != 0 --> E[success: false]
    C -- error event --> F[success: false]
    D --> G[runCommandQuiet docker rm name]
    E --> G
    F --> G
    G --> H{spawn exits}
    H -- code 0 --> I[success: true]
    H -- code != 0 --> J[success: false]
    H -- error event --> K[success: false]
    I --> L[return void — caller ignores result]
    J --> L
    K --> L
Loading

Last reviewed commit: c603c9f

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

resolve(code === 0)
})
})
}
Copy link

Choose a reason for hiding this comment

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

New function duplicates existing one with minor difference

Low Severity

runCommandQuiet is a near-exact copy of the existing runCommand — the only difference is stdio: 'ignore' vs stdio: 'inherit'. Instead of duplicating the entire function, runCommand could accept an optional quiet parameter (or a stdio option) to control output visibility, avoiding redundant logic.

Additional Locations (1)
Fix in Cursor Fix in Web

Comment on lines +27 to +37
async function runCommandQuiet(command: string[]): Promise<boolean> {
return new Promise((resolve) => {
const process = spawn(command[0], command.slice(1), { stdio: 'ignore' })
process.on('error', () => {
resolve(false)
})
process.on('close', (code) => {
resolve(code === 0)
})
})
}
Copy link
Contributor

Choose a reason for hiding this comment

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

P2 Code duplication with runCommand

runCommandQuiet is functionally identical to the existing runCommand (lines 49–59), differing only in the stdio option ('ignore' vs 'inherit'). Keeping two near-identical implementations will make future maintenance harder. Consider refactoring into a single function with an optional parameter:

async function runCommand(command: string[], quiet = false): Promise<boolean> {
  return new Promise((resolve) => {
    const proc = spawn(command[0], command.slice(1), { stdio: quiet ? 'ignore' : 'inherit' })
    proc.on('error', () => resolve(false))
    proc.on('close', (code) => resolve(code === 0))
  })
}

Then callers use runCommand([...], true) for quiet execution, removing the need for runCommandQuiet entirely.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!


async function runCommandQuiet(command: string[]): Promise<boolean> {
return new Promise((resolve) => {
const process = spawn(command[0], command.slice(1), { stdio: 'ignore' })
Copy link
Contributor

Choose a reason for hiding this comment

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

P2 Variable name shadows global process

Naming the spawned child process silently shadows Node.js's built-in process global for the rest of this function body. Any future code added inside this function that tries to call process.exit(), process.env, etc., will unexpectedly operate on the ChildProcess object instead. The same pattern already exists in runCommand (line 51) — this PR replicates it. Rename both to something like proc or child.

Suggested change
const process = spawn(command[0], command.slice(1), { stdio: 'ignore' })
const proc = spawn(command[0], command.slice(1), { stdio: 'ignore' })
proc.on('error', () => {
resolve(false)
})
proc.on('close', (code) => {
resolve(code === 0)
})

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.

1 participant