ntermqt 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.
Files changed (58) hide show
  1. ntermqt-0.1.0/MANIFEST.in +8 -0
  2. ntermqt-0.1.0/PKG-INFO +327 -0
  3. ntermqt-0.1.0/README.md +291 -0
  4. ntermqt-0.1.0/nterm/__init__.py +54 -0
  5. ntermqt-0.1.0/nterm/__main__.py +619 -0
  6. ntermqt-0.1.0/nterm/askpass/__init__.py +22 -0
  7. ntermqt-0.1.0/nterm/askpass/server.py +393 -0
  8. ntermqt-0.1.0/nterm/config.py +158 -0
  9. ntermqt-0.1.0/nterm/connection/__init__.py +17 -0
  10. ntermqt-0.1.0/nterm/connection/profile.py +296 -0
  11. ntermqt-0.1.0/nterm/manager/__init__.py +29 -0
  12. ntermqt-0.1.0/nterm/manager/connect_dialog.py +322 -0
  13. ntermqt-0.1.0/nterm/manager/editor.py +262 -0
  14. ntermqt-0.1.0/nterm/manager/io.py +678 -0
  15. ntermqt-0.1.0/nterm/manager/models.py +346 -0
  16. ntermqt-0.1.0/nterm/manager/settings.py +264 -0
  17. ntermqt-0.1.0/nterm/manager/tree.py +493 -0
  18. ntermqt-0.1.0/nterm/resources.py +48 -0
  19. ntermqt-0.1.0/nterm/session/__init__.py +60 -0
  20. ntermqt-0.1.0/nterm/session/askpass_ssh.py +399 -0
  21. ntermqt-0.1.0/nterm/session/base.py +110 -0
  22. ntermqt-0.1.0/nterm/session/interactive_ssh.py +522 -0
  23. ntermqt-0.1.0/nterm/session/pty_transport.py +571 -0
  24. ntermqt-0.1.0/nterm/session/ssh.py +610 -0
  25. ntermqt-0.1.0/nterm/terminal/__init__.py +11 -0
  26. ntermqt-0.1.0/nterm/terminal/bridge.py +83 -0
  27. ntermqt-0.1.0/nterm/terminal/resources/terminal.html +253 -0
  28. ntermqt-0.1.0/nterm/terminal/resources/terminal.js +414 -0
  29. ntermqt-0.1.0/nterm/terminal/resources/xterm-addon-fit.min.js +8 -0
  30. ntermqt-0.1.0/nterm/terminal/resources/xterm-addon-unicode11.min.js +8 -0
  31. ntermqt-0.1.0/nterm/terminal/resources/xterm-addon-web-links.min.js +8 -0
  32. ntermqt-0.1.0/nterm/terminal/resources/xterm.css +209 -0
  33. ntermqt-0.1.0/nterm/terminal/resources/xterm.min.js +8 -0
  34. ntermqt-0.1.0/nterm/terminal/widget.py +380 -0
  35. ntermqt-0.1.0/nterm/theme/__init__.py +10 -0
  36. ntermqt-0.1.0/nterm/theme/engine.py +456 -0
  37. ntermqt-0.1.0/nterm/theme/stylesheet.py +377 -0
  38. ntermqt-0.1.0/nterm/theme/themes/clean.yaml +0 -0
  39. ntermqt-0.1.0/nterm/theme/themes/default.yaml +36 -0
  40. ntermqt-0.1.0/nterm/theme/themes/dracula.yaml +36 -0
  41. ntermqt-0.1.0/nterm/theme/themes/gruvbox_dark.yaml +36 -0
  42. ntermqt-0.1.0/nterm/theme/themes/gruvbox_hybrid.yaml +38 -0
  43. ntermqt-0.1.0/nterm/theme/themes/gruvbox_light.yaml +36 -0
  44. ntermqt-0.1.0/nterm/vault/__init__.py +32 -0
  45. ntermqt-0.1.0/nterm/vault/credential_manager.py +163 -0
  46. ntermqt-0.1.0/nterm/vault/keychain.py +135 -0
  47. ntermqt-0.1.0/nterm/vault/manager_ui.py +962 -0
  48. ntermqt-0.1.0/nterm/vault/profile.py +219 -0
  49. ntermqt-0.1.0/nterm/vault/resolver.py +250 -0
  50. ntermqt-0.1.0/nterm/vault/store.py +642 -0
  51. ntermqt-0.1.0/ntermqt.egg-info/PKG-INFO +327 -0
  52. ntermqt-0.1.0/ntermqt.egg-info/SOURCES.txt +56 -0
  53. ntermqt-0.1.0/ntermqt.egg-info/dependency_links.txt +1 -0
  54. ntermqt-0.1.0/ntermqt.egg-info/entry_points.txt +5 -0
  55. ntermqt-0.1.0/ntermqt.egg-info/requires.txt +15 -0
  56. ntermqt-0.1.0/ntermqt.egg-info/top_level.txt +1 -0
  57. ntermqt-0.1.0/pyproject.toml +59 -0
  58. ntermqt-0.1.0/setup.cfg +4 -0
@@ -0,0 +1,8 @@
1
+ include LICENSE
2
+ include README.md
3
+ recursive-include nterm/terminal/resources *
4
+ recursive-include nterm/theme/themes *.yaml
5
+ prune nterm/examples
6
+ prune screenshots
7
+ global-exclude __pycache__
8
+ global-exclude *.pyc
ntermqt-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,327 @@
1
+ Metadata-Version: 2.4
2
+ Name: ntermqt
3
+ Version: 0.1.0
4
+ Summary: Modern SSH terminal widget for PyQt6 with credential vault and jump host support
5
+ Author: Scott Peterman
6
+ License: GPL-3.0
7
+ Project-URL: Homepage, https://github.com/scottpeterman/nterm
8
+ Project-URL: Repository, https://github.com/scottpeterman/nterm
9
+ Project-URL: Issues, https://github.com/scottpeterman/nterm/issues
10
+ Keywords: ssh,terminal,pyqt6,network,automation
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Environment :: X11 Applications :: Qt
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Topic :: System :: Networking
20
+ Classifier: Topic :: Terminals :: Terminal Emulators/X Terminals
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ Requires-Dist: PyQt6>=6.4.0
24
+ Requires-Dist: PyQt6-WebEngine>=6.4.0
25
+ Requires-Dist: paramiko>=3.0.0
26
+ Requires-Dist: cryptography>=41.0.0
27
+ Requires-Dist: pyyaml>=6.0
28
+ Provides-Extra: keyring
29
+ Requires-Dist: keyring>=24.0.0; extra == "keyring"
30
+ Provides-Extra: dev
31
+ Requires-Dist: pytest; extra == "dev"
32
+ Requires-Dist: black; extra == "dev"
33
+ Requires-Dist: pyinstaller; extra == "dev"
34
+ Requires-Dist: build; extra == "dev"
35
+ Requires-Dist: twine; extra == "dev"
36
+
37
+ # nterm
38
+
39
+ **A modern SSH terminal for network engineers**
40
+
41
+ PyQt6 terminal widget with encrypted credential vault, jump host chaining, YubiKey/FIDO2 support, and legacy device compatibility.
42
+
43
+ Built for managing hundreds of devices through bastion hosts with hardware security keys.
44
+
45
+ ![nterm screenshot](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/gruvbox.png)
46
+
47
+ ---
48
+
49
+ ## Features
50
+
51
+ **Terminal**
52
+ - xterm.js rendering via QWebEngineView — full VT100/ANSI support
53
+ - Built-in themes: Catppuccin, Dracula, Nord, Solarized, Gruvbox (dark/light/hybrid)
54
+ - Custom YAML themes with independent terminal and UI colors
55
+ - Tab or window per session — pop sessions to separate windows
56
+ - Unicode, emoji, box-drawing characters
57
+
58
+ **Authentication**
59
+ - SSH Agent with YubiKey/FIDO2 hardware keys
60
+ - Password, key file, keyboard-interactive, certificate auth
61
+ - Multiple auth methods with automatic fallback
62
+ - RSA SHA-1 fallback for legacy devices (OpenSSH < 7.2)
63
+ - Legacy crypto support for old Juniper/Cisco gear
64
+
65
+ **Connection Management**
66
+ - Jump host chaining (unlimited hops)
67
+ - Auto-reconnection with exponential backoff
68
+ - Connection profiles in YAML/JSON
69
+ - Pattern-based credential resolution
70
+
71
+ **Credential Vault**
72
+ - AES-256 encryption with PBKDF2 (480,000 iterations)
73
+ - Pattern matching — map credentials to hosts by wildcard or tag
74
+ - Cross-platform keychain: macOS Keychain, Windows Credential Locker, Linux Secret Service
75
+ - Full PyQt6 management UI
76
+
77
+ ---
78
+
79
+ ## Screenshots
80
+
81
+ | Gruvbox Hybrid Theme | Credential Manager |
82
+ |---------------------|-------------------|
83
+ | ![gruvbox](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/gruvbox.png) | ![vault](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/vault.png) |
84
+
85
+ | Connection Dialog | Multi-vendor Support |
86
+ |----------------------------------------------------------------------------------------------|---------------------|
87
+ | ![connect](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/creds.png) | ![neofetch](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/neofetch.png) |
88
+
89
+ ---
90
+
91
+ ## Installation
92
+
93
+ ### From PyPI
94
+
95
+ ```bash
96
+ pip install nterm
97
+
98
+ # Optional: system keychain support
99
+ pip install nterm[keyring]
100
+
101
+ # Run
102
+ nterm
103
+ ```
104
+
105
+ ### From Source
106
+
107
+ ```bash
108
+ git clone https://github.com/scottpeterman/nterm.git
109
+ cd nterm
110
+
111
+ # Create virtual environment
112
+ python -m venv .venv
113
+ source .venv/bin/activate # Linux/macOS
114
+ # .venv\Scripts\activate # Windows
115
+
116
+ # Install in development mode
117
+ pip install -e .
118
+
119
+ # Optional: system keychain support
120
+ pip install keyring
121
+
122
+ # Run
123
+ nterm
124
+ # or
125
+ python -m nterm
126
+ ```
127
+
128
+ ### Requirements
129
+
130
+ - Python 3.10+
131
+ - PyQt6 with WebEngine
132
+ - paramiko
133
+ - cryptography
134
+ - pyyaml
135
+
136
+ ### Platform Support
137
+
138
+ | Platform | PTY | Keychain |
139
+ |----------|-----|----------|
140
+ | Linux | ✅ Native | Secret Service |
141
+ | macOS | ✅ Native | macOS Keychain |
142
+ | Windows 10+ | ✅ pywinpty | Credential Locker |
143
+
144
+ ---
145
+
146
+ ## Quick Start
147
+
148
+ ### As a Widget
149
+
150
+ ```python
151
+ from PyQt6.QtWidgets import QApplication, QMainWindow
152
+ from nterm import ConnectionProfile, AuthConfig, SSHSession, TerminalWidget, Theme
153
+
154
+ app = QApplication([])
155
+
156
+ terminal = TerminalWidget()
157
+ terminal.set_theme(Theme.gruvbox_hybrid())
158
+
159
+ profile = ConnectionProfile(
160
+ name="router",
161
+ hostname="192.168.1.1",
162
+ auth_methods=[AuthConfig.password_auth("admin", "secret")],
163
+ )
164
+
165
+ session = SSHSession(profile)
166
+ terminal.attach_session(session)
167
+ session.connect()
168
+
169
+ window = QMainWindow()
170
+ window.setCentralWidget(terminal)
171
+ window.resize(1000, 700)
172
+ window.show()
173
+
174
+ app.exec()
175
+ ```
176
+
177
+ ### With Credential Vault
178
+
179
+ ```python
180
+ from nterm.vault import CredentialStore, CredentialResolver
181
+
182
+ store = CredentialStore()
183
+ store.unlock("master-password")
184
+
185
+ # Add credential with pattern matching
186
+ store.add_credential(
187
+ name="network-devices",
188
+ username="admin",
189
+ password="secret",
190
+ match_hosts=["*.network.corp", "192.168.1.*"],
191
+ match_tags=["cisco", "juniper"],
192
+ )
193
+
194
+ # Auto-resolve credentials by hostname
195
+ resolver = CredentialResolver(store)
196
+ profile = resolver.resolve_for_device("switch01.network.corp", tags=["cisco"])
197
+
198
+ session = SSHSession(profile)
199
+ session.connect()
200
+ ```
201
+
202
+ ---
203
+
204
+ ## Themes
205
+
206
+ ### Built-in
207
+
208
+ ```python
209
+ Theme.default() # Catppuccin Mocha
210
+ Theme.dracula() # Dracula
211
+ Theme.nord() # Nord
212
+ Theme.solarized_dark() # Solarized Dark
213
+ Theme.gruvbox_dark() # Gruvbox Dark
214
+ Theme.gruvbox_light() # Gruvbox Light
215
+ Theme.gruvbox_hybrid() # Dark UI + Light terminal
216
+ ```
217
+
218
+ ### Custom YAML
219
+
220
+ ```yaml
221
+ # ~/.nterm/themes/my-theme.yaml
222
+ name: my-theme
223
+
224
+ terminal_colors:
225
+ background: "#1a1b26"
226
+ foreground: "#c0caf5"
227
+ cursor: "#c0caf5"
228
+ black: "#15161e"
229
+ red: "#f7768e"
230
+ green: "#9ece6a"
231
+ yellow: "#e0af68"
232
+ blue: "#7aa2f7"
233
+ magenta: "#bb9af7"
234
+ cyan: "#7dcfff"
235
+ white: "#a9b1d6"
236
+ # ... bright variants
237
+
238
+ # UI chrome (can differ from terminal)
239
+ background_color: "#1a1b26"
240
+ foreground_color: "#c0caf5"
241
+ border_color: "#33467c"
242
+ accent_color: "#7aa2f7"
243
+ ```
244
+
245
+ ---
246
+
247
+ ## Jump Hosts
248
+
249
+ ```python
250
+ profile = ConnectionProfile(
251
+ name="internal-db",
252
+ hostname="db01.internal.corp",
253
+ auth_methods=[AuthConfig.agent_auth("dbadmin")],
254
+ jump_hosts=[
255
+ JumpHostConfig(
256
+ hostname="bastion.corp.com",
257
+ auth=AuthConfig.agent_auth("youruser"),
258
+ requires_touch=True,
259
+ touch_prompt="Touch YubiKey for bastion...",
260
+ ),
261
+ ],
262
+ )
263
+ ```
264
+
265
+ ---
266
+
267
+ ## Legacy Device Support
268
+
269
+ nterm automatically handles old network equipment:
270
+
271
+ - **RSA SHA-1 fallback** for OpenSSH < 7.2 servers
272
+ - **Legacy KEX algorithms**: diffie-hellman-group14-sha1, group1-sha1
273
+ - **Legacy ciphers**: aes128-cbc, 3des-cbc
274
+ - **Auto-detection**: tries modern crypto first, falls back as needed
275
+
276
+ Tested with:
277
+ - Junos 14.x (2016)
278
+ - Cisco IOS 12.2
279
+ - Old Arista EOS
280
+ - Any device running OpenSSH 6.x
281
+
282
+ ---
283
+
284
+ ## Architecture
285
+
286
+ ```
287
+ nterm/
288
+ ├── connection/ # ConnectionProfile, AuthConfig, JumpHostConfig
289
+ ├── session/
290
+ │ ├── ssh.py # SSHSession (Paramiko) with legacy fallback
291
+ │ ├── interactive_ssh.py # Native SSH + PTY
292
+ │ └── pty_transport.py # Cross-platform PTY
293
+ ├── terminal/
294
+ │ ├── widget.py # TerminalWidget (PyQt6 + xterm.js)
295
+ │ └── bridge.py # Qt ↔ JavaScript bridge
296
+ ├── theme/
297
+ │ ├── engine.py # Theme system
298
+ │ └── themes/ # YAML theme files
299
+ ├── vault/
300
+ │ ├── store.py # Encrypted credential storage
301
+ │ ├── resolver.py # Pattern-based resolution
302
+ │ └── manager_ui.py # PyQt6 credential manager
303
+ └── manager/ # Session tree, connection dialogs
304
+ ```
305
+
306
+ ---
307
+
308
+ ## Related Projects
309
+
310
+ - [TerminalTelemetry](https://github.com/scottpeterman/terminaltelemetry) — PyQt6 terminal with network monitoring
311
+ - [Secure Cartography](https://github.com/scottpeterman/secure_cartography) — Network discovery and mapping
312
+
313
+ ---
314
+
315
+ ## License
316
+
317
+ GPLv3
318
+
319
+ ---
320
+
321
+ ## Contributing
322
+
323
+ Contributions welcome:
324
+ - Additional themes
325
+ - Windows testing
326
+ - Session recording/playback
327
+ - Telnet/serial support
@@ -0,0 +1,291 @@
1
+ # nterm
2
+
3
+ **A modern SSH terminal for network engineers**
4
+
5
+ PyQt6 terminal widget with encrypted credential vault, jump host chaining, YubiKey/FIDO2 support, and legacy device compatibility.
6
+
7
+ Built for managing hundreds of devices through bastion hosts with hardware security keys.
8
+
9
+ ![nterm screenshot](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/gruvbox.png)
10
+
11
+ ---
12
+
13
+ ## Features
14
+
15
+ **Terminal**
16
+ - xterm.js rendering via QWebEngineView — full VT100/ANSI support
17
+ - Built-in themes: Catppuccin, Dracula, Nord, Solarized, Gruvbox (dark/light/hybrid)
18
+ - Custom YAML themes with independent terminal and UI colors
19
+ - Tab or window per session — pop sessions to separate windows
20
+ - Unicode, emoji, box-drawing characters
21
+
22
+ **Authentication**
23
+ - SSH Agent with YubiKey/FIDO2 hardware keys
24
+ - Password, key file, keyboard-interactive, certificate auth
25
+ - Multiple auth methods with automatic fallback
26
+ - RSA SHA-1 fallback for legacy devices (OpenSSH < 7.2)
27
+ - Legacy crypto support for old Juniper/Cisco gear
28
+
29
+ **Connection Management**
30
+ - Jump host chaining (unlimited hops)
31
+ - Auto-reconnection with exponential backoff
32
+ - Connection profiles in YAML/JSON
33
+ - Pattern-based credential resolution
34
+
35
+ **Credential Vault**
36
+ - AES-256 encryption with PBKDF2 (480,000 iterations)
37
+ - Pattern matching — map credentials to hosts by wildcard or tag
38
+ - Cross-platform keychain: macOS Keychain, Windows Credential Locker, Linux Secret Service
39
+ - Full PyQt6 management UI
40
+
41
+ ---
42
+
43
+ ## Screenshots
44
+
45
+ | Gruvbox Hybrid Theme | Credential Manager |
46
+ |---------------------|-------------------|
47
+ | ![gruvbox](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/gruvbox.png) | ![vault](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/vault.png) |
48
+
49
+ | Connection Dialog | Multi-vendor Support |
50
+ |----------------------------------------------------------------------------------------------|---------------------|
51
+ | ![connect](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/creds.png) | ![neofetch](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/neofetch.png) |
52
+
53
+ ---
54
+
55
+ ## Installation
56
+
57
+ ### From PyPI
58
+
59
+ ```bash
60
+ pip install nterm
61
+
62
+ # Optional: system keychain support
63
+ pip install nterm[keyring]
64
+
65
+ # Run
66
+ nterm
67
+ ```
68
+
69
+ ### From Source
70
+
71
+ ```bash
72
+ git clone https://github.com/scottpeterman/nterm.git
73
+ cd nterm
74
+
75
+ # Create virtual environment
76
+ python -m venv .venv
77
+ source .venv/bin/activate # Linux/macOS
78
+ # .venv\Scripts\activate # Windows
79
+
80
+ # Install in development mode
81
+ pip install -e .
82
+
83
+ # Optional: system keychain support
84
+ pip install keyring
85
+
86
+ # Run
87
+ nterm
88
+ # or
89
+ python -m nterm
90
+ ```
91
+
92
+ ### Requirements
93
+
94
+ - Python 3.10+
95
+ - PyQt6 with WebEngine
96
+ - paramiko
97
+ - cryptography
98
+ - pyyaml
99
+
100
+ ### Platform Support
101
+
102
+ | Platform | PTY | Keychain |
103
+ |----------|-----|----------|
104
+ | Linux | ✅ Native | Secret Service |
105
+ | macOS | ✅ Native | macOS Keychain |
106
+ | Windows 10+ | ✅ pywinpty | Credential Locker |
107
+
108
+ ---
109
+
110
+ ## Quick Start
111
+
112
+ ### As a Widget
113
+
114
+ ```python
115
+ from PyQt6.QtWidgets import QApplication, QMainWindow
116
+ from nterm import ConnectionProfile, AuthConfig, SSHSession, TerminalWidget, Theme
117
+
118
+ app = QApplication([])
119
+
120
+ terminal = TerminalWidget()
121
+ terminal.set_theme(Theme.gruvbox_hybrid())
122
+
123
+ profile = ConnectionProfile(
124
+ name="router",
125
+ hostname="192.168.1.1",
126
+ auth_methods=[AuthConfig.password_auth("admin", "secret")],
127
+ )
128
+
129
+ session = SSHSession(profile)
130
+ terminal.attach_session(session)
131
+ session.connect()
132
+
133
+ window = QMainWindow()
134
+ window.setCentralWidget(terminal)
135
+ window.resize(1000, 700)
136
+ window.show()
137
+
138
+ app.exec()
139
+ ```
140
+
141
+ ### With Credential Vault
142
+
143
+ ```python
144
+ from nterm.vault import CredentialStore, CredentialResolver
145
+
146
+ store = CredentialStore()
147
+ store.unlock("master-password")
148
+
149
+ # Add credential with pattern matching
150
+ store.add_credential(
151
+ name="network-devices",
152
+ username="admin",
153
+ password="secret",
154
+ match_hosts=["*.network.corp", "192.168.1.*"],
155
+ match_tags=["cisco", "juniper"],
156
+ )
157
+
158
+ # Auto-resolve credentials by hostname
159
+ resolver = CredentialResolver(store)
160
+ profile = resolver.resolve_for_device("switch01.network.corp", tags=["cisco"])
161
+
162
+ session = SSHSession(profile)
163
+ session.connect()
164
+ ```
165
+
166
+ ---
167
+
168
+ ## Themes
169
+
170
+ ### Built-in
171
+
172
+ ```python
173
+ Theme.default() # Catppuccin Mocha
174
+ Theme.dracula() # Dracula
175
+ Theme.nord() # Nord
176
+ Theme.solarized_dark() # Solarized Dark
177
+ Theme.gruvbox_dark() # Gruvbox Dark
178
+ Theme.gruvbox_light() # Gruvbox Light
179
+ Theme.gruvbox_hybrid() # Dark UI + Light terminal
180
+ ```
181
+
182
+ ### Custom YAML
183
+
184
+ ```yaml
185
+ # ~/.nterm/themes/my-theme.yaml
186
+ name: my-theme
187
+
188
+ terminal_colors:
189
+ background: "#1a1b26"
190
+ foreground: "#c0caf5"
191
+ cursor: "#c0caf5"
192
+ black: "#15161e"
193
+ red: "#f7768e"
194
+ green: "#9ece6a"
195
+ yellow: "#e0af68"
196
+ blue: "#7aa2f7"
197
+ magenta: "#bb9af7"
198
+ cyan: "#7dcfff"
199
+ white: "#a9b1d6"
200
+ # ... bright variants
201
+
202
+ # UI chrome (can differ from terminal)
203
+ background_color: "#1a1b26"
204
+ foreground_color: "#c0caf5"
205
+ border_color: "#33467c"
206
+ accent_color: "#7aa2f7"
207
+ ```
208
+
209
+ ---
210
+
211
+ ## Jump Hosts
212
+
213
+ ```python
214
+ profile = ConnectionProfile(
215
+ name="internal-db",
216
+ hostname="db01.internal.corp",
217
+ auth_methods=[AuthConfig.agent_auth("dbadmin")],
218
+ jump_hosts=[
219
+ JumpHostConfig(
220
+ hostname="bastion.corp.com",
221
+ auth=AuthConfig.agent_auth("youruser"),
222
+ requires_touch=True,
223
+ touch_prompt="Touch YubiKey for bastion...",
224
+ ),
225
+ ],
226
+ )
227
+ ```
228
+
229
+ ---
230
+
231
+ ## Legacy Device Support
232
+
233
+ nterm automatically handles old network equipment:
234
+
235
+ - **RSA SHA-1 fallback** for OpenSSH < 7.2 servers
236
+ - **Legacy KEX algorithms**: diffie-hellman-group14-sha1, group1-sha1
237
+ - **Legacy ciphers**: aes128-cbc, 3des-cbc
238
+ - **Auto-detection**: tries modern crypto first, falls back as needed
239
+
240
+ Tested with:
241
+ - Junos 14.x (2016)
242
+ - Cisco IOS 12.2
243
+ - Old Arista EOS
244
+ - Any device running OpenSSH 6.x
245
+
246
+ ---
247
+
248
+ ## Architecture
249
+
250
+ ```
251
+ nterm/
252
+ ├── connection/ # ConnectionProfile, AuthConfig, JumpHostConfig
253
+ ├── session/
254
+ │ ├── ssh.py # SSHSession (Paramiko) with legacy fallback
255
+ │ ├── interactive_ssh.py # Native SSH + PTY
256
+ │ └── pty_transport.py # Cross-platform PTY
257
+ ├── terminal/
258
+ │ ├── widget.py # TerminalWidget (PyQt6 + xterm.js)
259
+ │ └── bridge.py # Qt ↔ JavaScript bridge
260
+ ├── theme/
261
+ │ ├── engine.py # Theme system
262
+ │ └── themes/ # YAML theme files
263
+ ├── vault/
264
+ │ ├── store.py # Encrypted credential storage
265
+ │ ├── resolver.py # Pattern-based resolution
266
+ │ └── manager_ui.py # PyQt6 credential manager
267
+ └── manager/ # Session tree, connection dialogs
268
+ ```
269
+
270
+ ---
271
+
272
+ ## Related Projects
273
+
274
+ - [TerminalTelemetry](https://github.com/scottpeterman/terminaltelemetry) — PyQt6 terminal with network monitoring
275
+ - [Secure Cartography](https://github.com/scottpeterman/secure_cartography) — Network discovery and mapping
276
+
277
+ ---
278
+
279
+ ## License
280
+
281
+ GPLv3
282
+
283
+ ---
284
+
285
+ ## Contributing
286
+
287
+ Contributions welcome:
288
+ - Additional themes
289
+ - Windows testing
290
+ - Session recording/playback
291
+ - Telnet/serial support
@@ -0,0 +1,54 @@
1
+ """
2
+ nterm - A themeable SSH terminal widget for PyQt6.
3
+
4
+ Clean architecture with:
5
+ - Connection profiles (fully serializable)
6
+ - Session management with auto-reconnect
7
+ - Jump host / bastion support
8
+ - YubiKey/FIDO2 agent auth (native SSH + PTY)
9
+ - xterm.js rendering
10
+ - Themeable UI
11
+
12
+ Session types:
13
+ - SSHSession: Paramiko-based, programmatic auth
14
+ - InteractiveSSHSession: Native ssh with PTY for full interactive auth
15
+ - HybridSSHSession: Interactive auth with ControlMaster reuse (Unix only)
16
+ """
17
+
18
+ __version__ = "0.2.0"
19
+ __author__ = "Scott Peterman"
20
+
21
+ from .connection.profile import (
22
+ ConnectionProfile,
23
+ AuthConfig,
24
+ AuthMethod,
25
+ JumpHostConfig,
26
+ )
27
+ from .session.base import Session, SessionState
28
+ from .session.ssh import SSHSession
29
+ from .session.interactive_ssh import InteractiveSSHSession, HybridSSHSession
30
+ from .session.pty_transport import is_pty_available, IS_WINDOWS
31
+ from .terminal.widget import TerminalWidget
32
+ from .theme.engine import Theme, ThemeEngine
33
+
34
+ __all__ = [
35
+ # Connection
36
+ "ConnectionProfile",
37
+ "AuthConfig",
38
+ "AuthMethod",
39
+ "JumpHostConfig",
40
+ # Sessions
41
+ "Session",
42
+ "SessionState",
43
+ "SSHSession",
44
+ "InteractiveSSHSession",
45
+ "HybridSSHSession",
46
+ # Utilities
47
+ "is_pty_available",
48
+ "IS_WINDOWS",
49
+ # Terminal
50
+ "TerminalWidget",
51
+ # Themes
52
+ "Theme",
53
+ "ThemeEngine",
54
+ ]