Initial commit
This commit is contained in:
250
skills/agent-design/SKILL.md
Normal file
250
skills/agent-design/SKILL.md
Normal file
@@ -0,0 +1,250 @@
|
||||
---
|
||||
name: box-factory-agent-design
|
||||
description: Interpretive guidance for designing Claude Code agents. Helps apply official documentation effectively and avoid common pitfalls. Use when creating or reviewing agents.
|
||||
---
|
||||
|
||||
# Agent Design Skill
|
||||
|
||||
This skill provides interpretive guidance for creating Claude Code agents. **ALWAYS fetch current official documentation before creating agents** - this skill helps you understand what the docs mean, not replace them.
|
||||
|
||||
## Required Reading Before Creating Agents
|
||||
|
||||
Fetch these docs with WebFetch every time:
|
||||
|
||||
- **<https://code.claude.com/docs/en/sub-agents.md>** - Core specification and examples
|
||||
- **<https://code.claude.com/docs/en/settings#tools-available-to-claude>** - Verify tool names
|
||||
- **<https://code.claude.com/docs/en/model-config.md>** - Current model options
|
||||
|
||||
## Critical Architecture Understanding
|
||||
|
||||
Agents operate in **isolated context** with a **return-based model**:
|
||||
|
||||
```
|
||||
User ↔ Main Claude → Agent (isolated, returns results)
|
||||
```
|
||||
|
||||
**Critical implications:**
|
||||
|
||||
- Agents CAN'T ask users questions
|
||||
- Agents CAN'T interact with users directly
|
||||
- Agents SHOULD do actual work (run code, write files, analyze code) when appropriate
|
||||
- Main agent handles ALL user communication
|
||||
|
||||
**The key distinction:** No user interaction (no asking questions, no confirming), but full ability to do autonomous work within scope.
|
||||
|
||||
**Common misconception:** If your agent prompt includes phrases like "ask the user", "gather from user", "clarify with user" - you've misunderstood the architecture.
|
||||
|
||||
## Decision Framework
|
||||
|
||||
### Agent vs Command vs Skill
|
||||
|
||||
**Use Agent when:**
|
||||
|
||||
- Need isolated context (won't pollute main conversation)
|
||||
- Want autonomous delegation (triggered by context)
|
||||
- Require specific tool restrictions
|
||||
- Task runs as part of larger workflows
|
||||
|
||||
**Use Command when:**
|
||||
|
||||
- User explicitly triggers it
|
||||
- Simple, straightforward task
|
||||
- No need for context isolation
|
||||
|
||||
**Use Skill when:**
|
||||
|
||||
- Knowledge needed by multiple contexts
|
||||
- Procedural expertise that's substantial
|
||||
- Progressive disclosure would save tokens
|
||||
|
||||
### Tool Selection Philosophy
|
||||
|
||||
**Match tools to autonomous responsibilities:**
|
||||
|
||||
- If agent's job is to write files → include Write/Edit
|
||||
- If agent only analyzes → Read, Grep, Glob only
|
||||
- Never include AskUserQuestion (agents can't use it)
|
||||
|
||||
**Common mistake:** Over-restricting tools because you're thinking "safety"
|
||||
|
||||
**Reality:** An agent whose job is generating code but only has Read tool can't do its job
|
||||
|
||||
**Balance:** Reviewers should be read-only; builders need write access
|
||||
|
||||
## Description Field Design
|
||||
|
||||
The `description` field determines when Claude delegates to your agent. This is critical for autonomous invocation.
|
||||
|
||||
**Official requirement:** "Natural language explanation of when to invoke the subagent"
|
||||
|
||||
**Quality test:** Would Claude invoke this agent based on context alone, or only when explicitly asked?
|
||||
|
||||
**Guidelines:**
|
||||
|
||||
- State WHEN to use (triggering conditions), not just WHAT it does
|
||||
- Be specific about context and use cases
|
||||
- Test empirically - if your agent isn't being invoked automatically, revise the description
|
||||
- Avoid overly generic descriptions that match too many scenarios
|
||||
|
||||
## Common Gotchas
|
||||
|
||||
### Gotcha #1: User Interaction Language
|
||||
|
||||
**Problem:** Agent prompts assume they can ask questions or confirm actions
|
||||
|
||||
**Forbidden phrases anywhere in agent prompt:**
|
||||
|
||||
- "ask the user", "gather from user", "clarify with user"
|
||||
- "request from user", "prompt the user", "wait for input"
|
||||
- "check with user", "verify with user", "confirm with user"
|
||||
|
||||
**Replace with:**
|
||||
|
||||
- "infer from context", "use provided parameters"
|
||||
- "make reasonable assumptions", "use available information"
|
||||
- "default to [specific behavior]"
|
||||
|
||||
### Gotcha #2: Hardcoding Version-Specific Info
|
||||
|
||||
**Problem:** Docs change; hardcoded details become outdated
|
||||
|
||||
**Instead of:**
|
||||
|
||||
```markdown
|
||||
Available models: sonnet, opus, haiku
|
||||
Use these tools: Read, Write, Edit, Bash
|
||||
```
|
||||
|
||||
**Do this:**
|
||||
|
||||
```markdown
|
||||
See model-config documentation for current options
|
||||
Refer to tools documentation for current capabilities
|
||||
```
|
||||
|
||||
### Gotcha #3: Tool Mismatches
|
||||
|
||||
**Problem:** Tools don't match the agent's autonomous responsibilities
|
||||
|
||||
**Examples:**
|
||||
|
||||
- ❌ Code generator with only Read (can't write generated code)
|
||||
- ❌ Test runner without Bash (can't run tests)
|
||||
- ❌ Code reviewer with Write/Edit (should be read-only)
|
||||
|
||||
**Solution:** Grant minimal necessary permissions for the agent's actual work
|
||||
|
||||
## Common Antipatterns
|
||||
|
||||
### Antipattern: Overly Broad Scope
|
||||
|
||||
**What you'll see:** "Full-stack engineer agent that handles everything"
|
||||
|
||||
**Why it fails:**
|
||||
|
||||
- Unclear when to delegate
|
||||
- Context pollution
|
||||
- Violates single responsibility principle
|
||||
|
||||
**Solution:** Split into focused agents (frontend-dev, backend-dev, db-specialist)
|
||||
|
||||
### Antipattern: Vague Delegation Triggers
|
||||
|
||||
**What you'll see:** Great functionality, vague description
|
||||
|
||||
**Why it fails:** Agent only fires on explicit request, not autonomously
|
||||
|
||||
**Solution:** Make description specific about triggering conditions and use cases
|
||||
|
||||
### Antipattern: Interactive Assumptions
|
||||
|
||||
**What you'll see:** "Ask user for target directory", "Confirm with user before proceeding"
|
||||
|
||||
**Why it fails:** Agents can't interact with users
|
||||
|
||||
**Solution:** "Use provided directory parameter or default to ./src", "Proceed based on available context"
|
||||
|
||||
## System Prompt Best Practices
|
||||
|
||||
### Structure
|
||||
|
||||
Use consistent markdown hierarchy:
|
||||
|
||||
```markdown
|
||||
# Agent Name (H1 - single heading)
|
||||
|
||||
## Purpose
|
||||
[Clear statement of role]
|
||||
|
||||
## Process
|
||||
1. Step one
|
||||
2. Step two
|
||||
|
||||
## Guidelines
|
||||
- Key principle one
|
||||
- Key principle two
|
||||
|
||||
## Constraints
|
||||
- What NOT to do
|
||||
- Boundaries and limitations
|
||||
```
|
||||
|
||||
### Content Quality
|
||||
|
||||
**Be specific and actionable:**
|
||||
|
||||
- ✅ "Run pytest -v and parse output for failures"
|
||||
- ❌ "Run tests and check for problems"
|
||||
|
||||
**Define scope clearly:**
|
||||
|
||||
- ✅ "Only analyze Python files in src/ directory"
|
||||
- ❌ "Analyze code"
|
||||
|
||||
**Include constraints:**
|
||||
|
||||
- ✅ "Never modify production configuration files"
|
||||
- ✅ "Only analyze; never modify code"
|
||||
|
||||
## Validation Workflow
|
||||
|
||||
Before finalizing an agent:
|
||||
|
||||
1. **Fetch official docs** - Verify against current specification
|
||||
2. **Check structure** - Valid YAML frontmatter, required fields present
|
||||
3. **Scan for forbidden language** - No user interaction phrases
|
||||
4. **Validate tools** - Match autonomous responsibilities, no AskUserQuestion
|
||||
5. **Test description** - Specific triggering conditions, not generic
|
||||
6. **Review system prompt** - Single H1, clear structure, actionable instructions
|
||||
7. **Verify no hardcoding** - No version-specific details that will become outdated
|
||||
|
||||
## Path Resolution
|
||||
|
||||
When writing agents:
|
||||
|
||||
1. If caller specifies path → use exact path
|
||||
2. If working in `.claude/agents/` → use that
|
||||
3. Default → `.claude/agents/` (project-level)
|
||||
4. User-level (`~/.claude/agents/`) → only when explicitly requested
|
||||
|
||||
## Documentation References
|
||||
|
||||
Authoritative sources to fetch before creating agents:
|
||||
|
||||
**Core specifications:**
|
||||
|
||||
- <https://code.claude.com/docs/en/sub-agents.md> - Agent structure, examples, patterns
|
||||
|
||||
**Tool verification:**
|
||||
|
||||
- <https://code.claude.com/docs/en/settings#tools-available-to-claude> - Current tool list
|
||||
|
||||
**Model selection:**
|
||||
|
||||
- <https://code.claude.com/docs/en/model-config.md> - Available models, selection guidance
|
||||
|
||||
**Workflow patterns:**
|
||||
|
||||
- <https://code.claude.com/docs/en/common-workflows.md> - Real-world delegation patterns
|
||||
|
||||
**Remember:** This skill helps you interpret and apply those docs effectively. Always fetch current documentation for specifications and details.
|
||||
1063
skills/box-factory-architecture/SKILL.md
Normal file
1063
skills/box-factory-architecture/SKILL.md
Normal file
File diff suppressed because it is too large
Load Diff
908
skills/hook-design/SKILL.md
Normal file
908
skills/hook-design/SKILL.md
Normal file
@@ -0,0 +1,908 @@
|
||||
---
|
||||
name: box-factory-hooks-design
|
||||
description: Interpretive guidance for designing Claude Code hooks. Helps you understand hook lifecycle, when to use hooks vs other patterns, and common pitfalls. Use when creating or reviewing hooks.
|
||||
---
|
||||
|
||||
# Hooks Design Skill
|
||||
|
||||
This skill provides interpretive guidance and best practices for creating Claude Code hooks. **ALWAYS fetch current official documentation before creating hooks** - this skill helps you understand what the docs mean and how to create excellent hooks.
|
||||
|
||||
## Required Reading Before Creating Hooks
|
||||
|
||||
Fetch these docs with WebFetch every time:
|
||||
|
||||
- **https://code.claude.com/docs/en/hooks** - Complete hook reference
|
||||
|
||||
## Core Understanding
|
||||
|
||||
### Hooks Are Deterministic Control
|
||||
|
||||
**Key insight:** Hooks provide guaranteed, deterministic execution at specific lifecycle events.
|
||||
|
||||
**What this means:**
|
||||
|
||||
- **Hooks** = Execute every single time (deterministic)
|
||||
- **Prompts/Instructions** = Claude might forget (probabilistic)
|
||||
- **Agents** = Context-dependent intelligence
|
||||
- **Use hooks when "always" matters**
|
||||
|
||||
**Decision question:** Do you need this to happen every single time, or is "usually" okay?
|
||||
|
||||
**Examples:**
|
||||
|
||||
- Format after every file write → Hook
|
||||
- Suggest code improvements → Prompt to Claude
|
||||
- Run tests after code changes → Hook if mandatory, agent if discretionary
|
||||
- Security validation before bash → Hook (must be enforced)
|
||||
|
||||
### Hook Architecture (How It Fits)
|
||||
|
||||
**Execution flow:**
|
||||
|
||||
```
|
||||
User Input → Claude Thinks → Tool Execution
|
||||
↑ ↓
|
||||
Hooks fire here ────┘
|
||||
```
|
||||
|
||||
**Critical implications:**
|
||||
|
||||
- **PreToolUse**: Can block/modify before tool runs
|
||||
- **PostToolUse**: Can react after tool completes successfully
|
||||
- **Stop**: Can't affect what Claude just did (it's done, only cleanup)
|
||||
- **UserPromptSubmit**: Runs before Claude sees the prompt
|
||||
|
||||
### Exit Codes Are Communication (Official Specification)
|
||||
|
||||
**Exit 0**: Hook succeeded, continue execution
|
||||
|
||||
- stdout displays in transcript mode (CTRL-R)
|
||||
- Exception: `UserPromptSubmit` and `SessionStart` where stdout becomes context for Claude
|
||||
|
||||
**Exit 2**: Blocking error, stop and handle
|
||||
|
||||
- stderr feeds to Claude for processing
|
||||
- Behavior varies by event:
|
||||
- **PreToolUse**: Blocks tool call
|
||||
- **Stop/SubagentStop**: Blocks stoppage
|
||||
- **UserPromptSubmit**: Blocks prompt, erases it, shows error to user only
|
||||
|
||||
**Other exit codes**: Non-blocking error
|
||||
|
||||
- stderr displays to user
|
||||
- Execution continues
|
||||
|
||||
**Best practice:** Use exit 2 sparingly - it's powerful but disruptive. Use it for security/safety enforcement, not preferences.
|
||||
|
||||
## Hook Events (Official Specification)
|
||||
|
||||
Complete list of available events:
|
||||
|
||||
| Event | When It Fires | Matcher Applies |
|
||||
|-------|--------------|----------------|
|
||||
| **PreToolUse** | After Claude creates tool params, before processing | Yes |
|
||||
| **PostToolUse** | Immediately after successful tool completion | Yes |
|
||||
| **PermissionRequest** | When permission dialogs shown to users | No |
|
||||
| **Notification** | When Claude Code sends notifications | No |
|
||||
| **UserPromptSubmit** | When users submit prompts, before Claude processes | No |
|
||||
| **Stop** | When main Claude agent finishes responding | No |
|
||||
| **SubagentStop** | When subagents (Task tool calls) complete | No |
|
||||
| **PreCompact** | Before compacting operations | No |
|
||||
| **SessionStart** | When sessions start or resume | No |
|
||||
| **SessionEnd** | When sessions terminate | No |
|
||||
|
||||
## Hook Types (Official Specification)
|
||||
|
||||
**Command Hooks** (`type: "command"`):
|
||||
|
||||
- Execute bash scripts with file system access
|
||||
- Default timeout: 60 seconds (customizable per hook)
|
||||
- Fast, deterministic operations
|
||||
- Use for formatters, linters, file ops, git commands
|
||||
|
||||
**Prompt-Based Hooks** (`type: "prompt"`):
|
||||
|
||||
- Send queries to Claude Haiku for context-aware decisions
|
||||
- Available for: `Stop`, `SubagentStop`, `UserPromptSubmit`, `PreToolUse`
|
||||
- Use when judgment/context understanding needed
|
||||
- Natural language evaluation
|
||||
|
||||
**Rule of thumb:** If you can write it as a bash script = command hook. If you need judgment = prompt hook.
|
||||
|
||||
## Hook Script Implementation Patterns (Best Practices)
|
||||
|
||||
### Bash vs Python for Hook Scripts
|
||||
|
||||
**Bash is ideal for:**
|
||||
|
||||
- Simple file operations (formatting, linting with external tools)
|
||||
- Calling CLI tools directly
|
||||
- Quick text processing with standard utilities
|
||||
- Minimal logic, mostly orchestration
|
||||
|
||||
**Python is better for:**
|
||||
|
||||
- Complex validation logic
|
||||
- JSON parsing and manipulation
|
||||
- Advanced text processing
|
||||
- Using Python libraries for analysis
|
||||
- Multi-step processing with error handling
|
||||
|
||||
### Python Hook Scripts with UV (Best Practice)
|
||||
|
||||
For Python-based hooks requiring dependencies or complex logic, use UV's single-file script format with inline metadata. This provides self-contained, executable scripts without separate environment setup.
|
||||
|
||||
**When to use Python hooks:**
|
||||
|
||||
- Parsing complex JSON from stdin
|
||||
- Advanced validation requiring libraries (AST analysis, schema validation)
|
||||
- Multi-step processing beyond simple shell pipelines
|
||||
- Need for structured error handling and reporting
|
||||
|
||||
**Pattern:** Use Skill tool: skill="box-factory:uv-scripts"
|
||||
|
||||
The uv-scripts skill provides complete patterns for creating Python hook scripts with inline dependencies, proper shebangs, and Claude Code integration.
|
||||
|
||||
**Quick example:**
|
||||
|
||||
```python
|
||||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# dependencies = ["ruff"]
|
||||
# ///
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
def main():
|
||||
file_paths = os.environ.get("CLAUDE_FILE_PATHS", "").split()
|
||||
if not file_paths:
|
||||
sys.exit(0)
|
||||
|
||||
result = subprocess.run(["ruff", "check", *file_paths])
|
||||
sys.exit(result.returncode)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
**Key advantages:**
|
||||
|
||||
- Self-contained (dependencies declared inline)
|
||||
- No separate virtual environment management
|
||||
- Executable directly with proper shebang
|
||||
- Fast startup with UV's performance
|
||||
- Perfect for plugin hooks (ships with dependencies)
|
||||
|
||||
## Matcher Syntax (Official Specification)
|
||||
|
||||
Matchers specify which tools trigger hooks (applies to PreToolUse and PostToolUse only):
|
||||
|
||||
**Exact matching:**
|
||||
```json
|
||||
"matcher": "Write"
|
||||
```
|
||||
|
||||
**Regex patterns with pipe:**
|
||||
```json
|
||||
"matcher": "Edit|Write"
|
||||
"matcher": "Notebook.*"
|
||||
```
|
||||
|
||||
**Wildcard (match all):**
|
||||
```json
|
||||
"matcher": "*"
|
||||
```
|
||||
|
||||
**Empty matcher:**
|
||||
Omit for events like `UserPromptSubmit` that don't apply to specific tools.
|
||||
|
||||
**Note:** Matchers are case-sensitive.
|
||||
|
||||
## Configuration Structure (Official Specification)
|
||||
|
||||
Located in `~/.claude/settings.json`, `.claude/settings.json`, or `.claude/settings.local.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"EventName": [
|
||||
{
|
||||
"matcher": "ToolPattern",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "bash-command",
|
||||
"timeout": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Timeout field:** Optional, specified in seconds (default 60).
|
||||
|
||||
## Hook Input (stdin) - Official Specification
|
||||
|
||||
All hooks receive JSON via stdin:
|
||||
|
||||
**Base structure (all events):**
|
||||
```json
|
||||
{
|
||||
"session_id": "string",
|
||||
"transcript_path": "path/to/transcript.jsonl",
|
||||
"cwd": "current/working/directory",
|
||||
"permission_mode": "default|plan|acceptEdits|bypassPermissions",
|
||||
"hook_event_name": "EventName"
|
||||
}
|
||||
```
|
||||
|
||||
**Event-specific fields:**
|
||||
|
||||
- **PreToolUse/PostToolUse**: Adds `tool_name`, `tool_input`
|
||||
- **UserPromptSubmit**: Adds `prompt`
|
||||
- Other events may include additional context
|
||||
|
||||
**Best practice:** Parse stdin JSON to access context, don't rely only on environment variables.
|
||||
|
||||
## Hook Output (stdout) - Official Specification
|
||||
|
||||
Two approaches for returning results:
|
||||
|
||||
### Simple Exit Code Approach
|
||||
|
||||
Just use exit codes and stderr for errors. Most common for straightforward hooks.
|
||||
|
||||
### Advanced JSON Output
|
||||
|
||||
Return structured JSON for sophisticated control:
|
||||
|
||||
```json
|
||||
{
|
||||
"continue": true,
|
||||
"stopReason": "Custom message",
|
||||
"suppressOutput": true,
|
||||
"systemMessage": "Warning to display",
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "EventName",
|
||||
"additionalContext": "string"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PostToolUse Communication Pattern (CRITICAL)
|
||||
|
||||
**Key insight:** PostToolUse hooks have two output channels with different visibility:
|
||||
|
||||
**For messages visible DIRECTLY to users (no verbose mode required):**
|
||||
|
||||
Use `systemMessage` field - displays immediately to users:
|
||||
|
||||
```json
|
||||
{
|
||||
"systemMessage": "Markdown formatted: path/to/file.md"
|
||||
}
|
||||
```
|
||||
|
||||
**For messages visible ONLY to Claude (user must enable verbose mode):**
|
||||
|
||||
Use `additionalContext` in `hookSpecificOutput`:
|
||||
|
||||
```json
|
||||
{
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PostToolUse",
|
||||
"additionalContext": "Internal context for Claude's awareness"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Complete output pattern:**
|
||||
|
||||
```python
|
||||
import json
|
||||
output = {
|
||||
"systemMessage": "Formatted successfully: file.md", # Shows to user directly
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PostToolUse",
|
||||
"additionalContext": "Additional context for Claude" # Only in verbose mode
|
||||
}
|
||||
}
|
||||
print(json.dumps(output), flush=True)
|
||||
sys.exit(0)
|
||||
```
|
||||
|
||||
**Common mistake:** Using only `additionalContext` when user feedback is needed. This requires users to enable verbose mode (CTRL-O) to see output.
|
||||
|
||||
**Correct pattern:**
|
||||
- **User feedback needed:** Use `systemMessage` (visible immediately)
|
||||
- **Claude context only:** Use `additionalContext` (verbose mode only)
|
||||
- **Both:** Include both fields in the JSON output
|
||||
- **Blocking errors:** Use exit 2 with stderr (rare, security/safety only)
|
||||
|
||||
### PreToolUse Special Output
|
||||
|
||||
For modifying or blocking tool execution:
|
||||
|
||||
```json
|
||||
{
|
||||
"permissionDecision": "allow|deny|ask",
|
||||
"updatedInput": {
|
||||
"modified": "tool parameters"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Use case:** Modify tool inputs before execution (e.g., add safety flags to bash commands).
|
||||
|
||||
## Environment Variables (Official Specification)
|
||||
|
||||
Available in command hooks:
|
||||
|
||||
| Variable | Purpose |
|
||||
|----------|---------|
|
||||
| `$CLAUDE_PROJECT_DIR` | Absolute path to project root |
|
||||
| `$CLAUDE_ENV_FILE` | File path for persisting env vars (SessionStart only) |
|
||||
| `${CLAUDE_PLUGIN_ROOT}` | Plugin directory path (for plugin hooks) |
|
||||
| `$CLAUDE_CODE_REMOTE` | `"true"` for remote, empty for local execution |
|
||||
|
||||
**Best practice:** Always quote variables: `"$CLAUDE_PROJECT_DIR"` not `$CLAUDE_PROJECT_DIR`
|
||||
|
||||
## Decision Framework
|
||||
|
||||
### Hook vs Agent vs Command
|
||||
|
||||
**Use Hook when:**
|
||||
|
||||
- Need guaranteed execution every time
|
||||
- Simple, deterministic rule (format, lint, validate)
|
||||
- Integrating with external tools
|
||||
- Performance/safety enforcement
|
||||
- Must happen at specific lifecycle event
|
||||
|
||||
**Use Agent when:**
|
||||
|
||||
- Complex decision-making involved
|
||||
- Need Claude's intelligence for analysis
|
||||
- Context-dependent logic
|
||||
- Natural language processing needed
|
||||
- Can be triggered proactively by context
|
||||
|
||||
**Use Command (Slash Command) when:**
|
||||
|
||||
- User wants explicit control over when it runs
|
||||
- Not tied to lifecycle events
|
||||
- One-off operations
|
||||
|
||||
## Common Use Patterns (Best Practices)
|
||||
|
||||
### SessionStart Pattern
|
||||
|
||||
**Purpose:** Initialize session state, inject context
|
||||
|
||||
```json
|
||||
{
|
||||
"SessionStart": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "cat .claude/project-context.md"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Key:** stdout becomes Claude's context. Use to load project guidelines, conventions, or state.
|
||||
|
||||
### UserPromptSubmit Pattern
|
||||
|
||||
**Purpose:** Validate or enrich prompts before Claude sees them
|
||||
|
||||
```json
|
||||
{
|
||||
"UserPromptSubmit": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "~/.claude/hooks/inject-security-reminders.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Key:** stdout goes to Claude. Can add context or use exit 2 to block prompts.
|
||||
|
||||
### PreToolUse Pattern
|
||||
|
||||
**Purpose:** Validate or modify before execution
|
||||
|
||||
```json
|
||||
{
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "~/.claude/hooks/security-check.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Power move:** Exit 2 to block dangerous commands and explain why to Claude.
|
||||
|
||||
### PostToolUse Pattern
|
||||
|
||||
**Purpose:** React to successful tool completion
|
||||
|
||||
```json
|
||||
{
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "prettier --write \"$CLAUDE_FILE_PATHS\" 2>/dev/null || true"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Common uses:** Format code, run linters, update documentation, cleanup.
|
||||
|
||||
**CRITICAL for PostToolUse:** To communicate results to users, hooks must output JSON to stdout with `systemMessage`:
|
||||
|
||||
```python
|
||||
#!/usr/bin/env -S uv run --quiet --script
|
||||
# /// script
|
||||
# dependencies = []
|
||||
# ///
|
||||
import json
|
||||
import sys
|
||||
|
||||
def output_json_response(system_message=None, additional_context=None):
|
||||
"""Output JSON response for Claude to process."""
|
||||
response = {}
|
||||
if system_message:
|
||||
response["systemMessage"] = system_message # Visible directly to user
|
||||
if additional_context:
|
||||
response["hookSpecificOutput"] = {
|
||||
"hookEventName": "PostToolUse",
|
||||
"additionalContext": additional_context # Only visible in verbose mode
|
||||
}
|
||||
print(json.dumps(response), flush=True)
|
||||
|
||||
# Read hook input from stdin
|
||||
hook_input = json.load(sys.stdin)
|
||||
file_path = hook_input.get("tool_input", {}).get("file_path")
|
||||
|
||||
# Run linter/formatter
|
||||
# ...
|
||||
|
||||
# Communicate result directly to user
|
||||
output_json_response(system_message=f"Formatted successfully: {file_path}")
|
||||
sys.exit(0)
|
||||
```
|
||||
|
||||
**Common mistakes:**
|
||||
- Using only `additionalContext` when user feedback is needed (requires verbose mode)
|
||||
- Writing to stderr instead of JSON stdout (completely invisible)
|
||||
|
||||
### Stop Pattern
|
||||
|
||||
**Purpose:** Session cleanup, final actions
|
||||
|
||||
```json
|
||||
{
|
||||
"Stop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "~/.claude/hooks/auto-commit.sh"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** Claude already responded, can't change that. Use for cleanup, notifications, test runs.
|
||||
|
||||
## Common Pitfalls (Best Practices)
|
||||
|
||||
### Pitfall #1: Blocking Everything
|
||||
|
||||
**Problem:** Overly aggressive hook blocks all operations
|
||||
|
||||
```json
|
||||
{
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "*",
|
||||
"hooks": [{"type": "command", "command": "exit 2"}]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Result:** Claude can't do anything, unusable.
|
||||
|
||||
**Better:** Selective blocking with clear criteria for security/safety only.
|
||||
|
||||
### Pitfall #2: Slow Hooks
|
||||
|
||||
**Problem:** Hook takes 30+ seconds, blocks user experience
|
||||
|
||||
```bash
|
||||
npm install # Slow, blocking
|
||||
exit 0
|
||||
```
|
||||
|
||||
**Impact:** Claude waits, terrible UX.
|
||||
|
||||
**Better:** Fast validation or background execution
|
||||
|
||||
```bash
|
||||
npm outdated | head -5 # Quick check
|
||||
exit 0
|
||||
```
|
||||
|
||||
**Or:** Adjust timeout for legitimately long operations:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "command",
|
||||
"command": "long-running-task.sh",
|
||||
"timeout": 120
|
||||
}
|
||||
```
|
||||
|
||||
### Pitfall #3: Silent Failures
|
||||
|
||||
**Problem:** Errors disappear into the void
|
||||
|
||||
```bash
|
||||
important-check || true
|
||||
exit 0
|
||||
```
|
||||
|
||||
**Result:** User never knows check failed.
|
||||
|
||||
**Better:** Clear error communication
|
||||
|
||||
```bash
|
||||
if ! important-check; then
|
||||
echo "Check failed: [specific reason]" >&2
|
||||
exit 1 # Non-blocking, but visible
|
||||
fi
|
||||
exit 0
|
||||
```
|
||||
|
||||
### Pitfall #4: Assuming User Interaction
|
||||
|
||||
**Problem:** Hook expects user input
|
||||
|
||||
```bash
|
||||
read -p "Confirm? " response
|
||||
exit 0
|
||||
```
|
||||
|
||||
**Result:** Hook hangs indefinitely (no user to respond).
|
||||
|
||||
**Better:** Fully automated decisions based on stdin JSON or environment.
|
||||
|
||||
### Pitfall #5: Ignoring Security
|
||||
|
||||
**Problem:** Hook doesn't validate inputs, vulnerable to path traversal
|
||||
|
||||
```bash
|
||||
cat "$SOME_PATH" # Dangerous if not validated
|
||||
```
|
||||
|
||||
**Result:** Could access sensitive files outside project.
|
||||
|
||||
**Better:** Validate and sanitize
|
||||
|
||||
```bash
|
||||
if [[ "$SOME_PATH" == *".."* ]]; then
|
||||
echo "Path traversal detected" >&2
|
||||
exit 2
|
||||
fi
|
||||
# Continue safely
|
||||
```
|
||||
|
||||
**Official guidance:** Skip sensitive files (`.env`, `.git/`, credentials). Validate inputs from stdin.
|
||||
|
||||
### Pitfall #6: Not Quoting Variables
|
||||
|
||||
**Problem:** Unquoted shell variables break with spaces
|
||||
|
||||
```bash
|
||||
prettier --write $CLAUDE_FILE_PATHS # Breaks if path has spaces
|
||||
```
|
||||
|
||||
**Better:** Always quote variables
|
||||
|
||||
```bash
|
||||
prettier --write "$CLAUDE_FILE_PATHS"
|
||||
```
|
||||
|
||||
### Pitfall #7: PostToolUse Using Wrong Output Field
|
||||
|
||||
**Problem:** Hook uses `additionalContext` when user feedback is needed
|
||||
|
||||
```python
|
||||
# Wrong - Only visible in verbose mode (CTRL-O)
|
||||
import json
|
||||
output = {
|
||||
"hookSpecificOutput": {
|
||||
"hookEventName": "PostToolUse",
|
||||
"additionalContext": "Formatted successfully: file.md"
|
||||
}
|
||||
}
|
||||
print(json.dumps(output), flush=True)
|
||||
sys.exit(0)
|
||||
```
|
||||
|
||||
**Result:** User must enable verbose mode to see feedback.
|
||||
|
||||
**Better:** Use `systemMessage` for direct user visibility
|
||||
|
||||
```python
|
||||
# Correct - Visible immediately to user
|
||||
import json
|
||||
output = {
|
||||
"systemMessage": "Formatted successfully: file.md"
|
||||
}
|
||||
print(json.dumps(output), flush=True)
|
||||
sys.exit(0)
|
||||
```
|
||||
|
||||
**Why:**
|
||||
- `systemMessage` displays directly to users (no verbose mode required)
|
||||
- `additionalContext` only visible in verbose mode (CTRL-O) or as Claude's context
|
||||
- stderr output is only for blocking errors (exit 2)
|
||||
|
||||
## Security Considerations (Official Guidance)
|
||||
|
||||
**Critical warning from docs:** "Claude Code hooks execute arbitrary shell commands on your system automatically."
|
||||
|
||||
**Implications:**
|
||||
|
||||
- Hooks can access/modify any files your user account permits
|
||||
- You bear sole responsibility for configured commands
|
||||
- Test thoroughly in safe environments first
|
||||
- Review hooks from untrusted sources carefully
|
||||
|
||||
**Protection mechanism:**
|
||||
|
||||
- Configuration snapshots captured at startup
|
||||
- Hook changes require review via `/hooks` menu
|
||||
- Prevents mid-session malicious modifications
|
||||
|
||||
**Best practices:**
|
||||
|
||||
1. Validate and sanitize all inputs from stdin
|
||||
2. Block path traversal (`..` in paths)
|
||||
3. Use absolute paths with `$CLAUDE_PROJECT_DIR`
|
||||
4. Skip sensitive files (`.env`, credentials, `.git/`)
|
||||
5. For prompt-based hooks, be specific about criteria
|
||||
6. Set appropriate timeouts
|
||||
7. Test in isolated environments first
|
||||
|
||||
## Debugging Hooks (Best Practices)
|
||||
|
||||
**View hook execution:**
|
||||
|
||||
Press **CTRL-R** in Claude Code to see:
|
||||
- Hook stdout/stderr
|
||||
- Execution flow
|
||||
- Exit codes
|
||||
- Timing information
|
||||
|
||||
**Add logging to hooks:**
|
||||
|
||||
```bash
|
||||
echo "Hook triggered: $(date)" >> ~/.claude/hook-log.txt
|
||||
echo "Input: $SOME_VAR" >> ~/.claude/hook-log.txt
|
||||
# Continue with hook logic
|
||||
exit 0
|
||||
```
|
||||
|
||||
**Parse stdin for debugging:**
|
||||
|
||||
```bash
|
||||
# Save stdin to debug
|
||||
cat > /tmp/hook-debug.json
|
||||
cat /tmp/hook-debug.json | jq '.' # Pretty print
|
||||
exit 0
|
||||
```
|
||||
|
||||
## Advanced Features (Official Specification)
|
||||
|
||||
### Modifying Tool Inputs (PreToolUse)
|
||||
|
||||
Return JSON to modify tool parameters:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Read stdin
|
||||
INPUT=$(cat)
|
||||
|
||||
# Add safety flag to bash commands
|
||||
MODIFIED=$(echo "$INPUT" | jq '.tool_input.command = .tool_input.command + " --safe-mode"')
|
||||
|
||||
# Return modified input
|
||||
echo "$MODIFIED" | jq '{permissionDecision: "allow", updatedInput: .tool_input}'
|
||||
exit 0
|
||||
```
|
||||
|
||||
### Custom Timeouts
|
||||
|
||||
Adjust timeout per hook:
|
||||
|
||||
```json
|
||||
{
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "./long-build.sh",
|
||||
"timeout": 300
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Prompt-Based Intelligence
|
||||
|
||||
Use Claude Haiku for context-aware decisions:
|
||||
|
||||
```json
|
||||
{
|
||||
"PreToolUse": [
|
||||
{
|
||||
"matcher": "Bash",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "prompt",
|
||||
"command": "Analyze this bash command for security risks. If dangerous, explain why and recommend safer alternative."
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Plugin Integration
|
||||
|
||||
When creating hooks for plugins:
|
||||
|
||||
**Structure:**
|
||||
```
|
||||
my-plugin/
|
||||
├── .claude-plugin/plugin.json
|
||||
└── hooks/
|
||||
└── hooks.json
|
||||
```
|
||||
|
||||
**Reference plugin root:**
|
||||
```bash
|
||||
"${CLAUDE_PLUGIN_ROOT}/scripts/hook-script.sh"
|
||||
```
|
||||
|
||||
See plugin-design skill for complete plugin context.
|
||||
|
||||
## Hook Quality Checklist
|
||||
|
||||
Before deploying hooks:
|
||||
|
||||
**Functionality (from official docs):**
|
||||
|
||||
- ✓ Correct event type for use case
|
||||
- ✓ Valid matcher pattern (if applicable)
|
||||
- ✓ Proper JSON structure in settings
|
||||
- ✓ Appropriate timeout configured
|
||||
|
||||
**Quality (best practices):**
|
||||
|
||||
- ✓ Fast execution (< 60s or custom timeout)
|
||||
- ✓ Clear error messages to stderr
|
||||
- ✓ Appropriate exit codes (0, 2, other)
|
||||
- ✓ No user interaction required
|
||||
- ✓ Variables quoted properly
|
||||
- ✓ Inputs validated/sanitized
|
||||
|
||||
**Security (best practices):**
|
||||
|
||||
- ✓ Path traversal blocked
|
||||
- ✓ Sensitive files skipped
|
||||
- ✓ Absolute paths used
|
||||
- ✓ No secret exposure
|
||||
- ✓ Tested in safe environment
|
||||
|
||||
## Example: High-Quality Hook
|
||||
|
||||
**Basic (hypothetical docs example):**
|
||||
|
||||
```json
|
||||
{
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write",
|
||||
"hooks": [{"type": "command", "command": "prettier --write"}]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Issues:**
|
||||
|
||||
- ❌ Missing file path variable
|
||||
- ❌ No error handling
|
||||
- ❌ Doesn't catch Edit operations
|
||||
|
||||
**Excellent (applying best practices):**
|
||||
|
||||
```json
|
||||
{
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "prettier --write \"$CLAUDE_FILE_PATHS\" 2>/dev/null || true",
|
||||
"timeout": 30
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Improvements:**
|
||||
|
||||
- ✅ Uses `$CLAUDE_FILE_PATHS` variable
|
||||
- ✅ Quoted variable for spaces
|
||||
- ✅ Error suppression (|| true) prevents blocking
|
||||
- ✅ Catches both Write and Edit
|
||||
- ✅ Custom timeout for faster failures
|
||||
- ✅ Redirects stderr to avoid noise
|
||||
|
||||
## Documentation References
|
||||
|
||||
These are the authoritative sources. Fetch them before creating hooks:
|
||||
|
||||
**Core specifications:**
|
||||
|
||||
- https://code.claude.com/docs/en/hooks - Complete hook reference
|
||||
|
||||
**Related topics:**
|
||||
|
||||
- See agent-design skill for when to use agents instead
|
||||
- See slash-command-design skill for user-triggered operations
|
||||
- See plugin-design skill for packaging hooks in plugins
|
||||
- See uv-scripts skill for Python-based hook implementation patterns
|
||||
|
||||
**Remember:** Official docs provide structure and features. This skill provides best practices and patterns for creating excellent hooks.
|
||||
722
skills/plugin-design/SKILL.md
Normal file
722
skills/plugin-design/SKILL.md
Normal file
@@ -0,0 +1,722 @@
|
||||
---
|
||||
name: box-factory-plugin-design
|
||||
description: Interpretive guidance for designing Claude Code plugins. Helps you understand plugin architecture, marketplace distribution, and when plugins are the right pattern. Use when creating or reviewing plugins.
|
||||
---
|
||||
|
||||
# Plugin Design Skill
|
||||
|
||||
This skill provides interpretive guidance and best practices for creating Claude Code plugins. **ALWAYS fetch current official documentation before creating plugins** - this skill helps you understand what the docs mean and how to create excellent plugins.
|
||||
|
||||
## Required Reading Before Creating Plugins
|
||||
|
||||
Fetch these docs with WebFetch every time:
|
||||
|
||||
- **<https://code.claude.com/docs/en/plugins>** - Plugin overview and quickstart
|
||||
- **<https://code.claude.com/docs/en/plugins-reference>** - Complete specifications
|
||||
- **<https://code.claude.com/docs/en/plugin-marketplaces>** - Distribution patterns
|
||||
|
||||
## Core Understanding
|
||||
|
||||
### Plugins Are Packaging, Not Functionality
|
||||
|
||||
**Key insight:** Plugins don't add new capabilities to Claude Code. They package existing extension points (commands, agents, skills, hooks, MCP servers) for distribution.
|
||||
|
||||
**What this means:**
|
||||
|
||||
- Plugins bundle components together
|
||||
- The value is distribution and discoverability
|
||||
- Components work the same inside or outside plugins
|
||||
- You're organizing and sharing, not creating new primitives
|
||||
|
||||
**Decision test:** If you're asking "should this be a plugin?", you're asking the wrong question. Ask "should I package these existing components for sharing?"
|
||||
|
||||
### Critical Directory Structure (Official Specification)
|
||||
|
||||
**The #1 mistake** that causes plugins to install but not work:
|
||||
|
||||
```
|
||||
✅ Correct:
|
||||
plugin-name/
|
||||
├── .claude-plugin/
|
||||
│ └── plugin.json ← Only metadata here
|
||||
├── commands/ ← At plugin root
|
||||
├── agents/ ← At plugin root
|
||||
├── skills/ ← At plugin root
|
||||
└── hooks/ ← At plugin root
|
||||
|
||||
❌ Wrong (won't work):
|
||||
plugin-name/
|
||||
└── .claude-plugin/
|
||||
├── plugin.json
|
||||
├── commands/ ← Won't be found!
|
||||
└── agents/ ← Won't be found!
|
||||
```
|
||||
|
||||
**Official docs say:** "All other directories (commands/, agents/, skills/, hooks/) must be at the plugin root, not inside `.claude-plugin/`."
|
||||
|
||||
### Skills Directory Structure
|
||||
|
||||
Skills use subdirectories with a `SKILL.md` file:
|
||||
|
||||
```
|
||||
skills/
|
||||
├── skill-one/
|
||||
│ ├── SKILL.md ← Skill definition
|
||||
│ └── helpers.py ← Supporting files (optional)
|
||||
└── skill-two/
|
||||
└── SKILL.md
|
||||
```
|
||||
|
||||
## Plugin Manifest (plugin.json) - Official Specification
|
||||
|
||||
Located at `.claude-plugin/plugin.json`:
|
||||
|
||||
### Required Fields
|
||||
|
||||
- **name**: Unique identifier in kebab-case (e.g., "deployment-tools")
|
||||
|
||||
### Optional Metadata Fields We Use
|
||||
|
||||
| Field | Type | Purpose |
|
||||
|-------|------|---------|
|
||||
| version | string | Semantic versioning (e.g., "2.1.0") |
|
||||
| description | string | Brief plugin purpose explanation |
|
||||
| repository | string | Source code location |
|
||||
|
||||
### Optional Metadata Fields We NEVER Use
|
||||
|
||||
| Field | Type | Purpose |
|
||||
|-------|------|---------|
|
||||
| author | object | Author details: `{name, email, url}` |
|
||||
| homepage | string | Documentation URL |
|
||||
| license | string | License identifier (MIT, Apache-2.0, etc.) |
|
||||
| keywords | array | Discovery tags for categorization |
|
||||
|
||||
### Component Path Fields (Optional)
|
||||
|
||||
Override default locations:
|
||||
|
||||
- **commands**: Additional command files/directories (string or array)
|
||||
- **agents**: Agent markdown files (string or array)
|
||||
- **hooks**: Hook configuration path or inline JSON
|
||||
- **mcpServers**: MCP server configuration path or inline JSON
|
||||
|
||||
**Note:** Custom paths *supplement* default directories, they don't replace them.
|
||||
|
||||
**Best practice:** Always include `description` and `version` even though they're optional - improves discoverability and user trust. Do NOT include `author`, `repository`, `homepage`, `license`, or `keywords` unless explicitly specified.
|
||||
|
||||
## Advanced Features (Official Specification)
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Use `${CLAUDE_PLUGIN_ROOT}` in paths to reference the plugin's absolute directory.
|
||||
|
||||
### Custom Component Paths
|
||||
|
||||
Specify additional locations for components:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-plugin",
|
||||
"commands": ["./extra-commands", "./legacy/commands"],
|
||||
"agents": "./custom-agents"
|
||||
}
|
||||
```
|
||||
|
||||
All paths must be relative to plugin root and start with `./`
|
||||
|
||||
### Inline Component Configuration
|
||||
|
||||
Define hooks or MCP servers directly in plugin.json instead of separate files:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-plugin",
|
||||
"hooks": {
|
||||
"PreToolUse:Bash": "./hooks/bash-guard.sh"
|
||||
},
|
||||
"mcpServers": {
|
||||
"custom-server": {
|
||||
"command": "node",
|
||||
"args": ["./server.js"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### MCP Server Configuration (Best Practices)
|
||||
|
||||
**CRITICAL:** When configuring MCP servers in plugins, follow these security and maintainability patterns.
|
||||
|
||||
#### Always Use External Configuration Files
|
||||
|
||||
**✅ CORRECT - External file:**
|
||||
|
||||
```json
|
||||
// plugin.json
|
||||
{
|
||||
"name": "my-plugin",
|
||||
"mcpServers": "./.mcp.json"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
// .mcp.json (at plugin root)
|
||||
{
|
||||
"github": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-github"],
|
||||
"env": {
|
||||
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**❌ WRONG - Inline configuration:**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-plugin",
|
||||
"mcpServers": {
|
||||
"github": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-github"],
|
||||
"env": {
|
||||
"GITHUB_PERSONAL_ACCESS_TOKEN": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Why external files are better:**
|
||||
- Separation of concerns (metadata vs configuration)
|
||||
- Easier to edit MCP config independently
|
||||
- Cleaner plugin.json focused on plugin metadata
|
||||
- Matches user expectations from standalone MCP setups
|
||||
|
||||
#### Always Use Environment Variable References
|
||||
|
||||
**✅ CORRECT - Environment variable reference:**
|
||||
|
||||
```json
|
||||
{
|
||||
"server-name": {
|
||||
"command": "server-binary",
|
||||
"env": {
|
||||
"API_KEY": "${API_KEY}",
|
||||
"AUTH_TOKEN": "${AUTH_TOKEN}",
|
||||
"DATABASE_URL": "${DATABASE_URL}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**❌ WRONG - Hardcoded empty strings:**
|
||||
|
||||
```json
|
||||
{
|
||||
"server-name": {
|
||||
"env": {
|
||||
"API_KEY": "",
|
||||
"AUTH_TOKEN": "",
|
||||
"DATABASE_URL": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**❌ VERY WRONG - Hardcoded actual secrets:**
|
||||
|
||||
```json
|
||||
{
|
||||
"server-name": {
|
||||
"env": {
|
||||
"API_KEY": "sk_live_abc123..."
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Why environment variables are critical:**
|
||||
- **Security**: Never commit secrets to git history
|
||||
- **Portability**: Different users/environments have different credentials
|
||||
- **Standard practice**: `${VAR_NAME}` is the established MCP pattern
|
||||
- **Documentation clarity**: Shows what env vars are required
|
||||
|
||||
#### Document Required Environment Variables
|
||||
|
||||
**In your README, always include:**
|
||||
|
||||
```markdown
|
||||
## MCP Server Setup
|
||||
|
||||
This plugin includes the [Server Name] MCP server.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- [Tool requirements, e.g., Node.js, Python]
|
||||
- [Service account or API access]
|
||||
|
||||
### Configuration
|
||||
|
||||
1. Obtain credentials:
|
||||
- Visit [credential URL]
|
||||
- Create [token/API key] with `scope1`, `scope2` permissions
|
||||
|
||||
2. Set environment variables:
|
||||
```bash
|
||||
export API_KEY="your_key_here"
|
||||
export AUTH_TOKEN="your_token_here"
|
||||
```
|
||||
|
||||
3. The MCP server will start automatically when the plugin is enabled
|
||||
```
|
||||
|
||||
**Required documentation elements:**
|
||||
- Prerequisites (tools, accounts, permissions)
|
||||
- How to obtain credentials with specific scopes/permissions
|
||||
- Exact environment variable names to set
|
||||
- Example export commands
|
||||
- When the server starts (usually: when plugin enabled)
|
||||
|
||||
#### Common MCP Server Types
|
||||
|
||||
**GitHub:**
|
||||
```json
|
||||
{
|
||||
"github": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-github"],
|
||||
"env": {
|
||||
"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_PERSONAL_ACCESS_TOKEN}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Filesystem:**
|
||||
```json
|
||||
{
|
||||
"filesystem": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/allowed/path"],
|
||||
"env": {}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Database:**
|
||||
```json
|
||||
{
|
||||
"database": {
|
||||
"command": "npx",
|
||||
"args": ["-y", "@modelcontextprotocol/server-postgres"],
|
||||
"env": {
|
||||
"DATABASE_URL": "${DATABASE_URL}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Custom server using plugin root:**
|
||||
```json
|
||||
{
|
||||
"custom": {
|
||||
"command": "${CLAUDE_PLUGIN_ROOT}/servers/custom-server",
|
||||
"args": ["--config", "${CLAUDE_PLUGIN_ROOT}/config.json"],
|
||||
"env": {
|
||||
"CUSTOM_API_KEY": "${CUSTOM_API_KEY}"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### MCP Configuration Checklist
|
||||
|
||||
Before publishing plugin with MCP servers:
|
||||
|
||||
**Security:**
|
||||
- ✓ All secrets use `${ENV_VAR}` references (never hardcoded)
|
||||
- ✓ No empty string placeholders for secrets
|
||||
- ✓ No actual credentials in git history
|
||||
- ✓ .env files in .gitignore if used for local testing
|
||||
|
||||
**Structure:**
|
||||
- ✓ MCP configuration in external file (`.mcp.json` or custom path)
|
||||
- ✓ Path in plugin.json is relative and starts with `./`
|
||||
- ✓ Valid JSON syntax in MCP configuration file
|
||||
|
||||
**Documentation:**
|
||||
- ✓ README explains how to obtain credentials
|
||||
- ✓ Required scopes/permissions documented
|
||||
- ✓ Environment variable names clearly listed
|
||||
- ✓ Example export commands provided
|
||||
- ✓ Troubleshooting section for common issues
|
||||
|
||||
**Testing:**
|
||||
- ✓ Verified MCP server starts with plugin enabled
|
||||
- ✓ Tested with actual credentials in environment
|
||||
- ✓ Confirmed required tools/dependencies work
|
||||
|
||||
## Marketplace Distribution (Official Specification)
|
||||
|
||||
### Marketplace.json Structure
|
||||
|
||||
Located at `.claude-plugin/marketplace.json`:
|
||||
|
||||
**Required fields:**
|
||||
|
||||
- **name**: Marketplace identifier (kebab-case)
|
||||
- **owner**: Maintainer information object
|
||||
- **plugins**: Array of plugin entries
|
||||
|
||||
**Plugin entry fields:**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "plugin-name",
|
||||
"source": "./plugins/plugin-name",
|
||||
"description": "Optional override",
|
||||
"strict": true
|
||||
}
|
||||
```
|
||||
|
||||
### Source Types
|
||||
|
||||
**Local path (development):**
|
||||
|
||||
```json
|
||||
"source": "./plugins/my-plugin"
|
||||
```
|
||||
|
||||
**GitHub repository:**
|
||||
|
||||
```json
|
||||
"source": {
|
||||
"source": "github",
|
||||
"repo": "owner/repo"
|
||||
}
|
||||
```
|
||||
|
||||
**Git URL:**
|
||||
|
||||
```json
|
||||
"source": {
|
||||
"source": "url",
|
||||
"url": "https://gitlab.com/user/plugin.git"
|
||||
}
|
||||
```
|
||||
|
||||
### The `strict` Field
|
||||
|
||||
- **`strict: true`** (default): Plugin must have its own `plugin.json`
|
||||
- **`strict: false`**: Marketplace entry serves as complete manifest
|
||||
|
||||
**Use `strict: false` when:** Packaging third-party content without modifying it.
|
||||
|
||||
## Decision Framework
|
||||
|
||||
### When to Create a Plugin
|
||||
|
||||
**Create plugin when:**
|
||||
|
||||
- You have multiple related components (commands + agents + hooks)
|
||||
- You want to share with team/community
|
||||
- You need versioning and distribution
|
||||
- You want one-command installation (`/plugin install`)
|
||||
|
||||
**Don't create plugin when:**
|
||||
|
||||
- Single command/agent (just share the file)
|
||||
- Personal workflow (no distribution need)
|
||||
- Rapid iteration (plugins add packaging overhead)
|
||||
- Testing concepts (develop components first, package later)
|
||||
|
||||
### Plugin Scope Philosophy (Best Practices)
|
||||
|
||||
**Good plugin scope:**
|
||||
|
||||
- Focused purpose (testing suite, security scanner, docs generator)
|
||||
- Related components work together
|
||||
- Clear value proposition
|
||||
- Composable with other plugins
|
||||
|
||||
**Bad plugin scope:**
|
||||
|
||||
- "Everything for development" (too broad)
|
||||
- Unrelated utilities thrown together
|
||||
- Duplicates core functionality
|
||||
- Conflicts with other plugins
|
||||
|
||||
## Development Workflow (Best Practices)
|
||||
|
||||
The docs show the mechanics. Here's the philosophy:
|
||||
|
||||
1. **Build components first** - Create and test commands/agents individually
|
||||
2. **Test without packaging** - Use `.claude/` directories for iteration
|
||||
3. **Package when ready** - Add plugin.json and organize structure
|
||||
4. **Validate locally** - Use `claude plugin validate .` command
|
||||
5. **Create test marketplace** - Local marketplace with absolute paths
|
||||
6. **Install and test** - `/plugin marketplace add ./path/to/marketplace`
|
||||
7. **Iterate** - Fix issues, restart Claude Code, test again
|
||||
8. **Document** - Write comprehensive README
|
||||
9. **Publish** - Push to GitHub, share marketplace
|
||||
|
||||
**Key insight:** Don't start with plugin structure. Build components, then package them.
|
||||
|
||||
## Testing Commands (Official Specification)
|
||||
|
||||
**Validate plugin structure:**
|
||||
|
||||
```bash
|
||||
claude plugin validate .
|
||||
```
|
||||
|
||||
Checks JSON syntax and directory structure.
|
||||
|
||||
**Add local marketplace for testing:**
|
||||
|
||||
```bash
|
||||
/plugin marketplace add ./absolute/path/to/marketplace
|
||||
```
|
||||
|
||||
**Install from local marketplace:**
|
||||
|
||||
```bash
|
||||
/plugin install plugin-name@marketplace-name
|
||||
```
|
||||
|
||||
**Verify installation:**
|
||||
|
||||
Check `/help` for newly installed commands and agents.
|
||||
|
||||
## Common Pitfalls (Best Practices)
|
||||
|
||||
### Pitfall #1: Components in Wrong Directory
|
||||
|
||||
**Problem:** Putting commands/agents inside `.claude-plugin/`
|
||||
|
||||
**Why it fails:** Claude Code only looks at plugin root for components
|
||||
|
||||
**Solution:** Keep `.claude-plugin/` for metadata only, put all components at root
|
||||
|
||||
### Pitfall #2: Premature Pluginification
|
||||
|
||||
**Problem:** Creating plugin for single command or concept
|
||||
|
||||
**Why it fails:**
|
||||
|
||||
- Overhead of marketplace setup
|
||||
- Harder to iterate quickly
|
||||
- Users just want the file
|
||||
- More complex to maintain
|
||||
|
||||
**Better:** Share the markdown file directly, create plugin later if collection grows
|
||||
|
||||
### Pitfall #3: Kitchen Sink Plugin
|
||||
|
||||
**Problem:** "All my utilities" plugin with unrelated components
|
||||
|
||||
**Why it fails:**
|
||||
|
||||
- Unclear purpose
|
||||
- Users only want subset
|
||||
- Hard to maintain and version
|
||||
- Discovery problems
|
||||
|
||||
**Better:** Focused plugins (testing tools, git helpers, docs generators)
|
||||
|
||||
### Pitfall #4: Missing Documentation
|
||||
|
||||
**Problem:** Plugin without README or usage examples
|
||||
|
||||
**Why it fails:**
|
||||
|
||||
- Users don't know what's included
|
||||
- No installation instructions
|
||||
- No troubleshooting guidance
|
||||
- Low adoption
|
||||
|
||||
**Solution:** Comprehensive README with:
|
||||
|
||||
- Installation steps
|
||||
- Component list with examples
|
||||
- Required dependencies
|
||||
- Troubleshooting section
|
||||
- Changelog
|
||||
|
||||
### Pitfall #5: Ignoring Semantic Versioning
|
||||
|
||||
**Problem:** Breaking changes in minor/patch versions
|
||||
|
||||
**Why it fails:** Users expect:
|
||||
|
||||
- `1.0.0 → 1.0.1` - Bug fixes only, safe to auto-update
|
||||
- `1.0.0 → 1.1.0` - New features, backward compatible
|
||||
- `1.0.0 → 2.0.0` - Breaking changes, needs migration
|
||||
|
||||
**Solution:** Follow semver strictly, document breaking changes
|
||||
|
||||
## Marketplace Organization (Best Practices)
|
||||
|
||||
### Embedded vs External Plugins
|
||||
|
||||
**Embedded (monorepo approach):**
|
||||
|
||||
```
|
||||
marketplace/
|
||||
├── .claude-plugin/marketplace.json
|
||||
└── plugins/
|
||||
├── plugin-one/
|
||||
└── plugin-two/
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
|
||||
- Single source of truth
|
||||
- Atomic updates
|
||||
- Easier testing
|
||||
|
||||
**Cons:**
|
||||
|
||||
- Monorepo management overhead
|
||||
- Slower independent development
|
||||
|
||||
**External (distributed approach):**
|
||||
|
||||
```json
|
||||
{
|
||||
"plugins": [
|
||||
{
|
||||
"name": "plugin-one",
|
||||
"source": {
|
||||
"source": "github",
|
||||
"repo": "org/plugin-one"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Pros:**
|
||||
|
||||
- Independent versioning
|
||||
- Faster iteration
|
||||
- Individual repos easier to manage
|
||||
|
||||
**Cons:**
|
||||
|
||||
- Dependency coordination
|
||||
- Potential version conflicts
|
||||
|
||||
### Team Distribution Strategy
|
||||
|
||||
**Official mechanism:** Configure `.claude/settings.json` at repository level:
|
||||
|
||||
```json
|
||||
{
|
||||
"extraKnownMarketplaces": ["owner/marketplace-repo"],
|
||||
"enabledPlugins": ["plugin-name@marketplace-name"]
|
||||
}
|
||||
```
|
||||
|
||||
**Best practices to consider:**
|
||||
|
||||
- Test plugins thoroughly before team rollout
|
||||
- Document required environment variables
|
||||
- Have rollback plan if plugin breaks
|
||||
- Establish approval process for new plugins
|
||||
- Communicate plugin updates to team
|
||||
|
||||
## Plugin Quality Checklist
|
||||
|
||||
Before publishing:
|
||||
|
||||
**Structure (from official docs):**
|
||||
|
||||
- ✓ Valid `plugin.json` at `.claude-plugin/plugin.json`
|
||||
- ✓ Components at plugin root (not in `.claude-plugin/`)
|
||||
- ✓ Proper directory names (commands, agents, skills, hooks)
|
||||
- ✓ `claude plugin validate .` passes
|
||||
- ✓ Relative paths start with `./`
|
||||
|
||||
**Metadata (best practices):**
|
||||
|
||||
- ✓ Descriptive name (kebab-case)
|
||||
- ✓ Clear description (what problem it solves)
|
||||
- ✓ Semantic versioning
|
||||
- ✓ Author info (for support)
|
||||
- ✓ Repository link (for issues/PRs)
|
||||
- ✓ Keywords for discovery
|
||||
|
||||
**Documentation (best practices):**
|
||||
|
||||
- ✓ Comprehensive README
|
||||
- ✓ Installation instructions
|
||||
- ✓ Usage examples for each component
|
||||
- ✓ Required dependencies documented
|
||||
- ✓ Troubleshooting section
|
||||
- ✓ Changelog
|
||||
|
||||
**Design (best practices):**
|
||||
|
||||
- ✓ Focused scope (clear purpose)
|
||||
- ✓ No duplication of core functionality
|
||||
- ✓ Components complement each other
|
||||
- ✓ Tested locally before publishing
|
||||
|
||||
## Example: High-Quality Plugin Manifest
|
||||
|
||||
**Basic (what docs show):**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "my-plugin",
|
||||
"description": "A plugin",
|
||||
"version": "1.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
**Issues:**
|
||||
|
||||
- ❌ Vague description
|
||||
|
||||
**Excellent (applying best practices):**
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "python-testing-suite",
|
||||
"version": "1.0.0",
|
||||
"description": "Comprehensive Python testing tools with pytest integration, coverage reporting, and failure analysis",
|
||||
"repository": "https://github.com/username/python-testing-suite",
|
||||
}
|
||||
```
|
||||
|
||||
**Improvements:**
|
||||
|
||||
- ✅ Specific description (what it does, how it helps)
|
||||
- ✅ (optional, but okay)Repository for issues and PRs
|
||||
|
||||
## Documentation References
|
||||
|
||||
These are the authoritative sources. Fetch them before creating plugins:
|
||||
|
||||
**Plugin creation:**
|
||||
|
||||
- <https://code.claude.com/docs/en/plugins> - Overview and quickstart
|
||||
|
||||
**Complete specifications:**
|
||||
|
||||
- <https://code.claude.com/docs/en/plugins-reference> - All schemas and patterns
|
||||
|
||||
**Distribution:**
|
||||
|
||||
- <https://code.claude.com/docs/en/plugin-marketplaces> - Marketplace setup
|
||||
|
||||
**Component specifications:**
|
||||
|
||||
- Reference agent-design, slash-command-design skills for component details
|
||||
|
||||
**Remember:** Official docs provide structure and features. This skill provides best practices and patterns for creating excellent plugins.
|
||||
907
skills/skill-design/SKILL.md
Normal file
907
skills/skill-design/SKILL.md
Normal file
@@ -0,0 +1,907 @@
|
||||
---
|
||||
name: box-factory-skill-design
|
||||
description: Meta-skill that teaches how to design Claude Code skills following the Box Factory philosophy. Helps you understand when to create skills, how to structure them for low maintenance, and how to add value beyond documentation. Use when creating or reviewing skills.
|
||||
---
|
||||
|
||||
# Skill Design Skill
|
||||
|
||||
This meta-skill teaches you how to design excellent Claude Code skills. **Skills are unique among Claude Code components** - they provide progressive knowledge disclosure and interpretive guidance that loads when relevant.
|
||||
|
||||
## Required Reading Before Creating Skills
|
||||
|
||||
**Official documentation:** Skills are part of the agent system but don't have dedicated documentation. Their purpose and structure are inferred from:
|
||||
|
||||
- **<https://code.claude.com/docs/en/sub-agents.md>** - Skills mentioned as knowledge loaded when relevant
|
||||
- Existing skills in the wild - Examine high-quality skills for patterns
|
||||
|
||||
## Core Understanding
|
||||
|
||||
### Skills Are Progressive Knowledge Disclosure
|
||||
|
||||
**Key insight:** Skills solve the "you can't put everything in the system prompt" problem.
|
||||
|
||||
**What this means:**
|
||||
|
||||
- **Without skills:** Important knowledge buried in long prompts or forgotten
|
||||
- **With skills:** Knowledge loads automatically when topics become relevant
|
||||
- **Value proposition:** Right information at the right time, without token bloat
|
||||
|
||||
**Decision test:** Does this information need to be available across multiple contexts, but not always?
|
||||
|
||||
### Skills vs System Prompts vs CLAUDE.md
|
||||
|
||||
**Skills are for:**
|
||||
|
||||
- Substantial procedural expertise (20+ lines of guidance)
|
||||
- Domain-specific knowledge needed sporadically
|
||||
- Interpretive frameworks that enhance understanding
|
||||
- Best practices that apply across multiple scenarios
|
||||
|
||||
**System prompts are for:**
|
||||
|
||||
- Always-relevant instructions
|
||||
- Core behavior and personality
|
||||
- Universal constraints
|
||||
|
||||
**CLAUDE.md is for:**
|
||||
|
||||
- Project-specific context
|
||||
- Repository structure
|
||||
- Team conventions
|
||||
- Always-loaded information
|
||||
|
||||
### Knowledge Delta Filter (Critical Understanding)
|
||||
|
||||
**THE MOST IMPORTANT PRINCIPLE:** Skills should only document what Claude DOESN'T already know.
|
||||
|
||||
**Why this matters:** Claude's training includes extensive knowledge of common development tools, standard workflows, well-established frameworks, and general best practices. Skills that duplicate this base knowledge waste tokens and create maintenance burden without adding value.
|
||||
|
||||
**Skills document the DELTA** - the difference between Claude's base knowledge and what Claude needs to know for your specific context.
|
||||
|
||||
**INCLUDE in skills (the delta):**
|
||||
|
||||
✅ **User-specific preferences and conventions**
|
||||
- "This user wants commit messages terse, single-line, no emojis, no attribution"
|
||||
- "This team uses specific naming conventions not found in standard docs"
|
||||
- "This project requires custom workflow steps"
|
||||
- Example: User's preference for no "Generated with Claude Code" messages
|
||||
|
||||
✅ **Edge cases and gotchas Claude would miss**
|
||||
- "Pre-commit hooks that modify files require retry with --amend"
|
||||
- "This API has undocumented rate limiting behavior"
|
||||
- "File system paths need special escaping in this environment"
|
||||
- Example: Specific retry logic for linter hooks that auto-fix
|
||||
|
||||
✅ **Decision frameworks for ambiguous situations**
|
||||
- "When to use gh CLI vs GitHub MCP server in this project"
|
||||
- "Tool selection hierarchy when multiple options exist"
|
||||
- "Which pattern to prefer when standards conflict"
|
||||
- Example: Prefer gh CLI when available, fall back to MCP
|
||||
|
||||
✅ **Things Claude gets wrong without guidance**
|
||||
- "Claude invents unsupported frontmatter in slash commands"
|
||||
- "Claude uses deprecated syntax for Tool X without this guidance"
|
||||
- "Claude doesn't know about this project-specific integration pattern"
|
||||
- Example: Claude making up `skills: git-workflow` frontmatter that doesn't exist
|
||||
|
||||
✅ **New or rapidly-changing technology (post-training)**
|
||||
- Claude Code itself (released after training cutoff)
|
||||
- New framework versions with breaking changes
|
||||
- Emerging tools not well-represented in training data
|
||||
- Example: Claude Code plugin system specifics
|
||||
|
||||
✅ **Integration patterns between tools (project-specific)**
|
||||
- "How this project connects Tool A with Tool B"
|
||||
- "Custom workflow orchestration"
|
||||
- "Project-specific toolchain configuration"
|
||||
- Example: Using both gh CLI and GitHub MCP server in same plugin
|
||||
|
||||
**EXCLUDE from skills (Claude already knows):**
|
||||
|
||||
❌ **Basic commands for well-known tools**
|
||||
- Don't document: git status, git commit, git push, git diff
|
||||
- Don't document: npm install, pip install, docker run
|
||||
- Don't document: Standard CLI flags and options Claude knows
|
||||
- Claude learned this in training and doesn't need reminders
|
||||
|
||||
❌ **Standard workflows Claude knows**
|
||||
- Don't document: Basic git branching workflow
|
||||
- Don't document: Standard PR review process
|
||||
- Don't document: Common testing patterns
|
||||
- These are well-established practices in Claude's training
|
||||
|
||||
❌ **General best practices (not project-specific)**
|
||||
- Don't document: "Write clear commit messages"
|
||||
- Don't document: "Test your code before committing"
|
||||
- Don't document: "Use semantic versioning"
|
||||
- Claude already knows these principles
|
||||
|
||||
❌ **Well-established patterns for common tools**
|
||||
- Don't document: REST API design basics
|
||||
- Don't document: Standard design patterns (MVC, etc.)
|
||||
- Don't document: Common security practices Claude knows
|
||||
- Training data covers these extensively
|
||||
|
||||
**Decision Test: Should This Be In A Skill?**
|
||||
|
||||
Before including content in a skill, ask:
|
||||
|
||||
1. **Would Claude get this wrong without the skill?**
|
||||
- Yes → Include it (fills a knowledge gap)
|
||||
- No → Exclude it (redundant with training)
|
||||
|
||||
2. **Is this specific to this user/project/context?**
|
||||
- Yes → Include it (contextual delta)
|
||||
- No → Probably exclude it (general knowledge)
|
||||
|
||||
3. **Is this well-documented in Claude's training data?**
|
||||
- No (new/custom/edge case) → Include it
|
||||
- Yes (standard practice) → Exclude it
|
||||
|
||||
4. **Would this information change Claude's behavior?**
|
||||
- Yes (corrects mistakes or fills gaps) → Include it
|
||||
- No (Claude already behaves this way) → Exclude it
|
||||
|
||||
**Example: git-workflow skill**
|
||||
|
||||
❌ **Bad (includes base knowledge):**
|
||||
```
|
||||
480 lines including:
|
||||
- How to use git status, git diff, git commit
|
||||
- Basic branching operations
|
||||
- Standard commit message formats
|
||||
- Common git commands
|
||||
```
|
||||
95% redundant, 5% valuable
|
||||
|
||||
✅ **Good (only includes delta):**
|
||||
```
|
||||
~80 lines including:
|
||||
- User's specific commit format preferences
|
||||
- Edge case: pre-commit hook retry logic
|
||||
- User requirement: no attribution text
|
||||
```
|
||||
100% valuable, focused on what Claude doesn't know
|
||||
|
||||
## The Box Factory Philosophy for Skills
|
||||
|
||||
### 1. Low-Maintenance by Design
|
||||
|
||||
**Defer to official documentation via WebFetch:**
|
||||
|
||||
```markdown
|
||||
## Required Reading Before Creating Agents
|
||||
|
||||
Fetch these docs with WebFetch every time:
|
||||
|
||||
- **https://code.claude.com/docs/en/sub-agents.md** - Core specification
|
||||
```
|
||||
|
||||
**Why:** Documentation changes; skills that defer stay valid.
|
||||
|
||||
**Don't hardcode:**
|
||||
|
||||
- ❌ "Available models: sonnet, opus, haiku"
|
||||
- ❌ "Tools include: Read, Write, Edit, Bash, Glob, Grep"
|
||||
- ❌ Specific syntax that may change
|
||||
|
||||
**Do reference:**
|
||||
|
||||
- ✅ "See model-config documentation for current options"
|
||||
- ✅ "Refer to tools documentation for current capabilities"
|
||||
- ✅ "Fetch official specification for syntax details"
|
||||
|
||||
### 2. Two-Layer Approach
|
||||
|
||||
**Layer 1: Official Specification**
|
||||
|
||||
- What the docs explicitly say
|
||||
- Required fields and syntax
|
||||
- Official examples
|
||||
- Mark with headings: `## X (Official Specification)`
|
||||
|
||||
**Layer 2: Best Practices**
|
||||
|
||||
- What the docs don't emphasize
|
||||
- Common gotchas and anti-patterns
|
||||
- Interpretive guidance
|
||||
- Mark with headings: `## X (Best Practices)`
|
||||
|
||||
**Example:**
|
||||
|
||||
```markdown
|
||||
## Frontmatter Fields (Official Specification)
|
||||
|
||||
The `description` field is optional and defaults to first line.
|
||||
|
||||
## Description Field Design (Best Practices)
|
||||
|
||||
Always include `description` even though it's optional - improves discoverability and Claude's ability to use the SlashCommand tool.
|
||||
```
|
||||
|
||||
### 3. Evidence-Based Recommendations
|
||||
|
||||
**All claims must be:**
|
||||
|
||||
✅ Grounded in official documentation, **OR**
|
||||
✅ Clearly marked as opinionated best practices, **OR**
|
||||
✅ Based on documented common pitfalls
|
||||
|
||||
**Avoid:**
|
||||
❌ Presenting opinions as official requirements
|
||||
❌ Making unsupported claims about "best practices"
|
||||
❌ Prescribing patterns not in documentation without labeling them
|
||||
|
||||
## Skill Structure (Best Practices)
|
||||
|
||||
### Frontmatter
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: skill-name
|
||||
description: What this skill teaches and when to use it
|
||||
---
|
||||
```
|
||||
|
||||
**Name:** kebab-case identifier
|
||||
**Description:** Clear triggering conditions for when the skill loads
|
||||
|
||||
### Content Organization
|
||||
|
||||
```markdown
|
||||
# Skill Name
|
||||
|
||||
[Opening paragraph explaining purpose and value]
|
||||
|
||||
## Required Reading Before [Task]
|
||||
|
||||
Fetch these docs with WebFetch every time:
|
||||
- [Official doc URLs with descriptions]
|
||||
|
||||
## Core Understanding
|
||||
|
||||
[Fundamental concepts, architecture, philosophy]
|
||||
|
||||
## [Topic] (Official Specification)
|
||||
|
||||
[What the official docs explicitly state]
|
||||
|
||||
## [Topic] (Best Practices)
|
||||
|
||||
[Interpretive guidance, gotchas, patterns]
|
||||
|
||||
## Decision Framework
|
||||
|
||||
[When to use X vs Y, with clear criteria]
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
[Anti-patterns with why they fail and better approaches]
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
[Validation items before finalizing]
|
||||
|
||||
## Documentation References
|
||||
|
||||
[Authoritative sources to fetch]
|
||||
```
|
||||
|
||||
### Content Quality Standards
|
||||
|
||||
**Be specific and actionable:**
|
||||
|
||||
- ✅ "Run pytest -v and parse output for failures"
|
||||
- ❌ "Run tests and check for problems"
|
||||
|
||||
**Distinguish official from opinionated:**
|
||||
|
||||
- ✅ "Official docs say 'description is optional.' Best practice: always include it."
|
||||
- ❌ "description is required" (when it's not)
|
||||
|
||||
**Use examples effectively:**
|
||||
|
||||
- Show before/after
|
||||
- Explain what makes the "after" better
|
||||
- Mark issues with ❌ and improvements with ✅
|
||||
|
||||
**Progressive disclosure:**
|
||||
|
||||
- Start with core concepts
|
||||
- Build to advanced features
|
||||
- Don't overwhelm with details upfront
|
||||
|
||||
## When to Create Skills
|
||||
|
||||
### Skill vs Agent vs Command
|
||||
|
||||
**Use a Skill when:**
|
||||
|
||||
- Multiple contexts need the same knowledge
|
||||
- Substantial procedural expertise (not just 2-3 bullet points)
|
||||
- Progressive disclosure would save tokens
|
||||
- Teaching "how to think about" something
|
||||
- You want automatic loading when topics arise
|
||||
|
||||
**Examples:**
|
||||
|
||||
- `agent-design` - Teaches how to design agents
|
||||
- `api-documentation-standards` - Formatting rules across projects
|
||||
- `security-practices` - Principles that apply broadly
|
||||
|
||||
**Use an Agent when:**
|
||||
|
||||
- Need isolated context for complex work
|
||||
- Want autonomous delegation
|
||||
- Doing actual work (writing files, running tests)
|
||||
- Task-oriented, not knowledge-oriented
|
||||
|
||||
**Examples:**
|
||||
|
||||
- `test-runner` - Executes tests and analyzes failures
|
||||
- `code-reviewer` - Performs analysis and provides feedback
|
||||
|
||||
**Use a Command when:**
|
||||
|
||||
- User wants explicit trigger
|
||||
- Simple, deterministic operation
|
||||
- One-off action
|
||||
|
||||
**Examples:**
|
||||
|
||||
- `/deploy` - User-triggered deployment
|
||||
- `/create-component` - File generation
|
||||
|
||||
### Scope Guidelines (Best Practices)
|
||||
|
||||
**Good skill scope:**
|
||||
|
||||
- Focused on single domain (API design, testing, security)
|
||||
- Self-contained knowledge
|
||||
- Clear boundaries
|
||||
- Composable with other skills
|
||||
|
||||
**Bad skill scope:**
|
||||
|
||||
- "Everything about development" (too broad)
|
||||
- Overlaps heavily with another skill
|
||||
- Just 3-4 bullet points (put in CLAUDE.md instead)
|
||||
- Project-specific details (put in CLAUDE.md instead)
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
### Pitfall #1: Duplicating Official Documentation
|
||||
|
||||
**Problem:** Skill becomes outdated copy of docs
|
||||
|
||||
```markdown
|
||||
## Available Models
|
||||
|
||||
The following models are available:
|
||||
- claude-sonnet-4-5-20250929
|
||||
- claude-opus-4-20250514
|
||||
- claude-3-5-haiku-20241022
|
||||
```
|
||||
|
||||
**Why it fails:** Model names change, skill becomes outdated
|
||||
|
||||
**Better:**
|
||||
|
||||
```markdown
|
||||
## Model Selection
|
||||
|
||||
Fetch current model options from:
|
||||
https://code.claude.com/docs/en/model-config.md
|
||||
|
||||
**Best practice:** Use haiku for simple tasks, sonnet for balanced work, opus for complex reasoning.
|
||||
```
|
||||
|
||||
### Pitfall #2: Hardcoding Version-Specific Details
|
||||
|
||||
**Problem:** Skill includes specifics that change
|
||||
|
||||
```markdown
|
||||
## Tool Permissions
|
||||
|
||||
Grant these tools to your agent:
|
||||
- Read (for reading files)
|
||||
- Write (for writing files)
|
||||
- Edit (for editing files)
|
||||
```
|
||||
|
||||
**Why it fails:** Tool list may expand, descriptions may change
|
||||
|
||||
**Better:**
|
||||
|
||||
```markdown
|
||||
## Tool Selection Philosophy
|
||||
|
||||
**Match tools to autonomous responsibilities:**
|
||||
|
||||
- If agent analyzes only → Read, Grep, Glob
|
||||
- If agent writes code → Add Write, Edit
|
||||
- If agent runs commands → Add Bash
|
||||
|
||||
Fetch current tool list from:
|
||||
https://code.claude.com/docs/en/settings#tools-available-to-claude
|
||||
```
|
||||
|
||||
### Pitfall #3: Presenting Opinions as Official Requirements
|
||||
|
||||
**Problem:** Blurs the line between specs and best practices
|
||||
|
||||
```markdown
|
||||
## Agent Description Field
|
||||
|
||||
The description field MUST use strong directive language like "ALWAYS use when" to ensure proper delegation.
|
||||
```
|
||||
|
||||
**Why it fails:** Official docs don't require this; it's a best practice opinion
|
||||
|
||||
**Better:**
|
||||
|
||||
```markdown
|
||||
## Description Field Design (Best Practices)
|
||||
|
||||
Official requirement: "Natural language explanation of when to invoke"
|
||||
|
||||
**Best practice:** Use specific triggering conditions and directive language to improve autonomous delegation. While not required, this pattern increases the likelihood of proper agent invocation.
|
||||
```
|
||||
|
||||
### Pitfall #4: Kitchen Sink Skills
|
||||
|
||||
**Problem:** One skill tries to cover everything
|
||||
|
||||
```markdown
|
||||
# Full-Stack Development Skill
|
||||
|
||||
This skill covers:
|
||||
- Frontend frameworks (React, Vue, Angular)
|
||||
- Backend APIs (Node, Python, Go, Rust)
|
||||
- Databases (SQL, NoSQL)
|
||||
- DevOps (Docker, K8s, CI/CD)
|
||||
- Security best practices
|
||||
- Testing strategies
|
||||
...
|
||||
```
|
||||
|
||||
**Why it fails:** Too broad, overwhelming, hard to maintain, loads unnecessarily
|
||||
|
||||
**Better:** Split into focused skills:
|
||||
|
||||
- `frontend-architecture`
|
||||
- `api-design`
|
||||
- `testing-strategy`
|
||||
|
||||
### Pitfall #5: No Clear Triggering Conditions
|
||||
|
||||
**Problem:** Description doesn't indicate when skill should load
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: api-standards
|
||||
description: API documentation standards
|
||||
---
|
||||
```
|
||||
|
||||
**Why it fails:** Unclear when this skill is relevant
|
||||
|
||||
**Better:**
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: api-standards
|
||||
description: Guidelines for designing and documenting REST APIs following team standards. Use when creating endpoints, reviewing API code, or writing API documentation.
|
||||
---
|
||||
```
|
||||
|
||||
### Pitfall #6: Documenting Claude's Base Knowledge
|
||||
|
||||
**Problem:** Skill includes comprehensive documentation of tools and workflows Claude already knows from training, creating token waste and maintenance burden without adding value.
|
||||
|
||||
**Bad example (hypothetical 480-line git-workflow skill):**
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: git-workflow
|
||||
description: Comprehensive git usage guide
|
||||
---
|
||||
|
||||
# Git Workflow Skill
|
||||
|
||||
## Common Git Operations
|
||||
|
||||
**Checking Repository Status:**
|
||||
|
||||
```bash
|
||||
git status # Shows staged, unstaged, and untracked files
|
||||
```
|
||||
|
||||
**See detailed diff:**
|
||||
|
||||
```bash
|
||||
git diff # Unstaged changes
|
||||
git diff --staged # Staged changes
|
||||
git diff HEAD # All changes
|
||||
```
|
||||
|
||||
**Commit Workflow:**
|
||||
|
||||
```bash
|
||||
# 1. Review changes
|
||||
git status
|
||||
git diff
|
||||
|
||||
# 2. Stage changes
|
||||
git add .
|
||||
|
||||
# 3. Commit with message
|
||||
git commit -m "fix: correct validation logic"
|
||||
```
|
||||
|
||||
**Branch Operations:**
|
||||
|
||||
```bash
|
||||
git checkout -b feature-name # Create and switch
|
||||
git switch main # Switch to main
|
||||
git branch # List branches
|
||||
```
|
||||
|
||||
[... 400 more lines documenting standard git commands, branching workflows, merge strategies, rebase operations, standard commit message formats, general best practices ...]
|
||||
```
|
||||
|
||||
**Why it fails:**
|
||||
|
||||
- Claude already knows all standard git commands from training
|
||||
- 95% of content is redundant with base knowledge
|
||||
- Wastes tokens loading information Claude doesn't need
|
||||
- Creates maintenance burden (skill needs updates when nothing actually changed)
|
||||
- Obscures the 5% that's actually valuable (user-specific preferences)
|
||||
- No behavioral change - Claude would do the same without this skill
|
||||
|
||||
**Better (focused 80-line version documenting only the delta):**
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: git-workflow
|
||||
description: User-specific git workflow preferences and edge case handling. Use when creating commits or handling pre-commit hook failures.
|
||||
---
|
||||
|
||||
# Git Workflow Skill
|
||||
|
||||
This skill documents workflow preferences and edge cases specific to this user. For standard git knowledge, Claude relies on base training.
|
||||
|
||||
## Commit Message Requirements (User Preference)
|
||||
|
||||
**This user requires:**
|
||||
|
||||
- Terse, single-line format (max ~200 characters)
|
||||
- No emojis or decorative elements
|
||||
- **No attribution text** (no "Co-Authored-By:", no "Generated with Claude Code")
|
||||
|
||||
**Format pattern:** `<type>: <brief specific description>`
|
||||
|
||||
**Examples:**
|
||||
```
|
||||
fix: prevent race condition in session cleanup
|
||||
add: rate limiting middleware
|
||||
```
|
||||
|
||||
**Avoid:**
|
||||
```
|
||||
❌ ✨ add: new feature (emoji)
|
||||
❌ fix: thing
|
||||
|
||||
🤖 Generated with Claude Code
|
||||
(attribution this user doesn't want)
|
||||
```
|
||||
|
||||
## Pre-Commit Hook Edge Case (Critical)
|
||||
|
||||
**Problem:** Pre-commit hooks modify files during commit, causing failure.
|
||||
|
||||
**Workflow:**
|
||||
|
||||
1. Attempt: `git commit -m "message"`
|
||||
2. Hook modifies files (auto-format)
|
||||
3. Commit FAILS (working directory changed)
|
||||
4. Stage modifications: `git add .`
|
||||
5. Retry ONCE: `git commit --amend --no-edit`
|
||||
|
||||
**Critical:** Only retry ONCE to avoid infinite loops.
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
- ✓ Message is terse, single-line, no emojis, no attribution
|
||||
- ✓ No secrets in staged files
|
||||
- ✓ Prepared for potential hook retry
|
||||
```
|
||||
|
||||
**Key improvements:**
|
||||
|
||||
- ✅ Went from 480 lines → 80 lines (83% reduction)
|
||||
- ✅ Removed all standard git knowledge Claude already has
|
||||
- ✅ Kept only user-specific preferences (commit format, no attribution)
|
||||
- ✅ Kept only edge cases Claude would miss (pre-commit hook retry logic)
|
||||
- ✅ 100% of content is valuable delta knowledge
|
||||
- ✅ Skill actually changes Claude's behavior (would get these things wrong without it)
|
||||
|
||||
**The delta principle:** Skills should only contain knowledge that bridges the gap between what Claude knows and what Claude needs to know for this specific context.
|
||||
|
||||
## Skill Quality Checklist
|
||||
|
||||
Before finalizing a skill:
|
||||
|
||||
**Structure (based on successful patterns):**
|
||||
|
||||
- ✓ Proper frontmatter with name and description
|
||||
- ✓ Clear description indicating when skill loads
|
||||
- ✓ Filename is `SKILL.md` (uppercase, not `skill.md`)
|
||||
- ✓ Located in `skills/[skill-name]/SKILL.md` subdirectory
|
||||
- ✓ Single H1 heading matching skill name
|
||||
- ✓ Organized with clear H2/H3 hierarchy
|
||||
|
||||
**Content quality:**
|
||||
|
||||
- ✓ Includes "Required Reading" section with official doc URLs
|
||||
- ✓ Distinguishes official specs from best practices
|
||||
- ✓ Avoids hardcoding version-specific details
|
||||
- ✓ Uses examples effectively (before/after, ❌/✅)
|
||||
- ✓ Provides decision frameworks
|
||||
- ✓ Includes common pitfalls section
|
||||
- ✓ Has validation checklist
|
||||
- ✓ Cites authoritative sources
|
||||
|
||||
**Philosophy alignment:**
|
||||
|
||||
- ✓ Defers to official docs via WebFetch instructions
|
||||
- ✓ Two-layer approach (specs + guidance)
|
||||
- ✓ Evidence-based recommendations
|
||||
- ✓ Focused scope, not kitchen sink
|
||||
- ✓ Interpretive, not duplicative
|
||||
- ✓ Progressive disclosure structure
|
||||
|
||||
## Example: High-Quality Skill Design
|
||||
|
||||
**Before (hypothetical low-quality skill):**
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: testing
|
||||
description: Testing stuff
|
||||
---
|
||||
|
||||
# Testing
|
||||
|
||||
Use pytest for Python testing.
|
||||
Use jest for JavaScript testing.
|
||||
|
||||
Make sure to write good tests.
|
||||
```
|
||||
|
||||
**Issues:**
|
||||
|
||||
- ❌ Vague description ("testing stuff")
|
||||
- ❌ No structure or organization
|
||||
- ❌ No official documentation references
|
||||
- ❌ Hardcodes specific tools without context
|
||||
- ❌ "Write good tests" is not actionable
|
||||
- ❌ No decision framework or examples
|
||||
- ❌ Too brief to warrant a skill (put in CLAUDE.md)
|
||||
|
||||
**After (applying skill-design principles):**
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: testing-strategy
|
||||
description: Interpretive guidance for test-driven development, test design, and testing workflows. Use when writing tests, reviewing test coverage, or designing testing strategies.
|
||||
---
|
||||
|
||||
# Testing Strategy Skill
|
||||
|
||||
This skill provides guidance for effective testing across languages and frameworks.
|
||||
|
||||
## Required Reading
|
||||
|
||||
Fetch language/framework-specific testing docs:
|
||||
|
||||
- **Python/pytest**: https://docs.pytest.org/
|
||||
- **JavaScript/Jest**: https://jestjs.io/docs/getting-started
|
||||
- **Go**: https://go.dev/doc/tutorial/add-a-test
|
||||
|
||||
## Core Testing Philosophy (Best Practices)
|
||||
|
||||
**The Testing Pyramid:**
|
||||
|
||||
- Many unit tests (fast, isolated, specific)
|
||||
- Fewer integration tests (moderate speed, component interaction)
|
||||
- Few end-to-end tests (slow, full system, critical paths)
|
||||
|
||||
**Why:** Balance coverage, speed, and maintenance burden.
|
||||
|
||||
## Test Design Principles (Best Practices)
|
||||
|
||||
**Arrange-Act-Assert pattern:**
|
||||
|
||||
```python
|
||||
def test_user_registration():
|
||||
# Arrange: Set up test data
|
||||
user_data = {"email": "test@example.com", "password": "secure123"}
|
||||
|
||||
# Act: Perform the action
|
||||
result = register_user(user_data)
|
||||
|
||||
# Assert: Verify outcomes
|
||||
assert result.success is True
|
||||
assert result.user.email == "test@example.com"
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- Clear test structure
|
||||
- Easy to understand intent
|
||||
- Maintainable
|
||||
|
||||
## When to Mock (Best Practices)
|
||||
|
||||
**Mock when:**
|
||||
|
||||
- External services (APIs, databases)
|
||||
- Time-dependent operations
|
||||
- File system operations
|
||||
- Random/non-deterministic behavior
|
||||
|
||||
**Don't mock when:**
|
||||
|
||||
- Testing integration between your components
|
||||
- Pure functions with no dependencies
|
||||
- Simple data transformations
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
### Pitfall #1: Testing Implementation Details
|
||||
|
||||
**Problem:** Tests break when refactoring even though behavior unchanged
|
||||
|
||||
```python
|
||||
# Bad: Tests internal structure
|
||||
def test_user_service():
|
||||
service = UserService()
|
||||
assert service._internal_cache is not None # Implementation detail
|
||||
```
|
||||
|
||||
**Better:** Test behavior, not structure
|
||||
|
||||
```python
|
||||
# Good: Tests observable behavior
|
||||
def test_user_service_caches_results():
|
||||
service = UserService()
|
||||
user1 = service.get_user(123)
|
||||
user2 = service.get_user(123)
|
||||
assert user1 is user2 # Behavior: caching works
|
||||
```
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
- ✓ Test names clearly describe what's being tested
|
||||
- ✓ One assertion concept per test
|
||||
- ✓ Tests are independent (can run in any order)
|
||||
- ✓ Mocks used appropriately (external dependencies only)
|
||||
- ✓ Test data is representative
|
||||
- ✓ Edge cases covered
|
||||
- ✓ Fast execution (< 1s for unit tests)
|
||||
|
||||
## Documentation References
|
||||
|
||||
- Fetch framework-specific docs for syntax
|
||||
- Testing philosophies: <https://martinfowler.com/articles/practical-test-pyramid.html>
|
||||
|
||||
```
|
||||
|
||||
**Improvements:**
|
||||
|
||||
- ✅ Specific, actionable description
|
||||
- ✅ Clear structure with progressive disclosure
|
||||
- ✅ Defers to official docs for syntax
|
||||
- ✅ Provides interpretive guidance (when to mock, testing pyramid)
|
||||
- ✅ Concrete examples with explanations
|
||||
- ✅ Common pitfalls with before/after
|
||||
- ✅ Validation checklist
|
||||
- ✅ Substantial enough to warrant a skill
|
||||
|
||||
## Creating Skills for Different Purposes
|
||||
|
||||
### Interpretive Guidance Skills (Like Box Factory's Design Skills)
|
||||
|
||||
**Purpose:** Help Claude understand how to apply official documentation
|
||||
|
||||
**Structure:**
|
||||
- Fetch official docs first
|
||||
- Explain what docs mean in practice
|
||||
- Provide decision frameworks
|
||||
- Include common gotchas
|
||||
- Show anti-patterns
|
||||
|
||||
**Example:** `agent-design`, `slash-command-design`, `plugin-design`
|
||||
|
||||
### Domain Knowledge Skills
|
||||
|
||||
**Purpose:** Provide reusable expertise across projects
|
||||
|
||||
**Structure:**
|
||||
- Define principles and philosophy
|
||||
- Provide decision frameworks
|
||||
- Include practical examples
|
||||
- Show common patterns
|
||||
- Reference external authoritative sources
|
||||
|
||||
**Example:** `api-standards`, `security-practices`, `testing-strategy`
|
||||
|
||||
### Procedural Skills
|
||||
|
||||
**Purpose:** Guide multi-step workflows
|
||||
|
||||
**Structure:**
|
||||
- Clear step-by-step process
|
||||
- Decision points and branching
|
||||
- Success criteria
|
||||
- Common failure modes
|
||||
- Recovery strategies
|
||||
|
||||
**Example:** `deployment-workflow`, `incident-response`, `code-review-checklist`
|
||||
|
||||
## File Structure
|
||||
|
||||
Skills live in subdirectories within `skills/`:
|
||||
|
||||
```
|
||||
|
||||
plugin-name/
|
||||
├── skills/
|
||||
│ ├── skill-one/
|
||||
│ │ ├── SKILL.md # Required: Skill content
|
||||
│ │ └── helper.py # Optional: Supporting files
|
||||
│ └── skill-two/
|
||||
│ └── SKILL.md
|
||||
|
||||
```
|
||||
|
||||
**Critical:** Filename must be `SKILL.md` (uppercase), not `skill.md`, `Skill.md`, or `skill.MD`
|
||||
|
||||
## Testing Skills
|
||||
|
||||
**How to verify a skill works:**
|
||||
|
||||
1. Use the Skill tool to invoke it
|
||||
2. Check if it loads in appropriate contexts
|
||||
3. Verify the guidance is helpful and accurate
|
||||
4. Test that official doc references are current
|
||||
5. Ensure examples run as shown
|
||||
|
||||
**Signs of a good skill:**
|
||||
|
||||
- Claude provides better answers in the skill's domain
|
||||
- Reduces need to repeat context
|
||||
- Catches common mistakes proactively
|
||||
- Loads automatically when relevant
|
||||
|
||||
## Documentation References
|
||||
|
||||
Skills are part of the agent system but lightweight:
|
||||
|
||||
**Official documentation:**
|
||||
|
||||
- https://code.claude.com/docs/en/sub-agents.md - Mentions skills briefly
|
||||
|
||||
**Examples of excellent skills:**
|
||||
|
||||
- Examine Box Factory's design skills (agent-design, slash-command-design, plugin-design, hooks-design) for patterns
|
||||
- Look for skills in well-maintained plugin marketplaces
|
||||
|
||||
**Philosophy resources:**
|
||||
|
||||
- Progressive disclosure principles
|
||||
- Token-efficient context management
|
||||
- Knowledge organization patterns
|
||||
|
||||
**Remember:** This meta-skill itself follows the principles it teaches - it defers to official docs, distinguishes specs from best practices, and provides interpretive guidance rather than duplication. This is the Box Factory way.
|
||||
504
skills/slash-command-design/SKILL.md
Normal file
504
skills/slash-command-design/SKILL.md
Normal file
@@ -0,0 +1,504 @@
|
||||
---
|
||||
name: box-factory-slash-command-design
|
||||
description: Interpretive guidance for designing Claude Code slash commands. Helps you apply official documentation effectively and create high-quality commands. Use when creating or reviewing slash commands.
|
||||
---
|
||||
|
||||
# Slash Command Design Skill
|
||||
|
||||
This skill provides interpretive guidance and best practices for creating Claude Code slash commands. **ALWAYS fetch current official documentation before creating commands** - this skill helps you understand what the docs mean and how to create excellent commands.
|
||||
|
||||
## Required Reading Before Creating Commands
|
||||
|
||||
Fetch these docs with WebFetch every time:
|
||||
|
||||
- **https://code.claude.com/docs/en/slash-commands.md** - Core specification and examples
|
||||
- **https://code.claude.com/docs/en/settings#tools-available-to-claude** - Verify tool names
|
||||
- **https://code.claude.com/docs/en/model-config.md** - Model selection guidance
|
||||
|
||||
## Core Understanding
|
||||
|
||||
### Commands Are User-Triggered, Not Autonomous
|
||||
|
||||
**Key distinction:**
|
||||
|
||||
- **Commands** = User explicitly invokes with `/command-name`
|
||||
- **Agents** = Claude autonomously delegates based on context
|
||||
- **Skills** = Knowledge that loads when relevant
|
||||
|
||||
**Quality test:** If you want this to happen automatically based on context, it's an agent, not a command.
|
||||
|
||||
### Command Structure
|
||||
|
||||
Commands are Markdown files with optional YAML frontmatter:
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Brief description (optional, defaults to first line)
|
||||
argument-hint: [expected-args]
|
||||
allowed-tools: Tool1, Tool2
|
||||
model: sonnet
|
||||
disable-model-invocation: false
|
||||
---
|
||||
|
||||
Command prompt content goes here.
|
||||
Use $1, $2 for individual arguments or $ARGUMENTS for all.
|
||||
```
|
||||
|
||||
## Frontmatter Fields (Official Specification)
|
||||
|
||||
All fields are optional:
|
||||
|
||||
| Field | Purpose | Default |
|
||||
|-------|---------|---------|
|
||||
| `description` | Brief command description for `/help` | First line of prompt |
|
||||
| `argument-hint` | Expected arguments (e.g., `[pr-number] [priority]`) | None |
|
||||
| `allowed-tools` | Restrict to specific tools (e.g., `Bash(git:*)`) | Inherits from conversation |
|
||||
| `model` | Specific model to use | Inherits from conversation |
|
||||
| `disable-model-invocation` | Prevents SlashCommand tool from auto-invoking | false |
|
||||
|
||||
**Best practice:** Always include `description` even though it's optional - improves discoverability and Claude's ability to use the SlashCommand tool.
|
||||
|
||||
## Argument Syntax (Official Specification)
|
||||
|
||||
**All arguments as single string:**
|
||||
|
||||
```markdown
|
||||
$ARGUMENTS
|
||||
```
|
||||
|
||||
Example: `/fix-issue 123 high-priority` → `$ARGUMENTS = "123 high-priority"`
|
||||
|
||||
**Individual positional arguments:**
|
||||
|
||||
```markdown
|
||||
$1, $2, $3, etc.
|
||||
```
|
||||
|
||||
Example: `/review-pr 456 high alice` → `$1="456"`, `$2="high"`, `$3="alice"`
|
||||
|
||||
**Official guidance:** "Use individual arguments (`$1`, `$2`) for complex commands with multiple parameters"
|
||||
|
||||
**Best practice:** Use `$1, $2` when you need arguments in different parts of the prompt or want to provide defaults. Keep argument parsing simple - if you need validation or complex logic, delegate to an agent.
|
||||
|
||||
## Advanced Features (Official Specification)
|
||||
|
||||
### Bash Execution with `!` Prefix
|
||||
|
||||
Execute bash commands before the prompt runs:
|
||||
|
||||
```markdown
|
||||
---
|
||||
allowed-tools: Bash(git:*)
|
||||
---
|
||||
|
||||
!git status
|
||||
|
||||
Review the git status above and suggest next steps.
|
||||
```
|
||||
|
||||
### File References with `@` Prefix
|
||||
|
||||
Include file contents in the prompt:
|
||||
|
||||
```markdown
|
||||
Review @src/utils/helpers.js for potential improvements.
|
||||
```
|
||||
|
||||
Multiple files: `Compare @src/old.js with @src/new.js`
|
||||
|
||||
### Subdirectory Namespacing
|
||||
|
||||
Organize commands in subdirectories:
|
||||
|
||||
```
|
||||
.claude/commands/frontend/component.md → /component (project:frontend)
|
||||
.claude/commands/backend/endpoint.md → /endpoint (project:backend)
|
||||
```
|
||||
|
||||
Command name comes from filename, subdirectory appears in `/help` as namespace label.
|
||||
|
||||
## Decision Framework
|
||||
|
||||
### Command vs Agent vs Skill
|
||||
|
||||
**Use Command when:**
|
||||
|
||||
- User wants explicit control over when it runs
|
||||
- Simple, deterministic operation
|
||||
- Wrapping a bash script or tool sequence
|
||||
- "I want to type `/something` to make X happen"
|
||||
|
||||
**Use Agent when:**
|
||||
|
||||
- Want autonomous delegation based on context
|
||||
- Need isolated context window
|
||||
- Require specific tool restrictions
|
||||
- Complex decision-making involved
|
||||
|
||||
**Use Skill when:**
|
||||
|
||||
- Multiple contexts need the same knowledge
|
||||
- Substantial procedural expertise
|
||||
- Progressive disclosure would save tokens
|
||||
|
||||
## Best Practices (Opinionated Guidance)
|
||||
|
||||
### Delegation Pattern
|
||||
|
||||
Most robust commands delegate to specialized agents rather than implementing complex logic:
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Run full test suite and analyze failures
|
||||
---
|
||||
|
||||
Use the test-runner agent to execute all tests and provide detailed failure analysis.
|
||||
```
|
||||
|
||||
**Why this works:**
|
||||
|
||||
- Keeps command simple and focused
|
||||
- Leverages specialized agent capabilities
|
||||
- Avoids reimplementing logic
|
||||
- Agent gets isolated context for complex work
|
||||
|
||||
**When to use:** Any command that needs file reading/parsing, complex decision trees, error recovery logic, or multi-step state management.
|
||||
|
||||
### Tool Restriction Pattern
|
||||
|
||||
For simple, deterministic operations, restrict tools for security and clarity:
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Show git status
|
||||
allowed-tools: Bash(git status:*)
|
||||
model: haiku
|
||||
---
|
||||
|
||||
Run `git status` and display the output.
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
|
||||
- Fast execution (haiku model)
|
||||
- Restricted permissions
|
||||
- Clear, single-purpose command
|
||||
|
||||
### Simple Sequential Pattern
|
||||
|
||||
**Commands CAN handle sequential bash operations** when they're straightforward and don't require file inspection or complex parsing:
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Install GitHub CLI if not present
|
||||
allowed-tools: Bash
|
||||
model: haiku
|
||||
---
|
||||
|
||||
Check if gh CLI is installed. If not, provide installation instructions for the user's platform.
|
||||
|
||||
Simple workflow:
|
||||
1. Check: `which gh` or `command -v gh`
|
||||
2. If not found, provide platform-specific install guidance
|
||||
3. Verify with `gh --version` if installed
|
||||
4. Output success message or next steps
|
||||
```
|
||||
|
||||
**This pattern is OK in commands when you have:**
|
||||
|
||||
✅ **3-5 sequential bash steps** - Simple linear workflow
|
||||
✅ **Basic conditionals** - Simple if/else (installed vs not installed)
|
||||
✅ **Simple verification** - Exit codes, command success/failure
|
||||
✅ **User-facing instructions** - Output guidance, next steps
|
||||
|
||||
**When to keep it in a command:**
|
||||
|
||||
- Checking if a tool is installed (`which`, `command -v`)
|
||||
- Installing via package manager (`brew install`, `apt-get install`)
|
||||
- Running simple verification (`--version`, `status` checks)
|
||||
- Providing user instructions based on results
|
||||
- Linear workflows without branching complexity
|
||||
|
||||
**Rule of thumb:** If you can write it as 3-5 bash commands with simple if/else logic and no file reading, keep it in the command.
|
||||
|
||||
**Delegate to an agent when you need:**
|
||||
|
||||
❌ **File reading/parsing** - Requires Read, Grep, or complex text processing
|
||||
❌ **Complex decision trees** - Framework detection, config file parsing, multi-path logic
|
||||
❌ **Error recovery logic** - Retries, fallbacks, multiple failure modes
|
||||
❌ **State management** - Tracking across multiple steps, rollback capability
|
||||
❌ **Multiple tool orchestration** - Coordinating Read + Grep + Write + Bash
|
||||
|
||||
**Example requiring agent delegation:**
|
||||
|
||||
```markdown
|
||||
# ❌ Too complex for command - needs agent
|
||||
---
|
||||
description: Set up test environment
|
||||
---
|
||||
|
||||
Detect test framework by:
|
||||
1. Read package.json, check for jest/mocha/vitest dependencies
|
||||
2. Read test config files (.jestrc, mocha.opts, vitest.config.ts)
|
||||
3. Scan for existing test files in src/, tests/, __tests__/
|
||||
4. Parse configuration to determine coverage settings
|
||||
5. Install missing dependencies based on framework
|
||||
6. Generate framework-specific config if missing
|
||||
7. Create example test files following detected patterns
|
||||
8. Verify setup with test run
|
||||
```
|
||||
|
||||
**Why this needs an agent:**
|
||||
|
||||
- Requires Read tool for multiple files
|
||||
- Complex decision tree (framework detection)
|
||||
- Config file parsing
|
||||
- State management across steps
|
||||
- Multiple failure modes to handle
|
||||
- Error recovery (config generation, dependency installation)
|
||||
|
||||
**Better approach:**
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Set up test environment for current project
|
||||
---
|
||||
|
||||
Use the test-setup agent to detect the test framework, install dependencies, and configure the testing environment.
|
||||
```
|
||||
|
||||
**The threshold:**
|
||||
|
||||
- **Commands:** `which gh && gh --version || echo "Install with: brew install gh"`
|
||||
- **Agents:** Anything requiring Read/Grep/Parse or complex multi-step decision-making
|
||||
|
||||
### Generation Pattern
|
||||
|
||||
For creating files/code, be specific about structure and requirements:
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Create a new React component with TypeScript
|
||||
argument-hint: component-name
|
||||
---
|
||||
|
||||
Create a new React component named `$1` in the components directory.
|
||||
|
||||
Include:
|
||||
- TypeScript interface for props
|
||||
- Basic component structure with proper typing
|
||||
- Export statement
|
||||
- Test file in __tests__ directory
|
||||
|
||||
Follow project conventions for imports and file structure.
|
||||
```
|
||||
|
||||
## Common Pitfalls (Best Practices)
|
||||
|
||||
### Pitfall #1: Knowledge Storage in Commands
|
||||
|
||||
**Problem:** Using commands to store documentation instead of actions
|
||||
|
||||
**Example of wrong pattern:**
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Show API documentation standards
|
||||
---
|
||||
|
||||
Our API documentation standards:
|
||||
[50 lines of guidelines...]
|
||||
```
|
||||
|
||||
**Why it's wrong:** This is knowledge, not an action. Commands should DO things.
|
||||
|
||||
**Better approach:** Create a skill for standards, command for action:
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Generate API documentation for current file
|
||||
---
|
||||
|
||||
Use the api-documentation skill to generate comprehensive API docs for the current file.
|
||||
```
|
||||
|
||||
### Pitfall #2: Reimplementing Agent Logic
|
||||
|
||||
**Problem:** Commands with complex logic that agents handle better
|
||||
|
||||
**Example of wrong pattern:**
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Run tests
|
||||
---
|
||||
|
||||
First, scan for test files in src/, tests/, and __tests__.
|
||||
Then determine the test framework by checking package.json.
|
||||
If Jest, run `npm test`. If pytest, run `pytest -v`.
|
||||
Parse the output for failures and categorize by severity...
|
||||
```
|
||||
|
||||
**Why it's wrong:** Too much logic, too many decisions, better in isolated context.
|
||||
|
||||
**Better approach:**
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Run full test suite
|
||||
---
|
||||
|
||||
Use the test-runner agent to execute the full test suite and analyze failures.
|
||||
```
|
||||
|
||||
### Pitfall #3: Overly Complex Arguments
|
||||
|
||||
**Problem:** Arguments that need extensive parsing or validation
|
||||
|
||||
**Example of questionable pattern:**
|
||||
|
||||
```markdown
|
||||
/deploy env=staging branch=main force=true rollback=false
|
||||
```
|
||||
|
||||
**Why it's questionable:** No argument validation, no type checking, brittle parsing.
|
||||
|
||||
**Better approach:** Keep arguments simple, let agent handle complexity:
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Deploy to specified environment
|
||||
argument-hint: environment
|
||||
---
|
||||
|
||||
Deploy to $1 environment. The deployer agent will handle validation, rollback strategy, and confirmation.
|
||||
```
|
||||
|
||||
### Pitfall #4: Scope Creep
|
||||
|
||||
**Problem:** Single command tries to do too much
|
||||
|
||||
**Example:**
|
||||
|
||||
```markdown
|
||||
description: Test, lint, format, commit, and deploy
|
||||
```
|
||||
|
||||
**Why it fails:** Multiple distinct operations with different failure modes.
|
||||
|
||||
**Better:** Separate commands or orchestrator agent that coordinates multiple specialized agents.
|
||||
|
||||
## Command Quality Checklist
|
||||
|
||||
Before finalizing a command:
|
||||
|
||||
**Structure (from official docs):**
|
||||
|
||||
- ✓ Valid YAML frontmatter (if used)
|
||||
- ✓ Proper markdown formatting
|
||||
- ✓ Filename is kebab-case (becomes command name)
|
||||
|
||||
**Best Practices (opinionated):**
|
||||
|
||||
- ✓ Includes `description` field for discoverability
|
||||
- ✓ Uses `argument-hint` if arguments expected
|
||||
- ✓ Action-oriented (not knowledge storage)
|
||||
- ✓ Delegates to agents for complex logic (file parsing, decision trees, error recovery)
|
||||
- ✓ Simple sequential bash is OK (3-5 steps, basic if/else)
|
||||
- ✓ Arguments are simple (if present)
|
||||
- ✓ Clear, single-purpose design
|
||||
- ✓ Appropriate tool restrictions (if needed)
|
||||
- ✓ Model choice matches complexity (haiku for simple, sonnet for complex)
|
||||
|
||||
## Path Resolution
|
||||
|
||||
**Official locations:**
|
||||
|
||||
- **Project-level:** `.claude/commands/` (shared with team)
|
||||
- **User-level:** `~/.claude/commands/` (personal, all projects)
|
||||
- **Plugin context:** `plugins/[name]/commands/` (when creating plugin commands)
|
||||
|
||||
**Resolution logic:**
|
||||
|
||||
1. If caller specifies exact path → use that
|
||||
2. If in plugin context → use `plugins/[name]/commands/`
|
||||
3. Default → `.claude/commands/` (project-level)
|
||||
4. User-level → only when explicitly requested
|
||||
|
||||
## Name Normalization
|
||||
|
||||
Command names must be kebab-case (filename without .md extension):
|
||||
|
||||
**Transform these:**
|
||||
|
||||
- "Run Tests" → `run-tests.md`
|
||||
- "create_component" → `create-component.md`
|
||||
- "DeployStaging" → `deploy-staging.md`
|
||||
|
||||
## Example: Good Command Design
|
||||
|
||||
**Before (from hypothetical docs):**
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Create component
|
||||
---
|
||||
|
||||
Create a new component.
|
||||
```
|
||||
|
||||
**Issues:**
|
||||
|
||||
- ❌ Description too vague
|
||||
- ❌ Prompt lacks specifics
|
||||
- ❌ No argument handling when clearly needed
|
||||
- ❌ No guidance on structure
|
||||
|
||||
**After (applying best practices):**
|
||||
|
||||
```markdown
|
||||
---
|
||||
description: Create a new React component with TypeScript and tests
|
||||
argument-hint: component-name
|
||||
---
|
||||
|
||||
Create a new React component named `$1`.
|
||||
|
||||
Requirements:
|
||||
- Location: src/components/$1/$1.tsx
|
||||
- TypeScript interface for props
|
||||
- Proper exports (default and named)
|
||||
- Test file: src/components/$1/__tests__/$1.test.tsx
|
||||
- Storybook file: src/components/$1/$1.stories.tsx
|
||||
|
||||
Follow project conventions:
|
||||
- Use existing component patterns as reference
|
||||
- Include JSDoc comments
|
||||
- Export types separately
|
||||
```
|
||||
|
||||
**Improvements:**
|
||||
|
||||
- ✅ Specific description (React + TypeScript + tests)
|
||||
- ✅ Clear argument placeholder and hint
|
||||
- ✅ Detailed deliverables listed
|
||||
- ✅ References project conventions
|
||||
- ✅ Actionable and unambiguous
|
||||
|
||||
## Documentation References
|
||||
|
||||
These are the authoritative sources. Fetch them before creating commands:
|
||||
|
||||
**Core specifications:**
|
||||
|
||||
- https://code.claude.com/docs/en/slash-commands.md - Command structure, examples, patterns
|
||||
|
||||
**Tool verification:**
|
||||
|
||||
- https://code.claude.com/docs/en/settings#tools-available-to-claude - Current tool list
|
||||
|
||||
**Model selection:**
|
||||
|
||||
- https://code.claude.com/docs/en/model-config.md - Model guidance
|
||||
|
||||
**Remember:** Official docs provide structure and features. This skill provides best practices and patterns for creating excellent commands.
|
||||
261
skills/uv-scripts/SKILL.md
Normal file
261
skills/uv-scripts/SKILL.md
Normal file
@@ -0,0 +1,261 @@
|
||||
---
|
||||
name: box-factory-uv-scripts
|
||||
description: UV-specific patterns for single-file Python scripts using inline metadata (PEP 723). Use when creating Python hooks, standalone utilities, or executable scripts in UV-managed projects.
|
||||
---
|
||||
|
||||
# UV Scripts Skill
|
||||
|
||||
This skill documents UV-specific patterns for single-file Python scripts with inline dependency metadata. For general Python knowledge, Claude relies on base training.
|
||||
|
||||
## Required Reading Before Creating UV Scripts
|
||||
|
||||
Fetch this documentation with WebFetch:
|
||||
|
||||
- **https://docs.astral.sh/uv/guides/scripts/** - Official UV scripts guide with current syntax
|
||||
|
||||
## Core Understanding
|
||||
|
||||
**What UV scripts solve:** Traditional Python scripts require separate environment setup or requirements.txt files. UV's inline metadata format (PEP 723) embeds dependencies directly in the script, enabling automatic environment creation on-demand.
|
||||
|
||||
**Key insight:** UV scripts are ideal for Claude Code hooks and standalone utilities because they're self-contained and executable without external configuration.
|
||||
|
||||
## Inline Metadata Format (Official Specification)
|
||||
|
||||
Dependencies declared in TOML comment block at top of file:
|
||||
|
||||
```python
|
||||
# /// script
|
||||
# dependencies = [
|
||||
# "requests<3",
|
||||
# "rich",
|
||||
# ]
|
||||
# ///
|
||||
|
||||
import requests
|
||||
import rich
|
||||
|
||||
# Your script logic here
|
||||
```
|
||||
|
||||
**Critical requirement:** The `dependencies` field MUST be provided even if empty:
|
||||
|
||||
```python
|
||||
# /// script
|
||||
# dependencies = []
|
||||
# ///
|
||||
```
|
||||
|
||||
**Optional Python version requirement:**
|
||||
|
||||
```python
|
||||
# /// script
|
||||
# requires-python = ">=3.12"
|
||||
# dependencies = ["requests<3"]
|
||||
# ///
|
||||
```
|
||||
|
||||
## Execution Pattern (Official Specification)
|
||||
|
||||
**Run with `uv run`:**
|
||||
|
||||
```bash
|
||||
uv run script.py
|
||||
```
|
||||
|
||||
UV automatically:
|
||||
- Parses inline metadata
|
||||
- Creates isolated environment
|
||||
- Installs dependencies
|
||||
- Executes script
|
||||
|
||||
**Important behavior:** When inline metadata exists, project dependencies are ignored (no need for `--no-project`).
|
||||
|
||||
## Shebang Pattern for Executables (Best Practice)
|
||||
|
||||
For standalone executable scripts (common for hooks):
|
||||
|
||||
```python
|
||||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# dependencies = ["rich"]
|
||||
# ///
|
||||
|
||||
import rich
|
||||
|
||||
if __name__ == "__main__":
|
||||
rich.print("[green]Hello from UV script![/green]")
|
||||
```
|
||||
|
||||
**Make executable:**
|
||||
|
||||
```bash
|
||||
chmod +x script.py
|
||||
./script.py # Runs directly without `uv run` prefix
|
||||
```
|
||||
|
||||
**Why this works:** Shebang enables PATH-based execution and simplifies hook scripts.
|
||||
|
||||
## When to Use UV Scripts (Best Practices)
|
||||
|
||||
**Use UV scripts for:**
|
||||
|
||||
- Claude Code hooks (deterministic execution, self-contained)
|
||||
- Standalone utilities (formatting, linting, code generation)
|
||||
- Shareable scripts (no separate environment setup needed)
|
||||
- One-off automation tasks
|
||||
|
||||
**Example use case (hook script):**
|
||||
|
||||
```python
|
||||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# dependencies = ["ruff"]
|
||||
# ///
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
result = subprocess.run(["ruff", "check", "."], capture_output=True)
|
||||
sys.exit(result.returncode)
|
||||
```
|
||||
|
||||
**Don't use UV scripts for:**
|
||||
|
||||
- Large applications (use proper UV projects instead)
|
||||
- Scripts with many files (multi-file projects need project structure)
|
||||
- Development requiring lockfile management (scripts don't auto-lock)
|
||||
|
||||
## Critical Gotchas (Best Practices)
|
||||
|
||||
### Gotcha #1: Empty Dependencies Must Be Explicit
|
||||
|
||||
**Problem:** Omitting `dependencies` field causes UV to fail.
|
||||
|
||||
```python
|
||||
# /// script
|
||||
# requires-python = ">=3.11"
|
||||
# ///
|
||||
# ERROR: Missing required 'dependencies' field
|
||||
```
|
||||
|
||||
**Solution:** Always include `dependencies`, even if empty:
|
||||
|
||||
```python
|
||||
# /// script
|
||||
# requires-python = ">=3.11"
|
||||
# dependencies = []
|
||||
# ///
|
||||
```
|
||||
|
||||
### Gotcha #2: Script Locking Requires Explicit Command
|
||||
|
||||
**Problem:** Unlike UV projects, scripts don't auto-generate lockfiles.
|
||||
|
||||
**Solution:** Explicitly lock if reproducibility needed:
|
||||
|
||||
```bash
|
||||
uv lock --script script.py
|
||||
```
|
||||
|
||||
This creates `script.lock` alongside `script.py`.
|
||||
|
||||
### Gotcha #3: Shebang Requires -S Flag
|
||||
|
||||
**Problem:** Standard shebang won't work with multi-word commands.
|
||||
|
||||
```python
|
||||
#!/usr/bin/env uv run --script
|
||||
# ERROR: env can't handle multiple arguments
|
||||
```
|
||||
|
||||
**Solution:** Use `-S` flag:
|
||||
|
||||
```python
|
||||
#!/usr/bin/env -S uv run --script
|
||||
# SUCCESS: Splits arguments correctly
|
||||
```
|
||||
|
||||
## Quality Checklist
|
||||
|
||||
Before finalizing a UV script:
|
||||
|
||||
**Format (official requirements):**
|
||||
- Script starts with `# /// script` comment block
|
||||
- `dependencies` field present (even if empty)
|
||||
- Comment block closed with `# ///`
|
||||
- No syntax errors in TOML metadata
|
||||
|
||||
**Best practices:**
|
||||
- Shebang uses `-S` flag for executables
|
||||
- Dependencies pinned appropriately (exact versions for reproducibility, ranges for flexibility)
|
||||
- Script made executable with `chmod +x` if intended for direct execution
|
||||
- Hook scripts return proper exit codes (0 = success, non-zero = failure)
|
||||
|
||||
## Common Pattern: Claude Code Hook Script
|
||||
|
||||
**Template for hook scripts:**
|
||||
|
||||
```python
|
||||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# dependencies = [
|
||||
# "tool-name>=1.0.0",
|
||||
# ]
|
||||
# ///
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import os
|
||||
|
||||
def main():
|
||||
"""Hook logic here."""
|
||||
# Get file paths from environment
|
||||
file_paths = os.environ.get("CLAUDE_FILE_PATHS", "").split()
|
||||
|
||||
if not file_paths:
|
||||
sys.exit(0) # Nothing to process
|
||||
|
||||
# Run tool
|
||||
result = subprocess.run(
|
||||
["tool-name", *file_paths],
|
||||
capture_output=True,
|
||||
text=True
|
||||
)
|
||||
|
||||
if result.returncode != 0:
|
||||
print(result.stderr, file=sys.stderr)
|
||||
sys.exit(2) # Block operation
|
||||
|
||||
sys.exit(0) # Success
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
**Hook registration in hooks.json:**
|
||||
|
||||
```json
|
||||
{
|
||||
"PostToolUse": [
|
||||
{
|
||||
"matcher": "Write|Edit",
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "./hooks/format-code.py"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## Documentation References
|
||||
|
||||
**Official UV documentation:**
|
||||
- https://docs.astral.sh/uv/guides/scripts/ - Current syntax and features
|
||||
- https://peps.python.org/pep-0723/ - PEP 723 specification for inline metadata
|
||||
|
||||
**Related patterns:**
|
||||
- Fetch box-factory:hooks-design skill for hook lifecycle and execution patterns
|
||||
- UV project documentation for multi-file Python projects
|
||||
Reference in New Issue
Block a user