spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic ยท github.com/anthropics

claude-code / plugins / plugin-dev / skills / plugin-settings / references / real-world-examples.md
395 lines ยท 9.3 KBPreviewCodeRaw
1# Real-World Plugin Settings Examples
2
3Detailed analysis of how production plugins use the `.claude/plugin-name.local.md` pattern.
4
5## multi-agent-swarm Plugin
6
7### Settings File Structure
8
9**.claude/multi-agent-swarm.local.md:**
10
11```markdown
12---
13agent_name: auth-implementation
14task_number: 3.5
15pr_number: 1234
16coordinator_session: team-leader
17enabled: true
18dependencies: ["Task 3.4"]
19additional_instructions: "Use JWT tokens, not sessions"
20---
21
22# Task: Implement Authentication
23
24Build JWT-based authentication for the REST API.
25
26## Requirements
27- JWT token generation and validation
28- Refresh token flow
29- Secure password hashing
30
31## Success Criteria
32- Auth endpoints implemented
33- Tests passing (100% coverage)
34- PR created and CI green
35- Documentation updated
36
37## Coordination
38Depends on Task 3.4 (user model).
39Report status to 'team-leader' session.
40```
41
42### How It's Used
43
44**File:** `hooks/agent-stop-notification.sh`
45
46**Purpose:** Send notifications to coordinator when agent becomes idle
47
48**Implementation:**
49
50```bash
51#!/bin/bash
52set -euo pipefail
53
54SWARM_STATE_FILE=".claude/multi-agent-swarm.local.md"
55
56# Quick exit if no swarm active
57if [[ ! -f "$SWARM_STATE_FILE" ]]; then
58 exit 0
59fi
60
61# Parse frontmatter
62FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$SWARM_STATE_FILE")
63
64# Extract configuration
65COORDINATOR_SESSION=$(echo "$FRONTMATTER" | grep '^coordinator_session:' | sed 's/coordinator_session: *//' | sed 's/^"\(.*\)"$/\1/')
66AGENT_NAME=$(echo "$FRONTMATTER" | grep '^agent_name:' | sed 's/agent_name: *//' | sed 's/^"\(.*\)"$/\1/')
67TASK_NUMBER=$(echo "$FRONTMATTER" | grep '^task_number:' | sed 's/task_number: *//' | sed 's/^"\(.*\)"$/\1/')
68PR_NUMBER=$(echo "$FRONTMATTER" | grep '^pr_number:' | sed 's/pr_number: *//' | sed 's/^"\(.*\)"$/\1/')
69ENABLED=$(echo "$FRONTMATTER" | grep '^enabled:' | sed 's/enabled: *//')
70
71# Check if enabled
72if [[ "$ENABLED" != "true" ]]; then
73 exit 0
74fi
75
76# Send notification to coordinator
77NOTIFICATION="๐Ÿค– Agent ${AGENT_NAME} (Task ${TASK_NUMBER}, PR #${PR_NUMBER}) is idle."
78
79if tmux has-session -t "$COORDINATOR_SESSION" 2>/dev/null; then
80 tmux send-keys -t "$COORDINATOR_SESSION" "$NOTIFICATION" Enter
81 sleep 0.5
82 tmux send-keys -t "$COORDINATOR_SESSION" Enter
83fi
84
85exit 0
86```
87
88**Key patterns:**
891. **Quick exit** (line 7-9): Returns immediately if file doesn't exist
902. **Field extraction** (lines 11-17): Parses each frontmatter field
913. **Enabled check** (lines 19-21): Respects enabled flag
924. **Action based on settings** (lines 23-29): Uses coordinator_session to send notification
93
94### Creation
95
96**File:** `commands/launch-swarm.md`
97
98Settings files are created during swarm launch with:
99
100```bash
101cat > "$WORKTREE_PATH/.claude/multi-agent-swarm.local.md" <<EOF
102---
103agent_name: $AGENT_NAME
104task_number: $TASK_ID
105pr_number: TBD
106coordinator_session: $COORDINATOR_SESSION
107enabled: true
108dependencies: [$DEPENDENCIES]
109additional_instructions: "$EXTRA_INSTRUCTIONS"
110---
111
112# Task: $TASK_DESCRIPTION
113
114$TASK_DETAILS
115EOF
116```
117
118### Updates
119
120PR number updated after PR creation:
121
122```bash
123# Update pr_number field
124sed "s/^pr_number: .*/pr_number: $PR_NUM/" \
125 ".claude/multi-agent-swarm.local.md" > temp.md
126mv temp.md ".claude/multi-agent-swarm.local.md"
127```
128
129## ralph-wiggum Plugin
130
131### Settings File Structure
132
133**.claude/ralph-loop.local.md:**
134
135```markdown
136---
137iteration: 1
138max_iterations: 10
139completion_promise: "All tests passing and build successful"
140started_at: "2025-01-15T14:30:00Z"
141---
142
143Fix all the linting errors in the project.
144Make sure tests pass after each fix.
145Document any changes needed in CLAUDE.md.
146```
147
148### How It's Used
149
150**File:** `hooks/stop-hook.sh`
151
152**Purpose:** Prevent session exit and loop Claude's output back as input
153
154**Implementation:**
155
156```bash
157#!/bin/bash
158set -euo pipefail
159
160RALPH_STATE_FILE=".claude/ralph-loop.local.md"
161
162# Quick exit if no active loop
163if [[ ! -f "$RALPH_STATE_FILE" ]]; then
164 exit 0
165fi
166
167# Parse frontmatter
168FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$RALPH_STATE_FILE")
169
170# Extract configuration
171ITERATION=$(echo "$FRONTMATTER" | grep '^iteration:' | sed 's/iteration: *//')
172MAX_ITERATIONS=$(echo "$FRONTMATTER" | grep '^max_iterations:' | sed 's/max_iterations: *//')
173COMPLETION_PROMISE=$(echo "$FRONTMATTER" | grep '^completion_promise:' | sed 's/completion_promise: *//' | sed 's/^"\(.*\)"$/\1/')
174
175# Check max iterations
176if [[ $MAX_ITERATIONS -gt 0 ]] && [[ $ITERATION -ge $MAX_ITERATIONS ]]; then
177 echo "๐Ÿ›‘ Ralph loop: Max iterations ($MAX_ITERATIONS) reached."
178 rm "$RALPH_STATE_FILE"
179 exit 0
180fi
181
182# Get transcript and check for completion promise
183TRANSCRIPT_PATH=$(echo "$HOOK_INPUT" | jq -r '.transcript_path')
184LAST_OUTPUT=$(grep '"role":"assistant"' "$TRANSCRIPT_PATH" | tail -1 | jq -r '.message.content | map(select(.type == "text")) | map(.text) | join("\n")')
185
186# Check for completion
187if [[ "$COMPLETION_PROMISE" != "null" ]] && [[ -n "$COMPLETION_PROMISE" ]]; then
188 PROMISE_TEXT=$(echo "$LAST_OUTPUT" | perl -0777 -pe 's/.*?<promise>(.*?)<\/promise>.*/$1/s; s/^\s+|\s+$//g')
189
190 if [[ "$PROMISE_TEXT" = "$COMPLETION_PROMISE" ]]; then
191 echo "โœ… Ralph loop: Detected completion"
192 rm "$RALPH_STATE_FILE"
193 exit 0
194 fi
195fi
196
197# Continue loop - increment iteration
198NEXT_ITERATION=$((ITERATION + 1))
199
200# Extract prompt from markdown body
201PROMPT_TEXT=$(awk '/^---$/{i++; next} i>=2' "$RALPH_STATE_FILE")
202
203# Update iteration counter
204TEMP_FILE="${RALPH_STATE_FILE}.tmp.$$"
205sed "s/^iteration: .*/iteration: $NEXT_ITERATION/" "$RALPH_STATE_FILE" > "$TEMP_FILE"
206mv "$TEMP_FILE" "$RALPH_STATE_FILE"
207
208# Block exit and feed prompt back
209jq -n \
210 --arg prompt "$PROMPT_TEXT" \
211 --arg msg "๐Ÿ”„ Ralph iteration $NEXT_ITERATION" \
212 '{
213 "decision": "block",
214 "reason": $prompt,
215 "systemMessage": $msg
216 }'
217
218exit 0
219```
220
221**Key patterns:**
2221. **Quick exit** (line 7-9): Skip if not active
2232. **Iteration tracking** (lines 11-20): Count and enforce max iterations
2243. **Promise detection** (lines 25-33): Check for completion signal in output
2254. **Prompt extraction** (line 38): Read markdown body as next prompt
2265. **State update** (lines 40-43): Increment iteration atomically
2276. **Loop continuation** (lines 45-53): Block exit and feed prompt back
228
229### Creation
230
231**File:** `scripts/setup-ralph-loop.sh`
232
233```bash
234#!/bin/bash
235PROMPT="$1"
236MAX_ITERATIONS="${2:-0}"
237COMPLETION_PROMISE="${3:-}"
238
239# Create state file
240cat > ".claude/ralph-loop.local.md" <<EOF
241---
242iteration: 1
243max_iterations: $MAX_ITERATIONS
244completion_promise: "$COMPLETION_PROMISE"
245started_at: "$(date -Iseconds)"
246---
247
248$PROMPT
249EOF
250
251echo "Ralph loop initialized: .claude/ralph-loop.local.md"
252```
253
254## Pattern Comparison
255
256| Feature | multi-agent-swarm | ralph-wiggum |
257|---------|-------------------|--------------|
258| **File** | `.claude/multi-agent-swarm.local.md` | `.claude/ralph-loop.local.md` |
259| **Purpose** | Agent coordination state | Loop iteration state |
260| **Frontmatter** | Agent metadata | Loop configuration |
261| **Body** | Task assignment | Prompt to loop |
262| **Updates** | PR number, status | Iteration counter |
263| **Deletion** | Manual or on completion | On loop exit |
264| **Hook** | Stop (notifications) | Stop (loop control) |
265
266## Best Practices from Real Plugins
267
268### 1. Quick Exit Pattern
269
270Both plugins check file existence first:
271
272```bash
273if [[ ! -f "$STATE_FILE" ]]; then
274 exit 0 # Not active
275fi
276```
277
278**Why:** Avoids errors when plugin isn't configured and performs fast.
279
280### 2. Enabled Flag
281
282Both use an `enabled` field for explicit control:
283
284```yaml
285enabled: true
286```
287
288**Why:** Allows temporary deactivation without deleting file.
289
290### 3. Atomic Updates
291
292Both use temp file + atomic move:
293
294```bash
295TEMP_FILE="${FILE}.tmp.$$"
296sed "s/^field: .*/field: $NEW_VALUE/" "$FILE" > "$TEMP_FILE"
297mv "$TEMP_FILE" "$FILE"
298```
299
300**Why:** Prevents corruption if process is interrupted.
301
302### 4. Quote Handling
303
304Both strip surrounding quotes from YAML values:
305
306```bash
307sed 's/^"\(.*\)"$/\1/'
308```
309
310**Why:** YAML allows both `field: value` and `field: "value"`.
311
312### 5. Error Handling
313
314Both handle missing/corrupt files gracefully:
315
316```bash
317if [[ ! -f "$FILE" ]]; then
318 exit 0 # No error, just not configured
319fi
320
321if [[ -z "$CRITICAL_FIELD" ]]; then
322 echo "Settings file corrupt" >&2
323 rm "$FILE" # Clean up
324 exit 0
325fi
326```
327
328**Why:** Fails gracefully instead of crashing.
329
330## Anti-Patterns to Avoid
331
332### โŒ Hardcoded Paths
333
334```bash
335# BAD
336FILE="/Users/alice/.claude/my-plugin.local.md"
337
338# GOOD
339FILE=".claude/my-plugin.local.md"
340```
341
342### โŒ Unquoted Variables
343
344```bash
345# BAD
346echo $VALUE
347
348# GOOD
349echo "$VALUE"
350```
351
352### โŒ Non-Atomic Updates
353
354```bash
355# BAD: Can corrupt file if interrupted
356sed -i "s/field: .*/field: $VALUE/" "$FILE"
357
358# GOOD: Atomic
359TEMP_FILE="${FILE}.tmp.$$"
360sed "s/field: .*/field: $VALUE/" "$FILE" > "$TEMP_FILE"
361mv "$TEMP_FILE" "$FILE"
362```
363
364### โŒ No Default Values
365
366```bash
367# BAD: Fails if field missing
368if [[ $MAX -gt 100 ]]; then
369 # MAX might be empty!
370fi
371
372# GOOD: Provide default
373MAX=${MAX:-10}
374```
375
376### โŒ Ignoring Edge Cases
377
378```bash
379# BAD: Assumes exactly 2 --- markers
380sed -n '/^---$/,/^---$/{ /^---$/d; p; }'
381
382# GOOD: Handles --- in body
383awk '/^---$/{i++; next} i>=2' # For body
384```
385
386## Conclusion
387
388The `.claude/plugin-name.local.md` pattern provides:
389- Simple, human-readable configuration
390- Version-control friendly (gitignored)
391- Per-project settings
392- Easy parsing with standard bash tools
393- Supports both structured config (YAML) and freeform content (markdown)
394
395Use this pattern for any plugin that needs user-configurable behavior or state persistence.