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.

Allow sandbox name lookup and improve file CLI

Match sandbox lookup by either sandboxFiles.sandboxId or
sandboxes.name in the getFiles handler. Update CLI listFiles to fetch
files via the client, use POCKETENV_TOKEN as an auth fallback, and
render a compact table with relative "created at" timestamps.

+66 -4
+9 -3
apps/api/src/xrpc/io/pocketenv/file/getFiles.ts
··· 1 1 import { XRPCError, type HandlerAuth } from "@atproto/xrpc-server"; 2 2 import type { Context } from "context"; 3 - import { eq, and, count } from "drizzle-orm"; 3 + import { eq, and, count, or } from "drizzle-orm"; 4 4 import type { Server } from "lexicon"; 5 5 import type { 6 6 QueryParams, ··· 66 66 params.sandboxId 67 67 ? and( 68 68 eq(users.did, auth.credentials.did), 69 - eq(sandboxFiles.sandboxId, params.sandboxId), 69 + or( 70 + eq(sandboxFiles.sandboxId, params.sandboxId), 71 + eq(sandboxes.name, params.sandboxId), 72 + ), 70 73 ) 71 74 : eq(users.did, auth.credentials.did), 72 75 ) ··· 90 93 params.sandboxId 91 94 ? and( 92 95 eq(users.did, auth.credentials.did), 93 - eq(sandboxFiles.sandboxId, params.sandboxId), 96 + or( 97 + eq(sandboxFiles.sandboxId, params.sandboxId), 98 + eq(sandboxes.name, params.sandboxId), 99 + ), 94 100 ) 95 101 : eq(users.did, auth.credentials.did), 96 102 )
+57 -1
apps/cli/src/cmd/file.ts
··· 1 1 import chalk from "chalk"; 2 2 import consola from "consola"; 3 3 import getAccessToken from "../lib/getAccessToken"; 4 + import dayjs from "dayjs"; 5 + import relativeTime from "dayjs/plugin/relativeTime"; 6 + import { client } from "../client"; 7 + import { env } from "../lib/env"; 8 + import CliTable3 from "cli-table3"; 9 + import type { File } from "../types/file"; 10 + import { c } from "../theme"; 11 + 12 + dayjs.extend(relativeTime); 4 13 5 14 export async function putFile(sandbox: string, path: string) { 6 15 const token = await getAccessToken(); ··· 10 19 ); 11 20 } 12 21 13 - export async function listFiles(sandbox: string) { 22 + export async function listFiles(sandboxId: string) { 14 23 const token = await getAccessToken(); 24 + 25 + const response = await client.get<{ files: File[] }>( 26 + "/xrpc/io.pocketenv.file.getFiles", 27 + { 28 + params: { 29 + sandboxId, 30 + }, 31 + headers: { 32 + Authorization: `Bearer ${env.POCKETENV_TOKEN || token}`, 33 + }, 34 + }, 35 + ); 36 + 37 + const table = new CliTable3({ 38 + head: [c.primary("ID"), c.primary("PATH"), c.primary("CREATED AT")], 39 + chars: { 40 + top: "", 41 + "top-mid": "", 42 + "top-left": "", 43 + "top-right": "", 44 + bottom: "", 45 + "bottom-mid": "", 46 + "bottom-left": "", 47 + "bottom-right": "", 48 + left: "", 49 + "left-mid": "", 50 + mid: "", 51 + "mid-mid": "", 52 + right: "", 53 + "right-mid": "", 54 + middle: " ", 55 + }, 56 + style: { 57 + border: [], 58 + head: [], 59 + }, 60 + }); 61 + 62 + for (const file of response.data.files) { 63 + table.push([ 64 + c.secondary(file.id), 65 + file.path, 66 + dayjs(file.createdAt).fromNow(), 67 + ]); 68 + } 69 + 70 + consola.log(table.toString()); 15 71 } 16 72 17 73 export async function deleteFile(sandbox: string, id: string) {