trooper-cli 0.1.5 → 0.1.6

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 CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Official command-line installer for Trooper's local desktop runtime.
4
4
 
5
- Trooper can run on your own Mac without a hosted cloud computer. This CLI installs the local bridge, starts the local AI gateway, and lets the Trooper desktop app pair the machine to your workspace.
5
+ Trooper can run on your own Mac without a hosted cloud computer. This CLI installs the local bridge, starts the local AI gateway, installs the Trooper desktop app when it is missing, and opens Trooper so the machine can pair to your workspace.
6
6
 
7
7
  ## Quick Start
8
8
 
@@ -12,7 +12,7 @@ Install Trooper locally on this Mac:
12
12
  npx -y trooper-cli
13
13
  ```
14
14
 
15
- Then open the Trooper desktop app to connect this computer to your workspace.
15
+ The command opens the Trooper desktop app when setup finishes.
16
16
 
17
17
  ## What It Sets Up
18
18
 
@@ -23,6 +23,7 @@ On macOS, `npx -y trooper-cli` prepares:
23
23
  - LaunchAgents so the local host can keep running
24
24
  - A Docker-compatible runtime using existing Docker or Colima when needed
25
25
  - Local runtime files under `~/Library/Application Support/Trooper/runtime`
26
+ - Trooper.app in `~/Applications` when the desktop app is not already installed
26
27
 
27
28
  The local desktop plan does not require a Trooper cloud computer or Stripe checkout.
28
29
 
@@ -40,6 +41,12 @@ This is shorthand for:
40
41
  npx -y trooper-cli onboard --yes
41
42
  ```
42
43
 
44
+ Install only the runtime and skip desktop app install/open:
45
+
46
+ ```bash
47
+ npx -y trooper-cli --skip-app
48
+ ```
49
+
43
50
  ### Install with a Trooper setup token
44
51
 
45
52
  The Trooper app may generate a short-lived setup token for workspace pairing:
@@ -85,7 +92,7 @@ npx -y --prefer-online trooper-cli@latest uninstall --yes --remove-app
85
92
 
86
93
  ## Desktop App
87
94
 
88
- Local desktop install is meant to be started from the Trooper Mac or Windows app. The web onboarding page shows the plan, but only the desktop app can safely launch the local helper installer.
95
+ The CLI installs and opens the Trooper Mac app automatically when it is missing. If the app is already installed in `~/Applications`, `/Applications`, or registered with Launch Services, the CLI opens the existing app instead of downloading it again.
89
96
 
90
97
  ## Links
91
98
 
package/bin/trooper.js CHANGED
@@ -5,6 +5,7 @@ import { randomBytes } from 'node:crypto';
5
5
 
6
6
  const DEFAULT_API_URL = 'https://trooper-production.up.railway.app';
7
7
  const LOCAL_MAC_SETUP_SCRIPT_URL = 'https://raw.githubusercontent.com/absurdfounder/trooper-bridge/main/setup-local-mac-host.sh';
8
+ const TROOPER_MAC_APP_DMG_URL = 'https://github.com/absurdfounder/trooper_landing/releases/download/macos-latest/Trooper.dmg';
8
9
  const LOCAL_MAC_LABELS = [
9
10
  'so.trooper.local-gateway',
10
11
  'so.trooper.local-bridge',
@@ -33,6 +34,7 @@ Options:
33
34
  --yes Run non-interactively with sensible defaults
34
35
  --keep-data Preserve local workspace/config data during uninstall
35
36
  --remove-app Also remove Trooper.app when uninstalling, if it is writable
37
+ --skip-app Install the local runtime only; do not install/open Trooper.app
36
38
  --print-command Print the installer command without running it
37
39
  --dry-run Same as --print-command
38
40
  -h, --help Show this help
@@ -49,7 +51,7 @@ function parseArgs(argv) {
49
51
  }
50
52
  const [key, inlineValue] = arg.split('=', 2);
51
53
  const name = key.replace(/^-+/, '');
52
- if (['help', 'h', 'dry-run', 'print-command', 'yes', 'y', 'keep-data', 'remove-app'].includes(name)) {
54
+ if (['help', 'h', 'dry-run', 'print-command', 'yes', 'y', 'keep-data', 'remove-app', 'skip-app'].includes(name)) {
53
55
  args[name] = true;
54
56
  continue;
55
57
  }
@@ -86,7 +88,67 @@ function localToken(prefix) {
86
88
  return `${prefix}_${randomBytes(24).toString('base64url')}`;
87
89
  }
88
90
 
89
- function buildLocalMacInstallCommand({ apiUrl }) {
91
+ function buildLocalMacAppInstallCommand() {
92
+ return `install_or_open_trooper_app() {
93
+ export PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
94
+ local app_path=""
95
+ for candidate in "$HOME/Applications/Trooper.app" "/Applications/Trooper.app"; do
96
+ if [[ -d "$candidate" ]]; then
97
+ app_path="$candidate"
98
+ break
99
+ fi
100
+ done
101
+
102
+ if [[ -z "$app_path" ]] && /usr/bin/open -Ra "Trooper" >/dev/null 2>&1; then
103
+ echo "Opening Trooper desktop app..."
104
+ /usr/bin/open -a "Trooper"
105
+ return 0
106
+ fi
107
+
108
+ if [[ -n "$app_path" ]]; then
109
+ echo "Opening Trooper desktop app..."
110
+ /usr/bin/open "$app_path"
111
+ return 0
112
+ fi
113
+
114
+ echo "Installing Trooper desktop app..."
115
+ local dmg_url="\${TROOPER_MAC_APP_DMG_URL:-${TROOPER_MAC_APP_DMG_URL}}"
116
+ local tmp_dmg mount_dir app_src install_root
117
+ tmp_dmg="$(/usr/bin/mktemp -t trooper-macos.XXXXXX).dmg"
118
+ mount_dir="$(/usr/bin/mktemp -d -t trooper-dmg.XXXXXX)"
119
+ install_root="$HOME/Applications"
120
+
121
+ cleanup_trooper_dmg() {
122
+ /usr/bin/hdiutil detach "$mount_dir" -quiet >/dev/null 2>&1 || true
123
+ /bin/rm -f "$tmp_dmg"
124
+ /bin/rm -rf "$mount_dir"
125
+ }
126
+ trap cleanup_trooper_dmg EXIT
127
+
128
+ /usr/bin/curl -fL --retry 3 --retry-delay 2 "$dmg_url" -o "$tmp_dmg"
129
+ /usr/bin/hdiutil attach "$tmp_dmg" -mountpoint "$mount_dir" -nobrowse -quiet
130
+ app_src="$(/usr/bin/find "$mount_dir" -maxdepth 1 -name "Trooper.app" -type d | /usr/bin/head -1)"
131
+ if [[ -z "$app_src" ]]; then
132
+ echo "Trooper.app was not found inside the downloaded DMG."
133
+ return 1
134
+ fi
135
+
136
+ /bin/mkdir -p "$install_root"
137
+ /bin/rm -rf "$install_root/Trooper.app"
138
+ /usr/bin/ditto "$app_src" "$install_root/Trooper.app"
139
+ /usr/bin/hdiutil detach "$mount_dir" -quiet >/dev/null 2>&1 || true
140
+ trap - EXIT
141
+ /bin/rm -f "$tmp_dmg"
142
+ /bin/rm -rf "$mount_dir"
143
+
144
+ echo "Trooper desktop app installed at: $install_root/Trooper.app"
145
+ /usr/bin/open "$install_root/Trooper.app"
146
+ }
147
+
148
+ install_or_open_trooper_app`;
149
+ }
150
+
151
+ function buildLocalMacInstallCommand({ apiUrl, installApp = true } = {}) {
90
152
  const hostSuffix = randomBytes(6).toString('hex');
91
153
  const env = {
92
154
  TROOPER_LOCAL_HOST: '1',
@@ -101,10 +163,12 @@ function buildLocalMacInstallCommand({ apiUrl }) {
101
163
  TUNNEL_PROVIDER: 'local',
102
164
  };
103
165
  return [
166
+ 'set -euo pipefail',
104
167
  buildExportCommand(env),
105
168
  `curl -fsSL ${shellSingleQuote(LOCAL_MAC_SETUP_SCRIPT_URL)} -o /tmp/trooper-local-mac-host.sh`,
106
169
  'chmod +x /tmp/trooper-local-mac-host.sh',
107
170
  'bash /tmp/trooper-local-mac-host.sh',
171
+ installApp ? buildLocalMacAppInstallCommand() : '',
108
172
  ].join('\n');
109
173
  }
110
174
 
@@ -261,7 +325,7 @@ async function main() {
261
325
  console.error('Tokenless local install is currently available for macOS. Open Trooper to prepare a paired installer for this platform.');
262
326
  process.exit(1);
263
327
  }
264
- const installCommand = buildLocalMacInstallCommand({ apiUrl });
328
+ const installCommand = buildLocalMacInstallCommand({ apiUrl, installApp: !args['skip-app'] });
265
329
  console.log('Starting Trooper local host setup on this Mac...');
266
330
  if (args['print-command'] || args['dry-run']) {
267
331
  console.log('\n' + installCommand);
@@ -269,7 +333,9 @@ async function main() {
269
333
  }
270
334
  runShellCommand(installCommand, platform, {
271
335
  failureLabel: 'Installer',
272
- successMessage: '\nTrooper local host is installed. Open Trooper to connect this Mac to your workspace.',
336
+ successMessage: args['skip-app']
337
+ ? '\nTrooper local host is installed. Open Trooper to connect this Mac to your workspace.'
338
+ : '\nTrooper local host is installed. Trooper desktop app is ready.',
273
339
  });
274
340
  return;
275
341
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trooper-cli",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Official Trooper CLI for installing and managing the local desktop AI runtime.",
5
5
  "type": "module",
6
6
  "bin": {