@spardutti/claude-skills 1.28.0 → 1.28.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.
Files changed (2) hide show
  1. package/lib/setup-hook.mjs +15 -39
  2. package/package.json +1 -1
@@ -2,25 +2,15 @@ import { mkdir, writeFile, readFile, chmod } from "node:fs/promises";
2
2
  import { join, resolve } from "node:path";
3
3
 
4
4
  // PreToolUse gate on Write|Edit|MultiEdit. Blocks the tool call unless
5
- // a per-prompt marker file exists at /tmp/claude-skill-gate-<UUID>,
6
- // where <UUID> is the uuid of the most recent typed user prompt. The
7
- // assistant creates the marker via Bash; Bash output is flushed
8
- // synchronously, so the marker is race-free against the message-buffering
9
- // behavior that broke the earlier text-sentinel approach (Claude Code
10
- // writes assistant content blocks to JSONL only after the turn completes,
11
- // so [skills-checked] text emitted in the same message as a tool_use is
12
- // invisible to PreToolUse). /tmp keeps the marker out of the project
13
- // directory so it can't leak into commits.
14
- //
15
- // LAST_PROMPT_UUID is detected by matching user-role lines whose content
16
- // is a JSON string ("role":"user","content":"..."), which excludes
17
- // tool_results, skill loads, task notifications, and slash-command
18
- // payloads (all of which use array content).
5
+ // a per-session marker file exists at /tmp/claude-skill-gate-<SESSION_ID>.
6
+ // Per-session (not per-prompt) so simple confirmations like "yes" don't
7
+ // re-lock the gate after evaluation has already happened in the session.
8
+ // The PostToolUse hook on Skill creates the marker automatically; for
9
+ // all-SKIP cases the model can `touch` the path manually.
19
10
  //
20
11
  // Pass-through cases:
21
12
  // - project has no .claude/skills/*/SKILL.md files
22
- // - transcript_path missing or unreadable
23
- // - no typed user prompt found in transcript
13
+ // - session_id missing from hook input
24
14
  const GATE_SCRIPT = `#!/bin/bash
25
15
  # PreToolUse gate: forces skill evaluation before file-writing tools run.
26
16
 
@@ -33,48 +23,34 @@ if ! find "$PROJECT_DIR" -path '*/.claude/skills/*/SKILL.md' 2>/dev/null | grep
33
23
  exit 0
34
24
  fi
35
25
 
36
- TRANSCRIPT=$(printf '%s' "$INPUT" | grep -o '"transcript_path":"[^"]*"' | head -1 | sed 's/"transcript_path":"//; s/"$//')
37
- if [ -z "$TRANSCRIPT" ] || [ ! -f "$TRANSCRIPT" ]; then
38
- exit 0
39
- fi
40
-
41
- LAST_LINE=$(grep -E '"role":"user","content":"' "$TRANSCRIPT" 2>/dev/null | tail -1)
42
- LAST_PROMPT_UUID=$(printf '%s' "$LAST_LINE" | grep -o '"uuid":"[^"]*"' | head -1 | sed 's/"uuid":"//;s/"$//')
43
- if [ -z "$LAST_PROMPT_UUID" ]; then
26
+ SESSION_ID=$(printf '%s' "$INPUT" | grep -o '"session_id":"[^"]*"' | head -1 | sed 's/"session_id":"//; s/"$//')
27
+ if [ -z "$SESSION_ID" ]; then
44
28
  exit 0
45
29
  fi
46
30
 
47
- MARKER="/tmp/claude-skill-gate-$LAST_PROMPT_UUID"
31
+ MARKER="/tmp/claude-skill-gate-$SESSION_ID"
48
32
  if [ -f "$MARKER" ]; then
49
- find /tmp -maxdepth 1 -name 'claude-skill-gate-*' ! -name "claude-skill-gate-$LAST_PROMPT_UUID" -delete 2>/dev/null
50
33
  exit 0
51
34
  fi
52
35
 
53
36
  cat <<EOF
54
- {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"Skill evaluation required before file edits. (1) List each available skill as ACTIVATE or SKIP with a one-line reason. (2) Call Skill() for any ACTIVATE entries — this auto-clears the gate. If all skills are SKIP, run this exact Bash command instead: touch /tmp/claude-skill-gate-$LAST_PROMPT_UUID (3) Then retry the file edit. The marker is unique to this user prompt and is auto-cleaned on the next prompt."}}
37
+ {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"Skill evaluation required before file edits in this session. (1) List each available skill as ACTIVATE or SKIP with a one-line reason. (2) Call Skill() for any ACTIVATE entries — this auto-clears the gate for the rest of the session. If all skills are SKIP, run this exact Bash command instead: touch /tmp/claude-skill-gate-$SESSION_ID (3) Then retry the file edit."}}
55
38
  EOF
56
39
  exit 0
57
40
  `;
58
41
 
59
- // PostToolUse on Skill: auto-creates the gate marker so the model doesn't
60
- // need an explicit touch. Uses the same UUID-detection logic as the gate.
42
+ // PostToolUse on Skill: auto-creates the per-session gate marker.
61
43
  const AUTO_MARK_SCRIPT = `#!/bin/bash
62
- # PostToolUse on Skill: auto-marks the skill-gate as satisfied.
44
+ # PostToolUse on Skill: auto-marks the skill-gate as satisfied for the session.
63
45
 
64
46
  INPUT=$(cat)
65
47
 
66
- TRANSCRIPT=$(printf '%s' "$INPUT" | grep -o '"transcript_path":"[^"]*"' | head -1 | sed 's/"transcript_path":"//; s/"$//')
67
- if [ -z "$TRANSCRIPT" ] || [ ! -f "$TRANSCRIPT" ]; then
68
- exit 0
69
- fi
70
-
71
- LAST_LINE=$(grep -E '"role":"user","content":"' "$TRANSCRIPT" 2>/dev/null | tail -1)
72
- LAST_PROMPT_UUID=$(printf '%s' "$LAST_LINE" | grep -o '"uuid":"[^"]*"' | head -1 | sed 's/"uuid":"//;s/"$//')
73
- if [ -z "$LAST_PROMPT_UUID" ]; then
48
+ SESSION_ID=$(printf '%s' "$INPUT" | grep -o '"session_id":"[^"]*"' | head -1 | sed 's/"session_id":"//; s/"$//')
49
+ if [ -z "$SESSION_ID" ]; then
74
50
  exit 0
75
51
  fi
76
52
 
77
- touch "/tmp/claude-skill-gate-$LAST_PROMPT_UUID"
53
+ touch "/tmp/claude-skill-gate-$SESSION_ID"
78
54
  exit 0
79
55
  `;
80
56
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spardutti/claude-skills",
3
- "version": "1.28.0",
3
+ "version": "1.28.1",
4
4
  "description": "CLI to install Claude Code skills from the claude-skills collection",
5
5
  "type": "module",
6
6
  "bin": {