replicas-cli 0.2.28 → 0.2.29

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 +192 -338
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -34,9 +34,9 @@ __export(index_exports, {
34
34
  CLI_VERSION: () => CLI_VERSION
35
35
  });
36
36
  module.exports = __toCommonJS(index_exports);
37
- var import_config17 = require("dotenv/config");
37
+ var import_config15 = require("dotenv/config");
38
38
  var import_commander = require("commander");
39
- var import_chalk18 = __toESM(require("chalk"));
39
+ var import_chalk17 = __toESM(require("chalk"));
40
40
 
41
41
  // src/commands/login.ts
42
42
  var import_http = __toESM(require("http"));
@@ -507,44 +507,14 @@ async function whoamiCommand() {
507
507
  var import_chalk5 = __toESM(require("chalk"));
508
508
 
509
509
  // src/lib/ssh.ts
510
- var import_fs2 = __toESM(require("fs"));
511
- var import_path2 = __toESM(require("path"));
512
510
  var import_child_process = require("child_process");
513
- var SSH_KEYS_DIR = import_path2.default.join(CONFIG_DIR, "keys");
514
- function ensureSSHKeysDir() {
515
- if (!import_fs2.default.existsSync(SSH_KEYS_DIR)) {
516
- import_fs2.default.mkdirSync(SSH_KEYS_DIR, { recursive: true, mode: 448 });
517
- }
518
- }
519
- function getSSHKeyPath(sshKeyId) {
520
- return import_path2.default.join(SSH_KEYS_DIR, `${sshKeyId}.pem`);
521
- }
522
- async function getSSHKey(sshKeyId) {
523
- const keyPath = getSSHKeyPath(sshKeyId);
524
- if (import_fs2.default.existsSync(keyPath)) {
525
- return import_fs2.default.readFileSync(keyPath, "utf-8");
526
- }
527
- const response = await orgAuthenticatedFetch(
528
- `/v1/keys/${sshKeyId}?includePrivateKey=true`
529
- );
530
- if (!response.privateKey) {
531
- throw new Error("Failed to retrieve private key from server");
532
- }
533
- ensureSSHKeysDir();
534
- import_fs2.default.writeFileSync(keyPath, response.privateKey, { mode: 384 });
535
- return response.privateKey;
536
- }
537
- async function scpCopyFile(privateKeyPath, localPath, remotePath, remoteHost) {
511
+ var SSH_OPTIONS = ["-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=/dev/null"];
512
+ async function scpCopyFile(token, host, localPath, remotePath) {
538
513
  return new Promise((resolve, reject) => {
539
514
  const scp = (0, import_child_process.spawn)("scp", [
540
- "-i",
541
- privateKeyPath,
542
- "-o",
543
- "StrictHostKeyChecking=no",
544
- "-o",
545
- "UserKnownHostsFile=/dev/null",
515
+ ...SSH_OPTIONS,
546
516
  localPath,
547
- `ubuntu@${remoteHost}:${remotePath}`
517
+ `${token}@${host}:${remotePath}`
548
518
  ], {
549
519
  stdio: "inherit"
550
520
  });
@@ -558,24 +528,17 @@ async function scpCopyFile(privateKeyPath, localPath, remotePath, remoteHost) {
558
528
  scp.on("error", reject);
559
529
  });
560
530
  }
561
- async function connectSSH(privateKeyPath, remoteHost, portMappings) {
531
+ async function connectSSH(token, host, portMappings) {
562
532
  return new Promise((resolve, reject) => {
563
- const sshArgs = [
564
- "-i",
565
- privateKeyPath,
566
- "-o",
567
- "StrictHostKeyChecking=no",
568
- "-o",
569
- "UserKnownHostsFile=/dev/null"
570
- ];
533
+ const sshArgs = [...SSH_OPTIONS];
571
534
  for (const [remotePort, localPort] of portMappings) {
572
535
  sshArgs.push("-L", `${localPort}:localhost:${remotePort}`);
573
536
  }
574
- sshArgs.push(`ubuntu@${remoteHost}`);
537
+ sshArgs.push(`${token}@${host}`);
575
538
  const ssh = (0, import_child_process.spawn)("ssh", sshArgs, {
576
539
  stdio: "inherit"
577
540
  });
578
- ssh.on("close", (code) => {
541
+ ssh.on("close", () => {
579
542
  resolve();
580
543
  });
581
544
  ssh.on("error", reject);
@@ -585,12 +548,10 @@ async function connectSSH(privateKeyPath, remoteHost, portMappings) {
585
548
  // src/lib/workspace-connection.ts
586
549
  var import_chalk4 = __toESM(require("chalk"));
587
550
  var import_prompts = __toESM(require("prompts"));
588
- var import_path5 = __toESM(require("path"));
589
- var import_fs4 = __toESM(require("fs"));
590
551
 
591
552
  // src/lib/git.ts
592
553
  var import_child_process2 = require("child_process");
593
- var import_path3 = __toESM(require("path"));
554
+ var import_path2 = __toESM(require("path"));
594
555
  function getGitRoot() {
595
556
  try {
596
557
  const root = (0, import_child_process2.execSync)("git rev-parse --show-toplevel", {
@@ -604,7 +565,7 @@ function getGitRoot() {
604
565
  }
605
566
  function getGitRepoName() {
606
567
  const root = getGitRoot();
607
- return import_path3.default.basename(root);
568
+ return import_path2.default.basename(root);
608
569
  }
609
570
  function isInsideGitRepo() {
610
571
  try {
@@ -619,16 +580,16 @@ function isInsideGitRepo() {
619
580
  }
620
581
 
621
582
  // src/lib/replicas-config.ts
622
- var import_fs3 = __toESM(require("fs"));
623
- var import_path4 = __toESM(require("path"));
583
+ var import_fs2 = __toESM(require("fs"));
584
+ var import_path3 = __toESM(require("path"));
624
585
  function readReplicasConfig() {
625
586
  try {
626
587
  const gitRoot = getGitRoot();
627
- const configPath = import_path4.default.join(gitRoot, "replicas.json");
628
- if (!import_fs3.default.existsSync(configPath)) {
588
+ const configPath = import_path3.default.join(gitRoot, "replicas.json");
589
+ if (!import_fs2.default.existsSync(configPath)) {
629
590
  return null;
630
591
  }
631
- const data = import_fs3.default.readFileSync(configPath, "utf-8");
592
+ const data = import_fs2.default.readFileSync(configPath, "utf-8");
632
593
  const config2 = JSON.parse(data);
633
594
  if (config2.copy && !Array.isArray(config2.copy)) {
634
595
  throw new Error('Invalid replicas.json: "copy" must be an array of file paths');
@@ -658,8 +619,8 @@ function validateCopyFiles(copyFiles) {
658
619
  const valid = [];
659
620
  const invalid = [];
660
621
  for (const file of copyFiles) {
661
- const fullPath = import_path4.default.join(gitRoot, file);
662
- if (import_fs3.default.existsSync(fullPath)) {
622
+ const fullPath = import_path3.default.join(gitRoot, file);
623
+ if (import_fs2.default.existsSync(fullPath)) {
663
624
  valid.push(file);
664
625
  } else {
665
626
  invalid.push(file);
@@ -669,7 +630,7 @@ function validateCopyFiles(copyFiles) {
669
630
  }
670
631
  function getAbsoluteCopyPath(relativePath) {
671
632
  const gitRoot = getGitRoot();
672
- return import_path4.default.join(gitRoot, relativePath);
633
+ return import_path3.default.join(gitRoot, relativePath);
673
634
  }
674
635
 
675
636
  // src/lib/ports.ts
@@ -733,7 +694,7 @@ Found ${response.workspaces.length} workspaces matching "${workspaceName}":`));
733
694
  choices: response.workspaces.map((ws) => ({
734
695
  title: `${ws.name} (${ws.status || "unknown"})`,
735
696
  value: ws.id,
736
- description: `IP: ${ws.ipv4_address || "N/A"} | Instance: ${ws.instance_type || "N/A"}`
697
+ description: `Status: ${ws.status || "unknown"}`
737
698
  }))
738
699
  });
739
700
  if (!selectResponse.workspaceId) {
@@ -743,21 +704,18 @@ Found ${response.workspaces.length} workspaces matching "${workspaceName}":`));
743
704
  }
744
705
  console.log(import_chalk4.default.green(`
745
706
  \u2713 Selected workspace: ${selectedWorkspace.name}`));
746
- console.log(import_chalk4.default.gray(` IP: ${selectedWorkspace.ipv4_address}`));
747
707
  console.log(import_chalk4.default.gray(` Status: ${selectedWorkspace.status || "unknown"}`));
748
708
  if (selectedWorkspace.status === "sleeping") {
749
709
  throw new Error(
750
710
  "Workspace is currently sleeping. Please wake it up in the dashboard at https://replicas.dev before connecting."
751
711
  );
752
712
  }
753
- if (!selectedWorkspace.ipv4_address) {
754
- throw new Error("Workspace does not have an IP address. It may not be running yet.");
755
- }
756
- console.log(import_chalk4.default.blue("\nRetrieving SSH key..."));
757
- const privateKey = await getSSHKey(selectedWorkspace.ssh_key_id);
758
- const keyPath = import_path5.default.join(CONFIG_DIR, "keys", `${selectedWorkspace.ssh_key_id}.pem`);
759
- import_fs4.default.writeFileSync(keyPath, privateKey, { mode: 384 });
760
- console.log(import_chalk4.default.green("\u2713 SSH key ready"));
713
+ console.log(import_chalk4.default.blue("\nRequesting SSH access token..."));
714
+ const tokenResponse = await orgAuthenticatedFetch(
715
+ `/v1/workspaces/${selectedWorkspace.id}/ssh-token`,
716
+ { method: "POST" }
717
+ );
718
+ console.log(import_chalk4.default.green("\u2713 SSH token received"));
761
719
  let repoName = null;
762
720
  if (options.copy) {
763
721
  if (!isInsideGitRepo()) {
@@ -781,7 +739,7 @@ Warning: ${invalid.length} file(s) not found locally:`));
781
739
  const remotePath = `/home/ubuntu/workspaces/${repoName}/${file}`;
782
740
  console.log(import_chalk4.default.gray(` Copying ${file}...`));
783
741
  try {
784
- await scpCopyFile(keyPath, localPath, remotePath, selectedWorkspace.ipv4_address);
742
+ await scpCopyFile(tokenResponse.token, tokenResponse.host, localPath, remotePath);
785
743
  console.log(import_chalk4.default.green(` \u2713 ${file}`));
786
744
  } catch (error) {
787
745
  console.log(import_chalk4.default.red(` \u2717 Failed to copy ${file}: ${error instanceof Error ? error.message : "Unknown error"}`));
@@ -813,7 +771,8 @@ Warning: ${invalid.length} file(s) not found locally:`));
813
771
  console.log(import_chalk4.default.green("\u2713 Port forwarding configured"));
814
772
  return {
815
773
  workspace: selectedWorkspace,
816
- sshKeyPath: keyPath,
774
+ sshToken: tokenResponse.token,
775
+ sshHost: tokenResponse.host,
817
776
  portMappings,
818
777
  repoName
819
778
  };
@@ -826,17 +785,13 @@ async function connectCommand(workspaceName, options) {
826
785
  process.exit(1);
827
786
  }
828
787
  try {
829
- const { workspace, sshKeyPath, portMappings } = await prepareWorkspaceConnection(
788
+ const { workspace, sshToken, sshHost, portMappings } = await prepareWorkspaceConnection(
830
789
  workspaceName,
831
790
  options
832
791
  );
833
792
  console.log(import_chalk5.default.blue(`
834
793
  Connecting to ${workspace.name}...`));
835
- let sshCommand = `ssh -i ${sshKeyPath}`;
836
- for (const [remotePort, localPort] of portMappings) {
837
- sshCommand += ` -L ${localPort}:localhost:${remotePort}`;
838
- }
839
- sshCommand += ` ubuntu@${workspace.ipv4_address}`;
794
+ const sshCommand = `ssh ${sshToken}@${sshHost}`;
840
795
  console.log(import_chalk5.default.gray(`SSH command: ${sshCommand}`));
841
796
  if (portMappings.size > 0) {
842
797
  console.log(import_chalk5.default.cyan("\nPort forwarding active:"));
@@ -845,7 +800,7 @@ Connecting to ${workspace.name}...`));
845
800
  }
846
801
  }
847
802
  console.log(import_chalk5.default.gray("\nPress Ctrl+D to disconnect.\n"));
848
- await connectSSH(sshKeyPath, workspace.ipv4_address, portMappings);
803
+ await connectSSH(sshToken, sshHost, portMappings);
849
804
  console.log(import_chalk5.default.green("\n\u2713 Disconnected from workspace.\n"));
850
805
  } catch (error) {
851
806
  console.error(import_chalk5.default.red(`
@@ -859,28 +814,28 @@ var import_chalk6 = __toESM(require("chalk"));
859
814
  var import_child_process4 = require("child_process");
860
815
 
861
816
  // src/lib/ssh-config.ts
862
- var import_fs5 = __toESM(require("fs"));
863
- var import_path6 = __toESM(require("path"));
817
+ var import_fs3 = __toESM(require("fs"));
818
+ var import_path4 = __toESM(require("path"));
864
819
  var import_os2 = __toESM(require("os"));
865
- var SSH_CONFIG_PATH = import_path6.default.join(import_os2.default.homedir(), ".ssh", "config");
820
+ var SSH_CONFIG_PATH = import_path4.default.join(import_os2.default.homedir(), ".ssh", "config");
866
821
  var REPLICAS_MARKER_START = "# === REPLICAS CLI MANAGED ENTRY START ===";
867
822
  var REPLICAS_MARKER_END = "# === REPLICAS CLI MANAGED ENTRY END ===";
868
823
  function ensureSSHDir() {
869
- const sshDir = import_path6.default.join(import_os2.default.homedir(), ".ssh");
870
- if (!import_fs5.default.existsSync(sshDir)) {
871
- import_fs5.default.mkdirSync(sshDir, { recursive: true, mode: 448 });
824
+ const sshDir = import_path4.default.join(import_os2.default.homedir(), ".ssh");
825
+ if (!import_fs3.default.existsSync(sshDir)) {
826
+ import_fs3.default.mkdirSync(sshDir, { recursive: true, mode: 448 });
872
827
  }
873
828
  }
874
829
  function readSSHConfig() {
875
830
  ensureSSHDir();
876
- if (!import_fs5.default.existsSync(SSH_CONFIG_PATH)) {
831
+ if (!import_fs3.default.existsSync(SSH_CONFIG_PATH)) {
877
832
  return "";
878
833
  }
879
- return import_fs5.default.readFileSync(SSH_CONFIG_PATH, "utf-8");
834
+ return import_fs3.default.readFileSync(SSH_CONFIG_PATH, "utf-8");
880
835
  }
881
836
  function writeSSHConfig(content) {
882
837
  ensureSSHDir();
883
- import_fs5.default.writeFileSync(SSH_CONFIG_PATH, content, { mode: 384 });
838
+ import_fs3.default.writeFileSync(SSH_CONFIG_PATH, content, { mode: 384 });
884
839
  }
885
840
  function generateConfigBlock(entry) {
886
841
  const lines = [
@@ -888,7 +843,6 @@ function generateConfigBlock(entry) {
888
843
  `Host ${entry.host}`,
889
844
  ` HostName ${entry.hostname}`,
890
845
  ` User ${entry.user}`,
891
- ` IdentityFile ${entry.identityFile}`,
892
846
  ` StrictHostKeyChecking no`,
893
847
  ` UserKnownHostsFile /dev/null`
894
848
  ];
@@ -949,7 +903,7 @@ async function codeCommand(workspaceName, options) {
949
903
  process.exit(1);
950
904
  }
951
905
  try {
952
- const { workspace, sshKeyPath, portMappings, repoName } = await prepareWorkspaceConnection(
906
+ const { workspace, sshToken, sshHost, portMappings, repoName } = await prepareWorkspaceConnection(
953
907
  workspaceName,
954
908
  options
955
909
  );
@@ -957,9 +911,8 @@ async function codeCommand(workspaceName, options) {
957
911
  console.log(import_chalk6.default.blue("\nConfiguring SSH connection..."));
958
912
  addOrUpdateSSHConfigEntry({
959
913
  host: hostAlias,
960
- hostname: workspace.ipv4_address,
961
- user: "ubuntu",
962
- identityFile: sshKeyPath,
914
+ hostname: sshHost,
915
+ user: sshToken,
963
916
  portForwards: portMappings
964
917
  });
965
918
  console.log(import_chalk6.default.green(`\u2713 SSH config entry created: ${hostAlias}`));
@@ -975,6 +928,8 @@ Opening ${ideCommand} for workspace ${workspace.name}...`));
975
928
  console.log(import_chalk6.default.cyan(` \u2022 localhost:${localPort} \u2192 workspace:${remotePort}`));
976
929
  }
977
930
  }
931
+ console.log(import_chalk6.default.yellow(`
932
+ Note: SSH tokens expire after 3 hours. Run this command again to refresh.`));
978
933
  const ide = (0, import_child_process4.spawn)(ideCommand, [
979
934
  "--remote",
980
935
  `ssh-remote+${hostAlias}`,
@@ -1595,75 +1550,10 @@ async function claudeAuthCommand(options = {}) {
1595
1550
  }
1596
1551
  }
1597
1552
 
1598
- // src/commands/dev-sync.ts
1599
- var import_chalk13 = __toESM(require("chalk"));
1600
- var import_child_process5 = require("child_process");
1601
- var import_path7 = __toESM(require("path"));
1602
- async function devSyncCommand(workspaceName) {
1603
- if (!isAuthenticated()) {
1604
- console.log(import_chalk13.default.red('Not logged in. Please run "replicas login" first.'));
1605
- process.exit(1);
1606
- }
1607
- try {
1608
- const { workspace, sshKeyPath } = await prepareWorkspaceConnection(workspaceName, {});
1609
- if (!workspace.ipv4_address) {
1610
- throw new Error("Workspace does not have an IP address");
1611
- }
1612
- console.log(import_chalk13.default.blue(`
1613
- Syncing engine to ${workspace.name}...`));
1614
- const scriptPath = import_path7.default.resolve(__dirname, "../../../engine/scripts/dev-sync.sh");
1615
- const devSync = (0, import_child_process5.spawn)(scriptPath, [
1616
- "--ip",
1617
- workspace.ipv4_address,
1618
- "--key",
1619
- sshKeyPath
1620
- ], {
1621
- stdio: "inherit",
1622
- shell: true
1623
- });
1624
- await new Promise((resolve, reject) => {
1625
- devSync.on("close", (code) => {
1626
- if (code === 0) {
1627
- resolve();
1628
- } else {
1629
- reject(new Error(`dev-sync script exited with code ${code}`));
1630
- }
1631
- });
1632
- devSync.on("error", (error) => {
1633
- reject(error);
1634
- });
1635
- });
1636
- console.log(import_chalk13.default.green("\n\u2713 Engine synced successfully.\n"));
1637
- console.log(import_chalk13.default.blue("Viewing logs (Ctrl+C to exit)...\n"));
1638
- const logs = (0, import_child_process5.spawn)("ssh", [
1639
- "-i",
1640
- sshKeyPath,
1641
- `ubuntu@${workspace.ipv4_address}`,
1642
- "sudo journalctl -fu replicas-engine"
1643
- ], {
1644
- stdio: "inherit"
1645
- });
1646
- process.on("SIGINT", () => {
1647
- logs.kill("SIGTERM");
1648
- console.log(import_chalk13.default.green("\n\n\u2713 Disconnected from logs.\n"));
1649
- process.exit(0);
1650
- });
1651
- await new Promise((resolve) => {
1652
- logs.on("close", () => {
1653
- resolve();
1654
- });
1655
- });
1656
- } catch (error) {
1657
- console.error(import_chalk13.default.red(`
1658
- Error: ${error instanceof Error ? error.message : "Unknown error"}`));
1659
- process.exit(1);
1660
- }
1661
- }
1662
-
1663
1553
  // src/commands/init.ts
1664
- var import_chalk14 = __toESM(require("chalk"));
1665
- var import_fs6 = __toESM(require("fs"));
1666
- var import_path8 = __toESM(require("path"));
1554
+ var import_chalk13 = __toESM(require("chalk"));
1555
+ var import_fs4 = __toESM(require("fs"));
1556
+ var import_path5 = __toESM(require("path"));
1667
1557
  var REPLICAS_CONFIG_FILENAME = "replicas.json";
1668
1558
  function getDefaultConfig() {
1669
1559
  return {
@@ -1677,34 +1567,34 @@ function getDefaultConfig() {
1677
1567
  };
1678
1568
  }
1679
1569
  function initCommand(options) {
1680
- const configPath = import_path8.default.join(process.cwd(), REPLICAS_CONFIG_FILENAME);
1681
- if (import_fs6.default.existsSync(configPath) && !options.force) {
1570
+ const configPath = import_path5.default.join(process.cwd(), REPLICAS_CONFIG_FILENAME);
1571
+ if (import_fs4.default.existsSync(configPath) && !options.force) {
1682
1572
  console.log(
1683
- import_chalk14.default.yellow(
1573
+ import_chalk13.default.yellow(
1684
1574
  `${REPLICAS_CONFIG_FILENAME} already exists in this directory.`
1685
1575
  )
1686
1576
  );
1687
- console.log(import_chalk14.default.gray("Use --force to overwrite the existing file."));
1577
+ console.log(import_chalk13.default.gray("Use --force to overwrite the existing file."));
1688
1578
  return;
1689
1579
  }
1690
1580
  const defaultConfig = getDefaultConfig();
1691
1581
  const configContent = JSON.stringify(defaultConfig, null, 2);
1692
1582
  try {
1693
- import_fs6.default.writeFileSync(configPath, configContent + "\n", "utf-8");
1694
- console.log(import_chalk14.default.green(`\u2713 Created ${REPLICAS_CONFIG_FILENAME}`));
1583
+ import_fs4.default.writeFileSync(configPath, configContent + "\n", "utf-8");
1584
+ console.log(import_chalk13.default.green(`\u2713 Created ${REPLICAS_CONFIG_FILENAME}`));
1695
1585
  console.log("");
1696
- console.log(import_chalk14.default.gray("Configuration options:"));
1586
+ console.log(import_chalk13.default.gray("Configuration options:"));
1697
1587
  console.log(
1698
- import_chalk14.default.gray(' copy - Files to sync to the workspace (e.g., [".env"])')
1588
+ import_chalk13.default.gray(' copy - Files to sync to the workspace (e.g., [".env"])')
1699
1589
  );
1700
1590
  console.log(
1701
- import_chalk14.default.gray(" ports - Ports to forward from the workspace (e.g., [3000, 8080])")
1591
+ import_chalk13.default.gray(" ports - Ports to forward from the workspace (e.g., [3000, 8080])")
1702
1592
  );
1703
1593
  console.log(
1704
- import_chalk14.default.gray(" systemPrompt - Custom instructions for AI coding assistants")
1594
+ import_chalk13.default.gray(" systemPrompt - Custom instructions for AI coding assistants")
1705
1595
  );
1706
1596
  console.log(
1707
- import_chalk14.default.gray(" startHook - Commands to run on workspace startup")
1597
+ import_chalk13.default.gray(" startHook - Commands to run on workspace startup")
1708
1598
  );
1709
1599
  } catch (error) {
1710
1600
  throw new Error(
@@ -1714,7 +1604,7 @@ function initCommand(options) {
1714
1604
  }
1715
1605
 
1716
1606
  // src/lib/version-check.ts
1717
- var import_chalk15 = __toESM(require("chalk"));
1607
+ var import_chalk14 = __toESM(require("chalk"));
1718
1608
  var MONOLITH_URL2 = process.env.REPLICAS_MONOLITH_URL || "https://api.replicas.dev";
1719
1609
  var VERSION_CHECK_TIMEOUT = 2e3;
1720
1610
  function compareVersions(v1, v2) {
@@ -1740,9 +1630,9 @@ async function checkForUpdates(currentVersion) {
1740
1630
  const data = await response.json();
1741
1631
  const latestVersion = data.version;
1742
1632
  if (compareVersions(latestVersion, currentVersion) > 0) {
1743
- console.error(import_chalk15.default.gray(`
1633
+ console.error(import_chalk14.default.gray(`
1744
1634
  Update available: ${currentVersion} \u2192 ${latestVersion}`));
1745
- console.error(import_chalk15.default.gray(`Run: npm i -g replicas-cli@latest
1635
+ console.error(import_chalk14.default.gray(`Run: npm i -g replicas-cli@latest
1746
1636
  `));
1747
1637
  }
1748
1638
  } catch {
@@ -1750,9 +1640,17 @@ Update available: ${currentVersion} \u2192 ${latestVersion}`));
1750
1640
  }
1751
1641
 
1752
1642
  // src/commands/replica.ts
1753
- var import_chalk16 = __toESM(require("chalk"));
1643
+ var import_chalk15 = __toESM(require("chalk"));
1754
1644
  var import_prompts3 = __toESM(require("prompts"));
1755
1645
 
1646
+ // ../shared/src/sandbox.ts
1647
+ var SANDBOX_LIFECYCLE = {
1648
+ AUTO_STOP_MINUTES: 60,
1649
+ AUTO_ARCHIVE_MINUTES: 60 * 24 * 7,
1650
+ AUTO_DELETE_MINUTES: -1,
1651
+ SSH_TOKEN_EXPIRATION_MINUTES: 3 * 60
1652
+ };
1653
+
1756
1654
  // ../shared/src/display-message/parsers/codex-parser.ts
1757
1655
  function safeJsonParse(str, fallback) {
1758
1656
  try {
@@ -2181,12 +2079,9 @@ function formatDate(dateString) {
2181
2079
  function formatStatus(status) {
2182
2080
  switch (status) {
2183
2081
  case "active":
2184
- return import_chalk16.default.green(status);
2185
- case "booting":
2186
- case "initializing":
2187
- return import_chalk16.default.yellow(status);
2082
+ return import_chalk15.default.green(status);
2188
2083
  case "sleeping":
2189
- return import_chalk16.default.gray(status);
2084
+ return import_chalk15.default.gray(status);
2190
2085
  default:
2191
2086
  return status;
2192
2087
  }
@@ -2199,87 +2094,87 @@ function formatDisplayMessage(message) {
2199
2094
  const time = new Date(message.timestamp).toLocaleTimeString();
2200
2095
  switch (message.type) {
2201
2096
  case "user":
2202
- console.log(import_chalk16.default.blue(`
2097
+ console.log(import_chalk15.default.blue(`
2203
2098
  [${time}] USER:`));
2204
- console.log(import_chalk16.default.white(` ${truncate(message.content, 500)}`));
2099
+ console.log(import_chalk15.default.white(` ${truncate(message.content, 500)}`));
2205
2100
  break;
2206
2101
  case "agent":
2207
- console.log(import_chalk16.default.green(`
2102
+ console.log(import_chalk15.default.green(`
2208
2103
  [${time}] ASSISTANT:`));
2209
- console.log(import_chalk16.default.white(` ${truncate(message.content, 500)}`));
2104
+ console.log(import_chalk15.default.white(` ${truncate(message.content, 500)}`));
2210
2105
  break;
2211
2106
  case "reasoning":
2212
- console.log(import_chalk16.default.gray(`
2107
+ console.log(import_chalk15.default.gray(`
2213
2108
  [${time}] THINKING:`));
2214
- console.log(import_chalk16.default.gray(` ${truncate(message.content, 300)}`));
2109
+ console.log(import_chalk15.default.gray(` ${truncate(message.content, 300)}`));
2215
2110
  break;
2216
2111
  case "command":
2217
- console.log(import_chalk16.default.magenta(`
2112
+ console.log(import_chalk15.default.magenta(`
2218
2113
  [${time}] COMMAND:`));
2219
- console.log(import_chalk16.default.white(` $ ${message.command}`));
2114
+ console.log(import_chalk15.default.white(` $ ${message.command}`));
2220
2115
  if (message.output) {
2221
- console.log(import_chalk16.default.gray(` ${truncate(message.output, 200)}`));
2116
+ console.log(import_chalk15.default.gray(` ${truncate(message.output, 200)}`));
2222
2117
  }
2223
2118
  if (message.exitCode !== void 0) {
2224
- const exitColor = message.exitCode === 0 ? import_chalk16.default.green : import_chalk16.default.red;
2119
+ const exitColor = message.exitCode === 0 ? import_chalk15.default.green : import_chalk15.default.red;
2225
2120
  console.log(exitColor(` Exit code: ${message.exitCode}`));
2226
2121
  }
2227
2122
  break;
2228
2123
  case "file_change":
2229
- console.log(import_chalk16.default.yellow(`
2124
+ console.log(import_chalk15.default.yellow(`
2230
2125
  [${time}] FILE CHANGES:`));
2231
2126
  for (const change of message.changes) {
2232
2127
  const icon = change.kind === "add" ? "+" : change.kind === "delete" ? "-" : "~";
2233
- const color = change.kind === "add" ? import_chalk16.default.green : change.kind === "delete" ? import_chalk16.default.red : import_chalk16.default.yellow;
2128
+ const color = change.kind === "add" ? import_chalk15.default.green : change.kind === "delete" ? import_chalk15.default.red : import_chalk15.default.yellow;
2234
2129
  console.log(color(` ${icon} ${change.path}`));
2235
2130
  }
2236
2131
  break;
2237
2132
  case "patch":
2238
- console.log(import_chalk16.default.yellow(`
2133
+ console.log(import_chalk15.default.yellow(`
2239
2134
  [${time}] PATCH:`));
2240
2135
  for (const op of message.operations) {
2241
2136
  const icon = op.action === "add" ? "+" : op.action === "delete" ? "-" : "~";
2242
- const color = op.action === "add" ? import_chalk16.default.green : op.action === "delete" ? import_chalk16.default.red : import_chalk16.default.yellow;
2137
+ const color = op.action === "add" ? import_chalk15.default.green : op.action === "delete" ? import_chalk15.default.red : import_chalk15.default.yellow;
2243
2138
  console.log(color(` ${icon} ${op.path}`));
2244
2139
  }
2245
2140
  break;
2246
2141
  case "tool_call":
2247
- console.log(import_chalk16.default.cyan(`
2142
+ console.log(import_chalk15.default.cyan(`
2248
2143
  [${time}] TOOL: ${message.tool}`));
2249
2144
  if (message.output) {
2250
- console.log(import_chalk16.default.gray(` ${truncate(message.output, 200)}`));
2145
+ console.log(import_chalk15.default.gray(` ${truncate(message.output, 200)}`));
2251
2146
  }
2252
2147
  break;
2253
2148
  case "web_search":
2254
- console.log(import_chalk16.default.cyan(`
2149
+ console.log(import_chalk15.default.cyan(`
2255
2150
  [${time}] WEB SEARCH:`));
2256
- console.log(import_chalk16.default.white(` "${message.query}"`));
2151
+ console.log(import_chalk15.default.white(` "${message.query}"`));
2257
2152
  break;
2258
2153
  case "todo_list":
2259
- console.log(import_chalk16.default.blue(`
2154
+ console.log(import_chalk15.default.blue(`
2260
2155
  [${time}] PLAN:`));
2261
2156
  for (const item of message.items) {
2262
- const icon = item.completed ? import_chalk16.default.green("[x]") : import_chalk16.default.gray("[ ]");
2157
+ const icon = item.completed ? import_chalk15.default.green("[x]") : import_chalk15.default.gray("[ ]");
2263
2158
  console.log(` ${icon} ${item.text}`);
2264
2159
  }
2265
2160
  break;
2266
2161
  case "subagent":
2267
- console.log(import_chalk16.default.magenta(`
2162
+ console.log(import_chalk15.default.magenta(`
2268
2163
  [${time}] SUBAGENT: ${message.description}`));
2269
2164
  if (message.output) {
2270
- console.log(import_chalk16.default.gray(` ${truncate(message.output, 200)}`));
2165
+ console.log(import_chalk15.default.gray(` ${truncate(message.output, 200)}`));
2271
2166
  }
2272
2167
  break;
2273
2168
  case "error":
2274
- console.log(import_chalk16.default.red(`
2169
+ console.log(import_chalk15.default.red(`
2275
2170
  [${time}] ERROR:`));
2276
- console.log(import_chalk16.default.red(` ${message.message}`));
2171
+ console.log(import_chalk15.default.red(` ${message.message}`));
2277
2172
  break;
2278
2173
  }
2279
2174
  }
2280
2175
  async function replicaListCommand(options) {
2281
2176
  if (!isAuthenticated()) {
2282
- console.log(import_chalk16.default.red('Not logged in. Please run "replicas login" first.'));
2177
+ console.log(import_chalk15.default.red('Not logged in. Please run "replicas login" first.'));
2283
2178
  process.exit(1);
2284
2179
  }
2285
2180
  try {
@@ -2291,96 +2186,93 @@ async function replicaListCommand(options) {
2291
2186
  `/v1/replica${query ? "?" + query : ""}`
2292
2187
  );
2293
2188
  if (response.replicas.length === 0) {
2294
- console.log(import_chalk16.default.yellow("\nNo replicas found.\n"));
2189
+ console.log(import_chalk15.default.yellow("\nNo replicas found.\n"));
2295
2190
  return;
2296
2191
  }
2297
- console.log(import_chalk16.default.green(`
2192
+ console.log(import_chalk15.default.green(`
2298
2193
  Replicas (Page ${response.page} of ${response.totalPages}, Total: ${response.total}):
2299
2194
  `));
2300
2195
  for (const replica of response.replicas) {
2301
- console.log(import_chalk16.default.white(` ${replica.name}`));
2302
- console.log(import_chalk16.default.gray(` ID: ${replica.id}`));
2196
+ console.log(import_chalk15.default.white(` ${replica.name}`));
2197
+ console.log(import_chalk15.default.gray(` ID: ${replica.id}`));
2303
2198
  if (replica.repository) {
2304
- console.log(import_chalk16.default.gray(` Repository: ${replica.repository}`));
2199
+ console.log(import_chalk15.default.gray(` Repository: ${replica.repository}`));
2305
2200
  }
2306
- console.log(import_chalk16.default.gray(` Instance: ${replica.instance_type}`));
2307
- console.log(import_chalk16.default.gray(` Status: ${formatStatus(replica.status)}`));
2308
- console.log(import_chalk16.default.gray(` Created: ${formatDate(replica.created_at)}`));
2201
+ console.log(import_chalk15.default.gray(` Status: ${formatStatus(replica.status)}`));
2202
+ console.log(import_chalk15.default.gray(` Created: ${formatDate(replica.created_at)}`));
2309
2203
  if (replica.pull_requests && replica.pull_requests.length > 0) {
2310
- console.log(import_chalk16.default.gray(` Pull Requests:`));
2204
+ console.log(import_chalk15.default.gray(` Pull Requests:`));
2311
2205
  for (const pr of replica.pull_requests) {
2312
- console.log(import_chalk16.default.cyan(` - #${pr.number}: ${pr.url}`));
2206
+ console.log(import_chalk15.default.cyan(` - #${pr.number}: ${pr.url}`));
2313
2207
  }
2314
2208
  }
2315
2209
  console.log();
2316
2210
  }
2317
2211
  } catch (error) {
2318
- console.error(import_chalk16.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2212
+ console.error(import_chalk15.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2319
2213
  process.exit(1);
2320
2214
  }
2321
2215
  }
2322
2216
  async function replicaGetCommand(id) {
2323
2217
  if (!isAuthenticated()) {
2324
- console.log(import_chalk16.default.red('Not logged in. Please run "replicas login" first.'));
2218
+ console.log(import_chalk15.default.red('Not logged in. Please run "replicas login" first.'));
2325
2219
  process.exit(1);
2326
2220
  }
2327
2221
  try {
2328
2222
  const response = await orgAuthenticatedFetch(`/v1/replica/${id}`);
2329
2223
  const replica = response.replica;
2330
- console.log(import_chalk16.default.green(`
2224
+ console.log(import_chalk15.default.green(`
2331
2225
  Replica: ${replica.name}
2332
2226
  `));
2333
- console.log(import_chalk16.default.gray(` ID: ${replica.id}`));
2227
+ console.log(import_chalk15.default.gray(` ID: ${replica.id}`));
2334
2228
  if (replica.repository) {
2335
- console.log(import_chalk16.default.gray(` Repository: ${replica.repository}`));
2229
+ console.log(import_chalk15.default.gray(` Repository: ${replica.repository}`));
2336
2230
  }
2337
- console.log(import_chalk16.default.gray(` Instance: ${replica.instance_type}`));
2338
- console.log(import_chalk16.default.gray(` Status: ${formatStatus(replica.status)}`));
2339
- console.log(import_chalk16.default.gray(` Created: ${formatDate(replica.created_at)}`));
2231
+ console.log(import_chalk15.default.gray(` Status: ${formatStatus(replica.status)}`));
2232
+ console.log(import_chalk15.default.gray(` Created: ${formatDate(replica.created_at)}`));
2340
2233
  if (replica.waking) {
2341
- console.log(import_chalk16.default.yellow("\n Workspace is waking from sleep. Retry in 30-90 seconds for full details.\n"));
2234
+ console.log(import_chalk15.default.yellow("\n Workspace is waking from sleep. Retry in 30-90 seconds for full details.\n"));
2342
2235
  } else {
2343
2236
  if (replica.coding_agent) {
2344
- console.log(import_chalk16.default.gray(` Coding Agent: ${replica.coding_agent}`));
2237
+ console.log(import_chalk15.default.gray(` Coding Agent: ${replica.coding_agent}`));
2345
2238
  }
2346
2239
  if (replica.branch) {
2347
- console.log(import_chalk16.default.gray(` Branch: ${replica.branch}`));
2240
+ console.log(import_chalk15.default.gray(` Branch: ${replica.branch}`));
2348
2241
  }
2349
2242
  if (replica.git_diff) {
2350
- console.log(import_chalk16.default.gray(` Changes: ${import_chalk16.default.green(`+${replica.git_diff.added}`)} / ${import_chalk16.default.red(`-${replica.git_diff.removed}`)}`));
2243
+ console.log(import_chalk15.default.gray(` Changes: ${import_chalk15.default.green(`+${replica.git_diff.added}`)} / ${import_chalk15.default.red(`-${replica.git_diff.removed}`)}`));
2351
2244
  }
2352
2245
  }
2353
2246
  if (replica.pull_requests && replica.pull_requests.length > 0) {
2354
- console.log(import_chalk16.default.gray(` Pull Requests:`));
2247
+ console.log(import_chalk15.default.gray(` Pull Requests:`));
2355
2248
  for (const pr of replica.pull_requests) {
2356
- console.log(import_chalk16.default.cyan(` - #${pr.number}: ${pr.url}`));
2249
+ console.log(import_chalk15.default.cyan(` - #${pr.number}: ${pr.url}`));
2357
2250
  }
2358
2251
  }
2359
2252
  console.log();
2360
2253
  } catch (error) {
2361
- console.error(import_chalk16.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2254
+ console.error(import_chalk15.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2362
2255
  process.exit(1);
2363
2256
  }
2364
2257
  }
2365
2258
  async function replicaCreateCommand(name, options) {
2366
2259
  if (!isAuthenticated()) {
2367
- console.log(import_chalk16.default.red('Not logged in. Please run "replicas login" first.'));
2260
+ console.log(import_chalk15.default.red('Not logged in. Please run "replicas login" first.'));
2368
2261
  process.exit(1);
2369
2262
  }
2370
2263
  try {
2371
2264
  const repoResponse = await orgAuthenticatedFetch("/v1/repositories");
2372
2265
  const repositories = repoResponse.repositories;
2373
2266
  if (repositories.length === 0) {
2374
- console.log(import_chalk16.default.red("No repositories found. Please add a repository first."));
2267
+ console.log(import_chalk15.default.red("No repositories found. Please add a repository first."));
2375
2268
  process.exit(1);
2376
2269
  }
2377
2270
  let replicaName = name;
2378
2271
  let message = options.message;
2379
2272
  let repository = options.repository;
2380
- let instanceType = options.instanceType;
2381
2273
  let codingAgent = options.agent;
2382
2274
  if (replicaName && /\s/.test(replicaName)) {
2383
- console.log(import_chalk16.default.red("Replica name cannot contain spaces."));
2275
+ console.log(import_chalk15.default.red("Replica name cannot contain spaces."));
2384
2276
  process.exit(1);
2385
2277
  }
2386
2278
  if (!replicaName) {
@@ -2395,7 +2287,7 @@ async function replicaCreateCommand(name, options) {
2395
2287
  }
2396
2288
  });
2397
2289
  if (!response2.name) {
2398
- console.log(import_chalk16.default.yellow("\nCancelled."));
2290
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2399
2291
  return;
2400
2292
  }
2401
2293
  replicaName = response2.name;
@@ -2412,7 +2304,7 @@ async function replicaCreateCommand(name, options) {
2412
2304
  }))
2413
2305
  });
2414
2306
  if (!response2.repository) {
2415
- console.log(import_chalk16.default.yellow("\nCancelled."));
2307
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2416
2308
  return;
2417
2309
  }
2418
2310
  repository = response2.repository;
@@ -2425,29 +2317,11 @@ async function replicaCreateCommand(name, options) {
2425
2317
  validate: (value) => value.trim() ? true : "Message is required"
2426
2318
  });
2427
2319
  if (!response2.message) {
2428
- console.log(import_chalk16.default.yellow("\nCancelled."));
2320
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2429
2321
  return;
2430
2322
  }
2431
2323
  message = response2.message;
2432
2324
  }
2433
- if (!instanceType) {
2434
- const response2 = await (0, import_prompts3.default)({
2435
- type: "select",
2436
- name: "instanceType",
2437
- message: "Select instance type:",
2438
- choices: [
2439
- { title: "Standard (2 vCPU, 4GB RAM)", value: "standard" },
2440
- { title: "Large (2 vCPU, 8GB RAM)", value: "large" },
2441
- { title: "Power (4 vCPU, 16GB RAM)", value: "power" }
2442
- ],
2443
- initial: 0
2444
- });
2445
- if (!response2.instanceType) {
2446
- console.log(import_chalk16.default.yellow("\nCancelled."));
2447
- return;
2448
- }
2449
- instanceType = response2.instanceType;
2450
- }
2451
2325
  if (!codingAgent) {
2452
2326
  const response2 = await (0, import_prompts3.default)({
2453
2327
  type: "select",
@@ -2460,46 +2334,40 @@ async function replicaCreateCommand(name, options) {
2460
2334
  initial: 0
2461
2335
  });
2462
2336
  if (!response2.agent) {
2463
- console.log(import_chalk16.default.yellow("\nCancelled."));
2337
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2464
2338
  return;
2465
2339
  }
2466
2340
  codingAgent = response2.agent;
2467
2341
  }
2468
- if (!instanceType || !["standard", "large", "power"].includes(instanceType)) {
2469
- console.log(import_chalk16.default.red(`Invalid instance type: ${instanceType}. Must be one of: standard, large, power`));
2470
- process.exit(1);
2471
- }
2472
2342
  if (!codingAgent || !["claude", "codex"].includes(codingAgent)) {
2473
- console.log(import_chalk16.default.red(`Invalid coding agent: ${codingAgent}. Must be one of: claude, codex`));
2343
+ console.log(import_chalk15.default.red(`Invalid coding agent: ${codingAgent}. Must be one of: claude, codex`));
2474
2344
  process.exit(1);
2475
2345
  }
2476
2346
  const body = {
2477
2347
  name: replicaName,
2478
2348
  message,
2479
2349
  repository,
2480
- instance_type: instanceType,
2481
2350
  coding_agent: codingAgent
2482
2351
  };
2483
- console.log(import_chalk16.default.gray("\nCreating replica..."));
2352
+ console.log(import_chalk15.default.gray("\nCreating replica..."));
2484
2353
  const response = await orgAuthenticatedFetch("/v1/replica", {
2485
2354
  method: "POST",
2486
2355
  body
2487
2356
  });
2488
2357
  const replica = response.replica;
2489
- console.log(import_chalk16.default.green(`
2358
+ console.log(import_chalk15.default.green(`
2490
2359
  Created replica: ${replica.name}`));
2491
- console.log(import_chalk16.default.gray(` ID: ${replica.id}`));
2492
- console.log(import_chalk16.default.gray(` Instance: ${replica.instance_type}`));
2493
- console.log(import_chalk16.default.gray(` Status: ${formatStatus(replica.status)}`));
2360
+ console.log(import_chalk15.default.gray(` ID: ${replica.id}`));
2361
+ console.log(import_chalk15.default.gray(` Status: ${formatStatus(replica.status)}`));
2494
2362
  console.log();
2495
2363
  } catch (error) {
2496
- console.error(import_chalk16.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2364
+ console.error(import_chalk15.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2497
2365
  process.exit(1);
2498
2366
  }
2499
2367
  }
2500
2368
  async function replicaSendCommand(id, options) {
2501
2369
  if (!isAuthenticated()) {
2502
- console.log(import_chalk16.default.red('Not logged in. Please run "replicas login" first.'));
2370
+ console.log(import_chalk15.default.red('Not logged in. Please run "replicas login" first.'));
2503
2371
  process.exit(1);
2504
2372
  }
2505
2373
  try {
@@ -2512,7 +2380,7 @@ async function replicaSendCommand(id, options) {
2512
2380
  validate: (value) => value.trim() ? true : "Message is required"
2513
2381
  });
2514
2382
  if (!response2.message) {
2515
- console.log(import_chalk16.default.yellow("\nCancelled."));
2383
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2516
2384
  return;
2517
2385
  }
2518
2386
  message = response2.message;
@@ -2522,7 +2390,7 @@ async function replicaSendCommand(id, options) {
2522
2390
  };
2523
2391
  if (options.agent) {
2524
2392
  if (!["claude", "codex"].includes(options.agent)) {
2525
- console.log(import_chalk16.default.red(`Invalid coding agent: ${options.agent}. Must be one of: claude, codex`));
2393
+ console.log(import_chalk15.default.red(`Invalid coding agent: ${options.agent}. Must be one of: claude, codex`));
2526
2394
  process.exit(1);
2527
2395
  }
2528
2396
  body.coding_agent = options.agent;
@@ -2534,21 +2402,21 @@ async function replicaSendCommand(id, options) {
2534
2402
  body
2535
2403
  }
2536
2404
  );
2537
- const statusColor = response.status === "sent" ? import_chalk16.default.green : import_chalk16.default.yellow;
2405
+ const statusColor = response.status === "sent" ? import_chalk15.default.green : import_chalk15.default.yellow;
2538
2406
  console.log(statusColor(`
2539
2407
  Message ${response.status}`));
2540
2408
  if (response.position !== void 0 && response.position > 0) {
2541
- console.log(import_chalk16.default.gray(` Queue position: ${response.position}`));
2409
+ console.log(import_chalk15.default.gray(` Queue position: ${response.position}`));
2542
2410
  }
2543
2411
  console.log();
2544
2412
  } catch (error) {
2545
- console.error(import_chalk16.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2413
+ console.error(import_chalk15.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2546
2414
  process.exit(1);
2547
2415
  }
2548
2416
  }
2549
2417
  async function replicaDeleteCommand(id, options) {
2550
2418
  if (!isAuthenticated()) {
2551
- console.log(import_chalk16.default.red('Not logged in. Please run "replicas login" first.'));
2419
+ console.log(import_chalk15.default.red('Not logged in. Please run "replicas login" first.'));
2552
2420
  process.exit(1);
2553
2421
  }
2554
2422
  try {
@@ -2560,24 +2428,24 @@ async function replicaDeleteCommand(id, options) {
2560
2428
  initial: false
2561
2429
  });
2562
2430
  if (!response.confirm) {
2563
- console.log(import_chalk16.default.yellow("\nCancelled."));
2431
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2564
2432
  return;
2565
2433
  }
2566
2434
  }
2567
2435
  await orgAuthenticatedFetch(`/v1/replica/${id}`, {
2568
2436
  method: "DELETE"
2569
2437
  });
2570
- console.log(import_chalk16.default.green(`
2438
+ console.log(import_chalk15.default.green(`
2571
2439
  Replica ${id} deleted.
2572
2440
  `));
2573
2441
  } catch (error) {
2574
- console.error(import_chalk16.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2442
+ console.error(import_chalk15.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2575
2443
  process.exit(1);
2576
2444
  }
2577
2445
  }
2578
2446
  async function replicaReadCommand(id, options) {
2579
2447
  if (!isAuthenticated()) {
2580
- console.log(import_chalk16.default.red('Not logged in. Please run "replicas login" first.'));
2448
+ console.log(import_chalk15.default.red('Not logged in. Please run "replicas login" first.'));
2581
2449
  process.exit(1);
2582
2450
  }
2583
2451
  try {
@@ -2589,79 +2457,79 @@ async function replicaReadCommand(id, options) {
2589
2457
  `/v1/replica/${id}/read${query ? "?" + query : ""}`
2590
2458
  );
2591
2459
  if (response.waking) {
2592
- console.log(import_chalk16.default.yellow("\nWorkspace is waking from sleep. Retry in 30-90 seconds.\n"));
2460
+ console.log(import_chalk15.default.yellow("\nWorkspace is waking from sleep. Retry in 30-90 seconds.\n"));
2593
2461
  return;
2594
2462
  }
2595
- console.log(import_chalk16.default.green(`
2463
+ console.log(import_chalk15.default.green(`
2596
2464
  Conversation History
2597
2465
  `));
2598
2466
  if (response.coding_agent) {
2599
- console.log(import_chalk16.default.gray(` Agent: ${response.coding_agent}`));
2467
+ console.log(import_chalk15.default.gray(` Agent: ${response.coding_agent}`));
2600
2468
  }
2601
2469
  if (response.thread_id) {
2602
- console.log(import_chalk16.default.gray(` Thread ID: ${response.thread_id}`));
2470
+ console.log(import_chalk15.default.gray(` Thread ID: ${response.thread_id}`));
2603
2471
  }
2604
- console.log(import_chalk16.default.gray(` Total Events: ${response.total}`));
2605
- console.log(import_chalk16.default.gray(` Showing: ${response.events.length} events`));
2472
+ console.log(import_chalk15.default.gray(` Total Events: ${response.total}`));
2473
+ console.log(import_chalk15.default.gray(` Showing: ${response.events.length} events`));
2606
2474
  if (response.hasMore) {
2607
- console.log(import_chalk16.default.gray(` Has More: yes (use --offset to paginate)`));
2475
+ console.log(import_chalk15.default.gray(` Has More: yes (use --offset to paginate)`));
2608
2476
  }
2609
2477
  console.log();
2610
2478
  if (response.events.length === 0) {
2611
- console.log(import_chalk16.default.yellow(" No events found.\n"));
2479
+ console.log(import_chalk15.default.yellow(" No events found.\n"));
2612
2480
  return;
2613
2481
  }
2614
- console.log(import_chalk16.default.gray("-".repeat(60)));
2482
+ console.log(import_chalk15.default.gray("-".repeat(60)));
2615
2483
  const agentType = response.coding_agent || "claude";
2616
2484
  const displayMessages = parseAgentEvents(response.events, agentType);
2617
2485
  for (const message of displayMessages) {
2618
2486
  formatDisplayMessage(message);
2619
2487
  }
2620
- console.log(import_chalk16.default.gray("\n" + "-".repeat(60)));
2488
+ console.log(import_chalk15.default.gray("\n" + "-".repeat(60)));
2621
2489
  console.log();
2622
2490
  } catch (error) {
2623
- console.error(import_chalk16.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2491
+ console.error(import_chalk15.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2624
2492
  process.exit(1);
2625
2493
  }
2626
2494
  }
2627
2495
 
2628
2496
  // src/commands/repositories.ts
2629
- var import_chalk17 = __toESM(require("chalk"));
2497
+ var import_chalk16 = __toESM(require("chalk"));
2630
2498
  function formatDate2(dateString) {
2631
2499
  return new Date(dateString).toLocaleString();
2632
2500
  }
2633
2501
  async function repositoriesListCommand() {
2634
2502
  if (!isAuthenticated()) {
2635
- console.log(import_chalk17.default.red('Not logged in. Please run "replicas login" first.'));
2503
+ console.log(import_chalk16.default.red('Not logged in. Please run "replicas login" first.'));
2636
2504
  process.exit(1);
2637
2505
  }
2638
2506
  try {
2639
2507
  const response = await orgAuthenticatedFetch("/v1/repositories");
2640
2508
  if (response.repositories.length === 0) {
2641
- console.log(import_chalk17.default.yellow("\nNo repositories found.\n"));
2509
+ console.log(import_chalk16.default.yellow("\nNo repositories found.\n"));
2642
2510
  return;
2643
2511
  }
2644
- console.log(import_chalk17.default.green(`
2512
+ console.log(import_chalk16.default.green(`
2645
2513
  Repositories (${response.repositories.length}):
2646
2514
  `));
2647
2515
  for (const repo of response.repositories) {
2648
- console.log(import_chalk17.default.white(` ${repo.name}`));
2649
- console.log(import_chalk17.default.gray(` URL: ${repo.url}`));
2650
- console.log(import_chalk17.default.gray(` Default Branch: ${repo.default_branch}`));
2651
- console.log(import_chalk17.default.gray(` Created: ${formatDate2(repo.created_at)}`));
2516
+ console.log(import_chalk16.default.white(` ${repo.name}`));
2517
+ console.log(import_chalk16.default.gray(` URL: ${repo.url}`));
2518
+ console.log(import_chalk16.default.gray(` Default Branch: ${repo.default_branch}`));
2519
+ console.log(import_chalk16.default.gray(` Created: ${formatDate2(repo.created_at)}`));
2652
2520
  if (repo.github_repository_id) {
2653
- console.log(import_chalk17.default.gray(` GitHub ID: ${repo.github_repository_id}`));
2521
+ console.log(import_chalk16.default.gray(` GitHub ID: ${repo.github_repository_id}`));
2654
2522
  }
2655
2523
  console.log();
2656
2524
  }
2657
2525
  } catch (error) {
2658
- console.error(import_chalk17.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2526
+ console.error(import_chalk16.default.red(`Error: ${error instanceof Error ? error.message : "Unknown error"}`));
2659
2527
  process.exit(1);
2660
2528
  }
2661
2529
  }
2662
2530
 
2663
2531
  // src/index.ts
2664
- var CLI_VERSION = "0.2.28";
2532
+ var CLI_VERSION = "0.2.29";
2665
2533
  var program = new import_commander.Command();
2666
2534
  program.name("replicas").description("CLI for managing Replicas workspaces").version(CLI_VERSION);
2667
2535
  program.command("login").description("Authenticate with your Replicas account").action(async () => {
@@ -2669,7 +2537,7 @@ program.command("login").description("Authenticate with your Replicas account").
2669
2537
  await loginCommand();
2670
2538
  } catch (error) {
2671
2539
  if (error instanceof Error) {
2672
- console.error(import_chalk18.default.red(`
2540
+ console.error(import_chalk17.default.red(`
2673
2541
  \u2717 ${error.message}
2674
2542
  `));
2675
2543
  }
@@ -2681,7 +2549,7 @@ program.command("init").description("Create a replicas.json configuration file")
2681
2549
  initCommand(options);
2682
2550
  } catch (error) {
2683
2551
  if (error instanceof Error) {
2684
- console.error(import_chalk18.default.red(`
2552
+ console.error(import_chalk17.default.red(`
2685
2553
  \u2717 ${error.message}
2686
2554
  `));
2687
2555
  }
@@ -2693,7 +2561,7 @@ program.command("logout").description("Clear stored credentials").action(() => {
2693
2561
  logoutCommand();
2694
2562
  } catch (error) {
2695
2563
  if (error instanceof Error) {
2696
- console.error(import_chalk18.default.red(`
2564
+ console.error(import_chalk17.default.red(`
2697
2565
  \u2717 ${error.message}
2698
2566
  `));
2699
2567
  }
@@ -2705,7 +2573,7 @@ program.command("whoami").description("Display current authenticated user").acti
2705
2573
  await whoamiCommand();
2706
2574
  } catch (error) {
2707
2575
  if (error instanceof Error) {
2708
- console.error(import_chalk18.default.red(`
2576
+ console.error(import_chalk17.default.red(`
2709
2577
  \u2717 ${error.message}
2710
2578
  `));
2711
2579
  }
@@ -2717,7 +2585,7 @@ program.command("tools").description("List tools available on the Replicas Machi
2717
2585
  await toolsCommand();
2718
2586
  } catch (error) {
2719
2587
  if (error instanceof Error) {
2720
- console.error(import_chalk18.default.red(`
2588
+ console.error(import_chalk17.default.red(`
2721
2589
  \u2717 ${error.message}
2722
2590
  `));
2723
2591
  }
@@ -2729,7 +2597,7 @@ program.command("codex-auth").description("Authenticate Replicas with your Codex
2729
2597
  await codexAuthCommand(options);
2730
2598
  } catch (error) {
2731
2599
  if (error instanceof Error) {
2732
- console.error(import_chalk18.default.red(`
2600
+ console.error(import_chalk17.default.red(`
2733
2601
  \u2717 ${error.message}
2734
2602
  `));
2735
2603
  }
@@ -2741,7 +2609,7 @@ program.command("claude-auth").description("Authenticate Replicas with your Clau
2741
2609
  await claudeAuthCommand(options);
2742
2610
  } catch (error) {
2743
2611
  if (error instanceof Error) {
2744
- console.error(import_chalk18.default.red(`
2612
+ console.error(import_chalk17.default.red(`
2745
2613
  \u2717 ${error.message}
2746
2614
  `));
2747
2615
  }
@@ -2754,7 +2622,7 @@ org.command("switch").description("Switch to a different organization").action(a
2754
2622
  await orgSwitchCommand();
2755
2623
  } catch (error) {
2756
2624
  if (error instanceof Error) {
2757
- console.error(import_chalk18.default.red(`
2625
+ console.error(import_chalk17.default.red(`
2758
2626
  \u2717 ${error.message}
2759
2627
  `));
2760
2628
  }
@@ -2766,7 +2634,7 @@ org.action(async () => {
2766
2634
  await orgCommand();
2767
2635
  } catch (error) {
2768
2636
  if (error instanceof Error) {
2769
- console.error(import_chalk18.default.red(`
2637
+ console.error(import_chalk17.default.red(`
2770
2638
  \u2717 ${error.message}
2771
2639
  `));
2772
2640
  }
@@ -2778,7 +2646,7 @@ program.command("connect <workspace-name>").description("Connect to a workspace
2778
2646
  await connectCommand(workspaceName, options);
2779
2647
  } catch (error) {
2780
2648
  if (error instanceof Error) {
2781
- console.error(import_chalk18.default.red(`
2649
+ console.error(import_chalk17.default.red(`
2782
2650
  \u2717 ${error.message}
2783
2651
  `));
2784
2652
  }
@@ -2790,34 +2658,20 @@ program.command("code <workspace-name>").description("Open a workspace in VSCode
2790
2658
  await codeCommand(workspaceName, options);
2791
2659
  } catch (error) {
2792
2660
  if (error instanceof Error) {
2793
- console.error(import_chalk18.default.red(`
2661
+ console.error(import_chalk17.default.red(`
2794
2662
  \u2717 ${error.message}
2795
2663
  `));
2796
2664
  }
2797
2665
  process.exit(1);
2798
2666
  }
2799
2667
  });
2800
- if (process.env.ENABLE_DEV_SYNC_COMMAND === "true") {
2801
- program.command("dev-sync <workspace-name>").description("[Dev] Sync local engine to workspace VM").action(async (workspaceName) => {
2802
- try {
2803
- await devSyncCommand(workspaceName);
2804
- } catch (error) {
2805
- if (error instanceof Error) {
2806
- console.error(import_chalk18.default.red(`
2807
- \u2717 ${error.message}
2808
- `));
2809
- }
2810
- process.exit(1);
2811
- }
2812
- });
2813
- }
2814
2668
  var config = program.command("config").description("Manage CLI configuration");
2815
2669
  config.command("get <key>").description("Get a configuration value").action(async (key) => {
2816
2670
  try {
2817
2671
  await configGetCommand(key);
2818
2672
  } catch (error) {
2819
2673
  if (error instanceof Error) {
2820
- console.error(import_chalk18.default.red(`
2674
+ console.error(import_chalk17.default.red(`
2821
2675
  \u2717 ${error.message}
2822
2676
  `));
2823
2677
  }
@@ -2829,7 +2683,7 @@ config.command("set <key> <value>").description("Set a configuration value").act
2829
2683
  await configSetCommand(key, value);
2830
2684
  } catch (error) {
2831
2685
  if (error instanceof Error) {
2832
- console.error(import_chalk18.default.red(`
2686
+ console.error(import_chalk17.default.red(`
2833
2687
  \u2717 ${error.message}
2834
2688
  `));
2835
2689
  }
@@ -2841,7 +2695,7 @@ config.command("list").description("List all configuration values").action(async
2841
2695
  await configListCommand();
2842
2696
  } catch (error) {
2843
2697
  if (error instanceof Error) {
2844
- console.error(import_chalk18.default.red(`
2698
+ console.error(import_chalk17.default.red(`
2845
2699
  \u2717 ${error.message}
2846
2700
  `));
2847
2701
  }
@@ -2853,7 +2707,7 @@ program.command("list").description("List all replicas").option("-p, --page <pag
2853
2707
  await replicaListCommand(options);
2854
2708
  } catch (error) {
2855
2709
  if (error instanceof Error) {
2856
- console.error(import_chalk18.default.red(`
2710
+ console.error(import_chalk17.default.red(`
2857
2711
  \u2717 ${error.message}
2858
2712
  `));
2859
2713
  }
@@ -2865,19 +2719,19 @@ program.command("get <id>").description("Get replica details by ID").action(asyn
2865
2719
  await replicaGetCommand(id);
2866
2720
  } catch (error) {
2867
2721
  if (error instanceof Error) {
2868
- console.error(import_chalk18.default.red(`
2722
+ console.error(import_chalk17.default.red(`
2869
2723
  \u2717 ${error.message}
2870
2724
  `));
2871
2725
  }
2872
2726
  process.exit(1);
2873
2727
  }
2874
2728
  });
2875
- program.command("create [name]").description("Create a new replica").option("-m, --message <message>", "Initial message for the replica").option("-r, --repository <repository>", "Repository name").option("-i, --instance-type <type>", "Instance type (standard, large, power)").option("-a, --agent <agent>", "Coding agent (claude, codex)").action(async (name, options) => {
2729
+ program.command("create [name]").description("Create a new replica").option("-m, --message <message>", "Initial message for the replica").option("-r, --repository <repository>", "Repository name").option("-a, --agent <agent>", "Coding agent (claude, codex)").action(async (name, options) => {
2876
2730
  try {
2877
2731
  await replicaCreateCommand(name, options);
2878
2732
  } catch (error) {
2879
2733
  if (error instanceof Error) {
2880
- console.error(import_chalk18.default.red(`
2734
+ console.error(import_chalk17.default.red(`
2881
2735
  \u2717 ${error.message}
2882
2736
  `));
2883
2737
  }
@@ -2889,7 +2743,7 @@ program.command("send <id>").description("Send a message to a replica").option("
2889
2743
  await replicaSendCommand(id, options);
2890
2744
  } catch (error) {
2891
2745
  if (error instanceof Error) {
2892
- console.error(import_chalk18.default.red(`
2746
+ console.error(import_chalk17.default.red(`
2893
2747
  \u2717 ${error.message}
2894
2748
  `));
2895
2749
  }
@@ -2901,7 +2755,7 @@ program.command("delete <id>").description("Delete a replica").option("-f, --for
2901
2755
  await replicaDeleteCommand(id, options);
2902
2756
  } catch (error) {
2903
2757
  if (error instanceof Error) {
2904
- console.error(import_chalk18.default.red(`
2758
+ console.error(import_chalk17.default.red(`
2905
2759
  \u2717 ${error.message}
2906
2760
  `));
2907
2761
  }
@@ -2913,7 +2767,7 @@ program.command("read <id>").description("Read conversation history of a replica
2913
2767
  await replicaReadCommand(id, options);
2914
2768
  } catch (error) {
2915
2769
  if (error instanceof Error) {
2916
- console.error(import_chalk18.default.red(`
2770
+ console.error(import_chalk17.default.red(`
2917
2771
  \u2717 ${error.message}
2918
2772
  `));
2919
2773
  }
@@ -2926,7 +2780,7 @@ repos.command("list").description("List all repositories").action(async () => {
2926
2780
  await repositoriesListCommand();
2927
2781
  } catch (error) {
2928
2782
  if (error instanceof Error) {
2929
- console.error(import_chalk18.default.red(`
2783
+ console.error(import_chalk17.default.red(`
2930
2784
  \u2717 ${error.message}
2931
2785
  `));
2932
2786
  }
@@ -2938,7 +2792,7 @@ repos.action(async () => {
2938
2792
  await repositoriesListCommand();
2939
2793
  } catch (error) {
2940
2794
  if (error instanceof Error) {
2941
- console.error(import_chalk18.default.red(`
2795
+ console.error(import_chalk17.default.red(`
2942
2796
  \u2717 ${error.message}
2943
2797
  `));
2944
2798
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.2.28",
3
+ "version": "0.2.29",
4
4
  "description": "CLI for managing Replicas workspaces - SSH into cloud dev environments with automatic port forwarding",
5
5
  "main": "dist/index.js",
6
6
  "bin": {