diff --git a/.dockerignore b/.dockerignore index 9bcce7a80897..c08bc0c03825 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,3 +1,7 @@ +# Ignore everything by default ** -!release-packages -!ci + +# Include only what's needed for the Railway build +!Dockerfile +!railway-entrypoint.sh +!railway.json diff --git a/.github/workflows/deploy-image.yml b/.github/workflows/deploy-image.yml new file mode 100644 index 000000000000..739ca3ae860a --- /dev/null +++ b/.github/workflows/deploy-image.yml @@ -0,0 +1,46 @@ +# Builds and pushes the Docker image to GitHub Container Registry +name: Publish Docker Image + +on: + push: + branches: [main] + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: ${{ github.repository }} + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@v5 + with: + images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} + tags: | + type=raw,value=latest + type=sha,prefix= + + - name: Build and push Docker image + uses: docker/build-push-action@v5 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000000..3833a4ce7077 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,116 @@ +# ============================================================================ +# Claude Code Server - Browser-based VS Code with AI Coding Assistants +# https://github.com/sphinxcode/claude-code-server +# ============================================================================ + +FROM codercom/code-server:4.108.0 + +USER root + +# ============================================================================ +# SYSTEM DEPENDENCIES +# Install gosu, Node.js 22, Python/uv, and essential tools +# Cache bust: 2026-01-30-v6 +# ============================================================================ + +RUN curl -fsSL https://deb.nodesource.com/setup_22.x | bash - \ + && apt-get update \ + && apt-get install -y --no-install-recommends \ + gosu \ + nodejs \ + python3 \ + python3-pip \ + python3-venv \ + pipx \ + git \ + curl \ + wget \ + unzip \ + jq \ + htop \ + vim \ + nano \ + ripgrep \ + && npm install -g npm@latest \ + && pip3 install --break-system-packages uv \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# ============================================================================ +# PERSISTENCE CONFIGURATION +# Default to /home/clauder for new deployments +# ============================================================================ + +ENV HOME=/home/clauder +ENV USER=clauder + +# XDG Base Directory Specification +ENV XDG_DATA_HOME=/home/clauder/.local/share +ENV XDG_CONFIG_HOME=/home/clauder/.config +ENV XDG_CACHE_HOME=/home/clauder/.cache +ENV XDG_STATE_HOME=/home/clauder/.local/state + +# PATH: Volume paths FIRST (user installs), image paths LAST (fallbacks) +ENV PATH="/home/clauder/.local/bin:/home/clauder/.local/node/bin:/home/clauder/.claude/local:/home/clauder/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:${PATH}" + +# Custom startup scripts directory +ENV ENTRYPOINTD=/home/clauder/entrypoint.d + +# ============================================================================ +# USER SETUP +# Create clauder user (UID 1000) with passwordless sudo +# - Stays non-root for Claude YOLO mode compatibility +# - Can use sudo for package installs (apt, npm -g, pip, etc.) +# ============================================================================ + +# Install sudo if not present, then configure user +RUN apt-get update && apt-get install -y sudo \ + && rm -rf /var/lib/apt/lists/* \ + && (groupadd -g 1000 clauder 2>/dev/null || true) \ + && (useradd -m -s /bin/bash -u 1000 -g 1000 clauder 2>/dev/null || usermod -l clauder -d /home/clauder -m coder 2>/dev/null || true) \ + && (groupmod -n clauder coder 2>/dev/null || true) \ + && mkdir -p /etc/sudoers.d \ + && echo "clauder ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/clauder \ + && chmod 0440 /etc/sudoers.d/clauder \ + && chown root:root /etc/sudoers.d/clauder + +# ============================================================================ +# DIRECTORY SETUP +# ============================================================================ + +RUN mkdir -p \ + /home/clauder/.local/share \ + /home/clauder/.config \ + /home/clauder/.cache \ + /home/clauder/.local/state \ + /home/clauder/.local/bin \ + /home/clauder/.local/node \ + /home/clauder/.claude \ + /home/clauder/entrypoint.d \ + /home/clauder/workspace \ + && chown -R 1000:1000 /home/clauder + +# Copy our custom entrypoint (replaces base image's entrypoint) +COPY railway-entrypoint.sh /usr/bin/railway-entrypoint.sh +RUN chmod +x /usr/bin/railway-entrypoint.sh + +# ============================================================================ +# CLAUDE CODE CLI INSTALLATION +# Install globally via npm - this is the official package +# ============================================================================ + +RUN npm install -g @anthropic-ai/claude-code \ + && echo "Claude CLI installed: $(claude --version 2>/dev/null || echo 'checking...')" + +# ============================================================================ +# RUNTIME +# Stay as root - entrypoint handles user switching based on RUN_AS_USER +# ============================================================================ + +WORKDIR /home/clauder/workspace +EXPOSE 8080 + +# Use our entrypoint which calls code-server directly +ENTRYPOINT ["/usr/bin/railway-entrypoint.sh"] + + diff --git a/PROJECT_BRIEF.md b/PROJECT_BRIEF.md new file mode 100644 index 000000000000..daef4a25c1d5 --- /dev/null +++ b/PROJECT_BRIEF.md @@ -0,0 +1,222 @@ +# Project Brief: Code-Server Railway Template + +**Project:** VSCode Cloud IDE with Claude Code Integration +**Repository:** `sphinxcode/code-server` +**Railway Service:** `code-ajna` (claude.sphinx.codes) +**Status:** In Progress + +--- + +## Executive Summary + +Create a production-ready, marketable Railway template that provides browser-based VS Code (code-server) with pre-installed Claude Code CLI, persistent extensions, and configurable user permissions. + +--- + +## Original Problems + +### 1. Root User Permission Issues +- **Symptom:** code-server displayed security warnings about running as root +- **Cause:** `RAILWAY_RUN_UID=0` was set, forcing container to run as root +- **Impact:** Couldn't bypass certain settings, security warnings in UI + +### 2. Non-Persistent Tools +- **Symptom:** npm, npx, extensions disappeared after redeployment +- **Cause:** Container running as root with `HOME=/root` (ephemeral), while volume mounted at `/home/coder` +- **Impact:** Users lost installed tools and configurations on each deploy + +### 3. Claude Code Not Pre-installed +- **Request:** Template users should have Claude Code CLI available out-of-the-box +- **Requirement:** Support for `claude --dangerously-skip-permissions` flag + +--- + +## Solution Architecture + +### Infrastructure +| Component | Value | +|-----------|-------| +| Base Image | `codercom/code-server:latest` | +| Volume Mount | `/home/coder` (Railway volume) | +| Service URL | `claude.sphinx.codes` | +| Project ID | `59ae99d7-dc99-4642-ae06-642cd8d8c83a` | +| Service ID | `34522d52-ba69-4fcf-83b7-210a765a0a76` | +| Environment ID | `a921a831-e480-451b-b9c7-04ce2f647c68` | + +### Key Files Modified + +#### [Dockerfile](file:///E:/AI-Terminal/sphinxcode/code-server/Dockerfile) +- Installs `gosu` for proper user switching +- Installs Node.js 20 LTS as fallback +- Installs Claude Code CLI to `/usr/local/bin/claude` +- Installs essential tools: ripgrep, jq, htop, vim, nano +- Sets up XDG directories for persistence +- PATH prioritizes volume paths over image paths + +#### [railway-entrypoint.sh](file:///E:/AI-Terminal/sphinxcode/code-server/railway-entrypoint.sh) +- Configurable user via `RUN_AS_USER` variable +- Shell profile setup (`.bashrc`, `.profile`) with PATH +- Permission fixing via `chown` when switching users +- User switching via `gosu` when `RUN_AS_USER=coder` +- Root symlinks for persistence when staying as root +- First-run initialization with welcome README +- Environment verification logging + +#### [README.md](file:///E:/AI-Terminal/sphinxcode/code-server/README.md) +- Documentation for all configuration variables +- Quick start guide for Claude Code +- Update behavior explanation +- Troubleshooting guide + +--- + +## Configuration Variables + +| Variable | Required | Default | Description | +|----------|----------|---------|-------------| +| `PASSWORD` | Yes | - | code-server login password | +| `RUN_AS_USER` | No | `root` | Set to `coder` for non-root execution | +| `CODER_HOME` | No | `/home/coder` | Volume mount path | +| `CODER_UID` | No | `1000` | User ID when switching to coder | +| `CODER_GID` | No | `1000` | Group ID when switching to coder | +| `GIT_REPO` | No | - | Repository to auto-clone on startup | + +--- + +## Persistence Strategy + +### Volume-First PATH Priority +``` +$HOME/.local/bin ← User-installed tools (Claude, etc.) +$HOME/.local/node/bin ← User-installed Node.js +$HOME/.claude/local ← Claude Code from volume +/usr/local/bin ← Image fallback (Claude) +/usr/bin ← Image fallback (Node.js) +``` + +### What Persists (on volume) +- Extensions: `~/.local/share/code-server/extensions/` +- Claude Code: `~/.local/bin/claude` or `~/.claude/` +- Claude auth: `~/.claude/` (API keys, settings) +- Node.js: `~/.local/node/` (if user installs) +- Shell config: `~/.bashrc`, `~/.profile` +- Workspace: `~/workspace/` + +### What Auto-Updates (from image) +- Node.js fallback in `/usr/bin/node` +- Claude Code fallback in `/usr/local/bin/claude` +- System packages (git, curl, etc.) + +--- + +## User Modes + +### Root Mode (Default) +``` +RUN_AS_USER=root (or not set) +``` +- Stays as root user +- Creates symlinks from `/root/` → `/home/coder/` for persistence +- Compatible with existing volumes owned by root + +### Coder Mode (Recommended for Claude) +``` +RUN_AS_USER=coder +``` +- Switches to coder user (UID 1000) via gosu +- Fixes volume permissions before switching +- No root warnings in code-server UI +- Required for `claude --dangerously-skip-permissions` + +--- + +## Issues Encountered & Resolved + +### 1. Railway Start Command Override +- **Problem:** Railway had a custom start command that bypassed our ENTRYPOINT +- **Solution:** Cleared the start command via `mcp_railway_service_update` + +### 2. Docker Layer Caching +- **Problem:** Railway used cached layers, ignoring our changes +- **Solution:** Added cache-bust comments to force rebuild + +### 3. Claude Installs to ~/.local/bin +- **Problem:** Assumed Claude installed to `~/.claude/local/` +- **Solution:** Updated PATH to include `$HOME/.local/bin` first + +### 4. Shell Profile Not Configured +- **Problem:** New terminals didn't have PATH set +- **Solution:** Entrypoint now writes to `.bashrc` and `.profile` + +--- + +## Current Status + +### Completed ✅ +- Dockerfile with gosu, Node.js, Claude Code +- Entrypoint with RUN_AS_USER variable +- Shell profile auto-configuration +- PATH priority for volume-installed tools +- README documentation +- Removed conflicting `railway.json` +- Cleared Railway start command override +- Set `RUN_AS_USER=coder` on Railway + +### Pending Verification 🔄 +- Confirm entrypoint output appears in Railway logs +- Verify user switches to `coder` (not `root@xxx`) +- Test `claude --dangerously-skip-permissions` works +- Confirm Claude authentication persists + +--- + +## Expected Startup Logs + +``` +╔══════════════════════════════════════════════════════════════════════════╗ +║ VSCode Cloud IDE - Claude Code & Node.js Ready ║ +╚══════════════════════════════════════════════════════════════════════════╝ + +→ Initial user: root (UID: 0) +→ RUN_AS_USER: coder +→ HOME: /home/coder + +→ Running setup as root... +→ Setting up shell profile... + ✓ Shell profile configured +→ Fixing permissions for coder user (UID: 1000)... + ✓ Permissions fixed +→ Switching to coder user via gosu... + +→ Running as: coder (UID: 1000) + +Environment: + → Node.js: v20.x.x [volume/image] + → npm: x.x.x + → git: x.x.x + → claude: x.x.x [volume/image] + +════════════════════════════════════════════════════════════════════════ +Starting code-server as coder... +════════════════════════════════════════════════════════════════════════ +``` + +--- + +## Files Summary + +| File | Location | Purpose | +|------|----------|---------| +| `Dockerfile` | sphinxcode/code-server | Image build configuration | +| `railway-entrypoint.sh` | sphinxcode/code-server | Container startup script | +| `README.md` | sphinxcode/code-server | User documentation | +| `railway.toml` | sphinxcode/code-server | Railway deployment config | + +--- + +## Next Steps + +1. **Verify Deployment** - Check if entrypoint runs and user switches properly +2. **Test Claude** - Authenticate and run `claude --dangerously-skip-permissions` +3. **Create Railway Template** - Make template public for others to deploy +4. **Update Template Docs** - Include volume attachment instructions diff --git a/README.md b/README.md new file mode 100644 index 000000000000..429520e816ac --- /dev/null +++ b/README.md @@ -0,0 +1,82 @@ +# Claude Code Server + +![Claude Code Server Logo](https://raw.githubusercontent.com/sphinxcode/claude-code-server/refs/heads/main/public/claude-code-server-logo.png) + +**Browser-based VS Code with Claude Code CLI pre-installed** + +[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/template/claude-code-server) + +![Mobile Mockup](https://raw.githubusercontent.com/sphinxcode/claude-code-server/refs/heads/main/public/iphone_mockup.png) + +Deploy a full VS Code development environment in the cloud with Claude Code CLI ready to go. Access it from any browser, on any device. Code with AI assistance anywhere. + +--- + +## Features + +- **Claude Code CLI Pre-installed** – Start AI-assisted coding immediately with `claude` or `claude-auto` (YOLO mode) +- **Browser-Based VS Code** – Full IDE experience accessible from any device +- **Persistent Storage** – Your extensions, settings, and projects survive redeploys +- **Non-Root Security** – Runs as the `clauder` user with optional sudo access +- **One-Click Deploy** – Deploy to Railway in 60 seconds + +--- + +## Quick Start + +### Deploy to Railway + +Click the button above, or: + +1. Go to [Railway Templates](https://railway.com/templates) +2. Search for "Claude Code Server" +3. Click **Deploy** and set your `PASSWORD` +4. Attach a volume to `/home/clauder` +5. Open the generated domain in your browser + +### First Login + +1. Enter the password you set +2. Open the terminal in VS Code +3. Run `claude` to start coding with AI + +--- + +## Configuration + +### Required Variables + +| Variable | Description | +|------------|------------------------------------| +| `PASSWORD` | Login password for the web IDE | + +### Optional Variables + +| Variable | Default | Description | +|----------------|--------------------------------|------------------------------------------| +| `CLAUDER_HOME` | `/home/clauder` | Volume mount path | +| `RUN_AS_USER` | `clauder` | Set to `root` if you need root access | +| `APP_NAME` | `Claude Code Server` | Login page title | +| `WELCOME_TEXT` | `Welcome to Claude Code Server`| Login page message | + +### Volume Configuration + +> ⚠️ **CRITICAL**: Without a volume, ALL data is lost on every redeploy! + +| Setting | Value | +|----------------|------------------| +| **Mount Path** | `/home/clauder` | +| **Size** | 5GB+ recommended | + +--- + +## Built With + +- [code-server](https://github.com/coder/code-server) – VS Code in the browser +- [Claude Code CLI](https://claude.ai/code) – AI coding assistant by Anthropic + +--- + +## License + +MIT diff --git a/public/claude-code-server-logo.png b/public/claude-code-server-logo.png new file mode 100644 index 000000000000..9b7d5ee33458 Binary files /dev/null and b/public/claude-code-server-logo.png differ diff --git a/public/claude-code-server-logo.svg b/public/claude-code-server-logo.svg new file mode 100644 index 000000000000..5c8413a1ce58 --- /dev/null +++ b/public/claude-code-server-logo.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/public/iphone_mockup.png b/public/iphone_mockup.png new file mode 100644 index 000000000000..6aea1642deea Binary files /dev/null and b/public/iphone_mockup.png differ diff --git a/public/social-preview.png b/public/social-preview.png new file mode 100644 index 000000000000..9d4af5aaf5eb Binary files /dev/null and b/public/social-preview.png differ diff --git a/railway-entrypoint.sh b/railway-entrypoint.sh new file mode 100644 index 000000000000..d48d0c59763d --- /dev/null +++ b/railway-entrypoint.sh @@ -0,0 +1,267 @@ +#!/bin/bash +set -e + +# ============================================================================ +# VSCode Cloud IDE - Railway Entrypoint +# Handles permission fix and optional user switching +# ============================================================================ + +echo "╔══════════════════════════════════════════════════════════════════════╗" +echo "║ VSCode Cloud IDE - Claude Code & Node.js Ready ║" +echo "╚══════════════════════════════════════════════════════════════════════╝" +echo "" + +# ============================================================================ +# CONFIGURABLE PATHS AND USER +# ============================================================================ + +CLAUDER_HOME="${CLAUDER_HOME:-/home/clauder}" +CLAUDER_UID="${CLAUDER_UID:-1000}" +CLAUDER_GID="${CLAUDER_GID:-1000}" + +# RUN_AS_USER: Defaults to "clauder" for non-root. Set to "root" if needed. +RUN_AS_USER="${RUN_AS_USER:-clauder}" + +export HOME="$CLAUDER_HOME" +export XDG_DATA_HOME="$CLAUDER_HOME/.local/share" +export XDG_CONFIG_HOME="$CLAUDER_HOME/.config" +export XDG_CACHE_HOME="$CLAUDER_HOME/.cache" +export XDG_STATE_HOME="$CLAUDER_HOME/.local/state" + +# PATH: Include all possible locations for installed tools +# - ~/.local/bin: pip user installs, pipx, local scripts +# - ~/.npm-global/bin: npm global installs (non-root) +# - /usr/local/bin: system-wide installs +# - /usr/lib/node_modules/.bin: npm global installs (root/sudo) +export PATH="$CLAUDER_HOME/.local/bin:$CLAUDER_HOME/.npm-global/bin:$CLAUDER_HOME/.local/node/bin:$CLAUDER_HOME/.claude/local:$CLAUDER_HOME/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/node_modules/.bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:$PATH" + +echo "→ Initial user: $(whoami) (UID: $(id -u))" +echo "→ RUN_AS_USER: $RUN_AS_USER" +echo "→ HOME: $HOME" + +# ============================================================================ +# DIRECTORY CREATION AND PERMISSION FIX +# ============================================================================ + +if [ "$(id -u)" = "0" ]; then + echo "" + echo "→ Running setup as root..." + + # Create directories if they don't exist + mkdir -p "$XDG_DATA_HOME" \ + "$XDG_CONFIG_HOME" \ + "$XDG_CACHE_HOME" \ + "$XDG_STATE_HOME" \ + "$HOME/.local/bin" \ + "$HOME/.local/node" \ + "$HOME/.claude" \ + "$HOME/entrypoint.d" \ + "$HOME/workspace" \ + "$XDG_DATA_HOME/code-server/extensions" \ + "$XDG_CONFIG_HOME/code-server" 2>/dev/null || true + + # ======================================================================== + # SHELL PROFILE SETUP + # ======================================================================== + + PROFILE_FILE="$HOME/.bashrc" + + if [ ! -f "$PROFILE_FILE" ] || ! grep -q '.npm-global' "$PROFILE_FILE" 2>/dev/null; then + echo "→ Setting up shell profile..." + cat >> "$PROFILE_FILE" << 'PROFILE' + +# ============================================================================ +# VSCode Cloud IDE - PATH Configuration +# ============================================================================ +export PATH="$HOME/.local/bin:$HOME/.npm-global/bin:$HOME/.local/node/bin:$HOME/.claude/local:$PATH" + +# npm global prefix for non-root installs +export NPM_CONFIG_PREFIX="$HOME/.npm-global" + +# Claude Code alias with --dangerously-skip-permissions +alias claude-auto='claude --dangerously-skip-permissions' +PROFILE + + # Create npm global directory + mkdir -p "$HOME/.npm-global/bin" 2>/dev/null || true + + echo " ✓ Shell profile configured" + fi + + # Also set up .profile for login shells + if [ ! -f "$HOME/.profile" ] || ! grep -q '.local/bin' "$HOME/.profile" 2>/dev/null; then + cat >> "$HOME/.profile" << 'PROFILE' + +# Load .bashrc for interactive shells +if [ -f "$HOME/.bashrc" ]; then + . "$HOME/.bashrc" +fi +PROFILE + fi + + # ======================================================================== + # USER SWITCHING (if RUN_AS_USER=clauder) + # ======================================================================== + + if [ "$RUN_AS_USER" = "clauder" ]; then + echo "→ Fixing permissions for clauder user (UID: $CLAUDER_UID)..." + chown -R "$CLAUDER_UID:$CLAUDER_GID" "$CLAUDER_HOME" 2>/dev/null || true + echo " ✓ Permissions fixed" + + # Check if gosu is available + if command -v gosu &>/dev/null; then + echo "→ Switching to clauder user via gosu..." + exec gosu "$CLAUDER_UID:$CLAUDER_GID" "$0" "$@" + else + echo " ⚠ gosu not found, staying as root" + fi + else + echo "→ Staying as root (set RUN_AS_USER=clauder to switch)" + + # Create symlinks from /root to volume for persistence + mkdir -p /root/.local 2>/dev/null || true + for dir in ".local/share" ".local/bin" ".local/node" ".config" ".cache" ".claude"; do + target="$CLAUDER_HOME/$dir" + link="/root/$dir" + if [ -d "$target" ] && [ ! -L "$link" ]; then + rm -rf "$link" 2>/dev/null || true + mkdir -p "$(dirname "$link")" 2>/dev/null || true + ln -sf "$target" "$link" 2>/dev/null || true + fi + done + echo " ✓ Root directories symlinked to $CLAUDER_HOME" + fi +fi + +# ============================================================================ +# RUNNING AS FINAL USER +# ============================================================================ + +echo "" +echo "→ Running as: $(whoami) (UID: $(id -u))" + +# ============================================================================ +# FIRST RUN SETUP +# ============================================================================ + +FIRST_RUN_MARKER="$XDG_DATA_HOME/.vscode-cloud-initialized" + +if [ ! -f "$FIRST_RUN_MARKER" ]; then + echo "→ First run detected - initializing..." + + if [ ! -f "$HOME/workspace/README.md" ]; then + cat > "$HOME/workspace/README.md" << 'WELCOME' +# Welcome to VSCode Cloud IDE + +Your cloud development environment is ready! + +## Features + +- **Claude Code CLI** - Pre-installed and ready to use +- **Node.js 20 LTS** - Pre-installed and ready to use +- **Persistent Extensions** - Install once, keep forever +- **Full Terminal** - npm, git, and more + +## Quick Start + +```bash +# Start Claude Code (with auto-accept for automation) +claude --dangerously-skip-permissions + +# Or use the alias +claude-auto + +# Interactive mode +claude +``` + +You'll need to authenticate with your Anthropic API key on first use. + +## Configuration + +Set these environment variables in Railway: + +- `RUN_AS_USER=clauder` - Run as non-root user (recommended for Claude) +- `RUN_AS_USER=root` - Stay as root + +Happy coding! 🚀 +WELCOME + fi + + touch "$FIRST_RUN_MARKER" 2>/dev/null || true + echo " ✓ Initialization complete" +fi + +# ============================================================================ +# ENVIRONMENT VERIFICATION +# ============================================================================ + +echo "" +echo "Environment:" + +# Node.js - show source +if [ -x "$CLAUDER_HOME/.local/node/bin/node" ]; then + echo " → Node.js: $(node --version 2>/dev/null) [volume]" +else + echo " → Node.js: $(node --version 2>/dev/null || echo 'not found') [image]" +fi + +# npm +echo " → npm: $(npm --version 2>/dev/null || echo 'not found')" + +# git +echo " → git: $(git --version 2>/dev/null | cut -d' ' -f3 || echo 'not found')" + +# Claude Code - show source +if [ -x "$CLAUDER_HOME/.local/bin/claude" ]; then + echo " → claude: $(claude --version 2>/dev/null || echo 'installed') [volume ~/.local/bin]" +elif [ -x "$CLAUDER_HOME/.claude/local/claude" ]; then + echo " → claude: $(claude --version 2>/dev/null || echo 'installed') [volume ~/.claude/local]" +elif command -v claude &>/dev/null; then + echo " → claude: $(claude --version 2>/dev/null || echo 'installed') [image]" +else + echo " → claude: not installed" +fi + +# Extensions count +if [ -d "$XDG_DATA_HOME/code-server/extensions" ]; then + EXT_COUNT=$(find "$XDG_DATA_HOME/code-server/extensions" -maxdepth 1 -type d 2>/dev/null | wc -l) + EXT_COUNT=$((EXT_COUNT - 1)) + if [ $EXT_COUNT -gt 0 ]; then + echo " → Extensions: $EXT_COUNT installed" + fi +fi + +# ============================================================================ +# CUSTOM STARTUP SCRIPTS +# ============================================================================ + +if [ -d "$HOME/entrypoint.d" ]; then + for script in "$HOME/entrypoint.d"/*.sh; do + if [ -f "$script" ] && [ -x "$script" ]; then + echo "" + echo "Running: $(basename "$script")" + "$script" || echo " ⚠ Script exited with code $?" + fi + done +fi + +# ============================================================================ +# START CODE-SERVER +# ============================================================================ + +# Branding customization +APP_NAME="${APP_NAME:-Claude Code Server}" +WELCOME_TEXT="${WELCOME_TEXT:-Welcome to Claude Code Server}" + +echo "" +echo "════════════════════════════════════════════════════════════════════════" +echo "Starting $APP_NAME as $(whoami)..." +echo "════════════════════════════════════════════════════════════════════════" +echo "" + +exec dumb-init /usr/bin/code-server \ + --bind-addr 0.0.0.0:8080 \ + --app-name "$APP_NAME" \ + --welcome-text "$WELCOME_TEXT" \ + "$CLAUDER_HOME/workspace" diff --git a/railway.toml b/railway.toml new file mode 100644 index 000000000000..4442b0792c2a --- /dev/null +++ b/railway.toml @@ -0,0 +1,18 @@ +# ============================================================================ +# Claude Code Server - Railway Configuration +# https://github.com/sphinxcode/claude-code-server +# ============================================================================ + +[build] +builder = "DOCKERFILE" +dockerfilePath = "Dockerfile" + +[deploy] +healthcheckPath = "/healthz" +healthcheckTimeout = 300 +restartPolicyType = "ON_FAILURE" +restartPolicyMaxRetries = 10 + +# Auto-generate a Railway domain on deployment +[[services.networking.external]] +port = 8080