248 lines
7.1 KiB
Python
Executable File
248 lines
7.1 KiB
Python
Executable File
#!/usr/bin/env -S uv run --script
|
|
# /// script
|
|
# requires-python = ">=3.10"
|
|
# dependencies = [
|
|
# "pydantic",
|
|
# "python-dotenv",
|
|
# "click",
|
|
# "rich",
|
|
# ]
|
|
# ///
|
|
"""
|
|
Run Claude Code slash commands from the command line.
|
|
|
|
Usage:
|
|
# Method 1: Direct execution (requires uv)
|
|
./adws/adw_slash_command.py /chore "Update documentation"
|
|
|
|
# Method 2: Using uv run
|
|
uv run adws/adw_slash_command.py /implement specs/<name-of-spec>.md
|
|
|
|
uv run adws/adw_slash_command.py /start
|
|
|
|
|
|
Examples:
|
|
# Run a slash command
|
|
./adws/adw_slash_command.py /chore "Add logging to agent.py"
|
|
|
|
# Run with specific model
|
|
./adws/adw_slash_command.py /implement plan.md --model opus
|
|
|
|
# Run from a different working directory
|
|
./adws/adw_slash_command.py /test --working-dir /path/to/project
|
|
|
|
# Use custom agent name
|
|
./adws/adw_slash_command.py /review --agent-name reviewer
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import json
|
|
from pathlib import Path
|
|
import click
|
|
from rich.console import Console
|
|
from rich.panel import Panel
|
|
from rich.table import Table
|
|
|
|
# Add the adw_modules directory to the path so we can import agent
|
|
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "adw_modules"))
|
|
|
|
from agent import (
|
|
AgentTemplateRequest,
|
|
AgentPromptResponse,
|
|
execute_template,
|
|
generate_short_id,
|
|
)
|
|
|
|
# Output file name constants
|
|
OUTPUT_JSONL = "cc_raw_output.jsonl"
|
|
OUTPUT_JSON = "cc_raw_output.json"
|
|
FINAL_OBJECT_JSON = "cc_final_object.json"
|
|
SUMMARY_JSON = "custom_summary_output.json"
|
|
|
|
|
|
@click.command()
|
|
@click.argument("slash_command", required=True)
|
|
@click.argument("args", nargs=-1) # Accept multiple optional arguments
|
|
@click.option(
|
|
"--model",
|
|
type=click.Choice(["sonnet", "opus", "haiku"]),
|
|
default="sonnet",
|
|
help="Claude model to use (sonnet=balanced, opus=max intelligence, haiku=fast & economical)",
|
|
)
|
|
@click.option(
|
|
"--working-dir",
|
|
type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True),
|
|
help="Working directory for command execution (default: current directory)",
|
|
)
|
|
@click.option(
|
|
"--agent-name",
|
|
default="executor",
|
|
help="Agent name for tracking (default: executor)",
|
|
)
|
|
def main(
|
|
slash_command: str,
|
|
args: tuple,
|
|
model: str,
|
|
working_dir: str,
|
|
agent_name: str,
|
|
):
|
|
"""Run Claude Code slash commands from the command line."""
|
|
console = Console()
|
|
|
|
# Generate a unique ID for this execution
|
|
adw_id = generate_short_id()
|
|
|
|
# Use current directory if no working directory specified
|
|
if not working_dir:
|
|
working_dir = os.getcwd()
|
|
|
|
# Create the template request
|
|
request = AgentTemplateRequest(
|
|
agent_name=agent_name,
|
|
slash_command=slash_command,
|
|
args=list(args), # Convert tuple to list
|
|
adw_id=adw_id,
|
|
model=model,
|
|
working_dir=working_dir,
|
|
)
|
|
|
|
# Create execution info table
|
|
info_table = Table(show_header=False, box=None, padding=(0, 1))
|
|
info_table.add_column(style="bold cyan")
|
|
info_table.add_column()
|
|
|
|
info_table.add_row("ADW ID", adw_id)
|
|
info_table.add_row("ADW Name", "adw_slash_command")
|
|
info_table.add_row("Command", slash_command)
|
|
info_table.add_row("Args", " ".join(args) if args else "(none)")
|
|
info_table.add_row("Model", model)
|
|
info_table.add_row("Working Dir", working_dir)
|
|
|
|
console.print(
|
|
Panel(
|
|
info_table,
|
|
title="[bold blue]🚀 Inputs[/bold blue]",
|
|
border_style="blue",
|
|
)
|
|
)
|
|
console.print()
|
|
|
|
try:
|
|
# Execute the slash command
|
|
with console.status("[bold yellow]Executing command...[/bold yellow]"):
|
|
response = execute_template(request)
|
|
|
|
# Display the result
|
|
if response.success:
|
|
# Success panel
|
|
result_panel = Panel(
|
|
response.output,
|
|
title="[bold green]✅ Success[/bold green]",
|
|
border_style="green",
|
|
padding=(1, 2),
|
|
)
|
|
console.print(result_panel)
|
|
|
|
if response.session_id:
|
|
console.print(
|
|
f"\n[bold cyan]Session ID:[/bold cyan] {response.session_id}"
|
|
)
|
|
else:
|
|
# Error panel
|
|
error_panel = Panel(
|
|
response.output,
|
|
title="[bold red]❌ Failed[/bold red]",
|
|
border_style="red",
|
|
padding=(1, 2),
|
|
)
|
|
console.print(error_panel)
|
|
|
|
if response.retry_code != "none":
|
|
console.print(
|
|
f"\n[bold yellow]Retry code:[/bold yellow] {response.retry_code}"
|
|
)
|
|
|
|
# Show output file info
|
|
console.print()
|
|
|
|
# Output files are in agents/<adw_id>/<agent_name>/
|
|
output_dir = f"./agents/{adw_id}/{agent_name}"
|
|
|
|
# Create the simple JSON summary file
|
|
simple_json_output = f"{output_dir}/{SUMMARY_JSON}"
|
|
|
|
# Determine the template file path
|
|
command_name = slash_command.lstrip("/") # Remove leading slash
|
|
path_to_slash_command_prompt = f".claude/commands/{command_name}.md"
|
|
|
|
with open(simple_json_output, "w") as f:
|
|
json.dump(
|
|
{
|
|
"adw_id": adw_id,
|
|
"slash_command": slash_command,
|
|
"args": list(args),
|
|
"path_to_slash_command_prompt": path_to_slash_command_prompt,
|
|
"model": model,
|
|
"working_dir": working_dir,
|
|
"success": response.success,
|
|
"session_id": response.session_id,
|
|
"retry_code": response.retry_code,
|
|
"output": response.output,
|
|
},
|
|
f,
|
|
indent=2,
|
|
)
|
|
|
|
# Files saved panel
|
|
files_table = Table(show_header=True, box=None)
|
|
files_table.add_column("File Type", style="bold cyan")
|
|
files_table.add_column("Path", style="dim")
|
|
files_table.add_column("Description", style="italic")
|
|
|
|
files_table.add_row(
|
|
"JSONL Stream",
|
|
f"{output_dir}/{OUTPUT_JSONL}",
|
|
"Raw streaming output from Claude Code",
|
|
)
|
|
files_table.add_row(
|
|
"JSON Array",
|
|
f"{output_dir}/{OUTPUT_JSON}",
|
|
"All messages as a JSON array",
|
|
)
|
|
files_table.add_row(
|
|
"Final Object",
|
|
f"{output_dir}/{FINAL_OBJECT_JSON}",
|
|
"Last message entry (final result)",
|
|
)
|
|
files_table.add_row(
|
|
"Summary",
|
|
simple_json_output,
|
|
"High-level execution summary with metadata",
|
|
)
|
|
|
|
console.print(
|
|
Panel(
|
|
files_table,
|
|
title="[bold blue]📄 Output Files[/bold blue]",
|
|
border_style="blue",
|
|
)
|
|
)
|
|
|
|
# Exit with appropriate code
|
|
sys.exit(0 if response.success else 1)
|
|
|
|
except Exception as e:
|
|
console.print(
|
|
Panel(
|
|
f"[bold red]{str(e)}[/bold red]",
|
|
title="[bold red]❌ Unexpected Error[/bold red]",
|
|
border_style="red",
|
|
)
|
|
)
|
|
sys.exit(2)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|