Attune uses incremental caching to speed up subsequent scans by only analyzing files that have changed since the last scan.
- Location:
.attune/cache.jsonin your project root - Format: JSON containing metadata, file fingerprints, and cached rule results
- Version: The cache includes a version string to handle format changes
The cache is automatically invalidated when:
-
Time-based expiration (default: 24 hours)
- Cache entries older than 24 hours are considered stale
- Configurable via
maxCacheAgeMsin programmatic usage
-
File modifications
- Any change to a file's modification time invalidates its cached result
- File size changes also trigger invalidation
-
Dependency changes
- Changes to
package.jsoninvalidate the entire cache - This ensures rules that check dependencies are re-run
- Changes to
-
Manual invalidation
- Delete
.attune/cache.jsonto force a full re-scan
- Delete
Caching is enabled by default. No flag needed for incremental scans:
attune analyze .Use --no-cache to force a full scan:
attune analyze . --no-cacheUse --verbose to see cache hits/misses:
attune analyze . --verboseOutput example:
📦 Incremental: Analyzing 5 changed files (48 files cached)
import { CacheManager } from 'attune';
const cache = new CacheManager('/path/to/project', {
enabled: true,
maxAgeMs: 24 * 60 * 60 * 1000, // 24 hours
});
// Check if file should be scanned
const shouldScan = cache.shouldScanFile('src/app.ts');
// After scanning, save results
cache.saveResults('src/app.ts', { findingsCount: 3 });| Option | Type | Default | Description |
|---|---|---|---|
enabled |
boolean | true | Enable/disable caching |
maxAgeMs |
number | 86400000 | Cache TTL in milliseconds (24h) |
The cache stores:
- File metadata: path, modification time, size
- Rule results: findings count per file
- Scan metadata: last scan time, version
Example cache structure:
{
"metadata": {
"version": "1.0.0",
"lastScan": 1700000000000,
"projectRoot": "/my/project",
"packageJsonMtime": 1699999900000
},
"files": {
"src/index.ts": {
"mtime": 1699999800000,
"size": 1234
}
},
"ruleResults": {
"src/index.ts": {
"TS_NO_IMPLICIT_ANY": {
"findingsCount": 2,
"timestamp": 1699999950000
}
}
}
}- Use caching in CI: Caching helps in CI too - the cache file can be persisted across runs
- Exclude large files: Files over 1MB are not cached by default
- Watch specific directories: Use
.attuneignoreto exclude directories that change frequently
If results seem outdated:
- Run with
--no-cacheto force re-scan - Or delete
.attune/cache.json
The cache can grow large in projects with many files. This is normal - each file needs only ~50 bytes. To reduce size:
- Increase
maxAgeMsto reduce cache refresh frequency - Use
.attuneignoreto exclude unnecessary directories
Ensure the .attune directory is preserved in CI:
# GitHub Actions example
- uses: actions/cache@v3
with:
path: .attune
key: attune-cache-${{ hashFiles('package.json') }}