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.

Guard service start and add service CLI

Skip starting a service when the sandbox status is not RUNNING; log an
info message and return. Add CLI command stubs for services
(create/list/start/stop/restart/delete) and register them in the CLI.

+70
+9
apps/api/src/xrpc/io/pocketenv/service/addService.ts
··· 75 75 return service; 76 76 }); 77 77 78 + if (record.status !== "RUNNING") { 79 + consola.info("Sandbox is not running, skipping service start", { 80 + sandboxId: record.id, 81 + serviceId: service.id, 82 + status: record.status, 83 + }); 84 + return; 85 + } 86 + 78 87 // start service 79 88 const sandbox = 80 89 record.provider === Providers.CLOUDFLARE
+11
apps/cli/src/cmd/service.ts
··· 1 + export async function createService() {} 2 + 3 + export async function listServices() {} 4 + 5 + export async function restartService() {} 6 + 7 + export async function startService() {} 8 + 9 + export async function stopService() {} 10 + 11 + export async function deleteService() {}
+50
apps/cli/src/index.ts
··· 23 23 import { c } from "./theme"; 24 24 import { exposeVscode } from "./cmd/vscode"; 25 25 import { exec } from "./cmd/exec"; 26 + import { 27 + createService, 28 + deleteService, 29 + listServices, 30 + restartService, 31 + startService, 32 + stopService, 33 + } from "./cmd/service"; 26 34 27 35 const program = new Command(); 28 36 ··· 299 307 .argument("<sandbox>", "the sandbox to get the Tailscale Auth Key from") 300 308 .description("get a Tailscale Auth Key (redacted) from the given sandbox") 301 309 .action(getTailscaleAuthKey); 310 + 311 + const service = program.command("service").description("manage services"); 312 + 313 + service 314 + .command("create") 315 + .argument("<sandbox>", "the sandbox to create the service in") 316 + .argument("<name>", "the name of the service") 317 + .argument("<command...>", "the command to run for the service") 318 + .description("create a new service in the given sandbox") 319 + .action(createService); 320 + 321 + service 322 + .command("list") 323 + .aliases(["ls"]) 324 + .argument("<sandbox>", "the sandbox to list services for") 325 + .description("list services in the given sandbox") 326 + .action(listServices); 327 + 328 + service 329 + .command("delete") 330 + .aliases(["rm", "remove"]) 331 + .argument("<service_id>", "the ID of the service to delete") 332 + .description("delete a service") 333 + .action(deleteService); 334 + 335 + service 336 + .command("start") 337 + .argument("<service_id>", "the ID of the service to start") 338 + .description("start a service") 339 + .action(startService); 340 + 341 + service 342 + .command("stop") 343 + .argument("<service_id>", "the ID of the service to stop") 344 + .description("stop a service") 345 + .action(stopService); 346 + 347 + service 348 + .command("restart") 349 + .argument("<service_id>", "the ID of the service to restart") 350 + .description("restart a service") 351 + .action(restartService); 302 352 303 353 if (process.argv.length <= 2) { 304 354 program.help();