@phenx-inc/ctlsurf 0.1.1 → 0.1.2

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.
@@ -238,13 +238,57 @@ if (mode === 'desktop') {
238
238
  try {
239
239
  electronPath = require('electron')
240
240
  } catch {
241
- console.error('[ctlsurf] Electron not found, falling back to terminal mode')
241
+ // Electron not installed prompt to install or fall back
242
+ if (process.stdin.isTTY && !args.includes('--terminal')) {
243
+ console.log(`\n${B} ctlsurf${R}\n`)
244
+ console.log(` Electron is not installed. Desktop mode requires Electron.\n`)
245
+ console.log(` ${D}1)${R} Install Electron and launch desktop mode`)
246
+ console.log(` ${D}2)${R} Launch in terminal mode instead`)
247
+ console.log(` ${D}3)${R} Exit\n`)
248
+
249
+ const readline = require('readline')
250
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout })
251
+ rl.question(` Choice ${D}(1/2/3)${R}: `, (answer) => {
252
+ rl.close()
253
+ answer = answer.trim()
254
+ if (answer === '1') {
255
+ console.log(`\n${D}Installing Electron (this may take a minute)...${R}\n`)
256
+ try {
257
+ execSync('npm install electron --no-save', { cwd: ROOT, stdio: 'inherit' })
258
+ console.log(`\n${G}✓${R} Electron installed. Launching desktop mode...\n`)
259
+ try {
260
+ const ep = require('electron')
261
+ execFileSync(String(ep), [ROOT, ...args], {
262
+ stdio: 'inherit',
263
+ env: { ...process.env, CTLSURF_WORKER_CWD: process.env.CTLSURF_WORKER_CWD || process.cwd() }
264
+ })
265
+ } catch (err) {
266
+ process.exit(err.status || 0)
267
+ }
268
+ } catch (err) {
269
+ console.error(`\n${Y}!${R} Electron install failed: ${err.message}`)
270
+ console.error(` Try manually: cd ${ROOT} && npm install electron\n`)
271
+ process.exit(1)
272
+ }
273
+ } else if (answer === '2') {
274
+ console.log('')
275
+ runTerminal()
276
+ } else {
277
+ process.exit(0)
278
+ }
279
+ })
280
+ return
281
+ }
282
+ // Non-interactive: fall back silently
242
283
  runTerminal()
243
284
  process.exit(0)
244
285
  }
245
286
 
246
287
  try {
247
- execFileSync(String(electronPath), [ROOT, ...args], { stdio: 'inherit' })
288
+ execFileSync(String(electronPath), [ROOT, ...args], {
289
+ stdio: 'inherit',
290
+ env: { ...process.env, CTLSURF_WORKER_CWD: process.env.CTLSURF_WORKER_CWD || process.cwd() }
291
+ })
248
292
  } catch (err) {
249
293
  process.exit(err.status || 0)
250
294
  }
@@ -259,7 +303,10 @@ function runTerminal() {
259
303
  process.exit(1)
260
304
  }
261
305
  try {
262
- execFileSync(process.execPath, [terminalPath, ...args], { stdio: 'inherit' })
306
+ execFileSync(process.execPath, [terminalPath, ...args], {
307
+ stdio: 'inherit',
308
+ env: { ...process.env, CTLSURF_WORKER_CWD: process.env.CTLSURF_WORKER_CWD || process.cwd() }
309
+ })
263
310
  } catch (err) {
264
311
  process.exit(err.status || 0)
265
312
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phenx-inc/ctlsurf",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Agent-agnostic terminal and desktop app for ctlsurf — run Claude Code, Codex, or any coding agent with live session logging and remote control",
5
5
  "main": "out/main/index.js",
6
6
  "bin": {
@@ -199,10 +199,62 @@ if [ "$FOUND_CLAUDE_CLI" = false ] && [ "$FOUND_CLAUDE_VSCODE" = false ] && \
199
199
  exit 1
200
200
  fi
201
201
 
202
- # Get API key (read from /dev/tty for curl|bash compatibility)
203
- echo "Get your API key from: https://app.ctlsurf.com/settings (API Keys tab)"
204
- echo -n "Enter your ctlsurf API key: "
205
- read API_KEY < /dev/tty
202
+ # Check for existing API key in environment or shell profile
203
+ EXISTING_KEY=""
204
+ EXISTING_URL=""
205
+
206
+ # Check env var
207
+ if [ -n "$CTLSURF_API_KEY" ]; then
208
+ EXISTING_KEY="$CTLSURF_API_KEY"
209
+ fi
210
+
211
+ # Check shell profile
212
+ if [ -z "$EXISTING_KEY" ]; then
213
+ for rc in "$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile"; do
214
+ if [ -f "$rc" ]; then
215
+ KEY_FROM_RC=$(grep '^export CTLSURF_API_KEY=' "$rc" 2>/dev/null | tail -1 | sed 's/^export CTLSURF_API_KEY="//' | sed 's/"$//')
216
+ if [ -n "$KEY_FROM_RC" ]; then
217
+ EXISTING_KEY="$KEY_FROM_RC"
218
+ break
219
+ fi
220
+ fi
221
+ done
222
+ fi
223
+
224
+ # Check CTLSURF_URL from env or profile
225
+ if [ -n "$CTLSURF_URL" ]; then
226
+ EXISTING_URL="$CTLSURF_URL"
227
+ else
228
+ for rc in "$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.bash_profile"; do
229
+ if [ -f "$rc" ]; then
230
+ URL_FROM_RC=$(grep '^export CTLSURF_URL=' "$rc" 2>/dev/null | tail -1 | sed 's/^export CTLSURF_URL="//' | sed 's/"$//')
231
+ if [ -n "$URL_FROM_RC" ]; then
232
+ EXISTING_URL="$URL_FROM_RC"
233
+ break
234
+ fi
235
+ fi
236
+ done
237
+ fi
238
+
239
+ # Use existing credentials or prompt
240
+ if [ -n "$EXISTING_KEY" ]; then
241
+ MASKED_KEY="${EXISTING_KEY:0:8}...${EXISTING_KEY: -4}"
242
+ echo -e "${GREEN}✓ Found existing API key: ${MASKED_KEY}${NC}"
243
+ echo -n "Use this key? (Y/n): "
244
+ read USE_EXISTING < /dev/tty
245
+ if [ -z "$USE_EXISTING" ] || [ "$USE_EXISTING" = "y" ] || [ "$USE_EXISTING" = "Y" ]; then
246
+ API_KEY="$EXISTING_KEY"
247
+ else
248
+ echo ""
249
+ echo "Get your API key from: https://app.ctlsurf.com/settings (API Keys tab)"
250
+ echo -n "Enter your ctlsurf API key: "
251
+ read API_KEY < /dev/tty
252
+ fi
253
+ else
254
+ echo "Get your API key from: https://app.ctlsurf.com/settings (API Keys tab)"
255
+ echo -n "Enter your ctlsurf API key: "
256
+ read API_KEY < /dev/tty
257
+ fi
206
258
 
207
259
  if [ -z "$API_KEY" ]; then
208
260
  echo -e "${RED}ERROR: API key is required${NC}"
@@ -210,9 +262,25 @@ if [ -z "$API_KEY" ]; then
210
262
  fi
211
263
 
212
264
  echo ""
213
- echo -n "Server URL [https://app.ctlsurf.com]: "
214
- read SERVER_URL < /dev/tty
215
- SERVER_URL=${SERVER_URL:-https://app.ctlsurf.com}
265
+
266
+ if [ -n "$EXISTING_URL" ]; then
267
+ # Strip /api/mcp suffix for display
268
+ DISPLAY_URL=$(echo "$EXISTING_URL" | sed 's|/api/mcp$||' | sed 's|/api$||')
269
+ echo -e "${GREEN}✓ Found existing server URL: ${DISPLAY_URL}${NC}"
270
+ echo -n "Use this URL? (Y/n): "
271
+ read USE_EXISTING_URL < /dev/tty
272
+ if [ -z "$USE_EXISTING_URL" ] || [ "$USE_EXISTING_URL" = "y" ] || [ "$USE_EXISTING_URL" = "Y" ]; then
273
+ SERVER_URL="$DISPLAY_URL"
274
+ else
275
+ echo -n "Server URL [https://app.ctlsurf.com]: "
276
+ read SERVER_URL < /dev/tty
277
+ SERVER_URL=${SERVER_URL:-https://app.ctlsurf.com}
278
+ fi
279
+ else
280
+ echo -n "Server URL [https://app.ctlsurf.com]: "
281
+ read SERVER_URL < /dev/tty
282
+ SERVER_URL=${SERVER_URL:-https://app.ctlsurf.com}
283
+ fi
216
284
  # Normalize URL
217
285
  SERVER_URL="${SERVER_URL%/}"
218
286
  SERVER_URL="${SERVER_URL%/api}"