Questions encountered during design and implementation that need resolution. Resolve each before the relevant implementation begins.
-
Go module path— Resolved:github.com/kstenerud/yoloai. -
Node.js version— Resolved: Node.js 22 LTS via NodeSource. Claude Code'senginesfield requires>=18.0.0; Node 22 is well within range. Node 20 LTS reaches EOL April 2026 — Node 22 LTS (maintenance until April 2027) avoids shipping with an EOL runtime. Anthropic's devcontainer still uses Node 20 as of February 2026, but no Node 22-specific incompatibilities have been found. The native Claude Code installer (curl script) is not suitable: bundles Bun with broken proxy support (issue #14165), segfaults on Debian bookworm AMD64 (#12044), and auto-updates. npm install shows a deprecation warning but remains the only reliable path for Docker/proxy use. See Implementation Research "Claude Code Installation Research". -
tini— Resolved: Usedocker run --init(Docker's built-in tini). Simpler than installing in image. We control all container creation in code so the flag is always passed. -
gosu— Resolved: Install from GitHub releases (static binary). Standard for Debian images. -
Claude ready indicator— Resolved: Fixed 3-second delay for MVP, configurable viaconfig.jsonstartup_delay. Polling deferred. -
Caret encoding scope— Resolved: Implement the full caret encoding spec. Trivial to implement and avoids platform-specific assumptions.
These were deferred from MVP but might be cheap to add and valuable for dogfooding:
-
— Resolved: Include in MVP. Trivial pass-through to agent command.--modelflag -
— Resolved: Include in MVP. Simpleyoloai execdocker execwrapper, useful for debugging. -
Dangerous directory detection— Resolved: Include in MVP. Small validation function. -
Dirty git repo warning— Resolved: Include in MVP. Small git status check.
-
Entrypoint configuration passing— Resolved: Bind-mounted JSON config file at/yoloai/config.json. Entrypoint reads all configuration from it — agent command, startup delay, UID/GID, submit sequence, and later overlay mounts, iptables rules, setup commands. Single source of truth from the start; no env vars. -
— Resolved: Post-MVP. Setup commands written to a bind-mounted script, executed by entrypoint before launching agent.setupcommands — execution mechanism -
tmux behavior when agent exits— Resolved:remain-on-exit on— container stays up after agent exits. User can still attach and see final output. Container only stops on explicityoloai stop/destroy. -
Context file content and delivery— Resolved: Post-MVP. Context file generated on host, bind-mounted read-only. Claude gets it via--append-system-prompt, Codex via prompt prepend.
-
Untracked files in diff/apply— Resolved:git add -Abefore diffing to capture untracked files. Runs in the sandbox copy, not the user's original. -
Multiple— Resolved: Post-MVP (MVP has single workdir, no aux dirs). Show all with headers per directory. Apply all at once with single confirmation. If one fails, stop and report which failed. User can re-run with:copydirectories in diff/apply[-- <path>...]to apply selectively. -
Commit-preserving apply— Resolved:yoloai applynow preserves individual commits by default usinggit format-patch+git am --3way. Uncommitted changes are applied as unstaged on top.--squashfor legacy single-patch behavior.--patches <dir>exports.patchfiles for manual curation (selective apply via deleting unwanted patches, or standard git tools likegit rebase -i/git cherry-pick).--no-wipto skip uncommitted changes. See commands.mdyoloai applysection. -
Overlay apply — patch transfer to host— Resolved: Capturegit diffoutput fromdocker execstdout, pipe togit applyon host. No temp file needed.
-
— Resolved: Post-MVP. Two forms: string (base directory — yoloai appends the agent's state subdir, e.g.agent_files— scope"${HOME}"→~/.claude/for Claude) or list (specific files/dirs to copy verbatim). Excludes session history and caches. If source doesn't exist, skip silently. Runtime state tracked instate.json(alongsidemeta.json). -
— Resolved: Post-MVP.agent_files— "first run" detectionstate.jsonis created at sandbox creation time alongsidemeta.json. It contains anagent_files_initializedboolean (initiallyfalse). Afteragent_filesseeding completes, the field is set totrue. To re-seed, set the field back tofalseand restart the sandbox.
-
How does the binary find Dockerfile and entrypoint at runtime?— Resolved:go:embedbundles defaults. On first run, seed~/.yoloai/Dockerfile.baseandentrypoint.shif they don't exist. Build always reads from~/.yoloai/, not embedded copies. User can edit for fast iteration. -
Codex binary download URL and versioning— Resolved: Post-MVP (Codex deferred). Pin version in Dockerfile when implemented. -
— Resolved: Post-MVP. Auto-provideyoloai build --secret— which secrets are automatically provided?~/.npmrcif it exists. No other automatic secrets. Additional secrets via--secretflag.
-
Docker network naming and lifecycle— Resolved: Post-MVP. Per-sandbox network:yoloai-<name>-net. Created duringyoloai new --network-isolated, destroyed duringyoloai destroy. -
Proxy allowlist file format— Resolved: Post-MVP. One domain per line,#comments. Bind-mounted file in proxy container. -
Proxy Go source location— Resolved: Post-MVP.cmd/proxy/main.go— separate binary in its own container, belongs incmd/.
-
— Resolved: Re-run full container creation logic fromyoloai startwhen container was removedmeta.json, skip copy step. Credential injection: create new temp file each time (ephemeral by design). -
— Resolved:yoloai listSTATUS "exited" detectiondocker exec tmux list-panes -t main -F '#{pane_dead}'. Combined with Docker container state gives: running, exited, stopped, removed.
-
Dangerous directory list— Resolved:$HOME,/, plus platform-specific: macOS (/System,/Library,/Applications), Linux (/usr,/etc,/var,/boot,/bin,/sbin,/lib). Simple string match on absolute path — no subdirectory blocking. -
— Resolved:yoloai difffor:rw— why docker exec?:rwrunsgit diffdirectly on host (bind mount = same files). Docker exec only needed for overlay. -
No workdir and no profile— Resolved: Error: "no workdir specified and no default workdir in profile" (exit 2). Workdir required for MVP. -
— Resolved: Post-MVP. Shell script loop spawned by entrypoint.auto_commit_intervalimplementationgit add -A && git commitwith authoryoloai <yoloai@localhost>, UTC timestamp message. Skips if no changes. Creates commit history thatyoloai applypreserves as individual commits (see #86). -
Profile without a Dockerfile— Resolved (revised): Dockerfile is optional per profile. Profiles without a Dockerfile useyoloai-basedirectly — no image build needed. This is simpler for runtime-only profiles (env, ports, directories) that don't need custom packages. If a profile explicitly depends onyoloai-base, base image updates affecting all dependents is expected and correct behavior. The earlier "always seed a Dockerfile" approach added unnecessary maintenance burden for the common case.
-
— Resolved: Workdir defaults to.:copyboilerplate:copy(the tool's core philosophy).yoloai new fix-bug .works.:rwrequires explicit suffix. Safe default preserved. -
Implicit workdir from cwd— Resolved (firm decision — do not revisit): Keep workdir explicit (.required). One character is low friction and avoids accidental sandboxing of wrong directory. This is a deliberate safety choice: implicit cwd defaulting is a footgun that leads to sandboxing the wrong directory. This has been discussed multiple times and the decision is final. -
Sandbox name repetition— Resolved: Shell completion viayoloai completion(Cobra built-in) in MVP.YOLOAI_SANDBOXenv var as fallback when name arg is omitted — explicit arg always wins. No specialyoloai usecommand; users justexport YOLOAI_SANDBOX=fix-bug. -
No— Resolved: Add--prompt-fileor stdin--prompt-file <path>. Both--prompt -and--prompt-file -read from stdin. -
No reset/retry workflow— Resolved: Addyoloai reset <name>— re-copies workdir from original, resets git baseline, keeps sandbox config and agent-state. -
First-time setup friction— Resolved:yoloai newauto-detects missing setup: creates~/.yoloai/if absent, builds base image if missing.yoloai initdropped.yoloai new --no-startfor setup-only (create sandbox without starting container). -
No default profile— Resolved: Adddefaults.profileto config.yaml. CLI--profileoverrides.--no-profileto explicitly use base image. -
— Resolved: Addyoloai diffno summary mode--statflag (passes through togit diff --stat). -
— Resolved:yoloai applyall-or-nothingyoloai apply <name> [-- <path>...]to apply specific files only. -
Shell completion setup— Resolved:yoloai completioncommand in MVP. Print setup instructions after first-run auto-setup duringyoloai new. -
"Is it done?" check— Deferred. Hard to detect agent idle vs working.yoloai logandyoloai listare sufficient for v1. -
Re-use prompt after destroy— Deferred.yoloai reset(#45) covers the main retry case without destroying.
-
No read-only/investigation mode shortcut— Resolved: Not a problem.:copywith overlay is instant. Agent needs write access even for investigation. No change needed. -
— Resolved: Reset re-sends the originalyoloai resetdoes not re-send the promptprompt.txtby default.--no-promptflag to suppress. -
No way to send a new prompt without attaching— Deferred. Between reset re-sending prompt (#54) and--prompt-filefor scripting, the gap is small. Addyoloai promptcommand post-MVP if needed. -
Quick successive tasks have too much ceremony— Deferred.yoloai run(create, wait, diff, prompt for apply, auto-destroy) is high-value sugar but the building blocks need to work first. Post-MVP. -
No indication of agent completion vs. crash— Resolved:yoloai listshows "done" (exit 0) vs "failed" (non-zero) using tmuxpane_dead_status. Not just "exited." -
— Resolved. CHANGES column added usingyoloai listdoesn't show unapplied changesgit status --porcelainon host-side work directory — lightweight (read-only, short-circuits), catches both tracked modifications and untracked files, no Docker needed. -
Multiple sandbox conflict detection is absent— Resolved: Include better error messaging — wrapgit applyfailures with context explaining why the patch failed. Predictive conflict detection deferred. -
No bulk destroy or stop— Resolved:yoloai destroy name1 name2 name3with single confirmation, plus--allflag. Same foryoloai stop. -
First-time base image build is slow and poorly communicated— Resolved: Clear "Building base image (first run only, ~2-5 minutes)..." message during auto-build on firstyoloai new. -
— Resolved:yoloai loghas no tail or searchNoSuperseded by #76: auto-page through--tail, no pager. Raw stdout output. User composes with unix tools.$PAGER/less -Rwhen stdout is a TTY. -
No way to see what prompt was given to a sandbox— Resolved: Includeyoloai show <name>in MVP. Displays all sandbox details: name, status, agent, profile, prompt, workdir (resolved path), creation time, baseline SHA, container ID. Essential for dogfooding/debugging. -
— Resolved: Documentation only. DocumentYOLOAI_SANDBOXis awkward for multi-sandbox workflowsYOLOAI_SANDBOXas "useful for single-sandbox sessions" rather than general convenience. -
— Resolved:yoloai applyon overlay requires container runningyoloai applyauto-starts the container when needed for overlay diff. No user action required. -
No— Resolved: Includeyoloai new --replacefor iterate-and-retry--replaceflag onyoloai new. Destroys existing sandbox of the same name and creates fresh. -
— Resolved: Includeyoloai resetpreserves agent-state, which may work against the user--cleanflag onyoloai resetto wipe agent-state for a truly fresh start. -
Workdir— Resolved: Already covered by existing creation output format showing resolved absolute path. No design change needed..has no confirmation of resolved path -
No inline prompt entry on— Deferred.yoloai newwithout--prompt--prompt,--prompt-file, and--prompt -(stdin) cover the bases.$EDITORintegration is polish for post-MVP. -
No— Resolved: Print warning "Note: agent is still running; diff may be incomplete" when tmux pane is alive duringyoloai diffsafety note while agent is runningyoloai diff. -
No way to inspect profile configuration— Resolved. Implemented asyoloai profile info <name>. Shows merged config with full inheritance chain. Supports--jsonandbaseprofile. -
Shell quoting for— Deferred. Same as #69.--promptis painful--prompt-fileand stdin already address the pain.--editfor$EDITORdeferred. -
— Resolved: Smart destroy confirmation — skip prompt when sandbox is stopped/exited with no unapplied changes. Only confirm when agent is running or unapplied changes exist.yoloai destroyconfirms even when unnecessary -
No warning when— Resolved: Error at creation time on path prefix overlap between any sandbox mounts —:rwworkdir overlaps with existing sandbox:rw/:rw,:rw/:copy,:copy/:copy. Check: does either resolved path start with the other?:forcesuffix overrides with a warning (same mechanism as dangerous directory detection). Error by default,:forceis the explicit escape hatch. -
Codex follow-up limitation undocumented— Deferred. Codex is post-MVP. Document the session persistence limitation when Codex is implemented.
-
— Resolved:yoloai diffandyoloai logshould auto-page when stdout is a TTYyoloai diffandyoloai logshould auto-page through$PAGER/less -Rwhen stdout is a TTY, matchinggit diff/git logbehavior. Piping (yoloai diff my-task | less) already works since both output raw to stdout; auto-paging is the polished default. -
No
yoloai waitcommand for scripting/CI — Deferred. No built-in way to block until the agent finishes — must pollyoloai list --json. Ayoloai wait <name> [--timeout <duration>]that blocks until agent exit (returning the agent's exit code) would enable CI workflows. Related to deferredyoloai run(#56) —runis sugar on top ofwait. Post-MVP. -
Multiple— Removed. The "compare two approaches in parallel" scenario is contrived — in practice you'd use:copysandboxes from same source — sequential apply conflictsresetor--replaceto iterate sequentially. Accidental overlap (forgot a sandbox exists) is already covered bygit applyerror wrapping (#59). -
— Resolved: Print "Starting container for overlay diff..." to stderr when auto-starting a stopped container duringyoloai applyauto-starting container for overlay should print a messageyoloai apply. Consistent with CLI-STANDARD.md progress-on-stderr convention. -
Cannot add— Resolved: Docker limitation — port mappings cannot be added to running containers. Document in--portafter sandbox creation--porthelp text: "Ports must be specified at creation time. To add ports later, useyoloai new --replace." No code change, just documentation. -
— Resolved: Inherent to:rwdiff shows all uncommitted changes, not just agent changes:rwmode —git diffruns against HEAD on the live directory, so pre-existing uncommitted changes are mixed with agent changes. Document inyoloai diffhelp: "For:rwdirectories, diff shows all uncommitted changes relative to HEAD, not just agent changes. Use:copymode for clean agent-only diffs." -
Post-creation output should adapt to whether— Resolved: Context-aware next-command suggestions after--promptwas givenyoloai new: without--prompt, suggestyoloai attach <name>(agent is waiting for input); with--prompt, suggestyoloai attach <name>to interact andyoloai diff <name>when done. -
— Resolved: Creation output shows a brief summary of resolved settings: agent, profile (or "base"), workdir path + mode, copy strategy, network mode. Confirms what was actually configured when options come from defaults + profile + CLI.yoloai newoutput should show resolved configuration -
— Resolved: Merge into singleshowandstatuscommands overlapyoloai showcommand.shownow includes directories with access modes (fromstatus).statusremoved from command table. -
Entrypoint JSON parsing— Resolved: Installjqin the base image. The entrypoint reads/yoloai/config.jsonviajqfor all configuration (agent_command, startup_delay, submit_sequence, host_uid, host_gid, etc.). Simpler and more robust than shell-only JSON parsing. -
Agent CLI arg passthrough— Resolved:yoloai new fix-bug . -- --max-turns 5passes everything after--verbatim to the agent command. Passthrough args are appended after yoloai's built-in flags (e.g.,claude --dangerously-skip-permissions --model claude-opus-4-latest --max-turns 5). Duplicating first-class flags in passthrough is undefined behavior (depends on agent's CLI parser). Standard--convention (npm, docker, cargo). High value for dogfooding — agents have many flags yoloai doesn't need to wrap.
-
Worktree source directories — .git file link is unsafe after copy— Resolved (Phase 4b bugfix). When the source directory is a git worktree,.gitis a file (not a directory) containing agitdir:pointer back to the main repo. Aftercp -rp, the copy's.gitfile still points to the original repo's object store — git operations in the container would affect the host repo. Fix:gitBaselinenow usesos.Lstatto detect.gitfiles, removes the worktree link, and creates a fresh standalone baseline viagit init. The baseline SHA is different from the original HEAD but that's correct — diff/apply only need a baseline representing the copy's initial state. -
Git worktrees as a copy strategy (instead of cp -rp)— Resolved: not pursuing.git worktree addwould be near-instant and share the object store, but has fundamental problems for coding agents: (a).gitignored files (node_modules/, build artifacts,.env) are not included — agents can't build or test without them; (b) worktree branches/refs are visible in the original repo — agent git operations pollute the host; (c) only works for git repos, not arbitrary directories. The planned overlayfs strategy (post-MVP) solves the same performance problem without these limitations.
Profile inheritance model— Resolved. Profiles specifyextends: <profile-name>(defaults tobaseif omitted). Config merge chain: base config.yaml → each profile in extends order → CLI flags. Image chain: each profile with a Dockerfile buildsyoloai-<name>FROM its parent's image. Profiles without Dockerfiles inherit their parent's resolved image. Cycle detection on the extends chain (error on revisit). Implemented ininternal/sandbox/profile.go.
- MCP server support inside containers — Claude Code's MCP config (
settings.json,~/.claude.json) gets seeded into the container, but MCP servers themselves don't work: stdio servers need their binary/script installed in the container (not available), and network servers referencelocalhostwhich resolves to the container, not the host. Possible solutions: custom profiles with MCP dependencies installed, or host-network passthrough. Low priority unless users report this as a blocker — MCP-heavy users are power users who could build a custom profile.
- macOS VM backend for native development — yoloAI's Linux Docker containers cannot run xcodebuild, Swift, or Xcode SDKs. Supporting macOS-native development requires a VM-based sandbox backend. Tart (Cirrus Labs) is the leading candidate (see Sandboxing Research "macOS VM Sandbox Research"). Partially resolved: The
runtime.Runtimeinterface ininternal/runtime/provides the backend abstraction, with Docker, Tart, and Seatbelt implementations. Remaining open questions:Architecture: How does yoloAI abstract over Docker (Linux) and Tart (macOS) backends? Shared interface with per-backend implementations? Or separate command paths?Resolved:runtime.Runtimeinterface with per-backend packages (internal/runtime/docker/,internal/runtime/tart/,internal/runtime/seatbelt/).- Image management: macOS VM images are ~30-70 GB (vs. ~1 GB for Linux Docker images). How to handle first-run image download? Pre-built images via OCI registry?
- 2-VM limit: Apple enforces a hard 2 concurrent macOS VM limit per Mac. How does yoloAI communicate and enforce this? Error on third sandbox? Queue?
- Xcode installation: Xcode is ~30 GB and requires Apple ID to download. How to pre-install in base images?
xcode-select --installfor CLI tools only? - Agent compatibility: Do Claude Code and other agents work correctly inside macOS VMs? Any differences from Linux container behavior?
- Diff/apply workflow: Does the copy/diff/apply workflow work unchanged? Tart's VirtioFS sharing may behave differently from Docker bind mounts.
- Startup time: ~5-15 seconds is acceptable but noticeably slower than Docker. Does this affect UX enough to require UI changes (progress indicator)?
- Comprehensive network allowlist audit for all agents — Gemini was missing
oauth2.googleapis.comfor OAuth token refresh (tokens expire after ~1 hour, breaking long sessions). Claude likely has the same class of issue — OAuth/API token refresh may need domains beyond what's currently allowed. All agents need a systematic audit: capture actual network traffic during full sessions (startup, auth, operation, token refresh, telemetry) and verify the allowlist covers everything. This is especially important for--network-isolatedmode where missing domains cause silent failures.
- Strategy for keeping model aliases current — Gemini's model aliases drifted (pointed to 2.5 when Gemini 3 was the current default). This will recur as providers release new models. Need a process to stay current. Options to discuss: periodic manual review cadence, automated checks against provider APIs/docs, pinning to stable identifiers that providers maintain (e.g.,
-latestsuffixes where available), or documenting that aliases are best-effort and users should use--modelfor specific versions.
Reference files pollute diff/apply workflow— Resolved. Bidirectional file exchange directory:~/.yoloai/sandboxes/<name>/files/on host, mounted rw at/yoloai/files/in sandbox. Managed viayoloai filessubcommands (put,get,ls,rm,path). Lives outside the work dir so it never appears in diff/apply. Works across all backends (Docker bind mount, Tart VirtioFS, Seatbelt SBPL sandbox dir rule). See commands.md for full spec.
-
Codex proxy support — Whether Codex's static Rust binary honors
HTTP_PROXY/HTTPS_PROXYenv vars is unverified (see commands.md, Security Research). Critical for--network-isolatedmode with Codex. If it ignores proxy env vars, would need iptables-only enforcement. -
Codex required network domains — Only
api.openai.comis confirmed (see commands.md). Additional domains (telemetry, model downloads) may be required. -
Codex TUI behavior in tmux — Interactive mode (
codex --yolowithoutexec) behavior in tmux is unverified (Agents Research). -
Image cleanup mechanism— Resolved.yoloai system prunenow removes dangling Docker images (stale build layers from image rebuilds) in addition to orphaned containers, VMs, and temp files. Uses Docker'sdangling=truefilter, which only removes unreferenced images — safe for running sandboxes.
-
Extension shell script security— Resolved. Initial release: documentation only (warn users to review scripts, same trust model as Makefiles). Follow-up: review-on-first-run — display action script and prompt for confirmation on first execution or after modification (track script hash to detect changes). -
Extension discovery and sharing— Resolved. Manual file copying — users share YAML files via gists, repos, blog posts. Format is already self-contained.--install <url>and curated repos are future enhancements if demand exists. -
Agent-agnostic extensions— Resolved. Shell branching on$agentis sufficient — no structured per-agent action sections. For very different agents, create separate extension files. Theagentfield accepts a string or list:agent: claude,agent: [claude, codex]. Omitagententirely for any-agent compatibility. yoloAI validates the current agent against the list before running the action. -
Extension arg validation— Resolved. No type validation — all args and flags are passed as strings. Errors surface naturally from the commands in the action script (e.g.,yoloai newerrors on nonexistent workdir). Keeps the YAML simple and doesn't limit what extensions can do. -
Profile env var / agent_args unset mechanism— Deferred. Env vars set to empty string (MY_VAR: "") remain defined in the container, which differs from being absent — scripts using${MY_VAR+x}to check for existence will still see the variable. A child profile cannot remove an inherited env var or agent_arg. A sentinel value (e.g.!unset) could work but adds complexity to every code path that reads env/agent_args, and users can restructure their profile chain as a workaround. Revisit if users report inheritance conflicts.