Run OpenCode inside Daytona sandboxes for two workflows: remote OpenCode web sessions and URL-driven repository audits.
This project automates Daytona sandbox setup and OpenCode execution.
It ships two entrypoints:
bun run start- boots OpenCode web in a fresh Daytona sandbox and prints an externally reachable preview URL.bun run analyze- runs headless OpenCode audits against one or more repository URLs and collects findings locally.
- What is this?
- Prerequisites
- Install On New Machine
- Quick Start
- Installer & Obsidian Cataloging
- Commands
- Repository Audit Workflow
- Output Layout
- Release Automation
- Release Process
- Development
- Compatibility Notes
- Bun 1.3+
DAYTONA_API_KEYDAYTONA_API_URLfor self-hosted Daytona (example:https://daytona.example.com/api)- Optional but recommended:
OPENCODE_SERVER_PASSWORD - Obsidian Headless CLI in
PATH(ob, installed vianpm install -g obsidian-headless) for non-disruptive sync - Obsidian Catalyst access (Headless Sync is currently open beta)
- Active Obsidian Sync subscription (required for
ob sync-*) - Optional:
obsidiandesktop CLI inPATHif you explicitly use desktop integration/open-after-catalog
Use the bootstrap installer:
curl -fsSL https://raw.githubusercontent.com/shpitdev/opencode-sandboxed-ad-hoc-research/main/scripts/install-gh-package.sh | bashIt will:
- reuse
gh authtoken when available and auto-attemptread:packagesscope refresh - otherwise prompt for a GitHub token with
read:packages - configure
~/.npmrcfor GitHub Packages - skip registry auth setup automatically when installing from a local tarball path
- install
@shpitdev/opencode-sandboxed-ad-hoc-researchglobally - launch the guided setup flow for Daytona/model credentials
bun install
bun run startOpenCode will be available on the printed Daytona preview URL.
Stop with Ctrl+C.
Run the guided installer:
bun run setupIt sets up:
~/.config/opencode/shpit.tomlfor shared preferences~/.config/opencode/.envfor optional credential storage- headless preflight checks when
obsidian.integration_mode = "headless":- verifies
obcommand is installed - runs
ob sync-list-remoteto validate account/login/sync access
- verifies
No provider API key is required if you only use free opencode/* models (for example opencode/minimax-m2.5-free).
analyze automatically catalogs findings to Obsidian when enabled in shpit.toml.
Example config:
[obsidian]
enabled = true
command = "obsidian"
integration_mode = "headless" # headless | desktop
headless_command = "ob"
vault_path = "/absolute/path/to/vault"
notes_root = "Research/OpenCode"
catalog_mode = "date" # date | repo
sync_after_catalog = true
sync_timeout_sec = 120
open_after_catalog = false # desktop mode onlyProject-level shpit.toml or .shpit.toml overrides global config.
The configured desktop command must be obsidian (not obs).
Headless setup is one-time per local vault path:
npm install -g obsidian-headless
ob login
ob sync-list-remote
mkdir -p ~/vaults/my-headless-vault
ob sync-setup --vault "My Vault" --path ~/vaults/my-headless-vault
ob sync --path ~/vaults/my-headless-vaultDo not run desktop Sync and Headless Sync on the same device for the same vault path; use a dedicated local path for headless workflows.
| Command | Purpose |
|---|---|
scripts/install-gh-package.sh |
Bootstrap install from GitHub Packages on a new machine |
bun run setup |
Guided setup for shared config/env, Obsidian mode selection, and headless preflight checks |
bun run start |
Launch OpenCode web in a Daytona sandbox |
bun run analyze -- --input example.md |
Analyze repos listed in a file |
bun run analyze -- <url1> <url2> |
Analyze direct repo URLs |
bun run build |
Compile distributable CLI files into dist/ |
bun run lint |
Lint with Biome |
bun run format |
Format with Biome |
bun run check |
Run Biome checks |
bun run typecheck |
Run TypeScript checks |
Useful start flags:
bun run start -- --port 3000 --target us --sandbox-name opencode-dev
bun run start -- --keep-sandbox
bun run start -- --no-opensrc/analyze-repos.ts supports evidence-based audits at scale.
- Creates one Daytona sandbox per URL
- Clones each repo in its sandbox
- Runs OpenCode headlessly to generate findings
- Copies findings plus repo README back to local output
- Deletes sandboxes automatically unless
--keep-sandbox
- Default model selection:
- Standard:
zai-coding-plan/glm-4.7-flash - Vision mode (
--vision):zai-coding-plan/glm-4.6v
- Standard:
- Override with
--model,--variant,OPENCODE_ANALYZE_MODEL, orOPENCODE_ANALYZE_VARIANT - Auto-installs missing
gitandnode/npminside sandbox - Forwards provider env vars (
OPENAI_*,ANTHROPIC_*,XAI_*,OPENROUTER_*,ZHIPU_*,MINIMAX_*, etc.) - Syncs local OpenCode config files from
~/.config/opencodewhen present - Syncs local OpenCode OAuth auth file (
~/.local/share/opencode/auth.json) into sandbox withchmod 600when present - When using
anthropic/*models, runsopencode models anthropicpreflight inside sandbox and fails early if the requested model is unavailable - Produces more skimmable reports with concise summary bullets, sentence-fragment-friendly style, and an ASCII logic/data-flow diagram section
- Uses a fixed Daytona lifecycle policy: auto-stop after 15 minutes, auto-archive after 30 minutes, auto-delete disabled
- Auto-catalogs findings into Obsidian when enabled via
shpit.toml, with optional automaticob syncin headless mode
bun run analyze -- --input example.md
bun run analyze -- https://github.com/owner/repo-one https://github.com/owner/repo-two
bun run analyze -- --out-dir findings --model zai-coding-plan/glm-4.7-flash --target us
bun run analyze -- --vision
bun run analyze -- --analyze-timeout-sec 3600 --keep-sandboxIf no URLs and no --input are provided, the script uses example.md when it exists.
<out-dir>/index.md- summary across all URLs<out-dir>/<NN-slug>/findings.md- final report for each repository<out-dir>/<NN-slug>/README.*- copied repository README (if found)<out-dir>/<NN-slug>/opencode-run.log- raw OpenCode run output<out-dir>/<NN-slug>/opencode-models-anthropic.log- Anthropic model-list preflight output (only whenanthropic/*model is requested)
Example retained in this repo:
bun run analyze -- --input example.md --out-dir findings-confidence-3 --analyze-timeout-sec 3600 --keep-sandboxmainmerges trigger.github/workflows/publish-package.ymlautomatically (no manual dispatch).- Versioning is enforced as patch-only
0.0.xand starts at0.0.1. - Normal PR merges publish a prerelease for the next patch with npm tag
next(for example0.0.2-next.<run>.<attempt>.<sha>), then keep/create a draft bump PR (for example0.0.1 -> 0.0.2). - Merging the automated bump PR publishes that bumped version as the public release (
latest) and does not create another.nextpublish.
Release operations, required repo settings, verification commands, and rollback steps are documented in RELEASE.md.
bun run lint
bun run format
bun run check
bun run typecheckProject config files:
biome.json.zed/settings.json.zed/tasks.jsontsconfig.build.json
- Works with modern Daytona control planes.
- Includes fallback support for older/self-hosted Daytona setups that expose
proxyToolboxUrlin/configbut not/sandbox/:id/toolbox-proxy-url. - No Daytona OpenCode plugin is required for this flow.