---
name: dev-start
description: Launch SmartStack dev environment (backend + frontend + admin credentials)
argument-hint: "[--stop] [--reset] [--backend-only] [--frontend-only]"
model: haiku
allowed-tools: Read, Bash, Glob, Write
---

## Arguments
$ARGUMENTS

## Current state (auto-injected)

- Dev session: !`cat .claude/dev-session.json 2>/dev/null || echo "no session"`
- Backend port check: !`netstat.exe -ano 2>/dev/null | grep -E ":(5142|5290) .*LISTENING" | head -5 || echo "no backend listening"`
- Frontend port check: !`netstat.exe -ano 2>/dev/null | grep -E ":(6173|3000) .*LISTENING" | head -5 || echo "no frontend listening"`
- API directory: !`ls -d src/*.Api 2>/dev/null || echo "no API found"`
- Web directory: !`ls -d web/*-web 2>/dev/null || echo "no web found"`
- Local config: !`cat src/*.Api/appsettings.Local.json 2>/dev/null || echo "no local config"`
- Frontend env standalone: !`cat web/*-web/.env.standalone 2>/dev/null || echo "no .env.standalone"`
- Frontend env development: !`cat web/*-web/.env.development 2>/dev/null || echo "no .env.development"`

<objective>
Launch the SmartStack development environment in one command: detect configuration, validate config coherence, start backend + frontend, and provide admin credentials.
Idempotent: safe to run multiple times. Detects already-running processes.
</objective>

<quick_start>
```bash
/dev-start                  # Launch everything (idempotent)
/dev-start --stop           # Stop backend + frontend
/dev-start --reset          # Force admin password reset
/dev-start --backend-only   # Launch only the backend
/dev-start --frontend-only  # Launch only the frontend
```
</quick_start>

<subcommands>

| Command | Description |
|---------|-------------|
| `/dev-start` | Launch all (idempotent) + validate configs |
| `/dev-start --stop` | Stop backend + frontend via taskkill.exe |
| `/dev-start --reset` | Force reset admin password |
| `/dev-start --backend-only` | Launch only backend |
| `/dev-start --frontend-only` | Launch only frontend |

</subcommands>

<workflow>

## Handle --stop

If `--stop` argument detected, execute the stop workflow and exit:

1. Find backend PID:
   ```bash
   netstat.exe -ano | grep ":${API_PORT} .*LISTENING" | awk '{print $5}' | head -1
   ```
2. If found: `taskkill.exe /PID $PID /F`
3. Find frontend PID:
   ```bash
   netstat.exe -ano | grep ":${WEB_PORT} .*LISTENING" | awk '{print $5}' | head -1
   ```
4. If found: `taskkill.exe /PID $PID /F`
5. Display stopped status and exit.

If no processes found, display "Nothing running" and exit.

## Step 1: Detect project

Find the API and Web directories:
- API: `src/*.Api` (first match)
- Web: `web/*-web` (first match)

If neither found, display error and exit.

## Step 2: Detect environment and ports

Check if `appsettings.Local.json` exists in the API directory:

| Condition | Mode | Backend | Frontend | Backend command | Frontend command |
|-----------|------|---------|----------|-----------------|------------------|
| `appsettings.Local.json` exists | **Local** | Port from `Kestrel:Endpoints:Http:Url` | Port from `.env.standalone` or `package.json` local script | `dotnet run --launch-profile Local` | `npm run local` |
| No local config | **Development** | Port 5142 (launchSettings http profile) | Port 6173 (vite default) | `dotnet run --environment Development` | `npm run dev` |

**Reading ports:**
- **Local backend port**: Parse `appsettings.Local.json` -> `Kestrel.Endpoints.Http.Url` -> extract port from URL (e.g., `http://localhost:5290` -> `5290`)
- **Local frontend port**: Parse `.env.standalone` -> look for port in `VITE_API_URL`, or parse `package.json` -> `scripts.local` for `--port` flag
- **Dev backend port**: Default `5142`
- **Dev frontend port**: Default `6173`

## Step 3: Validate config coherence

**CRITICAL: Verify that backend and frontend configs are consistent.**

### Rules to check:

| Rule | Backend source | Frontend source | Validation |
|------|---------------|-----------------|------------|
| Frontend calls correct backend | Port API (Kestrel or launchSettings) | `VITE_API_URL` in `.env.standalone` (Local) or `.env.development` (Dev) | Port in VITE_API_URL must match API port |
| Backend allows frontend (CORS) | `SmartStack:CorsOrigins[]` in appsettings | Frontend port | CorsOrigins must contain `http://localhost:{WEB_PORT}` |
| OAuth redirects to correct frontend | `Authentication:FrontendUrl` in appsettings | Frontend port | FrontendUrl must point to `http://localhost:{WEB_PORT}` |
| Local files exist in pairs | `appsettings.Local.json` | `.env.standalone` | If one exists, the other must too |

### In Local mode:

1. Read `appsettings.Local.json` -> extract `Kestrel:Endpoints:Http:Url` (API port)
2. Read `appsettings.Local.json` -> extract `Authentication:FrontendUrl` (expected frontend URL)
3. Read `.env.standalone` -> extract `VITE_API_URL` (expected API URL by frontend)
4. Verify `VITE_API_URL` port matches Kestrel port
5. Verify `Authentication:FrontendUrl` port matches frontend port
6. If `appsettings.Local.json` exists but NOT `.env.standalone` -> **create `.env.standalone`** with correct values (ask user first)
7. If `.env.standalone` exists but NOT `appsettings.Local.json` -> **warn** (config incomplete)

### In Development mode:

1. Verify `.env.development` contains `VITE_API_URL=http://localhost:5142` (NOT 5290 which is Local profile)
2. Verify `appsettings.json` -> `SmartStack:CorsOrigins` contains `http://localhost:6173`
3. Verify `Authentication:FrontendUrl` = `http://localhost:6173`

### If incoherence detected:

1. Display a clear WARNING with detected values vs expected values
2. Propose to auto-correct (write the correct files)
3. If user refuses, continue with a warning

### Output format for coherence:

```
Config Coherence Check:
  [OK] VITE_API_URL matches backend port (5290)
  [OK] CORS allows frontend (http://localhost:3000)
  [OK] OAuth redirect matches frontend
  [OK] Local config files paired

  -- OR --

  [WARN] VITE_API_URL=http://localhost:5290 but backend runs on port 5142
         Expected: VITE_API_URL=http://localhost:5142
  [WARN] .env.standalone missing (appsettings.Local.json exists)
         -> Creating .env.standalone with correct values...
```

## Step 4: Check if already running

```bash
netstat.exe -ano | grep ":${API_PORT} .*LISTENING"
netstat.exe -ano | grep ":${WEB_PORT} .*LISTENING"
```

If `--backend-only`: skip frontend checks.
If `--frontend-only`: skip backend checks.

## Step 5: Launch backend

If NOT already running and NOT `--frontend-only`:

```bash
# cd into the API directory first
cd {API_DIR} && dotnet run {LAUNCH_ARGS}
```

Use `Bash(run_in_background=true)` so it runs in background.

## Step 6: Launch frontend

If NOT already running and NOT `--backend-only`:

```bash
# cd into the Web directory first
cd {WEB_DIR} && npm run {SCRIPT}
```

Use `Bash(run_in_background=true)` so it runs in background.

## Step 7: Handle admin password

1. If `.claude/dev-session.json` exists and contains a password and `--reset` NOT specified -> reuse stored credentials
2. If `--reset` OR no stored password:
   a. If backend was just launched, wait for it to be UP first:
      ```bash
      # Poll up to 30 seconds (10 attempts x 3s)
      for i in $(seq 1 10); do
        netstat.exe -ano | grep ":${API_PORT} .*LISTENING" && break
        sleep 3
      done
      ```
   b. Run: `smartstack admin reset --force --json`
   c. Parse JSON output to extract email and password
   d. Write `.claude/dev-session.json`:
      ```json
      {
        "admin_password": "...",
        "admin_email": "local.admin@smartstack.local",
        "last_reset": "2026-03-10T14:30:00Z",
        "api_port": 5142,
        "web_port": 6173,
        "environment": "Development"
      }
      ```
   e. Verify `.claude/dev-session.json` is in `.gitignore`. If not, warn the user (contains credentials).

## Step 8: Display connection info

```
================================================================
          SMARTSTACK DEV ENVIRONMENT
================================================================

  Backend:   http://localhost:{API_PORT}        [RUNNING|STARTING]
  Frontend:  http://localhost:{WEB_PORT}        [RUNNING|STARTING]
  Swagger:   http://localhost:{API_PORT}/scalar

  Email:     local.admin@smartstack.local
  Password:  xxxxxxxxxxxxxx

  Environment: {Development|Local}
  Config:      OK | WARNING (details)
================================================================
```

</workflow>

<important_notes>

1. **Backend must be UP before admin reset** - Poll the port (2-3s intervals, max 30s) before attempting password reset
2. **Cross-worktree support** - Detect the correct API directory regardless of which worktree we're in
3. **No MCP required** - This skill only uses bash commands and the `smartstack` CLI
4. **Config coherence is critical** - Mismatched ports between backend/frontend is the #1 cause of "it doesn't work" issues
5. **Idempotent** - Running twice should detect already-running processes and reuse stored credentials
6. **dev-session.json contains secrets** - Must be in `.gitignore`

</important_notes>

<success_criteria>
- Backend and frontend detected and launched (or already running)
- Config coherence validated (or warnings displayed)
- Admin credentials available (reused or freshly reset)
- Connection info displayed in clear format
- No errors on repeated invocations (idempotent)
</success_criteria>
