claude-sandbox-agent 0.2.4 → 0.2.6

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,11 @@
1
+ {
2
+ "name": "claude-linear-agent",
3
+ "version": "0.1.0",
4
+ "description": "Skills and MCP integrations for the Linear AI agent — Linear, GitHub, Notion, and Context7",
5
+ "author": {
6
+ "name": "Matt Aliev"
7
+ },
8
+ "repository": "https://github.com/mattaliev/claude-linear-agent",
9
+ "license": "MIT",
10
+ "keywords": ["linear", "agent", "mcp", "notion", "github", "context7"]
11
+ }
@@ -0,0 +1,140 @@
1
+ ---
2
+ name: Doc Drift Check
3
+ description: This skill should be used when the user asks to "check docs for drift", "compare code changes against documentation", "review docs after PR", "find outdated documentation", "check if docs match the code", "verify documentation is up to date", or after completing a pull request review to verify documentation accuracy. Analyzes code changes against project docs, CLAUDE.md, database schema, Notion module pages, and Notion processes to catch mismatches.
4
+ ---
5
+
6
+ # Doc Drift Check
7
+
8
+ Analyze code changes from a PR or issue against all project documentation — both in the repository and in Notion — to catch mismatches that would lead to stale docs. Write a severity-categorized comment to the Linear issue only when meaningful drift is found.
9
+
10
+ ## When to Use
11
+
12
+ Invoke manually after reviewing a pull request or completing an issue review. Skip for trivial changes (typo fixes, formatting, dependency bumps) where doc drift is impossible.
13
+
14
+ ## Workflow
15
+
16
+ ### 1. Gather Context
17
+
18
+ Collect three inputs before analysis:
19
+
20
+ **Code changes** — Get the diff for the issue's PR:
21
+ - Use GitHub MCP to read the PR diff
22
+ - Note which files changed and the nature of changes (new files, modified APIs, removed features, config changes, model changes, service changes)
23
+
24
+ **Linear issue** — Read the issue description and metadata:
25
+ - Issue title, description, and acceptance criteria
26
+ - Team identifier (determines which Notion workspace to check):
27
+ - `KPL-` → Platform
28
+ - `KPE-` → Personal
29
+ - `KBU-` → Business
30
+ - Links to Notion pages or external docs in the description
31
+
32
+ **Repository documentation** — Read relevant local docs:
33
+ - `docs/` directory — scan for files related to changed code areas
34
+ - `CLAUDE.md` — project overview, architecture, env vars, structure
35
+ - Database schema files — check if schema changes are reflected
36
+
37
+ ### 2. Identify Relevant Notion Documentation
38
+
39
+ Based on the team identifier from the Linear issue, fetch the corresponding Product Development page in Notion. These pages contain module documentation, processes, and feature documents for each team.
40
+
41
+ **Team → Notion Product Development page mapping:**
42
+
43
+ | Team Prefix | Team | Notion Page ID |
44
+ |---|---|---|
45
+ | `KPL-` | Platform | `24c80383e1518012a3c2c410588782d5` |
46
+ | `KPE-` | Personal | `23a80383e15180ae91bae32b407ebaf9` |
47
+ | `KBU-` | Business | `24c80383e15180e19e78cfca4b49fe66` |
48
+
49
+ **Scan the Product Development page** for the appropriate team:
50
+ 1. Fetch the page and scan its child pages
51
+ 2. Identify module pages that relate to the changed code area
52
+ 3. Read those module pages — they describe models, services, and APIs for each module
53
+
54
+ **Check the Processes database** (`252cc951ac514d86ad3b6d9fc689409c`):
55
+ 1. The Processes database has a "Модули" relation linking processes to modules
56
+ 2. If code changes affect a module, find linked processes
57
+ 3. Check if process descriptions still match the implementation
58
+
59
+ ### 3. Analyze for Mismatches
60
+
61
+ Compare code changes against each relevant documentation source. Look for:
62
+
63
+ - **Model drift** — Code adds/removes/renames model fields, but module documentation in Notion still describes the old schema
64
+ - **Service drift** — New services added or service logic changed, but module page doesn't list them
65
+ - **API drift** — Endpoints added/changed/removed, but docs still reference old API
66
+ - **Process drift** — Implementation changes how a process works, but the process page in Notion doesn't reflect it
67
+ - **Missing documentation** — New module, feature, or config with no corresponding docs
68
+ - **Stale references** — Docs reference removed code, old file paths, or deprecated models
69
+ - **Issue description mismatch** — What was implemented differs from what the issue describes
70
+ - **Structural drift** — File/directory structure changed but project structure docs not updated
71
+ - **Environment drift** — New env vars, config values, or dependencies not documented
72
+
73
+ For detailed severity classification examples, consult `references/severity-guide.md`.
74
+
75
+ ### 4. Decision Gate
76
+
77
+ After analysis, decide whether to comment:
78
+
79
+ - **No mismatches found** → Do nothing. Do not write a "no issues found" comment.
80
+ - **Only trivial mismatches** (e.g., a slightly outdated example that doesn't mislead) → Skip.
81
+ - **Meaningful mismatches** → Proceed to write comment.
82
+
83
+ The bar for commenting: would someone reading the docs be misled or confused by the current state? If yes, comment. If not, skip.
84
+
85
+ ### 5. Write Linear Comment
86
+
87
+ Post a comment on the Linear issue using this format:
88
+
89
+ ```
90
+ 📋 Doc Drift Report
91
+
92
+ [1-2 sentence summary of what was found]
93
+
94
+ 🔴 Critical
95
+ - [Notion: Module "Payments" → Models section] — Code adds TransferFee model but module page doesn't list it
96
+ - [File: `CLAUDE.md` env vars table] — New SYNC_API_KEY env var required but not listed
97
+
98
+ 🟡 Moderate
99
+ - [Notion: Process "Customer Onboarding"] — Step 3 now calls ProviderService instead of direct API, process diagram outdated
100
+ - [File: `docs/architecture.md`] — New endpoint POST /api/v2/transfers not documented
101
+
102
+ 🟢 Light
103
+ - [Notion: Module "Crypto" → Services section] — CryptoSigningService renamed to AccessKeyService in code
104
+
105
+ ---
106
+ Suggested actions:
107
+ - Update Notion module page "Payments" with new TransferFee model
108
+ - Add SYNC_API_KEY to CLAUDE.md environment variables table
109
+ - Update process diagram in "Customer Onboarding" process page
110
+ ```
111
+
112
+ **Formatting rules:**
113
+ - Use severity emojis: 🔴 Critical, 🟡 Moderate, 🟢 Light
114
+ - Prefix with source: `[Notion: ...]` or `[File: ...]`
115
+ - Include specific page/section references
116
+ - Include a "Suggested actions" section with concrete fixes
117
+ - Omit empty severity categories
118
+
119
+ ## Severity Classification Quick Reference
120
+
121
+ | Severity | Description |
122
+ |---|---|
123
+ | 🔴 Critical | Model/schema changes undocumented, API changes, env var changes, breaking behavior, architecture shifts — someone would build against wrong assumptions |
124
+ | 🟡 Moderate | New services undocumented, process flow changes, new features without docs, workflow changes — someone would miss important capabilities |
125
+ | 🟢 Light | Renamed entities, outdated examples, minor wording, service method renames — someone might be briefly confused |
126
+
127
+ For detailed examples and edge cases, see `references/severity-guide.md`.
128
+
129
+ ## Tools Used
130
+
131
+ - **GitHub MCP** — read PR diffs and changed files
132
+ - **Linear MCP** — read issue description and team, post comments
133
+ - **Notion MCP** — fetch Product Development pages, module pages, process pages
134
+ - **Read, Grep, Glob** — scan local documentation files in the repository
135
+
136
+ ## Additional Resources
137
+
138
+ ### Reference Files
139
+
140
+ - **`references/severity-guide.md`** — Detailed severity classification with examples, edge cases, and per-source guidance
@@ -0,0 +1,174 @@
1
+ # Severity Classification Guide
2
+
3
+ Detailed guide for categorizing doc drift findings by severity level. Use this when analyzing mismatches between code changes and documentation.
4
+
5
+ ## 🔴 Critical — Would Cause Wrong Assumptions
6
+
7
+ These mismatches would cause someone to build against incorrect assumptions or make wrong decisions.
8
+
9
+ ### Model/Schema Changes
10
+
11
+ - Code adds a new model but the Notion module page doesn't list it
12
+ - Code removes or renames a model field, but the module documentation still references the old field
13
+ - Relationship between models changed (e.g., ForeignKey → ManyToMany) but not reflected in docs
14
+ - New required field added to a model but not documented in the module's models section
15
+
16
+ **Example:**
17
+ > Code adds `AccessKey` model to `andgate_crypto` module, but the Crypto module page in Notion under Platform's Product Development doesn't mention it.
18
+
19
+ ### API/Endpoint Changes
20
+
21
+ - New endpoint added without documentation
22
+ - Endpoint removed but still listed in docs
23
+ - Request/response format changed but docs show old format
24
+ - Authentication requirements changed
25
+
26
+ ### Environment & Configuration
27
+
28
+ - New environment variable required but not in CLAUDE.md or deployment docs
29
+ - Configuration option removed but still documented
30
+ - Default value changed for existing config
31
+
32
+ ### Architecture Changes
33
+
34
+ - New module/app created without corresponding Notion documentation
35
+ - Service dependencies changed (module A now depends on module B, but docs don't show this)
36
+ - Database migration adds/removes tables not reflected in schema docs
37
+
38
+ ---
39
+
40
+ ## 🟡 Moderate — Would Miss Important Capabilities
41
+
42
+ These mismatches would cause someone to miss important features or follow outdated procedures.
43
+
44
+ ### Service Changes
45
+
46
+ - New service class added to a module but module page doesn't list it in the services section
47
+ - Service method signature changed (different params) but process docs reference old signature
48
+ - Service now calls a different external provider but process diagrams show old flow
49
+
50
+ **Example:**
51
+ > Code adds `AccessKeyService` to handle crypto signing, but the Crypto module page doesn't list it under Services.
52
+
53
+ ### Process Flow Changes
54
+
55
+ - Steps in a business process reordered or modified
56
+ - New step added to a process (e.g., new validation step in onboarding)
57
+ - Conditional logic changed (e.g., different handling for B2B vs B2C)
58
+ - Process now has prerequisites that aren't documented
59
+
60
+ **Example:**
61
+ > Customer onboarding now requires provider-specific KYC before account creation, but the process page still shows a single KYC step.
62
+
63
+ ### Feature Documentation Gaps
64
+
65
+ - New feature implemented but no feature document exists
66
+ - Feature behavior changed significantly but feature docs describe old behavior
67
+ - Feature flag added without documentation in relevant places
68
+
69
+ ### Workflow Changes
70
+
71
+ - Webhook handling changed but webhook documentation outdated
72
+ - Background task behavior modified but not reflected in process docs
73
+ - Error handling strategy changed for a module
74
+
75
+ ---
76
+
77
+ ## 🟢 Light — Brief Confusion Only
78
+
79
+ These mismatches would cause someone brief confusion but wouldn't lead to incorrect work.
80
+
81
+ ### Naming/Renaming
82
+
83
+ - Service or utility class renamed but docs use old name
84
+ - File moved to different directory but docs reference old path
85
+ - Variable or constant renamed
86
+
87
+ **Example:**
88
+ > `CryptoSigningService` renamed to `AccessKeyService` in code but Notion module page still says `CryptoSigningService`.
89
+
90
+ ### Outdated Examples
91
+
92
+ - Code example in docs uses old import path
93
+ - Example shows deprecated API usage but functionally equivalent
94
+ - Test examples reference old fixtures
95
+
96
+ ### Minor Wording
97
+
98
+ - Documentation says "will be implemented" for already-implemented features
99
+ - Status markers (TODO, WIP) left in docs for completed work
100
+ - Comments in code reference old Notion page names
101
+
102
+ ---
103
+
104
+ ## Per-Source Analysis Guide
105
+
106
+ ### Notion Module Pages
107
+
108
+ Module pages describe models and services for each module. When checking:
109
+
110
+ 1. **Models section** — Compare listed models against actual Django models in the code
111
+ 2. **Services section** — Compare listed services against actual service classes
112
+ 3. **API section** — Compare listed endpoints against actual URL configs
113
+ 4. **Shared models** — Verify cross-module dependencies are still accurate
114
+ 5. **Dependency graph** — Check if module interdependencies changed
115
+
116
+ ### Notion Processes Database
117
+
118
+ Process pages describe business workflows. When checking:
119
+
120
+ 1. **Process steps** — Do the documented steps match the actual code flow?
121
+ 2. **Prerequisites** — Are process prerequisites still accurate?
122
+ 3. **Provider interactions** — Do provider-specific flows match current implementation?
123
+ 4. **Status transitions** — Do documented state machines match code?
124
+ 5. **Related modules** — Is the "Модули" relation still correct?
125
+
126
+ ### Repository docs/ Directory
127
+
128
+ Local documentation files. When checking:
129
+
130
+ 1. **Architecture docs** — Do they reflect current module structure?
131
+ 2. **API docs** — Do endpoint descriptions match implementations?
132
+ 3. **Setup/deployment docs** — Are instructions still accurate?
133
+
134
+ ### CLAUDE.md
135
+
136
+ Project-level documentation. When checking:
137
+
138
+ 1. **Environment variables table** — All required vars listed?
139
+ 2. **Project structure** — Does the tree match actual directory layout?
140
+ 3. **Technology stack** — Any new dependencies or tools?
141
+ 4. **Key documentation links** — Do referenced docs still exist?
142
+
143
+ ### Database Schema
144
+
145
+ Schema documentation. When checking:
146
+
147
+ 1. **Table definitions** — Do they match current migrations?
148
+ 2. **Relationships** — Are FK/M2M relations documented correctly?
149
+ 3. **Indexes** — Any new indexes not mentioned in schema docs?
150
+ 4. **New tables** — Any new migrations creating tables not in schema docs?
151
+
152
+ ---
153
+
154
+ ## Edge Cases
155
+
156
+ ### When NOT to Flag
157
+
158
+ - Code comments that are slightly outdated (not worth a Linear comment)
159
+ - Test file documentation being slightly behind (tests are self-documenting)
160
+ - Third-party library version bumps with no behavior change
161
+ - Formatting-only changes to documentation files
162
+ - Internal refactoring that doesn't change public interfaces or behavior
163
+
164
+ ### When to Escalate to Critical
165
+
166
+ Even if a change seems small, escalate if:
167
+ - It affects an external-facing API that developers build against
168
+ - It changes model fields that other services query
169
+ - It modifies environment variables needed for deployment
170
+ - It alters the behavior described in a process that operations follows
171
+
172
+ ### Multiple Small Issues
173
+
174
+ If there are many Light issues (5+) concentrated in one documentation area, consider grouping them and elevating to a single Moderate finding with a suggestion to do a documentation review for that area.
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import {
18
18
  } from "@anthropic-ai/claude-agent-sdk";
19
19
 
20
20
  // src/config.ts
21
- import { cpSync, existsSync, mkdirSync, writeFileSync } from "fs";
21
+ import { cpSync, existsSync, mkdirSync, renameSync } from "fs";
22
22
  import { dirname, resolve, join } from "path";
23
23
  import { fileURLToPath } from "url";
24
24
  var PLUGIN_DIRNAME = "agent-plugin";
@@ -33,25 +33,21 @@ function getPluginPath(cwd = process.cwd()) {
33
33
  function installClaudeConfig(cwd = process.cwd()) {
34
34
  const bundledPath = getBundledConfigPath();
35
35
  if (!existsSync(bundledPath)) {
36
- console.warn("Warning: Bundled claude-config not found. Skipping config installation.");
36
+ console.warn("Warning: Bundled claude-config not found. Skipping plugin installation.");
37
37
  return;
38
38
  }
39
39
  const pluginDir = getPluginPath(cwd);
40
40
  mkdirSync(pluginDir, { recursive: true });
41
- const manifestDir = join(pluginDir, ".claude-plugin");
42
- mkdirSync(manifestDir, { recursive: true });
43
- writeFileSync(join(manifestDir, "plugin.json"), JSON.stringify({
44
- name: "claude-linear-agent",
45
- version: "1.0.0",
46
- description: "MCP servers and skills for the Linear agent"
47
- }, null, 2));
48
- const skillsSrc = join(bundledPath, "skills");
49
- if (existsSync(skillsSrc)) {
50
- cpSync(skillsSrc, join(pluginDir, "skills"), { recursive: true, force: true });
51
- }
52
- const mcpSrc = join(bundledPath, "mcp.json");
53
- if (existsSync(mcpSrc)) {
54
- cpSync(mcpSrc, join(pluginDir, ".mcp.json"));
41
+ cpSync(bundledPath, pluginDir, { recursive: true, force: true });
42
+ const underscorePlugin = join(pluginDir, "_claude-plugin");
43
+ const dotPlugin = join(pluginDir, ".claude-plugin");
44
+ if (existsSync(underscorePlugin)) {
45
+ renameSync(underscorePlugin, dotPlugin);
46
+ }
47
+ const underscoreMcp = join(pluginDir, "_mcp.json");
48
+ const dotMcp = join(pluginDir, ".mcp.json");
49
+ if (existsSync(underscoreMcp)) {
50
+ renameSync(underscoreMcp, dotMcp);
55
51
  }
56
52
  console.log(`Installed agent plugin to ${pluginDir}`);
57
53
  }
@@ -170,6 +166,8 @@ var Agent = class {
170
166
  sdkOptions.resume = sessionId;
171
167
  sdkOptions.forkSession = forkSession;
172
168
  }
169
+ console.log(`[Agent.run] resume=${resumeSession} | sdkResume=${sdkOptions.resume ?? "none"} | pluginPath=${getPluginPath(cwd)}`);
170
+ console.log(`[Agent.run] prompt=${prompt.substring(0, 300)}...`);
173
171
  this.activeQuery = query({ prompt, options: sdkOptions });
174
172
  for await (const message of this.activeQuery) {
175
173
  if (checkInterruptFlag(this.externalSessionId)) {
@@ -183,6 +181,7 @@ var Agent = class {
183
181
  if (sysMsg.subtype === "init") {
184
182
  resultSessionId = sysMsg.session_id;
185
183
  this.currentSessionId = sysMsg.session_id;
184
+ console.log(`[Agent.run] SDK session initialized: ${sysMsg.session_id}`);
186
185
  }
187
186
  }
188
187
  if (message.type === "assistant") {
@@ -497,6 +496,8 @@ var startCommand = new Command("start").description("Start a new agent session")
497
496
  process.exit(1);
498
497
  }
499
498
  try {
499
+ console.log(`[CLI.start] sessionId=${sessionId} | cwd=${workingDir}`);
500
+ console.log(`[CLI.start] prompt=${prompt.substring(0, 300)}...`);
500
501
  const agent = createAgent(platform, sessionId);
501
502
  const result = await agent.run({
502
503
  prompt,
@@ -552,6 +553,8 @@ var resumeCommand = new Command3("resume").description("Resume an existing agent
552
553
  setInterruptFlag(sessionId);
553
554
  await new Promise((resolve2) => setTimeout(resolve2, INTERRUPT_WAIT_MS));
554
555
  try {
556
+ console.log(`[CLI.resume] sessionId=${sessionId} | claudeSessionId=${claudeSessionId} | cwd=${workingDir}`);
557
+ console.log(`[CLI.resume] prompt=${prompt.substring(0, 300)}...`);
555
558
  const agent = createAgent(platform, sessionId);
556
559
  const result = await agent.run({
557
560
  prompt,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/commands/start.ts","../src/linear/agent.ts","../src/agent.ts","../src/config.ts","../src/factory.ts","../src/callback.ts","../src/commands/stop.ts","../src/commands/resume.ts","../src/commands/init.ts"],"sourcesContent":["import { 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 { LinearClient } from '@linear/sdk';\nimport { createAgent, type Platform } from '@/factory';\nimport { reportResult } from '@/callback';\n\n/**\n * Send activity to Linear for pre-agent logging\n */\nasync function sendLinearActivity(\n sessionId: string,\n type: 'thought' | 'error',\n message: string,\n ephemeral = true\n): Promise<void> {\n const token = process.env.LINEAR_ACCESS_TOKEN;\n if (!token) return;\n\n try {\n const client = new LinearClient({ accessToken: token });\n await client.createAgentActivity({\n agentSessionId: sessionId,\n content: { type, body: message },\n ephemeral,\n });\n } catch {\n // Don't fail if activity sending fails\n }\n}\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 if (!process.env.ANTHROPIC_API_KEY) {\n await sendLinearActivity(sessionId, 'error', 'ANTHROPIC_API_KEY not set', false);\n process.exit(1);\n }\n\n try {\n const agent = createAgent(platform as Platform, sessionId);\n\n const result = await agent.run({\n prompt,\n cwd: workingDir,\n });\n\n if (result.error) {\n await sendLinearActivity(sessionId, 'error', `Agent error: ${result.error}`, false);\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 await sendLinearActivity(sessionId, 'error', `CLI fatal error: ${errorMessage}`, false);\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\nexport interface LinearAgentConfig {\n linearAccessToken: string;\n linearSessionId: string;\n}\n\nenum LinearActivityType {\n\tThought = 'thought',\n\tAction = 'action',\n\tResponse = 'response',\n\tError = 'error',\n\tElicitation = 'elicitation',\n}\n\n/** Tools that indicate exploration/subagent work — always ephemeral */\nconst EPHEMERAL_TOOLS = new Set(['Read', 'Grep', 'Glob', 'WebSearch', 'WebFetch', 'ToolSearch']);\n\nexport class LinearAgent extends Agent {\n private linearClient: LinearClient;\n private linearSessionId: string;\n private lastThoughtTime = 0;\n private thoughtDebounceMs = 1000;\n private isDelegating = false;\n private isCompleted = false;\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 protected async onStart(): Promise<void> {\n await this.sendActivity(LinearActivityType.Thought, 'Starting work...', true);\n }\n\n protected async onThinking(block: TextBlock): Promise<void> {\n if (this.isCompleted) return;\n\n const now = Date.now();\n if (now - this.lastThoughtTime < this.thoughtDebounceMs) return;\n this.lastThoughtTime = now;\n\n const content = block.text;\n if (content.length < 20) return;\n\n const truncated = content.length > 500\n ? content.substring(0, 500) + '...'\n : content;\n\n // Thoughts are always ephemeral\n await this.sendActivity(LinearActivityType.Thought, truncated, true);\n }\n\n protected async onToolUse(block: ToolUseBlock): Promise<void> {\n if (this.isCompleted) return;\n\n const { name } = block;\n\n // Task tool = delegation — mark as delegating\n if (name === 'Task') {\n this.isDelegating = true;\n const subagentType = String((block.input as Record<string, unknown>).subagent_type ?? 'subagent');\n await this.sendActionActivity('Delegating', subagentType, false);\n return;\n }\n\n // Determine if this action should be ephemeral\n const ephemeral = this.isDelegating || EPHEMERAL_TOOLS.has(name);\n\n const { action, parameter } = this.formatToolAction(block);\n await this.sendActionActivity(action, parameter, ephemeral);\n }\n\n protected async onPlanUpdate(steps: PlanStep[]): Promise<void> {\n if (steps.length === 0) return;\n\n // When we get a plan update from the main agent, delegation is over\n this.isDelegating = false;\n\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 protected async onComplete(message: SDKResultMessage): Promise<void> {\n this.isCompleted = true;\n this.isDelegating = false;\n\n const text = message.subtype === 'success' && message.result\n ? message.result\n : 'Task completed successfully.';\n await this.sendActivity(LinearActivityType.Response, text, false);\n }\n\n protected async onError(error: Error): Promise<void> {\n this.isCompleted = true;\n await this.sendActivity(LinearActivityType.Error, `Error: ${error.message}`, false);\n }\n\n\tprotected async onStop(): Promise<void> {\n\t\tthis.isCompleted = true;\n\t\tawait this.sendActivity(LinearActivityType.Response, 'Session stopped', false);\n\t}\n\n // ============================================\n // Helper methods\n // ============================================\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 private async sendActionActivity(\n action: string,\n parameter: string,\n ephemeral: boolean\n ): Promise<void> {\n try {\n await this.linearClient.createAgentActivity({\n agentSessionId: this.linearSessionId,\n content: { type: LinearActivityType.Action, action, parameter },\n ephemeral,\n });\n } catch (error) {\n console.error('Failed to send Linear activity:', error);\n }\n }\n\n private formatToolAction(block: ToolUseBlock): { action: string; parameter: string } {\n const { name, input } = block;\n const params = input as Record<string, unknown>;\n\n switch (name) {\n case 'Write':\n return { action: 'Creating file', parameter: String(params.file_path ?? '') };\n\n case 'Edit':\n return { action: 'Editing file', parameter: String(params.file_path ?? '') };\n\n case 'Read':\n return { action: 'Reading file', parameter: String(params.file_path ?? '') };\n\n case 'Bash': {\n const cmd = String(params.command ?? '');\n return { action: 'Running command', parameter: cmd.length > 80 ? cmd.substring(0, 80) + '...' : cmd };\n }\n\n case 'Grep':\n return { action: 'Searching', parameter: String(params.pattern ?? '') };\n\n case 'Glob':\n return { action: 'Finding files', parameter: String(params.pattern ?? '') };\n\n case 'Task':\n return { action: 'Delegating', parameter: String(params.subagent_type ?? 'subagent') };\n\n case 'Skill':\n return { action: 'Using skill', parameter: String(params.skill ?? '') };\n\n default:\n return { action: name, parameter: JSON.stringify(params).substring(0, 100) };\n }\n }\n\n private mapStatusToLinear(\n status: PlanStep['status']\n ): 'pending' | 'inProgress' | 'completed' | 'canceled' {\n switch (status) {\n case 'in_progress': return 'inProgress';\n case 'completed': return 'completed';\n case 'canceled': return 'canceled';\n case 'pending':\n default: 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\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';\nimport { getPluginPath } from './config.js';\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 // Set env vars before spawning (SDK env option replaces process env)\n process.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS = '1';\n\n // Build SDK options\n const sdkOptions: Options = {\n settingSources: ['project'],\n permissionMode: 'bypassPermissions',\n allowDangerouslySkipPermissions: true,\n plugins: [{ type: 'local', path: getPluginPath(cwd) }],\n\t systemPrompt: {\n\t\t\t\t\tpreset: 'claude_code',\n\t\t type: 'preset',\n\t },\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 { cpSync, existsSync, mkdirSync, writeFileSync } from 'fs';\nimport { dirname, resolve, join } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst PLUGIN_DIRNAME = 'agent-plugin';\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 plugin path relative to a working directory\n */\nexport function getPluginPath(cwd: string = process.cwd()): string {\n return join(cwd, PLUGIN_DIRNAME);\n}\n\n/**\n * Install bundled configs as a Claude Code plugin in the given directory.\n *\n * Creates <cwd>/agent-plugin/ with:\n * - .claude-plugin/plugin.json (manifest)\n * - .mcp.json (MCP server configurations)\n * - skills/ (custom skills)\n *\n * The plugin is then loaded by the SDK via the `plugins` option.\n */\nexport function installClaudeConfig(cwd: string = process.cwd()): void {\n const bundledPath = getBundledConfigPath();\n\n if (!existsSync(bundledPath)) {\n console.warn('Warning: Bundled claude-config not found. Skipping config installation.');\n return;\n }\n\n const pluginDir = getPluginPath(cwd);\n\n // Create plugin directory\n mkdirSync(pluginDir, { recursive: true });\n\n // Create plugin manifest\n const manifestDir = join(pluginDir, '.claude-plugin');\n mkdirSync(manifestDir, { recursive: true });\n writeFileSync(join(manifestDir, 'plugin.json'), JSON.stringify({\n name: 'claude-linear-agent',\n version: '1.0.0',\n description: 'MCP servers and skills for the Linear agent',\n }, null, 2));\n\n // Copy skills\n const skillsSrc = join(bundledPath, 'skills');\n if (existsSync(skillsSrc)) {\n cpSync(skillsSrc, join(pluginDir, 'skills'), { recursive: true, force: true });\n }\n\n // Copy MCP config (stored as mcp.json to survive npm install, rename to .mcp.json)\n const mcpSrc = join(bundledPath, 'mcp.json');\n if (existsSync(mcpSrc)) {\n cpSync(mcpSrc, join(pluginDir, '.mcp.json'));\n }\n\n console.log(`Installed agent plugin to ${pluginDir}`);\n}\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\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 const body = await response.text().catch(() => '');\n console.error(`[callback] Failed: ${response.status} ${response.statusText} - ${body}`);\n }\n } catch (error) {\n console.error('[callback] Failed to send session update:', error);\n }\n}\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\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\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\nexport interface AgentResult {\n sessionId: string;\n result?: string;\n error?: string;\n interrupted?: boolean;\n}\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 await reportCompleted(callbackUrl, callbackSecret, externalSessionId, result.sessionId);\n }\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 });\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 agent plugin (MCP servers, skills)')\n .action(() => {\n installClaudeConfig();\n });"],"mappings":"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","names":["Command","LinearClient","LinearClient","Command","Command","Command","Command","resolve","Command","Command","Command"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/start.ts","../src/linear/agent.ts","../src/agent.ts","../src/config.ts","../src/factory.ts","../src/callback.ts","../src/commands/stop.ts","../src/commands/resume.ts","../src/commands/init.ts"],"sourcesContent":["import { 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 { LinearClient } from '@linear/sdk';\nimport { createAgent, type Platform } from '@/factory';\nimport { reportResult } from '@/callback';\n\n/**\n * Send activity to Linear for pre-agent logging\n */\nasync function sendLinearActivity(\n sessionId: string,\n type: 'thought' | 'error',\n message: string,\n ephemeral = true\n): Promise<void> {\n const token = process.env.LINEAR_ACCESS_TOKEN;\n if (!token) return;\n\n try {\n const client = new LinearClient({ accessToken: token });\n await client.createAgentActivity({\n agentSessionId: sessionId,\n content: { type, body: message },\n ephemeral,\n });\n } catch {\n // Don't fail if activity sending fails\n }\n}\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 if (!process.env.ANTHROPIC_API_KEY) {\n await sendLinearActivity(sessionId, 'error', 'ANTHROPIC_API_KEY not set', false);\n process.exit(1);\n }\n\n try {\n console.log(`[CLI.start] sessionId=${sessionId} | cwd=${workingDir}`);\n console.log(`[CLI.start] prompt=${prompt.substring(0, 300)}...`);\n\n const agent = createAgent(platform as Platform, sessionId);\n\n const result = await agent.run({\n prompt,\n cwd: workingDir,\n });\n\n if (result.error) {\n await sendLinearActivity(sessionId, 'error', `Agent error: ${result.error}`, false);\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 await sendLinearActivity(sessionId, 'error', `CLI fatal error: ${errorMessage}`, false);\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\nexport interface LinearAgentConfig {\n linearAccessToken: string;\n linearSessionId: string;\n}\n\nenum LinearActivityType {\n\tThought = 'thought',\n\tAction = 'action',\n\tResponse = 'response',\n\tError = 'error',\n\tElicitation = 'elicitation',\n}\n\n/** Tools that indicate exploration/subagent work — always ephemeral */\nconst EPHEMERAL_TOOLS = new Set(['Read', 'Grep', 'Glob', 'WebSearch', 'WebFetch', 'ToolSearch']);\n\nexport class LinearAgent extends Agent {\n private linearClient: LinearClient;\n private linearSessionId: string;\n private lastThoughtTime = 0;\n private thoughtDebounceMs = 1000;\n private isDelegating = false;\n private isCompleted = false;\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 protected async onStart(): Promise<void> {\n await this.sendActivity(LinearActivityType.Thought, 'Starting work...', true);\n }\n\n protected async onThinking(block: TextBlock): Promise<void> {\n if (this.isCompleted) return;\n\n const now = Date.now();\n if (now - this.lastThoughtTime < this.thoughtDebounceMs) return;\n this.lastThoughtTime = now;\n\n const content = block.text;\n if (content.length < 20) return;\n\n const truncated = content.length > 500\n ? content.substring(0, 500) + '...'\n : content;\n\n // Thoughts are always ephemeral\n await this.sendActivity(LinearActivityType.Thought, truncated, true);\n }\n\n protected async onToolUse(block: ToolUseBlock): Promise<void> {\n if (this.isCompleted) return;\n\n const { name } = block;\n\n // Task tool = delegation — mark as delegating\n if (name === 'Task') {\n this.isDelegating = true;\n const subagentType = String((block.input as Record<string, unknown>).subagent_type ?? 'subagent');\n await this.sendActionActivity('Delegating', subagentType, false);\n return;\n }\n\n // Determine if this action should be ephemeral\n const ephemeral = this.isDelegating || EPHEMERAL_TOOLS.has(name);\n\n const { action, parameter } = this.formatToolAction(block);\n await this.sendActionActivity(action, parameter, ephemeral);\n }\n\n protected async onPlanUpdate(steps: PlanStep[]): Promise<void> {\n if (steps.length === 0) return;\n\n // When we get a plan update from the main agent, delegation is over\n this.isDelegating = false;\n\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 protected async onComplete(message: SDKResultMessage): Promise<void> {\n this.isCompleted = true;\n this.isDelegating = false;\n\n const text = message.subtype === 'success' && message.result\n ? message.result\n : 'Task completed successfully.';\n await this.sendActivity(LinearActivityType.Response, text, false);\n }\n\n protected async onError(error: Error): Promise<void> {\n this.isCompleted = true;\n await this.sendActivity(LinearActivityType.Error, `Error: ${error.message}`, false);\n }\n\n\tprotected async onStop(): Promise<void> {\n\t\tthis.isCompleted = true;\n\t\tawait this.sendActivity(LinearActivityType.Response, 'Session stopped', false);\n\t}\n\n // ============================================\n // Helper methods\n // ============================================\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 private async sendActionActivity(\n action: string,\n parameter: string,\n ephemeral: boolean\n ): Promise<void> {\n try {\n await this.linearClient.createAgentActivity({\n agentSessionId: this.linearSessionId,\n content: { type: LinearActivityType.Action, action, parameter },\n ephemeral,\n });\n } catch (error) {\n console.error('Failed to send Linear activity:', error);\n }\n }\n\n private formatToolAction(block: ToolUseBlock): { action: string; parameter: string } {\n const { name, input } = block;\n const params = input as Record<string, unknown>;\n\n switch (name) {\n case 'Write':\n return { action: 'Creating file', parameter: String(params.file_path ?? '') };\n\n case 'Edit':\n return { action: 'Editing file', parameter: String(params.file_path ?? '') };\n\n case 'Read':\n return { action: 'Reading file', parameter: String(params.file_path ?? '') };\n\n case 'Bash': {\n const cmd = String(params.command ?? '');\n return { action: 'Running command', parameter: cmd.length > 80 ? cmd.substring(0, 80) + '...' : cmd };\n }\n\n case 'Grep':\n return { action: 'Searching', parameter: String(params.pattern ?? '') };\n\n case 'Glob':\n return { action: 'Finding files', parameter: String(params.pattern ?? '') };\n\n case 'Task':\n return { action: 'Delegating', parameter: String(params.subagent_type ?? 'subagent') };\n\n case 'Skill':\n return { action: 'Using skill', parameter: String(params.skill ?? '') };\n\n default:\n return { action: name, parameter: JSON.stringify(params).substring(0, 100) };\n }\n }\n\n private mapStatusToLinear(\n status: PlanStep['status']\n ): 'pending' | 'inProgress' | 'completed' | 'canceled' {\n switch (status) {\n case 'in_progress': return 'inProgress';\n case 'completed': return 'completed';\n case 'canceled': return 'canceled';\n case 'pending':\n default: 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\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';\nimport { getPluginPath } from './config.js';\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 // Set env vars before spawning (SDK env option replaces process env)\n process.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS = '1';\n\n // Build SDK options\n const sdkOptions: Options = {\n settingSources: ['project'],\n permissionMode: 'bypassPermissions',\n allowDangerouslySkipPermissions: true,\n plugins: [{ type: 'local', path: getPluginPath(cwd) }],\n\t systemPrompt: {\n\t\t\t\t\tpreset: 'claude_code',\n\t\t type: 'preset',\n\t },\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 console.log(`[Agent.run] resume=${resumeSession} | sdkResume=${sdkOptions.resume ?? 'none'} | pluginPath=${getPluginPath(cwd)}`);\n console.log(`[Agent.run] prompt=${prompt.substring(0, 300)}...`);\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 console.log(`[Agent.run] SDK session initialized: ${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 { cpSync, existsSync, mkdirSync, renameSync } from 'fs';\nimport { dirname, resolve, join } from 'path';\nimport { fileURLToPath } from 'url';\n\nconst PLUGIN_DIRNAME = 'agent-plugin';\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 plugin path relative to a working directory\n */\nexport function getPluginPath(cwd: string = process.cwd()): string {\n return join(cwd, PLUGIN_DIRNAME);\n}\n\n/**\n * Install the bundled Claude Code plugin to <cwd>/agent-plugin/.\n *\n * The bundled files use underscores instead of dots (npm strips dotfiles).\n * This function copies them and renames back:\n * _claude-plugin/ → .claude-plugin/\n * _mcp.json → .mcp.json\n * skills/ → skills/ (no rename needed)\n */\nexport function installClaudeConfig(cwd: string = process.cwd()): void {\n const bundledPath = getBundledConfigPath();\n\n if (!existsSync(bundledPath)) {\n console.warn('Warning: Bundled claude-config not found. Skipping plugin installation.');\n return;\n }\n\n const pluginDir = getPluginPath(cwd);\n\n // Copy entire bundled directory\n mkdirSync(pluginDir, { recursive: true });\n cpSync(bundledPath, pluginDir, { recursive: true, force: true });\n\n // Restore dotfiles: _claude-plugin → .claude-plugin\n const underscorePlugin = join(pluginDir, '_claude-plugin');\n const dotPlugin = join(pluginDir, '.claude-plugin');\n if (existsSync(underscorePlugin)) {\n renameSync(underscorePlugin, dotPlugin);\n }\n\n // Restore dotfiles: _mcp.json → .mcp.json\n const underscoreMcp = join(pluginDir, '_mcp.json');\n const dotMcp = join(pluginDir, '.mcp.json');\n if (existsSync(underscoreMcp)) {\n renameSync(underscoreMcp, dotMcp);\n }\n\n console.log(`Installed agent plugin to ${pluginDir}`);\n}\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\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 const body = await response.text().catch(() => '');\n console.error(`[callback] Failed: ${response.status} ${response.statusText} - ${body}`);\n }\n } catch (error) {\n console.error('[callback] Failed to send session update:', error);\n }\n}\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\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\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\nexport interface AgentResult {\n sessionId: string;\n result?: string;\n error?: string;\n interrupted?: boolean;\n}\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 await reportCompleted(callbackUrl, callbackSecret, externalSessionId, result.sessionId);\n }\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 console.log(`[CLI.resume] sessionId=${sessionId} | claudeSessionId=${claudeSessionId} | cwd=${workingDir}`);\n console.log(`[CLI.resume] prompt=${prompt.substring(0, 300)}...`);\n\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 });\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 agent plugin (MCP servers, skills)')\n .action(() => {\n installClaudeConfig();\n });"],"mappings":"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","names":["Command","LinearClient","LinearClient","Command","Command","Command","Command","resolve","Command","Command","Command"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-sandbox-agent",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "CLI for running Claude agents in Vercel sandboxes",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,146 +0,0 @@
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
File without changes