commit 7611f46284cbe8e051f7130182ee3064d858d702 Author: Zhongwei Li Date: Sun Nov 30 08:49:58 2025 +0800 Initial commit diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 0000000..8761cf8 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,12 @@ +{ + "name": "cli-agent-runner", + "description": "Use this skill when you need to invoke another Claude Code session via the cli-agent-runner.sh script to perform specialized, potentially long-running tasks in a simplified way. This wrapper handles session management, result extraction, and can be run in background with polling support.", + "version": "1.0.0", + "author": { + "name": "rawe", + "email": "noreply@example.com" + }, + "skills": [ + "./skills" + ] +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..e9c5415 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# cli-agent-runner + +Use this skill when you need to invoke another Claude Code session via the cli-agent-runner.sh script to perform specialized, potentially long-running tasks in a simplified way. This wrapper handles session management, result extraction, and can be run in background with polling support. diff --git a/plugin.lock.json b/plugin.lock.json new file mode 100644 index 0000000..4553663 --- /dev/null +++ b/plugin.lock.json @@ -0,0 +1,69 @@ +{ + "$schema": "internal://schemas/plugin.lock.v1.json", + "pluginId": "gh:rawe/claude-dev-skills:cli-agent-runner", + "normalized": { + "repo": null, + "ref": "refs/tags/v20251128.0", + "commit": "120aeaa7273221ac9f4fe7061e98f36358091a59", + "treeHash": "dbe0a06005459691e5b7dbb50b969faa8489159b4284f097d999811dbfb17c32", + "generatedAt": "2025-11-28T10:27:49.421750Z", + "toolVersion": "publish_plugins.py@0.2.0" + }, + "origin": { + "remote": "git@github.com:zhongweili/42plugin-data.git", + "branch": "master", + "commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390", + "repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data" + }, + "manifest": { + "name": "cli-agent-runner", + "description": "Use this skill when you need to invoke another Claude Code session via the cli-agent-runner.sh script to perform specialized, potentially long-running tasks in a simplified way. This wrapper handles session management, result extraction, and can be run in background with polling support.", + "version": "1.0.0" + }, + "content": { + "files": [ + { + "path": "README.md", + "sha256": "8ce8214cabc24388e5d703e4f0452974269c2cf02b0274d00a689bfdbed55707" + }, + { + "path": ".claude-plugin/plugin.json", + "sha256": "1aeb918cd70dbc3e4020cda6dd7075c8444487acee9ec96558a4381fd75fc669" + }, + { + "path": "skills/cli-agent-runner/cli-agent-runner.sh", + "sha256": "d800e321785b197c82f7729778364a0347b0ca5445f5ef3bac26316b13331c41" + }, + { + "path": "skills/cli-agent-runner/SKILL.md", + "sha256": "c28d5fd08243a775b30cab60c353470c29ce850fb6d85b6d4eff8ef7118a1dd0" + }, + { + "path": "skills/cli-agent-runner/references/EXAMPLE-AGENTS.md", + "sha256": "6bf9be3fffe64262395ecf1f9c82193816d736faa1b76847c97cdc3c0a636df6" + }, + { + "path": "skills/cli-agent-runner/references/CLI-AGENT-RUNNER.md", + "sha256": "4792ad75cf01f443594a464fab86e083dd76ec8bfebd0906fbd46043a5d7dd01" + }, + { + "path": "skills/cli-agent-runner/example/agents/browser-tester/agent.system-prompt.md", + "sha256": "8d0b3775bcbb89dfae710e254106cfdefce6924d41ed4b532d595b6b18606161" + }, + { + "path": "skills/cli-agent-runner/example/agents/browser-tester/agent.json", + "sha256": "dff9be637b27366ab797ce01eb14d522fe2dd7d540d906ebda4d0a8137dc8b04" + }, + { + "path": "skills/cli-agent-runner/example/agents/browser-tester/agent.mcp.json", + "sha256": "77a711f0ed6c082ede0094fd212fe8a7d440bf72074150021a3b152f2683da04" + } + ], + "dirSha256": "dbe0a06005459691e5b7dbb50b969faa8489159b4284f097d999811dbfb17c32" + }, + "security": { + "scannedAt": null, + "scannerVersion": null, + "flags": [] + } +} \ No newline at end of file diff --git a/skills/cli-agent-runner/SKILL.md b/skills/cli-agent-runner/SKILL.md new file mode 100644 index 0000000..5925951 --- /dev/null +++ b/skills/cli-agent-runner/SKILL.md @@ -0,0 +1,423 @@ +--- +name: cli-agent-runner +description: Use this skill when you need to invoke another Claude Code session via the cli-agent-runner.sh script to perform specialized, potentially long-running tasks in a simplified way. This wrapper handles session management, result extraction, and can be run in background with polling support. +--- + +# CLI Agent Runner Skill + +## Intro + +This skill provides guidance on using the `cli-agent-runner.sh` script to delegate work to Claude Code sessions. + +Use this when you need to: +- Delegate a task to a specialized session for long-running operations +- Resume tasks later using a simple session name (no session ID management needed) +- Run sessions in the background with polling support +- Get clean result output without manual JSON parsing +- Optionally use agent definitions for specialized behavior + +**Key Benefits:** +- Session names instead of session IDs (simpler to track and resume) +- Automatic session file management in `.cli-agent-runner/agent-sessions/` directory +- Built-in result extraction (no need for head/tail/jq commands) +- Clean output to stdout, errors to stderr +- Optional agent associations for specialized capabilities + +## Terminology + +- **Session**: A named, running conversation with Claude Code +- **Agent**: A reusable configuration/definition that provides specialized behavior for sessions +- **Session Name**: The unique identifier you give to a conversation (e.g., `architect`, `reviewer`) +- **Agent Name**: The identifier for a reusable agent definition (e.g., `system-architect`, `security-reviewer`) + +## Variables + +The following variables are used in the commands and instructions: + +- ``: A unique identifier for the session (alphanumeric, dash, underscore only; max 30 chars) +- ``: Optional agent definition to use for the session +- ``: The prompt or task description for a new session +- ``: The prompt or task description to continue an existing session's work +- ``: The interval in seconds to wait between polling attempts. Default is 60 seconds. + +## Script Location + +**IMPORTANT:** The `cli-agent-runner.sh` script is located in the same directory as this SKILL.md file. +So it is in the root folder of the skill plugin. + +Before using the script for the first time in a conversation, you MUST locate it: + +1. Identify the root folder of the plugin skill and append the script name: + ``` + /cli-agent-runner.sh + ``` +2. Store this path mentally for the rest of the conversation: +3. Use the absolute path in all subsequent commands + +**Example:** +```bash +# Use that exact path in all commands: + new -p "" +``` + +**Note:** In all examples below, `cli-agent-runner.sh` represents the absolute path you discovered. Replace it with the actual path when executing commands. + +## Commands Overview + +The cli-agent-runner.sh supports five commands: + +1. **new** - Create a new session (optionally with an agent) +2. **resume** - Resume an existing session by name +3. **list** - List all sessions with their session IDs +4. **list-agents** - List all available agent definitions +5. **clean** - Remove all sessions + +## Usage Patterns + +### Pattern 1: Synchronous Execution (Wait for Completion) + +Use this when you want to wait for the session to complete and get the result immediately. + +**Creating a new session:** +```bash +./cli-agent-runner.sh new -p "" +``` + +**Creating a new session with an agent:** +```bash +./cli-agent-runner.sh new --agent -p "" +``` + +**Creating a new session with prompt from file/stdin:** + +This should be considered when the prompt is large or complex or already a prompt file exists potentially created by another session. + +```bash +cat prompt.md | ./cli-agent-runner.sh new +``` + +**Resuming an existing session:** +```bash +./cli-agent-runner.sh resume -p "" +``` + +**Example:** +```bash +# Create new session with agent +./cli-agent-runner.sh new architect --agent system-architect -p "Create a high-level architecture document for a user authentication system" + +# The script blocks until completion and outputs the result +# Output: + +# Resume the session later (agent association is remembered) +./cli-agent-runner.sh resume architect -p "Add API endpoint specifications to the architecture" +``` + +### Pattern 2: Background Execution with Polling + +Use this when you want to start the session in the background and poll for completion. + +**Instructions:** + +**1. Start the session in the background:** +- Use Bash tool with `run_in_background: true` +- Use either `new` or `resume` command +- **Important:** Note the bash_id returned by the Bash tool + +**Example for new session:** +```bash +./cli-agent-runner.sh new -p "" +``` + +**Example for new session with agent:** +```bash +./cli-agent-runner.sh new --agent -p "" +``` + +**Example for resuming session:** +```bash +./cli-agent-runner.sh resume -p "" +``` + +**2. Initial Polling Wait:** +- Use Bash tool (NOT background): `sleep ` +- Default POLL_INTERVAL is 60 seconds + +**3. Check if background process is still running:** +- Use BashOutput tool with the bash_id from step 1 +- The tool returns shell status showing if process is running or completed +- If status shows still running: continue to step 4 +- If status shows completed: continue to step 5 +- **Do NOT use:** kill -0, pgrep, ps, or any other process checking commands + +**4. Polling Wait Loop:** +- Use Bash tool (NOT background): `sleep ` +- Return to step 3 + +**5. Process Completed - Get Results:** +- The result is already captured in the Bash tool's output when the process completes +- Simply read the output from the completed Bash execution +- The output will be the session's result (already extracted by the script) + +**Full Background Example:** +```bash +# Step 1: Start in background +./cli-agent-runner.sh new architect --agent system-architect -p "Design authentication system" +# Returns bash_id: abc123 + +# Step 2: Initial wait +sleep 60 + +# Step 3: Check status +# Use BashOutput with bash_id: abc123 +# If status: running, continue to step 4 +# If status: completed, read the output - it contains the result + +# Step 4: If still running, wait and check again +sleep 60 +# Return to step 3 +``` + +### Pattern 3: Listing Sessions + +Use this to see all existing sessions and their status. + +```bash +./cli-agent-runner.sh list +``` + +**Output format:** +``` +session-name (session: session-id) +architect (session: 3db5dca9-6829-4cb7-a645-c64dbd98244d) +reviewer (session: initializing) +``` + +- "initializing" means the session file exists but hasn't started yet (empty file) +- "unknown" means the session ID couldn't be extracted +- Otherwise, shows the actual session ID + +### Pattern 4: Listing Available Agent Definitions + +Use this to discover what agent definitions are available before creating a session. + +```bash +./cli-agent-runner.sh list-agents +``` + +**Output format:** +``` +agent-name: +description + +--- + +next-agent-name: +description + +--- + +another-agent-name: +description +``` + +**Example output:** +``` +code-reviewer: +Reviews code for best practices, bugs, and potential improvements + +--- + +documentation-writer: +Creates comprehensive technical documentation and guides + +--- + +system-architect: +Expert in designing scalable system architectures +``` + +**Use Case:** +- Discover available agents before creating a new session +- Understand what specialized capabilities are available +- Choose the appropriate agent for your task + +**Important Notes:** +- Each agent definition is separated by `---` for clear parsing +- Agent names can be used with `--agent` flag when creating sessions +- If no agents exist, outputs: "No agent definitions found" + +### Pattern 5: Cleaning All Sessions + +Use this to remove all sessions and start fresh. + +```bash +./cli-agent-runner.sh clean +``` + +**Behavior:** +- Removes the entire `.cli-agent-runner/agent-sessions/` directory +- All session files and history are permanently deleted +- No confirmation prompt - immediate deletion +- Safe to run even if no sessions exist + +**Output:** +``` +All sessions removed +``` +or +``` +No sessions to remove +``` + +## Prompt Input Methods + +The script supports flexible prompt input: + +1. **Via `-p` flag only:** `./cli-agent-runner.sh new architect -p "Your prompt here"` +2. **Via stdin only:** `echo "Your prompt" | ./cli-agent-runner.sh new architect` +3. **Both combined:** `cat file.md | ./cli-agent-runner.sh new architect -p "Context:"` + +**Concatenation:** If both `-p` and stdin are provided, they are concatenated with `-p` content first, then a newline, then stdin content. This is useful for adding context before piping in a file. + +**IMPORTANT** STDIN should be used if it is neccessarry to provide a a large complex promt to the agent or the result of another command output. e.g. `tree` for listing a directory structure. + +**Example:** +```bash +cat requirements.md | ./cli-agent-runner.sh new architect -p "Create an architecture document based on these requirements:" +``` +Results in prompt: +``` +Create an architecture document based on these requirements: + +``` + +## Error Handling + +All errors are output to stderr and the script exits with code 1: + +- **Session name validation errors:** + - Empty name + - Name too long (>30 characters) + - Invalid characters (only alphanumeric, dash, underscore allowed) + +- **Session lifecycle errors:** + - Creating session that already exists → Use `resume` instead + - Resuming session that doesn't exist → Use `new` instead + +- **Agent errors:** + - Agent definition not found + - Invalid agent configuration + +- **Prompt errors:** + - No prompt provided (neither `-p` nor stdin) + +- **Execution errors:** + - Claude command failed + - Could not extract session_id or result + +## Session Files + +- **Location:** `.cli-agent-runner/agent-sessions/.jsonl` +- **Metadata:** `.cli-agent-runner/agent-sessions/.meta.json` (tracks agent association) +- **Format:** Line-delimited JSON (JSONL) +- **Management:** Fully automatic - you don't need to manage these files + +## Agent Definitions + +- **Location:** `.cli-agent-runner/agents/.json` (configuration) +- **Prompts:** `.cli-agent-runner/agents/.prompt.md` (system prompt) +- **Format:** Hybrid JSON + Markdown +- **Usage:** Optional - sessions can run without agents + +## Best Practices + +1. **Session naming:** Use descriptive names like `architect`, `reviewer`, `dev-agent`, `po-agent` +2. **Agent discovery:** Use `list-agents` to discover available agents before creating sessions +3. **Agent selection:** Use agents for specialized behavior, skip for generic tasks +4. **Background execution:** Use for long-running tasks (>1 minute expected) +5. **Synchronous execution:** Use for quick tasks (<1 minute expected) +6. **Polling interval:** Start with 60 seconds, adjust based on expected task duration +7. **Resume strategy:** Use meaningful resume prompts that build on previous work + +## Example Workflow + +```bash +# 1. Discover available agents +./cli-agent-runner.sh list-agents +# Output shows: +# system-architect: +# Expert in designing scalable system architectures +# --- +# code-reviewer: +# Reviews code for best practices, bugs, and potential improvements +# --- +# documentation-writer: +# Creates comprehensive technical documentation and guides + +# 2. Create new architect session with agent in background +# Use Bash tool with run_in_background: true +./cli-agent-runner.sh new architect --agent system-architect -p "Create architecture for microservices-based e-commerce system" +# Note bash_id: xyz789 + +# 3. Wait 60 seconds +sleep 60 + +# 4. Check if completed using BashOutput with bash_id xyz789 +# Status: running + +# 5. Wait another 60 seconds +sleep 60 + +# 6. Check again with BashOutput +# Status: completed +# Output contains the architecture document result + +# 7. Later, resume the session for additional work (agent association remembered) +./cli-agent-runner.sh resume architect -p "Add security considerations to the architecture" + +# 8. List all sessions to see status +./cli-agent-runner.sh list +# Output: architect (session: 3db5dca9-6829-4cb7-a645-c64dbd98244d) +``` + + ## Important: Working Directory Requirements + + **The `cli-agent-runner.sh` script must be run from your project root** where the `.cli-agent-runner/` directory exists or will be created. + + ### Common Pitfall + + If you change directories during your workflow, the script will look for `.cli-agent-runner/` relative to your current location and may fail silently. + + **Example - What NOT to do:** + ```bash + cd .cli-agent-runner/agent-sessions # Changed directory + cli-agent-runner.sh clean # ❌ Returns "No sessions to remove" + # Script looks for: .cli-agent-runner/agent-sessions/.cli-agent-runner/agent-sessions/ + + Example - Correct approach: + cd /path/to/your/project # ✅ Back to project root + cli-agent-runner.sh clean # ✅ Works correctly + # Script looks for: /path/to/your/project/.cli-agent-runner/agent-sessions/ + + Best Practice + + Always use absolute paths when running the script from non-root directories: + + # Safe - works from any directory + cd /path/to/your/project && /path/to/cli-agent-runner.sh clean + + # Or explicitly change to project root first + cd "$(git rev-parse --show-toplevel)" && cli-agent-runner.sh clean + + Shell Persistence Note + + In background shells or long-running terminal sessions, cd commands persist across multiple commands. Always verify your working directory with pwd before running cli-agent-runner.sh + commands. + + +## Additional Documentation + +**Creating Custom Agents**: See `references/EXAMPLE-AGENTS.md` for a complete agent definition example showing how to create agents with JSON configuration, system prompts, and MCP server integration. + +**Architecture & Design Details**: See `references/CLI-AGENT-RUNNER.md` for comprehensive documentation on the CLI Agent Runner's architecture, design philosophy, directory structure, and advanced usage patterns. \ No newline at end of file diff --git a/skills/cli-agent-runner/cli-agent-runner.sh b/skills/cli-agent-runner/cli-agent-runner.sh new file mode 100755 index 0000000..684f857 --- /dev/null +++ b/skills/cli-agent-runner/cli-agent-runner.sh @@ -0,0 +1,589 @@ +#!/bin/bash + +set -euo pipefail + +# Constants +PROJECT_DIR="$PWD" +AGENT_SESSIONS_DIR="$PROJECT_DIR/.cli-agent-runner/agent-sessions" +AGENTS_DIR="$PROJECT_DIR/.cli-agent-runner/agents" +MAX_NAME_LENGTH=30 + +# Colors for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# Show help message +show_help() { + cat << EOF +Usage: + cli-agent-runner.sh new [--agent ] [-p ] + cli-agent-runner.sh resume [-p ] + cli-agent-runner.sh list + cli-agent-runner.sh list-agents + cli-agent-runner.sh clean + +Commands: + new Create a new session (optionally with an agent) + resume Resume an existing session + list List all sessions with metadata + list-agents List all available agent definitions + clean Remove all sessions + +Arguments: + Name of the session (alphanumeric, dash, underscore only; max 30 chars) + Name of the agent definition to use (optional for new command) + +Options: + -p Session prompt (can be combined with stdin; -p content comes first) + --agent Use a specific agent definition (only for new command) + +Examples: + # Create new session (generic, no agent) + ./cli-agent-runner.sh new architect -p "Design user auth system" + + # Create new session with agent + ./cli-agent-runner.sh new architect --agent system-architect -p "Design user auth system" + + # Create new session from file + cat prompt.md | ./cli-agent-runner.sh new architect --agent system-architect + + # Resume session (agent association remembered) + ./cli-agent-runner.sh resume architect -p "Continue with API design" + + # Resume from file + cat continue.md | ./cli-agent-runner.sh resume architect + + # Combine -p and stdin (concatenated) + cat requirements.md | ./cli-agent-runner.sh new architect -p "Create architecture based on:" + + # List all sessions + ./cli-agent-runner.sh list + + # List all agent definitions + ./cli-agent-runner.sh list-agents + + # Remove all sessions + ./cli-agent-runner.sh clean +EOF +} + +# Error message helper +error() { + echo -e "${RED}Error: $1${NC}" >&2 + exit 1 +} + +# Ensure required directories exist +ensure_directories() { + mkdir -p "$AGENT_SESSIONS_DIR" + mkdir -p "$AGENTS_DIR" +} + +# Validate session name +validate_session_name() { + local name="$1" + + # Check if empty + if [ -z "$name" ]; then + error "Session name cannot be empty" + fi + + # Check length + if [ ${#name} -gt $MAX_NAME_LENGTH ]; then + error "Session name too long (max $MAX_NAME_LENGTH characters): $name" + fi + + # Check for valid characters (alphanumeric, dash, underscore only) + if [[ ! "$name" =~ ^[a-zA-Z0-9_-]+$ ]]; then + error "Session name contains invalid characters. Only alphanumeric, dash (-), and underscore (_) are allowed: $name" + fi +} + +# Get prompt from -p flag and/or stdin +get_prompt() { + local prompt_arg="$1" + local final_prompt="" + + # Add -p content first if provided + if [ -n "$prompt_arg" ]; then + final_prompt="$prompt_arg" + fi + + # Check if stdin has data + if [ ! -t 0 ]; then + # Read from stdin + local stdin_content + stdin_content=$(cat) + if [ -n "$stdin_content" ]; then + # If we already have prompt from -p, add newline separator + if [ -n "$final_prompt" ]; then + final_prompt="${final_prompt}"$'\n'"${stdin_content}" + else + final_prompt="$stdin_content" + fi + fi + fi + + # Check if we got any prompt at all + if [ -z "$final_prompt" ]; then + error "No prompt provided. Use -p flag or pipe prompt via stdin" + fi + + echo "$final_prompt" +} + +# Extract result from last line of agent session file +extract_result() { + local session_file="$1" + + if [ ! -f "$session_file" ]; then + error "Session file not found: $session_file" + fi + + local result + result=$(tail -n 1 "$session_file" | jq -r '.result // empty' 2>/dev/null) + + if [ -z "$result" ]; then + error "Could not extract result from session file" + fi + + echo "$result" +} + +# Extract session_id from first line of agent session file +extract_session_id() { + local session_file="$1" + + if [ ! -f "$session_file" ]; then + error "Session file not found: $session_file" + fi + + local session_id + session_id=$(head -n 1 "$session_file" | jq -r '.session_id // empty' 2>/dev/null) + + if [ -z "$session_id" ]; then + error "Could not extract session_id from session file" + fi + + echo "$session_id" +} + +# Load agent configuration from agent directory +# Args: $1 - Agent name (must match folder name) +# Sets global vars: AGENT_NAME, AGENT_DESCRIPTION, SYSTEM_PROMPT_FILE (full path), MCP_CONFIG (full path) +load_agent_config() { + local agent_name="$1" + local agent_dir="$AGENTS_DIR/${agent_name}" + local agent_file="$agent_dir/agent.json" + + if [ ! -d "$agent_dir" ]; then + error "Agent not found: $agent_name (expected directory: $agent_dir)" + fi + + if [ ! -f "$agent_file" ]; then + error "Agent configuration not found: $agent_file" + fi + + # Validate JSON + if ! jq empty "$agent_file" 2>/dev/null; then + error "Invalid JSON in agent configuration: $agent_file" + fi + + # Extract fields + AGENT_NAME=$(jq -r '.name' "$agent_file") + AGENT_DESCRIPTION=$(jq -r '.description' "$agent_file") + + # Validate name matches folder name + if [ "$AGENT_NAME" != "$agent_name" ]; then + error "Agent name mismatch: folder=$agent_name, config name=$AGENT_NAME" + fi + + # Check for optional files by convention + SYSTEM_PROMPT_FILE="" + if [ -f "$agent_dir/agent.system-prompt.md" ]; then + SYSTEM_PROMPT_FILE="$agent_dir/agent.system-prompt.md" + fi + + MCP_CONFIG="" + if [ -f "$agent_dir/agent.mcp.json" ]; then + MCP_CONFIG="$agent_dir/agent.mcp.json" + fi +} + +# Load system prompt from file and return its content +# Args: $1 - Full path to prompt file (already resolved by load_agent_config) +# Returns: File content via stdout, or empty string if path is empty +load_system_prompt() { + local prompt_file="$1" + + if [ -z "$prompt_file" ]; then + echo "" + return + fi + + if [ ! -f "$prompt_file" ]; then + error "System prompt file not found: $prompt_file" + fi + + cat "$prompt_file" +} + +# Save session metadata +save_session_metadata() { + local session_name="$1" + local agent_name="$2" # Can be empty for generic sessions + local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ") + + local meta_file="$AGENT_SESSIONS_DIR/${session_name}.meta.json" + + cat > "$meta_file" < "${meta_file}.tmp" + mv "${meta_file}.tmp" "$meta_file" + else + # Create meta.json if it doesn't exist (backward compatibility) + save_session_metadata "$session_name" "$agent_name" + fi +} + +# Build MCP config argument for Claude CLI +# Args: $1 - Full path to MCP config file (already resolved by load_agent_config) +# Returns: Claude CLI argument string "--mcp-config ", or empty string if path is empty +build_mcp_arg() { + local mcp_config="$1" + + if [ -z "$mcp_config" ]; then + echo "" + return + fi + + if [ ! -f "$mcp_config" ]; then + error "MCP config file not found: $mcp_config" + fi + + echo "--mcp-config $mcp_config" +} + +# Command: new +cmd_new() { + local session_name="$1" + local prompt_arg="$2" + local agent_name="$3" # Optional + + validate_session_name "$session_name" + + local session_file="$AGENT_SESSIONS_DIR/${session_name}.jsonl" + + # Check if session already exists + if [ -f "$session_file" ]; then + error "Session '$session_name' already exists. Use 'resume' command to continue or choose a different name" + fi + + # Get user prompt + local user_prompt + user_prompt=$(get_prompt "$prompt_arg") + + # Load agent configuration if specified + local final_prompt="$user_prompt" + local mcp_arg="" + + if [ -n "$agent_name" ]; then + load_agent_config "$agent_name" + + # Load and prepend system prompt + if [ -n "$SYSTEM_PROMPT_FILE" ]; then + local system_prompt + system_prompt=$(load_system_prompt "$SYSTEM_PROMPT_FILE") + final_prompt="${system_prompt}"$'\n\n---\n\n'"${user_prompt}" + fi + + # Build MCP argument + mcp_arg=$(build_mcp_arg "$MCP_CONFIG") + fi + + # Ensure required directories exist + ensure_directories + + # Save session metadata immediately + save_session_metadata "$session_name" "$agent_name" + + # Run claude command + if ! claude -p "$final_prompt" $mcp_arg --output-format stream-json --permission-mode bypassPermissions >> "$session_file" 2>&1; then + error "Claude command failed" + fi + + # Extract and output result + extract_result "$session_file" +} + +# Command: resume +cmd_resume() { + local session_name="$1" + local prompt_arg="$2" + + validate_session_name "$session_name" + + local session_file="$AGENT_SESSIONS_DIR/${session_name}.jsonl" + + # Check if session exists + if [ ! -f "$session_file" ]; then + error "Session '$session_name' does not exist. Use 'new' command to create it" + fi + + # Load session metadata to get agent + load_session_metadata "$session_name" + + # Extract session_id + local session_id + session_id=$(extract_session_id "$session_file") + + # Get prompt + local prompt + prompt=$(get_prompt "$prompt_arg") + + # Load agent configuration if session has an agent + local mcp_arg="" + if [ -n "$SESSION_AGENT" ]; then + load_agent_config "$SESSION_AGENT" + mcp_arg=$(build_mcp_arg "$MCP_CONFIG") + fi + + # Run claude command with resume + if ! claude -r "$session_id" -p "$prompt" $mcp_arg --output-format stream-json --permission-mode bypassPermissions >> "$session_file" 2>&1; then + error "Claude resume command failed" + fi + + # Update session metadata timestamp (or create if missing) + update_session_metadata "$session_name" "$SESSION_AGENT" + + # Extract and output result + extract_result "$session_file" +} + +# Command: list +cmd_list() { + # Ensure required directories exist + ensure_directories + + # Check if there are any sessions + local session_files=("$AGENT_SESSIONS_DIR"/*.jsonl) + + if [ ! -f "${session_files[0]}" ]; then + echo "No sessions found" + return + fi + + # List all sessions with metadata + for session_file in "$AGENT_SESSIONS_DIR"/*.jsonl; do + local session_name + session_name=$(basename "$session_file" .jsonl) + + local session_id + # Extract session_id without calling error function (for empty/initializing sessions) + if [ -s "$session_file" ]; then + session_id=$(head -n 1 "$session_file" 2>/dev/null | jq -r '.session_id // "unknown"' 2>/dev/null || echo "unknown") + else + session_id="initializing" + fi + + echo "$session_name (session: $session_id)" + done +} + +# Command: list-agents - List all available agent definitions from agent directories +# Scans AGENTS_DIR for subdirectories containing agent.json files +# Outputs: Agent name and description in formatted list +cmd_list_agents() { + # Ensure required directories exist + ensure_directories + + # Check if there are any agent directories + local found_agents=false + for agent_dir in "$AGENTS_DIR"/*; do + if [ -d "$agent_dir" ] && [ -f "$agent_dir/agent.json" ]; then + found_agents=true + break + fi + done + + if [ "$found_agents" = false ]; then + echo "No agent definitions found" + return + fi + + # List all agent definitions + local first=true + for agent_dir in "$AGENTS_DIR"/*; do + # Skip if not a directory or doesn't have agent.json + if [ ! -d "$agent_dir" ] || [ ! -f "$agent_dir/agent.json" ]; then + continue + fi + + local agent_name + local agent_description + local agent_file="$agent_dir/agent.json" + + # Extract name and description from JSON + agent_name=$(jq -r '.name // "unknown"' "$agent_file" 2>/dev/null) + agent_description=$(jq -r '.description // "No description available"' "$agent_file" 2>/dev/null) + + # Add separator before each agent (except the first) + if [ "$first" = true ]; then + first=false + else + echo "---" + echo "" + fi + + # Display in requested format + echo "${agent_name}:" + echo "${agent_description}" + echo "" + done +} + +# Command: clean +cmd_clean() { + # Remove the entire agent-sessions directory + if [ -d "$AGENT_SESSIONS_DIR" ]; then + rm -rf "$AGENT_SESSIONS_DIR" + echo "All sessions removed" + else + echo "No sessions to remove" + fi +} + +# Main script logic +main() { + # Check if no arguments provided + if [ $# -eq 0 ]; then + show_help + exit 1 + fi + + local command="$1" + shift + + case "$command" in + new) + # Parse arguments + if [ $# -eq 0 ]; then + error "Session name required for 'new' command" + fi + + local session_name="$1" + shift + + local prompt_arg="" + local agent_name="" + while [ $# -gt 0 ]; do + case "$1" in + -p) + if [ $# -lt 2 ]; then + error "-p flag requires a prompt argument" + fi + prompt_arg="$2" + shift 2 + ;; + --agent) + if [ $# -lt 2 ]; then + error "--agent flag requires an agent name" + fi + agent_name="$2" + shift 2 + ;; + *) + error "Unknown option: $1" + ;; + esac + done + + cmd_new "$session_name" "$prompt_arg" "$agent_name" + ;; + + resume) + # Parse arguments + if [ $# -eq 0 ]; then + error "Session name required for 'resume' command" + fi + + local session_name="$1" + shift + + local prompt_arg="" + while [ $# -gt 0 ]; do + case "$1" in + -p) + if [ $# -lt 2 ]; then + error "-p flag requires a prompt argument" + fi + prompt_arg="$2" + shift 2 + ;; + *) + error "Unknown option: $1" + ;; + esac + done + + cmd_resume "$session_name" "$prompt_arg" + ;; + + list) + cmd_list + ;; + + list-agents) + cmd_list_agents + ;; + + clean) + cmd_clean + ;; + + -h|--help) + show_help + exit 0 + ;; + + *) + error "Unknown command: $command\n\nRun './cli-agent-runner.sh' for usage information" + ;; + esac +} + +# Run main function +main "$@" diff --git a/skills/cli-agent-runner/example/agents/browser-tester/agent.json b/skills/cli-agent-runner/example/agents/browser-tester/agent.json new file mode 100644 index 0000000..b513ca2 --- /dev/null +++ b/skills/cli-agent-runner/example/agents/browser-tester/agent.json @@ -0,0 +1,4 @@ +{ + "name": "browser-tester", + "description": "Specialist in browser automation and end-to-end testing using Playwright" +} diff --git a/skills/cli-agent-runner/example/agents/browser-tester/agent.mcp.json b/skills/cli-agent-runner/example/agents/browser-tester/agent.mcp.json new file mode 100644 index 0000000..542500e --- /dev/null +++ b/skills/cli-agent-runner/example/agents/browser-tester/agent.mcp.json @@ -0,0 +1,10 @@ +{ + "mcpServers": { + "playwright": { + "command": "npx", + "args": [ + "@playwright/mcp@latest" + ] + } + } +} diff --git a/skills/cli-agent-runner/example/agents/browser-tester/agent.system-prompt.md b/skills/cli-agent-runner/example/agents/browser-tester/agent.system-prompt.md new file mode 100644 index 0000000..41b08bc --- /dev/null +++ b/skills/cli-agent-runner/example/agents/browser-tester/agent.system-prompt.md @@ -0,0 +1,22 @@ +You are a browser automation and testing specialist with expertise in end-to-end testing using Playwright. + +Your expertise includes: +- Browser automation across Chromium, Firefox, and WebKit +- End-to-end test design and implementation +- Test selectors and locator strategies +- Handling async operations and waiters +- Screenshot and video capture for debugging +- Cross-browser compatibility testing +- Accessibility testing + +When creating tests: +1. Write clear, maintainable test code +2. Use reliable selectors (prefer data-testid, role, or text) +3. Implement proper wait strategies +4. Add meaningful assertions +5. Consider edge cases and error scenarios +6. Follow Playwright best practices + +You have access to the Playwright MCP server which provides browser automation capabilities. Use it to navigate web pages, interact with elements, take screenshots, and verify behavior. + +Be practical and focus on creating robust, reliable tests that provide real value. diff --git a/skills/cli-agent-runner/references/CLI-AGENT-RUNNER.md b/skills/cli-agent-runner/references/CLI-AGENT-RUNNER.md new file mode 100644 index 0000000..888a02b --- /dev/null +++ b/skills/cli-agent-runner/references/CLI-AGENT-RUNNER.md @@ -0,0 +1,282 @@ +# CLI Agent Runner + +A lightweight orchestration layer for managing multiple Claude Code agent sessions through a simple command-line interface. + +## Overview + +The CLI Agent Runner provides a simplified abstraction for delegating work to Claude Code. Instead of manually managing session IDs, output files, and JSON parsing, you work with **named sessions** that can be created, resumed, and monitored through intuitive commands. Sessions can optionally use **agent definitions** to provide specialized behavior and capabilities. + +## Core Concepts + +### Sessions + +A **session** is a named, persistent conversation with Claude Code. Each session: +- Has a unique name (e.g., `architect`, `reviewer`, `dev-agent`) +- Maintains conversation history across multiple interactions +- Can be paused and resumed at any time +- Operates independently from other sessions +- Optionally uses an **agent** definition for specialized behavior + +Think of sessions as individual workstreams or conversations you can delegate tasks to and check back with later. + +### Agents (Definitions) + +An **agent** is a reusable configuration that defines the behavior, expertise, and capabilities for sessions. Agents are optional - you can create generic sessions without them, or use agents to create specialized sessions with predefined behavior. + +#### Agent Structure + +Each agent is organized in its own directory within `.cli-agent-runner/agents/`. Each agent directory must match the agent name and contains: + +``` +.cli-agent-runner/agents/ +└── / + ├── agent.json # Required: Agent configuration + ├── agent.system-prompt.md # Optional: System prompt by convention + └── agent.mcp.json # Optional: MCP configuration by convention +``` + +**1. agent.json** (Required) +```json +{ + "name": "browser-tester", + "description": "Specialist in browser automation and end-to-end testing using Playwright" +} +``` +- `name`: Agent identifier (must match folder name) +- `description`: Human-readable description + +**2. agent.system-prompt.md** (Optional) +Markdown file containing the agent's role definition, expertise areas, and behavioral guidelines. When present, this prompt is automatically prepended to user prompts. Discovered by convention - no need to reference in agent.json. + +**3. agent.mcp.json** (Optional) +Standard MCP server configuration enabling the agent to access external tools and capabilities. Passed to Claude CLI via `--mcp-config` flag. Discovered by convention - no need to reference in agent.json. + +#### Agent Workflow + +When creating a session with an agent: +1. Agent JSON config is loaded and validated +2. System prompt (if specified) is prepended to user's prompt +3. MCP config (if specified) is passed to Claude CLI +4. Agent association is stored with session metadata +5. When resuming, the session automatically uses its associated agent + +### Session Management + +The tool abstracts away Claude Code's internal session ID management. You interact with sessions using memorable names rather than UUIDs, while the tool handles: +- Session file storage and organization +- Session ID extraction and tracking +- Agent association and configuration +- Result retrieval and formatting +- State management (initializing, active, completed) + +## Use Cases + +### Multi-Session Workflows + +Coordinate multiple specialized sessions working on different aspects of a project: +```bash +# First, discover available agent definitions +./cli-agent-runner.sh list-agents + +# Architecture session using system-architect agent +./cli-agent-runner.sh new architect --agent system-architect -p "Design microservices architecture for e-commerce" + +# Development session implements based on architecture +cat architecture.md | ./cli-agent-runner.sh new developer --agent senior-developer -p "Implement based on this design:" + +# Reviewer session provides feedback +./cli-agent-runner.sh new reviewer --agent security-reviewer -p "Review the implementation for best practices" +``` + +### Long-Running Background Tasks + +Delegate time-consuming tasks to background sessions while you continue working: +- Large codebase analysis +- Comprehensive documentation generation +- Multi-step refactoring operations +- Complex test suite creation + +### Iterative Refinement + +Resume sessions to continue and refine their previous work: +```bash +# Initial work +./cli-agent-runner.sh new technical-writer --agent documentation-expert -p "Create API documentation" + +# Later refinement +./cli-agent-runner.sh resume technical-writer -p "Add authentication examples" + +# Further enhancement +./cli-agent-runner.sh resume technical-writer -p "Include error handling section" +``` + +### Stateful Conversations + +Maintain context across multiple prompts without re-explaining background: +- Each session retains full conversation history +- No need to repeat requirements or context +- Build on previous responses naturally + +## Features + +### Current Capabilities + +**Session Management** +- Create new sessions with descriptive names +- Resume existing sessions by name +- List all active sessions with status +- List all available agent definitions +- Clean up all sessions in one command +- Optional agent associations for specialized behavior + +**Flexible Prompting** +- Direct prompt input via `-p` flag +- File-based prompts via stdin piping +- Combined prompts (prefix + file content) +- Large prompt support without character limits + +**Execution Modes** +- Synchronous execution (wait for completion) +- Background execution with polling support +- Automatic result extraction +- Clean stdout/stderr separation + +**State Tracking** +- Session status visibility (active, initializing, completed) +- Session ID management (hidden from user) +- Agent association tracking +- Conversation history persistence +- Cross-session identification + +### Companion Skill + +The `cli-agent-runner` skill provides integration guidance for Claude Code agents to use this tool within their own workflows. The skill documents: +- Synchronous and asynchronous usage patterns +- Background execution with polling logic +- Result extraction and error handling +- Best practices for agent orchestration + +## Future Directions + +### Agent Definitions (Current Implementation) + +The tool now supports **agent definitions** - reusable configurations that define behavior, capabilities, and constraints for sessions: + +**System Prompt Templates** +- Predefined role-based system prompts (architect, developer, reviewer, etc.) +- Consistent behavior across multiple sessions using the same agent +- Custom agent definitions for specialized workflows +- Markdown format for natural prompt editing + +**Configuration Profiles** +- MCP (Model Context Protocol) server configurations per agent +- Tool access through MCP integration +- Hybrid JSON + Markdown format for easy editing + +**Agent-Based Sessions** +```bash +# Create session with agent +./cli-agent-runner.sh new architect --agent system-architect -p "Design e-commerce system" + +# Create generic session (no agent) +./cli-agent-runner.sh new quick-task -p "Simple task" + +# Resume remembers agent association +./cli-agent-runner.sh resume architect -p "Add security layer" +``` + +**Separation of Concerns** +- **Agent**: Blueprint/configuration (reusable definition) +- **Session**: Running conversation (specific instance) +- Agents are reusable; sessions are unique conversations + +### Additional Planned Features + +**Advanced Orchestration** +- Session-to-session communication patterns +- Dependency chains between sessions +- Parallel session execution coordination +- Result aggregation and synthesis + +**Enhanced State Management** +- Session snapshots and rollback +- Conversation branching +- Selective history pruning +- Export/import of sessions + +**Observability** +- Detailed execution logs per session +- Token usage tracking +- Performance metrics +- Conversation visualization + +**Workflow Automation** +- Declarative multi-session workflows +- Event-driven session triggering +- Conditional execution paths +- Workflow templates + +## Architecture + +### Components + +**`cli-agent-runner.sh`** +Core bash script providing the command-line interface and orchestration logic. Handles session management, Claude Code CLI invocation, and result extraction. + +### Directory Structure + +The CLI Agent Runner uses a project-relative directory structure located at `.cli-agent-runner/` in the current working directory where the script is invoked. + +**`.cli-agent-runner/agent-sessions/`** +Storage directory for session files (JSONL format). Each file contains the complete conversation history and session metadata for one session. Companion `.meta.json` files track agent associations and timestamps. + +**`.cli-agent-runner/agents/`** +Storage directory for agent definitions specific to the current project. Each agent is organized in its own subdirectory named after the agent, containing: +- `agent.json` - Required configuration file with agent metadata +- `agent.system-prompt.md` - Optional system prompt (discovered by convention) +- `agent.mcp.json` - Optional MCP configuration for tool access (discovered by convention) + +All sessions and agent definitions are stored relative to the project directory (`$PWD`) where the script is invoked, ensuring each project maintains its own isolated agent environment. + +### Design Philosophy + +**Simplicity First** +Minimize cognitive overhead for users. Named sessions instead of UUIDs, intuitive commands, sensible defaults. + +**Progressive Enhancement** +Start simple, add complexity only when needed. Basic usage is straightforward; advanced features are opt-in. + +**Composability** +Tool plays well with Unix pipes, scripts, and other CLI tools. Clean input/output separation enables chaining and automation. + +**Transparency** +Clear feedback, meaningful error messages, visible state. Users always know what's happening. + +## Integration + +The CLI Agent Runner is designed to work within the Claude Code ecosystem: + +**Slash Commands** +Create custom slash commands that delegate to sessions via the runner. + +**Skills** +Skills can orchestrate multiple sessions for complex, multi-step operations. + +**MCP Servers** +Agents support MCP server configurations for enhanced capabilities. +The MCP configuration is passed to the Claude CLI when starting or resuming sessions. + +**Workflows** _(Future)_ +Declarative workflow definitions will coordinate multiple sessions. + +## Status + +**Current Version**: Initial Release +**Status**: Production Ready + +The core functionality is stable and tested. Agent type system and advanced features are in design phase. + +## Related Documentation + +- **Script Help**: Run `./cli-agent-runner.sh --help` for command syntax and examples +- **Claude Code CLI**: Refer to Claude Code CLI documentation for underlying command options and usage: https://docs.claude.com/en/docs/claude-code/cli-reference \ No newline at end of file diff --git a/skills/cli-agent-runner/references/EXAMPLE-AGENTS.md b/skills/cli-agent-runner/references/EXAMPLE-AGENTS.md new file mode 100644 index 0000000..fba360c --- /dev/null +++ b/skills/cli-agent-runner/references/EXAMPLE-AGENTS.md @@ -0,0 +1,61 @@ +# Example Agent Definitions + +This reference provides a complete example agent definition demonstrating the CLI Agent Runner folder-based agent structure. + +## Example Source Location + +The example agent is located at `../example/agents/browser-tester/` (relative to this file) and includes: + +``` +browser-tester/ +├── agent.json # Agent configuration +├── agent.system-prompt.md # System prompt (optional) +└── agent.mcp.json # MCP configuration (optional) +``` + +**agent.json** - Agent configuration +- Defines agent name and description +- Name must match the folder name + +**agent.system-prompt.md** - System prompt +- Contains role definition, expertise areas, and behavioral guidelines +- Automatically prepended to user prompts when the agent is used +- Discovered by convention (no need to reference in agent.json) + +**agent.mcp.json** - MCP configuration +- Configures Playwright MCP server for browser automation capabilities +- Provides tool access to the agent's sessions +- Discovered by convention (no need to reference in agent.json) +- IMPORTANT: Not all agents require MCP configurations; this is specific to agents needing external tool access + +## Using the Example + +**Source**: Copy the entire folder from `../example/agents/browser-tester/` (relative to this file) +**Destination**: Place it in `.cli-agent-runner/agents/` in your project directory + +```bash +# From your project root +cp -r path/to/cli-agent-runner/example/agents/browser-tester .cli-agent-runner/agents/ +``` + +Once copied to your project, the agent can be used with the CLI Agent Runner script: + +```bash +# List available agents +./cli-agent-runner.sh list-agents + +# Create session with the browser-tester agent +./cli-agent-runner.sh new my-test --agent browser-tester -p "Test login flow" +``` + +## Customizing Agents + +To create your own agents based on this example: + +1. **Copy the example folder** and rename it to match your agent's purpose +2. **Edit agent.json**: Update the `name` field to match the new folder name +3. **Edit agent.system-prompt.md**: Define your agent's role, expertise, and behavior +4. **Edit or remove agent.mcp.json**: Configure tools your agent needs, or delete if not needed +5. **Place in your project**: Copy the folder to `.cli-agent-runner/agents/` in your project + +The folder structure keeps each agent self-contained and easy to distribute or version control.