You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
First slice of the sanddune init CLI. Scaffolds the config directory (.sanddune/) for Docker + Claude Code + the blank template. Refuses to run if .sanddune/ already exists (so no customizations are overwritten).
Out of scope for this slice: Podman variant, backlog managers (GitHub Issues, Beads), and the four advanced templates (simple-loop, sequential-reviewer, parallel-planner, parallel-planner-with-review) — those land in slice #19.
This slice covers the toolchain decisions that need maintainer judgment: interactive prompt UX, default Dockerfile contents, error messaging, and main.mts vs main.ts selection.
Acceptance criteria
sanddune init (run via bunx sanddune init or installed bin) prompts interactively for: agent (Claude Code), template (blank); image name defaults to sanddune:<repo-dir-name>
Flags --image-name, --agent, --model, --template skip the corresponding prompts (scriptable for CI/onboarding)
Refuses to run if .sanddune/ already exists; exits with an actionable error
Scaffolds .sanddune/:
Dockerfile — Node 22, git, curl, jq, GitHub CLI, Claude Code CLI, non-root agent user
prompt.md — convention scaffold; sanddune does not read this unless promptFile is passed
.env.example — placeholder for ANTHROPIC_API_KEY
.gitignore — ignores .env, logs/
main.mts if package.json lacks \"type\": \"module\", main.ts if it does
Template argument substitution runs on the Dockerfile and scaffold .md files (replaces {{KEY}} placeholders with values derived from user choices)
Builds the Docker image after scaffolding (one-shot bootstrap)
Default Dockerfile guidance: Claude refuses to run as root, so a non-root user is required; git, gh, and the Claude Code CLI must remain on PATH
Unit tests against a temp directory: scaffolds expected file tree; refuses on existing .sanddune/; flag-driven non-interactive path
Integration test: real sanddune init in a temp repo, then run bun run packages/cli/src/index.ts init and verify the resulting .sanddune/main.mts actually invokes run() against a fake agent
Parent
#1
What to build
First slice of the
sanddune initCLI. Scaffolds the config directory (.sanddune/) for Docker + Claude Code + the blank template. Refuses to run if.sanddune/already exists (so no customizations are overwritten).Out of scope for this slice: Podman variant, backlog managers (GitHub Issues, Beads), and the four advanced templates (
simple-loop,sequential-reviewer,parallel-planner,parallel-planner-with-review) — those land in slice #19.This slice covers the toolchain decisions that need maintainer judgment: interactive prompt UX, default Dockerfile contents, error messaging, and
main.mtsvsmain.tsselection.Acceptance criteria
sanddune init(run viabunx sanddune initor installedbin) prompts interactively for: agent (Claude Code), template (blank); image name defaults tosanddune:<repo-dir-name>--image-name,--agent,--model,--templateskip the corresponding prompts (scriptable for CI/onboarding).sanddune/already exists; exits with an actionable error.sanddune/:Dockerfile— Node 22, git, curl, jq, GitHub CLI, Claude Code CLI, non-rootagentuserprompt.md— convention scaffold; sanddune does not read this unlesspromptFileis passed.env.example— placeholder forANTHROPIC_API_KEY.gitignore— ignores.env,logs/main.mtsifpackage.jsonlacks\"type\": \"module\",main.tsif it does.mdfiles (replaces{{KEY}}placeholders with values derived from user choices).sanddune/; flag-driven non-interactive pathsanddune initin a temp repo, then runbun run packages/cli/src/index.ts initand verify the resulting.sanddune/main.mtsactually invokesrun()against a fake agentbun testandbun run typecheckpassBlocked by