open, interoperable sandbox platform for agents and humans 📦 ✨
pocketenv.io
claude-code
atproto
sandbox
openclaw
agent
1import chalk from "chalk";
2import { consola } from "consola";
3import { ctx } from "../src/context";
4import type * as Sandbox from "../src/lexicon/types/io/pocketenv/sandbox";
5import { createAgent } from "../src/lib/agent";
6import prompts from "prompts";
7
8const args = process.argv.slice(2);
9
10if (args.length === 0) {
11 consola.error("Please provide user author identifier (handle or DID).");
12 console.log(`Usage: ${chalk.cyan("npm run sandbox -- <handle|did>")}`);
13 process.exit(1);
14}
15
16const name = await prompts({
17 type: "text",
18 name: "value",
19 message: "What is the sandbox name?",
20});
21
22if (name.value.length < 3 || name.value.length > 240) {
23 consola.error("Sandbox name must be between 3 and 240 characters.");
24 process.exit(1);
25}
26
27const description = await prompts({
28 type: "text",
29 name: "value",
30 message: "Please provide a short description of the sandbox",
31});
32
33if (description.value.length > 3000) {
34 consola.error("Description is too long. Maximum length is 3000 characters.");
35 process.exit(1);
36}
37
38const rkey = await prompts({
39 type: "text",
40 name: "value",
41 message: "What is the record key (rkey) for the sandbox?",
42});
43
44if (!/^[a-zA-Z0-9_-]{3,30}$/.test(rkey.value)) {
45 consola.error(
46 "Invalid record key. Only alphanumeric characters, underscores, and hyphens are allowed. Length must be between 3 and 30 characters.",
47 );
48 process.exit(1);
49}
50
51consola.info("Creating sandbox with the following details:");
52consola.info("---");
53consola.info("Sandbox name:", name.value);
54consola.info("Description:", description.value);
55consola.info("Record key (rkey):", rkey.value);
56
57const confirm = await prompts({
58 type: "confirm",
59 name: "value",
60 message: "Do you want to proceed?",
61 initial: true,
62});
63
64if (!confirm.value) {
65 consola.info("Sandbox creation cancelled.");
66 process.exit(0);
67}
68
69let userDid = args[0];
70
71if (!userDid?.startsWith("did:plc:")) {
72 userDid = await ctx.baseIdResolver.handle.resolve(userDid!);
73}
74
75const agent = await createAgent(ctx.oauthClient, userDid!);
76
77consola.info(`Writing ${chalk.greenBright("io.pocketenv.sandbox")} record...`);
78
79const record: Sandbox.Record = {
80 $type: "io.pocketenv.sandbox",
81 name: name.value,
82 description: description.value,
83 vcpus: 1,
84 memory: 4,
85 disk: 3,
86 createdAt: new Date().toISOString(),
87};
88
89if (!agent) {
90 consola.error("failed to create agent");
91 process.exit(1);
92}
93
94const res = await agent.com.atproto.repo.createRecord({
95 repo: agent.assertDid,
96 collection: "io.pocketenv.sandbox",
97 record,
98 rkey: rkey.value,
99});
100
101consola.info(chalk.greenBright("Sandbox created successfully!"));
102consola.info(`Record created at: ${chalk.cyan(res.data.uri)}`);
103
104process.exit(0);