nterminal 1.2.12 → 1.2.14
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/README.md +9 -36
- package/bin/nterminal.js +10 -23
- package/dist/client/assets/{MarkdownPreview-DfZZD0C0.js → MarkdownPreview-DBMjXHXe.js} +1 -1
- package/dist/client/assets/index-BprWaATf.css +1 -0
- package/dist/client/assets/index-DJRitqb8.js +44 -0
- package/dist/client/index.html +2 -2
- package/dist/scripts/onboarding.js +31 -15
- package/dist/scripts/onboarding.js.map +1 -1
- package/dist/scripts/proxySetup.js +4 -1
- package/dist/scripts/proxySetup.js.map +1 -1
- package/dist/server/agent/agentRoutes.js +4 -2
- package/dist/server/agent/agentRoutes.js.map +1 -1
- package/dist/server/auth/cookies.js +0 -8
- package/dist/server/auth/cookies.js.map +1 -1
- package/dist/server/config.js +1 -1
- package/dist/server/config.js.map +1 -1
- package/dist/server/routes/agentManagementRoutes.js +87 -13
- package/dist/server/routes/agentManagementRoutes.js.map +1 -1
- package/dist/server/routes/updateRoutes.js +2 -2
- package/dist/server/routes/updateRoutes.js.map +1 -1
- package/dist/server/update/{gitUpdate.d.ts → packageUpdate.d.ts} +1 -9
- package/dist/server/update/packageUpdate.js +140 -0
- package/dist/server/update/packageUpdate.js.map +1 -0
- package/dist/server/update/runtimeUninstall.d.ts +2 -0
- package/dist/server/update/runtimeUninstall.js +45 -0
- package/dist/server/update/runtimeUninstall.js.map +1 -0
- package/dist/shared/protocol.d.ts +6 -8
- package/dist/shared/protocol.js.map +1 -1
- package/docs/configuration.md +7 -24
- package/docs/features.md +1 -1
- package/docs/onboarding.md +5 -46
- package/docs/operations.md +26 -45
- package/package.json +1 -1
- package/scripts/nterminalctl +93 -57
- package/dist/client/assets/index-CMVGLebq.js +0 -43
- package/dist/client/assets/index-DiQ82H7w.css +0 -1
- package/dist/server/update/gitUpdate.js +0 -241
- package/dist/server/update/gitUpdate.js.map +0 -1
|
@@ -60,6 +60,12 @@ export interface AgentPingResponse {
|
|
|
60
60
|
ok: boolean;
|
|
61
61
|
latencyMs: number;
|
|
62
62
|
}
|
|
63
|
+
export interface AgentUninstallResponse {
|
|
64
|
+
ok: boolean;
|
|
65
|
+
message: string;
|
|
66
|
+
disconnecting: boolean;
|
|
67
|
+
disconnected?: boolean;
|
|
68
|
+
}
|
|
63
69
|
export interface SystemStatsResponse {
|
|
64
70
|
cpuPercent: number | null;
|
|
65
71
|
memoryPercent: number;
|
|
@@ -76,16 +82,8 @@ export interface SystemStatsResponse {
|
|
|
76
82
|
export interface VersionInfo {
|
|
77
83
|
version: string;
|
|
78
84
|
runningVersion: string;
|
|
79
|
-
commit: string | null;
|
|
80
|
-
runningCommit: string | null;
|
|
81
|
-
branch: string | null;
|
|
82
|
-
dirty: boolean;
|
|
83
|
-
isGit: boolean;
|
|
84
|
-
installMode: 'git' | 'package';
|
|
85
85
|
}
|
|
86
86
|
export interface UpdateCheckResponse {
|
|
87
|
-
behind: number | null;
|
|
88
|
-
commit: string | null;
|
|
89
87
|
currentVersion?: string;
|
|
90
88
|
latestVersion?: string | null;
|
|
91
89
|
updateAvailable?: boolean | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/shared/protocol.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/shared/protocol.ts"],"names":[],"mappings":"AAwVA,MAAM,UAAU,0BAA0B,CAAC,GAAW;IACpD,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,OAAO,GAAG,MAAwC,CAAC;QACzD,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO,IAAI,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YAC3G,OAAO,OAAgC,CAAC;QAC1C,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa,IAAI,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YAC7E,OAAO,OAAgC,CAAC;QAC1C,CAAC;QACD,IACE,OAAO,CAAC,IAAI,KAAK,QAAQ;YACzB,OAAO,OAAO,CAAC,UAAU,KAAK,QAAQ;YACtC,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;YAC9B,MAAM,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAC9B,CAAC;YACD,OAAO,OAAgC,CAAC;QAC1C,CAAC;QACD,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;YACjE,OAAO,OAAgC,CAAC;QAC1C,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/docs/configuration.md
CHANGED
|
@@ -4,34 +4,17 @@ Configuration comes from `.env` or process environment variables.
|
|
|
4
4
|
|
|
5
5
|
## `.env.example`
|
|
6
6
|
|
|
7
|
-
`.env.example` is the
|
|
7
|
+
`.env.example` is the runtime template. Keep it in source control, but never commit the copied `.env` file.
|
|
8
8
|
|
|
9
|
-
The template intentionally contains only the core values
|
|
9
|
+
The template intentionally contains only the core values. Add advanced settings from the table below only when you need to override the defaults.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
For manual local setup:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
cp .env.example .env
|
|
17
|
-
npm run generate:secrets
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
Paste the generated `NTERMINAL_SESSION_SECRET=...` value into `.env`.
|
|
21
|
-
|
|
22
|
-
For normal package installs, prefer:
|
|
11
|
+
NTerminal package installs launched through `nterminal` read the runtime env file from `~/.nterminal/.env`.
|
|
23
12
|
|
|
24
13
|
```bash
|
|
25
14
|
nterminal onboarding
|
|
26
15
|
```
|
|
27
16
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
npm run onboarding
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Onboarding writes `.env` for you.
|
|
17
|
+
Onboarding writes `.env` for you, including an absolute `NTERMINAL_STATE_PATH` so password/TOTP state is read from the same file when the service starts.
|
|
35
18
|
|
|
36
19
|
## Settings
|
|
37
20
|
|
|
@@ -41,7 +24,7 @@ Onboarding writes `.env` for you.
|
|
|
41
24
|
| `NTERMINAL_PORT` | `3107` | HTTP server port. |
|
|
42
25
|
| `NTERMINAL_WORKSPACE_ROOT` | home directory | Startup directory for new terminal tabs. |
|
|
43
26
|
| `NTERMINAL_SHELL` | `$SHELL`, then `/bin/bash` | Shell path for new PTYs. |
|
|
44
|
-
| `NTERMINAL_STATE_PATH` |
|
|
27
|
+
| `NTERMINAL_STATE_PATH` | `~/.nterminal/state.json` | Local state file for password and layout data. Onboarding writes an absolute path. |
|
|
45
28
|
| `NTERMINAL_SESSION_SECRET` | required | Server secret for password hashing and session cookies. |
|
|
46
29
|
| `NTERMINAL_SESSION_TTL_SECONDS` | `43200` | Session lifetime in seconds. |
|
|
47
30
|
| `NTERMINAL_COOKIE_SECURE` | `false` locally | Set `true` when serving through HTTPS. |
|
|
@@ -54,8 +37,8 @@ Onboarding writes `.env` for you.
|
|
|
54
37
|
| `NTERMINAL_FILE_LIST_MAX_ENTRIES` | `2000` | Maximum entries returned in one file explorer directory listing. |
|
|
55
38
|
| `NTERMINAL_FILE_TEXT_MAX_BYTES` | `1048576` | Maximum bytes loaded for text or Markdown view/edit. |
|
|
56
39
|
| `NTERMINAL_FILE_PREVIEW_MAX_BYTES` | `52428800` | Maximum bytes served for browser file previews. |
|
|
57
|
-
| `NTERMINAL_PID_PATH` |
|
|
58
|
-
| `NTERMINAL_LOG_PATH` |
|
|
40
|
+
| `NTERMINAL_PID_PATH` | `~/.nterminal/nterminal.pid` | PID file for the control script. |
|
|
41
|
+
| `NTERMINAL_LOG_PATH` | `~/.nterminal/nterminal.log` | Log file for the control script. |
|
|
59
42
|
| `NTERMINAL_HEALTH_TIMEOUT_SECONDS` | `15` | Startup health-check timeout for the control script. |
|
|
60
43
|
| `NTERMINAL_STOP_TIMEOUT_SECONDS` | `20` | Graceful stop timeout for the control script. |
|
|
61
44
|
|
package/docs/features.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
- Each server keeps its own terminal layout, tabs, split panes, detached terminals, and file context.
|
|
18
18
|
- The sidebar switches servers without tearing down the inactive server workspaces.
|
|
19
19
|
- Server cards show CPU, memory, disk, and swap usage with percentages and absolute values.
|
|
20
|
-
- Settings includes an Updates section for checking
|
|
20
|
+
- Settings includes an Updates section for checking npm package updates on each server.
|
|
21
21
|
- Update all runs secondary server updates in parallel first, then updates the main server last.
|
|
22
22
|
- Background update checks run hourly and badge Settings/Updates when an update is available.
|
|
23
23
|
|
package/docs/onboarding.md
CHANGED
|
@@ -2,22 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
NTerminal uses one interactive command for both the main server and secondary servers.
|
|
4
4
|
|
|
5
|
-
For npm package installs:
|
|
6
|
-
|
|
7
5
|
```bash
|
|
8
6
|
npm install -g nterminal
|
|
9
7
|
nterminal onboarding
|
|
10
8
|
```
|
|
11
9
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
For source checkouts:
|
|
15
|
-
|
|
16
|
-
```bash
|
|
17
|
-
npm run onboarding
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
`npm install` runs automatically as the `preonboarding` hook, so a fresh checkout does not need a separate install step.
|
|
10
|
+
NTerminal stores `.env`, state, pid, and log files under `~/.nterminal`. Install with a user-writable npm global prefix so in-app updates can run `npm install -g nterminal@latest` without sudo.
|
|
21
11
|
|
|
22
12
|
## Main Server
|
|
23
13
|
|
|
@@ -33,9 +23,9 @@ The main setup flow:
|
|
|
33
23
|
|
|
34
24
|
1. Picks a bind address and port. The default main bind is `127.0.0.1`, so public traffic goes through the configured reverse proxy instead of bypassing TLS.
|
|
35
25
|
2. Requires a public `https://<domain>` URL for the proxy setup path. Raw IPs, `http://`, `localhost`, and `.local` URLs are rejected in that path.
|
|
36
|
-
3. Writes `.env`, including a generated `NTERMINAL_SESSION_SECRET`.
|
|
26
|
+
3. Writes `.env`, including a generated `NTERMINAL_SESSION_SECRET` and absolute `NTERMINAL_STATE_PATH`.
|
|
37
27
|
4. Sets the login password and enables TOTP headlessly. The CLI prints a terminal QR code, base32 secret, and `otpauth://` URI, then verifies the 6-digit code.
|
|
38
|
-
5. Optionally starts the
|
|
28
|
+
5. Optionally starts the installed package with `nterminal deploy`.
|
|
39
29
|
6. Optionally provisions nginx, DNS verification, firewall rules, and Let's Encrypt TLS.
|
|
40
30
|
|
|
41
31
|
The final summary prints the public URL, internal bind, and next steps.
|
|
@@ -55,10 +45,10 @@ The secondary setup flow:
|
|
|
55
45
|
1. Binds to `0.0.0.0` and picks a free port, preferring `3107`.
|
|
56
46
|
2. Asks for the URL the main server should use to reach this machine.
|
|
57
47
|
3. Asks for a display name.
|
|
58
|
-
4. Generates a session secret and `NTERMINAL_AGENT_TOKEN`, then writes `.env
|
|
48
|
+
4. Generates a session secret and `NTERMINAL_AGENT_TOKEN`, then writes `.env` with an absolute state path.
|
|
59
49
|
5. Prompts for the main server URL, password, and authenticator code.
|
|
60
50
|
6. Registers this secondary server with the main server automatically.
|
|
61
|
-
7. Optionally starts the
|
|
51
|
+
7. Optionally starts the installed package.
|
|
62
52
|
|
|
63
53
|
Onboard the main server first. The main must already have password and TOTP configured before a secondary server can register itself.
|
|
64
54
|
|
|
@@ -84,37 +74,6 @@ Privileged work uses one of two modes:
|
|
|
84
74
|
|
|
85
75
|
The "Main is ready" summary is printed only after the selected setup path has completed its checks.
|
|
86
76
|
|
|
87
|
-
## Local-Only Start
|
|
88
|
-
|
|
89
|
-
For a localhost-only development run without nginx/TLS onboarding:
|
|
90
|
-
|
|
91
|
-
```bash
|
|
92
|
-
npm install
|
|
93
|
-
cp .env.example .env
|
|
94
|
-
npm run generate:secrets
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
Paste the generated value into `.env`:
|
|
98
|
-
|
|
99
|
-
```env
|
|
100
|
-
NTERMINAL_SESSION_SECRET=replace-with-generate-secrets-output
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Then build and start:
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
npm run build
|
|
107
|
-
npm start
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
Open:
|
|
111
|
-
|
|
112
|
-
```text
|
|
113
|
-
http://127.0.0.1:3107
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
On the first visit, set the local NTerminal password and configure TOTP.
|
|
117
|
-
|
|
118
77
|
## Re-Running Onboarding
|
|
119
78
|
|
|
120
79
|
You can re-run onboarding to refresh generated config or register a secondary server again.
|
package/docs/operations.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Local Service Management
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Use the `nterminal` command:
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
nterminal doctor
|
|
@@ -13,69 +13,56 @@ nterminal restart
|
|
|
13
13
|
nterminal stop
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
For source checkouts, use the bundled control script through npm:
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm run ctl -- doctor
|
|
20
|
-
npm run ctl -- build
|
|
21
|
-
npm run ctl -- start
|
|
22
|
-
npm run ctl -- status
|
|
23
|
-
npm run ctl -- logs
|
|
24
|
-
npm run ctl -- restart
|
|
25
|
-
npm run ctl -- stop
|
|
26
|
-
```
|
|
27
|
-
|
|
28
16
|
The script starts the built server in the background, writes a PID file, appends logs, waits for the local health endpoint, and stops the real Node PID so PTY cleanup can run.
|
|
29
17
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
One-command source checkout deploy:
|
|
33
|
-
|
|
34
|
-
```bash
|
|
35
|
-
npm run deploy:local
|
|
36
|
-
```
|
|
18
|
+
Runtime files are kept under `~/.nterminal`.
|
|
37
19
|
|
|
38
20
|
Short aliases:
|
|
39
21
|
|
|
40
22
|
```bash
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
23
|
+
nterminal status
|
|
24
|
+
nterminal start
|
|
25
|
+
nterminal stop
|
|
26
|
+
nterminal restart
|
|
27
|
+
nterminal logs
|
|
46
28
|
```
|
|
47
29
|
|
|
48
30
|
## Updates
|
|
49
31
|
|
|
50
|
-
Each server updates itself
|
|
32
|
+
Each server updates itself as an npm package install.
|
|
51
33
|
|
|
52
34
|
The **updates** panel in the main server sidebar footer can manage the fleet:
|
|
53
35
|
|
|
54
|
-
- **Check for updates**
|
|
55
|
-
- **Update** runs `
|
|
36
|
+
- **Check for updates** checks the npm registry.
|
|
37
|
+
- **Update** runs `npm install -g nterminal@latest` plus restart.
|
|
56
38
|
- **Update all** updates secondary servers in parallel first and the main server last.
|
|
57
39
|
|
|
58
40
|
Notes:
|
|
59
41
|
|
|
60
|
-
- `--ff-only` stops and reports an error when a checkout has local commits or a diverged branch.
|
|
61
42
|
- npm package updates run as the same user that owns the running server process. Use a user-writable npm prefix, not a root-owned global install, if you want UI updates to work without sudo.
|
|
62
|
-
-
|
|
43
|
+
- An npm registry or permission error is reported as an explanatory status.
|
|
63
44
|
- Update endpoints require the same auth boundary as the rest of NTerminal.
|
|
64
45
|
|
|
65
|
-
## Clean
|
|
46
|
+
## Clean Uninstall
|
|
66
47
|
|
|
67
|
-
To
|
|
48
|
+
To remove the local runtime before uninstalling the npm package:
|
|
68
49
|
|
|
69
50
|
```bash
|
|
70
|
-
nterminal
|
|
51
|
+
nterminal uninstall --force
|
|
52
|
+
npm uninstall -g nterminal
|
|
71
53
|
```
|
|
72
54
|
|
|
73
|
-
|
|
74
|
-
|
|
55
|
+
`npm uninstall -g nterminal` cannot run cleanup automatically on modern npm versions. Run `nterminal uninstall --force` first; it stops the managed server, unloads an NTerminal launchd agent when present, kills NTerminal tmux sessions, removes runtime state under `~/.nterminal`, and removes `~/.nterminal/.env`.
|
|
56
|
+
|
|
57
|
+
If you already removed the package while a server is still running, reinstall or use npx to run the cleanup command, then uninstall again:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
npx nterminal@latest uninstall --force
|
|
61
|
+
npm uninstall -g nterminal
|
|
62
|
+
```
|
|
75
63
|
|
|
76
|
-
|
|
64
|
+
Option:
|
|
77
65
|
|
|
78
|
-
- omit `--env` to keep `.env`
|
|
79
66
|
- add `--keep-tmux` to preserve live tmux-backed panes
|
|
80
67
|
|
|
81
68
|
## Verification
|
|
@@ -114,17 +101,11 @@ If native PTY install or startup fails for a package install:
|
|
|
114
101
|
npm explore -g nterminal -- npm rebuild node-pty --build-from-source
|
|
115
102
|
```
|
|
116
103
|
|
|
117
|
-
For source checkouts:
|
|
118
|
-
|
|
119
|
-
```bash
|
|
120
|
-
npm rebuild node-pty --build-from-source
|
|
121
|
-
```
|
|
122
|
-
|
|
123
104
|
If the service script will not start:
|
|
124
105
|
|
|
125
106
|
```bash
|
|
126
|
-
|
|
127
|
-
|
|
107
|
+
nterminal doctor
|
|
108
|
+
nterminal logs
|
|
128
109
|
```
|
|
129
110
|
|
|
130
111
|
If you lose the local NTerminal password, stop the server and remove the local state file at `NTERMINAL_STATE_PATH`. The next browser visit will show the first-run password setup screen again.
|
package/package.json
CHANGED
package/scripts/nterminalctl
CHANGED
|
@@ -4,7 +4,8 @@ set -Eeuo pipefail
|
|
|
4
4
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
5
|
DEFAULT_APP_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
6
6
|
APP_DIR="${NTERMINAL_APP_DIR:-$DEFAULT_APP_DIR}"
|
|
7
|
-
|
|
7
|
+
DEFAULT_RUNTIME_DIR="${HOME:-$APP_DIR}/.nterminal"
|
|
8
|
+
ENV_FILE="${NTERMINAL_ENV_FILE:-$DEFAULT_RUNTIME_DIR/.env}"
|
|
8
9
|
|
|
9
10
|
COMMAND="${1:-help}"
|
|
10
11
|
if [[ $# -gt 0 ]]; then
|
|
@@ -65,13 +66,17 @@ resolve_path() {
|
|
|
65
66
|
|
|
66
67
|
load_env_file
|
|
67
68
|
|
|
69
|
+
DEFAULT_STATE_PATH="$DEFAULT_RUNTIME_DIR/state.json"
|
|
70
|
+
DEFAULT_PID_PATH="$DEFAULT_RUNTIME_DIR/nterminal.pid"
|
|
71
|
+
DEFAULT_LOG_PATH="$DEFAULT_RUNTIME_DIR/nterminal.log"
|
|
72
|
+
|
|
68
73
|
HOST="${NTERMINAL_HOST:-127.0.0.1}"
|
|
69
74
|
PORT="${NTERMINAL_PORT:-3107}"
|
|
70
75
|
NODE_BIN="${NTERMINAL_NODE_BIN:-node}"
|
|
71
76
|
NPM_BIN="${NTERMINAL_NPM_BIN:-npm}"
|
|
72
|
-
PID_PATH="$(resolve_path "${NTERMINAL_PID_PATH
|
|
73
|
-
LOG_PATH="$(resolve_path "${NTERMINAL_LOG_PATH
|
|
74
|
-
STATE_PATH="$(resolve_path "${NTERMINAL_STATE_PATH
|
|
77
|
+
PID_PATH="$(resolve_path "${NTERMINAL_PID_PATH:-${NTERMINAL_RUNTIME_PID_PATH:-$DEFAULT_PID_PATH}}")"
|
|
78
|
+
LOG_PATH="$(resolve_path "${NTERMINAL_LOG_PATH:-${NTERMINAL_RUNTIME_LOG_PATH:-$DEFAULT_LOG_PATH}}")"
|
|
79
|
+
STATE_PATH="$(resolve_path "${NTERMINAL_STATE_PATH:-${NTERMINAL_RUNTIME_STATE_PATH:-$DEFAULT_STATE_PATH}}")"
|
|
75
80
|
HEALTH_TIMEOUT_SECONDS="${NTERMINAL_HEALTH_TIMEOUT_SECONDS:-15}"
|
|
76
81
|
STOP_TIMEOUT_SECONDS="${NTERMINAL_STOP_TIMEOUT_SECONDS:-20}"
|
|
77
82
|
RUNTIME_ENTRY="$APP_DIR/dist/server/index.js"
|
|
@@ -91,6 +96,12 @@ if [[ -n "$UPDATE_LOCK_PATH" ]]; then
|
|
|
91
96
|
trap cleanup_update_lock EXIT
|
|
92
97
|
fi
|
|
93
98
|
|
|
99
|
+
export NTERMINAL_APP_DIR="$APP_DIR"
|
|
100
|
+
export NTERMINAL_ENV_FILE="$ENV_FILE"
|
|
101
|
+
export NTERMINAL_STATE_PATH="$STATE_PATH"
|
|
102
|
+
export NTERMINAL_PID_PATH="$PID_PATH"
|
|
103
|
+
export NTERMINAL_LOG_PATH="$LOG_PATH"
|
|
104
|
+
|
|
94
105
|
health_url() {
|
|
95
106
|
printf 'http://%s:%s/api/auth/session' "$HOST" "$PORT"
|
|
96
107
|
}
|
|
@@ -103,16 +114,8 @@ ensure_app_dir() {
|
|
|
103
114
|
[[ -d "$APP_DIR" ]] || die "app directory not found: $APP_DIR"
|
|
104
115
|
}
|
|
105
116
|
|
|
106
|
-
is_source_checkout() {
|
|
107
|
-
[[ -f "$APP_DIR/tsconfig.server.json" && -d "$APP_DIR/src" ]]
|
|
108
|
-
}
|
|
109
|
-
|
|
110
117
|
missing_env_message() {
|
|
111
|
-
|
|
112
|
-
printf '.env not found at %s; copy .env.example and run npm run generate:secrets' "$ENV_FILE"
|
|
113
|
-
else
|
|
114
|
-
printf '.env not found at %s; run nterminal onboarding' "$ENV_FILE"
|
|
115
|
-
fi
|
|
118
|
+
printf '.env not found at %s; run nterminal onboarding' "$ENV_FILE"
|
|
116
119
|
}
|
|
117
120
|
|
|
118
121
|
ensure_env_file() {
|
|
@@ -123,9 +126,6 @@ ensure_runtime() {
|
|
|
123
126
|
if [[ -f "$RUNTIME_ENTRY" ]]; then
|
|
124
127
|
return 0
|
|
125
128
|
fi
|
|
126
|
-
if is_source_checkout; then
|
|
127
|
-
die "dist/server/index.js not found; run scripts/nterminalctl build first"
|
|
128
|
-
fi
|
|
129
129
|
die "dist/server/index.js not found; reinstall nterminal"
|
|
130
130
|
}
|
|
131
131
|
|
|
@@ -198,6 +198,31 @@ launchd_controls_app() {
|
|
|
198
198
|
esac
|
|
199
199
|
}
|
|
200
200
|
|
|
201
|
+
launchd_agent_plist() {
|
|
202
|
+
local home_dir="${HOME:-}"
|
|
203
|
+
[[ -n "$home_dir" ]] || return 1
|
|
204
|
+
printf '%s/Library/LaunchAgents/%s.plist' "$home_dir" "$LAUNCHD_LABEL"
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
unload_launchd_if_controlled() {
|
|
208
|
+
launchd_controls_app || return 0
|
|
209
|
+
local domain
|
|
210
|
+
domain="$(launchd_domain)" || return 0
|
|
211
|
+
launchctl bootout "$domain" >/dev/null 2>&1 || launchctl remove "$LAUNCHD_LABEL" >/dev/null 2>&1 || true
|
|
212
|
+
rm -f "$PID_PATH"
|
|
213
|
+
info "NTerminal launchd agent unloaded label=$LAUNCHD_LABEL"
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
remove_owned_launchd_plist() {
|
|
217
|
+
local plist
|
|
218
|
+
plist="$(launchd_agent_plist || true)"
|
|
219
|
+
[[ -n "$plist" && -f "$plist" ]] || return 0
|
|
220
|
+
if grep -F "$APP_DIR" "$plist" >/dev/null 2>&1; then
|
|
221
|
+
rm -f "$plist"
|
|
222
|
+
info "NTerminal launchd plist removed path=$plist"
|
|
223
|
+
fi
|
|
224
|
+
}
|
|
225
|
+
|
|
201
226
|
remove_stale_pid() {
|
|
202
227
|
local pid
|
|
203
228
|
pid="$(read_pid || true)"
|
|
@@ -371,37 +396,14 @@ cmd_restart() {
|
|
|
371
396
|
|
|
372
397
|
cmd_build() {
|
|
373
398
|
ensure_app_dir
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
info "Package install uses bundled dist; no build needed."
|
|
377
|
-
return 0
|
|
378
|
-
fi
|
|
379
|
-
(
|
|
380
|
-
cd "$APP_DIR"
|
|
381
|
-
"$NPM_BIN" run build
|
|
382
|
-
)
|
|
399
|
+
ensure_runtime
|
|
400
|
+
info "Package install uses bundled dist; no build needed."
|
|
383
401
|
}
|
|
384
402
|
|
|
385
403
|
cmd_deploy() {
|
|
386
404
|
ensure_app_dir
|
|
387
405
|
ensure_env_file
|
|
388
|
-
|
|
389
|
-
cd "$APP_DIR"
|
|
390
|
-
if is_source_checkout && [[ -f package-lock.json ]]; then
|
|
391
|
-
"$NPM_BIN" ci
|
|
392
|
-
elif is_source_checkout; then
|
|
393
|
-
"$NPM_BIN" install
|
|
394
|
-
fi
|
|
395
|
-
if is_source_checkout; then
|
|
396
|
-
"$NPM_BIN" run typecheck
|
|
397
|
-
# node-pty's install script always compiles from source (no prebuilt
|
|
398
|
-
# download); ask npm to rebuild it explicitly after dependency updates.
|
|
399
|
-
"$NPM_BIN" rebuild node-pty --build-from-source
|
|
400
|
-
"$NPM_BIN" run build
|
|
401
|
-
else
|
|
402
|
-
ensure_runtime
|
|
403
|
-
fi
|
|
404
|
-
)
|
|
406
|
+
ensure_runtime
|
|
405
407
|
cmd_restart
|
|
406
408
|
}
|
|
407
409
|
|
|
@@ -453,15 +455,10 @@ clean_state_paths() {
|
|
|
453
455
|
local state_path="$1"
|
|
454
456
|
local pid_path="$2"
|
|
455
457
|
local log_path="$3"
|
|
456
|
-
local default_state_dir="$4"
|
|
457
458
|
local state_dir
|
|
458
459
|
state_dir="$(dirname "$state_path")"
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
else
|
|
462
|
-
rm -f "$state_path" "$pid_path" "$log_path" "$state_dir/update.lock"
|
|
463
|
-
rm -rf "$state_dir/notification-assets"
|
|
464
|
-
fi
|
|
460
|
+
rm -f "$state_path" "$pid_path" "$log_path" "$state_dir/update.lock"
|
|
461
|
+
rm -rf "$state_dir/notification-assets"
|
|
465
462
|
}
|
|
466
463
|
|
|
467
464
|
cmd_clean() {
|
|
@@ -479,7 +476,7 @@ cmd_clean() {
|
|
|
479
476
|
done
|
|
480
477
|
|
|
481
478
|
if (( force != 1 )); then
|
|
482
|
-
die "clean is destructive; rerun with:
|
|
479
|
+
die "clean is destructive; rerun with: $(control_command clean) --force [--env] [--keep-tmux]"
|
|
483
480
|
fi
|
|
484
481
|
|
|
485
482
|
ensure_app_dir
|
|
@@ -490,7 +487,7 @@ cmd_clean() {
|
|
|
490
487
|
|
|
491
488
|
local state_dir
|
|
492
489
|
state_dir="$(dirname "$STATE_PATH")"
|
|
493
|
-
clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH"
|
|
490
|
+
clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH"
|
|
494
491
|
if (( remove_env == 1 )); then
|
|
495
492
|
rm -f "$ENV_FILE"
|
|
496
493
|
fi
|
|
@@ -498,6 +495,41 @@ cmd_clean() {
|
|
|
498
495
|
info "NTerminal cleaned state_dir=$state_dir env_removed=$remove_env tmux_killed=$kill_tmux"
|
|
499
496
|
}
|
|
500
497
|
|
|
498
|
+
cmd_uninstall() {
|
|
499
|
+
local force=0
|
|
500
|
+
local kill_tmux=1
|
|
501
|
+
while [[ $# -gt 0 ]]; do
|
|
502
|
+
case "$1" in
|
|
503
|
+
--force) force=1 ;;
|
|
504
|
+
--keep-tmux) kill_tmux=0 ;;
|
|
505
|
+
*) die "unknown uninstall option: $1" ;;
|
|
506
|
+
esac
|
|
507
|
+
shift
|
|
508
|
+
done
|
|
509
|
+
|
|
510
|
+
if (( force != 1 )); then
|
|
511
|
+
die "uninstall is destructive; rerun with: $(control_command uninstall) --force [--keep-tmux]"
|
|
512
|
+
fi
|
|
513
|
+
|
|
514
|
+
ensure_app_dir
|
|
515
|
+
unload_launchd_if_controlled
|
|
516
|
+
stop_pid_file "$PID_PATH"
|
|
517
|
+
if (( kill_tmux == 1 )) && command -v tmux >/dev/null 2>&1; then
|
|
518
|
+
tmux -L nterminal kill-server >/dev/null 2>&1 || true
|
|
519
|
+
fi
|
|
520
|
+
clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH"
|
|
521
|
+
rm -f "$ENV_FILE"
|
|
522
|
+
remove_owned_launchd_plist
|
|
523
|
+
|
|
524
|
+
info "NTerminal runtime uninstalled state_dir=$(dirname "$STATE_PATH") env_removed=1 tmux_killed=$kill_tmux"
|
|
525
|
+
info "Package files are still installed. To remove them, run: npm uninstall -g nterminal"
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
control_command() {
|
|
529
|
+
local command="$1"
|
|
530
|
+
printf 'nterminal %s' "$command"
|
|
531
|
+
}
|
|
532
|
+
|
|
501
533
|
cmd_pid() {
|
|
502
534
|
local pid
|
|
503
535
|
pid="$(current_pid || true)"
|
|
@@ -568,17 +600,20 @@ cmd_doctor() {
|
|
|
568
600
|
|
|
569
601
|
cmd_help() {
|
|
570
602
|
cat <<EOF
|
|
571
|
-
Usage:
|
|
603
|
+
Usage: nterminal <command>
|
|
572
604
|
|
|
573
605
|
Commands:
|
|
574
606
|
status Show process status. Exit 0 when running, 3 when stopped.
|
|
575
607
|
start Start the built server in the background.
|
|
576
608
|
stop Stop the managed server with SIGTERM, then SIGKILL after timeout.
|
|
577
609
|
restart Stop and start the server.
|
|
578
|
-
build
|
|
579
|
-
deploy
|
|
610
|
+
build No-op for package installs; verifies the bundled runtime exists.
|
|
611
|
+
deploy Restart the installed package using the bundled runtime.
|
|
580
612
|
clean --force Stop server, kill NTerminal tmux sessions, and remove local state/log/pid files.
|
|
581
613
|
Add --env to also remove .env. Add --keep-tmux to preserve live panes.
|
|
614
|
+
uninstall --force
|
|
615
|
+
Stop server, unload NTerminal launchd agent, remove local runtime files and .env.
|
|
616
|
+
Add --keep-tmux to preserve live panes.
|
|
582
617
|
logs [N] Show the last N log lines. Default: 100.
|
|
583
618
|
logs -f [N] Follow logs.
|
|
584
619
|
doctor Check Node/npm/env/runtime/pid/log/port readiness.
|
|
@@ -589,9 +624,9 @@ Commands:
|
|
|
589
624
|
Environment:
|
|
590
625
|
NTERMINAL_APP_DIR Override app directory.
|
|
591
626
|
NTERMINAL_ENV_FILE Override .env path.
|
|
592
|
-
NTERMINAL_STATE_PATH Default
|
|
593
|
-
NTERMINAL_PID_PATH Default
|
|
594
|
-
NTERMINAL_LOG_PATH Default
|
|
627
|
+
NTERMINAL_STATE_PATH Default ~/.nterminal/state.json.
|
|
628
|
+
NTERMINAL_PID_PATH Default ~/.nterminal/nterminal.pid.
|
|
629
|
+
NTERMINAL_LOG_PATH Default ~/.nterminal/nterminal.log.
|
|
595
630
|
NTERMINAL_HEALTH_TIMEOUT_SECONDS Default 15.
|
|
596
631
|
NTERMINAL_STOP_TIMEOUT_SECONDS Default 20.
|
|
597
632
|
NTERMINAL_LAUNCHD_LABEL Default com.nterminal.local. Used when a loaded LaunchAgent controls this app.
|
|
@@ -606,6 +641,7 @@ case "$COMMAND" in
|
|
|
606
641
|
build) cmd_build "$@" ;;
|
|
607
642
|
deploy) cmd_deploy "$@" ;;
|
|
608
643
|
clean|purge) cmd_clean "$@" ;;
|
|
644
|
+
uninstall|remove) cmd_uninstall "$@" ;;
|
|
609
645
|
logs|log) cmd_logs "$@" ;;
|
|
610
646
|
doctor) cmd_doctor "$@" ;;
|
|
611
647
|
pid) cmd_pid "$@" ;;
|