claude-sandbox-agent 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.
@@ -0,0 +1,23 @@
1
+ {
2
+ "mcpServers": {
3
+ "linear": {
4
+ "type": "http",
5
+ "url": "https://mcp.linear.app/mcp",
6
+ "headers": {
7
+ "Authorization": "Bearer ${LINEAR_ACCESS_TOKEN}"
8
+ }
9
+ },
10
+ "notion": {
11
+ "type": "http",
12
+ "url": "https://mcp.notion.com/mcp",
13
+ "headers": {
14
+ "Authorization": "Bearer ${NOTION_API_KEY}",
15
+ "Notion-Version": "2025-09-03"
16
+ }
17
+ },
18
+ "context7": {
19
+ "command": "npx",
20
+ "args": ["-y", "@upstash/context7-mcp", "--api-key", "${CONTEXT7_API_KEY}"]
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,12 @@
1
+ {
2
+ "enabledPlugins": {
3
+ "agent-sdk-dev@claude-plugins-official": true,
4
+ "plugin-dev@claude-plugins-official": true,
5
+ "code-simplifier@claude-plugins-official": true,
6
+ "code-review@claude-plugins-official": true,
7
+ "pr-review-toolkit@claude-plugins-official": true
8
+ },
9
+ "env": {
10
+ "ENABLE_TOOL_SEARCH": "true"
11
+ }
12
+ }
@@ -0,0 +1,146 @@
1
+ # Project Lead Skill
2
+
3
+ > Skill for handling project leadership: planning, decomposition, and coordination
4
+
5
+ ## Overview
6
+
7
+ This skill enables the agent to act as a project lead when assigned to a Linear project. It handles the full lifecycle from initial planning through implementation coordination.
8
+
9
+ ## Workflow
10
+
11
+ ### Phase 1: Planning
12
+
13
+ When project is assigned to agent:
14
+
15
+ 1. **Create Planning Issue**
16
+ - Title: "{Project Name} - Research & Planning"
17
+ - Description: Links to project, outlines planning scope
18
+ - Assign to self (triggers new session)
19
+
20
+ 2. **Research & Analysis** (in planning issue session)
21
+ - Read project requirements
22
+ - Analyze existing codebase
23
+ - Research third-party APIs (if integration)
24
+ - Identify technical challenges
25
+ - Review related documentation in Notion
26
+
27
+ 3. **Create Plan in Notion**
28
+ - Create new Notion page: "{Project Name} - Implementation Plan"
29
+ - Structure:
30
+ - Overview & Goals
31
+ - Architecture Decisions
32
+ - Implementation Phases
33
+ - Task Breakdown
34
+ - Dependencies
35
+ - Security Considerations
36
+ - Testing Strategy
37
+ - Rollout Plan
38
+
39
+ 4. **Complete Planning Issue**
40
+ - Add comment with Notion plan link
41
+ - Move to "Done"
42
+ - Wait for plan review
43
+
44
+ ### Phase 2: Decomposition
45
+
46
+ Triggered when project status changes to "Story Stage":
47
+
48
+ 1. **Read Approved Plan**
49
+ - Fetch plan from Notion
50
+ - Parse implementation phases
51
+
52
+ 2. **Create Implementation Issues**
53
+ For each task in plan:
54
+ - Create Linear issue with:
55
+ - Clear title
56
+ - Detailed description from plan
57
+ - Acceptance criteria
58
+ - Link to plan in Notion
59
+ - Link to parent project
60
+ - Priority
61
+ - Dependencies (blocks/blocked by)
62
+
63
+ 3. **Set Issue Properties**
64
+ - Assign all issues to agent
65
+ - Set appropriate labels
66
+ - Order by dependency graph
67
+
68
+ 4. **Comment on Project**
69
+ - List all created issues
70
+ - Show dependency order
71
+ - Estimate timeline
72
+
73
+ ### Phase 3: Implementation
74
+
75
+ Each created issue triggers individual sessions:
76
+
77
+ 1. **Monitor Progress**
78
+ - Track issue completion
79
+ - Update project comments with status
80
+ - Handle blockers
81
+
82
+ 2. **Per-Issue Execution**
83
+ - Each issue handled as individual assignment (Mode 1)
84
+ - Implement → Test → PR → Review
85
+
86
+ ### Phase 4: QA Transition
87
+
88
+ When all implementation issues complete:
89
+
90
+ 1. **Verify Completion**
91
+ - Check all issues in "Done" state
92
+ - Verify all PRs created and linked
93
+
94
+ 2. **Create Summary**
95
+ - List all PRs
96
+ - Overall changes made
97
+ - Testing completed
98
+ - Known issues/limitations
99
+
100
+ 3. **Move to QA**
101
+ - Change project status to "QA"
102
+ - Add summary comment
103
+ - Notify team
104
+
105
+ ## Tools Used
106
+
107
+ - `linear_create_issue` - Create decomposed issues
108
+ - `linear_update_issue` - Update issue properties
109
+ - `linear_create_comment` - Progress updates
110
+ - `notion_create_page` - Create plan
111
+ - `notion_read_page` - Read approved plan
112
+ - Read, Grep, Glob - Code analysis
113
+ - WebFetch - Research external APIs
114
+
115
+ ## Example Usage
116
+
117
+ **Project Assigned:**
118
+ ```
119
+ Project: "Add Stripe Payment Integration"
120
+ Status: In Progress
121
+ Assigned to: Agent
122
+ ```
123
+
124
+ **Agent Actions:**
125
+ 1. Creates issue: "Add Stripe Payment Integration - Research & Planning"
126
+ 2. Self-assigns planning issue → new session
127
+ 3. Researches Stripe API, analyzes codebase
128
+ 4. Creates plan in Notion with architecture decisions
129
+ 5. Links plan in planning issue comment
130
+ 6. Moves planning issue to "Done"
131
+ 7. Waits for project status → "Story Stage"
132
+ 8. Creates 4 issues:
133
+ - "Stripe API - Backend Integration"
134
+ - "Payment UI - Checkout Flow"
135
+ - "Webhooks - Payment Events"
136
+ - "Tests - Payment Integration"
137
+ 9. Each issue gets implemented in separate sessions
138
+ 10. All done → moves project to "QA"
139
+
140
+ ## Notes
141
+
142
+ - Planning issue comment format should include clear next steps
143
+ - Always wait for explicit status change to "Story Stage" before decomposition
144
+ - Create issues in dependency order
145
+ - Link all issues to parent project
146
+ - Keep project comments updated with progress
@@ -0,0 +1 @@
1
+ #!/usr/bin/env node
package/dist/index.js ADDED
@@ -0,0 +1,573 @@
1
+ #!/usr/bin/env node
2
+ #!/usr/bin/env node
3
+
4
+ // src/index.ts
5
+ import { Command as Command5 } from "commander";
6
+
7
+ // src/commands/start.ts
8
+ import { Command } from "commander";
9
+
10
+ // src/linear/agent.ts
11
+ import { LinearClient } from "@linear/sdk";
12
+
13
+ // src/agent.ts
14
+ import * as fs from "fs";
15
+ import * as path from "path";
16
+ import {
17
+ query
18
+ } from "@anthropic-ai/claude-agent-sdk";
19
+ function getInterruptFilePath(externalSessionId) {
20
+ return path.join("/tmp", `agent-${externalSessionId}.interrupt`);
21
+ }
22
+ function checkInterruptFlag(externalSessionId) {
23
+ const filePath = getInterruptFilePath(externalSessionId);
24
+ try {
25
+ if (fs.existsSync(filePath)) {
26
+ const content = fs.readFileSync(filePath, "utf-8").trim();
27
+ return content === "true";
28
+ }
29
+ return false;
30
+ } catch {
31
+ return false;
32
+ }
33
+ }
34
+ function setInterruptFlag(externalSessionId) {
35
+ const filePath = getInterruptFilePath(externalSessionId);
36
+ fs.writeFileSync(filePath, "true", "utf-8");
37
+ }
38
+ function clearInterruptFlag(externalSessionId) {
39
+ const filePath = getInterruptFilePath(externalSessionId);
40
+ try {
41
+ if (fs.existsSync(filePath)) {
42
+ fs.unlinkSync(filePath);
43
+ }
44
+ } catch {
45
+ }
46
+ }
47
+ var Agent = class {
48
+ currentSessionId;
49
+ isRunning = false;
50
+ externalSessionId;
51
+ activeQuery;
52
+ constructor(externalSessionId) {
53
+ this.externalSessionId = externalSessionId;
54
+ }
55
+ // ============================================
56
+ // Event methods - Override in subclasses
57
+ // ============================================
58
+ /**
59
+ * Called when agent starts processing
60
+ */
61
+ async onStart() {
62
+ }
63
+ /**
64
+ * Called when agent emits a thinking/reasoning text
65
+ */
66
+ async onThinking(block) {
67
+ }
68
+ /**
69
+ * Called when agent uses a tool
70
+ */
71
+ async onToolUse(block) {
72
+ }
73
+ /**
74
+ * Called when agent updates its plan (via TodoWrite)
75
+ */
76
+ async onPlanUpdate(todos) {
77
+ }
78
+ /**
79
+ * Called when agent completes successfully
80
+ */
81
+ async onComplete(message) {
82
+ }
83
+ /**
84
+ * Called when agent encounters an error
85
+ */
86
+ async onError(error) {
87
+ }
88
+ /**
89
+ * Called when agent is stopped via stop command
90
+ */
91
+ async onStop() {
92
+ }
93
+ // ============================================
94
+ // Main execution logic
95
+ // ============================================
96
+ /**
97
+ * Run the agent with the given prompt
98
+ */
99
+ async run(runOptions) {
100
+ const {
101
+ prompt,
102
+ sessionId,
103
+ resumeSession = false,
104
+ forkSession = false,
105
+ cwd = process.cwd(),
106
+ options: additionalOptions = {}
107
+ } = runOptions;
108
+ this.isRunning = true;
109
+ let resultSessionId = sessionId ?? "";
110
+ let finalResult;
111
+ let wasInterrupted = false;
112
+ clearInterruptFlag(this.externalSessionId);
113
+ try {
114
+ await this.onStart();
115
+ const sdkOptions = {
116
+ settingSources: ["user", "project"],
117
+ permissionMode: "acceptEdits",
118
+ cwd,
119
+ ...additionalOptions
120
+ };
121
+ if (resumeSession && sessionId) {
122
+ sdkOptions.resume = sessionId;
123
+ sdkOptions.forkSession = forkSession;
124
+ }
125
+ this.activeQuery = query({ prompt, options: sdkOptions });
126
+ for await (const message of this.activeQuery) {
127
+ if (checkInterruptFlag(this.externalSessionId)) {
128
+ console.log("Interrupt flag detected, stopping agent...");
129
+ await this.activeQuery.interrupt();
130
+ wasInterrupted = true;
131
+ break;
132
+ }
133
+ if (message.type === "system") {
134
+ const sysMsg = message;
135
+ if (sysMsg.subtype === "init") {
136
+ resultSessionId = sysMsg.session_id;
137
+ this.currentSessionId = sysMsg.session_id;
138
+ }
139
+ }
140
+ if (message.type === "assistant") {
141
+ await this.processAssistantMessage(message);
142
+ }
143
+ if (message.type === "result") {
144
+ const resultMsg = message;
145
+ if (resultMsg.subtype === "success" && resultMsg.result) {
146
+ finalResult = resultMsg.result;
147
+ }
148
+ await this.onComplete(resultMsg);
149
+ }
150
+ }
151
+ return {
152
+ sessionId: resultSessionId,
153
+ result: finalResult,
154
+ interrupted: wasInterrupted
155
+ };
156
+ } catch (error) {
157
+ const err = error instanceof Error ? error : new Error(String(error));
158
+ await this.onError(err);
159
+ return {
160
+ sessionId: resultSessionId,
161
+ error: err.message,
162
+ interrupted: wasInterrupted
163
+ };
164
+ } finally {
165
+ this.isRunning = false;
166
+ this.activeQuery = void 0;
167
+ clearInterruptFlag(this.externalSessionId);
168
+ }
169
+ }
170
+ /**
171
+ * Interrupt the currently running agent
172
+ * Returns true if an interrupt was sent, false if no active query
173
+ */
174
+ async interrupt() {
175
+ if (this.activeQuery) {
176
+ await this.activeQuery.interrupt();
177
+ return true;
178
+ }
179
+ return false;
180
+ }
181
+ /**
182
+ * Stop the agent session
183
+ * Sets interrupt flag and calls onStop callback
184
+ */
185
+ async stop() {
186
+ setInterruptFlag(this.externalSessionId);
187
+ await this.onStop();
188
+ }
189
+ /**
190
+ * Process an assistant message and call appropriate event methods
191
+ */
192
+ async processAssistantMessage(message) {
193
+ const content = message.message.content;
194
+ for (const block of content) {
195
+ if (block.type === "text") {
196
+ await this.onThinking(block);
197
+ }
198
+ if (block.type === "tool_use") {
199
+ if (block.name === "TodoWrite") {
200
+ const input = block.input;
201
+ if (input.todos) {
202
+ await this.onPlanUpdate(input.todos);
203
+ }
204
+ } else {
205
+ await this.onToolUse(block);
206
+ }
207
+ }
208
+ }
209
+ }
210
+ /**
211
+ * Check if agent is currently running
212
+ */
213
+ isActive() {
214
+ return this.isRunning;
215
+ }
216
+ /**
217
+ * Get current session ID
218
+ */
219
+ getSessionId() {
220
+ return this.currentSessionId;
221
+ }
222
+ };
223
+
224
+ // src/linear/agent.ts
225
+ var LinearAgent = class extends Agent {
226
+ linearClient;
227
+ linearSessionId;
228
+ lastThoughtTime = 0;
229
+ thoughtDebounceMs = 1e3;
230
+ // Debounce thoughts to avoid spam
231
+ constructor(config) {
232
+ super(config.linearSessionId);
233
+ this.linearClient = new LinearClient({ accessToken: config.linearAccessToken });
234
+ this.linearSessionId = config.linearSessionId;
235
+ }
236
+ // ============================================
237
+ // Event method implementations
238
+ // ============================================
239
+ /**
240
+ * Called when agent starts
241
+ */
242
+ async onStart() {
243
+ await this.sendActivity("thought" /* Thought */, "Starting work...", true);
244
+ }
245
+ /**
246
+ * Called when agent is thinking/reasoning
247
+ * Sends as ephemeral thought activity (debounced)
248
+ */
249
+ async onThinking(block) {
250
+ const now = Date.now();
251
+ if (now - this.lastThoughtTime < this.thoughtDebounceMs) {
252
+ return;
253
+ }
254
+ this.lastThoughtTime = now;
255
+ const content = block.text;
256
+ if (content.length < 20) {
257
+ return;
258
+ }
259
+ const truncated = content.length > 500 ? content.substring(0, 500) + "..." : content;
260
+ await this.sendActivity("thought" /* Thought */, truncated, true);
261
+ }
262
+ /**
263
+ * Called when agent uses a tool
264
+ * Sends as action activity
265
+ */
266
+ async onToolUse(block) {
267
+ const description = this.formatToolDescription(block);
268
+ await this.sendActivity("action" /* Action */, description, false);
269
+ }
270
+ /**
271
+ * Called when agent updates its plan
272
+ * Maps to Linear session plan
273
+ */
274
+ async onPlanUpdate(steps) {
275
+ if (steps.length === 0) return;
276
+ const linearSteps = steps.map((step) => ({
277
+ content: step.content,
278
+ status: this.mapStatusToLinear(step.status)
279
+ }));
280
+ try {
281
+ await this.linearClient.updateAgentSession(this.linearSessionId, {
282
+ plan: linearSteps
283
+ });
284
+ } catch (error) {
285
+ console.error("Failed to update Linear plan:", error);
286
+ }
287
+ }
288
+ /**
289
+ * Called when agent completes
290
+ * Sends as final activity
291
+ */
292
+ async onComplete(message) {
293
+ const text = message.subtype === "success" && message.result ? message.result : "Task completed successfully.";
294
+ await this.sendActivity("final" /* Final */, text, false);
295
+ }
296
+ /**
297
+ * Called when agent errors
298
+ * Sends as error activity
299
+ */
300
+ async onError(error) {
301
+ await this.sendActivity("error" /* Error */, `Error: ${error.message}`, false);
302
+ }
303
+ async onStop() {
304
+ await this.sendActivity("final" /* Final */, "Session stopped", false);
305
+ }
306
+ // ============================================
307
+ // Helper methods
308
+ // ============================================
309
+ /**
310
+ * Send activity to Linear
311
+ */
312
+ async sendActivity(type, body, ephemeral) {
313
+ try {
314
+ await this.linearClient.createAgentActivity({
315
+ agentSessionId: this.linearSessionId,
316
+ content: { type, body },
317
+ ephemeral
318
+ });
319
+ } catch (error) {
320
+ console.error("Failed to send Linear activity:", error);
321
+ }
322
+ }
323
+ /**
324
+ * Format tool use description for display
325
+ */
326
+ formatToolDescription(block) {
327
+ const { name, input } = block;
328
+ const params = input;
329
+ switch (name) {
330
+ case "Write":
331
+ return `Creating file: ${params.file_path}`;
332
+ case "Edit":
333
+ return `Editing: ${params.file_path}`;
334
+ case "Read":
335
+ return `Reading: ${params.file_path}`;
336
+ case "Bash": {
337
+ const cmd = String(params.command ?? "");
338
+ const desc = params.description ?? cmd.substring(0, 50);
339
+ return `Running: ${desc}`;
340
+ }
341
+ case "Grep":
342
+ return `Searching for: ${params.pattern}`;
343
+ case "Glob":
344
+ return `Finding files: ${params.pattern}`;
345
+ case "Task":
346
+ return `Delegating to: ${params.subagent_type ?? "subagent"}`;
347
+ case "Skill":
348
+ return `Using skill: ${params.skill}`;
349
+ default:
350
+ return `Using ${name}`;
351
+ }
352
+ }
353
+ /**
354
+ * Map internal status to Linear plan status
355
+ */
356
+ mapStatusToLinear(status) {
357
+ switch (status) {
358
+ case "in_progress":
359
+ return "inProgress";
360
+ case "completed":
361
+ return "completed";
362
+ case "canceled":
363
+ return "canceled";
364
+ case "pending":
365
+ default:
366
+ return "pending";
367
+ }
368
+ }
369
+ };
370
+ var createLinearAgent = (sessionId) => {
371
+ const linearAccessToken = process.env.LINEAR_ACCESS_TOKEN;
372
+ if (!linearAccessToken) {
373
+ throw new Error("Linear access token is missing");
374
+ }
375
+ return new LinearAgent({ linearAccessToken, linearSessionId: sessionId });
376
+ };
377
+
378
+ // src/factory.ts
379
+ function createAgent(platform, sessionId) {
380
+ switch (platform) {
381
+ case "linear":
382
+ return createLinearAgent(sessionId);
383
+ default:
384
+ throw new Error(`Unsupported platform: ${platform}`);
385
+ }
386
+ }
387
+
388
+ // src/callback.ts
389
+ async function sendSessionUpdate(callbackUrl, callbackSecret, update) {
390
+ try {
391
+ const response = await fetch(callbackUrl, {
392
+ method: "POST",
393
+ headers: {
394
+ "Content-Type": "application/json",
395
+ "Authorization": `Bearer ${callbackSecret}`
396
+ },
397
+ body: JSON.stringify(update)
398
+ });
399
+ if (!response.ok) {
400
+ console.error(`Callback failed: ${response.status} ${response.statusText}`);
401
+ }
402
+ } catch (error) {
403
+ console.error("Failed to send session update:", error);
404
+ }
405
+ }
406
+ async function reportRunning(callbackUrl, callbackSecret, externalSessionId, claudeSessionId) {
407
+ await sendSessionUpdate(callbackUrl, callbackSecret, {
408
+ externalSessionId,
409
+ claudeSessionId,
410
+ state: "running"
411
+ });
412
+ }
413
+ async function reportCompleted(callbackUrl, callbackSecret, externalSessionId, claudeSessionId) {
414
+ await sendSessionUpdate(callbackUrl, callbackSecret, {
415
+ externalSessionId,
416
+ claudeSessionId,
417
+ state: "completed"
418
+ });
419
+ }
420
+ async function reportError(callbackUrl, callbackSecret, externalSessionId, error) {
421
+ await sendSessionUpdate(callbackUrl, callbackSecret, {
422
+ externalSessionId,
423
+ state: "error",
424
+ error
425
+ });
426
+ }
427
+ async function reportResult(callbackUrl, externalSessionId, result) {
428
+ const callbackSecret = process.env.CLAUDE_LINEAR_CALLBACK_SECRET;
429
+ if (!callbackUrl || !callbackSecret) {
430
+ return;
431
+ }
432
+ if (result.sessionId) {
433
+ await reportRunning(callbackUrl, callbackSecret, externalSessionId, result.sessionId);
434
+ }
435
+ if (result.error) {
436
+ await reportError(callbackUrl, callbackSecret, externalSessionId, result.error);
437
+ } else if (!result.interrupted) {
438
+ await reportCompleted(callbackUrl, callbackSecret, externalSessionId, result.sessionId);
439
+ }
440
+ }
441
+
442
+ // src/commands/start.ts
443
+ var startCommand = new Command("start").description("Start a new agent session").requiredOption("--platform <platform>", "Platform type (linear)").requiredOption("--session-id <id>", "External session ID (e.g., Linear session ID)").requiredOption("--prompt <prompt>", "Initial prompt for the agent").option("--callback-url <url>", "Server callback URL for session updates").option("--working-dir <dir>", "Working directory", process.cwd()).action(async (options) => {
444
+ const { platform, sessionId, prompt, callbackUrl, workingDir } = options;
445
+ try {
446
+ const agent = createAgent(platform, sessionId);
447
+ const result = await agent.run({
448
+ prompt,
449
+ cwd: workingDir,
450
+ options: {
451
+ settingSources: ["user", "project"],
452
+ permissionMode: "bypassPermissions"
453
+ }
454
+ });
455
+ await reportResult(callbackUrl, sessionId, result);
456
+ console.log(JSON.stringify({
457
+ status: result.error ? "error" : result.interrupted ? "interrupted" : "completed",
458
+ claudeSessionId: result.sessionId,
459
+ result: result.result,
460
+ error: result.error
461
+ }));
462
+ process.exit(result.error ? 1 : 0);
463
+ } catch (error) {
464
+ const errorMessage = error instanceof Error ? error.message : String(error);
465
+ console.error(JSON.stringify({ status: "error", error: errorMessage }));
466
+ process.exit(1);
467
+ }
468
+ });
469
+ var start_default = startCommand;
470
+
471
+ // src/commands/stop.ts
472
+ import { Command as Command2 } from "commander";
473
+ var stopCommand = new Command2("stop").description("Stop an agent session gracefully").requiredOption("--platform <platform>", "Platform type (linear)").requiredOption("--session-id <id>", "External session ID (e.g., Linear session ID)").action(async (options) => {
474
+ const { platform, sessionId } = options;
475
+ try {
476
+ const agent = createAgent(platform, sessionId);
477
+ await agent.stop();
478
+ console.log(JSON.stringify({
479
+ status: "stopped",
480
+ sessionId
481
+ }));
482
+ process.exit(0);
483
+ } catch (error) {
484
+ const errorMessage = error instanceof Error ? error.message : String(error);
485
+ console.error(JSON.stringify({
486
+ status: "error",
487
+ error: errorMessage
488
+ }));
489
+ process.exit(1);
490
+ }
491
+ });
492
+
493
+ // src/commands/resume.ts
494
+ import { Command as Command3 } from "commander";
495
+ var INTERRUPT_WAIT_MS = 500;
496
+ var resumeCommand = new Command3("resume").description("Resume an existing agent session").requiredOption("--platform <platform>", "Platform type (linear)").requiredOption("--session-id <id>", "External session ID (e.g., Linear session ID)").requiredOption("--claude-session-id <id>", "Claude SDK session ID to resume").requiredOption("--prompt <prompt>", "New prompt/user input").option("--callback-url <url>", "Server callback URL for session updates").option("--working-dir <dir>", "Working directory", process.cwd()).action(async (options) => {
497
+ const { platform, sessionId, claudeSessionId, prompt, callbackUrl, workingDir } = options;
498
+ setInterruptFlag(sessionId);
499
+ await new Promise((resolve2) => setTimeout(resolve2, INTERRUPT_WAIT_MS));
500
+ try {
501
+ const agent = createAgent(platform, sessionId);
502
+ const result = await agent.run({
503
+ prompt,
504
+ sessionId: claudeSessionId,
505
+ resumeSession: true,
506
+ forkSession: false,
507
+ cwd: workingDir,
508
+ options: {
509
+ settingSources: ["user", "project"],
510
+ permissionMode: "acceptEdits"
511
+ }
512
+ });
513
+ await reportResult(callbackUrl, sessionId, result);
514
+ console.log(JSON.stringify({
515
+ status: result.error ? "error" : result.interrupted ? "interrupted" : "completed",
516
+ claudeSessionId: result.sessionId,
517
+ result: result.result,
518
+ error: result.error
519
+ }));
520
+ process.exit(result.error ? 1 : 0);
521
+ } catch (error) {
522
+ const errorMessage = error instanceof Error ? error.message : String(error);
523
+ console.error(JSON.stringify({ status: "error", error: errorMessage }));
524
+ process.exit(1);
525
+ }
526
+ });
527
+
528
+ // src/commands/init.ts
529
+ import { Command as Command4 } from "commander";
530
+
531
+ // src/config.ts
532
+ import { cpSync, existsSync as existsSync2, mkdirSync } from "fs";
533
+ import { dirname, resolve, join as join2 } from "path";
534
+ import { fileURLToPath } from "url";
535
+ import { homedir } from "os";
536
+ function getBundledConfigPath() {
537
+ const __filename = fileURLToPath(import.meta.url);
538
+ const __dirname = dirname(__filename);
539
+ return resolve(__dirname, "claude-config");
540
+ }
541
+ function getUserClaudeDir() {
542
+ return join2(homedir(), ".claude");
543
+ }
544
+ function installClaudeConfig() {
545
+ const bundledPath = getBundledConfigPath();
546
+ const userClaudeDir = getUserClaudeDir();
547
+ if (!existsSync2(bundledPath)) {
548
+ console.warn("Warning: Bundled claude-config not found. Skipping config installation.");
549
+ return;
550
+ }
551
+ if (!existsSync2(userClaudeDir)) {
552
+ mkdirSync(userClaudeDir, { recursive: true });
553
+ }
554
+ cpSync(bundledPath, userClaudeDir, { recursive: true, force: true });
555
+ console.log(`Installed Claude configs to ${userClaudeDir}`);
556
+ }
557
+
558
+ // src/commands/init.ts
559
+ var initCommand = new Command4("init").description("Install Claude configs to ~/.claude/ (MCP servers, plugins, skills)").action(() => {
560
+ console.log("Initializing Claude configs...");
561
+ installClaudeConfig();
562
+ console.log("Done. Claude Agent SDK will now use bundled configs.");
563
+ });
564
+
565
+ // src/index.ts
566
+ var program = new Command5();
567
+ program.name("claude-sandbox-agent").description("CLI for running Claude agents in Vercel sandboxes").version("0.1.0");
568
+ program.addCommand(initCommand);
569
+ program.addCommand(start_default);
570
+ program.addCommand(stopCommand);
571
+ program.addCommand(resumeCommand);
572
+ program.parse();
573
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/start.ts","../src/linear/agent.ts","../src/agent.ts","../src/factory.ts","../src/callback.ts","../src/commands/stop.ts","../src/commands/resume.ts","../src/commands/init.ts","../src/config.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { Command } from 'commander';\nimport startCommand from './commands/start';\nimport { stopCommand } from './commands/stop';\nimport { resumeCommand } from './commands/resume';\nimport { initCommand } from './commands/init';\n\nconst program = new Command();\n\nprogram\n .name('claude-sandbox-agent')\n .description('CLI for running Claude agents in Vercel sandboxes')\n .version('0.1.0');\n\nprogram.addCommand(initCommand);\nprogram.addCommand(startCommand);\nprogram.addCommand(stopCommand);\nprogram.addCommand(resumeCommand);\n\nprogram.parse();\n","import { Command } from 'commander';\nimport { createAgent, type Platform } from '@/factory';\nimport { reportResult } from '@/callback';\n\nconst startCommand = new Command('start')\n .description('Start a new agent session')\n .requiredOption('--platform <platform>', 'Platform type (linear)')\n .requiredOption('--session-id <id>', 'External session ID (e.g., Linear session ID)')\n .requiredOption('--prompt <prompt>', 'Initial prompt for the agent')\n .option('--callback-url <url>', 'Server callback URL for session updates')\n .option('--working-dir <dir>', 'Working directory', process.cwd())\n .action(async (options) => {\n const { platform, sessionId, prompt, callbackUrl, workingDir } = options;\n\n try {\n const agent = createAgent(platform as Platform, sessionId);\n\n const result = await agent.run({\n prompt,\n cwd: workingDir,\n options: {\n settingSources: ['user', 'project'],\n permissionMode: 'bypassPermissions',\n },\n });\n\n await reportResult(callbackUrl, sessionId, result);\n\n console.log(JSON.stringify({\n status: result.error ? 'error' : (result.interrupted ? 'interrupted' : 'completed'),\n claudeSessionId: result.sessionId,\n result: result.result,\n error: result.error,\n }));\n\n process.exit(result.error ? 1 : 0);\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(JSON.stringify({ status: 'error', error: errorMessage }));\n process.exit(1);\n }\n });\n\nexport default startCommand;\n","import { LinearClient } from '@linear/sdk';\nimport type { SDKResultMessage } from '@anthropic-ai/claude-agent-sdk';\nimport {\n Agent,\n type PlanStep,\n type TextBlock,\n type ToolUseBlock\n} from '@/agent';\n\n/**\n * LinearAgent configuration\n */\nexport interface LinearAgentConfig {\n linearAccessToken: string;\n linearSessionId: string;\n}\n\n/**\n * Linear activity types\n */\nenum LinearActivityType {\n\tThought = 'thought',\n\tAction = 'action',\n\tFinal = 'final',\n\tError = 'error',\n\tAwaitingInput = 'awaiting_input',\n}\n/**\n * LinearAgent\n *\n * Extends Agent to emit events as Linear activities.\n * Overrides event methods to map to Linear's activity system.\n */\nexport class LinearAgent extends Agent {\n private linearClient: LinearClient;\n private linearSessionId: string;\n private lastThoughtTime = 0;\n private thoughtDebounceMs = 1000; // Debounce thoughts to avoid spam\n\n constructor(config: LinearAgentConfig) {\n super(config.linearSessionId);\n this.linearClient = new LinearClient({ accessToken: config.linearAccessToken });\n this.linearSessionId = config.linearSessionId;\n }\n\n // ============================================\n // Event method implementations\n // ============================================\n\n /**\n * Called when agent starts\n */\n protected async onStart(): Promise<void> {\n await this.sendActivity(LinearActivityType.Thought, 'Starting work...', true);\n }\n\n /**\n * Called when agent is thinking/reasoning\n * Sends as ephemeral thought activity (debounced)\n */\n protected async onThinking(block: TextBlock): Promise<void> {\n const now = Date.now();\n\n // Debounce thoughts to avoid spamming Linear\n if (now - this.lastThoughtTime < this.thoughtDebounceMs) {\n return;\n }\n\n this.lastThoughtTime = now;\n\n const content = block.text;\n\n // Skip very short thoughts\n if (content.length < 20) {\n return;\n }\n\n // Truncate long thoughts\n const truncated = content.length > 500\n ? content.substring(0, 500) + '...'\n : content;\n\n await this.sendActivity(LinearActivityType.Thought, truncated, true);\n }\n\n /**\n * Called when agent uses a tool\n * Sends as action activity\n */\n protected async onToolUse(block: ToolUseBlock): Promise<void> {\n const description = this.formatToolDescription(block);\n await this.sendActivity(LinearActivityType.Action, description, false);\n }\n\n /**\n * Called when agent updates its plan\n * Maps to Linear session plan\n */\n protected async onPlanUpdate(steps: PlanStep[]): Promise<void> {\n if (steps.length === 0) return;\n\n // Map to Linear's plan format\n const linearSteps = steps.map(step => ({\n content: step.content,\n status: this.mapStatusToLinear(step.status),\n }));\n\n try {\n await this.linearClient.updateAgentSession(this.linearSessionId, {\n plan: linearSteps,\n });\n } catch (error) {\n console.error('Failed to update Linear plan:', error);\n }\n }\n\n /**\n * Called when agent completes\n * Sends as final activity\n */\n protected async onComplete(message: SDKResultMessage): Promise<void> {\n const text = message.subtype === 'success' && message.result\n ? message.result\n : 'Task completed successfully.';\n await this.sendActivity(LinearActivityType.Final, text, false);\n }\n\n /**\n * Called when agent errors\n * Sends as error activity\n */\n protected async onError(error: Error): Promise<void> {\n await this.sendActivity(LinearActivityType.Error, `Error: ${error.message}`, false);\n }\n\n\tprotected async onStop(): Promise<void> {\n\t\tawait this.sendActivity(LinearActivityType.Final, 'Session stopped', false);\n\t}\n\n // ============================================\n // Helper methods\n // ============================================\n\n /**\n * Send activity to Linear\n */\n private async sendActivity(\n type: LinearActivityType,\n body: string,\n ephemeral: boolean\n ): Promise<void> {\n try {\n await this.linearClient.createAgentActivity({\n agentSessionId: this.linearSessionId,\n content: { type, body },\n ephemeral,\n });\n } catch (error) {\n console.error('Failed to send Linear activity:', error);\n }\n }\n\n /**\n * Format tool use description for display\n */\n private formatToolDescription(block: ToolUseBlock): string {\n const { name, input } = block;\n const params = input as Record<string, unknown>;\n\n switch (name) {\n case 'Write':\n return `Creating file: ${params.file_path}`;\n\n case 'Edit':\n return `Editing: ${params.file_path}`;\n\n case 'Read':\n return `Reading: ${params.file_path}`;\n\n case 'Bash': {\n const cmd = String(params.command ?? '');\n const desc = params.description ?? cmd.substring(0, 50);\n return `Running: ${desc}`;\n }\n\n case 'Grep':\n return `Searching for: ${params.pattern}`;\n\n case 'Glob':\n return `Finding files: ${params.pattern}`;\n\n case 'Task':\n return `Delegating to: ${params.subagent_type ?? 'subagent'}`;\n\n case 'Skill':\n return `Using skill: ${params.skill}`;\n\n default:\n return `Using ${name}`;\n }\n }\n\n /**\n * Map internal status to Linear plan status\n */\n private mapStatusToLinear(\n status: PlanStep['status']\n ): 'pending' | 'inProgress' | 'completed' | 'canceled' {\n switch (status) {\n case 'in_progress':\n return 'inProgress';\n case 'completed':\n return 'completed';\n case 'canceled':\n return 'canceled';\n case 'pending':\n default:\n return 'pending';\n }\n }\n}\n\n\nexport const createLinearAgent = (sessionId: string) => {\n\tconst linearAccessToken = process.env.LINEAR_ACCESS_TOKEN;\n\tif (!linearAccessToken) {\n\t\tthrow new Error('Linear access token is missing');\n\t}\n\treturn new LinearAgent({ linearAccessToken, linearSessionId: sessionId })\n}\n","import * as fs from 'fs';\nimport * as path from 'path';\nimport {\n query,\n type Query,\n type Options,\n type SDKAssistantMessage,\n type SDKResultMessage,\n type SDKSystemMessage,\n} from '@anthropic-ai/claude-agent-sdk';\nimport type { TextBlock, ToolUseBlock } from '@anthropic-ai/sdk/resources/messages';\n\n/**\n * Plan step for tracking progress\n */\nexport interface PlanStep {\n content: string;\n status: 'pending' | 'in_progress' | 'completed' | 'canceled';\n}\n\n/**\n * Agent run options\n */\nexport interface AgentRunOptions {\n prompt: string;\n sessionId?: string; // SDK session ID for resumption\n resumeSession?: boolean; // Whether to resume existing session\n forkSession?: boolean; // Whether to fork when resuming\n cwd?: string; // Working directory\n options?: Partial<Options>; // Additional SDK options\n}\n\n/**\n * Agent run result\n */\nexport interface AgentRunResult {\n sessionId: string;\n result?: string;\n error?: string;\n interrupted?: boolean;\n}\n\n// ============================================\n// Interrupt file utilities\n// ============================================\n\n/**\n * Get the path to the interrupt flag file for a session\n */\nexport function getInterruptFilePath(externalSessionId: string): string {\n return path.join('/tmp', `agent-${externalSessionId}.interrupt`);\n}\n\n/**\n * Check if the interrupt flag is set\n */\nexport function checkInterruptFlag(externalSessionId: string): boolean {\n const filePath = getInterruptFilePath(externalSessionId);\n try {\n if (fs.existsSync(filePath)) {\n const content = fs.readFileSync(filePath, 'utf-8').trim();\n return content === 'true';\n }\n return false;\n } catch {\n return false;\n }\n}\n\n/**\n * Set the interrupt flag\n */\nexport function setInterruptFlag(externalSessionId: string): void {\n const filePath = getInterruptFilePath(externalSessionId);\n fs.writeFileSync(filePath, 'true', 'utf-8');\n}\n\n/**\n * Clear the interrupt flag\n */\nexport function clearInterruptFlag(externalSessionId: string): void {\n const filePath = getInterruptFilePath(externalSessionId);\n try {\n if (fs.existsSync(filePath)) {\n fs.unlinkSync(filePath);\n }\n } catch {\n // Ignore errors\n }\n}\n\n/**\n * Base Agent class\n *\n * Runs Claude Agent SDK and calls event methods for each message type.\n * Extend this class and override the event methods you need to integrate\n * with different platforms (Linear, Slack, etc.)\n */\nexport abstract class Agent {\n protected currentSessionId?: string;\n protected isRunning = false;\n protected externalSessionId: string;\n private activeQuery?: Query;\n\n constructor(externalSessionId: string) {\n this.externalSessionId = externalSessionId;\n }\n\n // ============================================\n // Event methods - Override in subclasses\n // ============================================\n\n /**\n * Called when agent starts processing\n */\n protected async onStart(): Promise<void> {\n // Override in subclasses\n }\n\n /**\n * Called when agent emits a thinking/reasoning text\n */\n protected async onThinking(block: TextBlock): Promise<void> {\n // Override in subclasses\n }\n\n /**\n * Called when agent uses a tool\n */\n protected async onToolUse(block: ToolUseBlock): Promise<void> {\n // Override in subclasses\n }\n\n /**\n * Called when agent updates its plan (via TodoWrite)\n */\n protected async onPlanUpdate(todos: PlanStep[]): Promise<void> {\n // Override in subclasses\n }\n\n /**\n * Called when agent completes successfully\n */\n protected async onComplete(message: SDKResultMessage): Promise<void> {\n // Override in subclasses\n }\n\n /**\n * Called when agent encounters an error\n */\n protected async onError(error: Error): Promise<void> {\n // Override in subclasses\n }\n\n /**\n * Called when agent is stopped via stop command\n */\n protected async onStop(): Promise<void> {\n // Override in subclasses\n }\n\n // ============================================\n // Main execution logic\n // ============================================\n\n /**\n * Run the agent with the given prompt\n */\n public async run(runOptions: AgentRunOptions): Promise<AgentRunResult> {\n const {\n prompt,\n sessionId,\n resumeSession = false,\n forkSession = false,\n cwd = process.cwd(),\n options: additionalOptions = {},\n } = runOptions;\n\n this.isRunning = true;\n let resultSessionId = sessionId ?? '';\n let finalResult: string | undefined;\n let wasInterrupted = false;\n\n // Clear any existing interrupt flag before starting\n clearInterruptFlag(this.externalSessionId);\n\n try {\n await this.onStart();\n\n // Build SDK options\n const sdkOptions: Options = {\n settingSources: ['user', 'project'],\n permissionMode: 'acceptEdits',\n cwd,\n ...additionalOptions,\n };\n\n // Add resume options if resuming\n if (resumeSession && sessionId) {\n sdkOptions.resume = sessionId;\n sdkOptions.forkSession = forkSession;\n }\n\n // Run the agent\n this.activeQuery = query({ prompt, options: sdkOptions });\n for await (const message of this.activeQuery) {\n // Check for interrupt flag\n if (checkInterruptFlag(this.externalSessionId)) {\n console.log('Interrupt flag detected, stopping agent...');\n await this.activeQuery.interrupt();\n wasInterrupted = true;\n break;\n }\n\n // Capture session ID from init message\n if (message.type === 'system') {\n const sysMsg = message as SDKSystemMessage;\n if (sysMsg.subtype === 'init') {\n resultSessionId = sysMsg.session_id;\n this.currentSessionId = sysMsg.session_id;\n }\n }\n\n // Process assistant messages\n if (message.type === 'assistant') {\n await this.processAssistantMessage(message as SDKAssistantMessage);\n }\n\n // Handle result message\n if (message.type === 'result') {\n const resultMsg = message as SDKResultMessage;\n if (resultMsg.subtype === 'success' && resultMsg.result) {\n finalResult = resultMsg.result;\n }\n await this.onComplete(resultMsg);\n }\n }\n\n return {\n sessionId: resultSessionId,\n result: finalResult,\n interrupted: wasInterrupted,\n };\n\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n await this.onError(err);\n\n return {\n sessionId: resultSessionId,\n error: err.message,\n interrupted: wasInterrupted,\n };\n\n } finally {\n this.isRunning = false;\n this.activeQuery = undefined;\n // Clear interrupt flag after we're done\n clearInterruptFlag(this.externalSessionId);\n }\n }\n\n /**\n * Interrupt the currently running agent\n * Returns true if an interrupt was sent, false if no active query\n */\n public async interrupt(): Promise<boolean> {\n if (this.activeQuery) {\n await this.activeQuery.interrupt();\n return true;\n }\n return false;\n }\n\n /**\n * Stop the agent session\n * Sets interrupt flag and calls onStop callback\n */\n public async stop(): Promise<void> {\n setInterruptFlag(this.externalSessionId);\n await this.onStop();\n }\n\n /**\n * Process an assistant message and call appropriate event methods\n */\n private async processAssistantMessage(message: SDKAssistantMessage): Promise<void> {\n const content = message.message.content;\n\n for (const block of content) {\n // Text block -> onThinking\n if (block.type === 'text') {\n await this.onThinking(block);\n }\n\n // Tool use block -> onToolUse or onPlanUpdate\n if (block.type === 'tool_use') {\n // Handle TodoWrite specially - emit as plan update\n if (block.name === 'TodoWrite') {\n const input = block.input as { todos?: PlanStep[] };\n if (input.todos) {\n await this.onPlanUpdate(input.todos);\n }\n } else {\n await this.onToolUse(block);\n }\n }\n }\n }\n\n /**\n * Check if agent is currently running\n */\n public isActive(): boolean {\n return this.isRunning;\n }\n\n /**\n * Get current session ID\n */\n public getSessionId(): string | undefined {\n return this.currentSessionId;\n }\n}\n\nexport { TextBlock, ToolUseBlock }\n","import { Agent } from './agent';\nimport {createLinearAgent, LinearAgent} from './linear/agent';\n\n/**\n * Supported platforms\n */\nexport type Platform = 'linear';\n\n/**\n * Create an agent for the specified platform\n */\nexport function createAgent(platform: Platform, sessionId: string): Agent {\n switch (platform) {\n case 'linear':\n\t\t\treturn createLinearAgent(sessionId)\n default:\n throw new Error(`Unsupported platform: ${platform}`);\n }\n}\n","/**\n * HTTP callback client for updating session state on the server\n */\n\nexport interface SessionUpdate {\n externalSessionId: string;\n claudeSessionId?: string;\n state: 'running' | 'completed' | 'error';\n error?: string;\n}\n\n/**\n * Send a session update to the server callback endpoint\n */\nexport async function sendSessionUpdate(\n callbackUrl: string,\n callbackSecret: string,\n update: SessionUpdate\n): Promise<void> {\n try {\n const response = await fetch(callbackUrl, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Authorization': `Bearer ${callbackSecret}`,\n },\n body: JSON.stringify(update),\n });\n\n if (!response.ok) {\n console.error(`Callback failed: ${response.status} ${response.statusText}`);\n }\n } catch (error) {\n console.error('Failed to send session update:', error);\n }\n}\n\n/**\n * Update session as running with Claude session ID\n */\nexport async function reportRunning(\n callbackUrl: string,\n callbackSecret: string,\n externalSessionId: string,\n claudeSessionId: string\n): Promise<void> {\n await sendSessionUpdate(callbackUrl, callbackSecret, {\n externalSessionId,\n claudeSessionId,\n state: 'running',\n });\n}\n\n/**\n * Update session as completed\n */\nexport async function reportCompleted(\n callbackUrl: string,\n callbackSecret: string,\n externalSessionId: string,\n claudeSessionId: string\n): Promise<void> {\n await sendSessionUpdate(callbackUrl, callbackSecret, {\n externalSessionId,\n claudeSessionId,\n state: 'completed',\n });\n}\n\n/**\n * Update session as errored\n */\nexport async function reportError(\n callbackUrl: string,\n callbackSecret: string,\n externalSessionId: string,\n error: string\n): Promise<void> {\n await sendSessionUpdate(callbackUrl, callbackSecret, {\n externalSessionId,\n state: 'error',\n error,\n });\n}\n\n/**\n * Agent run result for reporting\n */\nexport interface AgentResult {\n sessionId: string;\n result?: string;\n error?: string;\n interrupted?: boolean;\n}\n\n/**\n * Report agent result to callback server\n * Handles running, completed, error, and interrupted states\n */\nexport async function reportResult(\n callbackUrl: string | undefined,\n externalSessionId: string,\n result: AgentResult\n): Promise<void> {\n const callbackSecret = process.env.CLAUDE_LINEAR_CALLBACK_SECRET;\n\n if (!callbackUrl || !callbackSecret) {\n return;\n }\n\n // Report running status with session ID\n if (result.sessionId) {\n await reportRunning(callbackUrl, callbackSecret, externalSessionId, result.sessionId);\n }\n\n // Report final status\n if (result.error) {\n await reportError(callbackUrl, callbackSecret, externalSessionId, result.error);\n } else if (!result.interrupted) {\n // Only report completed if not interrupted\n await reportCompleted(callbackUrl, callbackSecret, externalSessionId, result.sessionId);\n }\n // If interrupted, don't report - resume will handle it\n}\n","import { Command } from 'commander';\nimport { createAgent, type Platform } from '@/factory';\n\nexport const stopCommand = new Command('stop')\n .description('Stop an agent session gracefully')\n .requiredOption('--platform <platform>', 'Platform type (linear)')\n .requiredOption('--session-id <id>', 'External session ID (e.g., Linear session ID)')\n .action(async (options) => {\n const { platform, sessionId } = options;\n\n try {\n const agent = createAgent(platform as Platform, sessionId);\n await agent.stop();\n\n console.log(JSON.stringify({\n status: 'stopped',\n sessionId,\n }));\n process.exit(0);\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(JSON.stringify({\n status: 'error',\n error: errorMessage,\n }));\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { createAgent, type Platform } from '@/factory';\nimport { setInterruptFlag } from '@/agent';\nimport { reportResult } from '@/callback';\n\nconst INTERRUPT_WAIT_MS = 500;\n\nexport const resumeCommand = new Command('resume')\n .description('Resume an existing agent session')\n .requiredOption('--platform <platform>', 'Platform type (linear)')\n .requiredOption('--session-id <id>', 'External session ID (e.g., Linear session ID)')\n .requiredOption('--claude-session-id <id>', 'Claude SDK session ID to resume')\n .requiredOption('--prompt <prompt>', 'New prompt/user input')\n .option('--callback-url <url>', 'Server callback URL for session updates')\n .option('--working-dir <dir>', 'Working directory', process.cwd())\n .action(async (options) => {\n const { platform, sessionId, claudeSessionId, prompt, callbackUrl, workingDir } = options;\n\n // Set interrupt flag in case another agent is running\n setInterruptFlag(sessionId);\n await new Promise(resolve => setTimeout(resolve, INTERRUPT_WAIT_MS));\n\n try {\n const agent = createAgent(platform as Platform, sessionId);\n\n const result = await agent.run({\n prompt,\n sessionId: claudeSessionId,\n resumeSession: true,\n forkSession: false,\n cwd: workingDir,\n options: {\n settingSources: ['user', 'project'],\n permissionMode: 'acceptEdits',\n },\n });\n\n await reportResult(callbackUrl, sessionId, result);\n\n console.log(JSON.stringify({\n status: result.error ? 'error' : (result.interrupted ? 'interrupted' : 'completed'),\n claudeSessionId: result.sessionId,\n result: result.result,\n error: result.error,\n }));\n\n process.exit(result.error ? 1 : 0);\n\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n console.error(JSON.stringify({ status: 'error', error: errorMessage }));\n process.exit(1);\n }\n });\n","import { Command } from 'commander';\nimport { installClaudeConfig } from '../config';\n\nexport const initCommand = new Command('init')\n .description('Install Claude configs to ~/.claude/ (MCP servers, plugins, skills)')\n .action(() => {\n console.log('Initializing Claude configs...');\n installClaudeConfig();\n console.log('Done. Claude Agent SDK will now use bundled configs.');\n });","import { cpSync, existsSync, mkdirSync } from 'fs';\nimport { dirname, resolve, join } from 'path';\nimport { fileURLToPath } from 'url';\nimport { homedir } from 'os';\n\n/**\n * Get the path to the bundled claude-config directory\n */\nfunction getBundledConfigPath(): string {\n const __filename = fileURLToPath(import.meta.url);\n const __dirname = dirname(__filename);\n return resolve(__dirname, 'claude-config');\n}\n\n/**\n * Get the user's ~/.claude directory path\n */\nfunction getUserClaudeDir(): string {\n return join(homedir(), '.claude');\n}\n\n/**\n * Install bundled Claude configs to ~/.claude/\n *\n * This copies:\n * - settings.json (plugins, env vars)\n * - .mcp.json (MCP server configurations)\n * - skills/ (custom skills)\n * - agents/ (custom agents, if any)\n *\n * Files are merged/overwritten - existing user configs will be replaced.\n */\nexport function installClaudeConfig(): void {\n const bundledPath = getBundledConfigPath();\n const userClaudeDir = getUserClaudeDir();\n\n if (!existsSync(bundledPath)) {\n console.warn('Warning: Bundled claude-config not found. Skipping config installation.');\n return;\n }\n\n // Ensure ~/.claude exists\n if (!existsSync(userClaudeDir)) {\n mkdirSync(userClaudeDir, { recursive: true });\n }\n\n // Copy bundled configs to user directory\n cpSync(bundledPath, userClaudeDir, { recursive: true, force: true });\n\n console.log(`Installed Claude configs to ${userClaudeDir}`);\n}\n\n/**\n * Check if Claude configs are installed\n */\nexport function isConfigInstalled(): boolean {\n const userClaudeDir = getUserClaudeDir();\n const settingsPath = join(userClaudeDir, 'settings.json');\n return existsSync(settingsPath);\n}"],"mappings":"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","names":["Command","Command","Command","Command","Command","resolve","Command","existsSync","join","Command","Command"]}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "claude-sandbox-agent",
3
+ "version": "0.1.0",
4
+ "description": "CLI for running Claude agents in Vercel sandboxes",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "types": "./dist/index.d.ts",
8
+ "bin": {
9
+ "claude-sandbox-agent": "./dist/index.js"
10
+ },
11
+ "files": [
12
+ "dist"
13
+ ],
14
+ "keywords": [
15
+ "claude",
16
+ "agent",
17
+ "linear",
18
+ "sandbox",
19
+ "cli"
20
+ ],
21
+ "author": "",
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "@anthropic-ai/claude-agent-sdk": "^0.1.76",
25
+ "@anthropic-ai/sdk": "^0.71.2",
26
+ "@linear/sdk": "^68.1.0",
27
+ "commander": "^12.1.0"
28
+ },
29
+ "devDependencies": {
30
+ "@types/node": "^22.0.0",
31
+ "tsup": "^8.4.0",
32
+ "typescript": "^5.9.3"
33
+ },
34
+ "engines": {
35
+ "node": ">=20.0.0"
36
+ },
37
+ "scripts": {
38
+ "build": "tsup",
39
+ "dev": "tsup --watch",
40
+ "typecheck": "tsc --noEmit"
41
+ }
42
+ }