convert-to-apple-container
npx machina-cli add skill qwibitai/nanoclaw/convert-to-apple-container --openclawConvert to Apple Container
This skill switches NanoClaw's container runtime from Docker to Apple Container (macOS-only). It uses the skills engine for deterministic code changes, then walks through verification.
What this changes:
- Container runtime binary:
docker→container - Mount syntax:
-v path:path:ro→--mount type=bind,source=...,target=...,readonly - Startup check:
docker info→container system status(with auto-start) - Orphan detection:
docker ps --filter→container ls --format json - Build script default:
docker→container - Dockerfile entrypoint:
.envshadowing viamount --bindinside the container (Apple Container only supports directory mounts, not file mounts like Docker's/dev/nulloverlay) - Container runner: main-group containers start as root for
mount --bind, then drop privileges viasetpriv
What stays the same:
- Mount security/allowlist validation
- All exported interfaces and IPC protocol
- Non-main container behavior (still uses
--userflag) - All other functionality
Prerequisites
Verify Apple Container is installed:
container --version && echo "Apple Container ready" || echo "Install Apple Container first"
If not installed:
- Download from https://github.com/apple/container/releases
- Install the
.pkgfile - Verify:
container --version
Apple Container requires macOS. It does not work on Linux.
Phase 1: Pre-flight
Check if already applied
Read .nanoclaw/state.yaml. If convert-to-apple-container is in applied_skills, skip to Phase 3 (Verify). The code changes are already in place.
Check current runtime
grep "CONTAINER_RUNTIME_BIN" src/container-runtime.ts
If it already shows 'container', the runtime is already Apple Container. Skip to Phase 3.
Phase 2: Apply Code Changes
Run the skills engine to apply this skill's code package. The package files are in this directory alongside this SKILL.md.
Initialize skills system (if needed)
If .nanoclaw/ directory doesn't exist yet:
npx tsx scripts/apply-skill.ts --init
Or call initSkillsSystem() from skills-engine/migrate.ts.
Apply the skill
npx tsx scripts/apply-skill.ts .claude/skills/convert-to-apple-container
This deterministically:
- Replaces
src/container-runtime.tswith the Apple Container implementation - Replaces
src/container-runtime.test.tswith Apple Container-specific tests - Updates
src/container-runner.tswith .env shadow mount fix and privilege dropping - Updates
container/Dockerfilewith entrypoint that shadows .env viamount --bind - Updates
container/build.shto default tocontainerruntime - Records the application in
.nanoclaw/state.yaml
If the apply reports merge conflicts, read the intent files:
modify/src/container-runtime.ts.intent.md— what changed and invariantsmodify/src/container-runner.ts.intent.md— .env shadow and privilege drop changesmodify/container/Dockerfile.intent.md— entrypoint changes for .env shadowingmodify/container/build.sh.intent.md— what changed for build script
Validate code changes
npm test
npm run build
All tests must pass and build must be clean before proceeding.
Phase 3: Verify
Ensure Apple Container runtime is running
container system status || container system start
Build the container image
./container/build.sh
Test basic execution
echo '{}' | container run -i --entrypoint /bin/echo nanoclaw-agent:latest "Container OK"
Test readonly mounts
mkdir -p /tmp/test-ro && echo "test" > /tmp/test-ro/file.txt
container run --rm --entrypoint /bin/bash \
--mount type=bind,source=/tmp/test-ro,target=/test,readonly \
nanoclaw-agent:latest \
-c "cat /test/file.txt && touch /test/new.txt 2>&1 || echo 'Write blocked (expected)'"
rm -rf /tmp/test-ro
Expected: Read succeeds, write fails with "Read-only file system".
Test read-write mounts
mkdir -p /tmp/test-rw
container run --rm --entrypoint /bin/bash \
-v /tmp/test-rw:/test \
nanoclaw-agent:latest \
-c "echo 'test write' > /test/new.txt && cat /test/new.txt"
cat /tmp/test-rw/new.txt && rm -rf /tmp/test-rw
Expected: Both operations succeed.
Full integration test
npm run build
launchctl kickstart -k gui/$(id -u)/com.nanoclaw
Send a message via WhatsApp and verify the agent responds.
Troubleshooting
Apple Container not found:
- Download from https://github.com/apple/container/releases
- Install the
.pkgfile - Verify:
container --version
Runtime won't start:
container system start
container system status
Image build fails:
# Clean rebuild — Apple Container caches aggressively
container builder stop && container builder rm && container builder start
./container/build.sh
Container can't write to mounted directories: Check directory permissions on the host. The container runs as uid 1000.
Summary of Changed Files
| File | Type of Change |
|---|---|
src/container-runtime.ts | Full replacement — Docker → Apple Container API |
src/container-runtime.test.ts | Full replacement — tests for Apple Container behavior |
src/container-runner.ts | .env shadow mount removed, main containers start as root with privilege drop |
container/Dockerfile | Entrypoint: mount --bind for .env shadowing, setpriv privilege drop |
container/build.sh | Default runtime: docker → container |
Source
git clone https://github.com/qwibitai/nanoclaw/blob/main/.claude/skills/convert-to-apple-container/SKILL.mdView on GitHub Overview
This skill switches NanoClaw's container runtime from Docker to Apple Container (macOS-only). It uses the skills engine for deterministic code changes, then walks through verification. It updates runtime, mounts, and entrypoints to leverage macOS native isolation.
How This Skill Works
The skill deterministically replaces the Docker-based runtime with Apple Container, updates tests to Apple Container-specific tests, and modifies the runner and build scripts. It changes the container runtime binary from docker to container, converts -v path:path:ro mounts to --mount type=bind,source=...,target=...,readonly, updates the startup check and orphan detection commands, and adjusts the Dockerfile entrypoint to shadow .env via mount --bind. It also applies privilege dropping in the main-group containers and records the change in state.
When to Use It
- You want Apple Container instead of Docker on macOS
- You are setting up NanoClaw on macOS and prefer the native runtime
- You need Apple Container-specific tests and behavior
- You want .env shadow mounting and privilege handling aligned with Apple Container
- You want to avoid Docker on macOS while keeping existing interfaces
Quick Start
- Step 1: Verify Apple Container is installed: container --version
- Step 2: Initialize skills (if needed) and apply the skill: npx tsx scripts/apply-skill.ts .claude/skills/convert-to-apple-container
- Step 3: Verify the runtime and tests: container system status; ./container/build.sh; echo '{}' | container run -i --entrypoint /bin/echo nanoclaw-agent:latest "Container OK"
Best Practices
- Verify Apple Container is installed before applying
- Check .nanoclaw/state.yaml to avoid reapplying if already done
- Review and test the Apple Container-specific tests after apply
- Run npm test and npm run build to validate changes
- Verify basic execution and mounts with container system status and sample runs
Example Use Cases
- Migrating an existing macOS NanoClaw project from Docker to Apple Container for native isolation
- Applying the skill and confirming that container runtime binaries now reference container
- Running pre-flight checks and ensuring state.yaml reflects the applied change
- Building the container image with the new Apple Container runtime
- Executing a simple test command like echo Container OK via container run