# Flowchad Setup

> Initialize Flowchad in a project — auto-discover existing tests, analytics, specs, and user flows, then scaffold flow definitions. Run as first step before any /flow-walk.

- Skill: `fellowship-dev/flowchad-setup` (Agent Skill)
- Install (CLI): `npx skillmds@latest add fellowship-dev/flowchad-setup`
- Raw SKILL.md: https://api.skillmd.com/api/skills/fellowship-dev/flowchad-setup/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Data & Analytics
- Author: fellowship-dev (https://skillmd.com/u/fellowship-dev)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/fellowship-dev/flowchad-setup

---


# Flowchad Setup

Initialize Flowchad in a project by discovering what already exists, asking what's missing, and scaffolding flow definitions.

## Phase 0: Update Check

Before doing anything else, check if flowchad needs updating:

```bash
if [ -f ".flowchad/.version" ] && [ -f "scripts/check-updates.sh" ]; then
  bash scripts/check-updates.sh
fi
```

If an update is available, inform the user: "A newer version of flowchad is available. Run `bash scripts/update.sh` to update, then re-run `/flowchad-setup`." Do not block — proceed with setup regardless.

## Phase 1: Auto-Discovery (no user input)

Scan the project silently. Gather everything before asking a single question.

### 1a. Detect Test Framework & Existing Flows

Search for e2e/integration tests — these are flows already defined in code.

```bash
# Find test files
find . -type f \( \
  -name "*.spec.ts" -o -name "*.spec.js" \
  -o -name "*.test.ts" -o -name "*.test.js" \
  -o -name "*.e2e.ts" -o -name "*.e2e.js" \
  -o -name "*_spec.rb" -o -name "*_test.rb" \
  -o -name "*.feature" \
  -o -path "*/cypress/**/*.cy.*" \
  -o -path "*/playwright/**/*" \
  -o -path "*/e2e/**/*" \
  -o -path "*/integration/**/*" \
\) 2>/dev/null | head -50
```

For each test file found, extract:
- What user flow it covers (sign up, login, checkout, etc.)
- What URLs/routes it hits
- What assertions it makes (these become `expect` in flow definitions)

### 1b. Detect Analytics SDKs

```bash
# Check dependency files for analytics
grep -r "mixpanel\|posthog\|segment\|amplitude\|google-analytics\|gtag\|plausible\|matomo" \
  package.json Gemfile requirements.txt pyproject.toml composer.json \
  2>/dev/null

# Check for SDK imports in source code
grep -rl "mixpanel\|posthog\|analytics\|segment" \
  --include="*.js" --include="*.ts" --include="*.rb" --include="*.py" \
  --include="*.jsx" --include="*.tsx" \
  src/ app/ lib/ pages/ components/ 2>/dev/null | head -20

# Check for MCP servers already configured
cat .mcp.json 2>/dev/null
cat .claude/mcp.json 2>/dev/null
```

### 1c. Detect Speckit Specs

```bash
ls .speckit/ specs/ 2>/dev/null
ls .claude/commands/speckit-* .claude/commands/spec-* 2>/dev/null
```

### 1d. Detect App Framework & Routes

```bash
# Rails
[ -f config/routes.rb ] && echo "RAILS" && cat config/routes.rb

# Next.js pages/app router
[ -d pages ] && echo "NEXTJS_PAGES" && find pages -name "*.tsx" -o -name "*.jsx" 2>/dev/null
[ -d app ] && echo "NEXTJS_APP" && find app -name "page.tsx" -o -name "page.jsx" 2>/dev/null

# Django
find . -name "urls.py" -not -path "*/venv/*" 2>/dev/null | head -5

# Express/Hono/Fastify
grep -r "app\.\(get\|post\|put\|delete\|route\)" --include="*.ts" --include="*.js" \
  src/ routes/ 2>/dev/null | head -20
```

### 1e. Detect i18n Configuration

Run `scripts/detect-i18n.sh` (relative to the project root) to auto-detect supported locales:

```bash
bash scripts/detect-i18n.sh .
# Output: space-separated locale codes, e.g. "en" or "en es fr"
```

The script checks (in order, first match wins):
1. **Next.js** — `i18n.locales` array in `next.config.{js,mjs,ts,cjs}`
2. **locales/ or messages/ directories** — subdirectory names or top-level JSON/YAML filenames
3. **Strapi** — i18n plugin detection (falls through if locales are DB-only)
4. **hreflang tags** — `<link rel="alternate" hreflang=...>` scraped from `config.yml` base URL
5. **Default** — `en` (no locale prefix)

Store result as `$DETECTED_LOCALES` (e.g., `"en"` or `"en es"`). Convert to YAML list format: `[en]` or `[en, es]`.

**On re-run (existing config.yml):** compare detected locales to the current `locales:` field. If changed, update the field and all existing flows in `.flowchad/flows/*.yml`.

### 1f. Detect Dev Server, URLs & Credentials

FlowChad is designed to run against the local dev server first. Detect the dev server command and URLs in priority order: **localhost > staging > production**.

```bash
# 1. Detect dev server command
grep -A2 '"dev"\|"start"\|"serve"' package.json 2>/dev/null
grep -m1 "rails s\|bin/dev\|foreman start" Procfile* Makefile 2>/dev/null
grep -m1 "runserver\|manage.py" Makefile 2>/dev/null

# 2. Detect dev server port
grep -ri "PORT\|localhost\|127\.0\.0\.1\|0\.0\.0\.0" \
  .env .env.development .env.local \
  config/environments/development.rb \
  2>/dev/null | head -10

# 3. Detect staging/production URLs (lower priority)
grep -ri "staging\|test.*url\|base.*url\|APP_URL\|NEXT_PUBLIC.*URL" \
  .env.example .env.test .env.staging .env.production \
  config/environments/staging.rb config/environments/production.rb \
  2>/dev/null

# 4. Check for seed/fixture users
find . -path "*/seeds*" -o -path "*/fixtures*" -o -path "*/factories*" \
  2>/dev/null | head -10
```

## Phase 2: Present Findings & Ask

Present a summary:

```
## Flowchad Setup — Discovery Report

**Framework:** [Rails / Next.js / etc.]
**Dev server:** [npm run dev / rails s / not detected]
**Dev URL:** [http://localhost:3000 / not detected]
**Staging URL:** [found / not found]
**Production URL:** [found / not found]
**Test files found:** N files across [Cypress / Playwright / RSpec / etc.]
**Existing flows detected:** [list of user journeys found in tests]
**Analytics:** [Mixpanel / PostHog / none]
**Speckit:** [installed / not found]
**Routes:** N public routes detected
**Test credentials:** [found in fixtures / not found]
**i18n locales:** [en] (English-only) | [en, es, ...] (detected from {source})
```

Then ask ONLY what's missing. **URL priority is localhost > staging > production** — FlowChad runs against the local dev server by default:

- If dev server detected: "I found `npm run dev` on port 3000. Want to use `http://localhost:3000` as the default URL? (Make sure your dev server is running)"
- If no dev server detected: "What port does your dev server run on? (e.g., `http://localhost:3000`). If you don't have a local setup, provide a staging or production URL instead."
- If no test credentials: "Do you have a test account? (email/password)"
- If analytics found: "Found [Mixpanel] — want me to set up the MCP server for funnel data?"
- If tests found: "Found N e2e tests — want me to convert them to Flowchad flow definitions?"
- If no tests: "No existing e2e tests found. Want me to generate flow definitions from your routes?"

## Phase 3: Scaffold

After user answers, populate the existing `.flowchad/` structure.

### Update config.yml

Fill in discovered values in `.flowchad/config.yml`:

```yaml
name: {project_name}
url: {localhost_url or staging_url or production_url}  # prefer localhost
type: {saas|website|mobile|internal}

timing:
  slow: 3
  critical: 10

credentials:
  email: $TEST_USER_EMAIL
  password: $TEST_USER_PASSWORD

analytics:
  provider: {mixpanel|posthog|none}
  mcp: true

# Detected by /flowchad-setup via scripts/detect-i18n.sh
# [en] = English-only site. [en, es] = locale-prefixed routes exist for /es/*.
locales: [{detected_locales_csv}]
```

### Convert Existing Tests to Flow Definitions

For each e2e test found, generate a `.yml` flow definition in `.flowchad/flows/`.

**Naming rules:**
- `name` field: a descriptive sentence explaining the scenario (actor + action + outcome)
- Filename: the scenario as a kebab-case slug
- Add a `context` block with relevant preconditions extracted from the test setup
- Write rich `expect` strings that explain what a human would judge, not just pass/fail

```yaml
# .flowchad/flows/new-user-signs-up-with-email-and-password.yml
# Auto-generated from: {source_test_file}
name: New user signs up with email and password and lands on the dashboard
url: {start_url}
tags: [{category}]
priority: P0
locales: [{detected_locales_csv}]  # from scripts/detect-i18n.sh
context:
  user: new_account
  auth: logged_out
steps:
  - action: navigate
    url: {url}
    expect: >
      {Rich description from test assertion — what the page should look like and why}
    timing: 3s
```

### Generate Flows from Routes (if no tests exist)

For each public route, generate a flow with a descriptive name:

```yaml
# .flowchad/flows/visitor-loads-homepage-and-sees-hero-section.yml
name: Visitor loads the homepage and sees the hero section with CTA
url: {route_path}
tags: [auto-generated]
priority: P2
locales: [{detected_locales_csv}]  # from scripts/detect-i18n.sh
context:
  user: anonymous
  auth: logged_out
steps:
  - action: navigate
    url: {route_path}
    expect: >
      Page loads successfully with main content visible.
      No error pages, broken layouts, or missing assets.
    timing: 3s
```

### Set Up Analytics MCP (if applicable)

If Mixpanel detected, add to `.mcp.json`:
```json
{
  "mcpServers": {
    "mixpanel": {
      "command": "npx",
      "args": ["-y", "@mixpanel/mcp-server"],
      "env": { "MIXPANEL_TOKEN": "${MIXPANEL_TOKEN}" }
    }
  }
}
```

If PostHog detected:
```json
{
  "mcpServers": {
    "posthog": {
      "command": "npx",
      "args": ["-y", "@posthog/mcp-server"],
      "env": {
        "POSTHOG_API_KEY": "${POSTHOG_API_KEY}",
        "POSTHOG_HOST": "${POSTHOG_HOST}"
      }
    }
  }
}
```

## Phase 4: Summary

Print what was created:

```
## Flowchad initialized!

Created:
- .flowchad/config.yml (updated)
- .flowchad/flows/ — {N} flow definitions
- .mcp.json updated with {analytics_provider} (if applicable)

i18n: detected locales [{detected_locales_csv}] from {source}.
      Flow walk will only generate /{locale}/* paths for confirmed locales.
      Re-run /flowchad-setup to refresh if i18n config changes.

Next steps:
1. Review generated flows in .flowchad/flows/
2. Add test credentials to your .env
3. Run /flow-walk {first_flow} to walk your first flow
```

