tmux-wrapper 0.1.0__tar.gz
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.
- tmux_wrapper-0.1.0/LICENSE +21 -0
- tmux_wrapper-0.1.0/PKG-INFO +194 -0
- tmux_wrapper-0.1.0/README.md +170 -0
- tmux_wrapper-0.1.0/pyproject.toml +46 -0
- tmux_wrapper-0.1.0/setup.cfg +4 -0
- tmux_wrapper-0.1.0/tests/test_tmux_wrapper.py +313 -0
- tmux_wrapper-0.1.0/tmux_wrapper.egg-info/PKG-INFO +194 -0
- tmux_wrapper-0.1.0/tmux_wrapper.egg-info/SOURCES.txt +11 -0
- tmux_wrapper-0.1.0/tmux_wrapper.egg-info/dependency_links.txt +1 -0
- tmux_wrapper-0.1.0/tmux_wrapper.egg-info/entry_points.txt +2 -0
- tmux_wrapper-0.1.0/tmux_wrapper.egg-info/requires.txt +1 -0
- tmux_wrapper-0.1.0/tmux_wrapper.egg-info/top_level.txt +1 -0
- tmux_wrapper-0.1.0/tmux_wrapper.py +1114 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Randomizez
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tmux-wrapper
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Lightweight tmux automation wrapper and renderer.
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Project-URL: Homepage, https://github.com/Randomizez/TmuxWrapper
|
|
7
|
+
Project-URL: Repository, https://github.com/Randomizez/TmuxWrapper
|
|
8
|
+
Project-URL: Issues, https://github.com/Randomizez/TmuxWrapper/issues
|
|
9
|
+
Keywords: tmux,terminal,automation,cli
|
|
10
|
+
Classifier: Environment :: Console
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Terminals
|
|
19
|
+
Requires-Python: >=3.9
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Requires-Dist: fire>=0.7.1
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# tmux-wrapper
|
|
26
|
+
|
|
27
|
+
`tmux-wrapper` is a small Python module and CLI for driving a tmux session like
|
|
28
|
+
a human: type text, press key chords, inspect what changed, and scroll through
|
|
29
|
+
history.
|
|
30
|
+
|
|
31
|
+
It is designed for agent workflows, test automation, and other cases where you
|
|
32
|
+
want a simple tmux control surface instead of shelling out to a large stack of
|
|
33
|
+
custom tmux commands.
|
|
34
|
+
|
|
35
|
+
## Features
|
|
36
|
+
|
|
37
|
+
- `type(text)` sends literal text to the active pane.
|
|
38
|
+
- `press(chords)` sends key chords such as `Enter`, `Ctrl+C`, or `Ctrl+B Z`.
|
|
39
|
+
- `snapshot()` captures the full current screen and resets the diff baseline.
|
|
40
|
+
- `view()` is the recommended inspection API. It returns a contextual,
|
|
41
|
+
line-oriented delta against the previous capture.
|
|
42
|
+
- `glance()` returns incremental additions plus collapsed
|
|
43
|
+
`...[N unchanged lines]` markers for unchanged regions.
|
|
44
|
+
- `scroll_up(lines=3)` and `scroll_down(lines=3)` emulate mouse-wheel style
|
|
45
|
+
scrolling via tmux copy mode.
|
|
46
|
+
- `tmux-c` provides the same workflow from the command line.
|
|
47
|
+
|
|
48
|
+
## Requirements
|
|
49
|
+
|
|
50
|
+
- Python 3.9+
|
|
51
|
+
- `tmux` installed and available on `PATH`
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
Install from PyPI:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
pip install tmux-wrapper
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
After installation, the CLI command `tmux-c` is available:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
tmux-c 1 glance
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Quick Start
|
|
68
|
+
|
|
69
|
+
### Python API
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from tmux_wrapper import Keys, TMUXWrapper
|
|
73
|
+
|
|
74
|
+
tmux = TMUXWrapper(session="demo")
|
|
75
|
+
|
|
76
|
+
# Establish a baseline for future view()/glance() calls.
|
|
77
|
+
tmux.snapshot()
|
|
78
|
+
|
|
79
|
+
tmux.type("echo hello")
|
|
80
|
+
tmux.press([(Keys.Enter,)])
|
|
81
|
+
print(tmux.view())
|
|
82
|
+
|
|
83
|
+
# For a compact "only what was newly added" report:
|
|
84
|
+
print(tmux.glance())
|
|
85
|
+
|
|
86
|
+
tmux.scroll_up(5)
|
|
87
|
+
print(tmux.view())
|
|
88
|
+
|
|
89
|
+
tmux.scroll_down(999)
|
|
90
|
+
tmux.delete()
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### CLI
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
tmux-c demo snapshot
|
|
97
|
+
tmux-c demo type "ls /data"
|
|
98
|
+
tmux-c demo press Enter
|
|
99
|
+
tmux-c demo view
|
|
100
|
+
tmux-c demo glance
|
|
101
|
+
tmux-c demo scroll_up 5
|
|
102
|
+
tmux-c demo view
|
|
103
|
+
tmux-c demo scroll_down 999
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## How Inspection Works
|
|
107
|
+
|
|
108
|
+
`view()` is the default inspection method.
|
|
109
|
+
|
|
110
|
+
- `snapshot()` captures the full screen and stores it as the new baseline.
|
|
111
|
+
- `view()` compares the current screen against the previous capture.
|
|
112
|
+
- `glance()` uses the same diff basis, but returns only added lines plus
|
|
113
|
+
`...[N unchanged lines]` markers for unchanged regions.
|
|
114
|
+
- Added lines are marked with `!!`.
|
|
115
|
+
- Removed lines are hidden.
|
|
116
|
+
- `?` helper lines from `difflib.ndiff` are also hidden.
|
|
117
|
+
- If there are no new additions, `glance()` returns `[Nothing Changed]`.
|
|
118
|
+
|
|
119
|
+
Example:
|
|
120
|
+
|
|
121
|
+
```text
|
|
122
|
+
!!new output line
|
|
123
|
+
existing prompt context
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
For compact incremental output, `glance()` returns abbreviated output such as:
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
...[12 unchanged lines]
|
|
130
|
+
!!new output line
|
|
131
|
+
...[3 unchanged lines]
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Press Syntax
|
|
135
|
+
|
|
136
|
+
In Python, `press()` accepts a list of chords:
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
tmux.press([(Keys.Enter,)])
|
|
140
|
+
tmux.press([(Keys.Ctrl, Keys.C)])
|
|
141
|
+
tmux.press([(Keys.Ctrl, Keys.B), (Keys.Z,)])
|
|
142
|
+
tmux.press([(Keys.Ctrl, Keys.B), (Keys.Left,)])
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
In the CLI, each chord is passed as an argument:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
tmux-c demo press Enter
|
|
149
|
+
tmux-c demo press Ctrl+C
|
|
150
|
+
tmux-c demo press Ctrl+B Z
|
|
151
|
+
tmux-c demo press Ctrl+B Left
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
## Scrolling
|
|
155
|
+
|
|
156
|
+
`scroll_up()` and `scroll_down()` are line-based helpers built on tmux copy
|
|
157
|
+
mode.
|
|
158
|
+
|
|
159
|
+
- `scroll_up(lines)` enters copy mode and scrolls up by `lines`.
|
|
160
|
+
- `scroll_down(lines)` scrolls down by `lines`.
|
|
161
|
+
- When `scroll_down()` reaches the bottom, it exits copy mode automatically.
|
|
162
|
+
|
|
163
|
+
This matches the intended "mouse wheel with `set -g mouse on`" feel more closely
|
|
164
|
+
than page-based movement.
|
|
165
|
+
|
|
166
|
+
## Session Behavior
|
|
167
|
+
|
|
168
|
+
- `TMUXWrapper(session="name")` creates the session if it does not already
|
|
169
|
+
exist.
|
|
170
|
+
- If the wrapper created the session, object cleanup will delete it by default.
|
|
171
|
+
- Calling `delete()` always deletes the session immediately.
|
|
172
|
+
- CLI snapshot/view/glance state is persisted per session so repeated
|
|
173
|
+
`tmux-c ...` calls can diff across separate invocations.
|
|
174
|
+
|
|
175
|
+
## Development
|
|
176
|
+
|
|
177
|
+
Install development dependencies with uv:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
uv sync --dev
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
Run tests:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
env -u VIRTUAL_ENV uv run pytest -q
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Notes
|
|
190
|
+
|
|
191
|
+
- The package focuses on a practical tmux-driving workflow, not a full tmux
|
|
192
|
+
abstraction layer.
|
|
193
|
+
- The renderer captures the full tmux window, not just a single pane.
|
|
194
|
+
- The cursor is rendered visibly in full-screen snapshots.
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
# tmux-wrapper
|
|
2
|
+
|
|
3
|
+
`tmux-wrapper` is a small Python module and CLI for driving a tmux session like
|
|
4
|
+
a human: type text, press key chords, inspect what changed, and scroll through
|
|
5
|
+
history.
|
|
6
|
+
|
|
7
|
+
It is designed for agent workflows, test automation, and other cases where you
|
|
8
|
+
want a simple tmux control surface instead of shelling out to a large stack of
|
|
9
|
+
custom tmux commands.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- `type(text)` sends literal text to the active pane.
|
|
14
|
+
- `press(chords)` sends key chords such as `Enter`, `Ctrl+C`, or `Ctrl+B Z`.
|
|
15
|
+
- `snapshot()` captures the full current screen and resets the diff baseline.
|
|
16
|
+
- `view()` is the recommended inspection API. It returns a contextual,
|
|
17
|
+
line-oriented delta against the previous capture.
|
|
18
|
+
- `glance()` returns incremental additions plus collapsed
|
|
19
|
+
`...[N unchanged lines]` markers for unchanged regions.
|
|
20
|
+
- `scroll_up(lines=3)` and `scroll_down(lines=3)` emulate mouse-wheel style
|
|
21
|
+
scrolling via tmux copy mode.
|
|
22
|
+
- `tmux-c` provides the same workflow from the command line.
|
|
23
|
+
|
|
24
|
+
## Requirements
|
|
25
|
+
|
|
26
|
+
- Python 3.9+
|
|
27
|
+
- `tmux` installed and available on `PATH`
|
|
28
|
+
|
|
29
|
+
## Installation
|
|
30
|
+
|
|
31
|
+
Install from PyPI:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install tmux-wrapper
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
After installation, the CLI command `tmux-c` is available:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
tmux-c 1 glance
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Quick Start
|
|
44
|
+
|
|
45
|
+
### Python API
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from tmux_wrapper import Keys, TMUXWrapper
|
|
49
|
+
|
|
50
|
+
tmux = TMUXWrapper(session="demo")
|
|
51
|
+
|
|
52
|
+
# Establish a baseline for future view()/glance() calls.
|
|
53
|
+
tmux.snapshot()
|
|
54
|
+
|
|
55
|
+
tmux.type("echo hello")
|
|
56
|
+
tmux.press([(Keys.Enter,)])
|
|
57
|
+
print(tmux.view())
|
|
58
|
+
|
|
59
|
+
# For a compact "only what was newly added" report:
|
|
60
|
+
print(tmux.glance())
|
|
61
|
+
|
|
62
|
+
tmux.scroll_up(5)
|
|
63
|
+
print(tmux.view())
|
|
64
|
+
|
|
65
|
+
tmux.scroll_down(999)
|
|
66
|
+
tmux.delete()
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### CLI
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
tmux-c demo snapshot
|
|
73
|
+
tmux-c demo type "ls /data"
|
|
74
|
+
tmux-c demo press Enter
|
|
75
|
+
tmux-c demo view
|
|
76
|
+
tmux-c demo glance
|
|
77
|
+
tmux-c demo scroll_up 5
|
|
78
|
+
tmux-c demo view
|
|
79
|
+
tmux-c demo scroll_down 999
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## How Inspection Works
|
|
83
|
+
|
|
84
|
+
`view()` is the default inspection method.
|
|
85
|
+
|
|
86
|
+
- `snapshot()` captures the full screen and stores it as the new baseline.
|
|
87
|
+
- `view()` compares the current screen against the previous capture.
|
|
88
|
+
- `glance()` uses the same diff basis, but returns only added lines plus
|
|
89
|
+
`...[N unchanged lines]` markers for unchanged regions.
|
|
90
|
+
- Added lines are marked with `!!`.
|
|
91
|
+
- Removed lines are hidden.
|
|
92
|
+
- `?` helper lines from `difflib.ndiff` are also hidden.
|
|
93
|
+
- If there are no new additions, `glance()` returns `[Nothing Changed]`.
|
|
94
|
+
|
|
95
|
+
Example:
|
|
96
|
+
|
|
97
|
+
```text
|
|
98
|
+
!!new output line
|
|
99
|
+
existing prompt context
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
For compact incremental output, `glance()` returns abbreviated output such as:
|
|
103
|
+
|
|
104
|
+
```text
|
|
105
|
+
...[12 unchanged lines]
|
|
106
|
+
!!new output line
|
|
107
|
+
...[3 unchanged lines]
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Press Syntax
|
|
111
|
+
|
|
112
|
+
In Python, `press()` accepts a list of chords:
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
tmux.press([(Keys.Enter,)])
|
|
116
|
+
tmux.press([(Keys.Ctrl, Keys.C)])
|
|
117
|
+
tmux.press([(Keys.Ctrl, Keys.B), (Keys.Z,)])
|
|
118
|
+
tmux.press([(Keys.Ctrl, Keys.B), (Keys.Left,)])
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
In the CLI, each chord is passed as an argument:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
tmux-c demo press Enter
|
|
125
|
+
tmux-c demo press Ctrl+C
|
|
126
|
+
tmux-c demo press Ctrl+B Z
|
|
127
|
+
tmux-c demo press Ctrl+B Left
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Scrolling
|
|
131
|
+
|
|
132
|
+
`scroll_up()` and `scroll_down()` are line-based helpers built on tmux copy
|
|
133
|
+
mode.
|
|
134
|
+
|
|
135
|
+
- `scroll_up(lines)` enters copy mode and scrolls up by `lines`.
|
|
136
|
+
- `scroll_down(lines)` scrolls down by `lines`.
|
|
137
|
+
- When `scroll_down()` reaches the bottom, it exits copy mode automatically.
|
|
138
|
+
|
|
139
|
+
This matches the intended "mouse wheel with `set -g mouse on`" feel more closely
|
|
140
|
+
than page-based movement.
|
|
141
|
+
|
|
142
|
+
## Session Behavior
|
|
143
|
+
|
|
144
|
+
- `TMUXWrapper(session="name")` creates the session if it does not already
|
|
145
|
+
exist.
|
|
146
|
+
- If the wrapper created the session, object cleanup will delete it by default.
|
|
147
|
+
- Calling `delete()` always deletes the session immediately.
|
|
148
|
+
- CLI snapshot/view/glance state is persisted per session so repeated
|
|
149
|
+
`tmux-c ...` calls can diff across separate invocations.
|
|
150
|
+
|
|
151
|
+
## Development
|
|
152
|
+
|
|
153
|
+
Install development dependencies with uv:
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
uv sync --dev
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Run tests:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
env -u VIRTUAL_ENV uv run pytest -q
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## Notes
|
|
166
|
+
|
|
167
|
+
- The package focuses on a practical tmux-driving workflow, not a full tmux
|
|
168
|
+
abstraction layer.
|
|
169
|
+
- The renderer captures the full tmux window, not just a single pane.
|
|
170
|
+
- The cursor is rendered visibly in full-screen snapshots.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "tmux-wrapper"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Lightweight tmux automation wrapper and renderer."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.9"
|
|
7
|
+
license = "MIT"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
keywords = ["tmux", "terminal", "automation", "cli"]
|
|
10
|
+
classifiers = [
|
|
11
|
+
"Environment :: Console",
|
|
12
|
+
"Intended Audience :: Developers",
|
|
13
|
+
"Programming Language :: Python :: 3",
|
|
14
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
15
|
+
"Programming Language :: Python :: 3.9",
|
|
16
|
+
"Programming Language :: Python :: 3.10",
|
|
17
|
+
"Programming Language :: Python :: 3.11",
|
|
18
|
+
"Programming Language :: Python :: 3.12",
|
|
19
|
+
"Topic :: Terminals",
|
|
20
|
+
]
|
|
21
|
+
dependencies = [
|
|
22
|
+
"fire>=0.7.1",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
[project.urls]
|
|
26
|
+
Homepage = "https://github.com/Randomizez/TmuxWrapper"
|
|
27
|
+
Repository = "https://github.com/Randomizez/TmuxWrapper"
|
|
28
|
+
Issues = "https://github.com/Randomizez/TmuxWrapper/issues"
|
|
29
|
+
|
|
30
|
+
[build-system]
|
|
31
|
+
requires = ["setuptools>=68"]
|
|
32
|
+
build-backend = "setuptools.build_meta"
|
|
33
|
+
|
|
34
|
+
[project.scripts]
|
|
35
|
+
tmux-c = "tmux_wrapper:main"
|
|
36
|
+
|
|
37
|
+
[tool.setuptools]
|
|
38
|
+
py-modules = ["tmux_wrapper"]
|
|
39
|
+
|
|
40
|
+
[dependency-groups]
|
|
41
|
+
dev = [
|
|
42
|
+
"pytest>=8.4.2",
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[tool.pytest.ini_options]
|
|
46
|
+
testpaths = ["tests"]
|