Jesse A. Green / notebook

n8n-workflows — Administrator & Developer Guide

Generated June 2026 from Zie619/n8n-workflows at ed8dd70

AI-generated documentation. The library is checked by sampling (three repositories so far); this guide was not individually reviewed. Verify against the project before relying on it.

A self-hosted search engine and documentation platform for a large curated collection of n8n workflow .json files. At its core it is a Python FastAPI service backed by a SQLite FTS5 index, with a parallel Node.js (Express) implementation of the same API, a static single-page front end, and container/Kubernetes deployment assets. This guide covers architecture, configuration, security, operations, and internals in enough depth to deploy, harden, extend, or reimplement the system.

Tip

For end-user search syntax, the web UI, and everyday workflow discovery, see the companion User Guide. This document assumes you operate or develop the platform.

Important

Scope note — what is and isn't the product. The shipping, wired-together application is the core search server (run.py → api_server.py → workflow_db.py) plus its static front end, with a Node.js equivalent under src/. The repository also contains several standalone, experimental feature modules (src/ai_assistant.py, src/analytics_engine.py, src/enhanced_api.py, src/integration_hub.py, src/performance_monitor.py, src/user_management.py, src/community_features.py) that each build their own FastAPI app and are not mounted into the main server. They are documented in Section 9 and clearly labeled as optional/standalone. The repository additionally bundles an unrelated subproject, medcards-ai/ (a Next.js application), which is not part of this platform and is out of scope here.


1. Executive Summary

Attribute Detail
Purpose Index, search, browse, visualize, and serve a large collection of n8n workflow JSON files
Primary stack Python 3.9–3.12, FastAPI 0.109, Uvicorn 0.27, Pydantic 2.5, SQLite (FTS5)
Alternative stack Node.js ≥18, Express, sqlite3, fs-extra (mirrors the core API)
Storage Single SQLite database file (database/workflows.db by default); WAL mode
Front end Static single-page app (vanilla JS) served from static/; a GitHub Pages mirror lives in docs/
API surface (core) 12 REST endpoints + Swagger UI at /docs
Published catalog size 4,343 workflows, 29,528 nodes, 268 integrations, 16 categories
Deployment Docker / Docker Compose (dev + prod overlays), Kubernetes manifests (k8s/), Helm chart (helm/workflows-docs/)
External services required None at runtime — fully self-contained and offline-capable

Design goals reflected in the code:

  • Speed — SQLite FTS5 + targeted indexes + WAL/PRAGMA tuning for sub-100 ms search.
  • Self-contained — no external database, message broker, or cloud dependency.
  • Incremental indexing — per-file MD5 hashing skips unchanged files on re-index.
  • Defense at the file boundary — strict filename validation guards the only file-serving endpoints against path traversal.

2. Architecture Overview

2.1 System Topology

                         Browser / API client
                                  │
                                  ▼
        ┌──────────────────────────────────────────────────┐
        │  Core Server (choose ONE stack)                    │
        │                                                    │
        │   Python: run.py ──► api_server.py (FastAPI)       │
        │                          │   Uvicorn/Gunicorn      │
        │                          ▼                         │
        │                   workflow_db.py                   │
        │                  (WorkflowDatabase)                │
        │                                                    │
        │   Node:   src/server.js (Express)                  │
        │                          │                         │
        │                          ▼                         │
        │                   src/database.js                  │
        └──────────────────────────┬─────────────────────────┘
                                   │
                ┌──────────────────┼───────────────────┐
                ▼                  ▼                   ▼
        database/workflows.db   workflows/**.json   static/ (+ docs/ mirror)
        (SQLite, FTS5, WAL)     (source of truth)   (front end assets)
                                                          ▲
                                            context/*.json (category maps)

The workflow .json files in workflows/ are the source of truth. The database is a derived, rebuildable index — deleting it and re-indexing reproduces all state.

  1. Client calls GET /api/workflows?q=...&trigger=....
  2. api_server.py parses/validates query params via Pydantic-typed FastAPI signatures.
  3. It delegates to WorkflowDatabase.search_workflows() in workflow_db.py.
  4. If a query string is present, the DB runs an FTS5 MATCH against workflows_fts, joined to the workflows table, ordered by FTS rank; otherwise it runs a filtered table scan ordered by analyzed_at.
  5. Results are validated into WorkflowSummary Pydantic models and returned as a paginated SearchResponse.

2.3 Component inventory

Component File Responsibility
Launcher run.py Dependency check, directory setup, index bootstrap, start Uvicorn
API app api_server.py FastAPI app, routes, CORS, GZip, rate limiting, filename validation
Data layer workflow_db.py SQLite schema, indexing, FTS search, stats, categories
Node API src/server.js Express server mirroring the core endpoints
Node data layer src/database.js WorkflowDatabase (sqlite3) — schema, indexing, FTS search
Node indexer src/index-workflows.js CLI to (re)build the database in the Node stack
Front end docs/js/search.js, docs/js/app.js Client search, filtering, cards, modal, keyboard shortcuts
Category data context/unique_categories.json, context/search_categories.json Category list + filename→category mappings

3. Requirements

3.1 Runtime

Requirement Detail
Python 3.9–3.12 (dependency pins target this range)
Node.js ≥18 (only if using the Node stack; see engines in the bundled package.json)
OS Linux, macOS, or Windows (paths handled cross-platform)
Memory Modest; the prod Compose overlay caps the container at 512 MB
Disk Source JSON collection + ~tens of MB for the SQLite index

3.2 Python dependencies (requirements.txt)

Package Pinned version Role
fastapi 0.109.0 Web framework for the core API
uvicorn[standard] 0.27.0 ASGI server (development / single-process)
pydantic 2.5.3 Request/response models and validation
gunicorn 21.2.0 Production process manager (multi-worker)
PyJWT 2.8.0 JWT tokens — used only by the standalone user-management module
passlib[bcrypt] 1.7.4 Password hashing — standalone user-management module
python-multipart 0.0.9 Form parsing (auth endpoints)
httpx 0.26.0 Outbound HTTP — used by the standalone integration hub
requests 2.31.0 Outbound HTTP (sync)
psutil 5.9.8 System metrics — standalone performance monitor
email-validator 2.1.0 Email validation — standalone user-management module

Note

Several of these packages (PyJWT, passlib, psutil, email-validator, python-multipart) are required only by the standalone feature modules in Section 9, not by the core search server. The core server needs only fastapi, uvicorn, pydantic, and the Python standard library (sqlite3).


4. Configuration Reference

All configuration is via environment variables and command-line flags. There is no config file for the core server.

4.1 Environment variables

Variable Default Consumed by Purpose
WORKFLOW_DB_PATH workflows.db workflow_db.py Path to the SQLite database. run.py overrides this to database/workflows.db at startup.
CI (unset) run.py If true/1/yes, skip indexing on startup (same as --skip-index).
ADMIN_TOKEN (unset) api_server.py Gates POST /api/reindex. If unset, the reindex endpoint is disabled (returns 503).
NODE_ENV (unset) src/server.js Standard Node environment switch for the Node stack.
JWT_SECRET_KEY (empty) src/user_management.py (standalone) Secret for signing JWTs in the optional auth module.
ADMIN_PASSWORD (empty) src/user_management.py (standalone) Initial admin password for the optional auth module.

The Docker Compose overlays set additional process-level variables (ENVIRONMENT, LOG_LEVEL, DEBUG, RELOAD, ENABLE_METRICS, MAX_WORKERS) consumed by the container entrypoint/compose rather than the Python code directly.

Caution

ADMIN_TOKEN is checked with a plain string comparison and passed as a query parameter (?admin_token=...) to /api/reindex. Query parameters are commonly logged by proxies and servers. If you enable reindexing, terminate TLS in front of the service, restrict the endpoint at the proxy, and rotate the token if it may have been logged.

4.2 Command-line flags

run.py (primary launcher):

Flag Default Effect
--host 127.0.0.1 Bind address
--port 8000 Bind port
--reindex off Force full re-index before serving
--dev off Auto-reload (passes reload=True to Uvicorn)
--skip-index off Start without indexing

api_server.py (run directly, bypassing run.py):

Flag Default Effect
--host 127.0.0.1 Bind address
--port 8000 Bind port
--reload off Auto-reload

workflow_db.py (DB CLI): --index, --force, --search "TEXT", --stats.

src/index-workflows.js (Node indexer): -f/--force, --stats.

src/server.js (Node server): -p/--port, -h/--host, --dev.


5. Database & Indexing Internals

5.1 Schema

The database (workflow_db.py → init_database()) creates one base table, one FTS5 virtual table, five indexes, and three sync triggers.

workflows table:

Column Type Notes
id INTEGER PK AUTOINCREMENT
filename TEXT UNIQUE NOT NULL Basename of the workflow file (also the API key)
name TEXT NOT NULL Human-readable name (from JSON name or derived from filename)
workflow_id TEXT The id field inside the workflow JSON
active BOOLEAN DEFAULT 0 From the workflow's active flag
description TEXT From JSON description, else generated
trigger_type TEXT Manual / Webhook / Scheduled / Complex
complexity TEXT low / medium / high
node_count INTEGER Number of nodes
integrations TEXT JSON array of detected services
tags TEXT JSON array
created_at, updated_at TEXT From the workflow JSON
file_hash TEXT MD5 of the file (change detection)
file_size INTEGER Bytes
analyzed_at TIMESTAMP When indexed

workflows_fts — FTS5 virtual table over filename, name, description, integrations, tags, configured as an external-content table (content=workflows, content_rowid=id). Three triggers (workflows_ai/workflows_ad/workflows_au) keep it in sync on insert/delete/update.

Indexes: idx_trigger_type, idx_complexity, idx_active, idx_node_count, idx_filename.

Performance PRAGMAs set at init: journal_mode=WAL, synchronous=NORMAL, cache_size=10000, temp_store=MEMORY.

5.2 Indexing pipeline (index_all_workflows)

  1. Recursively glob workflows/**/*.json.
  2. For each file: unless force_reindex, compute MD5 and compare to the stored file_hash; skip if unchanged.
  3. analyze_workflow_file() parses JSON and extracts: node count → complexity bucket; trigger type and integrations from node types (analyze_nodes()); a name (JSON name, or format_workflow_name() from the filename); and a description (JSON description, or generate_description()).
  4. INSERT OR REPLACE into workflows; triggers update the FTS index.
  5. Returns {processed, skipped, errors}.

Tip

Indexing is idempotent and incremental. Re-running after adding a handful of files reprocesses only those files. Use --force to rebuild after changing the analysis logic itself (e.g. the service-mapping table), since unchanged files would otherwise be skipped.

5.3 Integration & trigger detection

analyze_nodes() maps node type strings to friendly service names via a large service_mappings dictionary (e.g. n8n-nodes-base.slack → "Slack", @n8n/... namespaced nodes handled too). Utility nodes (set, if, merge, code, stickyNote, wait, filter, etc.) map to None and are excluded from the integration list. Trigger type is inferred from node types: a webhook node → Webhook, cron/schedule → Scheduled, otherwise Manual; a large multi-integration workflow (>10 nodes and >3 integrations) is promoted to Complex.

get_service_categories() groups services into broad buckets (messaging, email, cloud_storage, database, project_management, ai_ml, social_media, ecommerce, analytics, calendar_tasks, forms, development) used by search_by_category() and the /api/workflows/category/{category} endpoint.

Note

The user-facing display categories shown in the UI (AI Agent Development, CRM & Sales, …) come from context/*.json and the /api/categories endpoint. The internal get_service_categories() buckets above are a separate, code-level grouping used by the category-search endpoint. They are related but not identical lists.


6. Core API Reference

Served by api_server.py (FastAPI app titled "N8N Workflow Documentation API", version 2.0.0). All responses are JSON unless noted. Interactive docs at /docs, OpenAPI schema at /openapi.json.

Method Path Auth Notes
GET / none Serves static/index.html (or a setup-required page if missing)
GET /health none {"status":"healthy", ...}
GET /api/stats none StatsResponse — totals, triggers, complexity, integrations
GET /api/workflows none Search/filter; params q, trigger, complexity, active_only, page, per_page
GET /api/workflows/{filename} none Metadata + raw JSON; rate-limited, filename-validated
GET /api/workflows/{filename}/download none FileResponse of the JSON; rate-limited, filename-validated
GET /api/workflows/{filename}/diagram none Mermaid flowchart code; rate-limited, filename-validated
POST /api/reindex ADMIN_TOKEN Background re-index; ?force=, ?admin_token=; rate-limited
GET /api/integrations none Integration count summary
GET /api/categories none Category list (from context/*.json)
GET /api/category-mappings none filename→category map for client-side filtering
GET /api/workflows/category/{category} none Workflows in a service category

per_page is bounded 1–100; page ≥ 1. The search endpoint returns a SearchResponse envelope (workflows, total, page, per_page, pages, query, filters).

Middleware: GZipMiddleware (compresses responses ≥ 1000 bytes) and CORSMiddleware (restricted — see Section 7). A global exception handler returns {"detail": "Internal server error: ..."} with HTTP 500.

Warning

The global exception handler echoes the exception string into the response body. This can leak internal detail (paths, SQL fragments) to clients. Consider replacing it with a generic message and server-side logging before exposing the service publicly. See Section 11 (Improvements).

6.1 Status codes you'll see

Code Where Meaning
400 filename endpoints Invalid filename format (failed validation)
401 /api/reindex Invalid authentication token
404 filename endpoints Workflow not in DB or not on disk
429 rate-limited endpoints Rate limit exceeded (>60 req/min/IP)
503 /api/reindex Endpoint disabled (no ADMIN_TOKEN set)
500 any Unhandled error (body includes exception text)

7. Security

7.1 Path-traversal protection (validate_filename)

The three filename-bearing endpoints (detail, download, diagram) all call validate_filename() before touching the filesystem. It:

  • Decodes the input up to 3 times to defeat nested URL-encoding (%252e%252e).
  • Rejects any string containing .., slashes/backslashes, null bytes, newlines, ~, :, |, <, >, *, ?, $, ;, &.
  • Rejects absolute paths and Windows drive letters.
  • Requires the name to match ^[a-zA-Z0-9_\-]+\.json$.

As defense in depth, after locating a candidate file the handlers call Path.resolve().relative_to(workflows_path) and refuse anything resolving outside the workflows/ tree. The repository ships test_security.sh, which fires a battery of traversal payloads and asserts they're blocked (400/404), plus a positive-path download test.

Important

Because filenames are restricted to [A-Za-z0-9_-].json, any workflow file whose name contains spaces, dots (beyond the extension), or other characters will be un-downloadable through the API even though it indexes fine. Keep workflow filenames within that charset.

7.2 Rate limiting

check_rate_limit() keeps a per-IP in-memory list of request timestamps and enforces MAX_REQUESTS_PER_MINUTE = 60. It is applied to the detail, download, diagram, and reindex endpoints.

Caution

Rate-limit state is an in-process dict. It is not shared across workers or replicas and resets on restart, and it keys on request.client.host — which behind a reverse proxy is the proxy's IP unless you configure trusted forwarded headers. For real protection at scale, enforce rate limiting at the proxy/edge instead of relying on this.

7.3 CORS

api_server.py restricts CORS to an explicit allowlist: http://localhost:3000, :8000, :8080, https://zie619.github.io, and a Render community URL — with methods limited to GET/POST and headers to Content-Type/Authorization. Edit ALLOWED_ORIGINS to add your own front-end origin.

Note

The standalone enhanced_api.py module, by contrast, uses allow_origins=["*"]. That is another reason to treat the standalone modules (Section 9) as not production-ready as-is.

7.4 Authentication posture

The core server has no authentication for browsing or for the read endpoints — it is designed to serve a public, read-only catalog. The only privileged action is /api/reindex, gated by ADMIN_TOKEN. Login/JWT functionality exists only in the optional src/user_management.py module (Section 9), which is not mounted by default.

7.5 Hardening checklist

  • [ ] Run behind a TLS-terminating reverse proxy (the prod Compose overlay uses Traefik).
  • [ ] Add proxy-level auth (e.g. Traefik basicauth) if the catalog should not be public.
  • [ ] Leave ADMIN_TOKEN unset unless you actively need remote reindexing; prefer reindexing via CLI on the host.
  • [ ] Restrict /api/reindex at the proxy even when ADMIN_TOKEN is set.
  • [ ] Replace the verbose global exception handler before public exposure.
  • [ ] Enforce rate limiting at the edge, not just in-process.
  • [ ] Mount workflows/ read-only into the container (the prod overlay already does: ./workflows:/app/workflows:ro).

8. Deployment & Operations

8.1 Docker / Docker Compose

The repo provides a base docker-compose.yml plus two overlays:

  • docker-compose.dev.yml — bind-mounts the source for live editing, runs python run.py --host 0.0.0.0 --port 8000 --dev, exposes 8000/8001, and offers optional db-admin (Adminer) and file-watcher profiles.
  • docker-compose.prod.yml — restart: always, production env vars (ENVIRONMENT=production, LOG_LEVEL=warning, ENABLE_METRICS=true, MAX_WORKERS=4), named volumes for the DB and logs, a read-only mount of workflows/, resource limits (512 MB / 0.5 CPU), Traefik labels for TLS + basicauth, and optional Prometheus monitoring.

One-command bring-up (build, start, health-check, open browser):

./run-as-docker-container.sh

Manual:

docker compose up -d --build                                   # base
docker compose -f docker-compose.yml -f docker-compose.dev.yml up   # dev
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d # prod
docker compose logs -f
docker compose down

8.2 Kubernetes & Helm

  • k8s/ contains raw Kubernetes manifests.
  • helm/workflows-docs/ is a Helm chart (with templates/) for templated deployment.

Use the Helm chart for parameterized installs; fall back to the raw manifests for a quick kubectl apply -f k8s/.

8.3 Production server

For production, prefer Gunicorn (pinned in requirements.txt) managing Uvicorn workers rather than the single-process uvicorn.run() used by run.py:

gunicorn api_server:app -k uvicorn.workers.UvicornWorker -w 4 -b 0.0.0.0:8000

Warning

The in-process rate limiter and the empty-DB auto-index logic assume a single process. With multiple Gunicorn workers, ensure the database is already indexed before starting (run python workflow_db.py --index first, or start once with run.py to build it), so workers don't race to index on first request.

8.4 Routine operations

Task Command
Build/refresh index python workflow_db.py --index (add --force to rebuild)
Check catalog stats python workflow_db.py --stats or GET /api/stats
Health check GET /health
Remote reindex (if enabled) POST /api/reindex?admin_token=$ADMIN_TOKEN&force=true
Back up state Copy the database/workflows.db* files (include WAL/SHM) or just re-index from workflows/
Rotate / reset DB Delete database/workflows.db*, then re-index

Tip

The database is fully derivable from workflows/. The simplest disaster recovery is to keep the workflow JSON files under version control and re-index — no database backup strategy is strictly required.

8.5 The static / GitHub Pages mirror

docs/ is a static export intended for GitHub Pages (zie619.github.io). Its docs/js/search.js loads a pre-built api/search-index.json and does client-side filtering — there is no live server in that mode. docs/api/*.json (stats.json, integrations.json, categories.json, metadata.json) are the static data snapshots that front end consumes. Regenerate them when you publish a new static build.


9. Optional / Standalone Feature Modules

Important

Everything in this section lives under src/*.py, builds its own FastAPI application object, and is not imported or mounted by api_server.py. Running the core server does not expose these endpoints. They appear to be experimental/auxiliary and are documented here for completeness and for developers who may wish to wire them in. Treat them as not production-ready without review (permissive CORS, query-string secrets, simulated data — noted below).

Module App object / port Endpoints (prefix) Notes
ai_assistant.py ai_app @ :8001 POST /chat, GET /chat/interface Keyword/intent heuristic search — not an LLM. Returns matched workflows + canned suggestions.
analytics_engine.py analytics_app @ :8002 /analytics/overview, /trends, /insights, /dashboard Real DB aggregations except get_trend_analysis(), which returns hardcoded simulated values.
enhanced_api.py EnhancedAPI.app /api/v2/workflows, /api/v2/workflows/search, /api/v2/recommendations, /api/v2/analytics/* CORS *. Imports community features.
community_features.py helper create_community_api_endpoints(app) /api/workflows/{id}/rate, /ratings, /stats, /view, /download, /top-rated, /most-popular Adds ratings/reviews/views/collections tables to the SQLite DB.
integration_hub.py own app /integrations/{github,slack,discord,airtable,notion}, /webhooks/{endpoint}, /integrations/status Outbound sync helpers via httpx/requests.
performance_monitor.py own app /monitor/metrics, /history, /alerts, /dashboard, WebSocket Uses psutil to sample system metrics.
user_management.py own app /auth/{register,login,me}, /users CRUD, /auth/dashboard JWT (PyJWT) + bcrypt (passlib). Creates a default admin. Requires JWT_SECRET_KEY, ADMIN_PASSWORD.

9.1 Community features data model

If wired in, community_features.py adds these SQLite tables alongside workflows: workflow_ratings (1–5 star, unique per (workflow_id,user_id)), workflow_stats (aggregate ratings/views/downloads), user_profiles, workflow_collections (favorites, JSON id array), and workflow_comments (threaded via parent_id). Ratings outside 1–5 raise ValueError('Rating must be between 1 and 5').

9.2 Wiring one in (developer note)

These modules expose either a module-level app or a create_* helper. To integrate, e.g., community endpoints into the main server you would import and call create_community_api_endpoints(app) against the api_server.py app and run a single process. Before doing so, review CORS, auth, secret handling, and the SQL-string building in ai_assistant.search_workflows_intelligent() (see Section 11).


10. Code Quality & Conventions

Strengths observed in the source:

  • Consistent, well-commented modules with docstrings on public functions.
  • Pydantic models (WorkflowSummary, SearchResponse, StatsResponse) give the core API a typed, self-documenting contract and power the /docs UI.
  • Parameterized SQL in the core search/stats/category paths (no string interpolation of user input).
  • Deliberate security work at the file boundary, with a dedicated test script.
  • The Python and Node implementations are kept conceptually aligned (same schema, same complexity thresholds, same format_workflow_name rules).

Patterns & conventions:

  • The filename (basename) is the public identity of a workflow throughout the API.
  • Complexity is a pure function of node count (≤5 / ≤15 / else).
  • JSON-encoded arrays (integrations, tags) are stored as TEXT and parsed on read.
  • Connections open and close per query (no shared pool) — fine at this scale, simple to reason about.

11. Potential Improvements & Tech Debt

These are observations from the source, prioritized for an operator/maintainer.

Caution

Bug — search_workflows_intelligent() in ai_assistant.py. When the detected intent is "integration", the code does params.append('Webhook') but params is never defined in that scope (and the subsequent query is executed without parameters), which will raise a NameError/parameter mismatch. This standalone module's intent-based branch is effectively broken. Fix before wiring the AI assistant in.

Warning

SQL string interpolation in the standalone AI module. ai_assistant.py builds its WHERE clause by interpolating extracted keywords directly into SQL (name LIKE '%{keyword}%'). Keywords are derived from a fixed vocabulary so exploitation is limited, but this pattern should be converted to parameterized queries before any production use. The core server does not have this issue.

Other items:

  • Verbose global exception handler (api_server.py) leaks exception text to clients — replace with a generic message + server-side logging.
  • /api/reindex token via query string — move to a header (Authorization/X-Admin-Token) to avoid proxy/access-log leakage, and use a constant-time comparison.
  • In-process rate limiting — does not survive restarts or scale across workers; move to the edge or a shared store.
  • /api/integrations returns an empty list with only a count — it could surface the ranked integration list already present in docs/api/integrations.json.
  • Simulated analytics — analytics_engine.get_trend_analysis() returns hardcoded values; either implement real historical tracking or label it clearly as a demo.
  • Repository hygiene — the unrelated medcards-ai/ Next.js subproject and several experimental src/ modules inflate the repo and dependency surface; consider splitting them into separate repositories.
  • Known issue #156 (No module named 'workflow_db') stems from running outside the repo root; documenting the working directory requirement (done in the User Guide) mitigates it.

12. Testing

Script What it covers
test_security.sh Fires path-traversal payloads at /download and asserts 400/404; verifies a valid download returns 200. Requires the server running on :8000.
test_api.sh Smoke-tests search, categories, integrations, complexity filter, pagination, and single-workflow fetch via curl.
test_workflows.py Validates sample workflow JSON files (presence of name, nodes, connections) across representative categories; reports a per-category pass rate.

Run them against a locally running instance:

python run.py --skip-index &     # or with a built DB
bash test_api.sh
bash test_security.sh
python test_workflows.py

Note

These are shell/script smoke tests, not a unit-test suite. There is no pytest configuration in the core project; coverage of the indexing/search logic is via the live API scripts above.


13. Quick Reference

Launch (Python):

python run.py [--host H] [--port P] [--reindex] [--dev] [--skip-index]
python api_server.py [--host H] [--port P] [--reload]

Database CLI:

python workflow_db.py [--index] [--force] [--search "TEXT"] [--stats]

Node stack:

node src/index-workflows.js [--force] [--stats]
node src/server.js [-p PORT] [-h HOST] [--dev]

Production (Gunicorn):

python workflow_db.py --index      # build DB first
gunicorn api_server:app -k uvicorn.workers.UvicornWorker -w 4 -b 0.0.0.0:8000

Containers:

./run-as-docker-container.sh
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d

Environment variables:

Var Purpose
WORKFLOW_DB_PATH SQLite path (default workflows.db; run.py sets database/workflows.db)
CI Skip indexing on startup
ADMIN_TOKEN Enables/guards POST /api/reindex
NODE_ENV Node server environment
JWT_SECRET_KEY, ADMIN_PASSWORD Standalone user-management module only

Core endpoints: /, /health, /api/stats, /api/workflows, /api/workflows/{filename}[/download|/diagram], /api/reindex, /api/integrations, /api/categories, /api/category-mappings, /api/workflows/category/{category}, /docs.