
Content Hash Cache Pattern
- 5.8k installs
- 238k repo stars
- Updated August 5, 2026
- affaan-m/everything-claude-code
content-hash-cache-pattern is an agent skill that caches expensive file processing results using SHA-256 content hashes as keys, with a service wrapper around pure extraction functions.
About
This skill defines a content-hash file cache for expensive processing such as PDF parsing, text extraction, or image analysis. Cache keys are SHA-256 digests of file bytes, not paths, so renames and moves still hit cache while content edits invalidate automatically without an index file. Implementation chunks large files in 64KB reads, stores each entry as a frozen dataclass serialized to {hash}.json for O(1) lookup, and treats JSON corruption as a cache miss. A service-layer wrapper extract_with_cache checks the hash, returns cached documents on hit, otherwise calls a pure extract_text function and writes a new entry, preserving single responsibility. CLI tools can expose --cache and --no-cache by toggling cache_enabled. Best practices log truncated hashes on hit or miss, keep processors ignorant of caching, and never crash on bad cache files. Anti-patterns reject path-keyed dictionaries, embedding cache branches inside extraction functions, and dataclasses.asdict for nested frozen types. Skip when results must always be fresh, cache blobs would be huge, or outputs depend on parameters beyond raw file content.
- Key caches by SHA-256 of file contents so moves and renames still hit while edits invalidate
- Store one {hash}.json entry per digest for O(1) lookup without maintaining a separate index
- Wrap pure extract_text in extract_with_cache so processing logic stays cache-agnostic
- Chunk hashing at 64KB to handle large files without loading entire payloads into memory
- Return None on corrupt cache JSON and reprocess on the next run instead of crashing
Content Hash Cache Pattern by the numbers
- 5,775 all-time installs (skills.sh)
- +221 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #9 of 290 Python skills by installs in the Skillselion catalog
- Security screen: MEDIUM risk (skills.sh audit)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
content-hash-cache-pattern capabilities & compatibility
- Capabilities
- key caches by sha 256 of file contents so moves · store one {hash}.json entry per digest for o(1) · wrap pure extract_text in extract_with_cache so · chunk hashing at 64kb to handle large files with · return none on corrupt cache json and reprocess
- Use cases
- pdf parsing · orchestration
What content-hash-cache-pattern says it does
Unlike path-based caching, this approach survives file moves/renames and auto-invalidates when content changes.
Keep the processing function pure. Add caching as a separate service layer.
Treat corruption as cache miss
npx skills add https://github.com/affaan-m/everything-claude-code --skill content-hash-cache-patternAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 5.8k |
|---|---|
| repo stars | ★ 238k |
| Security audit | 3 / 3 scanners passed |
| Last updated | August 5, 2026 |
| Repository | affaan-m/everything-claude-code ↗ |
What it does
Add deterministic, path-independent caching around expensive Python file extraction pipelines.
Who is it for?
Python CLIs or batch pipelines that reprocess PDFs, images, or documents and need a --cache toggle without polluting core extractors.
Skip if: Real-time feeds that must always be fresh, gigantic cache entries better streamed, or outputs that vary with extraction configs independent of file bytes.
When should I use this skill?
Activate when building file processing pipelines, processing cost is high and files repeat, you need --cache/--no-cache CLI control, or you want caching without modifying pure functions.
What you get
Agents add hash-keyed JSON caches with graceful miss handling so repeated PDF, OCR, or text extraction runs skip unchanged files safely.
- hash cache service
- CLI cache flags
- cached extraction results
Files
Content-Hash File Cache Pattern
Cache expensive file processing results (PDF parsing, text extraction, image analysis) using SHA-256 content hashes as cache keys. Unlike path-based caching, this approach survives file moves/renames and auto-invalidates when content changes.
When to Activate
- Building file processing pipelines (PDF, images, text extraction)
- Processing cost is high and same files are processed repeatedly
- Need a
--cache/--no-cacheCLI option - Want to add caching to existing pure functions without modifying them
Core Pattern
1. Content-Hash-Based Cache Key
Use file content (not path) as the cache key:
import hashlib
from pathlib import Path
_HASH_CHUNK_SIZE = 65536 # 64KB chunks for large files
def compute_file_hash(path: Path) -> str:
"""SHA-256 of file contents (chunked for large files)."""
if not path.is_file():
raise FileNotFoundError(f"File not found: {path}")
sha256 = hashlib.sha256()
with open(path, "rb") as f:
while True:
chunk = f.read(_HASH_CHUNK_SIZE)
if not chunk:
break
sha256.update(chunk)
return sha256.hexdigest()Why content hash? File rename/move = cache hit. Content change = automatic invalidation. No index file needed.
2. Frozen Dataclass for Cache Entry
from dataclasses import dataclass
@dataclass(frozen=True, slots=True)
class CacheEntry:
file_hash: str
source_path: str
document: ExtractedDocument # The cached result3. File-Based Cache Storage
Each cache entry is stored as {hash}.json — O(1) lookup by hash, no index file required.
import json
from typing import Any
def write_cache(cache_dir: Path, entry: CacheEntry) -> None:
cache_dir.mkdir(parents=True, exist_ok=True)
cache_file = cache_dir / f"{entry.file_hash}.json"
data = serialize_entry(entry)
cache_file.write_text(json.dumps(data, ensure_ascii=False), encoding="utf-8")
def read_cache(cache_dir: Path, file_hash: str) -> CacheEntry | None:
cache_file = cache_dir / f"{file_hash}.json"
if not cache_file.is_file():
return None
try:
raw = cache_file.read_text(encoding="utf-8")
data = json.loads(raw)
return deserialize_entry(data)
except (json.JSONDecodeError, ValueError, KeyError):
return None # Treat corruption as cache miss4. Service Layer Wrapper (SRP)
Keep the processing function pure. Add caching as a separate service layer.
def extract_with_cache(
file_path: Path,
*,
cache_enabled: bool = True,
cache_dir: Path = Path(".cache"),
) -> ExtractedDocument:
"""Service layer: cache check -> extraction -> cache write."""
if not cache_enabled:
return extract_text(file_path) # Pure function, no cache knowledge
file_hash = compute_file_hash(file_path)
# Check cache
cached = read_cache(cache_dir, file_hash)
if cached is not None:
logger.info("Cache hit: %s (hash=%s)", file_path.name, file_hash[:12])
return cached.document
# Cache miss -> extract -> store
logger.info("Cache miss: %s (hash=%s)", file_path.name, file_hash[:12])
doc = extract_text(file_path)
entry = CacheEntry(file_hash=file_hash, source_path=str(file_path), document=doc)
write_cache(cache_dir, entry)
return docKey Design Decisions
| Decision | Rationale |
|---|---|
| SHA-256 content hash | Path-independent, auto-invalidates on content change |
{hash}.json file naming | O(1) lookup, no index file needed |
| Service layer wrapper | SRP: extraction stays pure, cache is a separate concern |
| Manual JSON serialization | Full control over frozen dataclass serialization |
Corruption returns None | Graceful degradation, re-processes on next run |
cache_dir.mkdir(parents=True) | Lazy directory creation on first write |
Best Practices
- Hash content, not paths — paths change, content identity doesn't
- Chunk large files when hashing — avoid loading entire files into memory
- Keep processing functions pure — they should know nothing about caching
- Log cache hit/miss with truncated hashes for debugging
- Handle corruption gracefully — treat invalid cache entries as misses, never crash
Anti-Patterns to Avoid
# BAD: Path-based caching (breaks on file move/rename)
cache = {"/path/to/file.pdf": result}
# BAD: Adding cache logic inside the processing function (SRP violation)
def extract_text(path, *, cache_enabled=False, cache_dir=None):
if cache_enabled: # Now this function has two responsibilities
...
# BAD: Using dataclasses.asdict() with nested frozen dataclasses
# (can cause issues with complex nested types)
data = dataclasses.asdict(entry) # Use manual serialization insteadWhen to Use
- File processing pipelines (PDF parsing, OCR, text extraction, image analysis)
- CLI tools that benefit from
--cache/--no-cacheoptions - Batch processing where the same files appear across runs
- Adding caching to existing pure functions without modifying them
When NOT to Use
- Data that must always be fresh (real-time feeds)
- Cache entries that would be extremely large (consider streaming instead)
- Results that depend on parameters beyond file content (e.g., different extraction configs)
Related skills
Forks & variants (1)
Content Hash Cache Pattern has 1 known copy in the catalog totaling 1.4k installs. They canonicalize to this original listing.
- affaan-m - 1.4k installs
How it compares
Pick content-hash caching when files move or change often; use path-based caches only for immutable, fixed-location assets.
FAQ
Why hash file content instead of the path?
Content hashes stay stable across renames and moves, and any byte change produces a new key so stale results invalidate without maintaining a path index.
Where should cache logic live relative to extraction?
Keep extract_text pure and implement cache check, miss handling, and writes in a separate extract_with_cache service wrapper.
How should the cache behave on corrupted JSON files?
read_cache should return None on decode or schema errors so the pipeline treats corruption as a miss and reprocesses on the next run.
Is Content Hash Cache Pattern safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.