Goal
Add a Docker sandbox backend with parity to the current worktree sandbox.
Scope
- Add Docker as an additive backend behind
--sandbox docker
- Keep worktree as default backend
- Preserve current
main UX while resolving the actual GitHub default branch internally
- Make Docker support
clone, workspace create, workspace run, workspace attach, workspace prompt, and workspace remove
Product decisions
- Source of truth for repo contents is the host checkout
- Before copying, refresh against remote default branch without mutating the user's host checkout
- Main gets its own container
- Each branch workspace gets its own long-lived container
- Branch creation copies the default-branch repo, then creates/checks out the target branch inside the container
- Repo copy includes full git metadata, not just files
- Docker workspace state is a snapshot at init time; no auto-resync after creation
workspace prompt runs inside the container
workspace attach uses docker exec -it <container> bash
- Docker
detach is a no-op
- Docker labels/names are the source of truth for workspace lookup/listing
- Build the image lazily on first Docker use from a Dockerfile under
~/.local/share/skipper
- Base image starts from Ubuntu and installs Node, Bun, and OpenCode
- Mount host auth/config read-only for OpenCode, git, GitHub CLI, and ssh
- Keep current repo-name identity at the CLI surface for now
Architecture
Runtime selection
- Add a global
--sandbox flag
- Default to worktree
- Use DI/runtime wiring to provide the selected backend instead of hardcoding
WorkTreeSandboxServiceLayer
Core interfaces
- Keep
SandboxService as the main lifecycle boundary if possible
- Add backend-aware workspace registry / locator / handle services so run/prompt/list flows do not depend on raw host cwd strings
- Keep the existing filesystem service for host checkout management, but stop treating it as the only workspace lookup source
Docker backend behavior
- Ensure a clean default-branch source snapshot from the host-side repo data
- Create a main container for repo-level clone flow
- Create one container per branch workspace
- Copy the repo into the container at runtime
- For branch workspaces, create/check out the branch inside the container after copy
- Execute commands in the container workspace
- Run OpenCode inside the container for prompt flow
- Remove container resources on workspace destroy
Workspace lookup
- Worktree backend keeps current filesystem-based lookup
- Docker backend lists/locates workspaces from Docker labels and container names
- Shared workspace selection should route through a backend-aware registry layer
Implementation phases
- Add backend selection plumbing for
--sandbox with worktree as default
- Add backend-aware workspace registry / locator / handle abstractions
- Add Docker image bootstrap and lazy image build flow
- Add Docker sandbox adapter for init, execute, attach, detach, and destroy
- Make prompt flow container-aware so OpenCode runs inside Docker
- Update listing/selection/docs/tests and verify both backends
Likely files
packages/core/src/runtime/local-work-tree.runtime.ts
packages/core/src/workspace/port/sandbox.service.ts
packages/core/src/workspace/use-case/init-workspace.use-case.ts
packages/core/src/workspace/use-case/run-command-in-workspace.use-case.ts
packages/core/src/workspace/use-case/prompt-workspace.use-case.ts
packages/core/src/workspace/use-case/list-main-project.use-case.ts
packages/core/src/workspace/use-case/list-branch-project.use-case.ts
packages/cli/src/common/global-flags.ts
packages/cli/src/index.ts
packages/cli/src/command/clone.command.ts
packages/cli/src/command/workspace/workspace.common.ts
- new Docker runtime / adapter / registry helpers under
packages/core/src/runtime/ and packages/core/src/workspace/adapter/
Verification
sk clone git@github.com:owner/repo.git --sandbox docker creates host checkout + main container
sk workspace create --repository repo --branch feat/x --sandbox docker creates a branch container from default-branch source
sk workspace run --repository repo --branch feat/x --command 'pwd' --sandbox docker runs inside the right container workspace
sk workspace attach --repository repo --branch feat/x --sandbox docker opens an interactive shell in the container
sk workspace prompt --repository repo --branch feat/x 'Explain this codebase' --sandbox docker runs OpenCode inside the container
sk workspace remove --repository repo --branch feat/x --sandbox docker cleans up container resources
- worktree backend still works unchanged by default
- run
bun test and bun run check:fix
Goal
Add a Docker sandbox backend with parity to the current worktree sandbox.
Scope
--sandbox dockermainUX while resolving the actual GitHub default branch internallyclone,workspace create,workspace run,workspace attach,workspace prompt, andworkspace removeProduct decisions
workspace promptruns inside the containerworkspace attachusesdocker exec -it <container> bashdetachis a no-op~/.local/share/skipperArchitecture
Runtime selection
--sandboxflagWorkTreeSandboxServiceLayerCore interfaces
SandboxServiceas the main lifecycle boundary if possibleDocker backend behavior
Workspace lookup
Implementation phases
--sandboxwith worktree as defaultLikely files
packages/core/src/runtime/local-work-tree.runtime.tspackages/core/src/workspace/port/sandbox.service.tspackages/core/src/workspace/use-case/init-workspace.use-case.tspackages/core/src/workspace/use-case/run-command-in-workspace.use-case.tspackages/core/src/workspace/use-case/prompt-workspace.use-case.tspackages/core/src/workspace/use-case/list-main-project.use-case.tspackages/core/src/workspace/use-case/list-branch-project.use-case.tspackages/cli/src/common/global-flags.tspackages/cli/src/index.tspackages/cli/src/command/clone.command.tspackages/cli/src/command/workspace/workspace.common.tspackages/core/src/runtime/andpackages/core/src/workspace/adapter/Verification
sk clone git@github.com:owner/repo.git --sandbox dockercreates host checkout + main containersk workspace create --repository repo --branch feat/x --sandbox dockercreates a branch container from default-branch sourcesk workspace run --repository repo --branch feat/x --command 'pwd' --sandbox dockerruns inside the right container workspacesk workspace attach --repository repo --branch feat/x --sandbox dockeropens an interactive shell in the containersk workspace prompt --repository repo --branch feat/x 'Explain this codebase' --sandbox dockerruns OpenCode inside the containersk workspace remove --repository repo --branch feat/x --sandbox dockercleans up container resourcesbun testandbun run check:fix