Skip to content

fix: handle long commands in tmux send_command via temp script fallback#719

Open
geoffjay wants to merge 2 commits intomainfrom
issue-714
Open

fix: handle long commands in tmux send_command via temp script fallback#719
geoffjay wants to merge 2 commits intomainfrom
issue-714

Conversation

@geoffjay
Copy link
Copy Markdown
Owner

fix: handle long commands in tmux send_command via temp script fallback

fix(wrap): handle long commands in tmux send_command via temp-script fallback (closes #714)

@geoffjay geoffjay added the review-agent Used to invoke a review by an agent tracking this label label Mar 23, 2026
@geoffjay
Copy link
Copy Markdown
Owner Author

This change is part of the following stack:

Change managed by git-spice.

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 23, 2026

Codecov Report

❌ Patch coverage is 46.66667% with 16 lines in your changes missing coverage. Please review.
✅ Project coverage is 55.65%. Comparing base (a5867f0) to head (698ff17).
⚠️ Report is 12 commits behind head on main.

Files with missing lines Patch % Lines
crates/wrap/src/tmux.rs 46.66% 16 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #719      +/-   ##
==========================================
- Coverage   55.66%   55.65%   -0.02%     
==========================================
  Files         126      126              
  Lines       13759    13789      +30     
==========================================
+ Hits         7659     7674      +15     
- Misses       6100     6115      +15     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@geoffjay
Copy link
Copy Markdown
Owner Author

⚠️ Conductor: Codecov threshold failures — reviewer discretion

All build, test, clippy, format, and security checks pass. The only failing checks are:

  • codecov/patch — new code in this PR has insufficient test coverage
  • codecov/project — total project coverage dropped below configured threshold

This PR implements a fix via a temp-script approach (writing long commands to a temp file before piping to tmux). The fix may be difficult to unit-test directly without a live tmux session.

Reviewer: please assess whether the coverage drop is acceptable given the nature of this fix (tmux integration behaviour), or request additional tests before approving. The conductor will not block merge on codecov-only failures if you approve.

Noted by conductor pipeline sync. Linked issue #714 is already closed.

Copy link
Copy Markdown
Owner Author

@geoffjay geoffjay left a comment

Choose a reason for hiding this comment

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

Review: fix(wrap): handle long commands in tmux send_command via temp-script fallback

Stack position: issue-714 is directly on main but git-spice reports
(needs restack) — the branch is behind main and must be rebased before
the conductor can merge it.

The fix is correct, well-reasoned, and matches the approach recommended in
the triage notes. Three non-blocking observations below.


Code quality: approved

TMUX_SEND_KEYS_MAX_LEN = 8 KB — the empirical range (works up to ~12 KB,
fails at ~18 KB) is documented in the comment. 8 KB is a conservative choice
with room for the conductor's ~6 KB prompt. ✅

Debug log truncation&command[..command.len().min(120)] prevents
multi-kilobyte log lines for long commands. ✅

send_command_via_script — correctly isolates the fallback path. Best-effort
remove_file on send-keys failure is appropriate (the script would otherwise
remain until the next trap EXIT). ✅

write_temp_scripttrap 'rm -f "$0"' EXIT is the standard self-deleting
script pattern. The #[cfg(unix)] chmod 0o755 block is a good cross-platform
guard for the permission step. ✅

Test coverage — 4 meaningful tests for write_temp_script: file creation,
shebang + trap content, command embedding, path uniqueness. These cover the
new code paths well. ✅


Non-blocking observations

1. Script path is not quoted in send_cmd

let send_cmd = format!("sh {script_str}");

If temp_dir() returns a path containing a space (e.g. a macOS user home
under a name with spaces), the send-keys invocation will split the path and
sh will error. Quoting the path is straightforward:

let send_cmd = format!("sh '{script_str}'");

Single-quoting is safe here because temp_dir() paths don't contain single
quotes on any supported platform. In practice /tmp and
/var/folders/.../T/ have no spaces, so this won't cause failures today —
but quoting is the correct defensive practice.

2. uuid is already a dependency — stronger uniqueness available

The temp filename uses nanosecond timestamp + PID:

let name = format!(
    "agentd-cmd-{}-{}.sh",
    SystemTime::now().duration_since(UNIX_EPOCH)…as_nanos(),
    std::process::id(),
);

uuid is already in wrap/Cargo.toml. Two rapid calls in the same process
could theoretically collide if the system clock resolution is coarser than
nanoseconds (some environments round to microseconds). uuid::Uuid::new_v4()
gives a 122-bit random filename with negligible collision probability and no
clock dependency:

let name = format!("agentd-cmd-{}.sh", uuid::Uuid::new_v4());

The current approach is fine in practice — this is a minor robustness note.

3. chmod 0o755 is unused

The script is invoked as sh {path}, not as ./{path}, so the executable
bit is never consulted by the kernel. The #[cfg(unix)] block can be removed
without any functional change. Leaving it in is harmless but adds a syscall
that does nothing.

4. Tests 6 and 7 test arithmetic, not behavior

test_short_command_does_not_need_script and test_long_command_needs_script
assert that "echo hello".len() <= 8192 and "x".repeat(8193).len() > 8192
— these are arithmetic identities, not behavioral coverage. They'd be better
rewritten to call send_command against a mock or at least verify that the
write_temp_script path is triggered. As unit tests that will never fail, they
don't add regression value. Non-blocking — the four write_temp_script tests
provide the meaningful coverage.


Action required before merge

Rebase onto main:

git-spice branch restack
git-spice branch submit

Once restacked, add merge-queue. The non-blocking observations above can
be addressed in the same commit or deferred to a follow-up.

@geoffjay geoffjay added needs-restack Branch is behind its stack parent, needs git-spice restack and removed review-agent Used to invoke a review by an agent tracking this label labels Mar 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-restack Branch is behind its stack parent, needs git-spice restack

Projects

None yet

Development

Successfully merging this pull request may close these issues.

wrap: tmux send-keys fails with long commands (system_prompt)

1 participant