# HeyLead CLI & Developer Experience Improvements

**Inspired by:** [Resend CLI](https://resend.com/changelog/cli) — 53 commands, dual human/agent output, `doctor` diagnostics, natural language scheduling.

**Goal:** Bring standalone CLI access and DX polish to HeyLead without replacing the MCP-first architecture.

---

## 1. `heylead doctor` — One-Command Diagnostics

**Priority:** High
**Effort:** Small (new MCP tool action + optional CLI entry point)

Resend's `resend doctor` checks version, API key, domains, and connected agents in one shot. HeyLead users currently debug setup issues step-by-step through chat.

### What it checks
- HeyLead version (local vs PyPI latest)
- Backend reachable (`GET /health`)
- LinkedIn account connected + status (active/expired/reconnect needed)
- Voice signature exists
- Scheduler status (enabled, last run, pending jobs)
- SQLite DB integrity (`PRAGMA integrity_check`)
- Python version compatibility

### Output
```
heylead doctor

  Version      v0.10.132 (latest: v0.10.132) ✓
  Backend      https://heylead-api-...run.app — 200 OK ✓
  LinkedIn     Connected (Denys Chumak) — active ✓
  Voice        Signature analyzed (324 posts) ✓
  Scheduler    Enabled, 3 pending jobs, last run 12m ago ✓
  Database     OK (17 tables, WAL mode) ✓
  Python       3.12.4 ✓

  All checks passed.
```

### Implementation
- Add `doctor` action to the existing `scheduler` tool or create a dedicated `doctor` MCP tool
- Reuse existing health checks scattered across `setup_profile`, `scheduler(action='diagnostics')`, and `_ensure_account_connected()`
- For CLI mode: wire as `heylead doctor` subcommand

---

## 2. Standalone CLI Wrapper

**Priority:** High
**Effort:** Medium

HeyLead is MCP-only today — you need an AI agent to use it. A thin CLI wrapper opens it to:
- Developers who want terminal access without AI
- CI/CD pipelines (export leads, check campaign status)
- Quick checks ("do I have replies?") without opening an editor

### Proposed commands

```bash
# Auth
heylead login                        # Browser OAuth → store JWT locally
heylead auth switch                  # Switch between accounts/profiles

# Diagnostics
heylead doctor                       # Full health check

# Campaigns
heylead campaigns list               # Show all campaigns with status
heylead campaigns create "CTOs at fintech startups"
heylead campaigns pause <id>
heylead campaigns resume <id>

# Status & Replies
heylead status                       # Dashboard summary
heylead replies                      # New replies across campaigns
heylead next                         # Suggested next action

# Contacts
heylead contacts search "John"
heylead contacts export --format csv

# Inbox
heylead inbox                        # Recent LinkedIn conversations
heylead inbox read --name "Alice"

# Scheduler
heylead scheduler status
heylead scheduler on --cloud
```

### Architecture
- Thin CLI layer (`src/heylead/cli.py`) using `click` or `typer`
- Calls the **same service functions** that MCP tools call — zero logic duplication
- Entry point in `pyproject.toml`: `[project.scripts] heylead = "heylead.cli:main"`
- Does NOT replace MCP — it's a parallel interface to the same engine

---

## 3. Dual Output Mode (Human vs Machine)

**Priority:** Medium
**Effort:** Small

Resend auto-detects TTY vs pipe and switches between rich tables and JSON.

### Behavior
| Context | Output |
|---------|--------|
| Interactive terminal (TTY) | Styled tables, spinners, color, progress bars |
| Piped / CI / `--json` flag | Clean JSON to stdout, nothing to stderr |
| MCP tool response | Structured text (current behavior, unchanged) |

### Implementation
- Detect `sys.stdout.isatty()` at CLI entry
- Use `rich` (already common in Python CLIs) for TTY formatting
- `--json` flag forces machine output regardless of TTY
- `--quiet` / `-q` suppresses non-essential output

---

## 4. Named Error Codes

**Priority:** Medium
**Effort:** Small

Replace generic error strings with machine-parseable codes. Benefits both AI agents (smarter retry logic) and CLI users (grep-friendly).

### Error code catalog

| Code | Meaning | Current behavior |
|------|---------|-----------------|
| `account_disconnected` | LinkedIn session expired | Generic "No LinkedIn account" string |
| `rate_limited` | LinkedIn/backend rate limit hit | Various error messages |
| `subscription_required` | Action needs LinkedIn Premium | 403 with body text |
| `not_connected` | DM to non-connection | 403 with body text |
| `setup_required` | setup_profile not run yet | Tool-specific error strings |
| `campaign_not_found` | Invalid campaign ID | KeyError or generic message |
| `prospect_skipped` | Prospect already skipped/closed | Various |
| `quota_exhausted` | Daily send limit reached | Various |

### Format
```json
{
  "error": true,
  "code": "account_disconnected",
  "message": "LinkedIn session expired. Re-run setup_profile to reconnect.",
  "retry": false
}
```

### Implementation
- Define `ErrorCode` enum in `src/heylead/errors.py`
- Wrap in `HeyLeadError(code, message, retry=False)` exception class
- MCP tools catch and format; CLI formats with color + exit code
- Backward-compatible: MCP tool responses still return readable strings, just with the code embedded

---

## 5. Natural Language in Parameters

**Priority:** Low
**Effort:** Small

Resend accepts "tomorrow at 9am" for scheduling. HeyLead could accept natural time expressions in follow-up delays and scheduling.

### Where it applies
| Parameter | Today | Proposed |
|-----------|-------|----------|
| `followup_delay_days` | `"1,3,7,14"` | `"1 day, 3 days, 1 week, 2 weeks"` |
| `stale_invite_days` | `30` | `"1 month"` |
| Scheduler toggle | cron expression | `"weekdays 9am-6pm"` |
| One-shot reminders | ISO timestamp | `"tomorrow at 3pm"` |

### Implementation
- Use `dateparser` or `parsedatetime` library
- Parse at the CLI/tool boundary, convert to internal numeric format
- Fall back to numeric parsing if natural language fails
- MCP tools accept both formats (backward-compatible)

---

## 6. Multi-Profile Support

**Priority:** Low
**Effort:** Small

HeyLead already has `account(action='switch')` for LinkedIn accounts. Extend to full profile management for users managing multiple businesses.

### Behavior
```bash
heylead login --profile "startup-a"
heylead login --profile "agency"
heylead status --profile "startup-a"
```

### Storage
```
~/.heylead/
  profiles/
    default/
      config.json      # JWT, account_id, preferences
      data/heylead.db
    startup-a/
      config.json
      data/heylead.db
    agency/
      config.json
      data/heylead.db
```

### Implementation
- `--profile` flag on CLI, `profile` param on MCP tools
- Each profile has isolated DB + credentials
- Default profile used when flag omitted

---

## 7. Interactive Progressive Prompting (CLI only)

**Priority:** Low
**Effort:** Medium

Resend's CLI prompts for missing fields interactively instead of failing. Apply to HeyLead CLI.

### Example
```bash
$ heylead campaigns create
? Target audience: CTOs at fintech startups in Europe
? Campaign name (optional): Fintech CTOs Q1
? Company context (URL or description): https://heylead.dev
? Voice memos? (Y/n): Y
Creating campaign... ✓

Campaign "Fintech CTOs Q1" created with 47 prospects.
Autopilot is ON — outreach starts automatically.
```

### Implementation
- Use `rich.prompt` or `questionary` for interactive input
- Only in CLI mode (MCP tools keep current param-based interface)
- Auto-suggestions for common fields (verified domains, recent ICPs)

---

## Implementation Roadmap

### Phase 1 — Quick wins (1-2 days)
1. `doctor` diagnostic tool/action
2. Named error codes enum + `HeyLeadError` class
3. Wire error codes into top 5 most common failure paths

### Phase 2 — CLI foundation (3-5 days)
4. `heylead` CLI entry point with `typer`
5. `login`, `doctor`, `status`, `replies`, `next` commands
6. Dual output mode (TTY vs JSON)

### Phase 3 — Full CLI + polish (3-5 days)
7. Remaining CLI commands (campaigns, contacts, inbox, scheduler)
8. Interactive prompting for `campaigns create`
9. Natural language time parsing
10. Multi-profile storage

---

## What NOT to do

- Do NOT replace MCP tools with CLI — CLI is an **additional** interface
- Do NOT duplicate business logic — CLI calls the same service layer
- Do NOT add a web dashboard — terminal-first is the brand
- Do NOT over-engineer the CLI before validating demand — ship `doctor` + `status` + `replies` first, expand based on usage
