Files
localgenai/pyinfra/framework/compose/code-server/README.md

3.5 KiB

code-server — VS Code in the browser

Full VS Code served from the box at http://framework:8443. The reason it exists in this stack: Claude Code runs inside the container, so long agent tasks execute on the Framework Desktop and survive the laptop sleeping, the browser tab closing, or you walking away with the phone. Any device on the tailnet gets the same editor with the same state.

Bring-up

cd /srv/docker/code-server && docker compose up -d

First start pulls the image and runs the universal-package-install mod (installs tmux), so give it a minute before the UI answers on :8443.

HTTPS is required for extension panels. VS Code webviews (the Claude Code panel included) need a secure context; over plain http://framework:8443 they render blank. Serve it via Tailscale: sudo tailscale serve --bg --https=8443 8443https://framework.<tailnet>.ts.net:8443. Localhost also counts as secure (ssh -L 8443:localhost:8443 framework).

One-time setup (in the code-server UI)

  1. Install the Claude Code extension. Extensions panel → search "Claude Code". code-server uses the Open VSX registry, where Anthropic publishes the official extension (https://open-vsx.org/extension/Anthropic/claude-code).

  2. Sign in. The OAuth flow in a browser context is a copy/paste dance: the extension shows a URL → open it in another tab → approve → paste the code back. Credentials land in /config/.claude/ and persist across container recreates.

  3. (Optional) CLI in the terminal. The extension bundles its own CLI, but for tmux-based long runs install it explicitly:

    curl -fsSL https://claude.ai/install.sh | bash
    

    Lands in ~/.local/bin (= /config/.local/bin, persisted).

Long-running tasks

The Claude process is a child of the container, not of your browser tab — closing the tab does nothing to it. Reattach from any device and the session is where you left it. For multi-hour unattended runs, prefer a tmux pane in the integrated terminal:

tmux new -s longtask
claude    # kick off the task, detach with C-b d

If you want to steer from a phone or claude.ai/code instead of this UI, use claude remote-control (see the framework README's "Claude Code on the box" section) — that works in the host's tmux too, no container needed.

Scope and security

  • No password is set — same trust model as every other service on this Tailscale-only box. If the host ever sees LAN/internet traffic, set HASHED_PASSWORD in the compose env and bind to localhost; a browser terminal is a shell.
  • The workspace is container-scoped on purpose: Claude Code in here sees /workspace and /config, not the host filesystem or the docker socket. Bind-mount specific repos into /workspace/<name> when you want them editable (host UID 1000 == container PUID 1000, so ownership just works).
  • host.docker.internal reaches the sibling services — handy for pointing scripts at Ollama (:11434) or LiteLLM (:4000) from the integrated terminal.

State layout

Path (host) What lives there
/srv/docker/code-server/config $HOME: extensions, settings, ~/.claude, CLIs
/srv/docker/code-server/workspace default project area (DEFAULT_WORKSPACE)

Back up config if you care about extension state and Claude session history; everything else is reproducible from the repo.