# Hubspot Pipeline Cleanup

> Use when the user wants to clean up HubSpot (or any CRM — Salesforce, Pipedrive, Close) pipeline, identify stale deals, fix deal stages, or audit pipeline health. Triggers on "my pipeline is a mess", "find stale deals", "clean up HubSpot", "review my deals", "what should I close out", "pipeline review before forecast", "deals stuck in stage X", or running quarterly pipeline hygiene. Also triggers when the user mentions forecast accuracy problems or sales velocity metrics.

- Skill: `fengyiqicoder/hubspot-pipeline-cleanup` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add fengyiqicoder/hubspot-pipeline-cleanup`
- Raw SKILL.md: https://api.skillmd.com/api/skills/fengyiqicoder/hubspot-pipeline-cleanup/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: fengyiqicoder (https://skillmd.com/u/fengyiqicoder)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/fengyiqicoder/hubspot-pipeline-cleanup

---


# HubSpot Pipeline Cleanup

## Overview

A messy CRM pipeline destroys forecast accuracy, demoralizes reps ("everything looks stuck"), and hides real opportunities. This skill walks the user through a **systematic pipeline audit** that identifies which deals to close, push, or escalate — based on objective rules, not gut feel.

**Core principle**: A deal that hasn't moved stages in 2x the average sales cycle for that stage is **either dead or being neglected**. Treat it as dead until proven otherwise.

## The 4-quadrant deal classification

For every open deal, classify into one quadrant:

| | Recent activity (≤14d) | No recent activity (>14d) |
|---|---|---|
| **In stage <2x avg time** | 🟢 Healthy — leave alone | 🟡 Nudge — needs activity |
| **In stage ≥2x avg time** | 🟠 Stuck — coach the rep | 🔴 Dead — close-lost it |

**Definitions:**
- "Recent activity" = email logged, call logged, meeting completed, or stage change
- "Avg time in stage" = your historical average for that pipeline stage. If unknown, default: Qualification 14d, Demo 21d, Proposal 14d, Negotiation 21d

## Workflow

### Step 1: Ask the user for context

```
1. Which pipeline are we cleaning? (Sales / Customer Success / Partnerships / Other)
2. What's your typical sales cycle (in days)?
3. Any deals you already know are dead?
4. Date of last formal pipeline review?
```

If user says "I don't know my sales cycle" → use defaults from [references/sales-velocity-benchmarks.md](references/sales-velocity-benchmarks.md).

### Step 2: Pull the deal list

Ask user to export from HubSpot:
- All open deals
- Columns: Deal Name, Stage, Amount, Close Date, Last Modified Date, Last Contacted Date, Owner, Stage Entry Date

Save as CSV. If user pastes the list, parse it directly.

### Step 3: Classify each deal

For each deal, compute:

```
days_in_current_stage = today - stage_entry_date
days_since_activity   = today - last_contacted_date
stage_health          = days_in_current_stage / avg_time_for_stage

if stage_health < 2 and days_since_activity ≤ 14:  HEALTHY
if stage_health < 2 and days_since_activity > 14:  NUDGE
if stage_health ≥ 2 and days_since_activity ≤ 14:  STUCK
if stage_health ≥ 2 and days_since_activity > 14:  DEAD
```

### Step 4: Surface the cleanup actions

For each category, recommend specific actions:

**🟢 HEALTHY** — No action. List them only.

**🟡 NUDGE** — One-liner per deal: "Email [Contact] re: [last context]". Group by owner.

**🟠 STUCK** — These need a coach-the-rep conversation. Surface the pattern:
- "3 deals stuck in 'Proposal' for owner X" → maybe rep struggles closing
- "5 deals stuck in 'Demo' across pipeline" → maybe demo doesn't convert; root-cause it

**🔴 DEAD** — Recommend close-lost with reason. Ask user to confirm before bulk-closing.

### Step 5: Forecast clean-up impact

After classification, show:

```
Pipeline before cleanup: $X across N deals
After removing DEAD: $Y across M deals (more accurate forecast)
Recovered hours: estimated X hours/month rep time wasted on dead deals
```

## The "close-lost reason" trap

HubSpot's default close-lost reasons are too generic ("No decision", "Went with competitor"). They tell you nothing.

**Push for specifics:**
- ❌ "Lost to competitor" → ✅ "Lost to [Competitor] — they had [specific feature/price]"
- ❌ "Budget" → ✅ "Budget — wanted to stay <$X, our floor was $Y"
- ❌ "Timing" → ✅ "Timing — wanted to wait for [event/quarter]"

See [references/close-lost-taxonomy.md](references/close-lost-taxonomy.md) for the actionable taxonomy.

## Quarterly cleanup ritual

This skill should run **every quarter at minimum**. Suggest the user calendar:

1. **Week 1 of quarter**: cleanup (this skill)
2. **Week 2**: rep 1:1s on stuck deals
3. **Week 12**: forecast finalization (informed by clean pipeline)

## Red flags

- **>40% of pipeline is "DEAD"** → systemic issue: leads-quality, qualification process, or rep behavior
- **Average deal age > 2x sales cycle** → forecast is fiction; pipeline coverage ratio meaningless
- **One owner has 3x the dead-deal rate** → coaching opportunity, not a "lazy rep" judgment
- **Recent activity = "task created" only** → activity theater, not real engagement
- **Deals reopening multiple times** → poor qualification at top of funnel

## Quick reference

| Symptom | Likely cause | First action |
|---------|-------------|--------------|
| Forecast keeps slipping | Stale deals inflating coverage | Run this cleanup |
| Reps say "pipeline is full" but no closes | Quality vs. quantity issue | Filter by deal age |
| Same deal name appears 3x | Duplicate / re-entry | HubSpot dedupe tool |
| All deals close-date = end of quarter | Wishful thinking | Force per-deal date based on actual stage |
| Win rate dropping | Stuck deals diluting wins | Cleanup + qualification refresh |

## What NOT to do

- **Don't mass-close-lost without rep review** — you might kill a real deal
- **Don't change ownership during cleanup** — does more harm than good mid-quarter
- **Don't add new mandatory fields during cleanup** — pile-on; do it next quarter
- **Don't use AI to write the rep coaching message** — the rep needs to own the relationship

