@kennethsolomon/shipkit 3.7.0 → 3.8.0

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.
Files changed (27) hide show
  1. package/README.md +5 -0
  2. package/package.json +1 -1
  3. package/skills/sk:fast-track/SKILL.md +80 -0
  4. package/skills/sk:gates/SKILL.md +97 -0
  5. package/skills/sk:retro/SKILL.md +124 -0
  6. package/skills/sk:reverse-doc/SKILL.md +116 -0
  7. package/skills/sk:scope-check/SKILL.md +93 -0
  8. package/skills/sk:setup-claude/SKILL.md +53 -0
  9. package/skills/sk:setup-claude/scripts/apply_setup_claude.py +206 -6
  10. package/skills/sk:setup-claude/templates/.claude/agents/e2e-tester.md +46 -0
  11. package/skills/sk:setup-claude/templates/.claude/agents/linter.md +53 -0
  12. package/skills/sk:setup-claude/templates/.claude/agents/perf-auditor.md +43 -0
  13. package/skills/sk:setup-claude/templates/.claude/agents/security-auditor.md +47 -0
  14. package/skills/sk:setup-claude/templates/.claude/agents/test-runner.md +42 -0
  15. package/skills/sk:setup-claude/templates/.claude/rules/api.md.template +14 -0
  16. package/skills/sk:setup-claude/templates/.claude/rules/frontend.md.template +15 -0
  17. package/skills/sk:setup-claude/templates/.claude/rules/laravel.md.template +15 -0
  18. package/skills/sk:setup-claude/templates/.claude/rules/react.md.template +14 -0
  19. package/skills/sk:setup-claude/templates/.claude/rules/tests.md.template +16 -0
  20. package/skills/sk:setup-claude/templates/.claude/settings.json.template +76 -0
  21. package/skills/sk:setup-claude/templates/.claude/statusline.sh +50 -0
  22. package/skills/sk:setup-claude/templates/hooks/log-agent.sh +24 -0
  23. package/skills/sk:setup-claude/templates/hooks/pre-compact.sh +44 -0
  24. package/skills/sk:setup-claude/templates/hooks/session-start.sh +53 -0
  25. package/skills/sk:setup-claude/templates/hooks/session-stop.sh +33 -0
  26. package/skills/sk:setup-claude/templates/hooks/validate-commit.sh +81 -0
  27. package/skills/sk:setup-claude/templates/hooks/validate-push.sh +43 -0
@@ -0,0 +1,50 @@
1
+ #!/bin/bash
2
+ # Claude Code statusline: Shows persistent status in CLI
3
+ # Receives JSON on stdin with context_window, model info
4
+ # Outputs a single formatted line
5
+
6
+ INPUT=$(cat)
7
+
8
+ # Parse context and model — use jq if available
9
+ if command -v jq >/dev/null 2>&1; then
10
+ MODEL=$(echo "$INPUT" | jq -r '.model // "unknown"' 2>/dev/null)
11
+ CTX_USED=$(echo "$INPUT" | jq -r '.context_window.used // 0' 2>/dev/null)
12
+ CTX_TOTAL=$(echo "$INPUT" | jq -r '.context_window.total // 1' 2>/dev/null)
13
+ else
14
+ MODEL="unknown"
15
+ CTX_USED=0
16
+ CTX_TOTAL=1
17
+ fi
18
+
19
+ # Calculate context percentage
20
+ if [ "$CTX_TOTAL" -gt 0 ] 2>/dev/null; then
21
+ CTX_PCT=$((CTX_USED * 100 / CTX_TOTAL))
22
+ else
23
+ CTX_PCT=0
24
+ fi
25
+
26
+ # Branch
27
+ BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "none")
28
+
29
+ # Current workflow step
30
+ STEP="—"
31
+ if [ -f "tasks/workflow-status.md" ]; then
32
+ NEXT_LINE=$(grep -E ">>\s*next\s*<<" "tasks/workflow-status.md" 2>/dev/null | head -1)
33
+ if [ -n "$NEXT_LINE" ]; then
34
+ # Extract step number and name from table row
35
+ STEP_NUM=$(echo "$NEXT_LINE" | grep -oE '^\|[[:space:]]*[0-9]+' | grep -oE '[0-9]+')
36
+ STEP_NAME=$(echo "$NEXT_LINE" | sed 's/.*| *>> next << *|.*//' | sed 's/|.*//;s/^ *//;s/ *$//')
37
+ if [ -n "$STEP_NUM" ]; then
38
+ STEP="Step ${STEP_NUM}"
39
+ fi
40
+ fi
41
+ fi
42
+
43
+ # Task name from todo.md
44
+ TASK="—"
45
+ if [ -f "tasks/todo.md" ]; then
46
+ TASK=$(head -1 "tasks/todo.md" 2>/dev/null | sed 's/^# TODO.*— //' | cut -c1-40)
47
+ fi
48
+
49
+ # Output single line
50
+ echo "[${CTX_PCT}%] ${MODEL} | ${STEP} | ${BRANCH} | ${TASK}"
@@ -0,0 +1,24 @@
1
+ #!/bin/bash
2
+ # Claude Code SubagentStart hook: Log agent invocations for audit trail
3
+ # Tracks which agents are being used and when
4
+ #
5
+ # Input schema (SubagentStart):
6
+ # { "agent_id": "agent-abc123", "agent_name": "linter", ... }
7
+
8
+ INPUT=$(cat)
9
+
10
+ # Parse agent name
11
+ if command -v jq >/dev/null 2>&1; then
12
+ AGENT_NAME=$(echo "$INPUT" | jq -r '.agent_name // "unknown"' 2>/dev/null)
13
+ else
14
+ AGENT_NAME=$(echo "$INPUT" | grep -oE '"agent_name"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/"agent_name"[[:space:]]*:[[:space:]]*"//;s/"$//')
15
+ [ -z "$AGENT_NAME" ] && AGENT_NAME="unknown"
16
+ fi
17
+
18
+ TIMESTAMP=$(date +%Y%m%d_%H%M%S)
19
+
20
+ # Append to audit log (create tasks/ dir if needed)
21
+ mkdir -p tasks 2>/dev/null
22
+ echo "$TIMESTAMP | Agent invoked: $AGENT_NAME" >> "tasks/agent-audit.log" 2>/dev/null
23
+
24
+ exit 0
@@ -0,0 +1,44 @@
1
+ #!/bin/bash
2
+ # Claude Code PreCompact hook: Preserve session state before context compression
3
+ # Outputs critical state so Claude retains it after compaction
4
+
5
+ echo "=== Pre-Compaction State Snapshot ==="
6
+
7
+ # Workflow status
8
+ if [ -f "tasks/workflow-status.md" ]; then
9
+ echo ""
10
+ echo "--- workflow-status.md ---"
11
+ cat "tasks/workflow-status.md" 2>/dev/null | head -30
12
+ TOTAL_LINES=$(wc -l < "tasks/workflow-status.md" 2>/dev/null | tr -d ' ')
13
+ if [ "$TOTAL_LINES" -gt 30 ]; then
14
+ echo " ... ($TOTAL_LINES total lines)"
15
+ fi
16
+ fi
17
+
18
+ # Git status
19
+ echo ""
20
+ echo "--- Uncommitted Changes ---"
21
+ STAGED=$(git diff --cached --name-only 2>/dev/null)
22
+ UNSTAGED=$(git diff --name-only 2>/dev/null)
23
+ UNTRACKED=$(git ls-files --others --exclude-standard 2>/dev/null)
24
+
25
+ [ -n "$STAGED" ] && echo "Staged:" && echo "$STAGED" | sed 's/^/ /'
26
+ [ -n "$UNSTAGED" ] && echo "Unstaged:" && echo "$UNSTAGED" | sed 's/^/ /'
27
+ [ -n "$UNTRACKED" ] && echo "Untracked:" && echo "$UNTRACKED" | sed 's/^/ /'
28
+
29
+ if [ -z "$STAGED" ] && [ -z "$UNSTAGED" ] && [ -z "$UNTRACKED" ]; then
30
+ echo " (clean)"
31
+ fi
32
+
33
+ # Log compaction event
34
+ if [ -d "tasks" ]; then
35
+ echo "" >> "tasks/progress.md" 2>/dev/null
36
+ echo "### [$(date +%Y-%m-%d)] Context compaction occurred at $(date +%H:%M:%S)" >> "tasks/progress.md" 2>/dev/null
37
+ fi
38
+
39
+ echo ""
40
+ echo "--- Recovery ---"
41
+ echo "Read tasks/workflow-status.md to restore current step."
42
+ echo "Read tasks/progress.md for recent work."
43
+ echo "==================================="
44
+ exit 0
@@ -0,0 +1,53 @@
1
+ #!/bin/bash
2
+ # Claude Code SessionStart hook: Load project context at session start
3
+ # Outputs context that Claude sees when a session begins
4
+
5
+ echo "=== ShipKit — Session Context ==="
6
+
7
+ # Current branch
8
+ BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
9
+ if [ -n "$BRANCH" ]; then
10
+ echo "Branch: $BRANCH"
11
+ echo ""
12
+ echo "Recent commits:"
13
+ git log --oneline -5 2>/dev/null | while read -r line; do
14
+ echo " $line"
15
+ done
16
+ fi
17
+
18
+ # Current workflow step from workflow-status.md
19
+ if [ -f "tasks/workflow-status.md" ]; then
20
+ echo ""
21
+ NEXT_STEP=$(grep -E ">>\s*next\s*<<" "tasks/workflow-status.md" 2>/dev/null | head -1)
22
+ if [ -n "$NEXT_STEP" ]; then
23
+ echo "Workflow: $NEXT_STEP"
24
+ else
25
+ echo "Workflow: all steps complete or not started"
26
+ fi
27
+ fi
28
+
29
+ # Tech debt count
30
+ if [ -f "tasks/tech-debt.md" ]; then
31
+ TOTAL=$(grep -c "^### \[" "tasks/tech-debt.md" 2>/dev/null || echo 0)
32
+ RESOLVED=$(grep -c "^Resolved:" "tasks/tech-debt.md" 2>/dev/null || echo 0)
33
+ UNRESOLVED=$((TOTAL - RESOLVED))
34
+ if [ "$UNRESOLVED" -gt 0 ]; then
35
+ echo "Tech Debt: $UNRESOLVED unresolved item(s)"
36
+ fi
37
+ fi
38
+
39
+ # Code health (skip on large codebases to keep session start fast)
40
+ if [ -d "src" ]; then
41
+ FILE_COUNT=$(find src/ -type f 2>/dev/null | head -1001 | wc -l | tr -d ' ')
42
+ if [ "$FILE_COUNT" -le 1000 ]; then
43
+ TODO_COUNT=$(grep -r "TODO" src/ 2>/dev/null | wc -l | tr -d ' ')
44
+ FIXME_COUNT=$(grep -r "FIXME" src/ 2>/dev/null | wc -l | tr -d ' ')
45
+ if [ "$TODO_COUNT" -gt 0 ] || [ "$FIXME_COUNT" -gt 0 ]; then
46
+ echo ""
47
+ echo "Code health: ${TODO_COUNT} TODOs, ${FIXME_COUNT} FIXMEs in src/"
48
+ fi
49
+ fi
50
+ fi
51
+
52
+ echo "==================================="
53
+ exit 0
@@ -0,0 +1,33 @@
1
+ #!/bin/bash
2
+ # Claude Code Stop hook: Log session accomplishments
3
+ # Runs when a Claude Code session ends
4
+
5
+ # Only log if tasks/ directory exists (ShipKit project)
6
+ if [ ! -d "tasks" ]; then
7
+ exit 0
8
+ fi
9
+
10
+ TIMESTAMP=$(date +%Y-%m-%d\ %H:%M:%S)
11
+
12
+ # Get current branch
13
+ BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown")
14
+
15
+ # Count commits in this session (last hour)
16
+ RECENT_COMMITS=$(git log --since="1 hour ago" --oneline 2>/dev/null | wc -l | tr -d ' ')
17
+
18
+ # Get current workflow step
19
+ CURRENT_STEP=""
20
+ if [ -f "tasks/workflow-status.md" ]; then
21
+ CURRENT_STEP=$(grep -E ">>\s*next\s*<<" "tasks/workflow-status.md" 2>/dev/null | head -1 | sed 's/.*| //' | sed 's/ |.*//')
22
+ fi
23
+
24
+ # Append session end to progress.md
25
+ {
26
+ echo ""
27
+ echo "### [$TIMESTAMP] Session ended"
28
+ echo "- Branch: $BRANCH"
29
+ echo "- Commits this session: $RECENT_COMMITS"
30
+ [ -n "$CURRENT_STEP" ] && echo "- Next step: $CURRENT_STEP"
31
+ } >> "tasks/progress.md" 2>/dev/null
32
+
33
+ exit 0
@@ -0,0 +1,81 @@
1
+ #!/bin/bash
2
+ # Claude Code PreToolUse hook: Validates git commit commands
3
+ # Receives JSON on stdin with tool_input.command
4
+ # Exit 0 = allow, Exit 2 = block (stderr shown to Claude)
5
+ #
6
+ # Validates: conventional commit format, debug statements, hardcoded secrets
7
+
8
+ INPUT=$(cat)
9
+
10
+ # Parse command — use jq if available, fall back to grep
11
+ if command -v jq >/dev/null 2>&1; then
12
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
13
+ else
14
+ COMMAND=$(echo "$INPUT" | grep -oE '"command"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/"command"[[:space:]]*:[[:space:]]*"//;s/"$//')
15
+ fi
16
+
17
+ # Only process git commit commands
18
+ if ! echo "$COMMAND" | grep -qE '^git[[:space:]]+commit'; then
19
+ exit 0
20
+ fi
21
+
22
+ WARNINGS=""
23
+
24
+ # Extract commit message from -m flag
25
+ COMMIT_MSG=$(echo "$COMMAND" | grep -oE '\-m[[:space:]]+"[^"]*"' | sed 's/-m[[:space:]]*"//;s/"$//' || echo "")
26
+ if [ -z "$COMMIT_MSG" ]; then
27
+ COMMIT_MSG=$(echo "$COMMAND" | grep -oE "\-m[[:space:]]+'[^']*'" | sed "s/-m[[:space:]]*'//;s/'$//" || echo "")
28
+ fi
29
+
30
+ # Validate conventional commit format (type(scope): message or type: message)
31
+ if [ -n "$COMMIT_MSG" ]; then
32
+ if ! echo "$COMMIT_MSG" | grep -qE '^(feat|fix|docs|refactor|chore|test|style|perf|ci|build|revert)(\([a-zA-Z0-9_-]+\))?(!)?:[[:space:]].+'; then
33
+ WARNINGS="$WARNINGS\nCOMMIT: Message does not follow conventional commit format: type(scope): message"
34
+ fi
35
+ fi
36
+
37
+ # Check staged files for debug statements and secrets
38
+ STAGED=$(git diff --cached --name-only 2>/dev/null)
39
+ if [ -n "$STAGED" ]; then
40
+ # Read full staged diff once (avoids repeated git subprocess calls per file)
41
+ FULL_DIFF=$(git diff --cached 2>/dev/null)
42
+
43
+ while IFS= read -r file; do
44
+ if [ -f "$file" ]; then
45
+ FILE_DIFF=$(echo "$FULL_DIFF" | sed -n "/^diff --git a\/$file /,/^diff --git /p")
46
+ # JavaScript/TypeScript debug
47
+ if echo "$file" | grep -qE '\.(js|ts|jsx|tsx)$'; then
48
+ if echo "$FILE_DIFF" | grep -E '^\+.*console\.(log|debug|warn)\(' | grep -qv '//.*console'; then
49
+ WARNINGS="$WARNINGS\nDEBUG: $file has console.log/debug/warn in staged changes"
50
+ fi
51
+ if echo "$FILE_DIFF" | grep -qE '^\+.*debugger'; then
52
+ WARNINGS="$WARNINGS\nDEBUG: $file has debugger statement in staged changes"
53
+ fi
54
+ fi
55
+ # PHP debug
56
+ if echo "$file" | grep -qE '\.php$'; then
57
+ if echo "$FILE_DIFF" | grep -qE '^\+.*(dd\(|dump\(|var_dump\(|print_r\()'; then
58
+ WARNINGS="$WARNINGS\nDEBUG: $file has dd/dump/var_dump in staged changes"
59
+ fi
60
+ fi
61
+ # Python debug
62
+ if echo "$file" | grep -qE '\.py$'; then
63
+ if echo "$FILE_DIFF" | grep -qE '^\+.*(breakpoint\(\)|pdb\.set_trace\(\))'; then
64
+ WARNINGS="$WARNINGS\nDEBUG: $file has breakpoint/pdb in staged changes"
65
+ fi
66
+ fi
67
+ fi
68
+ done <<< "$STAGED"
69
+
70
+ # Check for potential hardcoded secrets (reuse FULL_DIFF)
71
+ if echo "$FULL_DIFF" | grep -qE '^\+.*(PRIVATE_KEY|SECRET_KEY|API_KEY|PASSWORD|TOKEN)[[:space:]]*=.*[a-zA-Z0-9]{16,}'; then
72
+ WARNINGS="$WARNINGS\nSECRET: Staged changes may contain hardcoded secrets. Review before committing."
73
+ fi
74
+ fi
75
+
76
+ # Print warnings (non-blocking) and allow commit
77
+ if [ -n "$WARNINGS" ]; then
78
+ echo -e "=== Commit Validation Warnings ===$WARNINGS\n================================" >&2
79
+ fi
80
+
81
+ exit 0
@@ -0,0 +1,43 @@
1
+ #!/bin/bash
2
+ # Claude Code PreToolUse hook: Warns on push to protected branches
3
+ # Receives JSON on stdin with tool_input.command
4
+ # Exit 0 = allow (warnings only), Exit 2 = block
5
+ #
6
+ # Warns on: push to main/master/production/release, force push
7
+
8
+ INPUT=$(cat)
9
+
10
+ # Parse command
11
+ if command -v jq >/dev/null 2>&1; then
12
+ COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
13
+ else
14
+ COMMAND=$(echo "$INPUT" | grep -oE '"command"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/"command"[[:space:]]*:[[:space:]]*"//;s/"$//')
15
+ fi
16
+
17
+ # Only process git push commands
18
+ if ! echo "$COMMAND" | grep -qE '^git[[:space:]]+push'; then
19
+ exit 0
20
+ fi
21
+
22
+ WARNINGS=""
23
+
24
+ # Check for protected branch names
25
+ for branch in main master production release; do
26
+ if echo "$COMMAND" | grep -qE "(origin[[:space:]]+${branch}|[[:space:]]${branch}$)"; then
27
+ WARNINGS="$WARNINGS\nPROTECTED: Pushing to '${branch}' — this is a protected branch. Confirm this is intentional."
28
+ fi
29
+ done
30
+
31
+ # Check for force push
32
+ if echo "$COMMAND" | grep -qE '\-\-force([[:space:]]|$)|\-f([[:space:]]|$)'; then
33
+ WARNINGS="$WARNINGS\nFORCE: Using --force push. This rewrites remote history and is destructive."
34
+ fi
35
+ if echo "$COMMAND" | grep -qE '\-\-force-with-lease'; then
36
+ WARNINGS="$WARNINGS\nFORCE: Using --force-with-lease. Safer than --force but still rewrites history."
37
+ fi
38
+
39
+ if [ -n "$WARNINGS" ]; then
40
+ echo -e "=== Push Validation Warnings ===$WARNINGS\n================================" >&2
41
+ fi
42
+
43
+ exit 0