ntermqt 0.1.1__py3-none-any.whl → 0.1.4__py3-none-any.whl

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.
nterm/terminal/widget.py CHANGED
@@ -6,11 +6,12 @@ from __future__ import annotations
6
6
  import base64
7
7
  import json
8
8
  import logging
9
+ import re
9
10
  from pathlib import Path
10
- from typing import Optional
11
+ from typing import Optional, BinaryIO
11
12
 
12
13
  from PyQt6.QtCore import Qt, QUrl, pyqtSignal, pyqtSlot
13
- from PyQt6.QtWidgets import QWidget, QVBoxLayout, QApplication
14
+ from PyQt6.QtWidgets import QWidget, QVBoxLayout, QApplication, QFileDialog
14
15
  from PyQt6.QtWebEngineWidgets import QWebEngineView
15
16
  from PyQt6.QtWebEngineCore import QWebEngineSettings
16
17
  from PyQt6.QtWebChannel import QWebChannel
@@ -29,6 +30,9 @@ from nterm.resources import resources
29
30
  # Default threshold for multiline paste warning
30
31
  MULTILINE_PASTE_THRESHOLD = 1
31
32
 
33
+ # ANSI escape sequence pattern for stripping from capture logs
34
+ ANSI_ESCAPE = re.compile(rb'\x1b\[[0-9;]*[a-zA-Z]|\x1b\].*?\x07|\x1b\[[\?0-9;]*[hl]')
35
+
32
36
 
33
37
  class TerminalWidget(QWidget):
34
38
  """
@@ -55,6 +59,10 @@ class TerminalWidget(QWidget):
55
59
  self._multiline_threshold = multiline_threshold
56
60
  self._pending_paste: Optional[bytes] = None # held during confirmation
57
61
 
62
+ # Session capture
63
+ self._capture_file: Optional[BinaryIO] = None
64
+ self._capture_path: Optional[Path] = None
65
+
58
66
  self._setup_ui()
59
67
  self._setup_bridge()
60
68
 
@@ -99,6 +107,9 @@ class TerminalWidget(QWidget):
99
107
  self._bridge.paste_confirmed.connect(self._on_paste_confirmed)
100
108
  self._bridge.paste_cancelled.connect(self._on_paste_cancelled)
101
109
 
110
+ # Capture signals
111
+ self._bridge.capture_toggled.connect(self._on_capture_toggle)
112
+
102
113
  # Load terminal HTML
103
114
  try:
104
115
  html_path = resources.get_path("terminal", "resources", "terminal.html")
@@ -130,6 +141,9 @@ class TerminalWidget(QWidget):
130
141
  self._awaiting_reconnect_confirm = False
131
142
  logger.debug("Detached session")
132
143
 
144
+ # Stop any active capture
145
+ self.stop_capture()
146
+
133
147
  def set_theme(self, theme: Theme) -> None:
134
148
  """
135
149
  Apply theme to terminal.
@@ -157,6 +171,11 @@ class TerminalWidget(QWidget):
157
171
  Args:
158
172
  data: Bytes to display
159
173
  """
174
+ # Session capture - strip ANSI escapes for clean text
175
+ if self._capture_file:
176
+ clean = ANSI_ESCAPE.sub(b'', data)
177
+ self._capture_file.write(clean)
178
+
160
179
  if self._ready:
161
180
  data_b64 = base64.b64encode(data).decode('ascii')
162
181
  self._bridge.write_data.emit(data_b64)
@@ -190,6 +209,58 @@ class TerminalWidget(QWidget):
190
209
  if self._ready:
191
210
  self._bridge.hide_overlay.emit()
192
211
 
212
+ # -------------------------------------------------------------------------
213
+ # Session capture
214
+ # -------------------------------------------------------------------------
215
+
216
+ @property
217
+ def is_capturing(self) -> bool:
218
+ """Check if session capture is active."""
219
+ return self._capture_file is not None
220
+
221
+ def start_capture(self, path: Path) -> None:
222
+ """
223
+ Start capturing session output to file.
224
+
225
+ Args:
226
+ path: File path to write captured output
227
+ """
228
+ self.stop_capture() # Close any existing capture
229
+ self._capture_path = path
230
+ self._capture_file = open(path, 'wb')
231
+ self._bridge.set_capture_state.emit(True, path.name)
232
+ logger.info(f"Started capture: {path}")
233
+
234
+ def stop_capture(self) -> None:
235
+ """Stop capturing session output."""
236
+ if self._capture_file:
237
+ self._capture_file.close()
238
+ logger.info(f"Stopped capture: {self._capture_path}")
239
+ self._capture_file = None
240
+ self._capture_path = None
241
+ self._bridge.set_capture_state.emit(False, "")
242
+
243
+ @pyqtSlot()
244
+ def _on_capture_toggle(self):
245
+ """Handle capture menu item click."""
246
+ if self._capture_file:
247
+ self.stop_capture()
248
+ else:
249
+ # Show file save dialog
250
+ default_name = "session.log"
251
+ if self._session:
252
+ # Use hostname if available for default filename
253
+ default_name = f"session_{self._session.hostname}.log" if hasattr(self._session, 'hostname') else "session.log"
254
+
255
+ path, _ = QFileDialog.getSaveFileName(
256
+ self,
257
+ "Save Session Capture",
258
+ str(Path.home() / default_name),
259
+ "Log Files (*.log *.txt);;All Files (*)"
260
+ )
261
+ if path:
262
+ self.start_capture(Path(path))
263
+
193
264
  # -------------------------------------------------------------------------
194
265
  # Clipboard operations
195
266
  # -------------------------------------------------------------------------
nterm/theme/engine.py CHANGED
@@ -564,6 +564,50 @@ class Theme:
564
564
  overlay_text_color="#3c3836",
565
565
  )
566
566
 
567
+ @classmethod
568
+ def nord_hybrid(cls) -> Theme:
569
+ """
570
+ Nord Hybrid theme.
571
+
572
+ Polar Night UI + Snow Storm terminal.
573
+ Dark chrome, soft light terminal (not harsh white).
574
+ """
575
+ return cls(
576
+ name="nord_hybrid",
577
+ terminal_colors={
578
+ "background": "#eceff4",
579
+ "foreground": "#2e3440",
580
+ "cursor": "#2e3440",
581
+ "cursorAccent": "#eceff4",
582
+ "selectionBackground": "#d8dee9",
583
+ "selectionForeground": "#2e3440",
584
+ "black": "#2e3440",
585
+ "red": "#bf616a",
586
+ "green": "#a3be8c",
587
+ "yellow": "#d08770",
588
+ "blue": "#5e81ac",
589
+ "magenta": "#b48ead",
590
+ "cyan": "#88c0d0",
591
+ "white": "#d8dee9",
592
+ "brightBlack": "#4c566a",
593
+ "brightRed": "#bf616a",
594
+ "brightGreen": "#a3be8c",
595
+ "brightYellow": "#ebcb8b",
596
+ "brightBlue": "#81a1c1",
597
+ "brightMagenta": "#b48ead",
598
+ "brightCyan": "#8fbcbb",
599
+ "brightWhite": "#eceff4",
600
+ },
601
+ font_family="JetBrains Mono, Cascadia Code, Consolas, Menlo, monospace",
602
+ font_size=14,
603
+ background_color="#2e3440",
604
+ foreground_color="#d8dee9",
605
+ border_color="#3b4252",
606
+ accent_color="#88c0d0",
607
+ overlay_background="rgba(46, 52, 64, 0.95)",
608
+ overlay_text_color="#eceff4",
609
+ )
610
+
567
611
  @classmethod
568
612
  def gruvbox_hybrid(cls) -> Theme:
569
613
  """
@@ -630,6 +674,7 @@ class ThemeEngine:
630
674
  self._themes["default"] = Theme.default()
631
675
  self._themes["dracula"] = Theme.dracula()
632
676
  self._themes["nord"] = Theme.nord()
677
+ self._themes["nord_hybrid"] = Theme.nord_hybrid()
633
678
  self._themes["solarized_dark"] = Theme.solarized_dark()
634
679
  self._themes["gruvbox_dark"] = Theme.gruvbox_dark()
635
680
  self._themes["gruvbox_light"] = Theme.gruvbox_light()
@@ -0,0 +1,43 @@
1
+ name: nord_hybrid
2
+
3
+ # Nord Hybrid theme
4
+ # Polar Night UI + softer Snow Storm terminal
5
+ # Adjusted palette for better contrast on light background
6
+
7
+ terminal_colors:
8
+ # Softer terminal - nord4 instead of nord6
9
+ background: "#d8dee9"
10
+ foreground: "#2e3440"
11
+ cursor: "#2e3440"
12
+ cursorAccent: "#d8dee9"
13
+ selectionBackground: "#4c566a"
14
+ selectionForeground: "#eceff4"
15
+ # Darkened palette for light background contrast
16
+ black: "#2e3440"
17
+ red: "#a54242"
18
+ green: "#4e6a3d"
19
+ yellow: "#a07040"
20
+ blue: "#3b6186"
21
+ magenta: "#8a4b7c"
22
+ cyan: "#2b7694"
23
+ white: "#4c566a"
24
+ brightBlack: "#3b4252"
25
+ brightRed: "#bf616a"
26
+ brightGreen: "#5c8045"
27
+ brightYellow: "#d08770"
28
+ brightBlue: "#5e81ac"
29
+ brightMagenta: "#b48ead"
30
+ brightCyan: "#4e9a9a"
31
+ brightWhite: "#2e3440"
32
+
33
+ font_family: "JetBrains Mono, Cascadia Code, Consolas, monospace"
34
+ font_size: 14
35
+
36
+ # Polar Night UI chrome (unchanged)
37
+ background_color: "#2e3440"
38
+ foreground_color: "#d8dee9"
39
+ border_color: "#3b4252"
40
+ accent_color: "#88c0d0"
41
+
42
+ overlay_background: "rgba(46, 52, 64, 0.95)"
43
+ overlay_text_color: "#eceff4"
nterm/vault/store.py CHANGED
@@ -295,7 +295,7 @@ class CredentialStore:
295
295
 
296
296
  # Encrypt sensitive fields
297
297
  password_enc = self._encrypt(password) if password else None
298
- ssh_key_enc = self._encrypt(ssh_key) if ssh_key else None
298
+ ssh_key_enc = self._encrypt(ssh_key.strip()) if ssh_key else None
299
299
  ssh_key_pass_enc = self._encrypt(ssh_key_passphrase) if ssh_key_passphrase else None
300
300
 
301
301
  # Serialize lists
@@ -523,8 +523,8 @@ class CredentialStore:
523
523
  updates['password_enc'] = self._encrypt(kwargs['password']) if kwargs['password'] else None
524
524
 
525
525
  if 'ssh_key' in kwargs:
526
- updates['ssh_key_enc'] = self._encrypt(kwargs['ssh_key']) if kwargs['ssh_key'] else None
527
-
526
+ updates['ssh_key_enc'] = self._encrypt(kwargs['ssh_key'].strip()) if kwargs['ssh_key'] else None
527
+
528
528
  if 'ssh_key_passphrase' in kwargs:
529
529
  updates['ssh_key_passphrase_enc'] = self._encrypt(kwargs['ssh_key_passphrase']) if kwargs['ssh_key_passphrase'] else None
530
530
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ntermqt
3
- Version: 0.1.1
3
+ Version: 0.1.4
4
4
  Summary: Modern SSH terminal widget for PyQt6 with credential vault and jump host support
5
5
  Author: Scott Peterman
6
6
  License: GPL-3.0
@@ -25,14 +25,23 @@ Requires-Dist: PyQt6-WebEngine>=6.4.0
25
25
  Requires-Dist: paramiko>=3.0.0
26
26
  Requires-Dist: cryptography>=41.0.0
27
27
  Requires-Dist: pyyaml>=6.0
28
+ Requires-Dist: click>=8.0.0
29
+ Requires-Dist: pexpect>=4.8.0; sys_platform != "win32"
30
+ Requires-Dist: pywinpty>=2.0.0; sys_platform == "win32"
28
31
  Provides-Extra: keyring
29
32
  Requires-Dist: keyring>=24.0.0; extra == "keyring"
33
+ Provides-Extra: scripting
34
+ Requires-Dist: ipython>=8.0.0; extra == "scripting"
30
35
  Provides-Extra: dev
31
36
  Requires-Dist: pytest; extra == "dev"
32
37
  Requires-Dist: black; extra == "dev"
33
38
  Requires-Dist: pyinstaller; extra == "dev"
34
39
  Requires-Dist: build; extra == "dev"
35
40
  Requires-Dist: twine; extra == "dev"
41
+ Requires-Dist: ipython>=8.0.0; extra == "dev"
42
+ Provides-Extra: all
43
+ Requires-Dist: keyring>=24.0.0; extra == "all"
44
+ Requires-Dist: ipython>=8.0.0; extra == "all"
36
45
 
37
46
  # nterm
38
47
 
@@ -50,9 +59,11 @@ Built for managing hundreds of devices through bastion hosts with hardware secur
50
59
 
51
60
  **Terminal**
52
61
  - xterm.js rendering via QWebEngineView — full VT100/ANSI support
53
- - Built-in themes: Catppuccin, Dracula, Nord, Solarized, Gruvbox (dark/light/hybrid)
62
+ - 12 built-in themes: Catppuccin, Dracula, Nord, Solarized, Gruvbox, Enterprise variants
63
+ - Hybrid themes: dark UI chrome with light terminal for readability
54
64
  - Custom YAML themes with independent terminal and UI colors
55
65
  - Tab or window per session — pop sessions to separate windows
66
+ - Session capture to file (clean text, ANSI stripped)
56
67
  - Unicode, emoji, box-drawing characters
57
68
 
58
69
  **Authentication**
@@ -74,6 +85,12 @@ Built for managing hundreds of devices through bastion hosts with hardware secur
74
85
  - Cross-platform keychain: macOS Keychain, Windows Credential Locker, Linux Secret Service
75
86
  - Full PyQt6 management UI
76
87
 
88
+ **Scripting API** *(Experimental)*
89
+ - Query device inventory and credentials programmatically
90
+ - Built-in IPython console with API pre-loaded
91
+ - CLI for shell scripts and automation
92
+ - Foundation for MCP tools and agentic workflows
93
+
77
94
  ---
78
95
 
79
96
  ## Screenshots
@@ -88,15 +105,48 @@ Built for managing hundreds of devices through bastion hosts with hardware secur
88
105
 
89
106
  ---
90
107
 
108
+ ## Dev Console
109
+
110
+ nterm includes a built-in development console accessible via **Dev → IPython** or **Dev → Shell**. Open in a tab alongside your SSH sessions, or pop out to a separate window.
111
+
112
+ ![IPython Console](https://raw.githubusercontent.com/scottpeterman/nterm/main/screenshots/ipython.png)
113
+
114
+ The IPython console runs in the same Python environment as nterm, with the scripting API pre-loaded. Query your device inventory, inspect credentials, and prototype automation workflows without leaving the app.
115
+
116
+ ```python
117
+ # Available immediately when IPython opens
118
+ api.devices() # List all saved devices
119
+ api.search("leaf") # Search by name/hostname
120
+ api.credentials() # List credentials (after api.unlock())
121
+ api.help() # Show all commands
122
+ ```
123
+
124
+ **Use cases:**
125
+ - Debug connection issues with live access to session objects
126
+ - Prototype automation scripts against your real device inventory
127
+ - Test credential resolution patterns
128
+ - Build and test MCP tools interactively
129
+
130
+ Requires the `scripting` extra: `pip install ntermqt[scripting]`
131
+
132
+ ---
133
+
91
134
  ## Installation
92
135
 
136
+ ### Be aware due to a naming conflict, the pypi package is actually "ntermqt"
137
+
93
138
  ### From PyPI
94
139
 
140
+ https://pypi.org/project/ntermqt/
141
+
95
142
  ```bash
96
- pip install nterm
143
+ pip install ntermqt
144
+
145
+ # With optional scripting support (IPython)
146
+ pip install ntermqt[scripting]
97
147
 
98
- # Optional: system keychain support
99
- pip install nterm[keyring]
148
+ # With all optional features
149
+ pip install ntermqt[all]
100
150
 
101
151
  # Run
102
152
  nterm
@@ -114,10 +164,7 @@ source .venv/bin/activate # Linux/macOS
114
164
  # .venv\Scripts\activate # Windows
115
165
 
116
166
  # Install in development mode
117
- pip install -e .
118
-
119
- # Optional: system keychain support
120
- pip install keyring
167
+ pip install -e ".[all]"
121
168
 
122
169
  # Run
123
170
  nterm
@@ -137,12 +184,70 @@ python -m nterm
137
184
 
138
185
  | Platform | PTY | Keychain |
139
186
  |----------|-----|----------|
140
- | Linux | ✅ Native | Secret Service |
141
- | macOS | ✅ Native | macOS Keychain |
187
+ | Linux | ✅ pexpect | Secret Service |
188
+ | macOS | ✅ pexpect | macOS Keychain |
142
189
  | Windows 10+ | ✅ pywinpty | Credential Locker |
143
190
 
144
191
  ---
145
192
 
193
+ ## Scripting API *(Experimental)*
194
+
195
+ nterm includes a scripting API for programmatic access to your device inventory and credential vault. Use it from IPython, CLI, or Python scripts.
196
+
197
+ ### IPython Console
198
+
199
+ Open **Dev → IPython → Open in Tab** to get an interactive console with the API pre-loaded:
200
+
201
+ ```python
202
+ api.devices() # List all saved devices
203
+ api.search("leaf") # Search by name/hostname
204
+ api.devices("eng-*") # Glob pattern filter
205
+
206
+ api.unlock("vault-password") # Unlock credential vault
207
+ api.credentials() # List credentials (metadata only)
208
+
209
+ api.help() # Show all commands
210
+ ```
211
+
212
+ ### CLI
213
+
214
+ ```bash
215
+ nterm-cli devices # List all devices
216
+ nterm-cli search leaf # Search devices
217
+ nterm-cli device eng-leaf-1 # Device details
218
+ nterm-cli credentials --unlock # List credentials
219
+ nterm-cli --json devices # JSON output for scripting
220
+ ```
221
+
222
+ ### Python Scripts
223
+
224
+ ```python
225
+ from nterm.scripting import NTermAPI
226
+
227
+ api = NTermAPI()
228
+
229
+ # Query devices
230
+ for device in api.devices("*spine*"):
231
+ print(f"{device.name}: {device.hostname}")
232
+
233
+ # Work with credentials
234
+ api.unlock("vault-password")
235
+ cred = api.credential("lab-admin")
236
+ print(f"Username: {cred.username}")
237
+ ```
238
+
239
+ ### Roadmap
240
+
241
+ The scripting API is the foundation for:
242
+
243
+ - **Command execution** — `api.connect()` and `api.send()` for programmatic device interaction
244
+ - **Batch operations** — Fan out commands across device groups
245
+ - **MCP tool integration** — Expose nterm capabilities to AI agents
246
+
247
+ See [scripting/README.md](nterm/scripting/README.md) for full API documentation.
248
+
249
+ ---
250
+
146
251
  ## Quick Start
147
252
 
148
253
  ### As a Widget
@@ -203,19 +308,33 @@ session.connect()
203
308
 
204
309
  ## Themes
205
310
 
206
- ### Built-in
311
+ nterm includes 12 built-in themes covering dark, light, and hybrid styles.
312
+
313
+ ### Built-in Themes
207
314
 
208
315
  ```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
316
+ # Dark themes
317
+ Theme.default() # Catppuccin Mocha
318
+ Theme.dracula() # Dracula
319
+ Theme.nord() # Nord
320
+ Theme.solarized_dark() # Solarized Dark
321
+ Theme.gruvbox_dark() # Gruvbox Dark
322
+ Theme.enterprise_dark() # Microsoft-inspired dark
323
+
324
+ # Light themes
325
+ Theme.gruvbox_light() # Gruvbox Light
326
+ Theme.enterprise_light() # Microsoft-inspired light
327
+ Theme.clean() # Warm paper tones
328
+
329
+ # Hybrid themes (dark UI + light terminal)
330
+ Theme.gruvbox_hybrid() # Gruvbox dark chrome, light terminal
331
+ Theme.nord_hybrid() # Nord polar night chrome, snow storm terminal
332
+ Theme.enterprise_hybrid() # VS Code-style dark/light split
216
333
  ```
217
334
 
218
- ### Custom YAML
335
+ **Hybrid themes** combine a dark application chrome (menus, tabs, sidebars) with a light terminal for maximum readability — ideal for long sessions reviewing configs or logs.
336
+
337
+ ### Custom YAML Themes
219
338
 
220
339
  ```yaml
221
340
  # ~/.nterm/themes/my-theme.yaml
@@ -244,6 +363,19 @@ accent_color: "#7aa2f7"
244
363
 
245
364
  ---
246
365
 
366
+ ## Session Capture
367
+
368
+ Capture session output to a file for documentation, auditing, or extracting config snippets.
369
+
370
+ **Right-click in terminal → Start Capture...** to begin recording. Output is saved as clean text with ANSI escape sequences stripped — ready for grep, diff, or pasting into tickets.
371
+
372
+ - Per-session capture (each tab independent)
373
+ - File dialog for save location
374
+ - Menu shows active capture filename
375
+ - Auto-stops when session closes
376
+
377
+ ---
378
+
247
379
  ## Jump Hosts
248
380
 
249
381
  ```python
@@ -289,6 +421,7 @@ nterm/
289
421
  ├── session/
290
422
  │ ├── ssh.py # SSHSession (Paramiko) with legacy fallback
291
423
  │ ├── interactive_ssh.py # Native SSH + PTY
424
+ │ ├── local_terminal.py # Local shell/IPython sessions
292
425
  │ └── pty_transport.py # Cross-platform PTY
293
426
  ├── terminal/
294
427
  │ ├── widget.py # TerminalWidget (PyQt6 + xterm.js)
@@ -300,7 +433,10 @@ nterm/
300
433
  │ ├── store.py # Encrypted credential storage
301
434
  │ ├── resolver.py # Pattern-based resolution
302
435
  │ └── manager_ui.py # PyQt6 credential manager
303
- └── manager/ # Session tree, connection dialogs
436
+ ├── manager/ # Session tree, connection dialogs
437
+ └── scripting/ # API, CLI, automation support
438
+ ├── api.py # NTermAPI class
439
+ └── cli.py # nterm-cli entry point
304
440
  ```
305
441
 
306
442
  ---
@@ -1,36 +1,41 @@
1
1
  nterm/__init__.py,sha256=Liu1bya6xi3NnwO9KLqqlYyLD1eS-2HeEdEpJRc2480,1346
2
- nterm/__main__.py,sha256=RUcfNViOs6JrljEglX7LrBMgBv-_O3I0cKzydc7XNPI,28992
2
+ nterm/__main__.py,sha256=X4R51lyR9j3IteX-Bzs1Q-UcbCJFfvcVitaPWDFBdck,33765
3
3
  nterm/config.py,sha256=19T28opP-rdLRuxXCGP-qrklAlh4HNbXNTyAwveBhu8,4690
4
4
  nterm/resources.py,sha256=SYC8JeF7vVfER93KKRd-tt5b25t0tHTkd7fSJqVDXnI,1447
5
5
  nterm/askpass/__init__.py,sha256=UpJBk0EOm0nkRwMVv7YdIB4v75ZJpSYmNsU_GlgzbUg,495
6
6
  nterm/askpass/server.py,sha256=5tvjYryyfu-n8Cw2KbucwaZfWiqYnFk-iBAVBI8FMfw,12873
7
7
  nterm/connection/__init__.py,sha256=2qQ9LGxUxmwem8deOD2WZVkeD6rIVlTlx5Zh2cUEmxY,261
8
8
  nterm/connection/profile.py,sha256=4RMgnRNKCc-dFGEIpmQc_bob5MtzxO04_PljP-qUGLs,9450
9
+ nterm/examples/basic_terminal.py,sha256=vbDI1xl-Radv6GYZ0yC6QUafQp_tSX2pWIf7tk58W8E,15256
9
10
  nterm/manager/__init__.py,sha256=_QIeTap5CTL3jdTS1Q16fAt-PrqcNPUVr9gtJ22f0ng,774
10
11
  nterm/manager/connect_dialog.py,sha256=yd8g_gYttT_UdflRxSfyss8OQTfrvKLUOMg4Kj8FPNo,11711
11
12
  nterm/manager/editor.py,sha256=Fn2YWHJ1EwPYrhKhsi4GTBYwRfCYsHsqgKkLY-LQ8JI,8469
12
13
  nterm/manager/io.py,sha256=R5ksWgpEz0VdVCokcgTN5G3PFgp5QYhjjt40OypSWkY,21687
13
14
  nterm/manager/models.py,sha256=cvC2HzCRadNG1EYsnZN4C9YS6uolHGcUGGZtt-wzGF4,12237
14
15
  nterm/manager/settings.py,sha256=r6MTw_9r1Wl2UX_ALpXIuPbDvJ0D91Y8wRKq6Bfr_3g,9210
15
- nterm/manager/tree.py,sha256=D1aLVH7xy9m-V1PSwu-GFW1r6UYd93zyufrO0HBRidE,18996
16
+ nterm/manager/tree.py,sha256=I78wSjkSuyM6903II-XNyPug9saMSODUNBCHCDrq4ls,22397
17
+ nterm/scripting/__init__.py,sha256=4WvwvJfJNMwXW6jas8wFreIzKBgjvAhMQnR2cnA_mEE,967
18
+ nterm/scripting/api.py,sha256=O-EyV0ksj7LATMSSPrDJShE3x4JPuEBs0SsPZdc2yUo,13931
19
+ nterm/scripting/cli.py,sha256=W2DK4ZnuutaArye_to7CBchg0ogClURxVbGsMdnj1y0,9187
16
20
  nterm/session/__init__.py,sha256=FkgHF1WPz78JBOWHSC7LLynG2NqoR6aanNTRlEzsO6I,1612
17
21
  nterm/session/askpass_ssh.py,sha256=U-frmLBIXwE2L5ZCEtai91G1dVRSWKLCtxn88t_PqGs,14083
18
22
  nterm/session/base.py,sha256=NNFt2uy-rTkwigrHcdnfREk_QZDxNe0CoP16C-7oIWs,2475
19
23
  nterm/session/interactive_ssh.py,sha256=qBhVGFdkx4hRyEzx0ZdBZZeiuwCav6BR4UtKqPnCssM,17846
20
- nterm/session/pty_transport.py,sha256=VLVIr96f5SsDv2oZlb2TgdcaApNCN2ci5PGkbQ41c_g,16906
24
+ nterm/session/local_terminal.py,sha256=sG2lFAOpItMiT93dYCi05nrGRS-MB52XG4J-iZbcoLM,7066
25
+ nterm/session/pty_transport.py,sha256=QwSFqKKuJhgcLWzv1CUKf3aCGDGbbkmmGwIB1L1A2PU,17176
21
26
  nterm/session/ssh.py,sha256=sGOxjBa9FX6GjVwkmfiKsupoLVsrPVk-LSREjlNmAdE,20942
22
27
  nterm/terminal/__init__.py,sha256=uFnG366Z166pK-ijT1dZanVSSFVZCiMGeNKXvss_sDg,184
23
- nterm/terminal/bridge.py,sha256=FSZMArlq-7a3IsKUrOL42MZeDJ4FfdZwC5UTRk1xryc,2860
24
- nterm/terminal/widget.py,sha256=snUBsH4W0njPogGk3TJYJuvye3YCL1GJSt3cV2YFCeI,13165
25
- nterm/terminal/resources/terminal.html,sha256=LNtXx19SVANjObNydWoAqkBJloKz_bt0kbN41Z7EFxI,7778
26
- nterm/terminal/resources/terminal.js,sha256=wZqVhEu-_KASGfDo-s3nmVZKhupI2r-Ak_poIn_1FU8,13224
28
+ nterm/terminal/bridge.py,sha256=mSkxZr3UGyaFI14w08dzekCkOhfUetq0GIjrBtA3qI0,3199
29
+ nterm/terminal/widget.py,sha256=mxUrQxFmigNR6S3vgnzHahTRGYQI2bNYTBqNg47yaR8,15716
30
+ nterm/terminal/resources/terminal.html,sha256=1onb3qUdDa0qzETR8XaKx0UR6BPlCm_ZpMFVgt36ZPA,7985
31
+ nterm/terminal/resources/terminal.js,sha256=zW9n1MRujSXv66ENgU-gzk_mc75EpWye_f88ejChSW4,13852
27
32
  nterm/terminal/resources/xterm-addon-fit.min.js,sha256=x45XlcZIes3ySrQ2eY1KnOw4SBAbKBvGWwYfOdtxS-E,1789
28
33
  nterm/terminal/resources/xterm-addon-unicode11.min.js,sha256=_sT7CbMSksBfUPmKZYj29IDjq7LMjiwciFs0iGNomBM,7500
29
34
  nterm/terminal/resources/xterm-addon-web-links.min.js,sha256=_iizzOZ3_DRg6y7iu111muLnWVW8bzC9V6_EAPu0hK8,3219
30
35
  nterm/terminal/resources/xterm.css,sha256=gy8_LGA7Q61DUf8ElwFQzHqHMBQnbbEmpgZcbdgeSHI,5383
31
36
  nterm/terminal/resources/xterm.min.js,sha256=_B3TGyIePl-SlIbgeoC0d6iq-dzitPnD_-fdJfNwZV0,283670
32
37
  nterm/theme/__init__.py,sha256=ZTywoJliQcFre0Gh7I30n-_7RrPmdR1NHnE4wSkSCsQ,130
33
- nterm/theme/engine.py,sha256=e1mh8JQeErqc59d1-rbcsbVvz86_BEZCrtDapDjQOyk,24718
38
+ nterm/theme/engine.py,sha256=0C3K9hoFOdEVJv3xJXmPs1DPGT2mSVJNtA0dDm4w-uA,26340
34
39
  nterm/theme/stylesheet.py,sha256=Ycy-y_kiP-SLcQFrAEdJtbSDtKm4yvBfxEe-N26qlDg,9004
35
40
  nterm/theme/themes/clean.yaml,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
36
41
  nterm/theme/themes/default.yaml,sha256=niUrI_K8fayPCZDy1gc3hueLtkWjfmm1p1R33JjYgS4,810
@@ -41,15 +46,16 @@ nterm/theme/themes/enterprise_light.yaml,sha256=Q6H5lSsStoFVJNFS63IPp0FaBhkjN9uB
41
46
  nterm/theme/themes/gruvbox_dark.yaml,sha256=cAr-67R7QhW80ncHptpyyrZuUqD65xoSuLtmHeDgQM0,815
42
47
  nterm/theme/themes/gruvbox_hybrid.yaml,sha256=Ml7Ed3sTBjcSYVJ9t961KhiG3DwMAdVdRBtzI4eWZg0,936
43
48
  nterm/theme/themes/gruvbox_light.yaml,sha256=InqYF-TsLLIzhCHpSSHqSxnest5tu28htQ4AaFN4BFY,820
49
+ nterm/theme/themes/nord_hybrid.yaml,sha256=QAT056Jo2UAdQPmbc3GezjpD7Mge-GQSl4wPeSiaqSE,1065
44
50
  nterm/vault/__init__.py,sha256=e1W3GZKOf0FXNerSp1mojl-yaidYIsygnRwTGBd6mfM,708
45
51
  nterm/vault/credential_manager.py,sha256=TWAMfjpntPXEJ-4AauDz2PPS0q140sUebFk8AjvC-A0,5347
46
52
  nterm/vault/keychain.py,sha256=_2-yUhc2ro-An2zvFlJHYyxozM55iJ4bSseOVKMCNGo,4229
47
53
  nterm/vault/manager_ui.py,sha256=qle-W40j6L_pOR0AaOCeyU8myizFTRkISNrloCn0H_Y,34530
48
54
  nterm/vault/profile.py,sha256=qM9TJf68RKdjtxo-sJehO7wS4iTi2G26BKbmlmHLA5M,6246
49
55
  nterm/vault/resolver.py,sha256=GWB2YR9H1MH98RGQBKvitIsjWT_-wSMLuddZNz4wbns,7800
50
- nterm/vault/store.py,sha256=fbmABHWRjkZ5t42O7r74D3B_R2mZ0WPY8STPo3fGMdw,21191
51
- ntermqt-0.1.1.dist-info/METADATA,sha256=a_JjKJqiQl6Y21PXUkhb9s9qnJdKoC5DxTu-8Fhwfrs,8594
52
- ntermqt-0.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
53
- ntermqt-0.1.1.dist-info/entry_points.txt,sha256=5OEnwVRWwTZjFYXaVNzWdFt-gm2QojCLk50sCLnC2y4,93
54
- ntermqt-0.1.1.dist-info/top_level.txt,sha256=bZdnNLTHNRNqo9jsOQGUWF7h5st0xW_thH0n2QOxWUo,6
55
- ntermqt-0.1.1.dist-info/RECORD,,
56
+ nterm/vault/store.py,sha256=_0Lfe0WKjm3uSAtxgn9qAPlpBOLCuq9SVgzqsE_qaGQ,21199
57
+ ntermqt-0.1.4.dist-info/METADATA,sha256=riL6P_O6COkgWjf4eWq-7cEFiFiorlhlNCvTdr4xhvg,13573
58
+ ntermqt-0.1.4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
59
+ ntermqt-0.1.4.dist-info/entry_points.txt,sha256=Gunr-_3w-aSpfqoMuGKM2PJSCRo9hZ7K1BksUtp1yd8,130
60
+ ntermqt-0.1.4.dist-info/top_level.txt,sha256=bZdnNLTHNRNqo9jsOQGUWF7h5st0xW_thH0n2QOxWUo,6
61
+ ntermqt-0.1.4.dist-info/RECORD,,
@@ -1,5 +1,6 @@
1
1
  [console_scripts]
2
2
  nterm = nterm.__main__:main
3
+ nterm-cli = nterm.scripting.cli:main
3
4
 
4
5
  [gui_scripts]
5
6
  nterm-gui = nterm.__main__:main