ace-tmux 0.14.3 → 0.17.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +58 -0
- data/README.md +11 -3
- data/docs/demo/ace-tmux-getting-started.tape.yml +5 -1
- data/docs/getting-started.md +7 -3
- data/docs/usage.md +168 -10
- data/lib/ace/tmux/atoms/named_key_registry.rb +34 -0
- data/lib/ace/tmux/atoms/tmux_command_builder.rb +28 -1
- data/lib/ace/tmux/atoms/window_name_sanitizer.rb +25 -0
- data/lib/ace/tmux/cli/commands/attach.rb +26 -0
- data/lib/ace/tmux/cli/commands/capture.rb +41 -0
- data/lib/ace/tmux/cli/commands/detach.rb +28 -0
- data/lib/ace/tmux/cli/commands/list.rb +113 -48
- data/lib/ace/tmux/cli/commands/list_presets.rb +67 -0
- data/lib/ace/tmux/cli/commands/send.rb +169 -0
- data/lib/ace/tmux/cli/commands/wait.rb +57 -0
- data/lib/ace/tmux/cli/commands/window.rb +2 -3
- data/lib/ace/tmux/cli.rb +27 -2
- data/lib/ace/tmux/models/runtime_target.rb +46 -0
- data/lib/ace/tmux/molecules/local_process_inspector.rb +84 -0
- data/lib/ace/tmux/molecules/runtime_target_resolver.rb +267 -0
- data/lib/ace/tmux/molecules/tmux_executor.rb +8 -0
- data/lib/ace/tmux/molecules/wait_condition_validator.rb +25 -0
- data/lib/ace/tmux/organisms/control_surface.rb +523 -0
- data/lib/ace/tmux/organisms/session_manager.rb +17 -3
- data/lib/ace/tmux/organisms/window_manager.rb +8 -3
- data/lib/ace/tmux/version.rb +1 -1
- data/lib/ace/tmux.rb +11 -0
- metadata +15 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c4edb05780dda3c73b507989856230c358bc6b94be33bc27e34a71f0bd1a7d79
|
|
4
|
+
data.tar.gz: 679f06b6a332dbb3237c7383a6d61c665fd0bf65934a668ddc13fa1d46d86cfc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 68d7a486f473d1095be471419db504421d53fa797ebaf7588c0273da6edb0c48bc24c050040662ab30941e253196343807f8db61997487d7ebbb555daa6474d5
|
|
7
|
+
data.tar.gz: da33e7b0921b5a0033827bee7aa1a9c40c3422d82591435f61e336bc61bb82d035029236c28b20e3bafa3ff2cf1a147d79758bcd71496c429a1f32945ca5a77f
|
data/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,64 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.17.2] - 2026-04-24
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- Clarified usage docs to treat speculative shared read-side follow-up as closed for now, so any future tmux inspectability expansion must start as a new task rather than reopening the archived `8r6.t.xeu` task family.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- Clarified usage docs to treat `ace-tmux list` as the shipped read-side runtime inventory baseline and removed stale `ace-tmux state` references from capture and boundary notes.
|
|
17
|
+
|
|
18
|
+
## [0.17.1] - 2026-04-24
|
|
19
|
+
|
|
20
|
+
## [0.17.0] - 2026-04-16
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
- Added a shared tmux runtime control surface with public `ace-tmux send`, `capture`, `wait`, `attach`, and `detach` commands.
|
|
24
|
+
- Added `send --wait` plus a new `agent` wait condition so interactive CLI panes, including shell-wrapped Codex/Claude/pi launches, can accept a prompt, block until the visible response settles, and then capture the final same-pane screen tail in one command.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
- Added runtime target resolution, bounded named-key validation, and the v1 tmux wait-condition set for ACE-managed live control flows.
|
|
28
|
+
- Reworked `ace-tmux send` around `--cmd`, repeatable `--msg` / `--key`, and inline `--capture` output so one call can submit pane input and immediately tail feedback.
|
|
29
|
+
- Split preset discovery from runtime inspection: `ace-tmux --list-presets [TYPE]` now lists preset names, while `ace-tmux list` inspects live tmux panes in the current window by default and supports `--all-panes`, `--windows`, and `--sessions`.
|
|
30
|
+
- Tightened `ace-tmux send --wait output` so it matches post-send output instead of succeeding on stale visible text, and added `ace-tmux wait --lines` to control the observed pane tail.
|
|
31
|
+
- Expanded README, CLI help, docs, demo tape, and retained E2E coverage to document the control-side contract and the `--list-presets` plus runtime `list` split.
|
|
32
|
+
|
|
33
|
+
### Fixed
|
|
34
|
+
- Qualified the default shared-control executor path so public `ace-tmux` control commands construct correctly without injected dependencies.
|
|
35
|
+
- Restored detached explicit-session active-window fallback so `ACE_TMUX_SESSION` launches can still resolve the current window outside a live tmux client.
|
|
36
|
+
- Validate `ace-tmux` pane targets before dispatch so invalid `session:window:pane` input now returns a corrective error that points users to `%pane_id`, `session:window.pane`, `.pane`, or `--window ... --pane ...`.
|
|
37
|
+
- Bound `capture-pane` with `-E -1` so `ace-tmux capture --lines N` and `ace-tmux send --capture N` return the last `N` visible pane rows instead of an oversized scrollback slice.
|
|
38
|
+
- Resolve pane shorthands through stable tmux window ids so `.pane`, bare pane indexes, and dotted window names like `ace-t.n1d` target the intended pane instead of producing invalid pane targets.
|
|
39
|
+
- Pace the first submit `Enter` for interactive CLI panes such as `codex`, `claude`, and `pi`, and capture their visible bottom screen rows so sends submit reliably and `--capture` reflects the current TUI screen instead of stale scrollback.
|
|
40
|
+
- `ace-tmux wait --for pane-exited` now succeeds when the pane disappears entirely instead of timing out on missing-pane targets.
|
|
41
|
+
- `ace-tmux detach` now reports the resolved target session name, even when the session came from ACE env vars or live tmux context.
|
|
42
|
+
|
|
43
|
+
### Technical
|
|
44
|
+
- Added optional `split-window -P -F` command building so shared tmux consumers can capture the created pane id without private command arrays.
|
|
45
|
+
|
|
46
|
+
## [0.14.6] - 2026-04-23
|
|
47
|
+
|
|
48
|
+
### Technical
|
|
49
|
+
- Removed the stale cross-TC `session-name` fallback from retained existing-session verification so the goal now relies only on in-scope session continuity evidence.
|
|
50
|
+
|
|
51
|
+
## [0.14.5] - 2026-04-23
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
### Fixed
|
|
55
|
+
- Improved tmux session targeting so session-aware commands respect existing `TMUX` context instead of forcing socket-level targeting when already attached.
|
|
56
|
+
- Added regression coverage for active-session command paths that previously depended on socket-legacy behavior.
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
- Fixed session targeting so commands now respect an active `TMUX` session and avoid forcing legacy `tmux -S` socket targeting when already inside tmux.
|
|
61
|
+
|
|
62
|
+
## [0.14.4] - 2026-04-22
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
- Sanitized ACE-managed tmux window names so path-derived names such as `ace-t.k5a` become tmux-safe targets like `ace-t-k5a`.
|
|
66
|
+
- Tracked startup windows by tmux window ID after creation so session startup selection no longer depends on raw or punctuation-bearing window names.
|
|
67
|
+
|
|
10
68
|
## [0.14.3] - 2026-04-16
|
|
11
69
|
|
|
12
70
|
### Technical
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<h1> ACE - TMUX </h1>
|
|
3
3
|
|
|
4
|
-
Composable tmux sessions from YAML presets, with window injection
|
|
4
|
+
Composable tmux sessions from YAML presets, with window injection and shared control operations for active sessions.
|
|
5
5
|
|
|
6
6
|
<img src="../docs/brand/AgenticCodingEnvironment.Logo.XS.jpg" alt="ACE Logo" width="480">
|
|
7
7
|
<br><br>
|
|
@@ -16,13 +16,15 @@
|
|
|
16
16
|
|
|
17
17
|
[Getting Started](docs/getting-started.md) | [Usage Guide](docs/usage.md) | [Handbook - Skills, Agents, Templates](docs/handbook.md)
|
|
18
18
|
|
|
19
|
-
`ace-tmux` helps you standardize terminal workspaces with preset-driven sessions, reusable windows, and
|
|
19
|
+
`ace-tmux` helps you standardize terminal workspaces with preset-driven sessions, reusable windows, nested pane layouts, runtime inspection, and a shared live-control surface for pane/session interaction. You can discover preset names with `--list-presets`, spin up a full workspace from a session preset, inspect the live tmux state with `list`, inject a focused window into an already-running tmux session, or use `send`/`capture`/`wait`/`attach`/`detach` as the public ACE tmux control contract.
|
|
20
20
|
|
|
21
21
|
## How It Works
|
|
22
22
|
|
|
23
23
|
1. Define session and window layouts in YAML presets stored in `.ace/tmux/` (project), `~/.ace/tmux/` (user), or gem defaults.
|
|
24
24
|
2. Run `ace-tmux start [PRESET]` to create a full session or `ace-tmux window [PRESET]` to inject a window into the current session. Use `ace-tmux start ... --name <session>` when you need multiple concurrent sessions from the same preset.
|
|
25
|
-
3.
|
|
25
|
+
3. Use `ace-tmux list` to inspect panes in the current window, or widen the scope with `--all-panes`, `--windows`, or `--sessions`.
|
|
26
|
+
4. Use `ace-tmux send`, `capture`, `wait`, `attach`, and `detach` for shared live tmux interaction without dropping to raw `tmux`.
|
|
27
|
+
5. Presets are deep-merged through the config cascade, so project-level overrides layer cleanly on top of shared defaults.
|
|
26
28
|
|
|
27
29
|
## Use Cases
|
|
28
30
|
|
|
@@ -30,10 +32,16 @@
|
|
|
30
32
|
|
|
31
33
|
**Inject windows into running sessions** - run `ace-tmux window [PRESET]` to add a new window from presets without recreating the current session, useful for spinning up focused tool or test panes on the fly.
|
|
32
34
|
|
|
35
|
+
**Inspect tmux state without raw tmux** - run `ace-tmux list` to inspect the current window’s panes, `ace-tmux list --windows` for the current session’s windows, or `ace-tmux list --sessions` for the tmux server view.
|
|
36
|
+
|
|
37
|
+
**Control tmux through a shared ACE contract** - run `ace-tmux send`, `capture`, `wait`, `attach`, and `detach` when higher-level ACE tools or operators need live pane/session control without re-implementing tmux wrappers.
|
|
38
|
+
|
|
33
39
|
**Compose nested pane layouts in YAML** - use `direction` and nested pane containers to model custom split trees beyond tmux built-in layouts, keeping workspace structure version-controlled alongside your project.
|
|
34
40
|
|
|
35
41
|
**Reuse presets through config cascade** - load project presets from `.ace/tmux/`, personal presets from `~/.ace/tmux/`, and gem defaults via `.ace-defaults/tmux/` with deep-merge behavior so teams share a baseline while individuals customize.
|
|
36
42
|
|
|
43
|
+
**Discover preset names cleanly** - run `ace-tmux --list-presets` with an optional `sessions`, `windows`, or `panes` filter when you need to inspect available presets without overloading the live-runtime `list` command.
|
|
44
|
+
|
|
37
45
|
**Orchestrate task-focused workspaces** - pair with [ace-overseer](../ace-overseer) and [ace-assign](../ace-assign) for assignment-driven worktree and tmux orchestration that spins up isolated workspaces per task.
|
|
38
46
|
|
|
39
47
|
## Testing
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Showcase ace-tmux preset discovery, session start, and window management
|
|
2
|
+
description: Showcase ace-tmux preset discovery, runtime listing, session start, and window management
|
|
3
3
|
tags:
|
|
4
4
|
- ace-tmux
|
|
5
5
|
- docs
|
|
@@ -11,6 +11,10 @@ settings:
|
|
|
11
11
|
format: gif
|
|
12
12
|
scenes:
|
|
13
13
|
- name: Discover available presets (sessions, windows, panes)
|
|
14
|
+
commands:
|
|
15
|
+
- type: ace-tmux --list-presets
|
|
16
|
+
sleep: 4s
|
|
17
|
+
- name: Inspect panes in the current tmux window
|
|
14
18
|
commands:
|
|
15
19
|
- type: ace-tmux list
|
|
16
20
|
sleep: 4s
|
data/docs/getting-started.md
CHANGED
|
@@ -3,8 +3,8 @@ doc-type: user
|
|
|
3
3
|
title: ace-tmux Getting Started
|
|
4
4
|
purpose: Tutorial for creating sessions and adding windows with ace-tmux.
|
|
5
5
|
ace-docs:
|
|
6
|
-
last-updated: 2026-
|
|
7
|
-
last-checked: 2026-
|
|
6
|
+
last-updated: 2026-04-16
|
|
7
|
+
last-checked: 2026-04-16
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Getting Started with ace-tmux
|
|
@@ -22,6 +22,8 @@ Verify command availability: `ace-tmux --help`.
|
|
|
22
22
|
|
|
23
23
|
## Start Your First Session
|
|
24
24
|
|
|
25
|
+
See available presets first with `ace-tmux --list-presets sessions`.
|
|
26
|
+
|
|
25
27
|
Run: `ace-tmux start`.
|
|
26
28
|
|
|
27
29
|
`ace-tmux` resolves the default session preset from `defaults.session` in config.
|
|
@@ -78,9 +80,11 @@ Use it in a session or add it directly with `ace-tmux window cc`.
|
|
|
78
80
|
|
|
79
81
|
| Command | Purpose |
|
|
80
82
|
| --- | --- |
|
|
83
|
+
| `ace-tmux --list-presets [TYPE]` | Show available preset names |
|
|
81
84
|
| `ace-tmux start [PRESET]` | Start or attach to a session preset |
|
|
82
85
|
| `ace-tmux window [PRESET]` | Add a window preset to a running session |
|
|
83
|
-
| `ace-tmux list` | Show
|
|
86
|
+
| `ace-tmux list` | Show live panes in the current window |
|
|
87
|
+
| `ace-tmux list --windows` | Show windows in the current session |
|
|
84
88
|
|
|
85
89
|
## Next steps
|
|
86
90
|
|
data/docs/usage.md
CHANGED
|
@@ -3,8 +3,8 @@ doc-type: user
|
|
|
3
3
|
title: ace-tmux Usage
|
|
4
4
|
purpose: Full CLI and configuration reference for ace-tmux.
|
|
5
5
|
ace-docs:
|
|
6
|
-
last-updated: 2026-
|
|
7
|
-
last-checked: 2026-
|
|
6
|
+
last-updated: 2026-04-24
|
|
7
|
+
last-checked: 2026-04-24
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
# Usage
|
|
@@ -13,7 +13,13 @@ ace-docs:
|
|
|
13
13
|
|
|
14
14
|
- `ace-tmux start [PRESET] [OPTIONS]`
|
|
15
15
|
- `ace-tmux window [PRESET] [OPTIONS]`
|
|
16
|
-
- `ace-tmux list [
|
|
16
|
+
- `ace-tmux list [OPTIONS]`
|
|
17
|
+
- `ace-tmux --list-presets [TYPE]`
|
|
18
|
+
- `ace-tmux send [OPTIONS]`
|
|
19
|
+
- `ace-tmux capture [OPTIONS]`
|
|
20
|
+
- `ace-tmux wait [OPTIONS]`
|
|
21
|
+
- `ace-tmux attach [OPTIONS]`
|
|
22
|
+
- `ace-tmux detach [OPTIONS]`
|
|
17
23
|
|
|
18
24
|
`PRESET` is optional for `start` and `window` when defaults are configured.
|
|
19
25
|
|
|
@@ -70,26 +76,173 @@ Behavior notes:
|
|
|
70
76
|
- Inside tmux, current session is auto-detected.
|
|
71
77
|
- Outside tmux, provide `--session` (or set `ACE_TMUX_SESSION`).
|
|
72
78
|
- If no preset is provided, `defaults.window` is used.
|
|
79
|
+
- ACE-managed window names are normalized to `A-Z`, `a-z`, `0-9`, `_`, and `-`; other punctuation is replaced with `-`.
|
|
73
80
|
|
|
74
81
|
## `ace-tmux list`
|
|
75
82
|
|
|
76
|
-
List
|
|
83
|
+
List live tmux sessions, windows, or panes.
|
|
77
84
|
|
|
78
85
|
Examples:
|
|
79
86
|
|
|
80
87
|
- `ace-tmux list`
|
|
81
|
-
- `ace-tmux list
|
|
82
|
-
- `ace-tmux list windows`
|
|
83
|
-
- `ace-tmux list
|
|
88
|
+
- `ace-tmux list --all-panes`
|
|
89
|
+
- `ace-tmux list --windows`
|
|
90
|
+
- `ace-tmux list --sessions`
|
|
91
|
+
- `ace-tmux list --session dev --window work`
|
|
92
|
+
|
|
93
|
+
Options:
|
|
94
|
+
|
|
95
|
+
- `--session`, `-s`: target session name
|
|
96
|
+
- `--window`, `-w`: target window name, index, or tmux window id (`@2`)
|
|
97
|
+
- `--all-panes`: list panes across the resolved session
|
|
98
|
+
- `--windows`: list windows in the resolved session
|
|
99
|
+
- `--sessions`: list all tmux sessions
|
|
100
|
+
|
|
101
|
+
Behavior notes:
|
|
102
|
+
|
|
103
|
+
- With no scope flags, `list` shows panes in the resolved current window.
|
|
104
|
+
- `--all-panes` expands from the current window to every window in the resolved session.
|
|
105
|
+
- `--windows` lists windows in the resolved session.
|
|
106
|
+
- `--sessions` lists tmux sessions and does not accept `--session` or `--window`.
|
|
107
|
+
- Runtime target resolution follows the same precedence as the control surface: explicit flags, then ACE tmux env vars, then live tmux context.
|
|
108
|
+
|
|
109
|
+
## `ace-tmux --list-presets`
|
|
110
|
+
|
|
111
|
+
List available tmux preset names.
|
|
112
|
+
|
|
113
|
+
Examples:
|
|
114
|
+
|
|
115
|
+
- `ace-tmux --list-presets`
|
|
116
|
+
- `ace-tmux --list-presets sessions`
|
|
117
|
+
- `ace-tmux --list-presets windows`
|
|
84
118
|
|
|
85
119
|
Arguments:
|
|
86
120
|
|
|
87
|
-
- `TYPE`:
|
|
121
|
+
- `TYPE`: optional `sessions`, `windows`, or `panes`
|
|
122
|
+
|
|
123
|
+
## `ace-tmux send`
|
|
124
|
+
|
|
125
|
+
Send a submitted command, literal text, or bounded named keys to a target pane.
|
|
126
|
+
|
|
127
|
+
Examples:
|
|
128
|
+
|
|
129
|
+
- `ace-tmux send --pane %1 --cmd "bundle exec rake test"`
|
|
130
|
+
- `ace-tmux send --session dev --window work --pane 0 --cmd "ace-task status" --capture`
|
|
131
|
+
- `ace-tmux send --pane %8 --cmd "ping" --wait --capture 20`
|
|
132
|
+
- `ace-tmux send --pane %8 --cmd "Task context?" --wait agent --timeout 30 --capture`
|
|
133
|
+
- `ace-tmux send --pane .1 --msg "echo ready" --key Enter`
|
|
134
|
+
- `ace-tmux send --pane %1 --msg "echo ready" --key Enter`
|
|
135
|
+
- `ace-tmux send --pane %1 --key C-c`
|
|
136
|
+
|
|
137
|
+
Options:
|
|
138
|
+
|
|
139
|
+
- `--session`, `-s`: target session name
|
|
140
|
+
- `--window`, `-w`: target window name, index, or tmux window id (`@2`)
|
|
141
|
+
- `--pane`, `-p`: target pane id (`%8`), full pane target (`dev:work.1`), or current-window pane shorthand (`.1`)
|
|
142
|
+
- `--cmd`, `-c`: command text to send and submit with `Enter`
|
|
143
|
+
- `--msg`, `-m`: literal text chunk to send without `Enter`
|
|
144
|
+
- `--key`, `-k`: named key to send
|
|
145
|
+
- `--capture [lines[:wait]]`: capture recent pane output after sending; defaults to `40:2`
|
|
146
|
+
- `--wait [condition]`: wait after send; bare `--wait` defaults to `agent`
|
|
147
|
+
- `--pattern`: pattern to match when waiting for `output`
|
|
148
|
+
- `--timeout`, `-t`: wait timeout in seconds when `--wait` is used
|
|
149
|
+
- `--interval`, `-i`: wait polling interval in seconds when `--wait` is used
|
|
150
|
+
- `--quiet`, `-q`: suppress non-essential output
|
|
151
|
+
|
|
152
|
+
Behavior notes:
|
|
153
|
+
|
|
154
|
+
- Provide at least one of `--cmd`, `--msg`, or `--key`.
|
|
155
|
+
- Use either `--cmd` or `--msg`, not both.
|
|
156
|
+
- Repeated `--msg` values are sent in order, then any implicit `Enter` from `--cmd`, then repeated `--key` values in order.
|
|
157
|
+
- `--cmd` always appends one final `Enter`.
|
|
158
|
+
- Embedded newlines in `--cmd` or `--msg` remain literal text; they are not expanded into extra key presses.
|
|
159
|
+
- Named keys are intentionally bounded; unsupported raw tmux key syntax is rejected.
|
|
160
|
+
- Interactive CLI panes such as `codex`, `claude`, and `pi` get a brief automatic pause before the first submit `Enter` after text so the TUI sees a submit key instead of a paste burst.
|
|
161
|
+
- `--wait agent` blocks until a supported interactive CLI pane visibly changes and then settles; bare `--wait` is shorthand for that main send-and-wait flow.
|
|
162
|
+
- `send --wait output` compares against the pre-send pane tail, so existing visible matches do not satisfy the wait unless the pattern appears again after the send.
|
|
163
|
+
- Interactive CLI detection also covers panes launched through shell wrappers, so detached `fish -c codex` / similar panes still use the interactive send, wait, and capture path.
|
|
164
|
+
- When `--wait` and `--capture` are used together, ACE waits first and then captures from the same pane, so the printed tail reflects the settled post-response screen.
|
|
165
|
+
- Target resolution uses one precedence rule across the control surface: explicit flags, then ACE tmux env vars, then live tmux context.
|
|
166
|
+
- `--capture N` prints the visible bottom `N` rows for interactive CLI panes and a recent history tail for generic shell panes.
|
|
167
|
+
- Supported pane forms are `%8`, `dev:work.1`, `.1`, and bare `1`. `dev:work:1` is invalid; use `dev:work.1` instead.
|
|
168
|
+
- `.1` and bare `1` both resolve against the explicit or resolved current window.
|
|
169
|
+
- Window names may contain dots. ACE resolves pane shorthands through tmux window ids internally, so `--window ace-t.n1d --pane .3` remains valid.
|
|
170
|
+
|
|
171
|
+
## `ace-tmux capture`
|
|
172
|
+
|
|
173
|
+
Capture recent output from a tmux pane.
|
|
174
|
+
|
|
175
|
+
Examples:
|
|
176
|
+
|
|
177
|
+
- `ace-tmux capture --pane %1`
|
|
178
|
+
- `ace-tmux capture --pane %1 --lines 80`
|
|
179
|
+
|
|
180
|
+
Options:
|
|
181
|
+
|
|
182
|
+
- `--session`, `-s`: target session name
|
|
183
|
+
- `--window`, `-w`: target window name, index, or tmux window id (`@2`)
|
|
184
|
+
- `--pane`, `-p`: target pane id (`%8`), full pane target (`dev:work.1`), or current-window pane shorthand (`.1`)
|
|
185
|
+
- `--lines`, `-n`: number of recent lines to capture
|
|
186
|
+
|
|
187
|
+
Behavior notes:
|
|
188
|
+
|
|
189
|
+
- Capture is a live control-side pane-tail operation, not a generic read-side runtime inventory surface.
|
|
190
|
+
- `--lines N` captures the visible bottom `N` rows for interactive CLI panes such as `codex`, `claude`, and `pi`.
|
|
191
|
+
- Generic shell panes keep using a recent history tail instead of the current visible screen.
|
|
192
|
+
- Interactive CLI captures may include visible draft/composer text when it is on screen.
|
|
193
|
+
- Pane targeting follows the same rules as `send`: `%8`, `dev:work.1`, `.1`, or bare `1`.
|
|
194
|
+
|
|
195
|
+
## `ace-tmux wait`
|
|
196
|
+
|
|
197
|
+
Wait for a bounded tmux condition.
|
|
198
|
+
|
|
199
|
+
Examples:
|
|
200
|
+
|
|
201
|
+
- `ace-tmux wait --pane %1 --for output --pattern "Task context:"`
|
|
202
|
+
- `ace-tmux wait --pane %8 --for agent`
|
|
203
|
+
- `ace-tmux wait --session dev --for window-active --window work-fs`
|
|
204
|
+
- `ace-tmux wait --pane %1 --for pane-exited`
|
|
88
205
|
|
|
89
206
|
Options:
|
|
90
207
|
|
|
91
|
-
- `--
|
|
92
|
-
- `--
|
|
208
|
+
- `--for`, `-f`: one of `agent`, `output`, `window-exists`, `window-active`, `pane-exists`, `pane-exited`
|
|
209
|
+
- `--session`, `-s`: target session name
|
|
210
|
+
- `--window`, `-w`: target window name, index, or tmux window id (`@2`)
|
|
211
|
+
- `--pane`, `-p`: target pane id (`%8`), full pane target (`dev:work.1`), or current-window pane shorthand (`.1`)
|
|
212
|
+
- `--pattern`: output substring to match
|
|
213
|
+
- `--lines`, `-n`: number of lines to observe for `output` and `agent` waits
|
|
214
|
+
- `--timeout`, `-t`: timeout in seconds
|
|
215
|
+
- `--interval`, `-i`: polling interval in seconds
|
|
216
|
+
- `--quiet`, `-q`: suppress non-essential output
|
|
217
|
+
|
|
218
|
+
Behavior notes:
|
|
219
|
+
|
|
220
|
+
- `--for agent` waits for a supported interactive CLI pane such as `codex`, `claude`, or `pi` to become visibly idle/stable, including panes launched through wrapper shells.
|
|
221
|
+
- `--pattern` is required for `--for output`.
|
|
222
|
+
- `--for output` observes the last `--lines` lines of the target pane.
|
|
223
|
+
- `--for pane-exited` succeeds when the pane reports `pane_dead=1` or disappears entirely.
|
|
224
|
+
- Wait timeouts fail clearly; they do not silently fall through.
|
|
225
|
+
- Pane targeting follows the same rules as `send`: `%8`, `dev:work.1`, `.1`, or bare `1`.
|
|
226
|
+
|
|
227
|
+
## `ace-tmux attach`
|
|
228
|
+
|
|
229
|
+
Attach to a tmux session using the same shared target-resolution rules.
|
|
230
|
+
|
|
231
|
+
Examples:
|
|
232
|
+
|
|
233
|
+
- `ace-tmux attach --session dev`
|
|
234
|
+
|
|
235
|
+
## `ace-tmux detach`
|
|
236
|
+
|
|
237
|
+
Detach clients from a tmux session.
|
|
238
|
+
|
|
239
|
+
Examples:
|
|
240
|
+
|
|
241
|
+
- `ace-tmux detach --session dev`
|
|
242
|
+
|
|
243
|
+
Behavior notes:
|
|
244
|
+
|
|
245
|
+
- `detach` removes attached clients from the target session and is intended to replace raw `tmux detach-client -s ...` usage in ACE-owned flows.
|
|
93
246
|
|
|
94
247
|
## Config Cascade
|
|
95
248
|
|
|
@@ -200,6 +353,11 @@ Chained preset references are supported (depth-limited).
|
|
|
200
353
|
- [Getting Started](getting-started.md)
|
|
201
354
|
- [Handbook Reference](handbook.md)
|
|
202
355
|
|
|
356
|
+
## Boundary Notes
|
|
357
|
+
|
|
358
|
+
- `ace-tmux` control commands (`send`, `capture`, `wait`, `attach`, `detach`) define the live interaction surface.
|
|
359
|
+
- Read-side runtime inventory currently uses the shipped `ace-tmux list` surface. No additional shared read-side CLI follow-up is active today; any future consumer-driven expansion should start as a new task rather than reopening the archived `8r6.t.xeu` family.
|
|
360
|
+
|
|
203
361
|
## Testing Contract
|
|
204
362
|
|
|
205
363
|
- `ace-test ace-tmux` validates deterministic fast coverage in `test/fast/`.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ace
|
|
4
|
+
module Tmux
|
|
5
|
+
module Atoms
|
|
6
|
+
module NamedKeyRegistry
|
|
7
|
+
module_function
|
|
8
|
+
|
|
9
|
+
KEYS = {
|
|
10
|
+
"enter" => "Enter",
|
|
11
|
+
"tab" => "Tab",
|
|
12
|
+
"space" => "Space",
|
|
13
|
+
"escape" => "Escape",
|
|
14
|
+
"esc" => "Escape",
|
|
15
|
+
"up" => "Up",
|
|
16
|
+
"down" => "Down",
|
|
17
|
+
"left" => "Left",
|
|
18
|
+
"right" => "Right",
|
|
19
|
+
"c-c" => "C-c"
|
|
20
|
+
}.freeze
|
|
21
|
+
|
|
22
|
+
def normalize(key)
|
|
23
|
+
value = key.to_s.strip
|
|
24
|
+
raise Ace::Tmux::ValidationError, "Named key is required" if value.empty?
|
|
25
|
+
|
|
26
|
+
normalized = KEYS[value.downcase]
|
|
27
|
+
raise Ace::Tmux::ValidationError, "Unsupported named key: #{key}" unless normalized
|
|
28
|
+
|
|
29
|
+
normalized
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -63,11 +63,12 @@ module Ace
|
|
|
63
63
|
# @param horizontal [Boolean] Split horizontally (default: vertically)
|
|
64
64
|
# @param tmux [String] tmux binary path
|
|
65
65
|
# @return [Array<String>]
|
|
66
|
-
def split_window(target, root: nil, horizontal: false, tmux: "tmux")
|
|
66
|
+
def split_window(target, root: nil, horizontal: false, print_format: nil, tmux: "tmux")
|
|
67
67
|
cmd = [tmux, "split-window"]
|
|
68
68
|
cmd << "-h" if horizontal
|
|
69
69
|
cmd.concat(["-t", target])
|
|
70
70
|
cmd.concat(["-c", File.expand_path(root)]) if root
|
|
71
|
+
cmd.concat(["-P", "-F", print_format]) if print_format
|
|
71
72
|
cmd
|
|
72
73
|
end
|
|
73
74
|
|
|
@@ -80,6 +81,10 @@ module Ace
|
|
|
80
81
|
[tmux, "send-keys", "-t", target, keys, "Enter"]
|
|
81
82
|
end
|
|
82
83
|
|
|
84
|
+
def send_raw_keys(target, *keys, tmux: "tmux")
|
|
85
|
+
[tmux, "send-keys", "-t", target, *keys]
|
|
86
|
+
end
|
|
87
|
+
|
|
83
88
|
# Set the layout for a window
|
|
84
89
|
# @param target [String] Target window
|
|
85
90
|
# @param layout [String] Layout name (e.g., "main-vertical", "tiled")
|
|
@@ -131,6 +136,12 @@ module Ace
|
|
|
131
136
|
cmd
|
|
132
137
|
end
|
|
133
138
|
|
|
139
|
+
def list_windows(target, format: nil, tmux: "tmux")
|
|
140
|
+
cmd = [tmux, "list-windows", "-t", target]
|
|
141
|
+
cmd.concat(["-F", format]) if format
|
|
142
|
+
cmd
|
|
143
|
+
end
|
|
144
|
+
|
|
134
145
|
# Set a window option
|
|
135
146
|
# @param target [String] Target window
|
|
136
147
|
# @param option [String] Option name (e.g., "main-pane-width")
|
|
@@ -197,6 +208,22 @@ module Ace
|
|
|
197
208
|
cmd.concat(["-F", format]) if format
|
|
198
209
|
cmd
|
|
199
210
|
end
|
|
211
|
+
|
|
212
|
+
def capture_pane(target, lines: 40, tmux: "tmux")
|
|
213
|
+
start = -Integer(lines.to_i.abs)
|
|
214
|
+
[tmux, "capture-pane", "-p", "-t", target, "-S", start.to_s, "-E", "-1"]
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def capture_pane_visible(target, start_line:, end_line:, include_alternate: false, tmux: "tmux")
|
|
218
|
+
cmd = [tmux, "capture-pane", "-p"]
|
|
219
|
+
cmd << "-a" if include_alternate
|
|
220
|
+
cmd.concat(["-t", target, "-S", Integer(start_line).to_s, "-E", Integer(end_line).to_s])
|
|
221
|
+
cmd
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
def detach_client(session, tmux: "tmux")
|
|
225
|
+
[tmux, "detach-client", "-s", session]
|
|
226
|
+
end
|
|
200
227
|
end
|
|
201
228
|
end
|
|
202
229
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Ace
|
|
4
|
+
module Tmux
|
|
5
|
+
module Atoms
|
|
6
|
+
# Normalizes ACE-managed tmux window names to avoid target parsing ambiguity.
|
|
7
|
+
module WindowNameSanitizer
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
def call(value, fallback: "window")
|
|
11
|
+
sanitized = sanitize(value)
|
|
12
|
+
sanitized.empty? ? sanitize(fallback).then { |name| name.empty? ? "window" : name } : sanitized
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def sanitize(value)
|
|
16
|
+
value.to_s
|
|
17
|
+
.gsub(/[^A-Za-z0-9_-]+/, "-")
|
|
18
|
+
.gsub(/-+/, "-")
|
|
19
|
+
.gsub(/\A-|-+\z/, "")
|
|
20
|
+
end
|
|
21
|
+
private_class_method :sanitize
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ace/support/cli"
|
|
4
|
+
require "ace/core"
|
|
5
|
+
|
|
6
|
+
module Ace
|
|
7
|
+
module Tmux
|
|
8
|
+
module CLI
|
|
9
|
+
module Commands
|
|
10
|
+
class Attach < Ace::Support::Cli::Command
|
|
11
|
+
include Ace::Support::Cli::Base
|
|
12
|
+
|
|
13
|
+
desc "Attach to a tmux session using shared target resolution"
|
|
14
|
+
|
|
15
|
+
option :session, type: :string, aliases: %w[-s], desc: "Target session name"
|
|
16
|
+
|
|
17
|
+
def call(**options)
|
|
18
|
+
Organisms::ControlSurface.new.attach_session(session: options[:session])
|
|
19
|
+
rescue Ace::Tmux::Error => e
|
|
20
|
+
raise Ace::Support::Cli::Error, e.message
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ace/support/cli"
|
|
4
|
+
require "ace/core"
|
|
5
|
+
|
|
6
|
+
module Ace
|
|
7
|
+
module Tmux
|
|
8
|
+
module CLI
|
|
9
|
+
module Commands
|
|
10
|
+
class Capture < Ace::Support::Cli::Command
|
|
11
|
+
include Ace::Support::Cli::Base
|
|
12
|
+
|
|
13
|
+
desc <<~DESC.strip
|
|
14
|
+
Capture recent output from a tmux pane
|
|
15
|
+
|
|
16
|
+
Interactive CLI panes capture the visible bottom of the current screen.
|
|
17
|
+
Generic shell panes capture a recent history tail.
|
|
18
|
+
DESC
|
|
19
|
+
|
|
20
|
+
example [
|
|
21
|
+
"--pane %1",
|
|
22
|
+
"--pane %8 --lines 20",
|
|
23
|
+
"--session dev --window work --pane .1 --lines 10"
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
option :session, type: :string, aliases: %w[-s], desc: "Target session name"
|
|
27
|
+
option :window, type: :string, aliases: %w[-w], desc: "Target window name, index, or tmux window id (@2)"
|
|
28
|
+
option :pane, type: :string, aliases: %w[-p], desc: "Target pane id (%8), full pane target (dev:work.1), or current-window pane shorthand (.1)"
|
|
29
|
+
option :lines, type: :integer, aliases: %w[-n], default: 40, desc: "Number of recent lines to capture"
|
|
30
|
+
|
|
31
|
+
def call(**options)
|
|
32
|
+
output = Organisms::ControlSurface.new.capture_recent_output(**options.slice(:session, :window, :pane, :lines))
|
|
33
|
+
puts output
|
|
34
|
+
rescue Ace::Tmux::Error => e
|
|
35
|
+
raise Ace::Support::Cli::Error, e.message
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ace/support/cli"
|
|
4
|
+
require "ace/core"
|
|
5
|
+
|
|
6
|
+
module Ace
|
|
7
|
+
module Tmux
|
|
8
|
+
module CLI
|
|
9
|
+
module Commands
|
|
10
|
+
class Detach < Ace::Support::Cli::Command
|
|
11
|
+
include Ace::Support::Cli::Base
|
|
12
|
+
|
|
13
|
+
desc "Detach clients from a tmux session"
|
|
14
|
+
|
|
15
|
+
option :session, type: :string, aliases: %w[-s], desc: "Target session name"
|
|
16
|
+
option :quiet, type: :boolean, aliases: %w[-q], desc: "Suppress non-essential output"
|
|
17
|
+
|
|
18
|
+
def call(**options)
|
|
19
|
+
session = Organisms::ControlSurface.new.detach_session(session: options[:session])
|
|
20
|
+
puts "Detached session #{session}" unless options[:quiet]
|
|
21
|
+
rescue Ace::Tmux::Error => e
|
|
22
|
+
raise Ace::Support::Cli::Error, e.message
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|