Skip to content

Commit 9a70db0

Browse files
ci(release): publish latest release
1 parent f535511 commit 9a70db0

File tree

625 files changed

+48691
-23179
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

625 files changed

+48691
-23179
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/bin/bash
2+
# Copied from https://github.com/diet103/claude-code-infrastructure-showcase/blob/c586f9d8854989abbe9040cde61527888ded3904/.claude/hooks/skill-activation-prompt.sh
3+
set -e
4+
5+
cd "$CLAUDE_PROJECT_DIR/.claude/hooks"
6+
cat | bun run skill-activation-prompt.ts
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#!/usr/bin/env node
2+
/** biome-ignore-all lint/suspicious/noConsole: script output */
3+
// Copied from https://github.com/diet103/claude-code-infrastructure-showcase/blob/c586f9d8854989abbe9040cde61527888ded3904/.claude/hooks/skill-activation-prompt.ts
4+
import { readFileSync } from 'fs'
5+
import { join } from 'path'
6+
7+
interface HookInput {
8+
session_id: string
9+
transcript_path: string
10+
cwd: string
11+
permission_mode: string
12+
prompt: string
13+
}
14+
15+
interface PromptTriggers {
16+
keywords?: string[]
17+
intentPatterns?: string[]
18+
}
19+
20+
interface SkillRule {
21+
type: 'guardrail' | 'domain'
22+
enforcement: 'block' | 'suggest' | 'warn'
23+
priority: 'critical' | 'high' | 'medium' | 'low'
24+
promptTriggers?: PromptTriggers
25+
}
26+
27+
interface SkillRules {
28+
version: string
29+
skills: Record<string, SkillRule>
30+
}
31+
32+
interface MatchedSkill {
33+
name: string
34+
matchType: 'keyword' | 'intent'
35+
config: SkillRule
36+
}
37+
38+
async function main() {
39+
try {
40+
// Read input from stdin
41+
const input = readFileSync(0, 'utf-8')
42+
const data: HookInput = JSON.parse(input)
43+
const prompt = data.prompt.toLowerCase()
44+
45+
// Load skill rules
46+
const projectDir = process.env.CLAUDE_PROJECT_DIR || '$HOME/project'
47+
const rulesPath = join(projectDir, '.claude', 'skills', 'skill-rules.json')
48+
const rules: SkillRules = JSON.parse(readFileSync(rulesPath, 'utf-8'))
49+
50+
const matchedSkills: MatchedSkill[] = []
51+
52+
// Check each skill for matches
53+
for (const [skillName, config] of Object.entries(rules.skills)) {
54+
const triggers = config.promptTriggers
55+
if (!triggers) {
56+
continue
57+
}
58+
59+
// Keyword matching
60+
if (triggers.keywords) {
61+
const keywordMatch = triggers.keywords.some((kw) => prompt.includes(kw.toLowerCase()))
62+
if (keywordMatch) {
63+
matchedSkills.push({ name: skillName, matchType: 'keyword', config })
64+
continue
65+
}
66+
}
67+
68+
// Intent pattern matching
69+
if (triggers.intentPatterns) {
70+
const intentMatch = triggers.intentPatterns.some((pattern) => {
71+
const regex = new RegExp(pattern, 'i')
72+
return regex.test(prompt)
73+
})
74+
if (intentMatch) {
75+
matchedSkills.push({ name: skillName, matchType: 'intent', config })
76+
}
77+
}
78+
}
79+
80+
// Generate output if matches found
81+
if (matchedSkills.length > 0) {
82+
let output = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'
83+
output += '🎯 SKILL ACTIVATION CHECK\n'
84+
output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n'
85+
86+
// Group by priority
87+
const critical = matchedSkills.filter((s) => s.config.priority === 'critical')
88+
const high = matchedSkills.filter((s) => s.config.priority === 'high')
89+
const medium = matchedSkills.filter((s) => s.config.priority === 'medium')
90+
const low = matchedSkills.filter((s) => s.config.priority === 'low')
91+
92+
if (critical.length > 0) {
93+
output += '⚠️ CRITICAL SKILLS (REQUIRED):\n'
94+
critical.forEach((s) => (output += ` → ${s.name}\n`))
95+
output += '\n'
96+
}
97+
98+
if (high.length > 0) {
99+
output += '📚 RECOMMENDED SKILLS:\n'
100+
high.forEach((s) => (output += ` → ${s.name}\n`))
101+
output += '\n'
102+
}
103+
104+
if (medium.length > 0) {
105+
output += '💡 SUGGESTED SKILLS:\n'
106+
medium.forEach((s) => (output += ` → ${s.name}\n`))
107+
output += '\n'
108+
}
109+
110+
if (low.length > 0) {
111+
output += '📌 OPTIONAL SKILLS:\n'
112+
low.forEach((s) => (output += ` → ${s.name}\n`))
113+
output += '\n'
114+
}
115+
116+
output += 'ACTION: Use Skill tool BEFORE responding\n'
117+
output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'
118+
119+
console.log(output)
120+
}
121+
122+
process.exit(0)
123+
} catch (err) {
124+
console.error('Error in skill-activation-prompt hook:', err)
125+
process.exit(1)
126+
}
127+
}
128+
129+
main().catch((err) => {
130+
console.error('Uncaught error:', err)
131+
process.exit(1)
132+
})

.claude/settings.json

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,32 @@
11
{
2-
"permissions": {
3-
"deny": [
4-
"Read(**/.env)",
5-
"Edit(**/.env)",
6-
"Read(~/.aws/**)",
7-
"Edit(~/.aws/**)",
8-
"Read(~/.ssh/**)",
9-
"Edit(~/.ssh/**)",
10-
"Read(~/.gnupg/**)",
11-
"Edit(~/.gnupg/**)",
12-
"Read(~/.git-credentials)",
13-
"Edit(~/.git-credentials)",
14-
"Read($HOME/Library/Keychains/**)",
15-
"Edit($HOME/Library/Keychains/**)",
16-
"Read(/private/etc/**)",
17-
"Edit(/private/etc/**)"
18-
]
19-
}
2+
"permissions": {
3+
"deny": [
4+
"Read(**/.env)",
5+
"Edit(**/.env)",
6+
"Read(~/.aws/**)",
7+
"Edit(~/.aws/**)",
8+
"Read(~/.ssh/**)",
9+
"Edit(~/.ssh/**)",
10+
"Read(~/.gnupg/**)",
11+
"Edit(~/.gnupg/**)",
12+
"Read(~/.git-credentials)",
13+
"Edit(~/.git-credentials)",
14+
"Read($HOME/Library/Keychains/**)",
15+
"Edit($HOME/Library/Keychains/**)",
16+
"Read(/private/etc/**)",
17+
"Edit(/private/etc/**)"
18+
]
19+
},
20+
"hooks": {
21+
"UserPromptSubmit": [
22+
{
23+
"hooks": [
24+
{
25+
"type": "command",
26+
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/skill-activation-prompt.sh"
27+
}
28+
]
29+
}
30+
]
2031
}
32+
}

.claude/skills/skill-rules.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"version": "1.0",
3+
"description": "Skill activation triggers for Claude Code. Controls when skills automatically suggest or block actions.",
4+
"skills": {
5+
"web-e2e": {
6+
"type": "domain",
7+
"enforcement": "block",
8+
"priority": "critical",
9+
"description": "Run, debug, and create Playwright e2e tests for the web app.",
10+
"promptTriggers": {
11+
"keywords": ["e2e", "end-to-end", "playwright"],
12+
"intentPatterns": ["(run|start|debug|create|explain).*?e2e"]
13+
}
14+
}
15+
},
16+
"notes": {
17+
"enforcement_types": {
18+
"suggest": "Skill suggestion appears but doesn't block execution",
19+
"block": "Requires skill to be used before proceeding (guardrail)",
20+
"warn": "Shows warning but allows proceeding"
21+
},
22+
"priority_levels": {
23+
"critical": "Highest - Always trigger when matched",
24+
"high": "Important - Trigger for most matches",
25+
"medium": "Moderate - Trigger for clear matches",
26+
"low": "Optional - Trigger only for explicit matches"
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)