the universal sandbox runtime for agents and humans. pocketenv.io
sandbox openclaw agent claude-code vercel-sandbox deno-sandbox cloudflare-sandbox atproto sprites daytona
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

at 1241cd4e999bb3f48dca4cab7bcff14fe6f5d6ad 406 lines 13 kB view raw
1import chalk from "chalk"; 2import { version } from "../package.json" assert { type: "json" }; 3import { Command } from "commander"; 4import start from "./cmd/start"; 5import login from "./cmd/login"; 6import whoami from "./cmd/whoami"; 7import ssh from "./cmd/ssh"; 8import listSandboxes from "./cmd/list"; 9import stop from "./cmd/stop"; 10import createSandbox from "./cmd/create"; 11import logout from "./cmd/logout"; 12import deleteSandbox from "./cmd/rm"; 13import { deleteSecret, listSecrets, putSecret } from "./cmd/secret"; 14import { deleteEnv, listEnvs, putEnv } from "./cmd/env"; 15import { getSshKey, putKeys } from "./cmd/sshkeys"; 16import { getTailscaleAuthKey, putAuthKey } from "./cmd/tailscale"; 17import { exposePort } from "./cmd/expose"; 18import { unexposePort } from "./cmd/unexpose"; 19import { createVolume, deleteVolume, listVolumes } from "./cmd/volume"; 20import { deleteFile, listFiles, putFile } from "./cmd/file"; 21import consola from "consola"; 22import { listPorts } from "./cmd/ports"; 23import { c } from "./theme"; 24import { exposeVscode } from "./cmd/vscode"; 25import { exec } from "./cmd/exec"; 26import { 27 createService, 28 deleteService, 29 listServices, 30 restartService, 31 startService, 32 stopService, 33} from "./cmd/service"; 34import copy from "./cmd/copy"; 35import ps from "./cmd/ps"; 36import { createBackup, listBackups, restoreBackup } from "./cmd/backup"; 37 38const program = new Command(); 39 40program 41 .name("pocketenv") 42 .description( 43 `${chalk.bold.rgb(0, 232, 198)(`pocketenv v${version}`)} ${c.muted("─")} ${c.muted("Open, interoperable sandbox platform for agents and humans")}`, 44 ) 45 .version(version); 46 47program.configureHelp({ 48 styleTitle: (str) => chalk.bold.rgb(0, 210, 255)(str), 49 styleCommandText: (str) => c.secondary(str), 50 styleDescriptionText: (str) => c.muted(str), 51 styleOptionText: (str) => c.highlight(str), 52 styleArgumentText: (str) => c.accent(str), 53 styleSubcommandText: (str) => c.secondary(str), 54}); 55 56program.addHelpText( 57 "after", 58 ` 59${chalk.bold.rgb(0, 210, 255)("─".repeat(90))} 60 ${chalk.bold.rgb(0, 232, 198)("Learn more:")} ${c.link("https://docs.pocketenv.io")} 61 ${chalk.bold.rgb(0, 232, 198)("Discord:")} ${c.link("https://discord.gg/9ada4pFUFS")} 62 ${chalk.bold.rgb(0, 232, 198)("Report bugs:")} ${c.link("https://github.com/pocketenv-io/pocketenv/issues")} 63${chalk.bold.rgb(0, 210, 255)("─".repeat(90))} 64`, 65); 66 67program 68 .command("login") 69 .argument("<handle>", "your AT Proto handle (e.g., <username>.bsky.social)") 70 .description("login with your AT Proto account and get a session token") 71 .action(login); 72 73program 74 .command("whoami") 75 .description("get the current logged-in user") 76 .action(whoami); 77 78program 79 .command("console") 80 .aliases(["shell", "ssh", "s"]) 81 .argument("[sandbox]", "the sandbox to connect to") 82 .description("open an interactive shell for the given sandbox") 83 .action(ssh); 84 85program.command("ls").description("list sandboxes").action(listSandboxes); 86 87program 88 .command("copy") 89 .aliases(["cp"]) 90 .argument("<source>", "the source file or directory") 91 .argument("<destination>", "the destination file or directory") 92 .description("copy files from or to a running sandbox") 93 .addHelpText( 94 "after", 95 ` 96${chalk.bold("Examples:")} 97 ${c.primary("pocketenv cp ./local-file.txt my-sandbox:/remote-file.txt")} Copy a local file to a sandbox 98 ${c.primary("pocketenv cp my-sandbox:/remote-file.txt ./local-file.txt")} Copy a file from a sandbox to local 99 ${c.primary("pocketenv cp my-sandbox:/remote-dir ./local-dir")} Copy a directory from a sandbox to local 100 ${c.primary("pocketenv cp ./local-dir my-sandbox:/remote-dir")} Copy a local directory to a sandbox 101`, 102 ) 103 .action(copy); 104 105program.command("ps").description("list running Sandboxes").action(ps); 106 107program 108 .command("start") 109 .argument("<sandbox>", "the sandbox to start") 110 .option("--ssh, -s", "connect to the Sandbox and automatically open a shell") 111 .option( 112 "--repo, -r <repo>", 113 "the repository to clone into the sandbox (e.g., github:user/repo, tangled:user/repo, or a Git URL)", 114 ) 115 .option( 116 "--keep-alive, -k", 117 "keep the sandbox alive, ignoring inactivity timeout", 118 ) 119 .description("start the given sandbox") 120 .action(start); 121 122program 123 .command("stop") 124 .argument("<sandbox>", "the sandbox to stop") 125 .description("stop the given sandbox") 126 .action(stop); 127 128program 129 .command("create") 130 .aliases(["new"]) 131 .option("--provider, -p <provider>", "the provider to use for the sandbox") 132 .option( 133 "--base, -b <base>", 134 "the base sandbox to use for the sandbox, e.g. openclaw, claude-code, codex, copilot ...", 135 ) 136 .option("--ssh, -s", "connect to the Sandbox and automatically open a shell") 137 .option( 138 "--repo, -r <repo>", 139 "the repository to clone into the sandbox (e.g., github:user/repo, tangled:user/repo, or a Git URL)", 140 ) 141 .argument("[name]", "the name of the sandbox to create") 142 .description("create a new sandbox") 143 .action(createSandbox); 144 145program 146 .command("logout") 147 .description("logout (removes session token)") 148 .action(logout); 149 150program 151 .command("rm") 152 .aliases(["delete", "remove"]) 153 .argument("<sandbox>", "the sandbox to delete") 154 .description("delete the given sandbox") 155 .action(deleteSandbox); 156 157program 158 .command("vscode") 159 .aliases(["code", "code-server"]) 160 .argument("<sandbox>", "the sandbox to expose VS Code for") 161 .description("expose a visual studio code server to the internet") 162 .action(exposeVscode); 163 164program 165 .enablePositionalOptions() 166 .command("exec") 167 .argument("<sandbox>", "the sandbox to execute the command in") 168 .argument("<command...>", "the command to execute") 169 .description("execute a command in the given sandbox") 170 .passThroughOptions() 171 .action(exec); 172 173program 174 .command("expose") 175 .argument("<sandbox>", "the sandbox to expose a port for") 176 .argument("<port>", "the port to expose", (val) => { 177 const port = parseInt(val, 10); 178 if (isNaN(port)) { 179 consola.error(`port must be a number, got: ${val}`); 180 process.exit(1); 181 } 182 return port; 183 }) 184 .argument("[description]", "an optional description for the exposed port") 185 .description("expose a port from the given sandbox to the internet") 186 .action(exposePort); 187 188program 189 .command("unexpose") 190 .argument("<sandbox>", "the sandbox to unexpose a port for") 191 .argument("<port>", "the port to unexpose", (val) => { 192 const port = parseInt(val, 10); 193 if (isNaN(port)) { 194 consola.error(`port must be a number, got: ${val}`); 195 process.exit(1); 196 } 197 return port; 198 }) 199 .description("unexpose a port from the given sandbox") 200 .action(unexposePort); 201 202const backup = program.command("backup").description("manage sandbox backups"); 203 204backup 205 .command("create") 206 .argument("<sandbox>", "the sandbox to create a backup for") 207 .argument("<directory>", "the directory to backup") 208 .option("--description, -d <description>", "an optional description for the backup") 209 .option("--ttl, -t <ttl>", "time to live for the backup (e.g., 24h, 7d)", "3d") 210 .description("create a backup for the given sandbox") 211 .action(createBackup); 212 213backup 214 .command("restore") 215 .argument("<backup_id>", "the ID of the backup to restore") 216 .description("restore a backup to the given sandbox") 217 .action(restoreBackup); 218 219backup 220 .command("list") 221 .aliases(["ls"]) 222 .argument("<sandbox>", "the sandbox to list backups for") 223 .description("list backups for the given sandbox") 224 .action(listBackups); 225 226const volume = program.command("volume").description("manage volumes"); 227 228volume 229 .command("put") 230 .argument("<sandbox>", "the sandbox to put the volume in") 231 .argument("<name>", "the name of the volume") 232 .argument("<path>", "the path to mount the volume at") 233 .description("put a volume in the given sandbox") 234 .action(createVolume); 235 236volume 237 .command("list") 238 .aliases(["ls"]) 239 .argument("<sandbox>", "the sandbox to list volumes for") 240 .description("list volumes in the given sandbox") 241 .action(listVolumes); 242 243volume 244 .command("delete") 245 .aliases(["rm", "remove"]) 246 .argument("<id>", "the ID of the volume to delete") 247 .description("delete a volume") 248 .action(deleteVolume); 249 250const file = program.command("file").description("manage files"); 251 252file 253 .command("put") 254 .argument("<sandbox>", "the sandbox to put the file in") 255 .argument("<path>", "the remote path to upload the file to") 256 .argument("[localPath]", "the local path of the file to upload") 257 .description("upload a file to the given sandbox") 258 .action(putFile); 259 260file 261 .command("list") 262 .aliases(["ls"]) 263 .argument("<sandbox>", "the sandbox to list files for") 264 .description("list files in the given sandbox") 265 .action(listFiles); 266 267file 268 .command("delete") 269 .aliases(["rm", "remove"]) 270 .argument("<id>", "the ID of the file to delete") 271 .description("delete a file") 272 .action(deleteFile); 273 274program 275 .command("ports") 276 .argument("<sandbox>", "the sandbox to list exposed ports for") 277 .description("list exposed ports for a sandbox") 278 .action(listPorts); 279 280const secret = program.command("secret").description("manage secrets"); 281 282secret 283 .command("put") 284 .argument("<sandbox>", "the sandbox to put the secret in") 285 .argument("<key>", "the key of the secret") 286 .description("put a secret in the given sandbox") 287 .action(putSecret); 288 289secret 290 .command("list") 291 .aliases(["ls"]) 292 .argument("<sandbox>", "the sandbox to list secrets for") 293 .description("list secrets in the given sandbox") 294 .action(listSecrets); 295 296secret 297 .command("delete") 298 .aliases(["rm", "remove"]) 299 .argument("<secret_id>", "the ID of the secret to delete") 300 .description("delete a secret") 301 .action(deleteSecret); 302 303const env = program.command("env").description("manage environment variables"); 304 305env 306 .command("put") 307 .argument("<sandbox>", "the sandbox to put the environment variable in") 308 .argument("<key>", "the key of the environment variable") 309 .argument("<value>", "the value of the environment variable") 310 .description("put an environment variable in the given sandbox") 311 .action(putEnv); 312 313env 314 .command("list") 315 .aliases(["ls"]) 316 .argument("<sandbox>", "the sandbox to list environment variables for") 317 .description("list environment variables in the given sandbox") 318 .action(listEnvs); 319 320env 321 .command("delete") 322 .aliases(["rm", "remove"]) 323 .argument("<variable_id>", "the ID of the environment variable to delete") 324 .description("delete an environment variable") 325 .action(deleteEnv); 326 327const sshkeys = program.command("sshkeys").description("manage SSH keys"); 328 329sshkeys 330 .command("put") 331 .argument("<sandbox>", "the sandbox to put the SSH key in") 332 .option("--private-key <path>", "the path to the SSH private key") 333 .option("--public-key <path>", "the path to the SSH public key") 334 .option("--generate, -g", "generate a new SSH key pair") 335 .description("put an SSH key in the given sandbox") 336 .action(putKeys); 337 338sshkeys 339 .command("get") 340 .argument("<sandbox>", "the sandbox to get the SSH key from") 341 .description("get an SSH key (public key only) from the given sandbox") 342 .action(getSshKey); 343 344const tailscale = program.command("tailscale").description("manage Tailscale"); 345 346tailscale 347 .command("put") 348 .argument("<sandbox>", "the sandbox to put the Tailscale Auth Key in") 349 .description("put a Tailscale Auth Key in the given sandbox") 350 .action(putAuthKey); 351 352tailscale 353 .command("get") 354 .argument("<sandbox>", "the sandbox to get the Tailscale Auth Key from") 355 .description("get a Tailscale Auth Key (redacted) from the given sandbox") 356 .action(getTailscaleAuthKey); 357 358const service = program.command("service").description("manage services"); 359 360service 361 .command("create") 362 .argument("<sandbox>", "the sandbox to create the service in") 363 .argument("<name>", "the name of the service") 364 .argument("<command...>", "the command to run for the service") 365 .option("--description, -d <description>", "a description for the service") 366 .option("--ports, -p <ports...>", "a list of ports to expose for the service") 367 .description("create a new service in the given sandbox") 368 .action(createService); 369 370service 371 .command("list") 372 .aliases(["ls"]) 373 .argument("<sandbox>", "the sandbox to list services for") 374 .description("list services in the given sandbox") 375 .action(listServices); 376 377service 378 .command("delete") 379 .aliases(["rm", "remove"]) 380 .argument("<service_id>", "the ID of the service to delete") 381 .description("delete a service") 382 .action(deleteService); 383 384service 385 .command("start") 386 .argument("<service_id>", "the ID of the service to start") 387 .description("start a service") 388 .action(startService); 389 390service 391 .command("stop") 392 .argument("<service_id>", "the ID of the service to stop") 393 .description("stop a service") 394 .action(stopService); 395 396service 397 .command("restart") 398 .argument("<service_id>", "the ID of the service to restart") 399 .description("restart a service") 400 .action(restartService); 401 402if (process.argv.length <= 2) { 403 program.help(); 404} 405 406program.parse(process.argv);