@zentao-hub/cli 0.1.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 +175 -0
- package/README.zh-CN.md +192 -0
- package/dist/agents.d.ts +62 -0
- package/dist/agents.js +202 -0
- package/dist/agents.js.map +1 -0
- package/dist/commands/init.d.ts +9 -0
- package/dist/commands/init.js +94 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install-claude-md.d.ts +12 -0
- package/dist/commands/install-claude-md.js +25 -0
- package/dist/commands/install-claude-md.js.map +1 -0
- package/dist/commands/install-commands.d.ts +8 -0
- package/dist/commands/install-commands.js +27 -0
- package/dist/commands/install-commands.js.map +1 -0
- package/dist/commands/install-hooks.d.ts +7 -0
- package/dist/commands/install-hooks.js +31 -0
- package/dist/commands/install-hooks.js.map +1 -0
- package/dist/commands/install-mcp.d.ts +20 -0
- package/dist/commands/install-mcp.js +203 -0
- package/dist/commands/install-mcp.js.map +1 -0
- package/dist/commands/login.d.ts +17 -0
- package/dist/commands/login.js +110 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +7 -0
- package/dist/commands/logout.js +59 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/profiles.d.ts +5 -0
- package/dist/commands/profiles.js +26 -0
- package/dist/commands/profiles.js.map +1 -0
- package/dist/commands/register.d.ts +12 -0
- package/dist/commands/register.js +26 -0
- package/dist/commands/register.js.map +1 -0
- package/dist/commands/repos.d.ts +8 -0
- package/dist/commands/repos.js +28 -0
- package/dist/commands/repos.js.map +1 -0
- package/dist/commands/uninstall-claude-md.d.ts +6 -0
- package/dist/commands/uninstall-claude-md.js +13 -0
- package/dist/commands/uninstall-claude-md.js.map +1 -0
- package/dist/commands/uninstall-commands.d.ts +7 -0
- package/dist/commands/uninstall-commands.js +21 -0
- package/dist/commands/uninstall-commands.js.map +1 -0
- package/dist/commands/uninstall-hooks.d.ts +6 -0
- package/dist/commands/uninstall-hooks.js +36 -0
- package/dist/commands/uninstall-hooks.js.map +1 -0
- package/dist/commands/uninstall-mcp.d.ts +8 -0
- package/dist/commands/uninstall-mcp.js +99 -0
- package/dist/commands/uninstall-mcp.js.map +1 -0
- package/dist/commands/uninstall.d.ts +14 -0
- package/dist/commands/uninstall.js +28 -0
- package/dist/commands/uninstall.js.map +1 -0
- package/dist/commands/use.d.ts +6 -0
- package/dist/commands/use.js +20 -0
- package/dist/commands/use.js.map +1 -0
- package/dist/commands/whoami.d.ts +6 -0
- package/dist/commands/whoami.js +48 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/commands/workspace.d.ts +8 -0
- package/dist/commands/workspace.js +28 -0
- package/dist/commands/workspace.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +496 -0
- package/dist/index.js.map +1 -0
- package/dist/paths.d.ts +16 -0
- package/dist/paths.js +36 -0
- package/dist/paths.js.map +1 -0
- package/dist/prompt.d.ts +7 -0
- package/dist/prompt.js +43 -0
- package/dist/prompt.js.map +1 -0
- package/dist/registry.d.ts +16 -0
- package/dist/registry.js +42 -0
- package/dist/registry.js.map +1 -0
- package/dist/util.d.ts +27 -0
- package/dist/util.js +70 -0
- package/dist/util.js.map +1 -0
- package/package.json +57 -0
- package/templates/.claude/commands/bug-analyze.md +46 -0
- package/templates/.claude/commands/fix-bug.md +193 -0
- package/templates/.githooks/commit-msg +47 -0
- package/templates/CLAUDE.md +86 -0
- package/templates/repos.yaml.example +26 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Deven Liu
|
|
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,175 @@
|
|
|
1
|
+
# @zentao-hub/cli
|
|
2
|
+
|
|
3
|
+
English | [简体中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
> **Not the official [`zentao-cli`](https://github.com/easysoft/zentao-cli).** This is the companion CLI for `@zentao-hub/mcp` — it installs slash commands / prompts, MCP server entries, hooks, and per-agent instruction files for the AI agent of your choice. For general-purpose terminal CRUD against ZenTao, use the official CLI instead.
|
|
6
|
+
|
|
7
|
+
The companion CLI for `@zentao-hub/mcp`. **The MCP server itself does not need it** — this CLI just bundles a handful of "manually copy or hand-write the script" tasks into subcommands:
|
|
8
|
+
|
|
9
|
+
- Install `/fix-bug` and `/bug-analyze` into the chosen agent's slash-command / prompt dir
|
|
10
|
+
- `--agent claude` → `~/.claude/commands/*.md`
|
|
11
|
+
- `--agent codex` → `~/.codex/prompts/*.md`
|
|
12
|
+
- `--agent copilot` → `<repo>/.github/prompts/*.prompt.md`
|
|
13
|
+
- `--agent copilot-cli` → `~/.copilot/agents/*.agent.md`
|
|
14
|
+
- Register the `zentao-hub` MCP server in the agent's config (Claude Code / Copilot in VS Code / Copilot CLI / Codex CLI)
|
|
15
|
+
- Install a commit-msg hook (blocks AI signatures + enforces Conventional Commits) into a target repository
|
|
16
|
+
- Drop the per-agent instructions file: `CLAUDE.md` (Claude Code), `AGENTS.md` (Codex / Copilot CLI), `.github/copilot-instructions.md` (Copilot in VS Code)
|
|
17
|
+
- **Uninstall** every `install` artifact in one shot, or one target at a time
|
|
18
|
+
- Initialize / inspect the bug-context workspace — **one workspace per profile** at `<$ZENTAO_HUB or ~/.zentao-hub>/<profile>/`
|
|
19
|
+
- Maintain the `repos.yaml` registry inside each profile's workspace (productId → one or more repositories)
|
|
20
|
+
|
|
21
|
+
> The CLI does not run the bug-fixing flow on behalf of the agent. The flow still goes through the slash commands / prompts and the MCP server, because "waiting for the user to confirm", "reading screenshots", and "exploring code" only make sense with an LLM in the loop. The CLI only handles _setting up the environment_.
|
|
22
|
+
|
|
23
|
+
## Supported agents
|
|
24
|
+
|
|
25
|
+
| Agent ID | Tool | MCP config file | Instructions file |
|
|
26
|
+
| -------------- | ------------------------------- | --------------------------------------------------------------------------------- | ---------------------------------------------- |
|
|
27
|
+
| `claude` | Claude Code | `~/.claude.json` or `<repo>/.mcp.json` | `CLAUDE.md` |
|
|
28
|
+
| `copilot` | GitHub Copilot (VS Code) | User `User/mcp.json` or `<repo>/.vscode/mcp.json` | `.github/copilot-instructions.md` |
|
|
29
|
+
| `copilot-cli` | GitHub Copilot CLI | `~/.copilot/mcp-config.json` (user) or `<repo>/.mcp.json` (workspace) | `AGENTS.md` |
|
|
30
|
+
| `codex` | OpenAI Codex CLI | `~/.codex/config.toml` (user-only) | `AGENTS.md` |
|
|
31
|
+
|
|
32
|
+
## Install
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
npm install -g @zentao-hub/cli
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Or for development inside this monorepo (uses pnpm):
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
corepack enable
|
|
42
|
+
pnpm install
|
|
43
|
+
pnpm run build
|
|
44
|
+
node packages/cli/dist/index.js help
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Usage
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
zentao-hub <command> [options]
|
|
51
|
+
|
|
52
|
+
install <target> install one of: commands | hooks | claude-md | mcp
|
|
53
|
+
uninstall [target] reverse a single target, or omit for a one-shot revert
|
|
54
|
+
of commands + hooks + claude-md (mcp not included)
|
|
55
|
+
init initialize the per-profile workspace
|
|
56
|
+
register <pid> <path> register a repository under a productId in the active profile's repos.yaml
|
|
57
|
+
repos [productId] print the active profile's registry
|
|
58
|
+
workspace, ws show the currently resolved workspace (supports --print-path for scripts)
|
|
59
|
+
login / logout / whoami / profiles / use manage credentials
|
|
60
|
+
help print help
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Run `zentao-hub help` for the full set of options.
|
|
64
|
+
|
|
65
|
+
## A typical one-time setup
|
|
66
|
+
|
|
67
|
+
The example below targets Claude Code (`--agent claude`). Swap `--agent` for
|
|
68
|
+
`copilot` / `copilot-cli` / `codex` to set the same thing up for another
|
|
69
|
+
agent — credentials, workspace, and registry are shared across agents.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
# 1. Install the packages and log in once (credentials are shared across agents).
|
|
73
|
+
npm install -g @zentao-hub/mcp @zentao-hub/cli
|
|
74
|
+
zentao-hub login
|
|
75
|
+
|
|
76
|
+
# 2. Register the zentao-hub MCP server in the agent's config.
|
|
77
|
+
zentao-hub install mcp --agent claude
|
|
78
|
+
|
|
79
|
+
# 3. Install the slash commands / prompts.
|
|
80
|
+
zentao-hub install commands --agent claude
|
|
81
|
+
|
|
82
|
+
# 4. Initialize the bug-context workspace (agent-agnostic).
|
|
83
|
+
zentao-hub init
|
|
84
|
+
echo 'export ZENTAO_HUB=$HOME/.zentao-hub' >> ~/.zshrc
|
|
85
|
+
|
|
86
|
+
# 5. Per target repository: drop the instructions file, the commit-msg hook,
|
|
87
|
+
# and register the repo under a productId.
|
|
88
|
+
cd ~/projects/venus-fe
|
|
89
|
+
zentao-hub install claude-md --agent claude # claude→CLAUDE.md, codex/copilot-cli→AGENTS.md, copilot→.github/copilot-instructions.md
|
|
90
|
+
zentao-hub install hooks # commit-msg hook (agent-agnostic)
|
|
91
|
+
zentao-hub register 2 . --name venus-frontend --tag frontend --tag electron
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
After that, open the chosen agent (Claude Code / Copilot Chat / Copilot CLI / Codex CLI) and type:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
/bug-analyze 9634 # analyze only
|
|
98
|
+
/fix-bug 27 # list active bugs assigned to you under product 27 and let you pick
|
|
99
|
+
/fix-bug 27 9634 # fix it directly
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
## Workspace layout
|
|
103
|
+
|
|
104
|
+
`$ZENTAO_HUB` (default `~/.zentao-hub`) is the *hub root*. The actual workspace is per-profile: `<root>/<profile>/`. This keeps bug context, registry, and attachments isolated when you have logins for multiple ZenTao instances (e.g. one per client). After `zentao-hub init --profile <name>`:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
$ZENTAO_HUB/
|
|
108
|
+
├── credentials.json ← shared across profiles
|
|
109
|
+
├── default/ ← profile workspace
|
|
110
|
+
│ ├── repos.yaml ← registry: productId → list of repositories
|
|
111
|
+
│ ├── repos.yaml.example ← template
|
|
112
|
+
│ └── bugs/ ← one sub-directory per bug, written by the slash commands
|
|
113
|
+
│ └── <bugId>/
|
|
114
|
+
│ ├── raw.json
|
|
115
|
+
│ ├── description.md
|
|
116
|
+
│ ├── history.md
|
|
117
|
+
│ ├── analysis.md
|
|
118
|
+
│ └── attachments/
|
|
119
|
+
│ ├── <id>-<title>.<ext>
|
|
120
|
+
│ └── inline/
|
|
121
|
+
│ └── inline-N-<basename>
|
|
122
|
+
└── client-foo/ ← second profile, fully isolated
|
|
123
|
+
├── repos.yaml
|
|
124
|
+
└── bugs/
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Slash commands / prompts pick the workspace via the active `$ZENTAO_PROFILE` (which the MCP server already honors for auth). When `zentao-hub` is on `$PATH`, they run `zentao-hub workspace --profile $ZENTAO_PROFILE --print-path` to get the directory.
|
|
128
|
+
|
|
129
|
+
### Migrating from the old flat layout
|
|
130
|
+
|
|
131
|
+
Earlier versions wrote `bugs/` and `repos.yaml` directly under the root. If you upgrade and still have files there, `zentao-hub init --migrate-legacy` moves them into the `default/` profile workspace.
|
|
132
|
+
|
|
133
|
+
## The `repos.yaml` registry
|
|
134
|
+
|
|
135
|
+
A single productId can map to multiple repositories (frontend / backend / DB migrations / ...). `/fix-bug` Phase 2 supports multi-select; for cross-repo bugs it iterates per repository with worktree → commit → squash.
|
|
136
|
+
|
|
137
|
+
Structure:
|
|
138
|
+
|
|
139
|
+
```yaml
|
|
140
|
+
products:
|
|
141
|
+
27:
|
|
142
|
+
- name: eda-schematic
|
|
143
|
+
path: /Users/you/projects/eda-studio/eda-schematic
|
|
144
|
+
tags: [frontend]
|
|
145
|
+
- name: eda-interop
|
|
146
|
+
path: /Users/you/projects/eda-studio/eda-interop
|
|
147
|
+
tags: [api]
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
You can edit it by hand, or append entries with `zentao-hub register`.
|
|
151
|
+
|
|
152
|
+
## Flow overview (what the slash commands actually do)
|
|
153
|
+
|
|
154
|
+
`/fix-bug` has three phases:
|
|
155
|
+
|
|
156
|
+
```
|
|
157
|
+
Phase 1 — Bug context (does not touch any repository)
|
|
158
|
+
Phase 2 — Pick repositories (multi-select; new inputs are written back to repos.yaml)
|
|
159
|
+
Phase 3 — For each chosen repo: worktree → edit → test → squash merge
|
|
160
|
+
Phase 4 — Wrap-up suggestions (push / resolve_bug / delete worktree)
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`/bug-analyze` runs only Phase 1. If you later want to actually fix the bug, run `/fix-bug <productId> <bugId>` and the previously downloaded context is reused.
|
|
164
|
+
|
|
165
|
+
## Design trade-offs
|
|
166
|
+
|
|
167
|
+
- **The CLI installs environment, it does not run the flow.** Slash commands / prompts are LLM-in-the-loop by design; the CLI is not a replacement.
|
|
168
|
+
- **A central workspace, not a per-repo directory.** During analysis you don't yet know which repo to change; in multi-repo scenarios, putting context inside any one of them is awkward.
|
|
169
|
+
- **`worktree`, not `checkout`.** Leaves the main checkout alone, and multi-repo work is naturally parallel.
|
|
170
|
+
- **Squash, not fast-forward.** The main branch should see one clean `fix: #N` commit.
|
|
171
|
+
- **No automatic push / resolve / branch delete.** Side-effecting cross-boundary operations are kept explicit, for the user to trigger.
|
|
172
|
+
|
|
173
|
+
## License
|
|
174
|
+
|
|
175
|
+
[MIT](../../LICENSE) © Deven Liu
|
package/README.zh-CN.md
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# @zentao-hub/cli
|
|
2
|
+
|
|
3
|
+
[English](README.md) | 简体中文
|
|
4
|
+
|
|
5
|
+
> **不是禅道官方的 [`zentao-cli`](https://github.com/easysoft/zentao-cli)。** 本包是 `@zentao-hub/mcp` 的配套 CLI——只装 AI agent 的 slash command / prompt、hook、模板。要在终端直接 CRUD 禅道,请用官方的 `zentao-cli`。
|
|
6
|
+
|
|
7
|
+
`@zentao-hub/mcp` 的配套 CLI。**MCP server 本身不需要它** —— 它只是把原本要靠手抄/复制脚本完成的事情包成几个子命令:
|
|
8
|
+
|
|
9
|
+
- 把 `/fix-bug`、`/bug-analyze` 装到目标 agent 的 slash command / prompt 目录
|
|
10
|
+
- `--agent claude` → `~/.claude/commands/*.md`
|
|
11
|
+
- `--agent codex` → `~/.codex/prompts/*.md`
|
|
12
|
+
- `--agent copilot` → `<repo>/.github/prompts/*.prompt.md`
|
|
13
|
+
- `--agent copilot-cli` → `~/.copilot/agents/*.agent.md`
|
|
14
|
+
- 在目标 agent 的配置里注册 `zentao-hub` MCP server(Claude Code / Copilot in VS Code / Copilot CLI / Codex CLI 各自的 config 文件)
|
|
15
|
+
- 把 commit-msg hook(拦 AI 署名 + 校 Conventional Commits)装到目标代码库
|
|
16
|
+
- 按 agent 复制协作规则文件:`CLAUDE.md`(Claude Code)/ `AGENTS.md`(Codex / Copilot CLI)/ `.github/copilot-instructions.md`(Copilot in VS Code)
|
|
17
|
+
- 初始化 / 查看 bug-context workspace —— **每个 profile 一个 workspace**,在 `<$ZENTAO_HUB 或 ~/.zentao-hub>/<profile>/`
|
|
18
|
+
- 维护每个 profile workspace 里的 `repos.yaml` 注册表(productId → 多个代码库)
|
|
19
|
+
|
|
20
|
+
> CLI 不替 agent 跑修 bug 流程 —— 流程仍然走 slash command + MCP,因为「等用户确认」「读截图」「调研代码」这些只有 LLM 在循环里才合理。CLI 只解决 _装环境_ 这一段。
|
|
21
|
+
|
|
22
|
+
## 支持的 agent
|
|
23
|
+
|
|
24
|
+
| Agent ID | 说明 | MCP 配置文件 | 协作规则文件 |
|
|
25
|
+
| -------------- | ----------------------------- | -------------------------------------------------------------------- | ----------------------------------------- |
|
|
26
|
+
| `claude` | Claude Code | `~/.claude.json` 或 `<repo>/.mcp.json` | `CLAUDE.md` |
|
|
27
|
+
| `copilot` | GitHub Copilot (VS Code) | 用户 `User/mcp.json` 或 `<repo>/.vscode/mcp.json` | `.github/copilot-instructions.md` |
|
|
28
|
+
| `copilot-cli` | GitHub Copilot CLI | `~/.copilot/mcp-config.json`(user)或 `<repo>/.mcp.json`(workspace)| `AGENTS.md` |
|
|
29
|
+
| `codex` | OpenAI Codex CLI | `~/.codex/config.toml`(user-only) | `AGENTS.md` |
|
|
30
|
+
|
|
31
|
+
## 安装
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install -g @zentao-hub/cli
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
或本 monorepo 内开发(使用 pnpm):
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
corepack enable
|
|
41
|
+
pnpm install
|
|
42
|
+
pnpm run build
|
|
43
|
+
node packages/cli/dist/index.js help
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## 用法
|
|
47
|
+
|
|
48
|
+
```text
|
|
49
|
+
zentao-hub <command> [options]
|
|
50
|
+
|
|
51
|
+
install <target> 装其中一项:commands | hooks | claude-md | mcp
|
|
52
|
+
uninstall [target] 回滚单项,或不带 target 一键回滚 commands + hooks + claude-md
|
|
53
|
+
(mcp 不在一键回滚里,要单独执行 uninstall mcp)
|
|
54
|
+
init 初始化当前 profile 的 workspace
|
|
55
|
+
register <pid> <path> 把仓库登记到当前 profile 的 repos.yaml
|
|
56
|
+
repos [productId] 打印当前 profile 的注册表
|
|
57
|
+
workspace, ws 显示当前 profile 解析到的 workspace(支持 --print-path 给脚本用)
|
|
58
|
+
login / logout / whoami / profiles / use 凭据管理
|
|
59
|
+
help 打印帮助
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
跑 `zentao-hub help` 看完整选项。
|
|
63
|
+
|
|
64
|
+
## 典型一次性安装流程
|
|
65
|
+
|
|
66
|
+
下面以 Claude Code 为例(`--agent claude`)。把每条命令里的 `--agent` 换成 `copilot` / `copilot-cli` / `codex` 即可装到对应 agent;凭据、workspace、注册表跨 agent 共用。
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
# 1. 装包 + 登录(凭据所有 agent 共用)
|
|
70
|
+
npm install -g @zentao-hub/mcp @zentao-hub/cli
|
|
71
|
+
zentao-hub login
|
|
72
|
+
|
|
73
|
+
# 2. 在 agent 配置里注册 zentao-hub MCP server
|
|
74
|
+
zentao-hub install mcp --agent claude
|
|
75
|
+
|
|
76
|
+
# 3. 装 slash command / prompt
|
|
77
|
+
zentao-hub install commands --agent claude
|
|
78
|
+
|
|
79
|
+
# 4. 初始化 bug-context workspace(与具体 agent 无关)
|
|
80
|
+
zentao-hub init
|
|
81
|
+
echo 'export ZENTAO_HUB=$HOME/.zentao-hub' >> ~/.zshrc
|
|
82
|
+
|
|
83
|
+
# 5. 每个目标代码库:装协作规则文件 + commit-msg hook + 登记 productId
|
|
84
|
+
cd ~/projects/venus-fe
|
|
85
|
+
zentao-hub install claude-md --agent claude # claude→CLAUDE.md, codex/copilot-cli→AGENTS.md, copilot→.github/copilot-instructions.md
|
|
86
|
+
zentao-hub install hooks # commit-msg hook(与 agent 无关)
|
|
87
|
+
zentao-hub register 2 . --name venus-frontend --tag 前端 --tag electron
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
之后在所选 agent 里(Claude Code / Copilot Chat / Copilot CLI / Codex CLI)启动并输入:
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
/bug-analyze 9634 # 只分析
|
|
94
|
+
/fix-bug 27 # 列产品 27 你名下 active bug 让你挑
|
|
95
|
+
/fix-bug 27 9634 # 直接修
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## 一键卸载
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
zentao-hub uninstall # 全卸:slash command + 当前仓库的 hook + 当前仓库的 CLAUDE.md
|
|
102
|
+
zentao-hub uninstall --repo ~/projects/foo
|
|
103
|
+
zentao-hub uninstall --keep-hooks-path
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
需要更细粒度:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
zentao-hub uninstall commands
|
|
110
|
+
zentao-hub uninstall hooks --repo .
|
|
111
|
+
zentao-hub uninstall claude-md --repo .
|
|
112
|
+
zentao-hub uninstall mcp --agent claude
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
凭据和 workspace 不会被动 —— 那是用户数据,用 `zentao-hub logout --all` 删凭据,`rm -rf <hub-root>/<profile>` 删 workspace。
|
|
116
|
+
|
|
117
|
+
## Workspace 目录结构
|
|
118
|
+
|
|
119
|
+
`$ZENTAO_HUB`(默认 `~/.zentao-hub`)是 *hub root*,每个 profile 一个 workspace:`<root>/<profile>/`。这样多个禅道实例(比如不同客户)的 bug 上下文、注册表、附件天然隔离。`zentao-hub init --profile <name>` 之后:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
$ZENTAO_HUB/
|
|
123
|
+
├── credentials.json ← 跨 profile 共用
|
|
124
|
+
├── default/ ← profile workspace
|
|
125
|
+
│ ├── repos.yaml ← 注册表:productId → 代码库列表
|
|
126
|
+
│ ├── repos.yaml.example ← 模板
|
|
127
|
+
│ └── bugs/ ← 每个 bug 一个子目录,由 slash command 写入
|
|
128
|
+
│ └── <bugId>/
|
|
129
|
+
│ ├── raw.json
|
|
130
|
+
│ ├── description.md
|
|
131
|
+
│ ├── history.md
|
|
132
|
+
│ ├── analysis.md
|
|
133
|
+
│ └── attachments/
|
|
134
|
+
│ ├── <id>-<title>.<ext>
|
|
135
|
+
│ └── inline/
|
|
136
|
+
│ └── inline-N-<basename>
|
|
137
|
+
└── client-foo/ ← 第二个 profile,完全隔离
|
|
138
|
+
├── repos.yaml
|
|
139
|
+
└── bugs/
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
slash command / prompt 通过当前的 `$ZENTAO_PROFILE`(MCP server 鉴权也用这个)来挑 workspace。`zentao-hub` 在 `$PATH` 上时,会跑 `zentao-hub workspace --profile $ZENTAO_PROFILE --print-path` 拿到目录。
|
|
143
|
+
|
|
144
|
+
### 从老的扁平结构迁移
|
|
145
|
+
|
|
146
|
+
更早的版本把 `bugs/` 和 `repos.yaml` 直接写在根目录下。如果升级后这些文件还在那儿,`zentao-hub init --migrate-legacy` 会把它们搬到 `default/` profile workspace。
|
|
147
|
+
|
|
148
|
+
## 注册表 `repos.yaml`
|
|
149
|
+
|
|
150
|
+
一个 productId 可以对应多个代码库(前端 / 后端 / 数据库迁移 / …)。`/fix-bug` 在 Phase 2 支持多选,跨库 bug 时按仓库循环 worktree + commit + squash。
|
|
151
|
+
|
|
152
|
+
结构:
|
|
153
|
+
|
|
154
|
+
```yaml
|
|
155
|
+
products:
|
|
156
|
+
27:
|
|
157
|
+
- name: eda-schematic
|
|
158
|
+
path: /Users/you/projects/eda-studio/eda-schematic
|
|
159
|
+
tags: [前端]
|
|
160
|
+
- name: eda-interop
|
|
161
|
+
path: /Users/you/projects/eda-studio/eda-interop
|
|
162
|
+
tags: [api]
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
可以手工编辑,也可以用 `zentao-hub register` 追加。
|
|
166
|
+
|
|
167
|
+
## 流程概览(slash command 跑的事)
|
|
168
|
+
|
|
169
|
+
`/fix-bug` 三阶段:
|
|
170
|
+
|
|
171
|
+
```
|
|
172
|
+
Phase 1 — Bug 上下文(不依赖任何代码库)
|
|
173
|
+
Phase 2 — 选代码库(多选;新输入的写回 repos.yaml)
|
|
174
|
+
Phase 3 — 按每个选中的库循环:worktree → 改 → 测 → squash merge
|
|
175
|
+
Phase 4 — 收尾建议(push / resolve_bug / 删 worktree)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
`/bug-analyze` 只跑 Phase 1。之后想真修,直接 `/fix-bug <productId> <bugId>`,已下载的 context 会复用。
|
|
179
|
+
|
|
180
|
+
## 设计取舍
|
|
181
|
+
|
|
182
|
+
- **CLI 只装环境,不跑流程**:slash command / prompt 是 LLM-in-the-loop 的设计,CLI 不取代它。
|
|
183
|
+
- **集中 workspace 而非仓库内**:bug 分析阶段不知道改哪个库;多库场景下放任何一个库都尴尬。
|
|
184
|
+
- **workspace 按 profile 隔离**:多 ZenTao 实例(不同客户/环境)的 bug 上下文与注册表互不污染。
|
|
185
|
+
- **worktree 而非 checkout**:主仓库不动,多库场景天然并行。
|
|
186
|
+
- **squash 而非 fast-forward**:主分支只想看一个干净的「fix: #N」commit。
|
|
187
|
+
- **不主动 push / resolve / 删分支**:副作用 / 跨边界操作留给用户显式触发。
|
|
188
|
+
- **uninstall 不动用户数据**:凭据、workspace 不会被 uninstall 删,避免误伤。
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
[MIT](../../LICENSE) © Deven Liu
|
package/dist/agents.d.ts
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
export type AgentId = "claude" | "copilot" | "copilot-cli" | "codex";
|
|
2
|
+
export interface AgentInfo {
|
|
3
|
+
id: AgentId;
|
|
4
|
+
label: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const AGENTS: readonly AgentInfo[];
|
|
7
|
+
/** Pretty label for log output. Centralized so commands don't drift. */
|
|
8
|
+
export declare function describeAgent(agent: AgentId): string;
|
|
9
|
+
/**
|
|
10
|
+
* Resolve which agent to target. If `explicit` is provided it must match a
|
|
11
|
+
* known id (case-insensitive). Otherwise — in interactive shells — show the
|
|
12
|
+
* menu; in non-interactive shells refuse rather than silently picking one.
|
|
13
|
+
*/
|
|
14
|
+
export declare function resolveAgent(explicit?: string): Promise<AgentId>;
|
|
15
|
+
/**
|
|
16
|
+
* Where slash-command / prompt files live for each agent.
|
|
17
|
+
*
|
|
18
|
+
* Claude and Codex have a user-level prompts dir; Copilot has no such concept,
|
|
19
|
+
* so we drop into the repo's `.github/prompts/` (workspace-level prompts).
|
|
20
|
+
*/
|
|
21
|
+
export declare function resolveAgentPromptsDir(agent: AgentId, opts?: {
|
|
22
|
+
explicit?: string;
|
|
23
|
+
repo?: string;
|
|
24
|
+
}): {
|
|
25
|
+
dir: string;
|
|
26
|
+
suffix: string;
|
|
27
|
+
scope: "user" | "workspace";
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Repo-level "tell the AI how to work in this repo" file. Each agent reads a
|
|
31
|
+
* different filename, so we map agent → relative path inside the repo.
|
|
32
|
+
*/
|
|
33
|
+
export declare function resolveAgentInstructionsFile(agent: AgentId, repo: string): {
|
|
34
|
+
abs: string;
|
|
35
|
+
rel: string;
|
|
36
|
+
};
|
|
37
|
+
export interface McpTarget {
|
|
38
|
+
/** File the config will be merged into. */
|
|
39
|
+
path: string;
|
|
40
|
+
/** Format that file uses. */
|
|
41
|
+
format: "json" | "toml";
|
|
42
|
+
/** Top-level key under which servers live (JSON formats). */
|
|
43
|
+
jsonKey?: "mcpServers" | "servers";
|
|
44
|
+
/** Section header used (TOML format). */
|
|
45
|
+
tomlSectionPrefix?: string;
|
|
46
|
+
/** Whether this is a user-level or workspace-level config. */
|
|
47
|
+
scope: "user" | "workspace";
|
|
48
|
+
/** Human-friendly description for log output. */
|
|
49
|
+
describe: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Resolve where an MCP server entry should be written for the given agent.
|
|
53
|
+
*
|
|
54
|
+
* Scope:
|
|
55
|
+
* - "user" (default for all agents): user-level config in the home dir
|
|
56
|
+
* - "workspace": project-level config inside `<repo>` (Claude + Copilot only;
|
|
57
|
+
* Codex has no documented workspace config so we fall back to user-level)
|
|
58
|
+
*/
|
|
59
|
+
export declare function resolveMcpTarget(agent: AgentId, opts?: {
|
|
60
|
+
scope?: "user" | "workspace";
|
|
61
|
+
repo?: string;
|
|
62
|
+
}): McpTarget;
|
package/dist/agents.js
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import { CliError } from "./util.js";
|
|
4
|
+
import { promptLine } from "./prompt.js";
|
|
5
|
+
export const AGENTS = [
|
|
6
|
+
{ id: "claude", label: "Claude Code" },
|
|
7
|
+
{ id: "copilot", label: "GitHub Copilot (VS Code)" },
|
|
8
|
+
{ id: "copilot-cli", label: "GitHub Copilot CLI" },
|
|
9
|
+
{ id: "codex", label: "OpenAI Codex CLI" },
|
|
10
|
+
];
|
|
11
|
+
/** Pretty label for log output. Centralized so commands don't drift. */
|
|
12
|
+
export function describeAgent(agent) {
|
|
13
|
+
return AGENTS.find((a) => a.id === agent)?.label ?? agent;
|
|
14
|
+
}
|
|
15
|
+
/** Resolve ~/.copilot honoring $COPILOT_HOME, used by Copilot CLI. */
|
|
16
|
+
function copilotHome() {
|
|
17
|
+
return process.env.COPILOT_HOME
|
|
18
|
+
? path.resolve(process.env.COPILOT_HOME)
|
|
19
|
+
: path.join(os.homedir(), ".copilot");
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Resolve which agent to target. If `explicit` is provided it must match a
|
|
23
|
+
* known id (case-insensitive). Otherwise — in interactive shells — show the
|
|
24
|
+
* menu; in non-interactive shells refuse rather than silently picking one.
|
|
25
|
+
*/
|
|
26
|
+
export async function resolveAgent(explicit) {
|
|
27
|
+
if (explicit) {
|
|
28
|
+
const lower = explicit.toLowerCase();
|
|
29
|
+
const hit = AGENTS.find((a) => a.id === lower);
|
|
30
|
+
if (!hit) {
|
|
31
|
+
throw new CliError(`Unknown agent '${explicit}'. Supported: ${AGENTS.map((a) => a.id).join(", ")}`);
|
|
32
|
+
}
|
|
33
|
+
return hit.id;
|
|
34
|
+
}
|
|
35
|
+
if (!process.stdin.isTTY) {
|
|
36
|
+
throw new CliError(`--agent is required in non-interactive mode. Supported: ${AGENTS.map((a) => a.id).join(", ")}`);
|
|
37
|
+
}
|
|
38
|
+
process.stdout.write(`Pick a target agent:\n`);
|
|
39
|
+
AGENTS.forEach((a, i) => {
|
|
40
|
+
process.stdout.write(` ${i + 1}) ${a.id.padEnd(8)} ${a.label}\n`);
|
|
41
|
+
});
|
|
42
|
+
const answer = (await promptLine(`Choice [1-${AGENTS.length}] (default 1): `)).trim();
|
|
43
|
+
if (!answer)
|
|
44
|
+
return AGENTS[0].id;
|
|
45
|
+
const byNum = Number(answer);
|
|
46
|
+
if (Number.isInteger(byNum) && byNum >= 1 && byNum <= AGENTS.length) {
|
|
47
|
+
return AGENTS[byNum - 1].id;
|
|
48
|
+
}
|
|
49
|
+
const byId = AGENTS.find((a) => a.id === answer.toLowerCase());
|
|
50
|
+
if (byId)
|
|
51
|
+
return byId.id;
|
|
52
|
+
throw new CliError(`Invalid choice '${answer}'`);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Where slash-command / prompt files live for each agent.
|
|
56
|
+
*
|
|
57
|
+
* Claude and Codex have a user-level prompts dir; Copilot has no such concept,
|
|
58
|
+
* so we drop into the repo's `.github/prompts/` (workspace-level prompts).
|
|
59
|
+
*/
|
|
60
|
+
export function resolveAgentPromptsDir(agent, opts = {}) {
|
|
61
|
+
if (opts.explicit) {
|
|
62
|
+
return { dir: path.resolve(opts.explicit), suffix: promptSuffix(agent), scope: "user" };
|
|
63
|
+
}
|
|
64
|
+
switch (agent) {
|
|
65
|
+
case "claude":
|
|
66
|
+
return { dir: path.join(os.homedir(), ".claude", "commands"), suffix: ".md", scope: "user" };
|
|
67
|
+
case "codex":
|
|
68
|
+
return { dir: path.join(os.homedir(), ".codex", "prompts"), suffix: ".md", scope: "user" };
|
|
69
|
+
case "copilot": {
|
|
70
|
+
const repo = path.resolve(opts.repo ?? process.cwd());
|
|
71
|
+
return { dir: path.join(repo, ".github", "prompts"), suffix: ".prompt.md", scope: "workspace" };
|
|
72
|
+
}
|
|
73
|
+
case "copilot-cli":
|
|
74
|
+
// Copilot CLI has no "slash command" concept; the closest mapping is
|
|
75
|
+
// custom agents at ~/.copilot/agents/<name>.agent.md. They run as
|
|
76
|
+
// /<name> from inside `copilot`.
|
|
77
|
+
return { dir: path.join(copilotHome(), "agents"), suffix: ".agent.md", scope: "user" };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
function promptSuffix(agent) {
|
|
81
|
+
if (agent === "copilot")
|
|
82
|
+
return ".prompt.md";
|
|
83
|
+
if (agent === "copilot-cli")
|
|
84
|
+
return ".agent.md";
|
|
85
|
+
return ".md";
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Repo-level "tell the AI how to work in this repo" file. Each agent reads a
|
|
89
|
+
* different filename, so we map agent → relative path inside the repo.
|
|
90
|
+
*/
|
|
91
|
+
export function resolveAgentInstructionsFile(agent, repo) {
|
|
92
|
+
const repoAbs = path.resolve(repo);
|
|
93
|
+
const rel = agentInstructionsRel(agent);
|
|
94
|
+
return { abs: path.join(repoAbs, rel), rel };
|
|
95
|
+
}
|
|
96
|
+
function agentInstructionsRel(agent) {
|
|
97
|
+
switch (agent) {
|
|
98
|
+
case "claude":
|
|
99
|
+
return "CLAUDE.md";
|
|
100
|
+
case "codex":
|
|
101
|
+
return "AGENTS.md";
|
|
102
|
+
case "copilot":
|
|
103
|
+
return path.join(".github", "copilot-instructions.md");
|
|
104
|
+
case "copilot-cli":
|
|
105
|
+
// Copilot CLI reads AGENTS.md as primary instructions (cross-tool
|
|
106
|
+
// standard, shared with Codex). The .github/copilot-instructions.md
|
|
107
|
+
// file is also read but already covered by the "copilot" target.
|
|
108
|
+
return "AGENTS.md";
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Resolve where an MCP server entry should be written for the given agent.
|
|
113
|
+
*
|
|
114
|
+
* Scope:
|
|
115
|
+
* - "user" (default for all agents): user-level config in the home dir
|
|
116
|
+
* - "workspace": project-level config inside `<repo>` (Claude + Copilot only;
|
|
117
|
+
* Codex has no documented workspace config so we fall back to user-level)
|
|
118
|
+
*/
|
|
119
|
+
export function resolveMcpTarget(agent, opts = {}) {
|
|
120
|
+
const scope = opts.scope ?? "user";
|
|
121
|
+
const repo = path.resolve(opts.repo ?? process.cwd());
|
|
122
|
+
if (agent === "claude") {
|
|
123
|
+
if (scope === "workspace") {
|
|
124
|
+
return {
|
|
125
|
+
path: path.join(repo, ".mcp.json"),
|
|
126
|
+
format: "json",
|
|
127
|
+
jsonKey: "mcpServers",
|
|
128
|
+
scope: "workspace",
|
|
129
|
+
describe: "Claude Code project-scope config (.mcp.json)",
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
return {
|
|
133
|
+
path: path.join(os.homedir(), ".claude.json"),
|
|
134
|
+
format: "json",
|
|
135
|
+
jsonKey: "mcpServers",
|
|
136
|
+
scope: "user",
|
|
137
|
+
describe: "Claude Code user config (~/.claude.json)",
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
if (agent === "copilot") {
|
|
141
|
+
if (scope === "workspace") {
|
|
142
|
+
return {
|
|
143
|
+
path: path.join(repo, ".vscode", "mcp.json"),
|
|
144
|
+
format: "json",
|
|
145
|
+
jsonKey: "servers",
|
|
146
|
+
scope: "workspace",
|
|
147
|
+
describe: "VS Code workspace MCP config (.vscode/mcp.json)",
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
path: vsCodeUserMcpPath(),
|
|
152
|
+
format: "json",
|
|
153
|
+
jsonKey: "servers",
|
|
154
|
+
scope: "user",
|
|
155
|
+
describe: "VS Code user MCP config (User/mcp.json)",
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
if (agent === "copilot-cli") {
|
|
159
|
+
if (scope === "workspace") {
|
|
160
|
+
// Copilot CLI accepts either `<repo>/.mcp.json` or
|
|
161
|
+
// `<repo>/.github/mcp.json` at the project level. We default to
|
|
162
|
+
// `.mcp.json` because it's the shared cross-tool path also used by
|
|
163
|
+
// Claude Code's project scope — one file covers both agents.
|
|
164
|
+
return {
|
|
165
|
+
path: path.join(repo, ".mcp.json"),
|
|
166
|
+
format: "json",
|
|
167
|
+
jsonKey: "mcpServers",
|
|
168
|
+
scope: "workspace",
|
|
169
|
+
describe: "Copilot CLI project config (.mcp.json)",
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
return {
|
|
173
|
+
path: path.join(copilotHome(), "mcp-config.json"),
|
|
174
|
+
format: "json",
|
|
175
|
+
jsonKey: "mcpServers",
|
|
176
|
+
scope: "user",
|
|
177
|
+
describe: "Copilot CLI user config (~/.copilot/mcp-config.json)",
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
// codex — TOML, user-only.
|
|
181
|
+
return {
|
|
182
|
+
path: path.join(os.homedir(), ".codex", "config.toml"),
|
|
183
|
+
format: "toml",
|
|
184
|
+
tomlSectionPrefix: "mcp_servers",
|
|
185
|
+
scope: "user",
|
|
186
|
+
describe: "Codex CLI config (~/.codex/config.toml)",
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function vsCodeUserMcpPath() {
|
|
190
|
+
const home = os.homedir();
|
|
191
|
+
if (process.platform === "darwin") {
|
|
192
|
+
return path.join(home, "Library", "Application Support", "Code", "User", "mcp.json");
|
|
193
|
+
}
|
|
194
|
+
if (process.platform === "win32") {
|
|
195
|
+
const appData = process.env.APPDATA ?? path.join(home, "AppData", "Roaming");
|
|
196
|
+
return path.join(appData, "Code", "User", "mcp.json");
|
|
197
|
+
}
|
|
198
|
+
// linux + others
|
|
199
|
+
const xdg = process.env.XDG_CONFIG_HOME ?? path.join(home, ".config");
|
|
200
|
+
return path.join(xdg, "Code", "User", "mcp.json");
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.js","sourceRoot":"","sources":["../src/agents.ts"],"names":[],"mappings":"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"}
|