| name | convert-to-apple-container |
| description | Historical migration skill for the old Docker/Apple Container runtime. Current NanoClaw uses a local Codex worker and does not require Apple Container. |
Convert 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.
Historical status: The current default runtime no longer has src/container-runtime.ts or a container lifecycle path. Do not apply this skill to the current Codex-worker architecture unless you are deliberately reviving the old container runtime. For normal installs, Apple Container is not required.
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:
.env shadowing via mount --bind inside the container (Apple Container only supports directory mounts, not file mounts like Docker's /dev/null overlay)
- Container runner: main-group containers start as root for
mount --bind, then drop privileges via setpriv
What stays the same:
- Mount security/allowlist validation
- All exported interfaces and IPC protocol
- Non-main container behavior (still uses
--user flag)
- All other functionality
Prerequisites
Verify Apple Container is installed:
container --version && echo "Apple Container ready" || echo "Install Apple Container first"
If not installed:
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.ts with the Apple Container implementation
- Replaces
src/container-runtime.test.ts with Apple Container-specific tests
- Updates
src/container-runner.ts with .env shadow mount fix and privilege dropping
- Updates
container/Dockerfile with entrypoint that shadows .env via mount --bind
- Updates
container/build.sh to default to container runtime
- 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 invariants
modify/src/container-runner.ts.intent.md — .env shadow and privilege drop changes
modify/container/Dockerfile.intent.md — entrypoint changes for .env shadowing
modify/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:
Runtime won't start:
container system start
container system status
Image build fails:
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 |