Skip to content

feat: add native tmux tools - #26

Merged
trotsky1997 merged 5 commits into
mainfrom
agent/codex-wsl-gpt5-5/f4597232
Jun 1, 2026
Merged

feat: add native tmux tools#26
trotsky1997 merged 5 commits into
mainfrom
agent/codex-wsl-gpt5-5/f4597232

Conversation

@trotsky1997

@trotsky1997 trotsky1997 commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • add native tmux tools: tmux_run, tmux_send, tmux_capture, tmux_kill, tmux_listen, and tmux_wait
  • namespace sessions as ra__{session}, return structured JSON/errors, and document schemas
  • add shared tmux event expression semantics for tmux_listen and tmux_wait (event, pattern, regex, hook)
  • support tmux_wait events for output updates, output matches, program exit, program output, hook expressions, and bounded sleep with required timeout_ms
  • sync PRD/GitHub issue/OpenSpec wording for the six-tool scope
  • archive OpenSpec changes and add tmux integration tests, including a real tmux round trip when available

Closes #24.

Verification

  • cargo check
  • cargo test --test tmux_tools
  • cargo test
  • openspec validate add-tmux-wait-tool --strict
  • openspec validate --specs --strict

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

Sorry @trotsky1997, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@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: 50d0f6286a

ℹ️ 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".

Comment thread src/tools/tmux.rs
Comment on lines +315 to +318
if params.wait {
run_blocking(call_id, &tmux, &target, &params, ctx).await
} else {
run_nonblocking(call_id, &tmux, &target, &params, ctx).await

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Gate tmux_run through ACP permissions

When Ra is running with an ACP host attached (ctx.client/session_id set), this path still runs arbitrary tmux_run.command locally via tmux without calling request_permission; in contrast, the existing bash, git, and gh execution tools gate host-attached executions before running terminal commands. This lets a model execute shell commands through tmux_run in ACP sessions without the user approval expected for execute-class tools.

Useful? React with 👍 / 👎.

Comment thread src/tools/tmux.rs
Comment on lines +1162 to +1164
let valid = value.chars().all(|ch| {
ch.is_ascii_alphanumeric() || matches!(ch, '_' | '-' | '.') || (allow_percent && ch == '%')
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Reject dots in tmux window names

When a caller chooses a window name containing ., validation accepts it, but the target string is later rendered as session:window.pane; tmux's documented target-pane syntax uses . as the window/pane separator, so a window like logs.v1 becomes ambiguous and tmux_capture, tmux_send, or tmux_kill can fail or target the wrong pane after creating that window. Either disallow . for window names or target by window id instead.

Useful? React with 👍 / 👎.

Comment thread src/tools/tmux.rs
Comment on lines +1091 to +1092
Some(pane) => format!("{session}:{window}.{pane}"),
None => format!("{session}:{window}"),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use exact tmux targets for sessions and windows

When the requested logical session/window is absent but a longer name exists (for example dev while only ra__dev2 exists), these rendered targets can still match the longer target because the tmux target-session docs say lookup falls back to the start of a session name unless an = prefix forces exact matching; the same target rules apply to windows. That means tmux_capture/tmux_send/tmux_kill can operate on the wrong Ra-owned session or window instead of failing or creating the requested target.

Useful? React with 👍 / 👎.

@trotsky1997

Copy link
Copy Markdown
Owner Author

Reviewed PR #26 at head 66e9f26. I would block merge until the two correctness bugs below and the current merge conflict are fixed.

Findings:

  1. Medium - src/tools/tmux.rs:1724 allows . in window names, but TmuxTarget::new formats pane targets as session:window.pane at src/tools/tmux.rs:1489. A validated window such as logs.2 becomes ambiguous to tmux target parsing (logs window, pane 2) and commands like capture/send can silently target the wrong pane or fail. Either disallow . for window names or build targets with an unambiguous addressing strategy.

  2. Medium - src/tools/tmux.rs:1197 builds send-keys -t <target> -l <keys> without a -- separator before the payload. Literal text beginning with - is parsed by tmux as another send-keys option, so normal inputs like --help, -v, or pasted flag-like text fail. This also affects tmux_run when reusing an existing pane through send_args (src/tools/tmux.rs:934). Add -- before user-provided key payload and cover it with a regression test.

  3. Blocking mechanically - GitHub still reports mergeStateStatus: DIRTY for the PR. It needs a rebase/merge conflict resolution before it can merge.

Non-blocking but worth addressing:

  • tmux_run/tmux_send can execute arbitrary shell/input but do not use the ACP permission request path that git/gh use in src/tools/cli.rs. Either mirror the permission flow or document the intentional policy difference in spec/tools.md.
  • cargo clippy --all-targets -- -D warnings still fails on listen_response too-many-arguments (src/tools/tmux.rs:1333) and manual prefix stripping in text_delta (src/tools/tmux.rs:1787).
  • Add regression coverage for dotted window names and leading-dash literal tmux_send input.

Verification run from an extracted PR tree with tmux 3.4 / cargo 1.94.0:

  • CARGO_TARGET_DIR=/tmp/ra-pr26-review-4fbfc510/target cargo test --test tmux_tools -> 10 passed
  • CARGO_TARGET_DIR=/tmp/ra-pr26-review-4fbfc510/target cargo clippy --all-targets -- -D warnings -> fails with the two clippy diagnostics above

I attempted to submit this as a REQUEST_CHANGES review, but GitHub rejected it because the available GitHub identity is treated as the PR author, so this is posted as a PR comment instead.

@trotsky1997
trotsky1997 force-pushed the agent/codex-wsl-gpt5-5/f4597232 branch from 66e9f26 to 5c13f53 Compare June 1, 2026 23:09
local and others added 5 commits June 2, 2026 07:14
Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
- validate_name: disallow '.' in window names to prevent ambiguous
  tmux target parsing (session:window.pane). Sessions and panes still
  allow '.'; only windows are restricted.
- send_args: insert '--' before literal keys payload so leading '-'
  characters are not parsed as tmux flags.
- send_args: remove dead include_enter parameter (always false at all
  call sites; Enter is sent separately).
- listen_response: wrap 8 positional args into ListenResponse struct
  to satisfy clippy's too-many-arguments lint.
- text_delta: replace manual prefix-strip with strip_prefix().
- tests: update argv assertions to include '--' separator.

Co-authored-by: multica-agent <github@multica.ai>
strip_exit_marker now takes the call's unique token and only recognizes
markers of the form __RA_TMUX_EXIT:<token>:__<exit_code>__. A command
that prints the old static marker __RA_TMUX_EXIT:N__ can no longer
cause tmux_wait or tmux_run (wait:true) to return early with a false
command_exit_code.

wait_script updated to emit the token-scoped marker; both call sites
(run_blocking, execute_tmux_wait_program) pass the token. Tests updated
and a new regression test added for the wrong-token case.

Co-authored-by: multica-agent <github@multica.ai>
@trotsky1997
trotsky1997 force-pushed the agent/codex-wsl-gpt5-5/f4597232 branch from 5c13f53 to 584a5df Compare June 1, 2026 23:23
@trotsky1997
trotsky1997 merged commit 37c00a0 into main Jun 1, 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.

feat: native tmux tools

1 participant