@raindrop-ai/claude-code 0.0.8 → 0.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "raindrop",
3
+ "version": "0.0.10",
4
+ "description": "Observability for Claude Code \u2014 automatic session, tool call, and prompt tracing",
5
+ "author": {
6
+ "name": "Raindrop AI",
7
+ "email": "support@raindrop.ai"
8
+ },
9
+ "homepage": "https://docs.raindrop.ai/sdk/claude-code",
10
+ "repository": "https://github.com/raindrop-ai/claude-code-plugin",
11
+ "license": "MIT",
12
+ "hooks": "./hooks/hooks.json",
13
+ "mcpServers": "./.mcp.json"
14
+ }
package/.mcp.json ADDED
@@ -0,0 +1,9 @@
1
+ {
2
+ "mcpServers": {
3
+ "raindrop-diagnostics": {
4
+ "command": "${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code",
5
+ "args": ["mcp-serve"],
6
+ "transport": "stdio"
7
+ }
8
+ }
9
+ }
package/dist/cli.js CHANGED
@@ -654,7 +654,7 @@ globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
654
654
 
655
655
  // src/package-info.ts
656
656
  var PACKAGE_NAME = "@raindrop-ai/claude-code";
657
- var PACKAGE_VERSION = "0.0.8";
657
+ var PACKAGE_VERSION = "0.0.10";
658
658
 
659
659
  // src/shipper.ts
660
660
  var EventShipper2 = class extends EventShipper {
@@ -1010,12 +1010,13 @@ function readTimestamp(key) {
1010
1010
  return Number.isFinite(ts) ? ts : void 0;
1011
1011
  }
1012
1012
  async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1013
- var _a;
1014
- const convoId = payload.session_id;
1013
+ var _a, _b;
1014
+ const convoId = (_a = config.convoId) != null ? _a : payload.session_id;
1015
1015
  const baseProperties = {
1016
1016
  ...config.customProperties,
1017
1017
  cwd: payload.cwd,
1018
1018
  permission_mode: payload.permission_mode,
1019
+ claude_code_session_id: payload.session_id,
1019
1020
  plugin_version: PACKAGE_VERSION,
1020
1021
  sdk: PACKAGE_NAME,
1021
1022
  sdk_version: PACKAGE_VERSION,
@@ -1024,7 +1025,7 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1024
1025
  };
1025
1026
  switch (payload.hook_event_name) {
1026
1027
  case "SessionStart":
1027
- writeState(`model_${payload.session_id}`, (_a = payload.model) != null ? _a : "");
1028
+ writeState(`model_${payload.session_id}`, (_b = payload.model) != null ? _b : "");
1028
1029
  tryCaptureAppendSystemPrompt(payload.session_id);
1029
1030
  break;
1030
1031
  case "UserPromptSubmit":
@@ -1040,10 +1041,10 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1040
1041
  handlePostToolUseFailure(payload, getCurrentEventId(payload.session_id), traceShipper);
1041
1042
  break;
1042
1043
  case "Stop":
1043
- await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper, traceShipper);
1044
+ await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper, traceShipper);
1044
1045
  break;
1045
1046
  case "StopFailure":
1046
- await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper, traceShipper, {
1047
+ await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper, traceShipper, {
1047
1048
  error: payload.error,
1048
1049
  error_details: payload.error_details
1049
1050
  });
@@ -1061,10 +1062,10 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1061
1062
  handleInstructionsLoaded(payload);
1062
1063
  break;
1063
1064
  case "PostCompact":
1064
- await handlePostCompact(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper);
1065
+ await handlePostCompact(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper);
1065
1066
  break;
1066
1067
  case "SessionEnd":
1067
- await handleSessionEnd(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper);
1068
+ await handleSessionEnd(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper);
1068
1069
  deleteState(turnEventKey(payload.session_id));
1069
1070
  deleteState(rootSpanKey(payload.session_id));
1070
1071
  deleteState(`model_${payload.session_id}`);
@@ -1214,11 +1215,11 @@ function handlePermissionDenied(payload, eventId, traceShipper) {
1214
1215
  }
1215
1216
  });
1216
1217
  }
1217
- async function handlePostCompact(payload, eventId, config, properties, eventShipper) {
1218
+ async function handlePostCompact(payload, eventId, convoId, config, properties, eventShipper) {
1218
1219
  await eventShipper.patch(eventId, {
1219
1220
  isPending: true,
1220
1221
  userId: config.userId,
1221
- convoId: payload.session_id,
1222
+ convoId,
1222
1223
  eventName: config.eventName,
1223
1224
  properties: {
1224
1225
  ...properties,
@@ -1508,7 +1509,7 @@ function buildStopOutput(summary, lastAssistantMessage) {
1508
1509
  }
1509
1510
  return finalMessage;
1510
1511
  }
1511
- async function handleStopOrFailure(payload, eventId, config, properties, eventShipper, traceShipper, extraProperties) {
1512
+ async function handleStopOrFailure(payload, eventId, convoId, config, properties, eventShipper, traceShipper, extraProperties) {
1512
1513
  const { summary, props: transcriptProps } = enrichFromTranscript(payload, eventId, traceShipper);
1513
1514
  const instructions = gatherInstructions(payload.session_id);
1514
1515
  const appendSysPrompt = readAppendSystemPrompt(payload.session_id);
@@ -1516,7 +1517,7 @@ async function handleStopOrFailure(payload, eventId, config, properties, eventSh
1516
1517
  await eventShipper.patch(eventId, {
1517
1518
  isPending: false,
1518
1519
  userId: config.userId,
1519
- convoId: payload.session_id,
1520
+ convoId,
1520
1521
  eventName: config.eventName,
1521
1522
  output,
1522
1523
  ...(summary == null ? void 0 : summary.model) ? { model: summary.model } : {},
@@ -1529,10 +1530,11 @@ async function handleStopOrFailure(payload, eventId, config, properties, eventSh
1529
1530
  }
1530
1531
  });
1531
1532
  }
1532
- async function handleSessionEnd(payload, eventId, config, properties, eventShipper) {
1533
+ async function handleSessionEnd(payload, eventId, convoId, config, properties, eventShipper) {
1533
1534
  await eventShipper.patch(eventId, {
1534
1535
  isPending: false,
1535
1536
  userId: config.userId,
1537
+ convoId,
1536
1538
  eventName: config.eventName,
1537
1539
  properties: {
1538
1540
  ...properties,
@@ -1588,8 +1590,15 @@ function loadConfig() {
1588
1590
  writeKey: (_c = (_b = process.env["RAINDROP_WRITE_KEY"]) != null ? _b : file.write_key) != null ? _c : "",
1589
1591
  endpoint: (_e = (_d = process.env["RAINDROP_API_URL"]) != null ? _d : file.api_url) != null ? _e : "https://api.raindrop.ai/v1",
1590
1592
  userId: (_g = (_f = process.env["RAINDROP_USER_ID"]) != null ? _f : file.user_id) != null ? _g : systemUser,
1591
- debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_h = file.debug) != null ? _h : false,
1592
- enabled: (_i = file.enabled) != null ? _i : true,
1593
+ convoId: ((_h = process.env["RAINDROP_CONVO_ID"]) == null ? void 0 : _h.trim()) || void 0,
1594
+ debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_i = file.debug) != null ? _i : false,
1595
+ enabled: (() => {
1596
+ var _a2;
1597
+ const env = process.env["RAINDROP_ENABLED"];
1598
+ if (!env) return (_a2 = file.enabled) != null ? _a2 : true;
1599
+ const lower = env.toLowerCase();
1600
+ return lower !== "false" && env !== "0";
1601
+ })(),
1593
1602
  eventName: (_k = (_j = process.env["RAINDROP_EVENT_NAME"]) != null ? _j : file.event_name) != null ? _k : "claude_code_session",
1594
1603
  customProperties,
1595
1604
  selfDiagnostics
@@ -1763,6 +1772,7 @@ async function handleHook() {
1763
1772
  }
1764
1773
  const mapperConfig = {
1765
1774
  userId: config.userId,
1775
+ convoId: config.convoId,
1766
1776
  debug: config.debug,
1767
1777
  eventName: config.eventName,
1768
1778
  customProperties: config.customProperties
@@ -2043,6 +2053,62 @@ async function runSetup(args2) {
2043
2053
  `);
2044
2054
  }
2045
2055
  }
2056
+ function runUninstall(scope = "user") {
2057
+ const settingsPath = getClaudeSettingsPath(scope, process.cwd());
2058
+ const scopeLabel = scope === "project" ? "project" : "global";
2059
+ if (!existsSync6(settingsPath)) {
2060
+ console.log(`
2061
+ No settings file found at ${settingsPath}. Nothing to uninstall.
2062
+ `);
2063
+ return;
2064
+ }
2065
+ let settings;
2066
+ try {
2067
+ settings = JSON.parse(readFileSync6(settingsPath, "utf-8"));
2068
+ } catch (e) {
2069
+ console.error(` Could not parse ${settingsPath}`);
2070
+ process.exit(1);
2071
+ }
2072
+ const hooks = settings["hooks"];
2073
+ let removedHooks = 0;
2074
+ if (hooks) {
2075
+ for (const event of Object.keys(hooks)) {
2076
+ const groups = hooks[event];
2077
+ if (!Array.isArray(groups)) continue;
2078
+ const original = groups.length;
2079
+ hooks[event] = groups.filter((group) => {
2080
+ var _a;
2081
+ const hookList = (_a = group.hooks) != null ? _a : [];
2082
+ return !hookList.some(
2083
+ (h) => typeof h["command"] === "string" && h["command"].includes("raindrop-claude-code")
2084
+ );
2085
+ });
2086
+ removedHooks += original - hooks[event].length;
2087
+ if (hooks[event].length === 0) {
2088
+ delete hooks[event];
2089
+ }
2090
+ }
2091
+ if (Object.keys(hooks).length === 0) {
2092
+ delete settings["hooks"];
2093
+ }
2094
+ }
2095
+ writeFileSync4(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
2096
+ let mcpRemoved = false;
2097
+ try {
2098
+ execSync2(`claude mcp remove raindrop-diagnostics --scope ${scope}`, { stdio: "ignore" });
2099
+ mcpRemoved = true;
2100
+ } catch (e) {
2101
+ }
2102
+ console.log(`
2103
+ Raindrop uninstalled (${scopeLabel}):`);
2104
+ console.log(` - ${removedHooks} hook entries removed from ${settingsPath}`);
2105
+ if (mcpRemoved) {
2106
+ console.log(` - raindrop-diagnostics MCP server deregistered`);
2107
+ }
2108
+ console.log(`
2109
+ To reinstall, run: raindrop-claude-code setup
2110
+ `);
2111
+ }
2046
2112
  var DEBUG_LOG_PATH = "/tmp/raindrop-hooks.log";
2047
2113
  var DEBUG_PREFIX = "RAINDROP_DEBUG=true ";
2048
2114
  var TEE_SUFFIX = ` 2>&1 | tee -a ${DEBUG_LOG_PATH} || true`;
@@ -2448,6 +2514,11 @@ async function main() {
2448
2514
  console.log(" Raindrop hooks disabled.");
2449
2515
  break;
2450
2516
  }
2517
+ case "uninstall": {
2518
+ const uninstallScope = parseFlag("scope") === "project" ? "project" : "user";
2519
+ runUninstall(uninstallScope);
2520
+ break;
2521
+ }
2451
2522
  case "debug-on": {
2452
2523
  const debugScope = parseFlag("scope") === "project" ? "project" : "user";
2453
2524
  toggleDebug(true, debugScope);
@@ -2484,6 +2555,8 @@ async function main() {
2484
2555
  hook Handle a Claude Code hook event (reads JSON from stdin)
2485
2556
  mcp-serve Start the self-diagnostics MCP server (stdio)
2486
2557
  status Check local debugger connectivity
2558
+ uninstall Remove all Raindrop hooks from settings.json
2559
+ --scope=SCOPE "user" (default) or "project"
2487
2560
  enable Enable Raindrop hooks
2488
2561
  disable Disable Raindrop hooks
2489
2562
  debug-on Enable debug logging to /tmp/raindrop-hooks.log
@@ -2494,11 +2567,14 @@ async function main() {
2494
2567
  Environment:
2495
2568
  RAINDROP_WRITE_KEY API write key (alternative to --write-key or config file)
2496
2569
  RAINDROP_USER_ID User ID override
2570
+ RAINDROP_CONVO_ID Conversation/thread ID override
2497
2571
  RAINDROP_EVENT_NAME Custom event name (default: "claude_code_session")
2498
2572
  RAINDROP_PROPERTIES JSON object merged into every event's properties
2573
+ RAINDROP_ENABLED Set to "false" to disable all telemetry
2499
2574
  RAINDROP_API_URL Custom API endpoint
2500
2575
  RAINDROP_LOCAL_DEBUGGER Local debugger URL (auto-detected if running on :5899)
2501
2576
  RAINDROP_DEBUG Set to "true" for verbose logging
2577
+ RAINDROP_SELF_DIAGNOSTICS JSON object to customize self-diagnostics signal categories
2502
2578
  `);
2503
2579
  if (!command || command === "help" || command === "--help" || command === "-h") {
2504
2580
  process.exit(0);
package/dist/index.cjs CHANGED
@@ -690,7 +690,7 @@ globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = import_async_hooks.AsyncLocalStorage;
690
690
 
691
691
  // src/package-info.ts
692
692
  var PACKAGE_NAME = "@raindrop-ai/claude-code";
693
- var PACKAGE_VERSION = "0.0.8";
693
+ var PACKAGE_VERSION = "0.0.10";
694
694
 
695
695
  // src/shipper.ts
696
696
  var EventShipper2 = class extends EventShipper {
@@ -774,8 +774,15 @@ function loadConfig() {
774
774
  writeKey: (_c = (_b = process.env["RAINDROP_WRITE_KEY"]) != null ? _b : file.write_key) != null ? _c : "",
775
775
  endpoint: (_e = (_d = process.env["RAINDROP_API_URL"]) != null ? _d : file.api_url) != null ? _e : "https://api.raindrop.ai/v1",
776
776
  userId: (_g = (_f = process.env["RAINDROP_USER_ID"]) != null ? _f : file.user_id) != null ? _g : systemUser,
777
- debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_h = file.debug) != null ? _h : false,
778
- enabled: (_i = file.enabled) != null ? _i : true,
777
+ convoId: ((_h = process.env["RAINDROP_CONVO_ID"]) == null ? void 0 : _h.trim()) || void 0,
778
+ debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_i = file.debug) != null ? _i : false,
779
+ enabled: (() => {
780
+ var _a2;
781
+ const env = process.env["RAINDROP_ENABLED"];
782
+ if (!env) return (_a2 = file.enabled) != null ? _a2 : true;
783
+ const lower = env.toLowerCase();
784
+ return lower !== "false" && env !== "0";
785
+ })(),
779
786
  eventName: (_k = (_j = process.env["RAINDROP_EVENT_NAME"]) != null ? _j : file.event_name) != null ? _k : "claude_code_session",
780
787
  customProperties,
781
788
  selfDiagnostics
@@ -1123,12 +1130,13 @@ function readTimestamp(key) {
1123
1130
  return Number.isFinite(ts) ? ts : void 0;
1124
1131
  }
1125
1132
  async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1126
- var _a;
1127
- const convoId = payload.session_id;
1133
+ var _a, _b;
1134
+ const convoId = (_a = config.convoId) != null ? _a : payload.session_id;
1128
1135
  const baseProperties = {
1129
1136
  ...config.customProperties,
1130
1137
  cwd: payload.cwd,
1131
1138
  permission_mode: payload.permission_mode,
1139
+ claude_code_session_id: payload.session_id,
1132
1140
  plugin_version: PACKAGE_VERSION,
1133
1141
  sdk: PACKAGE_NAME,
1134
1142
  sdk_version: PACKAGE_VERSION,
@@ -1137,7 +1145,7 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1137
1145
  };
1138
1146
  switch (payload.hook_event_name) {
1139
1147
  case "SessionStart":
1140
- writeState(`model_${payload.session_id}`, (_a = payload.model) != null ? _a : "");
1148
+ writeState(`model_${payload.session_id}`, (_b = payload.model) != null ? _b : "");
1141
1149
  tryCaptureAppendSystemPrompt(payload.session_id);
1142
1150
  break;
1143
1151
  case "UserPromptSubmit":
@@ -1153,10 +1161,10 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1153
1161
  handlePostToolUseFailure(payload, getCurrentEventId(payload.session_id), traceShipper);
1154
1162
  break;
1155
1163
  case "Stop":
1156
- await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper, traceShipper);
1164
+ await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper, traceShipper);
1157
1165
  break;
1158
1166
  case "StopFailure":
1159
- await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper, traceShipper, {
1167
+ await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper, traceShipper, {
1160
1168
  error: payload.error,
1161
1169
  error_details: payload.error_details
1162
1170
  });
@@ -1174,10 +1182,10 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1174
1182
  handleInstructionsLoaded(payload);
1175
1183
  break;
1176
1184
  case "PostCompact":
1177
- await handlePostCompact(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper);
1185
+ await handlePostCompact(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper);
1178
1186
  break;
1179
1187
  case "SessionEnd":
1180
- await handleSessionEnd(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper);
1188
+ await handleSessionEnd(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper);
1181
1189
  deleteState(turnEventKey(payload.session_id));
1182
1190
  deleteState(rootSpanKey(payload.session_id));
1183
1191
  deleteState(`model_${payload.session_id}`);
@@ -1327,11 +1335,11 @@ function handlePermissionDenied(payload, eventId, traceShipper) {
1327
1335
  }
1328
1336
  });
1329
1337
  }
1330
- async function handlePostCompact(payload, eventId, config, properties, eventShipper) {
1338
+ async function handlePostCompact(payload, eventId, convoId, config, properties, eventShipper) {
1331
1339
  await eventShipper.patch(eventId, {
1332
1340
  isPending: true,
1333
1341
  userId: config.userId,
1334
- convoId: payload.session_id,
1342
+ convoId,
1335
1343
  eventName: config.eventName,
1336
1344
  properties: {
1337
1345
  ...properties,
@@ -1621,7 +1629,7 @@ function buildStopOutput(summary, lastAssistantMessage) {
1621
1629
  }
1622
1630
  return finalMessage;
1623
1631
  }
1624
- async function handleStopOrFailure(payload, eventId, config, properties, eventShipper, traceShipper, extraProperties) {
1632
+ async function handleStopOrFailure(payload, eventId, convoId, config, properties, eventShipper, traceShipper, extraProperties) {
1625
1633
  const { summary, props: transcriptProps } = enrichFromTranscript(payload, eventId, traceShipper);
1626
1634
  const instructions = gatherInstructions(payload.session_id);
1627
1635
  const appendSysPrompt = readAppendSystemPrompt(payload.session_id);
@@ -1629,7 +1637,7 @@ async function handleStopOrFailure(payload, eventId, config, properties, eventSh
1629
1637
  await eventShipper.patch(eventId, {
1630
1638
  isPending: false,
1631
1639
  userId: config.userId,
1632
- convoId: payload.session_id,
1640
+ convoId,
1633
1641
  eventName: config.eventName,
1634
1642
  output,
1635
1643
  ...(summary == null ? void 0 : summary.model) ? { model: summary.model } : {},
@@ -1642,10 +1650,11 @@ async function handleStopOrFailure(payload, eventId, config, properties, eventSh
1642
1650
  }
1643
1651
  });
1644
1652
  }
1645
- async function handleSessionEnd(payload, eventId, config, properties, eventShipper) {
1653
+ async function handleSessionEnd(payload, eventId, convoId, config, properties, eventShipper) {
1646
1654
  await eventShipper.patch(eventId, {
1647
1655
  isPending: false,
1648
1656
  userId: config.userId,
1657
+ convoId,
1649
1658
  eventName: config.eventName,
1650
1659
  properties: {
1651
1660
  ...properties,
package/dist/index.d.cts CHANGED
@@ -244,6 +244,7 @@ interface RaindropConfig {
244
244
  writeKey: string;
245
245
  endpoint: string;
246
246
  userId: string;
247
+ convoId?: string;
247
248
  debug: boolean;
248
249
  enabled: boolean;
249
250
  eventName: string;
@@ -292,6 +293,7 @@ interface HookPayload {
292
293
  }
293
294
  interface MapperConfig {
294
295
  userId: string;
296
+ convoId?: string;
295
297
  debug: boolean;
296
298
  eventName: string;
297
299
  customProperties: Record<string, unknown>;
@@ -308,7 +310,7 @@ declare function mapHookToRaindrop(payload: HookPayload, config: MapperConfig, e
308
310
  declare function extractAppendSystemPrompt(args: string[]): string | undefined;
309
311
 
310
312
  declare const PACKAGE_NAME = "@raindrop-ai/claude-code";
311
- declare const PACKAGE_VERSION = "0.0.8";
313
+ declare const PACKAGE_VERSION = "0.0.10";
312
314
 
313
315
  /** A tool call extracted from an assistant message content block. */
314
316
  interface LLMToolCall {
package/dist/index.d.ts CHANGED
@@ -244,6 +244,7 @@ interface RaindropConfig {
244
244
  writeKey: string;
245
245
  endpoint: string;
246
246
  userId: string;
247
+ convoId?: string;
247
248
  debug: boolean;
248
249
  enabled: boolean;
249
250
  eventName: string;
@@ -292,6 +293,7 @@ interface HookPayload {
292
293
  }
293
294
  interface MapperConfig {
294
295
  userId: string;
296
+ convoId?: string;
295
297
  debug: boolean;
296
298
  eventName: string;
297
299
  customProperties: Record<string, unknown>;
@@ -308,7 +310,7 @@ declare function mapHookToRaindrop(payload: HookPayload, config: MapperConfig, e
308
310
  declare function extractAppendSystemPrompt(args: string[]): string | undefined;
309
311
 
310
312
  declare const PACKAGE_NAME = "@raindrop-ai/claude-code";
311
- declare const PACKAGE_VERSION = "0.0.8";
313
+ declare const PACKAGE_VERSION = "0.0.10";
312
314
 
313
315
  /** A tool call extracted from an assistant message content block. */
314
316
  interface LLMToolCall {
package/dist/index.js CHANGED
@@ -645,7 +645,7 @@ globalThis.RAINDROP_ASYNC_LOCAL_STORAGE = AsyncLocalStorage;
645
645
 
646
646
  // src/package-info.ts
647
647
  var PACKAGE_NAME = "@raindrop-ai/claude-code";
648
- var PACKAGE_VERSION = "0.0.8";
648
+ var PACKAGE_VERSION = "0.0.10";
649
649
 
650
650
  // src/shipper.ts
651
651
  var EventShipper2 = class extends EventShipper {
@@ -729,8 +729,15 @@ function loadConfig() {
729
729
  writeKey: (_c = (_b = process.env["RAINDROP_WRITE_KEY"]) != null ? _b : file.write_key) != null ? _c : "",
730
730
  endpoint: (_e = (_d = process.env["RAINDROP_API_URL"]) != null ? _d : file.api_url) != null ? _e : "https://api.raindrop.ai/v1",
731
731
  userId: (_g = (_f = process.env["RAINDROP_USER_ID"]) != null ? _f : file.user_id) != null ? _g : systemUser,
732
- debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_h = file.debug) != null ? _h : false,
733
- enabled: (_i = file.enabled) != null ? _i : true,
732
+ convoId: ((_h = process.env["RAINDROP_CONVO_ID"]) == null ? void 0 : _h.trim()) || void 0,
733
+ debug: process.env["RAINDROP_DEBUG"] === "true" ? true : (_i = file.debug) != null ? _i : false,
734
+ enabled: (() => {
735
+ var _a2;
736
+ const env = process.env["RAINDROP_ENABLED"];
737
+ if (!env) return (_a2 = file.enabled) != null ? _a2 : true;
738
+ const lower = env.toLowerCase();
739
+ return lower !== "false" && env !== "0";
740
+ })(),
734
741
  eventName: (_k = (_j = process.env["RAINDROP_EVENT_NAME"]) != null ? _j : file.event_name) != null ? _k : "claude_code_session",
735
742
  customProperties,
736
743
  selfDiagnostics
@@ -1078,12 +1085,13 @@ function readTimestamp(key) {
1078
1085
  return Number.isFinite(ts) ? ts : void 0;
1079
1086
  }
1080
1087
  async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1081
- var _a;
1082
- const convoId = payload.session_id;
1088
+ var _a, _b;
1089
+ const convoId = (_a = config.convoId) != null ? _a : payload.session_id;
1083
1090
  const baseProperties = {
1084
1091
  ...config.customProperties,
1085
1092
  cwd: payload.cwd,
1086
1093
  permission_mode: payload.permission_mode,
1094
+ claude_code_session_id: payload.session_id,
1087
1095
  plugin_version: PACKAGE_VERSION,
1088
1096
  sdk: PACKAGE_NAME,
1089
1097
  sdk_version: PACKAGE_VERSION,
@@ -1092,7 +1100,7 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1092
1100
  };
1093
1101
  switch (payload.hook_event_name) {
1094
1102
  case "SessionStart":
1095
- writeState(`model_${payload.session_id}`, (_a = payload.model) != null ? _a : "");
1103
+ writeState(`model_${payload.session_id}`, (_b = payload.model) != null ? _b : "");
1096
1104
  tryCaptureAppendSystemPrompt(payload.session_id);
1097
1105
  break;
1098
1106
  case "UserPromptSubmit":
@@ -1108,10 +1116,10 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1108
1116
  handlePostToolUseFailure(payload, getCurrentEventId(payload.session_id), traceShipper);
1109
1117
  break;
1110
1118
  case "Stop":
1111
- await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper, traceShipper);
1119
+ await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper, traceShipper);
1112
1120
  break;
1113
1121
  case "StopFailure":
1114
- await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper, traceShipper, {
1122
+ await handleStopOrFailure(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper, traceShipper, {
1115
1123
  error: payload.error,
1116
1124
  error_details: payload.error_details
1117
1125
  });
@@ -1129,10 +1137,10 @@ async function mapHookToRaindrop(payload, config, eventShipper, traceShipper) {
1129
1137
  handleInstructionsLoaded(payload);
1130
1138
  break;
1131
1139
  case "PostCompact":
1132
- await handlePostCompact(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper);
1140
+ await handlePostCompact(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper);
1133
1141
  break;
1134
1142
  case "SessionEnd":
1135
- await handleSessionEnd(payload, getCurrentEventId(payload.session_id), config, baseProperties, eventShipper);
1143
+ await handleSessionEnd(payload, getCurrentEventId(payload.session_id), convoId, config, baseProperties, eventShipper);
1136
1144
  deleteState(turnEventKey(payload.session_id));
1137
1145
  deleteState(rootSpanKey(payload.session_id));
1138
1146
  deleteState(`model_${payload.session_id}`);
@@ -1282,11 +1290,11 @@ function handlePermissionDenied(payload, eventId, traceShipper) {
1282
1290
  }
1283
1291
  });
1284
1292
  }
1285
- async function handlePostCompact(payload, eventId, config, properties, eventShipper) {
1293
+ async function handlePostCompact(payload, eventId, convoId, config, properties, eventShipper) {
1286
1294
  await eventShipper.patch(eventId, {
1287
1295
  isPending: true,
1288
1296
  userId: config.userId,
1289
- convoId: payload.session_id,
1297
+ convoId,
1290
1298
  eventName: config.eventName,
1291
1299
  properties: {
1292
1300
  ...properties,
@@ -1576,7 +1584,7 @@ function buildStopOutput(summary, lastAssistantMessage) {
1576
1584
  }
1577
1585
  return finalMessage;
1578
1586
  }
1579
- async function handleStopOrFailure(payload, eventId, config, properties, eventShipper, traceShipper, extraProperties) {
1587
+ async function handleStopOrFailure(payload, eventId, convoId, config, properties, eventShipper, traceShipper, extraProperties) {
1580
1588
  const { summary, props: transcriptProps } = enrichFromTranscript(payload, eventId, traceShipper);
1581
1589
  const instructions = gatherInstructions(payload.session_id);
1582
1590
  const appendSysPrompt = readAppendSystemPrompt(payload.session_id);
@@ -1584,7 +1592,7 @@ async function handleStopOrFailure(payload, eventId, config, properties, eventSh
1584
1592
  await eventShipper.patch(eventId, {
1585
1593
  isPending: false,
1586
1594
  userId: config.userId,
1587
- convoId: payload.session_id,
1595
+ convoId,
1588
1596
  eventName: config.eventName,
1589
1597
  output,
1590
1598
  ...(summary == null ? void 0 : summary.model) ? { model: summary.model } : {},
@@ -1597,10 +1605,11 @@ async function handleStopOrFailure(payload, eventId, config, properties, eventSh
1597
1605
  }
1598
1606
  });
1599
1607
  }
1600
- async function handleSessionEnd(payload, eventId, config, properties, eventShipper) {
1608
+ async function handleSessionEnd(payload, eventId, convoId, config, properties, eventShipper) {
1601
1609
  await eventShipper.patch(eventId, {
1602
1610
  isPending: false,
1603
1611
  userId: config.userId,
1612
+ convoId,
1604
1613
  eventName: config.eventName,
1605
1614
  properties: {
1606
1615
  ...properties,
@@ -0,0 +1,147 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "hooks": [
6
+ {
7
+ "type": "command",
8
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
9
+ "timeout": 10
10
+ }
11
+ ]
12
+ }
13
+ ],
14
+ "UserPromptSubmit": [
15
+ {
16
+ "hooks": [
17
+ {
18
+ "type": "command",
19
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
20
+ "timeout": 10
21
+ }
22
+ ]
23
+ }
24
+ ],
25
+ "PreToolUse": [
26
+ {
27
+ "hooks": [
28
+ {
29
+ "type": "command",
30
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
31
+ "timeout": 10
32
+ }
33
+ ]
34
+ }
35
+ ],
36
+ "PostToolUse": [
37
+ {
38
+ "hooks": [
39
+ {
40
+ "type": "command",
41
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
42
+ "timeout": 10
43
+ }
44
+ ]
45
+ }
46
+ ],
47
+ "PostToolUseFailure": [
48
+ {
49
+ "hooks": [
50
+ {
51
+ "type": "command",
52
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
53
+ "timeout": 10
54
+ }
55
+ ]
56
+ }
57
+ ],
58
+ "SubagentStart": [
59
+ {
60
+ "hooks": [
61
+ {
62
+ "type": "command",
63
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
64
+ "timeout": 10
65
+ }
66
+ ]
67
+ }
68
+ ],
69
+ "SubagentStop": [
70
+ {
71
+ "hooks": [
72
+ {
73
+ "type": "command",
74
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
75
+ "timeout": 10
76
+ }
77
+ ]
78
+ }
79
+ ],
80
+ "Stop": [
81
+ {
82
+ "hooks": [
83
+ {
84
+ "type": "command",
85
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
86
+ "timeout": 10
87
+ }
88
+ ]
89
+ }
90
+ ],
91
+ "StopFailure": [
92
+ {
93
+ "hooks": [
94
+ {
95
+ "type": "command",
96
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
97
+ "timeout": 10
98
+ }
99
+ ]
100
+ }
101
+ ],
102
+ "SessionEnd": [
103
+ {
104
+ "hooks": [
105
+ {
106
+ "type": "command",
107
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
108
+ "timeout": 10
109
+ }
110
+ ]
111
+ }
112
+ ],
113
+ "PostCompact": [
114
+ {
115
+ "hooks": [
116
+ {
117
+ "type": "command",
118
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
119
+ "timeout": 10
120
+ }
121
+ ]
122
+ }
123
+ ],
124
+ "InstructionsLoaded": [
125
+ {
126
+ "hooks": [
127
+ {
128
+ "type": "command",
129
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
130
+ "timeout": 10
131
+ }
132
+ ]
133
+ }
134
+ ],
135
+ "PermissionDenied": [
136
+ {
137
+ "hooks": [
138
+ {
139
+ "type": "command",
140
+ "command": "\"${CLAUDE_PLUGIN_ROOT}/node_modules/.bin/raindrop-claude-code\" hook",
141
+ "timeout": 10
142
+ }
143
+ ]
144
+ }
145
+ ]
146
+ }
147
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@raindrop-ai/claude-code",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "Raindrop observability for Claude Code CLI \u2014 automatic session, tool call, and prompt tracing via hooks",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -25,7 +25,10 @@
25
25
  "sideEffects": false,
26
26
  "files": [
27
27
  "dist/**",
28
- "README.md"
28
+ "README.md",
29
+ ".claude-plugin/**",
30
+ "hooks/**",
31
+ ".mcp.json"
29
32
  ],
30
33
  "keywords": [
31
34
  "raindrop",