---
name: step-start
description: Create new branch with worktree
next_step: null
---

# Step: START - Create Branch

## YOUR TASK:

Create a new feature/release/hotfix branch with optional worktree setup.

**ULTRA THINK about branch naming and base selection.**

---

## INPUT PARSING:

```
{branch_type} = feature | release | hotfix
{branch_name} = normalized name (kebab-case)
{no_worktree} = --no-worktree flag present
```

**From flags:**
- `-f {name}` → branch_type=feature, branch_name={name}
- `-r {name}` → branch_type=release, branch_name={name}
- `-h {name}` → branch_type=hotfix, branch_name={name}

---

## EXECUTION SEQUENCE:

### 1. Load Config and Analyze Context

```bash
# Load GitFlow config (sets GF_* variables)
# See _shared.md → READ_GITFLOW_CONFIG for all variables
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }

CURRENT_BRANCH=$(git branch --show-current)
git fetch origin --quiet

# Version from config
VERSION="$GF_VERSION"
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "none")

# Develop ahead of main?
DEVELOP_AHEAD=$(git rev-list --count origin/$GF_MAIN_BRANCH..origin/$GF_DEVELOP_BRANCH 2>/dev/null || echo "0")

# Working directory status
DIRTY=$(git status --porcelain | wc -l)
```

**Display:**
```
Current: {CURRENT_BRANCH} | Version: {VERSION} | Tag: {LAST_TAG}
Develop → Main: {DEVELOP_AHEAD} commits {DEVELOP_AHEAD > 10 ? "(Release recommended)" : ""}
```

### 2. Interactive Questions (if no args)

**If branch_type missing:**
```yaml
AskUserQuestion:
  header: "Type"
  question: "What type of branch?"
  options:
    - label: "Feature"
      description: "New feature from develop"
    - label: "Release v{X.Y+1.0}"
      description: "Prepare release from develop"
    - label: "Hotfix"
      description: "Urgent fix from main"
```

**If branch_name missing:**
```yaml
AskUserQuestion:
  header: "Name"
  question: "Branch name? (will be normalized to kebab-case)"
  # Free text input
```

### 3. Normalize and Validate

```bash
# Normalize name
normalize_branch_name() {
  echo "$1" | tr '[:upper:]' '[:lower:]' | \
    sed 'y/àâäéèêëïîôùûüçœæ/aaaeeeeiioouucoa/' | \
    sed "s/[ _']/-/g" | sed 's/[^a-z0-9-]//g' | \
    sed 's/--*/-/g' | sed 's/^-//;s/-$//' | cut -c1-50
}

BRANCH_NAME=$(normalize_branch_name "$branch_name")
FULL_BRANCH="${branch_type}/${BRANCH_NAME}"

# Check if exists
LOCAL_EXISTS=$(git branch --list "$FULL_BRANCH")
REMOTE_EXISTS=$(git branch -r --list "origin/$FULL_BRANCH")

[ -n "$LOCAL_EXISTS" ] || [ -n "$REMOTE_EXISTS" ] && {
  echo "ERROR: Branch '$FULL_BRANCH' already exists"
  # Options: Different name | Checkout existing | Delete and recreate
}
```

### 4. Determine Base Branch

| Type | Base Branch | Target |
|------|-------------|--------|
| feature | develop | develop |
| release | develop | main + develop |
| hotfix | main | main + develop |

```bash
case "$branch_type" in
  feature) BASE_BRANCH="develop"; TARGET="develop" ;;
  release) BASE_BRANCH="develop"; TARGET="main" ;;
  hotfix)  BASE_BRANCH="main"; TARGET="main" ;;
esac
```

### 5. Handle Dirty Working Directory

```bash
[ "$DIRTY" -gt 0 ] && {
  echo "Working directory has uncommitted changes"
  # Options: Stash | Commit | Continue anyway | Cancel
}
```

### 6. Create Branch and Worktree

**Read worktree mode from config (already loaded by read_gitflow_config):**
```bash
WORKTREE_MODE="$GF_WORKTREE_MODE"
```

**Mode: organized (uses absolute paths from config)**
```bash
case "$branch_type" in
  feature) WORKTREE_PATH="$GF_FEATURES_PATH/$BRANCH_NAME" ;;
  release) WORKTREE_PATH="$GF_RELEASES_PATH/v$VERSION" ;;
  hotfix)  WORKTREE_PATH="$GF_HOTFIXES_PATH/$BRANCH_NAME" ;;
esac

mkdir -p "$(dirname $WORKTREE_PATH)"
git worktree add -b "$FULL_BRANCH" "$WORKTREE_PATH" "origin/$BASE_BRANCH"
```

**Mode: --no-worktree**
```bash
git checkout "$BASE_BRANCH" && git pull origin "$BASE_BRANCH"
git checkout -b "$FULL_BRANCH"
```

### 6b. Push Branch to Remote (AUTOMATIC)

**ALWAYS push immediately after branch creation:**
```bash
git push -u origin "$FULL_BRANCH"

# CRITICAL: Verify push and update tracking refs
git fetch origin $FULL_BRANCH:refs/remotes/origin/$FULL_BRANCH --force --quiet
LOCAL_SHA=$(git rev-parse HEAD)
REMOTE_SHA=$(git rev-parse origin/$FULL_BRANCH)
if [ "$LOCAL_SHA" = "$REMOTE_SHA" ]; then
  echo "✅ Branch pushed and verified - origin/$FULL_BRANCH in sync"
else
  echo "⚠️ Push verification failed"
  echo "  Local:  $LOCAL_SHA"
  echo "  Remote: $REMOTE_SHA"
fi
```

### 7. Create Local Environment Config (Backend + Frontend)

**Detect project structure:**
```bash
# Find API project directory
API_DIR=$(find "$WORKTREE_PATH" -type d -name "*.Api" -path "*/src/*" | head -1)
# Find Web project directory
WEB_DIR=$(find "$WORKTREE_PATH" -type d -name "*-web" -path "*/web/*" | head -1)

# Generate unique ports based on branch name hash (to avoid conflicts between worktrees)
# Use shasum (portable across macOS/Linux/Windows Git Bash) with md5sum fallback
HASH=$(echo "$BRANCH_NAME" | shasum 2>/dev/null || echo "$BRANCH_NAME" | md5sum 2>/dev/null || echo "$BRANCH_NAME" | cksum)
HASH=$(echo "$HASH" | cut -c1-4)
HASH_NUM=$((16#$HASH % 100))
API_PORT=$((5200 + HASH_NUM))
WEB_PORT=$((5300 + HASH_NUM))

# Project name from config (not from pwd)
PROJECT_NAME=$(echo "$GF_PROJECT_NAME" | tr '[:upper:]' '[:lower:]')
DB_NAME=$(echo "${PROJECT_NAME}_${branch_type}_${BRANCH_NAME}" | cut -c1-63)
```

#### 7a. Backend: appsettings.Local.json

**If API project detected:**
```bash
[ -n "$API_DIR" ] && [ -f "$API_DIR/appsettings.json" ] && {
  cat > "$API_DIR/appsettings.Local.json" << EOF
{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=${DB_NAME};Trusted_Connection=true;TrustServerCertificate=true"
  },
  "SmartStack": {
    "AutoMigrate": true,
    "FailOnMigrationError": true,
    "EnableDevSeeding": true
  },
  "Authentication": {
    "FrontendUrl": "http://localhost:${WEB_PORT}"
  },
  "Kestrel": {
    "Endpoints": {
      "Http": {
        "Url": "http://localhost:${API_PORT}"
      }
    }
  },
  "Serilog": {
    "MinimumLevel": {
      "Default": "Debug"
    }
  }
}
EOF
  echo "Created: $API_DIR/appsettings.Local.json (DB: $DB_NAME, Port: $API_PORT)"
}
```

#### 7b. Frontend: .env.local + npm script

**If Web project detected:**
```bash
[ -n "$WEB_DIR" ] && [ -f "$WEB_DIR/package.json" ] && {
  # Create .env.local
  cat > "$WEB_DIR/.env.local" << EOF
# Local environment configuration
# Generated by /gitflow:start for branch: ${FULL_BRANCH}
# Run with: npm run local

VITE_API_URL=http://localhost:${API_PORT}
VITE_APP_ENV=local
VITE_DEBUG=true
EOF
  echo "Created: $WEB_DIR/.env.local (API: localhost:$API_PORT)"

  # Add "local" script to package.json if not exists
  if ! grep -q '"local"' "$WEB_DIR/package.json"; then
    # Use Node.js to safely modify package.json
    node -e "
      const fs = require('fs');
      const pkg = JSON.parse(fs.readFileSync('$WEB_DIR/package.json', 'utf8'));
      if (!pkg.scripts.local) {
        pkg.scripts.local = 'vite --mode local --port ${WEB_PORT}';
        fs.writeFileSync('$WEB_DIR/package.json', JSON.stringify(pkg, null, 2) + '\n');
        console.log('Added script: npm run local');
      }
    "
  fi
}
```

#### 7c. Backend: launchSettings.json Local Profile

**If API project detected and Properties/launchSettings.json exists:**
```bash
LAUNCH_SETTINGS="$API_DIR/Properties/launchSettings.json"
[ -n "$API_DIR" ] && [ -f "$LAUNCH_SETTINGS" ] && {
  # Use Node.js to safely add/update Local profile in launchSettings.json
  node -e "
    const fs = require('fs');
    const ls = JSON.parse(fs.readFileSync('$LAUNCH_SETTINGS', 'utf8'));
    ls.profiles = ls.profiles || {};
    ls.profiles.Local = {
      commandName: 'Project',
      dotnetRunMessages: true,
      launchBrowser: false,
      applicationUrl: 'http://localhost:${API_PORT}',
      environmentVariables: {
        ASPNETCORE_ENVIRONMENT: 'Local'
      }
    };
    fs.writeFileSync('$LAUNCH_SETTINGS', JSON.stringify(ls, null, 2) + '\n');
    console.log('Updated: launchSettings.json Local profile (Port: ${API_PORT})');
  "
}
```

#### 7d. Summary of local config

```
┌─────────────────────────────────────────────────────────────┐
│  LOCAL ENVIRONMENT CONFIGURED                               │
├─────────────────────────────────────────────────────────────┤
│  Database:  ${DB_NAME}                                      │
│  API Port:  ${API_PORT}  →  dotnet run --launch-profile Local│
│  Web Port:  ${WEB_PORT}  →  npm run local                   │
└─────────────────────────────────────────────────────────────┘
```

### 8. Store State

```bash
# Save to state for next steps
{
  "branch_type": "{branch_type}",
  "branch_name": "{FULL_BRANCH}",
  "base_branch": "{BASE_BRANCH}",
  "target_branch": "{TARGET}",
  "worktree_path": "{WORKTREE_PATH}",
  "version_current": "{VERSION}",
  "local_config": {
    "database": "{DB_NAME}",
    "api_port": "{API_PORT}",
    "web_port": "{WEB_PORT}",
    "api_dir": "{API_DIR}",
    "web_dir": "{WEB_DIR}"
  }
}
```

### 9. Summary

```
╔══════════════════════════════════════════════════════════════════╗
║                    {BRANCH_TYPE} CREATED                          ║
╠══════════════════════════════════════════════════════════════════╣
║  Branch:   {FULL_BRANCH}                                          ║
║  Base:     {BASE_BRANCH}                                          ║
║  Target:   {TARGET}                                               ║
║  Worktree: {WORKTREE_PATH}                                        ║
╠══════════════════════════════════════════════════════════════════╣
║  LOCAL ENVIRONMENT:                                               ║
║  Database: {DB_NAME}                                              ║
║  API:      http://localhost:{API_PORT}                            ║
║  Web:      http://localhost:{WEB_PORT}                            ║
╠══════════════════════════════════════════════════════════════════╣
║  NEXT STEPS:                                                      ║
║                                                                    ║
║  1. Go to worktree:                                               ║
║     cd {WORKTREE_PATH}                                            ║
║                                                                    ║
║  2. Start backend (auto-migrates Core + Extensions DB):           ║
║     dotnet run --project src/{Project}.Api --launch-profile Local ║
║                                                                    ║
║  3. Reset admin password:                                         ║
║     ss admin reset                                                ║
║                                                                    ║
║  4. Start frontend (other terminal):                              ║
║     cd web/{project}-web && npm run local                         ║
║                                                                    ║
║  5. Make changes and commit:                                      ║
║     /gitflow commit                                               ║
║                                                                    ║
║  6. Create pull request:                                          ║
║     /gitflow pr                                                   ║
║                                                                    ║
║  7. After PR merged, finalize:                                    ║
║     /gitflow finish                                               ║
╚══════════════════════════════════════════════════════════════════╝
```

---

## ERROR HANDLING:

| Error | Solution |
|-------|----------|
| Branch exists | Offer: rename, checkout, or delete |
| Dirty working directory | Offer: stash, commit, or continue |
| Worktree path exists | Remove orphan or use different path |
| Base branch behind remote | Pull before creating |

---

## SUCCESS CRITERIA:

- Branch created from correct base
- **Branch pushed to remote (AUTOMATIC)**
- Worktree set up (if enabled)
- Backend local config created: `appsettings.Local.json` (if .NET API detected)
- Backend launch profile created: `launchSettings.json` Local profile with unique port (if .NET API detected)
- Frontend local config created: `.env.local` + `npm run local` script (if web project detected)
- Ports synchronized between backend and frontend (unique per branch)
- State stored for subsequent steps

## NEXT STEP:

User works on code, then runs `/gitflow commit`.
