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.

Use record.id for sandbox and wire CLI calls

CLI: rename sandbox->sandboxId and id->serviceId; send POST requests
to xrpc service endpoints with auth headers. Add success message on
create and unify error logs.

+64 -17
+2 -2
apps/api/src/xrpc/io/pocketenv/service/addService.ts
··· 49 49 const [service] = await tx 50 50 .insert(schema.services) 51 51 .values({ 52 - sandboxId: params.sandboxId, 52 + sandboxId: record.id, 53 53 name: input.body.service.name, 54 54 description: input.body.service.description, 55 55 command: input.body.service.command, ··· 67 67 tx 68 68 .insert(schema.sandboxPorts) 69 69 .values({ 70 - sandboxId: params.sandboxId, 70 + sandboxId: record.id, 71 71 serviceId: service.id, 72 72 exposedPort: port, 73 73 description: `Port ${port} for service ${service.name}`,
+62 -15
apps/cli/src/cmd/service.ts
··· 17 17 }; 18 18 19 19 export async function createService( 20 - sandbox: string, 20 + sandboxId: string, 21 21 name: string, 22 22 command: string[], 23 23 { ports, description }: CreateServiceOptions, 24 24 ) { 25 25 const token = await getAccessToken(); 26 26 27 - console.log( 28 - `Creating service ${name} in sandbox ${sandbox} with command: ${command.join(" ")}`, 29 - ); 30 - console.log(`Ports: ${ports?.join(", ") || "None"}`); 31 - console.log(`Description: ${description || "None"}`); 27 + try { 28 + await client.post( 29 + "/xrpc/io.pocketenv.service.addService", 30 + { 31 + service: { 32 + name, 33 + command, 34 + description, 35 + ports, 36 + }, 37 + }, 38 + { 39 + params: { 40 + sandboxId, 41 + }, 42 + headers: { 43 + Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`, 44 + }, 45 + }, 46 + ); 32 47 33 - try { 48 + consola.success(`Service ${c.highlight(name)} created successfully`); 34 49 } catch (error) { 35 50 consola.error("Failed to create service", error); 36 51 process.exit(1); ··· 103 118 } 104 119 } 105 120 106 - export async function restartService(id: string) { 121 + export async function restartService(serviceId: string) { 107 122 const token = await getAccessToken(); 108 123 try { 124 + await client.post("/xrpc/io.pocketenv.service.restartService", undefined, { 125 + params: { 126 + serviceId, 127 + }, 128 + headers: { 129 + Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`, 130 + }, 131 + }); 109 132 } catch (error) { 110 - consola.error(`Failed to restart service ${id}`, error); 133 + consola.error(`Failed to restart service ${serviceId}`, error); 111 134 process.exit(1); 112 135 } 113 136 } 114 137 115 - export async function startService(id: string) { 138 + export async function startService(serviceId: string) { 116 139 const token = await getAccessToken(); 117 140 118 141 try { 142 + await client.post("/xrpc/io.pocketenv.service.startService", undefined, { 143 + params: { 144 + serviceId, 145 + }, 146 + headers: { 147 + Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`, 148 + }, 149 + }); 119 150 } catch (error) { 120 - consola.error(`Failed to start service ${id}`, error); 151 + consola.error(`Failed to start service ${serviceId}`, error); 121 152 process.exit(1); 122 153 } 123 154 } 124 155 125 - export async function stopService(id: string) { 156 + export async function stopService(serviceId: string) { 126 157 const token = await getAccessToken(); 127 158 128 159 try { 160 + await client.post("/xrpc/io.pocketenv.service.stopService", undefined, { 161 + params: { 162 + serviceId, 163 + }, 164 + headers: { 165 + Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`, 166 + }, 167 + }); 129 168 } catch (error) { 130 - consola.error(`Failed to stop service ${id}`, error); 169 + consola.error(`Failed to stop service ${serviceId}`, error); 131 170 process.exit(1); 132 171 } 133 172 } 134 173 135 - export async function deleteService(id: string) { 174 + export async function deleteService(serviceId: string) { 136 175 const token = await getAccessToken(); 137 176 138 177 try { 178 + await client.post("/xrpc/io.pocketenv.service.deleteService", undefined, { 179 + params: { 180 + serviceId, 181 + }, 182 + headers: { 183 + Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`, 184 + }, 185 + }); 139 186 } catch (error) { 140 - consola.error(`Failed to delete service ${id}`, error); 187 + consola.error(`Failed to delete service ${serviceId}`, error); 141 188 process.exit(1); 142 189 } 143 190 }