diff --git a/Dockerfile b/Dockerfile index ec7121023..2d4d1cb98 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,20 +1,25 @@ # ============================================================================ -# VSCode Cloud IDE - Claude Code & Node.js Ready -# Browser-based VSCode with persistent extensions and Node.js -# https://github.com/sphinxcode/code-server +# Claude Code Server - Browser-based VS Code with AI Coding Assistants +# https://github.com/sphinxcode/claude-code-server # ============================================================================ -FROM codercom/code-server:latest +FROM codercom/code-server:4.108.0 USER root -# Install gosu for proper user switching, Node.js, and essential tools -# Cache bust: 2026-01-29-v3 +# ============================================================================ +# SYSTEM DEPENDENCIES +# Install gosu, Node.js 20, Python/uv, and essential tools +# Cache bust: 2026-01-29-v4 +# ============================================================================ + RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ && apt-get update \ && apt-get install -y --no-install-recommends \ gosu \ nodejs \ + python3 \ + python3-pip \ git \ curl \ wget \ @@ -25,6 +30,7 @@ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ nano \ ripgrep \ && npm install -g npm@latest \ + && pip3 install --break-system-packages uv \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* @@ -32,36 +38,46 @@ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \ # PERSISTENCE CONFIGURATION # ============================================================================ -ENV HOME=/home/coder -ENV USER=coder +ENV HOME=/home/clauder +ENV USER=clauder # XDG Base Directory Specification -ENV XDG_DATA_HOME=/home/coder/.local/share -ENV XDG_CONFIG_HOME=/home/coder/.config -ENV XDG_CACHE_HOME=/home/coder/.cache -ENV XDG_STATE_HOME=/home/coder/.local/state +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/coder/.local/bin:/home/coder/.local/node/bin:/home/coder/.claude/local:/home/coder/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:${PATH}" +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/coder/entrypoint.d +ENV ENTRYPOINTD=/home/clauder/entrypoint.d + +# ============================================================================ +# USER SETUP +# Create clauder user with same UID as coder for compatibility +# ============================================================================ + +RUN groupadd -g 1000 clauder 2>/dev/null || true \ + && useradd -m -s /bin/bash -u 1000 -g 1000 clauder 2>/dev/null || true \ + && usermod -l clauder coder 2>/dev/null || true \ + && groupmod -n clauder coder 2>/dev/null || true # ============================================================================ # DIRECTORY SETUP # ============================================================================ RUN mkdir -p \ - /home/coder/.local/share \ - /home/coder/.config \ - /home/coder/.cache \ - /home/coder/.local/state \ - /home/coder/.local/bin \ - /home/coder/.local/node \ - /home/coder/.claude \ - /home/coder/entrypoint.d \ - /home/coder/workspace \ - && chown -R 1000:1000 /home/coder + /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 @@ -70,6 +86,7 @@ RUN chmod +x /usr/bin/railway-entrypoint.sh # ============================================================================ # FALLBACK CLAUDE CODE CLI INSTALLATION # Installed to /usr/local/bin as fallback - volume version takes priority +# Claude Code is ALWAYS installed (cannot be disabled) # ============================================================================ RUN curl -fsSL https://claude.ai/install.sh | bash \ @@ -84,7 +101,7 @@ RUN curl -fsSL https://claude.ai/install.sh | bash \ # Stay as root - entrypoint handles user switching based on RUN_AS_USER # ============================================================================ -WORKDIR /home/coder/workspace +WORKDIR /home/clauder/workspace EXPOSE 8080 # Use our entrypoint which calls code-server directly diff --git a/PROJECT_BRIEF.md b/PROJECT_BRIEF.md new file mode 100644 index 000000000..daef4a25c --- /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 index 162cbbca7..48cfed00d 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,17 @@ -# VSCode Cloud IDE +# Claude Code Server -**Browser-based VSCode with Claude Code & Node.js** +**Browser-based VS Code with Claude Code & AI Coding Assistants** -[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/template/TEMPLATE_ID) +[![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/template/claude-code-server) -Cloud IDE with persistent extensions, settings, and tools. - ---- - -## Features - -- **Claude Code** & **Node.js 20** pre-installed -- Extensions persist across redeployments -- Configurable user (root or coder) -- Shell profile auto-configured with PATH +Cloud IDE with persistent extensions, settings, and tools. Pre-installed Claude Code CLI. --- ## Quick Start ```bash -# Claude Code with auto-accept (for automation) +# Claude Code with auto-accept claude --dangerously-skip-permissions # Or use the alias @@ -32,46 +23,80 @@ claude --- -## Environment Variables +## ⚠️ Claude Code Authentication -| Variable | Required | Default | Description | -|----------|----------|---------|-------------| -| `PASSWORD` | Yes | - | Login password | -| `RUN_AS_USER` | No | `root` | Set to `coder` for non-root | -| `CODER_HOME` | No | `/home/coder` | Volume mount path | -| `CODER_UID` | No | `1000` | User ID (when RUN_AS_USER=coder) | -| `CODER_GID` | No | `1000` | Group ID (when RUN_AS_USER=coder) | +When running `claude` for the first time: + +1. The CLI will display an authentication URL +2. **Copy the URL to a different browser** (not this code-server browser) +3. Complete the login in that browser +4. Copy the code displayed after login +5. Paste the code back into the CLI + +Your credentials persist in `~/.claude/` across redeployments. --- -## Running as Non-Root (Recommended for Claude) +## 📍 Railway Deployment -Set in Railway variables: -``` -RUN_AS_USER=coder -``` +> **Region**: Set your Railway region to **US West** for the fastest performance. -This enables: +### Required Variables + +| Variable | Description | +|----------|-------------| +| `PASSWORD` | Login password for code-server | + +### User Configuration + +| Variable | Default | Description | +|----------|---------|-------------| +| `CLAUDER_HOME` | `/home/clauder` | Volume mount path | +| `CLAUDER_UID` | `1000` | User ID for clauder | +| `CLAUDER_GID` | `1000` | Group ID for clauder | +| `RUN_AS_USER` | `root` | Set to `clauder` for non-root execution | + +### Pre-Install AI CLIs + +Set to `1` to install on startup (default: `0`): + +| Variable | CLI | Description | +|----------|-----|-------------| +| `INSTALL_OPENCODE` | OpenCode | Google's agentic AI IDE | +| `INSTALL_GEMINI` | Gemini CLI | Google Gemini assistant | +| `INSTALL_KILOCODE` | KiloCode | VS Code AI coding | +| `INSTALL_CONTINUE` | Continue | Open-source AI code assistant | +| `INSTALL_CODEX` | Codex | OpenAI Codex CLI | + +> **Note**: Claude Code is **always installed** and cannot be disabled. + +### Pre-Install Development Frameworks + +| Variable | Framework | Description | +|----------|-----------|-------------| +| `INSTALL_BMAD` | BMAD Method | Spec-driven development workflow | +| `INSTALL_OPENSPEC` | OpenSpec | AI-powered spec generation | +| `INSTALL_SPECKIT` | Spec-Kit | GitHub's specification toolkit | + +--- + +## How It Works + +1. **Starts as root** – fixes volume permissions +2. **Installs optional CLIs** – based on environment variables +3. **Switches to clauder** – uses `gosu` for clean handoff +4. **Runs code-server** – as non-root user + +This means: - ✅ No root permission warnings -- ✅ `claude --dangerously-skip-permissions` works properly -- ✅ Better security - ---- - -## Update Behavior - -| Component | Behavior | -|-----------|----------| -| **Volume tools** | You control - install to `~/.local/bin/` | -| **Image tools** | Auto-update on redeploy (fallback) | -| **Extensions** | Persist on volume | -| **Claude auth** | Persists in `~/.claude/` | +- ✅ Existing volumes work fine +- ✅ Claude `--dangerously-skip-permissions` works --- ## Custom Startup Scripts -Add to `$CODER_HOME/entrypoint.d/`: +Add scripts to `$CLAUDER_HOME/entrypoint.d/`: ```bash #!/bin/bash @@ -82,6 +107,30 @@ Make executable: `chmod +x script.sh` --- +## Update Behavior + +| Component | Behavior | +|-----------|----------| +| **Volume tools** | You control – install to `~/.local/bin/` | +| **Image tools** | Auto-update on redeploy (fallback) | +| **Extensions** | Persist on volume | +| **Claude auth** | Persists on volume | + +Logs show `[volume]` or `[image]` next to each tool. + +--- + +## Troubleshooting + +| Issue | Solution | +|-------|----------| +| Permission denied | Check `CLAUDER_UID` matches your volume owner | +| Claude not found | Run `which claude` to check PATH | +| Extensions missing | Verify volume mounted at `CLAUDER_HOME` | +| Auth URL won't open | Copy URL to a different browser | + +--- + ## Credits - [code-server](https://github.com/coder/code-server) by Coder diff --git a/railway-entrypoint.sh b/railway-entrypoint.sh index 05bb7787d..a5fc5dc45 100644 --- a/railway-entrypoint.sh +++ b/railway-entrypoint.sh @@ -2,12 +2,13 @@ set -e # ============================================================================ -# VSCode Cloud IDE - Railway Entrypoint -# Handles permission fix and optional user switching +# Claude Code Server - Railway Entrypoint +# Handles permission fix, optional user switching, and CLI installations +# https://github.com/sphinxcode/claude-code-server # ============================================================================ echo "╔══════════════════════════════════════════════════════════════════════╗" -echo "║ VSCode Cloud IDE - Claude Code & Node.js Ready ║" +echo "║ Claude Code Server - AI Coding Assistants Ready ║" echo "╚══════════════════════════════════════════════════════════════════════╝" echo "" @@ -15,21 +16,21 @@ echo "" # CONFIGURABLE PATHS AND USER # ============================================================================ -CODER_HOME="${CODER_HOME:-/home/coder}" -CODER_UID="${CODER_UID:-1000}" -CODER_GID="${CODER_GID:-1000}" +CLAUDER_HOME="${CLAUDER_HOME:-/home/clauder}" +CLAUDER_UID="${CLAUDER_UID:-1000}" +CLAUDER_GID="${CLAUDER_GID:-1000}" -# RUN_AS_USER: Set to "coder" to run as non-root, or "root" (default) to stay as root +# RUN_AS_USER: Set to "clauder" to run as non-root, or "root" (default) to stay as root RUN_AS_USER="${RUN_AS_USER:-root}" -export HOME="$CODER_HOME" -export XDG_DATA_HOME="$CODER_HOME/.local/share" -export XDG_CONFIG_HOME="$CODER_HOME/.config" -export XDG_CACHE_HOME="$CODER_HOME/.cache" -export XDG_STATE_HOME="$CODER_HOME/.local/state" +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 ~/.local/bin where Claude installs by default -export PATH="$CODER_HOME/.local/bin:$CODER_HOME/.local/node/bin:$CODER_HOME/.claude/local:$CODER_HOME/node_modules/.bin:/usr/local/bin:/usr/bin:/usr/lib/code-server/lib/vscode/bin/remote-cli:$PATH" +export PATH="$CLAUDER_HOME/.local/bin:$CLAUDER_HOME/.local/node/bin:$CLAUDER_HOME/.claude/local:$CLAUDER_HOME/node_modules/.bin:/usr/local/bin:/usr/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" @@ -56,6 +57,94 @@ if [ "$(id -u)" = "0" ]; then "$XDG_DATA_HOME/code-server/extensions" \ "$XDG_CONFIG_HOME/code-server" 2>/dev/null || true + # ======================================================================== + # OPTIONAL CLI INSTALLATIONS + # Install CLIs based on environment variables (only if not already present) + # ======================================================================== + + echo "" + echo "→ Checking optional CLI installations..." + + # OpenCode + if [ "${INSTALL_OPENCODE:-0}" = "1" ]; then + if ! command -v opencode &>/dev/null; then + echo " → Installing OpenCode..." + curl -fsSL https://raw.githubusercontent.com/opencode-ai/opencode/refs/heads/main/install | bash || echo " ⚠ OpenCode install failed" + else + echo " ✓ OpenCode already installed" + fi + fi + + # Gemini CLI + if [ "${INSTALL_GEMINI:-0}" = "1" ]; then + if ! command -v gemini &>/dev/null; then + echo " → Installing Gemini CLI..." + npm install -g @google/gemini-cli || echo " ⚠ Gemini CLI install failed" + else + echo " ✓ Gemini CLI already installed" + fi + fi + + # KiloCode CLI + if [ "${INSTALL_KILOCODE:-0}" = "1" ]; then + if ! command -v kilocode &>/dev/null; then + echo " → Installing KiloCode CLI..." + npm install -g @kilocode/cli || echo " ⚠ KiloCode CLI install failed" + else + echo " ✓ KiloCode CLI already installed" + fi + fi + + # Continue CLI + if [ "${INSTALL_CONTINUE:-0}" = "1" ]; then + if ! command -v continue &>/dev/null; then + echo " → Installing Continue CLI..." + npm install -g @continuedev/cli || echo " ⚠ Continue CLI install failed" + else + echo " ✓ Continue CLI already installed" + fi + fi + + # Codex CLI + if [ "${INSTALL_CODEX:-0}" = "1" ]; then + if ! command -v codex &>/dev/null; then + echo " → Installing Codex CLI..." + npm install -g @openai/codex || echo " ⚠ Codex CLI install failed" + else + echo " ✓ Codex CLI already installed" + fi + fi + + # ======================================================================== + # OPTIONAL DEVELOPMENT FRAMEWORK INSTALLATIONS + # ======================================================================== + + # BMAD Method + if [ "${INSTALL_BMAD:-0}" = "1" ]; then + echo " → Installing BMAD Method..." + npx bmad-method install || echo " ⚠ BMAD install failed" + fi + + # OpenSpec + if [ "${INSTALL_OPENSPEC:-0}" = "1" ]; then + if ! command -v openspec &>/dev/null; then + echo " → Installing OpenSpec..." + npm install -g @fission-ai/openspec@latest || echo " ⚠ OpenSpec install failed" + else + echo " ✓ OpenSpec already installed" + fi + fi + + # Spec-Kit + if [ "${INSTALL_SPECKIT:-0}" = "1" ]; then + if ! command -v specify &>/dev/null; then + echo " → Installing Spec-Kit..." + uv tool install specify-cli --from git+https://github.com/github/spec-kit.git || echo " ⚠ Spec-Kit install failed" + else + echo " ✓ Spec-Kit already installed" + fi + fi + # ======================================================================== # SHELL PROFILE SETUP # ======================================================================== @@ -67,7 +156,7 @@ if [ "$(id -u)" = "0" ]; then cat >> "$PROFILE_FILE" << 'PROFILE' # ============================================================================ -# VSCode Cloud IDE - PATH Configuration +# Claude Code Server - PATH Configuration # ============================================================================ export PATH="$HOME/.local/bin:$HOME/.local/node/bin:$HOME/.claude/local:$PATH" @@ -89,28 +178,28 @@ PROFILE fi # ======================================================================== - # USER SWITCHING (if RUN_AS_USER=coder) + # USER SWITCHING (if RUN_AS_USER=clauder) # ======================================================================== - if [ "$RUN_AS_USER" = "coder" ]; then - echo "→ Fixing permissions for coder user (UID: $CODER_UID)..." - chown -R "$CODER_UID:$CODER_GID" "$CODER_HOME" 2>/dev/null || true + 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 coder user via gosu..." - exec gosu "$CODER_UID:$CODER_GID" "$0" "$@" + 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=coder to switch)" + 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="$CODER_HOME/$dir" + target="$CLAUDER_HOME/$dir" link="/root/$dir" if [ -d "$target" ] && [ ! -L "$link" ]; then rm -rf "$link" 2>/dev/null || true @@ -118,7 +207,7 @@ PROFILE ln -sf "$target" "$link" 2>/dev/null || true fi done - echo " ✓ Root directories symlinked to $CODER_HOME" + echo " ✓ Root directories symlinked to $CLAUDER_HOME" fi fi @@ -133,14 +222,14 @@ echo "→ Running as: $(whoami) (UID: $(id -u))" # FIRST RUN SETUP # ============================================================================ -FIRST_RUN_MARKER="$XDG_DATA_HOME/.vscode-cloud-initialized" +FIRST_RUN_MARKER="$XDG_DATA_HOME/.claude-code-server-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 +# Welcome to Claude Code Server Your cloud development environment is ready! @@ -164,13 +253,21 @@ claude-auto claude ``` -You'll need to authenticate with your Anthropic API key on first use. +## Claude Code Authentication + +⚠️ **Important**: When authenticating Claude Code: +1. Copy the authentication URL +2. Open it in a **different browser** (not this code-server browser) +3. Complete the login there +4. Copy the code and paste it back into the CLI + +Your credentials persist across redeployments. ## Configuration Set these environment variables in Railway: -- `RUN_AS_USER=coder` - Run as non-root user (recommended for Claude) +- `RUN_AS_USER=clauder` - Run as non-root user (recommended) - `RUN_AS_USER=root` - Stay as root (default) Happy coding! 🚀 @@ -189,7 +286,7 @@ echo "" echo "Environment:" # Node.js - show source -if [ -x "$CODER_HOME/.local/node/bin/node" ]; then +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]" @@ -201,10 +298,10 @@ 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 "$CODER_HOME/.local/bin/claude" ]; then +# Claude Code - show source (always installed) +if [ -x "$CLAUDER_HOME/.local/bin/claude" ]; then echo " → claude: $(claude --version 2>/dev/null || echo 'installed') [volume ~/.local/bin]" -elif [ -x "$CODER_HOME/.claude/local/claude" ]; then +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]" @@ -212,6 +309,13 @@ else echo " → claude: not installed" fi +# Show optional CLIs if installed +command -v opencode &>/dev/null && echo " → opencode: installed" +command -v gemini &>/dev/null && echo " → gemini: installed" +command -v kilocode &>/dev/null && echo " → kilocode: installed" +command -v continue &>/dev/null && echo " → continue: installed" +command -v codex &>/dev/null && echo " → codex: installed" + # 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) @@ -245,4 +349,4 @@ echo "Starting code-server as $(whoami)..." echo "════════════════════════════════════════════════════════════════════════" echo "" -exec dumb-init /usr/bin/code-server --bind-addr 0.0.0.0:8080 /home/coder/workspace +exec dumb-init /usr/bin/code-server --bind-addr 0.0.0.0:8080 "$HOME/workspace" diff --git a/railway.toml b/railway.toml index e12903c58..ec4b67d0e 100644 --- a/railway.toml +++ b/railway.toml @@ -1,5 +1,6 @@ # ============================================================================ -# VSCode Cloud IDE - Railway Configuration +# Claude Code Server - Railway Configuration +# https://github.com/sphinxcode/claude-code-server # ============================================================================ [build]