the universal sandbox runtime for agents and humans.
pocketenv.io
sandbox
openclaw
agent
claude-code
vercel-sandbox
deno-sandbox
cloudflare-sandbox
atproto
sprites
daytona
1import { editor, input } from "@inquirer/prompts";
2import consola from "consola";
3import fs from "node:fs/promises";
4import { Sandbox } from "@pocketenv/sdk";
5import chalk from "chalk";
6import { configureSdk } from "../lib/sdk";
7
8export async function getSshKey(sandboxName: string) {
9 await configureSdk();
10
11 try {
12 const sandbox = await Sandbox.get(sandboxName);
13 const sshKeys = await sandbox.sshKeys.get();
14
15 consola.log("\nPrivate Key:");
16 consola.log((sshKeys.privateKey ?? "").replace(/\\n/g, "\n"));
17 consola.log("\nPublic Key:");
18 consola.log(sshKeys.publicKey, "\n");
19 } catch (error) {
20 consola.info(
21 `No SSH keys found for this sandbox.\n Create one with ${chalk.greenBright(`pocketenv sshkeys put ${sandboxName} --generate`)}.`,
22 );
23 }
24}
25
26export async function putKeys(
27 sandboxName: string,
28 options: { generate?: boolean; publicKey?: string; privateKey?: string },
29) {
30 let privateKey: string | undefined;
31 let publicKey: string | undefined;
32
33 await configureSdk();
34 const sandbox = await Sandbox.get(sandboxName);
35
36 if (options.generate) {
37 const generated = await sandbox.sshKeys.generate();
38 privateKey = generated.privateKey;
39 publicKey = generated.publicKey;
40 }
41
42 if (options.privateKey && !options.generate) {
43 privateKey = await fs.readFile(options.privateKey, "utf8");
44 }
45
46 if (options.publicKey && !options.generate) {
47 publicKey = await fs.readFile(options.publicKey, "utf8");
48 }
49
50 const validatePrivateKey = (value: string): string | true => {
51 const trimmed = value.trim();
52 if (!trimmed.startsWith("-----BEGIN")) {
53 return "Private key must start with a PEM header (e.g. -----BEGIN OPENSSH PRIVATE KEY-----)";
54 }
55 if (!trimmed.endsWith("-----")) {
56 return "Private key must end with a PEM footer (e.g. -----END OPENSSH PRIVATE KEY-----)";
57 }
58 return true;
59 };
60
61 if (!privateKey) {
62 privateKey = (
63 await editor({
64 message: "Enter your SSH private key (opens in $EDITOR):",
65 postfix: ".pem",
66 waitForUserInput: false,
67 validate: validatePrivateKey,
68 })
69 ).trim();
70 }
71
72 if (!publicKey) {
73 publicKey = (
74 await input({
75 message: "Enter your SSH public key:",
76 validate: (value: string): string | true =>
77 value.trim().length > 0 ? true : "Public key cannot be empty.",
78 })
79 ).trim();
80 }
81
82 if (!sandbox) {
83 consola.error(`Sandbox not found: ${chalk.greenBright(sandboxName)}`);
84 process.exit(1);
85 }
86
87 try {
88 await sandbox.sshKeys.put(publicKey, privateKey);
89 consola.success("SSH keys saved successfully!");
90 } catch {
91 consola.error("Failed to save SSH keys");
92 }
93}