claude-dev-cli 0.5.0__py3-none-any.whl → 0.7.0__py3-none-any.whl
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.
Potentially problematic release.
This version of claude-dev-cli might be problematic. Click here for more details.
- claude_dev_cli/__init__.py +1 -1
- claude_dev_cli/cli.py +568 -10
- claude_dev_cli/template_manager.py +288 -0
- claude_dev_cli/warp_integration.py +243 -0
- claude_dev_cli/workflows.py +340 -0
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.7.0.dist-info}/METADATA +69 -3
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.7.0.dist-info}/RECORD +11 -8
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.7.0.dist-info}/WHEEL +0 -0
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.7.0.dist-info}/entry_points.txt +0 -0
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.7.0.dist-info}/licenses/LICENSE +0 -0
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.7.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
"""Template management for reusable prompts."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
import re
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Dict, List, Optional, Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Template:
|
|
10
|
+
"""Represents a reusable prompt template."""
|
|
11
|
+
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
name: str,
|
|
15
|
+
content: str,
|
|
16
|
+
description: Optional[str] = None,
|
|
17
|
+
variables: Optional[List[str]] = None,
|
|
18
|
+
category: Optional[str] = None,
|
|
19
|
+
builtin: bool = False
|
|
20
|
+
):
|
|
21
|
+
self.name = name
|
|
22
|
+
self.content = content
|
|
23
|
+
self.description = description or ""
|
|
24
|
+
self.variables = variables or self._extract_variables(content)
|
|
25
|
+
self.category = category or "general"
|
|
26
|
+
self.builtin = builtin
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
def _extract_variables(content: str) -> List[str]:
|
|
30
|
+
"""Extract {{variable}} placeholders from content."""
|
|
31
|
+
return list(set(re.findall(r'\{\{(\w+)\}\}', content)))
|
|
32
|
+
|
|
33
|
+
def render(self, **kwargs: str) -> str:
|
|
34
|
+
"""Render template with provided variables."""
|
|
35
|
+
result = self.content
|
|
36
|
+
for var, value in kwargs.items():
|
|
37
|
+
result = result.replace(f'{{{{{var}}}}}', value)
|
|
38
|
+
return result
|
|
39
|
+
|
|
40
|
+
def get_missing_variables(self, **kwargs: str) -> List[str]:
|
|
41
|
+
"""Get list of required variables not provided."""
|
|
42
|
+
return [var for var in self.variables if var not in kwargs]
|
|
43
|
+
|
|
44
|
+
def to_dict(self) -> Dict[str, Any]:
|
|
45
|
+
"""Convert to dictionary for storage."""
|
|
46
|
+
return {
|
|
47
|
+
"name": self.name,
|
|
48
|
+
"content": self.content,
|
|
49
|
+
"description": self.description,
|
|
50
|
+
"variables": self.variables,
|
|
51
|
+
"category": self.category,
|
|
52
|
+
"builtin": self.builtin
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@classmethod
|
|
56
|
+
def from_dict(cls, data: Dict[str, Any]) -> "Template":
|
|
57
|
+
"""Create from dictionary."""
|
|
58
|
+
return cls(
|
|
59
|
+
name=data["name"],
|
|
60
|
+
content=data["content"],
|
|
61
|
+
description=data.get("description", ""),
|
|
62
|
+
variables=data.get("variables", []),
|
|
63
|
+
category=data.get("category", "general"),
|
|
64
|
+
builtin=data.get("builtin", False)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class TemplateManager:
|
|
69
|
+
"""Manages template storage and retrieval."""
|
|
70
|
+
|
|
71
|
+
# Built-in templates
|
|
72
|
+
BUILTIN_TEMPLATES = [
|
|
73
|
+
Template(
|
|
74
|
+
name="code-review",
|
|
75
|
+
content="""Review this code for:
|
|
76
|
+
- Security vulnerabilities
|
|
77
|
+
- Performance issues
|
|
78
|
+
- Best practices
|
|
79
|
+
- Potential bugs
|
|
80
|
+
- Code clarity
|
|
81
|
+
|
|
82
|
+
{{code}}
|
|
83
|
+
|
|
84
|
+
Focus on: {{focus}}""",
|
|
85
|
+
description="Comprehensive code review with customizable focus",
|
|
86
|
+
category="review",
|
|
87
|
+
builtin=True
|
|
88
|
+
),
|
|
89
|
+
Template(
|
|
90
|
+
name="code-review-security",
|
|
91
|
+
content="""Perform a security-focused code review of this code:
|
|
92
|
+
|
|
93
|
+
{{code}}
|
|
94
|
+
|
|
95
|
+
Check for:
|
|
96
|
+
- SQL injection vulnerabilities
|
|
97
|
+
- XSS vulnerabilities
|
|
98
|
+
- Authentication/authorization issues
|
|
99
|
+
- Data validation problems
|
|
100
|
+
- Sensitive data exposure
|
|
101
|
+
- CSRF vulnerabilities""",
|
|
102
|
+
description="Security-focused code review",
|
|
103
|
+
category="review",
|
|
104
|
+
builtin=True
|
|
105
|
+
),
|
|
106
|
+
Template(
|
|
107
|
+
name="test-strategy",
|
|
108
|
+
content="""Generate a comprehensive test strategy for this {{language}} code:
|
|
109
|
+
|
|
110
|
+
{{code}}
|
|
111
|
+
|
|
112
|
+
Include:
|
|
113
|
+
- Unit tests for core functionality
|
|
114
|
+
- Edge cases and error handling
|
|
115
|
+
- Integration test scenarios
|
|
116
|
+
- Mock/stub suggestions
|
|
117
|
+
- Test data examples""",
|
|
118
|
+
description="Generate testing strategy and test cases",
|
|
119
|
+
category="testing",
|
|
120
|
+
builtin=True
|
|
121
|
+
),
|
|
122
|
+
Template(
|
|
123
|
+
name="debug-error",
|
|
124
|
+
content="""Help me debug this error:
|
|
125
|
+
|
|
126
|
+
Error: {{error}}
|
|
127
|
+
|
|
128
|
+
Code context:
|
|
129
|
+
{{code}}
|
|
130
|
+
|
|
131
|
+
Please:
|
|
132
|
+
1. Explain what's causing the error
|
|
133
|
+
2. Suggest fixes with code examples
|
|
134
|
+
3. Explain how to prevent similar errors""",
|
|
135
|
+
description="Debug error with context",
|
|
136
|
+
category="debugging",
|
|
137
|
+
builtin=True
|
|
138
|
+
),
|
|
139
|
+
Template(
|
|
140
|
+
name="optimize-performance",
|
|
141
|
+
content="""Analyze this code for performance optimization:
|
|
142
|
+
|
|
143
|
+
{{code}}
|
|
144
|
+
|
|
145
|
+
Consider:
|
|
146
|
+
- Time complexity improvements
|
|
147
|
+
- Memory usage optimization
|
|
148
|
+
- Algorithm efficiency
|
|
149
|
+
- Database query optimization (if applicable)
|
|
150
|
+
- Caching opportunities
|
|
151
|
+
|
|
152
|
+
Provide specific code improvements.""",
|
|
153
|
+
description="Performance optimization analysis",
|
|
154
|
+
category="optimization",
|
|
155
|
+
builtin=True
|
|
156
|
+
),
|
|
157
|
+
Template(
|
|
158
|
+
name="refactor-clean",
|
|
159
|
+
content="""Refactor this code to improve:
|
|
160
|
+
- Readability
|
|
161
|
+
- Maintainability
|
|
162
|
+
- Code organization
|
|
163
|
+
- Naming conventions
|
|
164
|
+
- {{language}} idioms
|
|
165
|
+
|
|
166
|
+
{{code}}
|
|
167
|
+
|
|
168
|
+
Provide the refactored version with explanations.""",
|
|
169
|
+
description="Clean code refactoring",
|
|
170
|
+
category="refactoring",
|
|
171
|
+
builtin=True
|
|
172
|
+
),
|
|
173
|
+
Template(
|
|
174
|
+
name="explain-code",
|
|
175
|
+
content="""Explain this code in detail:
|
|
176
|
+
|
|
177
|
+
{{code}}
|
|
178
|
+
|
|
179
|
+
Include:
|
|
180
|
+
- What it does (high-level)
|
|
181
|
+
- How it works (step-by-step)
|
|
182
|
+
- Why certain approaches were used
|
|
183
|
+
- Potential improvements
|
|
184
|
+
|
|
185
|
+
Audience level: {{level}}""",
|
|
186
|
+
description="Detailed code explanation",
|
|
187
|
+
category="documentation",
|
|
188
|
+
builtin=True
|
|
189
|
+
),
|
|
190
|
+
Template(
|
|
191
|
+
name="api-design",
|
|
192
|
+
content="""Design a {{style}} API for:
|
|
193
|
+
|
|
194
|
+
{{description}}
|
|
195
|
+
|
|
196
|
+
Include:
|
|
197
|
+
- Endpoint definitions
|
|
198
|
+
- Request/response formats
|
|
199
|
+
- Error handling
|
|
200
|
+
- Authentication approach
|
|
201
|
+
- Rate limiting considerations""",
|
|
202
|
+
description="API design assistance",
|
|
203
|
+
category="design",
|
|
204
|
+
builtin=True
|
|
205
|
+
),
|
|
206
|
+
]
|
|
207
|
+
|
|
208
|
+
def __init__(self, templates_dir: Path):
|
|
209
|
+
self.templates_dir = templates_dir
|
|
210
|
+
self.templates_file = templates_dir / "templates.json"
|
|
211
|
+
self.templates_dir.mkdir(parents=True, exist_ok=True)
|
|
212
|
+
self._load_templates()
|
|
213
|
+
|
|
214
|
+
def _load_templates(self) -> None:
|
|
215
|
+
"""Load templates from disk."""
|
|
216
|
+
self.templates: Dict[str, Template] = {}
|
|
217
|
+
|
|
218
|
+
# Load built-in templates
|
|
219
|
+
for template in self.BUILTIN_TEMPLATES:
|
|
220
|
+
self.templates[template.name] = template
|
|
221
|
+
|
|
222
|
+
# Load user templates
|
|
223
|
+
if self.templates_file.exists():
|
|
224
|
+
try:
|
|
225
|
+
with open(self.templates_file, 'r') as f:
|
|
226
|
+
data = json.load(f)
|
|
227
|
+
for template_data in data.get("templates", []):
|
|
228
|
+
template = Template.from_dict(template_data)
|
|
229
|
+
self.templates[template.name] = template
|
|
230
|
+
except Exception:
|
|
231
|
+
pass
|
|
232
|
+
|
|
233
|
+
def _save_templates(self) -> None:
|
|
234
|
+
"""Save user templates to disk."""
|
|
235
|
+
# Only save non-builtin templates
|
|
236
|
+
user_templates = [
|
|
237
|
+
t.to_dict() for t in self.templates.values() if not t.builtin
|
|
238
|
+
]
|
|
239
|
+
|
|
240
|
+
with open(self.templates_file, 'w') as f:
|
|
241
|
+
json.dump({"templates": user_templates}, f, indent=2)
|
|
242
|
+
|
|
243
|
+
def add_template(self, template: Template) -> None:
|
|
244
|
+
"""Add or update a template."""
|
|
245
|
+
if template.name in self.templates and self.templates[template.name].builtin:
|
|
246
|
+
raise ValueError(f"Cannot override builtin template: {template.name}")
|
|
247
|
+
|
|
248
|
+
self.templates[template.name] = template
|
|
249
|
+
self._save_templates()
|
|
250
|
+
|
|
251
|
+
def get_template(self, name: str) -> Optional[Template]:
|
|
252
|
+
"""Get a template by name."""
|
|
253
|
+
return self.templates.get(name)
|
|
254
|
+
|
|
255
|
+
def list_templates(
|
|
256
|
+
self,
|
|
257
|
+
category: Optional[str] = None,
|
|
258
|
+
builtin_only: bool = False,
|
|
259
|
+
user_only: bool = False
|
|
260
|
+
) -> List[Template]:
|
|
261
|
+
"""List templates with optional filters."""
|
|
262
|
+
templates = list(self.templates.values())
|
|
263
|
+
|
|
264
|
+
if category:
|
|
265
|
+
templates = [t for t in templates if t.category == category]
|
|
266
|
+
|
|
267
|
+
if builtin_only:
|
|
268
|
+
templates = [t for t in templates if t.builtin]
|
|
269
|
+
elif user_only:
|
|
270
|
+
templates = [t for t in templates if not t.builtin]
|
|
271
|
+
|
|
272
|
+
return sorted(templates, key=lambda t: (t.category, t.name))
|
|
273
|
+
|
|
274
|
+
def delete_template(self, name: str) -> bool:
|
|
275
|
+
"""Delete a template (cannot delete builtins)."""
|
|
276
|
+
if name not in self.templates:
|
|
277
|
+
return False
|
|
278
|
+
|
|
279
|
+
if self.templates[name].builtin:
|
|
280
|
+
raise ValueError(f"Cannot delete builtin template: {name}")
|
|
281
|
+
|
|
282
|
+
del self.templates[name]
|
|
283
|
+
self._save_templates()
|
|
284
|
+
return True
|
|
285
|
+
|
|
286
|
+
def get_categories(self) -> List[str]:
|
|
287
|
+
"""Get list of all template categories."""
|
|
288
|
+
return sorted(set(t.category for t in self.templates.values()))
|
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"""Warp terminal integration for enhanced output formatting."""
|
|
2
|
+
|
|
3
|
+
import json
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any, Dict, List, Optional
|
|
6
|
+
|
|
7
|
+
import yaml
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def format_as_warp_block(
|
|
11
|
+
content: str,
|
|
12
|
+
title: Optional[str] = None,
|
|
13
|
+
language: Optional[str] = None,
|
|
14
|
+
actions: Optional[List[Dict[str, str]]] = None
|
|
15
|
+
) -> str:
|
|
16
|
+
"""Format content as a Warp block with optional actions.
|
|
17
|
+
|
|
18
|
+
Warp blocks support special formatting and click-to-run actions.
|
|
19
|
+
"""
|
|
20
|
+
block_parts = []
|
|
21
|
+
|
|
22
|
+
if title:
|
|
23
|
+
block_parts.append(f"### {title}")
|
|
24
|
+
block_parts.append("")
|
|
25
|
+
|
|
26
|
+
# Add content with language if code block
|
|
27
|
+
if language:
|
|
28
|
+
block_parts.append(f"```{language}")
|
|
29
|
+
block_parts.append(content)
|
|
30
|
+
block_parts.append("```")
|
|
31
|
+
else:
|
|
32
|
+
block_parts.append(content)
|
|
33
|
+
|
|
34
|
+
# Add actions if provided
|
|
35
|
+
if actions:
|
|
36
|
+
block_parts.append("")
|
|
37
|
+
block_parts.append("**Actions:**")
|
|
38
|
+
for action in actions:
|
|
39
|
+
label = action.get('label', 'Run')
|
|
40
|
+
command = action.get('command', '')
|
|
41
|
+
block_parts.append(f"- [{label}](`{command}`)")
|
|
42
|
+
|
|
43
|
+
return "\n".join(block_parts)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def generate_warp_workflow(
|
|
47
|
+
workflow_name: str,
|
|
48
|
+
commands: List[Dict[str, str]],
|
|
49
|
+
output_path: Optional[Path] = None
|
|
50
|
+
) -> str:
|
|
51
|
+
"""Generate a Warp workflow file from command list.
|
|
52
|
+
|
|
53
|
+
Warp workflows allow users to execute predefined command sequences.
|
|
54
|
+
"""
|
|
55
|
+
workflow = {
|
|
56
|
+
"name": workflow_name,
|
|
57
|
+
"command": "://" + workflow_name.lower().replace(" ", "-"),
|
|
58
|
+
"tags": ["claude-dev-cli"],
|
|
59
|
+
"description": f"Generated from claude-dev-cli",
|
|
60
|
+
"arguments": [],
|
|
61
|
+
"source_specs": [
|
|
62
|
+
{
|
|
63
|
+
"type": "command",
|
|
64
|
+
"command": cmd.get('command', ''),
|
|
65
|
+
"description": cmd.get('description', '')
|
|
66
|
+
}
|
|
67
|
+
for cmd in commands
|
|
68
|
+
]
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
workflow_yaml = yaml.dump(workflow, default_flow_style=False, sort_keys=False)
|
|
72
|
+
|
|
73
|
+
if output_path:
|
|
74
|
+
output_path.write_text(workflow_yaml)
|
|
75
|
+
|
|
76
|
+
return workflow_yaml
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def export_builtin_workflows(output_dir: Path) -> List[Path]:
|
|
80
|
+
"""Export built-in Warp workflows for common claude-dev-cli tasks."""
|
|
81
|
+
output_dir.mkdir(parents=True, exist_ok=True)
|
|
82
|
+
|
|
83
|
+
workflows = [
|
|
84
|
+
{
|
|
85
|
+
"name": "Code Review Workflow",
|
|
86
|
+
"commands": [
|
|
87
|
+
{
|
|
88
|
+
"command": "cdc review {{file}}",
|
|
89
|
+
"description": "Review code for issues"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"command": "cdc review {{file}} --interactive",
|
|
93
|
+
"description": "Review with follow-up questions"
|
|
94
|
+
}
|
|
95
|
+
]
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"name": "Test Generation Workflow",
|
|
99
|
+
"commands": [
|
|
100
|
+
{
|
|
101
|
+
"command": "cdc generate tests {{file}} -o tests/test_{{file}}",
|
|
102
|
+
"description": "Generate tests"
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"command": "pytest tests/test_{{file}}",
|
|
106
|
+
"description": "Run tests"
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
"name": "Refactor Workflow",
|
|
112
|
+
"commands": [
|
|
113
|
+
{
|
|
114
|
+
"command": "cdc refactor {{file}} --interactive",
|
|
115
|
+
"description": "Get refactoring suggestions"
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
"command": "cdc review {{file}}",
|
|
119
|
+
"description": "Review changes"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"command": "git add {{file}} && cdc git commit",
|
|
123
|
+
"description": "Commit changes"
|
|
124
|
+
}
|
|
125
|
+
]
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"name": "Debug Workflow",
|
|
129
|
+
"commands": [
|
|
130
|
+
{
|
|
131
|
+
"command": "python {{file}} 2>&1 | cdc debug",
|
|
132
|
+
"description": "Run and debug errors"
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
"command": "cdc debug -f {{file}} -e \"{{error}}\"",
|
|
136
|
+
"description": "Debug specific error"
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
}
|
|
140
|
+
]
|
|
141
|
+
|
|
142
|
+
created_files = []
|
|
143
|
+
for workflow in workflows:
|
|
144
|
+
filename = workflow['name'].lower().replace(' ', '-') + '.yaml'
|
|
145
|
+
filepath = output_dir / filename
|
|
146
|
+
generate_warp_workflow(
|
|
147
|
+
workflow['name'],
|
|
148
|
+
workflow['commands'],
|
|
149
|
+
filepath
|
|
150
|
+
)
|
|
151
|
+
created_files.append(filepath)
|
|
152
|
+
|
|
153
|
+
return created_files
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def format_code_review_for_warp(review_output: str, file_path: str) -> str:
|
|
157
|
+
"""Format code review output as Warp block with actions."""
|
|
158
|
+
actions = [
|
|
159
|
+
{
|
|
160
|
+
"label": "Review with follow-up",
|
|
161
|
+
"command": f"cdc review {file_path} --interactive"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"label": "Refactor",
|
|
165
|
+
"command": f"cdc refactor {file_path} --interactive"
|
|
166
|
+
}
|
|
167
|
+
]
|
|
168
|
+
|
|
169
|
+
return format_as_warp_block(
|
|
170
|
+
content=review_output,
|
|
171
|
+
title="Code Review",
|
|
172
|
+
actions=actions
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def format_test_generation_for_warp(test_output: str, file_path: str) -> str:
|
|
177
|
+
"""Format test generation output as Warp block with actions."""
|
|
178
|
+
test_file = f"tests/test_{Path(file_path).name}"
|
|
179
|
+
|
|
180
|
+
actions = [
|
|
181
|
+
{
|
|
182
|
+
"label": "Save tests",
|
|
183
|
+
"command": f"cdc generate tests {file_path} -o {test_file}"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
"label": "Run tests",
|
|
187
|
+
"command": f"pytest {test_file}"
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
return format_as_warp_block(
|
|
192
|
+
content=test_output,
|
|
193
|
+
title="Generated Tests",
|
|
194
|
+
language="python",
|
|
195
|
+
actions=actions
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def create_warp_launch_config(
|
|
200
|
+
name: str,
|
|
201
|
+
command: str,
|
|
202
|
+
cwd: Optional[str] = None,
|
|
203
|
+
env: Optional[Dict[str, str]] = None
|
|
204
|
+
) -> Dict[str, Any]:
|
|
205
|
+
"""Create a Warp launch configuration.
|
|
206
|
+
|
|
207
|
+
Launch configs allow quick environment setup in Warp.
|
|
208
|
+
"""
|
|
209
|
+
config = {
|
|
210
|
+
"name": name,
|
|
211
|
+
"command": command,
|
|
212
|
+
"type": "terminal"
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if cwd:
|
|
216
|
+
config["cwd"] = cwd
|
|
217
|
+
|
|
218
|
+
if env:
|
|
219
|
+
config["env"] = env
|
|
220
|
+
|
|
221
|
+
return config
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
def export_launch_configs(output_path: Path) -> None:
|
|
225
|
+
"""Export Warp launch configurations for claude-dev-cli."""
|
|
226
|
+
configs = [
|
|
227
|
+
create_warp_launch_config(
|
|
228
|
+
name="Claude Dev CLI - Interactive",
|
|
229
|
+
command="cdc interactive"
|
|
230
|
+
),
|
|
231
|
+
create_warp_launch_config(
|
|
232
|
+
name="Claude Dev CLI - Review Mode",
|
|
233
|
+
command="cdc review"
|
|
234
|
+
),
|
|
235
|
+
create_warp_launch_config(
|
|
236
|
+
name="Claude Dev CLI - Test Generation",
|
|
237
|
+
command="cdc generate tests"
|
|
238
|
+
)
|
|
239
|
+
]
|
|
240
|
+
|
|
241
|
+
output_path.parent.mkdir(parents=True, exist_ok=True)
|
|
242
|
+
with open(output_path, 'w') as f:
|
|
243
|
+
json.dump({"launch_configurations": configs}, f, indent=2)
|