feat(runtime): add execution profiles#408
Conversation
Introduce server-scoped execution profiles for local, WSL, Docker, and command runtimes so workspace creation can choose a runtime strategy instead of relying on a single default binary path. Add device-scoped connection profile foundations for remote server shortcuts and SSH bootstrap metadata, then surface both profile systems in the home screen and settings flows so runtime selection and remote reconnect UX can evolve together. Implement initial Docker and custom-command launch builders plus SSH bootstrap and tunnel session management for remote connections. Validation ran with the server and UI typechecks, the UI production build, and targeted tests for execution profile resolution and launch command generation.
Add a first-class SSH connection flow to the home screen so users can save an SSH bootstrap target, reconnect from recent connections, and open the remote server window without dropping into settings first. Expose the active execution profile in instance information and add the required localized strings so the selected runtime and SSH connection metadata remain visible after launch. Validation: npm run typecheck --workspace @codenomad/ui; npm run typecheck --workspace @neuralnomads/codenomad; npm run build --workspace @codenomad/ui.
Add a first-class 'Connect SSH Host' flow to the home screen so users can save SSH bootstrap targets, reconnect them from the shared connections list, and open the remote window without detouring through settings. Rename the home-screen remote tab from 'Servers' to 'Connections' so it accurately covers both remote server URLs and SSH-based entries, and expose the active execution profile inside instance information for easier runtime verification. Validation: npm run typecheck --workspace @codenomad/ui; npm run typecheck --workspace @neuralnomads/codenomad; npm run build --workspace @codenomad/ui.
Add a Preview command flow to Execution Profiles so operators can inspect the exact launcher command, working directory, and injected environment before targeting custom runtimes. The settings UI now requests a server-generated preview and renders the resolved command line alongside an optional sample workspace path for Docker mounts and cwd resolution. Build previews from the same launch and spawn pipeline used at runtime so WSL profiles show the real wsl.exe wrapper, WSLENV propagation, and quoting behavior instead of a simplified placeholder command. Reuse current server config for log level, environment variables, auth endpoints, and config paths while redacting secrets in the response. Validation: npm run typecheck --workspace @neuralnomads/codenomad; npm run typecheck --workspace @codenomad/ui; npm run build --workspace @codenomad/ui; node --import tsx --test packages/server/src/workspaces/execution-launch.test.ts
Add a lightweight Test profile action beside the execution profile preview so operators can verify that a runtime is actually reachable from the CodeNomad host before using it for new workspaces. The settings screen now reports a pass/fail result and reuses the resolved preview payload for context. Use a server-side test endpoint that stays intentionally minimal: local and WSL profiles validate the target binary, custom command profiles validate the wrapper executable, and Docker profiles validate both the Docker CLI and the configured local image. This keeps the first test pass fast and low-risk without spawning an OpenCode server. Validation: npm run typecheck --workspace @neuralnomads/codenomad; npm run typecheck --workspace @codenomad/ui; npm run build --workspace @codenomad/ui
Add copy actions for execution and connection profiles so users can create variants without rebuilding existing SSH or runtime settings from scratch. The duplicated records receive fresh ids and connection copies clear last-connected metadata while preserving the original launch or SSH fields. Locale keys are added for the new actions and shared copy suffix. Validated earlier with the targeted UI typecheck and build for the duplicate profile changes.
Show the last successful connection time in the Home connection list and in Settings so saved SSH and remote server profiles communicate which targets were used recently. The display reuses persisted lastConnectedAt metadata, keeps invalid timestamps hidden in Settings, and adds locale keys for both Home and Settings surfaces without changing connection behavior. Validated with npm run typecheck --workspace @codenomad/ui and npm run build --workspace @codenomad/ui.
Internationalize the saved connection type badges on the Home screen and show SSH targets with their configured port so similar hosts are easier to distinguish before connecting. The change keeps the existing connection flow intact, centralizes the display target formatting in the Home view, and adds locale keys for every registered UI language. Validated with npm run typecheck --workspace @codenomad/ui and npm run build --workspace @codenomad/ui.
Format saved SSH connection summaries without a stray space before the port so Settings matches the Home connection list and hosts with custom ports are easier to scan. The change is display-only and keeps remote path rendering unchanged. Validated with npm run typecheck --workspace @codenomad/ui.
Address review risks around execution and connection profiles before taking the draft PR out of validation. Docker runtime secrets now flow through process environment instead of command-line KEY=value args, runtime/request logs redact sensitive profile payloads, and WSL profiles carry their distro into spawn/test/preview resolution so Linux paths launch through wsl.exe. SSH connection handling now defaults to the HTTP listener port, uses bounded non-interactive SSH options, validates option-like host/user inputs, and avoids saving duplicate profiles when Save & Connect fails. Config normalization now preserves valid execution profiles when a malformed entry is present. UI polish localizes desktop-only errors and execution profile kinds, updates SSH remote port defaults, and keeps remote window errors on the i18n path. Validated with server/UI typechecks, targeted execution launch/spawn/binary resolver tests, and the UI build.
|
@pascalandr - We need to discuss this as it won't work as it is. It depends on the opencode-config folder that resides on the server. |
Clarify in the SSH connection dialog and settings form that bootstrap scripts must start a remote CodeNomad server installation with its own server-side opencode-config available. This avoids implying that the SSH flow copies the local plugin config to the remote host; it only opens a tunnel to a remote CodeNomad server. Validated with npm run typecheck --workspace @codenomad/ui.
Resolve PR NeuralNomadsAI#408 conflicts after upstream dev added clone-repository workspace support. The only manual conflict was in the Home view imports, where both the connection-profile additions and the new clone-workspace GitBranch icon are preserved. Validated with server and UI typechecks, targeted server tests including git clone coverage, and the UI build.
Refocus PR NeuralNomadsAI#408 on choosing how workspaces launch the OpenCode runtime: local, WSL, Docker, and custom command profiles. This removes the managed SSH tunnel/bootstrap-to-remote-CodeNomad-server path because remote server transport is already handled outside CodeNomad and by the existing Connect CodeNomad Server flow. The cleanup removes connection-profile abstractions, SSH tunnel API routes/session management, and SSH bootstrap UI/copy while preserving saved remote server behavior. It also redacts sensitive preview args and keeps readiness-failure runtime cleanup from the earlier hardening work. Validated with server and UI typechecks, targeted execution/spawn/clone tests, and the UI production build.
Adds SSH as a first-class execution profile so the current CodeNomad server can launch OpenCode on a remote host without introducing a second remote CodeNomad server lifecycle. The launcher reserves local runtime and callback ports, starts OpenCode through ssh with forward and reverse tunnels, and rewrites callback URLs for the remote shell environment. Settings schemas, preview/test routes, UI form fields, i18n messages, and instance metadata now understand the ssh profile kind. Validation covers resolver behavior and launch command generation for SSH alongside existing WSL, Docker, command, spawn, and clone workspace tests. Verified with server and UI typechecks plus the UI production build.
Keeps Docker and SSH execution profiles reachable from the current CodeNomad server by reserving host ports before launch and using fixed OpenCode runtime ports for forwarded transports. Docker profiles now publish the reserved runtime port on localhost instead of relying on an unexposed container port. SSH profiles send the remote shell script over stdin, validate environment variable names before interpolation, and avoid placing callback secrets in the local ssh argv. The UI preferences normalizer now preserves saved SSH execution profiles so settings round-trips do not drop them. Coverage adds Docker reserved-port assertions and an unsafe SSH environment-name regression test.
Docker execution profiles publish a reserved localhost port on the host, so OpenCode must bind to all container interfaces rather than the default loopback address inside the container. Adds --hostname 0.0.0.0 only for Docker launches while leaving local, WSL, command, and SSH behavior unchanged. The launch test asserts the fixed port, publish mapping, and container bind host stay aligned.
SSH execution profiles run OpenCode on a different filesystem, so the server-local OpenCode config template cannot be referenced directly by OPENCODE_CONFIG_DIR. Before launching the remote runtime, CodeNomad now archives the packaged OpenCode config template and streams it over ssh into a per-workspace directory under /tmp on the remote host. The SSH launch environment then points OPENCODE_CONFIG_DIR at that remote directory and best-effort cleanup removes it when the runtime exits or startup fails. This keeps SSH as an execution profile for the current CodeNomad server while addressing the config locality issue raised in review. Verified with server/UI typechecks, focused runtime tests, and the UI production build.
Resolved in latest push. The SSH execution profile no longer points the remote OpenCode process at the server-local config path. Before launching the SSH runtime, CodeNomad now archives the packaged OpenCode config template and streams it over ssh into a per-workspace directory on the remote host under /tmp, then sets OPENCODE_CONFIG_DIR to that remote path for the launched opencode serve process. Cleanup is best-effort on exit/startup failure. Docker/WSL/local continue using their existing local/mapped config paths. |
Use scp to copy the packaged OpenCode config directory to SSH execution hosts before launch instead of streaming a tar archive. This keeps SSH profiles independent from a local-only OPENCODE_CONFIG_DIR while avoiding a tar dependency on either side of the connection. The remote temp directory is still cleaned before copy and after runtime shutdown, and the SSH target validation is shared between ssh and scp command construction. Validated with the server typecheck and focused workspace/settings tests.
|
Updated the SSH config sync to avoid the tar dependency. SSH profiles now clean the remote temp config directory with ssh, copy the packaged OpenCode config with scp -r, and keep using that remote path for OPENCODE_CONFIG_DIR. Validated after rebasing on the latest branch:
|
|
I was thinking about how to make opencode_config implementation better. Essentially it is an opencode plugin that is used for codenomad.
|
|
opencode-config features is being worked in #433 |
|
@shantur |
Summary
local,wsl,docker,command, andsshruntimes so new workspaces can choose how the OpenCode runtime is launched.Preview commandandTest profileflows so users can inspect launch commands and validate local/WSL/Docker/custom command/SSH profiles before using them.Scope
opencode serveon the configured remote host throughssh, forward the remote OpenCode runtime back to the current CodeNomad server, and reverse-forward callback traffic back to the current server.Connect CodeNomad Serverflow; network transport such as VPN, SSH tunnel, Tailscale, or reverse proxy stays external to CodeNomad.Validation
npm run typecheck --workspace @neuralnomads/codenomadnpm run typecheck --workspace @codenomad/uinpm run build --workspace @codenomad/uinode --import tsx --test "packages/server/src/settings/binaries.test.ts" "packages/server/src/workspaces/execution-launch.test.ts" "packages/server/src/workspaces/__tests__/spawn.test.ts" "packages/server/src/workspaces/__tests__/git-clone.test.ts"Notes