@wirecat/cli-template 0.9.0 → 0.11.0

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 (119) hide show
  1. package/.github/workflows/ci.yml +18 -0
  2. package/.github/workflows/release.yml +63 -0
  3. package/CHANGELOG.md +72 -1
  4. package/CLAUDE.md +1 -3
  5. package/bin/release +5 -3
  6. package/contracts/help.snap +2 -0
  7. package/dist/bin/clidev.js +34 -12
  8. package/dist/bundle/all-profiles-MJ6XSFOO.js +24 -0
  9. package/dist/bundle/anthropic-W5UKBZUB.js +70 -0
  10. package/dist/bundle/app-server-EZ46JAHB.js +217 -0
  11. package/dist/bundle/bun-HB6O2TTT.js +169 -0
  12. package/dist/bundle/bun-sqlite-KBXOW2ES.js +69 -0
  13. package/dist/bundle/chunk-2B5U4Z5H.js +100 -0
  14. package/dist/bundle/chunk-35KYY65W.js +122 -0
  15. package/dist/bundle/chunk-4LURWBVV.js +752 -0
  16. package/dist/bundle/chunk-5D4AEUVA.js +24783 -0
  17. package/dist/bundle/chunk-7IXL4UFK.js +158 -0
  18. package/dist/bundle/chunk-ADLS6FVG.js +24600 -0
  19. package/dist/bundle/chunk-AK257OMS.js +8353 -0
  20. package/dist/bundle/chunk-CXQXVKUY.js +24 -0
  21. package/dist/bundle/chunk-DFDN6AUB.js +21 -0
  22. package/dist/bundle/chunk-E42W72PQ.js +151 -0
  23. package/dist/bundle/chunk-EFHLQXG6.js +5104 -0
  24. package/dist/bundle/chunk-EGRB55FF.js +264 -0
  25. package/dist/bundle/chunk-ERGB4NJA.js +53 -0
  26. package/dist/bundle/chunk-ERKR3VJ5.js +1146 -0
  27. package/dist/bundle/chunk-FDBINRWA.js +884 -0
  28. package/dist/bundle/chunk-FZZIU4B7.js +34514 -0
  29. package/dist/bundle/chunk-GOO67PDU.js +2 -0
  30. package/dist/bundle/chunk-HDY5X3WQ.js +281 -0
  31. package/dist/bundle/chunk-HTQTIKWP.js +928 -0
  32. package/dist/bundle/chunk-IBBN7Z3A.js +630 -0
  33. package/dist/bundle/chunk-IDWW4TU2.js +18 -0
  34. package/dist/bundle/chunk-IGHEW777.js +164 -0
  35. package/dist/bundle/chunk-IN3FVRPK.js +76 -0
  36. package/dist/bundle/chunk-JAOGZMKQ.js +48 -0
  37. package/dist/bundle/chunk-JHO2LL2J.js +459 -0
  38. package/dist/bundle/chunk-JRK73FOW.js +78 -0
  39. package/dist/bundle/chunk-KAREKBUZ.js +24 -0
  40. package/dist/bundle/chunk-KJTNT4SW.js +82 -0
  41. package/dist/bundle/chunk-L5WWMP5M.js +1904 -0
  42. package/dist/bundle/chunk-MFS52LTZ.js +570 -0
  43. package/dist/bundle/chunk-MJRSEUKG.js +442 -0
  44. package/dist/bundle/chunk-MUSYGFCY.js +3556 -0
  45. package/dist/bundle/chunk-N2Z3MCOF.js +779 -0
  46. package/dist/bundle/chunk-NOVLCHDV.js +45 -0
  47. package/dist/bundle/chunk-O3UXNU3S.js +54 -0
  48. package/dist/bundle/chunk-O5EHUB2V.js +2 -0
  49. package/dist/bundle/chunk-OV6PHTAY.js +36226 -0
  50. package/dist/bundle/chunk-PBN4RBHS.js +2315 -0
  51. package/dist/bundle/chunk-PDGXMKJS.js +31 -0
  52. package/dist/bundle/chunk-PJOVK7PG.js +191 -0
  53. package/dist/bundle/chunk-QBP7OMN5.js +58 -0
  54. package/dist/bundle/chunk-QJ6XW4DM.js +7556 -0
  55. package/dist/bundle/chunk-QKWRL4OD.js +1028 -0
  56. package/dist/bundle/chunk-RUKDZEID.js +73 -0
  57. package/dist/bundle/chunk-SVDF6NJF.js +215 -0
  58. package/dist/bundle/chunk-TAYOKLGF.js +193 -0
  59. package/dist/bundle/chunk-TGB5F7NC.js +288 -0
  60. package/dist/bundle/chunk-V3ZTQ24B.js +161 -0
  61. package/dist/bundle/chunk-VLNKTMV7.js +3103 -0
  62. package/dist/bundle/chunk-VYSUKHKL.js +63 -0
  63. package/dist/bundle/chunk-Y5E2WNWB.js +35 -0
  64. package/dist/bundle/chunk-YJNUDHJD.js +3390 -0
  65. package/dist/bundle/chunk-Z7MSIRSQ.js +6848 -0
  66. package/dist/bundle/chunk-ZLY6GUAS.js +82 -0
  67. package/dist/bundle/chunk-ZVVMGPBJ.js +50 -0
  68. package/dist/bundle/clidev.js +22 -0
  69. package/dist/bundle/command-contract-75VJ36U4.js +29 -0
  70. package/dist/bundle/decode-AMXUVKNY.js +158 -0
  71. package/dist/bundle/dist-ESHIQU4M.js +7577 -0
  72. package/dist/bundle/echarts-GJDMQ2AQ.js +42501 -0
  73. package/dist/bundle/embed-L4CRZ2XQ.js +35 -0
  74. package/dist/bundle/embedder-IBGV4M2K.js +108 -0
  75. package/dist/bundle/first-run-VTKC2IBV.js +23 -0
  76. package/dist/bundle/first-screen-X5IJKBSU.js +27 -0
  77. package/dist/bundle/instructions-YJECS4KN.js +11 -0
  78. package/dist/bundle/mcp-G6XP2IRO.js +151 -0
  79. package/dist/bundle/mcp-OQBZXELQ.js +165 -0
  80. package/dist/bundle/mcp-RDZGYPSY.js +78 -0
  81. package/dist/bundle/node-NQG4EVZR.js +176 -0
  82. package/dist/bundle/node-P4E63KXA.js +2340 -0
  83. package/dist/bundle/node-TLZSIHIJ.js +21 -0
  84. package/dist/bundle/node-sqlite-BR7F3BLB.js +61 -0
  85. package/dist/bundle/oauth-J7UAWNIK.js +17 -0
  86. package/dist/bundle/open-BR47R5UE.js +19 -0
  87. package/dist/bundle/process-66I7RDPJ.js +91 -0
  88. package/dist/bundle/program-K6347XBZ.js +17279 -0
  89. package/dist/bundle/prompt-NE5JJ7UP.js +12 -0
  90. package/dist/bundle/recognize-GC3YFVIA.js +21 -0
  91. package/dist/bundle/remote-QELOMKQM.js +26 -0
  92. package/dist/bundle/rerank-BH6TZ2SP.js +49 -0
  93. package/dist/bundle/serve-WWLRNDT2.js +19 -0
  94. package/dist/bundle/server-DE6NLNUF.js +52 -0
  95. package/dist/bundle/server-ZPSQKOAH.js +39 -0
  96. package/dist/bundle/state-2BEGXAMO.js +33 -0
  97. package/dist/bundle/store-AH6WZMCF.js +120 -0
  98. package/dist/bundle/store-maintenance-command-PBXX3IEV.js +40 -0
  99. package/dist/version.d.ts +1 -1
  100. package/dist/version.d.ts.map +1 -1
  101. package/dist/version.js +1 -1
  102. package/dist/version.js.map +1 -1
  103. package/docs/commands.md +9 -13
  104. package/docs/dev/TESTING.md +10 -0
  105. package/docs/dev/reference-clis.md +7 -5
  106. package/docs/dev/skills/release/SKILL.md +15 -8
  107. package/docs/dev/skills/release/fresh-audit.md +4 -0
  108. package/docs/dev/test-matrix.md +1 -1
  109. package/kit/dist/new.js +1 -0
  110. package/package.json +8 -5
  111. package/scripts/audit.sh +14 -3
  112. package/scripts/smoke-bundle.ts +64 -0
  113. package/scripts/smoke.ts +18 -0
  114. package/scripts/test-matrix-untested.ts +1 -1
  115. package/scripts/version-level.test.ts +17 -1
  116. package/scripts/version-level.ts +35 -7
  117. package/skills/clidev-cli/SKILL.md +8 -0
  118. package/src/version.ts +1 -1
  119. package/lint/baseline/unknown-verb.json +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirecat/cli-template",
3
- "version": "0.9.0",
3
+ "version": "0.11.0",
4
4
  "description": "Start a new WireCat CLI: a working skeleton on cli-base and cli-core, copied by new and kept current by upgrade",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Viacheslav Ptsarev",
@@ -50,18 +50,20 @@
50
50
  "gitignore"
51
51
  ],
52
52
  "scripts": {
53
- "build": "tsc --build --force && pnpm kit:build",
53
+ "build": "tsc --build --force && cli-dev bundle --bin dist/bin/clidev.js && pnpm kit:build",
54
54
  "typecheck": "tsc --build --force --emitDeclarationOnly && tsc -p tsconfig.test.json && tsc -p tsconfig.scripts.json && pnpm kit:typecheck",
55
55
  "lint": "biome check .",
56
56
  "lint:fix": "biome check --write .",
57
57
  "test": "vitest run",
58
58
  "test:coverage": "vitest run --coverage",
59
+ "test:slow": "vitest run --reporter=json --outputFile=coverage/tests.json >/dev/null; cli-dev slow-tests",
59
60
  "test:matrix": "vitest run >/dev/null && pnpm build >/dev/null && pnpm test:matrix:check",
60
61
  "test:matrix:check": "cli-dev test-matrix --program scripts/command-program.ts --untested scripts/test-matrix-untested.ts --name clidev --check && git diff --exit-code -- docs/dev/test-matrix.md",
61
62
  "generate": "pnpm build && node --experimental-strip-types scripts/commands.ts",
62
63
  "generate:check": "pnpm build && node --experimental-strip-types scripts/commands.ts --check",
63
64
  "smoke": "node --experimental-strip-types scripts/smoke.ts",
64
- "smoke:bun": "bun scripts/smoke.ts",
65
+ "smoke:bun": "bun scripts/smoke.ts && bun scripts/smoke-bundle.ts",
66
+ "smoke:node": "node --experimental-strip-types scripts/smoke-bundle.ts",
65
67
  "package:check": "pnpm smoke",
66
68
  "docs:check": "cli-dev docs-check --rules scripts/docs-rules.ts --pages && pnpm docs:spell && rumdl check --config config/wirecat/rumdl.toml README.md SECURITY.md CHANGELOG.md CLAUDE.md AGENTS.md docs/*.md docs/dev/*.md && pnpm docs:lint && pnpm kit:docs",
67
69
  "docs:lint": "markdownlint-cli2",
@@ -84,8 +86,8 @@
84
86
  },
85
87
  "dependencies": {
86
88
  "@modelcontextprotocol/server": "2.4.0",
87
- "@wirecat/cli-base": "0.63.0",
88
- "@wirecat/cli-core": "0.463.0",
89
+ "@wirecat/cli-base": "0.65.0",
90
+ "@wirecat/cli-core": "0.495.0",
89
91
  "commander": "15.0.0"
90
92
  },
91
93
  "devDependencies": {
@@ -98,6 +100,7 @@
98
100
  "@vitest/coverage-v8": "5.0.5",
99
101
  "@wirecat/cli-testing": "0.5.3",
100
102
  "cspell": "10.4.0",
103
+ "esbuild": "0.28.2",
101
104
  "lefthook": "2.2.2",
102
105
  "markdownlint-cli2": "0.24.0",
103
106
  "rumdl": "0.3.0",
package/scripts/audit.sh CHANGED
@@ -8,18 +8,29 @@ command=$(node --input-type=module -e "import('$root/dist/identity.js').then((m)
8
8
  scratch=$(mktemp -d)
9
9
  trap 'rm -rf "$scratch"' EXIT
10
10
  # A CLI that starts may move the store under HOME; every CLI run here gets a throwaway one.
11
+ # Moved folders do not hide the keyring: it is reached over D-Bus.
11
12
  export HOME="$scratch/home" MESSAGING_STORE="$scratch/store" WIRECAT_STATE_DIR="$scratch/state"
13
+ export DBUS_SESSION_BUS_ADDRESS=disabled:
12
14
  mkdir -p "$HOME"
13
15
  npm install -g --prefix "$scratch/prefix" --ignore-scripts --no-audit --no-fund --loglevel error \
14
- @wirecat/tg-cli @wirecat/max-cli @wirecat/whatsapp-cli @wirecat/cli-memo @wirecat/drive-cli @wirecat/zoom-cli
16
+ @wirecat/tg-cli @wirecat/max-cli @wirecat/whatsapp-cli @wirecat/cli-memo @wirecat/drive-cli @wirecat/zoom-cli \
17
+ @wirecat/gcal-cli
15
18
  bin="$scratch/prefix/bin"
16
19
  others=()
17
20
  # A groups file replaces cli-base's PARITY_GROUPS. The template keeps one because it is in no group of cli-base's.
18
21
  [ -f "$root/config/parity-groups.json" ] && others+=(--groups "$root/config/parity-groups.json")
19
- for cli in tg max wa memo drive zm; do
22
+ for cli in tg max wa memo drive zm gcal; do
20
23
  [ "$cli" = "$command" ] || others+=(--cli "$bin/$cli")
21
24
  done
25
+ # This CLI's entity schemas and error reasons, from its own `commands info`, so same-entity-schema and
26
+ # same-error-reason measure it. shared-command-contract needs `--complete`, which wants cli-core's doctor contract.
27
+ node "$root/dist/bin/$command.js" commands info --json >"$scratch/info.json"
28
+ node -e 'const info = JSON.parse(require("fs").readFileSync(process.argv[1], "utf8"))
29
+ require("fs").writeFileSync(process.argv[2], JSON.stringify(info.schemas))
30
+ require("fs").writeFileSync(process.argv[3], JSON.stringify(info.reasons))' \
31
+ "$scratch/info.json" "$scratch/schemas.json" "$scratch/reasons.json"
22
32
  "$root/node_modules/.bin/cli-dev" audit --cli "$root/dist/bin/$command.js" "${others[@]}" --for "$command" \
23
- --lint "$command=$root/lint" >"$scratch/scorecard.txt" || { cat "$scratch/scorecard.txt"; exit 1; }
33
+ --lint "$command=$root/lint" --schemas "$command=$scratch/schemas.json" --reasons "$command=$scratch/reasons.json" \
34
+ >"$scratch/scorecard.txt" || { cat "$scratch/scorecard.txt"; exit 1; }
24
35
  awk -v cli="$command" 'NR == 1 || $1 == cli' "$scratch/scorecard.txt"
25
36
  grep -q "^$command *total " "$scratch/scorecard.txt" || { echo "audit: no scorecard row for $command" >&2; exit 1; }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * The published bin is a loader for `dist/bundle/` (cli-base's `cli-dev bundle`, WC-LAY-10). This runs it, with
3
+ * directories of its own, under Node (`pnpm smoke:node`) and Bun (`pnpm smoke:bun`): the vitest suite runs against
4
+ * `src/`, so this is the proof the bundle a user installs works.
5
+ *
6
+ * pnpm build && pnpm smoke:node
7
+ */
8
+ import { spawnSync } from "node:child_process"
9
+ import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs"
10
+ import { tmpdir } from "node:os"
11
+ import { join } from "node:path"
12
+
13
+ const COMMAND = "clidev"
14
+ const PREFIX = "CLIDEV"
15
+
16
+ const runtime = "Bun" in globalThis ? "bun" : "node"
17
+ const failures: string[] = []
18
+ const check = (what: string, condition: boolean) => {
19
+ if (!condition) failures.push(what)
20
+ }
21
+
22
+ // Overridden directories also move the keyring entry, so nothing here reads the owner's accounts or store.
23
+ const isolated = mkdtempSync(join(tmpdir(), `${COMMAND}-bundle-smoke-`))
24
+ const run = (args: string[], env: Record<string, string> = {}) =>
25
+ spawnSync(process.execPath, [`dist/bin/${COMMAND}.js`, ...args], {
26
+ encoding: "utf8",
27
+ env: {
28
+ ...process.env,
29
+ [`${PREFIX}_CONFIG_DIR`]: join(isolated, "config"),
30
+ [`${PREFIX}_STATE_DIR`]: join(isolated, "state"),
31
+ [`${PREFIX}_CACHE_DIR`]: join(isolated, "cache"),
32
+ [`${PREFIX}_NO_UPDATE_CHECK`]: "1",
33
+ MESSAGING_STORE: join(isolated, "store.db"),
34
+ DBUS_SESSION_BUS_ADDRESS: "disabled:",
35
+ ...env,
36
+ },
37
+ })
38
+
39
+ const loader = readFileSync(`dist/bin/${COMMAND}.js`, "utf8")
40
+ check("the bin starts the bundle", loader.includes(`import("../bundle/${COMMAND}.js")`))
41
+ const preloaded = [...loader.matchAll(/"\.\.\/bundle\/([^"]+)"/g)].map(([, chunk]) => chunk ?? "")
42
+ check(
43
+ "a server preloads only chunks the bundle has",
44
+ preloaded.length > 1 && preloaded.every((chunk) => existsSync(join("dist/bundle", chunk))),
45
+ )
46
+
47
+ const version = run(["--version"])
48
+ check("--version prints a version and nothing else", /^\d+\.\d+\.\d+\n$/.test(version.stdout) && version.stderr === "")
49
+ const recorded = run(["--version"], { [`${PREFIX}_TEST_ARGV_LOG`]: join(isolated, "argv.jsonl") })
50
+ check("the loader's --version is the bundle's", recorded.stdout === version.stdout)
51
+ check("--help names the command", run(["--help"]).stdout.includes(`Usage: ${COMMAND}`))
52
+ check("skill show prints the SKILL.md the package ships", run(["skill", "show"]).stdout.startsWith("---"))
53
+ check(
54
+ "doctor finds the document readers",
55
+ run(["doctor", "--json"]).stdout.includes('"files":{"checked":true,"ok":true'),
56
+ )
57
+ rmSync(isolated, { recursive: true, force: true })
58
+
59
+ if (failures.length > 0) {
60
+ console.error(`${COMMAND} bundle smoke FAILED under ${runtime}:`)
61
+ for (const failure of failures) console.error(` - ${failure}`)
62
+ process.exit(1)
63
+ }
64
+ console.log(`${COMMAND} bundle smoke passed under ${runtime}`)
package/scripts/smoke.ts CHANGED
@@ -24,6 +24,23 @@ const shipped = files
24
24
  .map((entry) => entry.replace(/^\//, ""))
25
25
  .map((entry) => (statSync(join(root, entry), { throwIfNoEntry: false })?.isDirectory() ? `${entry}/` : entry))
26
26
  assert.deepEqual(packContents(root, ["package.json", ...shipped], "package.json and the paths in its files list")(), [])
27
+ // WC-REL-16. The template's own package ships the skeleton's sources, since `new` copies them.
28
+ const FORBIDDEN = [
29
+ "src",
30
+ "scripts",
31
+ ".github",
32
+ "bin/release",
33
+ "config",
34
+ "lint",
35
+ "contracts",
36
+ "docs/dev",
37
+ "template.json",
38
+ ]
39
+ const overlaps = (entry: string, path: string) =>
40
+ entry === path || entry.startsWith(`${path}/`) || path.startsWith(`${entry}/`)
41
+ const forbidden = shipped.flatMap((entry) => FORBIDDEN.filter((path) => overlaps(entry.replace(/\/$/, ""), path)))
42
+ if (name !== "@wirecat/cli-template")
43
+ assert.deepEqual(forbidden, [], "package.json's files ships paths WC-REL-16 forbids")
27
44
  const temp = mkdtempSync(join(tmpdir(), "clidev-package-"))
28
45
  try {
29
46
  const userConfig = join(temp, "npm-user-config")
@@ -48,6 +65,7 @@ try {
48
65
  ...process.env,
49
66
  NODE_OPTIONS: "",
50
67
  HOME: temp,
68
+ DBUS_SESSION_BUS_ADDRESS: "disabled:",
51
69
  CLIDEV_CONFIG_DIR: join(temp, "config"),
52
70
  CLIDEV_STATE_DIR: join(temp, "state"),
53
71
  CLIDEV_CACHE_DIR: join(temp, "cache"),
@@ -29,6 +29,6 @@ export const UNTESTED: { command: string; option?: string; reason: string }[] =
29
29
  {
30
30
  command: "mcp server stop",
31
31
  reason:
32
- "starts a detached `mcp serve --http` from the built entry; cli-core tests mcpServerCommand, and the background run was checked by hand against dist/",
32
+ "stops the detached server that `mcp server start` wrote a pid file for; cli-core tests mcpServerCommand, and no live scenario starts a server to stop",
33
33
  },
34
34
  ]
@@ -1,5 +1,5 @@
1
1
  import { expect, it } from "vitest"
2
- import { versionLevelProblem } from "./version-level.js"
2
+ import { nextVersion, versionLevelProblem } from "./version-level.js"
3
3
 
4
4
  const changelog = (version: string, headings: string[], previous = "0.1.8") =>
5
5
  [`## ${version} — 26.10.2026`, ...headings.flatMap((h) => [`### ${h}`, "- x"]), `## ${previous} — 25.10.2026`].join(
@@ -28,3 +28,19 @@ it("refuses a patch release that adds something", () => {
28
28
  it("checks nothing while the top section is Unreleased", () => {
29
29
  expect(versionLevelProblem("## Unreleased\n\n### Removed\n\n- x\n\n## 0.1.8 — 25.10.2026\n")).toBeUndefined()
30
30
  })
31
+
32
+ const unreleased = (headings: string[], previous = "0.1.1") =>
33
+ ["## Unreleased", ...headings.flatMap((h) => [`### ${h}`, "- x"]), `## ${previous} — 29.10.2026`].join("\n")
34
+
35
+ it.each([
36
+ [["Fixed"], "0.1.2", "0.1.2"],
37
+ [["Added"], "0.1.2", "0.2.0"],
38
+ [["Removed"], "0.1.2", "0.2.0"],
39
+ [["Added"], "0.3.1", "0.3.1"],
40
+ ])("raises the next free number for %j from %s to %s", (headings, next, expected) => {
41
+ expect(nextVersion(unreleased(headings), next)).toBe(expected)
42
+ })
43
+
44
+ it("raises a 1.x release that may break callers to the next major", () => {
45
+ expect(nextVersion(unreleased(["Changed — may break callers"], "1.4.2"), "1.4.3")).toBe("2.0.0")
46
+ })
@@ -21,13 +21,35 @@ const needed = (version: string, section: string): Level => {
21
21
  return /^### Added$/m.test(section) ? "minor" : "patch"
22
22
  }
23
23
 
24
+ const raise = (from: string, level: Level) => {
25
+ const [a = 0, b = 0, c = 0] = parse(from)
26
+ if (level === "major") return `${a + 1}.0.0`
27
+ return level === "minor" ? `${a}.${b + 1}.0` : `${a}.${b}.${c + 1}`
28
+ }
29
+
30
+ const later = (x: string, y: string) => {
31
+ const [a, b] = [parse(x), parse(y)]
32
+ const i = a.findIndex((n, k) => n !== b[k])
33
+ return i === -1 || (a[i] ?? 0) > (b[i] ?? 0) ? x : y
34
+ }
35
+
36
+ const sections = (changelog: string) => {
37
+ const [top, below] = [...changelog.matchAll(/^## (\S+).*$/gm)]
38
+ if (!top || !below?.[1]) return undefined
39
+ return { version: top[1], previous: below[1], section: changelog.slice(top.index, below.index) }
40
+ }
41
+
42
+ // The next free number on npm is a patch; the top section may need a minor or major over the version below it.
43
+ export const nextVersion = (changelog: string, next: string): string => {
44
+ const parts = sections(changelog)
45
+ if (!parts) return next
46
+ return later(next, raise(parts.previous, needed(next, parts.section)))
47
+ }
48
+
24
49
  export const versionLevelProblem = (changelog: string): string | undefined => {
25
- const headings = [...changelog.matchAll(/^## (\S+).*$/gm)]
26
- const [top, below] = headings
27
- const version = top?.[1]
28
- const previous = below?.[1]
29
- if (!top || !below || !version || !previous || !/^\d+\.\d+\.\d+$/.test(version)) return undefined
30
- const section = changelog.slice(top.index, below.index)
50
+ const parts = sections(changelog)
51
+ if (!parts?.version || !/^\d+\.\d+\.\d+$/.test(parts.version)) return undefined
52
+ const { version, previous, section } = parts
31
53
  const want = needed(version, section)
32
54
  const got = raised(previous, version)
33
55
  if (LEVELS.indexOf(got) >= LEVELS.indexOf(want)) return undefined
@@ -35,7 +57,13 @@ export const versionLevelProblem = (changelog: string): string | undefined => {
35
57
  }
36
58
 
37
59
  if (process.argv[1] === fileURLToPath(import.meta.url)) {
38
- const problem = versionLevelProblem(readFileSync(resolve(import.meta.dirname, "../CHANGELOG.md"), "utf8"))
60
+ const changelog = readFileSync(resolve(import.meta.dirname, "../CHANGELOG.md"), "utf8")
61
+ const [flag, next] = process.argv.slice(2)
62
+ if (flag === "--next" && next) {
63
+ console.log(nextVersion(changelog, next))
64
+ process.exit(0)
65
+ }
66
+ const problem = versionLevelProblem(changelog)
39
67
  if (problem) {
40
68
  console.error(`${problem} (docs/dev/skills/release/SKILL.md, step 6)`)
41
69
  process.exit(1)
@@ -1,6 +1,14 @@
1
1
  ---
2
2
  name: clidev-cli
3
3
  description: Use clidev, a WireCat CLI started from cli-template, from an agent — find a command, run it with the owner's profile, read JSON answers. Use when a task needs clidev. It does not connect to a service yet.
4
+ metadata:
5
+ openclaw:
6
+ requires:
7
+ bins: [clidev]
8
+ install:
9
+ - kind: node
10
+ package: "@wirecat/clidev-cli"
11
+ bins: [clidev]
4
12
  ---
5
13
 
6
14
  # clidev
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = "0.9.0"
1
+ export const VERSION = "0.11.0"
@@ -1 +0,0 @@
1
- ["mcp revoke", "mcp serve"]