@kennethsolomon/shipkit 3.10.2 → 3.11.1
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/README.md +92 -4
- package/commands/sk/context-budget.md +5 -0
- package/commands/sk/eval.md +5 -0
- package/commands/sk/health.md +5 -0
- package/commands/sk/help.md +32 -8
- package/commands/sk/learn.md +5 -0
- package/commands/sk/resume-session.md +5 -0
- package/commands/sk/safety-guard.md +5 -0
- package/commands/sk/save-session.md +5 -0
- package/commands/sk/set-profile.md +8 -0
- package/package.json +1 -1
- package/skills/sk:brainstorming/SKILL.md +13 -0
- package/skills/sk:context-budget/SKILL.md +126 -0
- package/skills/sk:eval/SKILL.md +188 -0
- package/skills/sk:health/SKILL.md +146 -0
- package/skills/sk:learn/SKILL.md +138 -0
- package/skills/sk:resume-session/SKILL.md +95 -0
- package/skills/sk:safety-guard/SKILL.md +134 -0
- package/skills/sk:save-session/SKILL.md +84 -0
- package/skills/sk:setup-claude/SKILL.md +39 -2
- package/skills/sk:setup-claude/templates/.claude/settings.json.template +110 -26
- package/skills/sk:setup-claude/templates/CLAUDE.md.template +8 -1
- package/skills/sk:setup-claude/templates/hooks/config-protection.sh +71 -0
- package/skills/sk:setup-claude/templates/hooks/console-log-warning.sh +42 -0
- package/skills/sk:setup-claude/templates/hooks/cost-tracker.sh +26 -0
- package/skills/sk:setup-claude/templates/hooks/post-edit-format.sh +53 -0
- package/skills/sk:setup-claude/templates/hooks/safety-guard.sh +72 -0
- package/skills/sk:setup-claude/templates/hooks/suggest-compact.sh +35 -0
- package/skills/sk:setup-optimizer/SKILL.md +59 -8
- package/skills/sk:start/SKILL.md +25 -0
|
@@ -26,50 +26,134 @@
|
|
|
26
26
|
"hooks": {
|
|
27
27
|
"SessionStart": [
|
|
28
28
|
{
|
|
29
|
-
"
|
|
30
|
-
"
|
|
31
|
-
|
|
29
|
+
"matcher": "",
|
|
30
|
+
"hooks": [
|
|
31
|
+
{
|
|
32
|
+
"type": "command",
|
|
33
|
+
"command": "bash .claude/hooks/session-start.sh",
|
|
34
|
+
"timeout": 10000
|
|
35
|
+
}
|
|
36
|
+
]
|
|
32
37
|
}
|
|
33
38
|
],
|
|
34
39
|
"PreCompact": [
|
|
35
40
|
{
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
|
|
41
|
+
"matcher": "",
|
|
42
|
+
"hooks": [
|
|
43
|
+
{
|
|
44
|
+
"type": "command",
|
|
45
|
+
"command": "bash .claude/hooks/pre-compact.sh",
|
|
46
|
+
"timeout": 10000
|
|
47
|
+
}
|
|
48
|
+
]
|
|
39
49
|
}
|
|
40
50
|
],
|
|
41
51
|
"PreToolUse": [
|
|
42
52
|
{
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
53
|
+
"matcher": "Bash",
|
|
54
|
+
"hooks": [
|
|
55
|
+
{
|
|
56
|
+
"type": "command",
|
|
57
|
+
"command": "bash .claude/hooks/validate-commit.sh",
|
|
58
|
+
"timeout": 10000
|
|
59
|
+
}
|
|
60
|
+
]
|
|
50
61
|
},
|
|
51
62
|
{
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
63
|
+
"matcher": "Bash",
|
|
64
|
+
"hooks": [
|
|
65
|
+
{
|
|
66
|
+
"type": "command",
|
|
67
|
+
"command": "bash .claude/hooks/validate-push.sh",
|
|
68
|
+
"timeout": 5000
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"matcher": "Edit|Write",
|
|
74
|
+
"hooks": [
|
|
75
|
+
{
|
|
76
|
+
"type": "command",
|
|
77
|
+
"command": "bash .claude/hooks/config-protection.sh",
|
|
78
|
+
"timeout": 5000
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"matcher": "Edit|Write",
|
|
84
|
+
"hooks": [
|
|
85
|
+
{
|
|
86
|
+
"type": "command",
|
|
87
|
+
"command": "bash .claude/hooks/suggest-compact.sh",
|
|
88
|
+
"timeout": 3000
|
|
89
|
+
}
|
|
90
|
+
]
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"matcher": "Bash|Edit|Write",
|
|
94
|
+
"hooks": [
|
|
95
|
+
{
|
|
96
|
+
"type": "command",
|
|
97
|
+
"command": "bash .claude/hooks/safety-guard.sh",
|
|
98
|
+
"timeout": 5000
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
],
|
|
103
|
+
"PostToolUse": [
|
|
104
|
+
{
|
|
105
|
+
"matcher": "Edit",
|
|
106
|
+
"hooks": [
|
|
107
|
+
{
|
|
108
|
+
"type": "command",
|
|
109
|
+
"command": "bash .claude/hooks/post-edit-format.sh",
|
|
110
|
+
"timeout": 10000
|
|
111
|
+
}
|
|
112
|
+
]
|
|
59
113
|
}
|
|
60
114
|
],
|
|
61
115
|
"SubagentStart": [
|
|
62
116
|
{
|
|
63
|
-
"
|
|
64
|
-
"
|
|
65
|
-
|
|
117
|
+
"matcher": "",
|
|
118
|
+
"hooks": [
|
|
119
|
+
{
|
|
120
|
+
"type": "command",
|
|
121
|
+
"command": "bash .claude/hooks/log-agent.sh",
|
|
122
|
+
"timeout": 5000
|
|
123
|
+
}
|
|
124
|
+
]
|
|
66
125
|
}
|
|
67
126
|
],
|
|
68
127
|
"Stop": [
|
|
69
128
|
{
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
|
|
129
|
+
"matcher": "",
|
|
130
|
+
"hooks": [
|
|
131
|
+
{
|
|
132
|
+
"type": "command",
|
|
133
|
+
"command": "bash .claude/hooks/session-stop.sh",
|
|
134
|
+
"timeout": 10000
|
|
135
|
+
}
|
|
136
|
+
]
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
"matcher": "",
|
|
140
|
+
"hooks": [
|
|
141
|
+
{
|
|
142
|
+
"type": "command",
|
|
143
|
+
"command": "bash .claude/hooks/console-log-warning.sh",
|
|
144
|
+
"timeout": 10000
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
},
|
|
148
|
+
{
|
|
149
|
+
"matcher": "",
|
|
150
|
+
"hooks": [
|
|
151
|
+
{
|
|
152
|
+
"type": "command",
|
|
153
|
+
"command": "bash .claude/hooks/cost-tracker.sh",
|
|
154
|
+
"timeout": 5000
|
|
155
|
+
}
|
|
156
|
+
]
|
|
73
157
|
}
|
|
74
158
|
]
|
|
75
159
|
}
|
|
@@ -281,26 +281,33 @@ Create entries in: `[ARCH_CHANGELOG_DIR]`
|
|
|
281
281
|
| `/sk:accessibility` | WCAG 2.1 AA audit — runs after design, before implementation |
|
|
282
282
|
| `/sk:api-design` | Design API contracts (endpoints, payloads, auth, errors) before implementation |
|
|
283
283
|
| `/sk:autopilot` | Hands-free workflow — all 8 steps, auto-skip, auto-advance, auto-commit |
|
|
284
|
-
| `/sk:brainstorm` | Explore requirements and design |
|
|
284
|
+
| `/sk:brainstorm` | Explore requirements and design (includes search-first research) |
|
|
285
285
|
| `/sk:branch` | Create feature branch auto-named from current task |
|
|
286
286
|
| `/sk:change` | Handle mid-workflow requirement changes — re-enter at correct step |
|
|
287
287
|
| `/sk:context` | Load all context files + output session brief for fast session start |
|
|
288
|
+
| `/sk:context-budget` | Audit context window token consumption and find savings |
|
|
288
289
|
| `/sk:dashboard` | Read-only workflow Kanban board — localhost server, multi-worktree |
|
|
289
290
|
| `/sk:debug` | Investigate and debug issues (bug fix entry point) |
|
|
290
291
|
| `/sk:e2e` | E2E behavioral verification using agent-browser (final quality gate) |
|
|
292
|
+
| `/sk:eval` | Define, run, and report on evaluations for agent reliability |
|
|
291
293
|
| `/sk:execute-plan` | Execute `tasks/todo.md` checkboxes in batches |
|
|
292
294
|
| `/sk:fast-track` | Abbreviated workflow for small changes — skip planning, keep all gates |
|
|
293
295
|
| `/sk:features` | Sync feature specs with shipped implementation |
|
|
294
296
|
| `/sk:finish-feature` | Changelog + PR creation |
|
|
295
297
|
| `/sk:frontend-design` | UI mockup before implementation. Prompts to create Pencil visual mockup |
|
|
296
298
|
| `/sk:gates` | Run all quality gates in optimized parallel batches |
|
|
299
|
+
| `/sk:health` | Harness self-audit scorecard (7 categories, 0-70) |
|
|
297
300
|
| `/sk:hotfix` | Emergency fix workflow — skip design/TDD, quality gates enforced |
|
|
301
|
+
| `/sk:learn` | Extract reusable patterns from sessions into learned instincts |
|
|
298
302
|
| `/sk:lint` | Auto-detect and run all project linters + dependency audits |
|
|
299
303
|
| `/sk:perf` | Performance audit — bundle, N+1, Core Web Vitals, memory |
|
|
300
304
|
| `/sk:release` | Version bump + changelog + tag |
|
|
305
|
+
| `/sk:resume-session` | Resume a previously saved session with full context restoration |
|
|
301
306
|
| `/sk:retro` | Post-ship retrospective: velocity, blockers, action items |
|
|
302
307
|
| `/sk:reverse-doc` | Generate architecture/design docs from existing code |
|
|
303
308
|
| `/sk:review` | Self-review with simplify pre-pass + multi-dimensional review |
|
|
309
|
+
| `/sk:safety-guard` | Protect against destructive ops (careful/freeze/guard modes) |
|
|
310
|
+
| `/sk:save-session` | Save current session state for cross-session continuity |
|
|
304
311
|
| `/sk:scope-check` | Compare implementation against plan, detect scope creep |
|
|
305
312
|
| `/sk:security-check` | OWASP security audit on changed files |
|
|
306
313
|
| `/sk:seo-audit` | SEO audit — dual-mode (source templates + dev server), ask-before-fix |
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# config-protection.sh — PreToolUse hook for Edit/Write
|
|
3
|
+
# Blocks modifications to linter/formatter configs.
|
|
4
|
+
# Override: SHIPKIT_ALLOW_CONFIG_EDIT=1
|
|
5
|
+
|
|
6
|
+
set -euo pipefail
|
|
7
|
+
|
|
8
|
+
if [[ "${SHIPKIT_ALLOW_CONFIG_EDIT:-0}" == "1" ]]; then
|
|
9
|
+
exit 0
|
|
10
|
+
fi
|
|
11
|
+
|
|
12
|
+
# Read the tool input from stdin
|
|
13
|
+
INPUT=$(cat)
|
|
14
|
+
|
|
15
|
+
# Extract the file path from the tool input
|
|
16
|
+
FILE_PATH=$(echo "$INPUT" | grep -oE '"file_path"\s*:\s*"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')
|
|
17
|
+
|
|
18
|
+
if [[ -z "$FILE_PATH" ]]; then
|
|
19
|
+
exit 0
|
|
20
|
+
fi
|
|
21
|
+
|
|
22
|
+
BASENAME=$(basename "$FILE_PATH")
|
|
23
|
+
|
|
24
|
+
# Protected config patterns
|
|
25
|
+
PROTECTED_CONFIGS=(
|
|
26
|
+
".eslintrc"
|
|
27
|
+
".eslintrc.js"
|
|
28
|
+
".eslintrc.cjs"
|
|
29
|
+
".eslintrc.json"
|
|
30
|
+
".eslintrc.yml"
|
|
31
|
+
".eslintrc.yaml"
|
|
32
|
+
"eslint.config.js"
|
|
33
|
+
"eslint.config.mjs"
|
|
34
|
+
"eslint.config.cjs"
|
|
35
|
+
".prettierrc"
|
|
36
|
+
".prettierrc.js"
|
|
37
|
+
".prettierrc.cjs"
|
|
38
|
+
".prettierrc.json"
|
|
39
|
+
".prettierrc.yml"
|
|
40
|
+
".prettierrc.yaml"
|
|
41
|
+
"prettier.config.js"
|
|
42
|
+
"prettier.config.mjs"
|
|
43
|
+
"biome.json"
|
|
44
|
+
"biome.jsonc"
|
|
45
|
+
".stylelintrc"
|
|
46
|
+
".stylelintrc.json"
|
|
47
|
+
".stylelintrc.js"
|
|
48
|
+
"stylelint.config.js"
|
|
49
|
+
"phpstan.neon"
|
|
50
|
+
"phpstan.neon.dist"
|
|
51
|
+
"pint.json"
|
|
52
|
+
"rector.php"
|
|
53
|
+
".php-cs-fixer.php"
|
|
54
|
+
".php-cs-fixer.dist.php"
|
|
55
|
+
".rubocop.yml"
|
|
56
|
+
".golangci.yml"
|
|
57
|
+
".golangci.yaml"
|
|
58
|
+
"rustfmt.toml"
|
|
59
|
+
".clang-format"
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
for config in "${PROTECTED_CONFIGS[@]}"; do
|
|
63
|
+
if [[ "$BASENAME" == "$config" ]]; then
|
|
64
|
+
echo "BLOCKED: Modifying linter/formatter config '$BASENAME'."
|
|
65
|
+
echo "Fix the code instead of weakening the rules."
|
|
66
|
+
echo "Override: set SHIPKIT_ALLOW_CONFIG_EDIT=1"
|
|
67
|
+
exit 2
|
|
68
|
+
fi
|
|
69
|
+
done
|
|
70
|
+
|
|
71
|
+
exit 0
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# console-log-warning.sh — Stop hook
|
|
3
|
+
# Scans git-modified files for debug statements and warns if found.
|
|
4
|
+
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
8
|
+
cd "$PROJECT_ROOT"
|
|
9
|
+
|
|
10
|
+
MODIFIED_FILES=$(git diff --name-only --diff-filter=ACMR 2>/dev/null)
|
|
11
|
+
STAGED_FILES=$(git diff --cached --name-only --diff-filter=ACMR 2>/dev/null)
|
|
12
|
+
ALL_FILES=$(echo -e "${MODIFIED_FILES}\n${STAGED_FILES}" | sort -u | grep -v '^$')
|
|
13
|
+
|
|
14
|
+
if [[ -z "$ALL_FILES" ]]; then
|
|
15
|
+
exit 0
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
DEBUG_PATTERNS='console\.log\|console\.warn\|console\.error\|console\.debug\|console\.trace\|debugger\b\|\bdd(\|\bdump(\|\bvar_dump(\|\bprint_r(\|\blog\.Print\|log\.Debug\|\bpdb\.set_trace\|\bbreakpoint()'
|
|
19
|
+
|
|
20
|
+
FOUND=0
|
|
21
|
+
REPORT=""
|
|
22
|
+
|
|
23
|
+
while IFS= read -r file; do
|
|
24
|
+
[[ -z "$file" || ! -f "$file" ]] && continue
|
|
25
|
+
MATCHES=$(grep -n "$DEBUG_PATTERNS" "$file" 2>/dev/null || true)
|
|
26
|
+
if [[ -n "$MATCHES" ]]; then
|
|
27
|
+
FOUND=$((FOUND + 1))
|
|
28
|
+
REPORT+=" $file:\n"
|
|
29
|
+
while IFS= read -r match; do
|
|
30
|
+
REPORT+=" $match\n"
|
|
31
|
+
done <<< "$MATCHES"
|
|
32
|
+
fi
|
|
33
|
+
done <<< "$ALL_FILES"
|
|
34
|
+
|
|
35
|
+
if [[ $FOUND -gt 0 ]]; then
|
|
36
|
+
echo ""
|
|
37
|
+
echo "WARNING: Debug statements found in $FOUND modified file(s):"
|
|
38
|
+
echo -e "$REPORT"
|
|
39
|
+
echo "Consider removing before committing."
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
exit 0
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# cost-tracker.sh — Stop hook (async)
|
|
3
|
+
# Logs session metadata to .claude/sessions/cost-log.jsonl
|
|
4
|
+
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
8
|
+
SESSIONS_DIR="$PROJECT_ROOT/.claude/sessions"
|
|
9
|
+
LOG_FILE="$SESSIONS_DIR/cost-log.jsonl"
|
|
10
|
+
|
|
11
|
+
mkdir -p "$SESSIONS_DIR"
|
|
12
|
+
|
|
13
|
+
BRANCH=$(git branch --show-current 2>/dev/null || echo "unknown")
|
|
14
|
+
TIMESTAMP=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
15
|
+
DATE=$(date +"%Y-%m-%d")
|
|
16
|
+
|
|
17
|
+
# Count commits made during this session (last 8 hours)
|
|
18
|
+
RECENT_COMMITS=$(git log --since="8 hours ago" --oneline 2>/dev/null | wc -l | tr -d ' ')
|
|
19
|
+
|
|
20
|
+
# Count modified files
|
|
21
|
+
MODIFIED_COUNT=$(git diff --name-only 2>/dev/null | wc -l | tr -d ' ')
|
|
22
|
+
STAGED_COUNT=$(git diff --cached --name-only 2>/dev/null | wc -l | tr -d ' ')
|
|
23
|
+
|
|
24
|
+
echo "{\"timestamp\":\"$TIMESTAMP\",\"date\":\"$DATE\",\"branch\":\"$BRANCH\",\"commits\":$RECENT_COMMITS,\"modified_files\":$MODIFIED_COUNT,\"staged_files\":$STAGED_COUNT}" >> "$LOG_FILE"
|
|
25
|
+
|
|
26
|
+
exit 0
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# post-edit-format.sh — PostToolUse hook for Edit
|
|
3
|
+
# Auto-formats the edited file using the project's formatter.
|
|
4
|
+
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
INPUT=$(cat)
|
|
8
|
+
FILE_PATH=$(echo "$INPUT" | grep -oE '"file_path"\s*:\s*"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')
|
|
9
|
+
|
|
10
|
+
if [[ -z "$FILE_PATH" || ! -f "$FILE_PATH" ]]; then
|
|
11
|
+
exit 0
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
EXT="${FILE_PATH##*.}"
|
|
15
|
+
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
16
|
+
|
|
17
|
+
format_file() {
|
|
18
|
+
# Biome (JS/TS/JSON)
|
|
19
|
+
if [[ -f "$PROJECT_ROOT/biome.json" || -f "$PROJECT_ROOT/biome.jsonc" ]]; then
|
|
20
|
+
if [[ "$EXT" =~ ^(js|jsx|ts|tsx|json|jsonc)$ ]]; then
|
|
21
|
+
npx biome format --write "$FILE_PATH" 2>/dev/null && return 0
|
|
22
|
+
fi
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# Prettier (JS/TS/CSS/HTML/MD)
|
|
26
|
+
if [[ -f "$PROJECT_ROOT/.prettierrc" || -f "$PROJECT_ROOT/.prettierrc.json" || -f "$PROJECT_ROOT/.prettierrc.js" || -f "$PROJECT_ROOT/.prettierrc.cjs" || -f "$PROJECT_ROOT/prettier.config.js" || -f "$PROJECT_ROOT/prettier.config.mjs" ]]; then
|
|
27
|
+
if [[ "$EXT" =~ ^(js|jsx|ts|tsx|css|scss|html|md|json|yaml|yml|vue|svelte)$ ]]; then
|
|
28
|
+
npx prettier --write "$FILE_PATH" 2>/dev/null && return 0
|
|
29
|
+
fi
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
# Pint (PHP)
|
|
33
|
+
if [[ -f "$PROJECT_ROOT/pint.json" || -f "$PROJECT_ROOT/vendor/bin/pint" ]]; then
|
|
34
|
+
if [[ "$EXT" == "php" ]]; then
|
|
35
|
+
"$PROJECT_ROOT/vendor/bin/pint" "$FILE_PATH" 2>/dev/null && return 0
|
|
36
|
+
fi
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# gofmt (Go)
|
|
40
|
+
if [[ "$EXT" == "go" ]]; then
|
|
41
|
+
command -v gofmt &>/dev/null && gofmt -w "$FILE_PATH" 2>/dev/null && return 0
|
|
42
|
+
fi
|
|
43
|
+
|
|
44
|
+
# cargo fmt (Rust)
|
|
45
|
+
if [[ "$EXT" == "rs" ]]; then
|
|
46
|
+
command -v rustfmt &>/dev/null && rustfmt "$FILE_PATH" 2>/dev/null && return 0
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
return 0
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
format_file
|
|
53
|
+
exit 0
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# safety-guard.sh — PreToolUse hook for Bash/Edit/Write
|
|
3
|
+
# Reads .claude/safety-guard.json for active mode and directory constraints.
|
|
4
|
+
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
|
|
8
|
+
GUARD_CONFIG="$PROJECT_ROOT/.claude/safety-guard.json"
|
|
9
|
+
|
|
10
|
+
if [[ ! -f "$GUARD_CONFIG" ]]; then
|
|
11
|
+
exit 0
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
INPUT=$(cat)
|
|
15
|
+
MODE=$(python3 -c "import json; print(json.load(open('$GUARD_CONFIG')).get('mode', 'off'))" 2>/dev/null || echo "off")
|
|
16
|
+
|
|
17
|
+
if [[ "$MODE" == "off" ]]; then
|
|
18
|
+
exit 0
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# Extract tool info
|
|
22
|
+
TOOL_NAME="${TOOL_NAME:-}"
|
|
23
|
+
FILE_PATH=$(echo "$INPUT" | grep -oE '"file_path"\s*:\s*"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')
|
|
24
|
+
COMMAND=$(echo "$INPUT" | grep -oE '"command"\s*:\s*"[^"]*"' | head -1 | sed 's/.*: *"//;s/"$//')
|
|
25
|
+
|
|
26
|
+
# Careful mode: block destructive commands
|
|
27
|
+
if [[ "$MODE" == "careful" || "$MODE" == "guard" ]]; then
|
|
28
|
+
if [[ -n "$COMMAND" ]]; then
|
|
29
|
+
DESTRUCTIVE_PATTERNS=(
|
|
30
|
+
"rm -rf"
|
|
31
|
+
"rm -fr"
|
|
32
|
+
"git push --force"
|
|
33
|
+
"git push -f"
|
|
34
|
+
"git reset --hard"
|
|
35
|
+
"git clean -f"
|
|
36
|
+
"DROP TABLE"
|
|
37
|
+
"DROP DATABASE"
|
|
38
|
+
"chmod 777"
|
|
39
|
+
"chmod -R 777"
|
|
40
|
+
"--no-verify"
|
|
41
|
+
)
|
|
42
|
+
for pattern in "${DESTRUCTIVE_PATTERNS[@]}"; do
|
|
43
|
+
if echo "$COMMAND" | grep -qi "$pattern"; then
|
|
44
|
+
echo "BLOCKED by safety-guard (careful mode): destructive command detected."
|
|
45
|
+
echo " Command: $COMMAND"
|
|
46
|
+
echo " Pattern: $pattern"
|
|
47
|
+
echo " Disable: /sk:safety-guard off"
|
|
48
|
+
exit 2
|
|
49
|
+
fi
|
|
50
|
+
done
|
|
51
|
+
fi
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# Freeze mode: block writes outside specified directory
|
|
55
|
+
if [[ "$MODE" == "freeze" || "$MODE" == "guard" ]]; then
|
|
56
|
+
FREEZE_DIR=$(python3 -c "import json; print(json.load(open('$GUARD_CONFIG')).get('freeze_dir', ''))" 2>/dev/null || echo "")
|
|
57
|
+
if [[ -n "$FREEZE_DIR" && -n "$FILE_PATH" ]]; then
|
|
58
|
+
# Resolve to absolute paths for comparison
|
|
59
|
+
ABS_FREEZE=$(cd "$PROJECT_ROOT" && cd "$FREEZE_DIR" 2>/dev/null && pwd || echo "$PROJECT_ROOT/$FREEZE_DIR")
|
|
60
|
+
ABS_FILE=$(cd "$(dirname "$FILE_PATH")" 2>/dev/null && echo "$(pwd)/$(basename "$FILE_PATH")" || echo "$FILE_PATH")
|
|
61
|
+
|
|
62
|
+
if [[ "$ABS_FILE" != "$ABS_FREEZE"* ]]; then
|
|
63
|
+
echo "BLOCKED by safety-guard (freeze mode): write outside frozen directory."
|
|
64
|
+
echo " File: $FILE_PATH"
|
|
65
|
+
echo " Allowed: $FREEZE_DIR"
|
|
66
|
+
echo " Disable: /sk:safety-guard off"
|
|
67
|
+
exit 2
|
|
68
|
+
fi
|
|
69
|
+
fi
|
|
70
|
+
fi
|
|
71
|
+
|
|
72
|
+
exit 0
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# suggest-compact.sh — PreToolUse hook for Edit/Write
|
|
3
|
+
# Tracks tool call count and suggests /compact at threshold.
|
|
4
|
+
|
|
5
|
+
set -uo pipefail
|
|
6
|
+
|
|
7
|
+
THRESHOLD="${SHIPKIT_COMPACT_THRESHOLD:-50}"
|
|
8
|
+
REPEAT_INTERVAL=25
|
|
9
|
+
|
|
10
|
+
# Use a session-scoped counter file
|
|
11
|
+
COUNTER_FILE="/tmp/shipkit-tool-count-${PPID:-$$}"
|
|
12
|
+
|
|
13
|
+
# Read current count
|
|
14
|
+
COUNT=0
|
|
15
|
+
if [[ -f "$COUNTER_FILE" ]]; then
|
|
16
|
+
COUNT=$(cat "$COUNTER_FILE" 2>/dev/null || echo "0")
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
COUNT=$((COUNT + 1))
|
|
20
|
+
echo "$COUNT" > "$COUNTER_FILE"
|
|
21
|
+
|
|
22
|
+
# Check if we should suggest compaction
|
|
23
|
+
if [[ $COUNT -eq $THRESHOLD ]]; then
|
|
24
|
+
echo ""
|
|
25
|
+
echo "HINT: You've made $COUNT+ tool calls this session."
|
|
26
|
+
echo "Consider running /compact if context feels heavy."
|
|
27
|
+
elif [[ $COUNT -gt $THRESHOLD ]]; then
|
|
28
|
+
PAST_THRESHOLD=$((COUNT - THRESHOLD))
|
|
29
|
+
if [[ $((PAST_THRESHOLD % REPEAT_INTERVAL)) -eq 0 ]]; then
|
|
30
|
+
echo ""
|
|
31
|
+
echo "HINT: $COUNT tool calls this session. Consider /compact."
|
|
32
|
+
fi
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
exit 0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sk:setup-optimizer
|
|
3
|
-
description: "Diagnose, update workflow, enrich, and
|
|
3
|
+
description: "Diagnose, update workflow, deploy hooks, enrich CLAUDE.md, and keep project infrastructure current. The single command for ongoing ShipKit maintenance."
|
|
4
4
|
triggers:
|
|
5
5
|
- optimize claude
|
|
6
6
|
- optimize setup
|
|
@@ -20,14 +20,15 @@ allowed-tools:
|
|
|
20
20
|
|
|
21
21
|
## Overview
|
|
22
22
|
|
|
23
|
-
The single command to keep your
|
|
23
|
+
The single command to keep your entire ShipKit project infrastructure current. Diagnoses problems, updates the workflow, deploys missing hooks, scans your codebase, and enriches CLAUDE.md with project context — all while preserving your customizations.
|
|
24
24
|
|
|
25
25
|
### What It Does
|
|
26
26
|
|
|
27
27
|
1. **Diagnoses** — finds missing sections, stale info, inconsistencies, and gaps
|
|
28
28
|
2. **Updates workflow** — refreshes the workflow section to the latest template version
|
|
29
|
-
3. **
|
|
30
|
-
4. **
|
|
29
|
+
3. **Deploys hooks** — installs missing hooks and updates settings.json wiring
|
|
30
|
+
4. **Discovers** — scans project structure, docs, and workflows
|
|
31
|
+
5. **Enriches** — merges discoveries into CLAUDE.md while preserving your edits
|
|
31
32
|
|
|
32
33
|
## Usage
|
|
33
34
|
|
|
@@ -44,9 +45,10 @@ Before making any changes, runs a diagnostic pass on the existing CLAUDE.md:
|
|
|
44
45
|
- **Inconsistencies** — compares documented vs actual project state (directories, scripts, workflows)
|
|
45
46
|
- **Section completeness** — flags sections that exist but are empty or have only placeholder text
|
|
46
47
|
- **Outdated workflow** — checks if the workflow matches the current 8-step flow with `/sk:gates` as single gate step
|
|
47
|
-
- **Missing commands** — checks for `sk:start`, `sk:autopilot`, `sk:team` in the Commands table
|
|
48
|
+
- **Missing commands** — checks for `sk:start`, `sk:autopilot`, `sk:team`, `sk:learn`, `sk:context-budget`, `sk:health`, `sk:save-session`, `sk:resume-session`, `sk:safety-guard`, `sk:eval` in the Commands table
|
|
48
49
|
- **Auto-skip rules** — checks for auto-skip detection rules in the workflow section
|
|
49
50
|
- **Stale tracker references** — checks for `tasks/workflow-status.md` references (removed — progress tracked via git branch + todo.md checkboxes)
|
|
51
|
+
- **Missing hooks** — checks if `.claude/hooks/` exists and contains both core and enhanced hooks
|
|
50
52
|
|
|
51
53
|
Reports findings before proceeding. If issues are found, they inform subsequent steps.
|
|
52
54
|
|
|
@@ -89,6 +91,54 @@ Explore → Design → Plan → Branch → Write Tests + Implement → Commit
|
|
|
89
91
|
4. Insert missing sections (Sub-Agent Patterns, Project Memory, etc.) in their correct positions
|
|
90
92
|
5. Preserve all `<!-- LOCK -->` and project-specific sections
|
|
91
93
|
|
|
94
|
+
### Step 1.5: Hooks Deployment
|
|
95
|
+
|
|
96
|
+
After updating the workflow, check and deploy hooks:
|
|
97
|
+
|
|
98
|
+
1. **Check if `.claude/hooks/` exists** — if not, create it
|
|
99
|
+
2. **Check for core hooks** — `session-start.sh`, `session-stop.sh`, `pre-compact.sh`, `validate-commit.sh`, `validate-push.sh`, `log-agent.sh`
|
|
100
|
+
3. **Check for enhanced hooks** — `config-protection.sh`, `post-edit-format.sh`, `console-log-warning.sh`, `cost-tracker.sh`, `suggest-compact.sh`, `safety-guard.sh`
|
|
101
|
+
4. **Check `.claude/settings.json`** — verify hooks are wired correctly
|
|
102
|
+
|
|
103
|
+
**Report status and prompt:**
|
|
104
|
+
|
|
105
|
+
> "Hooks: [X/6 core, Y/6 enhanced] installed
|
|
106
|
+
> Install missing hooks? [y/n]"
|
|
107
|
+
|
|
108
|
+
**If yes:**
|
|
109
|
+
|
|
110
|
+
1. **Locate templates** — resolve the ShipKit templates directory:
|
|
111
|
+
- `~/.claude/skills/sk:setup-claude/templates/hooks/` (symlinked install)
|
|
112
|
+
- Or the npm global path if installed via `npm install -g`
|
|
113
|
+
|
|
114
|
+
2. **Deploy missing hook scripts** (create-if-missing, never overwrite existing):
|
|
115
|
+
```bash
|
|
116
|
+
# For each missing hook file:
|
|
117
|
+
cp "$TEMPLATE_DIR/hooks/<hook>.sh" ".claude/hooks/<hook>.sh"
|
|
118
|
+
chmod +x ".claude/hooks/<hook>.sh"
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
3. **Update `.claude/settings.json`** — read the latest `settings.json.template` and merge new hook entries into the existing settings.json:
|
|
122
|
+
- **Preserve** existing hooks, permissions, statusline config
|
|
123
|
+
- **Add** only missing hook entries (new PreToolUse, PostToolUse, Stop entries)
|
|
124
|
+
- **Never remove** existing entries — additive merge only
|
|
125
|
+
|
|
126
|
+
4. **Report what was deployed:**
|
|
127
|
+
```
|
|
128
|
+
Deployed hooks:
|
|
129
|
+
+ config-protection.sh (PreToolUse — blocks linter config edits)
|
|
130
|
+
+ post-edit-format.sh (PostToolUse — auto-format after edits)
|
|
131
|
+
+ console-log-warning.sh (Stop — warn on debug statements)
|
|
132
|
+
+ cost-tracker.sh (Stop — session metadata logging)
|
|
133
|
+
+ suggest-compact.sh (PreToolUse — compact suggestions)
|
|
134
|
+
+ safety-guard.sh (PreToolUse — freeze/careful mode)
|
|
135
|
+
~ Updated .claude/settings.json with new hook wiring
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**If no:** skip hook deployment, continue to Step 2.
|
|
139
|
+
|
|
140
|
+
**Idempotency:** Never overwrite existing hook files — the user may have customized them. Only deploy hooks that don't exist yet. For settings.json, merge additively.
|
|
141
|
+
|
|
92
142
|
### Step 2: Scan & Enrich
|
|
93
143
|
|
|
94
144
|
After workflow update, proceeds with codebase discovery and enrichment:
|
|
@@ -183,10 +233,11 @@ This content will never be regenerated.
|
|
|
183
233
|
|
|
184
234
|
## When to Use
|
|
185
235
|
|
|
186
|
-
✅ **Use `/
|
|
236
|
+
✅ **Use `/sk:setup-optimizer` when:**
|
|
237
|
+
- ShipKit was updated and your project needs the latest hooks/commands
|
|
187
238
|
- You've added new directories to your project
|
|
188
239
|
- You've created documentation files
|
|
189
240
|
- You want to refresh project context
|
|
190
|
-
- Monthly maintenance of CLAUDE.md
|
|
241
|
+
- Monthly maintenance of CLAUDE.md and hooks
|
|
191
242
|
|
|
192
|
-
✅ **Safe to run multiple times
|
|
243
|
+
✅ **Safe to run multiple times** — existing customizations and hook files are never overwritten.
|
package/skills/sk:start/SKILL.md
CHANGED
|
@@ -53,6 +53,31 @@ Read the task description from arguments. Scan for signal keywords to determine
|
|
|
53
53
|
| `backend` only | `solo` |
|
|
54
54
|
| `unknown` | `solo` (default) |
|
|
55
55
|
|
|
56
|
+
### Step 1.5 — Missing Context Detection (automatic, no prompt)
|
|
57
|
+
|
|
58
|
+
After classification, scan the task description for gaps. This is informational only — does NOT block.
|
|
59
|
+
|
|
60
|
+
**Critical context checks:**
|
|
61
|
+
|
|
62
|
+
| Check | How to detect | Auto-resolve |
|
|
63
|
+
|-------|--------------|--------------|
|
|
64
|
+
| Tech stack specified? | Look for framework/language keywords | Auto-detect from package.json, composer.json, go.mod, Cargo.toml |
|
|
65
|
+
| Acceptance criteria present? | Look for "should", "must", "when", "given" | Cannot auto-resolve — flag for user |
|
|
66
|
+
| Scope boundaries stated? | Look for "only", "not", "exclude", "just" | Cannot auto-resolve — flag for user |
|
|
67
|
+
| Security requirements? | Check if task involves auth, user data, payments, tokens | Flag: "This touches auth/user data — consider security requirements" |
|
|
68
|
+
| Testing expectations? | Look for "test", "coverage", "spec" | Default: 100% coverage on new code (per workflow) |
|
|
69
|
+
|
|
70
|
+
**If 3+ critical items are missing**, include in the recommendation output:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
Missing Context (3 items — consider clarifying):
|
|
74
|
+
- No acceptance criteria detected
|
|
75
|
+
- No scope boundaries stated (what should NOT change?)
|
|
76
|
+
- Task involves user data but no security requirements mentioned
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
This check runs silently. If <3 items missing, no output.
|
|
80
|
+
|
|
56
81
|
### Step 2 — Recommend (one prompt, user confirms or overrides)
|
|
57
82
|
|
|
58
83
|
Present the classification and recommendation:
|