Minimal useOpenCodeRuntime setup against a local OpenCode server.
This page sets up a working chat against a local OpenCode server in three steps. It assumes you have OpenCode running; if not, follow opencode.ai to install and start the server first.
Wire up the runtime provider
"use client";
import { AssistantRuntimeProvider } from "@assistant-ui/react";
import { useOpenCodeRuntime } from "@assistant-ui/react-opencode";
export function MyRuntimeProvider({
children,
}: {
children: React.ReactNode;
}) {
const runtime = useOpenCodeRuntime({
baseUrl: "http://localhost:4096",
});
return (
<AssistantRuntimeProvider runtime={runtime}>
{children}
</AssistantRuntimeProvider>
);
}baseUrl defaults to http://localhost:4096 if omitted.
Render the Thread
import { Thread } from "@/components/assistant-ui/elements/thread.aui";
import { MyRuntimeProvider } from "./MyRuntimeProvider";
export default function Page() {
return (
<MyRuntimeProvider>
<Thread />
</MyRuntimeProvider>
);
}Set up UI components
Follow the UI Components guide to wire up the Thread, composer, and supporting primitives.
The runtime opens an SSE event stream against the OpenCode server, listens for session and message events, and projects them into the thread. Each OpenCode session corresponds to one thread; the thread list reflects sessions on the server.
Archiving an OpenCode session is one-way: OpenCode has no way to unarchive it, so an archived session still opens but stays archived, and unarchiving it rejects.
Default model and agent
Pin a default model or agent when starting new sessions:
const runtime = useOpenCodeRuntime({
baseUrl: "http://localhost:4096",
defaultModel: { providerID: "anthropic", modelID: "claude-sonnet-5" },
defaultAgent: "coder",
});Bring your own client
If you need a pre-configured OpencodeClient (e.g. for auth headers), pass it directly:
import { createOpencodeClient } from "@assistant-ui/react-opencode";
const client = createOpencodeClient({
baseUrl: "http://localhost:4096",
// additional client config...
});
const runtime = useOpenCodeRuntime({ client });Create the client once, outside the component or in useState. The runtime keeps its connection and thread list per client, so a client built inline on every render never settles.
Resuming a session
Pass initialSessionId to open the runtime against an existing session on first load:
const runtime = useOpenCodeRuntime({
baseUrl: "http://localhost:4096",
initialSessionId: "ses_abc123",
});Store threads in Assistant Cloud
Pass cloud to back the thread list with Assistant Cloud instead of the OpenCode server's session list. cloud is the only switch: unlike the runtimes whose list lives in the browser, NEXT_PUBLIC_ASSISTANT_BASE_URL alone keeps the OpenCode session list. Each cloud thread maps to an OpenCode session through its external id: a new thread creates a session, deleting the thread deletes its session when the session still exists, and the dashboard shows the conversation. The thread list opens cloud threads, so initialSessionId is not used with cloud. A cloud thread that no OpenCode runtime created has no session: it opens empty, and sending in it rejects. Renaming and archiving change the cloud thread only; the OpenCode session keeps its own title.
const runtime = useOpenCodeRuntime({
baseUrl: "http://localhost:4096",
cloud,
});