{"_id":"flownav","_rev":"8-e7a49ce41dfd431ade357a48c759abf8","name":"flownav","dist-tags":{"latest":"0.2.2"},"versions":{"0.0.0-stage":{"name":"flownav","version":"0.0.0-stage","_id":"flownav@0.0.0-stage","stub":true,"maintainers":[{"name":"omertdev","email":"omertur06@gmail.com"}],"dist":{"shasum":"1a03bc414b6cada6bf8b5e85e9a26da62f3f6257","tarball":"https://registry.npmjs.org/flownav/-/flownav-0.0.0-stage.tgz","fileCount":2,"integrity":"sha512-D15zpNrPDwvkwRFEJWaDnoCfM5lBzdJo4ggfgc3gegXlw0OipfolwohnMAhkJ4FNVAQsDW7pSLsHvPhyIZNW9w==","signatures":[{"sig":"MEUCIApFHkeBygdSQfBIovOECYy0RHgSJt5cdXqxa9d2e307AiEAqWNzPa3TDGmI78VxUBRBasF4HJAKFoaWqivKlzam/6E=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":329},"_npmUser":{"name":"omertdev","email":"omertur06@gmail.com"},"description":"Temporary package placeholder for staged publishing","directories":{}},"0.1.0":{"name":"flownav","version":"0.1.0","keywords":["n8n","workflow","graph","mcp","cli"],"author":{"name":"Omer Turkenits"},"license":"MIT","_id":"flownav@0.1.0","maintainers":[{"name":"omertdev","email":"omertur06@gmail.com"}],"homepage":"https://github.com/OmerTurkenits/flownav#readme","bugs":{"url":"https://github.com/OmerTurkenits/flownav/issues"},"bin":{"fnav":"dist/cli.js","flownav":"dist/cli.js"},"dist":{"shasum":"fa820f8133df55f9cc9d1cff51eb421e638fa111","tarball":"https://registry.npmjs.org/flownav/-/flownav-0.1.0.tgz","fileCount":21,"integrity":"sha512-g2M45EWooG+/yIxKL40jAyscS6CYOOWb4zRk0Ikidd6lD2h46dLEnLaUHc1FvEykBOXGzSw1ZUrl0zAXVt6vLQ==","signatures":[{"sig":"MEUCIQCJt9DMqx4Fx1hq+eolCpCj2dl9+Qj+leKgZ6SeeV0bfQIgISNomjNVmsBJZjGOQR3lofR4ixPSArBHxR1vCPLgpE4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQClv/F/mYvMlzw19AGzntmgVjYiwDNcwokhFhqvomJ5gQIhALavxFIP+LpvRtZzPT7a7pbeFW5E6sUUD7SaN7jOfVkl","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":128567},"type":"module","engines":{"node":">=22.12"},"gitHead":"7dacb356f87b9609df54740a3f995d05409c9a06","scripts":{"test":"npm run build && node --test test/*.test.mjs","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"omertdev","email":"omertur06@gmail.com"},"repository":{"url":"git+https://github.com/OmerTurkenits/flownav.git","type":"git"},"_npmVersion":"10.9.0","description":"Typed node graph for n8n workflows: explain, path, affected (rename/delete safety), checks, and an MCP server so agents navigate workflows with far fewer tokens.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.6.6"},"_npmOperationalInternal":{"tmp":"tmp/flownav_0.1.0_1793881426471_0.35166120030153014","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"flownav","version":"0.1.1","keywords":["n8n","workflow","graph","mcp","cli"],"author":{"name":"Omer Turkenits"},"license":"MIT","_id":"flownav@0.1.1","maintainers":[{"name":"omertdev","email":"omertur06@gmail.com"}],"homepage":"https://github.com/OmerTurkenits/flownav#readme","bugs":{"url":"https://github.com/OmerTurkenits/flownav/issues"},"bin":{"fnav":"dist/cli.js","flownav":"dist/cli.js"},"dist":{"shasum":"03f1ec56f5b1ea4c04cf68814cf35f31d337463b","tarball":"https://registry.npmjs.org/flownav/-/flownav-0.1.1.tgz","fileCount":22,"integrity":"sha512-gCGeEB0+IP67wkvjPH+WKY3qglNJ2N3tMV3O//SezlM/99cadQIF5Gs1P0H/8UWZ8gJdkJtwBQa2XijpHzBVKg==","signatures":[{"sig":"MEUCIGzrGH2sRPZt3ysJEj2/sS4D3hKfiANk8Mx3Htnn1IZ7AiEA+8A8EnuK+hMTqwxn9pP54kMBYHI5IebFloUWiJzFw6c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIELHfabjMiupYpNGFfVi9s210UUwAsqP/+ujKOFWB+aiAiEAkSSj8HXf/RtTXQxOTm07rLBSDGEPTatNrZ73lKp5fHg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":139784},"type":"module","engines":{"node":">=22.12"},"gitHead":"f8ae3457d2bb67b93106b12c38413a9a80002e62","scripts":{"test":"npm run build && node --test test/*.test.mjs","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"omertdev","email":"omertur06@gmail.com"},"repository":{"url":"git+https://github.com/OmerTurkenits/flownav.git","type":"git"},"_npmVersion":"10.9.0","description":"Typed node graph for n8n workflows: explain, path, affected (rename/delete safety), checks, and an MCP server so agents navigate workflows with far fewer tokens.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.6.6"},"_npmOperationalInternal":{"tmp":"tmp/flownav_0.1.1_1793884266075_0.00549981674538691","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"flownav","version":"0.1.2","keywords":["n8n","workflow","graph","mcp","cli"],"author":{"name":"Omer Turkenits"},"license":"MIT","_id":"flownav@0.1.2","maintainers":[{"name":"omertdev","email":"omertur06@gmail.com"}],"homepage":"https://github.com/OmerTurkenits/flownav#readme","bugs":{"url":"https://github.com/OmerTurkenits/flownav/issues"},"bin":{"fnav":"dist/cli.js","flownav":"dist/cli.js"},"dist":{"shasum":"1144b84b10d8f89a29bda99522340a72658027d5","tarball":"https://registry.npmjs.org/flownav/-/flownav-0.1.2.tgz","fileCount":22,"integrity":"sha512-SsbTXJRTfOq1jBUnaISAXnzbEzVraxAQQw5hZA3FmoqK2Sz21Yu0tjcLnBdtQaBTyFhkATBbEHnvcfOj2IE6wA==","signatures":[{"sig":"MEYCIQDW/nPGyX0csvBQN1JcI386lwvQECEiVR5MllNNBzMYZgIhALrqjUnfl8O9wenUW+PVUb8oqa65Hc5rK2MBOc3KZ8gf","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCICyO4TAZ5Zkx9tDo/2rnp/HD6AVo25AzXran3FrDiBrRAiEA5QOOYEFgePE7tiR5t4Pi89v0+PayqaWc+R+q5DbH2zY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":139779},"type":"module","engines":{"node":">=22.12"},"gitHead":"e1a9f466f81b238662cbd3ebaa5918167a5675f6","scripts":{"test":"npm run build && node --test test/*.test.mjs","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"omertdev","email":"omertur06@gmail.com"},"repository":{"url":"git+https://github.com/OmerTurkenits/flownav.git","type":"git"},"_npmVersion":"10.9.0","description":"Typed node graph for n8n workflows: explain, path, affected (rename/delete safety), checks, and an MCP server so agents navigate workflows with far fewer tokens.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.6.6"},"_npmOperationalInternal":{"tmp":"tmp/flownav_0.1.2_1793887503196_0.6629858931563006","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"flownav","version":"0.1.3","keywords":["n8n","workflow","workflow-automation","graph","mcp","model-context-protocol","ai","ai-agents","claude","rename","static-analysis","cli"],"author":{"name":"Omer Turkenits"},"license":"MIT","_id":"flownav@0.1.3","maintainers":[{"name":"omertdev","email":"omertur06@gmail.com"}],"homepage":"https://github.com/OmerTurkenits/flownav#readme","bugs":{"url":"https://github.com/OmerTurkenits/flownav/issues"},"bin":{"fnav":"dist/cli.js","flownav":"dist/cli.js"},"dist":{"shasum":"396f07b808966eeea9c70d73f7005902650ed4a5","tarball":"https://registry.npmjs.org/flownav/-/flownav-0.1.3.tgz","fileCount":22,"integrity":"sha512-q/ZH2IyKMtWQ6QDJaYJZtjPA8l/i6/m7CBSHHt1QQtTT3yxtRTjU+K9Wm+A4xs4qrrcG92POFZBeeBUjrL08bA==","signatures":[{"sig":"MEQCIBIMi4thFhfGYy70cokPAxp8URz75iuFHhayvBTu+ZigAiBmpSQEuz3mQ7QFufbQxfAV4EZeVJW8CQB3GWhF4uGnzg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIDBQwD2s6MW6REoxypPC5CsePfIgynbZpV+PuSZnq1SFAiEAhuyCb+96dKQKtPVwMWTC9QWMlGWP4oHtdCumv49L5us=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":144974},"type":"module","engines":{"node":">=22.12"},"gitHead":"671d1f392f7205b27269ee442428e966bf3172ce","scripts":{"test":"npm run build && node --test test/*.test.mjs","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"omertdev","email":"omertur06@gmail.com"},"repository":{"url":"git+https://github.com/OmerTurkenits/flownav.git","type":"git"},"_npmVersion":"10.9.0","description":"See what references an n8n node before you rename it. A typed graph of your workflows with a CLI and an MCP server, so AI agents read a few lines instead of the whole workflow JSON.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.6.6"},"_npmOperationalInternal":{"tmp":"tmp/flownav_0.1.3_1794079210170_0.04668970390491045","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"flownav","version":"0.2.0","keywords":["n8n","workflow","workflow-automation","graph","mcp","model-context-protocol","ai","ai-agents","claude","rename","static-analysis","cli"],"author":{"name":"Omer Turkenits"},"license":"MIT","_id":"flownav@0.2.0","maintainers":[{"name":"omertdev","email":"omertur06@gmail.com"}],"homepage":"https://github.com/OmerTurkenits/flownav#readme","bugs":{"url":"https://github.com/OmerTurkenits/flownav/issues"},"bin":{"fnav":"dist/cli.js","flownav":"dist/cli.js"},"dist":{"shasum":"ebea47e48c0d785918c994d037f967a3c362aa9f","tarball":"https://registry.npmjs.org/flownav/-/flownav-0.2.0.tgz","fileCount":24,"integrity":"sha512-9BsnvqGPcP+TlX3TSssdvQlZes0hyl+CgiknDr25q7LO9sLydYdL6BWXTHBSukoexjrNPgh5q1xYSonA87AeKQ==","signatures":[{"sig":"MEQCIFnWtCqK/lslybW7PfxTWVRevmQTsIosxHsFeIgMYafrAiABmzW7AqVghQ22M8PZYeVLPpFZtm3UomLEdkUcXgSQTQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIHJKIKABeZJa4+1dgZxJSmA/YFA1pDRLssFzVlNKSob2AiEAr+OwxYxQnTo9qkTjPdx2o3Qetm+DTVirLotLIxvr5TQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":168237},"type":"module","engines":{"node":">=22.12"},"gitHead":"5d661a90d80e11f33d3221c091cf375a483c8158","scripts":{"test":"npm run build && node --test test/*.test.mjs","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"omertdev","email":"omertur06@gmail.com"},"repository":{"url":"git+https://github.com/OmerTurkenits/flownav.git","type":"git"},"_npmVersion":"10.9.0","description":"See what references an n8n node before you rename it. A typed graph of your workflows with a CLI and an MCP server, so AI agents read a few lines instead of the whole workflow JSON.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.6.6"},"_npmOperationalInternal":{"tmp":"tmp/flownav_0.2.0_1794079848262_0.40152530820175125","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"flownav","version":"0.2.1","keywords":["n8n","workflow","workflow-automation","graph","mcp","model-context-protocol","ai","ai-agents","claude","rename","static-analysis","cli"],"author":{"name":"Omer Turkenits"},"license":"MIT","_id":"flownav@0.2.1","maintainers":[{"name":"omertdev","email":"omertur06@gmail.com"}],"homepage":"https://github.com/OmerTurkenits/flownav#readme","bugs":{"url":"https://github.com/OmerTurkenits/flownav/issues"},"bin":{"fnav":"dist/cli.js","flownav":"dist/cli.js"},"dist":{"shasum":"056c6e4c4e248998be409d67075fb76eb315c0eb","tarball":"https://registry.npmjs.org/flownav/-/flownav-0.2.1.tgz","fileCount":24,"integrity":"sha512-sYJyqvKPEizVSkUeoGWVDYc7Xx+RxYs6ZbWvwE79gw7zZ7txADFY8qtb4rw4s9077al+4w1vMiy8/rGGU/xeDA==","signatures":[{"sig":"MEUCIGFbCs4lBa69QD8qM8zEzGujRAuEyE776m1o/afXAVHYAiEA/Cl1psAd+ltjD50LtrGWmvqNcEVpi1lBlC8SBaMeFLw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIQDBO00KlF2diOt2G21XE0clpqWlM6bEPo+pNHgjkbCsUQIgRHWvc3P2E9hoL25lWBzMQKeObshpORVX0B1IKcsGv74=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":170367},"type":"module","engines":{"node":">=22.12"},"gitHead":"d1b920d000d27056121d6d7f16d4a56c2d9668c8","scripts":{"test":"npm run build && node --test test/*.test.mjs","build":"tsc","prepublishOnly":"npm run build"},"_npmUser":{"name":"omertdev","email":"omertur06@gmail.com"},"repository":{"url":"git+https://github.com/OmerTurkenits/flownav.git","type":"git"},"_npmVersion":"10.9.0","description":"See what references an n8n node before you rename it. A typed graph of your workflows with a CLI and an MCP server, so AI agents read a few lines instead of the whole workflow JSON.","directories":{},"_nodeVersion":"26.1.0","dependencies":{"commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.6.6"},"_npmOperationalInternal":{"tmp":"tmp/flownav_0.2.1_1794127223929_0.8523529554291439","host":"s3://npm-registry-packages-npm-production"}},"0.2.2":{"_id":"flownav@0.2.2","bin":{"fnav":"dist/cli.js","flownav":"dist/cli.js"},"bugs":{"url":"https://github.com/OmerTurkenits/flownav/issues"},"dist":{"shasum":"f69f71f28f3d70ba8d238eadcc94eaa6944452ff","tarball":"https://registry.npmjs.org/flownav/-/flownav-0.2.2.tgz","fileCount":24,"integrity":"sha512-c/TTflKADN6kMpxJd0CcuSdqT1mEpk0E94ZBhWrAuyOJ7EMpKj7UguM+meWk5m1FLYyva3DR5HkM/9xl8TqG5A==","signatures":[{"sig":"MEYCIQCcFwDSmO/0Du7aC6i31PvbCJ33goqJOByh1s1rR6cT5wIhAKJHR+HHTqj76YKdSobpPohRNH76DAALYOsLDg0CdRFU","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD+UUVGIcfybDjG1J/BF3/QXHKQnbcvJghN5cADPDG5rQIgb/24U0+FWW/L8Y+qNpPJdom+Pdf71Ge0HlItVRiyAMU="}],"unpackedSize":170415},"name":"flownav","type":"module","author":{"name":"Omer Turkenits"},"engines":{"node":">=22.12"},"gitHead":"5cf2580b6cc87c1d50f7977c1880a76057368f4f","license":"MIT","mcpName":"io.github.OmerTurkenits/flownav","scripts":{"test":"npm run build && node --test test/*.test.mjs","build":"tsc","prepublishOnly":"npm run build"},"version":"0.2.2","_npmUser":{"name":"omertdev","email":"omertur06@gmail.com"},"homepage":"https://github.com/OmerTurkenits/flownav#readme","keywords":["n8n","workflow","workflow-automation","graph","mcp","model-context-protocol","ai","ai-agents","claude","rename","static-analysis","cli"],"repository":{"url":"git+https://github.com/OmerTurkenits/flownav.git","type":"git"},"_npmVersion":"10.9.0","description":"See what references an n8n node before you rename it. A typed graph of your workflows with a CLI and an MCP server, so AI agents read a few lines instead of the whole workflow JSON.","directories":{},"maintainers":[{"name":"omertdev","email":"omertur06@gmail.com"}],"_nodeVersion":"26.1.0","dependencies":{"commander":"^15.0.0"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^7.0.2","@types/node":"^26.6.6"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/flownav_0.2.2_1794243369737_0.8605138916113723"}}},"time":{"created":"2026-11-05T12:22:10.255Z","modified":"2026-11-09T16:56:10.045Z","0.0.0-stage":"2026-11-05T12:22:10.255Z","0.1.0":"2026-11-05T12:23:46.630Z","0.1.1":"2026-11-05T13:11:06.186Z","0.1.2":"2026-11-05T14:05:03.294Z","0.1.3":"2026-11-07T19:20:10.261Z","0.2.0":"2026-11-07T19:30:48.350Z","0.2.1":"2026-11-08T08:40:24.116Z","0.2.2":"2026-11-09T16:56:09.844Z"},"bugs":{"url":"https://github.com/OmerTurkenits/flownav/issues"},"author":{"name":"Omer Turkenits"},"license":"MIT","homepage":"https://github.com/OmerTurkenits/flownav#readme","keywords":["n8n","workflow","workflow-automation","graph","mcp","model-context-protocol","ai","ai-agents","claude","rename","static-analysis","cli"],"repository":{"url":"git+https://github.com/OmerTurkenits/flownav.git","type":"git"},"description":"See what references an n8n node before you rename it. A typed graph of your workflows with a CLI and an MCP server, so AI agents read a few lines instead of the whole workflow JSON.","maintainers":[{"name":"omertdev","email":"omertur06@gmail.com"}],"readme":"# flownav\n\n[![CI](https://github.com/OmerTurkenits/flownav/actions/workflows/ci.yml/badge.svg)](https://github.com/OmerTurkenits/flownav/actions/workflows/ci.yml)\n\n**A typed node graph for n8n workflows, so an AI agent (or you) can navigate a workflow without reading raw JSON.**\n\nflownav turns exported workflow JSON, or a live n8n instance, into a queryable graph: connections, AI agent tools and models, expression references between nodes, cross-workflow calls, credentials and shared resources. An agent asks for one node's card or \"what breaks if I rename this?\" and gets a few lines back instead of thousands of lines of JSON.\n\nIt is read-only against n8n. Inspired by [graphify](https://github.com/safishamsi/graphify), which does the same for code.\n\n## Why\n\n- **Token cost.** A real workflow export is large and mostly noise. `flownav explain \"Node\"` is about ten lines.\n- **The rename gap.** The n8n editor tries to rewrite `$('Old Name')` references when you rename a node, but community reports describe that as imperfect, and references inside Code nodes' JavaScript are reported not to be rewritten. Renames that don't go through the editor (the API, edited JSON, an AI agent changing a workflow) don't get that rewrite step at all, and deleting a node never fixes the references to it. A broken reference fails silently. `flownav affected \"Old Name\" --rename` lists exactly which nodes and parameters reference the node by name, so you can check them before and after you change anything.\n- **Cross-workflow structure.** Sub-workflows, agent tool workflows, error workflows and webhook-to-webhook calls become edges, so you can ask what calls what across your whole instance.\n\n## Install\n\nNeeds Node 22.12 or newer.\n\n```bash\nnpm install -g flownav      # then use: flownav ...   (or the short alias: fnav)\n# or without installing:\nnpx flownav --help\n```\n\n## Try it in a minute\n\nThe repo ships three small example workflows in [`examples/`](examples). They contain deliberately planted problems.\n\n```bash\ngit clone https://github.com/OmerTurkenits/flownav && cd flownav\nflownav build examples        # -> .flownav/graph.json and .flownav/WORKFLOW_REPORT.md\nflownav check\nflownav view --open           # interactive graph in your browser\n```\n\n## An example graph\n\n`examples/orders.json` is a webhook that routes orders, calls a sub-workflow, has an AI agent with a tool, a loop, and a Code node with problems. This is what `flownav diagram wf-orders` draws (GitHub renders it):\n\n```mermaid\nflowchart LR\n  n0([\"Order Webhook<br/>Webhook POST /orders (responseNode)\"])\n  n1[\"Normalize\"]\n  n2{\"Is Large Order\"}\n  n3[\"Notify Sales\"]\n  n4[\"Save Order\"]\n  n5[\"Enrich\"]\n  n6[\"Reply\"]\n  n7{{\"Support Agent\"}}\n  n8[\"Chat Model\"]\n  n9[\"Lookup Order\"]\n  n10[/\"Loop Orders\"/]\n  n11[\"Ping Self\"]\n  n12[\"Orphan Code\"]\n  n13([\"Chat Trigger\"])\n  n14([\"Nightly\"])\n  n0 --> n1\n  n1 --> n2\n  n2 -->|\"true\"| n3\n  n2 -->|\"false\"| n4\n  n3 --> n6\n  n4 --> n5\n  n5 --> n6\n  n8 -.->|\"ai_languageModel\"| n7\n  n9 -.->|\"ai_tool\"| n7\n  n10 -->|\"loop\"| n11\n  n11 --> n10\n  n13 --> n7\n  n14 --> n10\n  n1 -.->|\"reads email\"| n3\n  n5 -.->|\"reads customerId\"| n6\n  n3 -.->|\"reads ok\"| n6\n  n1 -.->|\"reads email\"| n12\n  n11 ==>|\"self\"| n0\n```\n\nSolid arrows are connections (with branch labels such as `true`/`false`/`loop`). Dotted arrows are AI sub-nodes and expression reads (`reads email` means the node uses the `email` field of another node by name). Thick arrows are cross-workflow or webhook calls. Triggers are rounded, IF/Switch are diamonds, agents are hexagons.\n\nWith `--collapse` you get one box per workflow, which is the readable view for many workflows (`flownav diagram --collapse`):\n\n```mermaid\nflowchart LR\n  w0[\"Enrich customer<br/>3 nodes\"]\n  w1[\"Error handler<br/>2 nodes\"]\n  w2[\"Order intake<br/>15 nodes\"]\n  w2 ==>|\"2× calls\"| w0\n  w2 ==>|\"on error\"| w1\n```\n\n## Example queries\n\nEverything below is real output from the examples.\n\n**A node's card**\n\n```text\n$ flownav explain \"Is Large Order\"\nwf-orders:Is Large Order  [if v2]  (group \"Intake\")\n  IF 1 condition(s)\ninputs:\n  ← wf-orders:Normalize\noutputs:\n  [0 true] → wf-orders:Notify Sales\n  [1 false] → wf-orders:Save Order\n```\n\n**What breaks if I rename this node?**\n\n```text\n$ flownav affected \"Normalize\" --rename\nwf-orders:Normalize — impact of rename\n2 node(s) reference \"Normalize\" by name and will break unless their expressions are rewritten:\n  × wf-orders:Notify Sales uses {email}  in text\n      text: {{ 'Big order from ' + $('Normalize').item.json.email }}\n  × wf-orders:Orphan Code uses {email}  in jsCode\n      jsCode: L1: const row = $('Normalize').first().json.email;\n```\n\n**A path, even across workflows**\n\n```text\n$ flownav path \"Save Order\" \"Shape\"\n1 shortest path(s), 4 hop(s):\n#1 wf-orders:Save Order —main→ wf-orders:Enrich —calls EXTRACTED→ wf-enrich:When called —main→ wf-enrich:Fetch CRM —main→ wf-enrich:Shape\n```\n\n**An AI agent as a card**\n\n```text\n$ flownav explain \"Support Agent\"\nwf-orders:Support Agent  [agent v1.7]\n  AI Agent\ninputs:\n  ← wf-orders:Chat Model [ai_languageModel] (sub-node)\n  ← wf-orders:Lookup Order [ai_tool] (sub-node)\n  ← wf-orders:Chat Trigger\noutputs:\n  (none)\nagent card:\n  ai_languageModel: wf-orders:Chat Model\n  ai_tool: wf-orders:Lookup Order\n```\n\n**Who calls this workflow?**\n\n```text\n$ flownav callers wf-enrich\nEnrich customer (wf-enrich) is called by 2 edge(s):\n  wf-orders:Enrich  (calls EXTRACTED)\n  wf-orders:Lookup Order  (calls:tool EXTRACTED)\n```\n\n**Health checks**\n\n```text\n$ flownav check\n6 finding(s)\n  ERROR dead-refs          [wf-orders] Orphan Code reads \"Deleted Step\", which does not exist\n  WARN  fragile-reads      [wf-orders] Orphan Code reads $('Normalize') but Normalize is not upstream via main; it may not have run\n  WARN  unreachable        [wf-orders] Orphan Code is not reachable from any trigger\n  INFO  cycles             [wf-orders] loop (Loop Over Items): Ping Self <-> Loop Orders\n  INFO  dead-ends          [wf-orders] Loop Orders output [0 done] is not connected\n  INFO  no-error-handler   [wf-enrich] Enrich customer has no error workflow and no node-level error handling\n```\n\n`check` exits with code 1 when it finds an `ERROR`. Use `--fail-on warn` (or `info`) to fail on less severe findings, `--fail-on none` to always exit 0, and `--only a,b` to run just some checks. See [Use it in CI](#use-it-in-ci).\n\n## Using it with an AI agent\n\n```bash\nflownav install claude --mcp     # writes .claude/skills/flownav/SKILL.md and .mcp.json\n```\n\nThis installs a skill that tells the agent to query flownav before reading, renaming or deleting nodes, and registers an MCP server (`flownav serve`, stdio) exposing `flownav_scan`, `explain`, `neighbors`, `path`, `find`, `affected`, `callers`, `calls`, `uses`, `check`, `read` and `report`. The server reads `.flownav/graph.json` from the working directory (or `--graph <file>`) and reloads it when the file changes. The skill works without MCP too, as long as the agent can run shell commands.\n\nA typical rename: the agent runs `scan` to find the workflow id, then `affected \"wf-orders:Normalize\"`, edits the listed expressions together with the rename using whatever tool it has for editing n8n, syncs again, and runs `check` to confirm nothing dangles. flownav does not write to n8n; it tells the agent what is safe.\n\n### When the request is not specific\n\nTool replies are written for an agent to act on. If a name matches several nodes or workflows, flownav refuses to pick one and says so:\n\n```text\n$ flownav explain order\nerror: \"order\" matches 5 nodes. Do not guess: ask the user which one they mean. Then use the workflow:node form.\n  1. Order intake › Order Webhook  [webhook]  use: wf-orders:Order Webhook\n       Webhook POST /orders (responseNode) · group \"Intake\" · starts the workflow\n  2. Order intake › Is Large Order  [if]  use: wf-orders:Is Large Order\n       IF 1 condition(s) · group \"Intake\" · after: Normalize\n  3. Order intake › Save Order  [googleSheets]  use: wf-orders:Save Order\n       googleSheets: append · group \"Intake\" · after: Is Large Order\n  ...\n```\n\nEach candidate carries one line of context (what the node does, its sticky-note group, and what feeds it or what it plugs into), so the agent can ask a specific question instead of \"which one?\". Workflow candidates show their trigger types and whether they are active. If a partial name matches exactly one node, it resolves but the reply starts with a `NOTE:` asking the agent to confirm with the user before changing anything. To search a family of workflows, use `flownav find --match \"<part of workflow name>\" --name \"<part of node name>\"` (`--name` searches node names only; `--text` also searches parameters and code). The installed skill tells the agent to stop and ask in these cases. How reliably an agent follows that depends on the agent.\n\n## Reading code in small pieces\n\nflownav normally returns structure (cards, paths, references), not code. When an agent (or you) needs to read a large Code node, `read` returns it in small, capped slices instead of the whole node:\n\n```text\n$ flownav read \"Orphan Code\"                 # default: an outline\nwf-orders:Orphan Code · jsCode · 3 line(s), 127 chars\nlongest line: 46 chars\nfunctions: none found\nnode references:\n  Normalize  line 1  {email}\n  Deleted Step  line 2  {x}\nnext: grep for a name, or read a range with lines\n\n$ flownav read \"Orphan Code\" --grep normalize\nwf-orders:Orphan Code · jsCode · 3 line(s), 127 chars\n> 1: const row = $('Normalize').first().json.email;\n  2: const gone = $('Deleted Step').first().json.x;\n  3: return [{ json: { row, gone } }];\n1 of 1 matching line(s) shown\n\n$ flownav read \"Orphan Code\" --lines 2-3\n```\n\n- **Outline** (the default): size, the longest line, function names, and which nodes the code references, all with line numbers, so you can pick a slice without reading blindly.\n- **`--grep <pattern>`**: matching lines with context (`--context`, default 2, up to 10), overlapping windows merged, up to `--max` matches (default 20). Literal and case-insensitive by default; `--regex` and `--case` change that.\n- **`--lines 120-180`** (also `120` or `120-`): numbered lines, with a hint for the next slice. An open-ended range returns 60 lines.\n- **Long lines:** a line over 240 characters is shown windowed, and `--cols 241-480` reads inside it, which is what you need for minified or generated code.\n- **`--param`** reads another text parameter (for example an HTML field); without it, `read` uses `jsCode`, `pythonCode`, `functionCode` or `code`.\n\nEvery reply is capped at about 6,000 characters whatever you ask for, and secrets in the code are redacted (key-like assignments such as `apiKey = \"...\"`, and token shapes such as `Bearer ...`; this is best-effort, not a guarantee). `read` takes the code from your exported files, or does one read-only `GET` of that workflow from your instance (it needs the API key in the environment variable named by your profile, `N8N_API_KEY` by default). `--from <folder>` reads from a folder of exports instead. If the workflow changed since the graph was built, the reply starts with a warning and shows the current source. The MCP tool `flownav_read` does the same and cannot be pointed at other folders.\n\n## Seeing the graph\n\n```bash\nflownav view --open                       # interactive HTML: pan, zoom, search, click a node for its card\nflownav view \"My workflow\" --open         # one workflow\nflownav view --match Order --collapse     # every workflow whose name contains \"Order\", one box each\nflownav view --focus \"Some node\" --depth 2\nflownav diagram --match Order --out orders.md   # Mermaid text instead\n```\n\n`view` writes a single self-contained HTML file (no CDN, no network requests, no external fonts). Click a node to dim everything else and see its card and connections; tick or untick edge kinds to declutter. `--collapse` draws one box per workflow with the calls between them. The files contain your node names and webhook paths, so treat them like the workflows themselves.\n\n## Live n8n\n\n```bash\nexport N8N_API_KEY=...                       # read from the environment, never written to disk or logs\nflownav profile add prod --url https://n8n.example.com\nflownav sync --profile prod --executions\nflownav status --check                       # is the graph stale?\n```\n\nOnly `GET /api/v1/...` requests are ever sent (`X-N8N-API-KEY` header, cursor pagination). Syncs are incremental: a workflow whose `updatedAt` and `versionId` are unchanged is reused, and `--full` forces a refetch. A read-only API key is enough. Profiles store the URL and the *name* of the environment variable holding the key, never the key.\n\n## What it models\n\nEdges point in the direction of data or control flow and carry a `kind`, an optional `label`, optional `fields`, and a `confidence`.\n\n| kind | meaning | confidence |\n|---|---|---|\n| `main` | connection; labels `true`/`false`, `case N` or the rule's output name, `loop`/`done`, `error` | EXPLICIT |\n| `capability` | `ai_*` sub-node (model, tool, memory) into its agent | EXPLICIT |\n| `reads` | an expression or Code node reads another node, with field names (`$('X')`, `$node[\"X\"]`, `$items(\"X\")`) | EXTRACTED |\n| `calls` | Execute Workflow / agent tool workflow into the callee's trigger | EXTRACTED by id, INFERRED by name |\n| `on_error` | `settings.errorWorkflow` | EXTRACTED |\n| `webhook_calls` | HTTP Request to `/webhook/<path>` matched to a Webhook node | INFERRED |\n| `responds_via` | Webhook to a reachable Respond to Webhook | EXTRACTED |\n| `uses` | node to credential (by id, never the secret) | EXPLICIT |\n| `reads_resource` / `writes_resource` / `uses_resource` | same sheet, table, channel, `$env` or `$vars` across nodes | INFERRED / EXTRACTED |\n\nDetails that matter:\n\n- Only `{{ }}` blocks inside `=` strings, and the source of Code nodes, are scanned for references. String literals and comments inside code are ignored, so text such as browser JavaScript held in a string (`$('form')`) is not mistaken for a node reference.\n- In Code nodes, `$(n)` where `n` iterates a literal list (`for (const n of [\"A\",\"B\"])`, `.forEach`, `const n = \"A\"`) yields INFERRED `reads` edges to each name.\n- Other dynamic references (computed node names, runtime workflow ids, embedded or URL sub-workflows) are recorded as *unresolved* and listed in the report. They are never guessed.\n- Sticky notes are not nodes; nodes inside a sticky's rectangle get its title as their group.\n\n## Commands\n\n```text\nflownav build <path>                  files -> graph + report         (--out dir, --no-report)\nflownav sync [--profile p | --url u]  live n8n, incremental           (--active --tags --name --project --executions --full)\nflownav status [--check]              what is loaded; --check compares with the instance\nflownav profile add|list|remove       base URL + the NAME of the env var holding the key\nflownav report | scan                 full report | compact inventory\nflownav explain <node>\nflownav neighbors <node> [--depth N --dir in|out|both --kinds a,b]\nflownav path <A> <B> [--max N --kinds a,b]\nflownav find [--type --cred --text --name --resource --workflow --match --disabled --trigger]\nflownav affected <node> --rename|--delete|--schema|--behavior\nflownav callers <workflow> | calls <workflow> | uses --cred <c>\nflownav read <node> [--outline | --grep p [--regex --case --context n --max n] | --lines a-b]\n                    [--param p --cols a-b --from path]     read part of a Code node, capped and redacted\nflownav stats [--from path]           measure raw JSON tokens against flownav replies on your workflows\nflownav check [--only a,b] [--fail-on error|warn|info|none]\n                                      checks: fragile-reads, dead-refs, cycles, unreachable, dead-ends, no-error-handler, webhook-no-respond\nflownav view [workflow] [--match text --collapse --focus <node> --depth N --out file.html --open]\nflownav diagram [workflow] [--match text --collapse --focus <node> --depth N --no-reads --dir LR|TD --out file.md]\nflownav diff old.json new.json        what changed between two graphs\nflownav install claude [--global] [--mcp]\nflownav serve                         MCP server on stdio\n```\n\nGlobal options: `--graph <file>` and `--format text|json`. Nodes are addressed as `Name` or `workflow:Name` (workflow id or name).\n\n## Use it in CI\n\n`flownav check` exits with code 1 when it finds an error, and `--only dead-refs` limits it to broken references (a node that reads a node that no longer exists, a connection to a missing node, a call to a missing workflow). Two ways to feed it, as a GitHub Actions example:\n\n```yaml\nname: n8n workflow check\non: [pull_request]\njobs:\n  flownav:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - uses: actions/setup-node@v4\n        with:\n          node-version: 22\n      # Option A: workflow JSON exported into the repo (e.g. ./workflows)\n      - run: npx -y flownav build ./workflows\n      # Option B: a live instance with a read-only API key stored as a secret\n      # - run: npx -y flownav sync --url ${{ secrets.N8N_URL }}\n      #   env:\n      #     N8N_API_KEY: ${{ secrets.N8N_API_KEY }}\n      - run: npx -y flownav check --only dead-refs\n```\n\nFor a manual \"before I touch this\" step, run `flownav affected \"Node\" --rename` instead. flownav is static analysis: it can only gate on what it can see, so references built at runtime are reported as unresolved and are not failures.\n\n## Privacy and safety\n\n- Read-only against n8n: the only network method is `GET`.\n- `pinData` (sample execution data) is dropped on load and never stored.\n- String parameters are redacted before being kept for search: values under secret-looking keys (`apiKey`, `token`, `password`, `Authorization`, ...) and known token shapes (Bearer, `sk-...`, GitHub, Slack, AWS, JWT).\n- Credentials are recorded by id and type only.\n- `flownav read` is the one command that returns code. It redacts key-like assignments and token shapes (best-effort), caps every reply, and for live graphs makes a single read-only `GET` of the one workflow it needs.\n- Execution data is not fetched; `--executions` records only the last status per workflow.\n- `.flownav/` holds your graph and is git-ignored by this repo. Don't commit it or share the HTML views if your workflows are sensitive.\n\n## Token savings (an estimate, not a benchmark)\n\nThis is a back-of-the-envelope model, not a measurement of real agent sessions. Tokens are estimated as characters ÷ 4.\n\n- **n**: nodes the agent would otherwise read; **τ**: tokens per node in raw n8n JSON (assumed 300, it varies a lot: Code and HTML nodes are far heavier than a Set node); **W = n·τ**.\n- **S ≈ 1,600 tokens**: flownav's fixed overhead per session (the 12 MCP tool definitions, about 1,000 tokens, plus the skill, about 550).\n- **r ≈ 100 tokens**: a typical reply. `explain` and `affected` replies are tens of tokens; a `scan` of a dozen workflows is a few hundred.\n- With prompt caching, text read once costs about 1.25× the first time and about 0.1× on each later turn. For Q questions:\n  - raw: `C_raw ≈ W · (1.25 + 0.1·(Q − 1))`\n  - flownav: `C_flow ≈ S · (1.25 + 0.1·(Q − 1)) + Q · r`\n- Saving = `1 − C_flow / C_raw`.\n\nRaw reading grows with the workflow; a flownav reply depends only on a node's local connections.\n\n**Saving when the agent reads the whole workflow:**\n\n| workflow size | raw tokens | 1 question | 10 questions |\n|---|---|---|---|\n| 5 nodes | 1,500 | −12% (costs more) | −38% (costs more) |\n| 10 nodes | 3,000 | 44% | 31% |\n| 30 nodes | 9,000 | 81% | 77% |\n| 132 nodes | 40,000 | 96% | 95% |\n| whole instance (443 nodes) | 133,000 | 99% | 98% |\n\n**Saving when the agent searches and reads only a fraction of a 132-node workflow:**\n\n| fraction read | 1 question | 10 questions |\n|---|---|---|\n| 30% | 86% | 83% |\n| 20% | 79% | 74% |\n| 10% | 58% | 48% |\n\nWhat to take from it:\n\n- Below roughly 6 nodes, reading the JSON is cheaper than loading the tools. Around 10 to 30 nodes flownav saves about half to four fifths; on large workflows the saving approaches 100%.\n- Most agents search instead of reading everything, so for large workflows a realistic range is about 55 to 90%; the 96% rows are the best case.\n- τ is the main unknown, and `flownav stats` measures it on your own workflows (the bundled examples come out at about 130 tokens per node, well below the 300 assumed here, because they are small and hand-written; real Code and HTML nodes are far heavier). You can also run the same task with and without flownav and compare the usage Claude reports, several times, or measure the size of your own exports, or run the same task with and without flownav and compare the usage Claude reports, several times, since agent runs vary.\n- Tokens are not the only benefit: `affected` finds `$('Name')` references in expressions and Code nodes that a skimming agent misses.\n\n## Limitations\n\n- It is static analysis. It does not run workflows and cannot see references built at runtime; those are listed as unresolved.\n- `fragile-reads` uses upstream-via-main reachability, not dominators, so a read placed after a Merge of both branches is treated as safe.\n- Edges observed in real executions (an OBSERVED confidence level) are not implemented.\n- The n8n export format is not formally specified. It has been exercised on the examples here and on one real instance of about a dozen workflows; fields may differ on other n8n versions. Please open an issue with a (sanitized) export if something is misparsed.\n- The interactive viewer uses a simple layered layout, so edges can cross or overlap in dense workflows.\n- flownav reads and checks; it does not edit workflows. Pair it with whatever tool you use to edit them.\n\n## Development\n\n```bash\nnpm install\nnpm test        # builds, then runs node --test on test/\n```\n\nSource is TypeScript under `src/`; the CLI entry is `src/cli.ts`. `examples/` holds the fixtures used by the tests and this README.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}