{"_id":"@ai-hero/sandcastle","_rev":"30-06b200998ce67e5a592d0582da8d58e8","name":"@ai-hero/sandcastle","dist-tags":{"latest":"0.5.10"},"versions":{"0.0.1":{"name":"@ai-hero/sandcastle","version":"0.0.1","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.0.1","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"5a0817e4cda10be5edcff9606dd96be25aa54a41","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.0.1.tgz","fileCount":133,"integrity":"sha512-lg58EMWBM2ojHZrAhSe7GqATaKEayHGNSBYJrZ6oWPdZN5frNAUW+LlFAfDNZhjbl/Foc2032FH6NueMmw8NRQ==","signatures":[{"sig":"MEQCIEtN0fZ/7VwIbcYxQMMpcU8M2llIEB3zeEsLZQVe/dDdAiA/Oojpvdea+ulHiNQzPWSKVi7QWdxbQXR472HeLiaLfw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":322019},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"3d046db0ec27719373e82915b562a56708d863fa","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","test:watch":"vitest","format:check":"prettier --check .","run-sandcastle":"tsx .sandcastle/run.ts"},"_npmUser":{"name":"mpocock","email":"mpocock@me.com"},"_npmVersion":"10.9.4","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"22.21.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.0.1_1774511001981_0.17981070889565132","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@ai-hero/sandcastle","version":"0.1.0","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.1.0","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"399ddf778ad9f686091a42f06dbad65f59d10346","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.1.0.tgz","fileCount":110,"integrity":"sha512-fZuP0JkxBWggGAE77JkSKeJZ88bqmICKX8oFEAo4S72n1gqKcnKmzLJdKo1dMV8fB28sL+7udZAw/TvCtiERiw==","signatures":[{"sig":"MEUCIAHIhssVmn88Tg0ZpxPsZzAB8yRIo9xgOwr1IGUZqJmqAiEAmEjNIiMPSqys9yxvKmN2l8GAOBRRCcNev7tVZ+bicys=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":256370},"main":"./dist/index.js","type":"module","_from":"file:ai-hero-sandcastle-0.1.0.tgz","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","test:watch":"vitest","format:check":"prettier --check .","run-sandcastle":"tsx .sandcastle/run.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"_resolved":"/tmp/2fa24a4b58e1765aabb57107775a94ea/ai-hero-sandcastle-0.1.0.tgz","_integrity":"sha512-fZuP0JkxBWggGAE77JkSKeJZ88bqmICKX8oFEAo4S72n1gqKcnKmzLJdKo1dMV8fB28sL+7udZAw/TvCtiERiw==","_npmVersion":"11.9.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.0","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.1.0_1774519960587_0.3964314277823555","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"@ai-hero/sandcastle","version":"0.1.4","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.1.4","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"4503639b7156ca839b41ec41451d258d3b37b2c0","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.1.4.tgz","fileCount":110,"integrity":"sha512-4AsnN0evR0FYFJl0H3zakLTvjuzydGemgM4+lXF2oCR9dlnGyVLsR+OwCjFxbyyFPP+VbIAGU7MFjNShnF4rvg==","signatures":[{"sig":"MEQCIEOPhxfFOgcXtgVC9IjIOQjLngSQQDUwGKtPYn2V+gIiAiByjbWPSAoDH6TZkM8h2XlbzOl75Kp676NJXZyvPsfE1Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.1.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":257107},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"3787868618c3e34100688bf4812205a7063a6107","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","test:watch":"vitest","format:check":"prettier --check .","run-sandcastle":"tsx .sandcastle/run.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.9.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.0","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.1.4_1774524849327_0.9730405866241842","host":"s3://npm-registry-packages-npm-production"}},"0.1.5":{"name":"@ai-hero/sandcastle","version":"0.1.5","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.1.5","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"7a1693623b9965374934d7d638551de62c33b3ef","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.1.5.tgz","fileCount":110,"integrity":"sha512-tSqmAYYEUVIfyJg3jyxdLZ2anbrdT7enf4zv6BnsLsVEv6FYMlquIYXuCX1fp/HnFbu5DFh+D7zA9cnr9jtYMg==","signatures":[{"sig":"MEUCIEJeRbw6Artv5QnkgCZAZOYO1NnsIkcQmGCAP9H+PdMrAiEAvvJ+39z8DLHgVeQe8mfjXUscSrAYtN8YG9QSA0D/lfk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.1.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":257208},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"455758361f347268cd591db7d44b097d682cfc3f","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","test:watch":"vitest","format:check":"prettier --check .","run-sandcastle":"tsx .sandcastle/run.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.9.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.0","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.1.5_1774558789178_0.12374496480830421","host":"s3://npm-registry-packages-npm-production"}},"0.1.6":{"name":"@ai-hero/sandcastle","version":"0.1.6","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.1.6","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"dd7fe881a8e369ba802bed9e2125683ee5dce924","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.1.6.tgz","fileCount":110,"integrity":"sha512-9X5UowToDjXfIOYtF40uRbOSDR8G9J+zea/qj4Sty4W0U4LO/bruw9swtAbEBLr3Ui57MongsRI5Cpux+UX+cw==","signatures":[{"sig":"MEQCICFmUjs8XE82AN4bEyokPZO8ea4ptLePVDOH8BRiQWOrAiBWoMwxy/NHSaR8LQAym7B2CvR+o2RGJWDZxXJJYxsBtQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.1.6","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":256614},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"ff05ae8680fd897805f7a773f3db8016cfa2e7d2","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","test:watch":"vitest","format:check":"prettier --check .","run-sandcastle":"tsx .sandcastle/run.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.9.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.0","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.1.6_1774559246768_0.9235745100672763","host":"s3://npm-registry-packages-npm-production"}},"0.1.7":{"name":"@ai-hero/sandcastle","version":"0.1.7","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.1.7","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"324452b1b7933811f32a76b2fa5b482c22790de4","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.1.7.tgz","fileCount":110,"integrity":"sha512-pgM48q67oaN3iXFzrpQAGVQZz+g8hRo/uB3XFWkS75KtpOsqIGywWhY0EkAz4CeElb46oHIRlAf/Bg8OwBz3DQ==","signatures":[{"sig":"MEUCID+6O98ldiycSTgTDeLYTIL013UBl3/a9Thr9Cq4AI4oAiEA9841Pe91gw65E2844Zgi94psx7cbH8Z+mcvEqrT1K4E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.1.7","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":267172},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"0f089e585631e52678fce3b0ed9a875d3d99474e","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","test:watch":"vitest","format:check":"prettier --check .","run-sandcastle":"tsx .sandcastle/run.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.9.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.0","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.1.7_1775050961533_0.8888930959056234","host":"s3://npm-registry-packages-npm-production"}},"0.1.8":{"name":"@ai-hero/sandcastle","version":"0.1.8","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.1.8","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"0129f4eb8d22a507b714e6427986a355bc41acbd","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.1.8.tgz","fileCount":110,"integrity":"sha512-Gn4bNvdZQgCQqEYKR0/XQ48dIyynlGF3T8QXe+PowAz6uLgQN0G3pbK0PTB1i8OhlI2fPVM9Ze1c0l4cTZat+g==","signatures":[{"sig":"MEYCIQDNC1APde6BeailS92pQycVJkAVH1ARnMn8SSTQ0PpMnQIhAKpMZaxaaJ0HdZLL249sppmz5VZqZ6fz+Osd9ZXEjvsJ","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.1.8","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":270810},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"0a78aa660423978fe1d17cb9b9c0ac14b2b665a1","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.9.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.0","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.1.8_1775056115913_0.8215344253200694","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@ai-hero/sandcastle","version":"0.2.0","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.2.0","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"b0d05c7cd9f3d6f6c2b6bc6496543708a3bc15f0","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.2.0.tgz","fileCount":118,"integrity":"sha512-PEHxSjvdJgoCWSqVMvx/1J4OkUMFip8dN+plLyh4HjBX4BoN8hxhngVyHCNh0Mj9P5tPrB1YXTPnj3BWUDMIjQ==","signatures":[{"sig":"MEQCIE5xDXApBrTqGp49YAlcEBWBnBEaWnfnxs2bl2o5E9nYAiBW0UDPiqjKsx3FjEAcXzhTr/5Yph8Jb78qRJvhazP/Zg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":327145},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"4548b975b888c1bf3e001beb86e6dd8c0cc45870","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.2.0_1775129501725_0.153157168842061","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@ai-hero/sandcastle","version":"0.2.1","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.2.1","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"376c42ba8fd5b4c23ccbde4602648a2959486907","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.2.1.tgz","fileCount":118,"integrity":"sha512-Md2c5pngZY9QC+/uP0ZdcazD9w/8HHmPUCYzwPuzzihyWIlFs6YfZPmfEvb3RT2F1qWNlU0xg2QOGm7UBazIow==","signatures":[{"sig":"MEUCIQCUzQA2O2REdzezuBIsF0ueejlFHH3ztn6kPz+w8nFtNAIgGI/CiBSs0gDHHBjaCDCrYSUYO0ST60Afle9aS0Qz7r8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":327213},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"9000fc8e4d8e5a63568b7a39bbbdf0d530ea2b95","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.2.1_1775209557473_0.6938295728612269","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"name":"@ai-hero/sandcastle","version":"0.2.2","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.2.2","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"cc790b4f28ef22e4c90341402b15ecc5af7cd5cd","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.2.2.tgz","fileCount":118,"integrity":"sha512-55yr3dO5htQuMz2Nb1uT1VxsrMRktGGSBfI624fwapuJgW+AdqwAgl7+sbByUPeY2RXW/FZsYeGhdfSVhSWCww==","signatures":[{"sig":"MEUCIFaShFkOWjkT2tfTDGEczs38P5ZkaBDWpQuQISaLufF1AiEAwtGsu8izK5GY3kbVcxtIRgW2tLHe0NzY9Ieog8qZddY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.2.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":330156},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"f0cdc8fc0c65df1b6009a8ea9044a0bf746a6568","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.2.2_1775390999690_0.7292209289987321","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"@ai-hero/sandcastle","version":"0.2.3","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.2.3","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"dee27825af81955a2d0f28fe548dbb5e392ec76c","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.2.3.tgz","fileCount":118,"integrity":"sha512-SPOL7q0FPpT3TuA9aSvwovj/LJRsS9sLGVGomD9GicuEEqaS8xuHoLGlN3RX8Vtts9O/0FKDudOTF45Z7FjMvA==","signatures":[{"sig":"MEUCIQDmISi6G0Cz3Y+iLuvM0gQoHdI3ZZfYzECgW7gCxlRapAIgf4jWHF24JBhSe8R3/Rdcz+GpBPBtandJa19psjnoMk4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.2.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":333401},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"f63cfc1ba9bb6e6e5d3a4eeba413aff60f3fe541","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.2.3_1775392908023_0.9036638161710724","host":"s3://npm-registry-packages-npm-production"}},"0.2.4":{"name":"@ai-hero/sandcastle","version":"0.2.4","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.2.4","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"892e664ce5e9ac69f9817fa30b5d81c15ae5b2a7","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.2.4.tgz","fileCount":118,"integrity":"sha512-0FCZZWxak+2U9lf2EuTbN60fwx/EypF8x8CCSigS1ako6MkFf7UaE9piI59wNiCULd/IJ/LYsnTzTf2VrFQVLQ==","signatures":[{"sig":"MEUCIQCM3ov7WbOKVwqssckitfUEfFRHyl/cuw7ctttrx4808QIgHr7+BZGc4Dre63HKQsDOdrHoLAqmkHeAHmstCd2erm0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.2.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":334568},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"44fd1fd82f88b7b38bcebaf272d962f58e1ac2ef","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.2.4_1775808899407_0.28479014999013863","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@ai-hero/sandcastle","version":"0.3.0","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.3.0","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"6753be99146814f57785adcd0f59d3718ea2143b","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.3.0.tgz","fileCount":142,"integrity":"sha512-WPlL8jxxNIL2167eEUetIeht6AH2uxkNGwJhTRildp9fVEgYlNmB+bHn8OPpH+/mSLbDrFyyCtAlEICuzSAk9A==","signatures":[{"sig":"MEYCIQCXh2k9Vxfkd7vyA92IpZzVf6Fiw9ZPh3MIHAPhCXgbNgIhAJ23bo2AZxIS0jcdvLpDc0KkzqZX3pLfIIU3hb0eMEQB","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":383242},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"}},"gitHead":"9f542dfaae76c8edc47b6a711747c7ed8cf18b19","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.3.0_1775827880384_0.14138393703273233","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@ai-hero/sandcastle","version":"0.4.0","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.4.0","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"163fbeabb35fa83c91e26ddf85446ba68303d049","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.4.0.tgz","fileCount":142,"integrity":"sha512-d/lAT9XBNjqYGOZUo99BW56DUDca2rxCEFW8mQ4EnKethZ2DftZlyveK8W1dMpMTxJW/lse/X5C+YjdIlwzDMw==","signatures":[{"sig":"MEQCIAbrjVVuqgt95pbN6uIjYRGb14vTOrZvo6kmexUzjn11AiBNW/y2Nura7AyqH1g3zHwChQ+aRtks8cz7PMY0UyfV7Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.4.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":406090},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"}},"gitHead":"90fc04a5ba6f063812c6d4d0c069da371df8c64e","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.4.0_1775894780094_0.9326142827067974","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@ai-hero/sandcastle","version":"0.4.1","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.4.1","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"4ea1e217f5b969386e265bea2e28243290d830a0","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.4.1.tgz","fileCount":175,"integrity":"sha512-FoA08gDTAugX1v8QZA9zKm4SIWiYXg+JLYw569eElqJxuz5UfFqevncYsECK3UErwMBu15G4KN7r2X/qFs7RGg==","signatures":[{"sig":"MEMCIC3wjhbc7Ag1eL5dXlK1I+S0+9QX7PXQw51ifsie8MCnAh8Ls61PiWOyb863XYo1V4naTLXzONGuscyGZviZXoqi","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.4.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":493665},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"}},"gitHead":"79456c5c8a7654cfbb8f29fb5b11e1db52555067","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.4.1_1776108108728_0.8740781578113934","host":"s3://npm-registry-packages-npm-production"}},"0.4.2":{"name":"@ai-hero/sandcastle","version":"0.4.2","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.4.2","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"045f811ba2cce0a93f6bd9ca19b488699af77cf5","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.4.2.tgz","fileCount":175,"integrity":"sha512-prv5sJEnbngI0czOIOAlGd+xlqirB6ph6PGwoZAiFukMe1mTErlIYOK0UUJLgVfkdoCMsB505iF0dILr/wfvkg==","signatures":[{"sig":"MEYCIQDxFt1gpgB29k9u1rFA8wKeI3St8T/CNo00pUU+H/j+owIhAPjiIOkLTuvV29IXX53GOVijVJigsjte1TUcoirUKIZg","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.4.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":494696},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"}},"gitHead":"f96582c10069cfc1841de37372b1b2dbb7d3fd88","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.4.2_1776111151436_0.052317602584434963","host":"s3://npm-registry-packages-npm-production"}},"0.4.3":{"name":"@ai-hero/sandcastle","version":"0.4.3","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.4.3","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"0c14d59f786f2603a0bb5c2081e07decca1f4566","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.4.3.tgz","fileCount":175,"integrity":"sha512-MqD0e+f1a9FY7QT4ebX878LOpWKUbTBgPT+iRSt0VxklHw+PjGpX+e0eWZpv1JwxsL7CysVdr2cpRNzXYurkpQ==","signatures":[{"sig":"MEUCIQCebrp5dE1sG0Roc0wDh+pd6nnVUNGHVm/1yPEhlQ2ZDAIgI7rlSjMJuJjyl9DN865q4sJ8ZBmVZgydpbEocfSRvZ0=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.4.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":499007},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"}},"gitHead":"dba7a67fa46d117197a58c81153cd1efd3d8f505","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.4.3_1776148754806_0.39489256622908764","host":"s3://npm-registry-packages-npm-production"}},"0.4.4":{"name":"@ai-hero/sandcastle","version":"0.4.4","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.4.4","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"19ad5eeb98d934028028b150bcf8a768cb4cbb97","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.4.4.tgz","fileCount":179,"integrity":"sha512-NwJCwPv6HOrwjTNl0hUVXRQRP29jsdepi4FTRFGPYCuCSChLDaOheL1D1vGc4Khom09N/08XBml2uXjAVa5ZhA==","signatures":[{"sig":"MEYCIQD2XlB301OcPKCdL63l12xFYMZv6ipApmP8IUmRZc/7NwIhAN2p2b6PAA0nGtkl11NFdvqV4hx0TXnHT56Wtsr8Gry8","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.4.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":510551},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"}},"gitHead":"3caef929627aad52b2b881050eecb6e4602d6408","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.4.4_1776156114083_0.8913828772853545","host":"s3://npm-registry-packages-npm-production"}},"0.4.5":{"name":"@ai-hero/sandcastle","version":"0.4.5","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.4.5","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"963a432266939d2f913097bf70471ca5db4587f8","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.4.5.tgz","fileCount":179,"integrity":"sha512-drkUN2tQSoLWCPwSuh/IDaGzme8a5i71IXe70y7aUPd5Ol+MlEjItLKmxf+A7nKO/eXBZcbhL9HX3CJxk+ViFA==","signatures":[{"sig":"MEUCIQCfEh55zT2yVkMEsw6uAOr8XrPyWDmPToomusi7vmw6mgIgYfpKDXHMwW9W4BY4qEk5TLSUJvB7GF+Rsppa4o+k3Ew=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.4.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":511972},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"}},"gitHead":"f51e14f99785f728d3fc335f55bf33110fbd8104","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check ."},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.4.5_1776181915751_0.7234350866214931","host":"s3://npm-registry-packages-npm-production"}},"0.4.6":{"name":"@ai-hero/sandcastle","version":"0.4.6","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.4.6","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"4351045779988d3b5c5f9938577df5618802587e","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.4.6.tgz","fileCount":191,"integrity":"sha512-4A7WVZ4j3wBTYlsWKBBo2jG6alNp8GdOimetebG4qESma9O0VKCzYovr6IjZ+Zm7i7jCpazR+wYpb752fpac5g==","signatures":[{"sig":"MEUCIQDtfrOJi6SA+UIUEj63liLQGtM+mHaUmRiWNeglgbOk4AIgH5oyx1xl1bAMUvAoO3oiSCL5NPKchvrAvDVkjYZxO3w=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.4.6","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":586247},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"},"./sandboxes/no-sandbox":{"types":"./dist/sandboxes/no-sandbox.d.ts","import":"./dist/sandboxes/no-sandbox.js"}},"gitHead":"0531b0e1967efa85de33565d1ef9361a5f9a0c4a","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-podman":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-podman.ts","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check .","test-interactive":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-interactive.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.4.6_1776247643069_0.7640374627383546","host":"s3://npm-registry-packages-npm-production"}},"0.4.7":{"name":"@ai-hero/sandcastle","version":"0.4.7","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.4.7","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"6ff4668521d77bb4c36bc4344b33a1f66b60d267","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.4.7.tgz","fileCount":191,"integrity":"sha512-68qvRINHN7XmRCJp1HqNzdKBgSViSKtQmJN9+K8lHXjZGRTSQoKeT2zDO54uoy33AO61cnlobDhw8hHmUxyDDA==","signatures":[{"sig":"MEUCIQCtuvjJDmotxRGYxk5FpW0HUHriFwBrPwhnVfUM+8nxjAIgU0RRJp7yLUJbfJs7MUzegmljrYlm4TLBUQ8fTRwZIJc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.4.7","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":586437},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"},"./sandboxes/no-sandbox":{"types":"./dist/sandboxes/no-sandbox.d.ts","import":"./dist/sandboxes/no-sandbox.js"}},"gitHead":"bbe17769283988abd2f2f8df8c8b203016f4c49b","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-podman":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-podman.ts","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check .","test-interactive":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-interactive.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.4.7_1776248018732_0.8875798732699594","host":"s3://npm-registry-packages-npm-production"}},"0.4.8":{"name":"@ai-hero/sandcastle","version":"0.4.8","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.4.8","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"dad54fff59d6867793b35f2df371c5939a8dd9e9","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.4.8.tgz","fileCount":190,"integrity":"sha512-EvAr3M0wKMC/m7IbpgSN17r3bvON7po1kSmdiYHqpPBCTTSizAUnOfLbRAha3bXn/P1B5JXELkOOjsfLYjhg9A==","signatures":[{"sig":"MEQCIH9sCQjGxjxushuHkvfj3dDcbwxtzG3Y0GFdgiEM5ZhZAiAzHQv77A7IriyqTdf5t9hn0YJDSLMuZAz5FXhqrN7lfw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.4.8","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":663822},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"},"./sandboxes/no-sandbox":{"types":"./dist/sandboxes/no-sandbox.d.ts","import":"./dist/sandboxes/no-sandbox.js"}},"gitHead":"1fba706da4b227d76b60257b505f992fb4ada8ce","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-podman":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-podman.ts","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check .","test-interactive":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-interactive.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.4.8_1776427896982_0.5777449802910404","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@ai-hero/sandcastle","version":"0.5.0","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.5.0","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"2c24a9344ff25e8a2e407a0dc1217e96ce9f5c80","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.5.0.tgz","fileCount":198,"integrity":"sha512-5S+4uX3yOj2R16yALXFwsmxbNO/3eaaQ55rbetUrnvV4OW2jFITxqkKVgWSsQsC3aK083Oii3L0FYKzU8gIPxA==","signatures":[{"sig":"MEUCIQCCCcULYZqz8dx5bRd7YSCoVJ2tXw5NqwYQV60VlpByNwIgJUMMurpmWSk8tYDjbFwnJXu4uRuufo33ZgYzseiqRWU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.5.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":715790},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"},"./sandboxes/no-sandbox":{"types":"./dist/sandboxes/no-sandbox.d.ts","import":"./dist/sandboxes/no-sandbox.js"}},"gitHead":"e9fb01b88384357fdcd19b9e576cfeb028874175","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-podman":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-podman.ts","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check .","test-interactive":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-interactive.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.5.0_1776791675347_0.8050518388467462","host":"s3://npm-registry-packages-npm-production"}},"0.5.1":{"name":"@ai-hero/sandcastle","version":"0.5.1","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.5.1","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"ba1fb9b69e5bded8ca5f82d71139ab549707b95c","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.5.1.tgz","fileCount":206,"integrity":"sha512-S2a0Bzw6ca6ksOfoGYgm1DO0eyLVQCn6a4YRkYPNDxU4gVzRed1ymagukmFLoAeZPFM2C/SoQmM7No9mNE9OwA==","signatures":[{"sig":"MEUCIGngUWoQLHk+lajlU/Quw7GG4xnVmgHb56UnCTLZaizTAiEA5eLFpmRa5M2t6Ndq0t9c1w+ZzvNv2Ac/x1lms3jvLos=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.5.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":728106},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"},"./sandboxes/no-sandbox":{"types":"./dist/sandboxes/no-sandbox.d.ts","import":"./dist/sandboxes/no-sandbox.js"}},"gitHead":"308b6a7976791b3e9c33b8396f0f576905ff3793","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-podman":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-podman.ts","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check .","test-interactive":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-interactive.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.5.1_1776800584415_0.24777361091423966","host":"s3://npm-registry-packages-npm-production"}},"0.5.4":{"name":"@ai-hero/sandcastle","version":"0.5.4","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.5.4","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"73fda3ed7715443d4a4a4c6d1a33da1277ca4da9","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.5.4.tgz","fileCount":222,"integrity":"sha512-m4CcrgR5Sj4Qv4gnyKE3uCKqbywLcor8CoLSg11DXJtS6rm2xcZ/rjeiBr1zoqF2zpMqV6vIMKvSPAt8bcFW1g==","signatures":[{"sig":"MEQCIGdFBblqoRDS5+DSHPUPoTFSd2VGJpIpDYvS7v6L4+1WAiAZvYPyizbiOZ0R8qsObKuQipYSBWgCgcgo5h6Uk5vH5A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.5.4","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":799587},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"},"./sandboxes/no-sandbox":{"types":"./dist/sandboxes/no-sandbox.d.ts","import":"./dist/sandboxes/no-sandbox.js"}},"gitHead":"0ade9bbd71f8e011dd9305b35c3db07dd7ce6540","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-podman":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-podman.ts","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check .","test-interactive":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-interactive.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.5.4_1777058741864_0.29723108675900867","host":"s3://npm-registry-packages-npm-production"}},"0.5.5":{"name":"@ai-hero/sandcastle","version":"0.5.5","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.5.5","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"100697cb26aa9771654d3ca0b0c9ee9541318ef3","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.5.5.tgz","fileCount":222,"integrity":"sha512-zdwc3zcEgUHWjlJAwfUlP0WpQy0xYN8oYuPSNYZ3UzUCZdy7dDnpa8EFoZE4dTkW0ogan5MhZ94SeylFZFqYMQ==","signatures":[{"sig":"MEQCIApqIcnVvR8gisaElhVvrer9HuRnhdPywxWazzacwsLLAiB9SHNAquay9N6XAHCCX5lYuR37wizzpGhGRvjLkRGg4Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.5.5","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":799900},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"},"./sandboxes/no-sandbox":{"types":"./dist/sandboxes/no-sandbox.d.ts","import":"./dist/sandboxes/no-sandbox.js"}},"gitHead":"972e266b97d9e9a210f8e91c42a23037a587b9a7","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-podman":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-podman.ts","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check .","test-interactive":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-interactive.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.5.5_1777276992359_0.18734872759590426","host":"s3://npm-registry-packages-npm-production"}},"0.5.6":{"name":"@ai-hero/sandcastle","version":"0.5.6","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.5.6","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"7d69f16b9f6c680232ab3a6f798ea9a2c5a0a483","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.5.6.tgz","fileCount":222,"integrity":"sha512-HGbDRBdu2xLWChnYAyjnVb9G4AvS7joUjHrLd0+6r3jjyMmb6+EZyO/UnLPa0BdJE3MlWW8XTjPSldxICtsZHw==","signatures":[{"sig":"MEQCIBgFkPXgJImj2c8pJPavv/q6Ob9An1tns5pdD0DEuyQMAiBF2upOsS/KzGcuEGlO9/RZlNGP02Dt2UCS5J6xjCvNPg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.5.6","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":808452},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"},"./sandboxes/no-sandbox":{"types":"./dist/sandboxes/no-sandbox.d.ts","import":"./dist/sandboxes/no-sandbox.js"}},"gitHead":"e64093149f55756052a6a3ab9cf0acc909caac86","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-podman":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-podman.ts","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check .","test-interactive":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-interactive.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.5.6_1777494167550_0.6365185526465988","host":"s3://npm-registry-packages-npm-production"}},"0.5.7":{"name":"@ai-hero/sandcastle","version":"0.5.7","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.5.7","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"85184d6cdbe51b72f9394eb7e30a970b60d5a41e","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.5.7.tgz","fileCount":222,"integrity":"sha512-5ZznDx9LQCdOYooL+INx6+35tH44Lb/7+BYUmgWPuBXy5YD7pt14GgMHMWbx3NtSYot7VcBMrgj7UpAQmpRrDA==","signatures":[{"sig":"MEQCIFiPqoVm54LVpq2kewPhCki63X6NZzPSVGBSV9GnIQbsAiBliLH5Q17iwnjB3myMEw6AuoUrBPWBq3w7xLMg4uDv2g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.5.7","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":808422},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"},"./sandboxes/no-sandbox":{"types":"./dist/sandboxes/no-sandbox.d.ts","import":"./dist/sandboxes/no-sandbox.js"}},"gitHead":"20cb6086b567f3fd83f2b2cb9c7ad565a852c67f","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-podman":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-podman.ts","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check .","test-interactive":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-interactive.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.5.7_1777641353128_0.17951643024198805","host":"s3://npm-registry-packages-npm-production"}},"0.5.8":{"name":"@ai-hero/sandcastle","version":"0.5.8","keywords":["cli","sandbox","docker","ai","agent"],"license":"MIT","_id":"@ai-hero/sandcastle@0.5.8","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"homepage":"https://github.com/mattpocock/sandcastle#readme","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"bin":{"sandcastle":"dist/main.js"},"dist":{"shasum":"ab355354980e7bc36566960a7ec49e13d544be04","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.5.8.tgz","fileCount":222,"integrity":"sha512-dOBQ5MzzO8zMJ4R3tI9SKjlezq+3JdKZDi3fYyIPoaqbdQJWpw4w429BKRry9m2+uO94Ur7W48J0wEPQKd6ybg==","signatures":[{"sig":"MEQCIGhdrREkSxaaquU4hs77iCzw3uyO+qBIuhuNogNHlyngAiB1s2iKn+JcYLA/HIv83ubbNx6Ri+MIIwfeVlEbgD0Krw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.5.8","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":809313},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./sandboxes/docker":{"types":"./dist/sandboxes/docker.d.ts","import":"./dist/sandboxes/docker.js"},"./sandboxes/podman":{"types":"./dist/sandboxes/podman.d.ts","import":"./dist/sandboxes/podman.js"},"./sandboxes/vercel":{"types":"./dist/sandboxes/vercel.d.ts","import":"./dist/sandboxes/vercel.js"},"./sandboxes/daytona":{"types":"./dist/sandboxes/daytona.d.ts","import":"./dist/sandboxes/daytona.js"},"./sandboxes/no-sandbox":{"types":"./dist/sandboxes/no-sandbox.d.ts","import":"./dist/sandboxes/no-sandbox.js"}},"gitHead":"b9f7ca48ab3653ad77b14317b59955d6fb471aae","scripts":{"test":"vitest run","build":"tsgo --project tsconfig.build.json","format":"prettier --write .","prepare":"husky","release":"changeset publish","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","typecheck":"tsgo --noEmit","sandcastle":"npm run build && tsx .sandcastle/run.ts","test:watch":"vitest","test-podman":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-podman.ts","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","format:check":"prettier --check .","test-interactive":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-interactive.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"repository":{"url":"git+https://github.com/mattpocock/sandcastle.git","type":"git"},"_npmVersion":"11.11.0","description":"CLI for orchestrating AI agents in isolated sandbox environments","directories":{},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"_nodeVersion":"24.14.1","dependencies":{"effect":"^3.20.0","@effect/cli":"^0.74.0","@clack/prompts":"^1.1.0","@effect/printer":"^0.48.0","@effect/platform":"^0.95.0","@effect/printer-ansi":"^0.48.0","@effect/platform-node":"^0.105.0"},"_hasShrinkwrap":false,"packageManager":"npm@10.9.2","devDependencies":{"tsx":"^4.21.0","husky":"^9.1.7","vitest":"^3.2.0","prettier":"^3.5.3","@types/node":"^25.5.0","lint-staged":"^15.5.1","@effect/vitest":"^0.28.0","@changesets/cli":"^2.30.0","@typescript/native-preview":"^7.0.0-dev.20260317.1"},"peerDependencies":{"@daytona/sdk":"^0.164.0","@vercel/sandbox":">=1.0.0"},"peerDependenciesMeta":{"@daytona/sdk":{"optional":true},"@vercel/sandbox":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/sandcastle_0.5.8_1778073534603_0.8687282411336712","host":"s3://npm-registry-packages-npm-production"}},"0.5.10":{"name":"@ai-hero/sandcastle","version":"0.5.10","description":"CLI for orchestrating AI agents in isolated sandbox environments","type":"module","main":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"},"./sandboxes/docker":{"import":"./dist/sandboxes/docker.js","types":"./dist/sandboxes/docker.d.ts"},"./sandboxes/vercel":{"import":"./dist/sandboxes/vercel.js","types":"./dist/sandboxes/vercel.d.ts"},"./sandboxes/podman":{"import":"./dist/sandboxes/podman.js","types":"./dist/sandboxes/podman.d.ts"},"./sandboxes/daytona":{"import":"./dist/sandboxes/daytona.js","types":"./dist/sandboxes/daytona.d.ts"},"./sandboxes/no-sandbox":{"import":"./dist/sandboxes/no-sandbox.js","types":"./dist/sandboxes/no-sandbox.d.ts"}},"bin":{"sandcastle":"dist/main.js"},"scripts":{"build":"tsgo --project tsconfig.build.json","postbuild":"rm -rf dist/templates && cp -r src/templates dist/templates","test":"vitest run","test:watch":"vitest","typecheck":"tsgo --noEmit","format":"prettier --write .","format:check":"prettier --check .","prepare":"husky","release":"changeset publish","sandcastle":"npm run build && tsx .sandcastle/run.ts","test-podman":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-podman.ts","test-vercel":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-vercel.ts","test-interactive":"npm run build && tsx --env-file=.sandcastle/.env .sandcastle/test-interactive.ts"},"keywords":["cli","sandbox","docker","ai","agent"],"packageManager":"npm@10.9.2","repository":{"type":"git","url":"git+https://github.com/mattpocock/sandcastle.git"},"license":"MIT","devDependencies":{"@changesets/cli":"^2.30.0","@effect/vitest":"^0.28.0","@types/node":"^25.5.0","@typescript/native-preview":"^7.0.0-dev.20260317.1","husky":"^9.1.7","lint-staged":"^15.5.1","prettier":"^3.5.3","tsx":"^4.21.0","vitest":"^3.2.0"},"dependencies":{"@clack/prompts":"^1.1.0","@effect/cli":"^0.74.0","@effect/platform":"^0.95.0","@effect/platform-node":"^0.105.0","@effect/printer":"^0.48.0","@effect/printer-ansi":"^0.48.0","effect":"^3.20.0"},"peerDependencies":{"@vercel/sandbox":">=1.0.0","@daytona/sdk":"^0.164.0"},"peerDependenciesMeta":{"@vercel/sandbox":{"optional":true},"@daytona/sdk":{"optional":true}},"lint-staged":{"*.{ts,tsx,js,jsx,json,md}":"prettier --write"},"gitHead":"9100690b0dc5a181fd5ef0f5251c91be4a8fb874","_id":"@ai-hero/sandcastle@0.5.10","bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"homepage":"https://github.com/mattpocock/sandcastle#readme","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-6nEUfWA0W5fRxEgyPrqUqqJyBsniNSM2ABKo8+5fKZ9yeBStqz7CWn0jG7HzNYa4AB5yVHKFZg5yW5kZUSbSog==","shasum":"2d40b99b672e123ce951008a9af53cf38ab1b034","tarball":"https://registry.npmjs.org/@ai-hero/sandcastle/-/sandcastle-0.5.10.tgz","fileCount":230,"unpackedSize":850484,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-hero%2fsandcastle@0.5.10","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCkg1hmoBZlEH0GrikKyV5J/X2z29vnLCwgHZQauSZnnwIhAN8j5fcKvUJRTkZgX9VgYswNK6HdjH7ZLHtwCIi6pWhK"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:634e1010-beee-470b-bdce-16017f32690f"}},"directories":{},"maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sandcastle_0.5.10_1778227860880_0.2120173447978848"},"_hasShrinkwrap":false}},"time":{"created":"2026-03-26T07:43:21.900Z","modified":"2026-05-08T08:11:01.948Z","0.0.1":"2026-03-26T07:43:22.162Z","0.1.0":"2026-03-26T10:12:40.724Z","0.1.4":"2026-03-26T11:34:09.459Z","0.1.5":"2026-03-26T20:59:49.371Z","0.1.6":"2026-03-26T21:07:26.906Z","0.1.7":"2026-04-01T13:42:41.683Z","0.1.8":"2026-04-01T15:08:36.159Z","0.2.0":"2026-04-02T11:31:41.887Z","0.2.1":"2026-04-03T09:45:57.637Z","0.2.2":"2026-04-05T12:09:59.841Z","0.2.3":"2026-04-05T12:41:48.158Z","0.2.4":"2026-04-10T08:14:59.550Z","0.3.0":"2026-04-10T13:31:20.574Z","0.4.0":"2026-04-11T08:06:20.257Z","0.4.1":"2026-04-13T19:21:48.952Z","0.4.2":"2026-04-13T20:12:31.584Z","0.4.3":"2026-04-14T06:39:14.950Z","0.4.4":"2026-04-14T08:41:54.268Z","0.4.5":"2026-04-14T15:51:55.904Z","0.4.6":"2026-04-15T10:07:23.216Z","0.4.7":"2026-04-15T10:13:38.871Z","0.4.8":"2026-04-17T12:11:37.173Z","0.5.0":"2026-04-21T17:14:35.559Z","0.5.1":"2026-04-21T19:43:04.611Z","0.5.4":"2026-04-24T19:25:42.148Z","0.5.5":"2026-04-27T08:03:12.557Z","0.5.6":"2026-04-29T20:22:47.777Z","0.5.7":"2026-05-01T13:15:53.309Z","0.5.8":"2026-05-06T13:18:54.744Z","0.5.10":"2026-05-08T08:11:01.507Z"},"bugs":{"url":"https://github.com/mattpocock/sandcastle/issues"},"license":"MIT","homepage":"https://github.com/mattpocock/sandcastle#readme","keywords":["cli","sandbox","docker","ai","agent"],"repository":{"type":"git","url":"git+https://github.com/mattpocock/sandcastle.git"},"description":"CLI for orchestrating AI agents in isolated sandbox environments","maintainers":[{"name":"mpocock","email":"mpocock@me.com"}],"readme":"<div align=\"center\">\n  <picture>\n    <source media=\"(prefers-color-scheme: dark)\" srcset=\"https://res.cloudinary.com/total-typescript/image/upload/v1775033787/readme-sandcastle-ondark_2x.png\">\n    <source media=\"(prefers-color-scheme: light)\" srcset=\"https://res.cloudinary.com/total-typescript/image/upload/v1775033787/readme-sandcastle-onlight_2x.png\">\n    <img alt=\"Sandcastle\" src=\"https://res.cloudinary.com/total-typescript/image/upload/v1775033787/readme-sandcastle-onlight_2x.png\" height=\"200\" style=\"margin-bottom: 20px;\">\n  </picture>\n</div>\n\n## What Is Sandcastle?\n\nA TypeScript library for orchestrating AI coding agents in isolated sandboxes:\n\n1. You invoke agents with a single `sandcastle.run()`.\n2. Sandcastle handles sandboxing the agent with a configurable branch strategy.\n3. The commits made on the branches get merged back.\n\nSandcastle is provider-agnostic — it ships with built-in providers for Docker, Podman, and Vercel, and you can create your own. Great for parallelizing multiple AFK agents, creating review pipelines, or even just orchestrating your own agents.\n\n## Prerequisites\n\n- [Git](https://git-scm.com/)\n- A sandbox provider — Sandcastle needs an isolated environment to run agents in. Built-in options:\n  - [Docker Desktop](https://www.docker.com/) — most common for local development\n  - [Podman](https://podman.io/) — rootless alternative to Docker\n  - [Vercel](https://vercel.com/) — cloud-based Firecracker microVMs via `@vercel/sandbox`\n  - Or [create your own](#custom-sandbox-providers) using `createBindMountSandboxProvider` or `createIsolatedSandboxProvider`\n\n## Quick start\n\n1. Install the package:\n\n```bash\nnpm install --save-dev @ai-hero/sandcastle\n```\n\n2. Run `sandcastle init`. This scaffolds a `.sandcastle` directory with all the files needed.\n\n```bash\nnpx sandcastle init\n```\n\n3. Edit `.sandcastle/.env` and fill in your default values for `ANTHROPIC_API_KEY`. If you want to use your Claude subscription instead of an API key, see [#191](https://github.com/mattpocock/sandcastle/issues/191).\n\n```bash\ncp .sandcastle/.env.example .sandcastle/.env\n```\n\n4. Run the `.sandcastle/main.ts` (or `main.mts`) file with `npx tsx`\n\n```bash\nnpx tsx .sandcastle/main.ts\n```\n\n```typescript\n// 3. Run the agent via the JS API\nimport { run, claudeCode } from \"@ai-hero/sandcastle\";\nimport { docker } from \"@ai-hero/sandcastle/sandboxes/docker\";\n\nawait run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  sandbox: docker(), // or podman(), vercel(), or your own provider\n  promptFile: \".sandcastle/prompt.md\",\n});\n```\n\n## Sandbox Providers\n\nSandcastle uses a `SandboxProvider` to create isolated environments. The `sandbox` option on `run()` and `createSandbox()` accepts any provider. A no-sandbox option is also available for `interactive()` and `wt.interactive()`. Built-in providers:\n\n| Provider   | Import path                                | Type       | Accepted by                                   |\n| ---------- | ------------------------------------------ | ---------- | --------------------------------------------- |\n| Docker     | `@ai-hero/sandcastle/sandboxes/docker`     | Bind-mount | `run()`, `createSandbox()`, `interactive()`   |\n| Podman     | `@ai-hero/sandcastle/sandboxes/podman`     | Bind-mount | `run()`, `createSandbox()`, `interactive()`   |\n| Vercel     | `@ai-hero/sandcastle/sandboxes/vercel`     | Isolated   | `run()`, `createSandbox()`, `interactive()`   |\n| No-sandbox | `@ai-hero/sandcastle/sandboxes/no-sandbox` | None       | `interactive()`, `wt.interactive()` (default) |\n\nWorktree methods (`wt.run()`, `wt.interactive()`, `wt.createSandbox()`) accept the same providers as their top-level counterparts. `wt.interactive()` defaults to `noSandbox()` when no sandbox is specified.\n\n```typescript\nimport { docker } from \"@ai-hero/sandcastle/sandboxes/docker\";\nimport { podman } from \"@ai-hero/sandcastle/sandboxes/podman\";\nimport { vercel } from \"@ai-hero/sandcastle/sandboxes/vercel\";\nimport { noSandbox } from \"@ai-hero/sandcastle/sandboxes/no-sandbox\";\n\n// Docker, Podman, and Vercel are interchangeable in run() and createSandbox():\nawait run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  sandbox: docker(),\n  prompt: \"...\",\n});\n\n// No-sandbox runs the agent directly on the host — interactive() only:\nawait interactive({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  sandbox: noSandbox(),\n  prompt: \"...\", // optional — omit to launch the TUI with no initial prompt\n  cwd: \"/path/to/other-repo\", // optional — defaults to process.cwd()\n});\n```\n\nYou can also [create your own provider](#custom-sandbox-providers) using `createBindMountSandboxProvider` or `createIsolatedSandboxProvider`.\n\n## API\n\nSandcastle exports a programmatic `run()` function for use in scripts, CI pipelines, or custom tooling. The examples below use `docker()`, but any `SandboxProvider` works in its place.\n\n```typescript\nimport { run, claudeCode } from \"@ai-hero/sandcastle\";\nimport { docker } from \"@ai-hero/sandcastle/sandboxes/docker\";\n\nconst result = await run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  sandbox: docker(),\n  promptFile: \".sandcastle/prompt.md\",\n});\n\nconsole.log(result.iterations.length); // number of iterations executed\nconsole.log(result.iterations); // per-iteration results with optional sessionId\nconsole.log(result.commits); // array of { sha } for commits created\nconsole.log(result.branch); // target branch name\n```\n\n### All options\n\n```typescript\nimport { run, claudeCode } from \"@ai-hero/sandcastle\";\nimport { docker } from \"@ai-hero/sandcastle/sandboxes/docker\";\n\nconst result = await run({\n  // Agent provider — required. Pass a model string to claudeCode().\n  // Optional second arg for provider-specific options like effort level.\n  agent: claudeCode(\"claude-opus-4-6\", { effort: \"high\" }),\n\n  // Sandbox provider — required. Any SandboxProvider works (docker, podman, vercel, or custom).\n  // Provider-specific config (like imageName, mounts) lives inside the provider factory call.\n  sandbox: docker({\n    imageName: \"sandcastle:local\",\n    // Optional: override the UID/GID used for --user flag (defaults to host UID/GID).\n    // Must match the UID baked into the image. Pre-flight check catches mismatches.\n    // containerUid: 1000,\n    // containerGid: 1000,\n    // Optional: mount host directories into the sandbox (e.g. package manager caches)\n    // hostPath supports absolute, tilde-expanded (~), and relative paths (resolved from cwd).\n    // sandboxPath supports absolute and relative paths (resolved from the sandbox repo directory).\n    mounts: [\n      { hostPath: \"~/.npm\", sandboxPath: \"/home/agent/.npm\", readonly: true },\n      { hostPath: \"data\", sandboxPath: \"data\" }, // mounts <cwd>/data → <sandbox-repo>/data\n    ],\n    // Optional: SELinux volume label — \"z\" (default, shared), \"Z\" (private), or false (none).\n    // No-op on non-SELinux systems (Docker Desktop on macOS/Windows, Linux without SELinux).\n    selinuxLabel: \"z\",\n    // Optional: provider-level env vars merged at launch time\n    env: { DOCKER_SPECIFIC: \"value\" },\n    // Optional: attach container to Docker network(s) — string or string[]\n    network: \"my-network\",\n  }),\n\n  // Host repo directory — replaces process.cwd() as the anchor for\n  // .sandcastle/ artifacts (worktrees, logs, env, patches) and git operations.\n  // Relative paths resolve against process.cwd(). Defaults to process.cwd().\n  cwd: \"../other-repo\",\n\n  // Branch strategy — controls how the agent's changes relate to branches.\n  // Defaults to { type: \"head\" } for bind-mount and { type: \"merge-to-head\" } for isolated providers.\n  branchStrategy: { type: \"branch\", branch: \"agent/fix-42\" },\n\n  // Prompt source — provide one of these, not both.\n  // Note: promptFile resolves against process.cwd(), NOT cwd.\n  promptFile: \".sandcastle/prompt.md\", // path to a prompt file\n  // prompt: \"Fix issue #42 in this repo\", // OR an inline prompt string\n\n  // Values substituted for {{KEY}} placeholders in the prompt.\n  promptArgs: {\n    ISSUE_NUMBER: \"42\",\n  },\n\n  // Maximum number of agent iterations to run before stopping. Default: 1\n  maxIterations: 5,\n\n  // Display name for this run, shown as a prefix in log output.\n  name: \"fix-issue-42\",\n\n  // Lifecycle hooks grouped by where they run: host or sandbox.\n  hooks: {\n    host: {\n      onWorktreeReady: [{ command: \"cp .env.example .env\" }],\n      onSandboxReady: [{ command: \"echo setup done\" }],\n    },\n    sandbox: {\n      onSandboxReady: [{ command: \"npm install\" }],\n    },\n  },\n\n  // Host-relative file paths to copy into the sandbox before the container starts.\n  // Not supported with branchStrategy: { type: \"head\" }.\n  copyToWorktree: [\".env\"],\n\n  // Override default timeouts for built-in lifecycle steps.\n  // Unset keys keep their defaults.\n  timeouts: {\n    copyToWorktreeMs: 120_000, // default: 60_000\n  },\n\n  // How to record progress. Default: write to a file under .sandcastle/logs/\n  logging: {\n    type: \"file\",\n    path: \".sandcastle/logs/my-run.log\",\n    // Optional: forward the agent's output stream to your own observability system.\n    // Fires for each text chunk and tool call the agent produces. Errors thrown\n    // by the callback are swallowed so a broken forwarder cannot kill the run.\n    onAgentStreamEvent: (event) => {\n      // event is { type: \"text\" | \"toolCall\", iteration, timestamp, ... }\n      myLogger.info(event);\n    },\n  },\n  // logging: { type: \"stdout\" }, // OR render an interactive UI in the terminal\n\n  // String (or array of strings) the agent emits to end the iteration loop early.\n  // Default: \"<promise>COMPLETE</promise>\"\n  completionSignal: \"<promise>COMPLETE</promise>\",\n\n  // Idle timeout in seconds — resets whenever the agent produces output. Default: 600 (10 minutes)\n  idleTimeoutSeconds: 600,\n\n  // Structured output — extract a typed payload from the agent's stdout.\n  // Requires maxIterations === 1 and the tag must appear in the prompt.\n  // output: Output.object({ tag: \"result\", schema: z.object({ answer: z.number() }) }),\n  // output: Output.string({ tag: \"summary\" }),\n});\n\nconsole.log(result.iterations.length); // number of iterations executed\nconsole.log(result.completionSignal); // matched signal string, or undefined if none fired\nconsole.log(result.commits); // array of { sha } for commits created\nconsole.log(result.branch); // target branch name\n```\n\n### `createSandbox()` — reusable sandbox\n\nUse `createSandbox()` when you need to run multiple agents (or multiple rounds of the same agent) inside a single sandbox. It creates the sandbox once, and you call `sandbox.run()` as many times as you need. This avoids repeated container startup costs and keeps all runs on the same branch.\n\nUse `run()` instead when you only need a single one-shot invocation — it handles sandbox lifecycle automatically.\n\n#### Basic single-run usage\n\n```typescript\nimport { createSandbox, claudeCode } from \"@ai-hero/sandcastle\";\nimport { docker } from \"@ai-hero/sandcastle/sandboxes/docker\";\n\nawait using sandbox = await createSandbox({\n  branch: \"agent/fix-42\",\n  sandbox: docker(),\n});\n\nconst result = await sandbox.run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  prompt: \"Fix issue #42 in this repo.\",\n});\n\nconsole.log(result.commits); // [{ sha: \"abc123\" }]\n```\n\n#### Multi-run implement-then-review\n\n```typescript\nimport { createSandbox, claudeCode } from \"@ai-hero/sandcastle\";\nimport { docker } from \"@ai-hero/sandcastle/sandboxes/docker\";\n\nawait using sandbox = await createSandbox({\n  branch: \"agent/fix-42\",\n  sandbox: docker(),\n  hooks: { sandbox: { onSandboxReady: [{ command: \"npm install\" }] } },\n});\n\n// Step 1: implement\nconst implResult = await sandbox.run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  promptFile: \".sandcastle/implement.md\",\n  maxIterations: 5,\n});\n\n// Step 2: review on the same branch, same container\nconst reviewResult = await sandbox.run({\n  agent: claudeCode(\"claude-sonnet-4-6\"),\n  prompt: \"Review the changes and fix any issues.\",\n});\n```\n\nCommits from all `run()` calls accumulate on the same branch. The sandbox container stays alive between runs, so installed dependencies and build artifacts persist.\n\n#### Automatic cleanup with `await using`\n\n`await using` calls `sandbox.close()` automatically when the block exits. If the sandbox has uncommitted changes, the worktree is preserved on disk; if clean, both container and worktree are removed.\n\n#### Manual `close()` with `CloseResult`\n\n```typescript\nconst sandbox = await createSandbox({\n  branch: \"agent/fix-42\",\n  sandbox: docker(),\n});\n// ... run agents ...\nconst closeResult = await sandbox.close();\nif (closeResult.preservedWorktreePath) {\n  console.log(`Worktree preserved at ${closeResult.preservedWorktreePath}`);\n}\n```\n\n#### `CreateSandboxOptions`\n\n| Option           | Type            | Default         | Description                                                          |\n| ---------------- | --------------- | --------------- | -------------------------------------------------------------------- |\n| `branch`         | string          | —               | **Required.** Explicit branch for the sandbox                        |\n| `sandbox`        | SandboxProvider | —               | **Required.** Sandbox provider (e.g. `docker()`, `podman()`)         |\n| `cwd`            | string          | `process.cwd()` | Host repo directory — relative paths resolve against `process.cwd()` |\n| `hooks`          | SandboxHooks    | —               | Lifecycle hooks (`host.*`, `sandbox.*`) — run once at creation time  |\n| `copyToWorktree` | string[]        | —               | Host-relative file paths to copy into the sandbox at creation time   |\n| `timeouts`       | Timeouts        | —               | Override default timeouts (e.g. `{ copyToWorktreeMs: 120_000 }`)     |\n\n#### `Sandbox`\n\n| Property / Method       | Type                                                               | Description                                  |\n| ----------------------- | ------------------------------------------------------------------ | -------------------------------------------- |\n| `branch`                | string                                                             | The branch the sandbox is on                 |\n| `worktreePath`          | string                                                             | Host path to the worktree                    |\n| `run(options)`          | `(SandboxRunOptions) => Promise<SandboxRunResult>`                 | Invoke an agent inside the existing sandbox  |\n| `interactive(options)`  | `(SandboxInteractiveOptions) => Promise<SandboxInteractiveResult>` | Launch an interactive session in the sandbox |\n| `close()`               | `() => Promise<CloseResult>`                                       | Tear down the container and sandbox          |\n| `[Symbol.asyncDispose]` | `() => Promise<void>`                                              | Auto teardown via `await using`              |\n\n#### `SandboxRunOptions`\n\n| Option               | Type               | Default                       | Description                                                         |\n| -------------------- | ------------------ | ----------------------------- | ------------------------------------------------------------------- |\n| `agent`              | AgentProvider      | —                             | **Required.** Agent provider (e.g. `claudeCode(\"claude-opus-4-6\")`) |\n| `prompt`             | string             | —                             | Inline prompt (mutually exclusive with `promptFile`)                |\n| `promptFile`         | string             | —                             | Path to prompt file (mutually exclusive with `prompt`)              |\n| `promptArgs`         | PromptArgs         | —                             | Key-value map for `{{KEY}}` placeholder substitution                |\n| `maxIterations`      | number             | `1`                           | Maximum iterations to run                                           |\n| `completionSignal`   | string \\| string[] | `<promise>COMPLETE</promise>` | String(s) the agent emits to stop the iteration loop early          |\n| `idleTimeoutSeconds` | number             | `600`                         | Idle timeout in seconds — resets on each agent output event         |\n| `name`               | string             | —                             | Display name for the run                                            |\n| `logging`            | object             | file (auto-generated)         | `{ type: 'file', path }` or `{ type: 'stdout' }`                    |\n| `signal`             | AbortSignal        | —                             | Cancels the run when aborted; handle stays usable afterward         |\n\n#### `SandboxRunResult`\n\n| Field              | Type                | Description                                                        |\n| ------------------ | ------------------- | ------------------------------------------------------------------ |\n| `iterations`       | `IterationResult[]` | Per-iteration results (use `.length` for the count)                |\n| `completionSignal` | string?             | The matched completion signal string, or `undefined` if none fired |\n| `stdout`           | string              | Combined agent output from all iterations                          |\n| `commits`          | `{ sha }[]`         | Commits created during the run                                     |\n| `logFilePath`      | string?             | Path to the log file (only when logging to a file)                 |\n\n#### `CloseResult`\n\n| Field                   | Type    | Description                                                              |\n| ----------------------- | ------- | ------------------------------------------------------------------------ |\n| `preservedWorktreePath` | string? | Host path to the preserved worktree, set when it had uncommitted changes |\n\n### `createWorktree()` — independent worktree lifecycle\n\nUse `createWorktree()` when you need a worktree (git worktree) as an independent, first-class concept — separate from any sandbox. This is useful when you want to run an interactive session first and then hand the same worktree to a sandboxed AFK agent.\n\nOnly `branch` and `merge-to-head` strategies are accepted; `head` is a compile-time type error since it means no worktree.\n\nPass `cwd` to target a repo other than `process.cwd()`. Relative paths resolve against `process.cwd()`; absolute paths pass through. A `CwdError` is thrown if the path does not exist or is not a directory.\n\n```typescript\nimport { createWorktree } from \"@ai-hero/sandcastle\";\n\nawait using wt = await createWorktree({\n  branchStrategy: { type: \"branch\", branch: \"agent/fix-42\" },\n  copyToWorktree: [\"node_modules\"],\n  cwd: \"/path/to/other-repo\", // optional — defaults to process.cwd()\n});\n\nconsole.log(wt.worktreePath); // host path to the worktree\nconsole.log(wt.branch); // \"agent/fix-42\"\n\n// Run an interactive session in the worktree (defaults to noSandbox)\nawait wt.interactive({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  prompt: \"Explore the codebase and understand the bug.\",\n});\n\n// Run an AFK agent in the worktree (sandbox is required)\nconst result = await wt.run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  sandbox: docker({ imageName: \"sandcastle:myrepo\" }),\n  prompt: \"Fix issue #42.\",\n  maxIterations: 3,\n});\nconsole.log(result.commits); // commits made during the run\n\n// Create a long-lived sandbox from the worktree\nimport { docker } from \"@ai-hero/sandcastle/sandboxes/docker\";\n\nawait using sandbox = await wt.createSandbox({\n  sandbox: docker(),\n  hooks: { sandbox: { onSandboxReady: [{ command: \"npm install\" }] } },\n});\n\n// sandbox.close() tears down the container only — the worktree stays\nawait sandbox.close();\n\n// wt.close() cleans up the worktree\n```\n\n`wt.close()` checks for uncommitted changes: if the worktree is dirty, it's preserved on disk; if clean, it's removed. `await using` calls `close()` automatically. The worktree persists after `run()`, `interactive()`, and `createSandbox()` complete, so you can hand it to another agent or inspect it.\n\n**Split ownership**: When a sandbox is created via `wt.createSandbox()`, `sandbox.close()` tears down the container only — the worktree remains. `wt.close()` is responsible for worktree cleanup. This differs from the top-level `createSandbox()`, where `sandbox.close()` owns both container and worktree.\n\n#### `CreateWorktreeOptions`\n\n| Option           | Type                   | Default | Description                                                               |\n| ---------------- | ---------------------- | ------- | ------------------------------------------------------------------------- |\n| `branchStrategy` | WorktreeBranchStrategy | —       | **Required.** `{ type: \"branch\", branch }` or `{ type: \"merge-to-head\" }` |\n| `copyToWorktree` | string[]               | —       | Host-relative file paths to copy into the worktree at creation time       |\n| `timeouts`       | Timeouts               | —       | Override default timeouts (e.g. `{ copyToWorktreeMs: 120_000 }`)          |\n\n#### `Worktree`\n\n| Property / Method        | Type                                                                  | Description                                         |\n| ------------------------ | --------------------------------------------------------------------- | --------------------------------------------------- |\n| `branch`                 | string                                                                | The branch the worktree is on                       |\n| `worktreePath`           | string                                                                | Host path to the worktree                           |\n| `run(options)`           | `(options: WorktreeRunOptions) => Promise<WorktreeRunResult>`         | Run an AFK agent in the worktree (sandbox required) |\n| `interactive(options)`   | `(options: WorktreeInteractiveOptions) => Promise<InteractiveResult>` | Run an interactive agent session in the worktree    |\n| `createSandbox(options)` | `(options: WorktreeCreateSandboxOptions) => Promise<Sandbox>`         | Create a long-lived sandbox backed by this worktree |\n| `close()`                | `() => Promise<CloseResult>`                                          | Clean up the worktree (preserves if dirty)          |\n| `[Symbol.asyncDispose]`  | `() => Promise<void>`                                                 | Auto cleanup via `await using`                      |\n\n#### `WorktreeInteractiveOptions`\n\n| Option       | Type                   | Default       | Description                                                                                       |\n| ------------ | ---------------------- | ------------- | ------------------------------------------------------------------------------------------------- |\n| `agent`      | AgentProvider          | —             | **Required.** Agent provider                                                                      |\n| `sandbox`    | AnySandboxProvider     | `noSandbox()` | Sandbox provider (defaults to no sandbox)                                                         |\n| `prompt`     | string                 | —             | Inline prompt (mutually exclusive with `promptFile`)                                              |\n| `promptFile` | string                 | —             | Path to prompt file                                                                               |\n| `name`       | string                 | —             | Optional session name                                                                             |\n| `hooks`      | SandboxHooks           | —             | Lifecycle hooks (`host.*`, `sandbox.*`)                                                           |\n| `promptArgs` | PromptArgs             | —             | Key-value map for `{{KEY}}` placeholder substitution                                              |\n| `env`        | Record<string, string> | —             | Environment variables to inject into the sandbox                                                  |\n| `signal`     | AbortSignal            | —             | Cancel the session when aborted. The worktree is preserved on disk. Rejects with `signal.reason`. |\n\n#### `WorktreeRunOptions`\n\n| Option               | Type                   | Default | Description                                                                                                                         |\n| -------------------- | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------- |\n| `agent`              | AgentProvider          | —       | **Required.** Agent provider                                                                                                        |\n| `sandbox`            | SandboxProvider        | —       | **Required.** Sandbox provider (AFK agents must be sandboxed)                                                                       |\n| `prompt`             | string                 | —       | Inline prompt (mutually exclusive with `promptFile`)                                                                                |\n| `promptFile`         | string                 | —       | Path to prompt file                                                                                                                 |\n| `maxIterations`      | number                 | 1       | Maximum iterations to run                                                                                                           |\n| `completionSignal`   | string \\| string[]     | —       | Substring(s) to stop the iteration loop early                                                                                       |\n| `idleTimeoutSeconds` | number                 | 600     | Idle timeout in seconds                                                                                                             |\n| `name`               | string                 | —       | Optional run name                                                                                                                   |\n| `logging`            | LoggingOption          | file    | Logging mode                                                                                                                        |\n| `hooks`              | SandboxHooks           | —       | Lifecycle hooks (`host.*`, `sandbox.*`)                                                                                             |\n| `promptArgs`         | PromptArgs             | —       | Key-value map for `{{KEY}}` placeholder substitution                                                                                |\n| `env`                | Record<string, string> | —       | Environment variables to inject into the sandbox                                                                                    |\n| `resumeSession`      | string                 | —       | Resume a prior Claude Code session by ID. Incompatible with `maxIterations > 1`. Session file must exist on host.                   |\n| `signal`             | AbortSignal            | —       | Cancel the run when aborted. Kills the in-flight agent subprocess; the worktree is preserved on disk. Rejects with `signal.reason`. |\n\n#### `WorktreeRunResult`\n\n| Property           | Type                | Description                                            |\n| ------------------ | ------------------- | ------------------------------------------------------ |\n| `iterations`       | `IterationResult[]` | Per-iteration results (use `.length` for the count)    |\n| `completionSignal` | string              | The matched completion signal, or undefined            |\n| `stdout`           | string              | Combined stdout output from all agent iterations       |\n| `commits`          | { sha: string }[]   | List of commits made by the agent during the run       |\n| `branch`           | string              | The branch name the agent worked on                    |\n| `logFilePath`      | string              | Path to the log file, if logging was drained to a file |\n\n#### `WorktreeCreateSandboxOptions`\n\n| Option           | Type            | Default | Description                                                         |\n| ---------------- | --------------- | ------- | ------------------------------------------------------------------- |\n| `sandbox`        | SandboxProvider | —       | **Required.** Sandbox provider (e.g. `docker()`)                    |\n| `hooks`          | SandboxHooks    | —       | Lifecycle hooks (`host.*`, `sandbox.*`)                             |\n| `copyToWorktree` | string[]        | —       | Host-relative file paths to copy into the worktree at creation time |\n| `timeouts`       | Timeouts        | —       | Override default timeouts (e.g. `{ copyToWorktreeMs: 120_000 }`)    |\n\n## How it works\n\nSandcastle uses a **branch strategy** configured on the sandbox provider to control how the agent's changes relate to branches. There are three strategies:\n\n- **Head** (`{ type: \"head\" }`) — The agent writes directly to the host working directory. No worktree, no branch indirection. This is the default for bind-mount providers like `docker()`.\n- **Merge-to-head** (`{ type: \"merge-to-head\" }`) — Sandcastle creates a temporary branch in a git worktree. The agent works on the temp branch, and changes are merged back to HEAD when done. The temp branch is cleaned up after merge.\n- **Branch** (`{ type: \"branch\", branch: \"foo\" }`) — Commits land on an explicitly named branch in a git worktree.\n\nFor bind-mount providers (like Docker), the worktree directory is bind-mounted into the container — the agent writes directly to the host filesystem through the mount, so no sync is needed.\n\nFrom your point of view, you just configure `branchStrategy: { type: 'branch', branch: 'foo' }` on `run()`, and get a commit on branch `foo` once it's complete. All 100% local.\n\n## Prompts\n\nSandcastle uses a flexible prompt system. You write the prompt, and the engine executes it — no opinions about workflow, task management, or context sources are imposed.\n\n### Prompt resolution\n\nYou must provide exactly one of:\n\n1. `prompt: \"inline string\"` — pass an inline prompt directly via `RunOptions`\n2. `promptFile: \"./path/to/prompt.md\"` — point to a specific file via `RunOptions`\n\n`prompt` and `promptFile` are mutually exclusive — providing both is an error. If neither is provided, `run()` throws an error asking you to supply one.\n\n**Inline prompts (`prompt: \"...\"`) are passed to the agent literally.** No `{{KEY}}` substitution, no `` !`command` `` expansion, no built-in `{{SOURCE_BRANCH}}` / `{{TARGET_BRANCH}}` injection. If you need values interpolated into an inline prompt, build the string in JavaScript (`` `Work on ${branch}…` ``). Passing `promptArgs` alongside an inline prompt is an error — switch to `promptFile` to use substitution.\n\nThe substitution and expansion features below apply **only** to prompts sourced from `promptFile`.\n\n> **Convention**: `sandcastle init` scaffolds `.sandcastle/prompt.md` and all templates explicitly reference it via `promptFile: \".sandcastle/prompt.md\"`. This is a convention, not an automatic fallback — Sandcastle does not read `.sandcastle/prompt.md` unless you pass it as `promptFile`.\n\n### Dynamic context with `` !`command` ``\n\nUse `` !`command` `` expressions in your prompt to pull in dynamic context. Each expression is replaced with the command's stdout before the prompt is sent to the agent. All expressions in a prompt run **in parallel** for faster expansion.\n\nCommands run **inside the sandbox** after `sandbox.onSandboxReady` hooks complete, so they see the same repo state the agent sees (including installed dependencies).\n\n```markdown\n# Open issues\n\n!`gh issue list --state open --label Sandcastle --json number,title,body,comments,labels --limit 20`\n\n# Recent commits\n\n!`git log --oneline -10`\n```\n\nIf any command exits with a non-zero code, the run fails immediately with an error.\n\n### Prompt arguments with `{{KEY}}`\n\nUse `{{KEY}}` placeholders in your prompt to inject values from the `promptArgs` option. This is useful for reusing the same prompt file across multiple runs with different parameters.\n\n```typescript\nimport { run } from \"@ai-hero/sandcastle\";\n\nawait run({\n  promptFile: \"./my-prompt.md\",\n  promptArgs: { ISSUE_NUMBER: 42, PRIORITY: \"high\" },\n});\n```\n\nIn the prompt file:\n\n```markdown\nWork on issue #{{ISSUE_NUMBER}} (priority: {{PRIORITY}}).\n```\n\nPrompt argument substitution runs on the host before shell expression expansion, so `{{KEY}}` placeholders inside `` !`command` `` expressions are replaced first:\n\n```markdown\n!`gh issue view {{ISSUE_NUMBER}} --json body -q .body`\n```\n\nA `{{KEY}}` placeholder with no matching prompt argument is an error. Unused prompt arguments produce a warning.\n\n`` !`command` `` expansion only runs on shell blocks written in the prompt file itself. Any `` !`…` `` pattern that appears inside an argument value is treated as inert text — it won't be executed against the host shell. This makes it safe to pass user-authored content (issue titles, PR descriptions, docs excerpts) through `promptArgs`.\n\n### Built-in prompt arguments\n\nSandcastle automatically injects two built-in prompt arguments into every prompt:\n\n| Placeholder         | Value                                                             |\n| ------------------- | ----------------------------------------------------------------- |\n| `{{SOURCE_BRANCH}}` | The branch the agent works on (determined by the branch strategy) |\n| `{{TARGET_BRANCH}}` | The host's active branch at `run()` time                          |\n\nUse them in your prompt without passing them via `promptArgs`:\n\n```markdown\nYou are working on {{SOURCE_BRANCH}}. When diffing, compare against {{TARGET_BRANCH}}.\n```\n\nPassing `SOURCE_BRANCH` or `TARGET_BRANCH` in `promptArgs` is an error — built-in prompt arguments cannot be overridden.\n\n### Early termination with `<promise>COMPLETE</promise>`\n\nWhen the agent outputs `<promise>COMPLETE</promise>`, the orchestrator stops the iteration loop early. This is a convention you document in your prompt for the agent to follow — the engine never injects it.\n\nThis is useful for task-based workflows where the agent should stop once it has finished, rather than running all remaining iterations.\n\nYou can override the default signal by passing `completionSignal` to `run()`. It accepts a single string or an array of strings:\n\n```ts\nawait run({\n  // ...\n  completionSignal: \"DONE\",\n});\n\n// Or pass multiple signals — the loop stops on the first match:\nawait run({\n  // ...\n  completionSignal: [\"TASK_COMPLETE\", \"TASK_ABORTED\"],\n});\n```\n\nTell the agent to output your chosen string(s) in the prompt, and the orchestrator will stop when it detects any of them. The matched signal is returned as `result.completionSignal`.\n\n### Structured output\n\nUse `Output.object()` to extract a typed, schema-validated JSON payload from the agent's stdout. The agent emits its answer inside an XML tag you specify, and Sandcastle parses, validates, and returns it on `result.output`. See [ADR 0010](docs/adr/0010-structured-output.md) for design rationale.\n\n```ts\nimport { run, Output, claudeCode } from \"@ai-hero/sandcastle\";\nimport { docker } from \"@ai-hero/sandcastle/sandboxes/docker\";\nimport { z } from \"zod\";\n\nconst result = await run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  sandbox: docker(),\n  prompt: `Analyze the code, and output the result as JSON inside <result> tags.\n    The result must match this schema:\n    { summary: string; score: string }\n  `,\n  output: Output.object({\n    tag: \"result\",\n    schema: z.object({ summary: z.string(), score: z.number() }),\n  }),\n});\n\nconsole.log(result.output.summary); // typed as string\nconsole.log(result.output.score); // typed as number\n```\n\n`Output.string({ tag })` extracts the tag contents as a plain string (trimmed, no JSON parsing). Both helpers require `maxIterations` to be `1` (the default). The resolved prompt must contain the configured opening tag literal.\n\n### Templates\n\n`sandcastle init` prompts you to choose a sandbox provider (Docker or Podman), a backlog manager (GitHub Issues or Beads), and a template, which scaffolds a ready-to-use prompt and `main.mts` suited to a specific workflow. If your project's `package.json` has `\"type\": \"module\"`, the file will be named `main.ts` instead. Five templates are available:\n\n| Template                       | Description                                                               |\n| ------------------------------ | ------------------------------------------------------------------------- |\n| `blank`                        | Bare scaffold — write your own prompt and orchestration                   |\n| `simple-loop`                  | Picks issues one by one and closes them                                   |\n| `sequential-reviewer`          | Implements issues one by one, with a code review step after each          |\n| `parallel-planner`             | Plans parallelizable issues, executes on separate branches, then merges   |\n| `parallel-planner-with-review` | Plans parallelizable issues, executes with per-branch review, then merges |\n\nSelect a template during `sandcastle init` when prompted, or re-run init in a fresh repo to try a different one.\n\n## CLI commands\n\n### `sandcastle init`\n\nScaffolds the `.sandcastle/` config directory and builds the container image. This is the first command you run in a new repo. You choose a sandbox provider (Docker or Podman) during init — selecting Podman writes a `Containerfile` instead of `Dockerfile` and uses `sandcastle podman build-image` for the build step.\n\n| Option         | Required | Default                      | Description                                                          |\n| -------------- | -------- | ---------------------------- | -------------------------------------------------------------------- |\n| `--image-name` | No       | `sandcastle:<repo-dir-name>` | Docker image name                                                    |\n| `--agent`      | No       | Interactive prompt           | Agent to use (`claude-code`, `pi`, `codex`, `opencode`)              |\n| `--model`      | No       | Agent's default model        | Model to use (e.g. `claude-sonnet-4-6`). Defaults to agent's default |\n| `--template`   | No       | Interactive prompt           | Template to scaffold (e.g. `blank`, `simple-loop`)                   |\n\nCreates the following files:\n\n```\n.sandcastle/\n├── Dockerfile      # Sandbox environment (customize as needed)\n├── prompt.md       # Agent instructions\n├── .env.example    # Token placeholders\n└── .gitignore      # Ignores .env, logs/\n```\n\nErrors if `.sandcastle/` already exists to prevent overwriting customizations.\n\n### `sandcastle docker build-image`\n\nRebuilds the Docker image from an existing `.sandcastle/` directory. Use this after modifying the Dockerfile. On Linux/macOS, the build automatically passes `--build-arg AGENT_UID=$(id -u)` and `AGENT_GID=$(id -g)` so the image's `agent` user matches the host UID — this prevents permission errors on image-built files without runtime chown.\n\n| Option         | Required | Default                      | Description                                                                       |\n| -------------- | -------- | ---------------------------- | --------------------------------------------------------------------------------- |\n| `--image-name` | No       | `sandcastle:<repo-dir-name>` | Docker image name                                                                 |\n| `--dockerfile` | No       | —                            | Path to a custom Dockerfile (build context will be the current working directory) |\n\n### `sandcastle docker remove-image`\n\nRemoves the Docker image.\n\n| Option         | Required | Default                      | Description       |\n| -------------- | -------- | ---------------------------- | ----------------- |\n| `--image-name` | No       | `sandcastle:<repo-dir-name>` | Docker image name |\n\n### `sandcastle podman build-image`\n\nBuilds the Podman image from an existing `.sandcastle/` directory. Use this after modifying the Containerfile.\n\n| Option            | Required | Default                      | Description                                                                          |\n| ----------------- | -------- | ---------------------------- | ------------------------------------------------------------------------------------ |\n| `--image-name`    | No       | `sandcastle:<repo-dir-name>` | Podman image name                                                                    |\n| `--containerfile` | No       | —                            | Path to a custom Containerfile (build context will be the current working directory) |\n\n### `sandcastle podman remove-image`\n\nRemoves the Podman image.\n\n| Option         | Required | Default                      | Description       |\n| -------------- | -------- | ---------------------------- | ----------------- |\n| `--image-name` | No       | `sandcastle:<repo-dir-name>` | Podman image name |\n\n### `RunOptions`\n\n| Option               | Type               | Default                       | Description                                                                                                                                                     |\n| -------------------- | ------------------ | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `agent`              | AgentProvider      | —                             | **Required.** Agent provider (e.g. `claudeCode(\"claude-opus-4-6\")`, `pi(\"claude-sonnet-4-6\")`, `codex(\"gpt-5.4-mini\")`, `opencode(\"opencode/big-pickle\")`)      |\n| `sandbox`            | SandboxProvider    | —                             | **Required.** Sandbox provider (e.g. `docker()`, `podman()`, `docker({ imageName: \"sandcastle:local\" })`)                                                       |\n| `cwd`                | string             | `process.cwd()`               | Host repo directory — anchor for `.sandcastle/` artifacts and git operations. Relative paths resolve against `process.cwd()`.                                   |\n| `prompt`             | string             | —                             | Inline prompt (mutually exclusive with `promptFile`)                                                                                                            |\n| `promptFile`         | string             | —                             | Path to prompt file (mutually exclusive with `prompt`). Resolves against `process.cwd()`, **not** `cwd`.                                                        |\n| `maxIterations`      | number             | `1`                           | Maximum iterations to run                                                                                                                                       |\n| `hooks`              | SandboxHooks       | —                             | Lifecycle hooks (`host.*`, `sandbox.*`)                                                                                                                         |\n| `name`               | string             | —                             | Display name for the run, shown as a prefix in log output                                                                                                       |\n| `promptArgs`         | PromptArgs         | —                             | Key-value map for `{{KEY}}` placeholder substitution                                                                                                            |\n| `branchStrategy`     | BranchStrategy     | per-provider default          | Branch strategy: `{ type: 'head' }`, `{ type: 'merge-to-head' }`, or `{ type: 'branch', branch: '…' }`                                                          |\n| `copyToWorktree`     | string[]           | —                             | Host-relative file paths to copy into the sandbox before start (not supported with `branchStrategy: { type: 'head' }`)                                          |\n| `logging`            | object             | file (auto-generated)         | `{ type: 'file', path }` or `{ type: 'stdout' }`                                                                                                                |\n| `completionSignal`   | string \\| string[] | `<promise>COMPLETE</promise>` | String or array of strings the agent emits to stop the iteration loop early                                                                                     |\n| `idleTimeoutSeconds` | number             | `600`                         | Idle timeout in seconds — resets on each agent output event                                                                                                     |\n| `resumeSession`      | string             | —                             | Resume a prior Claude Code session by ID. Incompatible with `maxIterations > 1`. Session file must exist on host.                                               |\n| `signal`             | AbortSignal        | —                             | Cancel the run when aborted. Kills the in-flight agent subprocess and cancels lifecycle hooks; the worktree is preserved on disk. Rejects with `signal.reason`. |\n| `timeouts`           | Timeouts           | —                             | Override default timeouts for built-in lifecycle steps. Currently supports `{ copyToWorktreeMs?: number }` (default: 60 000).                                   |\n| `output`             | OutputDefinition   | —                             | Structured output definition (`Output.object(…)` or `Output.string(…)`). Requires `maxIterations === 1`. See [Structured output](#structured-output).           |\n\n### `RunResult`\n\n| Field              | Type                | Description                                                        |\n| ------------------ | ------------------- | ------------------------------------------------------------------ |\n| `iterations`       | `IterationResult[]` | Per-iteration results (use `.length` for the count)                |\n| `completionSignal` | string?             | The matched completion signal string, or `undefined` if none fired |\n| `stdout`           | string              | Agent output                                                       |\n| `commits`          | `{ sha }[]`         | Commits created during the run                                     |\n| `branch`           | string              | Target branch name                                                 |\n| `logFilePath`      | string?             | Path to the log file (only when logging to a file)                 |\n| `output`           | T?                  | Typed structured output (only present when `output` option is set) |\n\n### `IterationResult`\n\n| Field             | Type              | Description                                                                                                                         |\n| ----------------- | ----------------- | ----------------------------------------------------------------------------------------------------------------------------------- |\n| `sessionId`       | string?           | Claude Code session ID from the init line, or `undefined` for non-Claude agents                                                     |\n| `sessionFilePath` | string?           | Absolute host path to the captured session JSONL, or `undefined` when capture is off                                                |\n| `usage`           | `IterationUsage`? | Token usage snapshot from the last assistant message, or `undefined` when capture is off or provider does not support usage parsing |\n\n### `IterationUsage`\n\n| Field                      | Type   | Description                                |\n| -------------------------- | ------ | ------------------------------------------ |\n| `inputTokens`              | number | Input tokens consumed                      |\n| `cacheCreationInputTokens` | number | Tokens used to create prompt cache entries |\n| `cacheReadInputTokens`     | number | Tokens read from prompt cache              |\n| `outputTokens`             | number | Output tokens generated                    |\n\n### Session capture\n\nAfter each Claude Code iteration, Sandcastle automatically captures the agent's session JSONL from the sandbox to the host at `~/.claude/projects/<encoded-path>/sessions/<session-id>.jsonl`. The `cwd` fields inside each JSONL entry are rewritten to match the host repo root, so `claude --resume` works natively.\n\nSession capture is enabled by default for `claudeCode()` and can be opted out via `captureSessions: false`. Non-Claude agent providers never attempt capture. Capture failure fails the run.\n\n### Session resume\n\nPass `resumeSession` to `run()` to continue a prior Claude Code conversation inside a new sandbox:\n\n```typescript\nconst result = await run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  sandbox: docker(),\n  prompt: \"Continue where you left off\",\n  resumeSession: \"abc-123-def\",\n});\n```\n\nBefore the sandbox starts, Sandcastle validates that the session file exists on the host and transfers it into the sandbox with `cwd` fields rewritten to match the sandbox-side path. The Claude Code agent receives `--resume <id>` on its print command for iteration 1.\n\nConstraints:\n\n- `resumeSession` is incompatible with `maxIterations > 1` (throws before sandbox creation).\n- The session file must exist at `~/.claude/projects/<encoded-path>/sessions/<id>.jsonl` (throws before sandbox creation).\n- Only iteration 1 receives the resume flag; subsequent iterations (if any) start fresh.\n- Non-Claude agent providers ignore `resumeSession`.\n\n### `ClaudeCodeOptions`\n\nThe `claudeCode()` factory accepts an optional second argument for provider-specific options:\n\n```typescript\nagent: claudeCode(\"claude-opus-4-6\", { effort: \"high\" });\n```\n\n| Option            | Type                                         | Default | Description                                               |\n| ----------------- | -------------------------------------------- | ------- | --------------------------------------------------------- |\n| `effort`          | `\"low\"` \\| `\"medium\"` \\| `\"high\"` \\| `\"max\"` | —       | Claude Code reasoning effort level (`max` is Opus only)   |\n| `env`             | `Record<string, string>`                     | `{}`    | Environment variables injected by this agent provider     |\n| `captureSessions` | `boolean`                                    | `true`  | Capture agent session JSONL to host for `claude --resume` |\n\n### `CodexOptions`\n\nThe `codex()` factory accepts an optional second argument for provider-specific options:\n\n```typescript\nagent: codex(\"gpt-5.4\", { effort: \"high\" });\n```\n\n| Option   | Type                                           | Default | Description                                               |\n| -------- | ---------------------------------------------- | ------- | --------------------------------------------------------- |\n| `effort` | `\"low\"` \\| `\"medium\"` \\| `\"high\"` \\| `\"xhigh\"` | —       | Codex reasoning effort level via `model_reasoning_effort` |\n| `env`    | `Record<string, string>`                       | `{}`    | Environment variables injected by this agent provider     |\n\n### Provider `env`\n\nBoth **agent providers** and **sandbox providers** accept an optional `env: Record<string, string>` in their options. These environment variables are merged with the `.sandcastle/.env` resolver output at launch time:\n\n```typescript\nawait run({\n  agent: claudeCode(\"claude-opus-4-6\", {\n    env: { ANTHROPIC_API_KEY: \"sk-ant-...\" },\n  }),\n  sandbox: docker({\n    env: { DOCKER_SPECIFIC_VAR: \"value\" },\n  }),\n  prompt: \"Fix issue #42\",\n});\n```\n\n**Merge rules:**\n\n- Provider env (agent + sandbox) overrides `.sandcastle/.env` resolver output for shared keys\n- Agent provider env and sandbox provider env **must not overlap** — if they share any key, `run()` throws an error\n- When `env` is not provided, it defaults to `{}`\n\nEnvironment variables are also resolved automatically from `.sandcastle/.env` and `process.env` — no need to pass them to the API. The required variables depend on the **agent provider** (see `sandcastle init` output for details).\n\n## Custom Sandbox Providers\n\nSandcastle ships with built-in providers for Docker, Podman, and Vercel, but you can create your own. A sandbox provider tells Sandcastle how to execute commands in an isolated environment. There are two kinds:\n\n- **Bind-mount** — the sandbox can mount a host directory. Sandcastle creates a worktree on the host and the provider mounts it in. No file sync needed. Use this for Docker, Podman, or any local container runtime.\n- **Isolated** — the sandbox has its own filesystem (e.g. a cloud VM). The provider handles syncing code in and out via `copyIn` and `copyFileOut`. Use this when the sandbox cannot access the host filesystem.\n\n### The sandbox handle contract\n\nBoth provider types return a **sandbox handle** from their `create()` function. The handle exposes:\n\n| Method         | Required   | Description                                                                  |\n| -------------- | ---------- | ---------------------------------------------------------------------------- |\n| `exec`         | Both       | Run a command, optionally streaming stdout line-by-line via `options.onLine` |\n| `close`        | Both       | Tear down the sandbox                                                        |\n| `copyFileIn`   | Bind-mount | Copy a single file from the host into the sandbox                            |\n| `copyFileOut`  | Both       | Copy a single file from the sandbox to the host                              |\n| `copyIn`       | Isolated   | Copy a file or directory from the host into the sandbox                      |\n| `worktreePath` | Both       | Absolute path to the repo directory inside the sandbox                       |\n\n### `ExecResult`\n\nEvery `exec` call returns an `ExecResult`:\n\n```typescript\ninterface ExecResult {\n  readonly stdout: string;\n  readonly stderr: string;\n  readonly exitCode: number;\n}\n```\n\n### Bind-mount provider example\n\nA minimal bind-mount provider that shells out to local processes (no container):\n\n```typescript\nimport {\n  createBindMountSandboxProvider,\n  type BindMountCreateOptions,\n  type BindMountSandboxHandle,\n  type ExecResult,\n} from \"@ai-hero/sandcastle\";\nimport { execFile, spawn } from \"node:child_process\";\nimport { copyFile as fsCopyFile, mkdir as fsMkdir } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\nimport { createInterface } from \"node:readline\";\n\nconst localProcess = () =>\n  createBindMountSandboxProvider({\n    name: \"local-process\",\n    create: async (\n      options: BindMountCreateOptions,\n    ): Promise<BindMountSandboxHandle> => {\n      const worktreePath = options.worktreePath;\n\n      return {\n        worktreePath,\n\n        exec: (\n          command: string,\n          opts?: { onLine?: (line: string) => void; cwd?: string },\n        ): Promise<ExecResult> => {\n          if (opts?.onLine) {\n            const onLine = opts.onLine;\n            return new Promise((resolve, reject) => {\n              const proc = spawn(\"sh\", [\"-c\", command], {\n                cwd: opts?.cwd ?? worktreePath,\n                stdio: [\"ignore\", \"pipe\", \"pipe\"],\n              });\n\n              const stdoutChunks: string[] = [];\n              const stderrChunks: string[] = [];\n\n              const rl = createInterface({ input: proc.stdout! });\n              rl.on(\"line\", (line) => {\n                stdoutChunks.push(line);\n                onLine(line); // forward each line to Sandcastle\n              });\n\n              proc.stderr!.on(\"data\", (chunk: Buffer) => {\n                stderrChunks.push(chunk.toString());\n              });\n\n              proc.on(\"error\", (err) => reject(err));\n              proc.on(\"close\", (code) => {\n                resolve({\n                  stdout: stdoutChunks.join(\"\\n\"),\n                  stderr: stderrChunks.join(\"\"),\n                  exitCode: code ?? 0,\n                });\n              });\n            });\n          }\n\n          return new Promise((resolve, reject) => {\n            execFile(\n              \"sh\",\n              [\"-c\", command],\n              { cwd: opts?.cwd ?? worktreePath, maxBuffer: 10 * 1024 * 1024 },\n              (error, stdout, stderr) => {\n                if (error && error.code === undefined) {\n                  reject(new Error(`exec failed: ${error.message}`));\n                } else {\n                  resolve({\n                    stdout: stdout.toString(),\n                    stderr: stderr.toString(),\n                    exitCode: typeof error?.code === \"number\" ? error.code : 0,\n                  });\n                }\n              },\n            );\n          });\n        },\n\n        copyFileIn: async (hostPath: string, sandboxPath: string) => {\n          await fsMkdir(dirname(sandboxPath), { recursive: true });\n          await fsCopyFile(hostPath, sandboxPath);\n        },\n\n        copyFileOut: async (sandboxPath: string, hostPath: string) => {\n          await fsMkdir(dirname(hostPath), { recursive: true });\n          await fsCopyFile(sandboxPath, hostPath);\n        },\n\n        close: async () => {\n          // nothing to tear down for a local process\n        },\n      };\n    },\n  });\n```\n\n### Isolated provider example\n\nA minimal isolated provider using a temp directory:\n\n```typescript\nimport {\n  createIsolatedSandboxProvider,\n  type IsolatedSandboxHandle,\n  type ExecResult,\n} from \"@ai-hero/sandcastle\";\nimport { execFile, spawn } from \"node:child_process\";\nimport { copyFile, mkdir, mkdtemp, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { dirname, join } from \"node:path\";\nimport { createInterface } from \"node:readline\";\n\nconst tempDir = () =>\n  createIsolatedSandboxProvider({\n    name: \"temp-dir\",\n    create: async (): Promise<IsolatedSandboxHandle> => {\n      const root = await mkdtemp(join(tmpdir(), \"sandbox-\"));\n      const worktreePath = join(root, \"workspace\");\n      await mkdir(worktreePath, { recursive: true });\n\n      return {\n        worktreePath,\n\n        exec: (\n          command: string,\n          opts?: { onLine?: (line: string) => void; cwd?: string },\n        ): Promise<ExecResult> => {\n          if (opts?.onLine) {\n            const onLine = opts.onLine;\n            return new Promise((resolve, reject) => {\n              const proc = spawn(\"sh\", [\"-c\", command], {\n                cwd: opts?.cwd ?? worktreePath,\n                stdio: [\"ignore\", \"pipe\", \"pipe\"],\n              });\n\n              const stdoutChunks: string[] = [];\n              const stderrChunks: string[] = [];\n\n              const rl = createInterface({ input: proc.stdout! });\n              rl.on(\"line\", (line) => {\n                stdoutChunks.push(line);\n                onLine(line);\n              });\n\n              proc.stderr!.on(\"data\", (chunk: Buffer) => {\n                stderrChunks.push(chunk.toString());\n              });\n\n              proc.on(\"error\", (err) => reject(err));\n              proc.on(\"close\", (code) => {\n                resolve({\n                  stdout: stdoutChunks.join(\"\\n\"),\n                  stderr: stderrChunks.join(\"\"),\n                  exitCode: code ?? 0,\n                });\n              });\n            });\n          }\n\n          return new Promise((resolve, reject) => {\n            execFile(\n              \"sh\",\n              [\"-c\", command],\n              { cwd: opts?.cwd ?? worktreePath, maxBuffer: 10 * 1024 * 1024 },\n              (error, stdout, stderr) => {\n                if (error && error.code === undefined) {\n                  reject(new Error(`exec failed: ${error.message}`));\n                } else {\n                  resolve({\n                    stdout: stdout.toString(),\n                    stderr: stderr.toString(),\n                    exitCode: typeof error?.code === \"number\" ? error.code : 0,\n                  });\n                }\n              },\n            );\n          });\n        },\n\n        copyIn: async (hostPath: string, sandboxPath: string) => {\n          const info = await stat(hostPath);\n          if (info.isDirectory()) {\n            await cp(hostPath, sandboxPath, { recursive: true });\n          } else {\n            await mkdir(dirname(sandboxPath), { recursive: true });\n            await copyFile(hostPath, sandboxPath);\n          }\n        },\n\n        copyFileOut: async (sandboxPath: string, hostPath: string) => {\n          await mkdir(dirname(hostPath), { recursive: true });\n          await copyFile(sandboxPath, hostPath);\n        },\n\n        close: async () => {\n          await rm(root, { recursive: true, force: true });\n        },\n      };\n    },\n  });\n```\n\n### Branch strategies\n\nA branch strategy controls where the agent's commits land. Configure it when constructing the provider:\n\n| Strategy        | Behavior                                                                 | Bind-mount | Isolated  |\n| --------------- | ------------------------------------------------------------------------ | ---------- | --------- |\n| `head`          | Agent writes directly to the host working directory. No worktree created | Default    | N/A       |\n| `merge-to-head` | Sandcastle creates a temp branch, merges back to HEAD when done          | Supported  | Default   |\n| `branch`        | Commits land on an explicit named branch you provide                     | Supported  | Supported |\n\n**When to use each:**\n\n- **`head`** — fast iteration during development. No branch indirection, no merge step. Only works with bind-mount providers since the agent needs direct host filesystem access.\n- **`merge-to-head`** — safe default for automation. The agent works on a throwaway branch; if something goes wrong, HEAD is untouched. Use this for CI or unattended runs.\n- **`branch`** — when you want commits on a specific branch (e.g. for a PR). Pass `{ type: \"branch\", branch: \"agent/fix-42\" }`.\n\nBranch strategy is now configured on `run()`, not on the provider:\n\n```typescript\nimport { run, claudeCode } from \"@ai-hero/sandcastle\";\nimport { docker } from \"@ai-hero/sandcastle/sandboxes/docker\";\n\n// head — direct write, bind-mount only (default for bind-mount providers)\nawait run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  sandbox: docker(),\n  prompt: \"…\",\n});\n// merge-to-head — temp branch, merge back (default for isolated providers)\nawait run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  sandbox: tempDir(),\n  prompt: \"…\",\n});\n// branch — explicit named branch\nawait run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  sandbox: docker(),\n  branchStrategy: { type: \"branch\", branch: \"agent/fix-42\" },\n  prompt: \"…\",\n});\n```\n\n### Passing to `run()`\n\nPass your custom provider via the `sandbox` option — it works the same as the built-in `docker()` provider:\n\n```typescript\nimport { run, claudeCode } from \"@ai-hero/sandcastle\";\n\nconst result = await run({\n  agent: claudeCode(\"claude-opus-4-6\"),\n  sandbox: localProcess(), // your custom provider\n  prompt: \"Fix issue #42 in this repo.\",\n});\n```\n\n### Reference implementations\n\nFor real-world examples, see:\n\n- [`src/sandboxes/docker.ts`](src/sandboxes/docker.ts) — bind-mount provider using Docker containers (with SELinux label support)\n- [`src/sandboxes/vercel.ts`](src/sandboxes/vercel.ts) — isolated provider using Vercel Firecracker microVMs via `@vercel/sandbox`\n- [`src/sandboxes/podman.ts`](src/sandboxes/podman.ts) — bind-mount provider using Podman containers (with SELinux label support)\n- [`src/sandboxes/test-isolated.ts`](src/sandboxes/test-isolated.ts) — isolated provider using temp directories (used in tests)\n\n## Configuration\n\n### Config directory (`.sandcastle/`)\n\nAll per-repo sandbox configuration lives in `.sandcastle/`. Run `sandcastle init` to create it.\n\n### Custom Dockerfile\n\nThe `.sandcastle/Dockerfile` controls the sandbox environment. The default template installs:\n\n- **Node.js 22** (base image)\n- **git**, **curl**, **jq** (system dependencies)\n- **GitHub CLI** (`gh`)\n- **Claude Code CLI**\n- A non-root `agent` user (required — Claude runs as this user)\n\nWhen customizing the Dockerfile, ensure you keep:\n\n- A non-root user (the default `agent` user) for Claude to run as\n- `git` (required for commits and branch operations)\n- `gh` (required for issue fetching)\n- Claude Code CLI installed and on PATH\n\nAdd your project-specific dependencies (e.g., language runtimes, build tools) to the Dockerfile as needed.\n\n### Hooks\n\nHooks are grouped by **where** they run — `host` (on the developer's machine) or `sandbox` (inside the container):\n\n```ts\nhooks: {\n  host: {\n    onWorktreeReady: [{ command: \"cp .env.example .env\" }],\n    onSandboxReady:  [{ command: \"echo sandbox is up\" }],\n  },\n  sandbox: {\n    onSandboxReady: [\n      { command: \"npm install\", timeoutMs: 300_000 },\n      { command: \"apt-get install -y ffmpeg\", sudo: true },\n    ],\n  },\n}\n```\n\n| Hook                     | Runs on | When                                         | Working directory                           |\n| ------------------------ | ------- | ---","readmeFilename":"README.md"}