nterminal 1.2.0
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.
- package/.env.example +12 -0
- package/LICENSE +674 -0
- package/README.md +181 -0
- package/assets/brand/app-icon-1024.png +0 -0
- package/assets/brand/app-icon-384.png +0 -0
- package/assets/brand/apple-touch-icon-360.png +0 -0
- package/assets/brand/favicon-32.png +0 -0
- package/assets/brand/favicon-64.png +0 -0
- package/assets/brand/favicon-96.png +0 -0
- package/assets/brand/favicon.svg +4 -0
- package/assets/brand/nterminal-mark-64.png +0 -0
- package/assets/brand/nterminal-mark.svg +4 -0
- package/assets/brand/nterminal-wordmark-486x68.png +0 -0
- package/assets/brand/nterminal-wordmark.svg +3 -0
- package/assets/screenshot/scr.png +0 -0
- package/bin/nterminal.js +114 -0
- package/dist/client/apple-touch-icon.png +0 -0
- package/dist/client/assets/MarkdownPreview-BeDi-V7k.js +29 -0
- package/dist/client/assets/MesloLGS-NF-Bold-Italic-DwFsXcwX.ttf +0 -0
- package/dist/client/assets/MesloLGS-NF-Bold-kN-HYz-g.ttf +0 -0
- package/dist/client/assets/MesloLGS-NF-Italic-CMg1T6-G.ttf +0 -0
- package/dist/client/assets/MesloLGS-NF-Regular-Cxr8pvCI.ttf +0 -0
- package/dist/client/assets/index-BQkKYjXb.js +33 -0
- package/dist/client/assets/index-WqeS39wU.css +1 -0
- package/dist/client/assets/notifications/character-2258.mp4 +0 -0
- package/dist/client/assets/notifications/character-2260.mp4 +0 -0
- package/dist/client/assets/notifications/character-2272.mp4 +0 -0
- package/dist/client/brand/nterminal-mark-64.png +0 -0
- package/dist/client/brand/nterminal-mark.svg +4 -0
- package/dist/client/brand/nterminal-wordmark-486x68.png +0 -0
- package/dist/client/brand/nterminal-wordmark.svg +3 -0
- package/dist/client/icons/app-icon-1024.png +0 -0
- package/dist/client/icons/app-icon-384.png +0 -0
- package/dist/client/icons/favicon-32.png +0 -0
- package/dist/client/icons/favicon-64.png +0 -0
- package/dist/client/icons/favicon-96.png +0 -0
- package/dist/client/icons/favicon.svg +4 -0
- package/dist/client/index.html +21 -0
- package/dist/client/manifest.webmanifest +24 -0
- package/dist/scripts/generate-secrets.js +3 -0
- package/dist/scripts/generate-secrets.js.map +1 -0
- package/dist/scripts/onboarding.js +814 -0
- package/dist/scripts/onboarding.js.map +1 -0
- package/dist/scripts/proxySetup.js +1007 -0
- package/dist/scripts/proxySetup.js.map +1 -0
- package/dist/server/agent/agentAuth.d.ts +6 -0
- package/dist/server/agent/agentAuth.js +35 -0
- package/dist/server/agent/agentAuth.js.map +1 -0
- package/dist/server/agent/agentProxy.d.ts +5 -0
- package/dist/server/agent/agentProxy.js +63 -0
- package/dist/server/agent/agentProxy.js.map +1 -0
- package/dist/server/agent/agentRoutes.d.ts +9 -0
- package/dist/server/agent/agentRoutes.js +327 -0
- package/dist/server/agent/agentRoutes.js.map +1 -0
- package/dist/server/agent/agentWebSocketProxy.d.ts +3 -0
- package/dist/server/agent/agentWebSocketProxy.js +65 -0
- package/dist/server/agent/agentWebSocketProxy.js.map +1 -0
- package/dist/server/auth/authService.d.ts +100 -0
- package/dist/server/auth/authService.js +415 -0
- package/dist/server/auth/authService.js.map +1 -0
- package/dist/server/auth/cookies.d.ts +11 -0
- package/dist/server/auth/cookies.js +39 -0
- package/dist/server/auth/cookies.js.map +1 -0
- package/dist/server/auth/ipMatch.d.ts +14 -0
- package/dist/server/auth/ipMatch.js +103 -0
- package/dist/server/auth/ipMatch.js.map +1 -0
- package/dist/server/auth/rateLimit.d.ts +17 -0
- package/dist/server/auth/rateLimit.js +25 -0
- package/dist/server/auth/rateLimit.js.map +1 -0
- package/dist/server/auth/totpService.d.ts +10 -0
- package/dist/server/auth/totpService.js +37 -0
- package/dist/server/auth/totpService.js.map +1 -0
- package/dist/server/config.d.ts +27 -0
- package/dist/server/config.js +138 -0
- package/dist/server/config.js.map +1 -0
- package/dist/server/files/fileExplorerService.d.ts +38 -0
- package/dist/server/files/fileExplorerService.js +551 -0
- package/dist/server/files/fileExplorerService.js.map +1 -0
- package/dist/server/files/rootToken.d.ts +51 -0
- package/dist/server/files/rootToken.js +139 -0
- package/dist/server/files/rootToken.js.map +1 -0
- package/dist/server/http.d.ts +13 -0
- package/dist/server/http.js +69 -0
- package/dist/server/http.js.map +1 -0
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +45 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/routes/agentManagementRoutes.d.ts +9 -0
- package/dist/server/routes/agentManagementRoutes.js +304 -0
- package/dist/server/routes/agentManagementRoutes.js.map +1 -0
- package/dist/server/routes/authRoutes.d.ts +10 -0
- package/dist/server/routes/authRoutes.js +95 -0
- package/dist/server/routes/authRoutes.js.map +1 -0
- package/dist/server/routes/fileRoutes.d.ts +11 -0
- package/dist/server/routes/fileRoutes.js +185 -0
- package/dist/server/routes/fileRoutes.js.map +1 -0
- package/dist/server/routes/notificationAssetRoutes.d.ts +9 -0
- package/dist/server/routes/notificationAssetRoutes.js +280 -0
- package/dist/server/routes/notificationAssetRoutes.js.map +1 -0
- package/dist/server/routes/securityRoutes.d.ts +7 -0
- package/dist/server/routes/securityRoutes.js +53 -0
- package/dist/server/routes/securityRoutes.js.map +1 -0
- package/dist/server/routes/socketBackpressure.d.ts +26 -0
- package/dist/server/routes/socketBackpressure.js +63 -0
- package/dist/server/routes/socketBackpressure.js.map +1 -0
- package/dist/server/routes/terminalLayoutRoutes.d.ts +9 -0
- package/dist/server/routes/terminalLayoutRoutes.js +108 -0
- package/dist/server/routes/terminalLayoutRoutes.js.map +1 -0
- package/dist/server/routes/terminalRoutes.d.ts +14 -0
- package/dist/server/routes/terminalRoutes.js +177 -0
- package/dist/server/routes/terminalRoutes.js.map +1 -0
- package/dist/server/routes/terminalWebSocket.d.ts +9 -0
- package/dist/server/routes/terminalWebSocket.js +129 -0
- package/dist/server/routes/terminalWebSocket.js.map +1 -0
- package/dist/server/routes/totpRoutes.d.ts +7 -0
- package/dist/server/routes/totpRoutes.js +46 -0
- package/dist/server/routes/totpRoutes.js.map +1 -0
- package/dist/server/routes/updateRoutes.d.ts +7 -0
- package/dist/server/routes/updateRoutes.js +24 -0
- package/dist/server/routes/updateRoutes.js.map +1 -0
- package/dist/server/routes/uploadRoutes.d.ts +9 -0
- package/dist/server/routes/uploadRoutes.js +95 -0
- package/dist/server/routes/uploadRoutes.js.map +1 -0
- package/dist/server/storage/fileStore.d.ts +90 -0
- package/dist/server/storage/fileStore.js +275 -0
- package/dist/server/storage/fileStore.js.map +1 -0
- package/dist/server/system/stats.d.ts +2 -0
- package/dist/server/system/stats.js +37 -0
- package/dist/server/system/stats.js.map +1 -0
- package/dist/server/terminal/NodePtyAdapter.d.ts +4 -0
- package/dist/server/terminal/NodePtyAdapter.js +14 -0
- package/dist/server/terminal/NodePtyAdapter.js.map +1 -0
- package/dist/server/terminal/PtyAdapter.d.ts +57 -0
- package/dist/server/terminal/PtyAdapter.js +2 -0
- package/dist/server/terminal/PtyAdapter.js.map +1 -0
- package/dist/server/terminal/TerminalManager.d.ts +74 -0
- package/dist/server/terminal/TerminalManager.js +561 -0
- package/dist/server/terminal/TerminalManager.js.map +1 -0
- package/dist/server/terminal/TmuxPtyAdapter.d.ts +25 -0
- package/dist/server/terminal/TmuxPtyAdapter.js +543 -0
- package/dist/server/terminal/TmuxPtyAdapter.js.map +1 -0
- package/dist/server/terminal/codexTranscriptSource.d.ts +9 -0
- package/dist/server/terminal/codexTranscriptSource.js +144 -0
- package/dist/server/terminal/codexTranscriptSource.js.map +1 -0
- package/dist/server/terminal/cwdResolver.d.ts +8 -0
- package/dist/server/terminal/cwdResolver.js +37 -0
- package/dist/server/terminal/cwdResolver.js.map +1 -0
- package/dist/server/terminal/outputBuffer.d.ts +7 -0
- package/dist/server/terminal/outputBuffer.js +17 -0
- package/dist/server/terminal/outputBuffer.js.map +1 -0
- package/dist/server/terminal/transcriptHistory.d.ts +7 -0
- package/dist/server/terminal/transcriptHistory.js +315 -0
- package/dist/server/terminal/transcriptHistory.js.map +1 -0
- package/dist/server/update/gitUpdate.d.ts +27 -0
- package/dist/server/update/gitUpdate.js +241 -0
- package/dist/server/update/gitUpdate.js.map +1 -0
- package/dist/server/uploads/uploadPaths.d.ts +18 -0
- package/dist/server/uploads/uploadPaths.js +116 -0
- package/dist/server/uploads/uploadPaths.js.map +1 -0
- package/dist/server/uploads/uploadService.d.ts +21 -0
- package/dist/server/uploads/uploadService.js +230 -0
- package/dist/server/uploads/uploadService.js.map +1 -0
- package/dist/shared/layoutState.d.ts +6 -0
- package/dist/shared/layoutState.js +115 -0
- package/dist/shared/layoutState.js.map +1 -0
- package/dist/shared/notificationAssets.d.ts +9 -0
- package/dist/shared/notificationAssets.js +27 -0
- package/dist/shared/notificationAssets.js.map +1 -0
- package/dist/shared/protocol.d.ts +308 -0
- package/dist/shared/protocol.js +29 -0
- package/dist/shared/protocol.js.map +1 -0
- package/dist/shared/types.d.ts +56 -0
- package/dist/shared/types.js +2 -0
- package/dist/shared/types.js.map +1 -0
- package/docs/assets/nterminal-workspace.png +0 -0
- package/docs/configuration.md +97 -0
- package/docs/features.md +126 -0
- package/docs/onboarding.md +122 -0
- package/docs/operations.md +112 -0
- package/docs/terminal-history.md +54 -0
- package/package.json +85 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/assets/notifications/character-2258.mp4 +0 -0
- package/public/assets/notifications/character-2260.mp4 +0 -0
- package/public/assets/notifications/character-2272.mp4 +0 -0
- package/public/brand/nterminal-mark-64.png +0 -0
- package/public/brand/nterminal-mark.svg +4 -0
- package/public/brand/nterminal-wordmark-486x68.png +0 -0
- package/public/brand/nterminal-wordmark.svg +3 -0
- package/public/icons/app-icon-1024.png +0 -0
- package/public/icons/app-icon-384.png +0 -0
- package/public/icons/favicon-32.png +0 -0
- package/public/icons/favicon-64.png +0 -0
- package/public/icons/favicon-96.png +0 -0
- package/public/icons/favicon.svg +4 -0
- package/public/manifest.webmanifest +24 -0
- package/scripts/nterminalctl +588 -0
package/README.md
ADDED
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# NTerminal
|
|
2
|
+
|
|
3
|
+
<img src="public/icons/app-icon-1024.png" alt="NTerminal app icon" width="96" height="96">
|
|
4
|
+
|
|
5
|
+
NTerminal turns your own machines into one secure browser workspace for real shells, Codex, Claude, files, and long-running terminal sessions.
|
|
6
|
+
|
|
7
|
+
<img src="assets/screenshot/scr.png" alt="NTerminal workspace with split terminal panes" width="100%">
|
|
8
|
+
|
|
9
|
+
NTerminal is a single-owner web terminal for machines you control. It is not a hosted shell product, not a SaaS app, and not a multi-user IDE.
|
|
10
|
+
|
|
11
|
+
## How It Works
|
|
12
|
+
|
|
13
|
+
```text
|
|
14
|
+
Browser
|
|
15
|
+
-> Main Server
|
|
16
|
+
-> Secondary Servers
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
- **Main Server** serves the browser UI, owns login/session security, stores the server list, and proxies terminal/file traffic to secondary servers.
|
|
20
|
+
- **Secondary Servers** run on additional machines and expose their local shells/files to the main server after guided onboarding.
|
|
21
|
+
- Each server is a normal Node.js process connected to real host PTYs through `node-pty`.
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
Clone the repo on the machine that should become the **main server**, then run:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npm run onboarding
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Choose `main`. Onboarding installs dependencies, writes `.env`, creates secrets, sets your password and TOTP, and can build/start the service.
|
|
32
|
+
|
|
33
|
+
To add another machine, clone the repo there and run the same command:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
npm run onboarding
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Choose `secondary`, enter the main server URL, log in once from the CLI, and the server registers itself in the main UI.
|
|
40
|
+
|
|
41
|
+
After onboarding finishes, open the URL printed in the final summary and log in with your password plus authenticator code.
|
|
42
|
+
|
|
43
|
+
See [docs/onboarding.md](docs/onboarding.md) for the full main/secondary setup flow, nginx/TLS automation, and local-only setup.
|
|
44
|
+
|
|
45
|
+
After NTerminal is published to npm, package installs can use:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
npm install -g nterminal
|
|
49
|
+
nterminal onboarding
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Package installs keep runtime config and state under `~/.nterminal` so package updates do not overwrite local sessions or secrets.
|
|
53
|
+
Use a user-writable npm global prefix if you want in-app updates to run without sudo.
|
|
54
|
+
|
|
55
|
+
## Key Features
|
|
56
|
+
|
|
57
|
+
### One Workspace For Multiple Servers
|
|
58
|
+
|
|
59
|
+
- Manage the main server and all secondary servers from one terminal UI.
|
|
60
|
+
- Switch servers from the sidebar without losing terminal layout or pane state.
|
|
61
|
+
- Keep separate tabs, split panes, detached terminals, and file context per server.
|
|
62
|
+
- Run fleet updates from the UI; git checkouts and npm package installs use their own safe update paths.
|
|
63
|
+
|
|
64
|
+
### Secure Personal Access
|
|
65
|
+
|
|
66
|
+
- Password plus TOTP two-factor authentication.
|
|
67
|
+
- Single active session: a new login revokes the previous browser session.
|
|
68
|
+
- Session IP binding with subnet tolerance for common residential/CGNAT rotation.
|
|
69
|
+
- Trusted devices and trusted networks for repeat access from known places.
|
|
70
|
+
- Same-origin cookie and WebSocket checks for terminal/file mutation routes.
|
|
71
|
+
|
|
72
|
+
### Persistent Terminal Workspace
|
|
73
|
+
|
|
74
|
+
- Real host shell PTYs with tabs and split panes.
|
|
75
|
+
- Refresh and temporary WebSocket reconnects reattach to active PTYs.
|
|
76
|
+
- Closing a tab or pane soft-detaches it into a restorable pill instead of killing the shell.
|
|
77
|
+
- Optional tmux-backed PTY persistence keeps shells alive across NTerminal Node restarts.
|
|
78
|
+
- Tab titles sync with tmux window names so labels survive detach/reattach cycles.
|
|
79
|
+
|
|
80
|
+
### Codex / Claude Friendly History
|
|
81
|
+
|
|
82
|
+
- Mouse wheel scrolling moves terminal output history, not Codex/Claude prompt history.
|
|
83
|
+
- Older tmux scrollback loads incrementally when you reach the top.
|
|
84
|
+
- Supported Codex/Claude panes can continue into JSONL transcript history from `~/.codex/sessions` or `~/.claude/projects`.
|
|
85
|
+
- Scroll progress, a jump-to-bottom button, mobile drag handles, and follow-tail behavior keep large outputs usable.
|
|
86
|
+
|
|
87
|
+
### Files, Uploads, And Clipboard
|
|
88
|
+
|
|
89
|
+
- Sidebar file explorer follows the selected pane's working directory.
|
|
90
|
+
- View/edit text and Markdown files, preview browser-supported files, and reject stale overwrites.
|
|
91
|
+
- Drag files or folders into the workspace to upload them into the active pane's cwd.
|
|
92
|
+
- Terminal Ctrl+C copies selected text and falls through to SIGINT when nothing is selected; Ctrl+V pastes clipboard text.
|
|
93
|
+
|
|
94
|
+
### Completion Notifications
|
|
95
|
+
|
|
96
|
+
- In-app completion toasts appear when background commands finish.
|
|
97
|
+
- Toasts can auto-dismiss, stay until dismissed, or use custom MP4/WebM videos.
|
|
98
|
+
- Settings can preview built-in/uploaded videos, enable/disable them, and randomly choose from the enabled set.
|
|
99
|
+
- Clicking a completion toast jumps back to the server and pane that finished.
|
|
100
|
+
- Optional OS notifications are available when the page is hidden.
|
|
101
|
+
|
|
102
|
+
### Mobile And PWA
|
|
103
|
+
|
|
104
|
+
- iPad home-screen metadata and icons are included.
|
|
105
|
+
- Mobile terminal key bar exposes Ctrl, Esc, Tab, and arrows when needed.
|
|
106
|
+
- Touch scrolling controls are tuned for long terminal output.
|
|
107
|
+
|
|
108
|
+
### Simple npm Toolchain
|
|
109
|
+
|
|
110
|
+
- The project uses npm so source checkouts and package installs use the same package manager.
|
|
111
|
+
- `npm run onboarding` runs install automatically on fresh checkouts.
|
|
112
|
+
- The `nterminal` CLI entrypoint is prepared for global npm installs.
|
|
113
|
+
|
|
114
|
+
## Requirements
|
|
115
|
+
|
|
116
|
+
- Node.js 22 or newer.
|
|
117
|
+
- Linux or macOS.
|
|
118
|
+
- Native build tools required by `node-pty`.
|
|
119
|
+
- Optional `tmux` for PTY persistence across Node restarts.
|
|
120
|
+
|
|
121
|
+
If PTY creation fails after install, rebuild the native module:
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
npm rebuild node-pty --build-from-source
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Common Commands
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npm run onboarding
|
|
131
|
+
npm run service:status
|
|
132
|
+
npm run service:logs
|
|
133
|
+
npm run service:restart
|
|
134
|
+
npm test
|
|
135
|
+
npm run build
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
For production-style local operation, `npm run ctl -- <command>` wraps `scripts/nterminalctl` and manages the built server, PID file, logs, health checks, and restarts.
|
|
139
|
+
|
|
140
|
+
## Documentation
|
|
141
|
+
|
|
142
|
+
- [Onboarding](docs/onboarding.md): main/secondary setup, nginx, TLS, firewall, and local-only setup.
|
|
143
|
+
- [Configuration](docs/configuration.md): `.env`, environment variables, and deployment examples.
|
|
144
|
+
- [Operations](docs/operations.md): service control, updates, clean uninstall, verification, and troubleshooting.
|
|
145
|
+
- [Terminal History](docs/terminal-history.md): tmux scrollback, alternate buffer behavior, Codex/Claude JSONL history, and large-output ergonomics.
|
|
146
|
+
- [Features](docs/features.md): files, uploads, notifications, mobile controls, keyboard shortcuts, and PWA behavior.
|
|
147
|
+
- [Security](SECURITY.md): supported security boundary and vulnerability reporting.
|
|
148
|
+
|
|
149
|
+
## Limitations
|
|
150
|
+
|
|
151
|
+
- No multi-user accounts or roles.
|
|
152
|
+
- No container isolation for spawned shells by default.
|
|
153
|
+
- No recovery of live PTYs after an OS reboot.
|
|
154
|
+
- No Node-restart PTY persistence on hosts without `tmux`.
|
|
155
|
+
- No VS Code extension host, debugger, task runner, or Git UI.
|
|
156
|
+
- No package-manager distribution is published yet.
|
|
157
|
+
|
|
158
|
+
## Publication Notes
|
|
159
|
+
|
|
160
|
+
Keep local runtime files out of source control:
|
|
161
|
+
|
|
162
|
+
- `.env`
|
|
163
|
+
- `.env.*` except `.env.example`
|
|
164
|
+
- `.nterminal/`
|
|
165
|
+
- `.claude/`
|
|
166
|
+
- `dist/`
|
|
167
|
+
- logs
|
|
168
|
+
- `test-results/`
|
|
169
|
+
- `playwright-report/`
|
|
170
|
+
|
|
171
|
+
The package metadata is prepared for npm publication. The source code is licensed under GPL-3.0-only.
|
|
172
|
+
|
|
173
|
+
## Acknowledgements
|
|
174
|
+
|
|
175
|
+
NTerminal is inspired by [Mansio](https://github.com/Younkyum/mansio) and [Leominal](https://github.com/jcwleo/leominal).
|
|
176
|
+
|
|
177
|
+
It reworks the persistent browser terminal idea around multi-server operation, OTP and IP-bound sessions, easier onboarding, and a more browser-native terminal experience with smooth scrollback and tab management, aiming to provide a more convenient and safer workspace for developers working across multiple remote servers.
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
NTerminal is licensed under GPL-3.0-only. See [LICENSE](LICENSE).
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64" width="64" height="64">
|
|
2
|
+
<rect width="64" height="64" rx="12" ry="12" fill="#0A0A0B"/>
|
|
3
|
+
<text font-family="'JetBrains Mono', ui-monospace, monospace" font-weight="700" font-size="50" dominant-baseline="middle"><tspan x="-13.00" y="34.56" fill="#FF2A3D">{</tspan><tspan x="17.00" y="34.56" fill="#fff">n</tspan><tspan x="47.00" y="34.56" fill="#FF2A3D">}</tspan></text>
|
|
4
|
+
</svg>
|
|
Binary file
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32">
|
|
2
|
+
<rect width="32" height="32" rx="6" ry="6" fill="#0A0A0B"/>
|
|
3
|
+
<text font-family="'JetBrains Mono', ui-monospace, monospace" font-weight="700" font-size="25" dominant-baseline="middle"><tspan x="-6.50" y="17.28" fill="#FF2A3D">{</tspan><tspan x="8.50" y="17.28" fill="#fff">n</tspan><tspan x="23.50" y="17.28" fill="#FF2A3D">}</tspan></text>
|
|
4
|
+
</svg>
|
|
Binary file
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 243 34" width="243" height="34">
|
|
2
|
+
<text font-family="'JetBrains Mono', ui-monospace, monospace" font-weight="700" font-size="33"><tspan x="0.00" y="28.00" fill="#FF2A3D">{</tspan><tspan x="22.16" y="28.00" fill="#fff">n</tspan><tspan x="41.96" y="28.00" fill="#FF2A3D">·</tspan><tspan x="61.76" y="28.00" fill="#fff">terminal</tspan><tspan x="222.51" y="28.00" fill="#FF2A3D">}</tspan></text>
|
|
3
|
+
</svg>
|
|
Binary file
|
package/bin/nterminal.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import os from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { spawnSync } from 'node:child_process';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const binDir = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const appDir = path.resolve(binDir, '..');
|
|
10
|
+
const packageMode = !existsSync(path.join(appDir, '.git')) && !existsSync(path.join(appDir, 'src'));
|
|
11
|
+
const userStateDir = path.join(os.homedir(), '.nterminal');
|
|
12
|
+
|
|
13
|
+
const [command = 'help', ...args] = process.argv.slice(2);
|
|
14
|
+
|
|
15
|
+
function defaultEnv() {
|
|
16
|
+
const env = {
|
|
17
|
+
...process.env,
|
|
18
|
+
NTERMINAL_APP_DIR: process.env.NTERMINAL_APP_DIR ?? appDir
|
|
19
|
+
};
|
|
20
|
+
if (packageMode) {
|
|
21
|
+
env.NTERMINAL_ENV_FILE ??= path.join(userStateDir, '.env');
|
|
22
|
+
env.NTERMINAL_STATE_PATH ??= path.join(userStateDir, 'state.json');
|
|
23
|
+
env.NTERMINAL_PID_PATH ??= path.join(userStateDir, 'nterminal.pid');
|
|
24
|
+
env.NTERMINAL_LOG_PATH ??= path.join(userStateDir, 'nterminal.log');
|
|
25
|
+
}
|
|
26
|
+
return env;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function run(executable, runArgs) {
|
|
30
|
+
const result = spawnSync(executable, runArgs, {
|
|
31
|
+
cwd: appDir,
|
|
32
|
+
stdio: 'inherit',
|
|
33
|
+
env: defaultEnv()
|
|
34
|
+
});
|
|
35
|
+
process.exit(result.status ?? 1);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function runNode(modulePath, runArgs) {
|
|
39
|
+
run(process.execPath, [modulePath, ...runArgs]);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function runTypeScriptScript(scriptPath, runArgs) {
|
|
43
|
+
run(process.execPath, ['--import', 'tsx', scriptPath, ...runArgs]);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function scriptEntrypoint(name) {
|
|
47
|
+
const built = path.join(appDir, 'dist', 'scripts', `${name}.js`);
|
|
48
|
+
if (existsSync(built)) {
|
|
49
|
+
return { type: 'node', path: built };
|
|
50
|
+
}
|
|
51
|
+
const source = path.join(appDir, 'scripts', `${name}.ts`);
|
|
52
|
+
if (existsSync(source)) {
|
|
53
|
+
return { type: 'tsx', path: source };
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function runScript(name, runArgs) {
|
|
59
|
+
const entrypoint = scriptEntrypoint(name);
|
|
60
|
+
if (!entrypoint) {
|
|
61
|
+
console.error(`error: ${name} entrypoint not found; run npm run build first`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
if (entrypoint.type === 'node') {
|
|
65
|
+
runNode(entrypoint.path, runArgs);
|
|
66
|
+
}
|
|
67
|
+
runTypeScriptScript(entrypoint.path, runArgs);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function runCtl(runArgs) {
|
|
71
|
+
run('bash', [path.join(appDir, 'scripts', 'nterminalctl'), ...runArgs]);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function printHelp() {
|
|
75
|
+
console.log(`Usage: nterminal <command>
|
|
76
|
+
|
|
77
|
+
Commands:
|
|
78
|
+
onboarding Run interactive main/secondary onboarding.
|
|
79
|
+
generate-secrets Print a new NTERMINAL_SESSION_SECRET.
|
|
80
|
+
status Show process status.
|
|
81
|
+
start Start the built server.
|
|
82
|
+
stop Stop the managed server.
|
|
83
|
+
restart Restart the managed server.
|
|
84
|
+
build Build the app.
|
|
85
|
+
deploy npm install/ci, typecheck, build, then restart.
|
|
86
|
+
clean --force Remove local runtime state.
|
|
87
|
+
logs [N] Show recent logs.
|
|
88
|
+
logs -f [N] Follow logs.
|
|
89
|
+
doctor Check local runtime readiness.
|
|
90
|
+
pid Print the running PID.
|
|
91
|
+
url Print the configured local URL.
|
|
92
|
+
help Show this help.
|
|
93
|
+
`);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
switch (command) {
|
|
97
|
+
case 'onboarding':
|
|
98
|
+
runScript('onboarding', args);
|
|
99
|
+
break;
|
|
100
|
+
case 'generate-secrets':
|
|
101
|
+
case 'generate:secrets':
|
|
102
|
+
runScript('generate-secrets', args);
|
|
103
|
+
break;
|
|
104
|
+
case 'ctl':
|
|
105
|
+
runCtl(args);
|
|
106
|
+
break;
|
|
107
|
+
case 'help':
|
|
108
|
+
case '-h':
|
|
109
|
+
case '--help':
|
|
110
|
+
printHelp();
|
|
111
|
+
break;
|
|
112
|
+
default:
|
|
113
|
+
runCtl([command, ...args]);
|
|
114
|
+
}
|
|
Binary file
|