docker
Manage Docker containers, images, volumes, and Compose stacks via the `docker` CLI — list, inspect, logs, run, build, stop, remove, compose up/down. Use for local container ops.
git clone --depth 1 https://github.com/AtomicBot-ai/atomic-agent /tmp/docker && cp -r /tmp/docker/starter-skills/docker ~/.claude/skills/dockerSKILL.md
# docker
Drive local containers with the [`docker`](https://docs.docker.com/) CLI. Reads
(`ps`, `images`, `logs`, `inspect`) are safe to run directly; **writes**
(`run`, `build`, `stop`, `rm`, `rmi`, `prune`, `compose down`) mutate state and
surface the runtime approval gate — confirm intent with the user first.
## Setup health check (run first, every session)
Verify with **one solo step**:
```
[{ "tool": "os.shell.run", "args": { "cmd": "docker", "args": ["version", "--format", "{{.Server.Version}}"] } }]
```
Outcome map:
- `exit 0` + version → daemon reachable, proceed.
- `command not found: docker` → enter **Setup playbook → "docker missing"**.
- `Cannot connect to the Docker daemon` → enter **Setup playbook → "daemon not running"**.
## Setup playbook (when prerequisites are missing)
OFFER help; do not dump docs on the user.
### docker missing
Reply (solo `reply` step):
> "Docker is not installed. On macOS, install Docker Desktop
> (https://docker.com/products/docker-desktop) or run `brew install --cask
> docker`, then launch the app. Tell me when it is running and I will re-check."
Do NOT attempt to install Docker Desktop silently — it needs a GUI launch and
privileged setup.
### daemon not running
> "Docker is installed, but the daemon is not running. Open Docker Desktop (or
> run `systemctl start docker` on Linux), then tell me when it is up."
Do not try to start the daemon via `os.shell.run` on macOS — it requires the
Desktop app.
## When to use
- "List running containers / images", "show logs for <container>".
- "Run / build / stop / remove a container", "bring a compose stack up/down".
- Inspecting container config, ports, networks, volumes.
## When NOT to use
- Pushing to a registry or production deploys — confirm explicitly; high risk.
- Editing Dockerfiles — use `os.fs.*` tools, then `docker build`.
- Orchestration beyond Compose (Kubernetes) — out of scope; use a `kubectl` skill.
## Common operations
All examples invoke `os.shell.run` with `cmd: "docker"`. Reads are listed first.
### Reads (safe to run directly)
| Goal | args |
|---|---|
| Running containers | `["ps"]` |
| All containers | `["ps", "-a"]` |
| List images | `["images"]` |
| Container logs (last 100) | `["logs", "--tail", "100", "<name>"]` |
| Inspect | `["inspect", "<name>"]` |
| Resource stats (one shot) | `["stats", "--no-stream"]` |
| Compose status | `["compose", "ps"]` |
### Writes (confirm with the user first; approval gate fires)
| Goal | args |
|---|---|
| Run detached | `["run", "-d", "--name", "web", "-p", "8080:80", "nginx"]` |
| Build image | `["build", "-t", "myapp:dev", "."]` |
| Stop container | `["stop", "<name>"]` |
| Remove container | `["rm", "<name>"]` |
| Remove image | `["rmi", "myapp:dev"]` |
| Exec a command | `["exec", "<name>", "sh", "-c", "echo hi"]` |
| Compose up | `["compose", "up", "-d"]` |
| Compose down | `["compose", "down"]` |
## Bind-mounted projects: interpreter-bound directories are not portable
Applies **only when a host directory is bind-mounted into a container**
(`-v "$PWD:/app"`, or a Compose `volumes:` entry). Skip this section entirely
for native, non-container work — a plain host-side `python -m venv` is fine and
needs no warning.
A virtual environment records **absolute paths to the interpreter that built
it**. A `.venv` created inside a container stores container paths, so it stops
working the moment it is used from the host — and the reverse is equally true.
Because the directory lives in the mounted project folder, it outlives the
container and looks like an ordinary project artifact. It is not one.
Other build output written into the mount is unusable across runtimes for a
related but distinct reason — platform and ABI mismatch rather than baked-in
paths: `node_modules` containing compiled native addons, and Go or Rust build
caches. `.tox` and `.nox` hit both, since they contain real virtual
environments. Treat all of them as runtime-specific.
This is normal Python behaviour, not a fault in the project or the container.
### Worked example
Create the environment inside a container against a bind mount:
```
[{ "tool": "os.shell.run", "args": { "cmd": "docker", "args": ["run", "--rm", "-v", "/Users/me/proj:/app", "-w", "/app", "python:3.12", "python", "-m", "venv", ".venv"] } }]
```
Inside the container the environment resolves correctly:
```
/app/.venv/bin/python3.12 -> /usr/local/bin/python3.12 # exists in the image
/app/.venv/bin/python3 -> python3.12 # relative
/app/.venv/bin/python -> python3.12 # relative
```
Note which link is absolute: the **versioned** name. `python` and `python3` are
relative links pointing at it, so inspecting `bin/python3` alone shows a bare
`python3.12` and reveals nothing. The interpreter path is baked in twice — in
that versioned symlink, and in the `home` key of `pyvenv.cfg`. Back on the host
neither target exists, so the very same `.venv` is dead:
```
$ .venv/bin/python --version
.venv/bin/python: No such file or directory
$ grep '^home' .venv/pyvenv.cfg
home = /usr/local/bin # a container path
```
Recreate it on the host with the host interpreter — into a **separate**
directory, so the two never overwrite each other:
```
[{ "tool": "os.shell.run", "args": { "cmd": "python3", "args": ["-m", "venv", ".venv-host"] } }]
```
Then install into whichever environment matches the runtime you are about to
use. Do not attempt to "repair" a foreign `.venv`; recreating is faster and
reliable.
### Guidance
- Never assume a container-created `.venv` can be activated on the host, or the
other way round. Recreate it per runtime instead.
- **Preferred:** build the container's environment *outside* the mount — create
it at a path like `/opt/venv` and put `/opt/venv/bin` first on `PATH`.
Nothing interpreter-bound is then written into the user's project folder, so
the problem cannot arise at all. Fall back to distinct in-prRead macOS Calendar events via the `icalBuddy` CLI and create events via AppleScript (osascript). Use to check the user's calendar, agenda, upcoming events, or add an event on macOS.
Manage Apple Notes via the `memo` CLI on macOS — create, view, search, edit, export.
Manage Apple Reminders via the `remindctl` CLI on macOS — list, add, complete, delete, manage lists.
Transcribe speech from audio files (mp3, m4a, wav, ogg, flac, webm) to text using the local `whisper` CLI — no API key. Use whenever a task hinges on the spoken content of an audio attachment.
Currency exchange rates and conversion via the Frankfurter API (no key). Use for FX rates, "convert X to Y", or historical/time-series rates.
Process audio and video with the `ffmpeg` / `ffprobe` CLIs — convert, trim, extract audio, resize, change format, make GIFs, inspect media. Use for any audio/video transformation.
Drive GitHub via the official `gh` CLI — repos, issues, pull requests, releases, gists, Actions runs, and raw REST through `gh api`. Use when the user asks to inspect or manage GitHub.
Use the `gog` CLI for Google Workspace tasks across Gmail, Calendar, Drive, Docs, Sheets, Contacts, and related services. Use when the user asks to check email, search Gmail, inspect calendar events, find Drive files, read Docs or Sheets, or manage Google Workspace data through `gog`.