Skip to content
DocumentationReferencev1.2.1

Caching

Content keys, TypeScript metadata fingerprints, SQLite contention waits, and unresolved cache limits.

Signalint stores diagnostic cache state in .signalint/cache.sqlite using Node’s built-in node:sqlite. Both check tools consult this cache. Neither is an unconditional force-refresh command.

Oxlint, Biome, and ESLint reuse matching requested-file snapshots. Misses are submitted as a batch and split back into per-file results.

The implemented key contains:

SHA-256(file content)
: engine
: hash of recognized native config files
: Signalint version
: engine version resolved for the cache lookup

It is based on contents, not Git status or mtime. Importantly, the file path is not part of this key.

Two files with identical contents can share a cache entry. Cached diagnostics are relocated to the requested filename, but path-dependent rules or overrides are not re-evaluated on a hit. This can reuse diagnostics from the wrong file context.

If you depend on path-specific rules, use a direct native-engine run to verify results. Clearing the cache forces misses for the next run but does not eliminate the key collision from subsequent reuse.

  • engines.biome.includeFormatter is not hashed. Changing it can reuse results from the old mode; stop the server and clear the diagnostic cache after a change.
  • Engine resolution and version lookup are process-memoized. Restart after upgrading packages.
  • Cache-version lookup defaults to process.cwd(), while an engine can run against another root selected with SIGNALINT_PROJECT_ROOT or the server API. These roots can resolve different engine versions. Prefer launching in the intended root and clear cache after engine changes in an overridden-root setup.

Do not infer that every setting, plugin, or dependency change invalidates an entry.

The latest TypeScript result is stored separately. In 1.2.1 its state key combines a per-project cache partition and recognized config hash with a source-program fingerprint: a sorted list of JS/TS-family files under the selected config directory (or project root), each file’s path, size, and mtimeMs, plus explicit workspace dependency directories when supplied. File content itself is not hashed by this fingerprint. Requested relevant snapshots still use content keys as well.

This improves 1.0’s omitted-dependency behavior: an unrequested source edit that changes size/mtime inside the fingerprint walk can force a rerun. It is not TypeScript’s dependency graph. The walk skips node_modules, .git, .signalint, and dist, does not follow directory symlinks or interpret compiler include/exclude, and can miss sources outside its selected directory. A same-size edit with restored mtime can leave its fingerprint unchanged.

The TypeScript runner remains whole-program, but the check_files provider now filters displayed diagnostics to requested paths, adding filtered-count aliases when needed. Cached program state is not a promise that all external/imported/configured inputs were tracked. There is no force-refresh tool flag; use native tools when the fingerprint boundary is insufficient.

TypeScript selection and inspection limits

Section titled “TypeScript selection and inspection limits”

The project-check runner selects a config from its first target; see selection rules.

The default check_files runner still compiles the root . config, while its cache-hash/fingerprint probe uses the first requested file and can select a nearer config. Those can differ: a root config edit may not invalidate a result hashed against a nested config. New workspace dependency-directory fingerprinting does not remove this mismatch. The topological project-check path separately supplies a package-specific TypeScript runner.

The process-lifetime tsc --showConfig cache keys only the selected root file’s contents, not the full inheritance chain, path, or engine version. Restart and clear cached diagnostics after configuration changes whose coverage is uncertain.

EngineSources hashed by Signalint
OxlintRoot .oxlintrc, .oxlintrc.json, oxlint.json
BiomeRoot biome.json, biome.jsonc
ESLintRoot eslint.config.js, .mjs, .cjs, .ts, .mts, .cts
TypeScriptConfig selected by the hash probe; bounded extends / references traversal; first recognized root lockfile

These are hashing inputs, not a guarantee that every native engine accepts all of those names or that all configurations it loads are tracked.

For parseable JSON TypeScript configs, the walker follows its supported extends / references paths up to 50 unique paths. It uses JSON.parse, not the TypeScript configuration resolver. JSONC inheritance, package-based extends, nested linter configuration, dynamic imports, and plugin/dependency changes can be missed. The selected file’s own contents are hashed even if chain discovery stops. TypeScript hashing also incorporates the first readable root lockfile among pnpm-lock.yaml, package-lock.json, and yarn.lock; it is not an exhaustive dependency resolver.

The cache sets PRAGMA busy_timeout = 5000 so a competing connection can wait for a lock instead of immediately failing. This does not guarantee every concurrent run succeeds: a lock can outlast the wait, and cache waiting is not a cross-process transaction for engine execution or session JSONL writes.

  • File-result rows: 10,000 by default, with LRU eviction. Identical-content paths may share a row; this is not a count of unique checked filenames.
  • Normal TypeScript project-mode state: .signalint/cache/tsc/<project-id>/tsc.tsbuildinfo.
  • TypeScript build-mode state: native/configured .tsbuildinfo locations, not necessarily .signalint/.
  • Session history and metrics: .signalint/session.jsonl, separate from diagnostic caching.

After MCP checks have accumulated:

Terminal window
npx --no-install signalint stats

Its hit rate describes engine-file lookups in completed tasks. It does not report database disk usage, all project files, or total retained cache rows. See CLI statistics.

SIGNALINT_STATE_DIR redirects the SQLite cache, session log/statistics and normal project-mode TypeScript build info. Prefer an absolute per-project directory; sharing one destination can mix state. Snapshots, buffered live diagnostics and prepared transactions are separate in-memory stores. This override does not redirect every native build-mode artifact.

Stop the server before removing .signalint/cache.sqlite and .signalint/cache/ (or corresponding state-override paths), then reconnect. This does not remove build-mode .tsbuildinfo files elsewhere; locate those from the selected TypeScript configs if a complete compiler-state reset is needed.

Preserve session.jsonl and its backup to keep retained history. Deleting all of .signalint/ removes that history too. No cache reset substitutes for verification with native tools when a key limitation applies.

Source: src/checkFiles.ts, src/cache/sqliteCache.ts, and src/engines/tsc.ts.