/interview opens a local browser UI for refining a feature idea inside the same OpenCode session.
Use it when chat feels too loose and you want a cleaner question/answer flow plus a markdown spec saved in your repo.
Tip:
/interviewusually works well with a fast model. If the flow feels slower than it should, switch models in OpenCode withCtrl+X, thenm, and pick a faster one.
Start a new interview:
/interview build a kanban app for design teams
What happens:
OpenCode posts a localhost URL like this:
And the browser UI looks like this:
Resume an existing interview:
/interview interview/kanban-design-tool.md
You can also resume by basename if it exists in the configured output folder:
/interview kanban-design-tool
By default, interview files are written to:
interview/
Example:
interview/kanban-design-tool.md
The file contains three sections:
Frontmatter - session meta data for recoveryCurrent spec - 11-section structured specification doc (Introduction, Purpose, Requirements, Data Contracts, Acceptance Criteria, etc.)Q&A history - append-only question/answer recordExample:
# Kanban App For Design Teams
## Current spec
# Introduction
...
## 1. Purpose & Scope
...
## Q&A history
Q: Who is this for?
A: Design teams
Q: Is this web only or mobile too?
A: Web first
For new interviews, the assistant can suggest a concise title for the markdown filename.
Example:
build a kanban app for design teams with lightweight reviewsinterview/kanban-design-tool.mdIf the assistant does not provide a title, the original input is slugified as a fallback.
Interview files include YAML frontmatter for recovery after a crash or restart:
---
sessionID: ses_abc123
baseMessageCount: 42
updatedAt: 2026-04-14T10:30:00.000Z
---
This allows the dashboard to rebuild state from disk without a live session.
Inside the interview page:
1, 2, 3, ... select options for the active questionCustom↑ / ↓ move the active questionCmd+Enter or Ctrl+Enter submitsCmd+S or Ctrl+S also submitsThe interview module has two modes: per-session (default) and dashboard (opt-in).
When port is 0 (or unset) and dashboard is false (or unset), each OpenCode process runs its own interview server on a random port. This is the original behavior - no configuration needed.
{
"oh-my-opencode-slim": {
"interview": {}
// or explicitly:
// "interview": { "port": 0 }
}
}
/interview commandWhen dashboard is true or port is set to a value greater than 0, interview switches to dashboard mode. A single dashboard server aggregates interviews from all OpenCode sessions on the same machine.
// Option A: dashboard on default port (43211)
"interview": { "dashboard": true }
// Option B: dashboard on custom port
"interview": { "dashboard": true, "port": 8888 }
// Option C: port > 0 implies dashboard mode
"interview": { "port": 43211 }
.md files on disk.interview/ (or your configured output folder) across all known project directories, including your home directory.┌──────────────────────────────────────────────┐
│ Dashboard (dumb aggregator) │
│ │
│ • Receives state pushes from sessions │
│ • Serves dashboard UI + interview pages │
│ • Stores pending answers for session pickup │
│ • Binds to 127.0.0.1, token-authenticated │
└───────────▲───────────────────▲───────────────┘
│ POST state │ GET pending answers
┌───────────┴────────┐ ┌───────┴──────────────┐
│ Session Process A │ │ Session Process B │
│ (smart - drives │ │ (smart - drives │
│ LLM locally) │ │ LLM locally) │
└─────────────────────┘ └───────────────────────┘
Sessions are smart - they drive LLM interaction locally (parse state, inject prompts, write .md files). The dashboard is a dumb aggregator with a web UI. This means zero cross-process SDK dependency.
Browser submissions use a claim/ack delivery protocol. A session claims an answer, chat message, block comment, or nudge before forwarding it to OpenCode; successful forwarding acknowledges the claim, while a rejected continuation rolls it back for a later retry. A failed poll therefore never silently drops a queued action.
Any OpenCode process can become the dashboard. The first process to bind the configured port wins. If it dies:
.md files on disk using frontmatterSessions register their project directory with the dashboard so it knows where to scan for interview files. This happens automatically on first /interview command or session event - no manual setup needed.
The dashboard also scans your home directory's output folder by default, so interviews created from a home-directory OpenCode session are always visible.
The dashboard page includes a settings panel for:
{
"oh-my-opencode-slim": {
"interview": {
"maxQuestions": 2,
"outputFolder": "interview",
"autoOpenBrowser": true,
"port": 0,
"dashboard": false
}
}
}
maxQuestions - max questions per round, 1-10, default 2outputFolder - where markdown files are written, default interviewautoOpenBrowser - open the localhost UI in your default browser during interactive runs, default true (suppressed automatically in tests and CI)port - port for the interview server, 0-65535, default 0 (OS-assigned in per-session mode). Set a fixed port to enable dashboard mode. Note: ports 1-1023 require elevated privileges on most systems.dashboard - enable dashboard mode on the default port (43211), default false. Setting port to a value greater than 0 also enables dashboard mode. If both are set, port takes precedence.port |
dashboard |
Mode |
|---|---|---|
0 (default) |
false (default) |
Per-session - each process runs its own server |
0 |
true |
Dashboard on default port 43211 |
> 0 |
any | Dashboard on the specified port |
The v2 bridge receives the resolved values for all five interview options, so
maxQuestions, outputFolder, autoOpenBrowser, port, and dashboard are
also honored when OpenCode loads the v2 plugin entry point.
The interview UI binds to 127.0.0.1. To access it from a remote machine:
tailscale serve --bg --https=443 http://127.0.0.1:<port>
cloudflared tunnel --url http://127.0.0.1:<port>
ssh -L <port>:127.0.0.1:<port> your-server
<interview_state> blocksOn OpenCode v2, /interview uses an orchestrator-owned marker command and a
context bridge. Only the trailing marker message is rewritten, preserving the
provider cache prefix; streamed text events build the interview transcript in
memory. The bridge uses the v2 session methods for notifications, continuation,
and renaming without expanding the global client shim.
Selecting Complete asks for clean final markdown. The next clean assistant
response replaces only Current spec; frontmatter and append-only Q&A
history are retained, so stale <interview_state> output cannot overwrite the
final document.
In dashboard mode, session clients register at /api/register and unregister
at /api/unregister during cleanup. Browser submissions return HTTP 202 with
{ "status": "queued" }; the owning session processes them when idle.