clustermux 0.2.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.
@@ -0,0 +1,7 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ build/
5
+ dist/
6
+ .venv/
7
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Yitong Li
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,155 @@
1
+ Metadata-Version: 2.4
2
+ Name: clustermux
3
+ Version: 0.2.0
4
+ Summary: A dependency-free TUI for tmux sessions spread across SSH hosts
5
+ Project-URL: Homepage, https://github.com/lyttttt3333/clustermux
6
+ Project-URL: Repository, https://github.com/lyttttt3333/clustermux
7
+ Project-URL: Issues, https://github.com/lyttttt3333/clustermux/issues
8
+ Author: Yitong Li
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: cluster,hpc,ssh,terminal,tmux,tui
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console :: Curses
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Intended Audience :: System Administrators
16
+ Classifier: License :: OSI Approved :: MIT License
17
+ Classifier: Operating System :: MacOS
18
+ Classifier: Operating System :: POSIX :: Linux
19
+ Classifier: Programming Language :: Python :: 3
20
+ Classifier: Topic :: System :: Systems Administration
21
+ Classifier: Topic :: Terminals
22
+ Requires-Python: >=3.9
23
+ Description-Content-Type: text/markdown
24
+
25
+ # clustermux
26
+
27
+ A small, dependency-free TUI for managing **tmux sessions spread across SSH hosts** — HPC login nodes, cloud dev boxes, GPU clusters — from a single terminal window.
28
+
29
+ clustermux discovers every remote tmux session in parallel, shows you what's running where, and lets you attach, create, rename, kill, or hand off sessions without juggling terminal tabs or remembering which machine hosts which session.
30
+
31
+ ## Features
32
+
33
+ - **One dashboard for every host** — parallel SSH discovery of all remote tmux sessions, with reachability, latency, running command, and working directory
34
+ - **Persistent connections** — each attached session lives in a hidden local tmux window; detach and re-attach without disturbing the remote work
35
+ - **Split workspace** — a navigator sidebar plus a remote terminal pane, inside one local tmux session
36
+ - **iTerm2 integration (macOS)** — opens the manager, or any single session, in a new tab without disturbing your current one; standalone tabs auto-reconnect after transient SSH drops
37
+ - **Session management** — create empty sessions, rename, and kill remote tmux sessions from the TUI
38
+ - **Codex fork** — fork a running [Codex CLI](https://github.com/openai/codex) session into a new tmux session (finds the live rollout thread via `/proc` and runs `codex fork <thread-id>`)
39
+ - **One-command setup** — `clustermux --init` scans your SSH config, installs your key, and writes the hosts file; `clustermux --check` verifies the whole setup
40
+ - **Plain output mode** — `clustermux --list` for scripts and quick checks
41
+ - **Zero dependencies** — a single Python file using only the standard library
42
+
43
+ ## Requirements
44
+
45
+ - Local: Python ≥ 3.9, tmux, and (for tab features) macOS with iTerm2
46
+ - Remote hosts: SSH access (key-based, non-interactive) and tmux
47
+ - The full-screen dashboard (`--here`) and `--list` work on any terminal; the default tab-based flow requires iTerm2
48
+
49
+ ## Install
50
+
51
+ ### pipx / pip
52
+
53
+ ```bash
54
+ pipx install clustermux
55
+ # or
56
+ pip install clustermux
57
+ # or straight from the repo
58
+ pipx install git+https://github.com/lyttttt3333/clustermux.git
59
+ ```
60
+
61
+ ### Single-file script
62
+
63
+ clustermux is self-contained — download the file anywhere on your `PATH`:
64
+
65
+ ```bash
66
+ curl -L -o ~/.local/bin/clustermux \
67
+ https://raw.githubusercontent.com/lyttttt3333/clustermux/main/clustermux.py
68
+ chmod +x ~/.local/bin/clustermux
69
+ ```
70
+
71
+ ## First-time setup
72
+
73
+ On a fresh machine, one command walks you through everything:
74
+
75
+ ```bash
76
+ clustermux --init
77
+ ```
78
+
79
+ The wizard will:
80
+
81
+ 1. **SSH key** — use your existing `~/.ssh` key, or offer to generate an ed25519 one
82
+ 2. **Discover hosts** — scan `~/.ssh/config` (`Host` aliases, including `Include`d files) and any unhashed entries in `~/.ssh/known_hosts`
83
+ 3. **Probe connectivity** — test every candidate in parallel with `BatchMode` SSH, classifying each as reachable / key-rejected / unreachable
84
+ 4. **Install your key** — for hosts that reject key auth, offer to run `ssh-copy-id` (you type the password once per host)
85
+ 5. **Write the config** — reachable hosts are added to `~/.config/clustermux/hosts.json` with sensible group/label defaults (existing entries are kept, and the old file is backed up); you can review the result in `$EDITOR`
86
+
87
+ Then verify the whole setup at any time:
88
+
89
+ ```bash
90
+ clustermux --check
91
+ ```
92
+
93
+ This checks Python, tmux, ssh, iTerm2, your SSH key and config file, then probes every configured host and reports sessions and latency per node.
94
+
95
+ ## Configuration
96
+
97
+ `clustermux --init` writes this file for you, but you can also create `~/.config/clustermux/hosts.json` by hand (see [examples/hosts.json](examples/hosts.json)):
98
+
99
+ ```json
100
+ [
101
+ { "group": "GPU", "label": "login-01", "target": "me@gpu-login-01.example.com" },
102
+ { "group": "GPU", "label": "dev-01", "target": "gpu-dev-01", "connect_timeout": 20 },
103
+ { "group": "CPU", "label": "login", "target": "me@cpu-login.example.com" }
104
+ ]
105
+ ```
106
+
107
+ - `group` — shown as the cluster name in the UI
108
+ - `label` — per-host display name
109
+ - `target` — anything `ssh` accepts (host alias from `~/.ssh/config`, or `user@host`)
110
+ - `connect_timeout` — optional per-host SSH timeout in seconds (default: `--timeout`, 8s)
111
+
112
+ Hosts are validated at startup; SSH is always invoked with `BatchMode=yes`, so a host that needs a password simply shows up as offline instead of blocking the UI.
113
+
114
+ ## Usage
115
+
116
+ ```bash
117
+ clustermux # open the manager workspace in a new iTerm tab
118
+ clustermux --init # first-time setup: scan SSH config, install keys, write hosts.json
119
+ clustermux --check # verify local requirements and probe every host
120
+ clustermux --workspace # run the split navigator/terminal workspace here
121
+ clustermux --here # full-screen dashboard with pane previews, in this terminal
122
+ clustermux --list # print one snapshot as a table and exit
123
+ clustermux --refresh 60 # change the auto-refresh interval (seconds; 0 disables)
124
+ ```
125
+
126
+ ### Navigator keybindings (default workspace)
127
+
128
+ | Key | Action |
129
+ | --- | --- |
130
+ | `↑`/`↓` | move between clusters and sessions |
131
+ | `Enter` | attach the selected session in the right pane |
132
+ | `b` | open a remote Bash shell for the selected cluster |
133
+ | `t` | create a new empty tmux session on the selected cluster |
134
+ | `f` | fork the selected Codex session into a new tmux session |
135
+ | `e` / `x` | rename / kill the selected session |
136
+ | `o` | hand the session off to a standalone iTerm tab (auto-reconnects) |
137
+ | `r` | refresh all hosts |
138
+ | `Shift+←` | jump back to the sidebar from the remote pane |
139
+ | `q` | close the workspace (remote sessions keep running) |
140
+
141
+ Inside an attached remote tmux session, the remote prefix is `Ctrl-b` as usual; the local workspace uses `Ctrl-a`.
142
+
143
+ ### Dashboard keybindings (`--here`)
144
+
145
+ `↑↓` select · `Enter` attach here · `t` new tab · `r` refresh · `p` preview · `q` quit
146
+
147
+ ## How it works
148
+
149
+ - Discovery runs `tmux list-panes -a` on every host in parallel over SSH and parses a sentinel-separated format that survives older remote tmux builds.
150
+ - Attaching creates (or reuses) a hidden window in the local `clustermux` tmux session running a supervised `ssh -t host tmux attach-session ...`; the pane is swapped into the visible slot. Killing the workspace only disconnects local SSH clients — remote sessions and their processes keep running.
151
+ - The iTerm handoff moves a session into its own tab and respawns the workspace pane as a placeholder, so you can later pull it back into the workspace.
152
+
153
+ ## License
154
+
155
+ [MIT](LICENSE)
@@ -0,0 +1,131 @@
1
+ # clustermux
2
+
3
+ A small, dependency-free TUI for managing **tmux sessions spread across SSH hosts** — HPC login nodes, cloud dev boxes, GPU clusters — from a single terminal window.
4
+
5
+ clustermux discovers every remote tmux session in parallel, shows you what's running where, and lets you attach, create, rename, kill, or hand off sessions without juggling terminal tabs or remembering which machine hosts which session.
6
+
7
+ ## Features
8
+
9
+ - **One dashboard for every host** — parallel SSH discovery of all remote tmux sessions, with reachability, latency, running command, and working directory
10
+ - **Persistent connections** — each attached session lives in a hidden local tmux window; detach and re-attach without disturbing the remote work
11
+ - **Split workspace** — a navigator sidebar plus a remote terminal pane, inside one local tmux session
12
+ - **iTerm2 integration (macOS)** — opens the manager, or any single session, in a new tab without disturbing your current one; standalone tabs auto-reconnect after transient SSH drops
13
+ - **Session management** — create empty sessions, rename, and kill remote tmux sessions from the TUI
14
+ - **Codex fork** — fork a running [Codex CLI](https://github.com/openai/codex) session into a new tmux session (finds the live rollout thread via `/proc` and runs `codex fork <thread-id>`)
15
+ - **One-command setup** — `clustermux --init` scans your SSH config, installs your key, and writes the hosts file; `clustermux --check` verifies the whole setup
16
+ - **Plain output mode** — `clustermux --list` for scripts and quick checks
17
+ - **Zero dependencies** — a single Python file using only the standard library
18
+
19
+ ## Requirements
20
+
21
+ - Local: Python ≥ 3.9, tmux, and (for tab features) macOS with iTerm2
22
+ - Remote hosts: SSH access (key-based, non-interactive) and tmux
23
+ - The full-screen dashboard (`--here`) and `--list` work on any terminal; the default tab-based flow requires iTerm2
24
+
25
+ ## Install
26
+
27
+ ### pipx / pip
28
+
29
+ ```bash
30
+ pipx install clustermux
31
+ # or
32
+ pip install clustermux
33
+ # or straight from the repo
34
+ pipx install git+https://github.com/lyttttt3333/clustermux.git
35
+ ```
36
+
37
+ ### Single-file script
38
+
39
+ clustermux is self-contained — download the file anywhere on your `PATH`:
40
+
41
+ ```bash
42
+ curl -L -o ~/.local/bin/clustermux \
43
+ https://raw.githubusercontent.com/lyttttt3333/clustermux/main/clustermux.py
44
+ chmod +x ~/.local/bin/clustermux
45
+ ```
46
+
47
+ ## First-time setup
48
+
49
+ On a fresh machine, one command walks you through everything:
50
+
51
+ ```bash
52
+ clustermux --init
53
+ ```
54
+
55
+ The wizard will:
56
+
57
+ 1. **SSH key** — use your existing `~/.ssh` key, or offer to generate an ed25519 one
58
+ 2. **Discover hosts** — scan `~/.ssh/config` (`Host` aliases, including `Include`d files) and any unhashed entries in `~/.ssh/known_hosts`
59
+ 3. **Probe connectivity** — test every candidate in parallel with `BatchMode` SSH, classifying each as reachable / key-rejected / unreachable
60
+ 4. **Install your key** — for hosts that reject key auth, offer to run `ssh-copy-id` (you type the password once per host)
61
+ 5. **Write the config** — reachable hosts are added to `~/.config/clustermux/hosts.json` with sensible group/label defaults (existing entries are kept, and the old file is backed up); you can review the result in `$EDITOR`
62
+
63
+ Then verify the whole setup at any time:
64
+
65
+ ```bash
66
+ clustermux --check
67
+ ```
68
+
69
+ This checks Python, tmux, ssh, iTerm2, your SSH key and config file, then probes every configured host and reports sessions and latency per node.
70
+
71
+ ## Configuration
72
+
73
+ `clustermux --init` writes this file for you, but you can also create `~/.config/clustermux/hosts.json` by hand (see [examples/hosts.json](examples/hosts.json)):
74
+
75
+ ```json
76
+ [
77
+ { "group": "GPU", "label": "login-01", "target": "me@gpu-login-01.example.com" },
78
+ { "group": "GPU", "label": "dev-01", "target": "gpu-dev-01", "connect_timeout": 20 },
79
+ { "group": "CPU", "label": "login", "target": "me@cpu-login.example.com" }
80
+ ]
81
+ ```
82
+
83
+ - `group` — shown as the cluster name in the UI
84
+ - `label` — per-host display name
85
+ - `target` — anything `ssh` accepts (host alias from `~/.ssh/config`, or `user@host`)
86
+ - `connect_timeout` — optional per-host SSH timeout in seconds (default: `--timeout`, 8s)
87
+
88
+ Hosts are validated at startup; SSH is always invoked with `BatchMode=yes`, so a host that needs a password simply shows up as offline instead of blocking the UI.
89
+
90
+ ## Usage
91
+
92
+ ```bash
93
+ clustermux # open the manager workspace in a new iTerm tab
94
+ clustermux --init # first-time setup: scan SSH config, install keys, write hosts.json
95
+ clustermux --check # verify local requirements and probe every host
96
+ clustermux --workspace # run the split navigator/terminal workspace here
97
+ clustermux --here # full-screen dashboard with pane previews, in this terminal
98
+ clustermux --list # print one snapshot as a table and exit
99
+ clustermux --refresh 60 # change the auto-refresh interval (seconds; 0 disables)
100
+ ```
101
+
102
+ ### Navigator keybindings (default workspace)
103
+
104
+ | Key | Action |
105
+ | --- | --- |
106
+ | `↑`/`↓` | move between clusters and sessions |
107
+ | `Enter` | attach the selected session in the right pane |
108
+ | `b` | open a remote Bash shell for the selected cluster |
109
+ | `t` | create a new empty tmux session on the selected cluster |
110
+ | `f` | fork the selected Codex session into a new tmux session |
111
+ | `e` / `x` | rename / kill the selected session |
112
+ | `o` | hand the session off to a standalone iTerm tab (auto-reconnects) |
113
+ | `r` | refresh all hosts |
114
+ | `Shift+←` | jump back to the sidebar from the remote pane |
115
+ | `q` | close the workspace (remote sessions keep running) |
116
+
117
+ Inside an attached remote tmux session, the remote prefix is `Ctrl-b` as usual; the local workspace uses `Ctrl-a`.
118
+
119
+ ### Dashboard keybindings (`--here`)
120
+
121
+ `↑↓` select · `Enter` attach here · `t` new tab · `r` refresh · `p` preview · `q` quit
122
+
123
+ ## How it works
124
+
125
+ - Discovery runs `tmux list-panes -a` on every host in parallel over SSH and parses a sentinel-separated format that survives older remote tmux builds.
126
+ - Attaching creates (or reuses) a hidden window in the local `clustermux` tmux session running a supervised `ssh -t host tmux attach-session ...`; the pane is swapped into the visible slot. Killing the workspace only disconnects local SSH clients — remote sessions and their processes keep running.
127
+ - The iTerm handoff moves a session into its own tab and respawns the workspace pane as a placeholder, so you can later pull it back into the workspace.
128
+
129
+ ## License
130
+
131
+ [MIT](LICENSE)