| name | dev-setup |
| description | Setting up a Capsem development environment from scratch. Use when onboarding a new developer, setting up a new machine, or troubleshooting environment issues. Covers prerequisites, first-time setup, tool installation, VM asset builds, container runtime configuration (Colima/Docker memory and CPU requirements), and verification steps. |
Developer Setup
Prerequisites
- macOS 13+ (Ventura or later) -- required for Virtualization.framework
- Apple Silicon (arm64) -- primary target. Intel Macs are not supported for VM features.
- Docker (via Colima on macOS) -- needed for
just build-assets (kernel + rootfs builds)
Required tools
Run just doctor to check all of these:
| Tool | Purpose | Install |
|---|
| Rust (stable) | Host + guest binaries | rustup |
| just | Task runner | cargo install just |
| pnpm | Frontend package manager | npm i -g pnpm |
| Node.js 24+ | Frontend build | nvm or brew install node |
| uv | Python package manager | curl -LsSf https://astral.sh/uv/install.sh | sh |
| Docker (via Colima on macOS) | VM image builds | brew install colima docker (macOS) or sudo apt install docker.io (Linux) |
| Docker BuildKit (buildx) | Cross-arch container builds | brew install docker-buildx (macOS) or sudo apt install docker-buildx-plugin (Linux) |
Rust targets (auto-installed by just doctor-fix):
aarch64-unknown-linux-musl -- guest binaries (arm64)
x86_64-unknown-linux-musl -- guest binaries (x86_64)
Cargo tools (auto-installed by just doctor-fix):
cargo-llvm-cov -- coverage
cargo-audit -- vulnerability scanner
cargo-tauri -- Tauri CLI
b3sum -- BLAKE3 checksums
Container runtime setup
On macOS, Docker runs inside a Colima VM. The default memory allocation may be too small -- the rootfs build runs apt installs, npm installs, and curl-based CLI installers concurrently, which can OOM-kill the build (exit code 137).
Minimum: 12GB RAM. Recommended: 16GB RAM, 8 CPUs (Tauri's GTK/webkit2gtk dep chain pushes the install-test build past 8GB on cold caches; 12GB is the floor that doesn't OOM).
Colima (macOS)
brew install colima docker
colima start --vm-type vz --vz-rosetta --memory 16 --cpu 8
colima stop
colima start --vm-type vz --vz-rosetta --memory 16 --cpu 8
docker info | grep -E 'Total Memory|CPUs'
Colima recovery discipline
If Docker-dependent recipes fail on macOS, do not report Docker/Colima as
unavailable until you have checked for the common half-running Colima state.
The signature is:
colima list says the profile is Running
docker version / docker info cannot connect to
~/.colima/default/docker.sock
colima ssh -- docker ps fails with kex_exchange_identification,
Connection reset by peer, or colima status reports
error retrieving current runtime: empty value
First recovery attempt:
colima stop
colima start
docker version
If the profile needs its expected resources restored, start with the explicit
Capsem defaults instead:
colima stop
colima start --vm-type vz --vz-rosetta --memory 16 --cpu 8
docker version
Only after that restart fails should you treat Colima as a real environment
blocker. Record the exact failed command and the Docker/Colima output.
Linux
Docker runs natively on Linux -- no Colima or memory tuning needed.
sudo apt install docker.io
just doctor checks these resources automatically and fails if below minimum.
First-time setup
git clone <repo> && cd capsem
./bootstrap.sh
just exec "echo hello from capsem"
bootstrap.sh lives at the repo root (not under scripts/). It runs just build-assets as part of doctor's auto-fix, so step 3 just confirms the VM boots.
What bootstrap installs
Three phases. Default at every prompt is Yes (Enter accepts; type n to decline). --yes and non-tty input both auto-accept.
| Phase | Tool | Channel |
|---|
| 1 (hard prereqs) | bash, git, curl | system package manager (you install) |
| 1 | rustup (stable, minimal profile) | sh.rustup.rs |
| 1 | just | just.systems -> ~/.local/bin |
| 2 | uv | astral.sh/uv -> ~/.local/bin |
| 2 | Python deps | uv sync |
| 2 (macOS) | flock, pnpm | brew |
| 2 (macOS) | colima, docker, docker-buildx | brew (+ symlink into ~/.docker/cli-plugins) |
| 2 (macOS) | Colima VM | colima start --vm-type vz --vz-rosetta --memory 16 --cpu 8 |
| 2 | Frontend deps | pnpm install --frozen-lockfile |
| 3 | Doctor --fix | scripts/doctor-common.sh --fix -- Rust targets, cargo-llvm-cov, cargo-audit, b3sum, cargo-tauri (= tauri-cli crate), cargo-sbom, build VM assets, pack initrd |
Release-only local preflight also needs cdxgen. Install it with
npm install -g @cyclonedx/cdxgen before running
bash scripts/check-release-workflow.sh or local VM asset release dry runs.
Kernel version
Kernel selection is part of the profile-derived image build, not a standalone
developer setting. The build backend resolves the configured kernel branch
while materializing and building profile assets through capsem-admin/just.
Do not add a parallel kernel setting under runtime settings or backend-only
config.
Or step by step:
just doctor
just doctor-fix
just build-assets
just exec "echo hi"
If step 4 prints "hello from capsem" and exits cleanly, you're set.
Daily workflow
just shell
just exec "CMD"
just test
just ui
just dev
See /dev-just for the complete recipe reference.
Credentials
Do not create ~/.capsem/user.toml. Credentials are captured and replayed by
the credential broker plugin through profile/corp policy. Hermetic tests use
the local mock server and Ironbank fixtures; real OAuth/API-key manual runs are
debug evidence, not release proof.
Do not add setup-time admin or guest config roots. Runtime behavior is
profile/corp-owned; settings are UI/application preferences only. Generated
settings UI metadata may render controls, but it is not a product config
authority.
Claude Code permissions
To avoid repeated permission prompts when using just and capsem commands, add these to your Claude Code settings. Run /update-config or edit .claude/settings.local.json:
{
"permissions": {
"allow": [
"Bash(just *)",
"Bash(uv run *)",
"Bash(cargo *)",
"Bash(pnpm *)",
"Bash(cd frontend && pnpm *)",
"Bash(npx *)",
"Bash(python3 scripts/*)",
"Bash(rustup *)"
]
}
}
This allows:
just * -- all recipes (run, test, build-assets, query-session, list-sessions, doctor, etc.)
uv run * -- capsem-builder CLI and Python scripts
cargo * -- Rust builds, tests, checks
pnpm * -- frontend package management and builds
npx * -- skills CLI and other npx tools
python3 scripts/* -- project scripts (check_session, list_sessions, etc.)
rustup * -- target/component management
Codesigning
The app binary must be codesigned with com.apple.security.virtualization entitlement or
Virtualization.framework calls crash. The justfile handles this automatically via _sign recipe.
Prerequisites (macOS only):
- Xcode Command Line Tools:
xcode-select --install
entitlements.plist must exist in the repo root (checked into git)
Verification: just doctor includes a signing test that compiles a tiny binary, signs it with
the entitlements, and verifies the operation succeeds. Run just doctor after initial setup to
confirm signing works.
Linux developers: codesign is not available and not needed on Linux. VM features use the
KVM backend when /dev/kvm and /dev/vhost-vsock are available. Use just benchmark
for the same artifact-recording performance suite as macOS.
Troubleshooting
just run fails with codesign error
- Run
just doctor -- it will diagnose the specific signing issue
- Ensure Xcode CLTools are installed:
xcode-select --install
- Check entitlements file exists:
cat entitlements.plist
- Try manual sign:
codesign --sign - --entitlements entitlements.plist --force target/debug/capsem
- Check SIP status:
csrutil status
just doctor fails
Run just doctor-fix to auto-fix all fixable issues. Fixes run in dependency order (rustup targets before cargo tools before build-assets before pack-initrd). Non-fixable issues show install hints.
just build-assets or just test-install fails with exit code 137 (or 143 mid-cargo-build)
The container runtime VM ran out of memory. Bump Colima to at least 12GB (16GB recommended):
- Colima:
colima stop && colima start --vm-type vz --vz-rosetta --memory 16 --cpu 8
- Linux: Docker runs natively, no memory tuning needed
just build-assets fails with "Release file not valid yet"
The container VM's clock has drifted. The builder uses Acquire::Check-Valid-Until=false to work around this, but if you see this error on an old builder version:
- Colima:
colima stop && colima start --vm-type vz --vz-rosetta --memory 16 --cpu 8 (resets clock)
- Docker Desktop: restart Docker Desktop
just build-assets fails (other)
- Check Docker is running:
docker info
- Check the profile contract is valid:
capsem-admin profile check config/profiles/code/profile.toml --config-root config
- On first run, Docker image pulls can be slow
just run fails with "assets not found"
Run just build-assets first. Assets are gitignored and must be built locally.
cargo run or cargo test crashes with signing error
.cargo/config.toml must exist and be tracked in git -- it configures the custom runner (scripts/run_signed.sh) that signs binaries with Virtualization.framework entitlements before execution
- If missing:
git checkout .cargo/config.toml
- The justfile
_sign recipe signs separately, so just run works even without the cargo runner -- but direct cargo run/cargo test and IDE integrations will crash
- Lesson: bare
.gitignore patterns (no / prefix) match at any depth. Always anchor with / when you mean root-only (e.g., /config.toml not config.toml), or you risk silently ignoring files in subdirectories like .cargo/
Cross-compile errors
- Check
.cargo/config.toml has linker config for musl targets
- Run
rustup target add aarch64-unknown-linux-musl x86_64-unknown-linux-musl
- Platform-specific type issues: use
as _ for libc calls (see /dev-rust-patterns)
Disk full / Colima eating all disk space
Docker builds accumulate images, build cache, and stopped containers inside the Colima VM. The VM uses a Virtualization.framework raw disk that only grows, never shrinks on its own -- even after docker system prune, macOS doesn't get the space back.
The _docker-gc recipe runs automatically after build-assets, cross-compile, and test-install to prevent this. It prunes containers, images >72h, build cache >72h, and runs fstrim to release freed blocks back to macOS. If disk is already full:
docker system prune -af --volumes
colima ssh -- sudo fstrim /mnt/lima-colima
To check current state: colima ssh -- docker system df (inside VM) and du -sh ~/.colima (host).
Docker credential helper error (docker-credential-osxkeychain not found)
When Colima is installed standalone (without Docker Desktop), ~/.docker/config.json may reference a credential helper that doesn't exist. The symptom is docker run failing to pull images with exec: "docker-credential-osxkeychain": executable file not found.
Fix: set credsStore to empty string in ~/.docker/config.json:
{ "credsStore": "" }
just doctor checks for this under "Container Runtime" and will flag the mismatch.
VM boot hangs
- Check codesigning:
codesign -dvv target/debug/capsem 2>&1 | grep entitlements
- Check assets exist:
ls assets/arm64/vmlinuz assets/arm64/rootfs.erofs
- Check kernel architecture matches host: wrong-arch kernel causes silent hang.
VmConfig::build() now rejects mismatched kernels at config time.
- Try with debug logs:
RUST_LOG=capsem=debug just run
Doctor architecture
The doctor system is three bash scripts:
scripts/
doctor-common.sh # Entry point, cross-platform checks, fix registry, recap
doctor-macos.sh # macOS: Colima, Rosetta, codesigning, brew hints
doctor-linux.sh # Linux: KVM, apt/dnf hints
just doctor calls doctor-common.sh. just doctor-fix calls doctor-common.sh --fix.
Fix registry
All fixable issues use an ordered fix registry defined at the top of doctor-common.sh. Each entry has an ID, command, and description. Checks call fixable <id> <label> to mark a fix as needed. Fixes run in registry order (dependency order), deduped by design.
Registry order (each depends on the ones above it):
rustup-targets -- cross-compile targets
llvm-tools -- rust-lld linker
cargo-llvm-cov, cargo-audit, b3sum, cargo-tauri -- cargo tools
entitlements, cargo-config, run-signed -- git checkout config files
pnpm-install -- frontend deps
build-assets -- VM kernel + rootfs (needs docker)
pack-initrd -- guest binaries (needs assets)
Design rules
- Fixable checks use
fixable <id> <label>, not raw fail(). This registers the fix in the ordered registry.
- Non-fixable checks use
fail() with an install hint. System tools (node, docker, etc.) can't be auto-installed safely.
- Platform-specific checks live in
doctor-macos.sh / doctor-linux.sh. Each defines check_platform() and tool_hint().
- Test, don't just check. The codesigning section compiles and signs a test binary.
docker buildx version tests functionality, not just file existence.
- Recover Colima before declaring Docker dead. On macOS, a stale Colima VM
can leave the Docker socket present but unusable. Use the Colima recovery
discipline above before filing or reporting a Docker/Colima blocker.
- Bootstrap calls doctor.
bootstrap.sh checks bare minimums (bash, git, curl, rustup, just), installs Python/frontend deps, then runs doctor-common.sh --fix.