skills/compress/ was a byte-identical dupe of skills/caveman-compress/ (SHA256 match across all 7 scripts/ files; SKILL.md diff was name: + Process step 2 only; descriptions textually identical = arbitrary harness tie-break + double-counted listing budget). Kept caveman-compress canonical: it carries README.md (benchmarks + caveman-toolkit branding) and SECURITY.md (Snyk false-positive writeup), and matches the caveman-* prefix invariant. Ported the better Process-step wording from compress (`cd <directory_containing_this_SKILL.md>`) into caveman-compress; the prior `cd caveman-compress` form assumed cwd was the parent dir and broke when invoked from ~/.claude/skills/caveman-compress/. Added version: 1.0.0 to caveman-compress frontmatter (first versioned release; aligns with skill-versioning concept). Removed: skills/compress/, dist/compress.skill, ~/.claude/skills/compress/ (manual prune; install.sh has no prune step yet -- future [install-ps1] task should add --prune). Slash-command impact: /compress gone; /caveman-compress and /caveman:compress (toolkit-canonical) remain. Wiki: .wiki/concepts/compress-dedup.md (rationale + rejected alternatives), index.md + log.md updated. Tasks: [compress-dedup] flipped active -> done in same commit (per-task file .tasks/compress-dedup.md created with full decisions log). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.4 KiB
title, type, tags, updated
| title | type | tags | updated | ||||
|---|---|---|---|---|---|---|---|
| compress vs caveman-compress dedup | concept |
|
2026-05-05 |
compress vs caveman-compress dedup
Two skills shipped the same payload under different names. Kept
caveman-compress(richer, on-brand), deletedcompress. Recorded here so future readers don't reinvent the analysis.
What we found
Side-by-side audit of skills/compress/ and skills/caveman-compress/:
| Layer | compress |
caveman-compress |
|---|---|---|
scripts/__init__.py |
identical (SHA256) | same |
scripts/__main__.py |
identical | same |
scripts/benchmark.py |
identical | same |
scripts/cli.py |
identical | same |
scripts/compress.py |
identical | same |
scripts/detect.py |
identical | same |
scripts/validate.py |
identical | same |
SKILL.md description |
byte-identical text | byte-identical text |
SKILL.md Process step 2 |
cd <directory_containing_this_SKILL.md> && python3 -m scripts ... (generic) |
cd caveman-compress && python3 -m scripts ... (brittle, assumes cwd is parent) |
SKILL.md name: |
compress |
caveman-compress |
README.md |
absent | present (benchmarks table, branding, "Part of Caveman" toolkit linkage) |
SECURITY.md |
absent | present (Snyk false-positive writeup: subprocess + file I/O patterns explained) |
Frontmatter version: |
absent | absent (added 1.0.0 as part of this dedup) |
Description text in both skills' frontmatter:
Compress natural language memory files (CLAUDE.md, todos, preferences) into caveman format
to save input tokens. ... Trigger: /caveman:compress <filepath> or "compress memory file"
— literally the same paragraph. The harness loads both skill listings, both register independently, descriptions identical ⇒ activation tie-break is arbitrary, and the listing budget pays twice.
What we kept and why
Canonical = caveman-compress. Reasons in order of weight:
- Richer artefacts — README.md and SECURITY.md exist only here. The README is not boilerplate: benchmarks table on real files (claude-md-preferences.md, project-notes.md, mixed-with-code.md), 46% average savings claim, before/after example. The SECURITY.md is what static-analysis (Snyk) hooks into, so deleting it would re-open the same false-positive ticket the upstream author already closed.
- On-brand naming — the skill is part of the JuliusBrussee/caveman toolkit. The
caveman-*prefix lines up with the rest of the cluster:caveman(speak compressed),caveman-commit(commit-message variant),caveman-review(PR-review variant),caveman-help(help card),caveman-compress(compress files).compresswas the lone exception that broke the prefix invariant. - History reads cleanly — the per-task
[skill-readmes]plan groups the caveman cluster as a single batch for README work. Keeping the prefix means that batch covers all of them; mixing in a straycompresswould force a "wait, do we README this one separately?" decision later.
What we ported across before deleting
The only thing compress did better than caveman-compress was Process step 2. Original wording:
cd caveman-compress && python3 -m scripts <absolute_filepath>
This assumes cwd is the parent of caveman-compress/. When the agent invokes the skill from ~/.claude/skills/caveman-compress/, that assumption is false (cwd is the skills dir, parent is ~/.claude/). The compress SKILL.md had the robust form:
cd <directory_containing_this_SKILL.md> && python3 -m scripts <absolute_filepath>
— ported into caveman-compress/SKILL.md as part of this dedup. Net: the canonical skill now has the better instructions plus the README + SECURITY.
Also added version: 1.0.0 to frontmatter — first versioned release. Aligns with the rest of the infra-skill cluster (skill-versioning).
What we rejected
Alias-stub — keep skills/compress/SKILL.md as a tiny pointer file with description "alias for caveman-compress, see that skill". Rejected: the harness has no alias mechanism. Every SKILL.md file fully registers as a skill, with its description text consuming the listing budget. An alias-stub still occupies a listing slot and a description allowance — there's no "see that skill" indirection at the harness level. Pure waste of a listing entry.
Keep both, document them as siblings — let the user pick which slash-command name they prefer (/compress vs /caveman-compress). Rejected: descriptions are identical; the harness has no signal to disambiguate; activation tie-break is arbitrary. Forces every future /caveman:compress call to gamble on which copy the harness picks.
Delete caveman-compress, keep compress as the simpler name — rejected because we'd lose the README, SECURITY.md, and the caveman-toolkit branding link. compress was the stripped-down fork; reverting to it would be a net regression in artefact quality.
Install-path impact
scripts/install.sh has no prune step. Removing skills/compress/ does not remove ~/.claude/skills/compress/ on the user's machine — the install script copies, never deletes. Manual rm -rf ~/.claude/skills/compress/ is required during this dedup. Same applies to dist/compress.skill: deleted explicitly, since the next build.sh run iterates over skills/<name>/ and won't recreate an artefact for a source folder that no longer exists.
Future work: the
install-ps1⚪ task should at minimum matchinstall.sh's behavior, but is also the right time to add a--pruneflag that removes~/.claude/skills/<name>/for every name not inskills/<name>/. Would have made this dedup automatic instead of three-step.
Slash-command impact
Before: /compress, /caveman-compress, and /caveman:compress (toolkit-canonical) were all live.
After: /compress is gone. /caveman-compress and /caveman:compress still work. User confirmed /compress was effectively never used; no migration needed.
See also
- skill-versioning — why infra skills carry
version:in frontmatter and the project-discipline Rule 3 bumps tie back here - repo-layout — flat
skills/layout means duplicates show up as flat sibling folders, easy to spot in a directory listing - skill-vs-plugin — caveman-compress is a bare SKILL.md (no slash command, no hooks, no MCP), the right granularity for this workload