mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-10 02:24:35 +08:00
fix(security): Apply 3 critical security fixes
- sec-001: Add validateAllowedPath to /api/file endpoint (path traversal) - sec-002: Enable CSRF by default with CCW_DISABLE_CSRF opt-out - sec-003: Add validateAllowedPath to /api/dialog/browse and /api/dialog/open-file (path traversal) Ref: fix-1738072800000
This commit is contained in:
650
.claude/skills/lite-skill-generator/SKILL.md
Normal file
650
.claude/skills/lite-skill-generator/SKILL.md
Normal file
@@ -0,0 +1,650 @@
|
|||||||
|
---
|
||||||
|
name: lite-skill-generator
|
||||||
|
description: Lightweight skill generator with style learning - creates simple skills using flow-based execution and style imitation. Use for quick skill scaffolding, simple workflow creation, or style-aware skill generation.
|
||||||
|
allowed-tools: Read, Write, Bash, Glob, Grep, AskUserQuestion
|
||||||
|
---
|
||||||
|
|
||||||
|
# Lite Skill Generator
|
||||||
|
|
||||||
|
Lightweight meta-skill for rapid skill creation with intelligent style learning and flow-based execution.
|
||||||
|
|
||||||
|
## Core Concept
|
||||||
|
|
||||||
|
**Simplicity First**: Generate simple, focused skills quickly with minimal overhead. Learn from existing skills to maintain consistent style and structure.
|
||||||
|
|
||||||
|
**Progressive Disclosure**: Follow anthropics' three-layer loading principle:
|
||||||
|
1. **Metadata** - name, description, triggers (always loaded)
|
||||||
|
2. **SKILL.md** - core instructions (loaded when triggered)
|
||||||
|
3. **Bundled resources** - scripts, references, assets (loaded on demand)
|
||||||
|
|
||||||
|
## Execution Model
|
||||||
|
|
||||||
|
**3-Phase Flow**: Style Learning → Requirements Gathering → Generation
|
||||||
|
|
||||||
|
```
|
||||||
|
User Input → Phase 1: Style Analysis → Phase 2: Requirements → Phase 3: Generate → Skill Package
|
||||||
|
↓ ↓ ↓
|
||||||
|
Learn from examples Interactive prompts Write files + validate
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture Overview
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────────┐
|
||||||
|
│ Lite Skill Generator │
|
||||||
|
│ │
|
||||||
|
│ Input: Skill name, purpose, reference skills │
|
||||||
|
│ ↓ │
|
||||||
|
│ ┌─────────────────────────────────────────────────────────┐ │
|
||||||
|
│ │ Phase 1-3: Lightweight Pipeline │ │
|
||||||
|
│ │ ┌────┐ ┌────┐ ┌────┐ │ │
|
||||||
|
│ │ │ P1 │→│ P2 │→│ P3 │ │ │
|
||||||
|
│ │ │Styl│ │Req │ │Gen │ │ │
|
||||||
|
│ │ └────┘ └────┘ └────┘ │ │
|
||||||
|
│ └─────────────────────────────────────────────────────────┘ │
|
||||||
|
│ ↓ │
|
||||||
|
│ Output: .claude/skills/{skill-name}/ (minimal package) │
|
||||||
|
│ │
|
||||||
|
└─────────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3-Phase Workflow
|
||||||
|
|
||||||
|
### Phase 1: Style Analysis & Learning
|
||||||
|
|
||||||
|
Analyze reference skills to extract language patterns, structural conventions, and writing style.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Phase 1 Execution Flow
|
||||||
|
async function analyzeStyle(referencePaths) {
|
||||||
|
// Step 1: Load reference skills
|
||||||
|
const references = [];
|
||||||
|
for (const path of referencePaths) {
|
||||||
|
const content = Read(path);
|
||||||
|
references.push({
|
||||||
|
path: path,
|
||||||
|
content: content,
|
||||||
|
metadata: extractYAMLFrontmatter(content)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Extract style patterns
|
||||||
|
const styleProfile = {
|
||||||
|
// Structural patterns
|
||||||
|
structure: {
|
||||||
|
hasFrontmatter: references.every(r => r.metadata !== null),
|
||||||
|
sectionHeaders: extractCommonSections(references),
|
||||||
|
codeBlockUsage: detectCodeBlockPatterns(references),
|
||||||
|
flowDiagramUsage: detectFlowDiagrams(references)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Language patterns
|
||||||
|
language: {
|
||||||
|
instructionStyle: detectInstructionStyle(references), // 'imperative' | 'declarative' | 'procedural'
|
||||||
|
pseudocodeUsage: detectPseudocodePatterns(references),
|
||||||
|
verbosity: calculateVerbosityLevel(references), // 'concise' | 'detailed' | 'verbose'
|
||||||
|
terminology: extractCommonTerms(references)
|
||||||
|
},
|
||||||
|
|
||||||
|
// Organization patterns
|
||||||
|
organization: {
|
||||||
|
phaseStructure: detectPhasePattern(references), // 'sequential' | 'autonomous' | 'flat'
|
||||||
|
exampleDensity: calculateExampleRatio(references),
|
||||||
|
templateUsage: detectTemplateReferences(references)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 3: Generate style guide
|
||||||
|
return {
|
||||||
|
profile: styleProfile,
|
||||||
|
recommendations: generateStyleRecommendations(styleProfile),
|
||||||
|
examples: extractStyleExamples(references, styleProfile)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Structural pattern detection
|
||||||
|
function extractCommonSections(references) {
|
||||||
|
const allSections = references.map(r =>
|
||||||
|
r.content.match(/^##? (.+)$/gm)?.map(s => s.replace(/^##? /, ''))
|
||||||
|
).flat();
|
||||||
|
return findMostCommon(allSections);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Language style detection
|
||||||
|
function detectInstructionStyle(references) {
|
||||||
|
const imperativePattern = /^(Use|Execute|Run|Call|Create|Generate)\s/gim;
|
||||||
|
const declarativePattern = /^(The|This|Each|All)\s.*\s(is|are|will be)\s/gim;
|
||||||
|
const proceduralPattern = /^(Step \d+|Phase \d+|First|Then|Finally)\s/gim;
|
||||||
|
|
||||||
|
const scores = references.map(r => ({
|
||||||
|
imperative: (r.content.match(imperativePattern) || []).length,
|
||||||
|
declarative: (r.content.match(declarativePattern) || []).length,
|
||||||
|
procedural: (r.content.match(proceduralPattern) || []).length
|
||||||
|
}));
|
||||||
|
|
||||||
|
return getMaxStyle(scores);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pseudocode pattern detection
|
||||||
|
function detectPseudocodePatterns(references) {
|
||||||
|
const hasJavaScriptBlocks = references.some(r => r.content.includes('```javascript'));
|
||||||
|
const hasFunctionDefs = references.some(r => /function\s+\w+\(/m.test(r.content));
|
||||||
|
const hasFlowComments = references.some(r => /\/\/.*→/m.test(r.content));
|
||||||
|
|
||||||
|
return {
|
||||||
|
usePseudocode: hasJavaScriptBlocks && hasFunctionDefs,
|
||||||
|
flowAnnotations: hasFlowComments,
|
||||||
|
style: hasFunctionDefs ? 'functional' : 'imperative'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output**:
|
||||||
|
```
|
||||||
|
Style Analysis Complete:
|
||||||
|
Structure: Flow-based with pseudocode
|
||||||
|
Language: Procedural, detailed
|
||||||
|
Organization: Sequential phases
|
||||||
|
Key Patterns: 3-5 phases, function definitions, ASCII diagrams
|
||||||
|
|
||||||
|
Recommendations:
|
||||||
|
✓ Use phase-based structure (3-4 phases)
|
||||||
|
✓ Include pseudocode for complex logic
|
||||||
|
✓ Add ASCII flow diagrams
|
||||||
|
✓ Maintain concise documentation style
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 2: Requirements Gathering
|
||||||
|
|
||||||
|
Interactive discovery of skill requirements using learned style patterns.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
async function gatherRequirements(styleProfile) {
|
||||||
|
// Step 1: Basic information
|
||||||
|
const basicInfo = await AskUserQuestion({
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
question: "What is the skill name? (kebab-case, e.g., 'pdf-generator')",
|
||||||
|
header: "Name",
|
||||||
|
options: [
|
||||||
|
{ label: "pdf-generator", description: "Example: PDF generation skill" },
|
||||||
|
{ label: "code-analyzer", description: "Example: Code analysis skill" },
|
||||||
|
{ label: "Custom", description: "Enter custom name" }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "What is the primary purpose?",
|
||||||
|
header: "Purpose",
|
||||||
|
options: [
|
||||||
|
{ label: "Generation", description: "Create/generate artifacts" },
|
||||||
|
{ label: "Analysis", description: "Analyze/inspect code or data" },
|
||||||
|
{ label: "Transformation", description: "Convert/transform content" },
|
||||||
|
{ label: "Orchestration", description: "Coordinate multiple operations" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Step 2: Execution complexity
|
||||||
|
const complexity = await AskUserQuestion({
|
||||||
|
questions: [{
|
||||||
|
question: "How many main steps does this skill need?",
|
||||||
|
header: "Steps",
|
||||||
|
options: [
|
||||||
|
{ label: "2-3 steps", description: "Simple workflow (recommended for lite-skill)" },
|
||||||
|
{ label: "4-5 steps", description: "Moderate workflow" },
|
||||||
|
{ label: "6+ steps", description: "Complex workflow (consider full skill-generator)" }
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Step 3: Tool requirements
|
||||||
|
const tools = await AskUserQuestion({
|
||||||
|
questions: [{
|
||||||
|
question: "Which tools will this skill use? (select multiple)",
|
||||||
|
header: "Tools",
|
||||||
|
multiSelect: true,
|
||||||
|
options: [
|
||||||
|
{ label: "Read", description: "Read files" },
|
||||||
|
{ label: "Write", description: "Write files" },
|
||||||
|
{ label: "Bash", description: "Execute commands" },
|
||||||
|
{ label: "Task", description: "Launch agents" },
|
||||||
|
{ label: "AskUserQuestion", description: "Interactive prompts" }
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Step 4: Output format
|
||||||
|
const output = await AskUserQuestion({
|
||||||
|
questions: [{
|
||||||
|
question: "What does this skill produce?",
|
||||||
|
header: "Output",
|
||||||
|
options: [
|
||||||
|
{ label: "Single file", description: "One main output file" },
|
||||||
|
{ label: "Multiple files", description: "Several related files" },
|
||||||
|
{ label: "Directory structure", description: "Complete directory tree" },
|
||||||
|
{ label: "Modified files", description: "Edits to existing files" }
|
||||||
|
]
|
||||||
|
}]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Step 5: Build configuration
|
||||||
|
return {
|
||||||
|
name: basicInfo.Name,
|
||||||
|
purpose: basicInfo.Purpose,
|
||||||
|
description: generateDescription(basicInfo.Name, basicInfo.Purpose),
|
||||||
|
steps: parseStepCount(complexity.Steps),
|
||||||
|
allowedTools: tools.Tools,
|
||||||
|
outputType: output.Output,
|
||||||
|
styleProfile: styleProfile,
|
||||||
|
triggerPhrases: generateTriggerPhrases(basicInfo.Name, basicInfo.Purpose)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate skill description from name and purpose
|
||||||
|
function generateDescription(name, purpose) {
|
||||||
|
const templates = {
|
||||||
|
Generation: `Generate ${humanize(name)} with intelligent scaffolding`,
|
||||||
|
Analysis: `Analyze ${humanize(name)} with detailed reporting`,
|
||||||
|
Transformation: `Transform ${humanize(name)} with format conversion`,
|
||||||
|
Orchestration: `Orchestrate ${humanize(name)} workflow with multi-step coordination`
|
||||||
|
};
|
||||||
|
return templates[purpose] || `${humanize(name)} skill for ${purpose.toLowerCase()} tasks`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate trigger phrases
|
||||||
|
function generateTriggerPhrases(name, purpose) {
|
||||||
|
const base = [name, name.replace(/-/g, ' ')];
|
||||||
|
const purposeVariants = {
|
||||||
|
Generation: ['generate', 'create', 'build'],
|
||||||
|
Analysis: ['analyze', 'inspect', 'review'],
|
||||||
|
Transformation: ['transform', 'convert', 'format'],
|
||||||
|
Orchestration: ['orchestrate', 'coordinate', 'manage']
|
||||||
|
};
|
||||||
|
return [...base, ...purposeVariants[purpose].map(v => `${v} ${humanize(name)}`)];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Display to User**:
|
||||||
|
```
|
||||||
|
Requirements Gathered:
|
||||||
|
Name: pdf-generator
|
||||||
|
Purpose: Generation
|
||||||
|
Steps: 3 (Setup → Generate → Validate)
|
||||||
|
Tools: Read, Write, Bash
|
||||||
|
Output: Single file (PDF document)
|
||||||
|
Triggers: "pdf-generator", "generate pdf", "create pdf"
|
||||||
|
|
||||||
|
Style Application:
|
||||||
|
Using flow-based structure (from style analysis)
|
||||||
|
Including pseudocode blocks
|
||||||
|
Adding ASCII diagrams for clarity
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Phase 3: Generate Skill Package
|
||||||
|
|
||||||
|
Create minimal skill structure with style-aware content generation.
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
async function generateSkillPackage(requirements) {
|
||||||
|
const skillDir = `.claude/skills/${requirements.name}`;
|
||||||
|
const workDir = `.workflow/.scratchpad/lite-skill-gen-${Date.now()}`;
|
||||||
|
|
||||||
|
// Step 1: Create directory structure
|
||||||
|
Bash(`mkdir -p "${skillDir}" "${workDir}"`);
|
||||||
|
|
||||||
|
// Step 2: Generate SKILL.md (using learned style)
|
||||||
|
const skillContent = generateSkillMd(requirements);
|
||||||
|
Write(`${skillDir}/SKILL.md`, skillContent);
|
||||||
|
|
||||||
|
// Step 3: Conditionally add bundled resources
|
||||||
|
if (requirements.outputType === 'Directory structure') {
|
||||||
|
Bash(`mkdir -p "${skillDir}/templates"`);
|
||||||
|
const templateContent = generateTemplate(requirements);
|
||||||
|
Write(`${skillDir}/templates/base-template.md`, templateContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requirements.allowedTools.includes('Bash')) {
|
||||||
|
Bash(`mkdir -p "${skillDir}/scripts"`);
|
||||||
|
const scriptContent = generateScript(requirements);
|
||||||
|
Write(`${skillDir}/scripts/helper.sh`, scriptContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4: Generate README
|
||||||
|
const readmeContent = generateReadme(requirements);
|
||||||
|
Write(`${skillDir}/README.md`, readmeContent);
|
||||||
|
|
||||||
|
// Step 5: Validate structure
|
||||||
|
const validation = validateSkillStructure(skillDir, requirements);
|
||||||
|
Write(`${workDir}/validation-report.json`, JSON.stringify(validation, null, 2));
|
||||||
|
|
||||||
|
// Step 6: Return summary
|
||||||
|
return {
|
||||||
|
skillPath: skillDir,
|
||||||
|
filesCreated: [
|
||||||
|
`${skillDir}/SKILL.md`,
|
||||||
|
...(validation.hasTemplates ? [`${skillDir}/templates/`] : []),
|
||||||
|
...(validation.hasScripts ? [`${skillDir}/scripts/`] : []),
|
||||||
|
`${skillDir}/README.md`
|
||||||
|
],
|
||||||
|
validation: validation,
|
||||||
|
nextSteps: generateNextSteps(requirements)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate SKILL.md with style awareness
|
||||||
|
function generateSkillMd(req) {
|
||||||
|
const { styleProfile } = req;
|
||||||
|
|
||||||
|
// YAML frontmatter
|
||||||
|
const frontmatter = `---
|
||||||
|
name: ${req.name}
|
||||||
|
description: ${req.description}
|
||||||
|
allowed-tools: ${req.allowedTools.join(', ')}
|
||||||
|
---
|
||||||
|
`;
|
||||||
|
|
||||||
|
// Main content structure (adapts to style)
|
||||||
|
let content = frontmatter;
|
||||||
|
|
||||||
|
content += `\n# ${humanize(req.name)}\n\n`;
|
||||||
|
content += `${req.description}\n\n`;
|
||||||
|
|
||||||
|
// Add architecture diagram if style uses them
|
||||||
|
if (styleProfile.structure.flowDiagramUsage) {
|
||||||
|
content += generateArchitectureDiagram(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add execution flow
|
||||||
|
content += `## Execution Flow\n\n`;
|
||||||
|
if (styleProfile.language.pseudocodeUsage.usePseudocode) {
|
||||||
|
content += generatePseudocodeFlow(req);
|
||||||
|
} else {
|
||||||
|
content += generateProceduralFlow(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add phase sections
|
||||||
|
for (let i = 0; i < req.steps; i++) {
|
||||||
|
content += generatePhaseSection(i + 1, req, styleProfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add examples if style is verbose
|
||||||
|
if (styleProfile.language.verbosity !== 'concise') {
|
||||||
|
content += generateExamplesSection(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate architecture diagram
|
||||||
|
function generateArchitectureDiagram(req) {
|
||||||
|
return `## Architecture
|
||||||
|
\`\`\`
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ ${humanize(req.name)} │
|
||||||
|
│ │
|
||||||
|
│ Input → Phase 1 → Phase 2 → Phase 3 → Output │
|
||||||
|
│ ${getPhaseName(1, req)} │
|
||||||
|
│ ${getPhaseName(2, req)} │
|
||||||
|
│ ${getPhaseName(3, req)} │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate pseudocode flow
|
||||||
|
function generatePseudocodeFlow(req) {
|
||||||
|
return `\`\`\`javascript
|
||||||
|
async function ${toCamelCase(req.name)}(input) {
|
||||||
|
// Phase 1: ${getPhaseName(1, req)}
|
||||||
|
const prepared = await phase1Prepare(input);
|
||||||
|
|
||||||
|
// Phase 2: ${getPhaseName(2, req)}
|
||||||
|
const processed = await phase2Process(prepared);
|
||||||
|
|
||||||
|
// Phase 3: ${getPhaseName(3, req)}
|
||||||
|
const result = await phase3Finalize(processed);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate phase section
|
||||||
|
function generatePhaseSection(phaseNum, req, styleProfile) {
|
||||||
|
const phaseName = getPhaseName(phaseNum, req);
|
||||||
|
|
||||||
|
let section = `### Phase ${phaseNum}: ${phaseName}\n\n`;
|
||||||
|
|
||||||
|
if (styleProfile.language.pseudocodeUsage.usePseudocode) {
|
||||||
|
section += `\`\`\`javascript\n`;
|
||||||
|
section += `async function phase${phaseNum}${toCamelCase(phaseName)}(input) {\n`;
|
||||||
|
section += ` // TODO: Implement ${phaseName.toLowerCase()} logic\n`;
|
||||||
|
section += ` return output;\n`;
|
||||||
|
section += `}\n\`\`\`\n\n`;
|
||||||
|
} else {
|
||||||
|
section += `**Steps**:\n`;
|
||||||
|
section += `1. Load input data\n`;
|
||||||
|
section += `2. Process according to ${phaseName.toLowerCase()} logic\n`;
|
||||||
|
section += `3. Return result to next phase\n\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return section;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validation
|
||||||
|
function validateSkillStructure(skillDir, req) {
|
||||||
|
const requiredFiles = [`${skillDir}/SKILL.md`, `${skillDir}/README.md`];
|
||||||
|
const exists = requiredFiles.map(f => Bash(`test -f "${f}"`).exitCode === 0);
|
||||||
|
|
||||||
|
return {
|
||||||
|
valid: exists.every(e => e),
|
||||||
|
hasTemplates: Bash(`test -d "${skillDir}/templates"`).exitCode === 0,
|
||||||
|
hasScripts: Bash(`test -d "${skillDir}/scripts"`).exitCode === 0,
|
||||||
|
filesPresent: requiredFiles.filter((f, i) => exists[i]),
|
||||||
|
styleCompliance: checkStyleCompliance(skillDir, req.styleProfile)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Output**:
|
||||||
|
```
|
||||||
|
Skill Package Generated:
|
||||||
|
Location: .claude/skills/pdf-generator/
|
||||||
|
|
||||||
|
Structure:
|
||||||
|
✓ SKILL.md (entry point)
|
||||||
|
✓ README.md (usage guide)
|
||||||
|
✓ templates/ (directory templates)
|
||||||
|
✓ scripts/ (helper scripts)
|
||||||
|
|
||||||
|
Validation:
|
||||||
|
✓ All required files present
|
||||||
|
✓ Style compliance: 95%
|
||||||
|
✓ Frontmatter valid
|
||||||
|
✓ Tool references correct
|
||||||
|
|
||||||
|
Next Steps:
|
||||||
|
1. Review SKILL.md and customize phases
|
||||||
|
2. Test skill: /skill:pdf-generator "test input"
|
||||||
|
3. Iterate based on usage
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Complete Execution Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
User: "Create a PDF generator skill"
|
||||||
|
↓
|
||||||
|
Phase 1: Style Analysis
|
||||||
|
|-- Read reference skills (ccw.md, ccw-coordinator.md)
|
||||||
|
|-- Extract style patterns (flow diagrams, pseudocode, structure)
|
||||||
|
|-- Generate style profile
|
||||||
|
+-- Output: Style recommendations
|
||||||
|
↓
|
||||||
|
Phase 2: Requirements
|
||||||
|
|-- Ask: Name, purpose, steps
|
||||||
|
|-- Ask: Tools, output format
|
||||||
|
|-- Generate: Description, triggers
|
||||||
|
+-- Output: Requirements config
|
||||||
|
↓
|
||||||
|
Phase 3: Generation
|
||||||
|
|-- Create: Directory structure
|
||||||
|
|-- Write: SKILL.md (style-aware)
|
||||||
|
|-- Write: README.md
|
||||||
|
|-- Optionally: templates/, scripts/
|
||||||
|
|-- Validate: Structure and style
|
||||||
|
+-- Output: Skill package
|
||||||
|
↓
|
||||||
|
Return: Skill location + next steps
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase Execution Protocol
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
// Main entry point
|
||||||
|
async function liteSkillGenerator(input) {
|
||||||
|
// Phase 1: Style Learning
|
||||||
|
const references = [
|
||||||
|
'.claude/commands/ccw.md',
|
||||||
|
'.claude/commands/ccw-coordinator.md',
|
||||||
|
...discoverReferenceSkills(input)
|
||||||
|
];
|
||||||
|
const styleProfile = await analyzeStyle(references);
|
||||||
|
console.log(`Style Analysis: ${styleProfile.organization.phaseStructure}, ${styleProfile.language.verbosity}`);
|
||||||
|
|
||||||
|
// Phase 2: Requirements
|
||||||
|
const requirements = await gatherRequirements(styleProfile);
|
||||||
|
console.log(`Requirements: ${requirements.name} (${requirements.steps} phases)`);
|
||||||
|
|
||||||
|
// Phase 3: Generation
|
||||||
|
const result = await generateSkillPackage(requirements);
|
||||||
|
console.log(`✅ Generated: ${result.skillPath}`);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output Structure
|
||||||
|
|
||||||
|
**Minimal Package** (default):
|
||||||
|
```
|
||||||
|
.claude/skills/{skill-name}/
|
||||||
|
├── SKILL.md # Entry point with frontmatter
|
||||||
|
└── README.md # Usage guide
|
||||||
|
```
|
||||||
|
|
||||||
|
**With Templates** (if needed):
|
||||||
|
```
|
||||||
|
.claude/skills/{skill-name}/
|
||||||
|
├── SKILL.md
|
||||||
|
├── README.md
|
||||||
|
└── templates/
|
||||||
|
└── base-template.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**With Scripts** (if using Bash):
|
||||||
|
```
|
||||||
|
.claude/skills/{skill-name}/
|
||||||
|
├── SKILL.md
|
||||||
|
├── README.md
|
||||||
|
└── scripts/
|
||||||
|
└── helper.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Design Principles
|
||||||
|
|
||||||
|
1. **Style Learning** - Analyze reference skills to maintain consistency
|
||||||
|
2. **Minimal Overhead** - Generate only essential files (SKILL.md + README)
|
||||||
|
3. **Progressive Disclosure** - Follow anthropics' three-layer loading
|
||||||
|
4. **Flow-Based** - Use pseudocode and flow diagrams (when style appropriate)
|
||||||
|
5. **Interactive** - Guided requirements gathering via AskUserQuestion
|
||||||
|
6. **Fast Generation** - 3 phases instead of 6, focused on simplicity
|
||||||
|
7. **Style Awareness** - Adapt output based on detected patterns
|
||||||
|
|
||||||
|
## Style Pattern Detection
|
||||||
|
|
||||||
|
**Structural Patterns**:
|
||||||
|
- YAML frontmatter usage (100% in references)
|
||||||
|
- Section headers (H2 for major, H3 for sub-sections)
|
||||||
|
- Code blocks (JavaScript pseudocode, Bash examples)
|
||||||
|
- ASCII diagrams (architecture, flow charts)
|
||||||
|
|
||||||
|
**Language Patterns**:
|
||||||
|
- Instruction style: Procedural with function definitions
|
||||||
|
- Pseudocode: JavaScript-based with flow annotations
|
||||||
|
- Verbosity: Detailed but focused
|
||||||
|
- Terminology: Phase, workflow, pipeline, orchestrator
|
||||||
|
|
||||||
|
**Organization Patterns**:
|
||||||
|
- Phase structure: 3-5 sequential phases
|
||||||
|
- Example density: Moderate (1-2 per major section)
|
||||||
|
- Template usage: Minimal (only when necessary)
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
**Basic Generation**:
|
||||||
|
```
|
||||||
|
User: "Create a markdown formatter skill"
|
||||||
|
Lite-Skill-Generator:
|
||||||
|
→ Analyzes ccw.md style
|
||||||
|
→ Asks: Name? "markdown-formatter"
|
||||||
|
→ Asks: Purpose? "Transformation"
|
||||||
|
→ Asks: Steps? "3 steps"
|
||||||
|
→ Generates: .claude/skills/markdown-formatter/
|
||||||
|
```
|
||||||
|
|
||||||
|
**With Custom References**:
|
||||||
|
```
|
||||||
|
User: "Create a skill like software-manual but simpler"
|
||||||
|
Lite-Skill-Generator:
|
||||||
|
→ Analyzes software-manual skill
|
||||||
|
→ Learns: Multi-phase, agent-based, template-heavy
|
||||||
|
→ Simplifies: 3 phases, direct execution, minimal templates
|
||||||
|
→ Generates: Simplified version
|
||||||
|
```
|
||||||
|
|
||||||
|
## Comparison: lite-skill-generator vs skill-generator
|
||||||
|
|
||||||
|
| Aspect | lite-skill-generator | skill-generator |
|
||||||
|
|--------|---------------------|-----------------|
|
||||||
|
| **Phases** | 3 (Style → Req → Gen) | 6 (Spec → Req → Dir → Gen → Specs → Val) |
|
||||||
|
| **Style Learning** | Yes (analyze references) | No (fixed templates) |
|
||||||
|
| **Complexity** | Simple skills only | Full-featured skills |
|
||||||
|
| **Output** | Minimal (SKILL.md + README) | Complete (phases/, specs/, templates/) |
|
||||||
|
| **Generation Time** | Fast (~2 min) | Thorough (~10 min) |
|
||||||
|
| **Use Case** | Quick scaffolding | Production-ready skills |
|
||||||
|
|
||||||
|
## Workflow Integration
|
||||||
|
|
||||||
|
**Standalone**:
|
||||||
|
```bash
|
||||||
|
/skill:lite-skill-generator "Create a log analyzer skill"
|
||||||
|
```
|
||||||
|
|
||||||
|
**With References**:
|
||||||
|
```bash
|
||||||
|
/skill:lite-skill-generator "Create a skill based on ccw-coordinator.md style"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Batch Generation** (for multiple simple skills):
|
||||||
|
```bash
|
||||||
|
/skill:lite-skill-generator "Create 3 skills: json-validator, yaml-parser, toml-converter"
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Next Steps After Generation**:
|
||||||
|
1. Review `.claude/skills/{name}/SKILL.md`
|
||||||
|
2. Customize phase logic for your use case
|
||||||
|
3. Add examples to README.md
|
||||||
|
4. Test skill with sample input
|
||||||
|
5. Iterate based on real usage
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
---
|
||||||
|
name: {{SKILL_NAME}}
|
||||||
|
description: {{SKILL_DESCRIPTION}}
|
||||||
|
allowed-tools: {{ALLOWED_TOOLS}}
|
||||||
|
---
|
||||||
|
|
||||||
|
# {{SKILL_TITLE}}
|
||||||
|
|
||||||
|
{{SKILL_DESCRIPTION}}
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────┐
|
||||||
|
│ {{SKILL_TITLE}} │
|
||||||
|
│ │
|
||||||
|
│ Input → {{PHASE_1}} → {{PHASE_2}} → Output │
|
||||||
|
└─────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Execution Flow
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
async function {{SKILL_FUNCTION}}(input) {
|
||||||
|
// Phase 1: {{PHASE_1}}
|
||||||
|
const prepared = await phase1(input);
|
||||||
|
|
||||||
|
// Phase 2: {{PHASE_2}}
|
||||||
|
const result = await phase2(prepared);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 1: {{PHASE_1}}
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
async function phase1(input) {
|
||||||
|
// TODO: Implement {{PHASE_1_LOWER}} logic
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Phase 2: {{PHASE_2}}
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
async function phase2(input) {
|
||||||
|
// TODO: Implement {{PHASE_2_LOWER}} logic
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
/skill:{{SKILL_NAME}} "input description"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
**Basic Usage**:
|
||||||
|
```
|
||||||
|
User: "{{EXAMPLE_INPUT}}"
|
||||||
|
{{SKILL_NAME}}:
|
||||||
|
→ Phase 1: {{PHASE_1_ACTION}}
|
||||||
|
→ Phase 2: {{PHASE_2_ACTION}}
|
||||||
|
→ Output: {{EXAMPLE_OUTPUT}}
|
||||||
|
```
|
||||||
64
.claude/skills/lite-skill-generator/templates/style-guide.md
Normal file
64
.claude/skills/lite-skill-generator/templates/style-guide.md
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
# Style Guide Template
|
||||||
|
|
||||||
|
Generated by lite-skill-generator style analysis phase.
|
||||||
|
|
||||||
|
## Detected Patterns
|
||||||
|
|
||||||
|
### Structural Patterns
|
||||||
|
|
||||||
|
| Pattern | Detected | Recommendation |
|
||||||
|
|---------|----------|----------------|
|
||||||
|
| YAML Frontmatter | {{HAS_FRONTMATTER}} | {{FRONTMATTER_REC}} |
|
||||||
|
| ASCII Diagrams | {{HAS_DIAGRAMS}} | {{DIAGRAMS_REC}} |
|
||||||
|
| Code Blocks | {{HAS_CODE_BLOCKS}} | {{CODE_BLOCKS_REC}} |
|
||||||
|
| Phase Structure | {{PHASE_STRUCTURE}} | {{PHASE_REC}} |
|
||||||
|
|
||||||
|
### Language Patterns
|
||||||
|
|
||||||
|
| Pattern | Value | Notes |
|
||||||
|
|---------|-------|-------|
|
||||||
|
| Instruction Style | {{INSTRUCTION_STYLE}} | imperative/declarative/procedural |
|
||||||
|
| Pseudocode Usage | {{PSEUDOCODE_USAGE}} | functional/imperative/none |
|
||||||
|
| Verbosity Level | {{VERBOSITY}} | concise/detailed/verbose |
|
||||||
|
| Common Terms | {{TERMINOLOGY}} | domain-specific vocabulary |
|
||||||
|
|
||||||
|
### Organization Patterns
|
||||||
|
|
||||||
|
| Pattern | Value |
|
||||||
|
|---------|-------|
|
||||||
|
| Phase Count | {{PHASE_COUNT}} |
|
||||||
|
| Example Density | {{EXAMPLE_DENSITY}} |
|
||||||
|
| Template Usage | {{TEMPLATE_USAGE}} |
|
||||||
|
|
||||||
|
## Style Compliance Checklist
|
||||||
|
|
||||||
|
- [ ] YAML frontmatter with name, description, allowed-tools
|
||||||
|
- [ ] Architecture diagram (if pattern detected)
|
||||||
|
- [ ] Execution flow section with pseudocode
|
||||||
|
- [ ] Phase sections (sequential numbered)
|
||||||
|
- [ ] Usage examples section
|
||||||
|
- [ ] README.md for external documentation
|
||||||
|
|
||||||
|
## Reference Skills Analyzed
|
||||||
|
|
||||||
|
{{#REFERENCES}}
|
||||||
|
- `{{REF_PATH}}`: {{REF_NOTES}}
|
||||||
|
{{/REFERENCES}}
|
||||||
|
|
||||||
|
## Generated Configuration
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"style": {
|
||||||
|
"structure": "{{STRUCTURE_TYPE}}",
|
||||||
|
"language": "{{LANGUAGE_TYPE}}",
|
||||||
|
"organization": "{{ORG_TYPE}}"
|
||||||
|
},
|
||||||
|
"recommendations": {
|
||||||
|
"usePseudocode": {{USE_PSEUDOCODE}},
|
||||||
|
"includeDiagrams": {{INCLUDE_DIAGRAMS}},
|
||||||
|
"verbosityLevel": "{{VERBOSITY}}",
|
||||||
|
"phaseCount": {{PHASE_COUNT}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -113,9 +113,9 @@ export async function csrfValidation(ctx: CsrfMiddlewareContext): Promise<boolea
|
|||||||
const { pathname, req, res } = ctx;
|
const { pathname, req, res } = ctx;
|
||||||
|
|
||||||
if (!pathname.startsWith('/api/')) return true;
|
if (!pathname.startsWith('/api/')) return true;
|
||||||
// CSRF is disabled by default for local deployment scenarios.
|
// CSRF is enabled by default for security.
|
||||||
// Set CCW_ENABLE_CSRF=1 to enable CSRF protection.
|
// Set CCW_DISABLE_CSRF=1 to disable CSRF protection for local development.
|
||||||
if (!envFlagEnabled('CCW_ENABLE_CSRF')) return true;
|
if (envFlagEnabled('CCW_DISABLE_CSRF')) return true;
|
||||||
|
|
||||||
const method = (req.method || 'GET').toUpperCase();
|
const method = (req.method || 'GET').toUpperCase();
|
||||||
if (!['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) return true;
|
if (!['POST', 'PUT', 'PATCH', 'DELETE'].includes(method)) return true;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import type { Server } from 'http';
|
|||||||
import { readFileSync, existsSync, promises as fsPromises } from 'fs';
|
import { readFileSync, existsSync, promises as fsPromises } from 'fs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { resolvePath, getRecentPaths, trackRecentPath, removeRecentPath, normalizePathForDisplay } from '../../utils/path-resolver.js';
|
import { resolvePath, getRecentPaths, trackRecentPath, removeRecentPath, normalizePathForDisplay } from '../../utils/path-resolver.js';
|
||||||
|
import { validatePath as validateAllowedPath } from '../../utils/path-validator.js';
|
||||||
import { scanSessions } from '../session-scanner.js';
|
import { scanSessions } from '../session-scanner.js';
|
||||||
import { aggregateData } from '../data-aggregator.js';
|
import { aggregateData } from '../data-aggregator.js';
|
||||||
import {
|
import {
|
||||||
@@ -286,7 +287,12 @@ export async function handleSystemRoutes(ctx: SystemRouteContext): Promise<boole
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const content = await fsPromises.readFile(filePath, 'utf-8');
|
// Validate path is within allowed directories (fix: sec-001-a1b2c3d4)
|
||||||
|
const validatedPath = await validateAllowedPath(filePath, {
|
||||||
|
mustExist: true,
|
||||||
|
allowedDirectories: [process.cwd(), resolvePath('.ccw', 'sessions')]
|
||||||
|
});
|
||||||
|
const content = await fsPromises.readFile(validatedPath, 'utf-8');
|
||||||
const json = JSON.parse(content);
|
const json = JSON.parse(content);
|
||||||
res.writeHead(200, { 'Content-Type': 'application/json' });
|
res.writeHead(200, { 'Content-Type': 'application/json' });
|
||||||
res.end(JSON.stringify(json));
|
res.end(JSON.stringify(json));
|
||||||
@@ -442,6 +448,15 @@ export async function handleSystemRoutes(ctx: SystemRouteContext): Promise<boole
|
|||||||
targetPath = path.resolve(targetPath);
|
targetPath = path.resolve(targetPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate path is within allowed directories (fix: sec-003-c3d4e5f6)
|
||||||
|
const initialPath = process.cwd();
|
||||||
|
if (browsePath) {
|
||||||
|
targetPath = await validateAllowedPath(targetPath, {
|
||||||
|
mustExist: true,
|
||||||
|
allowedDirectories: [initialPath, os.homedir()]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const stat = await fs.promises.stat(targetPath);
|
const stat = await fs.promises.stat(targetPath);
|
||||||
if (!stat.isDirectory()) {
|
if (!stat.isDirectory()) {
|
||||||
@@ -502,6 +517,13 @@ export async function handleSystemRoutes(ctx: SystemRouteContext): Promise<boole
|
|||||||
targetPath = path.resolve(targetPath);
|
targetPath = path.resolve(targetPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validate path is within allowed directories (fix: sec-003-c3d4e5f6)
|
||||||
|
const initialPath = process.cwd();
|
||||||
|
targetPath = await validateAllowedPath(targetPath, {
|
||||||
|
mustExist: true,
|
||||||
|
allowedDirectories: [initialPath, os.homedir()]
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await fs.promises.access(targetPath, fs.constants.R_OK);
|
await fs.promises.access(targetPath, fs.constants.R_OK);
|
||||||
const stat = await fs.promises.stat(targetPath);
|
const stat = await fs.promises.stat(targetPath);
|
||||||
|
|||||||
Reference in New Issue
Block a user