sshplex 1.4.0__tar.gz → 1.6.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.
- sshplex-1.6.0/PKG-INFO +225 -0
- sshplex-1.6.0/README.md +172 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/pyproject.toml +4 -1
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/__init__.py +1 -1
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/config-template.yaml +8 -1
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/config.py +71 -3
- sshplex-1.6.0/sshplex/lib/multiplexer/iterm2_native.py +596 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/multiplexer/tmux.py +54 -69
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/ui/config_editor.py +244 -77
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/ui/host_selector.py +157 -8
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/ui/session_manager.py +309 -27
- sshplex-1.6.0/sshplex/lib/utils/__init__.py +23 -0
- sshplex-1.6.0/sshplex/lib/utils/iterm2.py +249 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/main.py +7 -2
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/sshplex_connector.py +111 -35
- sshplex-1.6.0/sshplex.egg-info/PKG-INFO +225 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex.egg-info/SOURCES.txt +3 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex.egg-info/requires.txt +3 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/tests/test_config.py +42 -0
- sshplex-1.4.0/PKG-INFO +0 -424
- sshplex-1.4.0/README.md +0 -373
- sshplex-1.4.0/sshplex.egg-info/PKG-INFO +0 -424
- {sshplex-1.4.0 → sshplex-1.6.0}/LICENSE +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/MANIFEST.in +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/setup.cfg +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/cli.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/__init__.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/cache.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/logger.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/multiplexer/__init__.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/multiplexer/base.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/onboarding/__init__.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/onboarding/wizard.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/sot/__init__.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/sot/ansible.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/sot/base.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/sot/consul.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/sot/factory.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/sot/netbox.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/sot/static.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex/lib/ui/__init__.py +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex.egg-info/dependency_links.txt +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex.egg-info/entry_points.txt +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/sshplex.egg-info/top_level.txt +0 -0
- {sshplex-1.4.0 → sshplex-1.6.0}/tests/test_cache.py +0 -0
sshplex-1.6.0/PKG-INFO
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: sshplex
|
|
3
|
+
Version: 1.6.0
|
|
4
|
+
Summary: Multiplex your SSH connections with style
|
|
5
|
+
Author-email: MJAHED Sabri <contact@sabrimjahed.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/sabrimjd/sshplex
|
|
8
|
+
Project-URL: Repository, https://github.com/sabrimjd/sshplex
|
|
9
|
+
Project-URL: Documentation, https://github.com/sabrimjd/sshplex#readme
|
|
10
|
+
Project-URL: Bug Tracker, https://github.com/sabrimjd/sshplex/issues
|
|
11
|
+
Keywords: ssh,tmux,multiplexer,netbox,tui,terminal
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: System Administrators
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
18
|
+
Classifier: Operating System :: MacOS
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
24
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
25
|
+
Classifier: Topic :: System :: Networking
|
|
26
|
+
Classifier: Topic :: System :: Systems Administration
|
|
27
|
+
Classifier: Topic :: Terminals
|
|
28
|
+
Requires-Python: >=3.8
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
License-File: LICENSE
|
|
31
|
+
Requires-Dist: pynetbox==7.6.1
|
|
32
|
+
Requires-Dist: textual==8.0.0
|
|
33
|
+
Requires-Dist: pyyaml==6.0.3
|
|
34
|
+
Requires-Dist: pydantic==2.12.5
|
|
35
|
+
Requires-Dist: loguru==0.7.3
|
|
36
|
+
Requires-Dist: rich==14.3.2
|
|
37
|
+
Requires-Dist: libtmux==0.53.1
|
|
38
|
+
Requires-Dist: pyperclip==1.11.0
|
|
39
|
+
Provides-Extra: consul
|
|
40
|
+
Requires-Dist: python-consul2>=0.1.5; extra == "consul"
|
|
41
|
+
Provides-Extra: iterm2
|
|
42
|
+
Requires-Dist: iterm2>=2.0.0; extra == "iterm2"
|
|
43
|
+
Provides-Extra: dev
|
|
44
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
45
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
46
|
+
Requires-Dist: black>=22.0.0; extra == "dev"
|
|
47
|
+
Requires-Dist: flake8>=5.0.0; extra == "dev"
|
|
48
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
49
|
+
Requires-Dist: ruff>=0.8.0; extra == "dev"
|
|
50
|
+
Requires-Dist: vulture>=2.11; extra == "dev"
|
|
51
|
+
Requires-Dist: types-PyYAML>=6.0.0; extra == "dev"
|
|
52
|
+
Dynamic: license-file
|
|
53
|
+
|
|
54
|
+

|
|
55
|
+
|
|
56
|
+
**Multiplex your SSH connections with style**
|
|
57
|
+
|
|
58
|
+
SSHplex is a Python-based SSH connection multiplexer with a modern TUI. Connect to multiple hosts simultaneously using tmux or iTerm2, with sources from NetBox, Ansible, Consul, or static lists.
|
|
59
|
+
|
|
60
|
+
## Features
|
|
61
|
+
|
|
62
|
+
- 🖥️ **Modern TUI** - Textual-based host selector with search, sort, and multi-select
|
|
63
|
+
- 🔌 **Multiple Sources** - NetBox, Ansible, Consul, static lists - use them together
|
|
64
|
+
- 📦 **3 Backends** - tmux standalone, tmux + iTerm2, or iTerm2 native (macOS)
|
|
65
|
+
- ✏️ **Config Editor** - Built-in YAML editor with validation (`e` key)
|
|
66
|
+
- 🔄 **Broadcast Input** - Sync commands across multiple SSH sessions
|
|
67
|
+
- 🔐 **SSH Security** - Configurable host key checking and retry logic
|
|
68
|
+
- 🚀 **Fast Startup** - Intelligent caching with configurable TTL
|
|
69
|
+
|
|
70
|
+
## Quick Start
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
# Install
|
|
74
|
+
pip install sshplex
|
|
75
|
+
|
|
76
|
+
# First-time setup (interactive wizard)
|
|
77
|
+
sshplex --onboarding
|
|
78
|
+
|
|
79
|
+
# Launch TUI
|
|
80
|
+
sshplex
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### Prerequisites
|
|
84
|
+
|
|
85
|
+
- Python 3.8+
|
|
86
|
+
- tmux (Linux/macOS) or iTerm2 (macOS)
|
|
87
|
+
- SSH key configured for target hosts
|
|
88
|
+
|
|
89
|
+
## Usage
|
|
90
|
+
|
|
91
|
+
| Key | Action |
|
|
92
|
+
|-----|--------|
|
|
93
|
+
| `Space` | Toggle host selection |
|
|
94
|
+
| `a` / `d` | Select / Deselect all |
|
|
95
|
+
| `Enter` | Connect to selected hosts |
|
|
96
|
+
| `/` | Search/filter hosts |
|
|
97
|
+
| `p` | Toggle panes/tabs mode |
|
|
98
|
+
| `b` | Toggle broadcast mode |
|
|
99
|
+
| `e` | Open config editor |
|
|
100
|
+
| `s` | Open session manager |
|
|
101
|
+
| `h` | Show keyboard shortcuts |
|
|
102
|
+
| `q` | Quit |
|
|
103
|
+
|
|
104
|
+
## Multiplexer Backends
|
|
105
|
+
|
|
106
|
+
| Backend | Platform | Best For |
|
|
107
|
+
|---------|----------|----------|
|
|
108
|
+
| **tmux** | Linux, macOS | Maximum compatibility, persistence |
|
|
109
|
+
| **tmux + iTerm2** | macOS | Native UI + persistence |
|
|
110
|
+
| **iTerm2 native** | macOS | Simple setup, no tmux dependency |
|
|
111
|
+
|
|
112
|
+
```yaml
|
|
113
|
+
# ~/.config/sshplex/sshplex.yaml
|
|
114
|
+
tmux:
|
|
115
|
+
backend: "tmux" # or "iterm2-native" on macOS
|
|
116
|
+
layout: "tiled"
|
|
117
|
+
max_panes_per_window: 5
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Sources of Truth
|
|
121
|
+
|
|
122
|
+
### Static Hosts
|
|
123
|
+
```yaml
|
|
124
|
+
sot:
|
|
125
|
+
import:
|
|
126
|
+
- name: "my-servers"
|
|
127
|
+
type: static
|
|
128
|
+
hosts:
|
|
129
|
+
- {name: "web-01", ip: "192.168.1.10", tags: ["web"]}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### NetBox
|
|
133
|
+
```yaml
|
|
134
|
+
sot:
|
|
135
|
+
import:
|
|
136
|
+
- name: "prod"
|
|
137
|
+
type: netbox
|
|
138
|
+
url: "https://netbox.example.com/"
|
|
139
|
+
token: "your-api-token"
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Ansible
|
|
143
|
+
```yaml
|
|
144
|
+
sot:
|
|
145
|
+
import:
|
|
146
|
+
- name: "inventory"
|
|
147
|
+
type: ansible
|
|
148
|
+
inventory_paths: ["/path/to/inventory.yml"]
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Consul
|
|
152
|
+
```bash
|
|
153
|
+
pip install "sshplex[consul]"
|
|
154
|
+
```
|
|
155
|
+
```yaml
|
|
156
|
+
sot:
|
|
157
|
+
import:
|
|
158
|
+
- name: "dc1"
|
|
159
|
+
type: consul
|
|
160
|
+
config:
|
|
161
|
+
host: "consul.example.com"
|
|
162
|
+
token: "your-token"
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
## CLI Reference
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
sshplex # Launch TUI
|
|
169
|
+
sshplex --onboarding # Interactive setup wizard
|
|
170
|
+
sshplex --debug # Test provider connectivity
|
|
171
|
+
sshplex --show-config # Show config paths
|
|
172
|
+
sshplex --clear-cache # Clear host cache
|
|
173
|
+
sshplex --config /path/to.yml # Use custom config
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Documentation
|
|
177
|
+
|
|
178
|
+
| Guide | Description |
|
|
179
|
+
|-------|-------------|
|
|
180
|
+
| [Configuration](docs/configuration.md) | Full config reference with examples |
|
|
181
|
+
| [Backends](docs/backends.md) | Multiplexer backend options and setup |
|
|
182
|
+
| [Troubleshooting](docs/troubleshooting.md) | Common issues and solutions |
|
|
183
|
+
|
|
184
|
+
## Installation Options
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
# Basic (tmux only)
|
|
188
|
+
pip install sshplex
|
|
189
|
+
|
|
190
|
+
# With Consul support
|
|
191
|
+
pip install "sshplex[consul]"
|
|
192
|
+
|
|
193
|
+
# With iTerm2 native support (macOS)
|
|
194
|
+
pip install "sshplex[iterm2]"
|
|
195
|
+
|
|
196
|
+
# Development
|
|
197
|
+
pip install -e ".[dev]"
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## Development
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
git clone https://github.com/sabrimjd/sshplex.git
|
|
204
|
+
cd sshplex
|
|
205
|
+
pip install -e ".[dev]"
|
|
206
|
+
|
|
207
|
+
# Run tests
|
|
208
|
+
pytest tests/ -v
|
|
209
|
+
|
|
210
|
+
# Quality checks
|
|
211
|
+
ruff check sshplex tests
|
|
212
|
+
mypy sshplex
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## License
|
|
216
|
+
|
|
217
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
218
|
+
|
|
219
|
+
## Author
|
|
220
|
+
|
|
221
|
+
**Sabrimjd** - [@sabrimjd](https://github.com/sabrimjd)
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
**SSHplex** - Because managing multiple SSH connections should be simple.
|
sshplex-1.6.0/README.md
ADDED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
**Multiplex your SSH connections with style**
|
|
4
|
+
|
|
5
|
+
SSHplex is a Python-based SSH connection multiplexer with a modern TUI. Connect to multiple hosts simultaneously using tmux or iTerm2, with sources from NetBox, Ansible, Consul, or static lists.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- 🖥️ **Modern TUI** - Textual-based host selector with search, sort, and multi-select
|
|
10
|
+
- 🔌 **Multiple Sources** - NetBox, Ansible, Consul, static lists - use them together
|
|
11
|
+
- 📦 **3 Backends** - tmux standalone, tmux + iTerm2, or iTerm2 native (macOS)
|
|
12
|
+
- ✏️ **Config Editor** - Built-in YAML editor with validation (`e` key)
|
|
13
|
+
- 🔄 **Broadcast Input** - Sync commands across multiple SSH sessions
|
|
14
|
+
- 🔐 **SSH Security** - Configurable host key checking and retry logic
|
|
15
|
+
- 🚀 **Fast Startup** - Intelligent caching with configurable TTL
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Install
|
|
21
|
+
pip install sshplex
|
|
22
|
+
|
|
23
|
+
# First-time setup (interactive wizard)
|
|
24
|
+
sshplex --onboarding
|
|
25
|
+
|
|
26
|
+
# Launch TUI
|
|
27
|
+
sshplex
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Prerequisites
|
|
31
|
+
|
|
32
|
+
- Python 3.8+
|
|
33
|
+
- tmux (Linux/macOS) or iTerm2 (macOS)
|
|
34
|
+
- SSH key configured for target hosts
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
| Key | Action |
|
|
39
|
+
|-----|--------|
|
|
40
|
+
| `Space` | Toggle host selection |
|
|
41
|
+
| `a` / `d` | Select / Deselect all |
|
|
42
|
+
| `Enter` | Connect to selected hosts |
|
|
43
|
+
| `/` | Search/filter hosts |
|
|
44
|
+
| `p` | Toggle panes/tabs mode |
|
|
45
|
+
| `b` | Toggle broadcast mode |
|
|
46
|
+
| `e` | Open config editor |
|
|
47
|
+
| `s` | Open session manager |
|
|
48
|
+
| `h` | Show keyboard shortcuts |
|
|
49
|
+
| `q` | Quit |
|
|
50
|
+
|
|
51
|
+
## Multiplexer Backends
|
|
52
|
+
|
|
53
|
+
| Backend | Platform | Best For |
|
|
54
|
+
|---------|----------|----------|
|
|
55
|
+
| **tmux** | Linux, macOS | Maximum compatibility, persistence |
|
|
56
|
+
| **tmux + iTerm2** | macOS | Native UI + persistence |
|
|
57
|
+
| **iTerm2 native** | macOS | Simple setup, no tmux dependency |
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
# ~/.config/sshplex/sshplex.yaml
|
|
61
|
+
tmux:
|
|
62
|
+
backend: "tmux" # or "iterm2-native" on macOS
|
|
63
|
+
layout: "tiled"
|
|
64
|
+
max_panes_per_window: 5
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Sources of Truth
|
|
68
|
+
|
|
69
|
+
### Static Hosts
|
|
70
|
+
```yaml
|
|
71
|
+
sot:
|
|
72
|
+
import:
|
|
73
|
+
- name: "my-servers"
|
|
74
|
+
type: static
|
|
75
|
+
hosts:
|
|
76
|
+
- {name: "web-01", ip: "192.168.1.10", tags: ["web"]}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### NetBox
|
|
80
|
+
```yaml
|
|
81
|
+
sot:
|
|
82
|
+
import:
|
|
83
|
+
- name: "prod"
|
|
84
|
+
type: netbox
|
|
85
|
+
url: "https://netbox.example.com/"
|
|
86
|
+
token: "your-api-token"
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### Ansible
|
|
90
|
+
```yaml
|
|
91
|
+
sot:
|
|
92
|
+
import:
|
|
93
|
+
- name: "inventory"
|
|
94
|
+
type: ansible
|
|
95
|
+
inventory_paths: ["/path/to/inventory.yml"]
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Consul
|
|
99
|
+
```bash
|
|
100
|
+
pip install "sshplex[consul]"
|
|
101
|
+
```
|
|
102
|
+
```yaml
|
|
103
|
+
sot:
|
|
104
|
+
import:
|
|
105
|
+
- name: "dc1"
|
|
106
|
+
type: consul
|
|
107
|
+
config:
|
|
108
|
+
host: "consul.example.com"
|
|
109
|
+
token: "your-token"
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## CLI Reference
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
sshplex # Launch TUI
|
|
116
|
+
sshplex --onboarding # Interactive setup wizard
|
|
117
|
+
sshplex --debug # Test provider connectivity
|
|
118
|
+
sshplex --show-config # Show config paths
|
|
119
|
+
sshplex --clear-cache # Clear host cache
|
|
120
|
+
sshplex --config /path/to.yml # Use custom config
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Documentation
|
|
124
|
+
|
|
125
|
+
| Guide | Description |
|
|
126
|
+
|-------|-------------|
|
|
127
|
+
| [Configuration](docs/configuration.md) | Full config reference with examples |
|
|
128
|
+
| [Backends](docs/backends.md) | Multiplexer backend options and setup |
|
|
129
|
+
| [Troubleshooting](docs/troubleshooting.md) | Common issues and solutions |
|
|
130
|
+
|
|
131
|
+
## Installation Options
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
# Basic (tmux only)
|
|
135
|
+
pip install sshplex
|
|
136
|
+
|
|
137
|
+
# With Consul support
|
|
138
|
+
pip install "sshplex[consul]"
|
|
139
|
+
|
|
140
|
+
# With iTerm2 native support (macOS)
|
|
141
|
+
pip install "sshplex[iterm2]"
|
|
142
|
+
|
|
143
|
+
# Development
|
|
144
|
+
pip install -e ".[dev]"
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Development
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
git clone https://github.com/sabrimjd/sshplex.git
|
|
151
|
+
cd sshplex
|
|
152
|
+
pip install -e ".[dev]"
|
|
153
|
+
|
|
154
|
+
# Run tests
|
|
155
|
+
pytest tests/ -v
|
|
156
|
+
|
|
157
|
+
# Quality checks
|
|
158
|
+
ruff check sshplex tests
|
|
159
|
+
mypy sshplex
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
165
|
+
|
|
166
|
+
## Author
|
|
167
|
+
|
|
168
|
+
**Sabrimjd** - [@sabrimjd](https://github.com/sabrimjd)
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
**SSHplex** - Because managing multiple SSH connections should be simple.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "sshplex"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.6.0"
|
|
8
8
|
description = "Multiplex your SSH connections with style"
|
|
9
9
|
authors = [{name = "MJAHED Sabri", email = "contact@sabrimjahed.com"}]
|
|
10
10
|
readme = "README.md"
|
|
@@ -44,6 +44,9 @@ dependencies = [
|
|
|
44
44
|
consul = [
|
|
45
45
|
"python-consul2>=0.1.5",
|
|
46
46
|
]
|
|
47
|
+
iterm2 = [
|
|
48
|
+
"iterm2>=2.0.0",
|
|
49
|
+
]
|
|
47
50
|
dev = [
|
|
48
51
|
"pytest>=7.0.0",
|
|
49
52
|
"pytest-cov>=4.0.0",
|
|
@@ -95,11 +95,18 @@ ssh:
|
|
|
95
95
|
key_path: "~/.ssh/id_rsa"
|
|
96
96
|
|
|
97
97
|
tmux:
|
|
98
|
+
backend: "tmux" # tmux, iterm2-native
|
|
99
|
+
iterm2_native_target: "current-window" # current-window, new-window (iterm2-native only)
|
|
100
|
+
iterm2_native_hide_from_history: true # prefix with leading space when dispatching (iterm2-native)
|
|
101
|
+
use_panes: true # true = panes, false = tabs
|
|
98
102
|
layout: "tiled" # tiled, even-horizontal, even-vertical
|
|
99
103
|
broadcast: false # Start with broadcast off
|
|
100
104
|
window_name: "sshplex"
|
|
101
105
|
max_panes_per_window: 5 # Maximum panes per window before creating a new window
|
|
102
|
-
|
|
106
|
+
# iTerm2 integration (macOS only)
|
|
107
|
+
control_with_iterm2: false # Use iTerm2 tmux -CC mode (macOS only)
|
|
108
|
+
iterm2_attach_target: "new-window" # Where to open tmux session: new-window, new-tab
|
|
109
|
+
iterm2_profile: "Default" # iTerm2 profile name to use
|
|
103
110
|
|
|
104
111
|
ui:
|
|
105
112
|
show_log_panel: false
|
|
@@ -69,12 +69,80 @@ class SSHConfig(BaseModel):
|
|
|
69
69
|
proxy: List[Proxy] = Field(alias='proxy', default_factory=list, description="List of proxies")
|
|
70
70
|
|
|
71
71
|
class TmuxConfig(BaseModel):
|
|
72
|
-
"""tmux configuration.
|
|
72
|
+
"""tmux/iTerm2 multiplexer configuration.
|
|
73
|
+
|
|
74
|
+
Three backend options:
|
|
75
|
+
1. tmux standalone: backend="tmux", control_with_iterm2=false
|
|
76
|
+
2. tmux + iTerm2: backend="tmux", control_with_iterm2=true (macOS only)
|
|
77
|
+
3. iTerm2 native: backend="iterm2-native" (macOS only)
|
|
78
|
+
"""
|
|
79
|
+
# Backend selection
|
|
80
|
+
backend: str = Field(
|
|
81
|
+
default="tmux",
|
|
82
|
+
description="Multiplexer backend: 'tmux' or 'iterm2-native'"
|
|
83
|
+
)
|
|
84
|
+
# Common options
|
|
85
|
+
use_panes: bool = Field(default=True, description="Connection mode: true=panes, false=tabs")
|
|
73
86
|
layout: str = "tiled" # tiled, even-horizontal, even-vertical
|
|
74
87
|
broadcast: bool = False # Start with broadcast off
|
|
75
88
|
window_name: str = "sshplex"
|
|
76
89
|
max_panes_per_window: int = Field(default=5, description="Maximum panes per window before creating a new window")
|
|
77
|
-
|
|
90
|
+
# iTerm2 + tmux integration (macOS only, for backend="tmux")
|
|
91
|
+
control_with_iterm2: bool = Field(default=False, description="Use iTerm2 tmux -CC mode (macOS only)")
|
|
92
|
+
iterm2_attach_target: str = Field(
|
|
93
|
+
default="new-window",
|
|
94
|
+
description="Where to open tmux session in iTerm2: new-window or new-tab"
|
|
95
|
+
)
|
|
96
|
+
# iTerm2 native specific (macOS only, for backend="iterm2-native")
|
|
97
|
+
iterm2_profile: str = Field(default="Default", description="iTerm2 profile to use for new windows/tabs")
|
|
98
|
+
iterm2_native_target: str = Field(
|
|
99
|
+
default="current-window",
|
|
100
|
+
description="Where to open iTerm2 native sessions: current-window or new-window"
|
|
101
|
+
)
|
|
102
|
+
iterm2_native_hide_from_history: bool = Field(
|
|
103
|
+
default=True,
|
|
104
|
+
description="Prefix native iTerm2 dispatched commands with a leading space"
|
|
105
|
+
)
|
|
106
|
+
iterm2_split_pattern: str = Field(
|
|
107
|
+
default="alternate",
|
|
108
|
+
description="Split pattern for iTerm2 native: alternate, vertical, horizontal"
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
def validate_backend_config(self) -> bool:
|
|
112
|
+
"""Validate backend configuration.
|
|
113
|
+
|
|
114
|
+
Returns:
|
|
115
|
+
True if config is valid, raises ValueError otherwise
|
|
116
|
+
"""
|
|
117
|
+
import platform
|
|
118
|
+
|
|
119
|
+
# Validate backend option
|
|
120
|
+
valid_backends = ["tmux", "iterm2-native"]
|
|
121
|
+
if self.backend not in valid_backends:
|
|
122
|
+
raise ValueError(
|
|
123
|
+
f"Invalid backend: {self.backend}. Must be one of: {valid_backends}"
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
# Validate iTerm2 native mode on macOS only
|
|
127
|
+
if self.backend == "iterm2-native" and platform.system().lower() != "darwin":
|
|
128
|
+
raise ValueError(
|
|
129
|
+
"backend: 'iterm2-native' is only supported on macOS. "
|
|
130
|
+
"Use backend: 'tmux' on Linux/other systems."
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
if self.iterm2_native_target not in ["current-window", "new-window"]:
|
|
134
|
+
raise ValueError(
|
|
135
|
+
"tmux.iterm2_native_target must be one of: ['current-window', 'new-window']"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# Validate control_with_iterm2 on macOS only
|
|
139
|
+
if self.control_with_iterm2 and platform.system().lower() != "darwin":
|
|
140
|
+
raise ValueError(
|
|
141
|
+
"tmux.control_with_iterm2 is only supported on macOS. "
|
|
142
|
+
"Set this to false on Linux/other systems."
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
return True
|
|
78
146
|
|
|
79
147
|
|
|
80
148
|
class AnsibleConfig(BaseModel):
|
|
@@ -88,7 +156,7 @@ class ConsulConfig(BaseModel):
|
|
|
88
156
|
port: int = Field(443, description="Consul port number")
|
|
89
157
|
token: str = Field("default_token", description="Consul token for authentication")
|
|
90
158
|
scheme: str = Field("https", description="URL scheme (e.g., 'https')")
|
|
91
|
-
verify: bool = Field(
|
|
159
|
+
verify: bool = Field(True, description="Whether to verify SSL certificates (default: True for security)")
|
|
92
160
|
dc: str = Field("dc1", description="Datacenter name")
|
|
93
161
|
cert: str = Field("", description="Path to SSL certificate")
|
|
94
162
|
|