mirror of
https://github.com/anthropics/claude-code.git
synced 2025-11-28 16:50:27 +08:00
Adds the plugin-dev plugin to public marketplace. A comprehensive toolkit for
developing Claude Code plugins with 7 expert skills, 3 AI-assisted agents, and
extensive documentation covering the complete plugin development lifecycle.
Key features:
- 7 skills: hook-development, mcp-integration, plugin-structure, plugin-settings,
command-development, agent-development, skill-development
- 3 agents: agent-creator (AI-assisted generation), plugin-validator (structure
validation), skill-reviewer (quality review)
- 1 command: /plugin-dev:create-plugin (guided 8-phase workflow)
- 10 utility scripts for validation and testing
- 21 reference docs with deep-dive guidance (~11k words)
- 9 working examples demonstrating best practices
Changes for public release:
- Replaced all references to internal repositories with "Claude Code"
- Updated MCP examples: internal.company.com → api.example.com
- Updated token variables: ${INTERNAL_TOKEN} → ${API_TOKEN}
- Reframed agent-creation-system-prompt as "proven in production"
- Preserved all ${CLAUDE_PLUGIN_ROOT} references (186 total)
- Preserved valuable test blocks in core modules
Validation:
- All 3 agents validated successfully with validate-agent.sh
- All JSON files validated with jq
- Zero internal references remaining
- 59 files migrated, 21,971 lines added
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
395 lines
9.3 KiB
Markdown
395 lines
9.3 KiB
Markdown
# Real-World Plugin Settings Examples
|
|
|
|
Detailed analysis of how production plugins use the `.claude/plugin-name.local.md` pattern.
|
|
|
|
## multi-agent-swarm Plugin
|
|
|
|
### Settings File Structure
|
|
|
|
**.claude/multi-agent-swarm.local.md:**
|
|
|
|
```markdown
|
|
---
|
|
agent_name: auth-implementation
|
|
task_number: 3.5
|
|
pr_number: 1234
|
|
coordinator_session: team-leader
|
|
enabled: true
|
|
dependencies: ["Task 3.4"]
|
|
additional_instructions: "Use JWT tokens, not sessions"
|
|
---
|
|
|
|
# Task: Implement Authentication
|
|
|
|
Build JWT-based authentication for the REST API.
|
|
|
|
## Requirements
|
|
- JWT token generation and validation
|
|
- Refresh token flow
|
|
- Secure password hashing
|
|
|
|
## Success Criteria
|
|
- Auth endpoints implemented
|
|
- Tests passing (100% coverage)
|
|
- PR created and CI green
|
|
- Documentation updated
|
|
|
|
## Coordination
|
|
Depends on Task 3.4 (user model).
|
|
Report status to 'team-leader' session.
|
|
```
|
|
|
|
### How It's Used
|
|
|
|
**File:** `hooks/agent-stop-notification.sh`
|
|
|
|
**Purpose:** Send notifications to coordinator when agent becomes idle
|
|
|
|
**Implementation:**
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
SWARM_STATE_FILE=".claude/multi-agent-swarm.local.md"
|
|
|
|
# Quick exit if no swarm active
|
|
if [[ ! -f "$SWARM_STATE_FILE" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Parse frontmatter
|
|
FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$SWARM_STATE_FILE")
|
|
|
|
# Extract configuration
|
|
COORDINATOR_SESSION=$(echo "$FRONTMATTER" | grep '^coordinator_session:' | sed 's/coordinator_session: *//' | sed 's/^"\(.*\)"$/\1/')
|
|
AGENT_NAME=$(echo "$FRONTMATTER" | grep '^agent_name:' | sed 's/agent_name: *//' | sed 's/^"\(.*\)"$/\1/')
|
|
TASK_NUMBER=$(echo "$FRONTMATTER" | grep '^task_number:' | sed 's/task_number: *//' | sed 's/^"\(.*\)"$/\1/')
|
|
PR_NUMBER=$(echo "$FRONTMATTER" | grep '^pr_number:' | sed 's/pr_number: *//' | sed 's/^"\(.*\)"$/\1/')
|
|
ENABLED=$(echo "$FRONTMATTER" | grep '^enabled:' | sed 's/enabled: *//')
|
|
|
|
# Check if enabled
|
|
if [[ "$ENABLED" != "true" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Send notification to coordinator
|
|
NOTIFICATION="🤖 Agent ${AGENT_NAME} (Task ${TASK_NUMBER}, PR #${PR_NUMBER}) is idle."
|
|
|
|
if tmux has-session -t "$COORDINATOR_SESSION" 2>/dev/null; then
|
|
tmux send-keys -t "$COORDINATOR_SESSION" "$NOTIFICATION" Enter
|
|
sleep 0.5
|
|
tmux send-keys -t "$COORDINATOR_SESSION" Enter
|
|
fi
|
|
|
|
exit 0
|
|
```
|
|
|
|
**Key patterns:**
|
|
1. **Quick exit** (line 7-9): Returns immediately if file doesn't exist
|
|
2. **Field extraction** (lines 11-17): Parses each frontmatter field
|
|
3. **Enabled check** (lines 19-21): Respects enabled flag
|
|
4. **Action based on settings** (lines 23-29): Uses coordinator_session to send notification
|
|
|
|
### Creation
|
|
|
|
**File:** `commands/launch-swarm.md`
|
|
|
|
Settings files are created during swarm launch with:
|
|
|
|
```bash
|
|
cat > "$WORKTREE_PATH/.claude/multi-agent-swarm.local.md" <<EOF
|
|
---
|
|
agent_name: $AGENT_NAME
|
|
task_number: $TASK_ID
|
|
pr_number: TBD
|
|
coordinator_session: $COORDINATOR_SESSION
|
|
enabled: true
|
|
dependencies: [$DEPENDENCIES]
|
|
additional_instructions: "$EXTRA_INSTRUCTIONS"
|
|
---
|
|
|
|
# Task: $TASK_DESCRIPTION
|
|
|
|
$TASK_DETAILS
|
|
EOF
|
|
```
|
|
|
|
### Updates
|
|
|
|
PR number updated after PR creation:
|
|
|
|
```bash
|
|
# Update pr_number field
|
|
sed "s/^pr_number: .*/pr_number: $PR_NUM/" \
|
|
".claude/multi-agent-swarm.local.md" > temp.md
|
|
mv temp.md ".claude/multi-agent-swarm.local.md"
|
|
```
|
|
|
|
## ralph-wiggum Plugin
|
|
|
|
### Settings File Structure
|
|
|
|
**.claude/ralph-loop.local.md:**
|
|
|
|
```markdown
|
|
---
|
|
iteration: 1
|
|
max_iterations: 10
|
|
completion_promise: "All tests passing and build successful"
|
|
started_at: "2025-01-15T14:30:00Z"
|
|
---
|
|
|
|
Fix all the linting errors in the project.
|
|
Make sure tests pass after each fix.
|
|
Document any changes needed in CLAUDE.md.
|
|
```
|
|
|
|
### How It's Used
|
|
|
|
**File:** `hooks/stop-hook.sh`
|
|
|
|
**Purpose:** Prevent session exit and loop Claude's output back as input
|
|
|
|
**Implementation:**
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
set -euo pipefail
|
|
|
|
RALPH_STATE_FILE=".claude/ralph-loop.local.md"
|
|
|
|
# Quick exit if no active loop
|
|
if [[ ! -f "$RALPH_STATE_FILE" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
# Parse frontmatter
|
|
FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$RALPH_STATE_FILE")
|
|
|
|
# Extract configuration
|
|
ITERATION=$(echo "$FRONTMATTER" | grep '^iteration:' | sed 's/iteration: *//')
|
|
MAX_ITERATIONS=$(echo "$FRONTMATTER" | grep '^max_iterations:' | sed 's/max_iterations: *//')
|
|
COMPLETION_PROMISE=$(echo "$FRONTMATTER" | grep '^completion_promise:' | sed 's/completion_promise: *//' | sed 's/^"\(.*\)"$/\1/')
|
|
|
|
# Check max iterations
|
|
if [[ $MAX_ITERATIONS -gt 0 ]] && [[ $ITERATION -ge $MAX_ITERATIONS ]]; then
|
|
echo "🛑 Ralph loop: Max iterations ($MAX_ITERATIONS) reached."
|
|
rm "$RALPH_STATE_FILE"
|
|
exit 0
|
|
fi
|
|
|
|
# Get transcript and check for completion promise
|
|
TRANSCRIPT_PATH=$(echo "$HOOK_INPUT" | jq -r '.transcript_path')
|
|
LAST_OUTPUT=$(grep '"role":"assistant"' "$TRANSCRIPT_PATH" | tail -1 | jq -r '.message.content | map(select(.type == "text")) | map(.text) | join("\n")')
|
|
|
|
# Check for completion
|
|
if [[ "$COMPLETION_PROMISE" != "null" ]] && [[ -n "$COMPLETION_PROMISE" ]]; then
|
|
PROMISE_TEXT=$(echo "$LAST_OUTPUT" | perl -0777 -pe 's/.*?<promise>(.*?)<\/promise>.*/$1/s; s/^\s+|\s+$//g')
|
|
|
|
if [[ "$PROMISE_TEXT" = "$COMPLETION_PROMISE" ]]; then
|
|
echo "✅ Ralph loop: Detected completion"
|
|
rm "$RALPH_STATE_FILE"
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
# Continue loop - increment iteration
|
|
NEXT_ITERATION=$((ITERATION + 1))
|
|
|
|
# Extract prompt from markdown body
|
|
PROMPT_TEXT=$(awk '/^---$/{i++; next} i>=2' "$RALPH_STATE_FILE")
|
|
|
|
# Update iteration counter
|
|
TEMP_FILE="${RALPH_STATE_FILE}.tmp.$$"
|
|
sed "s/^iteration: .*/iteration: $NEXT_ITERATION/" "$RALPH_STATE_FILE" > "$TEMP_FILE"
|
|
mv "$TEMP_FILE" "$RALPH_STATE_FILE"
|
|
|
|
# Block exit and feed prompt back
|
|
jq -n \
|
|
--arg prompt "$PROMPT_TEXT" \
|
|
--arg msg "🔄 Ralph iteration $NEXT_ITERATION" \
|
|
'{
|
|
"decision": "block",
|
|
"reason": $prompt,
|
|
"systemMessage": $msg
|
|
}'
|
|
|
|
exit 0
|
|
```
|
|
|
|
**Key patterns:**
|
|
1. **Quick exit** (line 7-9): Skip if not active
|
|
2. **Iteration tracking** (lines 11-20): Count and enforce max iterations
|
|
3. **Promise detection** (lines 25-33): Check for completion signal in output
|
|
4. **Prompt extraction** (line 38): Read markdown body as next prompt
|
|
5. **State update** (lines 40-43): Increment iteration atomically
|
|
6. **Loop continuation** (lines 45-53): Block exit and feed prompt back
|
|
|
|
### Creation
|
|
|
|
**File:** `scripts/setup-ralph-loop.sh`
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
PROMPT="$1"
|
|
MAX_ITERATIONS="${2:-0}"
|
|
COMPLETION_PROMISE="${3:-}"
|
|
|
|
# Create state file
|
|
cat > ".claude/ralph-loop.local.md" <<EOF
|
|
---
|
|
iteration: 1
|
|
max_iterations: $MAX_ITERATIONS
|
|
completion_promise: "$COMPLETION_PROMISE"
|
|
started_at: "$(date -Iseconds)"
|
|
---
|
|
|
|
$PROMPT
|
|
EOF
|
|
|
|
echo "Ralph loop initialized: .claude/ralph-loop.local.md"
|
|
```
|
|
|
|
## Pattern Comparison
|
|
|
|
| Feature | multi-agent-swarm | ralph-wiggum |
|
|
|---------|-------------------|--------------|
|
|
| **File** | `.claude/multi-agent-swarm.local.md` | `.claude/ralph-loop.local.md` |
|
|
| **Purpose** | Agent coordination state | Loop iteration state |
|
|
| **Frontmatter** | Agent metadata | Loop configuration |
|
|
| **Body** | Task assignment | Prompt to loop |
|
|
| **Updates** | PR number, status | Iteration counter |
|
|
| **Deletion** | Manual or on completion | On loop exit |
|
|
| **Hook** | Stop (notifications) | Stop (loop control) |
|
|
|
|
## Best Practices from Real Plugins
|
|
|
|
### 1. Quick Exit Pattern
|
|
|
|
Both plugins check file existence first:
|
|
|
|
```bash
|
|
if [[ ! -f "$STATE_FILE" ]]; then
|
|
exit 0 # Not active
|
|
fi
|
|
```
|
|
|
|
**Why:** Avoids errors when plugin isn't configured and performs fast.
|
|
|
|
### 2. Enabled Flag
|
|
|
|
Both use an `enabled` field for explicit control:
|
|
|
|
```yaml
|
|
enabled: true
|
|
```
|
|
|
|
**Why:** Allows temporary deactivation without deleting file.
|
|
|
|
### 3. Atomic Updates
|
|
|
|
Both use temp file + atomic move:
|
|
|
|
```bash
|
|
TEMP_FILE="${FILE}.tmp.$$"
|
|
sed "s/^field: .*/field: $NEW_VALUE/" "$FILE" > "$TEMP_FILE"
|
|
mv "$TEMP_FILE" "$FILE"
|
|
```
|
|
|
|
**Why:** Prevents corruption if process is interrupted.
|
|
|
|
### 4. Quote Handling
|
|
|
|
Both strip surrounding quotes from YAML values:
|
|
|
|
```bash
|
|
sed 's/^"\(.*\)"$/\1/'
|
|
```
|
|
|
|
**Why:** YAML allows both `field: value` and `field: "value"`.
|
|
|
|
### 5. Error Handling
|
|
|
|
Both handle missing/corrupt files gracefully:
|
|
|
|
```bash
|
|
if [[ ! -f "$FILE" ]]; then
|
|
exit 0 # No error, just not configured
|
|
fi
|
|
|
|
if [[ -z "$CRITICAL_FIELD" ]]; then
|
|
echo "Settings file corrupt" >&2
|
|
rm "$FILE" # Clean up
|
|
exit 0
|
|
fi
|
|
```
|
|
|
|
**Why:** Fails gracefully instead of crashing.
|
|
|
|
## Anti-Patterns to Avoid
|
|
|
|
### ❌ Hardcoded Paths
|
|
|
|
```bash
|
|
# BAD
|
|
FILE="/Users/alice/.claude/my-plugin.local.md"
|
|
|
|
# GOOD
|
|
FILE=".claude/my-plugin.local.md"
|
|
```
|
|
|
|
### ❌ Unquoted Variables
|
|
|
|
```bash
|
|
# BAD
|
|
echo $VALUE
|
|
|
|
# GOOD
|
|
echo "$VALUE"
|
|
```
|
|
|
|
### ❌ Non-Atomic Updates
|
|
|
|
```bash
|
|
# BAD: Can corrupt file if interrupted
|
|
sed -i "s/field: .*/field: $VALUE/" "$FILE"
|
|
|
|
# GOOD: Atomic
|
|
TEMP_FILE="${FILE}.tmp.$$"
|
|
sed "s/field: .*/field: $VALUE/" "$FILE" > "$TEMP_FILE"
|
|
mv "$TEMP_FILE" "$FILE"
|
|
```
|
|
|
|
### ❌ No Default Values
|
|
|
|
```bash
|
|
# BAD: Fails if field missing
|
|
if [[ $MAX -gt 100 ]]; then
|
|
# MAX might be empty!
|
|
fi
|
|
|
|
# GOOD: Provide default
|
|
MAX=${MAX:-10}
|
|
```
|
|
|
|
### ❌ Ignoring Edge Cases
|
|
|
|
```bash
|
|
# BAD: Assumes exactly 2 --- markers
|
|
sed -n '/^---$/,/^---$/{ /^---$/d; p; }'
|
|
|
|
# GOOD: Handles --- in body
|
|
awk '/^---$/{i++; next} i>=2' # For body
|
|
```
|
|
|
|
## Conclusion
|
|
|
|
The `.claude/plugin-name.local.md` pattern provides:
|
|
- Simple, human-readable configuration
|
|
- Version-control friendly (gitignored)
|
|
- Per-project settings
|
|
- Easy parsing with standard bash tools
|
|
- Supports both structured config (YAML) and freeform content (markdown)
|
|
|
|
Use this pattern for any plugin that needs user-configurable behavior or state persistence.
|