@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.
- package/lib/setup-hook.mjs +46 -2
- package/package.json +1 -1
package/lib/setup-hook.mjs
CHANGED
|
@@ -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}`);
|