@zyaiting/keelson 0.4.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/LICENSE +21 -0
- package/README.md +101 -0
- package/README_CN.md +101 -0
- package/bin/keelson.js +15 -0
- package/hooks/codebuddy-session.mjs +67 -0
- package/hooks/opencode-session.mjs +65 -0
- package/hooks/prompt-state.mjs +66 -0
- package/hooks/session-start.mjs +94 -0
- package/package.json +64 -0
- package/registry/models.json +118 -0
- package/registry/platforms.json +92 -0
- package/skills/keelson/SKILL.md +44 -0
- package/skills/keelson/references/build.md +61 -0
- package/skills/keelson/references/context.md +34 -0
- package/skills/keelson/references/debug.md +46 -0
- package/skills/keelson/references/design-lenses.md +78 -0
- package/skills/keelson/references/discover.md +70 -0
- package/skills/keelson/references/engineer.md +110 -0
- package/skills/keelson/references/frontend-delivery.md +38 -0
- package/skills/keelson/references/frontend-interaction.md +31 -0
- package/skills/keelson/references/frontend-review.md +33 -0
- package/skills/keelson/references/frontend-visual.md +31 -0
- package/skills/keelson/references/frontend.md +33 -0
- package/skills/keelson/references/handoff.md +43 -0
- package/skills/keelson/references/harness.md +54 -0
- package/skills/keelson/references/interview.md +120 -0
- package/skills/keelson/references/land.md +47 -0
- package/skills/keelson/references/model.md +29 -0
- package/skills/keelson/references/plan.md +106 -0
- package/skills/keelson/references/reconcile.md +61 -0
- package/skills/keelson/references/shape.md +86 -0
- package/skills/keelson/references/verify.md +64 -0
- package/skills/keelson/templates/GLOSSARY.md +5 -0
- package/skills/keelson/templates/INTENT.md +22 -0
- package/skills/keelson/templates/NOW.md +9 -0
- package/skills/keelson/templates/README.md +60 -0
- package/skills/keelson/templates/ROADMAP.md +12 -0
- package/skills/keelson/templates/change-quick.md +16 -0
- package/skills/keelson/templates/change.md +32 -0
- package/skills/keelson/templates/delta-spec.md +12 -0
- package/skills/keelson/templates/handoff.md +27 -0
- package/skills/keelson/templates/ledger.md +3 -0
- package/skills/keelson/templates/resident-block.md +7 -0
- package/skills/keelson/templates/rules-general.md +10 -0
- package/skills/keelson/templates/rules-index.md +5 -0
- package/skills/keelson/templates/spec.md +14 -0
- package/skills/keelson/templates/tasks.md +9 -0
- package/skills/keelson/templates/workflow.md +18 -0
- package/skills/zh/keelson/SKILL.md +46 -0
- package/skills/zh/keelson/references/build.md +61 -0
- package/skills/zh/keelson/references/context.md +34 -0
- package/skills/zh/keelson/references/debug.md +46 -0
- package/skills/zh/keelson/references/design-lenses.md +78 -0
- package/skills/zh/keelson/references/discover.md +70 -0
- package/skills/zh/keelson/references/engineer.md +110 -0
- package/skills/zh/keelson/references/frontend-delivery.md +38 -0
- package/skills/zh/keelson/references/frontend-interaction.md +31 -0
- package/skills/zh/keelson/references/frontend-review.md +33 -0
- package/skills/zh/keelson/references/frontend-visual.md +31 -0
- package/skills/zh/keelson/references/frontend.md +33 -0
- package/skills/zh/keelson/references/handoff.md +43 -0
- package/skills/zh/keelson/references/harness.md +54 -0
- package/skills/zh/keelson/references/interview.md +120 -0
- package/skills/zh/keelson/references/land.md +47 -0
- package/skills/zh/keelson/references/model.md +29 -0
- package/skills/zh/keelson/references/plan.md +106 -0
- package/skills/zh/keelson/references/reconcile.md +61 -0
- package/skills/zh/keelson/references/shape.md +86 -0
- package/skills/zh/keelson/references/verify.md +64 -0
- package/skills/zh/keelson/templates/GLOSSARY.md +5 -0
- package/skills/zh/keelson/templates/INTENT.md +22 -0
- package/skills/zh/keelson/templates/NOW.md +9 -0
- package/skills/zh/keelson/templates/README.md +60 -0
- package/skills/zh/keelson/templates/ROADMAP.md +12 -0
- package/skills/zh/keelson/templates/change-quick.md +16 -0
- package/skills/zh/keelson/templates/change.md +32 -0
- package/skills/zh/keelson/templates/delta-spec.md +12 -0
- package/skills/zh/keelson/templates/handoff.md +27 -0
- package/skills/zh/keelson/templates/ledger.md +3 -0
- package/skills/zh/keelson/templates/resident-block.md +7 -0
- package/skills/zh/keelson/templates/rules-general.md +10 -0
- package/skills/zh/keelson/templates/rules-index.md +5 -0
- package/skills/zh/keelson/templates/spec.md +14 -0
- package/skills/zh/keelson/templates/tasks.md +9 -0
- package/skills/zh/keelson/templates/workflow.md +18 -0
- package/src/cli.js +87 -0
- package/src/commands/ablate.js +96 -0
- package/src/commands/ask.js +64 -0
- package/src/commands/attest.js +71 -0
- package/src/commands/check.js +127 -0
- package/src/commands/context.js +95 -0
- package/src/commands/design.js +63 -0
- package/src/commands/doctor.js +157 -0
- package/src/commands/focus.js +84 -0
- package/src/commands/guide.js +59 -0
- package/src/commands/handoff.js +41 -0
- package/src/commands/hook.js +23 -0
- package/src/commands/impact.js +58 -0
- package/src/commands/init.js +289 -0
- package/src/commands/land.js +258 -0
- package/src/commands/models.js +62 -0
- package/src/commands/new.js +70 -0
- package/src/commands/platforms.js +39 -0
- package/src/commands/retro.js +114 -0
- package/src/commands/status.js +115 -0
- package/src/commands/uninstall.js +30 -0
- package/src/commands/validate.js +117 -0
- package/src/lib/args.js +30 -0
- package/src/lib/changes.js +114 -0
- package/src/lib/check-activity.js +29 -0
- package/src/lib/config.js +102 -0
- package/src/lib/decisions.js +59 -0
- package/src/lib/evidence.js +127 -0
- package/src/lib/fs.js +126 -0
- package/src/lib/git.js +353 -0
- package/src/lib/glob.js +54 -0
- package/src/lib/health.js +113 -0
- package/src/lib/lifecycle.js +120 -0
- package/src/lib/maintenance.js +66 -0
- package/src/lib/markdown.js +438 -0
- package/src/lib/models.js +195 -0
- package/src/lib/out.js +13 -0
- package/src/lib/paths.js +82 -0
- package/src/lib/rules.js +27 -0
- package/src/lib/runtime-path.js +22 -0
- package/src/lib/session.js +100 -0
- package/src/lib/specs.js +345 -0
- package/src/lib/transaction.js +93 -0
- package/src/platforms/index.js +3 -0
- package/src/platforms/integration.js +384 -0
- package/src/platforms/registry.js +46 -0
- package/src/platforms/runtime.js +249 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Atingaii
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<p align="center"><img src="https://raw.githubusercontent.com/Atingaii/keelson/main/docs/assets/keelson-banner.png" alt="Keelson" width="620"></p>
|
|
2
|
+
|
|
3
|
+
<p align="center"><strong>Start with a conversation. Leave work the next session can build on.</strong></p>
|
|
4
|
+
<p align="center">Project memory, engineering guidance, and acceptance checks for your coding agent. Describe the outcome; keep decisions and verification alongside the code.</p>
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="README_CN.md">简体中文</a> ·
|
|
8
|
+
<a href="#quick-start">Quick start</a> ·
|
|
9
|
+
<a href="docs/README.md">Documentation</a> ·
|
|
10
|
+
<a href="docs/platforms.md">Agent support</a>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<a href="https://github.com/Atingaii/keelson/actions/workflows/ci.yml"><img src="https://github.com/Atingaii/keelson/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI"></a>
|
|
15
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT license"></a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center"><img src="https://raw.githubusercontent.com/Atingaii/keelson/main/docs/assets/keelson-demo.gif" alt="Real agent conversation replay: a task-filter request followed by implementation, verification, and archiving" width="100%"></p>
|
|
19
|
+
<p align="center"><sub>Initialized example repository · Translated excerpts from a real session, with waits shortened · Just describe the task</sub></p>
|
|
20
|
+
|
|
21
|
+
## Why Keelson?
|
|
22
|
+
|
|
23
|
+
Coding agents can write code. Ongoing development also needs shared context, clear boundaries, and a reliable way to establish that work is done.
|
|
24
|
+
|
|
25
|
+
| A familiar problem | How Keelson helps |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| Every new session starts with another project explanation | Goals, decisions, and unfinished work stay in the repository for the next session. |
|
|
28
|
+
| Implementation starts before the request is understood | The agent reads existing code, defines acceptance, and asks about decisions that change the direction. |
|
|
29
|
+
| The code is written, but completion is unclear | Check records track the inputs they verified, keeping implementation, verification, and completion distinct. |
|
|
30
|
+
| The page works, but its design and interactions feel unfinished | Design guidance covers typography, color, feedback, responsive behavior, and accessibility, with browser acceptance. |
|
|
31
|
+
|
|
32
|
+
Keelson combines an **Agent Skill + local CLI**. The skill guides the agent's work; the CLI manages project state and verification records. Use it for features, bug fixes, refactoring, and frontend improvements.
|
|
33
|
+
|
|
34
|
+
## Requirements
|
|
35
|
+
|
|
36
|
+
- **Node.js 20+**, npm, and Git.
|
|
37
|
+
- A coding agent that can read project files, make changes, and run commands.
|
|
38
|
+
- A local project directory; Git is recommended for tracking code and project knowledge.
|
|
39
|
+
|
|
40
|
+
Keelson generates integrations for Codex, Claude Code, OpenCode, Gemini CLI, and other hosts. See [Agent support](docs/platforms.md) for capabilities and validation coverage.
|
|
41
|
+
|
|
42
|
+
## Quick start
|
|
43
|
+
|
|
44
|
+
**1. Install the CLI:**
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install -g @zyaiting/keelson
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**2. Initialize your project**, using Codex here:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cd /path/to/your/project
|
|
54
|
+
keelson init --codex
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**3. Open your agent in that directory and describe the task.** Initialize once, then keep working through conversation.
|
|
58
|
+
|
|
59
|
+
> Add a priority filter to the task list: show everything by default, with an option for high-priority tasks only. Keep existing calls compatible, add tests, and verify the result.
|
|
60
|
+
|
|
61
|
+
To upgrade, run `npm install -g @zyaiting/keelson@latest`, then `keelson update` in your project. See the [setup guide](docs/getting-started.md) and [supported agents](docs/platforms.md).
|
|
62
|
+
|
|
63
|
+
## From request to completion
|
|
64
|
+
|
|
65
|
+
**Understand → Scope → Implement and verify → Archive and resume**
|
|
66
|
+
|
|
67
|
+
The agent loads relevant guidance, maintains acceptance criteria, and runs project checks. It wraps up when the gates pass, asking for your input when a choice changes the plan. Small edits stay lightweight.
|
|
68
|
+
|
|
69
|
+
You can also ask:
|
|
70
|
+
|
|
71
|
+
- **Explore:** “Find where this feature belongs. Don't change code yet.”
|
|
72
|
+
- **Improve an interface:** “Polish the settings page, keep our brand, preserve input when saving fails, and check the mobile flow.”
|
|
73
|
+
- **Resume:** “Continue the previous change. First check what's left.”
|
|
74
|
+
|
|
75
|
+
Frontend work has 22 composable [design actions](docs/frontend.md), discoverable with `keelson design`, including critique, simplification, polish, and adaptation. Checking the actual interface requires the agent to use a browser.
|
|
76
|
+
|
|
77
|
+
## What stays in your project?
|
|
78
|
+
|
|
79
|
+
Initialization creates a small foundation. Further documents appear as the work needs them:
|
|
80
|
+
|
|
81
|
+
| Location | Purpose |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| `.keelson/INTENT.md`, `.keelson/NOW.md` | Project goals, constraints, and current progress. |
|
|
84
|
+
| `.keelson/config.yaml` | Project check commands and workflow configuration. |
|
|
85
|
+
| `.keelson/changes/`, `.keelson/specs/`, `.keelson/rules/` | Changes, behavior contracts, and project rules created as needed. |
|
|
86
|
+
| Host entry points such as `AGENTS.md` | Direct the agent to Keelson. |
|
|
87
|
+
|
|
88
|
+
Guidance comes from the installed package by default. Use `--vendor` when you want to commit a copy alongside your project. See [configuration](docs/configuration.md) for paths and options.
|
|
89
|
+
|
|
90
|
+
## Engineering principles
|
|
91
|
+
|
|
92
|
+
- **Start with the problem.** Establish outcomes, constraints, and invariants before choosing mechanisms. Additional complexity must earn its place.
|
|
93
|
+
- **Load and retain what matters.** Small edits move directly; larger work adds contracts and plans. Preserve knowledge the next change will need.
|
|
94
|
+
- **Build through feedback.** Use small steps, independent review, and focused checks. Record test results separately from browser observations.
|
|
95
|
+
- **Ground completion in evidence.** Check records are tied to verified inputs; changed code needs fresh verification. Ending a conversation does not finish a task.
|
|
96
|
+
|
|
97
|
+
Review commands in `.keelson/config.yaml` before their first execution. The agent runs and records checks with `keelson check --trust --record`; passing exit codes still need an acceptance review. See [verification and trust](docs/verification.md).
|
|
98
|
+
|
|
99
|
+
## Documentation and contributing
|
|
100
|
+
|
|
101
|
+
[Documentation](docs/README.md) · [CLI reference](docs/cli.md) · [Frontend design](docs/frontend.md) · [Contributing](CONTRIBUTING.md) · [Report an issue](https://github.com/Atingaii/keelson/issues) · [MIT](LICENSE)
|
package/README_CN.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
<p align="center"><img src="https://raw.githubusercontent.com/Atingaii/keelson/main/docs/assets/keelson-banner.png" alt="Keelson" width="620"></p>
|
|
2
|
+
|
|
3
|
+
<p align="center"><strong>在仓库里对话,让每次开发都有据可循、有处接续。</strong></p>
|
|
4
|
+
<p align="center">为编码 Agent 提供项目记忆、工程方法和验收流程。你描述目标,Agent 推进实现,把决策与验证留在代码旁。</p>
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
<a href="README.md">English</a> ·
|
|
8
|
+
<a href="#快速开始">快速开始</a> ·
|
|
9
|
+
<a href="docs/zh/README.md">文档</a> ·
|
|
10
|
+
<a href="docs/platforms.md">Agent 支持</a>
|
|
11
|
+
</p>
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<a href="https://github.com/Atingaii/keelson/actions/workflows/ci.yml"><img src="https://github.com/Atingaii/keelson/actions/workflows/ci.yml/badge.svg?branch=main" alt="CI"></a>
|
|
15
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="MIT license"></a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center"><img src="https://raw.githubusercontent.com/Atingaii/keelson/main/docs/assets/keelson-demo-zh.gif" alt="真实 Agent 对话回放:用户提出任务筛选需求,Agent 完成实现、验证与归档" width="100%"></p>
|
|
19
|
+
<p align="center"><sub>已初始化的示例仓库 · 真实会话节选,等待已压缩 · 用户只需提出需求</sub></p>
|
|
20
|
+
|
|
21
|
+
## 为什么选择 Keelson?
|
|
22
|
+
|
|
23
|
+
编码 Agent 能写代码,但长期开发还需要持续的上下文、明确的边界和可信的验收。
|
|
24
|
+
|
|
25
|
+
| 开发中遇到的问题 | Keelson 如何处理 |
|
|
26
|
+
| --- | --- |
|
|
27
|
+
| 换个会话,又要解释整个项目 | 将目标、决策和未完成工作保存在仓库,下次继续读取。 |
|
|
28
|
+
| 需求说完就开写,结果偏离预期 | 先读现有实现,明确验收;只对影响方向的关键选择提问。 |
|
|
29
|
+
| 代码写完了,却不知道是否真的完成 | 保存与当前代码对应的检查记录,区分实现、验证和完成。 |
|
|
30
|
+
| 页面能用,却缺少设计与交互细节 | 提供设计指导,覆盖排版、配色、状态反馈、响应式和无障碍,并要求浏览器验收。 |
|
|
31
|
+
|
|
32
|
+
Keelson 由 **Agent Skill + 本地 CLI** 组成:Skill 指导 Agent 如何工作,CLI 管理项目状态与验证记录。适用于新功能、问题修复、重构和前端体验优化。
|
|
33
|
+
|
|
34
|
+
## 环境要求
|
|
35
|
+
|
|
36
|
+
- **Node.js 20+**,以及 npm、Git。
|
|
37
|
+
- 一个能读取项目、修改文件并执行命令的编码 Agent。
|
|
38
|
+
- 一个本地项目目录;建议使用 Git 管理代码和项目知识。
|
|
39
|
+
|
|
40
|
+
支持生成 Codex、Claude Code、OpenCode、Gemini CLI 等宿主的集成入口;各宿主的能力与验证范围见 [Agent 支持](docs/platforms.md)。
|
|
41
|
+
|
|
42
|
+
## 快速开始
|
|
43
|
+
|
|
44
|
+
**1. 安装 CLI:**
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
npm install -g @zyaiting/keelson
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**2. 在你的项目中初始化**,以 Codex 为例:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
cd /path/to/your/project
|
|
54
|
+
keelson init --codex --lang zh
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**3. 在这个目录启动 Agent,直接提出需求。** 初始化只需一次;后续正常对话即可。
|
|
58
|
+
|
|
59
|
+
> 给任务列表加一个优先级筛选:默认显示全部,也能只看高优先级。保持现有调用兼容,补齐测试并完成验证。
|
|
60
|
+
|
|
61
|
+
升级 CLI:`npm install -g @zyaiting/keelson@latest`,然后在项目中运行 `keelson update`。更多设置见[上手教程](docs/zh/getting-started.md);其他宿主见 [Agent 支持](docs/platforms.md)。
|
|
62
|
+
|
|
63
|
+
## 从一句需求到一次完成
|
|
64
|
+
|
|
65
|
+
**理解目标 → 明确范围 → 实现与验证 → 归档与接续**
|
|
66
|
+
|
|
67
|
+
Agent 按任务读取需要的指导,维护验收标准并执行项目检查;条件满足后自动收尾。遇到影响方案的选择时再与你确认,普通小修改保持轻量。
|
|
68
|
+
|
|
69
|
+
你也可以这样说:
|
|
70
|
+
|
|
71
|
+
- **讨论方案:**“先看看这个功能应该放在哪里,暂时不改代码。”
|
|
72
|
+
- **改善界面:**“优化设置页,保留品牌风格,保存失败时不要丢输入,并检查手机端体验。”
|
|
73
|
+
- **接着开发:**“继续上次的改动,先确认还剩什么。”
|
|
74
|
+
|
|
75
|
+
前端任务有 22 个可组合的[设计动作](docs/zh/frontend.md),可通过 `keelson design` 查看,包括审视、简化、打磨和适配。实际界面效果需要 Agent 使用浏览器检查。
|
|
76
|
+
|
|
77
|
+
## 项目里会留下什么?
|
|
78
|
+
|
|
79
|
+
初始化保留最少的项目文件,后续随实际开发补充:
|
|
80
|
+
|
|
81
|
+
| 位置 | 用途 |
|
|
82
|
+
| --- | --- |
|
|
83
|
+
| `.keelson/INTENT.md`、`.keelson/NOW.md` | 项目目标、约束与当前进展。 |
|
|
84
|
+
| `.keelson/config.yaml` | 项目检查命令和工作流配置。 |
|
|
85
|
+
| `.keelson/changes/`、`.keelson/specs/`、`.keelson/rules/` | 按需建立的变更、行为契约和项目规则。 |
|
|
86
|
+
| 宿主入口,如 `AGENTS.md` | 引导 Agent 加载 Keelson。 |
|
|
87
|
+
|
|
88
|
+
默认从已安装的包读取指导。需要把指导副本一并提交时,才使用 `--vendor`。目录与选项详见[配置文档](docs/zh/configuration.md)。
|
|
89
|
+
|
|
90
|
+
## 工程学原理
|
|
91
|
+
|
|
92
|
+
- **从问题出发。** 先确认结果、约束和不变量,再选择技术方案;额外机制必须证明有用。
|
|
93
|
+
- **按需加载,逐步沉淀。** 小改动直接推进,复杂任务补充契约与计划;只保留下一次开发需要的知识。
|
|
94
|
+
- **用反馈推动实现。** 小步实现、独立审阅、针对性验证;测试结果与界面观察分别记录。
|
|
95
|
+
- **让完成有证据。** 检查记录绑定受检输入,代码变化后需要重新验证;结束对话不等于完成任务。
|
|
96
|
+
|
|
97
|
+
首次执行前应审阅 `.keelson/config.yaml` 中的检查命令。Agent 使用 `keelson check --trust --record` 运行并记录检查;退出码通过仍需对照验收标准。详见[验证与信任](docs/zh/verification.md)。
|
|
98
|
+
|
|
99
|
+
## 文档与参与
|
|
100
|
+
|
|
101
|
+
[完整文档](docs/zh/README.md) · [命令参考](docs/zh/cli.md) · [前端设计](docs/zh/frontend.md) · [贡献指南](CONTRIBUTING.md) · [反馈问题](https://github.com/Atingaii/keelson/issues) · [MIT](LICENSE)
|
package/bin/keelson.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { main } from '../src/cli.js';
|
|
3
|
+
|
|
4
|
+
// Set the exit code and let the process drain stdout on its own. On macOS a pipe is asynchronous,
|
|
5
|
+
// so calling process.exit() right after a large --json print would truncate the output.
|
|
6
|
+
main(process.argv.slice(2)).then(
|
|
7
|
+
(code) => {
|
|
8
|
+
process.exitCode = code ?? 0;
|
|
9
|
+
},
|
|
10
|
+
(err) => {
|
|
11
|
+
console.error(`keelson: ${err?.message ?? err}`);
|
|
12
|
+
if (process.env.KEELSON_DEBUG) console.error(err?.stack);
|
|
13
|
+
process.exitCode = err?.exitCode ?? 1;
|
|
14
|
+
},
|
|
15
|
+
);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// CodeBuddy session bridge for Keelson.
|
|
3
|
+
// SessionStart/UserPromptSubmit: touch local session runtime and inject a tiny focus hint.
|
|
4
|
+
// PreToolUse(Bash|PowerShell): deterministically prepend KEELSON_SESSION_ID to the command.
|
|
5
|
+
// Raw CodeBuddy session ids are never written to disk.
|
|
6
|
+
import crypto from 'node:crypto';
|
|
7
|
+
import fs from 'node:fs';
|
|
8
|
+
import path from 'node:path';
|
|
9
|
+
import { runtimeDir } from '../src/lib/runtime-path.js';
|
|
10
|
+
|
|
11
|
+
const hash = (value, n) => crypto.createHash('sha256').update(String(value)).digest('hex').slice(0, n);
|
|
12
|
+
const readJson = (p) => { try { return JSON.parse(fs.readFileSync(p, 'utf8')); } catch { return null; } };
|
|
13
|
+
const writeJson = (p, v) => { fs.mkdirSync(path.dirname(p), { recursive: true }); fs.writeFileSync(p, JSON.stringify(v, null, 2) + '\n'); };
|
|
14
|
+
const shellQuote = (v) => `'${String(v).replace(/'/g, "'\\''")}'`;
|
|
15
|
+
|
|
16
|
+
let input = {};
|
|
17
|
+
try {
|
|
18
|
+
const raw = fs.readFileSync(0, 'utf8');
|
|
19
|
+
if (raw.trim()) input = JSON.parse(raw);
|
|
20
|
+
} catch {}
|
|
21
|
+
|
|
22
|
+
const root = input.cwd || process.env.CODEBUDDY_PROJECT_DIR || process.cwd();
|
|
23
|
+
const sessionId = typeof input.session_id === 'string' ? input.session_id.trim() : '';
|
|
24
|
+
if (!sessionId || !fs.existsSync(path.join(root, '.keelson'))) process.exit(0);
|
|
25
|
+
|
|
26
|
+
const opaque = hash(`codebuddy:${sessionId}`, 32);
|
|
27
|
+
const key = hash(opaque, 24);
|
|
28
|
+
const sessionFile = path.join(runtimeDir(root), 'sessions', `${key}.json`);
|
|
29
|
+
const session = readJson(sessionFile) || { schema: 1, change: null, createdAt: new Date().toISOString() };
|
|
30
|
+
session.updatedAt = new Date().toISOString();
|
|
31
|
+
session.source = 'codebuddy';
|
|
32
|
+
writeJson(sessionFile, session);
|
|
33
|
+
|
|
34
|
+
const event = input.hook_event_name || '';
|
|
35
|
+
if (event === 'PreToolUse' && ['bash', 'powershell'].includes(String(input.tool_name || '').toLowerCase())) {
|
|
36
|
+
const command = input.tool_input?.command;
|
|
37
|
+
if (typeof command !== 'string' || !command.trim()) process.exit(0);
|
|
38
|
+
if (/\bKEELSON_SESSION_ID\s*=/.test(command.slice(0, 180))) process.exit(0);
|
|
39
|
+
const tool = String(input.tool_name || '').toLowerCase();
|
|
40
|
+
const injected = tool === 'powershell'
|
|
41
|
+
? `$env:KEELSON_SESSION_ID='${opaque}'; ${command}`
|
|
42
|
+
: `export KEELSON_SESSION_ID=${shellQuote(opaque)}; ${command}`;
|
|
43
|
+
process.stdout.write(JSON.stringify({
|
|
44
|
+
continue: true,
|
|
45
|
+
hookSpecificOutput: {
|
|
46
|
+
hookEventName: 'PreToolUse',
|
|
47
|
+
permissionDecision: 'allow',
|
|
48
|
+
permissionDecisionReason: 'Keelson attached the opaque session identity used only for local work-focus routing.',
|
|
49
|
+
modifiedInput: {
|
|
50
|
+
...input.tool_input,
|
|
51
|
+
command: injected,
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
}));
|
|
55
|
+
process.exit(0);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const changesDir = path.join(root, '.keelson', 'changes');
|
|
59
|
+
const active = fs.existsSync(changesDir)
|
|
60
|
+
? fs.readdirSync(changesDir, { withFileTypes: true })
|
|
61
|
+
.filter((d) => d.isDirectory() && d.name !== 'archive' && fs.existsSync(path.join(changesDir, d.name, 'change.md')))
|
|
62
|
+
.map((d) => d.name)
|
|
63
|
+
: [];
|
|
64
|
+
const focused = session.change && active.includes(session.change) ? session.change : null;
|
|
65
|
+
if (focused) process.stdout.write(`[keelson] session focus: ${focused}; use the existing change unless the user requests an independent outcome.\n`);
|
|
66
|
+
else if (active.length === 1) process.stdout.write(`[keelson] resume candidate: ${active[0]}; bind only if this prompt continues that work.\n`);
|
|
67
|
+
else if (active.length > 1) process.stdout.write(`[keelson] active changes: ${active.join(', ')}; no session focus, so do not guess.\n`);
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import crypto from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
const hash = (value, n) => crypto.createHash('sha256').update(String(value)).digest('hex').slice(0, n);
|
|
4
|
+
const stringValue = (value) => typeof value === 'string' && value.trim() ? value.trim() : null;
|
|
5
|
+
|
|
6
|
+
function lookupSession(input) {
|
|
7
|
+
if (!input || typeof input !== 'object') return null;
|
|
8
|
+
for (const key of ['session_id', 'sessionId', 'sessionID']) {
|
|
9
|
+
const value = stringValue(input[key]);
|
|
10
|
+
if (value) return value;
|
|
11
|
+
}
|
|
12
|
+
for (const key of ['input', 'event', 'properties', 'hook_input', 'hookInput']) {
|
|
13
|
+
const value = lookupSession(input[key]);
|
|
14
|
+
if (value) return value;
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function shellQuote(value) {
|
|
20
|
+
return `'${String(value).replace(/'/g, "'\\''")}'`;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function powershellQuote(value) {
|
|
24
|
+
return `'${String(value).replace(/'/g, "''")}'`;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function shellBase(value) {
|
|
28
|
+
return String(value ?? '').replace(/\\/g, '/').split('/').pop()?.toLowerCase() ?? '';
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function windowsPosix(env) {
|
|
32
|
+
if (env?.MSYSTEM || env?.MINGW_PREFIX || env?.OPENCODE_GIT_BASH_PATH) return true;
|
|
33
|
+
if (/(msys|mingw|cygwin)/i.test(env?.OSTYPE ?? '')) return true;
|
|
34
|
+
return /^(bash|sh|zsh)(\.exe)?$/.test(shellBase(env?.SHELL));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function prefix(identity, platform, env) {
|
|
38
|
+
if (platform === 'win32' && !windowsPosix(env)) return `$env:KEELSON_SESSION_ID = ${powershellQuote(identity)}; `;
|
|
39
|
+
return `export KEELSON_SESSION_ID=${shellQuote(identity)}; `;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function alreadyInjected(command) {
|
|
43
|
+
const first = String(command).trimStart().split(/[;&|]/, 1)[0].trimStart();
|
|
44
|
+
return /^KEELSON_SESSION_ID\s*=/.test(first) ||
|
|
45
|
+
/^export\s+KEELSON_SESSION_ID\s*=/.test(first) ||
|
|
46
|
+
/^env\s+.*KEELSON_SESSION_ID\s*=/.test(first) ||
|
|
47
|
+
/^\$env:KEELSON_SESSION_ID\s*=/i.test(first);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Project-local OpenCode plugin. It does one thing: carry the current OpenCode
|
|
51
|
+
// session identity into shell commands so Keelson CLI calls resolve the same
|
|
52
|
+
// private keelson-runtime/sessions/<key>.json pointer. It never decides work status.
|
|
53
|
+
export default async ({ platform = process.platform, env = process.env } = {}) => ({
|
|
54
|
+
'tool.execute.before': async (input, output) => {
|
|
55
|
+
if (String(input?.tool ?? '').toLowerCase() !== 'bash') return;
|
|
56
|
+
const args = output?.args;
|
|
57
|
+
if (!args || typeof args !== 'object') return;
|
|
58
|
+
const key = typeof args.command === 'string' ? 'command' : typeof args.cmd === 'string' ? 'cmd' : null;
|
|
59
|
+
if (!key || !args[key].trim() || alreadyInjected(args[key])) return;
|
|
60
|
+
const raw = lookupSession(input);
|
|
61
|
+
if (!raw) return;
|
|
62
|
+
const opaque = hash(`opencode:${raw}`, 32);
|
|
63
|
+
args[key] = prefix(opaque, platform, env) + args[key];
|
|
64
|
+
},
|
|
65
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Keelson per-prompt state hint.
|
|
3
|
+
// Touches session-local runtime state and emits only the current focus when one exists.
|
|
4
|
+
import crypto from 'node:crypto';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { runtimeDir } from '../src/lib/runtime-path.js';
|
|
8
|
+
|
|
9
|
+
const root = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
10
|
+
const k = path.join(root, '.keelson');
|
|
11
|
+
const changesDir = path.join(k, 'changes');
|
|
12
|
+
if (!fs.existsSync(k)) process.exit(0);
|
|
13
|
+
|
|
14
|
+
const read = (p) => (fs.existsSync(p) ? fs.readFileSync(p, 'utf8').replace(/\r\n?/g, '\n') : '');
|
|
15
|
+
const readJson = (p) => { try { return JSON.parse(read(p)); } catch { return null; } };
|
|
16
|
+
const writeJson = (p, value) => {
|
|
17
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
18
|
+
fs.writeFileSync(p, JSON.stringify(value, null, 2) + '\n');
|
|
19
|
+
};
|
|
20
|
+
const hash = (s, n) => crypto.createHash('sha256').update(String(s)).digest('hex').slice(0, n);
|
|
21
|
+
|
|
22
|
+
let input = {};
|
|
23
|
+
try {
|
|
24
|
+
const raw = fs.readFileSync(0, 'utf8');
|
|
25
|
+
if (raw.trim()) input = JSON.parse(raw);
|
|
26
|
+
} catch {}
|
|
27
|
+
const hostSession = input.session_id || input.sessionId || null;
|
|
28
|
+
const envIdentity = hostSession ? hash(`claude:${hostSession}`, 32) : (process.env.KEELSON_SESSION_ID || null);
|
|
29
|
+
const sessionKey = envIdentity ? hash(envIdentity, 24) : null;
|
|
30
|
+
const sessionPath = sessionKey ? path.join(runtimeDir(root), 'sessions', `${sessionKey}.json`) : null;
|
|
31
|
+
let session = sessionPath ? readJson(sessionPath) : null;
|
|
32
|
+
if (sessionPath) {
|
|
33
|
+
session ||= { schema: 1, change: null, createdAt: new Date().toISOString() };
|
|
34
|
+
session.updatedAt = new Date().toISOString();
|
|
35
|
+
session.source = 'claude-prompt';
|
|
36
|
+
writeJson(sessionPath, session);
|
|
37
|
+
}
|
|
38
|
+
if (!fs.existsSync(changesDir)) process.exit(0);
|
|
39
|
+
|
|
40
|
+
const summarize = (name) => {
|
|
41
|
+
const dir = path.join(changesDir, name);
|
|
42
|
+
const change = read(path.join(dir, 'change.md'));
|
|
43
|
+
if (!change) return null;
|
|
44
|
+
const tasks = read(path.join(dir, 'tasks.md'));
|
|
45
|
+
const total = (tasks.match(/^\s*[-*]\s+\[[ xX]\]/gm) || []).length;
|
|
46
|
+
const done = (tasks.match(/^\s*[-*]\s+\[[xX]\]/gm) || []).length;
|
|
47
|
+
const ledger = read(path.join(dir, 'ledger.md'));
|
|
48
|
+
const verifies = [...ledger.matchAll(/^###\s+Verify:[\s\S]*?exit\s*(?:code)?\s*[:=]?\s*(\d+)/gim)];
|
|
49
|
+
const lastExit = verifies.length ? Number(verifies.at(-1)[1]) : null;
|
|
50
|
+
const explicit = (change.match(/^status:\s*([\w-]+)/m) || [])[1];
|
|
51
|
+
const verify = verifies.length ? (lastExit === 0 ? 'passed' : 'failed') : 'not-run';
|
|
52
|
+
const open = (change.match(/^##\s+Open questions?\s*\n([\s\S]*?)(?=^##\s|(?![\s\S]))/im) || [])[1] || '';
|
|
53
|
+
const openCount = (open.match(/^\s*[-*]\s+(?!…|none)/gim) || []).length;
|
|
54
|
+
return `${name} · ${explicit || (total ? (done < total ? 'in-progress' : 'awaiting verification') : 'in-progress')} · verify ${verify}${total ? ` · ${done}/${total} tasks` : ''}${openCount ? ` · ${openCount} open` : ''}`;
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
if (session?.change) {
|
|
58
|
+
const line = summarize(session.change);
|
|
59
|
+
if (line) process.stdout.write(`[keelson] focus: ${line}\n`);
|
|
60
|
+
process.exit(0);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const names = fs.readdirSync(changesDir, { withFileTypes: true })
|
|
64
|
+
.filter((d) => d.isDirectory() && d.name !== 'archive' && fs.existsSync(path.join(changesDir, d.name, 'change.md')))
|
|
65
|
+
.map((d) => d.name);
|
|
66
|
+
if (names.length === 1) process.stdout.write(`[keelson] resume candidate: ${summarize(names[0])}; bind only if this prompt continues that work\n`);
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Keelson SessionStart hook.
|
|
3
|
+
// Tracks session-local work focus in Keelson's local runtime and prints a compact project snapshot.
|
|
4
|
+
import crypto from 'node:crypto';
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { runtimeDir } from '../src/lib/runtime-path.js';
|
|
8
|
+
|
|
9
|
+
const root = process.env.CLAUDE_PROJECT_DIR || process.cwd();
|
|
10
|
+
const k = path.join(root, '.keelson');
|
|
11
|
+
if (!fs.existsSync(k)) process.exit(0);
|
|
12
|
+
|
|
13
|
+
const read = (p) => (fs.existsSync(p) ? fs.readFileSync(p, 'utf8').replace(/\r\n?/g, '\n') : '');
|
|
14
|
+
const readJson = (p) => {
|
|
15
|
+
try { return JSON.parse(read(p)); } catch { return null; }
|
|
16
|
+
};
|
|
17
|
+
const writeJson = (p, value) => {
|
|
18
|
+
fs.mkdirSync(path.dirname(p), { recursive: true });
|
|
19
|
+
fs.writeFileSync(p, JSON.stringify(value, null, 2) + '\n');
|
|
20
|
+
};
|
|
21
|
+
const clip = (s, n) => (s.length > n ? s.slice(0, n).replace(/\s+\S*$/, '') + ' …' : s);
|
|
22
|
+
const section = (text, re) => {
|
|
23
|
+
const m = text.match(new RegExp(`^##\\s+(?:${re})[^\\n]*\\n([\\s\\S]*?)(?=^##\\s|(?![\\s\\S]))`, 'im'));
|
|
24
|
+
return m ? m[1].trim() : '';
|
|
25
|
+
};
|
|
26
|
+
const hash = (s, n) => crypto.createHash('sha256').update(String(s)).digest('hex').slice(0, n);
|
|
27
|
+
|
|
28
|
+
let input = {};
|
|
29
|
+
try {
|
|
30
|
+
const raw = fs.readFileSync(0, 'utf8');
|
|
31
|
+
if (raw.trim()) input = JSON.parse(raw);
|
|
32
|
+
} catch {}
|
|
33
|
+
|
|
34
|
+
const hostSession = input.session_id || input.sessionId || null;
|
|
35
|
+
// Never persist the host's raw session id. The exported identity is already opaque.
|
|
36
|
+
const envIdentity = hostSession ? hash(`claude:${hostSession}`, 32) : (process.env.KEELSON_SESSION_ID || null);
|
|
37
|
+
const sessionKey = envIdentity ? hash(envIdentity, 24) : null;
|
|
38
|
+
const sessionsDir = path.join(runtimeDir(root), 'sessions');
|
|
39
|
+
const sessionPath = sessionKey ? path.join(sessionsDir, `${sessionKey}.json`) : null;
|
|
40
|
+
|
|
41
|
+
if (envIdentity && process.env.CLAUDE_ENV_FILE) {
|
|
42
|
+
const line = `export KEELSON_SESSION_ID=${envIdentity}`;
|
|
43
|
+
try {
|
|
44
|
+
let last = null;
|
|
45
|
+
if (fs.existsSync(process.env.CLAUDE_ENV_FILE)) {
|
|
46
|
+
for (const raw of fs.readFileSync(process.env.CLAUDE_ENV_FILE, 'utf8').split(/\r?\n/)) {
|
|
47
|
+
const t = raw.trim();
|
|
48
|
+
if (t.startsWith('export KEELSON_SESSION_ID=')) last = t;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (last !== line) fs.appendFileSync(process.env.CLAUDE_ENV_FILE, line + '\n');
|
|
52
|
+
} catch {}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
let session = null;
|
|
56
|
+
if (sessionPath) {
|
|
57
|
+
session = readJson(sessionPath) || { schema: 1, change: null, createdAt: new Date().toISOString() };
|
|
58
|
+
session.updatedAt = new Date().toISOString();
|
|
59
|
+
session.source = 'claude-session-start';
|
|
60
|
+
writeJson(sessionPath, session);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const now = read(path.join(k, 'NOW.md')).trim();
|
|
64
|
+
const roadmapNow = section(read(path.join(k, 'ROADMAP.md')), 'Now');
|
|
65
|
+
const changesDir = path.join(k, 'changes');
|
|
66
|
+
const active = fs.existsSync(changesDir)
|
|
67
|
+
? fs.readdirSync(changesDir, { withFileTypes: true })
|
|
68
|
+
.filter((d) => d.isDirectory() && d.name !== 'archive' && fs.existsSync(path.join(changesDir, d.name, 'change.md')))
|
|
69
|
+
.map((d) => {
|
|
70
|
+
const dir = path.join(changesDir, d.name);
|
|
71
|
+
const change = read(path.join(dir, 'change.md'));
|
|
72
|
+
const tasks = read(path.join(dir, 'tasks.md'));
|
|
73
|
+
const total = (tasks.match(/^\s*[-*]\s+\[[ xX]\]/gm) || []).length;
|
|
74
|
+
const done = (tasks.match(/^\s*[-*]\s+\[[xX]\]/gm) || []).length;
|
|
75
|
+
const tier = (change.match(/^tier:\s*(\w+)/m) || [])[1] || 'quick';
|
|
76
|
+
const status = (change.match(/^status:\s*([\w-]+)/m) || [])[1] || null;
|
|
77
|
+
const owner = (change.match(/^owner:\s*(.+)$/m) || [])[1] || null;
|
|
78
|
+
return { name: d.name, tier, status, owner, done, total };
|
|
79
|
+
})
|
|
80
|
+
: [];
|
|
81
|
+
|
|
82
|
+
const focused = session?.change && active.some((c) => c.name === session.change) ? session.change : null;
|
|
83
|
+
const ordered = focused ? [...active].sort((a, b) => (a.name === focused ? -1 : b.name === focused ? 1 : 0)) : active;
|
|
84
|
+
const lines = ['[keelson] Canonical project facts/runtime live under .keelson/. Session focus is local and never marks a change complete.'];
|
|
85
|
+
if (focused) lines.push(`Session focus: ${focused}`);
|
|
86
|
+
else if (active.length === 1) lines.push(`Resume candidate: ${active[0].name} (bind with \`keelson focus --auto\` only if this request continues that work)`);
|
|
87
|
+
else if (active.length > 1) lines.push(`Active changes: ${active.map((c) => c.name).join(', ')} (no session focus)`);
|
|
88
|
+
if (roadmapNow && !/^…/.test(roadmapNow)) lines.push('', '--- ROADMAP.md · Now ---', clip(roadmapNow, 350));
|
|
89
|
+
if (now) lines.push('', '--- NOW.md ---', clip(now, 650));
|
|
90
|
+
if (ordered.length) {
|
|
91
|
+
lines.push('', '--- Active work ---');
|
|
92
|
+
for (const c of ordered.slice(0, 6)) lines.push(`${c.name}${c.name === focused ? ' [focus]' : ''}: ${c.tier}${c.status ? `, ${c.status}` : ''}${c.total ? `, ${c.done}/${c.total} tasks` : ''}${c.owner ? `, ${c.owner}` : ''}`);
|
|
93
|
+
}
|
|
94
|
+
process.stdout.write(lines.join('\n') + '\n');
|
package/package.json
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@zyaiting/keelson",
|
|
3
|
+
"version": "0.4.0",
|
|
4
|
+
"description": "Local, verifiable check records and durable decisions for AI-assisted code changes.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"keelson": "bin/keelson.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"bin",
|
|
11
|
+
"src",
|
|
12
|
+
"skills",
|
|
13
|
+
"hooks",
|
|
14
|
+
"registry",
|
|
15
|
+
"README.md",
|
|
16
|
+
"README_CN.md",
|
|
17
|
+
"LICENSE"
|
|
18
|
+
],
|
|
19
|
+
"scripts": {
|
|
20
|
+
"test": "node --test",
|
|
21
|
+
"lint": "node scripts/check-syntax.js",
|
|
22
|
+
"validate": "node bin/keelson.js validate",
|
|
23
|
+
"prepublishOnly": "npm test"
|
|
24
|
+
},
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=20"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"yaml": "^2.6.0"
|
|
30
|
+
},
|
|
31
|
+
"keywords": [
|
|
32
|
+
"ai",
|
|
33
|
+
"coding-agent",
|
|
34
|
+
"claude-code",
|
|
35
|
+
"codex",
|
|
36
|
+
"opencode",
|
|
37
|
+
"gemini-cli",
|
|
38
|
+
"kiro",
|
|
39
|
+
"codebuddy",
|
|
40
|
+
"pi-agent",
|
|
41
|
+
"agent-skills",
|
|
42
|
+
"spec-driven",
|
|
43
|
+
"workflow",
|
|
44
|
+
"session",
|
|
45
|
+
"verification"
|
|
46
|
+
],
|
|
47
|
+
"author": "Atingaii",
|
|
48
|
+
"license": "MIT",
|
|
49
|
+
"repository": {
|
|
50
|
+
"type": "git",
|
|
51
|
+
"url": "git+https://github.com/Atingaii/keelson.git"
|
|
52
|
+
},
|
|
53
|
+
"bugs": {
|
|
54
|
+
"url": "https://github.com/Atingaii/keelson/issues"
|
|
55
|
+
},
|
|
56
|
+
"homepage": "https://github.com/Atingaii/keelson#readme",
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"fast-check": "^4.10.2"
|
|
59
|
+
},
|
|
60
|
+
"publishConfig": {
|
|
61
|
+
"access": "public",
|
|
62
|
+
"registry": "https://registry.npmjs.org/"
|
|
63
|
+
}
|
|
64
|
+
}
|