flowforge-map 0.2.0__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/.gitignore +7 -0
  2. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/PKG-INFO +113 -15
  3. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/README.md +109 -14
  4. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/agent/server.py +237 -21
  5. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/api/agent.py +40 -19
  6. flowforge_map-0.4.0/backend/flowforge/api/apps.py +253 -0
  7. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/api/checks.py +19 -6
  8. flowforge_map-0.4.0/backend/flowforge/api/issues.py +150 -0
  9. flowforge_map-0.4.0/backend/flowforge/api/keys.py +273 -0
  10. flowforge_map-0.4.0/backend/flowforge/api/lock.py +270 -0
  11. flowforge_map-0.4.0/backend/flowforge/api/projects.py +140 -0
  12. flowforge_map-0.4.0/backend/flowforge/api/settings.py +204 -0
  13. flowforge_map-0.4.0/backend/flowforge/apps.py +151 -0
  14. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/checks/probes.py +8 -1
  15. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/cli.py +129 -26
  16. flowforge_map-0.4.0/backend/flowforge/cli_ui.py +208 -0
  17. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/home.py +18 -1
  18. flowforge_map-0.4.0/backend/flowforge/main.py +184 -0
  19. flowforge_map-0.4.0/backend/flowforge/project_states.py +126 -0
  20. flowforge_map-0.4.0/backend/flowforge/projects.py +158 -0
  21. flowforge_map-0.4.0/backend/flowforge/security/finders.py +370 -0
  22. flowforge_map-0.4.0/backend/flowforge/security/fixes.py +246 -0
  23. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/security/keystore.py +77 -14
  24. flowforge_map-0.4.0/backend/flowforge/security/local_only.py +68 -0
  25. flowforge_map-0.4.0/backend/flowforge/security/lock.py +290 -0
  26. flowforge_map-0.4.0/backend/flowforge/security/masks.py +40 -0
  27. flowforge_map-0.4.0/backend/flowforge/security/wire.py +645 -0
  28. flowforge_map-0.4.0/backend/flowforge/settings.py +46 -0
  29. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/state.py +11 -4
  30. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/storage.py +15 -0
  31. flowforge_map-0.4.0/backend/flowforge/terminal.py +134 -0
  32. flowforge_map-0.4.0/frontend/dist/assets/AddConnector-Bi8J4U4d.js +1 -0
  33. flowforge_map-0.4.0/frontend/dist/assets/Catalog-CA9b5nAc.css +1 -0
  34. flowforge_map-0.4.0/frontend/dist/assets/Catalog-zd0ADYry.js +1 -0
  35. flowforge_map-0.4.0/frontend/dist/assets/ChecksPage-B77bP82v.js +1 -0
  36. flowforge_map-0.4.0/frontend/dist/assets/Connector-D4bc9fm5.js +1 -0
  37. flowforge_map-0.4.0/frontend/dist/assets/ExportPage-X83lvpEi.js +34 -0
  38. flowforge_map-0.4.0/frontend/dist/assets/ExportPage-e2bor7CC.css +1 -0
  39. flowforge_map-0.4.0/frontend/dist/assets/FlowMapPage-BrnQhApb.js +2 -0
  40. flowforge_map-0.4.0/frontend/dist/assets/Health-DROS3rFg.js +1 -0
  41. flowforge_map-0.4.0/frontend/dist/assets/Health-FLn--j7D.css +1 -0
  42. flowforge_map-0.4.0/frontend/dist/assets/HowDrawn-CazyemwU.js +1 -0
  43. flowforge_map-0.4.0/frontend/dist/assets/IssuesPage-DI9W3uIc.js +1 -0
  44. flowforge_map-0.4.0/frontend/dist/assets/KeysPage-B2vcuxeq.js +1 -0
  45. flowforge_map-0.4.0/frontend/dist/assets/Later-89_57i-0.js +1 -0
  46. flowforge_map-0.4.0/frontend/dist/assets/LiveRun-DgaIy_Hy.js +1 -0
  47. flowforge_map-0.4.0/frontend/dist/assets/LiveRun-NyTlzZhk.css +1 -0
  48. flowforge_map-0.4.0/frontend/dist/assets/Recheck-IaxmWKc4.js +1 -0
  49. flowforge_map-0.4.0/frontend/dist/assets/RunHistory-DeusCIFP.js +1 -0
  50. flowforge_map-0.4.0/frontend/dist/assets/SettingsPage-CF0lFy0X.js +2 -0
  51. flowforge_map-0.4.0/frontend/dist/assets/SettingsPage-DrMN0pie.css +1 -0
  52. flowforge_map-0.4.0/frontend/dist/assets/client-8TP7XnGi.js +1 -0
  53. flowforge_map-0.4.0/frontend/dist/assets/flowmap-DhjGiCkH.js +7 -0
  54. flowforge_map-0.4.0/frontend/dist/assets/flowmap-qRSp4v09.css +1 -0
  55. flowforge_map-0.4.0/frontend/dist/assets/how-Bunfi3hG.css +1 -0
  56. flowforge_map-0.4.0/frontend/dist/assets/icons-B5HLu6t-.js +1 -0
  57. flowforge_map-0.4.0/frontend/dist/assets/index-Bl5rbBs-.js +11 -0
  58. flowforge_map-0.4.0/frontend/dist/assets/index-BygBw1rS.css +1 -0
  59. flowforge_map-0.4.0/frontend/dist/assets/links-BKyTYkee.js +4 -0
  60. flowforge_map-0.4.0/frontend/dist/assets/mapId-CAn3Vwt1.js +1 -0
  61. flowforge_map-0.4.0/frontend/dist/assets/sse-Bbzu7IqU.js +1 -0
  62. flowforge_map-0.4.0/frontend/dist/assets/status-BtyVLBUd.js +1 -0
  63. flowforge_map-0.4.0/frontend/dist/assets/useChecks-Dgca8Xe7.js +1 -0
  64. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/index.html +5 -2
  65. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/pyproject.toml +7 -1
  66. flowforge_map-0.2.0/backend/flowforge/api/keys.py +0 -107
  67. flowforge_map-0.2.0/backend/flowforge/main.py +0 -142
  68. flowforge_map-0.2.0/backend/flowforge/security/finders.py +0 -127
  69. flowforge_map-0.2.0/frontend/dist/assets/index-C-GjahSy.js +0 -52
  70. flowforge_map-0.2.0/frontend/dist/assets/index-CWfr5fii.css +0 -1
  71. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/LICENSE +0 -0
  72. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/__init__.py +0 -0
  73. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/agent/__init__.py +0 -0
  74. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/api/__init__.py +0 -0
  75. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/api/connectors.py +0 -0
  76. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/api/flowmap.py +0 -0
  77. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/api/runs.py +0 -0
  78. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/api/scan.py +0 -0
  79. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/api/security.py +0 -0
  80. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/api/stats.py +0 -0
  81. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/checks/__init__.py +0 -0
  82. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/checks/models.py +0 -0
  83. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/connectors/__init__.py +0 -0
  84. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/connectors/catalog.py +0 -0
  85. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/connectors/models.py +0 -0
  86. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/connectors/presets.py +0 -0
  87. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/connectors/registry.py +0 -0
  88. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/connectors/runtime.py +0 -0
  89. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/connectors/secrets.py +0 -0
  90. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/example_data.py +0 -0
  91. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flow/__init__.py +0 -0
  92. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flow/advice.py +0 -0
  93. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flow/curly.py +0 -0
  94. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flow/index.py +0 -0
  95. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flow/order.py +0 -0
  96. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flow/reach.py +0 -0
  97. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flow/rewrite.py +0 -0
  98. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flowmap/__init__.py +0 -0
  99. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flowmap/diff.py +0 -0
  100. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flowmap/fixture.py +0 -0
  101. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flowmap/models.py +0 -0
  102. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flowmap/planner.py +0 -0
  103. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flowmap/service.py +0 -0
  104. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/flowmap/validate.py +0 -0
  105. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/nodes/__init__.py +0 -0
  106. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/nodes/base.py +0 -0
  107. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/nodes/check_node.py +0 -0
  108. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/nodes/http_node.py +0 -0
  109. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/nodes/llm_node.py +0 -0
  110. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/nodes/local_node.py +0 -0
  111. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/nodes/mcp_node.py +0 -0
  112. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/nodes/mock_node.py +0 -0
  113. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scan/__init__.py +0 -0
  114. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scan/facts.py +0 -0
  115. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scan/files.py +0 -0
  116. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scan/manifests.py +0 -0
  117. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scan/mcp_config.py +0 -0
  118. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scan/models.py +0 -0
  119. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scan/patterns.py +0 -0
  120. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scan/python_ast.py +0 -0
  121. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scan/scanner.py +0 -0
  122. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scan/services.py +0 -0
  123. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scan/urls.py +0 -0
  124. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scheduler/__init__.py +0 -0
  125. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scheduler/cache.py +0 -0
  126. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scheduler/critical_path.py +0 -0
  127. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scheduler/durations.py +0 -0
  128. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scheduler/executor.py +0 -0
  129. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scheduler/graph.py +0 -0
  130. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/scheduler/rate_limit.py +0 -0
  131. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/schema.py +0 -0
  132. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/security/__init__.py +0 -0
  133. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/security/findings.py +0 -0
  134. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/security/logfilter.py +0 -0
  135. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/spa.py +0 -0
  136. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/flowforge/templating.py +0 -0
  137. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/workflows/diamond_mock.json +0 -0
  138. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/backend/workflows/stripe_to_razorpay.json +0 -0
  139. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/.env.example +0 -0
  140. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/.gitignore +0 -0
  141. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/.mcp.json +0 -0
  142. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/README.md +0 -0
  143. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/config.py +0 -0
  144. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/mcp_servers/currency.py +0 -0
  145. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/planner.py +0 -0
  146. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/requirements.txt +0 -0
  147. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/services/__init__.py +0 -0
  148. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/services/geo.py +0 -0
  149. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/services/llm.py +0 -0
  150. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/services/mcp_tools.py +0 -0
  151. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/services/weather.py +0 -0
  152. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/tools/packing_list.py +0 -0
  153. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/examples/trip-planner/trips/.gitkeep +0 -0
  154. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/classic.html +0 -0
  155. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/assets/geist-cyrillic-ext-wght-normal-DjL33-gN.woff2 +0 -0
  156. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/assets/geist-cyrillic-wght-normal-BEAKL7Jp.woff2 +0 -0
  157. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/assets/geist-latin-ext-wght-normal-DC-KSUi6.woff2 +0 -0
  158. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/assets/geist-latin-wght-normal-BgDaEnEv.woff2 +0 -0
  159. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/assets/geist-mono-cyrillic-ext-wght-normal-X_5orZeX.woff2 +0 -0
  160. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/assets/geist-mono-cyrillic-wght-normal-DiZS0aHC.woff2 +0 -0
  161. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/assets/geist-mono-latin-ext-wght-normal-Bwz-egvJ.woff2 +0 -0
  162. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/assets/geist-mono-latin-wght-normal-XN7g48iV.woff2 +0 -0
  163. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/assets/geist-mono-symbols2-wght-normal-CO5SzqOn.woff2 +0 -0
  164. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/assets/geist-mono-vietnamese-wght-normal-DadHysG0.woff2 +0 -0
  165. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/assets/geist-vietnamese-wght-normal-6IgcOCM7.woff2 +0 -0
  166. {flowforge_map-0.2.0 → flowforge_map-0.4.0}/frontend/dist/favicon.svg +0 -0
@@ -25,3 +25,10 @@ claude-resume.md
25
25
  desktop.ini
26
26
  .vscode/
27
27
  .idea/
28
+
29
+ # the desktop app (D42): build output
30
+ build/
31
+ desktop/src-tauri/binaries/
32
+ desktop/src-tauri/target/
33
+ desktop/node_modules/
34
+ desktop/src-tauri/gen/
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: flowforge-map
3
- Version: 0.2.0
3
+ Version: 0.4.0
4
4
  Summary: Map what your app depends on (LLMs, MCP servers, APIs), check their health and security, and see what could run faster. Local and free; the scan needs no AI.
5
5
  Project-URL: Homepage, https://github.com/Vishwa-Thangapandiyan/flowforge-agent-orchestrator
6
6
  Project-URL: Issues, https://github.com/Vishwa-Thangapandiyan/flowforge-agent-orchestrator/issues
@@ -26,9 +26,12 @@ Requires-Dist: jsonschema>=4.26.0
26
26
  Requires-Dist: keyring>=25
27
27
  Requires-Dist: mcp>=1.2
28
28
  Requires-Dist: openai>=1.40
29
+ Requires-Dist: packaging>=24
29
30
  Requires-Dist: pydantic>=2.8
30
31
  Requires-Dist: python-dotenv>=1.0
31
32
  Requires-Dist: python-multipart>=0.0.32
33
+ Requires-Dist: rich>=13
34
+ Requires-Dist: segno>=1.6
32
35
  Requires-Dist: uvicorn[standard]>=0.30
33
36
  Description-Content-Type: text/markdown
34
37
 
@@ -58,12 +61,52 @@ What makes it different: **it knows which chain of steps is the bottleneck and s
58
61
  ### Install
59
62
 
60
63
  ```bash
61
- uvx flowforge-map --example # try it: a sample app's maps in your browser, no keys, nothing sent
62
- pip install flowforge-map # or install it (the command is `flowforge`)
63
- flowforge --repo ~/my-app # map your own repo
64
+ npx flowforge-map --example # try it: a sample app's maps in your browser, no keys, nothing sent
65
+ npx flowforge-map --repo . # map the folder you're in
64
66
  ```
65
67
 
66
- You need Python 3.12 or newer ([uv](https://docs.astral.sh/uv/) installs it for you). The dashboard is inside the package: no Node needed. Your data lives in `~/.flowforge`.
68
+ That's all: no Python, no virtual env. The first run downloads FlowForge's ready-made program for your computer (about 60 MB, checked against the release's checksums) into `~/.flowforge/bin`; after that it starts at once, even offline. Works on Windows, macOS (Apple and Intel) and Linux x64 with Node 18+. Your data lives in `~/.flowforge`.
69
+
70
+ | You have | Run | |
71
+ |---|---|---|
72
+ | Node (most developers) | `npx flowforge-map` | ⭐ no Python needed |
73
+ | Node, every day | `npm i -g flowforge-map`, then just `flowforge` | installs the launcher; the program comes on first run |
74
+ | Python people | `uvx flowforge-map` or `pipx install flowforge-map` | Python 3.12+; no virtual env to manage |
75
+ | No terminal | the desktop app (Releases) | download and open; **Settings → Terminal** adds the `flowforge` command too (Linux .rpm/.deb have it already) |
76
+
77
+ Every way gives the same `flowforge` command: `npx flowforge-map status`, `npx flowforge-map key add STRIPE_KEY`, and so on. Linux ARM and Windows ARM have no ready-made build yet, so `npx` uses `uvx` there.
78
+
79
+ The first time, a short welcome walks you through three steps, each one skippable: your app's folder (or the example), pairing your coding agent once, and a lock for your keys. **⚙ Settings** at the bottom of the rail keeps what applies to every project: your agent, the theme and map style, the Vault's lock, and your data (each project's size, the MCP servers it may start, its check history, and the version, with **Check for updates**, which asks pypi.org only when you press it).
80
+
81
+ ### Terminal
82
+
83
+ ```bash
84
+ flowforge status [PROJECT] # health, issues, missing keys and the next step
85
+ flowforge projects # every project at a glance
86
+ flowforge issues [PROJECT] # security findings and fixes
87
+ flowforge check [PROJECT] # preview checks; run them from the dashboard
88
+ flowforge settings # saved settings, data location and version
89
+ flowforge scan ~/my-app # terminal summary; pipe it or use --json for JSON
90
+ flowforge key list # key names and statuses, never values
91
+ ```
92
+
93
+ Project commands use the current folder's project, else the last opened; PROJECT is its name or id. They read local files and work with the dashboard stopped. `--plain` or `NO_COLOR` disables colour and the banner; pipes have no colour or animation.
94
+
95
+ ### Desktop app
96
+
97
+ The same dashboard in its own window, with Python inside: nothing else to install. Download the installer for your computer from the [Releases](https://github.com/Vishwa-Thangapandiyan/flowforge-agent-orchestrator/releases) page:
98
+
99
+ | Your computer | Download |
100
+ |---|---|
101
+ | Windows | `FlowForge_x.y.z_x64-setup.exe` or `.msi` |
102
+ | Mac (Apple Silicon or Intel) | `FlowForge_x.y.z_aarch64.dmg` or `_x64.dmg` |
103
+ | Linux | `.AppImage`, `.deb` or `.rpm` |
104
+
105
+ The builds aren't signed yet (signing costs money every year), so the first launch asks once:
106
+ - **Mac:** right-click FlowForge in Applications → **Open** → **Open**.
107
+ - **Windows:** on "Windows protected your PC", click **More info** → **Run anyway**.
108
+
109
+ After that it opens normally. **Browse…** picks your app's folder; **Settings → Your agent** pairs your coding agent with the app's own FlowForge.
67
110
 
68
111
  ### From source (to work on FlowForge)
69
112
 
@@ -82,7 +125,7 @@ uv run flowforge --example # opens http://127.0.0.1:8000: a sampl
82
125
  ### Map your own repo
83
126
 
84
127
  ```bash
85
- uv run flowforge scan path/to/your/repo # what it depends on, as JSON: nothing stored, nothing sent
128
+ uv run flowforge scan path/to/your/repo # summary (pipe or --json for JSON); nothing stored, nothing sent
86
129
  uv run flowforge --repo path/to/your/repo # opens its dependency map; add --replace to switch folders
87
130
  ```
88
131
 
@@ -105,30 +148,80 @@ Switch the map to **Flow**. FlowForge reads your Python (by its syntax tree), Da
105
148
  - **Watch it run** plays the could-be schedule; pointing at a block lights up its path. Five map styles: Studio, Boxed, Blueprint, Metro, Soft.
106
149
 
107
150
 
151
+ ### Many projects
152
+
153
+ The home page lists every app you've mapped, with its dependencies, what needs fixing and missing keys. **+ New project** takes your app's folder, scans it and shows its map. The project tile at the top of the rail switches between the projects you have open, and each one comes back where you left it. **×** closes a project from that list without deleting it. Each project keeps its own map, checks, issues and keys; `flowforge --repo PATH` opens (or adds) that folder's project.
154
+
108
155
  ### Use it from your coding agent
109
156
 
110
- FlowForge is also an **MCP server**, so Claude Code, Codex or Antigravity can ask it about your app and then make the change themselves. Open **Connect agent** in the dashboard: it gives you the one line (or config block) for your agent, with the paths filled in. For Claude Code it looks like:
157
+ FlowForge is also an **MCP server**, so Claude Code, Codex or Antigravity can ask it about your app and then make the change themselves. **Settings → Your agent** (also on **Connect agent**) gives you the one line (or config block) for your agent. With `uvx`, for Claude Code it looks like:
111
158
 
112
159
  ```bash
113
- claude mcp add flowforge -- uv --directory /path/to/flowforge run flowforge mcp --repo /path/to/your/app
160
+ claude mcp add flowforge -- uvx flowforge-map mcp
114
161
  ```
115
162
 
116
- Your agent gets seven read-only tools: `get_map`, `get_flow`, `get_advice`, `check_health`, `get_security_findings`, `get_keys` and `what_changed`. Every answer is masked (key values never appear), FlowForge never edits your code, and a check starts an MCP server only after you said yes to it on the Checks page. FlowForge needs no AI of its own for any of this.
163
+ Pair your agent once and it sees every project: `flowforge mcp` with no folder answers about the project your agent is working in, or any other by name (`list_projects` shows them all). Your agent gets eleven tools: `list_projects`, `get_map`, `get_flow`, `get_advice`, `check_health`, `get_security_findings`, `get_keys`, `get_fix_requests`, `request_key`, `wait_for_keys` and `what_changed`. All read only, except `request_key`, which only asks you for a key by name. Every answer is masked (key values never appear), the agent can't make FlowForge change your code, and a check starts an MCP server only after you said yes to it on the Checks page. FlowForge needs no AI of its own for any of this.
164
+
165
+ ### Fix what's unsafe, with one click
166
+
167
+ The **Issues** page lists what the scan found unsafe, and every issue has one button:
168
+
169
+ | Issue | Button | What happens |
170
+ |---|---|---|
171
+ | A key written in Python, or in JS/TS that runs on Node | **Fix** | FlowForge shows the change (the key masked). On **Approve**, the key goes to your keys and the line reads it from the environment, on a new branch `flowforge/fix-…`. Your branch and files aren't touched; merge it when you're ready. |
172
+ | `http://`, an unpinned MCP server, a server given the whole disk, a key in `.mcp.json`, Dart or browser code | **Send to agent** | It joins your coding agent's list (`get_fix_requests`). Tell your agent "do the FlowForge fixes". |
173
+
174
+ Fix needs a git repo and the file committed. FlowForge works out the change itself, with no AI. Replace a key that was in your code with its provider anyway: older commits still hold it.
117
175
 
118
176
  ### Keys your coding agent never sees
119
177
 
120
- Your agent only needs a key's **name**: the code it writes reads `os.environ["STRIPE_SECRET_KEY"]`. You give FlowForge the value once, and your app gets it when it starts:
178
+ **Add to code.** The **Keys** page lists each place your code needs a key, with its `file:line`. Paste the key and press **Add to code**:
121
179
 
180
+ ```
181
+ lib/config.dart:8 String.fromEnvironment('SUPABASE_ANON_KEY') ← FlowForge found the spot
182
+ [ •••••••••••• ] [ Add to code ] ← you paste, one click
183
+ ✓ SUPABASE_ANON_KEY is in your app. Press Run as always.
184
+ Changed: .flowforge/dart-defines.json · Run config · .gitignore · Claude Code told not to read it · Vault
185
+ ```
186
+
187
+ The key goes where your app reads it, and **never into a code file**:
188
+
189
+ | Your app | The key goes to | Then |
190
+ |---|---|---|
191
+ | Flutter (`String.fromEnvironment`) | `.flowforge/dart-defines.json`, and `--dart-define-from-file` is added to your Run config (Android Studio, IntelliJ, VS Code) | press Run |
192
+ | Python, Node or Flutter with a `.env` loader | `.env` | start it as always |
193
+ | Vite | `.env.local` (as `VITE_…`) | start it as always |
194
+
195
+ - A placeholder like `apiKey = "ENTER KEY HERE"` is rewritten to read the key.
196
+ - A real key written in the code gets **Hide it**: one click moves it out the same way.
197
+ - The file is git-ignored, and nothing is committed: you see the change in `git diff`.
198
+ - An app that loads no file gets **Save**, and the Keys page says why.
199
+ - The settings a key needs come too: `SUPABASE_URL` is listed under **Your app also needs**, filled in from your Supabase key, with the same **Add to code** (a setting isn't secret, so it doesn't go to the Vault).
200
+
201
+ **With an agent**, the agent never gets a key; it gets a **mask**:
202
+
203
+ ```
204
+ you paste STRIPE_SECRET_KEY once → your agent sees ffkey://STRIPE_SECRET_KEY
205
+ the agent writes the mask where the key goes (or reads the env var STRIPE_SECRET_KEY in code)
206
+ the agent calls run_app(["flutter", "run", "--dart-define=STRIPE_SECRET_KEY=ffkey://STRIPE_SECRET_KEY"])
207
+ FlowForge asks you once: "Your agent wants to run flutter run … with STRIPE_SECRET_KEY" [Deny] [Allow]
208
+ FlowForge (plain code, no AI) fills the mask and starts the app → the output comes back masked
209
+ ```
210
+
211
+ Masks work in commands, in the environment and in `.env` lines; other config files never get the key written into them, so read the env var there. After you allow a command once, the same command runs without asking (**Settings** can turn the question off). The Keys page lists your agent's runs with **Stop**. This covers keys read when the app is *built* too, such as Flutter's `--dart-define` and Vite's `import.meta.env`. On the map, a 🔑 badge marks a block whose key is missing. With no keychain (a server, CI), keys go to an encrypted file in `~/.flowforge`.
212
+
213
+ **No agent?** The same works by hand:
122
214
  ```bash
123
215
  flowforge key add STRIPE_SECRET_KEY # typed hidden; saved in your OS keychain
124
216
  flowforge key list # each key the code reads: saved · in .env · missing
125
- flowforge key import # move a .env into FlowForge (then delete the .env)
126
- flowforge run -- python app.py # your app starts with the keys in its environment
217
+ flowforge run -- python app.py # your app starts with the keys (masks filled)
127
218
  ```
128
219
 
129
- Each command takes `--repo PATH` (default: the folder you're in). On the map, a 🔑 badge marks a block whose key is missing, and the ⚠ list has a box to paste it into. Your agent's `get_keys` tool gets names, statuses and the command to ask you to run, never a value. With no keychain (a server, CI), keys go to an encrypted file in `~/.flowforge`.
220
+ **When your agent adds a dependency that needs a key**, it calls `request_key("STRIPE_SECRET_KEY", "for Stripe in pay.py")`. The map says "Your agent asked for a key", and the new block shows in coral, "key missing". Click it, paste the key on the Keys page, and the agent's `wait_for_keys` returns the moment it's saved. The agent only ever sees the name.
221
+
222
+ **See a key again** in the **Vault**: set a password and scan the QR with an authenticator app (Google Authenticator, Authy, 1Password), once. After that, your password, then the 6-digit code on your phone, open it for 5 minutes. It lists every key with its health: healthy, written in code, in `.env`, can't read, unused, or old. It also shows where each key lives, what uses it, and whether it's a live or test key. Each value shows for 30 seconds. Forgot the password? `flowforge lock reset --forget` drops the lock (your keys stay) and the dashboard says so.
130
223
 
131
- What this does and doesn't promise: the key is never handed to your agent and isn't left in a file it reads by habit. An agent that can run commands as you could still run `flowforge run -- printenv`, or read your keychain, so it isn't impossible. MCP servers your coding tool starts get their environment from that tool, not from FlowForge.
224
+ What FlowForge promises: a key is never in anything your agent receives (answers, its own process, the output it returns), never in a code file, a stored row or a log. **Add to code** puts it in one hidden, git-ignored file next to your app (like `.env`), which Claude Code is told not to read; other agents could still read it. Outside FlowForge: what your own app does with a key, a key built into an app (anyone holding the app can read it, so use publishable keys there), and other programs running as your user. The 2FA on the Vault stops web pages, anyone at your browser, and anything without your phone.
132
225
 
133
226
  ### Send someone the map
134
227
 
@@ -175,6 +268,7 @@ To use real LLM steps, `cp .env.example .env` and add a free `NVIDIA_API_KEY` fr
175
268
  | **MCP Map** (Export) | The map to send: SVG, PNG, PDF, Mermaid or Flow JSON |
176
269
  | **Checks** | Check now, each dependency's verdict, why it's down and the likely fix, and the history |
177
270
  | **Connect agent** | The set-up for Claude Code, Codex or Antigravity; what your agent gets from this repo (dependencies, health, time, ways to be faster); and, once connected, what it asked |
271
+ | **Settings** (⚙, every project) | Your agent, paired once; the theme and the map style maps open in; the Vault's lock and where keys are kept (never a value); your data, each project's yeses and check history, and Check for updates |
178
272
  | **How the Planner drew it** | The analysis replayed: read the repo, run the app in test mode, trace the calls, draft, check. What it read, what it dropped and why |
179
273
  | **Re-check** | What changed in your repo since the last map: added, changed, removed, and conflicts with your edits. You pick what to take; the old version stays listed |
180
274
  | **Apps and connectors** (Map ⋯) | A catalog of 56 apps with search and categories, honest **Live** / **Demo only** badges, and a mock test run for every one. Apps you connected but your code doesn't call wait here, off the map |
@@ -255,7 +349,11 @@ FlowForge itself keeps keys out of its runs, events, cache, logs and the dashboa
255
349
  | `POST /connectors/{id}/test` | One harmless check (MCP and local apps) |
256
350
  | `GET /connectors/{id}/activity`, `GET /connectors/{id}/tools` | What an app has done; an MCP server's tools |
257
351
  | `GET /security` | The scan's security findings, by level, with the fix and a prompt for each (D31) |
258
- | `GET /keys`, `PUT /keys/{name}`, `DELETE /keys/{name}` | The keys the code reads and their status; save one (write-only: the value never comes back) or forget it (D36) |
352
+ | `GET /projects`, `POST /projects`, `PATCH\|DELETE /projects/{id}`, `/p/{id}/…` | Every project; add a folder; rename or remove one (its folder is never touched); any route above for one project (D39) |
353
+ | `GET\|PATCH /settings`, `DELETE /projects/{id}/checks\|confirmed`, `POST /settings/update-check` | Settings for every project (no secret in them); clear a project's check history or take back its yeses; ask pypi.org for the newest version, only when pressed (D40) |
354
+ | `GET /keys`, `PUT /keys/{name}`, `DELETE /keys/{name}`, `POST /keys/{name}/import` | The keys the code reads and their status; save one (write-only), move one in from `.env`, or forget it (D36, D37) |
355
+ | `GET /issues`, `POST /issues/{id}/preview\|fix\|send` | Every issue with its button; the masked change; make it on a new branch; send it to your agent (D37) |
356
+ | `GET /lock`, `POST /lock/setup\|confirm\|password\|code\|close`, `GET /vault/keys`, `POST /keys/reveal` | The Vault: its lock (your password, then the authenticator code) and, once open, every key's health and one value at a time (D37, D38) |
259
357
  | `GET /health/tools`, `GET /stats/savings`, `GET /meta`, `GET /presets` | Tool health, money and time, app info, ready-made apps |
260
358
  | `GET /workflows`, `GET /workflows/{name}` | The example workflows |
261
359
  | `GET /flow?layer=mine\|planner` | The flow map: blocks, lines, positions, critical path, your edits |
@@ -24,12 +24,52 @@ What makes it different: **it knows which chain of steps is the bottleneck and s
24
24
  ### Install
25
25
 
26
26
  ```bash
27
- uvx flowforge-map --example # try it: a sample app's maps in your browser, no keys, nothing sent
28
- pip install flowforge-map # or install it (the command is `flowforge`)
29
- flowforge --repo ~/my-app # map your own repo
27
+ npx flowforge-map --example # try it: a sample app's maps in your browser, no keys, nothing sent
28
+ npx flowforge-map --repo . # map the folder you're in
30
29
  ```
31
30
 
32
- You need Python 3.12 or newer ([uv](https://docs.astral.sh/uv/) installs it for you). The dashboard is inside the package: no Node needed. Your data lives in `~/.flowforge`.
31
+ That's all: no Python, no virtual env. The first run downloads FlowForge's ready-made program for your computer (about 60 MB, checked against the release's checksums) into `~/.flowforge/bin`; after that it starts at once, even offline. Works on Windows, macOS (Apple and Intel) and Linux x64 with Node 18+. Your data lives in `~/.flowforge`.
32
+
33
+ | You have | Run | |
34
+ |---|---|---|
35
+ | Node (most developers) | `npx flowforge-map` | ⭐ no Python needed |
36
+ | Node, every day | `npm i -g flowforge-map`, then just `flowforge` | installs the launcher; the program comes on first run |
37
+ | Python people | `uvx flowforge-map` or `pipx install flowforge-map` | Python 3.12+; no virtual env to manage |
38
+ | No terminal | the desktop app (Releases) | download and open; **Settings → Terminal** adds the `flowforge` command too (Linux .rpm/.deb have it already) |
39
+
40
+ Every way gives the same `flowforge` command: `npx flowforge-map status`, `npx flowforge-map key add STRIPE_KEY`, and so on. Linux ARM and Windows ARM have no ready-made build yet, so `npx` uses `uvx` there.
41
+
42
+ The first time, a short welcome walks you through three steps, each one skippable: your app's folder (or the example), pairing your coding agent once, and a lock for your keys. **⚙ Settings** at the bottom of the rail keeps what applies to every project: your agent, the theme and map style, the Vault's lock, and your data (each project's size, the MCP servers it may start, its check history, and the version, with **Check for updates**, which asks pypi.org only when you press it).
43
+
44
+ ### Terminal
45
+
46
+ ```bash
47
+ flowforge status [PROJECT] # health, issues, missing keys and the next step
48
+ flowforge projects # every project at a glance
49
+ flowforge issues [PROJECT] # security findings and fixes
50
+ flowforge check [PROJECT] # preview checks; run them from the dashboard
51
+ flowforge settings # saved settings, data location and version
52
+ flowforge scan ~/my-app # terminal summary; pipe it or use --json for JSON
53
+ flowforge key list # key names and statuses, never values
54
+ ```
55
+
56
+ Project commands use the current folder's project, else the last opened; PROJECT is its name or id. They read local files and work with the dashboard stopped. `--plain` or `NO_COLOR` disables colour and the banner; pipes have no colour or animation.
57
+
58
+ ### Desktop app
59
+
60
+ The same dashboard in its own window, with Python inside: nothing else to install. Download the installer for your computer from the [Releases](https://github.com/Vishwa-Thangapandiyan/flowforge-agent-orchestrator/releases) page:
61
+
62
+ | Your computer | Download |
63
+ |---|---|
64
+ | Windows | `FlowForge_x.y.z_x64-setup.exe` or `.msi` |
65
+ | Mac (Apple Silicon or Intel) | `FlowForge_x.y.z_aarch64.dmg` or `_x64.dmg` |
66
+ | Linux | `.AppImage`, `.deb` or `.rpm` |
67
+
68
+ The builds aren't signed yet (signing costs money every year), so the first launch asks once:
69
+ - **Mac:** right-click FlowForge in Applications → **Open** → **Open**.
70
+ - **Windows:** on "Windows protected your PC", click **More info** → **Run anyway**.
71
+
72
+ After that it opens normally. **Browse…** picks your app's folder; **Settings → Your agent** pairs your coding agent with the app's own FlowForge.
33
73
 
34
74
  ### From source (to work on FlowForge)
35
75
 
@@ -48,7 +88,7 @@ uv run flowforge --example # opens http://127.0.0.1:8000: a sampl
48
88
  ### Map your own repo
49
89
 
50
90
  ```bash
51
- uv run flowforge scan path/to/your/repo # what it depends on, as JSON: nothing stored, nothing sent
91
+ uv run flowforge scan path/to/your/repo # summary (pipe or --json for JSON); nothing stored, nothing sent
52
92
  uv run flowforge --repo path/to/your/repo # opens its dependency map; add --replace to switch folders
53
93
  ```
54
94
 
@@ -71,30 +111,80 @@ Switch the map to **Flow**. FlowForge reads your Python (by its syntax tree), Da
71
111
  - **Watch it run** plays the could-be schedule; pointing at a block lights up its path. Five map styles: Studio, Boxed, Blueprint, Metro, Soft.
72
112
 
73
113
 
114
+ ### Many projects
115
+
116
+ The home page lists every app you've mapped, with its dependencies, what needs fixing and missing keys. **+ New project** takes your app's folder, scans it and shows its map. The project tile at the top of the rail switches between the projects you have open, and each one comes back where you left it. **×** closes a project from that list without deleting it. Each project keeps its own map, checks, issues and keys; `flowforge --repo PATH` opens (or adds) that folder's project.
117
+
74
118
  ### Use it from your coding agent
75
119
 
76
- FlowForge is also an **MCP server**, so Claude Code, Codex or Antigravity can ask it about your app and then make the change themselves. Open **Connect agent** in the dashboard: it gives you the one line (or config block) for your agent, with the paths filled in. For Claude Code it looks like:
120
+ FlowForge is also an **MCP server**, so Claude Code, Codex or Antigravity can ask it about your app and then make the change themselves. **Settings → Your agent** (also on **Connect agent**) gives you the one line (or config block) for your agent. With `uvx`, for Claude Code it looks like:
77
121
 
78
122
  ```bash
79
- claude mcp add flowforge -- uv --directory /path/to/flowforge run flowforge mcp --repo /path/to/your/app
123
+ claude mcp add flowforge -- uvx flowforge-map mcp
80
124
  ```
81
125
 
82
- Your agent gets seven read-only tools: `get_map`, `get_flow`, `get_advice`, `check_health`, `get_security_findings`, `get_keys` and `what_changed`. Every answer is masked (key values never appear), FlowForge never edits your code, and a check starts an MCP server only after you said yes to it on the Checks page. FlowForge needs no AI of its own for any of this.
126
+ Pair your agent once and it sees every project: `flowforge mcp` with no folder answers about the project your agent is working in, or any other by name (`list_projects` shows them all). Your agent gets eleven tools: `list_projects`, `get_map`, `get_flow`, `get_advice`, `check_health`, `get_security_findings`, `get_keys`, `get_fix_requests`, `request_key`, `wait_for_keys` and `what_changed`. All read only, except `request_key`, which only asks you for a key by name. Every answer is masked (key values never appear), the agent can't make FlowForge change your code, and a check starts an MCP server only after you said yes to it on the Checks page. FlowForge needs no AI of its own for any of this.
127
+
128
+ ### Fix what's unsafe, with one click
129
+
130
+ The **Issues** page lists what the scan found unsafe, and every issue has one button:
131
+
132
+ | Issue | Button | What happens |
133
+ |---|---|---|
134
+ | A key written in Python, or in JS/TS that runs on Node | **Fix** | FlowForge shows the change (the key masked). On **Approve**, the key goes to your keys and the line reads it from the environment, on a new branch `flowforge/fix-…`. Your branch and files aren't touched; merge it when you're ready. |
135
+ | `http://`, an unpinned MCP server, a server given the whole disk, a key in `.mcp.json`, Dart or browser code | **Send to agent** | It joins your coding agent's list (`get_fix_requests`). Tell your agent "do the FlowForge fixes". |
136
+
137
+ Fix needs a git repo and the file committed. FlowForge works out the change itself, with no AI. Replace a key that was in your code with its provider anyway: older commits still hold it.
83
138
 
84
139
  ### Keys your coding agent never sees
85
140
 
86
- Your agent only needs a key's **name**: the code it writes reads `os.environ["STRIPE_SECRET_KEY"]`. You give FlowForge the value once, and your app gets it when it starts:
141
+ **Add to code.** The **Keys** page lists each place your code needs a key, with its `file:line`. Paste the key and press **Add to code**:
87
142
 
143
+ ```
144
+ lib/config.dart:8 String.fromEnvironment('SUPABASE_ANON_KEY') ← FlowForge found the spot
145
+ [ •••••••••••• ] [ Add to code ] ← you paste, one click
146
+ ✓ SUPABASE_ANON_KEY is in your app. Press Run as always.
147
+ Changed: .flowforge/dart-defines.json · Run config · .gitignore · Claude Code told not to read it · Vault
148
+ ```
149
+
150
+ The key goes where your app reads it, and **never into a code file**:
151
+
152
+ | Your app | The key goes to | Then |
153
+ |---|---|---|
154
+ | Flutter (`String.fromEnvironment`) | `.flowforge/dart-defines.json`, and `--dart-define-from-file` is added to your Run config (Android Studio, IntelliJ, VS Code) | press Run |
155
+ | Python, Node or Flutter with a `.env` loader | `.env` | start it as always |
156
+ | Vite | `.env.local` (as `VITE_…`) | start it as always |
157
+
158
+ - A placeholder like `apiKey = "ENTER KEY HERE"` is rewritten to read the key.
159
+ - A real key written in the code gets **Hide it**: one click moves it out the same way.
160
+ - The file is git-ignored, and nothing is committed: you see the change in `git diff`.
161
+ - An app that loads no file gets **Save**, and the Keys page says why.
162
+ - The settings a key needs come too: `SUPABASE_URL` is listed under **Your app also needs**, filled in from your Supabase key, with the same **Add to code** (a setting isn't secret, so it doesn't go to the Vault).
163
+
164
+ **With an agent**, the agent never gets a key; it gets a **mask**:
165
+
166
+ ```
167
+ you paste STRIPE_SECRET_KEY once → your agent sees ffkey://STRIPE_SECRET_KEY
168
+ the agent writes the mask where the key goes (or reads the env var STRIPE_SECRET_KEY in code)
169
+ the agent calls run_app(["flutter", "run", "--dart-define=STRIPE_SECRET_KEY=ffkey://STRIPE_SECRET_KEY"])
170
+ FlowForge asks you once: "Your agent wants to run flutter run … with STRIPE_SECRET_KEY" [Deny] [Allow]
171
+ FlowForge (plain code, no AI) fills the mask and starts the app → the output comes back masked
172
+ ```
173
+
174
+ Masks work in commands, in the environment and in `.env` lines; other config files never get the key written into them, so read the env var there. After you allow a command once, the same command runs without asking (**Settings** can turn the question off). The Keys page lists your agent's runs with **Stop**. This covers keys read when the app is *built* too, such as Flutter's `--dart-define` and Vite's `import.meta.env`. On the map, a 🔑 badge marks a block whose key is missing. With no keychain (a server, CI), keys go to an encrypted file in `~/.flowforge`.
175
+
176
+ **No agent?** The same works by hand:
88
177
  ```bash
89
178
  flowforge key add STRIPE_SECRET_KEY # typed hidden; saved in your OS keychain
90
179
  flowforge key list # each key the code reads: saved · in .env · missing
91
- flowforge key import # move a .env into FlowForge (then delete the .env)
92
- flowforge run -- python app.py # your app starts with the keys in its environment
180
+ flowforge run -- python app.py # your app starts with the keys (masks filled)
93
181
  ```
94
182
 
95
- Each command takes `--repo PATH` (default: the folder you're in). On the map, a 🔑 badge marks a block whose key is missing, and the ⚠ list has a box to paste it into. Your agent's `get_keys` tool gets names, statuses and the command to ask you to run, never a value. With no keychain (a server, CI), keys go to an encrypted file in `~/.flowforge`.
183
+ **When your agent adds a dependency that needs a key**, it calls `request_key("STRIPE_SECRET_KEY", "for Stripe in pay.py")`. The map says "Your agent asked for a key", and the new block shows in coral, "key missing". Click it, paste the key on the Keys page, and the agent's `wait_for_keys` returns the moment it's saved. The agent only ever sees the name.
184
+
185
+ **See a key again** in the **Vault**: set a password and scan the QR with an authenticator app (Google Authenticator, Authy, 1Password), once. After that, your password, then the 6-digit code on your phone, open it for 5 minutes. It lists every key with its health: healthy, written in code, in `.env`, can't read, unused, or old. It also shows where each key lives, what uses it, and whether it's a live or test key. Each value shows for 30 seconds. Forgot the password? `flowforge lock reset --forget` drops the lock (your keys stay) and the dashboard says so.
96
186
 
97
- What this does and doesn't promise: the key is never handed to your agent and isn't left in a file it reads by habit. An agent that can run commands as you could still run `flowforge run -- printenv`, or read your keychain, so it isn't impossible. MCP servers your coding tool starts get their environment from that tool, not from FlowForge.
187
+ What FlowForge promises: a key is never in anything your agent receives (answers, its own process, the output it returns), never in a code file, a stored row or a log. **Add to code** puts it in one hidden, git-ignored file next to your app (like `.env`), which Claude Code is told not to read; other agents could still read it. Outside FlowForge: what your own app does with a key, a key built into an app (anyone holding the app can read it, so use publishable keys there), and other programs running as your user. The 2FA on the Vault stops web pages, anyone at your browser, and anything without your phone.
98
188
 
99
189
  ### Send someone the map
100
190
 
@@ -141,6 +231,7 @@ To use real LLM steps, `cp .env.example .env` and add a free `NVIDIA_API_KEY` fr
141
231
  | **MCP Map** (Export) | The map to send: SVG, PNG, PDF, Mermaid or Flow JSON |
142
232
  | **Checks** | Check now, each dependency's verdict, why it's down and the likely fix, and the history |
143
233
  | **Connect agent** | The set-up for Claude Code, Codex or Antigravity; what your agent gets from this repo (dependencies, health, time, ways to be faster); and, once connected, what it asked |
234
+ | **Settings** (⚙, every project) | Your agent, paired once; the theme and the map style maps open in; the Vault's lock and where keys are kept (never a value); your data, each project's yeses and check history, and Check for updates |
144
235
  | **How the Planner drew it** | The analysis replayed: read the repo, run the app in test mode, trace the calls, draft, check. What it read, what it dropped and why |
145
236
  | **Re-check** | What changed in your repo since the last map: added, changed, removed, and conflicts with your edits. You pick what to take; the old version stays listed |
146
237
  | **Apps and connectors** (Map ⋯) | A catalog of 56 apps with search and categories, honest **Live** / **Demo only** badges, and a mock test run for every one. Apps you connected but your code doesn't call wait here, off the map |
@@ -221,7 +312,11 @@ FlowForge itself keeps keys out of its runs, events, cache, logs and the dashboa
221
312
  | `POST /connectors/{id}/test` | One harmless check (MCP and local apps) |
222
313
  | `GET /connectors/{id}/activity`, `GET /connectors/{id}/tools` | What an app has done; an MCP server's tools |
223
314
  | `GET /security` | The scan's security findings, by level, with the fix and a prompt for each (D31) |
224
- | `GET /keys`, `PUT /keys/{name}`, `DELETE /keys/{name}` | The keys the code reads and their status; save one (write-only: the value never comes back) or forget it (D36) |
315
+ | `GET /projects`, `POST /projects`, `PATCH\|DELETE /projects/{id}`, `/p/{id}/…` | Every project; add a folder; rename or remove one (its folder is never touched); any route above for one project (D39) |
316
+ | `GET\|PATCH /settings`, `DELETE /projects/{id}/checks\|confirmed`, `POST /settings/update-check` | Settings for every project (no secret in them); clear a project's check history or take back its yeses; ask pypi.org for the newest version, only when pressed (D40) |
317
+ | `GET /keys`, `PUT /keys/{name}`, `DELETE /keys/{name}`, `POST /keys/{name}/import` | The keys the code reads and their status; save one (write-only), move one in from `.env`, or forget it (D36, D37) |
318
+ | `GET /issues`, `POST /issues/{id}/preview\|fix\|send` | Every issue with its button; the masked change; make it on a new branch; send it to your agent (D37) |
319
+ | `GET /lock`, `POST /lock/setup\|confirm\|password\|code\|close`, `GET /vault/keys`, `POST /keys/reveal` | The Vault: its lock (your password, then the authenticator code) and, once open, every key's health and one value at a time (D37, D38) |
225
320
  | `GET /health/tools`, `GET /stats/savings`, `GET /meta`, `GET /presets` | Tool health, money and time, app info, ready-made apps |
226
321
  | `GET /workflows`, `GET /workflows/{name}` | The example workflows |
227
322
  | `GET /flow?layer=mine\|planner` | The flow map: blocks, lines, positions, critical path, your edits |