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.

@@ -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)