Deterministic testing for n8n workflows.
Lint them, auto-generate branch-coverage tests, run them safely, and get a scorecard of exactly what's untested.
">https://img.shields.io/badge/node-%E2%89%A5%2020-3fb950.svg">
Install · Quick start · Why · Roadmap · Contributing
If FlowProof looks useful, a ⭐ helps others find it — and tells me to keep building the next phases.
Status: v0.1 shipped the linter; execution has since landed on
main. Available today: static analysis (flowproof lint), plusflowproof compileandflowproof run— a workflow's impure nodes are compiled out and it is executed for real, reporting which nodes ran and which never did. Branch-coverage scorecards, scenario generation, and record-and-replay are next (see the roadmap).
People build large n8n workflows (20–40+ nodes) and "test" them with a single happy-path run in the editor. That says almost nothing about production behavior. Real failures cluster where a smoke test never looks:
- Data-contract mismatches — a field is null and a downstream expression crashes.
- External services misbehaving — timeouts, 500s, 429s, malformed responses.
- Untested branches — an IF/Switch path that has never once executed.
- Non-idempotent side effects — a retry creates duplicate records or emails.
- Loop/pagination bugs — non-termination, mishandled empty batches.
n8n's own Evaluations feature targets AI workflows (scoring probabilistic LLM output). FlowProof fills the other gap: deterministic testing of ordinary business workflows — structural, data-contract, branch-coverage, and failure-injection testing. It's complementary, not competitive.
Published on npm under the @malharlakdawala/flowproof-* scope. The CLI package installs a command named flowproof:
# Global CLI
npm install -g @malharlakdawala/flowproof-cli
flowproof lint ./workflows/onboarding.json
# Or add the libraries to a project
npm install -D @malharlakdawala/flowproof-lint @malharlakdawala/flowproof-connectHitting
EACCESonnpm i -g? That's a global-npm-prefix permission issue on macOS/Linux, not a FlowProof problem — either fix the npm prefix or usepnpm add -g @malharlakdawala/flowproof-cli, which installs into your home directory.
Or build from source
Requirements: Node ≥ 20 and pnpm.
git clone https://github.com/malharlakdawala/flowproof.git
cd flowproof && pnpm install && pnpm build
pnpm flowproof lint examples/workflows/buggy.json# Lint an exported workflow JSON
flowproof lint ./workflows/onboarding.json
# Emit JUnit for CI
flowproof lint ./workflows/onboarding.json --format junit --out flowproof-results.xml
# Lint a workflow straight from a live n8n instance (Cloud or self-hosted)
export N8N_URL=https://your-tenant.app.n8n.cloud # or http://localhost:5678
export N8N_API_KEY=… # never printed to logs
flowproof lint --instance --workflow-id abc123
# Scaffold a config
flowproof initRun a workflow safely — every impure node is compiled out first, so no external service is contacted:
# First run writes a fixture template next to the workflow and stops
flowproof run ./workflows/onboarding.json
# → wrote onboarding.fixtures.json — fields the workflow actually reads are
# pre-filled as "TODO:<field>". Replace them and re-run.
flowproof run ./workflows/onboarding.json
# Onboarding — success
# ✓ Fetch Customer [0]:1 1 item(s)
# ✓ Check Plan Type [0]:1 [1]:0
# ✓ Send Welcome [0]:1 1 item(s)
#
# Never executed on this path
# Notify Sales
# Inspect exactly what will run, without running it
flowproof compile ./workflows/onboarding.jsonrun needs an n8n available (npm i -g n8n, or --n8n <path>). It never contacts a
real service: impure nodes are replaced with fixture emitters before execution, and
compilation fails loudly if any of them is unmocked.
Programmatic use:
import { connect } from '@malharlakdawala/flowproof-connect';
import { lintWorkflow, formatReport } from '@malharlakdawala/flowproof-lint';
const model = await connect.file('./onboarding.json');
const report = lintWorkflow(model);
console.log(formatReport(report, 'pretty'));
process.exit(report.errorCount > 0 ? 1 : 0);no-unhandled-io, dangling-error-output, hardcoded-secret, leftover-pindata (errors by default) · unsafe-expression, hardcoded-url, no-retry-on-flaky-io, loop-no-termination-guard, orphan-node, deprecated-node-version (warnings) · and more — all configurable and pluggable. See @malharlakdawala/flowproof-lint.
FlowProof is a pnpm monorepo. Each package is independently versioned and testable.
| Package | Status | Purpose |
|---|---|---|
@malharlakdawala/flowproof-core |
✅ v0.1 | Normalized WorkflowModel, graph + fork analysis, expression extraction, node-behavior registry |
@malharlakdawala/flowproof-connect |
✅ v0.1 | Load workflows from a JSON file or a live n8n instance |
@malharlakdawala/flowproof-lint |
✅ v0.1 | Static analysis engine + built-in rules |
@malharlakdawala/flowproof-cli |
✅ v0.1 | The CLI (installs the flowproof command) |
@malharlakdawala/flowproof-scenarios |
🚧 Phase 2 | Branch-coverage scenario generation + stress menu |
@malharlakdawala/flowproof-mock |
✅ partial | Compiles impure nodes into fixture emitters; fixture scaffolding |
@malharlakdawala/flowproof-runner |
✅ partial | LocalRunner + result parsing; Docker runner and egress guard pending |
@malharlakdawala/flowproof-assert |
🚧 Phase 3 | Matchers + coverage scorecard |
@malharlakdawala/flowproof-report |
🚧 Phase 4 | Terminal / HTML / JUnit reporters |
@malharlakdawala/flowproof-sdk |
🚧 Phase 4 | describe/it-style authoring API |
@malharlakdawala/flowproof-record |
🚧 Phase 5 | Record real executions → replayable tests |
Built in phases; each phase is independently shippable.
- Phase 0 — Scaffolding. ✅ Monorepo, tooling, CI, example workflows.
- Phase 1 — core + connect + lint. ✅ v0.1: a workflow linter. ← you are here
- Phase 2 — fork discovery + structural scenario generation.
flowproof generate. - Phase 3 — runner + mock + determinism + assert + scorecard. v0.2: generate + run + score.
Build order note: Phase 3 (execution) is being built before Phase 2 (generation). Generating scenarios before anything can run them means designing the
Scenariotype blind — the runner's real requirements should define it. Tracked in #17. Phase numbers are kept as-is so existing issue labels stay meaningful.
- Phase 4 — stress-scenario library + reporters + GitHub Action + SDK. v0.3: full core product.
- Phase 5 — record & replay + CloudRunner. v0.4: the flagship differentiators.
- Phase 6 — extensibility hardening, docs site, community node-behavior registry. v1.0.
pnpm install
pnpm build # build all packages
pnpm test # run the full test suite (Vitest)
pnpm typecheck # project-wide type check
pnpm format # prettierNode ≥ 20 and pnpm are required.
FlowProof is designed for community extension — new lint rules, matchers, runners, and especially node behaviors (n8n ships new nodes constantly). See CONTRIBUTING.md.
MIT © FlowProof contributors.