nterminal 1.2.13 → 1.2.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/README.md +7 -34
  2. package/bin/nterminal.js +10 -23
  3. package/dist/client/assets/{MarkdownPreview-DfZZD0C0.js → MarkdownPreview-CPwwNmWh.js} +1 -1
  4. package/dist/client/assets/index-B3-WG4Tf.css +1 -0
  5. package/dist/client/assets/index-BgwRhgr0.js +44 -0
  6. package/dist/client/index.html +2 -2
  7. package/dist/scripts/onboarding.js +26 -57
  8. package/dist/scripts/onboarding.js.map +1 -1
  9. package/dist/scripts/proxySetup.js +1 -5
  10. package/dist/scripts/proxySetup.js.map +1 -1
  11. package/dist/server/agent/agentRoutes.d.ts +2 -0
  12. package/dist/server/agent/agentRoutes.js +22 -4
  13. package/dist/server/agent/agentRoutes.js.map +1 -1
  14. package/dist/server/auth/cookies.js +0 -8
  15. package/dist/server/auth/cookies.js.map +1 -1
  16. package/dist/server/config.js +1 -1
  17. package/dist/server/config.js.map +1 -1
  18. package/dist/server/routes/agentManagementRoutes.js +111 -23
  19. package/dist/server/routes/agentManagementRoutes.js.map +1 -1
  20. package/dist/server/routes/updateRoutes.d.ts +2 -0
  21. package/dist/server/routes/updateRoutes.js +16 -4
  22. package/dist/server/routes/updateRoutes.js.map +1 -1
  23. package/dist/server/storage/fileStore.d.ts +3 -0
  24. package/dist/server/storage/fileStore.js +22 -2
  25. package/dist/server/storage/fileStore.js.map +1 -1
  26. package/dist/server/terminal/TerminalManager.js +5 -1
  27. package/dist/server/terminal/TerminalManager.js.map +1 -1
  28. package/dist/server/update/manualUpdateState.d.ts +5 -0
  29. package/dist/server/update/manualUpdateState.js +13 -0
  30. package/dist/server/update/manualUpdateState.js.map +1 -0
  31. package/dist/server/update/packageUpdate.d.ts +23 -0
  32. package/dist/server/update/packageUpdate.js +181 -0
  33. package/dist/server/update/packageUpdate.js.map +1 -0
  34. package/dist/server/update/runtimeUninstall.d.ts +2 -0
  35. package/dist/server/update/runtimeUninstall.js +45 -0
  36. package/dist/server/update/runtimeUninstall.js.map +1 -0
  37. package/dist/shared/protocol.d.ts +14 -8
  38. package/dist/shared/protocol.js.map +1 -1
  39. package/docs/configuration.md +6 -23
  40. package/docs/features.md +1 -1
  41. package/docs/onboarding.md +3 -44
  42. package/docs/operations.md +26 -45
  43. package/package.json +1 -1
  44. package/scripts/nterminalctl +112 -71
  45. package/dist/client/assets/index-CMVGLebq.js +0 -43
  46. package/dist/client/assets/index-DiQ82H7w.css +0 -1
  47. package/dist/server/update/gitUpdate.d.ts +0 -27
  48. package/dist/server/update/gitUpdate.js +0 -241
  49. package/dist/server/update/gitUpdate.js.map +0 -1
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Local Service Management
4
4
 
5
- For production-style local operation from an npm package install, use the `nterminal` command:
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
- Source checkouts keep runtime files in the repository's `.nterminal/` directory by default. npm package installs launched through `nterminal` keep runtime files under `~/.nterminal`.
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
- npm run service:status
42
- npm run service:start
43
- npm run service:stop
44
- npm run service:restart
45
- npm run service:logs
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 with the method used to install it.
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** runs `git fetch` for git checkouts, or checks the npm registry for package installs.
55
- - **Update** runs `git pull --ff-only` plus rebuild/restart for git checkouts, or `npm install -g nterminal@latest` plus restart for package installs.
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
- - A git checkout with no upstream branch, or an npm registry/permission error, is reported as an explanatory status.
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 Local State
46
+ ## Clean Uninstall
66
47
 
67
- To clean a local install before reinstalling:
48
+ To remove the local runtime before uninstalling the npm package:
68
49
 
69
50
  ```bash
70
- nterminal clean --force --env
51
+ nterminal uninstall --force
52
+ npm uninstall -g nterminal
71
53
  ```
72
54
 
73
- This stops the managed server, kills NTerminal tmux sessions, removes runtime state under `~/.nterminal`, and removes `~/.nterminal/.env`.
74
- In a source checkout, run the same command as `npm run ctl -- clean --force --env`.
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
- Options:
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
- npm run ctl -- doctor
127
- npm run ctl -- logs
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nterminal",
3
- "version": "1.2.13",
3
+ "version": "1.2.15",
4
4
  "license": "GPL-3.0-only",
5
5
  "type": "module",
6
6
  "packageManager": "npm@10.9.7",
@@ -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
- ENV_FILE="${NTERMINAL_ENV_FILE:-$APP_DIR/.env}"
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,16 +66,9 @@ resolve_path() {
65
66
 
66
67
  load_env_file
67
68
 
68
- if [[ -f "$APP_DIR/tsconfig.server.json" && -d "$APP_DIR/src" ]]; then
69
- DEFAULT_STATE_PATH=".nterminal/state.json"
70
- DEFAULT_PID_PATH=".nterminal/nterminal.pid"
71
- DEFAULT_LOG_PATH=".nterminal/nterminal.log"
72
- else
73
- DEFAULT_RUNTIME_DIR="${HOME:-$APP_DIR}/.nterminal"
74
- DEFAULT_STATE_PATH="$DEFAULT_RUNTIME_DIR/state.json"
75
- DEFAULT_PID_PATH="$DEFAULT_RUNTIME_DIR/nterminal.pid"
76
- DEFAULT_LOG_PATH="$DEFAULT_RUNTIME_DIR/nterminal.log"
77
- fi
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"
78
72
 
79
73
  HOST="${NTERMINAL_HOST:-127.0.0.1}"
80
74
  PORT="${NTERMINAL_PORT:-3107}"
@@ -120,16 +114,8 @@ ensure_app_dir() {
120
114
  [[ -d "$APP_DIR" ]] || die "app directory not found: $APP_DIR"
121
115
  }
122
116
 
123
- is_source_checkout() {
124
- [[ -f "$APP_DIR/tsconfig.server.json" && -d "$APP_DIR/src" ]]
125
- }
126
-
127
117
  missing_env_message() {
128
- if is_source_checkout; then
129
- printf '.env not found at %s; copy .env.example and run npm run generate:secrets' "$ENV_FILE"
130
- else
131
- printf '.env not found at %s; run nterminal onboarding' "$ENV_FILE"
132
- fi
118
+ printf '.env not found at %s; run nterminal onboarding' "$ENV_FILE"
133
119
  }
134
120
 
135
121
  ensure_env_file() {
@@ -140,9 +126,6 @@ ensure_runtime() {
140
126
  if [[ -f "$RUNTIME_ENTRY" ]]; then
141
127
  return 0
142
128
  fi
143
- if is_source_checkout; then
144
- die "dist/server/index.js not found; run scripts/nterminalctl build first"
145
- fi
146
129
  die "dist/server/index.js not found; reinstall nterminal"
147
130
  }
148
131
 
@@ -183,10 +166,38 @@ is_running() {
183
166
  kill -0 "$pid" 2>/dev/null
184
167
  }
185
168
 
169
+ pid_controls_app() {
170
+ local pid="$1"
171
+ is_running "$pid" || return 1
172
+
173
+ local cmdline=""
174
+ if [[ -r "/proc/$pid/cmdline" ]]; then
175
+ cmdline="$(tr '\0' ' ' < "/proc/$pid/cmdline" 2>/dev/null || true)"
176
+ local cwd=""
177
+ cwd="$(readlink "/proc/$pid/cwd" 2>/dev/null || true)"
178
+ if [[ "$cmdline" == *"$RUNTIME_ENTRY"* ]]; then
179
+ [[ -z "$cwd" || "$cwd" == "$APP_DIR" ]] || return 1
180
+ return 0
181
+ fi
182
+ if [[ "$cwd" == "$APP_DIR" && "$cmdline" == *"dist/server/index.js"* ]]; then
183
+ return 0
184
+ fi
185
+ return 1
186
+ fi
187
+
188
+ if command -v ps >/dev/null 2>&1; then
189
+ cmdline="$(ps -p "$pid" -o command= 2>/dev/null || true)"
190
+ [[ "$cmdline" == *"$RUNTIME_ENTRY"* ]]
191
+ return
192
+ fi
193
+
194
+ return 1
195
+ }
196
+
186
197
  current_pid() {
187
198
  local pid
188
199
  pid="$(read_pid || true)"
189
- if [[ -n "$pid" && "$(is_running "$pid" && echo yes || echo no)" == yes ]]; then
200
+ if [[ -n "$pid" && "$(pid_controls_app "$pid" && echo yes || echo no)" == yes ]]; then
190
201
  printf '%s' "$pid"
191
202
  return 0
192
203
  fi
@@ -215,10 +226,35 @@ launchd_controls_app() {
215
226
  esac
216
227
  }
217
228
 
229
+ launchd_agent_plist() {
230
+ local home_dir="${HOME:-}"
231
+ [[ -n "$home_dir" ]] || return 1
232
+ printf '%s/Library/LaunchAgents/%s.plist' "$home_dir" "$LAUNCHD_LABEL"
233
+ }
234
+
235
+ unload_launchd_if_controlled() {
236
+ launchd_controls_app || return 0
237
+ local domain
238
+ domain="$(launchd_domain)" || return 0
239
+ launchctl bootout "$domain" >/dev/null 2>&1 || launchctl remove "$LAUNCHD_LABEL" >/dev/null 2>&1 || true
240
+ rm -f "$PID_PATH"
241
+ info "NTerminal launchd agent unloaded label=$LAUNCHD_LABEL"
242
+ }
243
+
244
+ remove_owned_launchd_plist() {
245
+ local plist
246
+ plist="$(launchd_agent_plist || true)"
247
+ [[ -n "$plist" && -f "$plist" ]] || return 0
248
+ if grep -F "$APP_DIR" "$plist" >/dev/null 2>&1; then
249
+ rm -f "$plist"
250
+ info "NTerminal launchd plist removed path=$plist"
251
+ fi
252
+ }
253
+
218
254
  remove_stale_pid() {
219
255
  local pid
220
256
  pid="$(read_pid || true)"
221
- if [[ -n "$pid" && ! "$(is_running "$pid" && echo yes || echo no)" == yes ]]; then
257
+ if [[ -n "$pid" && ! "$(pid_controls_app "$pid" && echo yes || echo no)" == yes ]]; then
222
258
  rm -f "$PID_PATH"
223
259
  fi
224
260
  }
@@ -388,37 +424,14 @@ cmd_restart() {
388
424
 
389
425
  cmd_build() {
390
426
  ensure_app_dir
391
- if ! is_source_checkout; then
392
- ensure_runtime
393
- info "Package install uses bundled dist; no build needed."
394
- return 0
395
- fi
396
- (
397
- cd "$APP_DIR"
398
- "$NPM_BIN" run build
399
- )
427
+ ensure_runtime
428
+ info "Package install uses bundled dist; no build needed."
400
429
  }
401
430
 
402
431
  cmd_deploy() {
403
432
  ensure_app_dir
404
433
  ensure_env_file
405
- (
406
- cd "$APP_DIR"
407
- if is_source_checkout && [[ -f package-lock.json ]]; then
408
- "$NPM_BIN" ci
409
- elif is_source_checkout; then
410
- "$NPM_BIN" install
411
- fi
412
- if is_source_checkout; then
413
- "$NPM_BIN" run typecheck
414
- # node-pty's install script always compiles from source (no prebuilt
415
- # download); ask npm to rebuild it explicitly after dependency updates.
416
- "$NPM_BIN" rebuild node-pty --build-from-source
417
- "$NPM_BIN" run build
418
- else
419
- ensure_runtime
420
- fi
421
- )
434
+ ensure_runtime
422
435
  cmd_restart
423
436
  }
424
437
 
@@ -451,6 +464,10 @@ stop_pid_file() {
451
464
  rm -f "$pid_path"
452
465
  return 0
453
466
  fi
467
+ if ! pid_controls_app "$pid"; then
468
+ rm -f "$pid_path"
469
+ return 0
470
+ fi
454
471
 
455
472
  kill -TERM "$pid" 2>/dev/null || true
456
473
  local deadline=$((SECONDS + STOP_TIMEOUT_SECONDS))
@@ -470,16 +487,10 @@ clean_state_paths() {
470
487
  local state_path="$1"
471
488
  local pid_path="$2"
472
489
  local log_path="$3"
473
- local default_state_dir="$4"
474
490
  local state_dir
475
491
  state_dir="$(dirname "$state_path")"
476
- if [[ "$state_dir" == "$default_state_dir" ]]; then
477
- rm -rf "$state_dir"
478
- else
479
- rm -f "$state_path" "$pid_path" "$log_path" "$state_dir/update.lock"
480
- rm -rf "$state_dir/notification-assets"
481
- rm -rf "$default_state_dir"
482
- fi
492
+ rm -f "$state_path" "$pid_path" "$log_path" "$state_dir/update.lock"
493
+ rm -rf "$state_dir/notification-assets"
483
494
  }
484
495
 
485
496
  cmd_clean() {
@@ -508,7 +519,7 @@ cmd_clean() {
508
519
 
509
520
  local state_dir
510
521
  state_dir="$(dirname "$STATE_PATH")"
511
- clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH" "$APP_DIR/.nterminal"
522
+ clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH"
512
523
  if (( remove_env == 1 )); then
513
524
  rm -f "$ENV_FILE"
514
525
  fi
@@ -516,13 +527,39 @@ cmd_clean() {
516
527
  info "NTerminal cleaned state_dir=$state_dir env_removed=$remove_env tmux_killed=$kill_tmux"
517
528
  }
518
529
 
530
+ cmd_uninstall() {
531
+ local force=0
532
+ local kill_tmux=1
533
+ while [[ $# -gt 0 ]]; do
534
+ case "$1" in
535
+ --force) force=1 ;;
536
+ --keep-tmux) kill_tmux=0 ;;
537
+ *) die "unknown uninstall option: $1" ;;
538
+ esac
539
+ shift
540
+ done
541
+
542
+ if (( force != 1 )); then
543
+ die "uninstall is destructive; rerun with: $(control_command uninstall) --force [--keep-tmux]"
544
+ fi
545
+
546
+ ensure_app_dir
547
+ unload_launchd_if_controlled
548
+ stop_pid_file "$PID_PATH"
549
+ if (( kill_tmux == 1 )) && command -v tmux >/dev/null 2>&1; then
550
+ tmux -L nterminal kill-server >/dev/null 2>&1 || true
551
+ fi
552
+ clean_state_paths "$STATE_PATH" "$PID_PATH" "$LOG_PATH"
553
+ rm -f "$ENV_FILE"
554
+ remove_owned_launchd_plist
555
+
556
+ info "NTerminal runtime uninstalled state_dir=$(dirname "$STATE_PATH") env_removed=1 tmux_killed=$kill_tmux"
557
+ info "Package files are still installed. To remove them, run: npm uninstall -g nterminal"
558
+ }
559
+
519
560
  control_command() {
520
561
  local command="$1"
521
- if is_source_checkout; then
522
- printf 'scripts/nterminalctl %s' "$command"
523
- else
524
- printf 'nterminal %s' "$command"
525
- fi
562
+ printf 'nterminal %s' "$command"
526
563
  }
527
564
 
528
565
  cmd_pid() {
@@ -595,17 +632,20 @@ cmd_doctor() {
595
632
 
596
633
  cmd_help() {
597
634
  cat <<EOF
598
- Usage: scripts/nterminalctl <command>
635
+ Usage: nterminal <command>
599
636
 
600
637
  Commands:
601
638
  status Show process status. Exit 0 when running, 3 when stopped.
602
639
  start Start the built server in the background.
603
640
  stop Stop the managed server with SIGTERM, then SIGKILL after timeout.
604
641
  restart Stop and start the server.
605
- build Build source checkouts. Package installs use bundled dist.
606
- deploy Build source checkouts when needed, then restart.
642
+ build No-op for package installs; verifies the bundled runtime exists.
643
+ deploy Restart the installed package using the bundled runtime.
607
644
  clean --force Stop server, kill NTerminal tmux sessions, and remove local state/log/pid files.
608
645
  Add --env to also remove .env. Add --keep-tmux to preserve live panes.
646
+ uninstall --force
647
+ Stop server, unload NTerminal launchd agent, remove local runtime files and .env.
648
+ Add --keep-tmux to preserve live panes.
609
649
  logs [N] Show the last N log lines. Default: 100.
610
650
  logs -f [N] Follow logs.
611
651
  doctor Check Node/npm/env/runtime/pid/log/port readiness.
@@ -616,9 +656,9 @@ Commands:
616
656
  Environment:
617
657
  NTERMINAL_APP_DIR Override app directory.
618
658
  NTERMINAL_ENV_FILE Override .env path.
619
- NTERMINAL_STATE_PATH Default .nterminal/state.json.
620
- NTERMINAL_PID_PATH Default .nterminal/nterminal.pid.
621
- NTERMINAL_LOG_PATH Default .nterminal/nterminal.log.
659
+ NTERMINAL_STATE_PATH Default ~/.nterminal/state.json.
660
+ NTERMINAL_PID_PATH Default ~/.nterminal/nterminal.pid.
661
+ NTERMINAL_LOG_PATH Default ~/.nterminal/nterminal.log.
622
662
  NTERMINAL_HEALTH_TIMEOUT_SECONDS Default 15.
623
663
  NTERMINAL_STOP_TIMEOUT_SECONDS Default 20.
624
664
  NTERMINAL_LAUNCHD_LABEL Default com.nterminal.local. Used when a loaded LaunchAgent controls this app.
@@ -633,6 +673,7 @@ case "$COMMAND" in
633
673
  build) cmd_build "$@" ;;
634
674
  deploy) cmd_deploy "$@" ;;
635
675
  clean|purge) cmd_clean "$@" ;;
676
+ uninstall|remove) cmd_uninstall "$@" ;;
636
677
  logs|log) cmd_logs "$@" ;;
637
678
  doctor) cmd_doctor "$@" ;;
638
679
  pid) cmd_pid "$@" ;;