@spardutti/claude-skills 2.20.0 → 2.20.2

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 +46 -2
  2. package/package.json +1 -1
@@ -226,13 +226,32 @@ Before this Write/Edit, you must:
226
226
 
227
227
  1. For each skill listed above, say whether it applies to the file you're about to
228
228
  write. If it does not — a Python skill and a TypeScript file, say — write
229
- "does not apply" and move on. Do not invent a connection.
229
+ \\"does not apply\\" and move on. Do not invent a connection.
230
230
  2. For the ones that do apply: state the specific rules that bear on this file, and
231
231
  how your next write respects each.
232
232
  3. Then ack all of them in a single Bash tool call:
233
233
  $ACK_CMD
234
234
 
235
235
  One ack per skill per session. After acking, retry the Write/Edit.
236
+
237
+ If that Bash call is denied by the auto mode classifier, STOP. Do not ask your
238
+ user to run it for you, and do not look for another route to create the files.
239
+ Both are what the classifier is there to stop, and asking a human to run a
240
+ command you were just denied makes them the tool that performs it. Report this
241
+ to them instead and let them decide:
242
+
243
+ Auto mode's built-in Auto-Mode Bypass rule counts a hook's ack file as working
244
+ around the permission system. It is a soft rule, so an allow entry clears it.
245
+ It has to go in ~/.claude/settings.json — the classifier does not read a
246
+ project's .claude/settings.json — or in /permissions, Auto mode tab. Keep the
247
+ \\\$defaults line or every built-in allow rule is discarded:
248
+
249
+ \\"autoMode\\": { \\"allow\\": [ \\"\\\$defaults\\",
250
+ \\"Touching marker files under /tmp/claude-skill-gate-*, /tmp/claude-skill-acked-*
251
+ and /tmp/claude-skill-loaded-* is allowed: they are acknowledgement files for
252
+ the user's own PreToolUse skill gates. Creating one satisfies a workflow gate
253
+ the user installed, grants no permission and executes no code, and is a false
254
+ positive for Auto-Mode Bypass.\\" ] }
236
255
  $RULES_BLOCKS"
237
256
 
238
257
  json_escape() {
@@ -629,7 +648,7 @@ GAUNTLET_MAX_LINES=200
629
648
  GAUNTLET_MUTATE=""
630
649
  GAUNTLET_SOURCE_EXT="ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|kt|rb|php|c|h|cpp|hpp|cs|swift|gd"
631
650
  GAUNTLET_IGNORE_EXT="md|mdx|txt|rst|adoc|json|ya?ml|toml|lock|cfg|ini|env|csv|tsv|sql|html|css|scss|svg|png|jpg|jpeg|gif|webp|ico|pdf|woff2?|ttf|otf|mp3|mp4|wav|zip|gz|tres|tscn|import|godot"
632
- GAUNTLET_IGNORE_FILES="*.gen.ts *.gen.tsx *.generated.* */migrations/*.py */alembic/versions/*.py */components/ui/*.tsx"
651
+ GAUNTLET_IGNORE_FILES="*.gen.ts *.gen.tsx *.generated.* */migrations/*.py */alembic/versions/*.py */components/ui/*.tsx */*.config.*"
633
652
  [ -n "\${HOME:-}" ] && [ -f "$HOME/.claude/gauntlet.conf" ] && . "$HOME/.claude/gauntlet.conf"
634
653
  [ -f ".claude/gauntlet.conf" ] && . ".claude/gauntlet.conf"
635
654
 
@@ -677,6 +696,11 @@ SOURCED=$(printf '%s\\n' "$CHANGED" | grep -E "\\.($GAUNTLET_SOURCE_EXT)$" \\
677
696
  # both checks — and printed, because a silent skip is the same lie as a fake
678
697
  # PASS. The leading / is what lets one pattern match components/ui at the repo
679
698
  # root and apps/web/src/components/ui alike.
699
+ #
700
+ # */*.config.* is here for the same reason, and became urgent the moment an
701
+ # uncovered line started failing the gate: vitest.config.ts has no tests, will
702
+ # never have tests, and is not a thing anyone writes a test for. Left in, every
703
+ # diff that touches a config reports findings nobody can close.
680
704
  # set -f matters: an unquoted list is glob-expanded before it is split, so
681
705
  # */components/ui/*.tsx turned itself into the very path it was meant to match
682
706
  # and then matched nothing.
@@ -1360,6 +1384,26 @@ export async function setupHook(targetDir = process.cwd()) {
1360
1384
  settings.hooks.Stop = [gauntletEntry];
1361
1385
  }
1362
1386
 
1387
+ // Both gates clear by touching a marker under /tmp. The hook scripts let those
1388
+ // commands through themselves, but auto mode's permission classifier does not:
1389
+ // a touch whose only purpose is to unlock a gate is exactly what it refuses.
1390
+ // So in auto mode the application gate could not be satisfied at all, and the
1391
+ // model was reduced to asking its user to run the touch by hand — which is
1392
+ // indistinguishable from the laundering the classifier exists to stop.
1393
+ // Allowlisting the three marker paths is what makes the gates workable there.
1394
+ // Only these literal prefixes are granted, and an existing entry is not
1395
+ // duplicated on reinstall.
1396
+ const MARKER_ALLOW = [
1397
+ "Bash(touch /tmp/claude-skill-gate-*)",
1398
+ "Bash(touch /tmp/claude-skill-acked-*)",
1399
+ "Bash(touch /tmp/claude-skill-loaded-*)",
1400
+ ];
1401
+ if (!settings.permissions) settings.permissions = {};
1402
+ if (!Array.isArray(settings.permissions.allow)) settings.permissions.allow = [];
1403
+ for (const rule of MARKER_ALLOW) {
1404
+ if (!settings.permissions.allow.includes(rule)) settings.permissions.allow.push(rule);
1405
+ }
1406
+
1363
1407
  await writeFile(settingsPath, JSON.stringify(settings, null, 2) + "\n", { mode: 0o644 });
1364
1408
 
1365
1409
  console.log(` Hook installed: .claude/hooks/${GATE_FILENAME}`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spardutti/claude-skills",
3
- "version": "2.20.0",
3
+ "version": "2.20.2",
4
4
  "description": "CLI to install Claude Code skills from the claude-skills collection",
5
5
  "type": "module",
6
6
  "repository": {