@iceinvein/agent-skills 0.1.16 → 0.1.17

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
@@ -657,6 +657,111 @@ async function updateAllSkills(cwd) {
657
657
  return results;
658
658
  }
659
659
 
660
+ // src/cli/commands/bump.ts
661
+ import { join as join7 } from "node:path";
662
+
663
+ // src/cli/semver.ts
664
+ function bumpVersion(current, level) {
665
+ const parts = current.split(".");
666
+ if (parts.length !== 3 || parts.some((p) => !/^\d+$/.test(p))) {
667
+ throw new Error(`Invalid semver version: '${current}'`);
668
+ }
669
+ const [major, minor, patch] = parts.map(Number);
670
+ switch (level) {
671
+ case "major":
672
+ return `${major + 1}.0.0`;
673
+ case "minor":
674
+ return `${major}.${minor + 1}.0`;
675
+ case "patch":
676
+ return `${major}.${minor}.${patch + 1}`;
677
+ }
678
+ }
679
+
680
+ // src/cli/commands/bump.ts
681
+ async function bumpSkill(repoRoot, skillName, level) {
682
+ const manifestPath = join7(repoRoot, "skills", skillName, "skill.json");
683
+ const file = Bun.file(manifestPath);
684
+ if (!await file.exists()) {
685
+ return { ok: false, error: `Skill '${skillName}' not found at skills/${skillName}/skill.json` };
686
+ }
687
+ const manifest = await file.json();
688
+ const from = manifest.version;
689
+ let to;
690
+ try {
691
+ to = bumpVersion(from, level);
692
+ } catch (e) {
693
+ return { ok: false, error: `Invalid version '${from}' in skills/${skillName}/skill.json` };
694
+ }
695
+ manifest.version = to;
696
+ await Bun.write(manifestPath, JSON.stringify(manifest, null, 2) + `
697
+ `);
698
+ return { ok: true, from, to };
699
+ }
700
+ function getLatestTag(repoRoot) {
701
+ const result = Bun.spawnSync(["git", "describe", "--tags", "--abbrev=0"], {
702
+ cwd: repoRoot
703
+ });
704
+ if (result.exitCode !== 0)
705
+ return null;
706
+ return result.stdout.toString().trim();
707
+ }
708
+ var EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
709
+ function getChangedSkills(repoRoot, sinceTag) {
710
+ const base = sinceTag ?? EMPTY_TREE;
711
+ const args = ["git", "diff", "--name-only", base, "HEAD", "--", "skills/"];
712
+ const result = Bun.spawnSync(args, { cwd: repoRoot });
713
+ const output = result.stdout.toString().trim();
714
+ if (!output)
715
+ return new Set;
716
+ const names = new Set;
717
+ for (const line of output.split(`
718
+ `)) {
719
+ const parts = line.split("/");
720
+ if (parts.length >= 2 && parts[0] === "skills") {
721
+ names.add(parts[1]);
722
+ }
723
+ }
724
+ return names;
725
+ }
726
+ function skillVersionChanged(repoRoot, skillName, sinceTag) {
727
+ const base = sinceTag ?? EMPTY_TREE;
728
+ const args = ["git", "diff", base, "HEAD", "--", `skills/${skillName}/skill.json`];
729
+ const result = Bun.spawnSync(args, { cwd: repoRoot });
730
+ const diff = result.stdout.toString();
731
+ const hasRemoved = diff.split(`
732
+ `).some((l) => l.startsWith("-") && !l.startsWith("---") && l.includes('"version"'));
733
+ const hasAdded = diff.split(`
734
+ `).some((l) => l.startsWith("+") && !l.startsWith("+++") && l.includes('"version"'));
735
+ return hasRemoved && hasAdded;
736
+ }
737
+ async function bumpAllChanged(repoRoot, level, dryRun) {
738
+ const tag = getLatestTag(repoRoot);
739
+ const changed = getChangedSkills(repoRoot, tag);
740
+ const results = [];
741
+ for (const skillName of changed) {
742
+ if (skillVersionChanged(repoRoot, skillName, tag))
743
+ continue;
744
+ if (dryRun) {
745
+ const manifestPath = join7(repoRoot, "skills", skillName, "skill.json");
746
+ const file = Bun.file(manifestPath);
747
+ if (!await file.exists())
748
+ continue;
749
+ const manifest = await file.json();
750
+ const from = manifest.version;
751
+ try {
752
+ const to = bumpVersion(from, level);
753
+ results.push({ name: skillName, ok: true, from, to });
754
+ } catch {
755
+ results.push({ name: skillName, ok: false, error: `Invalid version '${from}'` });
756
+ }
757
+ } else {
758
+ const result = await bumpSkill(repoRoot, skillName, level);
759
+ results.push({ name: skillName, ...result });
760
+ }
761
+ }
762
+ return results;
763
+ }
764
+
660
765
  // src/cli/update-check.ts
661
766
  var CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
662
767
  async function checkForUpdates(cwd) {
@@ -730,7 +835,7 @@ Select (comma-separated numbers, e.g. 1,3): `);
730
835
 
731
836
  // src/cli/index.ts
732
837
  import { mkdirSync as mkdirSync4 } from "fs";
733
- import { join as join7 } from "path";
838
+ import { join as join8 } from "path";
734
839
  import { homedir } from "os";
735
840
  function resolveInstallDir(flags) {
736
841
  if (flags.global !== undefined || flags.g !== undefined) {
@@ -738,7 +843,7 @@ function resolveInstallDir(flags) {
738
843
  }
739
844
  return process.cwd();
740
845
  }
741
- var BOOLEAN_FLAGS = new Set(["global", "g", "all"]);
846
+ var BOOLEAN_FLAGS = new Set(["global", "g", "all", "dry-run"]);
742
847
  function parseArgs(argv) {
743
848
  if (argv.length === 0)
744
849
  return { command: "help", args: [], flags: {} };
@@ -772,12 +877,15 @@ Usage:
772
877
  agent-skills remove <skill> [-g] Remove a skill
773
878
  agent-skills update <skill> [-g] Update a skill
774
879
  agent-skills update --all [-g] Update all installed skills
880
+ agent-skills bump <skill> [patch|minor|major] Bump a skill's version
881
+ agent-skills bump --all [patch|minor|major] Bump all changed skills
775
882
  agent-skills list List available skills
776
883
  agent-skills info <skill> Show skill details
777
884
 
778
885
  Flags:
779
886
  --tool <tool> Install for a specific tool (${TOOL_NAMES2.join(", ")})
780
887
  -g, --global Install to home directory (available in all projects)
888
+ --dry-run With bump --all: check without writing (exit 1 if unbumped)
781
889
  `);
782
890
  }
783
891
  function printInstalled(result, skipped) {
@@ -838,7 +946,7 @@ async function main() {
838
946
  gemini: ".gemini"
839
947
  };
840
948
  if (dirs[tool]) {
841
- mkdirSync4(join7(installDir, dirs[tool]), { recursive: true });
949
+ mkdirSync4(join8(installDir, dirs[tool]), { recursive: true });
842
950
  }
843
951
  }
844
952
  } else {
@@ -943,6 +1051,53 @@ ${m.name} v${m.version}`);
943
1051
  console.log(` Package: ${m.mcp.package}`);
944
1052
  break;
945
1053
  }
1054
+ case "bump": {
1055
+ const BUMP_LEVELS = ["patch", "minor", "major"];
1056
+ const repoRoot = import.meta.dir.replace(/\/dist\/cli$|\/src\/cli$/, "");
1057
+ if (flags.all !== undefined) {
1058
+ const levelArg = args[0] ?? "patch";
1059
+ if (!BUMP_LEVELS.includes(levelArg)) {
1060
+ console.error(`Error: invalid bump level '${levelArg}'. Must be one of: ${BUMP_LEVELS.join(", ")}`);
1061
+ process.exit(1);
1062
+ }
1063
+ const dryRun = flags["dry-run"] !== undefined;
1064
+ const results = await bumpAllChanged(repoRoot, levelArg, dryRun);
1065
+ if (results.length === 0) {
1066
+ if (!dryRun)
1067
+ console.log("All skill versions are up to date.");
1068
+ process.exit(0);
1069
+ }
1070
+ for (const r of results) {
1071
+ if (!r.ok) {
1072
+ console.error(` \u2717 ${r.name}: ${r.error}`);
1073
+ } else if (dryRun) {
1074
+ console.log(` needs bump: ${r.name} ${r.from} \u2192 ${r.to}`);
1075
+ } else {
1076
+ console.log(` \u2713 ${r.name} ${r.from} \u2192 ${r.to}`);
1077
+ }
1078
+ }
1079
+ if (dryRun)
1080
+ process.exit(1);
1081
+ break;
1082
+ }
1083
+ const skillName = args[0];
1084
+ if (!skillName) {
1085
+ console.error("Error: skill name required. Usage: agent-skills bump <skill> [patch|minor|major]");
1086
+ process.exit(1);
1087
+ }
1088
+ const level = args[1] ?? "patch";
1089
+ if (!BUMP_LEVELS.includes(level)) {
1090
+ console.error(`Error: invalid bump level '${args[1]}'. Must be one of: ${BUMP_LEVELS.join(", ")}`);
1091
+ process.exit(1);
1092
+ }
1093
+ const result = await bumpSkill(repoRoot, skillName, level);
1094
+ if (!result.ok) {
1095
+ console.error(`Error: ${result.error}`);
1096
+ process.exit(1);
1097
+ }
1098
+ console.log(`\u2713 ${skillName} ${result.from} \u2192 ${result.to}`);
1099
+ break;
1100
+ }
946
1101
  case "help":
947
1102
  default:
948
1103
  printHelp();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iceinvein/agent-skills",
3
- "version": "0.1.16",
3
+ "version": "0.1.17",
4
4
  "description": "Install agent skills into AI coding tools",
5
5
  "author": "iceinvein",
6
6
  "license": "MIT",
@@ -15,7 +15,11 @@
15
15
  "scripts": {
16
16
  "build": "bun build src/cli/index.ts --outdir dist/cli --target bun",
17
17
  "test": "bun test",
18
- "dev": "bun run src/cli/index.ts"
18
+ "dev": "bun run src/cli/index.ts",
19
+ "skill:bump": "bun run src/cli/index.ts bump",
20
+ "skill:bump:all": "bun run src/cli/index.ts bump --all",
21
+ "skill:bump:check": "bun run src/cli/index.ts bump --all --dry-run",
22
+ "release": "bash scripts/release.sh"
19
23
  },
20
24
  "keywords": [
21
25
  "ai",
@@ -36,9 +36,27 @@ Every response, cut these patterns:
36
36
  - Kill: [explanation] "So in summary, what we did was update the middleware to validate tokens correctly, which should fix the authentication issue."
37
37
  - Write: [explanation ends]
38
38
 
39
- **Narrating actions** — don't announce what you're about to do. Just do it.
39
+ **Narrating actions** — don't announce what you're about to do. Just do it. The tool call is the communication. Never preface a tool call with text explaining that you're about to make it.
40
40
  - Kill: "Let me take a look at the file for you. I'll read it now and analyze what's going on."
41
- - Write: [reads the file]
41
+ - Kill: "Now let me fix that issue."
42
+ - Kill: "Let me check the tests."
43
+ - Kill: "I'll update the config next."
44
+ - Kill: "We need to update the schema first."
45
+ - Kill: "First, I'll read the file to understand the structure."
46
+ - Write: [tool call — no preamble]
47
+
48
+ **Banned action-narration openers** — these phrases before a tool call are always filler. Cut them 100% of the time:
49
+ - "Let me..." / "Now let me..." / "Now I'll..."
50
+ - "I'll..." / "I need to..." / "We need to..."
51
+ - "First, let me..." / "Next, I'll..."
52
+ - "Going to..." / "I'm going to..."
53
+ - "Time to..." / "Let's..."
54
+
55
+ If context is needed between tool calls, state the *finding* or *decision*, not the action:
56
+ - Kill: "Now let me update the handler to fix this."
57
+ - Write: "The handler is missing the null check." [edits file]
58
+ - Kill: "Let me run the tests to verify."
59
+ - Write: [runs tests]
42
60
 
43
61
  **Over-explaining the obvious** — don't describe trivial operations.
44
62
  - Kill: "I'll create a new file called `utils.ts`. This file will contain utility functions that we can reuse across the project."
@@ -1,10 +1,15 @@
1
1
  {
2
2
  "name": "terse",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Professional output compression — proper grammar, no fluff, ~50-60% fewer tokens. Three levels: clean, tight, sharp.",
5
5
  "author": "iceinvein",
6
6
  "type": "prompt",
7
- "tools": ["claude", "cursor", "codex", "gemini"],
7
+ "tools": [
8
+ "claude",
9
+ "cursor",
10
+ "codex",
11
+ "gemini"
12
+ ],
8
13
  "files": {
9
14
  "prompt": "SKILL.md"
10
15
  },