replicas-cli 0.2.27 → 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 +200 -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,103 +2186,108 @@ 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;
2274
+ if (replicaName && /\s/.test(replicaName)) {
2275
+ console.log(import_chalk15.default.red("Replica name cannot contain spaces."));
2276
+ process.exit(1);
2277
+ }
2382
2278
  if (!replicaName) {
2383
2279
  const response2 = await (0, import_prompts3.default)({
2384
2280
  type: "text",
2385
2281
  name: "name",
2386
2282
  message: "Enter replica name (without spaces):",
2387
- validate: (value) => value.trim() ? true : "Name is required"
2283
+ validate: (value) => {
2284
+ if (!value.trim()) return "Name is required";
2285
+ if (/\s/.test(value)) return "Name cannot contain spaces";
2286
+ return true;
2287
+ }
2388
2288
  });
2389
2289
  if (!response2.name) {
2390
- console.log(import_chalk16.default.yellow("\nCancelled."));
2290
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2391
2291
  return;
2392
2292
  }
2393
2293
  replicaName = response2.name;
@@ -2404,7 +2304,7 @@ async function replicaCreateCommand(name, options) {
2404
2304
  }))
2405
2305
  });
2406
2306
  if (!response2.repository) {
2407
- console.log(import_chalk16.default.yellow("\nCancelled."));
2307
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2408
2308
  return;
2409
2309
  }
2410
2310
  repository = response2.repository;
@@ -2417,29 +2317,11 @@ async function replicaCreateCommand(name, options) {
2417
2317
  validate: (value) => value.trim() ? true : "Message is required"
2418
2318
  });
2419
2319
  if (!response2.message) {
2420
- console.log(import_chalk16.default.yellow("\nCancelled."));
2320
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2421
2321
  return;
2422
2322
  }
2423
2323
  message = response2.message;
2424
2324
  }
2425
- if (!instanceType) {
2426
- const response2 = await (0, import_prompts3.default)({
2427
- type: "select",
2428
- name: "instanceType",
2429
- message: "Select instance type:",
2430
- choices: [
2431
- { title: "Standard (2 vCPU, 4GB RAM)", value: "standard" },
2432
- { title: "Large (2 vCPU, 8GB RAM)", value: "large" },
2433
- { title: "Power (4 vCPU, 16GB RAM)", value: "power" }
2434
- ],
2435
- initial: 0
2436
- });
2437
- if (!response2.instanceType) {
2438
- console.log(import_chalk16.default.yellow("\nCancelled."));
2439
- return;
2440
- }
2441
- instanceType = response2.instanceType;
2442
- }
2443
2325
  if (!codingAgent) {
2444
2326
  const response2 = await (0, import_prompts3.default)({
2445
2327
  type: "select",
@@ -2452,46 +2334,40 @@ async function replicaCreateCommand(name, options) {
2452
2334
  initial: 0
2453
2335
  });
2454
2336
  if (!response2.agent) {
2455
- console.log(import_chalk16.default.yellow("\nCancelled."));
2337
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2456
2338
  return;
2457
2339
  }
2458
2340
  codingAgent = response2.agent;
2459
2341
  }
2460
- if (!instanceType || !["standard", "large", "power"].includes(instanceType)) {
2461
- console.log(import_chalk16.default.red(`Invalid instance type: ${instanceType}. Must be one of: standard, large, power`));
2462
- process.exit(1);
2463
- }
2464
2342
  if (!codingAgent || !["claude", "codex"].includes(codingAgent)) {
2465
- 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`));
2466
2344
  process.exit(1);
2467
2345
  }
2468
2346
  const body = {
2469
2347
  name: replicaName,
2470
2348
  message,
2471
2349
  repository,
2472
- instance_type: instanceType,
2473
2350
  coding_agent: codingAgent
2474
2351
  };
2475
- console.log(import_chalk16.default.gray("\nCreating replica..."));
2352
+ console.log(import_chalk15.default.gray("\nCreating replica..."));
2476
2353
  const response = await orgAuthenticatedFetch("/v1/replica", {
2477
2354
  method: "POST",
2478
2355
  body
2479
2356
  });
2480
2357
  const replica = response.replica;
2481
- console.log(import_chalk16.default.green(`
2358
+ console.log(import_chalk15.default.green(`
2482
2359
  Created replica: ${replica.name}`));
2483
- console.log(import_chalk16.default.gray(` ID: ${replica.id}`));
2484
- console.log(import_chalk16.default.gray(` Instance: ${replica.instance_type}`));
2485
- 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)}`));
2486
2362
  console.log();
2487
2363
  } catch (error) {
2488
- 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"}`));
2489
2365
  process.exit(1);
2490
2366
  }
2491
2367
  }
2492
2368
  async function replicaSendCommand(id, options) {
2493
2369
  if (!isAuthenticated()) {
2494
- 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.'));
2495
2371
  process.exit(1);
2496
2372
  }
2497
2373
  try {
@@ -2504,7 +2380,7 @@ async function replicaSendCommand(id, options) {
2504
2380
  validate: (value) => value.trim() ? true : "Message is required"
2505
2381
  });
2506
2382
  if (!response2.message) {
2507
- console.log(import_chalk16.default.yellow("\nCancelled."));
2383
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2508
2384
  return;
2509
2385
  }
2510
2386
  message = response2.message;
@@ -2514,7 +2390,7 @@ async function replicaSendCommand(id, options) {
2514
2390
  };
2515
2391
  if (options.agent) {
2516
2392
  if (!["claude", "codex"].includes(options.agent)) {
2517
- 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`));
2518
2394
  process.exit(1);
2519
2395
  }
2520
2396
  body.coding_agent = options.agent;
@@ -2526,21 +2402,21 @@ async function replicaSendCommand(id, options) {
2526
2402
  body
2527
2403
  }
2528
2404
  );
2529
- 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;
2530
2406
  console.log(statusColor(`
2531
2407
  Message ${response.status}`));
2532
2408
  if (response.position !== void 0 && response.position > 0) {
2533
- console.log(import_chalk16.default.gray(` Queue position: ${response.position}`));
2409
+ console.log(import_chalk15.default.gray(` Queue position: ${response.position}`));
2534
2410
  }
2535
2411
  console.log();
2536
2412
  } catch (error) {
2537
- 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"}`));
2538
2414
  process.exit(1);
2539
2415
  }
2540
2416
  }
2541
2417
  async function replicaDeleteCommand(id, options) {
2542
2418
  if (!isAuthenticated()) {
2543
- 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.'));
2544
2420
  process.exit(1);
2545
2421
  }
2546
2422
  try {
@@ -2552,24 +2428,24 @@ async function replicaDeleteCommand(id, options) {
2552
2428
  initial: false
2553
2429
  });
2554
2430
  if (!response.confirm) {
2555
- console.log(import_chalk16.default.yellow("\nCancelled."));
2431
+ console.log(import_chalk15.default.yellow("\nCancelled."));
2556
2432
  return;
2557
2433
  }
2558
2434
  }
2559
2435
  await orgAuthenticatedFetch(`/v1/replica/${id}`, {
2560
2436
  method: "DELETE"
2561
2437
  });
2562
- console.log(import_chalk16.default.green(`
2438
+ console.log(import_chalk15.default.green(`
2563
2439
  Replica ${id} deleted.
2564
2440
  `));
2565
2441
  } catch (error) {
2566
- 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"}`));
2567
2443
  process.exit(1);
2568
2444
  }
2569
2445
  }
2570
2446
  async function replicaReadCommand(id, options) {
2571
2447
  if (!isAuthenticated()) {
2572
- 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.'));
2573
2449
  process.exit(1);
2574
2450
  }
2575
2451
  try {
@@ -2581,79 +2457,79 @@ async function replicaReadCommand(id, options) {
2581
2457
  `/v1/replica/${id}/read${query ? "?" + query : ""}`
2582
2458
  );
2583
2459
  if (response.waking) {
2584
- 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"));
2585
2461
  return;
2586
2462
  }
2587
- console.log(import_chalk16.default.green(`
2463
+ console.log(import_chalk15.default.green(`
2588
2464
  Conversation History
2589
2465
  `));
2590
2466
  if (response.coding_agent) {
2591
- console.log(import_chalk16.default.gray(` Agent: ${response.coding_agent}`));
2467
+ console.log(import_chalk15.default.gray(` Agent: ${response.coding_agent}`));
2592
2468
  }
2593
2469
  if (response.thread_id) {
2594
- console.log(import_chalk16.default.gray(` Thread ID: ${response.thread_id}`));
2470
+ console.log(import_chalk15.default.gray(` Thread ID: ${response.thread_id}`));
2595
2471
  }
2596
- console.log(import_chalk16.default.gray(` Total Events: ${response.total}`));
2597
- 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`));
2598
2474
  if (response.hasMore) {
2599
- 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)`));
2600
2476
  }
2601
2477
  console.log();
2602
2478
  if (response.events.length === 0) {
2603
- console.log(import_chalk16.default.yellow(" No events found.\n"));
2479
+ console.log(import_chalk15.default.yellow(" No events found.\n"));
2604
2480
  return;
2605
2481
  }
2606
- console.log(import_chalk16.default.gray("-".repeat(60)));
2482
+ console.log(import_chalk15.default.gray("-".repeat(60)));
2607
2483
  const agentType = response.coding_agent || "claude";
2608
2484
  const displayMessages = parseAgentEvents(response.events, agentType);
2609
2485
  for (const message of displayMessages) {
2610
2486
  formatDisplayMessage(message);
2611
2487
  }
2612
- console.log(import_chalk16.default.gray("\n" + "-".repeat(60)));
2488
+ console.log(import_chalk15.default.gray("\n" + "-".repeat(60)));
2613
2489
  console.log();
2614
2490
  } catch (error) {
2615
- 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"}`));
2616
2492
  process.exit(1);
2617
2493
  }
2618
2494
  }
2619
2495
 
2620
2496
  // src/commands/repositories.ts
2621
- var import_chalk17 = __toESM(require("chalk"));
2497
+ var import_chalk16 = __toESM(require("chalk"));
2622
2498
  function formatDate2(dateString) {
2623
2499
  return new Date(dateString).toLocaleString();
2624
2500
  }
2625
2501
  async function repositoriesListCommand() {
2626
2502
  if (!isAuthenticated()) {
2627
- 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.'));
2628
2504
  process.exit(1);
2629
2505
  }
2630
2506
  try {
2631
2507
  const response = await orgAuthenticatedFetch("/v1/repositories");
2632
2508
  if (response.repositories.length === 0) {
2633
- console.log(import_chalk17.default.yellow("\nNo repositories found.\n"));
2509
+ console.log(import_chalk16.default.yellow("\nNo repositories found.\n"));
2634
2510
  return;
2635
2511
  }
2636
- console.log(import_chalk17.default.green(`
2512
+ console.log(import_chalk16.default.green(`
2637
2513
  Repositories (${response.repositories.length}):
2638
2514
  `));
2639
2515
  for (const repo of response.repositories) {
2640
- console.log(import_chalk17.default.white(` ${repo.name}`));
2641
- console.log(import_chalk17.default.gray(` URL: ${repo.url}`));
2642
- console.log(import_chalk17.default.gray(` Default Branch: ${repo.default_branch}`));
2643
- 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)}`));
2644
2520
  if (repo.github_repository_id) {
2645
- 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}`));
2646
2522
  }
2647
2523
  console.log();
2648
2524
  }
2649
2525
  } catch (error) {
2650
- 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"}`));
2651
2527
  process.exit(1);
2652
2528
  }
2653
2529
  }
2654
2530
 
2655
2531
  // src/index.ts
2656
- var CLI_VERSION = "0.2.27";
2532
+ var CLI_VERSION = "0.2.29";
2657
2533
  var program = new import_commander.Command();
2658
2534
  program.name("replicas").description("CLI for managing Replicas workspaces").version(CLI_VERSION);
2659
2535
  program.command("login").description("Authenticate with your Replicas account").action(async () => {
@@ -2661,7 +2537,7 @@ program.command("login").description("Authenticate with your Replicas account").
2661
2537
  await loginCommand();
2662
2538
  } catch (error) {
2663
2539
  if (error instanceof Error) {
2664
- console.error(import_chalk18.default.red(`
2540
+ console.error(import_chalk17.default.red(`
2665
2541
  \u2717 ${error.message}
2666
2542
  `));
2667
2543
  }
@@ -2673,7 +2549,7 @@ program.command("init").description("Create a replicas.json configuration file")
2673
2549
  initCommand(options);
2674
2550
  } catch (error) {
2675
2551
  if (error instanceof Error) {
2676
- console.error(import_chalk18.default.red(`
2552
+ console.error(import_chalk17.default.red(`
2677
2553
  \u2717 ${error.message}
2678
2554
  `));
2679
2555
  }
@@ -2685,7 +2561,7 @@ program.command("logout").description("Clear stored credentials").action(() => {
2685
2561
  logoutCommand();
2686
2562
  } catch (error) {
2687
2563
  if (error instanceof Error) {
2688
- console.error(import_chalk18.default.red(`
2564
+ console.error(import_chalk17.default.red(`
2689
2565
  \u2717 ${error.message}
2690
2566
  `));
2691
2567
  }
@@ -2697,7 +2573,7 @@ program.command("whoami").description("Display current authenticated user").acti
2697
2573
  await whoamiCommand();
2698
2574
  } catch (error) {
2699
2575
  if (error instanceof Error) {
2700
- console.error(import_chalk18.default.red(`
2576
+ console.error(import_chalk17.default.red(`
2701
2577
  \u2717 ${error.message}
2702
2578
  `));
2703
2579
  }
@@ -2709,7 +2585,7 @@ program.command("tools").description("List tools available on the Replicas Machi
2709
2585
  await toolsCommand();
2710
2586
  } catch (error) {
2711
2587
  if (error instanceof Error) {
2712
- console.error(import_chalk18.default.red(`
2588
+ console.error(import_chalk17.default.red(`
2713
2589
  \u2717 ${error.message}
2714
2590
  `));
2715
2591
  }
@@ -2721,7 +2597,7 @@ program.command("codex-auth").description("Authenticate Replicas with your Codex
2721
2597
  await codexAuthCommand(options);
2722
2598
  } catch (error) {
2723
2599
  if (error instanceof Error) {
2724
- console.error(import_chalk18.default.red(`
2600
+ console.error(import_chalk17.default.red(`
2725
2601
  \u2717 ${error.message}
2726
2602
  `));
2727
2603
  }
@@ -2733,7 +2609,7 @@ program.command("claude-auth").description("Authenticate Replicas with your Clau
2733
2609
  await claudeAuthCommand(options);
2734
2610
  } catch (error) {
2735
2611
  if (error instanceof Error) {
2736
- console.error(import_chalk18.default.red(`
2612
+ console.error(import_chalk17.default.red(`
2737
2613
  \u2717 ${error.message}
2738
2614
  `));
2739
2615
  }
@@ -2746,7 +2622,7 @@ org.command("switch").description("Switch to a different organization").action(a
2746
2622
  await orgSwitchCommand();
2747
2623
  } catch (error) {
2748
2624
  if (error instanceof Error) {
2749
- console.error(import_chalk18.default.red(`
2625
+ console.error(import_chalk17.default.red(`
2750
2626
  \u2717 ${error.message}
2751
2627
  `));
2752
2628
  }
@@ -2758,7 +2634,7 @@ org.action(async () => {
2758
2634
  await orgCommand();
2759
2635
  } catch (error) {
2760
2636
  if (error instanceof Error) {
2761
- console.error(import_chalk18.default.red(`
2637
+ console.error(import_chalk17.default.red(`
2762
2638
  \u2717 ${error.message}
2763
2639
  `));
2764
2640
  }
@@ -2770,7 +2646,7 @@ program.command("connect <workspace-name>").description("Connect to a workspace
2770
2646
  await connectCommand(workspaceName, options);
2771
2647
  } catch (error) {
2772
2648
  if (error instanceof Error) {
2773
- console.error(import_chalk18.default.red(`
2649
+ console.error(import_chalk17.default.red(`
2774
2650
  \u2717 ${error.message}
2775
2651
  `));
2776
2652
  }
@@ -2782,34 +2658,20 @@ program.command("code <workspace-name>").description("Open a workspace in VSCode
2782
2658
  await codeCommand(workspaceName, options);
2783
2659
  } catch (error) {
2784
2660
  if (error instanceof Error) {
2785
- console.error(import_chalk18.default.red(`
2661
+ console.error(import_chalk17.default.red(`
2786
2662
  \u2717 ${error.message}
2787
2663
  `));
2788
2664
  }
2789
2665
  process.exit(1);
2790
2666
  }
2791
2667
  });
2792
- if (process.env.ENABLE_DEV_SYNC_COMMAND === "true") {
2793
- program.command("dev-sync <workspace-name>").description("[Dev] Sync local engine to workspace VM").action(async (workspaceName) => {
2794
- try {
2795
- await devSyncCommand(workspaceName);
2796
- } catch (error) {
2797
- if (error instanceof Error) {
2798
- console.error(import_chalk18.default.red(`
2799
- \u2717 ${error.message}
2800
- `));
2801
- }
2802
- process.exit(1);
2803
- }
2804
- });
2805
- }
2806
2668
  var config = program.command("config").description("Manage CLI configuration");
2807
2669
  config.command("get <key>").description("Get a configuration value").action(async (key) => {
2808
2670
  try {
2809
2671
  await configGetCommand(key);
2810
2672
  } catch (error) {
2811
2673
  if (error instanceof Error) {
2812
- console.error(import_chalk18.default.red(`
2674
+ console.error(import_chalk17.default.red(`
2813
2675
  \u2717 ${error.message}
2814
2676
  `));
2815
2677
  }
@@ -2821,7 +2683,7 @@ config.command("set <key> <value>").description("Set a configuration value").act
2821
2683
  await configSetCommand(key, value);
2822
2684
  } catch (error) {
2823
2685
  if (error instanceof Error) {
2824
- console.error(import_chalk18.default.red(`
2686
+ console.error(import_chalk17.default.red(`
2825
2687
  \u2717 ${error.message}
2826
2688
  `));
2827
2689
  }
@@ -2833,7 +2695,7 @@ config.command("list").description("List all configuration values").action(async
2833
2695
  await configListCommand();
2834
2696
  } catch (error) {
2835
2697
  if (error instanceof Error) {
2836
- console.error(import_chalk18.default.red(`
2698
+ console.error(import_chalk17.default.red(`
2837
2699
  \u2717 ${error.message}
2838
2700
  `));
2839
2701
  }
@@ -2845,7 +2707,7 @@ program.command("list").description("List all replicas").option("-p, --page <pag
2845
2707
  await replicaListCommand(options);
2846
2708
  } catch (error) {
2847
2709
  if (error instanceof Error) {
2848
- console.error(import_chalk18.default.red(`
2710
+ console.error(import_chalk17.default.red(`
2849
2711
  \u2717 ${error.message}
2850
2712
  `));
2851
2713
  }
@@ -2857,19 +2719,19 @@ program.command("get <id>").description("Get replica details by ID").action(asyn
2857
2719
  await replicaGetCommand(id);
2858
2720
  } catch (error) {
2859
2721
  if (error instanceof Error) {
2860
- console.error(import_chalk18.default.red(`
2722
+ console.error(import_chalk17.default.red(`
2861
2723
  \u2717 ${error.message}
2862
2724
  `));
2863
2725
  }
2864
2726
  process.exit(1);
2865
2727
  }
2866
2728
  });
2867
- 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) => {
2868
2730
  try {
2869
2731
  await replicaCreateCommand(name, options);
2870
2732
  } catch (error) {
2871
2733
  if (error instanceof Error) {
2872
- console.error(import_chalk18.default.red(`
2734
+ console.error(import_chalk17.default.red(`
2873
2735
  \u2717 ${error.message}
2874
2736
  `));
2875
2737
  }
@@ -2881,7 +2743,7 @@ program.command("send <id>").description("Send a message to a replica").option("
2881
2743
  await replicaSendCommand(id, options);
2882
2744
  } catch (error) {
2883
2745
  if (error instanceof Error) {
2884
- console.error(import_chalk18.default.red(`
2746
+ console.error(import_chalk17.default.red(`
2885
2747
  \u2717 ${error.message}
2886
2748
  `));
2887
2749
  }
@@ -2893,7 +2755,7 @@ program.command("delete <id>").description("Delete a replica").option("-f, --for
2893
2755
  await replicaDeleteCommand(id, options);
2894
2756
  } catch (error) {
2895
2757
  if (error instanceof Error) {
2896
- console.error(import_chalk18.default.red(`
2758
+ console.error(import_chalk17.default.red(`
2897
2759
  \u2717 ${error.message}
2898
2760
  `));
2899
2761
  }
@@ -2905,7 +2767,7 @@ program.command("read <id>").description("Read conversation history of a replica
2905
2767
  await replicaReadCommand(id, options);
2906
2768
  } catch (error) {
2907
2769
  if (error instanceof Error) {
2908
- console.error(import_chalk18.default.red(`
2770
+ console.error(import_chalk17.default.red(`
2909
2771
  \u2717 ${error.message}
2910
2772
  `));
2911
2773
  }
@@ -2918,7 +2780,7 @@ repos.command("list").description("List all repositories").action(async () => {
2918
2780
  await repositoriesListCommand();
2919
2781
  } catch (error) {
2920
2782
  if (error instanceof Error) {
2921
- console.error(import_chalk18.default.red(`
2783
+ console.error(import_chalk17.default.red(`
2922
2784
  \u2717 ${error.message}
2923
2785
  `));
2924
2786
  }
@@ -2930,7 +2792,7 @@ repos.action(async () => {
2930
2792
  await repositoriesListCommand();
2931
2793
  } catch (error) {
2932
2794
  if (error instanceof Error) {
2933
- console.error(import_chalk18.default.red(`
2795
+ console.error(import_chalk17.default.red(`
2934
2796
  \u2717 ${error.message}
2935
2797
  `));
2936
2798
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.2.27",
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": {