opencode icon indicating copy to clipboard operation
opencode copied to clipboard

[FEATURE]: Named Remote Connections with Session Origin Tracking

Open isaiahdahl opened this issue 3 weeks ago • 2 comments

Feature hasn't been suggested before.

  • [x] I have verified this feature I'm about to request hasn't been suggested before.

Describe the enhancement you want to request

Problem Statement

Modern development increasingly happens inside isolated environments—Docker containers for different services, remote staging servers, VMs with specific toolchains, Kubernetes pods. Each environment has its own dependencies, tools, and file access. An AI coding agent must run inside the environment where the code lives because that’s where the tools work: the container with Node 22, the php server with it's own cli commands, the ML environment with GPU drivers.

OpenCode already has the primitives for this architecture:

opencode serve runs a headless daemon opencode attach connects a local TUI to a remote daemon But there’s significant friction in using these primitives for real multi-environment workflows.

What Multi-Environment Development Looks Like Today

Consider a typical microservices project with three containers:

Terminal 1: Start daemon in frontend container

docker exec -it frontend-app opencode serve --port 4001

Terminal 2: Start daemon in API container

docker exec -it backend-api opencode serve --port 4002

Terminal 3: Attach to one of them

opencode attach http://localhost:4001 # Which service was this again?

The next day, you return to your machine:

Are those daemons still running? What ports did you use? Which container was on which port? Your sessions are scattered across environments with no way to see them together

For SSH environments, the friction multiplies:

Start daemon on staging

ssh [email protected] "cd /var/www/app && opencode serve --port 4096"

Create tunnel in another terminal

ssh -L 4096:localhost:4096 [email protected]

Attach in a third terminal

opencode attach http://localhost:4096 This isn’t a power-user workflow—it’s the default experience for anyone using OpenCode with containers or remote hosts.

The Core Friction Points

No persistent connection memory — You must remember which URL corresponds to which environment. Ports are arbitrary numbers with no semantic meaning. Manual daemon lifecycle — Every reconnection requires checking if the daemon is running, restarting it if not, and re-establishing any tunnels. Sessions lack environment context — opencode session list shows a flat list. There’s no way to see “show me my staging sessions” or understand where a session ran. No shareable environment definitions — Teams can’t commit environment configurations to version control.

Why External Tooling Doesn’t Fully Solve This

Shell aliases and scripts can help with connection management:

alias oc-frontend='docker exec -it frontend-app opencode serve --port 4001 & sleep 2 && opencode attach http://localhost:4001' But this doesn’t solve:

Session organization — Sessions still have no environment metadata Cross-machine consistency — Aliases live in dotfiles, not project config Status visibility — No unified view of what’s running where Team sharing — Each developer maintains their own scripts The session organization problem specifically cannot be solved externally—it requires OpenCode to track where sessions originated.


Proposed Solution

Extend the existing attach command to support named connections with transport handlers, automatic daemon lifecycle management, and session origin tracking.

1. Transport URIs and Named Connections

Support URIs that specify how to connect to an environment:

Docker container

opencode attach docker://frontend-app --workdir /app

SSH host

opencode attach ssh://[email protected] --workdir /var/www/app

Kubernetes pod

opencode attach k8s://pod-name --namespace default --workdir /app

####Plain URL (existing behavior) opencode attach http://localhost:4096 Save connections with friendly names:

Save a connection

opencode attach --save frontend docker://frontend-app --workdir /app opencode attach --save staging ssh://[email protected] --workdir /var/www/app

List saved connections

opencode attach --list

Saved connections:
  frontend    docker://frontend-app:/app
  staging     ssh://[email protected]:/var/www/app

2. Connect by Name with Auto-Start

Once saved, connect by name:

opencode attach frontend

This command:

Looks up the saved connection frontend Checks if a daemon is already running in that environment If not, starts opencode serve via the appropriate transport (docker exec, ssh, kubectl exec) Establishes any necessary tunneling Attaches the local TUI to the remote daemon First connection shows the setup:

$ opencode attach frontend

Connecting to frontend (docker://frontend-app)... ✓ Container is running ✓ Started daemon on port 4001 ✓ Connected Subsequent connections are instant:

$ opencode attach frontend

Connecting to frontend... ✓ Daemon already running ✓ Connected

3. Session Origin Tracking

Sessions automatically record which environment they originated from:

$ opencode session list

ID          Origin      Title                        Updated
ses_abc123  staging     Fix API rate limiting        2 min ago
ses_def456  frontend    Refactor auth components     1 hour ago
ses_ghi789  api         Debug payment webhook        3 hours ago
ses_xyz000  local       Update README                1 day ago

Filter by origin:

$ opencode session list --origin staging

ID          Origin      Title                        Updated
ses_abc123  staging     Fix API rate limiting        2 min ago
ses_old456  staging     Deploy hotfix                3 days ago

4. Connection Status Overview

See the state of all saved connections:

$ opencode attach --status

Connection    Status          Port    Sessions
frontend      ● running       4001    3 sessions
api           ● running       4002    5 sessions
staging       ○ disconnected  -       4 sessions
ml            ○ stopped       -       2 sessions

5. Project Configuration

Define environments in opencode.json for team sharing:

{
  "environments": {
    "frontend": {
      "transport": "docker",
      "container": "frontend-app",
      "workdir": "/app"
    },
    "api": {
      "transport": "docker", 
      "container": "backend-api",
      "workdir": "/app"
    },
    "staging": {
      "transport": "ssh",
      "host": "staging.example.com",
      "user": "deploy",
      "workdir": "/var/www/app"
    }
  }
}

Project-defined environments merge with user-saved connections. Teams commit shared environments; individuals add their own.


CLI Summary

All functionality extends the existing attach command:

Command Description
opencode attach Connect to environment via transport URI
opencode attach Connect to saved environment by name
opencode attach --save Save a connection with a friendly name
opencode attach --list List saved connections
opencode attach --status Show running state of all connections
opencode attach --remove Remove a saved connection
opencode session list --origin Filter sessions by environment

Supported Transports

URI Scheme Description Example
docker:// Docker container docker://container-name
ssh:// SSH host ssh://user@host
k8s:// Kubernetes pod k8s://pod-name
podman:// Podman container podman://container-name
http:// Direct URL (existing) http://localhost:4096

New transports can be added as the ecosystem evolves.


Implementation Notes

Transport Handler Interface

Each transport implements:

interface TransportHandler {
  // Check if the environment is available (container running, host reachable)
  checkAvailable(): Promise<boolean>
  
  // Check if opencode daemon is already running in the environment
  checkDaemonRunning(): Promise<{ running: boolean; port?: number }>
  
  // Start opencode serve in the environment, return the port
  startDaemon(): Promise<number>
  
  // Establish connection (e.g., SSH tunnel) and return local URL
  connect(remotePort: number): Promise<string>
  
  // Clean up (close tunnels, etc.)
  disconnect(): Promise<void>
}

Session Metadata

Add origin field to session storage:

interface Session {
  id: string
  title: string
  // ... existing fields
  origin?: string  // Name of the environment, e.g., "frontend", "staging"
}

When a session is created via a named connection, the origin is automatically populated.

Daemon Discovery

For checking if a daemon is running:

Docker: docker exec pgrep -f "opencode serve" or attempt HTTP health check SSH: Similar check over SSH K8s: kubectl exec equivalent Alternatively, maintain a lightweight state file in the environment that records the daemon port.


Non-Goals

This proposal intentionally avoids:

Auto-installation of OpenCode on remotes — Security implications, and users can install OpenCode themselves. The connect command should fail clearly if OpenCode isn’t available in the environment. Auto-discovery of containers/hosts — Explicit configuration is clearer than magic detection. Users know their environments. Container orchestration — This doesn’t replace docker-compose or Kubernetes. It connects to containers that are already running. Complex process supervision — Just “check if running, start if not.” No restart policies or health monitoring.


Use Cases

Microservices Development

Each service runs in its own container with its own dependencies. Developer connects to whichever service they’re currently working on:

opencode attach frontend # Working on React app opencode attach api # Switch to backend work opencode attach ml # Debug recommendation engine Sessions stay organized by service.

Staging/Production Debugging

Quick connection to remote environments with session history preserved:

opencode attach staging

... debug issue, session saved with origin "staging"

Later, review what was done:

opencode session list --origin staging

Polyglot Projects

Different containers with different language toolchains. The Python ML container has different tools than the Go API container. Each environment gets its own agent instance with appropriate tool access.

Team Onboarding

New developer clones repo, environments are already defined:

git clone repo cd repo opencode attach --list

Shows: frontend, api, worker (from opencode.json)

opencode attach frontend

Just works


Summary

This feature extends OpenCode’s existing remote capabilities into a coherent workflow for multi-environment development. The key additions are:

Transport URIs — docker://, ssh://, k8s:// schemes for connecting to environments Named connections — Save and reuse connection configurations Automatic lifecycle — Start daemon if not running, establish tunnels as needed Session origin tracking — Sessions know where they came from Project configuration — Shareable environment definitions in opencode.json All functionality extends the existing attach command rather than introducing new command namespaces, keeping the CLI surface area minimal while significantly improving the multi-environment experience.

isaiahdahl avatar Dec 30 '25 18:12 isaiahdahl