genbox 1.0.194 → 1.0.196

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.
@@ -42,7 +42,6 @@ const chalk_1 = __importDefault(require("chalk"));
42
42
  const api_1 = require("../api");
43
43
  const genbox_selector_1 = require("../genbox-selector");
44
44
  const ssh_config_1 = require("../ssh-config");
45
- const local_session_manager_1 = require("../lib/local-session-manager");
46
45
  const os = __importStar(require("os"));
47
46
  const path = __importStar(require("path"));
48
47
  const fs = __importStar(require("fs"));
@@ -101,11 +100,23 @@ exports.connectCommand = new commander_1.Command('connect')
101
100
  });
102
101
  return;
103
102
  }
104
- // Handle local genbox without VM - attach to session
103
+ // Handle local genbox without VM - attach to session (native mode)
105
104
  if (isLocal && localSession) {
106
105
  console.log(chalk_1.default.dim(`Attaching to local genbox ${chalk_1.default.bold(localSession.name)}...`));
107
- const manager = (0, local_session_manager_1.getLocalSessionManager)();
108
- await manager.attachToSession(localSession);
106
+ // For native sessions, attach via dtach
107
+ const socketPath = path.join(os.homedir(), '.genbox', 'sockets', `${localSession.name}.sock`);
108
+ if (fs.existsSync(socketPath)) {
109
+ const dtach = (0, child_process_1.spawn)('dtach', ['-a', socketPath], { stdio: 'inherit' });
110
+ dtach.on('close', (code) => {
111
+ if (code !== 0) {
112
+ console.log(chalk_1.default.dim(`Session detached with code ${code}`));
113
+ }
114
+ });
115
+ }
116
+ else {
117
+ console.error(chalk_1.default.yellow(`Session socket not found: ${socketPath}`));
118
+ console.log(chalk_1.default.dim(`The session may have ended. Use 'gb session' to start a new one.`));
119
+ }
109
120
  return;
110
121
  }
111
122
  if (!target.ipAddress) {
@@ -45,8 +45,8 @@ const fs = __importStar(require("fs"));
45
45
  const path = __importStar(require("path"));
46
46
  const child_process_1 = require("child_process");
47
47
  const config_loader_1 = require("../config-loader");
48
- const local_session_manager_1 = require("../lib/local-session-manager");
49
48
  const local_genbox_provisioner_1 = require("../lib/local-genbox-provisioner");
49
+ const unified_session_1 = require("../lib/unified-session");
50
50
  const profile_resolver_1 = require("../profile-resolver");
51
51
  const api_1 = require("../api");
52
52
  const ssh_config_1 = require("../ssh-config");
@@ -486,19 +486,30 @@ async function createLocalGenboxFullReplica(nameArg, options, config, configLoad
486
486
  }
487
487
  /**
488
488
  * Create a simple local genbox (no genbox.yaml)
489
- * By default creates an isolated session with git worktree
489
+ * Now simplified to use UnifiedSessionManager for native sessions
490
+ * For docker/multipass, users should use 'gb local' command
490
491
  */
491
492
  async function createLocalGenboxSimple(nameArg, options) {
492
- const manager = (0, local_session_manager_1.getLocalSessionManager)();
493
493
  const provider = options.gemini ? 'gemini' : 'claude';
494
494
  const isolation = options.vm ? 'multipass' : options.native ? 'native' : 'docker';
495
- const useWorktree = !options.noWorktree && isolation !== 'native';
495
+ // For docker/multipass isolation, redirect to 'gb local' command
496
+ if (isolation !== 'native') {
497
+ console.log('');
498
+ console.log(chalk_1.default.yellow('Docker and Multipass isolation requires the full genbox setup.'));
499
+ console.log('');
500
+ console.log(chalk_1.default.dim('For isolated container/VM environments, use:'));
501
+ console.log(chalk_1.default.cyan(` gb local ${nameArg || ''}`));
502
+ console.log('');
503
+ console.log(chalk_1.default.dim('For a simple native session (no container), use:'));
504
+ console.log(chalk_1.default.cyan(` gb create --local --native ${nameArg || ''}`));
505
+ console.log('');
506
+ return;
507
+ }
496
508
  // Interactive name prompt if not provided (same as cloud flow)
497
509
  let name = nameArg;
498
510
  if (!name && !options.yes) {
499
511
  console.log('');
500
- console.log(chalk_1.default.blue('=== Create Local Genbox ==='));
501
- console.log(chalk_1.default.dim('No genbox.yaml found - using simple mode'));
512
+ console.log(chalk_1.default.blue('=== Create Local Native Session ==='));
502
513
  console.log('');
503
514
  name = await promptForName(false);
504
515
  }
@@ -506,108 +517,39 @@ async function createLocalGenboxSimple(nameArg, options) {
506
517
  // Auto-generate name in non-interactive mode
507
518
  name = (0, random_name_1.generateRandomName)();
508
519
  }
509
- // Native mode doesn't support worktrees
510
- if (options.native && !options.noWorktree) {
511
- console.log(chalk_1.default.yellow('Note: Native mode does not support isolated worktrees.'));
512
- console.log(chalk_1.default.dim('Use --vm or default Docker mode for isolated development.'));
513
- console.log('');
514
- }
515
520
  console.log('');
516
521
  console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
517
522
  console.log(` ${chalk_1.default.bold('Name:')} ${name}`);
518
- console.log(` ${chalk_1.default.bold('Type:')} ${isolation}`);
523
+ console.log(` ${chalk_1.default.bold('Type:')} native`);
519
524
  console.log(` ${chalk_1.default.bold('Provider:')} ${provider}`);
520
525
  console.log(` ${chalk_1.default.bold('Directory:')} ${process.cwd()}`);
521
- if (useWorktree && manager.isGitRepo(process.cwd())) {
522
- const branchName = options.branch || name;
523
- console.log(` ${chalk_1.default.bold('Isolation:')} Git worktree (branch: ${branchName})`);
524
- }
525
- else {
526
- console.log(` ${chalk_1.default.bold('Isolation:')} Mounted folder (shared)`);
527
- }
528
526
  console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
529
527
  console.log('');
530
528
  try {
531
- let session;
532
- if (useWorktree && manager.isGitRepo(process.cwd())) {
533
- // Create isolated session with worktree
534
- console.log(chalk_1.default.dim('Creating isolated development environment...'));
535
- console.log('');
536
- session = await manager.createIsolatedSession({
537
- provider,
538
- isolation: isolation,
539
- workdir: process.cwd(),
540
- name,
541
- branch: options.branch || name,
542
- sourceBranch: options.fromBranch,
543
- appPort: options.port ? parseInt(options.port, 10) : 3000,
544
- appName: options.appName || 'web',
545
- installDeps: !options.skipInstall,
546
- });
547
- }
548
- else {
549
- // Create simple session (mounted folder, no worktree)
550
- if (useWorktree && !manager.isGitRepo(process.cwd())) {
551
- console.log(chalk_1.default.yellow('Note: Not a git repository. Using mounted folder instead of worktree.'));
552
- console.log(chalk_1.default.dim('Initialize git to enable isolated development with worktrees.'));
553
- console.log('');
554
- }
555
- const spinner = (0, ora_1.default)(`Creating ${isolation} environment...`).start();
556
- try {
557
- session = await manager.createSession({
558
- provider,
559
- isolation,
560
- workdir: process.cwd(),
561
- name,
562
- });
563
- spinner.succeed(chalk_1.default.green('Local genbox created!'));
564
- }
565
- catch (err) {
566
- spinner.fail(chalk_1.default.red('Failed to create environment'));
567
- throw err;
568
- }
569
- }
529
+ const manager = (0, unified_session_1.getUnifiedSessionManager)();
530
+ const spinner = (0, ora_1.default)('Creating native session...').start();
531
+ const session = await manager.createSession({
532
+ type: 'native',
533
+ provider: provider,
534
+ name,
535
+ projectPath: process.cwd(),
536
+ syncEnabled: false,
537
+ });
538
+ spinner.succeed(chalk_1.default.green('Native session created!'));
570
539
  console.log('');
571
540
  console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
572
541
  console.log(` ${chalk_1.default.bold('Name:')} ${session.name}`);
573
542
  console.log(` ${chalk_1.default.bold('ID:')} ${session.id}`);
574
543
  console.log(` ${chalk_1.default.bold('Provider:')} ${session.provider}`);
575
- console.log(` ${chalk_1.default.bold('Isolation:')} ${session.isolation}`);
544
+ console.log(` ${chalk_1.default.bold('Type:')} ${session.type}`);
576
545
  console.log(` ${chalk_1.default.bold('Status:')} ${chalk_1.default.green(session.status)}`);
577
- if (session.worktreeBranch) {
578
- console.log(` ${chalk_1.default.bold('Branch:')} ${session.worktreeBranch}`);
579
- }
580
- if (session.worktreePath) {
581
- console.log(` ${chalk_1.default.bold('Worktree:')} ${chalk_1.default.dim(session.worktreePath)}`);
582
- }
583
- if (session.domain) {
584
- console.log(` ${chalk_1.default.bold('Domain:')} ${chalk_1.default.cyan(session.domain)}`);
585
- }
586
- if (session.containerId) {
587
- console.log(` ${chalk_1.default.bold('Container:')} ${session.containerId.slice(0, 12)}`);
588
- }
589
- if (session.vmName) {
590
- console.log(` ${chalk_1.default.bold('VM:')} ${session.vmName}`);
591
- }
592
546
  console.log(chalk_1.default.dim('───────────────────────────────────────────────'));
593
547
  console.log('');
594
- // Show domain setup hint if using worktree
595
- if (session.domain) {
596
- console.log(chalk_1.default.yellow('DNS Setup Required:'));
597
- console.log(chalk_1.default.dim(` Add to /etc/hosts: ${chalk_1.default.cyan(`127.0.0.1 ${session.domain}`)}`));
598
- console.log(chalk_1.default.dim(` Or run: ${chalk_1.default.cyan('gb setup-local')} for automatic proxy setup`));
599
- console.log('');
600
- }
601
548
  console.log(chalk_1.default.bold('Next steps:'));
549
+ console.log(` Start: ${chalk_1.default.cyan(`gb ${session.provider} ${session.name}`)}`);
602
550
  console.log(` Attach: ${chalk_1.default.cyan(`gb session ${session.name}`)}`);
603
- console.log(` Connect: ${chalk_1.default.cyan(`gb connect ${session.name}`)}`);
604
- console.log(` Status: ${chalk_1.default.cyan(`gb status ${session.name}`)}`);
551
+ console.log(` Status: ${chalk_1.default.cyan(`gb session list`)}`);
605
552
  console.log(` Destroy: ${chalk_1.default.cyan(`gb destroy ${session.name}`)}`);
606
- if (session.domain) {
607
- console.log('');
608
- console.log(chalk_1.default.dim(` Preview: ${chalk_1.default.cyan(`https://${session.domain}`)}`));
609
- console.log(chalk_1.default.dim(` or ${chalk_1.default.cyan(`http://localhost:${session.ports.preview}`)}`));
610
- }
611
553
  console.log('');
612
554
  }
613
555
  catch (error) {
@@ -46,7 +46,7 @@ const ora_1 = __importDefault(require("ora"));
46
46
  const api_1 = require("../api");
47
47
  const genbox_selector_1 = require("../genbox-selector");
48
48
  const ssh_config_1 = require("../ssh-config");
49
- const local_session_manager_1 = require("../lib/local-session-manager");
49
+ const unified_session_1 = require("../lib/unified-session");
50
50
  const local_genbox_provisioner_1 = require("../lib/local-genbox-provisioner");
51
51
  /**
52
52
  * Format genbox for display in selection list
@@ -403,8 +403,8 @@ async function destroyLocalGenbox(session, options) {
403
403
  }
404
404
  const spinner = (0, ora_1.default)(`Destroying local genbox ${session.name}...`).start();
405
405
  try {
406
- const manager = (0, local_session_manager_1.getLocalSessionManager)();
407
- await manager.destroySession(session.id);
406
+ const manager = (0, unified_session_1.getUnifiedSessionManager)();
407
+ await manager.deleteSession(session.id);
408
408
  spinner.succeed(chalk_1.default.green(`Local genbox '${session.name}' destroyed successfully.`));
409
409
  }
410
410
  catch (error) {
@@ -59,6 +59,7 @@ const prompts_1 = require("@inquirer/prompts");
59
59
  const config_store_1 = require("../config-store");
60
60
  const api_1 = require("../api");
61
61
  const ssh_keys_1 = require("../utils/ssh-keys");
62
+ const unified_session_1 = require("../lib/unified-session");
62
63
  const child_process_1 = require("child_process");
63
64
  const os = __importStar(require("os"));
64
65
  const path = __importStar(require("path"));
@@ -417,11 +418,19 @@ async function startDirectSession(provider) {
417
418
  }
418
419
  const useDtach = dtachStatus === 'available';
419
420
  ensureLocalSocketDir();
420
- const sessionName = `${provider}-${Date.now().toString(36)}`;
421
+ // Register session with UnifiedSessionManager (local-first, no API sync by default)
422
+ const sessionManager = (0, unified_session_1.getUnifiedSessionManager)();
423
+ const session = await sessionManager.createSession({
424
+ type: 'native',
425
+ provider: provider,
426
+ projectPath: process.cwd(),
427
+ syncEnabled: false, // Local-first: no API sync by default
428
+ });
429
+ const sessionName = session.name;
421
430
  const cliCommand = provider === 'claude'
422
431
  ? 'claude --dangerously-skip-permissions'
423
432
  : provider === 'gemini'
424
- ? 'gemini'
433
+ ? 'gemini --yolo'
425
434
  : 'codex';
426
435
  console.log(chalk_1.default.dim(`\nStarting ${provider} session...`));
427
436
  if (useDtach) {
@@ -431,6 +440,13 @@ async function startDirectSession(provider) {
431
440
  console.log(chalk_1.default.dim('Note: Session will end when you exit (no persistence)\n'));
432
441
  }
433
442
  const socketPath = path.join(getDtachSocketDir(), `${sessionName}.sock`);
443
+ // Update socket name in session record
444
+ await sessionManager.updateSession(session.id, {
445
+ infrastructure: {
446
+ dtachSocketName: sessionName,
447
+ dtachSocketPath: socketPath,
448
+ },
449
+ });
434
450
  let cmd;
435
451
  if (useDtach) {
436
452
  cmd = `dtach -A "${socketPath}" bash -c '${cliCommand}'`;
@@ -438,6 +454,8 @@ async function startDirectSession(provider) {
438
454
  else {
439
455
  cmd = cliCommand;
440
456
  }
457
+ // Mark session as running
458
+ await sessionManager.markRunning(session.id);
441
459
  const proc = (0, child_process_1.spawn)('bash', ['-c', cmd], { stdio: 'inherit' });
442
460
  await new Promise((resolve) => {
443
461
  proc.on('close', () => {
@@ -447,6 +465,8 @@ async function startDirectSession(provider) {
447
465
  }
448
466
  else {
449
467
  console.log(chalk_1.default.dim('\nSession ended.'));
468
+ // Mark session as stopped if not using dtach or socket doesn't exist
469
+ sessionManager.markStopped(session.id);
450
470
  }
451
471
  resolve();
452
472
  });
@@ -53,10 +53,9 @@ exports.sessionCommand = void 0;
53
53
  const commander_1 = require("commander");
54
54
  const chalk_1 = __importDefault(require("chalk"));
55
55
  const select_1 = __importDefault(require("@inquirer/select"));
56
- const local_session_manager_1 = require("../../lib/local-session-manager");
56
+ const unified_session_1 = require("../../lib/unified-session");
57
57
  const local_orchestrator_1 = require("../../lib/local-orchestrator");
58
58
  const local_genbox_provisioner_1 = require("../../lib/local-genbox-provisioner");
59
- const native_session_manager_1 = require("../../lib/native-session-manager");
60
59
  const hooks_configurator_1 = require("../../lib/hooks-configurator");
61
60
  const api_1 = require("../../api");
62
61
  const genbox_selector_1 = require("../../genbox-selector");
@@ -1385,31 +1384,15 @@ async function attachToLocalGenboxSession(session) {
1385
1384
  * Create new local session interactively
1386
1385
  */
1387
1386
  async function createNewLocalSession() {
1388
- const manager = (0, local_session_manager_1.getLocalSessionManager)();
1389
- // Get provider
1390
- let provider;
1391
- try {
1392
- provider = await (0, select_1.default)({
1393
- message: 'Which AI provider?',
1394
- choices: [
1395
- { name: 'Claude (Anthropic)', value: 'claude' },
1396
- { name: 'Gemini (Google)', value: 'gemini' },
1397
- ],
1398
- });
1399
- }
1400
- catch {
1401
- console.log(chalk_1.default.dim('\nCancelled.'));
1402
- return;
1403
- }
1404
- // Get isolation
1387
+ // Redirect to the native session flow (or show guidance for docker/multipass)
1405
1388
  let isolation;
1406
1389
  try {
1407
1390
  isolation = await (0, select_1.default)({
1408
1391
  message: 'Isolation level?',
1409
1392
  choices: [
1393
+ { name: 'Native (no isolation)', value: 'native' },
1410
1394
  { name: 'Docker (fast, lightweight)', value: 'docker' },
1411
1395
  { name: 'VM (full isolation)', value: 'multipass' },
1412
- { name: 'Native (no isolation)', value: 'native' },
1413
1396
  ],
1414
1397
  });
1415
1398
  }
@@ -1417,20 +1400,17 @@ async function createNewLocalSession() {
1417
1400
  console.log(chalk_1.default.dim('\nCancelled.'));
1418
1401
  return;
1419
1402
  }
1420
- console.log(chalk_1.default.dim(`\nCreating ${isolation} session with ${provider}...`));
1421
- try {
1422
- const session = await manager.createSession({
1423
- provider,
1424
- isolation,
1425
- workdir: process.cwd(),
1426
- });
1427
- console.log(chalk_1.default.green(`\nSession created: ${session.name}`));
1428
- console.log(chalk_1.default.dim('\nAttaching to session...\n'));
1429
- await manager.attachToSession(session);
1430
- console.log(chalk_1.default.dim('\nDetached from session.'));
1403
+ if (isolation === 'native') {
1404
+ // Use the native session flow with UnifiedSessionManager
1405
+ await createNativeSession();
1431
1406
  }
1432
- catch (error) {
1433
- console.error(chalk_1.default.red(`\nError: ${error.message}`));
1407
+ else {
1408
+ // Docker/multipass sessions require gb local or gb session start
1409
+ console.log(chalk_1.default.yellow(`\n${isolation} sessions require additional setup.`));
1410
+ console.log(chalk_1.default.dim('\nFor quick start, use native mode:'));
1411
+ console.log(chalk_1.default.cyan(' gb session start --native'));
1412
+ console.log(chalk_1.default.dim('\nOr create a local genbox:'));
1413
+ console.log(chalk_1.default.cyan(' gb local'));
1434
1414
  }
1435
1415
  }
1436
1416
  /**
@@ -1445,7 +1425,7 @@ async function createNewCloudSession() {
1445
1425
  * Attach to specific session by name
1446
1426
  */
1447
1427
  async function attachToSessionByName(name, options) {
1448
- const manager = (0, local_session_manager_1.getLocalSessionManager)();
1428
+ const sessionManager = (0, unified_session_1.getUnifiedSessionManager)();
1449
1429
  // Check local genbox sessions FIRST (from LocalGenboxProvisioner)
1450
1430
  // These have more complete info and better attachment handling
1451
1431
  const genboxSessions = getLocalGenboxSessions();
@@ -1454,13 +1434,23 @@ async function attachToSessionByName(name, options) {
1454
1434
  await attachToLocalGenboxSession(genboxSession);
1455
1435
  return;
1456
1436
  }
1457
- // Check simple local sessions (older-style sessions)
1458
- const localSession = await manager.getSessionByName(name);
1459
- if (localSession) {
1460
- console.log(chalk_1.default.dim(`\nAttaching to local session ${name}...\n`));
1461
- await manager.attachToSession(localSession);
1462
- console.log(chalk_1.default.dim('\nDetached from session.'));
1463
- return;
1437
+ // Check native sessions (via UnifiedSessionManager)
1438
+ const unifiedSession = sessionManager.getSessionByName(name);
1439
+ if (unifiedSession && unifiedSession.type === 'native') {
1440
+ // Attach using dtach
1441
+ const socketPath = getDtachSocketPath(unifiedSession.name);
1442
+ if (isDtachSocketAlive(socketPath)) {
1443
+ console.log(chalk_1.default.dim(`\nAttaching to session ${name}...`));
1444
+ console.log(chalk_1.default.dim('Tip: Detach with Ctrl+\\\n'));
1445
+ const proc = (0, child_process_1.spawn)('dtach', ['-a', socketPath], { stdio: 'inherit' });
1446
+ await new Promise(resolve => proc.on('close', () => resolve()));
1447
+ console.log(chalk_1.default.dim('\nDetached from session.'));
1448
+ return;
1449
+ }
1450
+ else {
1451
+ console.log(chalk_1.default.yellow(`Session ${name} is not running.`));
1452
+ return;
1453
+ }
1464
1454
  }
1465
1455
  // Check cloud sessions
1466
1456
  const cloudSessions = await getCloudSessions(options.all || false);
@@ -1727,7 +1717,7 @@ async function createNewSessionInGenbox(genbox) {
1727
1717
  * With tracking enabled via genbox-agent hooks
1728
1718
  */
1729
1719
  async function createNativeSession(options) {
1730
- const nativeManager = (0, native_session_manager_1.getNativeSessionManager)();
1720
+ const sessionManager = (0, unified_session_1.getUnifiedSessionManager)();
1731
1721
  const hooksConfigurator = (0, hooks_configurator_1.getHooksConfigurator)();
1732
1722
  // Select AI provider first
1733
1723
  let provider;
@@ -1763,30 +1753,19 @@ async function createNativeSession(options) {
1763
1753
  console.log(chalk_1.default.dim('Session will run without tracking.'));
1764
1754
  }
1765
1755
  }
1766
- // Create session record
1767
- const session = await nativeManager.createSession({
1756
+ // Create session record with UnifiedSessionManager (local-first, no API sync by default)
1757
+ const session = await sessionManager.createSession({
1758
+ type: 'native',
1768
1759
  provider,
1769
1760
  projectPath: process.cwd(),
1770
- noTracking: options?.noTracking,
1761
+ syncEnabled: false, // Local-first: no API sync by default
1771
1762
  });
1772
1763
  console.log(chalk_1.default.dim(`Session created: ${session.name}`));
1773
- // Build environment variables for the session
1774
- const sessionEnv = nativeManager.getSessionEnv(session);
1775
- const envExports = Object.entries(sessionEnv)
1776
- .map(([key, value]) => `export ${key}="${value}"`)
1777
- .join('; ');
1778
1764
  // CLI command with skip permissions flag
1779
1765
  const cliCommand = provider === 'claude'
1780
1766
  ? 'claude --dangerously-skip-permissions'
1781
- : 'gemini';
1782
- // Show status
1783
- if (session.apiSessionId) {
1784
- console.log(chalk_1.default.green(`Tracking enabled (session: ${session.apiSessionId})`));
1785
- console.log(chalk_1.default.dim(`View in dashboard: ${process.env.GENBOX_DASHBOARD_URL || 'https://dashboard.genbox.dev'}/sessions/${session.apiSessionId}`));
1786
- }
1787
- else {
1788
- console.log(chalk_1.default.yellow('Running without tracking (not logged in or API unavailable)'));
1789
- }
1767
+ : 'gemini --yolo';
1768
+ // Local-first: no API tracking status to show
1790
1769
  console.log(chalk_1.default.dim('\nStarting session...'));
1791
1770
  if (useDtach) {
1792
1771
  console.log(chalk_1.default.dim('Tip: Detach with Ctrl+\\\n'));
@@ -1795,15 +1774,15 @@ async function createNativeSession(options) {
1795
1774
  console.log(chalk_1.default.dim('Note: Session will end when you exit (no persistence)\n'));
1796
1775
  }
1797
1776
  // Mark session as running
1798
- nativeManager.markRunning(session.id);
1777
+ await sessionManager.markRunning(session.id);
1799
1778
  // Build the command
1800
1779
  const socketPath = getDtachSocketPath(session.name);
1801
1780
  let cmd;
1802
1781
  if (useDtach) {
1803
- cmd = `dtach -A "${socketPath}" bash -c '${envExports}; ${cliCommand}'`;
1782
+ cmd = `dtach -A "${socketPath}" bash -c '${cliCommand}'`;
1804
1783
  }
1805
1784
  else {
1806
- cmd = `bash -c '${envExports}; ${cliCommand}'`;
1785
+ cmd = cliCommand;
1807
1786
  }
1808
1787
  const proc = (0, child_process_1.spawn)('bash', ['-c', cmd], { stdio: 'inherit' });
1809
1788
  await new Promise((resolve) => {
@@ -1816,12 +1795,12 @@ async function createNativeSession(options) {
1816
1795
  console.log(chalk_1.default.dim(`Reattach with: ${chalk_1.default.cyan(`gb session ${session.name}`)}`));
1817
1796
  }
1818
1797
  else {
1819
- nativeManager.markStopped(session.id);
1798
+ sessionManager.markStopped(session.id);
1820
1799
  console.log(chalk_1.default.dim('\nSession ended.'));
1821
1800
  }
1822
1801
  }
1823
1802
  else {
1824
- nativeManager.markStopped(session.id);
1803
+ sessionManager.markStopped(session.id);
1825
1804
  console.log(chalk_1.default.dim('\nSession ended.'));
1826
1805
  }
1827
1806
  resolve();
@@ -1841,46 +1820,31 @@ function isDtachSessionRunning(sessionName) {
1841
1820
  }
1842
1821
  }
1843
1822
  /**
1844
- * Send initial prompt to a session
1823
+ * Send initial prompt to a session (not implemented for unified sessions)
1845
1824
  */
1846
- async function sendInitialPrompt(session, prompt) {
1847
- const manager = (0, local_session_manager_1.getLocalSessionManager)();
1848
- // Wait for CLI to be ready
1849
- await new Promise(resolve => setTimeout(resolve, 2000));
1850
- try {
1851
- await manager.sendPromptToSession(session, prompt);
1852
- console.log(chalk_1.default.dim(`Sent initial prompt: "${prompt.slice(0, 50)}${prompt.length > 50 ? '...' : ''}"`));
1853
- }
1854
- catch (error) {
1855
- console.log(chalk_1.default.yellow(`Warning: Could not send initial prompt: ${error.message}`));
1856
- }
1825
+ async function sendInitialPrompt(_session, prompt) {
1826
+ // Note: Sending prompts to running sessions requires terminal integration
1827
+ // This is a placeholder for future implementation
1828
+ console.log(chalk_1.default.dim(`Initial prompt provided: "${prompt.slice(0, 50)}${prompt.length > 50 ? '...' : ''}"`));
1829
+ console.log(chalk_1.default.yellow('Note: Auto-sending prompts to sessions is not yet supported.'));
1857
1830
  }
1858
1831
  /**
1859
1832
  * Quick local session shortcut
1860
1833
  */
1861
1834
  async function quickLocalSession(options) {
1862
- const manager = (0, local_session_manager_1.getLocalSessionManager)();
1863
1835
  const provider = options.gemini ? 'gemini' : 'claude';
1864
1836
  const isolation = options.vm ? 'multipass' : options.native ? 'native' : 'docker';
1865
- console.log(chalk_1.default.dim(`\nCreating ${isolation} session with ${provider}...`));
1866
- try {
1867
- const session = await manager.createSession({
1868
- provider,
1869
- isolation,
1870
- workdir: process.cwd(),
1871
- });
1872
- console.log(chalk_1.default.green(`\nSession created: ${session.name}`));
1873
- // Send initial prompt if provided
1874
- if (options.prompt) {
1875
- await sendInitialPrompt(session, options.prompt);
1876
- }
1877
- console.log(chalk_1.default.dim('\nAttaching to session...\n'));
1878
- await manager.attachToSession(session);
1879
- console.log(chalk_1.default.dim('\nDetached from session.'));
1880
- }
1881
- catch (error) {
1882
- console.error(chalk_1.default.red(`\nError: ${error.message}`));
1837
+ // For native sessions, use the unified session flow
1838
+ if (isolation === 'native') {
1839
+ await createNativeSession({ prompt: options.prompt });
1840
+ return;
1883
1841
  }
1842
+ // For docker/multipass, show guidance
1843
+ console.log(chalk_1.default.yellow(`\n${isolation} sessions require additional setup.`));
1844
+ console.log(chalk_1.default.dim('\nFor quick start, use native mode:'));
1845
+ console.log(chalk_1.default.cyan(` gb session start --native --${provider}`));
1846
+ console.log(chalk_1.default.dim('\nOr create a local genbox:'));
1847
+ console.log(chalk_1.default.cyan(' gb local'));
1884
1848
  }
1885
1849
  /**
1886
1850
  * Create a cloud session on an existing genbox
@@ -2075,9 +2039,24 @@ async function handleMultiSession(options, providerArgs) {
2075
2039
  }
2076
2040
  // Attach to selected session
2077
2041
  if (selectedSession.location === 'local') {
2078
- const manager = (0, local_session_manager_1.getLocalSessionManager)();
2079
- console.log(chalk_1.default.dim(`\nAttaching to ${selectedSession.session.name}...\n`));
2080
- await manager.attachToSession(selectedSession.session);
2042
+ const localSession = selectedSession.session;
2043
+ console.log(chalk_1.default.dim(`\nAttaching to ${localSession.name}...\n`));
2044
+ // For native sessions, use dtach directly
2045
+ if (localSession.isolation === 'native') {
2046
+ const socketPath = getDtachSocketPath(localSession.name);
2047
+ if (isDtachSocketAlive(socketPath)) {
2048
+ console.log(chalk_1.default.dim('Tip: Detach with Ctrl+\\\n'));
2049
+ const proc = (0, child_process_1.spawn)('dtach', ['-a', socketPath], { stdio: 'inherit' });
2050
+ await new Promise(resolve => proc.on('close', () => resolve()));
2051
+ }
2052
+ else {
2053
+ console.log(chalk_1.default.yellow('Session is not running.'));
2054
+ }
2055
+ }
2056
+ else {
2057
+ // For docker/multipass, redirect to gb local
2058
+ console.log(chalk_1.default.yellow('Use `gb local attach` for docker/multipass sessions.'));
2059
+ }
2081
2060
  console.log(chalk_1.default.dim('\nDetached from session.'));
2082
2061
  }
2083
2062
  else {