Files
claudaris/docs/claudaris.md
T
2026-07-21 02:17:06 -07:00

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/.bashrc and $DATA_DIR/home/bash_aliases — copied from files/bashrc and files/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/ssh exists, removed otherwise. Compose merges this file automatically when present; it's the only mount that can't live in docker-compose.yml directly, 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.