claude-dev-cli 0.5.0__py3-none-any.whl → 0.6.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 +204 -0
- claude_dev_cli/template_manager.py +288 -0
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.6.0.dist-info}/METADATA +56 -3
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.6.0.dist-info}/RECORD +9 -8
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.6.0.dist-info}/WHEEL +0 -0
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.6.0.dist-info}/entry_points.txt +0 -0
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {claude_dev_cli-0.5.0.dist-info → claude_dev_cli-0.6.0.dist-info}/top_level.txt +0 -0
claude_dev_cli/__init__.py
CHANGED
claude_dev_cli/cli.py
CHANGED
|
@@ -25,6 +25,7 @@ from claude_dev_cli.usage import UsageTracker
|
|
|
25
25
|
from claude_dev_cli import toon_utils
|
|
26
26
|
from claude_dev_cli.plugins import load_plugins
|
|
27
27
|
from claude_dev_cli.history import ConversationHistory, Conversation
|
|
28
|
+
from claude_dev_cli.template_manager import TemplateManager, Template
|
|
28
29
|
|
|
29
30
|
console = Console()
|
|
30
31
|
|
|
@@ -753,5 +754,208 @@ def toon_info(ctx: click.Context) -> None:
|
|
|
753
754
|
console.print("• Same data, fewer tokens")
|
|
754
755
|
|
|
755
756
|
|
|
757
|
+
@main.group()
|
|
758
|
+
def template() -> None:
|
|
759
|
+
"""Manage custom prompt templates."""
|
|
760
|
+
pass
|
|
761
|
+
|
|
762
|
+
|
|
763
|
+
@template.command('list')
|
|
764
|
+
@click.option('-c', '--category', help='Filter by category')
|
|
765
|
+
@click.option('--builtin', is_flag=True, help='Show only built-in templates')
|
|
766
|
+
@click.option('--user', is_flag=True, help='Show only user templates')
|
|
767
|
+
@click.pass_context
|
|
768
|
+
def template_list(
|
|
769
|
+
ctx: click.Context,
|
|
770
|
+
category: Optional[str],
|
|
771
|
+
builtin: bool,
|
|
772
|
+
user: bool
|
|
773
|
+
) -> None:
|
|
774
|
+
"""List available templates."""
|
|
775
|
+
console = ctx.obj['console']
|
|
776
|
+
config = Config()
|
|
777
|
+
manager = TemplateManager(config.config_dir)
|
|
778
|
+
|
|
779
|
+
templates = manager.list_templates(
|
|
780
|
+
category=category,
|
|
781
|
+
builtin_only=builtin,
|
|
782
|
+
user_only=user
|
|
783
|
+
)
|
|
784
|
+
|
|
785
|
+
if not templates:
|
|
786
|
+
console.print("[yellow]No templates found.[/yellow]")
|
|
787
|
+
return
|
|
788
|
+
|
|
789
|
+
from rich.table import Table
|
|
790
|
+
|
|
791
|
+
table = Table(show_header=True, header_style="bold magenta")
|
|
792
|
+
table.add_column("Name", style="cyan")
|
|
793
|
+
table.add_column("Category", style="green")
|
|
794
|
+
table.add_column("Variables", style="yellow")
|
|
795
|
+
table.add_column("Type", style="blue")
|
|
796
|
+
table.add_column("Description")
|
|
797
|
+
|
|
798
|
+
for tmpl in templates:
|
|
799
|
+
vars_display = ", ".join(tmpl.variables) if tmpl.variables else "-"
|
|
800
|
+
type_display = "🔒 Built-in" if tmpl.builtin else "📝 User"
|
|
801
|
+
table.add_row(
|
|
802
|
+
tmpl.name,
|
|
803
|
+
tmpl.category,
|
|
804
|
+
vars_display,
|
|
805
|
+
type_display,
|
|
806
|
+
tmpl.description
|
|
807
|
+
)
|
|
808
|
+
|
|
809
|
+
console.print(table)
|
|
810
|
+
|
|
811
|
+
# Show categories
|
|
812
|
+
categories = manager.get_categories()
|
|
813
|
+
console.print(f"\n[dim]Categories: {', '.join(categories)}[/dim]")
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
@template.command('show')
|
|
817
|
+
@click.argument('name')
|
|
818
|
+
@click.pass_context
|
|
819
|
+
def template_show(ctx: click.Context, name: str) -> None:
|
|
820
|
+
"""Show template details."""
|
|
821
|
+
console = ctx.obj['console']
|
|
822
|
+
config = Config()
|
|
823
|
+
manager = TemplateManager(config.config_dir)
|
|
824
|
+
|
|
825
|
+
tmpl = manager.get_template(name)
|
|
826
|
+
if not tmpl:
|
|
827
|
+
console.print(f"[red]Template not found: {name}[/red]")
|
|
828
|
+
sys.exit(1)
|
|
829
|
+
|
|
830
|
+
console.print(Panel(
|
|
831
|
+
f"[bold]{tmpl.name}[/bold]\n\n"
|
|
832
|
+
f"[dim]{tmpl.description}[/dim]\n\n"
|
|
833
|
+
f"Category: [green]{tmpl.category}[/green]\n"
|
|
834
|
+
f"Type: {'🔒 Built-in' if tmpl.builtin else '📝 User'}\n"
|
|
835
|
+
f"Variables: [yellow]{', '.join(tmpl.variables) if tmpl.variables else 'None'}[/yellow]",
|
|
836
|
+
title="Template Info",
|
|
837
|
+
border_style="blue"
|
|
838
|
+
))
|
|
839
|
+
|
|
840
|
+
console.print("\n[bold]Content:[/bold]\n")
|
|
841
|
+
console.print(Panel(tmpl.content, border_style="dim"))
|
|
842
|
+
|
|
843
|
+
|
|
844
|
+
@template.command('add')
|
|
845
|
+
@click.argument('name')
|
|
846
|
+
@click.option('-c', '--content', help='Template content (or use stdin)')
|
|
847
|
+
@click.option('-d', '--description', help='Template description')
|
|
848
|
+
@click.option('--category', default='general', help='Template category')
|
|
849
|
+
@click.pass_context
|
|
850
|
+
def template_add(
|
|
851
|
+
ctx: click.Context,
|
|
852
|
+
name: str,
|
|
853
|
+
content: Optional[str],
|
|
854
|
+
description: Optional[str],
|
|
855
|
+
category: str
|
|
856
|
+
) -> None:
|
|
857
|
+
"""Add a new template."""
|
|
858
|
+
console = ctx.obj['console']
|
|
859
|
+
config = Config()
|
|
860
|
+
manager = TemplateManager(config.config_dir)
|
|
861
|
+
|
|
862
|
+
# Get content from stdin if not provided
|
|
863
|
+
if not content:
|
|
864
|
+
if sys.stdin.isatty():
|
|
865
|
+
console.print("[yellow]Enter template content (Ctrl+D to finish):[/yellow]")
|
|
866
|
+
content = sys.stdin.read().strip()
|
|
867
|
+
|
|
868
|
+
if not content:
|
|
869
|
+
console.print("[red]Error: No content provided[/red]")
|
|
870
|
+
sys.exit(1)
|
|
871
|
+
|
|
872
|
+
try:
|
|
873
|
+
tmpl = Template(
|
|
874
|
+
name=name,
|
|
875
|
+
content=content,
|
|
876
|
+
description=description,
|
|
877
|
+
category=category
|
|
878
|
+
)
|
|
879
|
+
manager.add_template(tmpl)
|
|
880
|
+
|
|
881
|
+
console.print(f"[green]✓[/green] Template added: {name}")
|
|
882
|
+
if tmpl.variables:
|
|
883
|
+
console.print(f"[dim]Variables: {', '.join(tmpl.variables)}[/dim]")
|
|
884
|
+
|
|
885
|
+
except ValueError as e:
|
|
886
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
887
|
+
sys.exit(1)
|
|
888
|
+
|
|
889
|
+
|
|
890
|
+
@template.command('delete')
|
|
891
|
+
@click.argument('name')
|
|
892
|
+
@click.pass_context
|
|
893
|
+
def template_delete(ctx: click.Context, name: str) -> None:
|
|
894
|
+
"""Delete a user template."""
|
|
895
|
+
console = ctx.obj['console']
|
|
896
|
+
config = Config()
|
|
897
|
+
manager = TemplateManager(config.config_dir)
|
|
898
|
+
|
|
899
|
+
try:
|
|
900
|
+
if manager.delete_template(name):
|
|
901
|
+
console.print(f"[green]✓[/green] Template deleted: {name}")
|
|
902
|
+
else:
|
|
903
|
+
console.print(f"[red]Template not found: {name}[/red]")
|
|
904
|
+
sys.exit(1)
|
|
905
|
+
|
|
906
|
+
except ValueError as e:
|
|
907
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
908
|
+
sys.exit(1)
|
|
909
|
+
|
|
910
|
+
|
|
911
|
+
@template.command('use')
|
|
912
|
+
@click.argument('name')
|
|
913
|
+
@click.option('-a', '--api', help='API config to use')
|
|
914
|
+
@click.option('-m', '--model', help='Claude model to use')
|
|
915
|
+
@click.pass_context
|
|
916
|
+
def template_use(ctx: click.Context, name: str, api: Optional[str], model: Optional[str]) -> None:
|
|
917
|
+
"""Use a template with interactive variable input."""
|
|
918
|
+
console = ctx.obj['console']
|
|
919
|
+
config = Config()
|
|
920
|
+
manager = TemplateManager(config.config_dir)
|
|
921
|
+
|
|
922
|
+
tmpl = manager.get_template(name)
|
|
923
|
+
if not tmpl:
|
|
924
|
+
console.print(f"[red]Template not found: {name}[/red]")
|
|
925
|
+
sys.exit(1)
|
|
926
|
+
|
|
927
|
+
# Get variable values
|
|
928
|
+
variables = {}
|
|
929
|
+
if tmpl.variables:
|
|
930
|
+
console.print(f"\n[bold]Template: {name}[/bold]")
|
|
931
|
+
console.print(f"[dim]{tmpl.description}[/dim]\n")
|
|
932
|
+
|
|
933
|
+
for var in tmpl.variables:
|
|
934
|
+
value = console.input(f"[cyan]{var}:[/cyan] ").strip()
|
|
935
|
+
variables[var] = value
|
|
936
|
+
|
|
937
|
+
# Check for missing variables
|
|
938
|
+
missing = tmpl.get_missing_variables(**variables)
|
|
939
|
+
if missing:
|
|
940
|
+
console.print(f"[red]Missing required variables: {', '.join(missing)}[/red]")
|
|
941
|
+
sys.exit(1)
|
|
942
|
+
|
|
943
|
+
# Render template
|
|
944
|
+
prompt = tmpl.render(**variables)
|
|
945
|
+
|
|
946
|
+
# Call Claude
|
|
947
|
+
try:
|
|
948
|
+
client = ClaudeClient(api_config_name=api)
|
|
949
|
+
|
|
950
|
+
console.print("\n[bold green]Claude:[/bold green] ", end='')
|
|
951
|
+
for chunk in client.call_streaming(prompt, model=model):
|
|
952
|
+
console.print(chunk, end='')
|
|
953
|
+
console.print()
|
|
954
|
+
|
|
955
|
+
except Exception as e:
|
|
956
|
+
console.print(f"\n[red]Error: {e}[/red]")
|
|
957
|
+
sys.exit(1)
|
|
958
|
+
|
|
959
|
+
|
|
756
960
|
if __name__ == '__main__':
|
|
757
961
|
main(obj={})
|
|
@@ -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()))
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-dev-cli
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.6.0
|
|
4
4
|
Summary: A powerful CLI tool for developers using Claude AI with multi-API routing, test generation, code review, and usage tracking
|
|
5
5
|
Author-email: Julio <thinmanj@users.noreply.github.com>
|
|
6
6
|
License: MIT
|
|
@@ -72,6 +72,12 @@ A powerful command-line tool for developers using Claude AI with multi-API routi
|
|
|
72
72
|
- **Interactive**: Chat mode with conversation history
|
|
73
73
|
- **Streaming**: Real-time responses
|
|
74
74
|
|
|
75
|
+
### 📝 Custom Templates
|
|
76
|
+
- **Built-in Templates**: 8 pre-built templates for common tasks (code review, testing, debugging, etc.)
|
|
77
|
+
- **User Templates**: Create and manage your own reusable prompt templates
|
|
78
|
+
- **Variable Substitution**: Use {{variable}} placeholders for dynamic content
|
|
79
|
+
- **Categories**: Organize templates by category (review, testing, debugging, etc.)
|
|
80
|
+
|
|
75
81
|
### 🎒 TOON Format Support (Optional)
|
|
76
82
|
- **Token Reduction**: 30-60% fewer tokens than JSON
|
|
77
83
|
- **Cost Savings**: Reduce API costs significantly
|
|
@@ -156,7 +162,44 @@ git add .
|
|
|
156
162
|
cdc git commit
|
|
157
163
|
```
|
|
158
164
|
|
|
159
|
-
###
|
|
165
|
+
### 5. Custom Templates
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
# List all templates (built-in and user)
|
|
169
|
+
cdc template list
|
|
170
|
+
|
|
171
|
+
# Show template details
|
|
172
|
+
cdc template show code-review
|
|
173
|
+
|
|
174
|
+
# Add a custom template
|
|
175
|
+
cdc template add my-review -c "Review this code for {{focus}}: {{code}}" \
|
|
176
|
+
-d "Custom review template" --category review
|
|
177
|
+
|
|
178
|
+
# Use a template (interactive variable input)
|
|
179
|
+
cdc template use debug-error
|
|
180
|
+
|
|
181
|
+
# Delete a user template
|
|
182
|
+
cdc template delete my-review
|
|
183
|
+
|
|
184
|
+
# Filter by category
|
|
185
|
+
cdc template list --category review
|
|
186
|
+
|
|
187
|
+
# Show only user templates
|
|
188
|
+
cdc template list --user
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
#### Built-in Templates
|
|
192
|
+
|
|
193
|
+
- **code-review**: Comprehensive code review with customizable focus
|
|
194
|
+
- **code-review-security**: Security-focused code review
|
|
195
|
+
- **test-strategy**: Generate testing strategy and test cases
|
|
196
|
+
- **debug-error**: Debug error with context
|
|
197
|
+
- **optimize-performance**: Performance optimization analysis
|
|
198
|
+
- **refactor-clean**: Clean code refactoring
|
|
199
|
+
- **explain-code**: Detailed code explanation
|
|
200
|
+
- **api-design**: API design assistance
|
|
201
|
+
|
|
202
|
+
### 6. Usage Tracking
|
|
160
203
|
|
|
161
204
|
```bash
|
|
162
205
|
# View all usage
|
|
@@ -169,7 +212,7 @@ cdc usage --days 7
|
|
|
169
212
|
cdc usage --api client
|
|
170
213
|
```
|
|
171
214
|
|
|
172
|
-
###
|
|
215
|
+
### 7. TOON Format (Optional - Reduces Tokens by 30-60%)
|
|
173
216
|
|
|
174
217
|
```bash
|
|
175
218
|
# Check if TOON is installed
|
|
@@ -322,6 +365,16 @@ When using a client's Enterprise API:
|
|
|
322
365
|
| `cdc debug -f <file> -e <error>` | Debug code |
|
|
323
366
|
| `cdc refactor <file>` | Refactoring suggestions |
|
|
324
367
|
|
|
368
|
+
### Templates
|
|
369
|
+
|
|
370
|
+
| Command | Description |
|
|
371
|
+
|---------|-------------|
|
|
372
|
+
| `cdc template list` | List all templates |
|
|
373
|
+
| `cdc template show <name>` | Show template details |
|
|
374
|
+
| `cdc template add <name>` | Add new template |
|
|
375
|
+
| `cdc template delete <name>` | Delete user template |
|
|
376
|
+
| `cdc template use <name>` | Use template interactively |
|
|
377
|
+
|
|
325
378
|
### Git Helpers
|
|
326
379
|
|
|
327
380
|
| Command | Description |
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
claude_dev_cli/__init__.py,sha256=
|
|
2
|
-
claude_dev_cli/cli.py,sha256=
|
|
1
|
+
claude_dev_cli/__init__.py,sha256=8WXldNvP94ff1oD0MSxSxb5h0bEF-eJZyVHPopW8gq8,469
|
|
2
|
+
claude_dev_cli/cli.py,sha256=KJbUDQl_hA7jgLGxXQs01MW6inzevQk6d7_mUvvAAB8,31296
|
|
3
3
|
claude_dev_cli/commands.py,sha256=RKGx2rv56PM6eErvA2uoQ20hY8babuI5jav8nCUyUOk,3964
|
|
4
4
|
claude_dev_cli/config.py,sha256=RGX0sKplHUsrJJmU-4FuWWjoTbQVgWaMT8DgRUofrR4,8134
|
|
5
5
|
claude_dev_cli/core.py,sha256=yaLjEixDvPzvUy4fJ2UB7nMpPPLyKACjR-RuM-1OQBY,4780
|
|
6
6
|
claude_dev_cli/history.py,sha256=iQlqgTnXCsyCq5q-XaDl7V5MyPKQ3bx7o_k76-xWSAA,6863
|
|
7
7
|
claude_dev_cli/secure_storage.py,sha256=TK3WOaU7a0yTOtzdP_t_28fDRp2lovANNAC6MBdm4nQ,7096
|
|
8
|
+
claude_dev_cli/template_manager.py,sha256=ZFXOtRIoB6hpf8kLSF9TWJfvUPJt9b-PyEv3qTBK7Zs,8600
|
|
8
9
|
claude_dev_cli/templates.py,sha256=lKxH943ySfUKgyHaWa4W3LVv91SgznKgajRtSRp_4UY,2260
|
|
9
10
|
claude_dev_cli/toon_utils.py,sha256=S3px2UvmNEaltmTa5K-h21n2c0CPvYjZc9mc7kHGqNQ,2828
|
|
10
11
|
claude_dev_cli/usage.py,sha256=32rs0_dUn6ihha3vCfT3rwnvel_-sED7jvLpO7gu-KQ,7446
|
|
@@ -13,9 +14,9 @@ claude_dev_cli/plugins/base.py,sha256=H4HQet1I-a3WLCfE9F06Lp8NuFvVoIlou7sIgyJFK-
|
|
|
13
14
|
claude_dev_cli/plugins/diff_editor/__init__.py,sha256=gqR5S2TyIVuq-sK107fegsutQ7Z-sgAIEbtc71FhXIM,101
|
|
14
15
|
claude_dev_cli/plugins/diff_editor/plugin.py,sha256=M1bUoqpasD3ZNQo36Fu_8g92uySPZyG_ujMbj5UplsU,3073
|
|
15
16
|
claude_dev_cli/plugins/diff_editor/viewer.py,sha256=1IOXIKw_01ppJx5C1dQt9Kr6U1TdAHT8_iUT5r_q0NM,17169
|
|
16
|
-
claude_dev_cli-0.
|
|
17
|
-
claude_dev_cli-0.
|
|
18
|
-
claude_dev_cli-0.
|
|
19
|
-
claude_dev_cli-0.
|
|
20
|
-
claude_dev_cli-0.
|
|
21
|
-
claude_dev_cli-0.
|
|
17
|
+
claude_dev_cli-0.6.0.dist-info/licenses/LICENSE,sha256=DGueuJwMJtMwgLO5mWlS0TaeBrFwQuNpNZ22PU9J2bw,1062
|
|
18
|
+
claude_dev_cli-0.6.0.dist-info/METADATA,sha256=d1aptyTDwcmtYPMrSgTk4j5pHCPgVriDnyjx--JjDCk,12984
|
|
19
|
+
claude_dev_cli-0.6.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
20
|
+
claude_dev_cli-0.6.0.dist-info/entry_points.txt,sha256=zymgUIIVpFTARkFmxAuW2A4BQsNITh_L0uU-XunytHg,85
|
|
21
|
+
claude_dev_cli-0.6.0.dist-info/top_level.txt,sha256=m7MF6LOIuTe41IT5Fgt0lc-DK1EgM4gUU_IZwWxK0pg,15
|
|
22
|
+
claude_dev_cli-0.6.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|