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.

Remove sandbox copy entry after pull

Delete sandboxCp DB records when pulling a directory in both the
sandbox and cf-sandbox services. In the CLI copy command add logic for
the local->sandbox case: fetch the sandbox, verify it exists and is
RUNNING before uploading, import the Sandbox type, and adjust the copy
flow (placeholders added for other source/destination cases).

+45 -3
+5
apps/cf-sandbox/src/index.ts
··· 1012 1012 await sandbox.sh`mkdir -p /tmp/${outdir} && cd /tmp/${outdir} && curl https://sandbox.pocketenv.io/cp/${params.uuid} -H "Authorization: ${token}" | tar xvf -`; 1013 1013 await sandbox.sh`mkdir -p ${params.directoryPath} || sudo mkdir -p ${params.directoryPath}`; 1014 1014 await sandbox.sh`cp -r /tmp/${outdir}/* ${params.directoryPath} || sudo cp -r /tmp/${outdir}/* ${params.directoryPath}`; 1015 + 1016 + await c.var.db 1017 + .delete(sandboxCp) 1018 + .where(eq(sandboxCp.copyUuid, params.uuid)) 1019 + .execute(); 1015 1020 }); 1016 1021 1017 1022 app.post("/v1/sandboxes/:sandboxId/push-directory", async (c) => {
+34 -3
apps/cli/src/cmd/copy.ts
··· 9 9 import consola from "consola"; 10 10 import getAccessToken from "../lib/getAccessToken"; 11 11 import { client } from "../client"; 12 + import type { Sandbox } from "../types/sandbox"; 12 13 13 14 async function copy(source: string, destination: string) { 14 15 const spinner = ora( 15 16 `Copying files from ${c.primary(source)} to ${c.primary(destination)}...`, 16 17 ).start(); 17 18 18 - if (!source.includes(":/")) { 19 + if (!source.includes(":/") && destination.includes(":/")) { 20 + const sandboxId = destination.split(":/")[0]!; 21 + const token = await getAccessToken(); 22 + 23 + const { data } = await client.get<{ sandbox: Sandbox }>( 24 + "/xrpc/io.pocketenv.sandbox.getSandbox", 25 + { 26 + params: { 27 + id: sandboxId, 28 + }, 29 + headers: { 30 + Authorization: `Bearer ${token}`, 31 + }, 32 + }, 33 + ); 34 + 35 + if (!data.sandbox) { 36 + consola.error(`Sandbox not found: ${c.primary(sandboxId)}`); 37 + process.exit(1); 38 + } 39 + 40 + if (data.sandbox.status !== "RUNNING") { 41 + consola.error(`Sandbox ${c.primary(sandboxId)} is not running.`); 42 + process.exit(1); 43 + } 44 + 19 45 const output = await compressDirectory(source); 20 46 const uuid = await uploadToStorage(output); 21 47 consola.info(`Uploaded to storage with UUID: ${uuid}`); 22 48 await unlink(output); 23 - const sandboxId = destination.split(":/")[0]; 24 - const token = await getAccessToken(); 49 + 25 50 await client.post( 26 51 "/xrpc/io.pocketenv.sandbox.pullDirectory", 27 52 { ··· 34 59 }, 35 60 }, 36 61 ); 62 + } 63 + 64 + if (source.includes(":/") && !destination.includes(":/")) { 65 + } 66 + 67 + if (source.includes(":/") && destination.includes(":/")) { 37 68 } 38 69 39 70 spinner.stopAndPersist({
+6
apps/sandbox/src/index.ts
··· 17 17 spriteAuth, 18 18 denoAuth, 19 19 vercelAuth, 20 + sandboxCp, 20 21 } from "./schema/mod.ts"; 21 22 import { 22 23 adjectives, ··· 913 914 await sandbox.sh`mkdir -p /tmp/${outdir} && cd /tmp/${outdir} && curl https://sandbox.pocketenv.io/cp/${params.uuid} -H "Authorization: ${token}" | tar xvf -`; 914 915 await sandbox.sh`mkdir -p ${params.directoryPath} || sudo mkdir -p ${params.directoryPath}`; 915 916 await sandbox.sh`cp -r /tmp/${outdir}/* ${params.directoryPath} || sudo cp -r /tmp/${outdir}/* ${params.directoryPath}`; 917 + 918 + await c.var.db 919 + .delete(sandboxCp) 920 + .where(eq(sandboxCp.copyUuid, params.uuid)) 921 + .execute(); 916 922 917 923 return c.json({ success: true }); 918 924 });