@iceinvein/agent-skills 0.18.1 → 0.18.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.
package/dist/cli/index.js
CHANGED
|
@@ -425,6 +425,7 @@ function resolveBundlePaths(entries, bundle) {
|
|
|
425
425
|
|
|
426
426
|
// src/cli/adapters/claude.ts
|
|
427
427
|
import { chmodSync, existsSync as existsSync2, mkdirSync, rmSync, rmdirSync, statSync, unlinkSync } from "node:fs";
|
|
428
|
+
import { homedir } from "node:os";
|
|
428
429
|
import { dirname, join as join2 } from "node:path";
|
|
429
430
|
function shouldBeExecutable(relPath, content) {
|
|
430
431
|
if (relPath.endsWith(".sh"))
|
|
@@ -455,6 +456,12 @@ function matchesSkillDirective(hook, skillName, directive) {
|
|
|
455
456
|
return true;
|
|
456
457
|
return hook.command.includes(`Activate ${skillName} skill`);
|
|
457
458
|
}
|
|
459
|
+
function commandRunsScript(command, scriptPath, settingsPath) {
|
|
460
|
+
const home = homedir();
|
|
461
|
+
const config = dirname(settingsPath);
|
|
462
|
+
const expanded = command.replaceAll("${CLAUDE_CONFIG_DIR:-$HOME/.claude}", config).replaceAll("${CLAUDE_CONFIG_DIR:-${HOME}/.claude}", config).replaceAll("${CLAUDE_CONFIG_DIR}", config).replaceAll("$CLAUDE_CONFIG_DIR", config).replaceAll("${HOME}", home).replaceAll("$HOME", home).replaceAll("~/", `${home}/`);
|
|
463
|
+
return expanded.includes(scriptPath);
|
|
464
|
+
}
|
|
458
465
|
async function wireSessionStartHook(settingsPath, skillName, directive, scriptPath) {
|
|
459
466
|
let settings = {};
|
|
460
467
|
if (existsSync2(settingsPath)) {
|
|
@@ -468,6 +475,7 @@ async function wireSessionStartHook(settingsPath, skillName, directive, scriptPa
|
|
|
468
475
|
const legacy = `echo ${shq(directive)}`;
|
|
469
476
|
let adopted = false;
|
|
470
477
|
let custom = false;
|
|
478
|
+
let customRunsScript = false;
|
|
471
479
|
let changed = false;
|
|
472
480
|
for (const group of settings.hooks.SessionStart) {
|
|
473
481
|
const kept = [];
|
|
@@ -479,6 +487,9 @@ async function wireSessionStartHook(settingsPath, skillName, directive, scriptPa
|
|
|
479
487
|
const plain = hook.skill !== undefined || hook.command === legacy;
|
|
480
488
|
if (!plain) {
|
|
481
489
|
custom = true;
|
|
490
|
+
if (scriptPath && commandRunsScript(hook.command ?? "", scriptPath, settingsPath)) {
|
|
491
|
+
customRunsScript = true;
|
|
492
|
+
}
|
|
482
493
|
kept.push(hook);
|
|
483
494
|
continue;
|
|
484
495
|
}
|
|
@@ -499,7 +510,7 @@ async function wireSessionStartHook(settingsPath, skillName, directive, scriptPa
|
|
|
499
510
|
}
|
|
500
511
|
settings.hooks.SessionStart = settings.hooks.SessionStart.filter((group) => !group.hooks || group.hooks.length > 0);
|
|
501
512
|
if (adopted || custom) {
|
|
502
|
-
if (custom && !adopted && scriptPath) {
|
|
513
|
+
if (custom && !adopted && scriptPath && !customRunsScript) {
|
|
503
514
|
console.warn(`${skillName}: a hand-edited SessionStart hook already carries its directive, so it was left as is and ${scriptPath} was not wired; add it to that entry yourself if you want it.`);
|
|
504
515
|
}
|
|
505
516
|
if (changed) {
|
|
@@ -3418,9 +3429,9 @@ async function pickActivation(skillName, modes) {
|
|
|
3418
3429
|
// src/cli/index.ts
|
|
3419
3430
|
import { mkdirSync as mkdirSync4 } from "fs";
|
|
3420
3431
|
import { join as join11 } from "path";
|
|
3421
|
-
import { homedir } from "os";
|
|
3432
|
+
import { homedir as homedir2 } from "os";
|
|
3422
3433
|
async function otherScopeSkillCount(currentDir) {
|
|
3423
|
-
const home =
|
|
3434
|
+
const home = homedir2();
|
|
3424
3435
|
const otherDir = currentDir === home ? process.cwd() : home;
|
|
3425
3436
|
if (otherDir === currentDir)
|
|
3426
3437
|
return { scope: "global", count: 0 };
|
|
@@ -3432,7 +3443,7 @@ async function otherScopeSkillCount(currentDir) {
|
|
|
3432
3443
|
}
|
|
3433
3444
|
function resolveInstallDir(flags) {
|
|
3434
3445
|
if (flags.global !== undefined || flags.g !== undefined) {
|
|
3435
|
-
return
|
|
3446
|
+
return homedir2();
|
|
3436
3447
|
}
|
|
3437
3448
|
return process.cwd();
|
|
3438
3449
|
}
|
|
@@ -3569,7 +3580,7 @@ async function main() {
|
|
|
3569
3580
|
case "install":
|
|
3570
3581
|
case "browse": {
|
|
3571
3582
|
const installDir = resolveInstallDir(flags);
|
|
3572
|
-
const isGlobal = installDir ===
|
|
3583
|
+
const isGlobal = installDir === homedir2();
|
|
3573
3584
|
let names = args;
|
|
3574
3585
|
if (names.length === 0 || command === "browse") {
|
|
3575
3586
|
if (!process.stdin.isTTY) {
|
|
@@ -3770,7 +3781,7 @@ ${m.name} v${m.version}`);
|
|
|
3770
3781
|
break;
|
|
3771
3782
|
}
|
|
3772
3783
|
if (command !== "update") {
|
|
3773
|
-
const checkDir = flags.global !== undefined || flags.g !== undefined ?
|
|
3784
|
+
const checkDir = flags.global !== undefined || flags.g !== undefined ? homedir2() : process.cwd();
|
|
3774
3785
|
const outdated = await checkForUpdates(checkDir);
|
|
3775
3786
|
if (outdated.length > 0) {
|
|
3776
3787
|
const list = outdated.map((s) => `${s.name} (v${s.installed} \u2192 v${s.latest})`).join(", ");
|
package/package.json
CHANGED
package/skills/index.json
CHANGED
|
@@ -283,7 +283,7 @@
|
|
|
283
283
|
"name": "sluice",
|
|
284
284
|
"description": "Routes work by change shape into four channels (bypass, fast, main, deep) and applies only the rules each channel needs, so a one-line fix does not pay the cost of a multi-subsystem build. Carries seven rules as one-liners in the router and the full treatment in references read only on friction. Checks the finished plan with plan.sh validate rather than trusting it to memory, seeds the run state from it, keeps a deep run's task breakdown in .sluice/run.json so a statusline segment, one status command and a SessionStart hook can answer where the run is (the hook prints a live run at every session start, compaction included), and closes each run with a ledger read out of the session transcript: elapsed, tools, tokens, and what each dispatched agent cost where the transcript recorded it. Claude Code only; stands down where the superpowers pipeline governs the repo.",
|
|
285
285
|
"type": "prompt",
|
|
286
|
-
"version": "0.19.
|
|
286
|
+
"version": "0.19.3"
|
|
287
287
|
},
|
|
288
288
|
{
|
|
289
289
|
"name": "temporal-coupling-detector",
|
|
@@ -31,6 +31,52 @@ CONFIGURED="$(jq -r '.statusLine.command // empty' "$SETTINGS" 2>/dev/null || tr
|
|
|
31
31
|
[ -n "$CONFIGURED" ] || exit 0
|
|
32
32
|
|
|
33
33
|
RENDER="$(cd "$(dirname "$RENDER")" && pwd)/$(basename "$RENDER")"
|
|
34
|
+
# Physical, and so is every candidate below it: a tmpdir or a home reached
|
|
35
|
+
# through a symlink resolves one way from here and the other way out of a
|
|
36
|
+
# settings string, and the containment check below compares the two.
|
|
37
|
+
CONFIG="$(cd "$BUNDLE/../.." && pwd -P)"
|
|
38
|
+
|
|
39
|
+
# Someone who pasted the two lines a release ago has nothing left to do, and
|
|
40
|
+
# saying it again on every update is the one thing they cannot switch off. So
|
|
41
|
+
# the script the slot runs is read before anything is printed.
|
|
42
|
+
#
|
|
43
|
+
# It is recovered rather than known: settings.json holds a shell command, so
|
|
44
|
+
# every token carrying a slash is tried as a path, with the two variables a
|
|
45
|
+
# config path is ever written through expanded by substitution. Not by eval,
|
|
46
|
+
# which on a settings file means running its contents. A token that resolves to
|
|
47
|
+
# nothing is skipped and the instructions print as they did before, so a command
|
|
48
|
+
# this cannot read costs a notice rather than a wrong silence.
|
|
49
|
+
#
|
|
50
|
+
# Only paths inside the config directory this skill installed into are opened.
|
|
51
|
+
# The slot is someone elses shell string and may name anything; a postinstall
|
|
52
|
+
# that followed it wherever it pointed would be reading arbitrary files off a
|
|
53
|
+
# line it does not control.
|
|
54
|
+
statusline_script() {
|
|
55
|
+
local tok path dir
|
|
56
|
+
for tok in $(printf '%s' "$1" | tr -s "\"'| \t" '\n'); do
|
|
57
|
+
case "$tok" in */*) ;; *) continue ;; esac
|
|
58
|
+
path="$tok"
|
|
59
|
+
path="${path//\$\{CLAUDE_CONFIG_DIR:-\$HOME\/.claude\}/$CONFIG}"
|
|
60
|
+
path="${path//\$\{CLAUDE_CONFIG_DIR\}/$CONFIG}"
|
|
61
|
+
path="${path//\$CLAUDE_CONFIG_DIR/$CONFIG}"
|
|
62
|
+
path="${path//\$\{HOME\}/$HOME}"
|
|
63
|
+
path="${path//\$HOME/$HOME}"
|
|
64
|
+
case "$path" in "~/"*) path="$HOME/${path#\~/}" ;; esac
|
|
65
|
+
[ -f "$path" ] || continue
|
|
66
|
+
dir="$(cd "$(dirname "$path")" 2>/dev/null && pwd -P)"
|
|
67
|
+
[ -n "$dir" ] || continue
|
|
68
|
+
path="$dir/$(basename "$path")"
|
|
69
|
+
case "$path" in "$CONFIG"/*) ;; *) continue ;; esac
|
|
70
|
+
printf '%s\n' "$path"
|
|
71
|
+
return 0
|
|
72
|
+
done
|
|
73
|
+
return 1
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
SLOT_SCRIPT="$(statusline_script "$CONFIGURED" || true)"
|
|
77
|
+
if [ -n "$SLOT_SCRIPT" ] && grep -q "skills/sluice/scripts/statusline.sh" "$SLOT_SCRIPT" 2>/dev/null; then
|
|
78
|
+
exit 0
|
|
79
|
+
fi
|
|
34
80
|
|
|
35
81
|
# The slot points at the bundled command: the install claimed it and there is
|
|
36
82
|
# nothing for anyone to paste. Say so rather than print instructions that would
|
package/skills/sluice/skill.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sluice",
|
|
3
|
-
"version": "0.19.
|
|
3
|
+
"version": "0.19.3",
|
|
4
4
|
"description": "Routes work by change shape into four channels (bypass, fast, main, deep) and applies only the rules each channel needs, so a one-line fix does not pay the cost of a multi-subsystem build. Carries seven rules as one-liners in the router and the full treatment in references read only on friction. Checks the finished plan with plan.sh validate rather than trusting it to memory, seeds the run state from it, keeps a deep run's task breakdown in .sluice/run.json so a statusline segment, one status command and a SessionStart hook can answer where the run is (the hook prints a live run at every session start, compaction included), and closes each run with a ledger read out of the session transcript: elapsed, tools, tokens, and what each dispatched agent cost where the transcript recorded it. Claude Code only; stands down where the superpowers pipeline governs the repo.",
|
|
5
5
|
"author": "iceinvein",
|
|
6
6
|
"type": "prompt",
|