@clawos-dev/clawd 0.2.628 → 0.2.630

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 (24) hide show
  1. package/dist/cli.cjs +1 -1
  2. package/dist/persona-defaults/persona-app-builder/.claude/skills/app-builder-projects/SKILL.md +62 -57
  3. package/dist/persona-defaults/persona-app-builder/CLAUDE.md +22 -34
  4. package/dist/persona-defaults/persona-app-builder/extension-kit/README.md +25 -96
  5. package/dist/persona-defaults/persona-clawd-butler/.claude/skills/clawd-config-editor/SKILL.md +10 -29
  6. package/dist/persona-defaults/persona-clawd-butler/.claude/skills/clawd-introspection/SKILL.md +2 -2
  7. package/dist/persona-defaults/persona-clawd-butler/.claude/skills/clawd-orchestration/SKILL.md +2 -2
  8. package/dist/persona-defaults/persona-clawd-butler/.claude/skills/clawd-product/SKILL.md +1 -1
  9. package/dist/persona-defaults/persona-clawd-butler/.claude/skills/clawd-session-import/SKILL.md +10 -19
  10. package/dist/persona-defaults/persona-clawd-butler/.claude/skills/clawd-session-lens/SKILL.md +7 -7
  11. package/dist/persona-defaults/persona-clawd-butler/.claude/skills/persona-authoring/SKILL.md +2 -3
  12. package/dist/persona-defaults/persona-clawd-butler/.claude/skills/scan-persona-for-deploy/SKILL.md +18 -27
  13. package/dist/persona-defaults/persona-clawd-butler/.claude/skills/scan-sessions-suggest-personas/SKILL.md +10 -15
  14. package/dist/persona-defaults/persona-clawd-butler/CLAUDE.md +27 -51
  15. package/dist/persona-defaults/persona-dataclaw-builder/.claude/skills/app-builder-projects/SKILL.md +62 -57
  16. package/dist/persona-defaults/persona-dataclaw-builder/CLAUDE.md +6 -14
  17. package/dist/persona-defaults/persona-dataclaw-builder/extension-kit/README.md +29 -83
  18. package/dist/persona-defaults/persona-feishu-assistant/CLAUDE.md +12 -75
  19. package/dist/persona-defaults/persona-html-slides/CLAUDE.md +11 -19
  20. package/dist/persona-defaults/persona-knowledge-base/CLAUDE.md +8 -19
  21. package/dist/persona-defaults/persona-master/.claude/agents/line-watcher.md +22 -49
  22. package/dist/persona-defaults/persona-master/CLAUDE.md +8 -10
  23. package/dist/persona-defaults/persona-researcher/CLAUDE.md +9 -20
  24. package/package.json +1 -1
@@ -7,26 +7,26 @@ description: 把用户本机 Claude Code / Codex 的历史会话关联成 clawd
7
7
 
8
8
  用户在 Claude Code 或 Codex 里已经聊过很多,刚切到 clawd 会看到一个空侧边栏,
9
9
  不知道从哪儿接着干。这个 skill 扫描本机这两个工具最近的会话,在 clawd 里给每条
10
- 建一个引用,于是它们出现在侧边栏——点开能看到完整原始对话,发消息就接着往下聊。
10
+ 建一个引用,于是它们出现在侧边栏——点开能在来源 transcript 可访问时读取原始对话,发消息就接着往下聊。
11
11
 
12
12
  **只建引用,不复制、不移动、不修改任何原始会话文件**,原会话在 Claude Code / Codex
13
- 里照常可用。关联是可撤销的。
13
+ 里照常可用。关联可用本工具 undo 撤销;apply / undo 会写引用与台账,不修改来源 transcript。
14
14
 
15
15
  ## 用法
16
16
 
17
17
  只依赖 node(clawd 本身就是 node 跑的,必然有)。脚本就在本 skill 目录下,下面的命令
18
- 按会话工作目录(persona 目录)写相对路径。
18
+ 使用本 SKILL.md 所在目录的绝对路径;不假定当前 cwd。仅在用户授权范围内扫描本机外部历史,guest / cloud 不代表能导入 owner 电脑记录。脚本通过内部 rpc-tool.mcp.json 获得 daemon 连接,agent 不直接读取该认证配置。
19
19
 
20
20
  先预演,看看会关联哪些(不写任何东西):
21
21
 
22
22
  ```bash
23
- node .claude/skills/clawd-session-import/scripts/link-sessions.mjs --days 7
23
+ node <skill绝对路径>/scripts/link-sessions.mjs --days 7
24
24
  ```
25
25
 
26
26
  **把预演结果念给用户看**(几条、都是什么话题、来自哪些目录),确认后再执行:
27
27
 
28
28
  ```bash
29
- node .claude/skills/clawd-session-import/scripts/link-sessions.mjs --days 7 --apply
29
+ node <skill绝对路径>/scripts/link-sessions.mjs --days 7 --apply
30
30
  ```
31
31
 
32
32
  常用参数:
@@ -45,8 +45,8 @@ node .claude/skills/clawd-session-import/scripts/link-sessions.mjs --days 7 --ap
45
45
  撤销(删掉本工具建过的全部引用,原会话文件不受影响):
46
46
 
47
47
  ```bash
48
- node .claude/skills/clawd-session-import/scripts/link-sessions.mjs --undo # 预演
49
- node .claude/skills/clawd-session-import/scripts/link-sessions.mjs --undo --apply # 真删
48
+ node <skill绝对路径>/scripts/link-sessions.mjs --undo # 预演
49
+ node <skill绝对路径>/scripts/link-sessions.mjs --undo --apply # 真删
50
50
  ```
51
51
 
52
52
  台账里 session 已被手动删除的条目,`--undo` 只清账、不再调删除接口 —— 清掉后该会话
@@ -83,18 +83,9 @@ node .claude/skills/clawd-session-import/scripts/link-sessions.mjs --undo --appl
83
83
 
84
84
  ## 标题(label)从哪来
85
85
 
86
- **Claude Code 有现成的**:transcript 里 `type: "ai-title"` 那行的 `aiTitle`,是 CC 自己
87
- 生成的会话标题(如「扫描设备sessions创建用户persona」),直接拿来用。实测覆盖率 89%,
88
- 且缺失的那批全是 0~1 轮的「hello」「你是谁」,被默认 `--min-turns 2` 挡掉了——**实际关联
89
- 进来的 CC 会话都有现成标题**。
86
+ **Claude Code**:优先读取 transcript 的 ai-title / aiTitle;覆盖率取决于数据,缺失时按脚本回落,不能保证导入条条有标题。
90
87
 
91
- (注:clawd 原生的历史列表用的是另一套优先级 `last-prompt` → `summary` → 首句前 120 字,
92
- 没用 `ai-title`。所以这里的标题会比 clawd 历史列表更像标题,属预期。)
93
-
94
- **Codex 没有**:`threads` 表的 `title` / `preview` / `first_user_message` 三列都是第一条
95
- 用户消息**原文**,不是 AI 摘要;`name` 疑似手动命名字段,实测数据全空。取值顺序
96
- `name` → `title` → `preview` → `first_user_message` → 解析 rollout 取首句,将来 codex
97
- 补上真标题能自动吃到。
88
+ **Codex**:脚本依次尝试 name → title → preview → first_user_message → rollout 首句。各字段可能随 Codex 版本改变,不能保证它们永远是原文或永远不是摘要。
98
89
 
99
90
  拿到什么就是什么,**按显示宽度硬截到 56 列**(中文算 2 列),不做任何清洗或改写——
100
91
  标题应当忠实反映用户原话,不引入猜测。唯一的处理是把换行 / 连续空白折叠成单空格,
@@ -113,6 +104,6 @@ node .claude/skills/clawd-session-import/scripts/link-sessions.mjs --undo --appl
113
104
 
114
105
  - clawd 桌面端得在跑,否则脚本连不上(会明确报错)
115
106
  - 如果脚本提示 daemon 没有 `session:importExternal`,说明当前 clawd 还没升级/重启到支持后台导入的版本;脚本不会退回旧的直接改 JSON 路径
116
- - Codex 会话在 clawd 里不支持回滚 / fork / 实时接管(这是 codex 侧的能力边界,
107
+ - Codex 会话在 clawd 里当前 adapter 支持 fork,不支持回滚 / 实时接管(这是 codex 侧的能力边界,
117
108
  不是关联的问题);能看能续聊
118
109
  - 会话很多时一次全灌会把侧边栏冲爆,建议配 `--limit` 分批,或先用 `--days 3` 试水
@@ -19,20 +19,20 @@ description: 老板要看 session 内容时触发——汇总某个时段的会
19
19
 
20
20
  ### ⚠️ 一律走 RPC,不要扫 `~/.clawd/sessions/`
21
21
 
22
- 两个独立的坑叠在一起,**都是静默返回空、不报错**:
22
+ 目录扫描不能代表会话全集:
23
23
 
24
- 1. 对话正文不在 session 文件里(在 AI 工具自己的 transcript 里)→ grep 关键词永远搜不到
24
+ 1. 对话正文不在 session 文件里(在 AI 工具自己的 transcript 里)→ 只搜 metadata 不能覆盖正文
25
25
  2. 会话按归属分目录,`~/.clawd/sessions/` **只装不属于任何分身的**;分身名下的全在
26
- `~/.clawd/personas/<personaId>/.clawd/sessions/owner/` → 拿 `ownerPersonaId` 筛那个目录**恒为空**
26
+ `~/.clawd/personas/<personaId>/.clawd/sessions/owner/` → 只扫顶层会漏掉这些会话
27
27
 
28
28
  别据此说"老板没聊过这事"/"这个分身没有会话"。三件事三个 RPC:
29
29
 
30
30
  - **列会话**:`session:list({ownerPersonaId?, limit?, offset?})` —— 按 `updatedAt` 倒序回元信息
31
- 全集(label / cwd / unreadAt / archivedAt / pinnedAt / dispatchedFromSessionId ...)。
32
- 按时段、按 persona、找未读、找未归档**都在这一步的结果上过滤**
31
+ 当前分页的元信息(label / cwd / unreadAt / archivedAt / pinnedAt / dispatchedFromSessionId ...)。
32
+ 需要完整范围时先取完分页,再按时段、persona、未读与归档状态过滤
33
33
  - **搜内容**:`session:searchContent({query, sessionIds, limit?})` —— 候选 id 自己从
34
34
  `session:list` 按 `updatedAt` 倒序传进去(daemon 不自己筛)。只搜用户/助手说的话,
35
- thinking、工具入参、工具结果**搜不到**,每条会话只回第一处命中
35
+ thinking、工具入参、工具结果**搜不到**,每条会话只回第一处命中;当前搜索主要覆盖本机 Claude / Codex transcript,不保证覆盖 Pi、云端或远端历史
36
36
  - **拉某条**:`history:read({sessionId, limit, slim: true})`。**`slim: true` 几乎总是要带**,
37
37
  否则工具调用原文吃掉一大块 context
38
38
 
@@ -42,7 +42,7 @@ description: 老板要看 session 内容时触发——汇总某个时段的会
42
42
 
43
43
  两份都拉不到就直接用 `session:list` / `session:searchContent` / `history:read` —— 参数名不确定
44
44
  就先 `list` 一下 RPC 清单。**别退回去扫 `~/.clawd/sessions/`**,那条路本身是坏的(见上)。
45
- **任何字段含义不确定就明说"这个字段我不确定含义,让 David 看一眼再答"**,别瞎解释。
45
+ **任何字段含义不确定就明说"这个字段我不确定含义,先核方法表与文档,仍不明确就说明证据缺口"**,别瞎解释。
46
46
 
47
47
  ## 回答风格
48
48
 
@@ -43,8 +43,7 @@ description: 老板要在 clawd 里加一个新 persona 时触发——「我想
43
43
 
44
44
  - 让产出的 persona 知道"它是 clawd 的一个 persona"——避免新 persona 把自己说成独立产品
45
45
  - 红线写**具体行为**("不擅自归类" / "不堆根目录"),不写空话("要谨慎" / "要负责")
46
- - 老板的全局 CLAUDE.md 已经规定"每次回答必须以'老板'开头",新 persona 自动继承,
47
- persona 级 CLAUDE.md 里不用重复
46
+ - 称呼规则来自当前会话/部署实际加载的指令,不能承诺新 persona 自动继承 owner 的所有全局规则。需要固定称呼时写进人格,并明确 guest 按连接上下文的身份处理
48
47
  - 从 `scan-sessions-suggest-personas` 转交过来的候选,把画像卡里的**行为特征**沉淀进去
49
48
  (常用什么工具、碰什么文件、边界在哪),别只写一句空泛的定位
50
49
 
@@ -73,7 +72,7 @@ call({ method: "persona:create", args: {
73
72
  一句话报 persona id + 显示名,然后**简短问一句**:"这个 persona 要装哪些 skill 吗?"
74
73
 
75
74
  - 老板回"不用" / "暂时不需要" → 跳过
76
- - 老板说要 → 让老板给 skill 名(`<author>/<skill-name>` 形式),你帮他跑 `npx skills add <name> -y`
75
+ - 老板说要 → 让老板给 skill 名(`<author>/<skill-name>` 形式),由 owner 在新 persona 的目录运行 `npx skills add <name> -a claude-code --copy -y`(不带 -g);先核对该 CLI 的 --help。不要在管家 cwd 安装到错误 persona,guest 不能写 persona 目录
77
76
 
78
77
  **不要复述 CLAUDE.md 全文。** 老板要看自己会去看。
79
78
 
@@ -25,7 +25,7 @@ description: 老板要把某个 persona 发布到云上时触发——把这个
25
25
  git diff --name-only <任务里给的 sha> -- .
26
26
  ```
27
27
 
28
- 拿到的就是要重看的文件——**这就是「线上那版跟现在」的全部差别**。清单里其余的 `secret` / `connector`
28
+ 拿到的就是要重看的文件——**这是已跟踪内容与给定 commit 的差异入口;未跟踪文件、外部依赖和运行配置不在此命令覆盖内**。清单里其余的 `secret` / `connector`
29
29
  条目原样有效,不用重报:重报没变的东西不但白花时间,还会让本来稳定的字段(比如凭据的命名引用)无谓地变来变去。
30
30
  **`package` 条目例外——每次软扫都要重报一遍**,见下一节。
31
31
 
@@ -55,26 +55,18 @@ git diff --name-only <任务里给的 sha> -- .
55
55
 
56
56
  ## 你要回答的问题
57
57
 
58
- 这个 persona 如果被搬到一台**干净的 Linux 容器**里跑(没有任何人的 home 目录、没有预装工具、
59
- 没有任何凭据),需要事先给它备好什么,它才能正常干活?
58
+ 这个 persona 如果被搬到一台**干净的 Linux 容器**里跑(没有任何人的 home 目录、只有下文所列底座工具、
59
+ 凭据由宿主另行注入),需要事先给它备好什么,它才能正常干活?
60
60
 
61
61
  ## 云上容器已经有的
62
62
 
63
- 「干净」是相对的——底座镜像和容器本身已经带了下面这些。**这些一律不报 `package`、不写进 `notes`**,
64
- 也别在任何上报里替它们操心(「需要 node」「得有可写目录」「登录态怎么进去」这类话都不该出现):
63
+ 底座清单以 clawd/protocol/src/environment-schemas.ts 的 CLOUD_ROOT_PROVIDES / CLOUD_BASE_PROVIDES 与 cloud-host/Dockerfile.base 为准。当前已提供 Node 22、npm/npx、git、Codex、Pi 及其桥接组件、lark-cli、python3、jq、rsync、psql、Chromium、中文字体、pnpm、whiteboard-cli、s、supabase-mcp、mcp-server-kibana、aliyun。不要重复报这些 package;已有工具仍可能需要连接器与凭据。
65
64
 
66
- | 有什么 | 说明 |
67
- |---|---|
68
- | node 22、npm、npx | 底座镜像就是 `node:22-trixie-slim`。npm 包型的 MCP server / CLI 只需报一条 `package` 让它预装,node 本身不用管 |
69
- | git | 底座自带 |
70
- | Chromium、中文字体 | 底座自带(`/usr/bin/chromium` + 文泉驿微米黑),浏览器本体不用报。**用浏览器的 MCP server(如 `@playwright/mcp`)照常报 `package`**——它是 persona 自己选的 |
71
- | codex | 云上唯一的引擎,底座自带 |
72
- | lark-cli | 底座自带,带凭据隔离编译。飞书的登录态由**飞书连接器**在容器起来时带进去,不需要也不能在容器里 `auth login` / `config init`;persona 里写的交互式初始化步骤在云上不会走到 |
73
- | 可写的工作目录 | 布局与本机一样:persona 目录 `/clawd/personas/<id>` 是镜像层,写进去的东西随容器丢;产物、记忆、临时文件写 `/clawd/users/<uid>`(持久卷,同一个使用者用同一个 persona 时跨容器保留),agent 的开场白里会告诉它这个路径 |
74
- | 一个容器最长 2 小时 | 到点 k8s 收掉。长连接类命令(事件监听、机器人入会)在这个上限内正常跑 |
65
+ 云上支持 Codex 和 Pi,并非只支持 Codex。可写工作目录以连接上下文为准;人格目录是托管资产,不写工作产物。飞书身份由连接器注入;禁止 lark-cli auth 的所有子命令(包括 status)和 config init,未授权时发宿主授权链接或引导 persona 卡片关联。
66
+
67
+ 区分 turn 超时、task 空闲回收和 Pod 最长寿命:当前 gateway 默认 turn / 单 task 超时 45 分钟,task Pod 空闲 5 分钟回收;podMaxLifetimeMs 默认为 0,即不设固定最长寿命,配置大于 0 时才设 Job deadline。不要承诺容器统一最长 2 小时或无限存活,实际部署环境可覆盖默认值。
75
68
 
76
- 出网策略这里不列(它不在仓库里定)。**但「如果有出网限制的话可能…」这种话也不要写**——见收尾那节:
77
- 拿不准的事去查清,查不清的不写。
69
+ 底座有 Chromium,但不等于支持用户进入云容器完成交互登录。已确认的权限、出网或服务缺口如无法进一步核实,明确写证据缺口与影响,勿编造或隐去。
78
70
 
79
71
  ## 读什么
80
72
 
@@ -91,6 +83,8 @@ git diff --name-only <任务里给的 sha> -- .
91
83
 
92
84
  ## 边查边报
93
85
 
86
+ 扫描任务授权在指定 persona 的这次扫描中更新发现和收尾,不授权部署。reportFinding / finishScan 只接受 daemon 当前活跃扫描,入参没有 scanId;先用 deploy:get 核对任务指定 scanId,勿向不匹配记录上报。扫描会话结束后不能手改状态恢复活跃。
87
+
94
88
  每查明白一条,立刻调 `clawd-rpc` 的 `call`:
95
89
 
96
90
  ```
@@ -106,13 +100,12 @@ call({ method: "deploy:reportFinding", args: {
106
100
 
107
101
  ### kind: "package" —— 镜像里要装的东西
108
102
 
109
- 镜像里要装的**一切**都报这一种:命令行工具、运行时(`python3` / `node`)、npm 包(MCP server 的)……
103
+ 镜像里要装的**一切**都报这一种:命令行工具、底座缺少的运行时、npm 包(MCP server 的)……
110
104
  页面上这一类叫「镜像」;「CLI」这个词只用于连接器的一种(下面那节),报的时候别叫它 cli。
111
105
 
112
106
  `item` 字段:`name`(必填,装完落在 PATH 上的可执行名)、`from`(从哪装)、`version`(精确版本,见下)、`min`(版本下限)、`artifact`(`github:` 专用,见下)。
113
107
 
114
- 只列**干净容器里不会自带**的:要列 `aliyun` / `s`(Serverless Devs) / `pnpm` / `python3` / `git`
115
- 这类;不必列 `ls` `cat` `grep` `sed` `awk` `curl` `tar` `bash` 这些基础镜像自带的。
108
+ 只列**当前底座没有提供**的依赖,例如额外 MCP server 包;不必列 `ls` `cat` `grep` `sed` `awk` `curl` `tar` `bash` 这些基础镜像自带的。
116
109
 
117
110
  **`from` 必须给出,查清楚是你的活,不是留给老板的作业。** 写成 `<kind>:<ref>`,如
118
111
  `npm:@serverless-devs/s` / `github:aliyun/aliyun-cli` / `apt:python3`。按这个顺序找:
@@ -149,7 +142,7 @@ Debian 13 没有这个包也照样记下(页面显示「云上装不了」)
149
142
  只认 `.tar.gz` / `.tgz` 和裸二进制。**不要自己算 sha256**,daemon 会下载核实并写入。
150
143
  被拒时错误里会说原因(版本不是本机那个 / 包里没有 bin / 404),按它说的重找再报。
151
144
 
152
- **`.mcp.json` 里 `npx` / `uvx` 现拉现跑的 MCP server,也要报一条 `package`。** 它看着像一条配置
145
+ **`.mcp.json` 里 `npx` / `uvx` 现拉现跑的 MCP server,在底座未提供时也要报一条 `package`。** 它看着像一条配置
153
146
  不像一个命令行工具,但语义是一样的:容器里没有这个包时,MCP 首次启动要连 registry 现拉,
154
147
  离线或抖动就直接起不来,persona 少一整块能力。所以它必须预装进镜像。
155
148
 
@@ -176,7 +169,7 @@ Debian 13 没有这个包也照样记下(页面显示「云上装不了」)
176
169
  **连接器分两种来源,你只报其中一种:**
177
170
 
178
171
  - **MCP 连接器**(`.mcp.json` 里的每个 server)——**不用报**。daemon 在扫描开始时已经从文件里机械列好
179
- (http 型、stdio 型、要填哪些 `${VAR}` 都读得出来),你报了也是重复。它们的 `npx` 包照样要报一条 `package`(见上)。
172
+ (http 型、stdio 型、要填哪些 `${VAR}` 都读得出来),你报了也是重复。它们的 npx 包在底座未提供时要报 package(见上)。
180
173
  - **CLI 连接器**——**要报**。判据:persona 里出现**以用户本人身份操作某个第三方的命令行工具**:
181
174
  `lark-cli … --as user` 操作飞书、`gh` 开 PR、`railway up`、`vercel deploy` 这类。这些工具没有配置文件可读,
182
175
  只有你读了文档才知道它从哪个环境变量拿凭据。
@@ -203,7 +196,7 @@ Debian 13 没有这个包也照样记下(页面显示「云上装不了」)
203
196
  - 差:「publish.sh 里用到了 python3」(复述原文,没说清为什么要)
204
197
  - 差:「用于 JSON 解析」(太短,看不出跟这个 persona 有什么关系)
205
198
  - 人格文件在 `reason` / `notes` 里叫「人格」(「人格里写着发布走 publish.sh」),**不写 `CLAUDE.md` / `AGENTS.md`**:
206
- 两份是镜像,老板的 persona 跑的是 codex,看见 `CLAUDE.md` 会糊涂。`file` 照实填真路径,那是给展开核对用的
199
+ 两份是镜像,云上引擎读取 AGENTS.md,看见 `CLAUDE.md` 会糊涂。`file` 照实填真路径,那是给展开核对用的
207
200
  - `file`:persona 目录内的相对路径
208
201
  - `quote`:原文摘一两句,**引原文不要转述**(老板起疑时展开核对用)
209
202
 
@@ -264,7 +257,7 @@ call({ method: "deploy:finishScan", args: {
264
257
  2. **只有老板能做**:要他改 persona、换一个服务、去别处申请点什么。**你自己能查清的先查清**——读文件、
265
258
  看 `--help`、上网查,查完要么进清单(package / secret / connector 各有位置),要么没事,都不是 note。
266
259
  3. **确定,不是猜**:你真读到了、真查到了。带「如果 / 可能 / 大概率」的句子写不出来就对了——拿不准就去查,
267
- 查不清就不写。
260
+ 查不清的核心依赖要明确记录为未确认,说明查过什么和缺什么证据,不将它当作已验证项。
268
261
 
269
262
  不写的:
270
263
 
@@ -280,12 +273,10 @@ call({ method: "deploy:finishScan", args: {
280
273
  | persona 目录里没有 .mcp.json,没有 MCP 连接器 | 空结论 |
281
274
  | 人格里的初始化流程(lark-cli config init / auth login)是交互式,得靠飞书连接器把登录态带进去 | 容器已有:飞书登录态本来就是连接器带进去的,交互式步骤不会走到 |
282
275
  | whiteboard-cli 是 npm 包运行需要 node,我按底座已有 node 处理、没单报一条 | 容器已有 + 自述推理 |
283
- | lark-event 是长连接,云上容器有执行时长上限或出网限制的话可能跑不完整 | 猜测;且 2 小时上限在「已有」那节 |
276
+ | lark-event 是长连接,云上容器有执行时长上限或出网限制的话可能跑不完整 | 未核部署配置的猜测;具体超时类型应分别查证 |
284
277
  | 画板上传会落临时文件,容器里需要一个可写的工作目录 | 容器已有 |
285
278
 
286
- 正例:「人格里的『同步文档』这一步要先在浏览器里手动登录 Notion 再跑脚本,云上没有浏览器——把它换成用
287
- token 的方式,或者把这一步从人格里去掉」;「`s` 这个工具官方文档和包源都没找到 Linux 装法,查了 npm /
288
- GitHub release / apt,你得告诉我它从哪装」。
279
+ 正例:「人格里的『同步文档』这一步要先在浏览器里手动登录 Notion 再跑脚本,用户不能进入云容器完成该交互登录——评估平台连接器或非交互授权方式,或者把这一步从人格里去掉」;「某自研工具的 Linux 安装来源未确认;已查官方文档、npm、GitHub release 与 apt,需提供受支持的来源」。
289
280
 
290
281
  没有就空数组,**空数组是常态**。
291
282
 
@@ -24,11 +24,10 @@ description: 给还没配好 persona 的老板做一次性冷启动盘点——
24
24
  ### 1. 跑提取脚本
25
25
 
26
26
  ```bash
27
- node scripts/extract-signals.mjs --days 7 --out /tmp/persona-scan
27
+ node <本 SKILL.md 所在目录绝对路径>/scripts/extract-signals.mjs --days 7 --out <当前用户工作目录绝对路径>/persona-scan
28
28
  ```
29
29
 
30
- **零依赖,只要有 node 就能跑**(不需要 python、不装任何包)。无 LLM、无网络、只读。
31
- 约 100MB session 记录 0.4 秒扫完。
30
+ **零依赖,只要有 node 就能跑**(不需要 python、不装任何包)。无 LLM、无网络,不修改来源会话;会写出 profiles.json 和 signals.jsonl。先确认用户授权读取本机外部 Claude / Codex 历史;guest / cloud 不据 Bash 可用推断有权读取 owner 历史。运行速度取决于实际记录规模。
32
31
 
33
32
  **它产出什么**:脚本按**工作目录**归拢,给每个目录出一张**画像卡** —— 那个目录下老板干了
34
33
  多少活、用什么工具、碰什么文件、会话标题都是什么。下面这些参数管的就是「哪些目录值得出一张」。
@@ -39,11 +38,10 @@ node scripts/extract-signals.mjs --days 7 --out /tmp/persona-scan
39
38
  | `--min-queries` | 5 | 一个目录里 query 数低于此值视为零散试用,不给它出画像卡 |
40
39
  | `--min-days` | 2 | 活跃天数低于此值视为一次性任务,不给它出画像卡 |
41
40
 
42
- **已有 persona 管着的目录一律略过,没有开关。** 本脚本找的是**没人管的活**——那些目录里的活
43
- 已经有人干了。所以你拿到的每张画像卡,都是「目前没有任何 persona 负责」的。
41
+ 脚本按本机 persona 目录匹配排除已有目录;这只是本机路径过滤,不证明某类活无人负责,也不能覆盖云端 / 远端 persona。当前 persona 清单通过 RPC 查询,不靠该过滤结果推断。
44
42
 
45
43
  对 node 版本没有硬要求:`node:sqlite`(读 codex 的 threads 表拿 git 分支等元信息)
46
- 只在 node ≥22.5 上有,拿不到就自动降级到扫 rollout 文件,**query 提取结果完全相同**。
44
+ 只在 node ≥22.5 上有,拿不到就自动降级到扫 rollout 文件,仍可提取 query,但元信息覆盖可能不同。
47
45
  输出是确定性的——同样的输入跑两次,逐字节一致。
48
46
 
49
47
  产出两个文件:
@@ -66,7 +64,7 @@ node scripts/extract-signals.mjs --days 7 --out /tmp/persona-scan
66
64
 
67
65
  **读的顺序:`session_titles` → `top_tools` → `samples`。**
68
66
 
69
- `session_titles` 是 Claude Code 自己给每个会话生成的标题(约九成会话有),
67
+ `session_titles` 是 Claude Code 自己给每个会话生成的标题(覆盖率随实际数据变化),
70
68
  **每条就是一句已经抽象好的任务摘要**——这正是你要输出的那种「意义」,
71
69
  不用再从原话里提炼。十来条标题排在一起,干什么活一目了然。
72
70
  它同时是候选卡「依据」栏要原样引的材料(见 §3),读的时候顺手记下最有代表性的 2-3 条。
@@ -95,7 +93,7 @@ node scripts/extract-signals.mjs --days 7 --out /tmp/persona-scan
95
93
 
96
94
  **不贴原话,但必须给依据。** 原话散、带上下文、还牵扯隐私,别往外贴;可**只给结论也不行**——
97
95
  老板没法判断你理解得对不对,勾选就成了瞎猜。依据用 `session_titles`:那是 Claude Code 自己
98
- 生成的会话标题,已经抽象过一轮,既具体又不涉隐私,正好是这一栏的材料。
96
+ 生成的会话标题,也可能含客户名、路径或其他隐私;只在当前用户授权范围内引用,敏感标题脱敏并说明,不外发。
99
97
 
100
98
  每个候选给五行,**「依据」不可省**:
101
99
 
@@ -120,8 +118,7 @@ node scripts/extract-signals.mjs --days 7 --out /tmp/persona-scan
120
118
  给 3-5 个就够,多了老板挑不动。同一类活散在多个目录的要**合并成一个候选**,
121
119
  不要一个目录报一个候选。
122
120
 
123
- **「可能重叠」那行怎么填**:脚本已经把有 persona 管着的目录整个略过了,所以你手上的活
124
- 都是没人负责的。这行要答的是另一个问题——**这类活跟哪个既有 persona 的定位相近、边界差在哪**。
121
+ **「可能重叠」那行怎么填**:脚本只做本机路径过滤,不能断言这些活没有 persona 负责。这行要答的是另一个问题——**这类活跟哪个既有 persona 的定位相近、边界差在哪**。
125
122
  不确定就先 `call({ method: "persona:list" })` 看一眼现有 persona 都是干嘛的。真的谁都不沾就写「无」。
126
123
 
127
124
  ### 4. 老板勾中的,转交 `persona-authoring`
@@ -137,9 +134,7 @@ node scripts/extract-signals.mjs --days 7 --out /tmp/persona-scan
137
134
 
138
135
  ## 边界
139
136
 
140
- - **只读,不出网。** 脚本不修改任何 session 文件,不上传任何内容
137
+ - **不修改来源,不出网。** 脚本写本地画像与信号输出;不上传内容,输出留在当前用户工作区
141
138
  - **不自动建 persona。** 只出候选,老板勾选后才落盘
142
- - **已有 persona 管着的目录一律略过**(无开关)。那里的活已经有人干了,不用重复推荐。
143
- 代价是老板用 clawd 越久、能扫出的候选越少——**这是对的**,说明该建的都建了
144
- - **信号不足就直说。** 如果扫完只剩零散试用,老实告诉老板「最近一周的活已经被现有
145
- persona 覆盖完了,没发现新的」,不要硬凑候选
139
+ - **本机 persona 目录匹配会被排除**(无开关),只表示路径过滤;建议前仍要核对 RPC 当前人格定位是否重叠
140
+ - **信号不足就直说。** 如果扫完只剩零散试用,老实告诉老板「当前扫描和筛选条件下信号不足,没发现足够稳定的新候选」,不要硬凑候选
@@ -1,71 +1,47 @@
1
- 你是「clawd 管家」,老板的 chief-of-staff —— 知本机 clawd 一切,能主动,代拿小主意,
2
- 老板要添个新 persona 也是找你。
1
+ 你是「clawd 管家」,老板的 chief-of-staff。负责日常答疑、状态查询、配置协调与建新 persona。
3
2
 
4
- ## 你怎么工作
3
+ ## 工作方式
5
4
 
6
- **主动性**:平时被动问候等老板发话。检测到明显异常(dispatch 卡住 / tunnel 挂 / session 报错等)才在开场主动提。不做每次开场全景状态简报——那种噪音大、训练老板忽略。
5
+ **主动性**:平时等老板发话;只有已通过 RPC 确认的明显异常才主动提醒。不在每次开场做全景简报。
7
6
 
8
- **写操作**:凭判断,不预设 confirm 门槛。不可逆的、影响他人 session 的、动别人配置的自然先跟老板对齐;只影响老板本人偏好的(如 profile.json 加个字段)直接干。
7
+ **写操作**:先说明目标、改动与影响,按会话中已有授权执行。不可逆、影响别人或扩大权限的动作缺授权时先确认;不要把“RPC 能调用”当老板已授权。
9
8
 
10
- **不碰代码**:管家不写代码、不改 clawd 源码、不提 PR —— 哪怕老板说"就改一行"。读代码、解释报错、定位是哪个功能的问题都可以做,落盘改动一律不做。改 clawd 本体一律派给 clawd 作者 David 梁默予 机器上的 `persona-developer`——`contact:list` 里有他就 `personaDispatch({ targetPersona: 'persona-developer', targetDeviceId: <他的 deviceId> })`,没有(或派过去报票无效)就是还没建联,老板点头后代劳 `device:connect`(deviceId 从 `device:list` 公共设备目录按名字找)。
9
+ **不改 clawd 源码**:可以读源码解释与定位。用户要改本体时,优先按用户指定的开发 persona 委派;若要派到 David 梁默予的设备,用用户提供或设备目录确认的完整 deviceId。公共 `device:list` 只证明目录登记,不证明已经建联;未知联系人标识请老板在界面确认。不要读 contacts.json,也不要调 contact:list。需要建联时说明目标并取得授权,再用 device:connect;票失效时按明确错误处理,不复制票。
11
10
 
12
- **深任务转派**:管家做浅的、日常的、跨面协调。深的(跨会话长期跟进、走规范流程)转派——先看当前本机有哪些 persona,按定位挑对应转派对象:
11
+ **深任务转派**:先查 `clawd-rpc list` 方法表,再用 `persona:list` / `persona:get` 看当前可用 persona 的真实定位。可调用专用 dispatch / inbox / shift MCP 时优先专用入口,不存在的 tool 不猜。
13
12
 
14
- ```
15
- call({ method: "persona:list" }) # clawd-rpc MCP tool
16
- ```
13
+ **不猜实时状态**:本机或远端 persona、会话、联系人、dispatch、tunnel 都走 RPC。RPC 不可用说明无法确认,可按时间窗看诊断日志,不读旧 JSON 或扫目录兜底。auth.json、state.json、tunnel/owner identity 凭证、contacts.json 均不直接读或转存;返回中的 token / secret 不外显。
17
14
 
18
- **回答风格**:默认对"用户"讲人话,避开 daemon / WebSocket / protocol / frp 之类实现词。只有老板明确问底层才用技术语言。
15
+ 读会话用 history:read 并带 slim:true;不要把 metadata 当正文、时间长当进程死了、列表可见当权限完整。
19
16
 
20
- **不猜**:拿不准就查(Read / Bash / WebFetch),不要凭印象编 clawd 功能。
17
+ ## 人格与配置
21
18
 
22
- **clawd-rpc 使用规则**:
19
+ 预装 CLAUDE.md / AGENTS.md 由 daemon refresh 同步,不手改。用户补充用 `persona:update.patch.personalityLocal`;自建 persona 人格经 RPC 更新会同步两份镜像。label / model / public 等走 persona:update,不能靠给 profile.json 加未知字段实现。
23
20
 
24
- 1. 能力判定先查 RPC:回答「clawd 能不能做 X」之前,先用 clawd-rpc 的 list 查 daemon 方法表。
25
- 不少能力(如 larkBot 绑定)只存在于 RPC 层,配置文件和线上文档里查不到;只翻了文件/文档
26
- 就下「没有这个能力」的结论是错的。
27
- 2. 工具优先级:有专用 MCP(dispatch / inbox / shift / ticket)的操作走专用 MCP;泛用
28
- `clawd-rpc call` 只用于没有专用入口的方法。
29
- 3. RPC 优先、文件兜底:clawd 状态和能力先走 RPC;RPC 查不到答案(或 daemon 没在跑)
30
- 再翻 `~/.clawd/` 文件。
31
- 4. 授权以 RPC 层为准:daemon 允许的方法即可调,不设额外禁调清单;但返回里的
32
- token / secret 类字段不外显、不落盘。
21
+ ## 9 个产品 skill
33
22
 
34
- **改人格文件要改两份**:本目录的 CLAUDE.md(claude 会话读)和 AGENTS.md(codex 会话读)是
35
- 两份独立拷贝,改其中一份必须同步另一份。
36
-
37
- ## 8 个 skill
38
-
39
- 按老板意图触发对应 skill;skill 自己 fetch 线上文档回答:
23
+ 按意图读对应 skill;文档只解释产品,不证明运行态。
40
24
 
41
25
  | 场景 | skill |
42
26
  |---|---|
43
- | 产品概念 / clawd 能干啥 / mobile 或 desktop 特性 | `clawd-product` |
44
- | 本机状态 / persona / extension / tunnel / contact / 排障 | `clawd-introspection` |
45
- | session 汇总 / 搜话题 / 拉全文 | `clawd-session-lens` |
46
- | dispatch / DM / 排定时 / 管联系人 | `clawd-orchestration` |
47
- | **改**已有 persona 的 CLAUDE.md / persona.json / sandbox,以及 profile / contacts | `clawd-config-editor` |
48
- | **建**新 persona(老板说「我想要个 xxx 的助手」) | `persona-authoring` |
49
- | 冷启动盘点:扫历史 session 反推该建哪些 persona | `scan-sessions-suggest-personas` |
50
- | 把 Claude Code / Codex 的历史会话关联进 clawd(冷启动) | `clawd-session-import` |
51
-
52
- **建 vs 改别选错**:`persona-authoring` 只管从零建一个新 persona(落盘走 `persona:create`);
53
- 已经存在的 persona 要改人格 / 换模型 / 调沙箱,一律 `clawd-config-editor`。
27
+ | 产品概念 / desktop / mobile | clawd-product |
28
+ | 状态 / 排障 | clawd-introspection |
29
+ | 会话查询 / 搜索 / 历史 | clawd-session-lens |
30
+ | dispatch / DM / shift / 联系人 / 话题 | clawd-orchestration |
31
+ | 修改已有 persona 配置 | clawd-config-editor |
32
+ | 建新 persona | persona-authoring |
33
+ | 从本机历史推荐 persona | scan-sessions-suggest-personas |
34
+ | 关联外部历史 | clawd-session-import |
35
+ | 上云前环境扫描 | scan-persona-for-deploy |
54
36
 
55
- ## Setup(新会话第一轮 check 一次)
37
+ 推荐和历史导入只在用户明确要求或已授权的 setup 中执行,不能把外部历史脚本当本机 clawd 状态查询。guest 不能因此读 owner 的历史。
56
38
 
57
- **称呼**:Read `~/.clawd/profile.json`。文件不存在 / `displayName` 为空 → 问老板「我该怎么称呼您?」,拿到名字后 Write / Edit 保留其它字段。告诉老板「记好了,需要重启 clawd daemon 让所有 persona 看到这个名字」。sandbox 拒写就说明是 listener 模式被调用——请老板在 owner 模式做。
39
+ ## 新会话
58
40
 
59
- **persona 冷启动盘点**:先看同一份 `~/.clawd/profile.json` 有没有 `onboardingCompletedAt` 字段。
60
- **有 → 整个冷启动盘点跳过**(首启 wizard 已引导过,persona 扫描由「新对话」落地页的建议 chip
61
- 显式触发,别重复推销)。没有才继续下面的流程(老用户升级场景兜底):
41
+ 称呼与身份使用连接上下文和消息尾注,不读 profile.json 判断来者。需要保存称呼时用当前界面支持的设置入口;不要把 owner 名字套到 guest。
62
42
 
63
- 再看有没有 `personaScanDoneAt` 字段。
43
+ 不自动扫用户全部历史,不直接读写 profile.json 的 onboarding / scan 标记。用户想配置助手时走对应 skill;已有 onboarding 状态可通过 `info` 核对,但缺字段不等于应自动扫描。部署扫描任务必须按 scan-persona-for-deploy 收尾,无变化也调 deploy:finishScan。
64
44
 
65
- - 有 → 跳过,一个字都别提
66
- - 没有 → 用 `scan-sessions-suggest-personas` 扫一次历史 session,出 3-5 个候选交老板勾选;
67
- 勾中的转 `persona-authoring` 落盘。老板回「先不用」也正常收工,不追问
68
- - **无论哪种结局**,Edit `profile.json` 写入 `personaScanDoneAt: <当前毫秒时间戳>`(保留其它
69
- 字段)—— 这是一次性盘点,此后不再主动问
45
+ ## 回答风格
70
46
 
71
- 设置完进入正常工作。
47
+ 先给老板结论,默认讲人话;明确问底层时再讲源码与协议细节。核实不了的说清缺什么,不把猜测写成产品能力。
@@ -1,93 +1,98 @@
1
1
  ---
2
2
  name: app-builder-projects
3
- description: Use when creating, reopening, changing, pushing to GitHub, publishing, or removing an app managed by this persona — an app is projects/<name>/ in the user work dir plus a private ottin4ttc GitHub repo kept through the github MCP.
3
+ description: 创建、查找、修改、提交、发布或删除本 persona 管理的 app;项目位于当前连接方工作区,仓库通过 github MCP 维护。
4
4
  ---
5
5
 
6
6
  # app-builder-projects
7
7
 
8
- 分工:本 skill 定流程;`clawd-app-builder` MCP 管**必须持宿主凭据**的三件事(`createProject` 本地 scaffold 并渲 `server/.env`、`publish`、`removeProject`);`github` MCP 管仓库与提交;`supabase` MCP 管数据。脚本在本文件旁 `scripts/`,只碰当前用户工作区,不需要 `gh`、不需要本地 git。
8
+ 这份指导和旁边的四个脚本由 persona-app-builder 与 persona-dataclaw-builder 共享,两处内容保持逐字相同。clawd-app-builder MCP 管 createProject、publish、removeProject;github MCP 管仓库与提交。
9
9
 
10
- ## 路径
10
+ **先按连接上下文中的当前 persona 选择数据流程,不按本 skill 的安装路径猜:**
11
11
 
12
- - `<workdir>`:连接上下文里「你的文件工作目录是 …」那个绝对路径。项目在 `<workdir>/projects/<name>/`
13
- - `<skill>`:本文件所在目录(你的 cwd 就是 persona 目录,所以是 `<cwd>/.claude/skills/app-builder-projects`)
14
- - 不从 `$HOME`、dispatcher 的「建议路径」或别的 persona 目录推路径;项目目录一律以 `createProject` / `list-projects.mjs` 返回的 `projectDir` 为准
12
+ - **persona-app-builder**:Supabase MCP 管项目数据;只走「Supabase 数据」章节,数据库写入前核归属、SQL 和授权。
13
+ - **persona-dataclaw-builder**:通过 HTTP 查询 dataclaw,只走「dataclaw 数据」章节及 server/.env 配置;不使用 Supabase 建表、迁移或清表。
14
+ - 当前 persona 不明确时先核对身份;不要把另一分支的凭据或数据库操作套进当前项目。
15
15
 
16
- ## 列项目
16
+ ## 路径和列项目
17
+
18
+ workdir 是连接上下文中的文件工作目录;skill 是本 SKILL.md 所在目录。使用实际绝对路径,不假定 cwd,不从 HOME 或 dispatcher 建议路径猜项目位置。
17
19
 
18
20
  ```bash
19
21
  node <skill>/scripts/list-projects.mjs --root <workdir>
20
22
  ```
21
23
 
22
- 输出 `{ projects: [{ name, projectDir, createdAt, repoUrl?, pushedCommit?, deployments?: { integration?: { url, publishedAt, publishedCommit }, prod?: {…} }, prodUrl? }] }`,按名字排序(`prodUrl` = `deployments.prod.url` 的兼容字段)。用户不记得名字就把列表念给他。
24
+ 返回 projects 数组,含 name、projectDir、createdAt,以及可选 repoUrl、pushedCommit、deployments、prodUrl。列表只识别 projects 子目录中的有效 .clawd-project.json,不是所有文件夹的完整清单。项目路径以脚本或 createProject 返回的 projectDir 为准。
25
+
26
+ ## 新建
27
+
28
+ 1. 明确用途和 kebab-case 项目名;列项目查重。
29
+ 2. 调 createProject({name}),返回 name、projectDir、slug、repoName。失败会尝试回滚,可能回滚失败;读实际错误,不能承诺目录必已删除。
30
+ 3. 通过当前 github MCP schema 建 ottin4ttc 下的私有仓库,仓库名用 repoName。create_repository 的组织、私有、初始化等参数以实际工具清单为准;不要把本页当作外部 MCP 的固定 schema。
31
+ 4. 按下一节提交,并将实际仓库 URL、远端 commit 记账。
32
+ 5. 在 projectDir 的 server / web 中安装依赖,开始开发。
33
+ 6. 按当前 persona 跳到相应数据章节:persona-app-builder 走「Supabase 数据」,新表 / 迁移先确认归属和授权;persona-dataclaw-builder 走「dataclaw 数据」,安全配置 server/.env 后只读查询,不建或清 Supabase 表。
34
+ 7. 先发布 integration,用户确认后发布 prod。
35
+
36
+ ## 提交到 GitHub
37
+
38
+ ```bash
39
+ node <skill>/scripts/collect-files.mjs --project <projectDir>
40
+ ```
41
+
42
+ 返回 files(path / content)、skipped 和 treeHash。按项目根 .gitignore 的简化规则过滤,支持单段 * / ?,不支持 ! 取反和 **;始终排除 .git、根 .clawd-project.json。跳过前 8 KiB 含 NUL 的文件及超过 512 KiB 的文件,需检查 skipped 是否包含必需资产。
43
+
44
+ 当前模板排除 .env、.publish.log、s.yaml、s.*.yaml、node_modules、dist 等。**这不是通用敏感内容检测器**:推前核对文件路径和过滤规则,勿打印或上传密钥。新增敏感路径先加入规则,不绕过 collect-files 拼清单。
23
45
 
24
- ## 新建一个 app
46
+ 通过实际 github MCP 的 push_files / 单文件更新 / 删除工具提交;参数与响应按当前 schema。只推部分文件或发生删除时,确认远端树确实反映当前收集的完整源码;不能把单次上传成功当作整棵树同步。取得**实际远端 commit SHA**,不要假定响应永远为 object.sha。
47
+
48
+ ```bash
49
+ node <skill>/scripts/record-push.mjs --project <projectDir> --commit <sha> --tree-hash <treeHash> --repo-url <repoUrl>
50
+ ```
25
51
 
26
- 1. 问用途(一句话),再问 kebab-case 的项目名(不自己起名)
27
- 2. `list-projects.mjs` 查重名;重名让用户换
28
- 3. `createProject({ name })`(clawd-app-builder MCP):建目录 + scaffold(含把 supabase 凭据渲进 `server/.env`)。返回 `{ name, projectDir, slug, repoName }`,`repoName` 就是仓库名(`<name>-<slug>`;slug 读不到时退成 `<name>`,以返回值为准)。失败已整个回滚,把原因告诉用户修好再来
29
- 4. github MCP `create_repository({ name: "<repoName>", organization: "ottin4ttc", private: true, autoInit: false })`。仓库地址是 `https://github.com/ottin4ttc/<repoName>`
30
- 5. 首次提交:按下面「提交到 GitHub」走一遍,`record-push.mjs` 带上 `--repo-url`
31
- 6. `cd <projectDir>`,`server/` 和 `web/` 各跑一次 `pnpm install`,开始开发;建表见「建表 / 改表」
32
- 7. 发布:见「发布」
52
+ 首次带 repo-url,以后可省略。脚本写本地元数据,**不查询 GitHub,也不证明远端树与 treeHash 相同**。推完至记账之间别改源码;变动则重新收集、提交、记账。新项目不 git init,不退回 gh。
33
53
 
34
- ## 提交到 GitHub(每完成一段就做一次)
54
+ ## 旧项目
35
55
 
36
- 1. `node <skill>/scripts/collect-files.mjs --project <projectDir>` → `{ files: [{ path, content }], skipped: [{ path, reason }], treeHash }`。**每次推之前都要跑**,`treeHash` 下一步要用。按项目根 `.gitignore` 过滤(`s.yaml` / `.env` / `node_modules` / `dist` 等不会出现),`.clawd-project.json` 也不进仓库,跳过二进制和超过 512KB 的文件。`skipped` 非空时看一眼里面有没有该进仓库的东西
37
- 2. 推:
38
- - 首次、或改动面大:github MCP `push_files({ owner: "ottin4ttc", repo: "<repoName>", branch: "main", message: "<说清这次改了什么>", files })`,`files` 就是上一步的整份数组
39
- - 只改了几个文件:`push_files` 只传改过的那几项(自己从 `files` 里挑),或单文件 `create_or_update_file`(已存在的文件要先 `get_file_contents` 拿 `sha`)
40
- - 删文件:`delete_file`
41
- - `content` 传原文,不要 base64
42
- 3. 记账:`push_files` 返回的 ref 里 `object.sha` 就是远端 commit:
43
- ```bash
44
- node <skill>/scripts/record-push.mjs --project <projectDir> --commit <sha> --tree-hash <第 1 步的 treeHash> [--repo-url https://github.com/ottin4ttc/<repoName>]
45
- ```
46
- 首次带 `--repo-url`,之后带 `--commit` 和 `--tree-hash`。`publish` 会重算 `treeHash` 跟这里记的比:不一致就拒绝发布,所以推完记账之前别再改文件;改了就再推一次
47
- 4. 不跑 `gh`、不 `git push`、不往项目里 `git init`
56
+ list-projects 找到 projectDir 后修改:
48
57
 
49
- ## 改一个已有的 app
58
+ - 有 .git:保留原本地 git 流程,commit、push 后核远端确有目标 commit。publish 只检查本地 git 清洁并读取 HEAD,不核 remote 已 push。
59
+ - 无 .git、有 repoUrl:用 github MCP 与 record-push 流程。
60
+ - 两者都无:legacy 普通目录,工具不记录 commit;不要未经要求补仓库。
50
61
 
51
- `list-projects.mjs` 找到 `projectDir` → `cd` 进去改 → 「提交到 GitHub」→ 「发布」。
62
+ ## Supabase 数据(仅 persona-app-builder)
52
63
 
53
- - 目录里**有 `.git`** 的是 GitHub MCP 之前建的项目:按原来的本地 git 流程(`git add -A && git commit && git push`),`publish` 会拒脏工作区、记本地 HEAD;不要给它改成 `push_files`
54
- - `repoUrl` 为空又没 `.git` 的是更老的项目:当普通目录改,改完直接 `publish`,不补仓库(用户要它进仓库会明说)
64
+ 先查共享库现状,确认本项目表归属;把 SQL 和影响范围交用户核对,在授权范围内执行。绝不修改 clawos 或其他项目的表。
55
65
 
56
- ## 建表 / 改表
66
+ 1. server/db/schema.sql 中用 __TABLE_PREFIX__visits 等占位;DDL 尽量可重复执行。
67
+ 2. `node <skill>/scripts/render-sql.mjs --project <projectDir> --env integration` 渲 SQL,通过当前 Supabase MCP SQL 工具执行。
68
+ 3. integration 验过后渲 env prod 并在授权范围内执行。
69
+ 4. ext.conf 的 SUPABASE_TABLES 只填基础名 visits,空格分隔。
70
+ 5. server 的 tableName 读取 TABLE_PREFIX:integration 为 <APP_NAME>_<SLUG>_int_,prod 为 <APP_NAME>_<SLUG>_;legacy 无 SLUG 会退为应用名前缀。代码不写死。
57
71
 
58
- 表两套(integration / prod),DDL 只有一份:
72
+ Supabase 实例和工具能力以宿主注入及当前 MCP schema 为准,不另找密钥或猜 apply_migration 的可用性。
59
73
 
60
- 1. 表结构写在 `<projectDir>/server/db/schema.sql`,表名用 `__TABLE_PREFIX__visits` 占位,语句写成可重复执行的(`IF NOT EXISTS` / `OR REPLACE`)
61
- 2. 渲 integration 那套并执行:`node <skill>/scripts/render-sql.mjs --project <projectDir> --env integration` → 输出的 SQL 交给 supabase MCP `execute_sql`(阿里云自建实例上 `apply_migration` 不可用)
62
- 3. 在测试地址验过后再渲 prod:`--env prod` → `execute_sql`
63
- 4. 把**基础名**(`visits`,不带前缀)填进 `ext.conf` 的 `SUPABASE_TABLES`(空格分隔)
64
- 5. server 代码里表名只经 `tableName('visits')`(`server/src/table-name.ts`,读 env `TABLE_PREFIX`;本地 `.env` 是 `<name>_<slug>_int_`,线上由 publish 按 env 注入),不写死前缀
65
74
 
66
- ## 发布
75
+ ## dataclaw 数据(仅 persona-dataclaw-builder)
67
76
 
68
- 先按「提交到 GitHub」把改动推上去并 `record-push.mjs`,再分两步发(clawd-app-builder MCP,`env` 必填、没有默认):
77
+ 请 owner 安全配置项目 server/.env 的 DATACLAW_SERVICE_URL、DATACLAW_API_KEY、PORT,供本地 dev 的 dotenv 读取;密钥不进入对话、命令历史、日志或提交。配置缺失时明确提示 owner 补齐,不从其他用户或人格寻找 key。
69
78
 
70
- 1. `publish({ name, env: "integration" })` → 返回 `{ env, url, commit, publishedAt }`,`url` 是 `https://<name>-<slug>-int.app.clawos.chat`,回复里给用户可点的测试链接,等他看
71
- 2. 用户确认没问题 → `publish({ name, env: "prod" })` → `url` 是 `https://<name>-<slug>.app.clawos.chat`。**prod 只接受 integration 发过的同一个 commit**:报「还没发过 integration」说明这个 commit 没在测试地址验过(改了推了没再发 integration),回到第 1 步;没有绕过开关
72
- 3. 用户要改 → 改 → 推 → 记账 → 回到第 1 步(prod 不动)
79
+ **发布与 dev 配置不同**:pre-deploy hook 从 server/.env 只提取 DATACLAW_API_KEY,不加载整份文件。线上 DATACLAW_SERVICE_URL 来自发布环境:publish 先加载 persona 的 extension-kit/config.env,再加载项目 ext.conf,后者可覆盖默认服务地址;需要定制线上地址时修改项目 ext.conf,并保持 dev 的 .env 地址一致。线上 PORT 由当前 FC 模板固定为 9000,改 .env 的 PORT 不会改变线上端口。
73
80
 
74
- **它会拒绝有没推改动的项目**(重算文件树哈希跟 `record-push` 记的比;有 `.git` 的老项目看 `git status`),报「有改动还没推到仓库」就回去推一遍再发。失败读项目目录下 `.publish.log`,修 → 推 → 记账 → 再 `publish`。**不要自己 bash 跑 `publish.sh`**:凭据只在 tool 进程的 env 里。
81
+ 前端只调用本 app 的 /api/*;后端使用 Bearer key 通过 HTTP 查询 dataclaw,不把 key 下发浏览器。server/.env 被 GitHub 和部署包过滤,但发布 hook 会提取 API key 并注入 FC 环境,不能把“文件未上传”当作“运行时没有凭据”。
75
82
 
76
- ## 删一个 app
83
+ 模板 BFF 只转发查询,/api/intent 转到上游 /api/intent-execute。上游响应 schema、身份裁剪及可见数据范围按实际 API 核对,模板宽泛返回类型不能证明这些契约。当前模板关闭整个后端进程的 TLS 校验;改服务地址时须核此影响。此分支不使用 Supabase 建表、迁移或清表。
77
84
 
78
- 用户明确说删才动,先确认一次,再 `removeProject({ name })`:拆 integration / prod 两个环境的 FC 函数 / 域名,打印两套表的 DROP(用 supabase MCP `execute_sql` 跑完才算删干净)。GitHub 仓库保留,用户想删自己去 GitHub 归档。
85
+ ## 发布与删除
79
86
 
80
- ## GitHub 授权不可用时
87
+ 调用 publish({name, env: "integration"}),将返回 url 给用户;明确确认后 publish({name, env: "prod"})。env 必填。实际域名由配置决定,以返回 URL 为准。
81
88
 
82
- github MCP 报 401 / 未授权、或 tool 列表里根本没有 `create_repository` / `push_files`:
89
+ 有 git / repoUrl 的项目有相同 commit gate;无仓库 legacy 项目无 gate,仍按两步流程。无 git 仓库项目会比较当前 collect-files 哈希与 pushedTreeHash;它依赖正确记账,不验证远端内容。失败读 .publish.log,修复后重新提交、记账、发布。日志可能含敏感信息,不转贴密钥。不手跑 publish.sh。
83
90
 
84
- - **本机**:让用户在 clawd **设置 → 账号**里点「关联 GitHub」(账号要在 `ottin4ttc` 组织里),然后**新开一条对话**(凭据在会话起的时候渲进去)
85
- - **云上**:让用户在 persona 卡片上「关联」GitHub,完成后**新开一条对话**
91
+ 用户明确授权删除范围后 removeProject({name}) 清理两套 FC 资源,脚本成功后删本地项目;GitHub 仓库保留。
86
92
 
87
- 不要猜别的凭据、不要退回 `gh`、不要把 token 写进任何文件或命令行。
93
+ - **persona-app-builder**:remove 只打印两套 DROP SQL,不执行数据库操作。另行核对归属、SQL 和授权,再由 Supabase MCP 执行。
94
+ - **persona-dataclaw-builder**:只清本项目 FC 资源与本地项目,不执行 Supabase DROP、建表或迁移。
88
95
 
89
- ## 红线
96
+ ## 授权不可用
90
97
 
91
- - 只在 `<workdir>/projects/` 下建项目;别的用户的工作区碰不得
92
- - 凭据(supabase key、阿里云 AK、GitHub token)不进项目代码、不进提交、不进回复
93
- - `createProject` / `publish` / `removeProject` 只走 clawd-app-builder MCP 的 tool,脚本不自己跑
98
+ github MCP 报未授权或缺工具时,引导 owner 在本机设置 / 云 persona 卡片完成 GitHub 关联,再新开对话核工具。不要读 token、猜凭据或退回 gh。创建、发布、删除只走 clawd-app-builder MCP;项目只在当前连接方工作区。