Skip to content

Fix bash job completion notifications leaking to terminal - #2495

Closed
ggzeng wants to merge 1 commit into
manaflow-ai:mainfrom
ggzeng:fix/bash-job-notify
Closed

ggzeng wants to merge 1 commit into
manaflow-ai:mainfrom
ggzeng:fix/bash-job-notify

Conversation

@ggzeng

@ggzeng ggzeng commented Apr 1, 2026 •

Copy link
Copy Markdown

Summary

Replace { cmd; } & disown with ( cmd & ) subshell pattern in the bash integration script to prevent spurious [n] Done ... messages from appearing after every command.

Problem

After every command in a cmux bash terminal, users see:

[2]   Done                       { _cmux_send "report_shell_state $state --tab=$CMUX_TAB_ID --panel=$CMUX_PANEL_ID"; } > /dev/null 2>&1
[3]   Done                       { _cmux_send "ports_kick --tab=$CMUX_TAB_ID --panel=$CMUX_PANEL_ID"; } > /dev/null 2>&1

The { ... } & disown pattern registers a job number at creation time. When these short-lived tasks finish, bash reports completion before the next prompt — even though disown was called. This is a known bash behavior.

The zsh integration already handles this correctly via _cmux_send_bg using &!, but the bash side lacked an equivalent fix.

Fix

Changed 4 occurrences in cmux-bash-integration.bash:

  • _cmux_report_tty_once — tty name reporting
  • _cmux_report_shell_activity_state — shell state sync
  • _cmux_ports_kick — port scanner kick
  • _cmux_prompt_command — pwd sync

The outer ( ... ) subshell exits immediately. The inner cmd & process becomes an orphan that bash no longer tracks, preventing any job notification. Functionality is preserved.

Closes #2494

Test plan

  • Open a cmux terminal with bash, run a command — verify no [n] Done ... output
  • Verify shell state, port detection, cwd tracking, and git branch detection still work in the sidebar
  • Test in a non-cmux terminal to confirm no regression

Summary by cubic

Stop bash job-completion messages by launching cmux background tasks in a subshell. Replace { cmd; } & disown with ( cmd & ) so bash doesn’t track and announce jobs.

  • Bug Fixes
    • Prevent [n] Done ... lines after commands in cmux bash sessions using ( _cmux_send ... & ).
    • Updated: _cmux_report_tty_once, _cmux_report_shell_activity_state, _cmux_ports_kick, _cmux_prompt_command.

Written for commit aabda91. Summary will update on new commits.

Summary by CodeRabbit

  • Chores
    • Improved shell integration’s background task handling to be quieter and more reliable by changing how asynchronous notifications are launched and output is suppressed.
    • Reduced background noise and likelihood of orphaned processes by simplifying background execution mechanics.
    • No user-facing interfaces changed; behavior and features remain the same.

@vercel

vercel Bot commented Apr 1, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Apr 1, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Converted brace-group-plus-disown async patterns to subshell-wrapped backgrounding ( ... & ) for several _cmux_send invocations in the bash integration to prevent bash job-completion notifications; synchronous _cmux_send calls remain unchanged.

Changes

Cohort / File(s) Summary
Bash async job-launch refactor
Resources/shell-integration/cmux-bash-integration.bash
Replaced { ...; } >/dev/null 2>&1 & disown with ( _cmux_send ... >/dev/null 2>&1 & ) in _cmux_report_tty_once, _cmux_report_shell_activity_state, _cmux_ports_kick, and the prompt-command CWD report to avoid shell job notifications. Other _cmux_send usages unchanged.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

🐰 I hopped through bash and hushed the din,
Wrapped tiny sends so jobs don't win.
Subshells cradle the quiet calls,
Prompts stay calm, no "[n] Done" at all.
Hop—silence blooms across the hall. 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: converting bash job backgrounding patterns to prevent spurious job completion notifications.
Description check ✅ Passed The description covers the problem, root cause analysis, the fix applied, affected functions, and includes a test plan matching the repository template.
Linked Issues check ✅ Passed The PR fully addresses issue #2494 by replacing all four instances of { cmd; } & disown with ( cmd & ) in the specified functions to eliminate bash job notifications.
Out of Scope Changes check ✅ Passed All changes are directly related to the stated objective: modifying only the four specific locations in cmux-bash-integration.bash to prevent job completion notifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@greptile-apps

greptile-apps Bot commented Apr 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a UX annoyance in the bash shell integration where short-lived background tasks (shell-state sync, port detection, cwd tracking, tty reporting) were emitting [n] Done ... job-completion notices to the terminal after every command. The root cause is that { cmd; } & disown still registers a job number before disown removes the job, so bash prints the completion message when the job finishes. The fix adopts the ( cmd & ) subshell idiom, which is already used by the zsh integration via _cmux_send_bg &!.

Changes:

  • _cmux_report_tty_once — TTY-name reporting now uses ( _cmux_send \"$payload\" >/dev/null 2>&1 & )
  • _cmux_report_shell_activity_state — shell-state sync uses the same pattern
  • _cmux_ports_kick — port-scanner kick uses the same pattern
  • _cmux_prompt_command — pwd sync converted to ( local qpwd=...; _cmux_send ... & )

Notes:

  • The local qpwd declaration inside the (...) subshell in _cmux_prompt_command is now redundant (subshell variables never propagate to the parent regardless of local), but it is harmless and was inherited from the original brace-group where it was necessary.
  • The redirections and argument expansion are semantically identical to the old code; all four background tasks still discard stdout/stderr and fire-and-forget.

Confidence Score: 5/5

Safe to merge — targeted, well-understood bash idiom swap with no functional changes.

All four changed call sites use the same correct ( cmd & ) pattern. The fix is a well-known bash idiom for silent fire-and-forget background work, consistent with the existing zsh integration. No logic, data flow, or interface changes are introduced. The only non-functional observation (redundant local inside the _cmux_prompt_command subshell) does not affect behaviour.

No files require special attention.

Important Files Changed

Filename Overview
Resources/shell-integration/cmux-bash-integration.bash Four { ... } >/dev/null 2>&1 & disown blocks replaced with the ( cmd >/dev/null 2>&1 & ) subshell pattern to suppress spurious job-completion notifications; logic and functionality are unchanged.

Sequence Diagram

sequenceDiagram
    participant Shell as Bash Shell (PROMPT_COMMAND)
    participant Subshell as ( ) Subshell
    participant BgProc as _cmux_send (background)
    participant App as cmux App (socket)

    Shell->>Subshell: fork subshell ( _cmux_send ... & )
    activate Subshell
    Subshell->>BgProc: start & (orphan, no job tracking)
    Subshell-->>Shell: exits immediately
    deactivate Subshell
    Note over Shell: No job number registered<br/>No [n] Done ... notification
    BgProc->>App: send socket message (report_pwd / report_shell_state / ports_kick / tty)
    BgProc-->>BgProc: stdout/stderr → /dev/null
    BgProc-->>BgProc: exits (reparented to init, untracked)
Loading

Reviews (1): Last reviewed commit: "Fix bash job completion notifications le..." | Re-trigger Greptile

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 1 file

@sandipb

sandipb commented Apr 8, 2026

Copy link
Copy Markdown

The patch is not cleanly applying to the latest version of the integration script. I had to apply these manually.

@ggzeng
ggzeng force-pushed the fix/bash-job-notify branch from d86dfa3 to 73084b2 Compare April 9, 2026 15:45
@ggzeng

ggzeng commented Apr 10, 2026

Copy link
Copy Markdown
Author

Thanks for the heads up @sandipb! I'll rebase this onto the latest integration script so the patch applies cleanly. Should update shortly.

@ggzeng
ggzeng force-pushed the fix/bash-job-notify branch from 73084b2 to a598d25 Compare April 11, 2026 09:02
Replace `{ cmd; } & disown` with `( cmd & )` subshell pattern in 4
places. The outer subshell exits immediately, making the inner
background process an orphan that bash no longer tracks, preventing
spurious "[n] Done ..." messages.

Closes manaflow-ai#2494
@ggzeng
ggzeng force-pushed the fix/bash-job-notify branch from a598d25 to aabda91 Compare April 13, 2026 16:43
@ggzeng

ggzeng commented Apr 13, 2026

Copy link
Copy Markdown
Author

Rebased onto the latest main — the patch should now apply cleanly. @sandipb could you verify?

@sandipb

sandipb commented Apr 13, 2026

Copy link
Copy Markdown

The patch does cleanly apply. Thanks so much for updating it.

However I must point out that there is alternate PR from the cmux team which is working on this exact change too.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@Resources/shell-integration/cmux-bash-integration.bash`:
- Around line 1001-1004: In _cmux_emit_pr_command_hint(), replace the current
async send block that uses the braces/disown pattern (the `{ _cmux_send ...; }
>/dev/null 2>&1 & disown` code) with the subshell background pattern used
elsewhere: wrap the _cmux_send invocation in a subshell like `( _cmux_send ...
>/dev/null 2>&1 & )` so it is spawned in the background without causing bash
job-control “[n] Done …” notifications; ensure you preserve the same arguments
(e.g. the `report_...` string and `--tab=$CMUX_TAB_ID --panel=$CMUX_PANEL_ID`)
and quoting behavior used in _cmux_emit_pr_command_hint().
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 76e13417-7669-4656-97ed-a061557af591

📥 Commits

Reviewing files that changed from the base of the PR and between a598d25 and aabda91.

📒 Files selected for processing (1)
  • Resources/shell-integration/cmux-bash-integration.bash

Comment on lines +1001 to +1004
(
local qpwd="${pwd//\"/\\\"}"
_cmux_send "report_pwd \"${qpwd}\" --tab=$CMUX_TAB_ID --panel=$CMUX_PANEL_ID"
} >/dev/null 2>&1 & disown
_cmux_send "report_pwd \"${qpwd}\" --tab=$CMUX_TAB_ID --panel=$CMUX_PANEL_ID" >/dev/null 2>&1 &
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="Resources/shell-integration/cmux-bash-integration.bash"

# Expectation:
# - Lines 383, 401, 415, and 1001-1004 show the new subshell pattern.
# - Lines 511-513 still show the old brace-group + disown pattern.

printf 'Changed async send sites:\n'
nl -ba "$file" | sed -n '372,418p'

printf '\nRemaining brace-group + disown send site:\n'
nl -ba "$file" | sed -n '500,516p'

Repository: manaflow-ai/cmux

Length of output: 1781


🏁 Script executed:

# Fallback: attempt to list the repository details to understand availability
git ls-remote https://github.com/manaflow-ai/cmux.git HEAD

Repository: manaflow-ai/cmux

Length of output: 105


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="Resources/shell-integration/cmux-bash-integration.bash"

printf 'Changed async send sites (expecting new subshell pattern):\n'
printf '\nLines 383:\n'
sed -n '380,386p' "$file" | cat -n

printf '\nLines 401:\n'
sed -n '398,404p' "$file" | cat -n

printf '\nLines 415:\n'
sed -n '412,418p' "$file" | cat -n

printf '\nLines 1001-1004:\n'
sed -n '999,1006p' "$file" | cat -n

printf '\n\nRemaining brace-group + disown send site (should be at 511-513):\n'
sed -n '508,516p' "$file" | cat -n

Repository: manaflow-ai/cmux

Length of output: 1843


Convert remaining _cmux_emit_pr_command_hint() sender to subshell pattern to complete the fix.

This PR converts several async-send sites to the safer subshell form ( _cmux_send ... >/dev/null 2>&1 & ), but lines 511–513 in _cmux_emit_pr_command_hint() still use { _cmux_send ...; } >/dev/null 2>&1 & disown. Since _cmux_prompt_command() invokes this helper after successful gh pr ... commands, the bash job-control [n] Done ... notification leak persists. Apply the same conversion pattern to lines 511–513 to complete the fix.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Resources/shell-integration/cmux-bash-integration.bash` around lines 1001 -
1004, In _cmux_emit_pr_command_hint(), replace the current async send block that
uses the braces/disown pattern (the `{ _cmux_send ...; } >/dev/null 2>&1 &
disown` code) with the subshell background pattern used elsewhere: wrap the
_cmux_send invocation in a subshell like `( _cmux_send ... >/dev/null 2>&1 & )`
so it is spawned in the background without causing bash job-control “[n] Done …”
notifications; ensure you preserve the same arguments (e.g. the `report_...`
string and `--tab=$CMUX_TAB_ID --panel=$CMUX_PANEL_ID`) and quoting behavior
used in _cmux_emit_pr_command_hint().

@ggzeng

ggzeng commented Apr 17, 2026

Copy link
Copy Markdown
Author

Thanks for the heads up @sandipb! I noticed the CodeRabbit review also flagged a fifth _cmux_emit_pr_command_hint() function that still uses the old braces/disown pattern.

Since the cmux team has their own PR for this, I'm happy to either close this PR in favor of the official one, or add the fifth fix and keep this open.

Let me know what you'd prefer. I'll also check if the official PR covers all five call sites.

@ggzeng

ggzeng commented Apr 18, 2026

Copy link
Copy Markdown
Author

Closing this PR since the cmux team has an official PR addressing the same issue. Thanks @sandipb for testing and the heads-up!

@ggzeng ggzeng closed this Apr 18, 2026
@sandipb

sandipb commented Apr 18, 2026

Copy link
Copy Markdown

For others who may run into this PR:

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.

Bash integration: background job completion notifications leak to the terminal

2 participants