Skip to main content

Environment Variables

All configurable environment variables live in compose.yaml under the dev service. The init script writes them into /config on every boot, so they take effect immediately.

ANTHROPIC_AUTH_TOKEN is the only value you must provide: without it, Claude Code won't start. Every other variable falls back to the default shown in its table.

How it works​

compose.yaml init.sh /config/.bashrc
(dev service) → writes vars → /config/.zshrc

Edit compose.yaml, recreate the container, done.

Claude Code / API​

Env varDefaultWhat it does
ANTHROPIC_BASE_URL(empty)Leave empty for Anthropic. Set to a third-party URL (DeepSeek, OpenRouter, etc.) to use a different provider
ANTHROPIC_AUTH_TOKEN(required)Your API key. Get one at console.anthropic.com
ANTHROPIC_MODELclaude-opus-4-8Default model Claude Code uses for all tasks
ANTHROPIC_DEFAULT_OPUS_MODELclaude-opus-4-8Model used when Opus tier is selected
ANTHROPIC_DEFAULT_SONNET_MODELclaude-sonnet-4-6Model used when Sonnet tier is selected
ANTHROPIC_DEFAULT_HAIKU_MODELclaude-haiku-4-5Model for Haiku tier (lighter tasks, subagents)
CLAUDE_CODE_SUBAGENT_MODELclaude-haiku-4-5Model for background agents spawned by Claude Code
CLAUDE_CODE_EFFORT_LEVELmaxReasoning depth: low, medium, high, or max

Using a different provider​

If ANTHROPIC_BASE_URL is left empty, Claude Code connects directly to Anthropic's API. To use a third-party provider, set the URL and adjust model names.

DeepSeek example:

ANTHROPIC_BASE_URL: https://api.deepseek.com/anthropic
ANTHROPIC_AUTH_TOKEN: sk-... # your DeepSeek key
ANTHROPIC_MODEL: deepseek-v4-pro[1m]
ANTHROPIC_DEFAULT_HAIKU_MODEL: deepseek-v4-flash
CLAUDE_CODE_SUBAGENT_MODEL: deepseek-v4-flash

OpenRouter example:

ANTHROPIC_BASE_URL: https://openrouter.ai/api/anthropic
ANTHROPIC_AUTH_TOKEN: sk-or-v1-... # your OpenRouter key
ANTHROPIC_MODEL: anthropic/claude-opus-4-8

How to apply changes​

Edit compose.yaml, recreate the container:

docker compose up -d --force-recreate

Or, for a quick test without recreating:

nano ~/.zshrc
source ~/.zshrc

Git / GitHub​

Env varWhat it does
GIT_USER_NAMEYour name for commits (git config user.name)
GIT_USER_EMAILYour email for commits (git config user.email)
GITHUB_TOKENGitHub fine-grained PAT, used by both git (via gh credential helper) and the gh CLI

Creating a GitHub token​

Go to github.com/settings/tokens?type=beta:

  1. Repository access: "Only select repositories", pick which ones
  2. Permissions: Contents (read/write as needed), Metadata (read, auto-selected)
  3. Copy the github_pat_... token into GITHUB_TOKEN

The token can be revoked or scoped anytime. No account password stored: if the container is compromised, you only lose access to the repos you explicitly granted.

After setting these and recreating the container, both git clone/push/pull and gh CLI commands (gh pr, gh issue, etc.) use the token automatically.

Container settings​

Env varDefaultWhat it does
CUSTOM_USERabcCustom username. Replaces the default abc user on boot
PASSWORD(required)Login password for the ttyd web terminal
SUDO_PASSWORD(required)Sudo password inside the container. Also used for SSH login
PUID1000User ID for file permissions
PGID1000Group ID for file permissions
TZEurope/RomeTimezone

Session behavior​

These variables are not set in compose.yaml. They are passed at connection time (by your SSH client or in the shell) to control what happens when you log in.

Env varDefaultWhat it does
NO_CLAUDE(unset)Set to 1 to skip Claude auto-launch and get a plain shell
TMUX_AUTO(unset)Set to 1 to auto-attach a persistent tmux session on login
TMUX_TIMEOUT(unset)Hours before a detached tmux session is auto-killed (-1 = never, 0 = on detach, N = after N hours)

Claude auto-launch​

Claude launches automatically on every login (both SSH and web terminal). You land in /workplace with Claude ready. Exiting Claude (/exit or Ctrl+D) returns you to a normal shell prompt.

To skip the auto-launch:

NO_CLAUDE=1 ssh abc@<server> -p 2222 # → plain shell, no Claude

Persistent sessions with tmux​

Set TMUX_AUTO=1 on your SSH client (e.g. Termius environment variables) to wrap every session in tmux. When you disconnect, tmux keeps running. When you reconnect, you reattach to the same session with Claude still there.

# In Termius: set TMUX_AUTO=1 in the host's environment variables
# In a terminal:
TMUX_AUTO=1 ssh abc@<server> -p 2222 # → auto-attached to tmux "main"

Use TMUX_TIMEOUT to auto-clean detached sessions. For example, TMUX_TIMEOUT=2 kills sessions that have been detached for more than 2 hours. Run tmux-keep inside a session to override this and keep it alive indefinitely.

See Daily Workflow for full tmux usage.

Webhook Notifications​

When Claude Code finishes responding and waits for input (60+ seconds idle), a webhook can fire if no one is connected to the container. This is useful for long-running tasks: start Claude inside tmux, disconnect, and get notified when Claude is ready for your next prompt.

The feature uses Claude Code's built-in idle_prompt Notification hook. No external daemon or polling is required.

Env varDefaultWhat it does
CLAUDE_WEBHOOK_URL(empty)Webhook endpoint URL. Leave empty to disable. Receives a JSON POST when Claude goes idle with no active connections
CLAUDE_WEBHOOK_IDLE60Seconds of terminal silence before Claude is considered idle (minimum 60, matching Claude Code's hook timing)

Webhook payload​

{
"event": "claude_idle",
"timestamp": "2026-07-24T15:30:00Z",
"hostname": "claude-world",
"session_id": "35e6a910-...",
"last_output": "The fix has been applied to utils.py.\n\nAll tests pass.\n\n> What should I do next?"
}
FieldDescription
eventFixed value "claude_idle"
timestampUTC ISO 8601 timestamp
hostnameContainer hostname
session_idClaude Code session ID that triggered the hook
last_outputLast text message from Claude (up to 2000 characters)

How it works​

  1. You connect via SSH or web terminal, Claude auto-launches
  2. You give Claude a task, it starts processing
  3. You disconnect (tmux keeps Claude running if TMUX_AUTO=1)
  4. Claude finishes the task and waits for input
  5. After 60 seconds of idle, Claude Code fires the idle_prompt hook
  6. The hook checks who for active connections
  7. If no one is connected, it sends the webhook with Claude's last output

The webhook can point to any HTTP endpoint: Slack webhooks, Discord webhooks, Telegram bots, Zapier, n8n, ntfy, or a custom server.