diff --git a/.claude-plugin/README.md b/.claude-plugin/README.md new file mode 100644 index 00000000..e09945ac --- /dev/null +++ b/.claude-plugin/README.md @@ -0,0 +1,63 @@ +# agent-cli-dev Plugin for Claude Code + +This plugin teaches Claude Code how to spawn parallel AI coding agents in isolated git worktrees using `agent-cli dev`. + +## What It Does + +The plugin provides a skill that enables Claude Code to: + +- Create isolated git worktrees for parallel development +- Spawn AI coding agents (Claude, Codex, Gemini, Aider) in separate terminal tabs +- Manage multiple features/tasks simultaneously without branch conflicts +- Automatically set up project dependencies in new worktrees + +## Installation + +### Install agent-cli + +```bash +# Using uv (recommended) +uv tool install agent-cli + +# Or run directly without installing +uvx agent-cli dev new my-feature --agent --prompt "..." +``` + +### Install the Claude Code plugin + +```bash +# From the marketplace +claude plugin marketplace add basnijholt/agent-cli + +# Then install +claude plugin install agent-cli@agent-cli-dev +``` + +## Usage + +Once installed, Claude Code can automatically use this skill when you ask to: + +- "Work on multiple features in parallel" +- "Spawn agents for auth, payments, and notifications" +- "Create a worktree for this bug fix" +- "Delegate this task to a separate agent" + +## Key Commands + +```bash +# Create worktree with AI agent +agent-cli dev new my-feature --agent --prompt "Implement the login page" + +# Use prompt file for longer tasks +agent-cli dev new my-feature --agent --prompt-file task.md + +# Check status of all worktrees +agent-cli dev status + +# Clean up merged worktrees +agent-cli dev clean --merged +``` + +## Documentation + +Full documentation: [docs/commands/dev.md](https://github.com/basnijholt/agent-cli/blob/main/docs/commands/dev.md) diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json new file mode 100644 index 00000000..72df4441 --- /dev/null +++ b/.claude-plugin/marketplace.json @@ -0,0 +1,8 @@ +{ + "source": "./.claude-plugin", + "repository": "https://github.com/basnijholt/agent-cli", + "homepage": "https://github.com/basnijholt/agent-cli", + "documentation": "https://github.com/basnijholt/agent-cli/blob/main/docs/commands/dev.md", + "keywords": ["git", "worktree", "parallel", "agents", "development", "claude", "ai"], + "license": "MIT" +} diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 00000000..7edbc333 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,7 @@ +{ + "name": "agent-cli-dev", + "version": "1.0.0", + "author": "basnijholt", + "description": "Spawn parallel AI coding agents in isolated git worktrees. Creates isolated development environments with automatic project setup, letting you work on multiple features simultaneously with different AI agents (Claude, Codex, Gemini, Aider).", + "skills": ["./skills/agent-cli-dev"] +} diff --git a/.claude-plugin/skills/agent-cli-dev/SKILL.md b/.claude-plugin/skills/agent-cli-dev/SKILL.md new file mode 100644 index 00000000..82c5c62e --- /dev/null +++ b/.claude-plugin/skills/agent-cli-dev/SKILL.md @@ -0,0 +1,136 @@ +--- +name: agent-cli-dev +description: Spawns AI coding agents in isolated git worktrees. Use when the user asks to spawn or launch an agent, delegate a task to a separate agent, work in a separate worktree, or parallelize development across features. +--- + +# Parallel Development with agent-cli dev + +This skill teaches you how to spawn parallel AI coding agents in isolated git worktrees using the `agent-cli dev` command. + +## Installation + +If `agent-cli` is not available, install it first: + +```bash +# Install globally +uv tool install agent-cli + +# Or run directly without installing +uvx agent-cli dev new --agent --prompt "..." +``` + +## When to spawn parallel agents + +Spawn separate agents when: +- Multiple independent features/tasks can be worked on in parallel +- Tasks benefit from isolation (separate branches, no conflicts) +- Large refactoring that can be split by module/component +- Test-driven development (one agent for tests, one for implementation) + +Do NOT spawn when: +- Tasks are small and sequential +- Tasks have tight dependencies requiring constant coordination +- The overhead of context switching exceeds the benefit + +## Core command + +For short prompts: +```bash +agent-cli dev new --agent --prompt "Fix the login bug" +``` + +For longer prompts (recommended for multi-line or complex instructions): +```bash +agent-cli dev new --agent --prompt-file path/to/prompt.md +``` + +This creates: +1. A new git worktree with its own branch +2. Runs project setup (installs dependencies) +3. Saves your prompt to `.claude/TASK.md` in the worktree (for reference) +4. Opens a new terminal tab with an AI coding agent +5. Passes your prompt to the agent + +**Important**: Use `--prompt-file` for prompts longer than a single line. The `--prompt` option passes text through the shell, which can cause issues with special characters (exclamation marks, dollar signs, backticks, quotes) in ZSH and other shells. Using `--prompt-file` avoids all shell quoting issues. + +## Writing effective prompts for spawned agents + +Spawned agents work in isolation, so prompts must be **self-contained**. Include: + +1. **Clear task description**: What to implement/fix/refactor +2. **Relevant context**: File locations, patterns to follow, constraints +3. **Report request**: Ask the agent to write conclusions to `.claude/REPORT.md` + +### Using --prompt-file (recommended) + +For any prompt longer than a single sentence: + +1. Write the prompt to a temporary file (e.g., `.claude/spawn-prompt.md`) +2. Use `--prompt-file` to pass it to the agent +3. The file can be deleted after spawning + +Example workflow: +```bash +# 1. Write prompt to file (Claude does this with the Write tool) +# 2. Spawn agent with the file +agent-cli dev new my-feature --agent --prompt-file .claude/spawn-prompt.md +# 3. Optionally clean up +rm .claude/spawn-prompt.md +``` + +### Prompt template + +``` + + +Context: +- +- +- + +When complete, write a summary to .claude/REPORT.md including: +- What you implemented/changed +- Key decisions you made +- Any questions or concerns for review +``` + +## Checking spawned agent results + +After spawning, you can check progress: + +```bash +# List all worktrees and their status +agent-cli dev status + +# Read an agent's report +agent-cli dev run cat .claude/REPORT.md + +# Open the worktree in your editor +agent-cli dev editor +``` + +## Example: Multi-feature implementation + +If asked to implement auth, payments, and notifications: + +```bash +# Spawn three parallel agents +agent-cli dev new auth-feature --agent --prompt "Implement JWT authentication..." +agent-cli dev new payment-integration --agent --prompt "Add Stripe payment processing..." +agent-cli dev new email-notifications --agent --prompt "Implement email notification system..." +``` + +Each agent works independently in its own branch. Results can be reviewed and merged separately. + +## Key options + +| Option | Description | +|--------|-------------| +| `--agent` / `-a` | Start AI coding agent after creation | +| `--prompt` / `-p` | Initial prompt for the agent (short prompts only) | +| `--prompt-file` / `-P` | Read prompt from file (recommended for longer prompts) | +| `--from` / `-f` | Base branch (default: origin/main) | +| `--with-agent` | Specific agent: claude, aider, codex, gemini | +| `--agent-args` | Extra arguments for the agent | + +@examples.md diff --git a/.claude-plugin/skills/agent-cli-dev/examples.md b/.claude-plugin/skills/agent-cli-dev/examples.md new file mode 100644 index 00000000..e833eb96 --- /dev/null +++ b/.claude-plugin/skills/agent-cli-dev/examples.md @@ -0,0 +1,510 @@ +# Examples: Parallel Agent Workflows + +Real-world scenarios for spawning parallel AI coding agents, optimized for Claude 4.5 models. + +> **Note on prompts**: The examples below show prompt content inline for readability. In practice, **always use `--prompt-file`** for these multi-line prompts to avoid shell quoting issues: +> +> ```bash +> # Write prompt to file, then spawn +> agent-cli dev new my-feature --agent --prompt-file .claude/spawn-prompt.md +> ``` + +## Prompt structure guidelines + +Each prompt for a spawned agent should follow this structure: + +1. **Explicit task description** - Be specific about what to implement +2. **Workflow directive** - Read files in parallel, commit incrementally, verify before completing +3. **Code exploration** - Read and understand existing code before writing +4. **Context with motivation** - Explain why patterns matter +5. **Focused scope** - Keep solutions minimal, implement only what's requested +6. **Structured report** - Write conclusions to `.claude/REPORT.md` + +## Scenario 1: Multi-feature implementation + +**User request**: "Implement user auth, payment processing, and email notifications" + +**Strategy**: Three independent features → spawn three agents. + +```bash +agent-cli dev new auth-feature --agent --prompt "Implement JWT-based user authentication. + + +- Read multiple files in parallel when exploring the codebase +- Make incremental git commits as you complete each component +- Run tests and linting before writing your final report + + + +Start by reading these files (in parallel if independent): +- src/api/routes/ to understand existing endpoint patterns +- src/models/ to see how models are structured +- Any existing auth-related code to avoid duplication + +Think carefully about the existing patterns before designing your implementation. + + + +Backend is FastAPI in src/api/. This authentication system protects all user-facing endpoints, so reliability and security are critical. Follow the exact patterns in existing endpoints to maintain codebase consistency. + + + +Implement these endpoints following existing route patterns: +- POST /auth/register - create new user with password hashing +- POST /auth/login - validate credentials and return JWT token +- GET /auth/me - return current user (requires valid JWT) +- Create an auth dependency for protecting other routes +- Store JWT_SECRET in environment variable + + + +Keep the implementation simple and focused. Implement only what is requested. A working, minimal implementation is better than an over-designed one. Reuse existing abstractions where possible. + + + +After verifying tests pass and linting is clean, write to .claude/REPORT.md: + +## Summary +[2-3 sentences on what was implemented] + +## Files Changed +- path/to/file.py - description of change + +## Key Decisions +- Decision 1: rationale + +## Testing +How to verify the implementation works + +## Questions/Concerns +Any items needing review +" + +agent-cli dev new payment-integration --agent --prompt "Integrate Stripe payment processing. + + +- Read multiple files in parallel when exploring the codebase +- Make incremental git commits as you complete each component +- Run tests and linting before writing your final report + + + +Read these files to understand the codebase (parallelize independent reads): +- src/api/routes/ for endpoint patterns and error handling +- src/models/ for existing model patterns +- Any existing payment or billing code + +Only make claims about code you have actually read. + + + +This payment integration handles real money transactions and must be implemented correctly. Stripe webhooks are essential for tracking payment status - the system cannot rely solely on client-side confirmation. Use the stripe Python package and store STRIPE_SECRET_KEY in environment. + + + +- POST /payments/create-intent - create Stripe PaymentIntent, return client_secret +- POST /payments/webhook - handle Stripe webhook events (payment_intent.succeeded, payment_intent.failed) +- Add Payment model to track transaction status +- Include proper webhook signature verification for security + + + +Implement only what is specified. Focus on a working, secure implementation. Skip subscription handling, multiple payment methods, or other features unless explicitly requested. + + + +After verifying tests pass, write to .claude/REPORT.md: + +## Summary +[What was implemented] + +## Files Changed +[List with descriptions] + +## Security Considerations +[How webhook verification works, secret handling] + +## Testing +[How to test with Stripe test mode] + +## Questions/Concerns +[Any items for review] +" + +agent-cli dev new email-notifications --agent --prompt "Implement email notification system. + + +- Read multiple files in parallel when exploring the codebase +- Make incremental git commits as you complete each component +- Run tests and linting before writing your final report + + + +Start by reading the codebase to understand patterns: +- Examine src/api/ for how background tasks are handled +- Check existing configuration patterns for external services +- Look for template handling patterns + +Understand the existing architecture before implementing. + + + +Email notifications are user-facing and must be reliable. Background processing prevents blocking API responses. Template-based emails allow content changes without code changes. + + + +- Use an appropriate email library for the stack (e.g., fastapi-mail or aiosmtplib) +- Implement as background tasks to avoid blocking API responses +- Create templates for: welcome, password_reset, order_confirmation +- POST /notifications/send-test - endpoint for testing email delivery +- Store SMTP settings (host, port, user, password) in environment + + + +Implement the minimum required for reliable email delivery. Skip notification preferences, SMS, or push notifications unless requested. + + + +After verifying tests pass, write to .claude/REPORT.md with summary, files changed, library choice rationale, testing instructions, and any concerns. +" +``` + +## Scenario 2: Test-driven development + +**User request**: "Add a caching layer with comprehensive tests" + +**Strategy**: One agent writes tests first, another implements. + +```bash +agent-cli dev new cache-tests --agent --prompt "Write comprehensive tests for a caching layer. + + +Create a complete test suite that drives the implementation of a caching system. The tests define the interface - write them as if the implementation already exists. + + + +- Read test files in parallel to understand existing patterns +- Commit tests incrementally as you complete each test category +- Verify tests are syntactically valid before finishing + + + +First, explore the codebase (parallelize these reads): +- tests/ for existing test patterns and fixtures +- conftest.py for shared fixtures +- Project testing conventions + +Follow the exact testing patterns you find. + + + +The cache system should support: +- get(key: str) -> Any | None +- set(key: str, value: Any, ttl_seconds: int | None = None) -> None +- delete(key: str) -> bool +- clear() -> None +- Support for Redis backend and in-memory fallback + + + +Write tests in tests/test_cache.py using pytest: +- Basic get/set/delete operations +- TTL expiration (use time mocking) +- Cache miss returns None +- Backend switching/fallback behavior +- Concurrent access patterns +- Edge cases: empty keys, None values, large values + + + +Write only tests, not the implementation. The tests should fail initially and pass once implementation is complete. Write tests that verify behavior, not implementation details. + + + +When complete, write to .claude/REPORT.md: + +## Test Cases +| Test Name | What It Verifies | +|-----------|------------------| +| test_xxx | description | + +## Interface Decisions +- Why the interface is designed this way + +## Edge Cases Covered +- List of edge cases and why they matter + +## Implementation Suggestions +- Hints for the implementer +" +``` + +After reviewing the tests: + +```bash +agent-cli dev new cache-impl --from cache-tests --agent --prompt "Implement the caching layer to pass existing tests. + + +- Read all test files first to understand the complete interface +- Run tests frequently as you implement: pytest tests/test_cache.py -v +- Make incremental git commits after each passing test group +- Verify all tests pass before writing your report + + + +CRITICAL: Read the tests completely before writing any implementation. +- Read tests/test_cache.py to understand expected behavior +- Note the exact interface the tests expect +- Identify edge cases the tests check for + +The tests define the contract - implement to match them exactly. + + + +Implement in src/cache.py: +- CacheBackend abstract base class +- RedisBackend implementation (use redis-py) +- MemoryBackend implementation (dict-based with TTL support) +- Cache facade that selects backend based on configuration + + + +Implement exactly what the tests require. Skip features the tests don't verify. Skip distributed caching, cache warming, or advanced features unless tests require them. + + + +After ALL tests pass, write to .claude/REPORT.md: + +## Implementation Approach +[How the cache system works] + +## Test Results +[Output of pytest run showing all tests pass] + +## Deviations +[Any places where tests seemed incorrect or ambiguous] + +## Performance Notes +[Any performance considerations] +" +``` + +## Scenario 3: Large refactoring by module + +**User request**: "Refactor the API to use consistent error handling" + +**Strategy**: Split by module, each agent handles one area. + +```bash +agent-cli dev new refactor-users-errors --agent --prompt "Refactor error handling in the users module. + + +- Read all relevant files in parallel before making any changes +- Make incremental git commits as you refactor each endpoint +- Run tests after each change to catch regressions early +- Run linting before writing your final report + + + +Think carefully about the current state before making changes: +- Read ALL files in src/api/routes/users.py and related user logic +- Document the current error handling patterns you find +- Check how errors are handled in other modules for comparison +- Look for any error handling utilities that already exist + +Only modify code you have read and understood. + + + +Inconsistent error responses make API clients fragile and debugging difficult. A standard error format allows clients to handle errors programmatically and provides clear information for debugging. Logging errors with context is essential for production troubleshooting. + + + +Use HTTPException with structured detail: +{ + \"error\": \"ERROR_CODE\", + \"message\": \"Human readable description\", + \"details\": {} // optional additional context +} + +Error codes for users: USER_NOT_FOUND, USER_ALREADY_EXISTS, INVALID_CREDENTIALS, EMAIL_NOT_VERIFIED, etc. + +Before raising, log with context: +logger.warning(f\"User not found: {user_id}\", extra={\"user_id\": user_id}) + + + +ONLY modify files in src/api/routes/users.py and directly related user logic. Other agents are handling other modules. + + + +After tests pass and linting is clean, write to .claude/REPORT.md: + +## Changes Made +| File | Change Description | +|------|-------------------| +| path | what changed | + +## Error Codes Introduced +| Code | When Used | HTTP Status | +|------|-----------|-------------| + +## Breaking Changes +[Any API response changes that could affect clients] + +## Testing +[How to verify the changes work] +" +``` + +## Scenario 4: Documentation and implementation in parallel + +**User request**: "Add a plugin system with documentation" + +**Strategy**: One agent implements, another writes docs simultaneously. + +```bash +agent-cli dev new plugin-system --agent --prompt "Implement a plugin system. + + +- Read existing codebase structure in parallel before designing +- Make incremental git commits as you complete each component +- Run tests and linting before writing your final report + + + +Think carefully about the architecture before implementing: +- Read the existing codebase structure to understand where plugins fit +- Check for any existing extension points or hooks +- Look at how configuration is handled +- Understand the application lifecycle + +Design the plugin system to integrate naturally with existing patterns. + + + +- Plugin base class with lifecycle hooks: on_load(), on_unload(), on_event(event_name, data) +- Plugin registry for discovery and management +- Auto-load plugins from plugins/ directory +- Create one example plugin demonstrating the interface +- Plugins should be able to register event handlers + + + +Implement the minimal system that allows extending functionality through plugins. Skip: plugin dependencies, versioning, hot-reloading, sandboxing, or a plugin marketplace. + + + +- Use importlib for dynamic loading +- Simple dict-based event system is sufficient +- Plugins should fail gracefully without crashing the app + + + +After tests pass, write to .claude/REPORT.md: + +## Architecture +[Diagram or description of how plugins integrate] + +## Plugin Interface +\`\`\`python +class Plugin: + # document the interface +\`\`\` + +## Example Plugin +[Show the example plugin code] + +## Usage +[How to create and register a plugin] +" + +agent-cli dev new plugin-docs --agent --prompt "Write documentation for the plugin system. + + +Implementation is happening in parallel in another branch. Write documentation based on a standard plugin system design. The implementation agent will adapt if needed, or you can update docs after reviewing their work. + + + +- Plugin base class with on_load, on_unload, on_event hooks +- Plugin registry pattern with auto-discovery +- Plugins loaded from plugins/ directory +- Event-based communication + + + +Create these documentation files: +- docs/plugins/overview.md - What plugins are, why use them, architecture diagram +- docs/plugins/creating-plugins.md - Step-by-step tutorial with complete example +- docs/plugins/api-reference.md - Complete API documentation for Plugin class and registry + +Use clear examples and explain the \"why\" not just the \"how\". + + + +- Commit each documentation file as you complete it +- Ensure markdown renders correctly + + + +When complete, write to .claude/REPORT.md: + +## Documentation Structure +[Outline of what was created] + +## Assumptions Made +[What you assumed about the implementation] + +## Suggestions for Implementation +[Any insights from writing docs that could improve the design] + +## Open Questions +[Things that need clarification from the implementation] +" +``` + +## Reviewing results + +After agents complete their work: + +```bash +# Check status of all worktrees +agent-cli dev status + +# Read reports from each agent +agent-cli dev run auth-feature cat .claude/REPORT.md +agent-cli dev run payment-integration cat .claude/REPORT.md +agent-cli dev run email-notifications cat .claude/REPORT.md + +# Open a worktree to review code +agent-cli dev editor auth-feature + +# Run tests in a worktree +agent-cli dev run cache-impl pytest tests/test_cache.py -v + +# Clean up after merging +agent-cli dev clean --merged +``` + +## Report format reference + +All spawned agents should write to `.claude/REPORT.md` with at minimum: + +```markdown +## Summary +[2-3 sentences describing what was done] + +## Files Changed +- path/to/file.py - what changed and why + +## Key Decisions +- Decision: rationale for the choice made + +## Testing +How to verify the implementation works correctly + +## Questions/Concerns +Any items that need human review or clarification +``` + +This consistent format makes it easy to review work from multiple agents. diff --git a/.claude/skills/agent-cli-dev/SKILL.md b/.claude/skills/agent-cli-dev/SKILL.md index ab55059e..82c5c62e 100644 --- a/.claude/skills/agent-cli-dev/SKILL.md +++ b/.claude/skills/agent-cli-dev/SKILL.md @@ -47,8 +47,9 @@ agent-cli dev new --agent --prompt-file path/to/prompt.md This creates: 1. A new git worktree with its own branch 2. Runs project setup (installs dependencies) -3. Opens a new terminal tab with an AI coding agent -4. Passes your prompt to the agent +3. Saves your prompt to `.claude/TASK.md` in the worktree (for reference) +4. Opens a new terminal tab with an AI coding agent +5. Passes your prompt to the agent **Important**: Use `--prompt-file` for prompts longer than a single line. The `--prompt` option passes text through the shell, which can cause issues with special characters (exclamation marks, dollar signs, backticks, quotes) in ZSH and other shells. Using `--prompt-file` avoids all shell quoting issues. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8358e6f9..990c04b9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -35,3 +35,9 @@ repos: types: [python] pass_filenames: false always_run: true + - id: check-plugin-skill-sync + name: check plugin skill files in sync + entry: python scripts/check_plugin_skill_sync.py + language: python + pass_filenames: false + files: (agent_cli/dev/skill/|\.claude-plugin/skills/|\.claude/skills/) diff --git a/scripts/check_plugin_skill_sync.py b/scripts/check_plugin_skill_sync.py new file mode 100755 index 00000000..94c0dafd --- /dev/null +++ b/scripts/check_plugin_skill_sync.py @@ -0,0 +1,50 @@ +#!/usr/bin/env python3 +"""Check that plugin skill files are in sync with source files.""" + +import sys +from pathlib import Path + +SYNC_PAIRS = [ + # Plugin marketplace distribution + ("agent_cli/dev/skill/SKILL.md", ".claude-plugin/skills/agent-cli-dev/SKILL.md"), + ("agent_cli/dev/skill/examples.md", ".claude-plugin/skills/agent-cli-dev/examples.md"), + # Project-local skill (for Claude Code working on this repo) + ("agent_cli/dev/skill/SKILL.md", ".claude/skills/agent-cli-dev/SKILL.md"), + ("agent_cli/dev/skill/examples.md", ".claude/skills/agent-cli-dev/examples.md"), +] + + +def main() -> int: + """Check that plugin skill files match source files.""" + root = Path(__file__).parent.parent + out_of_sync = [] + + for source, target in SYNC_PAIRS: + source_path = root / source + target_path = root / target + + if not source_path.exists(): + print(f"Source not found: {source}") + continue + + if not target_path.exists(): + out_of_sync.append((source, target, "target missing")) + continue + + if source_path.read_text() != target_path.read_text(): + out_of_sync.append((source, target, "content differs")) + + if out_of_sync: + print("Plugin skill files are out of sync:") + for source, target, reason in out_of_sync: + print(f" {source} -> {target} ({reason})") + print("\nRun:") + print(" cp agent_cli/dev/skill/*.md .claude-plugin/skills/agent-cli-dev/") + print(" cp agent_cli/dev/skill/*.md .claude/skills/agent-cli-dev/") + return 1 + + return 0 + + +if __name__ == "__main__": + sys.exit(main())