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.json for project metadata and dependencies
  • tailwind.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:

  1. package.json or any tailwind.config.* file has a newer modification time than the cached preflight.json
  2. 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 from SKILL.md
  • _cachedAt timestamp 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.json or tailwind.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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →