Reconify is an open-source Go CLI and library for reconciling financial records from banks, payment service providers, ledgers, and spreadsheets.
It normalizes rows from different systems, matches transactions using explicit rules, and reports the evidence needed to investigate exceptions:
- exact matches;
- missing records on either side;
- amount and timing differences;
- duplicate groups; and
- grouped settlements such as one-to-many and many-to-many payouts.
Install Reconify from a release binary, with Go, or from source. Release binaries are published for macOS (Apple Silicon and Intel), Linux (amd64), and Windows (amd64).
Before installing, check whether Reconify is already available and identify a directory on PATH that is appropriate for this machine. Do not install a binary for a different operating system or CPU architecture.
Find every release on the Reconify releases page, or use the latest-release URLs below after confirming the target matches the machine.
curl -L -o reconify https://github.com/ReconifyHQ/reconify/releases/latest/download/reconify-darwin-arm64
chmod +x reconify
sudo mv reconify /usr/local/bin/
reconify --versioncurl -L -o reconify https://github.com/ReconifyHQ/reconify/releases/latest/download/reconify-darwin-amd64
chmod +x reconify
sudo mv reconify /usr/local/bin/
reconify --versioncurl -L -o reconify https://github.com/ReconifyHQ/reconify/releases/latest/download/reconify-linux-amd64
chmod +x reconify
sudo mv reconify /usr/local/bin/
reconify --versionInvoke-WebRequest -Uri "https://github.com/ReconifyHQ/reconify/releases/latest/download/reconify-windows-amd64.exe" -OutFile "reconify.exe"Move reconify.exe into a directory on PATH, then open a new terminal and verify it:
reconify --versionOn Unix-like systems, prefer a user-writable directory already on PATH; use elevated privileges only when necessary. If there is no compatible release binary, use the Go installation below only after confirming that Go is installed.
go install github.com/reconifyhq/reconify/cmd/reconify@latestMake sure your Go binary directory is on PATH, then verify the installation:
reconify --version
reconify capabilitiesgit clone https://github.com/ReconifyHQ/reconify.git
cd reconify
go mod download
make build
./reconify --versionThe build uses linker flags for version and build time.
Install the agent skills
If you are driving Reconify from a coding agent, install the guided workflows too:
npx @reconifyhq/skillsThis installs the canonical workflows and tool-specific adapters into:
.agents/skills/ # tool-agnostic workflows
.claude/skills/ # Claude adapters
.codex/skills/ # Codex adapters
The package includes workflows for reconciliation, bootstrapping, configuration, CLI usage, debugging, performance, and CI. The canonical names are reconify-engine-*; the older reconify-* names remain compatibility adapters.
For an unfamiliar task, read AGENTS.md, llms.txt, and the reconify-engine-reconcile workflow. The installed CLI exposes its current machine-readable contract through:
reconify capabilities
reconify config schema
reconify schema result
reconify schema diagnosticReconify reads local files. Your config controls input paths through file_pattern, --left-file, and --right-file. When using the disk index backend, Reconify writes temporary SQLite-backed index files to index.spill_dir or the system temporary directory.
Create a configuration interactively:
reconify config initFor a hand-written configuration, map each source to its input columns and define the pair to compare:
version: 1
timezone: UTC
sources:
ledger:
file_pattern: "data/ledger/*.csv"
parser:
type: csv
date_col: Date
date_layout: "2006-01-02"
amount_col: Amount
multiplier: 100
ref_col: Reference
name_col: Description
psp:
file_pattern: "data/psp/*.csv"
parser:
type: csv
date_col: Date
date_layout: "2006-01-02"
amount_col: Amount
multiplier: 100
ref_col: Reference
name_col: Description
pairs:
ledger_vs_psp:
left: ledger
right: psp
date_window: "1d"
amount_tolerance_minor: 0
name_mode: noneThen validate and run it:
reconify config validate --config reconify.yaml
reconify reconcile --config reconify.yaml \
--pair ledger_vs_psp --format json --out result.jsonSee examples/reconify.yaml for a larger configuration with resource budgets, multiple counterpart sources, grouped passes, and parser options.
Sources can read CSV, JSON, NDJSON, XLSX, and XLSM files. Set type: auto or omit type to infer the parser from the file extension. Legacy .xls files are not supported; save them as .xlsx or .csv first.
Every input row is normalized into a transaction. Amounts are stored as integer minor units: with multiplier: 100, 1500.00 becomes 150000. Dates use Go layouts such as 2006-01-02, and the parser can apply a configured timezone, decimal separator, and thousands separator.
Sources may declare additional monetary columns under parser.financials. They use the same
normalization rules as amount_col and support field, fixed, percentage, fixed-plus-percentage,
and component-sum expectations:
financials:
gross_col: Gross
net_col: Net
fields: {fee: Fee, tax: Tax}
expectations:
fee:
percentage: {base: gross, rate: 1.5}
operation: subtract
tolerance_minor: 1Configured cells must be present, non-empty, and valid. Financial findings are independent from
transaction match classification. financial_effect_diff and settlement_diff are exception
events; mapped fields without an expectation produce informational financial_unchecked events.
Sources without financials retain the existing output behavior.
Optional mappings include:
ref_colfor the reference used by exact matching;group_colfor duplicate detection when several valid rows share a reference;name_colfor optional token matching; andcurrency_colfor currency metadata and monetary totals.
Run reconify inspect FILE --format json to inspect a file before choosing these mappings. Run reconify parse --config reconify.yaml --source SOURCE --file FILE to inspect normalized transactions.
The default pipeline matches one row on the left to one row on the right by reference, amount tolerance, and date window. A result is classified as:
matchwhen reference, amount, and date all satisfy the pair rules;amount_diffwhen the reference and date match but the amount is outside tolerance;timing_diffwhen the reference and amount match but the date is outside the window; orunmatched_left/unmatched_rightwhen no counterpart can be reconciled.
Optional matching passes include:
name_tokens_one_to_one, using Jaccard similarity for rows without a reference match;one_to_many, for one aggregate row against several rows sharing a group key;many_to_many, for groups on both sides whose totals should be compared; andsubset_sum, for a bounded subset of right-side rows whose amounts sum within tolerance.
Duplicate detection is an annotation pass. It reports duplicate groups but does not discard rows or prevent them from participating in matching.
Read the engine guide before changing matching behavior.
reconcile supports these formats:
| Format | Memory profile | Use when |
|---|---|---|
json |
Buffers the full result | You need a conventional JSON object or deterministic output |
json-stream |
Releases Go objects early, but bytes accumulate | You need a streaming JSON object |
ndjson |
O(1) result memory | You need a crash-safe event stream or large-file output |
csv |
O(1) result memory | You need a flat tabular export |
table |
Buffers the full result | You need a human-readable terminal view |
For large jobs, prefer ndjson or csv:
reconify reconcile --config reconify.yaml --pair ledger_vs_psp \
--format ndjson --out result.ndjson \
--progress --progress-out progress.ndjson \
--heartbeat-every 30sProgress and diagnostics go to stderr. Reconciliation data goes to stdout or --out. --progress-out must be different from --out.
Use --result-mode to control emitted item events without changing the classification counters or monetary totals in the summary:
| Mode | Emits |
|---|---|
all |
Every event; default |
exceptions_only |
Diffs, unmatched rows, duplicates, and ambiguous groups; clean matches are suppressed |
summary_only |
Only the final summary |
For audits, --audit adds file hashes, timestamps, tool version, and the pair configuration snapshot. Combine it with --audit-fixed-timestamp when byte-identical reruns are required and the format supports audit data.
The right-side index can use one of four backends:
memoryfor the fastest lookups and highest RAM use;diskfor lower RAM use with SQLite temporary files;autoto choose based on file size and configured resource budgets; orpartitionedfor bounded-memory CSV reconciliation with disk-backed partitions.
Configure the backend and safety budgets under index:
index:
backend: auto
spill_dir: /tmp/reconify
max_memory_mb: 8192
max_temp_disk_mb: 16384
partition_count: 0Budgets are safeguards, not throughput guarantees. Reconify reports the selected backend and its estimates in structured output. A run fails before completion if the selected strategy cannot satisfy its configured memory or temporary-disk budget.
Read the performance guide before changing streaming, indexing, or large-file behavior. Read partitioned parallelism before changing partition workers, result chunks, carry-forward, or queue behavior.
Use --agent for machine-readable defaults and --error-format json for structured diagnostics on stderr:
reconify reconcile --agent --error-format json \
--config reconify.yaml --pair ledger_vs_psp \
--format ndjson --out result.ndjsonExit codes are stable for scripts and CI:
| Code | Meaning |
|---|---|
0 |
Command succeeded |
1 |
Unexpected or internal error |
2 |
Configuration or validation error |
3 |
Reconciliation completed with unmatched rows when --fail-if-unmatched is set |
4 |
Reconciliation completed with exception events when --fail-if-exceptions is set; takes precedence over 3 |
The versioned schemas are available through reconify schema capabilities, reconify schema result, reconify schema diagnostic, reconify schema profile, reconify schema explanation, and reconify config schema.
The config and engine packages can be imported by other Go modules:
package main
import (
"github.com/reconifyhq/reconify/config"
"github.com/reconifyhq/reconify/engine"
)
func reconcile() error {
cfg, err := config.Load("reconify.yaml")
if err != nil {
return err
}
left, err := engine.Parse("ledger", "ledger.csv", cfg.Sources["ledger"].Parser)
if err != nil {
return err
}
right, err := engine.Parse("psp", "psp.csv", cfg.Sources["psp"].Parser)
if err != nil {
return err
}
_, err = engine.Reconcile("ledger_vs_psp", "ledger", "psp", left, right, cfg.Pairs["ledger_vs_psp"])
return err
}For large inputs, prefer the CLI streaming path or the engine streaming APIs documented in the engine package.
Prerequisite: Go 1.25.0 or newer.
go mod download
go run ./cmd/reconify --help
go test ./...
make buildBefore opening a pull request after a code change, run the repository quality gate:
make checkmake check covers module drift, formatting, dependency boundaries, linting, security scans, race-tested coverage, builds, and smoke benchmarks. make preflight is an alias.
See CONTRIBUTING.md for the pull request process. The documentation site lives under docs/, and the installable agent workflows are packaged under skills/.
Reconify is released under the MIT License.