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 +10 -3
- package/bin/trooper.js +70 -4
- package/package.json +1 -1
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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: '
|
|
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
|
}
|