CodeNomad/packages/server
Pascal André 24a26807e0
feat(restore): persist Yolo and session expansion state (#611)
## Summary

- Persist server-owned Yolo state through OpenCode session metadata so
it survives workspace and CodeNomad restarts.
- Restore expanded and collapsed parent/subsession state from the
desktop client snapshot.
- Serialize CodeNomad metadata mutations so Yolo and worktree metadata
cannot overwrite each other.

## Yolo persistence

- Stores state under metadata.codenomad.yolo with enabled and
rootSessionId fields.
- Accepts a persisted marker only when it is owned by that session,
preventing copied fork metadata from enabling an unrelated family.
- Hydrates the project session tree before processing permission events
and queues events while hydration is pending.
- Keeps the server authoritative for family inheritance, permission
replies, toggles, and cleanup.
- Uses get/merge/update writes that preserve worktreeSlug and
third-party metadata.
- Serializes writes by session across CodeNomad instances and routes
worktree slug updates through the same server-owned path.
- Reconciles late ancestry and repeated root migrations without
re-enabling a family after a concurrent disable.

## Expansion restoration

- Captures bounded, deduplicated expanded session IDs per workspace in
the local desktop snapshot.
- Restores explicit expanded and collapsed state while preserving IDs
that are temporarily unavailable during startup reconciliation.
- Gives live user changes, deletions, and loaded-session authority
precedence over preserved state.
- Cleans expansion state when sessions or instances are removed.
- Keeps the active child visible when loading legacy snapshots that
predate expansion persistence.

## Validation

- 39 focused server permission and metadata tests pass.
- 66 focused client snapshot and restoration tests pass.
- Server and UI TypeScript typechecks pass.
- git diff --check passes.

## Limits

- Project hydration follows the existing 10,000-session list ceiling.
- Snapshot expansion persistence is capped at 256 session IDs.

Closes #607

Depends on anomalyco/opencode#23068.
2026-07-19 17:16:56 +01:00
..
scripts Package CodeNomad OpenCode plugin (#433) 2026-05-12 09:00:22 +01:00
src feat(restore): persist Yolo and session expansion state (#611) 2026-07-19 17:16:56 +01:00
.gitignore feat(release): add dev prereleases and update notices 2026-02-12 23:53:16 +00:00
.npmignore Rename CLI package to @neuralnomads/codenomad and bin codenomad 2025-11-20 23:51:44 +00:00
package-lock.json Bump version to 0.18.0 2026-06-19 13:55:00 +01:00
package.json feat(yolo): move permission auto-accept (Yolo) to the server (#561) 2026-07-08 21:13:44 +02:00
README.md feat(usage): show provider quota in session status (#584) 2026-07-15 10:25:00 +01:00
THIRD_PARTY_NOTICES.md feat(usage): show provider quota in session status (#584) 2026-07-15 10:25:00 +01:00
tsconfig.json fix(restore): simplify persistence and harden cross-platform cleanup (#602) 2026-07-17 22:17:15 +01:00

CodeNomad Server

CodeNomad Server is the high-performance engine behind the CodeNomad cockpit. It transforms your machine into a robust development host, managing the lifecycle of multiple OpenCode instances and providing the low-latency data streams that long-haul builders demand. It bridges your local filesystem with the UI, ensuring that whether you are on localhost or a remote tunnel, you have the speed, clarity, and control of a native workspace.

Features & Capabilities

🌍 Deployment Freedom

  • Remote Access: Host CodeNomad on a powerful workstation and access it from your lightweight laptop.
  • Code Anywhere: Tunnel in via VPN or SSH to code securely from coffee shops or while traveling.
  • Multi-Device: The responsive web client works on tablets and iPads, turning any screen into a dev terminal.
  • Always-On: Run as a background service so your sessions are always ready when you connect.

Workspace Power

  • Multi-Instance: Juggle multiple OpenCode sessions side-by-side with per-instance tabs.
  • Long-Context Native: Scroll through massive transcripts without hitches.
  • Deep Task Awareness: Monitor background tasks and child sessions without losing your flow.
  • Command Palette: A single, global palette to jump tabs, launch tools, and fire shortcuts.

Prerequisites

  • OpenCode: opencode must be installed and configured on your system.
  • Node.js 18+ and npm (for running or building from source).
  • A workspace folder on disk you want to serve.
  • Optional: a Chromium-based browser if you want --launch to open the UI automatically.

Usage

You can run CodeNomad directly without installing it:

npx @neuralnomads/codenomad --password <your-password> --launch

Authentication required: The server requires a password. Pass it via --password, the CODENOMAD_SERVER_PASSWORD environment variable, or create an auth.json file (see Authentication below).

To list all CLI options:

npx @neuralnomads/codenomad --help

On startup, CodeNomad prints two URLs:

  • Local Connection URL : ... (used by desktop shells)
  • Remote Connection URL : ... (used by browsers/other machines when remote access is enabled)

Install Globally

Or install it globally to use the codenomad command:

npm install -g @neuralnomads/codenomad
codenomad --password <your-password> --launch

Install Locally (per-project)

If you prefer to install CodeNomad into a project and run the local binary:

npm install @neuralnomads/codenomad
npx codenomad --password <your-password> --launch

(npx codenomad ... will use ./node_modules/.bin/codenomad when present.)

Common Flags

You can configure the server using flags or environment variables:

Flag Env Variable Description
--https <enabled> CLI_HTTPS Enable HTTPS listener (default true)
--http <enabled> CLI_HTTP Enable HTTP listener (default false)
--https-port <number> CLI_HTTPS_PORT HTTPS port (default 9898, use 0 for auto)
--http-port <number> CLI_HTTP_PORT HTTP port (default 9899, use 0 for auto)
--tls-key <path> CLI_TLS_KEY TLS private key (PEM). Requires --tls-cert.
--tls-cert <path> CLI_TLS_CERT TLS certificate (PEM). Requires --tls-key.
--tls-ca <path> CLI_TLS_CA Optional CA chain/bundle (PEM)
--tlsSANs <list> CLI_TLS_SANS Additional TLS SANs (comma-separated)
--host <addr> CLI_HOST Interface to bind (default 127.0.0.1)
--workspace-root <path> CLI_WORKSPACE_ROOT Restricts the root path where new workspaces can be opened. Git worktrees are created in .codenomad/worktrees inside the project folder.
--unrestricted-root CLI_UNRESTRICTED_ROOT Allow full-filesystem browsing
--config <path> CLI_CONFIG Config file location
--launch CLI_LAUNCH Open the UI in a Chromium-based browser
--log-level <level> CLI_LOG_LEVEL Logging level (trace, debug, info, warn, error)
--log-destination <path> CLI_LOG_DESTINATION Log destination file (defaults to stdout)
--username <username> CODENOMAD_SERVER_USERNAME Username for CodeNomad's internal auth (default codenomad)
--password <password> CODENOMAD_SERVER_PASSWORD Password for CodeNomad's internal auth
--generate-token CODENOMAD_GENERATE_TOKEN Emit a one-time local bootstrap token for desktop flows
--dangerously-skip-auth CODENOMAD_SKIP_AUTH Disable CodeNomad's internal auth (use only behind a trusted perimeter)
--ui-dir <path> CLI_UI_DIR Directory containing the built UI bundle
--ui-dev-server <url> CLI_UI_DEV_SERVER Proxy UI requests to a running dev server (requires --https=false --http=true)
--ui-no-update CLI_UI_NO_UPDATE Disable remote UI updates
--ui-auto-update <enabled> CLI_UI_AUTO_UPDATE Enable remote UI updates (true
--ui-manifest-url <url> CLI_UI_MANIFEST_URL Remote UI manifest URL

Dev Releases (Advanced)

If you want the latest bleeding-edge builds (published as GitHub pre-releases), use the dev package:

npx @neuralnomads/codenomad-dev --password <your-password> --launch

These environment variables control how CodeNomad checks for dev updates:

Env Variable Description
CODENOMAD_UPDATE_CHANNEL Update channel (use dev to enable dev build update checks)
CODENOMAD_GITHUB_REPO GitHub repo used for dev release checks (default NeuralNomadsAI/CodeNomad)

HTTP vs HTTPS

  • Default: --https=true --http=false (HTTPS only).
  • To run plain HTTP only (useful for development):
codenomad --https=false --http=true
  • To run both HTTPS (for remote) and HTTP loopback (for desktop):
codenomad --https=true --http=true

Remote Access Binding Rules

  • When remote access is enabled (bind host is non-loopback, e.g. --host 0.0.0.0):
    • HTTP listens on 127.0.0.1 only.
    • HTTPS listens on --host (LAN/all interfaces).
  • When remote access is disabled (bind host is loopback, e.g. --host 127.0.0.1):
    • Both HTTP and HTTPS listen on 127.0.0.1.

Self-Signed Certificates

If --https=true and you do not provide --tls-key/--tls-cert, CodeNomad generates a local certificate automatically under your config directory:

  • ~/.config/codenomad/tls/ca-cert.pem
  • ~/.config/codenomad/tls/server-cert.pem

Certificates are valid for about 30 days and rotate automatically on startup when needed. You can add extra SANs via:

codenomad --tlsSANs "localhost,127.0.0.1,my-hostname,192.168.1.10"

Browser warning: Self-signed certificates trigger a "Your connection is not private" warning in browsers on first visit. This is expected and safe for local development (127.0.0.1 / localhost):

  1. Chrome/Brave/Edge: Click AdvancedProceed to 127.0.0.1 (unsafe)
  2. Firefox: Click AdvancedAccept the Risk and Continue
  3. Alternative: For local-only development without the warning, run with --https=false --http=true

Note: Only accept self-signed certificates for localhost/127.0.0.1 that you control. For remote hosts, use proper TLS certificates.

Authentication

  • Default behavior: CodeNomad requires a login (username/password) and stores a session cookie in the browser.
  • --dangerously-skip-auth / CODENOMAD_SKIP_AUTH=true disables the login prompt and treats all requests as authenticated. Use this only when access is already protected by another layer (SSO proxy, VPN, Coder workspace auth, etc.). If you bind to 0.0.0.0 while skipping auth, anyone who can reach the port can access the API.

Setting a password

Practical setup options:

  1. Runtime password (every start): Use --password <your-password> or set CODENOMAD_SERVER_PASSWORD=<your-password> environment variable
  2. Persistent password (UI setup): Launch with --generate-token, complete the local bootstrap flow in your browser, then set a password through the UI settings

The --password flag and CODENOMAD_SERVER_PASSWORD env var are runtime credentials — they must be provided on every server start and are not persisted to disk.

Advanced: auth.json internals

The auth.json file (~/.config/codenomad/auth.json) is automatically created and managed by CodeNomad when you set a password through the UI. You generally don't need to edit this file manually. For reference, it uses the following scrypt-based schema:

{
  "version": 1,
  "username": "codenomad",
  "password": {
    "algorithm": "scrypt",
    "saltBase64": "<base64-salt>",
    "hashBase64": "<base64-hash>",
    "keyLength": 64,
    "params": {
      "N": 16384,
      "r": 8,
      "p": 1,
      "maxmem": 33554432
    }
  },
  "userProvided": true,
  "updatedAt": "2026-05-18T12:00:00.000Z"
}

Manual creation of this file is not recommended unless you have a helper to generate a valid scrypt PasswordHashRecord.

Progressive Web App (PWA)

When running as a server CodeNomad can also be installed as a PWA from any supported browser, giving you a native app experience just like the Electron installation but executing on the remote server instead.

  1. Open the CodeNomad UI in a Chromium-based browser (Chrome, Edge, Brave, etc.).
  2. Click the install icon in the address bar, or use the browser menu → "Install CodeNomad".
  3. The app will open in a standalone window and appear in your OS app list.

TLS requirement Browsers require a secure (https://) connection for PWA installation. If you host CodeNomad on a remote machine, use HTTPS. Self-signed certificates generally won't work unless they are explicitly trusted by the device/browser (e.g., via a custom CA).

Data Storage

  • Config: ~/.config/codenomad/config.json
  • Instance Data: ~/.config/codenomad/instances (chat history, etc.)

Provider Plan Usage

The Status panel automatically displays quota information for the provider used by the active session. CodeNomad reads existing OpenCode credentials and never returns provider secrets through its API.

Some optional usage integrations require credentials that OpenCode does not expose. They can be enabled without UI configuration through these environment variables:

  • Google token refresh: GOOGLE_OAUTH_CLIENT_ID and GOOGLE_OAUTH_CLIENT_SECRET
  • Antigravity token refresh: ANTIGRAVITY_OAUTH_CLIENT_ID and ANTIGRAVITY_OAUTH_CLIENT_SECRET
  • Cursor: CURSOR_ACCESS_TOKEN or CURSOR_TOKEN, with optional CURSOR_REFRESH_TOKEN
  • Ollama Cloud: OLLAMA_CLOUD_COOKIE
  • OpenCode Go: OPENCODE_GO_WORKSPACE_ID and OPENCODE_GO_AUTH_COOKIE