claude_code_report
Generate HTML reports of workflow runs. For a specific run ID, get agent sequence, cost breakdown, and collapsible transcripts. Omit run ID to list all runs.
Instructions
Generate a self-contained HTML report of a workflow run. No args: list all runs. run_id: detailed report for that run with agent sequence, cost breakdown, and collapsible transcripts. Save the returned HTML to a file and open in a browser.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| run_id | No | Generate detailed report for this run. Omit to list all runs. | |
| include_transcripts | No | Include full session transcripts in run reports (default: true, requires session persistence) |
Implementation Reference
- src/tools/report.ts:23-45 (handler)The async handler function for the 'claude_code_report' tool. It calls generateReport() with the timeline directory, optional run_id, and include_transcripts flag, returning the HTML result or an error message.
}, async ({ run_id, include_transcripts }) => { try { const html = await generateReport({ timelineDir: timelineConfig.dir, runId: run_id, includeTranscripts: persistSession && (include_transcripts !== false), }); return { content: [{ type: "text" as const, text: html, }], }; } catch (error) { return { content: [{ type: "text" as const, text: `Error generating report: ${error instanceof Error ? error.message : String(error)}`, }], isError: true, }; } }); - src/tools/report.ts:19-22 (schema)Input schema for the report tool: optional run_id (string) and include_transcripts (boolean, default true if session persistence is enabled).
inputSchema: z.object({ run_id: z.string().optional().describe("Generate detailed report for this run. Omit to list all runs."), include_transcripts: z.boolean().optional().describe("Include full session transcripts in run reports (default: true, requires session persistence)"), }), - src/tools/report.ts:6-46 (registration)Registration function registerReportTool that registers the tool with name `${toolName}_report` (e.g. 'claude_code_report') on the MCP server.
export function registerReportTool( server: McpServer, toolName: string, timelineConfig: TimelineConfig, persistSession: boolean, ) { server.registerTool(`${toolName}_report`, { description: [ "Generate a self-contained HTML report of a workflow run.", "No args: list all runs. run_id: detailed report for that run", "with agent sequence, cost breakdown, and collapsible transcripts.", "Save the returned HTML to a file and open in a browser.", ].join(" "), inputSchema: z.object({ run_id: z.string().optional().describe("Generate detailed report for this run. Omit to list all runs."), include_transcripts: z.boolean().optional().describe("Include full session transcripts in run reports (default: true, requires session persistence)"), }), }, async ({ run_id, include_transcripts }) => { try { const html = await generateReport({ timelineDir: timelineConfig.dir, runId: run_id, includeTranscripts: persistSession && (include_transcripts !== false), }); return { content: [{ type: "text" as const, text: html, }], }; } catch (error) { return { content: [{ type: "text" as const, text: `Error generating report: ${error instanceof Error ? error.message : String(error)}`, }], isError: true, }; } }); } - src/report.ts:113-118 (helper)The generateReport() function that dispatches to generateRunReport() or generateIndexReport() depending on whether a runId is provided.
export async function generateReport(opts: ReportOptions): Promise<string> { if (opts.runId) { return generateRunReport({ ...opts, runId: opts.runId }); } return generateIndexReport(opts); } - src/report.ts:83-99 (helper)generateRunReport() loads timeline entries for a specific run and renders the full HTML report with agent sequence, cost breakdown, and collapsible transcripts.
export async function generateRunReport(opts: ReportOptions & { runId: string }): Promise<string> { const run = await loadRunReport(opts.timelineDir, opts.runId, opts.includeTranscripts ?? true); if (!run) { return wrapHtml( "Run Not Found", `<h1>Run Not Found</h1><p>No timeline entries found for run <code>${esc(opts.runId)}</code>.</p>`, ); } const body = [ `<h1>Claude Octopus — Run Report</h1>`, `<p class="subtitle">Generated ${new Date().toISOString()}</p>`, renderRun(run), ].join("\n"); return wrapHtml(`Run: ${opts.runId}`, body); }