How the Hallmark Pre-flight Cache Works: A Deep Dive into Configuration Caching
Hallmark's pre-flight cache stores project analysis findings in .hallmark/preflight.json and reuses them on subsequent runs unless package.json or tailwind.config.* files have newer modification times.
Hallmark is an open-source project README generator by Nutlope that analyzes your codebase to create polished documentation. To avoid repeated expensive analysis, it implements a sophisticated caching mechanism that balances speed with accuracy. This article explains exactly how the pre-flight cache operates, when it invalidates, and how you can rely on it for fast, repeatable builds.
What Is the Hallmark Pre-flight Cache?
The pre-flight cache is Hallmark's mechanism for persisting project configuration analysis. When Hallmark first processes a repository, it runs a pre-flight step that inspects:
package.jsonfor project metadata and dependenciestailwind.config.*files for styling decisions- Other build configuration files that affect output
From this inspection, Hallmark computes findings—the macrostructure, theme selection, enrichment decisions, and image assets. Rather than recomputing these on every run, Hallmark writes them once to a JSON file and reuses the cached data when appropriate.
Where the Cache Lives
Hallmark stores pre-flight findings at:
.project-root/.hallmark/preflight.json
This path is created relative to your project's root directory. The .hallmark/ directory is typically gitignored, ensuring cached data remains local to each developer's environment and CI runner.
Cache Invalidation Rules
According to the [Hallmark skill definition in SKILL.md](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/SKILL.md) (lines 177-179), the cache becomes stale when either condition is met:
package.jsonor anytailwind.config.*file has a newer modification time than the cachedpreflight.json- The cache has exceeded its TTL—Hallmark can enforce time-based expiry similar to the GitHub star-count caching pattern demonstrated in
site/js/main.js
When stale, Hallmark re-executes the full pre-flight analysis, overwrites preflight.json with fresh findings, and continues processing.
How Hero Enrichment Uses Cached Data
The pre-flight cache serves double duty. In the hero-enrichment step, if you've attached an image asset, Hallmark prefers the already-cached image data stored in .hallmark/preflight.json rather than re-downloading or regenerating a placeholder.
This design avoids redundant network requests and ensures consistent hero image handling across multiple README generation runs. The hero-enrichment logic is detailed in [hero-enrichment.md](https://github.com/Nutlope/hallmark/blob/main/skills/hallmark/references/hero-enrichment.md).
Implementing the Cache Logic: Code Walkthrough
The following simplified implementation mirrors Hallmark's actual cache behavior:
import { readFileSync, writeFileSync, existsSync, statSync } from 'fs';
import { join } from 'path';
const ROOT = process.cwd();
const CACHE_PATH = join(ROOT, '.hallmark', 'preflight.json');
const CONFIG_FILES = ['package.json', 'tailwind.config.js'];
/**
* Return true if any config file is newer than the cache.
*/
function isCacheStale() {
if (!existsSync(CACHE_PATH)) return true;
const cacheMtime = statSync(CACHE_PATH).mtimeMs;
return CONFIG_FILES.some(f => {
const cfgPath = join(ROOT, f);
return existsSync(cfgPath) && statSync(cfgPath).mtimeMs > cacheMtime;
});
}
/**
* Load cached pre-flight data or recompute it.
*/
function getPreflightData() {
if (!isCacheStale()) {
const raw = readFileSync(CACHE_PATH, 'utf8');
return JSON.parse(raw);
}
// Expensive analysis only runs when cache is stale
const findings = runPreflightAnalysis(ROOT);
const payload = { ...findings, _cachedAt: Date.now() };
writeFileSync(CACHE_PATH, JSON.stringify(payload, null, 2));
return findings;
}
Key observations about this implementation:
isCacheStale()implements the exact mtime comparison rule fromSKILL.md_cachedAttimestamp enables optional TTL-based expiry- Atomic write pattern: findings are computed fully before writing, preventing corrupt cache states
Performance Characteristics
| Scenario | Behavior | Typical Latency |
|---|---|---|
| Cold start (no cache) | Full pre-flight analysis | Hundreds of milliseconds |
| Warm cache, fresh configs | Cache hit | < 5 ms (JSON parse only) |
| Stale cache (config changed) | Re-analysis + cache write | Similar to cold start |
The pre-flight cache transforms Hallmark from a per-run analysis tool into a near-instant documentation generator for iterative README editing.
Key Files in the Hallmark Repository
| File | Role in Pre-flight Caching |
|---|---|
skills/hallmark/SKILL.md |
Documents persistence policy and invalidation rules |
skills/hallmark/references/hero-enrichment.md |
Shows cache reuse for image asset handling |
.hallmark/preflight.json (generated) |
On-disk cache storing computed findings |
site/js/main.js |
Demonstrates TTL/stale-while-revalidate patterns that inspired the cache design |
Summary
- Hallmark's pre-flight cache persists analysis findings to
.hallmark/preflight.json - Cache invalidation triggers on mtime changes to
package.jsonortailwind.config.*files - The same cache supports hero-enrichment image data for consistent asset handling
- TTL-based expiry is available for environments requiring time-bounded freshness
- This architecture delivers sub-5ms repeated runs while guaranteeing accurate output when configurations change
Frequently Asked Questions
How do I force Hallmark to ignore the pre-flight cache?
Delete .hallmark/preflight.json from your project root. On the next run, Hallmark will perform a full pre-flight analysis as if processing the repository for the first time.
Does the pre-flight cache include generated README content?
No. The cache stores only findings—the metadata, structural decisions, and image references needed to generate documentation. The final README is always freshly rendered from these findings.
Will changes to my source code invalidate the pre-flight cache?
Not directly. The cache monitors configuration files (package.json, tailwind.config.*) rather than source files. If your code changes affect the README structure, modify package.json or touch the cache file to trigger re-analysis.
Is the .hallmark/ directory safe to commit to version control?
Generally no. Add .hallmark/ to your .gitignore. The cache contains environment-specific paths and timestamps that could cause inconsistencies across machines. It regenerates quickly on each fresh clone.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →