/interview command flow:
outputFolder,index.ts exports createInterviewManager.
manager.ts (composition root)
createInterviewService(ctx, interviewConfig) once.interview.dashboard === true || interview.port > 0.tryBecomeDashboard(...) to elect one process as dashboard,readDashboardAuthFile(port),/api/register and sync state back via /api/interviews/{id}/state,registerCommand, handleCommandExecuteBefore, handleEvent.createInterviewService (service.ts)
interviewsById, activeInterviewIds, sessionBusy, sessionModel.resolveExistingInterviewPath, createInterview, resumeInterview.findLatestAssistantState,buildFallbackState when needed,rewriteInterviewDocument.buildKickoffPrompt),buildResumePrompt),buildAnswerPrompt, handleNudgeAction).session.status updates busy tracking,session.deleted marks interview abandoned and drains maps.onStateChange callback for dashboard mode,onInterviewCreated callback for immediate registration,openBrowser for initial UI open.createInterviewServer (server.ts)
GET /, GET /api/interviews, GET /interview/{id}GET /api/interviews/{id}/statePOST /api/interviews/{id}/answersPOST /api/interviews/{id}/nudgegetSubmissionStatus.dashboard.ts
${XDG_DATA_HOME}/opencode/.dashboard-<port>.json,sessions registry,stateCache keyed by interview ID,rebuildFromFiles() from markdown frontmatter,Supporting modules:
document.ts: markdown/file helpers (slugify, path resolution, frontmatter,
title/summary extraction).parser.ts: assistant state parse pipeline (parseInterviewState,
findLatestAssistantState, buildFallbackState).prompts.ts: prompt templates for create/resume/answer/nudge.helpers.ts: request parsing and HTML/JSON response helpers.types.ts: domain schemas and interview contracts.src/index.ts wires this folder through
createInterviewManager(ctx, config).
Per-session mode
createInterviewServer({ port: 0 }),Dashboard mode
createInterviewManager invokes tryBecomeDashboard.setStatePushCallback,
setOnInterviewCreated),/pending and /nudge on idle.handleCommandExecuteBefore
handleEvent
session.status: idle:sessionBusy is reflected accurately.session.deleted:src/index.ts as the interview plugin module.src/interview/*.test.ts.