Skip to content

fix(tmux): expand short format aliases in tmux compat - #3206

Closed
onthebed wants to merge 1 commit into
manaflow-ai:mainfrom
onthebed:clawoss/fix/tmux-short-format-aliases
Closed

onthebed wants to merge 1 commit into
manaflow-ai:mainfrom
onthebed:clawoss/fix/tmux-short-format-aliases

Conversation

@onthebed

@onthebed onthebed commented Apr 28, 2026 •

Copy link
Copy Markdown

tmuxRenderFormat only substituted #{...} placeholders, so short tmux aliases like #S, #I, and #W came back literally from cmux __tmux-compat display-message -p.

This teaches both tmux-compat renderers to expand the existing short aliases before the long-form pass, and adds regression coverage in the Go unit tests plus the tmux-compat matrix test.

Tested with go test ./... in daemon/remote/cmd/cmuxd-remote; the macOS app-side matrix test was updated but not runnable in this Linux workspace.

Fixes #3190


Summary by cubic

Expand short tmux format aliases (#S, #I, #W, #P, #D, #F) in tmux-compat so display-message -p returns real values instead of literal aliases. Fixes #3190.

  • Bug Fixes
    • Expand short aliases before long-form #{...} substitution in CLI/cmux.swift and daemon/remote/cmd/cmuxd-remote/tmux_compat.go.
    • Handle escaped ## correctly; map aliases to context keys; set window_flags default to * in the CLI context.
    • Add regression tests in Go and update the tmux-compat matrix test to cover short aliases.

Written for commit 06a560d. Summary will update on new commits. Review in cubic

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Enhanced tmux format string compatibility by adding support for proper expansion of short format aliases (#S, #I, #P, #W, #F, #D) within format strings, with correct handling of escaped characters.
  • Tests

    • Added comprehensive test coverage for tmux format string alias expansion across CLI and daemon components.

Support short tmux format aliases like #S, #I, #W, #P, #D, and #F
in the tmux-compat renderer so display-message returns the same values
as the long-form placeholders.
@vercel

vercel Bot commented Apr 28, 2026

Copy link
Copy Markdown

@onthebed 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 28, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

Adds preprocessing to tmux format string rendering in both CLI (Swift) and daemon (Go) components that expands short-form format aliases (#S, #I, #W, #F, #D, #P) into corresponding context values before existing placeholder replacement, while preserving ## as escaped literals.

Changes

Cohort / File(s) Summary
Swift CLI Implementation
CLI/cmux.swift
Introduces tmux format alias map and preprocessing logic that expands short format tokens (e.g., #W, #I, #F) into context values before #{key} placeholder replacement. Adds default window_flags value ("*") to rendering context.
Go Daemon Implementation
daemon/remote/cmd/cmuxd-remote/tmux_compat.go
Implements equivalent preprocessing step for short format variables (#{D}, #{F}, #{I}, #{P}, #{S}, #{W}), expanding aliases before full variable substitution with fallback for unrecognized tokens.
Test Coverage
daemon/remote/cmd/cmuxd-remote/tmux_compat_test.go, tests_v2/test_tmux_compat_matrix.py
Expands test cases with richer tmux context metadata (session/workspace/window/pane info) and validates short-form alias expansion (#S/#I/#P/#W, #F/#D) alongside escaped sequences (##S).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • PR #2238: Implements identical tmux-format preprocessing that expands short #<char> aliases and preserves ## escapes before full #{key} substitution—same logic applied to the same rendering functions.

Poem

🐰 Short codes now hop and dance,
#S and #I get their chance,
Where ## keeps its wall,
The aliases expand, one and all! ✨

🚥 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 clearly and concisely describes the main change: fixing/adding short format alias expansion in the tmux compatibility layer.
Description check ✅ Passed The description covers the root cause, the fix, testing approach, and references the linked issue, but the Testing section lacks detail on what was manually verified beyond running go tests.
Linked Issues check ✅ Passed The PR successfully addresses the primary objective of issue #3190 by implementing short alias expansion in both tmux-compat renderers before long-form substitution.
Out of Scope Changes check ✅ Passed All code changes are directly related to expanding short tmux format aliases as required by issue #3190; no unrelated modifications detected.

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

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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.11.4)

level=error msg="[linters_context] typechecking error: pattern ./...: directory prefix . does not contain main module or its selected dependencies"


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 28, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes cmux __tmux-compat display-message -p not expanding short tmux format aliases (#S, #I, #W, etc.) by adding a pre-pass tmuxExpandShortFormatAliases function to both the Go daemon renderer and the Swift CLI renderer before the existing #{long_form} substitution loop. The implementation and Go unit tests look correct, but the new Python integration test assertion has a mismatch:

  • #W is compared against ws (the workspace UUID) when it should be compared against title (the renamed workspace title tmux-title-{stamp}), causing the integration test to always fail.

Confidence Score: 3/5

Core fix is correct but the integration test has a definite assertion bug that will fail on macOS.

The Go and Swift implementations are solid and the Go unit tests verify the expected behavior. However, the Python integration test asserts #W against the workspace UUID (ws) instead of the workspace title (title), which is a P1 defect that guarantees a test failure when run on macOS.

tests_v2/test_tmux_compat_matrix.py — the #W assertion and hardcoded index values need attention.

Important Files Changed

Filename Overview
daemon/remote/cmd/cmuxd-remote/tmux_compat.go Adds tmuxExpandShortFormatAliases (byte-level scan) and wires it into tmuxRenderFormat; logic is correct and consistent with the Swift side.
daemon/remote/cmd/cmuxd-remote/tmux_compat_test.go Good unit test coverage for short aliases, double-hash escape, and known+unknown alias combinations.
CLI/cmux.swift Swift implementation mirrors Go logic; adds window_flags to the default context; Unicode-aware character iteration is correct for this ASCII-only domain.
tests_v2/test_tmux_compat_matrix.py New integration test asserts #W expands to the workspace UUID (ws) but window_name is set from the workspace title, not the UUID — causing a definite test failure; window_index and pane_index are also hardcoded to 0.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["tmuxRenderFormat(format, context, fallback)"] --> B["tmuxExpandShortFormatAliases"]
    B --> C{"scan each byte"}
    C -->|"ch != '#'"| D["write ch as-is"]
    C -->|"ch == '#' and i+1 >= len"| D
    D --> C
    C -->|"ch == '#', next == '#'"| E["write '##', skip next"]
    E --> C
    C -->|"ch == '#', next in aliases"| F{"context has key?"}
    F -->|yes| G["write context value, skip next"]
    F -->|no| H["write '#', advance to next char"]
    G --> C
    H --> C
    C -->|done| I["long-form pass: replace #{key} tokens"]
    I --> J["regex strip remaining #{...}"]
    J --> K["TrimSpace → return or fallback"]
Loading

Reviews (1): Last reviewed commit: "fix(tmux): expand short format aliases i..." | Re-trigger Greptile

Comment on lines +273 to +274
_must(short_aliases.stdout.strip() == f"cmux:0.0 {ws}",
f"display-message short aliases should expand: {short_aliases.stdout!r}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 #W asserted against workspace UUID instead of workspace title

ws is the UUID returned by c.new_workspace(), but #W expands to window_name, which is set from the workspace's title field (see tmuxFormatContext in tmux_compat.go, line ~259). By this point in the test the workspace has been renamed to title = f"tmux-title-{stamp}", so #W would expand to that renamed title — not the UUID — causing this assertion to always fail.

Suggested change
_must(short_aliases.stdout.strip() == f"cmux:0.0 {ws}",
f"display-message short aliases should expand: {short_aliases.stdout!r}")
short_aliases = _run_cli(cli, ["display-message", "-p", "#S:#I.#P #W"])
_must(short_aliases.stdout.strip() == f"cmux:0.0 {title}",
f"display-message short aliases should expand: {short_aliases.stdout!r}")

Comment on lines +200 to +206
if key, ok := tmuxShortFormatAliases[next]; ok {
if value, exists := context[key]; exists {
builder.WriteString(value)
i++
continue
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Known alias but missing context key silently passes through

When a recognized alias (e.g. #I) appears in the format string but its context key (window_index) is absent from the map, the # is emitted and the loop advances to the alias letter, which is then emitted on the next iteration — reproducing the original #I literally. This passthrough is reasonable, but it diverges slightly from real tmux which would render an empty string. A brief comment clarifying the intended behavior would help future readers distinguish a deliberate design choice from a bug.

Comment on lines +272 to +274
short_aliases = _run_cli(cli, ["display-message", "-p", "#S:#I.#P #W"])
_must(short_aliases.stdout.strip() == f"cmux:0.0 {ws}",
f"display-message short aliases should expand: {short_aliases.stdout!r}")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 Hardcoded window_index=0 and pane_index=0 are fragile

The assertion "cmux:0.0 {title}" assumes #I (window_index) is 0 and #P (pane_index) is also 0. Window index depends on the order workspaces are listed by the daemon, which can be affected by pre-existing workspaces. Pane index after break-pane / join-pane / swap-pane operations may also not be 0. Consider reading back the actual index values from display-message #{window_index} and #{pane_index} and interpolating them into the expected string, or at least asserting that #S and #W expand correctly in isolation.

@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 `@tests_v2/test_tmux_compat_matrix.py`:
- Around line 272-274: The assertion hard-codes dynamic tmux context values;
update the check around short_aliases (result of _run_cli) so it doesn't require
fixed indices. Instead parse or regex-match short_aliases.stdout.strip(): verify
the part after the space equals the expected window name variable ws, and verify
the prefix matches the pattern "cmux:<number>.<number>" (e.g., with a regex like
r"^cmux:\d+\.\d+$" applied to the first token). Use the existing _must helper to
assert both conditions against short_aliases.stdout.strip() so the test no
longer depends on exact runtime `#I/`#P values.
🪄 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: c276b19e-f7f2-42f7-bcc8-c661f6e33391

📥 Commits

Reviewing files that changed from the base of the PR and between cc393c9 and 06a560d.

📒 Files selected for processing (4)
  • CLI/cmux.swift
  • daemon/remote/cmd/cmuxd-remote/tmux_compat.go
  • daemon/remote/cmd/cmuxd-remote/tmux_compat_test.go
  • tests_v2/test_tmux_compat_matrix.py

Comment on lines +272 to +274
short_aliases = _run_cli(cli, ["display-message", "-p", "#S:#I.#P #W"])
_must(short_aliases.stdout.strip() == f"cmux:0.0 {ws}",
f"display-message short aliases should expand: {short_aliases.stdout!r}")

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

Avoid hard-coding dynamic tmux context values in this regression assertion.

At Line 184 the test renames the window, and #I/#P/#W depend on current runtime context. Asserting cmux:0.0 {ws} makes this check brittle and can fail despite correct short-alias expansion.

Suggested fix
-        short_aliases = _run_cli(cli, ["display-message", "-p", "#S:`#I`.#P `#W`"])
-        _must(short_aliases.stdout.strip() == f"cmux:0.0 {ws}",
-              f"display-message short aliases should expand: {short_aliases.stdout!r}")
+        long_form = _run_cli(
+            cli,
+            ["display-message", "-p", "#{session_name}:#{window_index}.#{pane_index} #{window_name}"],
+        )
+        short_aliases = _run_cli(cli, ["display-message", "-p", "#S:`#I`.#P `#W`"])
+        _must(
+            short_aliases.stdout.strip() == long_form.stdout.strip(),
+            f"display-message short aliases should match long-form render: short={short_aliases.stdout!r} long={long_form.stdout!r}",
+        )
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests_v2/test_tmux_compat_matrix.py` around lines 272 - 274, The assertion
hard-codes dynamic tmux context values; update the check around short_aliases
(result of _run_cli) so it doesn't require fixed indices. Instead parse or
regex-match short_aliases.stdout.strip(): verify the part after the space equals
the expected window name variable ws, and verify the prefix matches the pattern
"cmux:<number>.<number>" (e.g., with a regex like r"^cmux:\d+\.\d+$" applied to
the first token). Use the existing _must helper to assert both conditions
against short_aliases.stdout.strip() so the test no longer depends on exact
runtime `#I/`#P values.

Copy link
Copy Markdown
Collaborator

Superseded by #13608, which ports the short-format fix onto current main with correct ## escaping and local/remote coverage. Closing this stale branch.

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.

__tmux-compat: short tmux format codes (#S, #I, #W, ...) are not substituted, breaking cmux omc

2 participants