Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
23a7ec1
ci(release): publish latest release
hello-happy-puppy Oct 28, 2025
60b7d92
ci(release): publish latest release
hello-happy-puppy Oct 30, 2025
269e0a8
ci(release): publish latest release
hello-happy-puppy Nov 5, 2025
deaefb5
ci(release): publish latest release
hello-happy-puppy Nov 13, 2025
0ef926c
ci(release): publish latest release
hello-happy-puppy Nov 13, 2025
173a940
ci(release): publish latest release
hello-happy-puppy Nov 15, 2025
f535511
ci(release): publish latest release
hello-happy-puppy Nov 17, 2025
9a70db0
ci(release): publish latest release
hello-happy-puppy Nov 19, 2025
0f117d8
ci(release): publish latest release
hello-happy-puppy Nov 20, 2025
b9b5ab9
ci(release): publish latest release
hello-happy-puppy Nov 21, 2025
0c31bed
ci(release): publish latest release
hello-happy-puppy Nov 21, 2025
58089c1
ci(release): publish latest release
hello-happy-puppy Nov 24, 2025
4125476
ci(release): publish latest release
hello-happy-puppy Nov 24, 2025
d359d65
ci(release): publish latest release
hello-happy-puppy Nov 24, 2025
9e2bcfb
ci(release): publish latest release
hello-happy-puppy Nov 26, 2025
9f6becd
ci(release): publish latest release
hello-happy-puppy Dec 1, 2025
bfb9c9a
ci(release): publish latest release
hello-happy-puppy Dec 2, 2025
52fff30
ci(release): publish latest release
hello-happy-puppy Dec 2, 2025
721ddf2
ci(release): publish latest release
hello-happy-puppy Dec 2, 2025
ee96537
ci(release): publish latest release
hello-happy-puppy Dec 2, 2025
2dd993d
ci(release): publish latest release
hello-happy-puppy Dec 2, 2025
39d285e
ci(release): publish latest release
hello-happy-puppy Dec 2, 2025
73d2409
ci(release): publish latest release
hello-happy-puppy Dec 3, 2025
7887825
ci(release): publish latest release
hello-happy-puppy Dec 3, 2025
4994670
ci(release): publish latest release
hello-happy-puppy Dec 4, 2025
25bd42d
ci(release): publish latest release
hello-happy-puppy Dec 5, 2025
340b8bf
ci(release): publish latest release
hello-happy-puppy Dec 5, 2025
67f9a00
ci(release): publish latest release
hello-happy-puppy Dec 10, 2025
9f1cb1b
ci(release): publish latest release
hello-happy-puppy Dec 11, 2025
27cf6fd
ci(release): publish latest release
hello-happy-puppy Dec 12, 2025
111b532
ci(release): publish latest release
hello-happy-puppy Dec 12, 2025
5bdad5b
ci(release): publish latest release
hello-happy-puppy Dec 18, 2025
55c403a
ci(release): publish latest release
hello-happy-puppy Dec 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .bun-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.2.21
1.3.1
6 changes: 6 additions & 0 deletions .claude/hooks/skill-activation-prompt.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/bin/bash
# Copied from https://github.com/diet103/claude-code-infrastructure-showcase/blob/c586f9d8854989abbe9040cde61527888ded3904/.claude/hooks/skill-activation-prompt.sh
set -e

cd "$CLAUDE_PROJECT_DIR/.claude/hooks"
cat | bun run skill-activation-prompt.ts
132 changes: 132 additions & 0 deletions .claude/hooks/skill-activation-prompt.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
#!/usr/bin/env node
/** biome-ignore-all lint/suspicious/noConsole: script output */
// Copied from https://github.com/diet103/claude-code-infrastructure-showcase/blob/c586f9d8854989abbe9040cde61527888ded3904/.claude/hooks/skill-activation-prompt.ts
import { readFileSync } from 'fs'
import { join } from 'path'

interface HookInput {
session_id: string
transcript_path: string
cwd: string
permission_mode: string
prompt: string
}

interface PromptTriggers {
keywords?: string[]
intentPatterns?: string[]
}

interface SkillRule {
type: 'guardrail' | 'domain'
enforcement: 'block' | 'suggest' | 'warn'
priority: 'critical' | 'high' | 'medium' | 'low'
promptTriggers?: PromptTriggers
}

interface SkillRules {
version: string
skills: Record<string, SkillRule>
}

interface MatchedSkill {
name: string
matchType: 'keyword' | 'intent'
config: SkillRule
}

async function main() {
try {
// Read input from stdin
const input = readFileSync(0, 'utf-8')
const data: HookInput = JSON.parse(input)
const prompt = data.prompt.toLowerCase()

// Load skill rules
const projectDir = process.env.CLAUDE_PROJECT_DIR || '$HOME/project'
const rulesPath = join(projectDir, '.claude', 'skills', 'skill-rules.json')
const rules: SkillRules = JSON.parse(readFileSync(rulesPath, 'utf-8'))

const matchedSkills: MatchedSkill[] = []

// Check each skill for matches
for (const [skillName, config] of Object.entries(rules.skills)) {
const triggers = config.promptTriggers
if (!triggers) {
continue
}

// Keyword matching
if (triggers.keywords) {
const keywordMatch = triggers.keywords.some((kw) => prompt.includes(kw.toLowerCase()))
if (keywordMatch) {
matchedSkills.push({ name: skillName, matchType: 'keyword', config })
continue
}
}

// Intent pattern matching
if (triggers.intentPatterns) {
const intentMatch = triggers.intentPatterns.some((pattern) => {
const regex = new RegExp(pattern, 'i')
return regex.test(prompt)
})
if (intentMatch) {
matchedSkills.push({ name: skillName, matchType: 'intent', config })
}
}
}

// Generate output if matches found
if (matchedSkills.length > 0) {
let output = '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'
output += '🎯 SKILL ACTIVATION CHECK\n'
output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n\n'

// Group by priority
const critical = matchedSkills.filter((s) => s.config.priority === 'critical')
const high = matchedSkills.filter((s) => s.config.priority === 'high')
const medium = matchedSkills.filter((s) => s.config.priority === 'medium')
const low = matchedSkills.filter((s) => s.config.priority === 'low')

if (critical.length > 0) {
output += '⚠️ CRITICAL SKILLS (REQUIRED):\n'
critical.forEach((s) => (output += ` → ${s.name}\n`))
output += '\n'
}

if (high.length > 0) {
output += '📚 RECOMMENDED SKILLS:\n'
high.forEach((s) => (output += ` → ${s.name}\n`))
output += '\n'
}

if (medium.length > 0) {
output += '💡 SUGGESTED SKILLS:\n'
medium.forEach((s) => (output += ` → ${s.name}\n`))
output += '\n'
}

if (low.length > 0) {
output += '📌 OPTIONAL SKILLS:\n'
low.forEach((s) => (output += ` → ${s.name}\n`))
output += '\n'
}

output += 'ACTION: Use Skill tool BEFORE responding\n'
output += '━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'

console.log(output)
}

process.exit(0)
} catch (err) {
console.error('Error in skill-activation-prompt hook:', err)
process.exit(1)
}
}

main().catch((err) => {
console.error('Uncaught error:', err)
process.exit(1)
})
32 changes: 32 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"permissions": {
"deny": [
"Read(**/.env)",
"Edit(**/.env)",
"Read(~/.aws/**)",
"Edit(~/.aws/**)",
"Read(~/.ssh/**)",
"Edit(~/.ssh/**)",
"Read(~/.gnupg/**)",
"Edit(~/.gnupg/**)",
"Read(~/.git-credentials)",
"Edit(~/.git-credentials)",
"Read($HOME/Library/Keychains/**)",
"Edit($HOME/Library/Keychains/**)",
"Read(/private/etc/**)",
"Edit(/private/etc/**)"
]
},
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"type": "command",
"command": "$CLAUDE_PROJECT_DIR/.claude/hooks/skill-activation-prompt.sh"
}
]
}
]
}
}
29 changes: 29 additions & 0 deletions .claude/skills/skill-rules.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"version": "1.0",
"description": "Skill activation triggers for Claude Code. Controls when skills automatically suggest or block actions.",
"skills": {
"web-e2e": {
"type": "domain",
"enforcement": "block",
"priority": "critical",
"description": "Run, debug, and create Playwright e2e tests for the web app.",
"promptTriggers": {
"keywords": ["e2e", "end-to-end", "playwright"],
"intentPatterns": ["(run|start|debug|create|explain).*?e2e"]
}
}
},
"notes": {
"enforcement_types": {
"suggest": "Skill suggestion appears but doesn't block execution",
"block": "Requires skill to be used before proceeding (guardrail)",
"warn": "Shows warning but allows proceeding"
},
"priority_levels": {
"critical": "Highest - Always trigger when matched",
"high": "Important - Trigger for most matches",
"medium": "Moderate - Trigger for clear matches",
"low": "Optional - Trigger only for explicit matches"
}
}
}
Loading