Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
Invar
The Unchanging Key for Changing Data
A high-precision CLI tool for generating deterministic, content-addressable identifiers from any data source. Built for CI/CD pipelines, build systems, and content-addressed storage.
Overview
Invar generates immutable structural state roots (Invar Keys) from arbitrary input data. Unlike traditional hashing, Invar processes data byte-by-byte through a mathematical synthesis engine, producing keys that represent the exact structural identity of your data.
Key Properties
- Deterministic: Identical input always produces identical keys
- Sensitive: A single byte change produces a completely different key
- Structural: Keys represent the exact structural identity of data
- Order-independent: Directory hashing produces consistent keys regardless of file system ordering
Installation
Pre-built Binaries
Download from GitHub Releases:
# Linux (x86_64)
# macOS (Apple Silicon)
Using Cargo
From Source
Docker
# Usage
|
Quick Start
# Generate key from a file
# Generate key from stdin
|
# Generate key from inline data
# Generate key from a directory
# Verify data matches an expected key
# Watch for changes
Features
File and Data Hashing
# From file
# From stdin
|
# From inline string
# JSON output with metadata
Directory Hashing
Hash entire directories with deterministic, order-independent results:
# Hash a directory recursively
# Include hidden files
# JSON output with file count and size
# Output: {"key": "abc123...", "file_count": 42, "total_bytes": 123456}
Ignore Patterns
Invar respects .gitignore and .invarignore files by default:
# Default behavior (respects .gitignore and .invarignore)
# Disable .gitignore
# Disable .invarignore
Create a .invarignore file for invar-specific exclusions:
# .invarignore - patterns specific to invar
*.log
build/
dist/
*.mp4
Streaming Mode
Process large files with constant memory usage:
# Stream large files
# With progress reporting (every N MB)
Watch Mode
Monitor files or directories for changes:
# Watch a single file
# Watch a directory recursively
# Custom debounce interval (milliseconds)
# JSON output for scripting
Verification
# Generate a key
KEY=
# Later, verify the file hasn't changed
# Verify a directory
Use Cases
CI/CD Cache Keys
# GitHub Actions
- name: Generate cache key
run: echo "CACHE_KEY=$(invar gen --directory src)" >> $GITHUB_ENV
- uses: actions/cache@v4
with:
key: build-${{ env.CACHE_KEY }}
Build System Integration
# Skip rebuild if source unchanged
CURRENT=
CACHED=
if [; then
else
fi
Content-Addressable Storage
# Store files by content hash
KEY=
Configuration Versioning
# Detect configuration changes
if ! ; then
fi
Output Formats
Text (Default)
JSON
{
}
{
}
Command Reference
invar gen (alias: g)
Generate an Invar key from input data.
| Option | Short | Description |
|---|---|---|
--file <PATH> |
-f |
Read from file |
--data <STRING> |
-d |
Read from string |
--directory <PATH> |
Hash directory recursively | |
--stream |
Use streaming mode (low memory) | |
--progress <MB> |
Report progress every N MB | |
--output <FORMAT> |
-o |
Output format: text or json |
--include-hidden |
Include hidden files (directories) | |
--follow-links |
Follow symbolic links | |
--no-gitignore |
Ignore .gitignore patterns | |
--no-invarignore |
Ignore .invarignore patterns |
invar check (alias: c)
Verify data produces an expected key.
| Option | Short | Description |
|---|---|---|
--expected <KEY> |
-e |
Expected 64-character hex key |
| (plus all gen options) |
Exit codes: 0 = match, 1 = mismatch or error
invar watch (alias: w)
Watch for file changes and report new keys.
| Option | Short | Description |
|---|---|---|
<PATH> |
File or directory to watch | |
--recursive |
-r |
Watch subdirectories |
--debounce <MS> |
Debounce interval (default: 500) | |
--output <FORMAT> |
-o |
Output format: text or json |
How It Works
Invar uses the Distinction Calculus to generate structural identifiers:
- Initialize the root Distinction (D0)
- Process each byte of input data
- Convert each byte to a canonical Distinction via binary path encoding
- Synthesize with the running root:
D_root = synthesize(D_root, D_byte) - Return the final Distinction ID as a 64-character hex string
This ensures:
- Byte-level precision: Every byte affects the final key
- Structural uniqueness: Different data produces different keys
- Mathematical determinism: Same data always produces same key
Examples
See the examples directory for:
- GitHub Actions cache workflows
- GitLab CI pipelines
- Docker build optimization
- Monorepo selective testing
Development
# Build
# Test (87 tests)
# Lint
# Format
License
Dual-licensed under MIT or Apache 2.0 at your option.
Acknowledgments
- Built on koru-lambda-core
- Named after Invar, an alloy with minimal thermal expansion