X-Ray · ZCode
ZCode 会在发提示词时打包 Git 历史,我在本机对上了
网上传它会静默上传全量 Git 历史。我本机装着 3.10.1,把 ~/.zcode 翻开以后,清单、加密包和上传状态都还在。
本机先对上的东西
应用在 /Applications/ZCode.app。版本字符串是 3.10.1.6272。数据目录在 ~/.zcode/v2/checkpoints/。六个工作区各有一份 repo_snapshot_manifest/v2 清单。文件时间都落在 2026 年 8 月 16 日晚上 20 点 08 分到 23 点 41 分。
状态文件里写着 captureStage 等于 prompt。你每发一句,它就试图打一次仓库快照。
清单里的主体是 .git/。harness 那次总共 965 MB,其中 961 MB 是 Git 目录。最大的 pack 文件有 915 MB。page-lingo、vibeguard、remem 也是同样的结构。工作区源码反而被 1 MB 单文件上限拦住了不少,Git 的 pack 没有这道闸。
传出去了几个
| 工作区 | GitHub | 快照 | 体积 |
|---|---|---|---|
| remem | 公开 | 服务端已接收 | 增量 103 KB,说明此前已有 baseline |
| voice-input | 公开 | 服务端已接收 | 185 KB |
| ultrastudio-dev-videos | 没有 git | 服务端已接收 | 空包 |
| harness | 公开 | 卡在 pending | 加密包 945 MB |
| vibeguard | 公开 | 卡在 pending | 加密包 162 MB |
| page-lingo | 私有 | 卡在 pending | 加密包 287 MB |
三个小包对上了 lastAcceptedManifestHash,pending 目录也空了。代码里这两件事和清掉 activeUpload 是同一次写入。大包还躺在本地,attemptCount 都是 1。对象上传超时写死 60 秒,几百 MB 在这个时限里传不完。
私有仓库 page-lingo 没传成功。已经传走的三个,内容本来就在公开 GitHub 上。我把五个仓库的全部历史 blob 扫过一遍,没有真实的密钥、私钥或带口令的远程地址。这是这几个仓库的运气,不是采集器替你挡掉了 Git 历史。
一次发送之后怎么走
host 进程里 sidecar 是直接 new 出来的。本地会话在 sessionSend 之前调用 scheduleRepoSnapshotSidecar。远程工作区如果带了 workspaceIdentity,这一步会跳过。
有登录 token 才会继续。下一步是 GET /api/v1/snapshot/upload-credential,查询参数是工作区绝对路径的 sha256 前 12 位。这个短哈希就是 checkpoints 目录名。
服务端返回 snapshot_id、RSA 公钥和可选的体积上限。客户端把文件打成 tar.gz,用 AES-256-CTR 加密,IV 明文写在密文前面,再用这把公钥把内容密钥包起来。私钥在服务端。这是防传输途中被截,厂商自己能解开。
包里还有 meta/prompt.json。字段 content 就是那一轮提示词原文。仓库状态和你刚说的话被放进同一个 snapshot_id。
为什么 Git 历史进得去
工作区文件走 git ls-files --cached --others --exclude-standard,尊重 gitignore。Git 目录是另一条腿,walkGitMetadataFiles 把整个 .git 递归进去,两份列表再合并。
过滤函数里,路径只要含有 .git 这一段,立刻放行。后面的密钥文件名、1 MB 上限、前 8 KB 空字节检测,对 pack 文件都用不上。
密钥 denylist 本身写得很勤快。.env、.npmrc、id_rsa、*.pem、*.key,文件名带 token 或 secret 的也会丢掉。harness 跟踪着的 .env.example 当时就在树上,8 月那次清单里没有它。工作区这一半确实在滤。问题是 pack 文件名看起来像普通二进制,历史里提交过一次又删掉的密钥,照样整包进 tar。
设置页那个开关
路径在设置,索引库,代码库。第一个开关叫「索引新文件夹」,文案只写自动索引少于五万文件的新目录。紧挨着的「即时搜索」开关明确写了数据存在本地。
我查证时 setting.json 里 repoSnapshotIndexingEnabled 是 false,repoSnapshotIndexingUserConfigured 这个字段根本不存在。设置页会显示关闭。renderer 用这两个标志决定勾选状态。host 里 repoSnapshotIndexingEnabled 只出现在 normalizeSettingsPatch,采集调度看不到它。
8 月那些快照已经落盘。当时 dual gate 即使存在,也没挡住这次采集。现在看到的 3.10.1 把 sidecar 无条件建起来,发送时继续调度。
想停下来可以做什么
退出登录。采集函数第一关就是 tokenProvider(),拿不到 zcodeJwtToken 或 accessToken 就返回。
网络层拦 /api/v1/snapshot/upload-credential。凭证失败则后面的扫描和加密都不会开始。
删掉 ~/.zcode/v2/checkpoints/。我查的时候 pending 里大约还有 1.4 GB,包括 page-lingo 那份私有历史。3.10.1 启动时不会扫描 pending 续传,flushWorkspace 只有采集成功后那一处调用。留着仍然没有好处,信封里的内容密钥就是给服务端解的。
设置页那个开关继续关着。以后版本一旦 host 开始读它,这就是用户侧仅有的开关。
这次只拆了本机这一份 3.10.1,以及 8 月 16 日留下的 checkpoints。其他版本、其他账号、服务端怎样存这些包,我没有证据。