main
1#!/usr/bin/env bun
2/**
3 * PostToolUse hook — capture interesting tool outputs to JSONL.
4 *
5 * Tool-output logs are Claude-specific (not shared across tools)
6 * and stay under ~/.config/claude/history/tool-outputs/.
7 */
8
9import { readStdinJSON, TOOL_OUTPUTS_DIR, dateStr, yearMonth, ensureDir, now } from "./lib.ts";
10import { appendFileSync } from "node:fs";
11import { join } from "node:path";
12
13interface ToolUseData {
14 tool_name: string;
15 tool_input: Record<string, unknown>;
16 tool_response: Record<string, unknown>;
17 conversation_id?: string;
18 timestamp?: string;
19}
20
21const INTERESTING_TOOLS = new Set([
22 "Bash",
23 "Edit",
24 "Write",
25 "Read",
26 "Task",
27 "NotebookEdit",
28 "Skill",
29 "SlashCommand",
30]);
31
32async function main() {
33 const data = await readStdinJSON<ToolUseData>();
34 if (!data || !INTERESTING_TOOLS.has(data.tool_name)) {
35 process.exit(0);
36 }
37
38 const d = now();
39 const dir = join(TOOL_OUTPUTS_DIR, yearMonth(d));
40 ensureDir(dir);
41
42 const entry = {
43 timestamp: data.timestamp || d.toISOString(),
44 tool: data.tool_name,
45 input: data.tool_input,
46 output: data.tool_response,
47 session: data.conversation_id || "",
48 };
49
50 const file = join(dir, `${dateStr(d)}_tool-outputs.jsonl`);
51
52 try {
53 appendFileSync(file, JSON.stringify(entry) + "\n");
54 } catch (err) {
55 process.stderr.write(`[capture-tool-output] Error: ${err}\n`);
56 }
57
58 process.exit(0);
59}
60
61main();