@christang/keel 5.73.0 → 5.74.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.
- package/README.md +16 -7
- package/README.zh-CN.md +12 -7
- package/assets/bootstrap/AGENTS.md +1 -1
- package/bin/keel +9 -0
- package/bin/keel.js +14 -7
- package/npm-shrinkwrap.json +1137 -0
- package/package.json +2 -1
- package/plugins/keel/.claude-plugin/plugin.json +1 -1
- package/plugins/keel/.codex-plugin/plugin.json +1 -1
- package/plugins/keel/scripts/session-start.js +68 -9
- package/scripts/bump_version.js +36 -11
- package/scripts/validate_plugin.py +473 -22
package/README.md
CHANGED
|
@@ -46,22 +46,31 @@ Node.js `>=20.19.0` (the bundled OpenSpec CLI needs it).
|
|
|
46
46
|
|
|
47
47
|
## Install
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
**Claude Code** — the plugin is the whole install. It is the published `@christang/keel`
|
|
50
|
+
package, so it carries the `keel` CLI and the bundled OpenSpec along with the skills and hooks,
|
|
51
|
+
and the agent's `keel` commands run the copy the plugin brought:
|
|
52
52
|
|
|
53
53
|
```bash
|
|
54
|
-
|
|
55
|
-
keel
|
|
54
|
+
claude plugin marketplace add TanglmChris/keel
|
|
55
|
+
claude plugin install keel@keel-marketplace
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
After an update, `/reload-plugins` applies it in the running session; otherwise it applies at the
|
|
59
|
+
next start.
|
|
60
|
+
|
|
61
|
+
**Codex, and your own terminal** — install the CLI as well (it also installs the bundled
|
|
62
|
+
OpenSpec CLI):
|
|
59
63
|
|
|
60
64
|
```bash
|
|
61
|
-
|
|
65
|
+
npm install -g @christang/keel
|
|
66
|
+
keel --version
|
|
62
67
|
codex plugin add keel@<marketplace> # Codex
|
|
63
68
|
```
|
|
64
69
|
|
|
70
|
+
A global `keel` comes first on PATH, ahead of the plugin's copy, so on Claude Code the agent runs
|
|
71
|
+
it instead. Keep it at the plugin's version or remove it (`npm rm -g @christang/keel`); the
|
|
72
|
+
session-start line names it whenever the two disagree.
|
|
73
|
+
|
|
65
74
|
<details>
|
|
66
75
|
<summary>Install the latest unreleased build from GitHub</summary>
|
|
67
76
|
|
package/README.zh-CN.md
CHANGED
|
@@ -38,22 +38,27 @@ Node.js `>=20.19.0`(内置的 OpenSpec CLI 需要)。
|
|
|
38
38
|
|
|
39
39
|
## 安装
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
**CLI** —— 一条命令(同时装上捆绑的 OpenSpec CLI):
|
|
41
|
+
**Claude Code** —— 装插件就够了。插件本身就是发布的 `@christang/keel` 包,技能和 hook 之外还带着
|
|
42
|
+
`keel` CLI 和捆绑的 OpenSpec;agent 运行的 `keel` 就是插件带来的这一份:
|
|
44
43
|
|
|
45
44
|
```bash
|
|
46
|
-
|
|
47
|
-
keel
|
|
45
|
+
claude plugin marketplace add TanglmChris/keel
|
|
46
|
+
claude plugin install keel@keel-marketplace
|
|
48
47
|
```
|
|
49
48
|
|
|
50
|
-
|
|
49
|
+
更新之后,在当前会话执行 `/reload-plugins` 即可生效;不执行的话,下次启动时生效。
|
|
50
|
+
|
|
51
|
+
**Codex,以及你自己的终端** —— 另外装一份 CLI(同时装上捆绑的 OpenSpec CLI):
|
|
51
52
|
|
|
52
53
|
```bash
|
|
53
|
-
|
|
54
|
+
npm install -g @christang/keel
|
|
55
|
+
keel --version
|
|
54
56
|
codex plugin add keel@<marketplace> # Codex
|
|
55
57
|
```
|
|
56
58
|
|
|
59
|
+
全局装的 `keel` 在 PATH 里排在插件那份前面,所以在 Claude Code 里 agent 会用它。要么让它和插件同版本,
|
|
60
|
+
要么卸掉(`npm rm -g @christang/keel`);两者版本不一致时,会话启动那一行会指出来。
|
|
61
|
+
|
|
57
62
|
> 捆绑的 OpenSpec 依赖在安装时会打印一行 opt-in 的 shell 补全提示。如果你的 npm 拦截安装脚本,
|
|
58
63
|
> 这行提示会被跳过,它纯属装饰,keel 照常工作。
|
|
59
64
|
|
package/bin/keel
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// The bare `keel` a Claude plugin's `bin/` puts on the agent's PATH (#164).
|
|
5
|
+
// On Claude the plugin is this published package, and the host adds `bin/`
|
|
6
|
+
// to PATH by file name, so `keel.js` alone would answer to `keel.js`. npm's
|
|
7
|
+
// own `bin` map keeps pointing at `keel.js`; this file only gives the plugin
|
|
8
|
+
// the same name.
|
|
9
|
+
require("./keel.js");
|
package/bin/keel.js
CHANGED
|
@@ -769,21 +769,28 @@ function openspecReportedVersion(command) {
|
|
|
769
769
|
// project that does not depend on OpenSpec directly. A lockfile that exists and
|
|
770
770
|
// cannot be parsed is a read failure. Collapsing them would either warn at
|
|
771
771
|
// everyone or hide a real failure.
|
|
772
|
+
//
|
|
773
|
+
// The lockfile is the one npm installs from: `npm-shrinkwrap.json` when it
|
|
774
|
+
// exists, else `package-lock.json`. A package that publishes itself — Keel
|
|
775
|
+
// does since #164 — carries the shrinkwrap, because npm never publishes a
|
|
776
|
+
// `package-lock.json`.
|
|
772
777
|
function declaredOpenSpecVersion(repo) {
|
|
773
|
-
const
|
|
774
|
-
|
|
778
|
+
const lockName = ["npm-shrinkwrap.json", "package-lock.json"].find((name) =>
|
|
779
|
+
fs.existsSync(path.join(repo, name))
|
|
780
|
+
);
|
|
781
|
+
if (!lockName) return { state: "none", version: null, lockName: null };
|
|
775
782
|
let lock;
|
|
776
783
|
try {
|
|
777
|
-
lock = JSON.parse(fs.readFileSync(
|
|
784
|
+
lock = JSON.parse(fs.readFileSync(path.join(repo, lockName), "utf8"));
|
|
778
785
|
} catch {
|
|
779
|
-
return { state: "unreadable", version: null };
|
|
786
|
+
return { state: "unreadable", version: null, lockName };
|
|
780
787
|
}
|
|
781
788
|
for (const [name, entry] of Object.entries(lock.packages || {})) {
|
|
782
789
|
if (name.endsWith("@fission-ai/openspec") && entry && entry.version) {
|
|
783
|
-
return { state: "declared", version: entry.version };
|
|
790
|
+
return { state: "declared", version: entry.version, lockName };
|
|
784
791
|
}
|
|
785
792
|
}
|
|
786
|
-
return { state: "none", version: null };
|
|
793
|
+
return { state: "none", version: null, lockName };
|
|
787
794
|
}
|
|
788
795
|
|
|
789
796
|
// "Not installed" and "installed and Keel cannot reach it" need different
|
|
@@ -1686,7 +1693,7 @@ function runDoctor(options) {
|
|
|
1686
1693
|
const declaredText = {
|
|
1687
1694
|
declared: `repo pins ${declared.version}`,
|
|
1688
1695
|
none: "repo declares no OpenSpec version",
|
|
1689
|
-
unreadable:
|
|
1696
|
+
unreadable: `repo ${declared.lockName} unreadable`,
|
|
1690
1697
|
}[declared.state];
|
|
1691
1698
|
const versions = `${resolvedVersion || "version unreadable"}, ${declaredText}`;
|
|
1692
1699
|
printDoctorLine(
|