Skip to content

Commit 7dd6174

Browse files
James Zhuclaude
andcommitted
Add 'cam prompt update' command with --file option
- Add new 'update' command to allow updating configured prompts - Support reading content from files with --file/-f flag - Allow updating description, name, and default status - Improve status command to show file paths for installed prompts - Add hidden alias 'edit' for update command 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent f29fbcc commit 7dd6174

File tree

1 file changed

+82
-5
lines changed

1 file changed

+82
-5
lines changed

code_assistant_manager/cli/prompts_commands.py

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,82 @@ def add_prompt(
144144
typer.echo(f" Set as default prompt")
145145

146146

147+
@prompt_app.command("update")
148+
def update_prompt(
149+
name: str = typer.Argument(..., help="Name of the prompt to update"),
150+
description: Optional[str] = typer.Option(None, "--description", "-d", help="Update the description"),
151+
file: Optional[Path] = typer.Option(None, "--file", "-f", help="Read new content from file"),
152+
new_name: Optional[str] = typer.Option(None, "--name", "-n", help="Rename the prompt"),
153+
default: Optional[bool] = typer.Option(None, "--default/--no-default", help="Set or unset as default prompt"),
154+
):
155+
"""Update a configured prompt's content, description, name, or default status.
156+
157+
Examples:
158+
cam prompt update my-prompt -f updated-prompt.md
159+
cam prompt update my-prompt --description "Updated description"
160+
cam prompt update my-prompt --name "New Prompt Name" --default
161+
cam prompt update my-prompt -f prompt.md -d "New description" --default
162+
"""
163+
manager = _get_manager()
164+
165+
# Find the prompt by name
166+
prompt = _find_prompt_by_name(manager, name)
167+
if not prompt:
168+
typer.echo(f"Error: Prompt '{name}' not found")
169+
raise typer.Exit(1)
170+
171+
# Read content from file if provided
172+
content = None
173+
if file:
174+
if not file.exists():
175+
typer.echo(f"Error: File not found: {file}")
176+
raise typer.Exit(1)
177+
content = file.read_text()
178+
if not content.strip():
179+
typer.echo("Error: File is empty")
180+
raise typer.Exit(1)
181+
182+
# Check if new name conflicts with existing prompt
183+
if new_name and new_name != name:
184+
existing_prompt = _find_prompt_by_name(manager, new_name)
185+
if existing_prompt:
186+
typer.echo(f"Error: Prompt with name '{new_name}' already exists")
187+
raise typer.Exit(1)
188+
189+
# Update the prompt
190+
try:
191+
updated_prompt = manager.update_prompt(
192+
prompt_id=prompt.id,
193+
content=content,
194+
description=description,
195+
name=new_name,
196+
)
197+
198+
# Handle default status change
199+
if default is True:
200+
manager.clear_default() # Clear any existing default
201+
manager.set_default(prompt.id)
202+
typer.echo(f" Set as default prompt")
203+
elif default is False and prompt.is_default:
204+
manager.clear_default()
205+
typer.echo(f" Unset as default prompt")
206+
207+
typer.echo(f"{Colors.GREEN}{Colors.RESET} Updated prompt: {updated_prompt.name}")
208+
209+
if content:
210+
typer.echo(f" Content updated from file: {file}")
211+
212+
if description:
213+
typer.echo(f" Description updated")
214+
215+
if new_name and new_name != name:
216+
typer.echo(f" Renamed from '{name}' to '{new_name}'")
217+
218+
except Exception as e:
219+
typer.echo(f"Error: {e}")
220+
raise typer.Exit(1)
221+
222+
147223
@prompt_app.command("remove")
148224
def remove_prompt(
149225
name: str = typer.Argument(..., help="Prompt name to remove"),
@@ -325,8 +401,8 @@ def status(
325401
if project_dir is None:
326402
project_dir = Path.cwd()
327403

328-
# Build installation map: prompt_id -> [(app, level), ...]
329-
install_map = {} # prompt_id -> list of (app, level) tuples
404+
# Build installation map: prompt_id -> [(app, level, file_path), ...]
405+
install_map = {} # prompt_id -> list of (app, level, file_path) tuples
330406
untracked = [] # list of (app, level, preview) for untracked installs
331407

332408
for app in VALID_APP_TYPES:
@@ -348,7 +424,7 @@ def status(
348424
if installed_id:
349425
if installed_id not in install_map:
350426
install_map[installed_id] = []
351-
install_map[installed_id].append((app, level))
427+
install_map[installed_id].append((app, level, file_path))
352428
else:
353429
preview = content[:30].replace('\n', ' ')
354430
if len(content) > 30:
@@ -367,7 +443,7 @@ def status(
367443
# Show where this prompt is installed
368444
if prompt_id in install_map:
369445
locations = install_map[prompt_id]
370-
loc_strs = [f"{app}:{level}" for app, level in locations]
446+
loc_strs = [f"{app}:{level} ({file_path})" for app, level, file_path in locations]
371447
typer.echo(f" Installed: {Colors.GREEN}{', '.join(loc_strs)}{Colors.RESET}")
372448
else:
373449
typer.echo(f" Installed: {Colors.DIM}nowhere{Colors.RESET}")
@@ -388,11 +464,12 @@ def status(
388464
typer.echo(f"{Colors.BOLD}Orphaned Installations (prompt deleted):{Colors.RESET}\n")
389465
for pid in orphaned:
390466
locations = install_map[pid]
391-
loc_strs = [f"{app}:{level}" for app, level in locations]
467+
loc_strs = [f"{app}:{level} ({file_path})" for app, level, file_path in locations]
392468
typer.echo(f" {Colors.RED}{pid}{Colors.RESET} - installed at: {', '.join(loc_strs)}")
393469
typer.echo()
394470

395471

396472
# Hidden aliases
397473
prompt_app.command("ls", hidden=True)(list_prompts)
398474
prompt_app.command("rm", hidden=True)(remove_prompt)
475+
prompt_app.command("edit", hidden=True)(update_prompt)

0 commit comments

Comments
 (0)