Files
Claude-Code-Workflow/.claude/skills/command-guide/analyze_commands.py
catlog22 6993677ed9 feat: Add command relationships and essential commands JSON files
- Introduced command-relationships.json to define relationships between various commands.
- Created essential-commands.json to provide detailed descriptions and usage scenarios for key commands.
- Implemented update-index.sh script for maintaining command index files, including backup and validation processes.
- Added templates for bug reports, feature requests, and questions to streamline issue reporting and feature suggestions.
2025-11-06 12:59:14 +08:00

355 lines
12 KiB
Python

#!/usr/bin/env python3
"""
Analyze all command files and generate index files for command-guide skill.
"""
import os
import re
import json
from pathlib import Path
from collections import defaultdict
from typing import Dict, List, Any
# Base paths
COMMANDS_DIR = Path("D:/Claude_dms3/.claude/commands")
INDEX_DIR = Path("D:/Claude_dms3/.claude/skills/command-guide/index")
def parse_frontmatter(content: str) -> Dict[str, Any]:
"""Extract YAML frontmatter from markdown content."""
frontmatter = {}
if content.startswith('---'):
lines = content.split('\n')
in_frontmatter = False
for i, line in enumerate(lines[1:], 1):
if line.strip() == '---':
break
if ':' in line:
key, value = line.split(':', 1)
frontmatter[key.strip()] = value.strip().strip('"')
return frontmatter
def categorize_command(file_path: Path) -> tuple:
"""Determine category and subcategory from file path."""
parts = file_path.relative_to(COMMANDS_DIR).parts
if len(parts) == 1:
return "general", None
category = parts[0] # cli, memory, task, workflow
subcategory = parts[1].replace('.md', '') if len(parts) > 2 else None
return category, subcategory
def determine_usage_scenario(name: str, description: str, category: str) -> str:
"""Determine primary usage scenario for command."""
name_lower = name.lower()
desc_lower = description.lower()
# Planning indicators
if any(word in name_lower for word in ['plan', 'design', 'breakdown', 'brainstorm']):
return "planning"
# Implementation indicators
if any(word in name_lower for word in ['implement', 'execute', 'generate', 'create', 'write']):
return "implementation"
# Testing indicators
if any(word in name_lower for word in ['test', 'tdd', 'verify', 'coverage']):
return "testing"
# Documentation indicators
if any(word in name_lower for word in ['docs', 'documentation', 'memory']):
return "documentation"
# Session management indicators
if any(word in name_lower for word in ['session', 'resume', 'status', 'complete']):
return "session-management"
# Analysis indicators
if any(word in name_lower for word in ['analyze', 'review', 'diagnosis']):
return "analysis"
return "general"
def determine_difficulty(name: str, description: str, category: str) -> str:
"""Determine difficulty level."""
name_lower = name.lower()
# Beginner commands
beginner_keywords = ['status', 'list', 'chat', 'analyze', 'version']
if any(word in name_lower for word in beginner_keywords):
return "Beginner"
# Advanced commands
advanced_keywords = ['tdd', 'conflict', 'agent', 'auto-parallel', 'coverage', 'synthesis']
if any(word in name_lower for word in advanced_keywords):
return "Advanced"
# Intermediate by default
return "Intermediate"
def analyze_command_file(file_path: Path) -> Dict[str, Any]:
"""Analyze a single command file and extract metadata."""
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# Parse frontmatter
frontmatter = parse_frontmatter(content)
# Extract data
name = frontmatter.get('name', file_path.stem)
description = frontmatter.get('description', '')
argument_hint = frontmatter.get('argument-hint', '')
# Determine categorization
category, subcategory = categorize_command(file_path)
usage_scenario = determine_usage_scenario(name, description, category)
difficulty = determine_difficulty(name, description, category)
# Build relative path
rel_path = str(file_path.relative_to(COMMANDS_DIR))
# Build full command name
if category == "general":
command_name = f"/{name}"
else:
if subcategory and subcategory not in name:
command_name = f"/{category}:{subcategory}:{name}"
else:
command_name = f"/{category}:{name}"
return {
"name": name,
"command": command_name,
"description": description,
"arguments": argument_hint,
"category": category,
"subcategory": subcategory,
"usage_scenario": usage_scenario,
"difficulty": difficulty,
"file_path": rel_path
}
def build_command_relationships() -> Dict[str, Any]:
"""Build command relationship mappings."""
relationships = {
# Workflow planning commands
"plan": {
"calls_internally": [
"session:start",
"tools:context-gather",
"tools:conflict-resolution",
"tools:task-generate",
"tools:task-generate-agent"
],
"next_steps": ["action-plan-verify", "status", "execute"],
"alternatives": ["tdd-plan"]
},
"tdd-plan": {
"calls_internally": [
"session:start",
"tools:context-gather",
"tools:task-generate-tdd"
],
"next_steps": ["tdd-verify", "status", "execute"],
"alternatives": ["plan"]
},
# Execution commands
"execute": {
"prerequisites": ["plan", "tdd-plan"],
"related": ["status", "resume"],
"next_steps": ["review", "tdd-verify"]
},
# Verification commands
"action-plan-verify": {
"prerequisites": ["plan"],
"next_steps": ["execute"],
"related": ["status"]
},
"tdd-verify": {
"prerequisites": ["execute"],
"related": ["tools:tdd-coverage-analysis"]
},
# Session management
"session:start": {
"next_steps": ["plan", "execute"],
"related": ["session:list", "session:resume"]
},
"session:resume": {
"alternatives": ["resume"],
"related": ["session:list", "status"]
},
# Task management
"task:create": {
"next_steps": ["task:execute"],
"related": ["task:breakdown"]
},
"task:breakdown": {
"next_steps": ["task:execute"],
"related": ["task:create"]
},
"task:replan": {
"prerequisites": ["plan"],
"related": ["action-plan-verify"]
},
# Memory/Documentation
"memory:docs": {
"calls_internally": [
"session:start",
"tools:context-gather"
],
"next_steps": ["execute"]
},
# CLI modes
"cli:execute": {
"alternatives": ["cli:codex-execute"],
"related": ["cli:analyze", "cli:chat"]
},
# Brainstorming
"brainstorm:artifacts": {
"next_steps": ["brainstorm:synthesis", "plan"],
"related": ["brainstorm:auto-parallel"]
},
"brainstorm:synthesis": {
"prerequisites": ["brainstorm:artifacts"],
"next_steps": ["plan"]
}
}
return relationships
def identify_essential_commands(all_commands: List[Dict]) -> List[Dict]:
"""Identify the most essential commands for beginners."""
# Essential command names (14 most important)
essential_names = [
"plan",
"execute",
"status",
"session:start",
"task:execute",
"cli:analyze",
"cli:chat",
"memory:docs",
"brainstorm:artifacts",
"action-plan-verify",
"resume",
"review",
"version",
"enhance-prompt"
]
essential = []
for cmd in all_commands:
# Check both command name and simple name
cmd_simple = cmd['command'].lstrip('/')
if cmd_simple in essential_names or cmd['name'] in essential_names:
essential.append(cmd)
return essential[:14] # Limit to 14
def main():
"""Main analysis function."""
import sys
import io
# Fix Windows console encoding
if sys.platform == 'win32':
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
print("Analyzing command files...")
# Find all command files
command_files = list(COMMANDS_DIR.rglob("*.md"))
print(f"Found {len(command_files)} command files")
# Analyze each command
all_commands = []
for cmd_file in sorted(command_files):
try:
metadata = analyze_command_file(cmd_file)
all_commands.append(metadata)
print(f" OK {metadata['command']}")
except Exception as e:
print(f" ERROR analyzing {cmd_file}: {e}")
print(f"\nAnalyzed {len(all_commands)} commands")
# Generate index files
INDEX_DIR.mkdir(parents=True, exist_ok=True)
# 1. all-commands.json
all_commands_path = INDEX_DIR / "all-commands.json"
with open(all_commands_path, 'w', encoding='utf-8') as f:
json.dump(all_commands, f, indent=2, ensure_ascii=False)
print(f"\nOK Generated {all_commands_path} ({os.path.getsize(all_commands_path)} bytes)")
# 2. by-category.json
by_category = defaultdict(lambda: defaultdict(list))
for cmd in all_commands:
cat = cmd['category']
subcat = cmd['subcategory'] or '_root'
by_category[cat][subcat].append(cmd)
by_category_path = INDEX_DIR / "by-category.json"
with open(by_category_path, 'w', encoding='utf-8') as f:
json.dump(dict(by_category), f, indent=2, ensure_ascii=False)
print(f"OK Generated {by_category_path} ({os.path.getsize(by_category_path)} bytes)")
# 3. by-use-case.json
by_use_case = defaultdict(list)
for cmd in all_commands:
by_use_case[cmd['usage_scenario']].append(cmd)
by_use_case_path = INDEX_DIR / "by-use-case.json"
with open(by_use_case_path, 'w', encoding='utf-8') as f:
json.dump(dict(by_use_case), f, indent=2, ensure_ascii=False)
print(f"OK Generated {by_use_case_path} ({os.path.getsize(by_use_case_path)} bytes)")
# 4. essential-commands.json
essential = identify_essential_commands(all_commands)
essential_path = INDEX_DIR / "essential-commands.json"
with open(essential_path, 'w', encoding='utf-8') as f:
json.dump(essential, f, indent=2, ensure_ascii=False)
print(f"OK Generated {essential_path} ({os.path.getsize(essential_path)} bytes)")
# 5. command-relationships.json
relationships = build_command_relationships()
relationships_path = INDEX_DIR / "command-relationships.json"
with open(relationships_path, 'w', encoding='utf-8') as f:
json.dump(relationships, f, indent=2, ensure_ascii=False)
print(f"OK Generated {relationships_path} ({os.path.getsize(relationships_path)} bytes)")
# Print summary statistics
print("\n=== Summary Statistics ===")
print(f"Total commands: {len(all_commands)}")
print(f"\nBy category:")
for cat in sorted(by_category.keys()):
total = sum(len(cmds) for cmds in by_category[cat].values())
print(f" {cat}: {total}")
for subcat in sorted(by_category[cat].keys()):
if subcat != '_root':
print(f" - {subcat}: {len(by_category[cat][subcat])}")
print(f"\nBy usage scenario:")
for scenario in sorted(by_use_case.keys()):
print(f" {scenario}: {len(by_use_case[scenario])}")
print(f"\nBy difficulty:")
difficulty_counts = defaultdict(int)
for cmd in all_commands:
difficulty_counts[cmd['difficulty']] += 1
for difficulty in ['Beginner', 'Intermediate', 'Advanced']:
print(f" {difficulty}: {difficulty_counts[difficulty]}")
print(f"\nEssential commands: {len(essential)}")
if __name__ == '__main__':
main()