Skip to content

Conversation

@ethanndickson
Copy link
Member

@ethanndickson ethanndickson commented Dec 5, 2025

Stack:

  1. 🤖 feat: add UI styling for background bash processes #923
  2. 🤖 feat: add background bash process execution with SSH support #920 (base) <- This PR

Summary

Adds run_in_background=true option to the bash tool, enabling agents to spawn long-running processes (dev servers, builds, file watchers) that persist independently.

Why This Approach

We needed background process support that works identically for both local and SSH runtimes. A few considerations drove the design:

  1. PTY-based output doesn't fit remote use cases. For SSH, maintaining a persistent PTY connection just to let agents read stdout would be fragile and complex. Agents need to search, filter, and tail output—not consume a live stream.

  2. File-based output lets agents use standard tools. By writing stdout/stderr to files on the target machine, agents can use tail -f, grep, head, etc. to inspect output. We don't need to reimplement these filtering capabilities in our own tooling.

  3. A proper long-lived remote daemon is future work. Ideally, SSH remotes would have a persistent mux process (or agent binary) that manages background jobs directly. The user's frontend would just connect to it. That's a significant architectural change. This PR provides background shell support without requiring that investment—the file-based approach works today with no remote-side dependencies.

Architecture

AI Tools (bash, bash_background_list, bash_background_terminate)
    ↓
BackgroundProcessManager (lifecycle, in-memory tracking)
    ↓
Runtime.spawnBackground() (LocalBaseRuntime / SSHRuntime)
    ↓
BackgroundHandle (file-based output & status)
    ↓
backgroundCommands.ts (shared shell builders for Local/SSH parity)

Key Design Decisions

Decision Rationale
File-based output Works identically for local and SSH, agents read via tail/cat
setsid + nohup Robust process isolation, clean group termination
Agent-only access Simpler security model, process tied to workspace context
Lazy status refresh No polling overhead, reads exit_code file on list()

Tools

  • bash(run_in_background=true) — spawns process, returns stdout_path/stderr_path
  • bash_background_list — lists processes with status and file paths
  • bash_background_terminate — kills process group (SIGTERM → wait → SIGKILL)

Output Structure

/tmp/mux-bashes/{workspaceId}/{bg-xxx}/
├── stdout.log    # Process stdout
├── stderr.log    # Process stderr  
├── exit_code     # Written by trap on exit
└── meta.json     # Process metadata

Platform Support

  • Unix/macOS: setsid + nohup pattern
  • SSH: Same pattern executed remotely
  • Windows: taskkill with MSYS2→Windows PID conversion

Testing

  • 19 unit tests in backgroundProcessManager.test.ts
  • 7 unit tests for background execution in bash.test.ts
  • Unit tests in backgroundCommands.test.ts

Generated with mux

Adds run_in_background=true option to bash tool for long-running processes
(dev servers, builds, file watchers). Returns process ID and output file
paths for agents to monitor via tail/grep/cat.

Key features:
- Works on both local and SSH runtimes (unified setsid+nohup pattern)
- Output written to files: /tmp/mux-bashes/{workspaceId}/{processId}/
- Exit code captured via bash trap to exit_code file
- Process group termination (SIGTERM → wait → SIGKILL)
- meta.json tracks process metadata

Tools:
- bash(run_in_background=true) - spawns process, returns stdout_path/stderr_path
- bash_background_list - lists processes with file paths
- bash_background_terminate - kills process group

Removed bash_background_read (agents read files directly with bash).

_Generated with mux_
@ethanndickson ethanndickson force-pushed the background-process-file-storage branch from fe89eef to 0c99075 Compare December 5, 2025 01:04
@ethanndickson ethanndickson force-pushed the background-process-file-storage branch from 0c99075 to 92ef0c8 Compare December 5, 2025 01:09
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

- Add NON_INTERACTIVE_ENV_VARS to SSH background spawns (parity with local)
- Use expanded paths in buildSpawnCommand so tilde resolves correctly
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Handle is always set on spawn and never cleared, so the null type
and guards were dead code from an unimplemented recovery feature.
Replace setTimeout(500) with polling helpers that retry until output
appears or exit code is set. Handles SSH latency variability without
making tests slower than necessary.
The earlier fix incorrectly passed expandTildeForSSH paths (already quoted)
to buildSpawnCommand which quotes again via shellQuote, breaking redirects.

Raw paths are correct - buildSpawnCommand handles quoting internally.
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Use os.tmpdir() instead of hardcoded /tmp/mux-bashes. On Windows,
convert to POSIX path using cygpath for Git Bash compatibility.

This fixes background process execution on Windows where /tmp doesn't
exist or requires elevated privileges.
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Add quotePath parameter to buildSpawnCommand allowing callers to choose
quoting strategy. SSH now uses expandTildeForSSH which produces double-
quoted paths with $HOME expansion, fixing ~/... bgOutputDir configs.

Local runtime continues using shellQuote (single quotes) as default.
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Add shell option to execAsync so callers can specify bash for POSIX
commands that don't work with cmd.exe (Windows default).

Fixed:
- LocalBaseRuntime.spawnBackground: nohup/setsid commands
- WorktreeRuntime.deleteWorkspace: rm -rf command
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

- Quote bash path in buildSpawnCommand to handle Windows paths with
  spaces (e.g., C:\Program Files\Git\bin\bash.exe)
- Add cwd validation to SSH spawnBackground (parity with local runtime)
- Add test for bash paths with spaces
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Add toPosixPath() utility that uses cygpath to convert Windows paths
(C:\foo\bar) to POSIX format (/c/foo/bar) for Git Bash compatibility.

Apply to:
- LocalBaseRuntime.spawnBackground: exitCodePath, cwd, stdoutPath, stderrPath
- WorktreeRuntime.deleteWorkspace: deletedPath for rm -rf
- runtimeFactory.getDefaultBgOutputDir: refactored to use shared utility
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ethanndickson ethanndickson force-pushed the background-process-file-storage branch from abc50fe to 99af592 Compare December 5, 2025 03:42
- getDefaultBgOutputDir: return native path for Node fs APIs, POSIX
  conversion happens at shell command construction time
- LocalBackgroundHandle.terminate: run winpid lookup via bash since
  /proc/PID/winpid is MSYS2's virtual filesystem, not visible to Node.js
- Add toPosixPath tests for path conversion behavior
- Add Windows POSIX path handling tests to backgroundCommands.test.ts
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

buildTerminateCommand now accepts optional quotePath parameter (like
buildSpawnCommand) to avoid double-quoting when used with SSH paths.

SSHBackgroundHandle.terminate() passes raw path + expandTildeForSSH
instead of pre-expanded path that would get quoted again by shellQuote.
@ethanndickson
Copy link
Member Author

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ethanndickson
Copy link
Member Author

@codex review

@ethanndickson ethanndickson force-pushed the background-process-file-storage branch from 36ea849 to c14210c Compare December 5, 2025 05:01
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@ethanndickson ethanndickson force-pushed the background-process-file-storage branch from 0c344cb to 9267c2c Compare December 5, 2025 05:06
@ethanndickson ethanndickson force-pushed the background-process-file-storage branch 2 times, most recently from b0305aa to 8848d10 Compare December 5, 2025 05:22
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