@abyrd9/harbor-cli 2.3.0 → 2.3.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.
Files changed (2) hide show
  1. package/dist/index.js +63 -23
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -352,16 +352,19 @@ WHAT IT DOES:
352
352
  - Attaches your terminal to it
353
353
  - You can then switch between service tabs with Shift+Left/Right
354
354
  - Press Ctrl+q to kill session, or detach with Ctrl+b then d
355
+ - Runs any configured 'after' scripts if the session is killed
355
356
 
356
357
  PREREQUISITES: Services must be running (started with 'harbor launch').
357
358
 
358
- EXAMPLE:
359
- harbor launch -d # Start in background
360
- harbor anchor # Attach to see the services`)
361
- .action(async () => {
359
+ EXAMPLES:
360
+ harbor launch -d # Start in background
361
+ harbor anchor # Attach to default session
362
+ harbor anchor --name my-app # Attach to a specific named session`)
363
+ .option('--name <name>', 'Specify which tmux session to attach to (defaults to config sessionName or "harbor")')
364
+ .action(async (options) => {
362
365
  try {
363
366
  const config = await readHarborConfig();
364
- const sessionName = config.sessionName || 'harbor';
367
+ const sessionName = options.name || config.sessionName || 'harbor';
365
368
  // Check if session exists
366
369
  const checkSession = spawn('tmux', ['has-session', '-t', sessionName], {
367
370
  stdio: 'pipe',
@@ -381,7 +384,26 @@ EXAMPLE:
381
384
  const attach = spawn('tmux', ['attach-session', '-t', sessionName], {
382
385
  stdio: 'inherit',
383
386
  });
384
- attach.on('close', (code) => {
387
+ attach.on('close', async (code) => {
388
+ // Check if session was killed (vs just detached)
389
+ const checkAfter = spawn('tmux', ['has-session', '-t', sessionName], {
390
+ stdio: 'pipe',
391
+ });
392
+ const sessionStillExists = await new Promise((resolve) => {
393
+ checkAfter.on('close', (checkCode) => {
394
+ resolve(checkCode === 0);
395
+ });
396
+ });
397
+ // If session no longer exists, it was killed - run after scripts
398
+ if (!sessionStillExists && config.after && config.after.length > 0) {
399
+ try {
400
+ await execute(config.after, 'after');
401
+ }
402
+ catch {
403
+ console.error('❌ After scripts failed');
404
+ process.exit(1);
405
+ }
406
+ }
385
407
  process.exit(code || 0);
386
408
  });
387
409
  }
@@ -399,15 +421,18 @@ WHAT IT DOES:
399
421
  - Finds the running Harbor tmux session
400
422
  - Kills the entire session (all service windows)
401
423
  - All services stop immediately
424
+ - Runs any configured 'after' scripts
402
425
 
403
426
  SAFE TO RUN: If no session is running, it simply reports that and exits cleanly.
404
427
 
405
- EXAMPLE:
406
- harbor scuttle # Stop all services`)
407
- .action(async () => {
428
+ EXAMPLES:
429
+ harbor scuttle # Stop default session
430
+ harbor scuttle --name my-app # Stop a specific named session`)
431
+ .option('--name <name>', 'Specify which tmux session to stop (defaults to config sessionName or "harbor")')
432
+ .action(async (options) => {
408
433
  try {
409
434
  const config = await readHarborConfig();
410
- const sessionName = config.sessionName || 'harbor';
435
+ const sessionName = options.name || config.sessionName || 'harbor';
411
436
  // Check if session exists
412
437
  const checkSession = spawn('tmux', ['has-session', '-t', sessionName], {
413
438
  stdio: 'pipe',
@@ -425,9 +450,19 @@ EXAMPLE:
425
450
  const killSession = spawn('tmux', ['kill-session', '-t', sessionName], {
426
451
  stdio: 'inherit',
427
452
  });
428
- killSession.on('close', (code) => {
453
+ killSession.on('close', async (code) => {
429
454
  if (code === 0) {
430
455
  console.log(`✅ Harbor session '${sessionName}' stopped`);
456
+ // Execute after scripts when session is killed
457
+ if (config.after && config.after.length > 0) {
458
+ try {
459
+ await execute(config.after, 'after');
460
+ }
461
+ catch {
462
+ console.error('❌ After scripts failed');
463
+ process.exit(1);
464
+ }
465
+ }
431
466
  }
432
467
  else {
433
468
  console.log('❌ Failed to stop Harbor session');
@@ -460,12 +495,14 @@ OUTPUT EXAMPLE:
460
495
 
461
496
  SAFE TO RUN: Works whether services are running or not.
462
497
 
463
- EXAMPLE:
464
- harbor bearings # Check what's running`)
465
- .action(async () => {
498
+ EXAMPLES:
499
+ harbor bearings # Check default session
500
+ harbor bearings --name my-app # Check a specific named session`)
501
+ .option('--name <name>', 'Specify which tmux session to check (defaults to config sessionName or "harbor")')
502
+ .action(async (options) => {
466
503
  try {
467
504
  const config = await readHarborConfig();
468
- const sessionName = config.sessionName || 'harbor';
505
+ const sessionName = options.name || config.sessionName || 'harbor';
469
506
  // Check if session exists
470
507
  const checkSession = spawn('tmux', ['has-session', '-t', sessionName], {
471
508
  stdio: 'pipe',
@@ -833,15 +870,18 @@ async function runServices(options = {}) {
833
870
  console.error(`dev.sh exited with code ${code}`);
834
871
  process.exit(1);
835
872
  }
836
- // Execute after scripts
837
- try {
838
- await execute(config.after || [], 'after');
839
- resolve();
840
- }
841
- catch {
842
- console.error('❌ After scripts failed');
843
- process.exit(1);
873
+ // Only execute after scripts in attached mode
874
+ // In headless mode, after scripts are run by 'scuttle' when session is killed
875
+ if (!options.detach) {
876
+ try {
877
+ await execute(config.after || [], 'after');
878
+ }
879
+ catch {
880
+ console.error('❌ After scripts failed');
881
+ process.exit(1);
882
+ }
844
883
  }
884
+ resolve();
845
885
  });
846
886
  });
847
887
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abyrd9/harbor-cli",
3
- "version": "2.3.0",
3
+ "version": "2.3.2",
4
4
  "description": "A CLI tool for orchestrating local development services in a tmux session. Perfect for microservices and polyglot projects with automatic service discovery and before/after script support.",
5
5
  "type": "module",
6
6
  "bin": {