Initial commit
This commit is contained in:
12
.claude-plugin/plugin.json
Normal file
12
.claude-plugin/plugin.json
Normal file
@@ -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"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -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.
|
||||||
69
plugin.lock.json
Normal file
69
plugin.lock.json
Normal file
@@ -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": []
|
||||||
|
}
|
||||||
|
}
|
||||||
423
skills/cli-agent-runner/SKILL.md
Normal file
423
skills/cli-agent-runner/SKILL.md
Normal file
@@ -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:
|
||||||
|
|
||||||
|
- `<session-name>`: A unique identifier for the session (alphanumeric, dash, underscore only; max 30 chars)
|
||||||
|
- `<agent-name>`: Optional agent definition to use for the session
|
||||||
|
- `<initial-prompt>`: The prompt or task description for a new session
|
||||||
|
- `<resume-prompt>`: The prompt or task description to continue an existing session's work
|
||||||
|
- `<POLL_INTERVAL>`: 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:
|
||||||
|
```
|
||||||
|
<path-to-skill-root-folder>/cli-agent-runner.sh
|
||||||
|
```
|
||||||
|
2. Store this path mentally for the rest of the conversation: <absolute-path-to-cli-agent-runner.sh>
|
||||||
|
3. Use the absolute path in all subsequent commands
|
||||||
|
|
||||||
|
**Example:**
|
||||||
|
```bash
|
||||||
|
# Use that exact path in all commands:
|
||||||
|
<absolute-path-to-cli-agent-runner.sh> new <session-name> -p "<prompt>"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** In all examples below, `cli-agent-runner.sh` represents the absolute path <absolute-path-to-cli-agent-runner.sh> 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 <session-name> -p "<initial-prompt>"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Creating a new session with an agent:**
|
||||||
|
```bash
|
||||||
|
./cli-agent-runner.sh new <session-name> --agent <agent-name> -p "<initial-prompt>"
|
||||||
|
```
|
||||||
|
|
||||||
|
**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 <session-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Resuming an existing session:**
|
||||||
|
```bash
|
||||||
|
./cli-agent-runner.sh resume <session-name> -p "<resume-prompt>"
|
||||||
|
```
|
||||||
|
|
||||||
|
**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: <result from session>
|
||||||
|
|
||||||
|
# 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 <session-name> -p "<initial-prompt>"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example for new session with agent:**
|
||||||
|
```bash
|
||||||
|
./cli-agent-runner.sh new <session-name> --agent <agent-name> -p "<initial-prompt>"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example for resuming session:**
|
||||||
|
```bash
|
||||||
|
./cli-agent-runner.sh resume <session-name> -p "<resume-prompt>"
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Initial Polling Wait:**
|
||||||
|
- Use Bash tool (NOT background): `sleep <POLL_INTERVAL>`
|
||||||
|
- 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 <POLL_INTERVAL>`
|
||||||
|
- 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:
|
||||||
|
<contents of requirements.md>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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/<session-name>.jsonl`
|
||||||
|
- **Metadata:** `.cli-agent-runner/agent-sessions/<session-name>.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/<agent-name>.json` (configuration)
|
||||||
|
- **Prompts:** `.cli-agent-runner/agents/<agent-name>.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.
|
||||||
589
skills/cli-agent-runner/cli-agent-runner.sh
Executable file
589
skills/cli-agent-runner/cli-agent-runner.sh
Executable file
@@ -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 <session-name> [--agent <agent-name>] [-p <prompt>]
|
||||||
|
cli-agent-runner.sh resume <session-name> [-p <prompt>]
|
||||||
|
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:
|
||||||
|
<session-name> Name of the session (alphanumeric, dash, underscore only; max 30 chars)
|
||||||
|
<agent-name> Name of the agent definition to use (optional for new command)
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-p <prompt> Session prompt (can be combined with stdin; -p content comes first)
|
||||||
|
--agent <name> 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" <<EOF
|
||||||
|
{
|
||||||
|
"session_name": "$session_name",
|
||||||
|
"agent": $([ -n "$agent_name" ] && echo "\"$agent_name\"" || echo "null"),
|
||||||
|
"created_at": "$timestamp",
|
||||||
|
"last_resumed_at": "$timestamp"
|
||||||
|
}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# Load session metadata
|
||||||
|
load_session_metadata() {
|
||||||
|
local session_name="$1"
|
||||||
|
local meta_file="$AGENT_SESSIONS_DIR/${session_name}.meta.json"
|
||||||
|
|
||||||
|
if [ ! -f "$meta_file" ]; then
|
||||||
|
# No metadata - treat as generic session (backward compatibility)
|
||||||
|
SESSION_AGENT=""
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
SESSION_AGENT=$(jq -r '.agent // empty' "$meta_file")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Update session metadata timestamp
|
||||||
|
update_session_metadata() {
|
||||||
|
local session_name="$1"
|
||||||
|
local agent_name="$2" # Optional: agent name if known
|
||||||
|
local meta_file="$AGENT_SESSIONS_DIR/${session_name}.meta.json"
|
||||||
|
local timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
||||||
|
|
||||||
|
if [ -f "$meta_file" ]; then
|
||||||
|
# Update last_resumed_at
|
||||||
|
jq ".last_resumed_at = \"$timestamp\"" "$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 <path>", 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 "$@"
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"name": "browser-tester",
|
||||||
|
"description": "Specialist in browser automation and end-to-end testing using Playwright"
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"playwright": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"@playwright/mcp@latest"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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.
|
||||||
282
skills/cli-agent-runner/references/CLI-AGENT-RUNNER.md
Normal file
282
skills/cli-agent-runner/references/CLI-AGENT-RUNNER.md
Normal file
@@ -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-name>/
|
||||||
|
├── 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
|
||||||
61
skills/cli-agent-runner/references/EXAMPLE-AGENTS.md
Normal file
61
skills/cli-agent-runner/references/EXAMPLE-AGENTS.md
Normal file
@@ -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.
|
||||||
Reference in New Issue
Block a user