#!/bin/sh set -eu FIXUID_BIN="${FIXUID_BIN:-fixuid}" INIT_BIN="${INIT_BIN:-/usr/local/bin/init-persistent-data}" DUMB_INIT_BIN="${DUMB_INIT_BIN:-/usr/bin/dumb-init}" CODE_SERVER_BIN="${CODE_SERVER_BIN:-/usr/bin/code-server}" SPACES_SYNC_BIN="${SPACES_SYNC_BIN:-/usr/local/bin/sync-workspace-spaces}" # Preserve the UID-repair behavior from the official image when the container # runtime permits setuid privilege changes. Platforms with NoNewPrivileges, # such as DigitalOcean App Platform, can safely retain the image-defined coder # UID because all fallback runtime paths are already writable by that user. if fixuid_output="$("${FIXUID_BIN}" -q 2>/dev/null)"; then eval "${fixuid_output}" else printf '%s\n' \ '[code-server] WARNING: fixuid is unavailable; continuing with the image-defined coder UID.' \ >&2 fi unset fixuid_output # Preserve the official image's optional user-renaming behavior. if [ "${DOCKER_USER-}" ]; then USER="${DOCKER_USER}" export USER if [ -z "$(id -u "${DOCKER_USER}" 2>/dev/null)" ]; then echo "${DOCKER_USER} ALL=(ALL) NOPASSWD:ALL" \ | sudo tee -a /etc/sudoers.d/nopasswd >/dev/null sudo usermod --login "${DOCKER_USER}" coder sudo groupmod -n "${DOCKER_USER}" coder sudo sed -i '/coder/d' /etc/sudoers.d/nopasswd fi fi export PORT="${PORT:-7860}" export WORKSPACE="${WORKSPACE:-/home/coder/workspace}" export DATA_ROOT="${DATA_ROOT:-/data}" export CODER_HOME="${CODER_HOME:-/home/coder}" export BOOTSTRAP_ROOT="${BOOTSTRAP_ROOT:-/opt/bootstrap}" export CODE_SERVER_BIN export CODE_SERVER_CONFIG="${CODE_SERVER_CONFIG:-/data/code-server/config.yaml}" export CODE_SERVER_USER_DATA="${CODE_SERVER_USER_DATA:-/data/code-server/user-data}" export CODE_SERVER_EXTENSIONS="${CODE_SERVER_EXTENSIONS:-/data/code-server/extensions}" export UV_CACHE_DIR="${UV_CACHE_DIR:-/data/cache/uv}" export HF_HOME="${HF_HOME:-/data/cache/huggingface}" export CLAUDE_CONFIG_DIR="${CLAUDE_CONFIG_DIR:-/data/claude}" export CLAUDE_SYSTEM_BIN="${CLAUDE_SYSTEM_BIN:-/usr/local/bin/claude-system}" export CLAUDE_VSCODE_WRAPPER="${CLAUDE_VSCODE_WRAPPER:-/usr/local/bin/claude-vscode-wrapper}" export SPACES_SYNC_BIN # Route both the Claude Code CLI and VS Code extension through OpenRouter. # OPENROUTER_API_KEY is supplied as a Hugging Face Space secret. Keep the # Anthropic API key explicitly empty to avoid Claude Code falling back to # Anthropic account authentication. export ANTHROPIC_BASE_URL="https://openrouter.ai/api" export ANTHROPIC_API_KEY="" export ANTHROPIC_MODEL="anthropic/claude-opus-4.8" export ANTHROPIC_DEFAULT_OPUS_MODEL="anthropic/claude-opus-4.8" export ANTHROPIC_DEFAULT_SONNET_MODEL="anthropic/claude-opus-4.8" export ANTHROPIC_DEFAULT_HAIKU_MODEL="anthropic/claude-opus-4.8" export CLAUDE_CODE_SUBAGENT_MODEL="anthropic/claude-opus-4.8" if [ -n "${OPENROUTER_API_KEY-}" ]; then export ANTHROPIC_AUTH_TOKEN="${OPENROUTER_API_KEY}" else unset ANTHROPIC_AUTH_TOKEN 2>/dev/null || true printf '%s\n' \ '[hf-code-server] WARNING: OPENROUTER_API_KEY is not configured; Claude Code will not authenticate.' \ >&2 fi "${INIT_BIN}" if [ -n "${SPACES_BUCKET-}" ]; then "${SPACES_SYNC_BIN}" watch & fi cd "${WORKSPACE}" # --ignore-last-opened makes the command-line folder authoritative instead of # restoring an older /home/coder session from persistent editor state. exec "${DUMB_INIT_BIN}" "${CODE_SERVER_BIN}" \ --bind-addr "0.0.0.0:${PORT}" \ --auth password \ --config "${CODE_SERVER_CONFIG}" \ --user-data-dir "${CODE_SERVER_USER_DATA}" \ --extensions-dir "${CODE_SERVER_EXTENSIONS}" \ --disable-telemetry \ --disable-update-check \ --ignore-last-opened \ "${WORKSPACE}"