5.1 KiB
The claudaris executable
./claudaris is a single bash script at the repo root that wraps
docker compose (see docker-compose.yml). It cds to its own directory
first, so it can be invoked from anywhere. Run it with no arguments (or
help) for usage. Plain docker compose subcommands work directly too, as
long as .env is present (compose reads it automatically) — claudaris
just adds the config wizard and the host-side seeding/mount logic below.
Usage: ./claudaris <command>
Commands:
config, configure Interactive wizard to write .env with your settings
build Build the container image (always --no-cache --pull)
start Start (or create) the container
connect Start the container if needed, then attach a tmux session
remove, stop, rm Stop and remove the container
help Show this message
All commands source .env if present (gitignored, written by config),
falling back to NAME=claudaris and the defaults listed below.
config (alias: configure)
Interactive wizard: prompts for NAME, DATA_DIR, and WORKSPACE_DIR,
showing the current/default value for each (enter keeps it), then writes all
three to .env. Safe to re-run any time. See
Getting started for what each variable
means.
build
sudo ./claudaris build
Runs docker compose build --no-cache --pull. Always uncached so a
rebuild picks up the latest Arch packages, the latest Claude Code release
(installed straight into /root in the image), and the latest
MCP server releases.
start
Runs docker compose up -d, which creates the container if it doesn't exist
and (re)starts it otherwise, per docker-compose.yml. Container/image name,
volumes, and workspace mount come from NAME/DATA_DIR/WORKSPACE_DIR,
which compose reads from .env the same way claudaris does — mount
changes in docker-compose.yml take effect on the next up -d without
needing remove first.
Before calling compose, start seeds the host side, without overwriting
anything that already exists:
$DATA_DIR/home/.bashrcand$DATA_DIR/home/bash_aliases— copied fromfiles/bashrcandfiles/bash_aliases.$DATA_DIR/claude/credentials.json,$DATA_DIR/claude/claude.json, and$DATA_DIR/opencode/auth.json— created empty. Seeding them as files matters: if Docker had to create the mount targets itself it would make directories, breaking the login mounts.docker-compose.override.yml(gitignored) — written to add the SSH mount below if$DATA_DIR/sshexists, removed otherwise. Compose merges this file automatically when present; it's the only mount that can't live indocker-compose.ymldirectly, since compose has no way to make a volume conditional on a host path existing.
The mounts, all declared in docker-compose.yml:
| Mount | Purpose |
|---|---|
hostname: ${NAME} |
Prompt reads root@$NAME instead of a random container ID. |
$DATA_DIR/home/.bashrc → /root/.bashrc |
Per-host shell config, editable without a rebuild. |
$DATA_DIR/home/bash_aliases → /opt/dotfiles/bash_aliases |
Per-host aliases and MCP env vars; sourced by .bashrc. |
$DATA_DIR/claude/credentials.json → /root/.claude/.credentials.json |
Claude Code OAuth token. |
$DATA_DIR/claude/claude.json → /root/.claude.json |
Claude Code account/onboarding state and user-scope MCP config. |
$DATA_DIR/opencode/auth.json → /root/.local/share/opencode/auth.json |
OpenCode provider credentials (API keys/OAuth tokens). |
$WORKSPACE_DIR → /projects |
Your project workspace. |
$DATA_DIR/ssh → /root/.ssh (read-only, override file, only if the host dir exists) |
Opt-in SSH access to other machines. |
The login files are individual file mounts rather than a directory volume on
purpose: both Claude Code and OpenCode likely save them atomically (write a
temp file, then rename() over the target), and rename() onto a symlink
replaces the symlink instead of writing through it — which would silently
break persistence. A bind mount doesn't have that failure mode.
connect
sudo ./claudaris connect
Runs docker compose up -d (a no-op if already running) and then
docker compose exec claudaris bash.
The explicit up -d matters because the container stops itself: the
entrypoint creates the main tmux session and exits once that session ends
(tmux defaults — a window closes when its shell exits, the session closes
with its last window). There's no --restart policy, so after a Ctrl+D the
container sits stopped until connect (or start) brings it back. tmux
itself stays installed and available — run it manually inside the container
(the in-container tmux wrapper attaches to the main session if it exists
and creates it otherwise) if you want it.
remove (aliases: stop, rm)
Runs docker compose down, stopping and removing the container so the next
start recreates it fresh — needed after a build to actually run the new
image, or after changing mounts. Nothing under $DATA_DIR or
$WORKSPACE_DIR is touched.