sshplex 1.1.0__tar.gz → 1.3.1__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.
Files changed (47) hide show
  1. sshplex-1.3.1/PKG-INFO +413 -0
  2. sshplex-1.3.1/README.md +362 -0
  3. {sshplex-1.1.0 → sshplex-1.3.1}/pyproject.toml +36 -7
  4. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/__init__.py +1 -1
  5. sshplex-1.3.1/sshplex/cli.py +243 -0
  6. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/config-template.yaml +10 -0
  7. sshplex-1.3.1/sshplex/lib/cache.py +240 -0
  8. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/config.py +38 -14
  9. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/logger.py +1 -1
  10. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/multiplexer/base.py +1 -1
  11. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/multiplexer/tmux.py +172 -36
  12. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/sot/ansible.py +8 -4
  13. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/sot/base.py +1 -1
  14. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/sot/consul.py +4 -3
  15. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/sot/factory.py +143 -53
  16. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/sot/netbox.py +6 -2
  17. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/sot/static.py +3 -2
  18. sshplex-1.3.1/sshplex/lib/ui/config_editor.py +771 -0
  19. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/ui/host_selector.py +173 -45
  20. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/ui/session_manager.py +124 -25
  21. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/main.py +96 -16
  22. sshplex-1.3.1/sshplex/sshplex_connector.py +252 -0
  23. sshplex-1.3.1/sshplex.egg-info/PKG-INFO +413 -0
  24. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex.egg-info/SOURCES.txt +2 -3
  25. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex.egg-info/requires.txt +8 -6
  26. sshplex-1.3.1/tests/test_cache.py +240 -0
  27. sshplex-1.3.1/tests/test_config.py +285 -0
  28. sshplex-1.1.0/PKG-INFO +0 -607
  29. sshplex-1.1.0/README.md +0 -558
  30. sshplex-1.1.0/sshplex/cli.py +0 -110
  31. sshplex-1.1.0/sshplex/lib/cache.py +0 -189
  32. sshplex-1.1.0/sshplex/lib/ssh/__init__.py +0 -1
  33. sshplex-1.1.0/sshplex/lib/ssh/connection.py +0 -1
  34. sshplex-1.1.0/sshplex/lib/ssh/manager.py +0 -1
  35. sshplex-1.1.0/sshplex/sshplex_connector.py +0 -148
  36. sshplex-1.1.0/sshplex.egg-info/PKG-INFO +0 -607
  37. sshplex-1.1.0/tests/test_config.py +0 -1
  38. {sshplex-1.1.0 → sshplex-1.3.1}/LICENSE +0 -0
  39. {sshplex-1.1.0 → sshplex-1.3.1}/MANIFEST.in +0 -0
  40. {sshplex-1.1.0 → sshplex-1.3.1}/setup.cfg +0 -0
  41. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/__init__.py +0 -0
  42. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/multiplexer/__init__.py +0 -0
  43. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/sot/__init__.py +0 -0
  44. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex/lib/ui/__init__.py +0 -0
  45. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex.egg-info/dependency_links.txt +0 -0
  46. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex.egg-info/entry_points.txt +0 -0
  47. {sshplex-1.1.0 → sshplex-1.3.1}/sshplex.egg-info/top_level.txt +0 -0
sshplex-1.3.1/PKG-INFO ADDED
@@ -0,0 +1,413 @@
1
+ Metadata-Version: 2.4
2
+ Name: sshplex
3
+ Version: 1.3.1
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: dev
42
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
43
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
44
+ Requires-Dist: black>=22.0.0; extra == "dev"
45
+ Requires-Dist: flake8>=5.0.0; extra == "dev"
46
+ Requires-Dist: mypy>=1.0.0; extra == "dev"
47
+ Requires-Dist: ruff>=0.8.0; extra == "dev"
48
+ Requires-Dist: vulture>=2.11; extra == "dev"
49
+ Requires-Dist: types-PyYAML>=6.0.0; extra == "dev"
50
+ Dynamic: license-file
51
+
52
+ ![SSHPlex Demo](demo/demo.gif)
53
+
54
+ **Multiplex your SSH connections with style**
55
+
56
+ SSHplex is a Python-based SSH connection multiplexer that provides a modern Terminal User Interface (TUI) for selecting and connecting to multiple hosts simultaneously using tmux. It integrates with multiple Sources of Truth (NetBox, Ansible, Consul, static lists) and creates organized tmux sessions for efficient multi-host management.
57
+
58
+ ## Features
59
+
60
+ - **Interactive TUI**: Modern host selector built with Textual - search, sort, select, connect
61
+ - **Multiple Sources of Truth**: NetBox, Ansible inventories, HashiCorp Consul, and static host lists - use them together or separately
62
+ - **Multi-Provider Support**: Configure multiple instances of the same provider type (e.g., multiple NetBox instances, multiple Consul datacenters)
63
+ - **tmux Integration**: Creates organized sessions with panes or windows for each host
64
+ - **iTerm2 Integration**: Native tmux `-CC` mode on macOS for iTerm2 tabs/splits, with improved detection and fallback guidance
65
+ - **Proxy Support**: Per-provider SSH proxy/jump host configuration
66
+ - **Wildcard Search**: Filter hosts across all columns with glob patterns
67
+ - **Config Editor**: Edit `sshplex.yaml` directly from the TUI (`e`) with tabbed form and validation
68
+ - **Built-in Help**: Keyboard shortcuts help modal (`h`) with live mode/state hints
69
+ - **Sortable Columns**: Click column headers to sort the host table
70
+ - **Copy to Clipboard**: Copy the host table to clipboard for sharing
71
+ - **Intelligent Caching**: Local host caching for fast startup (configurable TTL)
72
+ - **Broadcasting**: Sync input across multiple SSH connections
73
+ - **Session Manager**: Browse, connect to, or kill existing tmux sessions from the TUI
74
+ - **SSH Security**: Configurable host key checking with secure defaults
75
+ - **Connection Retry**: Automatic retry with exponential backoff for reliability
76
+ - **Enhanced CLI**: Debug mode, cache management, and configuration utilities
77
+
78
+ ## Prerequisites
79
+
80
+ - **Python 3.8+**
81
+ - **tmux**
82
+ - **SSH key** configured for target hosts
83
+ - **macOS or Linux** (Windows via WSL)
84
+
85
+ ```bash
86
+ # macOS
87
+ brew install tmux python3
88
+
89
+ # Ubuntu/Debian
90
+ sudo apt install tmux python3 python3-pip
91
+
92
+ # RHEL/CentOS/Fedora
93
+ sudo dnf install tmux python3 python3-pip
94
+ ```
95
+
96
+ ## Installation
97
+
98
+ ### From PyPI
99
+
100
+ ```bash
101
+ pip install sshplex
102
+
103
+ # With Consul support
104
+ pip install "sshplex[consul]"
105
+ ```
106
+
107
+ ### From Source
108
+
109
+ ```bash
110
+ git clone https://github.com/sabrimjd/sshplex.git
111
+ cd sshplex
112
+ pip install -e .
113
+
114
+ # With Consul support
115
+ pip install -e ".[consul]"
116
+
117
+ # With dev dependencies
118
+ pip install -e ".[dev]"
119
+ ```
120
+
121
+ ## Quick Start
122
+
123
+ ```bash
124
+ # Launch TUI (creates default config on first run)
125
+ sshplex
126
+
127
+ # Debug mode - test provider connectivity
128
+ sshplex --debug
129
+
130
+ # Show configuration paths
131
+ sshplex --show-config
132
+
133
+ # Clear host cache
134
+ sshplex --clear-cache
135
+ ```
136
+
137
+ On first run, SSHplex creates a config at `~/.config/sshplex/sshplex.yaml`. Edit it with your provider details, then run `sshplex` again.
138
+
139
+ ## What's New (Quality Upgrade)
140
+
141
+ Recent quality and UX improvements include:
142
+
143
+ - Stronger config/runtime error handling and input validation
144
+ - iTerm2 integration reliability improvements (installation/running detection + better fallback messaging)
145
+ - Parallel provider fetching support for faster multi-provider discovery
146
+ - Faster cache validity checks before deep metadata parsing
147
+ - TUI polish: config editor (`e`), help modal (`h`), and improved visual selection cues
148
+
149
+ See [CHANGELOG.md](CHANGELOG.md) for full details.
150
+
151
+ ## Usage
152
+
153
+ 1. **Start**: Run `sshplex`
154
+ 2. **Browse**: Hosts from all configured providers appear in the table
155
+ 3. **Search**: Press `/` to filter hosts (supports wildcards)
156
+ 4. **Select**: `Space` to toggle, `a` to select all, `d` to deselect all
157
+ 5. **Configure**: `p` to toggle panes/tabs, `b` to toggle broadcast
158
+ 6. **Edit Config**: `e` to open the built-in configuration editor
159
+ 7. **Connect**: `Enter` to create tmux session and connect
160
+ 8. **Sessions**: `s` to manage existing tmux sessions
161
+ 9. **Copy**: `c` to copy the host table to clipboard
162
+ 10. **Refresh**: `r` to refresh hosts from providers (bypasses cache)
163
+
164
+ ### TUI Keybindings
165
+
166
+ | Key | Action |
167
+ |-----|--------|
168
+ | `Space` | Toggle host selection |
169
+ | `a` | Select all hosts |
170
+ | `d` | Deselect all hosts |
171
+ | `Enter` | Connect to selected hosts |
172
+ | `/` | Search/filter hosts |
173
+ | `p` | Toggle panes/tabs mode |
174
+ | `b` | Toggle broadcast mode |
175
+ | `s` | Open session manager |
176
+ | `e` | Open configuration editor |
177
+ | `h` | Open keyboard shortcuts help |
178
+ | `c` | Copy table to clipboard |
179
+ | `r` | Refresh from providers |
180
+ | `Escape` | Focus table / clear search |
181
+ | `q` | Quit |
182
+
183
+ ### tmux Commands (once attached)
184
+
185
+ ```bash
186
+ Ctrl+b + Arrow Keys # Switch between panes
187
+ Ctrl+b + n/p # Next/Previous window
188
+ Ctrl+b + b # Toggle broadcast (custom SSHplex binding)
189
+ Ctrl+b + d # Detach from session
190
+ Ctrl+b + z # Zoom/unzoom current pane
191
+ ```
192
+
193
+ ## CLI Reference
194
+
195
+ ```bash
196
+ sshplex # Launch TUI
197
+ sshplex --debug # Test provider connectivity
198
+ sshplex --clear-cache # Clear host cache
199
+ sshplex --show-config # Show configuration paths
200
+ sshplex --config /path/to.yml # Use custom config file
201
+ sshplex --verbose # Enable verbose logging
202
+ sshplex --version # Show version
203
+ ```
204
+
205
+ ## Configuration
206
+
207
+ Configuration is stored at `~/.config/sshplex/sshplex.yaml`. See [config-template.yaml](sshplex/config-template.yaml) for a full example.
208
+
209
+ ### Static Hosts
210
+
211
+ ```yaml
212
+ sot:
213
+ import:
214
+ - name: "my-servers"
215
+ type: static
216
+ hosts:
217
+ - name: "web-01"
218
+ ip: "192.168.1.10"
219
+ description: "Web server"
220
+ tags: ["web", "production"]
221
+ - name: "db-01"
222
+ ip: "192.168.1.20"
223
+ description: "Database server"
224
+ tags: ["database", "production"]
225
+ ```
226
+
227
+ ### NetBox
228
+
229
+ ```yaml
230
+ sot:
231
+ import:
232
+ - name: "prod-netbox"
233
+ type: netbox
234
+ url: "https://netbox.example.com/"
235
+ token: "your-api-token"
236
+ verify_ssl: true
237
+ timeout: 30
238
+ default_filters:
239
+ status: "active"
240
+ role: "virtual-machine"
241
+ has_primary_ip: "true"
242
+ ```
243
+
244
+ ### Ansible Inventory
245
+
246
+ ```yaml
247
+ sot:
248
+ import:
249
+ - name: "production-hosts"
250
+ type: ansible
251
+ inventory_paths:
252
+ - "/path/to/inventory.yml"
253
+ default_filters:
254
+ groups: ["webservers", "databases"]
255
+ exclude_groups: ["maintenance"]
256
+ host_patterns: ["^prod-.*"]
257
+ ```
258
+
259
+ ### Consul
260
+
261
+ Requires `pip install "sshplex[consul]"`.
262
+
263
+ ```yaml
264
+ sot:
265
+ import:
266
+ - name: "consul-dc1"
267
+ type: consul
268
+ config:
269
+ host: "consul.example.com"
270
+ port: 443
271
+ token: "your-consul-token"
272
+ scheme: "https"
273
+ verify: false
274
+ dc: "dc1"
275
+ cert: "" # Optional SSL cert path
276
+ ```
277
+
278
+ ### SSH Proxy / Jump Host
279
+
280
+ Configure per-provider proxy routing:
281
+
282
+ ```yaml
283
+ ssh:
284
+ username: "admin"
285
+ key_path: "~/.ssh/id_ed25519"
286
+ port: 22
287
+ proxy:
288
+ - name: "prod-proxy"
289
+ imports: ["consul-dc1", "prod-netbox"] # Which providers use this proxy
290
+ host: "jumphost.example.com"
291
+ username: "admin"
292
+ key_path: "~/.ssh/jump_key"
293
+ ```
294
+
295
+ ### SSH Security Options
296
+
297
+ Configure SSH host key checking and retry behavior:
298
+
299
+ ```yaml
300
+ ssh:
301
+ username: "admin"
302
+ key_path: "~/.ssh/id_ed25519"
303
+ # Security options
304
+ strict_host_key_checking: false # Options: true (strict), false (accept-new)
305
+ user_known_hosts_file: "" # Empty = default ~/.ssh/known_hosts
306
+ # Connection retry
307
+ retry:
308
+ enabled: true
309
+ max_attempts: 3
310
+ delay_seconds: 2
311
+ exponential_backoff: true # Double delay on each retry
312
+ ```
313
+
314
+ **Security Note**: By default, SSHplex uses `StrictHostKeyChecking=accept-new` which automatically accepts new host keys but warns on key changes. For production environments, set `strict_host_key_checking: true` for maximum security.
315
+
316
+ ### iTerm2 Integration (macOS)
317
+
318
+ Enable native iTerm2 tmux integration with `-CC` mode:
319
+
320
+ ```yaml
321
+ tmux:
322
+ control_with_iterm2: true # Opens new iTerm2 window with native tabs/splits
323
+ ```
324
+
325
+ ### Cache
326
+
327
+ ```yaml
328
+ cache:
329
+ enabled: true
330
+ cache_dir: "~/.cache/sshplex"
331
+ ttl_hours: 24 # Refresh daily
332
+ ```
333
+
334
+ ### UI
335
+
336
+ ```yaml
337
+ ui:
338
+ show_log_panel: false
339
+ table_columns: ["name", "ip", "cluster", "role", "tags", "description", "provider"]
340
+ ```
341
+
342
+ ## Troubleshooting
343
+
344
+ ### Debug Mode
345
+
346
+ ```bash
347
+ sshplex --debug
348
+ ```
349
+
350
+ Tests provider connectivity and lists all discovered hosts.
351
+
352
+ ### Enable Logging
353
+
354
+ ```yaml
355
+ logging:
356
+ enabled: true
357
+ level: "DEBUG"
358
+ file: "logs/sshplex.log"
359
+ ```
360
+
361
+ ### Common Issues
362
+
363
+ | Issue | Solution |
364
+ |-------|----------|
365
+ | `tmux is not installed` | Install tmux: `brew install tmux` / `apt install tmux` |
366
+ | NetBox connection failed | Check URL, token, and network connectivity |
367
+ | Ansible inventory not loading | Verify file paths exist and YAML syntax is valid |
368
+ | No hosts found | Remove filters temporarily, check provider logs |
369
+ | Consul import error | Install with `pip install "sshplex[consul]"` |
370
+ | SSH key auth failed | Check key path and permissions (`chmod 600`) |
371
+
372
+ ## Development
373
+
374
+ ```bash
375
+ git clone https://github.com/sabrimjd/sshplex.git
376
+ cd sshplex
377
+ pip install -e ".[dev]"
378
+
379
+ # Run tests
380
+ python3 -m pytest tests/
381
+
382
+ # Lint & quality checks
383
+ ruff check sshplex tests
384
+ mypy sshplex
385
+ vulture sshplex tests --min-confidence 80
386
+
387
+ # Local Consul for testing
388
+ docker-compose -f docker-compose.consul.yml up -d
389
+ ```
390
+
391
+ ## Contributing
392
+
393
+ SSHplex welcomes contributions! The codebase follows the KISS principle.
394
+
395
+ ## License
396
+
397
+ MIT License - see [LICENSE](LICENSE) for details.
398
+
399
+ ## Author
400
+
401
+ **Sabrimjd** - [@sabrimjd](https://github.com/sabrimjd)
402
+
403
+ ## Acknowledgments
404
+
405
+ - [Textual](https://textual.textualize.io/) - Modern TUI framework
406
+ - [NetBox](https://netbox.dev/) - Infrastructure source of truth
407
+ - [HashiCorp Consul](https://www.consul.io/) - Service discovery
408
+ - [tmux](https://github.com/tmux/tmux) - Terminal multiplexing
409
+ - [loguru](https://github.com/Delgan/loguru) - Logging
410
+
411
+ ---
412
+
413
+ **SSHplex** - Because managing multiple SSH connections should be simple and elegant.