1实现原理 · 为什么它能做到
这是本批里少见的「有真代码」的 skill:SKILL.md 的核心指令只有一条——在 SKILL.md 所在目录执行 `python3 -m scripts <绝对路径>`,全部压缩逻辑在自带的 Python 包里。
The compression scripts live in `scripts/` (adjacent to this SKILL.md). If the path is not immediately available, search for `scripts/__main__.py` next to this SKILL.md. 2. From the directory containing this SKILL.md, run: python3 -m scripts <absolute_filepath>
压缩动作是把文件正文送去 Claude:优先走 Anthropic SDK(需 ANTHROPIC_API_KEY),否则退化为本地 `claude --print` CLI 子进程(用用户桌面认证)。
api_key = os.environ.get("ANTHROPIC_API_KEY") if api_key: try: import anthropic client = anthropic.Anthropic(api_key=api_key, timeout=CLAUDE_CALL_TIMEOUT_SECONDS) msg = client.messages.create( model=os.environ.get("CAVEMAN_MODEL", "claude-sonnet-4-5"),
代码块在送模型前被替换成不可解读的标记,回来后按「每个标记恰好出现一次」恢复,否则整体拒绝写入——这是防止「压缩把命令改坏」的核心机制。
def restore_code_blocks(text: str, blocks: List[Tuple[str, str]]) -> str: """Restore markers exactly; fail closed if model removed, copied, or altered one."""
写完不算完:另有一套结构性校验器(validate.py)比对原文与压缩稿的标题、代码块、URL、路径、项目符号、行内代码,失败则带着错误清单再请 Claude「只修列出的错误」并重试,最多 2 次。
validate_headings(orig, comp, result) validate_code_blocks(orig, comp, result) validate_urls(orig, comp, result) validate_paths(orig, comp, result) validate_bullets(orig, comp, result) validate_inline_codes(orig, comp, result)
写入是「先备份、回读校验、原子替换、保留权限位与换行风格」的一条链,多处是为修历史数据丢失事故而写的。
write_bytes_atomic(backup_path, original_raw) if backup_path.read_bytes() != original_raw: print(f"❌ Backup write verification failed: {backup_path}")
有硬性输入闸门:文件 >500KB 拒绝、疑似凭证/密钥的文件名拒绝、空文件拒绝、已有备份则中止(防覆盖)。
MAX_FILE_SIZE = 500_000 # 500KB
并发用 OS 原生文件锁(POSIX fcntl.flock / Windows msvcrt.locking),锁键 = 备份路径的 sha256 前 16 位;不支持锁的文件系统降级为「无协调继续跑」,锁目录/锁文件遇到符号链接直接拒绝。
return _state_base_dir("locks") / f"{digest}.lock"
非膨胀不变量:压缩结果按「去掉 frontmatter 的正文」比较,必须严格更短,否则中止且不动原文件;这条对修复路径也成立。
if not _is_smaller_than_body(compressed_body, body): print(" Original file is untouched (no backup created).") return False
可压缩范围由 detect.py 的扩展名白名单/黑名单 + 仅对无扩展名文件的内容嗅探决定,.original.md 备份永不二次压缩。
COMPRESSIBLE_EXTENSIONS = {".md", ".mdc", ".txt", ".markdown", ".rst", ".typ", ".typst", ".tex"}
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| api | Anthropic Messages API(经 anthropic Python SDK) |
| cli | claude CLI(Claude Code / Claude desktop 认证) |
| package | anthropic(Python SDK,可选) |
| package | tiktoken(可选,仅 benchmark.py) |
| cli | python3(运行时不带第三方依赖;仅标准库 contextlib/errno/hashlib/os/re/shutil/stat/subprocess/tempfile/time/pathlib,Windows 用 msvcrt、POSIX 用 fcntl) |
4风险提醒 风险提醒:橙色 · 评估后使用
- 文件正文外发第三方模型 API(数据边界) — 压缩必须把文件原文送给 Anthropic(SDK 或 claude CLI)。记忆文件(CLAUDE.md、项目笔记)常含内部约定、路径、乃至业务信息;敏感文件名 denylist 只能拦住名字可疑者,正文里的秘密不会被拦。Snyk 亦给出 High Risk 评级(其 SECURITY.md 自承此项)。企业对代码/文档外发有合规要求时需先评估。
- 原地覆盖用户文件 — 默认行为是用压缩稿覆盖原文件(备份在 out-of-tree 数据目录)。虽有备份、暂存校验、原子写与失败回滚,但备份存在与否是「覆盖后唯一退路」,且 backup_path 已存在时会直接中止(防覆盖旧备份)——用户若清理过该目录,历史原始稿即不可恢复。
- 语义层面无校验,只有结构校验 — validate.py 保证标题/代码块/URL/路径/列表/行内代码不变,但不保证正文语义不被误改(常识性事实、数字、语气都可能被模型改写)。压缩「记忆文件」等同于让模型重写你的记忆。
- 依赖宿主环境的 CLI 与凭证 — 无 API key 时依赖本机 claude CLI 及其桌面认证;Windows 下曾出现解码问题(issue #152),说明回退路径的平台假设较脆弱;CAVEMAN_MODEL 可被环境覆盖,指向非预期模型时行为与默认不同。
- 启发式 denylist 可被改名绕过 — is_sensitive_path 是文件名/路径正则与 token 匹配,用户若把凭证文件改名(如 prod-notes.md)即会放行——注释中明确把 override 设计为「用户改名」而非「加 --force」,即有意不做交互式确认。
5第二遍独立确认
- [ok] SKILL.md 提到的脚本路径与运行方式 — `python3 -m scripts <file>` 成立:scripts/__main__.py 导入 cli.main 并调用;cli.py 校验参数个数与文件存在/类型后执行 compress_file。SKILL.md 提示的 'search for scripts/__main__.py' 与实际文件名一致。
- [ok] Anthropic 为唯一网络出口 — 六个脚本中无 urllib/requests/socket/curl/wget 命中;网络仅经 anthropic SDK client.messages.create 或 claude CLI 子进程。SDK 端点在源码中未硬编码,故 external_deps.endpoint 留空(不臆测)。
- [ok] 「subprocess 无 shell 注入」这一说法 — subprocess.run([claude_bin, "--print", "--setting-sources", "", "--strict-mcp-config"], input=prompt, ...) 为列表参数 + stdin,无 shell=True;SECURITY.md 亦声明 'Does not use shell=True or string interpolation in subprocess calls'。
- [ok] 「备份在源目录之外」是否属实(SKILL.md / Purpose 段) — backup_dir_for() 返回 _state_base_dir("backups")/filepath.parent.name,其中 _state_base_dir 为 $XDG_DATA_HOME/caveman-compress 或 ~/.local/share/caveman-compress(Windows 用 %LOCALAPPDATA%),确实不在源文件旁;注释给出理由(skill auto-loader 会二次读入 .original.md)。
- [ok] 敏感文件拒绝覆盖面的自评(第一遍称「覆盖 .env/credentials/密钥」) — 逐条核对 SENSITIVE_BASENAME_REGEX 与 SENSITIVE_PATH_COMPONENTS/SENSITIVE_NAME_TOKENS:.env*、.netrc、credentials*、secret(s)*、password(s)*、id_rsa/dsa/ecdsa/ed25519(.pub)、authorized_keys、known_hosts、*.pem|key|p12|pfx|crt|cer|jks|keystore|asc|gpg;路径组件含 .ssh/.aws/.gnupg/.kube/.docker 与 credential(s)/secret(s);名字 token 含 secret/credential/password/passwd/apikey/accesskey/token/privatekey。属启发式 denylist(可被改名绕过),已在 analysis 注记,未夸大。
- [ok] 固定大小上限 500KB — compress_file 内 MAX_FILE_SIZE = 500_000 且在任何 API 调用之前检查;SECURITY.md 亦声明 'Files larger than 500KB are rejected before any API call is made'。
- [ok] 「校验不过则原文件不动」 — 压缩候选先写 <file>.caveman-staged 并对其跑 validate;只有 is_valid 才 _write_target(filepath, ...),两次重试用尽后 unlink 暂存与备份并打印 'Failed after retries: original left untouched'。
- [ok] SKILL.md 压缩规则 vs 脚本提示词是否一致(有无文档吹牛) — SKILL.md 的 Remove/Preserve/Compress 规则与 build_compress_prompt 的 STRICT RULES 同向(保代码块、保行内代码、保 URL、保标题、保路径命令),脚本还把「不要给整体套一层 ```markdown 围栏」写进提示词,并有 strip_llm_wrapper 兜底剥离。无夸大。
6结论
52e12dda463f9c55…15581d1400