caveman 的 caveman-compress 实战:把项目 CLAUDE.md 压成"穴居人格式"的测试夹具与完整流水线
本文以 tests/caveman-compress/claude-md-project.md 这个真实压缩产物为核心样本,完整拆解 caveman 仓库的 caveman-compress 技能是如何把一份 160 余行的项目记忆文件(CLAUDE.md)压缩成洞穴人风格短语句的:包括压缩前后逐节对照、压缩规则、检测-压缩-校验-重试的执行管线,以及保证"绝不改坏文件"的数据安全机制。读完你可以直接在自己的仓库上运行 /caveman-compress <filepath> 压缩记忆文件,并能看懂它每一步为什么这样设计。
这个文件是什么:一对"原文 / 压缩版"测试夹具
tests/caveman-compress/claude-md-project.md 是 caveman-compress 技能的一个压缩后样本,它描述的虚拟项目叫 Taskflow——一个全栈任务管理应用。与它同目录、同名的 .original.md 文件 是压缩前的原始版本(标准完整英文叙述),两者构成"原文 → 穴居人格式"的对照夹具,同目录还有 claude-md-preferences.md、todo-list.md、mixed-with-code.md 等多组同类夹具。
压缩版全文保持了原文档的完整章节骨架:Overview、Architecture(Frontend / Backend / Database / Infrastructure)、Key Conventions(Code Style / Testing)、Git Workflow、Common Commands、Environment Variables、Known Issues、Team——标题一个不少、顺序不变,变的只是标题下的正文:完整句子被压成短语句(fragment),而所有代码块、内联代码、路径、变量名逐字节保留。
压缩前后对照:这份 Taskflow CLAUDE.md 里哪些动了、哪些没动
先看压缩版的核心内容(以下继承自 压缩版样本 本身):
Overview(项目概况)
Taskflow full-stack task management app. Teams create, assign, track, manage tasks across projects with real-time collaboration. Started internal tool, now open-source.
Active dev focus: improve performance, add integrations (Slack, GitHub, Jira).
原文是一段完整的介绍("Taskflow is a full-stack task management application built with a modern web stack..."),压缩后去掉了冠词、连接词和解释性从句,事实点(团队协作、实时协作、内部工具转开源、当前重点是性能 + Slack/GitHub/Jira 集成)全部保留。
Architecture(架构)
压缩版完整继承了三层架构描述:
- Frontend:React 18 + TypeScript,Next.js 14(SSR + API routes),Radix UI + Tailwind CSS,全局状态用 React Context、服务端状态用 TanStack Query;代码结构
src/app/(App Router)、src/components/、src/lib/、src/types/。 - Backend:Node.js + Express,开发端口 3001,controller-service-repository 分层;
server/src/下controllers/(路由 + 校验)、services/(业务逻辑)、repositories/(Knex.js 数据库访问)、middleware/(认证、限流、错误处理)、jobs/(BullMQ 后台任务)。 - Database:PostgreSQL 15 主库,迁移在
server/migrations/(Knex.js);表包括 users、teams、projects、tasks、comments、attachments、audit logs;Redis 负责缓存、会话和 BullMQ 消息代理。 - Infrastructure:AWS ECS Fargate 部署;GitHub Actions CI/CD 三步流水线(PR 触发 lint/type-check/单测+集成测试 → 合入 main 构建镜像推 ECR 部署 staging → release tag 提升到生产)。
对照原文可以清楚看到压缩的"边界感":技术词与版本号一个不动("Next.js 14""PostgreSQL 15""BullMQ"),目录路径以反引号原样保留(`server/src/repositories/`),被砍掉的全是"The application follows a standard... with clear separation of concerns"这类解释性铺陈。
Common Commands(完整继承的命令表)
压缩版中原样保留的 bash 代码块(这是压缩规则中"代码块逐字节复制"的直接体现,压缩前后该块完全一致):
# Development
npm run dev # Start frontend + backend in parallel
npm run dev:frontend # Start only Next.js dev server
npm run dev:backend # Start only Express API server
# Testing
npm run test # Run unit tests with Vitest
npm run test:watch # Run tests in watch mode
npm run test:integration # Run integration tests (requires Docker)
npm run test:e2e # Run Playwright E2E tests
# Database
npm run db:migrate # Run pending migrations
npm run db:rollback # Rollback last migration batch
npm run db:seed # Seed database with sample data
npm run db:reset # Drop, recreate, migrate, and seed
# Build & Deploy
npm run build # Build frontend and backend
npm run lint # Run ESLint on all files
npm run typecheck # Run TypeScript compiler checks
docker compose up -d # Start all services locally with Docker
Environment Variables(环境变量)
| 变量 | 说明 | 示例/约束 |
|---|---|---|
DATABASE_URL |
PostgreSQL 连接串 | postgresql://user:pass@localhost:5432/taskflow |
REDIS_URL |
Redis 连接串 | redis://localhost:6379 |
JWT_SECRET |
JWT 签名密钥 | 至少 32 字符 |
NEXT_PUBLIC_API_URL |
前端访问的 API 地址 | http://localhost:3001 |
SLACK_WEBHOOK_URL |
可选,Slack 通知 webhook | — |
GITHUB_TOKEN |
可选,GitHub issue 同步 token | — |
用法:复制 .env.example → .env.local。这些内联代码和值全部在压缩中逐字保留。
其余章节
- Code Style:ESLint(Airbnb + TypeScript)+ Prettier,Husky + lint-staged 前置钩子;规则四条(strict TS、避免
any用了要注释、interface 优先于 type alias、状态用 discriminated unions)。 - Testing:单测
*.test.ts(Vitest + Testing Library);集成测试tests/integration/打真实 PostgreSQL(Docker),npm run test:integration;E2Etests/e2e/(Playwright,仅 CI)。规则:测行为不测实现、mock 外部服务、集成测试绝不 mock 数据库——原文里"we learned this the hard way..."这句血泪教训在压缩版中被整个删掉,只留三条规则本身。 - Git Workflow:trunk-based;分支格式
<type>/<ticket-id>-<short-description>(例feat/TF-123-add-slack-integration);Conventional Commits,类型 feat/fix/refactor/test/docs/chore/perf;≥1 人批准、CI 通过、squash merge。 - Known Issues:4 条(WebSocket 重连竞态 TF-456;>10MB 上传需分片;>500 任务仪表盘慢 TF-489;时区显示用服务器时区而非用户本地)——issue 编号 TF-456/TF-489 作为数值/编号被完整保留。
- Team:4 名成员及分工,专有名词(人名)不动。
压缩规则:caveman-compress 的"删什么 / 保什么"
上面的对照效果来自 skills/caveman-compress/SKILL.md 中定义的压缩规则,四张清单:
删除(Remove)
- 冠词:a、an、the
- 填充词:just、really、basically、actually、simply、essentially、generally
- 客套话:"sure"、"certainly"、"happy to"、"I'd recommend"
- 模糊措辞:"it might be worth"、"you could consider"
- 冗余短语:"in order to" → "to"、"make sure to" → "ensure"
- 连接性赘词:however、furthermore、additionally、in addition
逐字保留(Preserve EXACTLY,绝不修改)
- 围栏代码块(``` 和 4 空格缩进块)、内联代码(反引号内容)
- URL 与链接、文件路径(
/src/components/...、./config.yaml) - 命令(
npm install、docker build)、技术术语、专有名词 - 日期、版本号、数值、环境变量(
$HOME、NODE_ENV)
结构保留(Preserve Structure)
- 所有 markdown 标题(标题文本原样,只压标题下的正文)
- 项目符号层级、有序列表编号、表格结构、YAML frontmatter
主动压缩(Compress)
- 用短同义词("big" 不写 "extensive","fix" 不写 "implement a solution for")
- 允许句子碎片("Run tests before commit" 而非 "You should always run tests before committing")
- 去掉 "you should / make sure to / remember to",直接陈述动作
- 合并意思重复的 bullet,同模式的多个例子只留一个
CRITICAL RULE:任何 ``` 内的内容必须逐字复制——不删注释、不动空格、不重排行、不缩短命令;含代码块的文件中,代码块视为只读区域,只压其外侧的正文。
SKILL.md 给出的模式示例:
原文:"You should always make sure to run the test suite before pushing any changes to the main branch. This is important because it helps catch bugs early and prevents broken builds from being deployed to production." 压缩后:"Run tests before push to main. Catch bugs early, prevent broken prod deploys."
执行管线:从 /caveman-compress 到落盘
触发方式是斜杠命令 /caveman-compress <filepath>,或让用户压缩某个记忆文件。技能从 SKILL.md 所在目录运行 python3 -m scripts <absolute_filepath>,入口是 scripts/cli.py。完整流程(对应 SKILL.md 的 Process 一节):
- 检测文件类型(不耗 token):detect.py 按扩展名分类——
.md/.txt/.markdown/.rst/.typ/.typst/.tex判为natural_language可压缩;.py/.js/.ts/.json/.yaml/.toml/.env/.sql/.sh等直接跳过;无扩展名文件(如CLAUDE.md之外的 TODO、Dockerfile)则用内容启发式(shebang、JSON/YAML 解析、代码行占比 >40%)。注意should_compress显式跳过*.original.md,备份文件永远不会被二次压缩。本文的夹具claude-md-project.md走的就是.md可压缩路径。 - 调用 Claude 压缩:compress.py 的
call_claude优先走 Anthropic Python SDK(需设置ANTHROPIC_API_KEY,默认模型由CAVEMAN_MODEL指定,缺省claude-sonnet-4-5);否则回退到claude --printCLI(固定参数列表,不经过 shell,内容走 stdin)。 - 校验输出(不耗 token):validate.py 对压缩前后做六项比对,任一 error 即失败。
- 修复重试:校验失败时把错误清单发给 Claude 做定点修复(
build_fix_prompt明确"DO NOT recompress or rephrase",只修列出的错误),最多重试 2 次(MAX_RETRIES = 2);仍失败则报告错误、原文件保持未动。
CLI 的退出码也有讲究:0 成功或文件不属于自然语言而跳过,2 重试后仍失败,130 用户中断。
压缩前的两道"预写保护":frontmatter 与代码块掩码
真正发给模型的并不是原始全文。compress.py 会:
- 拆走 YAML frontmatter(
split_frontmatter):frontmatter 在输入中被外科式切除、在输出前原样拼回——注释说明里直言原因:"压缩 LLM 有无视 preserve-structure 规则去删改 frontmatter 的习性"。 - 掩码所有代码块(
mask_code_blocks,compress.py 第 488 行起):围栏块和 4 空格缩进块被替换成不透明标记@@CAVEMAN_PRESERVED_CODE_<i>_<sha256前16位>@@,模型只能看到标记。压缩结束后restore_code_blocks逐字节还原;若发现某个标记被模型删除、复制或改动(restored.count(marker) != 1),直接抛ValueError拒绝落盘——"fail closed"。这解释了为什么本文夹具里那段 npm 命令块能分毫不动地活下来:模型根本看不到它的真实内容。
校验器:六项检查如何卡住"坏输出"
validate(original, compressed) 返回 is_valid + errors + warnings,逐项对应 SKILL.md 的保留承诺:
| 校验项 | 检查内容 | 级别 |
|---|---|---|
validate_headings |
标题数量、文本、顺序一致(标题文本改了会让所有锚点链接失效);仅层级变化降级为警告 | 文本变更 = error |
validate_code_blocks |
围栏块 + 缩进代码块逐一精确比对;支持 CommonMark 嵌套围栏(外层 4 反引号包内层 3 反引号) | error |
validate_urls |
URL 集合双向比对,报告丢失/新增 | error |
validate_paths |
文件路径集合比对;只有"确定性路径"(带 ./、../、/、盘符前缀,或末段带点分扩展名)丢失才升级为 error,普通散文路径对("pros/cons")只警告 |
error / warning |
validate_bullets |
项目符号数量漂移超过 15% 才警告 | warning |
validate_inline_codes |
内联代码 span 用 Counter 精确比对(区分"丢失 3 次中的 1 次");先剥掉围栏块再配对反引号,防止代码块内的反引号串位 | 丢失 = error |
缩进代码块的识别有一段值得读的设计说明(validate.py 第 112-126 行):早期版本不识别 4 空格缩进块,"code blocks preserved exactly" 于是空对空地通过,而压缩器已把 kubectl delete pod --all -n prod 改写成 -n dev——对破坏性命令"干净地通过校验"是这个工具最坏的一种失败,因为它会覆写用户文件。列表内部的四空格缩进则刻意不视为代码(那只是列表内容缩进),避免把合法压缩误判为失败。
数据安全:备份、原子写、锁与拒绝清单
caveman-compress 是就地覆写工具,所以 compress.py 的防御密度很高,SECURITY.md 与 tests/test_compress_safety.py 共同钉死了这些保证:
- 500KB 上限:
MAX_FILE_SIZE = 500_000,超限在任何 API 调用之前直接拒绝。 - 敏感路径拒绝(
is_sensitive_path):credentials*、secrets*、id_ed25519、.pem/.key等文件名,以及.ssh、.aws、api-keys、private_keys等路径分量命中黑名单即拒绝——因为压缩意味着把原文发往第三方 API 边界;误报时用户需自行改名,无静默覆盖开关。 - 备份在树外(
backup_dir_for):原文以原始字节写入$XDG_DATA_HOME/caveman-compress/backups/<父目录名>/<stem>.original.md(Windows 为%LOCALAPPDATA%\caveman-compress\backups\...),而不是放在源文件旁边——目的是防止技能自动加载器把.original.md当活跃文件再次摄入。写备份后会读回比对字节,不一致就删掉坏备份并中止,绝不让"损坏的备份 + 被压缩的主文件"并存。(注意:仓库里的测试夹具把.original.md放在源文件旁边只是为了测试引用方便,与真实运行的备份位置不同。) - 空/无变化输出不落盘:Claude 返回空串、纯空白、或与输入(按正文部分比较,frontmatter 剔除后)逐字相同,一律中止且不产生备份——对应测试
test_empty_compressed_output_does_not_touch_disk、test_identical_compressed_output_does_not_touch_disk。 - 原子写(
write_text_atomic/write_bytes_atomic):先编码、写同目录临时文件、fsync、os.replace原子替换,并保留原文件权限位;编码中途失败不会留下 0 字节目标或.tmp残骸(issue #655 的回归)。 - 行尾保真:
read_source从原始字节检测行终止符(CRLF 占多数则 CRLF,否则 LF,混排文件取多数派),写回时原样还原;备份保存的是原始字节而非重新渲染的文本(issue #762 的回归——一行 CRLF 不应改写全文档)。 - 严格 UTF-8:解码失败即抛错拒绝("cannot read exactly = must not rewrite"),杜绝
errors="ignore"时代"丢一个 0xe9 字节、备份与主文件同损、读回校验还通过"的静默数据丢失(issue #686)。 - 跨会话锁(
file_lock):基于 OS 文件锁(POSIXfcntl.flock/ Windowsmsvcrt.locking),锁键是备份路径的 SHA-256 摘要,等锁上限 900 秒;锁文件带O_NOFOLLOW、锁目录拒绝符号链接。同一文件两次并发压缩会串行化,崩溃的持有者由 OS 自动释放锁。 - 失败恢复:重试耗尽后把备份中的原始字节写回目标并删除备份,文件回到压缩前状态。
- 修复回路的 preamble 防护(issue #588):修复响应若在正文前夹带 "Here is the fixed file:" 之类的散文前导,且原文首行是
---或#结构锚点,则该次修复被判无效丢弃。
网络与执行面:除 Anthropic API(SDK 或 CLI)外不发起任何网络请求,不执行文件内容,不触碰用户指定路径之外的文件,subprocess 调用为固定参数列表、无 shell=True(见 SECURITY.md)。
测试如何验证这条管线
tests/test_compress_safety.py 用 mock 掉 call_claude 的方式把上述每条保证变成断言,挑几个与本文夹具直接相关的:
test_code_blocks_are_masked_before_model_and_restored_byte_exact:断言树形图```text块与缩进代码在掩码后对模型不可见(assertNotIn("├── src", masked)),还原后逐字节相等。test_missing_or_duplicated_code_marker_fails_closed:标记被删或被复制时restore_code_blocks抛 "changed preserved code marker"。test_crlf_line_endings_survive_the_round_trip:CRLF 文档压缩后输出与备份都保持 CRLF。test_permission_preserved_across_compression:0o644权限位跨压缩保留。TestOuterWrapperStripping:strip_llm_wrapper只剥"首尾同一围栏块"的外包装,不会把普通 README 的首尾两段```bash块误删合并。
并发与锁的行为另有 tests/test_compress_concurrency.py 覆盖。
适用前提与限制
- 运行前置:Python 3 +
anthropicSDK 与环境变量ANTHROPIC_API_KEY,或已登录的claudeCLI(自动回退);模型可用CAVEMAN_MODEL覆盖。 - 只处理自然语言文件(
.md/.txt/.markdown/.rst/.typ/.typst/.tex及判定为自然语言的无扩展名文件);代码、配置、.env一律跳过;混合内容只压散文部分,拿不准就原样保留。 - 单文件 ≤500KB;敏感命名直接拒绝且无绕过开关;备份已存在时中止以防二次压缩覆盖首次备份。
- 压缩结果仍是给人和 LLM 读的记忆文件:本文夹具展示的 Taskflow 场景说明,架构分层、命令表、环境变量、已知问题这类"高信号密度"内容在压缩后依然自洽可查,而被删的多是修辞性连接语与轶事(如那句 "learned this the hard way")。
- 注意本文所述行为均以当前仓库代码为准;例如锁等待 900 秒、
MAX_RETRIES = 2、默认模型名等常量若上游更新会随之变化。
关键文件索引:样本与对照 tests/caveman-compress/claude-md-project.md / claude-md-project.original.md;规则 skills/caveman-compress/SKILL.md;编排 skills/caveman-compress/scripts/compress.py、检测 skills/caveman-compress/scripts/detect.py、校验 skills/caveman-compress/scripts/validate.py、入口 skills/caveman-compress/scripts/cli.py;安全说明 skills/caveman-compress/SECURITY.md;安全回归测试 tests/test_compress_safety.py。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00