[FEATURE]: Named Remote Connections with Session Origin Tracking #4004

Open
opened 2026-02-16 17:42:15 -05:00 by yindo · 2 comments
Owner

Originally created by @isaiahdahl on GitHub (Dec 30, 2025).

Originally assigned to: @thdxr on GitHub.

Feature hasn't been suggested before.

  • 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 deploy@staging.example.com "cd /var/www/app && opencode serve --port 4096"

Create tunnel in another terminal

ssh -L 4096:localhost:4096 deploy@staging.example.com

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://deploy@staging.example.com --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://deploy@staging.example.com --workdir /var/www/app

List saved connections

opencode attach --list

Saved connections:
  frontend    docker://frontend-app:/app
  staging     ssh://deploy@staging.example.com:/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.

Originally created by @isaiahdahl on GitHub (Dec 30, 2025). Originally assigned to: @thdxr on GitHub. ### 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 <url> 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 deploy@staging.example.com "cd /var/www/app && opencode serve --port 4096"` #### Create tunnel in another terminal `ssh -L 4096:localhost:4096 deploy@staging.example.com` #### 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://deploy@staging.example.com --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://deploy@staging.example.com --workdir /var/www/app` ### List saved connections `opencode attach --list` ``` Saved connections: frontend docker://frontend-app:/app staging ssh://deploy@staging.example.com:/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 <uri> |Connect to environment via transport URI| |opencode attach <name> |Connect to saved environment by name | |opencode attach --save <name> <uri> |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 <name> |Remove a saved connection | |opencode session list --origin <name>|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 <container> 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.
yindo added the discussion label 2026-02-16 17:42:15 -05:00
Author
Owner

@github-actions[bot] commented on GitHub (Dec 30, 2025):

This issue might be a duplicate of existing issues. Please check:

  • #5608: [FEATURE]: OpenCode-Desktop Remote Workspace - requests remote development workflow similar to VS Code
  • #5445: Add --session flag to opencode attach command - proposes adding session selection to attach command
  • #878: Feature Request: Connect TUI to Existing opencode serve Instance - requests ability to connect TUI to headless server
  • #4780: Can opencode ssh into and access a remote machine - question about SSH remote execution
  • #2963: Run agent remote sessions transparently aka Warpify - requests transparent remote session execution like Warp

Feel free to ignore if your feature request addresses these in different ways or has specific additional requirements.

@github-actions[bot] commented on GitHub (Dec 30, 2025): This issue might be a duplicate of existing issues. Please check: - #5608: [FEATURE]: OpenCode-Desktop Remote Workspace - requests remote development workflow similar to VS Code - #5445: Add --session flag to opencode attach command - proposes adding session selection to attach command - #878: Feature Request: Connect TUI to Existing `opencode serve` Instance - requests ability to connect TUI to headless server - #4780: Can opencode ssh into and access a remote machine - question about SSH remote execution - #2963: Run agent remote sessions transparently aka Warpify - requests transparent remote session execution like Warp Feel free to ignore if your feature request addresses these in different ways or has specific additional requirements.
Author
Owner

@FlippingBinary commented on GitHub (Dec 30, 2025):

This might also be very useful for cross-platform development with remote agents on different platforms, especially if they could be orchestrated as if they were local (like how oh-my-opencode's Sisyphus orchestrates local agents and background tasks).

@FlippingBinary commented on GitHub (Dec 30, 2025): This might also be very useful for cross-platform development with remote agents on different platforms, especially if they could be orchestrated as if they were local (like how `oh-my-opencode`'s Sisyphus orchestrates local agents and background tasks).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#4004