claude-dev-cli 0.4.0__tar.gz → 0.6.0__tar.gz

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.

Files changed (37) hide show
  1. {claude_dev_cli-0.4.0/src/claude_dev_cli.egg-info → claude_dev_cli-0.6.0}/PKG-INFO +56 -3
  2. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/README.md +55 -2
  3. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/pyproject.toml +1 -1
  4. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/__init__.py +1 -1
  5. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/cli.py +381 -1
  6. claude_dev_cli-0.6.0/src/claude_dev_cli/history.py +189 -0
  7. claude_dev_cli-0.6.0/src/claude_dev_cli/template_manager.py +288 -0
  8. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0/src/claude_dev_cli.egg-info}/PKG-INFO +56 -3
  9. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli.egg-info/SOURCES.txt +3 -0
  10. claude_dev_cli-0.6.0/tests/test_template_manager.py +327 -0
  11. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/LICENSE +0 -0
  12. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/MANIFEST.in +0 -0
  13. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/setup.cfg +0 -0
  14. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/commands.py +0 -0
  15. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/config.py +0 -0
  16. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/core.py +0 -0
  17. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/plugins/__init__.py +0 -0
  18. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/plugins/base.py +0 -0
  19. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/plugins/diff_editor/__init__.py +0 -0
  20. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/plugins/diff_editor/plugin.py +0 -0
  21. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/plugins/diff_editor/viewer.py +0 -0
  22. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/secure_storage.py +0 -0
  23. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/templates.py +0 -0
  24. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/toon_utils.py +0 -0
  25. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli/usage.py +0 -0
  26. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli.egg-info/dependency_links.txt +0 -0
  27. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli.egg-info/entry_points.txt +0 -0
  28. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli.egg-info/requires.txt +0 -0
  29. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/src/claude_dev_cli.egg-info/top_level.txt +0 -0
  30. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/tests/test_cli.py +0 -0
  31. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/tests/test_commands.py +0 -0
  32. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/tests/test_config.py +0 -0
  33. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/tests/test_core.py +0 -0
  34. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/tests/test_diff_editor.py +0 -0
  35. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/tests/test_secure_storage.py +0 -0
  36. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/tests/test_toon_utils.py +0 -0
  37. {claude_dev_cli-0.4.0 → claude_dev_cli-0.6.0}/tests/test_usage.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: claude-dev-cli
3
- Version: 0.4.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
- ### 4. Usage Tracking
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
- ### 5. TOON Format (Optional - Reduces Tokens by 30-60%)
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 |
@@ -29,6 +29,12 @@ A powerful command-line tool for developers using Claude AI with multi-API routi
29
29
  - **Interactive**: Chat mode with conversation history
30
30
  - **Streaming**: Real-time responses
31
31
 
32
+ ### 📝 Custom Templates
33
+ - **Built-in Templates**: 8 pre-built templates for common tasks (code review, testing, debugging, etc.)
34
+ - **User Templates**: Create and manage your own reusable prompt templates
35
+ - **Variable Substitution**: Use {{variable}} placeholders for dynamic content
36
+ - **Categories**: Organize templates by category (review, testing, debugging, etc.)
37
+
32
38
  ### 🎒 TOON Format Support (Optional)
33
39
  - **Token Reduction**: 30-60% fewer tokens than JSON
34
40
  - **Cost Savings**: Reduce API costs significantly
@@ -113,7 +119,44 @@ git add .
113
119
  cdc git commit
114
120
  ```
115
121
 
116
- ### 4. Usage Tracking
122
+ ### 5. Custom Templates
123
+
124
+ ```bash
125
+ # List all templates (built-in and user)
126
+ cdc template list
127
+
128
+ # Show template details
129
+ cdc template show code-review
130
+
131
+ # Add a custom template
132
+ cdc template add my-review -c "Review this code for {{focus}}: {{code}}" \
133
+ -d "Custom review template" --category review
134
+
135
+ # Use a template (interactive variable input)
136
+ cdc template use debug-error
137
+
138
+ # Delete a user template
139
+ cdc template delete my-review
140
+
141
+ # Filter by category
142
+ cdc template list --category review
143
+
144
+ # Show only user templates
145
+ cdc template list --user
146
+ ```
147
+
148
+ #### Built-in Templates
149
+
150
+ - **code-review**: Comprehensive code review with customizable focus
151
+ - **code-review-security**: Security-focused code review
152
+ - **test-strategy**: Generate testing strategy and test cases
153
+ - **debug-error**: Debug error with context
154
+ - **optimize-performance**: Performance optimization analysis
155
+ - **refactor-clean**: Clean code refactoring
156
+ - **explain-code**: Detailed code explanation
157
+ - **api-design**: API design assistance
158
+
159
+ ### 6. Usage Tracking
117
160
 
118
161
  ```bash
119
162
  # View all usage
@@ -126,7 +169,7 @@ cdc usage --days 7
126
169
  cdc usage --api client
127
170
  ```
128
171
 
129
- ### 5. TOON Format (Optional - Reduces Tokens by 30-60%)
172
+ ### 7. TOON Format (Optional - Reduces Tokens by 30-60%)
130
173
 
131
174
  ```bash
132
175
  # Check if TOON is installed
@@ -279,6 +322,16 @@ When using a client's Enterprise API:
279
322
  | `cdc debug -f <file> -e <error>` | Debug code |
280
323
  | `cdc refactor <file>` | Refactoring suggestions |
281
324
 
325
+ ### Templates
326
+
327
+ | Command | Description |
328
+ |---------|-------------|
329
+ | `cdc template list` | List all templates |
330
+ | `cdc template show <name>` | Show template details |
331
+ | `cdc template add <name>` | Add new template |
332
+ | `cdc template delete <name>` | Delete user template |
333
+ | `cdc template use <name>` | Use template interactively |
334
+
282
335
  ### Git Helpers
283
336
 
284
337
  | Command | Description |
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "claude-dev-cli"
7
- version = "0.4.0"
7
+ version = "0.6.0"
8
8
  description = "A powerful CLI tool for developers using Claude AI with multi-API routing, test generation, code review, and usage tracking"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.9"
@@ -9,7 +9,7 @@ Features:
9
9
  - Interactive and single-shot modes
10
10
  """
11
11
 
12
- __version__ = "0.2.0"
12
+ __version__ = "0.6.0"
13
13
  __author__ = "Julio"
14
14
  __license__ = "MIT"
15
15
 
@@ -1,5 +1,6 @@
1
1
  """Command-line interface for Claude Dev CLI."""
2
2
 
3
+ import os
3
4
  import sys
4
5
  from pathlib import Path
5
6
  from typing import Optional
@@ -23,6 +24,8 @@ from claude_dev_cli.commands import (
23
24
  from claude_dev_cli.usage import UsageTracker
24
25
  from claude_dev_cli import toon_utils
25
26
  from claude_dev_cli.plugins import load_plugins
27
+ from claude_dev_cli.history import ConversationHistory, Conversation
28
+ from claude_dev_cli.template_manager import TemplateManager, Template
26
29
 
27
30
  console = Console()
28
31
 
@@ -112,11 +115,36 @@ def ask(
112
115
 
113
116
  @main.command()
114
117
  @click.option('-a', '--api', help='API config to use')
118
+ @click.option('--continue', 'continue_conversation', is_flag=True,
119
+ help='Continue the last conversation')
120
+ @click.option('--save/--no-save', default=True, help='Save conversation history')
115
121
  @click.pass_context
116
- def interactive(ctx: click.Context, api: Optional[str]) -> None:
122
+ def interactive(
123
+ ctx: click.Context,
124
+ api: Optional[str],
125
+ continue_conversation: bool,
126
+ save: bool
127
+ ) -> None:
117
128
  """Start interactive chat mode."""
118
129
  console = ctx.obj['console']
119
130
 
131
+ # Setup conversation history
132
+ config = Config()
133
+ history_dir = config.config_dir / "history"
134
+ conv_history = ConversationHistory(history_dir)
135
+
136
+ # Load or create conversation
137
+ if continue_conversation:
138
+ conversation = conv_history.get_latest_conversation()
139
+ if conversation:
140
+ console.print(f"[green]↶ Continuing conversation from {conversation.updated_at.strftime('%Y-%m-%d %H:%M')}[/green]")
141
+ console.print(f"[dim]Messages: {len(conversation.messages)}[/dim]\n")
142
+ else:
143
+ console.print("[yellow]No previous conversation found, starting new one[/yellow]\n")
144
+ conversation = Conversation()
145
+ else:
146
+ conversation = Conversation()
147
+
120
148
  console.print(Panel.fit(
121
149
  "Claude Dev CLI - Interactive Mode\n"
122
150
  "Type 'exit' or 'quit' to end\n"
@@ -127,28 +155,177 @@ def interactive(ctx: click.Context, api: Optional[str]) -> None:
127
155
 
128
156
  try:
129
157
  client = ClaudeClient(api_config_name=api)
158
+ response_buffer = []
130
159
 
131
160
  while True:
132
161
  try:
133
162
  user_input = console.input("\n[bold cyan]You:[/bold cyan] ").strip()
134
163
 
135
164
  if user_input.lower() in ['exit', 'quit']:
165
+ if save and conversation.messages:
166
+ conv_history.save_conversation(conversation)
167
+ console.print(f"\n[dim]💾 Saved conversation: {conversation.conversation_id}[/dim]")
136
168
  break
169
+
170
+ if user_input.lower() == 'clear':
171
+ conversation = Conversation()
172
+ console.print("[yellow]Conversation cleared[/yellow]")
173
+ continue
174
+
137
175
  if not user_input:
138
176
  continue
139
177
 
178
+ # Add user message to history
179
+ conversation.add_message("user", user_input)
180
+
181
+ # Get response
140
182
  console.print("\n[bold green]Claude:[/bold green] ", end='')
183
+ response_buffer = []
141
184
  for chunk in client.call_streaming(user_input):
142
185
  console.print(chunk, end='')
186
+ response_buffer.append(chunk)
143
187
  console.print()
144
188
 
189
+ # Add assistant response to history
190
+ full_response = ''.join(response_buffer)
191
+ conversation.add_message("assistant", full_response)
192
+
193
+ # Auto-save periodically
194
+ if save and len(conversation.messages) % 10 == 0:
195
+ conv_history.save_conversation(conversation)
196
+
145
197
  except KeyboardInterrupt:
146
198
  console.print("\n\n[yellow]Interrupted. Type 'exit' to quit.[/yellow]")
147
199
  continue
148
200
 
149
201
  except Exception as e:
150
202
  console.print(f"[red]Error: {e}[/red]")
203
+ if save and conversation.messages:
204
+ conv_history.save_conversation(conversation)
205
+ sys.exit(1)
206
+
207
+
208
+ @main.group()
209
+ def completion() -> None:
210
+ """Shell completion installation."""
211
+ pass
212
+
213
+
214
+ @completion.command('install')
215
+ @click.option('--shell', type=click.Choice(['bash', 'zsh', 'fish', 'auto']), default='auto',
216
+ help='Shell type (auto-detects if not specified)')
217
+ @click.pass_context
218
+ def completion_install(ctx: click.Context, shell: str) -> None:
219
+ """Install shell completion for cdc command."""
220
+ console = ctx.obj['console']
221
+
222
+ # Auto-detect shell if needed
223
+ if shell == 'auto':
224
+ shell_path = os.environ.get('SHELL', '')
225
+ if 'zsh' in shell_path:
226
+ shell = 'zsh'
227
+ elif 'bash' in shell_path:
228
+ shell = 'bash'
229
+ elif 'fish' in shell_path:
230
+ shell = 'fish'
231
+ else:
232
+ console.print("[red]Could not auto-detect shell[/red]")
233
+ console.print("Please specify: --shell bash|zsh|fish")
234
+ sys.exit(1)
235
+
236
+ console.print(f"[cyan]Installing completion for {shell}...[/cyan]\n")
237
+
238
+ if shell == 'zsh':
239
+ console.print("Add this to your ~/.zshrc:\n")
240
+ console.print("[yellow]eval \"$(_CDC_COMPLETE=zsh_source cdc)\"[/yellow]\n")
241
+ console.print("Then run: [cyan]source ~/.zshrc[/cyan]")
242
+ elif shell == 'bash':
243
+ console.print("Add this to your ~/.bashrc:\n")
244
+ console.print("[yellow]eval \"$(_CDC_COMPLETE=bash_source cdc)\"[/yellow]\n")
245
+ console.print("Then run: [cyan]source ~/.bashrc[/cyan]")
246
+ elif shell == 'fish':
247
+ console.print("Add this to ~/.config/fish/completions/cdc.fish:\n")
248
+ console.print("[yellow]_CDC_COMPLETE=fish_source cdc | source[/yellow]\n")
249
+ console.print("Then reload: [cyan]exec fish[/cyan]")
250
+
251
+ console.print("\n[green]✓[/green] Instructions displayed above")
252
+ console.print("[dim]Completion will provide command and option suggestions[/dim]")
253
+
254
+
255
+ @completion.command('generate')
256
+ @click.option('--shell', type=click.Choice(['bash', 'zsh', 'fish']), required=True,
257
+ help='Shell type')
258
+ @click.pass_context
259
+ def completion_generate(ctx: click.Context, shell: str) -> None:
260
+ """Generate completion script for shell."""
261
+ import subprocess
262
+ import sys
263
+
264
+ env_var = f"_CDC_COMPLETE={shell}_source"
265
+ result = subprocess.run(
266
+ [sys.executable, '-m', 'claude_dev_cli.cli'],
267
+ env={**os.environ, '_CDC_COMPLETE': f'{shell}_source'},
268
+ capture_output=True,
269
+ text=True
270
+ )
271
+
272
+ if result.returncode == 0:
273
+ click.echo(result.stdout)
274
+ else:
275
+ ctx.obj['console'].print(f"[red]Error generating completion: {result.stderr}[/red]")
276
+ sys.exit(1)
277
+
278
+
279
+ @main.group()
280
+ def history() -> None:
281
+ """Manage conversation history."""
282
+ pass
283
+
284
+
285
+ @history.command('list')
286
+ @click.option('-n', '--limit', type=int, default=10, help='Number of conversations to show')
287
+ @click.option('-s', '--search', help='Search conversations')
288
+ @click.pass_context
289
+ def history_list(ctx: click.Context, limit: int, search: Optional[str]) -> None:
290
+ """List conversation history."""
291
+ console = ctx.obj['console']
292
+ config = Config()
293
+ conv_history = ConversationHistory(config.config_dir / "history")
294
+
295
+ conversations = conv_history.list_conversations(limit=limit, search_query=search)
296
+
297
+ if not conversations:
298
+ console.print("[yellow]No conversations found[/yellow]")
299
+ return
300
+
301
+ for conv in conversations:
302
+ summary = conv.get_summary(80)
303
+ console.print(f"\n[cyan]{conv.conversation_id}[/cyan]")
304
+ console.print(f"[dim]{conv.updated_at.strftime('%Y-%m-%d %H:%M')} | {len(conv.messages)} messages[/dim]")
305
+ console.print(f" {summary}")
306
+
307
+
308
+ @history.command('export')
309
+ @click.argument('conversation_id')
310
+ @click.option('--format', type=click.Choice(['markdown', 'json']), default='markdown')
311
+ @click.option('-o', '--output', type=click.Path(), help='Output file')
312
+ @click.pass_context
313
+ def history_export(ctx: click.Context, conversation_id: str, format: str, output: Optional[str]) -> None:
314
+ """Export a conversation."""
315
+ console = ctx.obj['console']
316
+ config = Config()
317
+ conv_history = ConversationHistory(config.config_dir / "history")
318
+
319
+ content = conv_history.export_conversation(conversation_id, format)
320
+ if not content:
321
+ console.print(f"[red]Conversation {conversation_id} not found[/red]")
151
322
  sys.exit(1)
323
+
324
+ if output:
325
+ Path(output).write_text(content)
326
+ console.print(f"[green]✓[/green] Exported to {output}")
327
+ else:
328
+ click.echo(content)
152
329
 
153
330
 
154
331
  @main.group()
@@ -577,5 +754,208 @@ def toon_info(ctx: click.Context) -> None:
577
754
  console.print("• Same data, fewer tokens")
578
755
 
579
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
+
580
960
  if __name__ == '__main__':
581
961
  main(obj={})