@orgloop/connector-claude-code 0.1.0

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.
package/LICENSE.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OrgLoop contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,115 @@
1
+ # @orgloop/connector-claude-code
2
+
3
+ Captures Claude Code session exit events via a webhook handler. Instead of polling an external API, this connector exposes an HTTP endpoint that receives POST requests from a Claude Code post-exit hook script.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @orgloop/connector-claude-code
9
+ ```
10
+
11
+ ## Configuration
12
+
13
+ ```yaml
14
+ sources:
15
+ - id: claude-code
16
+ connector: "@orgloop/connector-claude-code"
17
+ config: {}
18
+ poll:
19
+ interval: "30s" # how often to drain received webhook events
20
+ ```
21
+
22
+ This connector has no required config fields. The `poll.interval` controls how frequently accumulated webhook events are drained into the event pipeline.
23
+
24
+ ## Events emitted
25
+
26
+ Events are emitted as OrgLoop `actor.stopped` type.
27
+
28
+ ### Event kind
29
+
30
+ | Platform event | Trigger | Description |
31
+ |---|---|---|
32
+ | `session.exited` | Claude Code session ends | A Claude Code session has exited, delivered via webhook |
33
+
34
+ ### Example event payload
35
+
36
+ ```json
37
+ {
38
+ "id": "evt_a1b2c3d4e5f67890",
39
+ "timestamp": "2025-01-15T10:30:00.000Z",
40
+ "source": "claude-code",
41
+ "type": "actor.stopped",
42
+ "provenance": {
43
+ "platform": "claude-code",
44
+ "platform_event": "session.exited",
45
+ "author": "claude-code",
46
+ "author_type": "bot",
47
+ "session_id": "sess-abc123",
48
+ "working_directory": "/home/user/my-project"
49
+ },
50
+ "payload": {
51
+ "session_id": "sess-abc123",
52
+ "working_directory": "/home/user/my-project",
53
+ "duration_seconds": 120,
54
+ "exit_status": 0,
55
+ "summary": "Implemented auth module and added tests"
56
+ }
57
+ }
58
+ ```
59
+
60
+ ### Webhook request format
61
+
62
+ POST a JSON body to the connector's webhook endpoint:
63
+
64
+ ```json
65
+ {
66
+ "session_id": "sess-abc123",
67
+ "working_directory": "/home/user/my-project",
68
+ "duration_seconds": 120,
69
+ "exit_status": 0,
70
+ "summary": "Implemented auth module and added tests"
71
+ }
72
+ ```
73
+
74
+ | Field | Type | Required | Description |
75
+ |-------|------|----------|-------------|
76
+ | `session_id` | `string` | yes | Claude Code session identifier |
77
+ | `working_directory` | `string` | yes | Working directory of the session |
78
+ | `duration_seconds` | `number` | yes | Session duration in seconds |
79
+ | `exit_status` | `number` | yes | Process exit code (0 = success) |
80
+ | `summary` | `string` | no | Optional session summary text |
81
+ | `timestamp` | `string` | no | Optional ISO 8601 timestamp |
82
+
83
+ ## Example route
84
+
85
+ ```yaml
86
+ routes:
87
+ - name: claude-code-exit-review
88
+ when:
89
+ source: claude-code
90
+ events:
91
+ - actor.stopped
92
+ then:
93
+ actor: openclaw-agent
94
+ config:
95
+ session_key: "orgloop:claude-code:session-review"
96
+ with:
97
+ prompt_file: sops/review-claude-session.md
98
+ ```
99
+
100
+ ## Auth / prerequisites
101
+
102
+ - **No API tokens needed** -- this connector receives events via HTTP webhook.
103
+ - A Claude Code **Stop hook** must be configured to POST session data to the OrgLoop webhook endpoint when a session exits.
104
+ - The connector registration includes setup metadata for the hook. You can install it with:
105
+ ```bash
106
+ orgloop hook claude-code-stop
107
+ ```
108
+ This registers a post-exit hook in Claude Code's settings that sends session data to OrgLoop.
109
+
110
+ ## Limitations / known issues
111
+
112
+ - **Push-based, not polling** -- Unlike the GitHub and Linear connectors, this connector does not poll an external API. It waits for inbound webhook requests. If the hook is not installed or fails silently, no events will be generated.
113
+ - **No HMAC validation** -- The webhook endpoint does not validate request signatures. Protect it behind a firewall or reverse proxy if exposed to untrusted networks.
114
+ - **In-memory event buffer** -- Received webhook events are held in memory until the next `poll()` drains them. If the engine crashes between webhook receipt and poll, those events are lost.
115
+ - **Only POST accepted** -- Non-POST requests receive a 405 response.
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=source.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/source.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,411 @@
1
+ import { createHmac } from 'node:crypto';
2
+ import { EventEmitter } from 'node:events';
3
+ import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { join } from 'node:path';
6
+ import { afterEach, beforeEach, describe, expect, it } from 'vitest';
7
+ import { ClaudeCodeSource } from '../source.js';
8
+ const TEST_SECRET = 'test-webhook-secret-key';
9
+ function createMockRequest(body, method = 'POST', headers = {}) {
10
+ const req = new EventEmitter();
11
+ req.method = method;
12
+ req.headers = { ...headers };
13
+ // Simulate incoming data
14
+ setTimeout(() => {
15
+ req.emit('data', Buffer.from(body));
16
+ req.emit('end');
17
+ }, 0);
18
+ return req;
19
+ }
20
+ function createMockResponse() {
21
+ const res = {
22
+ statusCode: 200,
23
+ body: '',
24
+ writeHead(code, _headers) {
25
+ res.statusCode = code;
26
+ return res;
27
+ },
28
+ end(data) {
29
+ res.body = data ?? '';
30
+ return res;
31
+ },
32
+ };
33
+ return res;
34
+ }
35
+ function signPayload(body, secret) {
36
+ return `sha256=${createHmac('sha256', secret).update(body).digest('hex')}`;
37
+ }
38
+ const samplePayload = {
39
+ session_id: 'sess-123',
40
+ working_directory: '/tmp/test',
41
+ duration_seconds: 120,
42
+ exit_status: 0,
43
+ summary: 'Task completed',
44
+ };
45
+ describe('ClaudeCodeSource', () => {
46
+ it('initializes without error', async () => {
47
+ const source = new ClaudeCodeSource();
48
+ await source.init({
49
+ id: 'claude-code',
50
+ connector: '@orgloop/connector-claude-code',
51
+ config: { hook_type: 'post-exit' },
52
+ });
53
+ expect(source.id).toBe('claude-code');
54
+ });
55
+ it('returns empty events on initial poll', async () => {
56
+ const source = new ClaudeCodeSource();
57
+ await source.init({
58
+ id: 'claude-code',
59
+ connector: '@orgloop/connector-claude-code',
60
+ config: {},
61
+ });
62
+ const result = await source.poll(null);
63
+ expect(result.events).toHaveLength(0);
64
+ expect(result.checkpoint).toBeDefined();
65
+ });
66
+ it('receives webhook events and returns them on poll', async () => {
67
+ const source = new ClaudeCodeSource();
68
+ await source.init({
69
+ id: 'claude-code',
70
+ connector: '@orgloop/connector-claude-code',
71
+ config: {},
72
+ });
73
+ const handler = source.webhook();
74
+ const payload = {
75
+ session_id: 'sess-123',
76
+ working_directory: '/tmp/test',
77
+ duration_seconds: 120,
78
+ exit_status: 0,
79
+ summary: 'Task completed',
80
+ };
81
+ const req = createMockRequest(JSON.stringify(payload));
82
+ const res = createMockResponse();
83
+ const events = await handler(req, res);
84
+ expect(res.statusCode).toBe(200);
85
+ expect(events).toHaveLength(1);
86
+ expect(events[0].type).toBe('actor.stopped');
87
+ expect(events[0].source).toBe('claude-code');
88
+ expect(events[0].provenance.platform).toBe('claude-code');
89
+ expect(events[0].payload.session_id).toBe('sess-123');
90
+ // Now poll should drain the events
91
+ const result = await source.poll(null);
92
+ expect(result.events).toHaveLength(1);
93
+ expect(result.events[0].id).toBe(events[0].id);
94
+ // Second poll should be empty
95
+ const result2 = await source.poll(result.checkpoint);
96
+ expect(result2.events).toHaveLength(0);
97
+ });
98
+ it('rejects non-POST requests', async () => {
99
+ const source = new ClaudeCodeSource();
100
+ await source.init({
101
+ id: 'claude-code',
102
+ connector: '@orgloop/connector-claude-code',
103
+ config: {},
104
+ });
105
+ const handler = source.webhook();
106
+ const req = createMockRequest('', 'GET');
107
+ const res = createMockResponse();
108
+ const events = await handler(req, res);
109
+ expect(res.statusCode).toBe(405);
110
+ expect(events).toHaveLength(0);
111
+ });
112
+ it('rejects invalid JSON', async () => {
113
+ const source = new ClaudeCodeSource();
114
+ await source.init({
115
+ id: 'claude-code',
116
+ connector: '@orgloop/connector-claude-code',
117
+ config: {},
118
+ });
119
+ const handler = source.webhook();
120
+ const req = createMockRequest('not-json');
121
+ const res = createMockResponse();
122
+ const events = await handler(req, res);
123
+ expect(res.statusCode).toBe(400);
124
+ expect(events).toHaveLength(0);
125
+ });
126
+ it('cleans up on shutdown', async () => {
127
+ const source = new ClaudeCodeSource();
128
+ await source.init({
129
+ id: 'claude-code',
130
+ connector: '@orgloop/connector-claude-code',
131
+ config: {},
132
+ });
133
+ // Add an event via webhook
134
+ const handler = source.webhook();
135
+ const req = createMockRequest(JSON.stringify({
136
+ session_id: 'sess-456',
137
+ working_directory: '/tmp',
138
+ duration_seconds: 60,
139
+ exit_status: 0,
140
+ }));
141
+ const res = createMockResponse();
142
+ await handler(req, res);
143
+ await source.shutdown();
144
+ // After shutdown, pending events should be cleared
145
+ const result = await source.poll(null);
146
+ expect(result.events).toHaveLength(0);
147
+ });
148
+ });
149
+ describe('ClaudeCodeSource HMAC validation', () => {
150
+ it('accepts webhook with valid HMAC signature via x-hub-signature-256', async () => {
151
+ const source = new ClaudeCodeSource();
152
+ await source.init({
153
+ id: 'claude-code',
154
+ connector: '@orgloop/connector-claude-code',
155
+ config: { secret: TEST_SECRET },
156
+ });
157
+ const handler = source.webhook();
158
+ const body = JSON.stringify(samplePayload);
159
+ const signature = signPayload(body, TEST_SECRET);
160
+ const req = createMockRequest(body, 'POST', { 'x-hub-signature-256': signature });
161
+ const res = createMockResponse();
162
+ const events = await handler(req, res);
163
+ expect(res.statusCode).toBe(200);
164
+ expect(events).toHaveLength(1);
165
+ expect(events[0].type).toBe('actor.stopped');
166
+ expect(events[0].payload.session_id).toBe('sess-123');
167
+ });
168
+ it('accepts webhook with valid HMAC signature via x-signature', async () => {
169
+ const source = new ClaudeCodeSource();
170
+ await source.init({
171
+ id: 'claude-code',
172
+ connector: '@orgloop/connector-claude-code',
173
+ config: { secret: TEST_SECRET },
174
+ });
175
+ const handler = source.webhook();
176
+ const body = JSON.stringify(samplePayload);
177
+ const signature = signPayload(body, TEST_SECRET);
178
+ const req = createMockRequest(body, 'POST', { 'x-signature': signature });
179
+ const res = createMockResponse();
180
+ const events = await handler(req, res);
181
+ expect(res.statusCode).toBe(200);
182
+ expect(events).toHaveLength(1);
183
+ });
184
+ it('rejects webhook with invalid HMAC signature', async () => {
185
+ const source = new ClaudeCodeSource();
186
+ await source.init({
187
+ id: 'claude-code',
188
+ connector: '@orgloop/connector-claude-code',
189
+ config: { secret: TEST_SECRET },
190
+ });
191
+ const handler = source.webhook();
192
+ const body = JSON.stringify(samplePayload);
193
+ const badSignature = signPayload(body, 'wrong-secret');
194
+ const req = createMockRequest(body, 'POST', { 'x-hub-signature-256': badSignature });
195
+ const res = createMockResponse();
196
+ const events = await handler(req, res);
197
+ expect(res.statusCode).toBe(401);
198
+ expect(events).toHaveLength(0);
199
+ expect(JSON.parse(res.body).error).toBe('Invalid signature');
200
+ });
201
+ it('rejects webhook with missing signature when secret is configured', async () => {
202
+ const source = new ClaudeCodeSource();
203
+ await source.init({
204
+ id: 'claude-code',
205
+ connector: '@orgloop/connector-claude-code',
206
+ config: { secret: TEST_SECRET },
207
+ });
208
+ const handler = source.webhook();
209
+ const body = JSON.stringify(samplePayload);
210
+ const req = createMockRequest(body, 'POST');
211
+ const res = createMockResponse();
212
+ const events = await handler(req, res);
213
+ expect(res.statusCode).toBe(401);
214
+ expect(events).toHaveLength(0);
215
+ expect(JSON.parse(res.body).error).toBe('Missing signature');
216
+ });
217
+ it('accepts all requests when no secret is configured (backward compat)', async () => {
218
+ const source = new ClaudeCodeSource();
219
+ await source.init({
220
+ id: 'claude-code',
221
+ connector: '@orgloop/connector-claude-code',
222
+ config: {},
223
+ });
224
+ const handler = source.webhook();
225
+ const body = JSON.stringify(samplePayload);
226
+ const req = createMockRequest(body, 'POST');
227
+ const res = createMockResponse();
228
+ const events = await handler(req, res);
229
+ expect(res.statusCode).toBe(200);
230
+ expect(events).toHaveLength(1);
231
+ });
232
+ it('resolves secret from env var reference', async () => {
233
+ const envKey = 'TEST_CLAUDE_CODE_SECRET';
234
+ process.env[envKey] = TEST_SECRET;
235
+ try {
236
+ const source = new ClaudeCodeSource();
237
+ await source.init({
238
+ id: 'claude-code',
239
+ connector: '@orgloop/connector-claude-code',
240
+ config: { secret: `\${${envKey}}` },
241
+ });
242
+ const handler = source.webhook();
243
+ const body = JSON.stringify(samplePayload);
244
+ const signature = signPayload(body, TEST_SECRET);
245
+ const req = createMockRequest(body, 'POST', { 'x-hub-signature-256': signature });
246
+ const res = createMockResponse();
247
+ const events = await handler(req, res);
248
+ expect(res.statusCode).toBe(200);
249
+ expect(events).toHaveLength(1);
250
+ }
251
+ finally {
252
+ delete process.env[envKey];
253
+ }
254
+ });
255
+ it('rejects tampered body even with valid-format signature', async () => {
256
+ const source = new ClaudeCodeSource();
257
+ await source.init({
258
+ id: 'claude-code',
259
+ connector: '@orgloop/connector-claude-code',
260
+ config: { secret: TEST_SECRET },
261
+ });
262
+ const handler = source.webhook();
263
+ const originalBody = JSON.stringify(samplePayload);
264
+ const signature = signPayload(originalBody, TEST_SECRET);
265
+ // Tamper with the body after signing
266
+ const tamperedPayload = { ...samplePayload, exit_status: 1 };
267
+ const tamperedBody = JSON.stringify(tamperedPayload);
268
+ const req = createMockRequest(tamperedBody, 'POST', {
269
+ 'x-hub-signature-256': signature,
270
+ });
271
+ const res = createMockResponse();
272
+ const events = await handler(req, res);
273
+ expect(res.statusCode).toBe(401);
274
+ expect(events).toHaveLength(0);
275
+ });
276
+ });
277
+ describe('ClaudeCodeSource buffer persistence', () => {
278
+ let bufferDir;
279
+ beforeEach(() => {
280
+ bufferDir = join(tmpdir(), `orgloop-test-buffer-${Date.now()}-${Math.random().toString(36).slice(2)}`);
281
+ mkdirSync(bufferDir, { recursive: true });
282
+ });
283
+ afterEach(() => {
284
+ if (existsSync(bufferDir)) {
285
+ rmSync(bufferDir, { recursive: true, force: true });
286
+ }
287
+ });
288
+ it('persists events to JSONL file on disk', async () => {
289
+ const source = new ClaudeCodeSource();
290
+ await source.init({
291
+ id: 'test-src',
292
+ connector: '@orgloop/connector-claude-code',
293
+ config: { buffer_dir: bufferDir },
294
+ });
295
+ const handler = source.webhook();
296
+ const body = JSON.stringify(samplePayload);
297
+ const req = createMockRequest(body);
298
+ const res = createMockResponse();
299
+ await handler(req, res);
300
+ expect(res.statusCode).toBe(200);
301
+ // Verify the JSONL file exists and has content
302
+ const bufferPath = join(bufferDir, 'claude-code-test-src.jsonl');
303
+ expect(existsSync(bufferPath)).toBe(true);
304
+ const content = readFileSync(bufferPath, 'utf-8').trim();
305
+ const lines = content.split('\n');
306
+ expect(lines).toHaveLength(1);
307
+ const persisted = JSON.parse(lines[0]);
308
+ expect(persisted.type).toBe('actor.stopped');
309
+ expect(persisted.payload.session_id).toBe('sess-123');
310
+ });
311
+ it('poll drains buffer and clears file', async () => {
312
+ const source = new ClaudeCodeSource();
313
+ await source.init({
314
+ id: 'test-src',
315
+ connector: '@orgloop/connector-claude-code',
316
+ config: { buffer_dir: bufferDir },
317
+ });
318
+ const handler = source.webhook();
319
+ // Send two events
320
+ for (const sid of ['sess-001', 'sess-002']) {
321
+ const body = JSON.stringify({ ...samplePayload, session_id: sid });
322
+ const req = createMockRequest(body);
323
+ const res = createMockResponse();
324
+ await handler(req, res);
325
+ }
326
+ const result = await source.poll(null);
327
+ expect(result.events).toHaveLength(2);
328
+ expect(result.events[0].payload.session_id).toBe('sess-001');
329
+ expect(result.events[1].payload.session_id).toBe('sess-002');
330
+ // Buffer file should be cleared
331
+ const bufferPath = join(bufferDir, 'claude-code-test-src.jsonl');
332
+ const content = readFileSync(bufferPath, 'utf-8');
333
+ expect(content).toBe('');
334
+ // Second poll should be empty
335
+ const result2 = await source.poll(result.checkpoint);
336
+ expect(result2.events).toHaveLength(0);
337
+ });
338
+ it('survives crash — new instance reads buffered events', async () => {
339
+ // First instance writes events
340
+ const source1 = new ClaudeCodeSource();
341
+ await source1.init({
342
+ id: 'test-src',
343
+ connector: '@orgloop/connector-claude-code',
344
+ config: { buffer_dir: bufferDir },
345
+ });
346
+ const handler1 = source1.webhook();
347
+ const body = JSON.stringify(samplePayload);
348
+ const req = createMockRequest(body);
349
+ const res = createMockResponse();
350
+ await handler1(req, res);
351
+ // Simulate crash — don't poll or shutdown, just abandon the instance
352
+ // Second instance picks up buffered events via poll
353
+ const source2 = new ClaudeCodeSource();
354
+ await source2.init({
355
+ id: 'test-src',
356
+ connector: '@orgloop/connector-claude-code',
357
+ config: { buffer_dir: bufferDir },
358
+ });
359
+ const result = await source2.poll(null);
360
+ expect(result.events).toHaveLength(1);
361
+ expect(result.events[0].type).toBe('actor.stopped');
362
+ expect(result.events[0].payload.session_id).toBe('sess-123');
363
+ });
364
+ it('creates buffer directory if it does not exist', async () => {
365
+ const nestedDir = join(bufferDir, 'nested', 'deep');
366
+ expect(existsSync(nestedDir)).toBe(false);
367
+ const source = new ClaudeCodeSource();
368
+ await source.init({
369
+ id: 'test-src',
370
+ connector: '@orgloop/connector-claude-code',
371
+ config: { buffer_dir: nestedDir },
372
+ });
373
+ expect(existsSync(nestedDir)).toBe(true);
374
+ });
375
+ it('works with HMAC and buffer persistence together', async () => {
376
+ const source = new ClaudeCodeSource();
377
+ await source.init({
378
+ id: 'test-src',
379
+ connector: '@orgloop/connector-claude-code',
380
+ config: { secret: TEST_SECRET, buffer_dir: bufferDir },
381
+ });
382
+ const handler = source.webhook();
383
+ const body = JSON.stringify(samplePayload);
384
+ const signature = signPayload(body, TEST_SECRET);
385
+ const req = createMockRequest(body, 'POST', { 'x-hub-signature-256': signature });
386
+ const res = createMockResponse();
387
+ const events = await handler(req, res);
388
+ expect(res.statusCode).toBe(200);
389
+ expect(events).toHaveLength(1);
390
+ // Verify persisted to disk
391
+ const bufferPath = join(bufferDir, 'claude-code-test-src.jsonl');
392
+ expect(existsSync(bufferPath)).toBe(true);
393
+ // Poll reads from disk
394
+ const result = await source.poll(null);
395
+ expect(result.events).toHaveLength(1);
396
+ expect(result.events[0].payload.session_id).toBe('sess-123');
397
+ });
398
+ it('handles empty buffer file gracefully', async () => {
399
+ const bufferPath = join(bufferDir, 'claude-code-test-src.jsonl');
400
+ writeFileSync(bufferPath, '');
401
+ const source = new ClaudeCodeSource();
402
+ await source.init({
403
+ id: 'test-src',
404
+ connector: '@orgloop/connector-claude-code',
405
+ config: { buffer_dir: bufferDir },
406
+ });
407
+ const result = await source.poll(null);
408
+ expect(result.events).toHaveLength(0);
409
+ });
410
+ });
411
+ //# sourceMappingURL=source.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.test.js","sourceRoot":"","sources":["../../src/__tests__/source.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @orgloop/connector-claude-code — Claude Code hook-based source connector registration.
3
+ */
4
+ import type { ConnectorRegistration } from '@orgloop/sdk';
5
+ export default function register(): ConnectorRegistration;
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AAG1D,MAAM,CAAC,OAAO,UAAU,QAAQ,IAAI,qBAAqB,CAuBxD"}
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ /**
2
+ * @orgloop/connector-claude-code — Claude Code hook-based source connector registration.
3
+ */
4
+ import { ClaudeCodeSource } from './source.js';
5
+ export default function register() {
6
+ return {
7
+ id: 'claude-code',
8
+ source: ClaudeCodeSource,
9
+ setup: {
10
+ env_vars: [
11
+ {
12
+ name: 'CLAUDE_CODE_WEBHOOK_SECRET',
13
+ description: 'HMAC-SHA256 secret for validating webhook signatures (optional)',
14
+ required: false,
15
+ },
16
+ ],
17
+ integrations: [
18
+ {
19
+ id: 'claude-code-stop-hook',
20
+ description: 'Install a Stop hook in Claude Code settings so session exits notify OrgLoop',
21
+ platform: 'claude-code',
22
+ command: 'orgloop hook claude-code-stop',
23
+ },
24
+ ],
25
+ },
26
+ };
27
+ }
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,CAAC,OAAO,UAAU,QAAQ;IAC/B,OAAO;QACN,EAAE,EAAE,aAAa;QACjB,MAAM,EAAE,gBAAgB;QACxB,KAAK,EAAE;YACN,QAAQ,EAAE;gBACT;oBACC,IAAI,EAAE,4BAA4B;oBAClC,WAAW,EAAE,iEAAiE;oBAC9E,QAAQ,EAAE,KAAK;iBACf;aACD;YACD,YAAY,EAAE;gBACb;oBACC,EAAE,EAAE,uBAAuB;oBAC3B,WAAW,EACV,6EAA6E;oBAC9E,QAAQ,EAAE,aAAa;oBACvB,OAAO,EAAE,+BAA+B;iBACxC;aACD;SACD;KACD,CAAC;AACH,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Claude Code source connector — hook-based (webhook receiver).
3
+ *
4
+ * Instead of polling, this connector exposes a webhook handler that receives
5
+ * POST requests from Claude Code's post-exit hook script.
6
+ */
7
+ import type { PollResult, SourceConfig, SourceConnector, WebhookHandler } from '@orgloop/sdk';
8
+ export declare class ClaudeCodeSource implements SourceConnector {
9
+ readonly id = "claude-code";
10
+ private sourceId;
11
+ private secret?;
12
+ private bufferPath?;
13
+ private pendingEvents;
14
+ init(config: SourceConfig): Promise<void>;
15
+ poll(_checkpoint: string | null): Promise<PollResult>;
16
+ webhook(): WebhookHandler;
17
+ shutdown(): Promise<void>;
18
+ private persistEvent;
19
+ private loadBufferedEvents;
20
+ }
21
+ //# sourceMappingURL=source.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.d.ts","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EAEX,UAAU,EACV,YAAY,EACZ,eAAe,EACf,cAAc,EACd,MAAM,cAAc,CAAC;AA8BtB,qBAAa,gBAAiB,YAAW,eAAe;IACvD,QAAQ,CAAC,EAAE,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,MAAM,CAAC,CAAS;IACxB,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAsB;IAErC,IAAI,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBzC,IAAI,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,CAAC;IAiB3D,OAAO,IAAI,cAAc;IAqEnB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAI/B,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,kBAAkB;CAU1B"}
package/dist/source.js ADDED
@@ -0,0 +1,148 @@
1
+ /**
2
+ * Claude Code source connector — hook-based (webhook receiver).
3
+ *
4
+ * Instead of polling, this connector exposes a webhook handler that receives
5
+ * POST requests from Claude Code's post-exit hook script.
6
+ */
7
+ import { createHmac, timingSafeEqual } from 'node:crypto';
8
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
9
+ import { join } from 'node:path';
10
+ import { buildEvent } from '@orgloop/sdk';
11
+ /** Resolve env var references like ${WEBHOOK_SECRET} */
12
+ function resolveEnvVar(value) {
13
+ const match = value.match(/^\$\{(.+)\}$/);
14
+ if (match) {
15
+ const envValue = process.env[match[1]];
16
+ if (!envValue) {
17
+ throw new Error(`Environment variable ${match[1]} is not set`);
18
+ }
19
+ return envValue;
20
+ }
21
+ return value;
22
+ }
23
+ export class ClaudeCodeSource {
24
+ id = 'claude-code';
25
+ sourceId = 'claude-code';
26
+ secret;
27
+ bufferPath;
28
+ pendingEvents = [];
29
+ async init(config) {
30
+ this.sourceId = config.id;
31
+ const cfg = config.config;
32
+ if (cfg.secret) {
33
+ this.secret = resolveEnvVar(cfg.secret);
34
+ }
35
+ if (cfg.buffer_dir) {
36
+ const dir = resolveEnvVar(cfg.buffer_dir);
37
+ if (!existsSync(dir)) {
38
+ mkdirSync(dir, { recursive: true });
39
+ }
40
+ this.bufferPath = join(dir, `claude-code-${this.sourceId}.jsonl`);
41
+ this.loadBufferedEvents();
42
+ }
43
+ }
44
+ async poll(_checkpoint) {
45
+ // Drain any events received via webhook since last poll
46
+ let events;
47
+ if (this.bufferPath) {
48
+ events = this.loadBufferedEvents();
49
+ // Clear the buffer file
50
+ writeFileSync(this.bufferPath, '');
51
+ }
52
+ else {
53
+ events = [...this.pendingEvents];
54
+ this.pendingEvents = [];
55
+ }
56
+ const checkpoint = events.length > 0 ? events[events.length - 1].timestamp : new Date().toISOString();
57
+ return { events, checkpoint };
58
+ }
59
+ webhook() {
60
+ return async (req, res) => {
61
+ if (req.method !== 'POST') {
62
+ res.writeHead(405, { 'Content-Type': 'application/json' });
63
+ res.end(JSON.stringify({ error: 'Method not allowed' }));
64
+ return [];
65
+ }
66
+ const body = await readBody(req);
67
+ // HMAC validation if secret is configured
68
+ if (this.secret) {
69
+ const signature = req.headers['x-hub-signature-256'] ?? req.headers['x-signature'];
70
+ if (!signature) {
71
+ res.writeHead(401, { 'Content-Type': 'application/json' });
72
+ res.end(JSON.stringify({ error: 'Missing signature' }));
73
+ return [];
74
+ }
75
+ const expected = `sha256=${createHmac('sha256', this.secret).update(body).digest('hex')}`;
76
+ const sigBuffer = Buffer.from(signature);
77
+ const expectedBuffer = Buffer.from(expected);
78
+ if (sigBuffer.length !== expectedBuffer.length ||
79
+ !timingSafeEqual(sigBuffer, expectedBuffer)) {
80
+ res.writeHead(401, { 'Content-Type': 'application/json' });
81
+ res.end(JSON.stringify({ error: 'Invalid signature' }));
82
+ return [];
83
+ }
84
+ }
85
+ try {
86
+ const payload = JSON.parse(body);
87
+ const event = buildEvent({
88
+ source: this.sourceId,
89
+ type: 'actor.stopped',
90
+ provenance: {
91
+ platform: 'claude-code',
92
+ platform_event: 'session.exited',
93
+ author: 'claude-code',
94
+ author_type: 'bot',
95
+ session_id: payload.session_id,
96
+ working_directory: payload.working_directory,
97
+ },
98
+ payload: {
99
+ session_id: payload.session_id,
100
+ working_directory: payload.working_directory,
101
+ duration_seconds: payload.duration_seconds,
102
+ exit_status: payload.exit_status,
103
+ summary: payload.summary ?? '',
104
+ },
105
+ });
106
+ this.persistEvent(event);
107
+ res.writeHead(200, { 'Content-Type': 'application/json' });
108
+ res.end(JSON.stringify({ ok: true, event_id: event.id }));
109
+ return [event];
110
+ }
111
+ catch {
112
+ res.writeHead(400, { 'Content-Type': 'application/json' });
113
+ res.end(JSON.stringify({ error: 'Invalid JSON payload' }));
114
+ return [];
115
+ }
116
+ };
117
+ }
118
+ async shutdown() {
119
+ this.pendingEvents = [];
120
+ }
121
+ persistEvent(event) {
122
+ if (this.bufferPath) {
123
+ appendFileSync(this.bufferPath, `${JSON.stringify(event)}\n`);
124
+ }
125
+ else {
126
+ this.pendingEvents.push(event);
127
+ }
128
+ }
129
+ loadBufferedEvents() {
130
+ if (!this.bufferPath || !existsSync(this.bufferPath)) {
131
+ return [];
132
+ }
133
+ const content = readFileSync(this.bufferPath, 'utf-8').trim();
134
+ if (!content) {
135
+ return [];
136
+ }
137
+ return content.split('\n').map((line) => JSON.parse(line));
138
+ }
139
+ }
140
+ function readBody(req) {
141
+ return new Promise((resolve, reject) => {
142
+ const chunks = [];
143
+ req.on('data', (chunk) => chunks.push(chunk));
144
+ req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
145
+ req.on('error', reject);
146
+ });
147
+ }
148
+ //# sourceMappingURL=source.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"source.js","sourceRoot":"","sources":["../src/source.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "@orgloop/connector-claude-code",
3
+ "version": "0.1.0",
4
+ "description": "OrgLoop Claude Code connector — hook-based exit notifications",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "dependencies": {
9
+ "@orgloop/sdk": "0.1.0"
10
+ },
11
+ "orgloop": {
12
+ "type": "connector",
13
+ "provides": [
14
+ "source"
15
+ ],
16
+ "id": "claude-code"
17
+ },
18
+ "files": [
19
+ "dist"
20
+ ],
21
+ "publishConfig": {
22
+ "access": "public"
23
+ },
24
+ "license": "MIT",
25
+ "scripts": {
26
+ "build": "tsc",
27
+ "clean": "rm -rf dist",
28
+ "typecheck": "tsc --noEmit",
29
+ "test": "vitest run"
30
+ }
31
+ }