sshplex 1.1.0__tar.gz → 1.4.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.
Files changed (49) hide show
  1. sshplex-1.4.0/PKG-INFO +424 -0
  2. sshplex-1.4.0/README.md +373 -0
  3. {sshplex-1.1.0 → sshplex-1.4.0}/pyproject.toml +36 -7
  4. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/__init__.py +1 -1
  5. sshplex-1.4.0/sshplex/cli.py +243 -0
  6. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/config-template.yaml +10 -0
  7. sshplex-1.4.0/sshplex/lib/cache.py +240 -0
  8. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/config.py +38 -14
  9. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/logger.py +1 -1
  10. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/multiplexer/base.py +1 -1
  11. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/multiplexer/tmux.py +172 -36
  12. sshplex-1.4.0/sshplex/lib/onboarding/__init__.py +5 -0
  13. sshplex-1.4.0/sshplex/lib/onboarding/wizard.py +482 -0
  14. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/sot/ansible.py +8 -4
  15. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/sot/base.py +1 -1
  16. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/sot/consul.py +4 -3
  17. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/sot/factory.py +166 -55
  18. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/sot/netbox.py +6 -2
  19. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/sot/static.py +3 -2
  20. sshplex-1.4.0/sshplex/lib/ui/config_editor.py +771 -0
  21. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/ui/host_selector.py +173 -45
  22. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/ui/session_manager.py +124 -25
  23. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/main.py +119 -17
  24. sshplex-1.4.0/sshplex/sshplex_connector.py +252 -0
  25. sshplex-1.4.0/sshplex.egg-info/PKG-INFO +424 -0
  26. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex.egg-info/SOURCES.txt +4 -3
  27. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex.egg-info/requires.txt +8 -6
  28. sshplex-1.4.0/tests/test_cache.py +240 -0
  29. sshplex-1.4.0/tests/test_config.py +285 -0
  30. sshplex-1.1.0/PKG-INFO +0 -607
  31. sshplex-1.1.0/README.md +0 -558
  32. sshplex-1.1.0/sshplex/cli.py +0 -110
  33. sshplex-1.1.0/sshplex/lib/cache.py +0 -189
  34. sshplex-1.1.0/sshplex/lib/ssh/__init__.py +0 -1
  35. sshplex-1.1.0/sshplex/lib/ssh/connection.py +0 -1
  36. sshplex-1.1.0/sshplex/lib/ssh/manager.py +0 -1
  37. sshplex-1.1.0/sshplex/sshplex_connector.py +0 -148
  38. sshplex-1.1.0/sshplex.egg-info/PKG-INFO +0 -607
  39. sshplex-1.1.0/tests/test_config.py +0 -1
  40. {sshplex-1.1.0 → sshplex-1.4.0}/LICENSE +0 -0
  41. {sshplex-1.1.0 → sshplex-1.4.0}/MANIFEST.in +0 -0
  42. {sshplex-1.1.0 → sshplex-1.4.0}/setup.cfg +0 -0
  43. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/__init__.py +0 -0
  44. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/multiplexer/__init__.py +0 -0
  45. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/sot/__init__.py +0 -0
  46. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex/lib/ui/__init__.py +0 -0
  47. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex.egg-info/dependency_links.txt +0 -0
  48. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex.egg-info/entry_points.txt +0 -0
  49. {sshplex-1.1.0 → sshplex-1.4.0}/sshplex.egg-info/top_level.txt +0 -0
sshplex-1.4.0/PKG-INFO ADDED
@@ -0,0 +1,424 @@
1
+ Metadata-Version: 2.4
2
+ Name: sshplex
3
+ Version: 1.4.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: 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
+ # First-time setup - interactive onboarding wizard
125
+ sshplex --onboarding
126
+
127
+ # Launch TUI
128
+ sshplex
129
+
130
+ # Debug mode - test provider connectivity
131
+ sshplex --debug
132
+
133
+ # Show configuration paths
134
+ sshplex --show-config
135
+
136
+ # Clear host cache
137
+ sshplex --clear-cache
138
+ ```
139
+
140
+ ### First-Time Setup
141
+
142
+ Run `sshplex --onboarding` for an interactive setup wizard that will:
143
+ - Auto-detect your SSH keys and system dependencies
144
+ - Guide you through configuring inventory sources (NetBox, Ansible, Consul, or static hosts)
145
+ - Test connections before saving
146
+ - Generate a working configuration file
147
+
148
+ On first run without `--onboarding`, SSHplex creates a default config at `~/.config/sshplex/sshplex.yaml`. Edit it with your provider details, or use the built-in config editor (`e` key in TUI).
149
+
150
+ ## What's New (Quality Upgrade)
151
+
152
+ Recent quality and UX improvements include:
153
+
154
+ - Stronger config/runtime error handling and input validation
155
+ - iTerm2 integration reliability improvements (installation/running detection + better fallback messaging)
156
+ - Parallel provider fetching support for faster multi-provider discovery
157
+ - Faster cache validity checks before deep metadata parsing
158
+ - TUI polish: config editor (`e`), help modal (`h`), and improved visual selection cues
159
+
160
+ See [CHANGELOG.md](CHANGELOG.md) for full details.
161
+
162
+ ## Usage
163
+
164
+ 1. **Start**: Run `sshplex`
165
+ 2. **Browse**: Hosts from all configured providers appear in the table
166
+ 3. **Search**: Press `/` to filter hosts (supports wildcards)
167
+ 4. **Select**: `Space` to toggle, `a` to select all, `d` to deselect all
168
+ 5. **Configure**: `p` to toggle panes/tabs, `b` to toggle broadcast
169
+ 6. **Edit Config**: `e` to open the built-in configuration editor
170
+ 7. **Connect**: `Enter` to create tmux session and connect
171
+ 8. **Sessions**: `s` to manage existing tmux sessions
172
+ 9. **Copy**: `c` to copy the host table to clipboard
173
+ 10. **Refresh**: `r` to refresh hosts from providers (bypasses cache)
174
+
175
+ ### TUI Keybindings
176
+
177
+ | Key | Action |
178
+ |-----|--------|
179
+ | `Space` | Toggle host selection |
180
+ | `a` | Select all hosts |
181
+ | `d` | Deselect all hosts |
182
+ | `Enter` | Connect to selected hosts |
183
+ | `/` | Search/filter hosts |
184
+ | `p` | Toggle panes/tabs mode |
185
+ | `b` | Toggle broadcast mode |
186
+ | `s` | Open session manager |
187
+ | `e` | Open configuration editor |
188
+ | `h` | Open keyboard shortcuts help |
189
+ | `c` | Copy table to clipboard |
190
+ | `r` | Refresh from providers |
191
+ | `Escape` | Focus table / clear search |
192
+ | `q` | Quit |
193
+
194
+ ### tmux Commands (once attached)
195
+
196
+ ```bash
197
+ Ctrl+b + Arrow Keys # Switch between panes
198
+ Ctrl+b + n/p # Next/Previous window
199
+ Ctrl+b + b # Toggle broadcast (custom SSHplex binding)
200
+ Ctrl+b + d # Detach from session
201
+ Ctrl+b + z # Zoom/unzoom current pane
202
+ ```
203
+
204
+ ## CLI Reference
205
+
206
+ ```bash
207
+ sshplex # Launch TUI
208
+ sshplex --debug # Test provider connectivity
209
+ sshplex --clear-cache # Clear host cache
210
+ sshplex --show-config # Show configuration paths
211
+ sshplex --config /path/to.yml # Use custom config file
212
+ sshplex --verbose # Enable verbose logging
213
+ sshplex --version # Show version
214
+ ```
215
+
216
+ ## Configuration
217
+
218
+ Configuration is stored at `~/.config/sshplex/sshplex.yaml`. See [config-template.yaml](sshplex/config-template.yaml) for a full example.
219
+
220
+ ### Static Hosts
221
+
222
+ ```yaml
223
+ sot:
224
+ import:
225
+ - name: "my-servers"
226
+ type: static
227
+ hosts:
228
+ - name: "web-01"
229
+ ip: "192.168.1.10"
230
+ description: "Web server"
231
+ tags: ["web", "production"]
232
+ - name: "db-01"
233
+ ip: "192.168.1.20"
234
+ description: "Database server"
235
+ tags: ["database", "production"]
236
+ ```
237
+
238
+ ### NetBox
239
+
240
+ ```yaml
241
+ sot:
242
+ import:
243
+ - name: "prod-netbox"
244
+ type: netbox
245
+ url: "https://netbox.example.com/"
246
+ token: "your-api-token"
247
+ verify_ssl: true
248
+ timeout: 30
249
+ default_filters:
250
+ status: "active"
251
+ role: "virtual-machine"
252
+ has_primary_ip: "true"
253
+ ```
254
+
255
+ ### Ansible Inventory
256
+
257
+ ```yaml
258
+ sot:
259
+ import:
260
+ - name: "production-hosts"
261
+ type: ansible
262
+ inventory_paths:
263
+ - "/path/to/inventory.yml"
264
+ default_filters:
265
+ groups: ["webservers", "databases"]
266
+ exclude_groups: ["maintenance"]
267
+ host_patterns: ["^prod-.*"]
268
+ ```
269
+
270
+ ### Consul
271
+
272
+ Requires `pip install "sshplex[consul]"`.
273
+
274
+ ```yaml
275
+ sot:
276
+ import:
277
+ - name: "consul-dc1"
278
+ type: consul
279
+ config:
280
+ host: "consul.example.com"
281
+ port: 443
282
+ token: "your-consul-token"
283
+ scheme: "https"
284
+ verify: false
285
+ dc: "dc1"
286
+ cert: "" # Optional SSL cert path
287
+ ```
288
+
289
+ ### SSH Proxy / Jump Host
290
+
291
+ Configure per-provider proxy routing:
292
+
293
+ ```yaml
294
+ ssh:
295
+ username: "admin"
296
+ key_path: "~/.ssh/id_ed25519"
297
+ port: 22
298
+ proxy:
299
+ - name: "prod-proxy"
300
+ imports: ["consul-dc1", "prod-netbox"] # Which providers use this proxy
301
+ host: "jumphost.example.com"
302
+ username: "admin"
303
+ key_path: "~/.ssh/jump_key"
304
+ ```
305
+
306
+ ### SSH Security Options
307
+
308
+ Configure SSH host key checking and retry behavior:
309
+
310
+ ```yaml
311
+ ssh:
312
+ username: "admin"
313
+ key_path: "~/.ssh/id_ed25519"
314
+ # Security options
315
+ strict_host_key_checking: false # Options: true (strict), false (accept-new)
316
+ user_known_hosts_file: "" # Empty = default ~/.ssh/known_hosts
317
+ # Connection retry
318
+ retry:
319
+ enabled: true
320
+ max_attempts: 3
321
+ delay_seconds: 2
322
+ exponential_backoff: true # Double delay on each retry
323
+ ```
324
+
325
+ **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.
326
+
327
+ ### iTerm2 Integration (macOS)
328
+
329
+ Enable native iTerm2 tmux integration with `-CC` mode:
330
+
331
+ ```yaml
332
+ tmux:
333
+ control_with_iterm2: true # Opens new iTerm2 window with native tabs/splits
334
+ ```
335
+
336
+ ### Cache
337
+
338
+ ```yaml
339
+ cache:
340
+ enabled: true
341
+ cache_dir: "~/.cache/sshplex"
342
+ ttl_hours: 24 # Refresh daily
343
+ ```
344
+
345
+ ### UI
346
+
347
+ ```yaml
348
+ ui:
349
+ show_log_panel: false
350
+ table_columns: ["name", "ip", "cluster", "role", "tags", "description", "provider"]
351
+ ```
352
+
353
+ ## Troubleshooting
354
+
355
+ ### Debug Mode
356
+
357
+ ```bash
358
+ sshplex --debug
359
+ ```
360
+
361
+ Tests provider connectivity and lists all discovered hosts.
362
+
363
+ ### Enable Logging
364
+
365
+ ```yaml
366
+ logging:
367
+ enabled: true
368
+ level: "DEBUG"
369
+ file: "logs/sshplex.log"
370
+ ```
371
+
372
+ ### Common Issues
373
+
374
+ | Issue | Solution |
375
+ |-------|----------|
376
+ | `tmux is not installed` | Install tmux: `brew install tmux` / `apt install tmux` |
377
+ | NetBox connection failed | Check URL, token, and network connectivity |
378
+ | Ansible inventory not loading | Verify file paths exist and YAML syntax is valid |
379
+ | No hosts found | Remove filters temporarily, check provider logs |
380
+ | Consul import error | Install with `pip install "sshplex[consul]"` |
381
+ | SSH key auth failed | Check key path and permissions (`chmod 600`) |
382
+
383
+ ## Development
384
+
385
+ ```bash
386
+ git clone https://github.com/sabrimjd/sshplex.git
387
+ cd sshplex
388
+ pip install -e ".[dev]"
389
+
390
+ # Run tests
391
+ python3 -m pytest tests/
392
+
393
+ # Lint & quality checks
394
+ ruff check sshplex tests
395
+ mypy sshplex
396
+ vulture sshplex tests --min-confidence 80
397
+
398
+ # Local Consul for testing
399
+ docker-compose -f docker-compose.consul.yml up -d
400
+ ```
401
+
402
+ ## Contributing
403
+
404
+ SSHplex welcomes contributions! The codebase follows the KISS principle.
405
+
406
+ ## License
407
+
408
+ MIT License - see [LICENSE](LICENSE) for details.
409
+
410
+ ## Author
411
+
412
+ **Sabrimjd** - [@sabrimjd](https://github.com/sabrimjd)
413
+
414
+ ## Acknowledgments
415
+
416
+ - [Textual](https://textual.textualize.io/) - Modern TUI framework
417
+ - [NetBox](https://netbox.dev/) - Infrastructure source of truth
418
+ - [HashiCorp Consul](https://www.consul.io/) - Service discovery
419
+ - [tmux](https://github.com/tmux/tmux) - Terminal multiplexing
420
+ - [loguru](https://github.com/Delgan/loguru) - Logging
421
+
422
+ ---
423
+
424
+ **SSHplex** - Because managing multiple SSH connections should be simple and elegant.