@yeongjaeyou/claude-code-config 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/agents/code-review-handler.md +203 -0
- package/.claude/agents/issue-resolver.md +123 -0
- package/.claude/agents/python-pro.md +7 -2
- package/.claude/agents/web-researcher.md +5 -1
- package/.claude/commands/ask-deepwiki.md +46 -11
- package/.claude/commands/gh/auto-review-loop.md +201 -0
- package/.claude/commands/gh/create-issue-label.md +4 -0
- package/.claude/commands/gh/decompose-issue.md +24 -2
- package/.claude/commands/gh/post-merge.md +52 -10
- package/.claude/commands/gh/resolve-and-review.md +69 -0
- package/.claude/commands/gh/resolve-issue.md +3 -0
- package/.claude/commands/tm/convert-prd.md +4 -0
- package/.claude/commands/tm/post-merge.md +7 -1
- package/.claude/commands/tm/resolve-issue.md +4 -0
- package/.claude/commands/tm/sync-to-github.md +4 -0
- package/.claude/settings.json +15 -0
- package/.claude/skills/claude-md-generator/SKILL.md +130 -0
- package/.claude/skills/claude-md-generator/references/examples.md +261 -0
- package/.claude/skills/claude-md-generator/references/templates.md +156 -0
- package/.claude/skills/hook-creator/SKILL.md +88 -0
- package/.claude/skills/hook-creator/references/examples.md +339 -0
- package/.claude/skills/hook-creator/references/hook-events.md +193 -0
- package/.claude/skills/skill-creator/SKILL.md +160 -13
- package/.claude/skills/skill-creator/references/output-patterns.md +82 -0
- package/.claude/skills/skill-creator/references/workflows.md +28 -0
- package/.claude/skills/skill-creator/scripts/package_skill.py +10 -10
- package/.claude/skills/skill-creator/scripts/quick_validate.py +45 -15
- package/.claude/skills/slash-command-creator/SKILL.md +108 -0
- package/.claude/skills/slash-command-creator/references/examples.md +161 -0
- package/.claude/skills/slash-command-creator/references/frontmatter.md +74 -0
- package/.claude/skills/slash-command-creator/scripts/init_command.py +221 -0
- package/.claude/skills/subagent-creator/SKILL.md +127 -0
- package/.claude/skills/subagent-creator/assets/subagent-template.md +31 -0
- package/.claude/skills/subagent-creator/references/available-tools.md +63 -0
- package/.claude/skills/subagent-creator/references/examples.md +213 -0
- package/.claude/skills/youtube-collector/README.md +107 -0
- package/.claude/skills/youtube-collector/SKILL.md +158 -0
- package/.claude/skills/youtube-collector/references/data-schema.md +110 -0
- package/.claude/skills/youtube-collector/scripts/collect_videos.py +304 -0
- package/.claude/skills/youtube-collector/scripts/fetch_transcript.py +138 -0
- package/.claude/skills/youtube-collector/scripts/fetch_videos.py +229 -0
- package/.claude/skills/youtube-collector/scripts/register_channel.py +247 -0
- package/.claude/skills/youtube-collector/scripts/setup_api_key.py +151 -0
- package/package.json +1 -1
|
@@ -6,52 +6,82 @@ Quick validation script for skills - minimal version
|
|
|
6
6
|
import sys
|
|
7
7
|
import os
|
|
8
8
|
import re
|
|
9
|
+
import yaml
|
|
9
10
|
from pathlib import Path
|
|
10
11
|
|
|
11
12
|
def validate_skill(skill_path):
|
|
12
13
|
"""Basic validation of a skill"""
|
|
13
14
|
skill_path = Path(skill_path)
|
|
14
|
-
|
|
15
|
+
|
|
15
16
|
# Check SKILL.md exists
|
|
16
17
|
skill_md = skill_path / 'SKILL.md'
|
|
17
18
|
if not skill_md.exists():
|
|
18
19
|
return False, "SKILL.md not found"
|
|
19
|
-
|
|
20
|
+
|
|
20
21
|
# Read and validate frontmatter
|
|
21
22
|
content = skill_md.read_text()
|
|
22
23
|
if not content.startswith('---'):
|
|
23
24
|
return False, "No YAML frontmatter found"
|
|
24
|
-
|
|
25
|
+
|
|
25
26
|
# Extract frontmatter
|
|
26
27
|
match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
|
|
27
28
|
if not match:
|
|
28
29
|
return False, "Invalid frontmatter format"
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
|
|
31
|
+
frontmatter_text = match.group(1)
|
|
32
|
+
|
|
33
|
+
# Parse YAML frontmatter
|
|
34
|
+
try:
|
|
35
|
+
frontmatter = yaml.safe_load(frontmatter_text)
|
|
36
|
+
if not isinstance(frontmatter, dict):
|
|
37
|
+
return False, "Frontmatter must be a YAML dictionary"
|
|
38
|
+
except yaml.YAMLError as e:
|
|
39
|
+
return False, f"Invalid YAML in frontmatter: {e}"
|
|
40
|
+
|
|
41
|
+
# Define allowed properties
|
|
42
|
+
ALLOWED_PROPERTIES = {'name', 'description', 'license', 'allowed-tools', 'metadata'}
|
|
43
|
+
|
|
44
|
+
# Check for unexpected properties (excluding nested keys under metadata)
|
|
45
|
+
unexpected_keys = set(frontmatter.keys()) - ALLOWED_PROPERTIES
|
|
46
|
+
if unexpected_keys:
|
|
47
|
+
return False, (
|
|
48
|
+
f"Unexpected key(s) in SKILL.md frontmatter: {', '.join(sorted(unexpected_keys))}. "
|
|
49
|
+
f"Allowed properties are: {', '.join(sorted(ALLOWED_PROPERTIES))}"
|
|
50
|
+
)
|
|
51
|
+
|
|
32
52
|
# Check required fields
|
|
33
|
-
if 'name
|
|
53
|
+
if 'name' not in frontmatter:
|
|
34
54
|
return False, "Missing 'name' in frontmatter"
|
|
35
|
-
if 'description
|
|
55
|
+
if 'description' not in frontmatter:
|
|
36
56
|
return False, "Missing 'description' in frontmatter"
|
|
37
|
-
|
|
57
|
+
|
|
38
58
|
# Extract name for validation
|
|
39
|
-
|
|
40
|
-
if
|
|
41
|
-
|
|
59
|
+
name = frontmatter.get('name', '')
|
|
60
|
+
if not isinstance(name, str):
|
|
61
|
+
return False, f"Name must be a string, got {type(name).__name__}"
|
|
62
|
+
name = name.strip()
|
|
63
|
+
if name:
|
|
42
64
|
# Check naming convention (hyphen-case: lowercase with hyphens)
|
|
43
65
|
if not re.match(r'^[a-z0-9-]+$', name):
|
|
44
66
|
return False, f"Name '{name}' should be hyphen-case (lowercase letters, digits, and hyphens only)"
|
|
45
67
|
if name.startswith('-') or name.endswith('-') or '--' in name:
|
|
46
68
|
return False, f"Name '{name}' cannot start/end with hyphen or contain consecutive hyphens"
|
|
69
|
+
# Check name length (max 64 characters per spec)
|
|
70
|
+
if len(name) > 64:
|
|
71
|
+
return False, f"Name is too long ({len(name)} characters). Maximum is 64 characters."
|
|
47
72
|
|
|
48
73
|
# Extract and validate description
|
|
49
|
-
|
|
50
|
-
if
|
|
51
|
-
|
|
74
|
+
description = frontmatter.get('description', '')
|
|
75
|
+
if not isinstance(description, str):
|
|
76
|
+
return False, f"Description must be a string, got {type(description).__name__}"
|
|
77
|
+
description = description.strip()
|
|
78
|
+
if description:
|
|
52
79
|
# Check for angle brackets
|
|
53
80
|
if '<' in description or '>' in description:
|
|
54
81
|
return False, "Description cannot contain angle brackets (< or >)"
|
|
82
|
+
# Check description length (max 1024 characters per spec)
|
|
83
|
+
if len(description) > 1024:
|
|
84
|
+
return False, f"Description is too long ({len(description)} characters). Maximum is 1024 characters."
|
|
55
85
|
|
|
56
86
|
return True, "Skill is valid!"
|
|
57
87
|
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: slash-command-creator
|
|
3
|
+
description: Guide for creating Claude Code slash commands. Use when the user wants to create a new slash command, update an existing slash command, or asks about slash command syntax, frontmatter options, or best practices.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Slash Command Creator
|
|
7
|
+
|
|
8
|
+
Create custom slash commands for Claude Code to automate frequently-used prompts.
|
|
9
|
+
|
|
10
|
+
## Quick Start
|
|
11
|
+
|
|
12
|
+
Initialize a new command:
|
|
13
|
+
```bash
|
|
14
|
+
scripts/init_command.py <command-name> [--scope project|personal]
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Command Structure
|
|
18
|
+
|
|
19
|
+
Slash commands are Markdown files with optional YAML frontmatter:
|
|
20
|
+
|
|
21
|
+
```markdown
|
|
22
|
+
---
|
|
23
|
+
description: Brief description shown in /help
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
Your prompt instructions here.
|
|
27
|
+
|
|
28
|
+
$ARGUMENTS
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### File Locations
|
|
32
|
+
|
|
33
|
+
| Scope | Path | Shown as |
|
|
34
|
+
|----------|-------------------------|-------------------|
|
|
35
|
+
| Project | `.claude/commands/` | (project) |
|
|
36
|
+
| Personal | `~/.claude/commands/` | (user) |
|
|
37
|
+
|
|
38
|
+
### Namespacing
|
|
39
|
+
|
|
40
|
+
Organize commands in subdirectories:
|
|
41
|
+
- `.claude/commands/frontend/component.md` → `/component` shows "(project:frontend)"
|
|
42
|
+
- `~/.claude/commands/backend/api.md` → `/api` shows "(user:backend)"
|
|
43
|
+
|
|
44
|
+
## Features
|
|
45
|
+
|
|
46
|
+
### Arguments
|
|
47
|
+
|
|
48
|
+
**All arguments** - `$ARGUMENTS`:
|
|
49
|
+
```markdown
|
|
50
|
+
Fix issue #$ARGUMENTS following our coding standards
|
|
51
|
+
# /fix-issue 123 → "Fix issue #123 following..."
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
**Positional** - `$1`, `$2`, etc.:
|
|
55
|
+
```markdown
|
|
56
|
+
Review PR #$1 with priority $2
|
|
57
|
+
# /review 456 high → "Review PR #456 with priority high"
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Bash Execution
|
|
61
|
+
|
|
62
|
+
Execute shell commands with `!` prefix (requires `allowed-tools` in frontmatter):
|
|
63
|
+
|
|
64
|
+
```markdown
|
|
65
|
+
---
|
|
66
|
+
allowed-tools: Bash(git status:*), Bash(git diff:*)
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
Current status: !`git status`
|
|
70
|
+
Changes: !`git diff HEAD`
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### File References
|
|
74
|
+
|
|
75
|
+
Include file contents with `@` prefix:
|
|
76
|
+
|
|
77
|
+
```markdown
|
|
78
|
+
Review @src/utils/helpers.js for issues.
|
|
79
|
+
Compare @$1 with @$2.
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Frontmatter Options
|
|
83
|
+
|
|
84
|
+
| Field | Purpose | Required |
|
|
85
|
+
|---------------------------|----------------------------------------|----------|
|
|
86
|
+
| `description` | Brief description for /help | Yes |
|
|
87
|
+
| `allowed-tools` | Tools the command can use | No |
|
|
88
|
+
| `argument-hint` | Expected arguments hint | No |
|
|
89
|
+
| `model` | Specific model to use | No |
|
|
90
|
+
| `disable-model-invocation`| Prevent SlashCommand tool invocation | No |
|
|
91
|
+
|
|
92
|
+
See [references/frontmatter.md](references/frontmatter.md) for detailed reference.
|
|
93
|
+
|
|
94
|
+
## Examples
|
|
95
|
+
|
|
96
|
+
See [references/examples.md](references/examples.md) for complete examples including:
|
|
97
|
+
- Simple review/explain commands
|
|
98
|
+
- Commands with positional arguments
|
|
99
|
+
- Git workflow commands with bash execution
|
|
100
|
+
- Namespaced commands for frontend/backend
|
|
101
|
+
|
|
102
|
+
## Creation Workflow
|
|
103
|
+
|
|
104
|
+
1. **Identify the use case**: What prompt do you repeat often?
|
|
105
|
+
2. **Choose scope**: Project (shared) or personal (private)?
|
|
106
|
+
3. **Initialize**: Run `scripts/init_command.py <name>`
|
|
107
|
+
4. **Edit**: Update description and body
|
|
108
|
+
5. **Test**: Run the command in Claude Code
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
# Slash Command Examples
|
|
2
|
+
|
|
3
|
+
## Simple Commands
|
|
4
|
+
|
|
5
|
+
### Code Review Command
|
|
6
|
+
```markdown
|
|
7
|
+
---
|
|
8
|
+
description: Review code for bugs and improvements
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
Review this code for:
|
|
12
|
+
- Security vulnerabilities
|
|
13
|
+
- Performance issues
|
|
14
|
+
- Code style violations
|
|
15
|
+
- Potential bugs
|
|
16
|
+
|
|
17
|
+
$ARGUMENTS
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Explain Command
|
|
21
|
+
```markdown
|
|
22
|
+
---
|
|
23
|
+
description: Explain code in simple terms
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
Explain the following code in simple, easy-to-understand terms:
|
|
27
|
+
|
|
28
|
+
$ARGUMENTS
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Commands with Arguments
|
|
32
|
+
|
|
33
|
+
### Single Argument (`$ARGUMENTS`)
|
|
34
|
+
```markdown
|
|
35
|
+
---
|
|
36
|
+
description: Fix a GitHub issue
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
Fix issue #$ARGUMENTS following our coding standards.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Positional Arguments (`$1`, `$2`, etc.)
|
|
43
|
+
```markdown
|
|
44
|
+
---
|
|
45
|
+
argument-hint: [pr-number] [priority] [assignee]
|
|
46
|
+
description: Review pull request
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
Review PR #$1 with priority $2 and assign to $3.
|
|
50
|
+
Focus on security, performance, and code style.
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Commands with Bash Execution
|
|
54
|
+
|
|
55
|
+
Use `!` prefix to execute bash commands and include output in context.
|
|
56
|
+
|
|
57
|
+
### Git Commit Command
|
|
58
|
+
```markdown
|
|
59
|
+
---
|
|
60
|
+
allowed-tools: Bash(git add:*), Bash(git status:*), Bash(git commit:*)
|
|
61
|
+
description: Create a git commit
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Context
|
|
65
|
+
|
|
66
|
+
- Current git status: !`git status`
|
|
67
|
+
- Current git diff: !`git diff HEAD`
|
|
68
|
+
- Current branch: !`git branch --show-current`
|
|
69
|
+
- Recent commits: !`git log --oneline -10`
|
|
70
|
+
|
|
71
|
+
## Task
|
|
72
|
+
|
|
73
|
+
Based on the above changes, create a single git commit.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Deploy Command
|
|
77
|
+
```markdown
|
|
78
|
+
---
|
|
79
|
+
allowed-tools: Bash(npm:*), Bash(docker:*)
|
|
80
|
+
argument-hint: [environment]
|
|
81
|
+
description: Deploy to specified environment
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Current State
|
|
85
|
+
|
|
86
|
+
- Branch: !`git branch --show-current`
|
|
87
|
+
- Last commit: !`git log -1 --oneline`
|
|
88
|
+
|
|
89
|
+
## Deploy to $1
|
|
90
|
+
|
|
91
|
+
Run the deployment process for the $1 environment.
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
## Commands with File References
|
|
95
|
+
|
|
96
|
+
Use `@` prefix to include file contents.
|
|
97
|
+
|
|
98
|
+
### Review Implementation
|
|
99
|
+
```markdown
|
|
100
|
+
---
|
|
101
|
+
description: Review implementation against spec
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
Review the implementation in @src/utils/helpers.js against the specification.
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Compare Files
|
|
108
|
+
```markdown
|
|
109
|
+
---
|
|
110
|
+
argument-hint: [old-file] [new-file]
|
|
111
|
+
description: Compare two files
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
Compare @$1 with @$2 and summarize the differences.
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Namespaced Commands
|
|
118
|
+
|
|
119
|
+
Commands in subdirectories appear with namespace in description.
|
|
120
|
+
|
|
121
|
+
### Frontend Component (`.claude/commands/frontend/component.md`)
|
|
122
|
+
```markdown
|
|
123
|
+
---
|
|
124
|
+
description: Generate a React component
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
Generate a React component with the following requirements:
|
|
128
|
+
|
|
129
|
+
$ARGUMENTS
|
|
130
|
+
|
|
131
|
+
Follow our frontend coding standards and use TypeScript.
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Backend API (`.claude/commands/backend/api.md`)
|
|
135
|
+
```markdown
|
|
136
|
+
---
|
|
137
|
+
description: Generate API endpoint
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
Generate a REST API endpoint for:
|
|
141
|
+
|
|
142
|
+
$ARGUMENTS
|
|
143
|
+
|
|
144
|
+
Include validation, error handling, and documentation.
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Extended Thinking Commands
|
|
148
|
+
|
|
149
|
+
Include thinking keywords to trigger extended thinking.
|
|
150
|
+
|
|
151
|
+
```markdown
|
|
152
|
+
---
|
|
153
|
+
description: Analyze architecture deeply
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
Think step by step about the architecture implications of:
|
|
157
|
+
|
|
158
|
+
$ARGUMENTS
|
|
159
|
+
|
|
160
|
+
Consider scalability, maintainability, and performance.
|
|
161
|
+
```
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Slash Command Frontmatter Reference
|
|
2
|
+
|
|
3
|
+
## Required Fields
|
|
4
|
+
|
|
5
|
+
### `description`
|
|
6
|
+
Brief description of what the command does. Shown in `/help` output.
|
|
7
|
+
|
|
8
|
+
```yaml
|
|
9
|
+
description: Create a git commit with staged changes
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Optional Fields
|
|
13
|
+
|
|
14
|
+
### `allowed-tools`
|
|
15
|
+
Specifies which tools the command can use. Format: `ToolName(pattern:*)` or just `ToolName`.
|
|
16
|
+
|
|
17
|
+
```yaml
|
|
18
|
+
# Single tool
|
|
19
|
+
allowed-tools: Bash(git status:*)
|
|
20
|
+
|
|
21
|
+
# Multiple tools
|
|
22
|
+
allowed-tools: Bash(git add:*), Bash(git status:*), Bash(git commit:*)
|
|
23
|
+
|
|
24
|
+
# Tool without pattern
|
|
25
|
+
allowed-tools: Read, Write, Edit
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Common tool patterns:
|
|
29
|
+
- `Bash(command:*)` - Allow specific bash commands
|
|
30
|
+
- `Read` - File reading
|
|
31
|
+
- `Write` - File writing
|
|
32
|
+
- `Edit` - File editing
|
|
33
|
+
- `Grep` - Content search
|
|
34
|
+
- `Glob` - File pattern matching
|
|
35
|
+
|
|
36
|
+
### `argument-hint`
|
|
37
|
+
Shows expected arguments when auto-completing the command.
|
|
38
|
+
|
|
39
|
+
```yaml
|
|
40
|
+
# Single argument
|
|
41
|
+
argument-hint: [message]
|
|
42
|
+
|
|
43
|
+
# Multiple arguments
|
|
44
|
+
argument-hint: [pr-number] [priority] [assignee]
|
|
45
|
+
|
|
46
|
+
# Alternative syntax
|
|
47
|
+
argument-hint: add [tagId] | remove [tagId] | list
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### `model`
|
|
51
|
+
Specific model to use for this command. See [Models overview](https://docs.claude.com/en/docs/about-claude/models/overview).
|
|
52
|
+
|
|
53
|
+
```yaml
|
|
54
|
+
model: claude-3-5-haiku-20241022
|
|
55
|
+
model: claude-sonnet-4-5-20250929
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### `disable-model-invocation`
|
|
59
|
+
Prevents the `SlashCommand` tool from calling this command programmatically.
|
|
60
|
+
|
|
61
|
+
```yaml
|
|
62
|
+
disable-model-invocation: true
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Complete Frontmatter Example
|
|
66
|
+
|
|
67
|
+
```yaml
|
|
68
|
+
---
|
|
69
|
+
allowed-tools: Bash(git add:*), Bash(git status:*), Bash(git commit:*)
|
|
70
|
+
argument-hint: [message]
|
|
71
|
+
description: Create a git commit with staged changes
|
|
72
|
+
model: claude-3-5-haiku-20241022
|
|
73
|
+
---
|
|
74
|
+
```
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Slash Command Initializer - Creates a new slash command from template
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
init_command.py <command-name> [--scope project|personal] [--path <custom-path>]
|
|
7
|
+
|
|
8
|
+
Examples:
|
|
9
|
+
init_command.py review # Creates .claude/commands/review.md
|
|
10
|
+
init_command.py deploy --scope personal # Creates ~/.claude/commands/deploy.md
|
|
11
|
+
init_command.py test --path ./my-commands # Creates ./my-commands/test.md
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import sys
|
|
15
|
+
import os
|
|
16
|
+
from pathlib import Path
|
|
17
|
+
import argparse
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
COMMAND_TEMPLATE = '''---
|
|
21
|
+
description: {description}
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
# {command_title}
|
|
25
|
+
|
|
26
|
+
{body}
|
|
27
|
+
'''
|
|
28
|
+
|
|
29
|
+
COMMAND_TEMPLATE_WITH_TOOLS = '''---
|
|
30
|
+
allowed-tools: {allowed_tools}
|
|
31
|
+
description: {description}
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
# {command_title}
|
|
35
|
+
|
|
36
|
+
{body}
|
|
37
|
+
'''
|
|
38
|
+
|
|
39
|
+
COMMAND_TEMPLATE_FULL = '''---
|
|
40
|
+
allowed-tools: {allowed_tools}
|
|
41
|
+
argument-hint: {argument_hint}
|
|
42
|
+
description: {description}
|
|
43
|
+
model: {model}
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
# {command_title}
|
|
47
|
+
|
|
48
|
+
{body}
|
|
49
|
+
'''
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def title_case(name: str) -> str:
|
|
53
|
+
"""Convert hyphenated name to Title Case."""
|
|
54
|
+
return ' '.join(word.capitalize() for word in name.replace('-', ' ').split())
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def get_project_commands_path() -> Path:
|
|
58
|
+
"""Get the project-level commands directory."""
|
|
59
|
+
return Path.cwd() / '.claude' / 'commands'
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def get_personal_commands_path() -> Path:
|
|
63
|
+
"""Get the user-level commands directory."""
|
|
64
|
+
return Path.home() / '.claude' / 'commands'
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def init_command(
|
|
68
|
+
command_name: str,
|
|
69
|
+
scope: str = 'project',
|
|
70
|
+
custom_path: str = None,
|
|
71
|
+
description: str = None,
|
|
72
|
+
body: str = None,
|
|
73
|
+
allowed_tools: str = None,
|
|
74
|
+
argument_hint: str = None,
|
|
75
|
+
model: str = None,
|
|
76
|
+
namespace: str = None
|
|
77
|
+
) -> Path:
|
|
78
|
+
"""
|
|
79
|
+
Initialize a new slash command.
|
|
80
|
+
|
|
81
|
+
Args:
|
|
82
|
+
command_name: Name of the command (without .md extension)
|
|
83
|
+
scope: 'project' or 'personal'
|
|
84
|
+
custom_path: Optional custom path override
|
|
85
|
+
description: Command description
|
|
86
|
+
body: Command body content
|
|
87
|
+
allowed_tools: Comma-separated list of allowed tools
|
|
88
|
+
argument_hint: Hint for command arguments
|
|
89
|
+
model: Specific model to use
|
|
90
|
+
namespace: Optional subdirectory namespace
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
Path to created command file, or None if error
|
|
94
|
+
"""
|
|
95
|
+
# Determine base path
|
|
96
|
+
if custom_path:
|
|
97
|
+
base_path = Path(custom_path).resolve()
|
|
98
|
+
elif scope == 'personal':
|
|
99
|
+
base_path = get_personal_commands_path()
|
|
100
|
+
else:
|
|
101
|
+
base_path = get_project_commands_path()
|
|
102
|
+
|
|
103
|
+
# Add namespace subdirectory if specified
|
|
104
|
+
if namespace:
|
|
105
|
+
base_path = base_path / namespace
|
|
106
|
+
|
|
107
|
+
# Create directory if it doesn't exist
|
|
108
|
+
try:
|
|
109
|
+
base_path.mkdir(parents=True, exist_ok=True)
|
|
110
|
+
except Exception as e:
|
|
111
|
+
print(f"Error creating directory {base_path}: {e}")
|
|
112
|
+
return None
|
|
113
|
+
|
|
114
|
+
# Create command file path
|
|
115
|
+
command_file = base_path / f'{command_name}.md'
|
|
116
|
+
|
|
117
|
+
# Check if file already exists
|
|
118
|
+
if command_file.exists():
|
|
119
|
+
print(f"Error: Command already exists: {command_file}")
|
|
120
|
+
return None
|
|
121
|
+
|
|
122
|
+
# Prepare content
|
|
123
|
+
command_title = title_case(command_name)
|
|
124
|
+
description = description or f"[TODO: Brief description of /{command_name}]"
|
|
125
|
+
body = body or f"[TODO: Add instructions for /{command_name}]\n\n$ARGUMENTS"
|
|
126
|
+
|
|
127
|
+
# Choose template based on options
|
|
128
|
+
if allowed_tools and argument_hint and model:
|
|
129
|
+
content = COMMAND_TEMPLATE_FULL.format(
|
|
130
|
+
allowed_tools=allowed_tools,
|
|
131
|
+
argument_hint=argument_hint,
|
|
132
|
+
description=description,
|
|
133
|
+
model=model,
|
|
134
|
+
command_title=command_title,
|
|
135
|
+
body=body
|
|
136
|
+
)
|
|
137
|
+
elif allowed_tools:
|
|
138
|
+
content = COMMAND_TEMPLATE_WITH_TOOLS.format(
|
|
139
|
+
allowed_tools=allowed_tools,
|
|
140
|
+
description=description,
|
|
141
|
+
command_title=command_title,
|
|
142
|
+
body=body
|
|
143
|
+
)
|
|
144
|
+
else:
|
|
145
|
+
content = COMMAND_TEMPLATE.format(
|
|
146
|
+
description=description,
|
|
147
|
+
command_title=command_title,
|
|
148
|
+
body=body
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
# Write command file
|
|
152
|
+
try:
|
|
153
|
+
command_file.write_text(content)
|
|
154
|
+
print(f"Created: {command_file}")
|
|
155
|
+
return command_file
|
|
156
|
+
except Exception as e:
|
|
157
|
+
print(f"Error writing command file: {e}")
|
|
158
|
+
return None
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def main():
|
|
162
|
+
parser = argparse.ArgumentParser(
|
|
163
|
+
description='Initialize a new Claude Code slash command',
|
|
164
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
165
|
+
epilog='''
|
|
166
|
+
Examples:
|
|
167
|
+
%(prog)s review
|
|
168
|
+
Creates .claude/commands/review.md (project command)
|
|
169
|
+
|
|
170
|
+
%(prog)s deploy --scope personal
|
|
171
|
+
Creates ~/.claude/commands/deploy.md (personal command)
|
|
172
|
+
|
|
173
|
+
%(prog)s component --namespace frontend
|
|
174
|
+
Creates .claude/commands/frontend/component.md
|
|
175
|
+
|
|
176
|
+
%(prog)s commit --allowed-tools "Bash(git add:*), Bash(git commit:*)"
|
|
177
|
+
Creates command with specific tool permissions
|
|
178
|
+
|
|
179
|
+
Command naming:
|
|
180
|
+
- Use lowercase with hyphens (e.g., 'review-pr', 'run-tests')
|
|
181
|
+
- Avoid spaces and special characters
|
|
182
|
+
- Keep names concise and descriptive
|
|
183
|
+
'''
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
parser.add_argument('command_name', help='Name of the slash command (without .md)')
|
|
187
|
+
parser.add_argument('--scope', choices=['project', 'personal'], default='project',
|
|
188
|
+
help='Command scope: project (.claude/commands) or personal (~/.claude/commands)')
|
|
189
|
+
parser.add_argument('--path', dest='custom_path', help='Custom path for command file')
|
|
190
|
+
parser.add_argument('--namespace', help='Subdirectory namespace (e.g., frontend, backend)')
|
|
191
|
+
parser.add_argument('--description', help='Command description')
|
|
192
|
+
parser.add_argument('--allowed-tools', dest='allowed_tools', help='Comma-separated list of allowed tools')
|
|
193
|
+
parser.add_argument('--argument-hint', dest='argument_hint', help='Hint for command arguments')
|
|
194
|
+
parser.add_argument('--model', help='Specific model to use (e.g., claude-3-5-haiku-20241022)')
|
|
195
|
+
|
|
196
|
+
args = parser.parse_args()
|
|
197
|
+
|
|
198
|
+
result = init_command(
|
|
199
|
+
command_name=args.command_name,
|
|
200
|
+
scope=args.scope,
|
|
201
|
+
custom_path=args.custom_path,
|
|
202
|
+
description=args.description,
|
|
203
|
+
allowed_tools=args.allowed_tools,
|
|
204
|
+
argument_hint=args.argument_hint,
|
|
205
|
+
model=args.model,
|
|
206
|
+
namespace=args.namespace
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
if result:
|
|
210
|
+
print(f"\nSlash command '/{args.command_name}' initialized successfully!")
|
|
211
|
+
print("\nNext steps:")
|
|
212
|
+
print("1. Edit the command file to update the description and body")
|
|
213
|
+
print("2. Test the command by running it in Claude Code")
|
|
214
|
+
print(f"\nUsage: /{args.command_name} [arguments]")
|
|
215
|
+
sys.exit(0)
|
|
216
|
+
else:
|
|
217
|
+
sys.exit(1)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
if __name__ == "__main__":
|
|
221
|
+
main()
|