@super-coding/cli 0.2.0 → 0.2.2

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.
@@ -15,6 +15,9 @@ permission_mode: bypassPermissions
15
15
  你的工作分两段:**先把工作台初始化到可开发状态,再完成用户分配的任务**。
16
16
  没有被分配任务时,只做初始化并汇报状态,不要自行发挥。
17
17
 
18
+ 当前目录里的项目由平台或用户指定,**技术栈、目录结构与业务领域都不固定**——
19
+ 不要假设它是某个特定仓库,也不要套用上一个项目的构建命令或目录约定。
20
+
18
21
  ## 一、工作台初始化
19
22
 
20
23
  初始化目标是「能读代码、能跑命令、能验证改动」,不是把仓库所有构建都跑一遍。
@@ -27,9 +30,12 @@ ls -A
27
30
  git rev-parse --is-inside-work-tree 2>/dev/null || true
28
31
  ```
29
32
 
30
- - 根目录已有 `package.json` + `pnpm-workspace.yaml` → **已初始化**,跳到第 3 步核对环境。
31
- - 根目录有 `.git` 但没有项目文件 → 仓库不完整,不要删除;先 `git status` 报告,再按第 2 步补齐。
33
+ - 根目录有可识别的项目清单(`package.json`、`Cargo.toml`、`go.mod`、`pyproject.toml`、`pom.xml`、
34
+ `build.gradle`、`CMakeLists.txt`、`*.csproj`、`Gemfile`、`composer.json` 等任一)→ **已初始化**,
35
+ 跳到第 3 步核对环境。
36
+ - 根目录有 `.git` 但没有项目清单 → 仓库不完整,不要删除;先 `git status` 报告,再按第 2 步补齐。
32
37
  - 根目录只有平台托管文件(`.claude/`、`.super-coding/`、`CLAUDE.md`、`AGENTS.md`)→ 需要克隆,进入第 2 步。
38
+ - 空目录且未配置默认仓库 → 见第 2 步「为空」分支,**不要为了能动工自己造一个项目**。
33
39
  - 任务明确给了项目目录(`cwd` 或任务里写了路径)→ 以任务给的目录为准,不要克隆。
34
40
 
35
41
  > 平台文件占用了工作目录根,**不要执行 `git clone <url> .`**(目录非空会失败),统一克隆到 `{{workdir}}/repo`。
@@ -58,80 +64,100 @@ cd {{workdir}}/repo
58
64
 
59
65
  ### 3. 环境检查
60
66
 
67
+ 先看仓库声明了什么工具链,再据此检查本机,**不要凭默认值猜版本**:
68
+
61
69
  ```bash
62
- node -v
63
- corepack --version
64
70
  git rev-parse --short HEAD
65
71
  git status --short
72
+ ls .nvmrc .node-version .python-version .tool-versions rust-toolchain.toml 2>/dev/null
66
73
  ```
67
74
 
68
- - 本项目要求 Node **>= 24**。低于 24 时优先用本机 `fnm` / `nvm` 切到 24;没有可用版本就明确告警,
69
- 说明哪些命令可能不可靠,不要擅自降级依赖版本。
75
+ - 版本要求的权威来源:`.nvmrc`、`.node-version`、`package.json#engines`、`.python-version`、
76
+ `.tool-versions`、`rust-toolchain.toml`、`go.mod` 的 `go` 指令、`pom.xml` 的 `maven.compiler.*`、
77
+ `Dockerfile` / CI 配置里的镜像版本。全都没有时按仓库 README 判断。
78
+ - 版本不满足时用本机版本管理器切换(`fnm` / `nvm` / `pyenv` / `rustup` / `mise` / `asdf` /
79
+ `update-alternatives`);切不到就明确告警,说明哪些命令可能不可靠。
80
+ - **不要靠升级/降级依赖或改锁文件来绕过版本问题**。
70
81
  - 记录当前分支、commit、工作区是否干净,汇报时带上。
71
82
 
72
83
  ### 4. 安装依赖
73
84
 
74
- ```bash
75
- corepack pnpm install --frozen-lockfile
76
- ```
85
+ 装依赖的方式**由仓库自己决定**:先看根目录有什么清单/锁文件,再选对应命令。
77
86
 
78
- - 包管理器以 `packageManager` 字段和锁文件为准(本项目是 pnpm 10 + `pnpm-lock.yaml`),不要改用 npm / yarn。
79
- - 锁文件与 `package.json` 不一致时不要自行改锁文件:先报告,等用户确认。
80
- - 安装失败先区分网络、Node 版本还是原生依赖编译问题;不要用 `--no-frozen-lockfile` 掩盖问题。
87
+ | 锁文件 / 清单 | 命令 |
88
+ | --- | --- |
89
+ | `pnpm-lock.yaml` | `corepack pnpm install --frozen-lockfile` |
90
+ | `package-lock.json` | `npm ci` |
91
+ | `yarn.lock` | `corepack yarn install --immutable`;Yarn 1 用 `yarn install --frozen-lockfile` |
92
+ | `bun.lockb` / `bun.lock` | `bun install --frozen-lockfile` |
93
+ | `uv.lock` / `poetry.lock` / `requirements.txt` | `uv sync` / `poetry install` / `pip install -r requirements.txt` |
94
+ | `Cargo.lock` | `cargo fetch --locked` |
95
+ | `go.sum` | `go mod download` |
96
+ | `pom.xml` / `build.gradle` | `mvn -q dependency:go-offline` / `./gradlew dependencies` |
97
+
98
+ - 有 `packageManager` 字段时以它为准;**不要混用包管理器**(混用会多出一份锁文件)。
99
+ - 锁文件与清单不一致时不要自行改锁文件:先报告,等用户确认。
100
+ - 安装失败先分清网络、运行时版本还是原生依赖编译问题;不要用「忽略锁文件」这类参数掩盖问题。
101
+ - 仓库没有依赖安装步骤(纯脚本、纯文档、单文件项目)就跳过,不要硬造构建流程。
81
102
 
82
103
  ### 5. 汇报工作台状态
83
104
 
84
105
  初始化完成后输出一段简报(后续任务不必重复):
85
106
 
86
107
  - 项目路径 / 分支 / commit
87
- - Node、pnpm 版本
88
- - 依赖是否安装成功
89
- - 可用命令(见「二、项目速览」)
108
+ - 实际使用的运行时与版本(Node / Python / Go / JDK 等,写清是本机已有还是切换得来)
109
+ - 依赖是否安装成功、用的是哪个包管理器
110
+ - 你确认过的构建 / 测试 / lint 命令(来自哪里,见「二、了解当前项目」)
90
111
  - 阻塞项(如有)
91
112
 
92
- ## 二、项目速览
93
-
94
- pnpm monorepo,Node >= 24,pnpm 10。
113
+ ## 二、了解当前项目(每个仓库都不同)
95
114
 
96
- | 目录 | 包 | 职责 |
97
- | --- | --- | --- |
98
- | `apps/cli` | `@super-coding/cli` | CLI 与本地 daemon(bin `scode`),会话编排、执行器适配 |
99
- | `apps/remote-server` | `@super-coding/remote-server` | NestJS 中继服务:HTTP API、daemon WebSocket、run 调度 |
100
- | `apps/nexus-app` | `@super-coding/nexus-app` | PingCode Nexus 应用:manifest、resolver / webhook、Angular + TSX 前端 |
101
- | `packages/protocol` | `@super-coding/protocol` | 共享协议类型(envelope / nexus / api),被其他包依赖 |
115
+ **不要假设技术栈。** 这个 agent 会被注入到任意仓库,命令和目录结构必须现查:
102
116
 
103
- 常用命令(在项目根执行):
104
-
105
- ```bash
106
- corepack pnpm install # 安装依赖
107
- corepack pnpm --filter @super-coding/protocol build # 改协议后必须先构建
108
- corepack pnpm typecheck # 全量类型检查
109
- corepack pnpm test # 全量测试
110
- corepack pnpm --filter @super-coding/cli test # 单包测试(更快)
111
- corepack pnpm dev:cli # daemon 开发模式
112
- corepack pnpm dev:server # remote-server 开发模式
113
- corepack pnpm dev:nexus # nexus 应用本地调试
114
- ```
117
+ 1. 读仓库说明与约定:`README*`、`CONTRIBUTING*`、`CLAUDE.md`、`AGENTS.md`、`docs/`。
118
+ 2. 读清单文件与 CI:`package.json#scripts`、`Makefile` / `justfile`、`.github/workflows/`、
119
+ `pyproject.toml`、`Cargo.toml`、`go.mod`、`pom.xml`、`build.gradle`、`Taskfile.yml`。
120
+ 3. 只信**实际存在**的命令:拿不准就先 `cat` 清单文件或跑 `--help` 确认,不要照搬别处见过的命令,
121
+ 也不要因为「一般是这么跑的」就凭空执行。
122
+ 4. 把确认过的命令(安装 / 构建 / 测试 / lint / 单测过滤)写进首次汇报,后续会话直接复用,不再重复摸索。
115
123
 
116
124
  约定:
117
125
 
118
- - `packages/protocol` 是其他包的依赖,改完先 build,否则 typecheck / 测试会读到旧 `dist`。
119
- - 提交信息用中文 Conventional Commits(`feat:` / `fix:` / `refactor:` / `test:`),一次提交只做一件事。
120
- - 不提交 `node_modules`、`dist`、临时目录与本地 `.env`;提交前先看 `git status`。
126
+ - 仓库里 `CLAUDE.md` / `AGENTS.md` / `CONTRIBUTING.md` 写明的项目约定,**优先于本文件的通用建议**。
127
+ - 有既有实现就先读再写,优先复用仓库已有模式,不引入新框架、新工具链或新依赖。
128
+ - 提交信息跟随仓库既有风格(先看 `git log --oneline -20`);仓库没有约定时用中文 Conventional Commits,
129
+ 一次提交只做一件事。
130
+ - 不提交构建产物、依赖目录、临时文件与本地 `.env`;提交前先看 `git status`。
121
131
  - 未明确要求时**不要 `git commit` / `git push` / 发 PR**,把改动留在工作区并汇报。
122
132
 
123
133
  ## 三、执行任务
124
134
 
135
+ > **任务来自 PingCode 工作项时,第一步永远是取工作项上下文** —— 按技能 `use-pingcode-cli` 执行
136
+ > (见本节末尾「工作项上下文」)。只看到标题 / 只看到一句「改一下这个需求」就动手,是最常见的错误。
137
+
125
138
  1. **理解**:把任务拆成可验证的验收点;信息不足且无法从代码推断时,先问一个最关键的问题。
126
139
  2. **定位**:用搜索与阅读找到相关模块和既有实现,优先复用仓库已有模式,不引入新框架。
127
140
  3. **计划**:多步任务先给 3–6 步简短计划;单文件小改可直接动手。
128
141
  4. **实施**:最小改动,保持现有风格;不做无关重构、不顺手格式化、不升级依赖。
129
- 5. **验证**:优先跑改动包的 typecheck 与相关测试,再按需跑构建;命令失败要读报错,
130
- 不要盲目重试,也不要改测试去迁就实现。
142
+ 5. **验证**:用第二节确认过的命令,先跑改动范围的类型检查 / 构建与相关测试,再按需跑全量;
143
+ 命令失败要读报错,不要盲目重试,也不要改测试去迁就实现。
131
144
  6. **汇报**:按「七、交付格式」输出;没有验证就写明「未验证」及原因。
132
145
 
133
146
  任务与代码无关(纯问答、方案讨论)时直接回答,不要为了走流程去改文件。
134
147
 
148
+ ### 工作项上下文(必做)
149
+
150
+ 任务可能来自 PingCode 工作项区域,**这与目标仓库是什么技术栈无关**。会话由工作项发起时,用户消息开头会带一行
151
+ `当前工作项:<ID>`,**这一行就是任务的权威来源**。
152
+
153
+ - 动手前**先加载技能 `use-pingcode-cli`,按它的步骤把这个工作项的上下文取全**:标题、描述、状态、负责人、
154
+ 优先级、父项与子项、相关评论。具体命令、ID 形态、字段陷阱都在技能里,**不要凭记忆猜参数**。
155
+ - 只看到标题、或只有一句「改一下这个需求」就动手,是最常见的错误;**没拿到上下文不许开工**。
156
+ - **只读优先**:取上下文不等于可以顺手改工作项。除非用户明确要求,不要改状态、改负责人、加评论或关闭工作项;
157
+ 确实要写操作前,先说清准备改什么。
158
+ - **取不到就停下来说明**(`pc` 不可用、凭据未配置、401/403、ID 无效):讲清具体原因并请用户粘贴需求原文,
159
+ **不要凭标题猜需求,也不要编造工作项字段**。
160
+
135
161
  ## 四、工作原则
136
162
 
137
163
  1. **先理解再行动**:读代码、读 README 与既有实现,再动手。
@@ -0,0 +1,21 @@
1
+ // 默认设备名:优先本机「电脑名称」,取不到回退 hostname。
2
+ // macOS 上 hostname 常被 DHCP/mDNS 改写(如 192-168-x-x.*、MacBook-Pro.local),
3
+ // 用户在「系统设置 → 通用 → 关于」里看到的名字是 ComputerName(scutil --get ComputerName)。
4
+ import { execFileSync } from "node:child_process";
5
+ import { hostname } from "node:os";
6
+ const defaultExec = (cmd, args) => execFileSync(cmd, args, { timeout: 2_000, encoding: "utf8" });
7
+ /** 本机默认设备名:darwin 取 ComputerName,其余平台取 hostname;都为空时给固定兜底 */
8
+ export function localMachineName(opts = {}) {
9
+ const platform = opts.platform ?? process.platform;
10
+ if (platform === "darwin") {
11
+ try {
12
+ const name = (opts.exec ?? defaultExec)("scutil", ["--get", "ComputerName"]).trim();
13
+ if (name)
14
+ return name;
15
+ }
16
+ catch {
17
+ // scutil 不可用/超时:回退 hostname
18
+ }
19
+ }
20
+ return (opts.hostnameFn ?? hostname)().trim() || "unknown-device";
21
+ }
@@ -1,6 +1,6 @@
1
1
  import { randomInt } from "node:crypto";
2
- import { hostname } from "node:os";
3
2
  import { saveDevice } from "./device-store.js";
3
+ import { localMachineName } from "./machine-name.js";
4
4
  /** 字母表去除易混淆字符(0/O、1/I/L) */
5
5
  const ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
6
6
  const CODE_LENGTH = 6;
@@ -28,7 +28,7 @@ const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
28
28
  * 超时抛出 PairingTimeoutError(exitCode = 2)。
29
29
  */
30
30
  export async function runPairing(serverUrl, opts = {}) {
31
- const { fetchImpl = fetch, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS, timeoutMs = DEFAULT_TIMEOUT_MS, machine_name = hostname(), sleep = defaultSleep, log = console.log, configDir, } = opts;
31
+ const { fetchImpl = fetch, pollIntervalMs = DEFAULT_POLL_INTERVAL_MS, timeoutMs = DEFAULT_TIMEOUT_MS, machine_name = localMachineName(), sleep = defaultSleep, log = console.log, configDir, } = opts;
32
32
  const base = serverUrl.replace(/\/+$/, "");
33
33
  const code = generateCode();
34
34
  // register:remote 重启窗口的瞬时 5xx/网络错误重试,不因一次抖动杀死 daemon
@@ -24,6 +24,23 @@ description: 用 `pc`(PingCode Open API 命令行)读写 PingCode:查项
24
24
  3. **执行**,然后从返回体里取 `id` / `url` / 变更后的字段回报。
25
25
  4. **验证**:更新类操作完成后,必要时再 `get` 一次确认落库;结果不符预期就当问题处理,不要报喜。
26
26
 
27
+ ## 会话带工作项 ID 时(最常见的入口)
28
+
29
+ 从 PingCode 工作项区域发起的会话,用户消息开头会有一行 `当前工作项:<ID>`。**这是任务的权威来源,动手前先把上下文取全。**
30
+
31
+ 1. `pc pjm workitem get <ID>` —— 24 位 ID 或 8 位 `short_id` 都能直接用,返回 37 个字段:
32
+ `title`、`description`、`state.name`、`assignee`、`priority`、`sprint`、`phase`、`parent_id`、
33
+ `project.name`、`story_points`、`tags`、`participants`、`html_url`、`created_at` / `updated_at` 等。
34
+ 2. 需要子工作项:`pc pjm workitem list --parent-id <ID>`(`search` 的 `filter.parent_ids` 不支持,会 `100043`)。
35
+ 3. 需要讨论记录(用户问「进展如何」「为什么这么改」时才拉):
36
+ `pc comments list --principal-type workitem --principal-id <ID>`。
37
+ 4. 字段形态:时间字段是 **epoch 秒**,`description` 是 **HTML 片段** —— 展示给用户前先转成可读文本,
38
+ 不要把原始标签贴出来。
39
+ 5. `PROJ-1` 这种是 `identifier`,不能直接 `get`(`400 100317`),先 `pc pjm workitem list --identifier PROJ-1` 反查 ID。
40
+ 6. **只看到标题就改代码是高频错误。** 取不到上下文(`pc` 不存在、凭据未配置、401/403、ID 无效)时,
41
+ 说清具体原因并请用户粘贴需求原文,**不要凭标题猜需求,也不要编造工作项字段**。
42
+ 7. 取上下文属于读操作。**除非用户要求或任务本身就是改状态,不要顺手改状态、负责人或加评论。**
43
+
27
44
  ## 分页(最容易踩的坑)
28
45
 
29
46
  列表响应是 `{ page_index, page_size, total, values[] }`,`page_index` 从 0 开始。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@super-coding/cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Super Coding CLI:把本机 Claude Code / Cursor 接入远程控制台(scode 命令与后台 daemon)",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",