@spardutti/claude-skills 1.27.0 → 1.27.3

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 +23 -12
  2. package/package.json +1 -1
@@ -2,17 +2,24 @@ 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
- // the assistant has emitted the literal sentinel [skills-checked] since
6
- // the most recent user prompt. Resets every user turn, runs once per
7
- // turn (subsequent edits in the same turn pass through).
5
+ // a per-prompt marker file exists at $PROJECT_DIR/.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).
13
+ //
14
+ // LAST_PROMPT_UUID is detected by matching user-role lines whose content
15
+ // is a JSON string ("role":"user","content":"..."), which excludes
16
+ // tool_results, skill loads, task notifications, and slash-command
17
+ // payloads (all of which use array content).
8
18
  //
9
19
  // Pass-through cases:
10
20
  // - project has no .claude/skills/*/SKILL.md files
11
21
  // - transcript_path missing or unreadable
12
- // - no user prompt found in transcript
13
- //
14
- // tool_result lines (which include the gate's own deny message) are
15
- // filtered out of the sentinel scan to prevent self-satisfaction.
22
+ // - no typed user prompt found in transcript
16
23
  const GATE_SCRIPT = `#!/bin/bash
17
24
  # PreToolUse gate: forces skill evaluation before file-writing tools run.
18
25
 
@@ -30,17 +37,21 @@ if [ -z "$TRANSCRIPT" ] || [ ! -f "$TRANSCRIPT" ]; then
30
37
  exit 0
31
38
  fi
32
39
 
33
- LAST_PROMPT=$(grep -n '"type":"user"' "$TRANSCRIPT" 2>/dev/null | grep -v 'tool_use_id' | tail -1 | cut -d: -f1)
34
- if [ -z "$LAST_PROMPT" ]; then
40
+ LAST_LINE=$(grep -E '"role":"user","content":"' "$TRANSCRIPT" 2>/dev/null | tail -1)
41
+ LAST_PROMPT_UUID=$(printf '%s' "$LAST_LINE" | grep -o '"uuid":"[^"]*"' | head -1 | sed 's/"uuid":"//;s/"$//')
42
+ if [ -z "$LAST_PROMPT_UUID" ]; then
35
43
  exit 0
36
44
  fi
37
45
 
38
- if tail -n +"$LAST_PROMPT" "$TRANSCRIPT" | grep -v 'tool_use_id' | grep -qF '[skills-checked]'; then
46
+ MARKER_DIR="$PROJECT_DIR/.claude"
47
+ MARKER="$MARKER_DIR/.skill-gate-$LAST_PROMPT_UUID"
48
+ if [ -f "$MARKER" ]; then
49
+ find "$MARKER_DIR" -maxdepth 1 -name '.skill-gate-*' ! -name ".skill-gate-$LAST_PROMPT_UUID" -delete 2>/dev/null
39
50
  exit 0
40
51
  fi
41
52
 
42
- cat <<'EOF'
43
- {"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"Skill evaluation required before writing or editing code. List each available skill as ACTIVATE or SKIP with a one-line reason, call Skill() for any ACTIVATE entries, then emit the literal token [skills-checked] (square brackets included) on its own line. Then retry the tool call."}}
53
+ 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. (3) Run this exact Bash command to record approval: mkdir -p .claude && touch .claude/.skill-gate-$LAST_PROMPT_UUID (4) Then retry the file edit. The marker is unique to this user prompt and is auto-cleaned on the next prompt."}}
44
55
  EOF
45
56
  exit 0
46
57
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spardutti/claude-skills",
3
- "version": "1.27.0",
3
+ "version": "1.27.3",
4
4
  "description": "CLI to install Claude Code skills from the claude-skills collection",
5
5
  "type": "module",
6
6
  "bin": {