7 min read
A coding CLI becomes a service when sessions have owners
A process is not a product boundary
When I run a coding agent in a terminal, the boundary feels obvious: I start it, give it a task, and watch what it does. When the agent runs as a background service with an API and SDK, that boundary moves. The agent can outlive the terminal that started it, and another client can interact with its session. Now I have to decide who owns that work and what it means for a client to attach, disappear, or come back.
That is the architectural change I see in OpenCode 2.0’s announcement: the project describes a background service, an API and SDK, and Code Mode. The interesting shift is not simply that a CLI can be driven by another program. It is that the agent has become a service with a lifecycle beyond one interactive process.
I would not infer from “shared service” that a deployment is automatically a safe multi-user service. Sharing among a person’s clients and sharing across an organization are different contracts. The first may mean a terminal, desktop app, and web client connect to one local agent. The second introduces questions about identity, tenant boundaries, and which workspace a user is allowed to reach. Those distinctions need to be designed, not assumed from the presence of an API.
My starting position is simple: a session belongs to an explicitly identified owner, and a client connection is not that owner. If I blur those concepts, I make it hard to reason about who can resume work, who can approve an action, and who is responsible for cleaning up the resources it leaves behind.
A session needs an owner, not just an ID
An identifier tells a client which session it is asking about. It does not, by itself, tell the service whether that client is allowed to read, change, or stop the session. I would treat session ownership as a record the service can check on every operation, rather than as a convention in the user interface.
For a single-user local service, the owner might be the local user and the project directory might further bound the session. For a hosted service, I would expect an authenticated principal and an explicit workspace or tenant boundary. Those are different deployments; I would not quietly move from one to the other while keeping the same assumptions about trust.
A useful contract separates the concepts, even if the first implementation is small:
// Illustrative service contract, not an OpenCode API example.
type SessionRecord = {
id: string
ownerId: string
workspaceId: string
state: "running" | "waiting" | "finished" | "cancelled"
}
type ClientConnection = {
principalId: string
connectionId: string
}
function canAccessSession(
client: ClientConnection,
session: SessionRecord,
): boolean {
return client.principalId === session.ownerId
}
The important point is not this particular type shape. It is that session ownership remains true when the initiating client disconnects. If I instead tie ownership to a socket, browser tab, or terminal process, a temporary network interruption starts to look like an authorization change. That is the wrong coupling.
The OpenCode SDK documentation exposes session operations such as creating, listing, retrieving, and deleting sessions, alongside APIs for handling permission requests. That surface is useful because it makes the session a managed resource rather than an invisible side effect of a command. It also makes the caller’s authority consequential: an API that can list or delete sessions needs the same deliberate access policy as one that sends a prompt.
Reconnection is a consistency decision
I would expect clients to disconnect. Laptops sleep, browser tabs reload, and network paths fail. Those are ordinary operating conditions, not exceptional cases that justify throwing away the session.
So I would define reconnection as: authenticate again, prove access to the existing session, obtain its current state, then resume observing it. I would not let reconnect mean “start the prompt again.” Retrying a request that may already have reached the agent can duplicate work or produce a second set of side effects. A client needs a way to distinguish a new command from a retry of an earlier command; an idempotency key or another explicit request identity is one design option.
I would also separate durable state from live delivery. A stream of events is useful while connected, but it is not a durable history. If the client misses events, it needs a way to recover from the service’s current session state or a stored event position. Otherwise the UI can show a stale “running” status after the agent has stopped, or miss a permission request it must answer.
The service therefore needs to define which state survives a client reconnect, which state survives a service restart, and what a client can infer when it cannot get a definitive answer. “The connection dropped” is not a session state. I would make the service answer whether the session is running, waiting for input or permission, finished, or cancelled—and make the client handle each case without guessing.
Authorization belongs at the action boundary
A session may have access to a repository, tools, or credentials. A client that can send it instructions can potentially cause those capabilities to be used. That makes authorization more than a check when the session is created. I would check it when the client reads session data, sends a prompt, responds to a permission request, changes settings, or cancels work.
I would keep the authority to perform an action distinct from the authority to approve it. If the same automated client can both initiate a sensitive operation and silently satisfy every approval gate, the gate is not doing useful work. The right policy depends on the deployment, but the boundary should be explicit and testable.
Code Mode makes this consideration more important, not less. OpenCode’s 2.0 announcement describes it as a way for the agent to compose tool calls through code. I see that as a change in orchestration: fewer isolated interactions may be packaged into a larger operation. That can be useful, but it means I should inspect the permissions of the tools and resources reachable through the service, rather than assuming that a friendly client interface is a security boundary.
For an organization, I would begin with a narrow service identity and explicit workspace scope. I would not expose a service endpoint to a broader network and rely on possession of a session ID as the access policy. Nor would I assume that “the user is logged into the client” proves that every request arriving at the service is that user. Authentication, authorization, and network exposure are separate parts of the contract.
Lifecycle is part of the API
If sessions can outlive clients, the service needs a policy for when they stop. I would define who can cancel a running task, what happens when an owner is removed, and whether finished sessions are retained or deleted. Leaving all of that implicit turns an implementation detail into an accidental retention and resource policy.
The workspace boundary needs equal care. A session that refers to a working directory cannot safely be treated as a free-floating conversation if the directory disappears, moves, or becomes available to a different principal. I would have the service validate that the workspace is still available and authorized before resuming work, rather than trusting a path remembered by an earlier client.
I would design the first version for one clear ownership model, then add broader sharing only when there is a real requirement. A local service owned by one user is a coherent product. A team service needs explicit membership, role decisions, auditability, and cleanup rules. Calling both “the same agent with an API” hides the additional system I am taking responsibility for.
That is the operational contract I would ask for before treating a coding CLI as a shared service: sessions have durable owners, reconnects recover state without replaying work, authorization is checked where actions happen, and lifecycle rules say who can stop and clean up. The SDK makes integration possible; the contract is what makes that integration safe to operate.
Drafted with AI assistance, reviewed and edited by Ali.