Skip to content

Add nushell support: wrapper shim routing, resume envelope, fish-parity shell integration - #8104

Merged
austinywang merged 7 commits into
manaflow-ai:mainfrom
RemiKalbe:nushell-support
Aug 20, 2026
Merged

austinywang merged 7 commits into
manaflow-ai:mainfrom
RemiKalbe:nushell-support

Conversation

@RemiKalbe

@RemiKalbe RemiKalbe commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #10050

Nushell login shells get no shell integration: applyManagedShellSpecificStartupEnvironment has cases for zsh, bash, and fish, and nu falls through default:. For a nushell user this breaks in three places:

  1. Claude sessions are never captured. A typical env.nu rebuilds PATH with its own prepends, which shadows the per-surface cmux-cli-shims shim. The zsh and fish integrations recover from this; nushell has nothing, so cmux-claude-wrapper never runs and ~/.cmuxterm/claude-hook-sessions.json never gets written. Session resume and Claude notifications never work at all.
  2. Even with a captured session, every resume command is a parse error in nushell. The strings are POSIX (cd -- '…' 2>/dev/null || [ ! -d '…' ] && 'claude' '--resume' '<id>'), and nushell rejects &&, ||, [ … ], and quoted command heads like 'claude'.
  3. None of the socket reporting runs: busy/idle state, cwd tracking, tty registration, port-scan kicks.

The fix

Capture: a case "nu" that launches nushell as '<shell>' -l -e '<payload>', mirroring the fish replacement command. --execute runs the payload after the user's config and then opens the REPL. The payload is the new bundled cmux-nushell-bootstrap.nu squashed to one line: it moves cmux-cli-shims entries back to the front of PATH, then sources the integration file (path baked in as a literal, since nushell source needs a parse-time constant). If the bundle files are missing, the shell starts vanilla, same as the zsh/fish guards.

Resume: commands stay POSIX everywhere. At the points where cmux types a command into the user's interactive shell (panel resume, session drag-drop, clipboard copy, startup/fork/hibernation inline inputs) they get wrapped as ^/bin/sh -c "<escaped>", the same delegate-to-sh idea as the #5639 wrapper token. Inline inputs embedded into the zsh launcher scripts are not wrapped. The scripts instead grow a nu) dispatch branch that runs the command through /bin/sh and then execs nushell with the bootstrap payload rebuilt from CMUX_SHELL_INTEGRATION_DIR, so a resumed surface keeps its shim. (The first dogfood round caught a wrapped string reaching /bin/sh: /bin/sh: ^/bin/sh: No such file or directory. There are regression tests for exactly that now.)

Integration: cmux-nushell-integration.nu provides what the fish integration provides, with the same wire formats: report_tty, report_shell_state, report_pwd, ports_kick, claude/grok wrapper defs, scrollback restore, keyboard-protocol reset, remote relay fallback. State lives in _CMUX_* env vars and the hooks are registered as strings so def --env mutations persist across prompts; background sends use job spawn. The zsh-only extras (git-branch probes, PR polling, Ghostty job-table patching) are not replicated; fish doesn't have them either.

Commits

Two commits, red then green.

  1. Tests only. Three Python suites drive real nu against the bundled files: shim re-fronting under a hostile env.nu, the sh envelope (quoting edges, non-ASCII printf substitutions, env prefixes, and a pin that the legacy POSIX string stays a parse error), and the hook wire formats against a unix-socket fixture. CI installs a pinned, checksum-verified nushell 0.113.1 in the shard that runs the wrapper tests. Locally the tests skip with a message when nu is absent; on CI they fail instead, so they can never silently skip.
  2. The fix, plus Swift tests: nu rows in ShellStartupMatrixTests, the missing-bundle fallback, real-nu resume dispatch regressions next to the existing fish/tcsh Claude resume still drops cmux hooks after #5430: bare claude doesn't resolve to the wrapper inside the $SHELL -lic restore launcher #5639 tests, an end-to-end run of the generated launcher script under zsh with a fake nu login shell, and NushellTypedShellCommandTests in CMUXAgentLaunch. /usr/local/bin/nu comes out of the unsupported-shells matrix row, which is the clearest red-to-green flip in the diff.

Verified

Dogfooded over two rounds on a machine whose login shell is nushell 0.113.1: capture, app-relaunch auto-resume (including the resumed surface keeping its shim), panel resume, and session drag-drop. The design choices (why -e, why delegate to /bin/sh instead of teaching every builder a second dialect) came from probing real nu; the Python tests encode those probes.

No user-facing strings changed, so nothing to localize.

Not covered

Full zsh parity (git-branch probes, PR polling, job-table patching), nushell on remote cmux ssh hosts, and users with a custom Ghostty command, who skip the replacement command; fish has the same limitation.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added Nushell (nu) support for shell startup and typed, shell-safe session resume/command execution.
    • Introduced Nushell shell-integration for activity reporting, PWD tracking, port “kicks,” keyboard reset, and kitty scrollback restore.
    • Ensured cmux-cli-shims are re-fronted in Nushell PATH during bootstrap.
  • Bug Fixes
    • Corrected Nushell resume/launcher behavior by routing command evaluation through a /bin/sh -c boundary and preserving integration on re-entry.
  • Tests / CI
    • Expanded Nushell regression and end-to-end coverage (hooks, quoting/escaping, shim refronting, dialect handling).
    • Updated CI to install a pinned NuShell binary for macOS test shards.

@RemiKalbe
RemiKalbe requested a review from lawrencecchen as a code owner July 14, 2026 23:11
@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown

@RemiKalbe 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 Jul 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Nushell support was added across shell startup, command rendering, session resume paths, cmux shell integration, PATH shim ordering, CI setup, and regression tests.

Changes

Nushell shell integration

Layer / File(s) Summary
Nushell integration runtime
Resources/shell-integration/nushell/*, tests/test_nushell_integration_hooks.py, .github/workflows/ci.yml
Adds Nushell bootstrap and integration hooks for PATH shim ordering, socket or relay reporting, terminal restoration, command wrappers, and CI regression execution.
Nushell startup wiring
Packages/macOS/CmuxTerminal/..., Resources/shell-integration/nushell/*, cmuxTests/ShellStartup*
Detects Nushell during startup, embeds bootstrap and optional integration payloads, quotes generated commands, and handles missing bundles.
Shell-aware resume execution
Packages/macOS/CMUXAgentLaunch/..., Sources/*, cmuxTests/SessionPersistence*, tests/test_nushell_resume_command_dialect.py
Wraps POSIX resume commands for Nushell, updates resume, fork, and launcher paths, and validates quoting, fallback execution, integration re-entry, and shell dispatch.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TerminalSurface
  participant Nushell
  participant POSIXShell
  participant cmux_nushell_integration
  TerminalSurface->>Nushell: launch with -l -e startup payload
  Nushell->>cmux_nushell_integration: source integration and register hooks
  Nushell->>POSIXShell: execute wrapped resume command through /bin/sh -c
  cmux_nushell_integration->>TerminalSurface: report shell activity and session state
Loading

Possibly related PRs

  • manaflow-ai/cmux#4237: Adds the surface resume binding and restore plumbing extended here for Nushell dialect handling.

Suggested reviewers: lawrencecchen


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 27.54% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Cmux Swift @Concurrent ❓ Inconclusive Pending code inspection of Swift concurrency changes and review-bot rules. Need to inspect the diffed Swift files and .github/review-bot-rules/swift-concurrent-annotation.md to verify any @concurrent violations.
✅ Passed checks (23 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed New value types/helpers are nonisolated and Sendable as needed; UI-bound call sites remain on @MainActor, with no new mutable Sendable refs or background UI access.
Cmux Swift Blocking Runtime ✅ Passed Changed non-test Swift files only add shell-command rendering; no new semaphores, sync waits, sleeps, timers, polling, or manual locks were introduced.
Cmux Browser Automation Off-Main ✅ Passed The only changed file is NushellTypedShellCommand.swift; no browser socket automation, worker routing, or WebKit/AppKit code was modified.
Cmux Expensive Synchronous Load ✅ Passed PASS: The PR only adds Nushell command wrapping; the existing SharedLiveAgentIndex.shared ?? RestorableAgentSessionIndex.load() nil-cache fallback remains unchanged, with no new main-actor histor...
Cmux Cache Substitution Correctness ✅ Passed No fresh authoritative read was swapped for a cache in snapshot/history paths; the new typed-input code uses live snapshot data, and unreadable Nushell bundles fail closed with a documented nil fal...
Cmux No Hacky Sleeps ✅ Passed No new hacky sleeps were added; the Nushell refresh timer mirrors existing shell integrations and the new workflow step has no waits.
Cmux Algorithmic Complexity ✅ Passed New code is boundary-only string processing or fixed-size hook wiring; scans are single-pass over tiny bootstrap/PATH data, with no nested rescans or hot-path batching.
Cmux Swift Concurrency ✅ Passed PASS: The Nushell additions are synchronous helpers; I found no new DispatchQueue, Task.detached, completion-handler, or Combine state additions in the changed Swift code.
Cmux Swift File And Package Boundaries ✅ Passed PASS: The Nushell feature is split into a 41-line package helper plus small glue updates; no new oversized Swift file or >250-line growth in an existing one.
Cmux Swiftpm Lockfiles ✅ Passed Only a Swift source tweak changed; no Package.swift, Package.resolved, .gitignore, Xcode package refs, or workflow lockfile changes to review.
Cmux Swift Logging ✅ Passed PR hunk only marks NushellTypedShellCommand Sendable/nonisolated; no added print/debugPrint/dump/NSLog/Logger in runtime code.
Cmux User-Facing Error Privacy ✅ Passed No user-facing error copy changed; the new vendor-name strings are internal logger diagnostics, not alerts or returned messages.
Cmux Full Internationalization ✅ Passed Touched production code adds shell-dialect logic and logger/comments only; no new user-facing Swift copy or catalog files were introduced.
Cmux Swiftui State Layout ✅ Passed The checked-out commit only changes NushellTypedShellCommand; no SwiftUI views, state objects, GeometryReader, or render-time mutations were introduced.
Cmux Architecture Rethink ✅ Passed The diff only adds a stateless Nushell command-rendering helper; no sleeps, polling, locks, observers, or duplicate lifecycle wiring appear.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The only Swift change is a shell-command helper; it adds no NSWindow/NSPanel/WindowGroup code or cmuxAuxiliaryWindowIdentifiers changes.
Cmux Source Artifacts ✅ Passed Changed paths are intentional source, tests, configs, resources, fixtures, or submodule bumps; no temp/output/cache/screenshot/artifact files were added.
Cmux No Test Or Debug Seam In Production Source ✅ Passed The only production-source diff is NushellTypedShellCommand gaining nonisolated/Sendable; no #if DEBUG, ForTesting, or test-only seam members were added.
Cmux No Ambient Global State ✅ Passed The only code change is marking existing NushellTypedShellCommand as Sendable/nonisolated; no new top-level funcs, globals, or singleton/static-only namespaces were added.
Title check ✅ Passed The title clearly summarizes the main changes: Nushell support, wrapper routing, resume handling, and shell integration.
Description check ✅ Passed The description provides a detailed summary, rationale, testing evidence, verified scenarios, and explicit limitations, so it is mostly complete.
✨ 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.

@greptile-apps

greptile-apps Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds Nushell support for startup, resume, and shell integration. The main changes are:

  • Nushell startup now loads the cmux bootstrap and shell integration.
  • Resume commands typed into Nushell are routed through /bin/sh.
  • Restored Nushell launcher scripts re-enter with the integration payload.
  • Nushell hook tests cover PATH re-fronting, resume syntax, and socket reporting.

Confidence Score: 5/5

This looks safe to merge.

  • No blocking issues found in the changed code.

Important Files Changed

Filename Overview
Resources/shell-integration/nushell/cmux-nushell-integration.nu Adds Nushell hook integration for tty, state, pwd, port, wrapper, and scrollback behavior.
Sources/SessionPersistence.swift Adds Nushell launcher-script dispatch and re-entry payload construction.
Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/NushellTypedShellCommand.swift Adds the Nushell-safe typed command wrapper around POSIX resume commands.
Sources/RestorableAgentSession.swift Adds shell dialect selection for local and remote resume or fork startup inputs.
Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Spawn/TerminalSurface+StartupEnvironment.swift Adds managed Nushell startup payload generation and shim re-fronting.

Reviews (6): Last reviewed commit: "Mark NushellTypedShellCommand nonisolate..." | Re-trigger Greptile

Comment thread Resources/shell-integration/nushell/cmux-nushell-integration.nu
Comment thread Sources/SessionPersistence.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 89f555214e

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/RestorableAgentSession.swift Outdated

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@Resources/shell-integration/nushell/cmux-nushell-integration.nu`:
- Around line 31-36: Memoize the result of the `_cmux_socket_is_unix` probe for
the session instead of running `^/bin/test -S` on every hook invocation. Add a
session-scoped cached value and have `_cmux_report_shell_activity_state` and
`_cmux_ports_kick` reuse it, while preserving the existing empty/non-absolute
socket checks and activity-state deduplication behavior.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 43069287-b41f-46d6-a6a3-2f84a3b7dc4c

📥 Commits

Reviewing files that changed from the base of the PR and between d8f6bdd and 89f5552.

📒 Files selected for processing (19)
  • .github/workflows/ci.yml
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/NushellTypedShellCommand.swift
  • Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/NushellTypedShellCommandTests.swift
  • Packages/macOS/CmuxTerminal/Sources/CmuxTerminal/Spawn/TerminalSurface+StartupEnvironment.swift
  • Resources/shell-integration/nushell/cmux-nushell-bootstrap.nu
  • Resources/shell-integration/nushell/cmux-nushell-integration.nu
  • Sources/RestorableAgentSession.swift
  • Sources/SessionIndexView.swift
  • Sources/SessionPersistence.swift
  • Sources/SessionRestoredTerminalCommandStore.swift
  • Sources/SurfaceResumeCommandCanonicalizer+PortableAgentExecutable.swift
  • Sources/Workspace.swift
  • cmuxTests/SessionPersistenceResumeBindingTests.swift
  • cmuxTests/SessionPersistenceTests.swift
  • cmuxTests/ShellStartupMatrixTests.swift
  • cmuxTests/ShellStartupMissingBundleTests.swift
  • tests/test_nushell_integration_hooks.py
  • tests/test_nushell_resume_command_dialect.py
  • tests/test_nushell_shim_path_refront.py

Comment thread Resources/shell-integration/nushell/cmux-nushell-integration.nu Outdated

@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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/NushellTypedShellCommand.swift`:
- Around line 17-18: Mark the pure value-model struct NushellTypedShellCommand
as nonisolated while preserving its public initializer and existing behavior.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 574372de-86be-450a-8960-5e03b617f71f

📥 Commits

Reviewing files that changed from the base of the PR and between 8d12d69 and 14a96dd.

📒 Files selected for processing (9)
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/NushellTypedShellCommand.swift
  • Packages/macOS/CMUXAgentLaunch/Tests/CMUXAgentLaunchTests/NushellTypedShellCommandTests.swift
  • Resources/shell-integration/nushell/cmux-nushell-integration.nu
  • Sources/RestorableAgentSession.swift
  • Sources/SessionIndexView.swift
  • Sources/SessionPersistence.swift
  • Sources/Workspace.swift
  • cmuxTests/SessionPersistenceTests.swift
  • cmuxTests/ShellStartupMatrixTests.swift

@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.

♻️ Duplicate comments (1)
Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/NushellTypedShellCommand.swift (1)

17-19: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Mark the pure value struct as nonisolated.

As per coding guidelines, pure value-model structs should be marked as nonisolated to prevent implicit @MainActor isolation in Swift 6.

♻️ Proposed refactor
-public struct NushellTypedShellCommand {
+nonisolated public struct NushellTypedShellCommand {
     /// The renderer is stateless; construct at the call site.
     public init() {}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/NushellTypedShellCommand.swift`
around lines 17 - 19, Mark the pure value-model struct NushellTypedShellCommand
as nonisolated while preserving its public initializer and stateless behavior.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In
`@Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/NushellTypedShellCommand.swift`:
- Around line 17-19: Mark the pure value-model struct NushellTypedShellCommand
as nonisolated while preserving its public initializer and stateless behavior.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: aae8502c-0ffa-4071-adbd-0cc3c1c0a925

📥 Commits

Reviewing files that changed from the base of the PR and between 14a96dd and 23aa043.

📒 Files selected for processing (7)
  • Packages/macOS/CMUXAgentLaunch/Sources/CMUXAgentLaunch/NushellTypedShellCommand.swift
  • Resources/shell-integration/nushell/cmux-nushell-integration.nu
  • Sources/RestorableAgentSession.swift
  • Sources/SessionPersistence.swift
  • tests/test_nushell_integration_hooks.py
  • tests/test_nushell_resume_command_dialect.py
  • tests/test_nushell_shim_path_refront.py

@cursor

cursor Bot commented Jul 15, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@RemiKalbe

Copy link
Copy Markdown
Contributor Author

@lawrencecchen with the amount of PRs I fear this is never gonna get reviewed. Without this cmux is pretty much useless when you run Nushell.

@RemiKalbe

Copy link
Copy Markdown
Contributor Author

RemiKalbe and others added 7 commits August 12, 2026 10:00
cmux has no shell integration for nushell: the cmux-cli-shims claude
wrapper gets shadowed by user PATH prepends in env.nu (so sessions are
never captured and resume never works), resume command strings are
POSIX-only (parse errors when typed into or dispatched to nu), and the
fish-parity socket reporting (tty/activity/pwd/ports) never happens.

Red on purpose (two-commit regression policy):
- tests/test_nushell_shim_path_refront.py drives the bundled nushell
  bootstrap (not yet present) through real nu and asserts the shim wins
  over user PATH prepends.
- tests/test_nushell_integration_hooks.py drives the bundled nushell
  integration (not yet present) and asserts fish-format socket payloads.
- tests/test_nushell_resume_command_dialect.py pins the nushell resume
  dialect semantics on real nu (green; the Swift builders adopt these
  golden shapes in the fix commit) and documents that the legacy POSIX
  resume string is a nushell parse error.

CI installs a pinned, checksum-verified nushell 0.113.1 in the
app-host-unit-tests focused-regression shard so the new tests actually
run there; locally they skip loudly when nu is absent but fail if CI is
set, so they can never silently skip on CI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ty integration

Nushell login shells previously got no cmux shell integration at all
(applyManagedShellSpecificStartupEnvironment fell through default:), so:
user env.nu PATH prepends shadowed the per-surface cmux-cli-shims claude
wrapper (sessions were never captured into
~/.cmuxterm/claude-hook-sessions.json and resume/notifications never
worked), every resume string was a nushell parse error, and the
tty/activity/pwd/ports socket reporting never ran.

Capture: `case "nu"` returns a fish-style replacement launch command
`'<shell>' -l -e '<payload>'` — nu's --execute runs the payload after the
user's env.nu/config.nu and enters the REPL. The payload is the new
bundled Resources/shell-integration/nushell/cmux-nushell-bootstrap.nu
squashed to one line (re-fronts cmux-cli-shims PATH entries after user
prepends, normalizing string PATHs) plus a `source` of the new
integration file with the bundle path baked in (nushell `source` needs a
parse-time constant). Missing bundle files degrade to a vanilla shell,
matching the zsh/fish guards.

Resume: cmux-generated resume/relaunch commands stay POSIX everywhere;
NushellTypedShellCommand (CMUXAgentLaunch) wraps them at the final typed
boundary as `^/bin/sh -c "<escaped>"` — the same portable-envelope
approach as manaflow-ai#5639's /bin/sh -c wrapper token and the /bin/zsh
launcher-script inputs. TerminalStartupTypedShellCommand applies it (from
$SHELL dialect) at the typed-keystroke chokepoints only: sessions-panel
resume, session drag-drop, clipboard copy, and agent
startup/fork/hibernation inline inputs. Inline inputs embedded into the
zsh launcher scripts stay raw POSIX — wrapping them made the launcher's
`nu) /bin/sh -c '<cmd>'` dispatch print
"/bin/sh: ^/bin/sh: No such file or directory" (caught in dogfood). The
restore launcher script and the restored terminal command script gain a
`nu)` dispatch branch that runs the POSIX command through /bin/sh, and
the launcher re-enters nushell with the cmux bootstrap payload rebuilt at
runtime from CMUX_SHELL_INTEGRATION_DIR so the resumed surface keeps the
shim re-front and integration.

Integration: Resources/shell-integration/nushell/cmux-nushell-integration.nu
brings nushell to fish parity — report_tty/report_shell_state/report_pwd/
ports_kick over the cmux socket (ncat/socat/nc chain, `job spawn`
background sends) from pre_execution/pre_prompt string hooks (def --env
state persists in _CMUX_* env vars), claude/grok wrapper defs, scrollback
restore, keyboard-protocol reset, and the remote-relay fallback.
zsh-only extras (git-branch probes, PR polling, Ghostty job-table
patching) are intentionally not replicated — fish does not have them
either.

Tests: the commit turns the red nushell regression suite green
(tests/test_nushell_shim_path_refront.py, test_nushell_integration_hooks.py;
test_nushell_resume_command_dialect.py pins the envelope semantics on real
nu). Swift coverage: nu rows in ShellStartupMatrixTests (payload squash,
quoting, dialect detection, typed-input wrap), the nu missing-bundle
fallback, a real-nu typed-resume dispatch regression mirroring the
fish/tcsh manaflow-ai#5639 tests, launcher-script regressions for the nu) dispatch
and the raw-inline/typed-boundary split (including an end-to-end run of
the generated launcher script under zsh with a fake nu login shell), and
NushellTypedShellCommandTests in CMUXAgentLaunch. /usr/local/bin/nu is
removed from the unsupported-shells matrix row.

Verified on nushell 0.113.1: -e runs post-config with persistent env and
hooks, `cd` persists from `if` blocks, quoted command heads are parse
errors (hence the /bin/sh envelope), and job spawn exists for background
sends. Dogfooded on a nushell login shell: capture, auto-resume,
panel resume, and session drag-drop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…round-send coverage

Codex: resumeStartupInput/forkStartupInput are also used for remote
workspace restores and remote forks, where the returned input is typed
into the remote host's shell after attach — deriving the dialect from
the local $SHELL leaked the nushell `^/bin/sh -c` envelope to remote
POSIX shells. Thread an explicit dialect through startupInput and pass
.posix at the four remote call sites in Workspace.

Greptile P2: the resume launcher script interpolated
CMUX_SHELL_INTEGRATION_DIR into the nushell source literal unescaped;
escape backslashes and double quotes first (verified against a path
containing a double quote).

Greptile P1 claimed `job spawn { _cmux_send … }` jobs cannot resolve the
sourced def — disproven against real nu (closures capture command decls
at parse time; all payloads deliver), but the sync-only test coverage it
pointed at was a real gap: tests/test_nushell_integration_hooks.py now
exercises the background job-spawn path without CMUX_TEST_SYNC_SEND.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ket probe cache

The no-ambient-global-state pre-merge rule forbids new caseless-enum
static namespaces: NushellTypedShellCommand and
TerminalStartupTypedShellCommand are now constructable structs
(NushellTypedShellCommand() matching the AgentLaunchEnvironmentPolicy
idiom in CMUXAgentLaunch; TerminalStartupTypedShellCommand owns its
dialect). The four remote call sites now go through a named
TerminalStartupShellDialect.remoteHost seam that documents the
remote-shells-are-POSIX assumption in one place until the SSH bootstrap
reports the actual remote shell back.

CodeRabbit's hot-path finding: _cmux_socket_is_unix forked /bin/test on
every prompt hook, before the activity-state dedupe. The probe now
caches its positive result for the session (negative results re-probe so
a socket that comes up late still gets found), and the dedupe check runs
before the probe.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Swift gets DocC comments on the members that lacked them
(TerminalStartupShellDialect.forShellPath, the
TerminalStartupTypedShellCommand members, the
startupInputWithLauncherScript overloads, and the dialect-carrying
resume/fork startup inputs). Every def in the nushell integration and
bootstrap now has a doc comment directly above it — nushell renders
those in `help <command>` — and the never-called _cmux_relay_params
helper found during this audit is deleted. The Python test helpers get
PEP 257 one-liners.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The stateless renderer is nonisolated by default today (the package sets
no default isolation), but the explicit marker keeps it callable from
nonisolated contexts if CMUXAgentLaunch ever adopts MainActor default
isolation, and Sendable matches the module's convention for value types
(AgentLaunchEnvironmentPolicy, ClaudeConfigDirectoryPath).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
forkProjectedTmuxAgentConversationToNewWorkspace types its startup input
into the remote host's shell after SSH attach; the default .loginShell
dialect would wrap the POSIX payload as ^/bin/sh for local nushell
logins, which the remote POSIX shell cannot parse — the same remote
leak the PR review already fixed at the other remote fork sites.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@austinywang
austinywang merged commit 4539296 into manaflow-ai:main Aug 20, 2026
6 checks passed
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.

Nushell login shells get no shell integration: Claude sessions are never captured, resume never works

2 participants