Skip to main content
skill CX Codex

cleanup-lead-owners — Claude Code skill: HubSpot owner cleanup

Strips departed employees out of HubSpot and moves their contacts, companies and deals to someone still on the team. Handy the week a person leaves.

Install into Claude Code · Skills CLI (Vercel) All methods and platforms ↓
npx skills add TomGranot/hubspot-admin-skills --skill cleanup-lead-owners -a claude-code
Open on GitHub

What cleanup-lead-owners does

The skill walks your CRM through the Owners API. It pulls both active and deactivated owners, lines them up against your roster of current employees, and flags anyone who should not be holding records — former staff, contractors, vendors. For each flagged owner it counts the contacts, companies and deals attached.

Reassignment runs through the batch update API, either to one default owner or by territory and round-robin rules. Companies and deals follow their contacts. When that finishes, the skill points you at /assign-unowned-contacts to sweep up anything left ownerless, then has you search for contacts whose hubspot_owner_id still matches a deactivated owner — the count should land at zero.

Have a HubSpot service key ready in HUBSPOT_ACCESS_TOKEN inside .env, scoped for crm.objects.owners.read plus write access to contacts, companies and deals. You also need Python 3.10+ with uv, a list of current employees, and a rule for where orphaned records go. Deactivating users takes Super Admin rights in HubSpot settings. Without the employee list there is nothing to compare owners against, so the skill cannot tell a leaver from a current hire. Log the original owner assignments first; rollback is a batch update of hubspot_owner_id back to the old value.

What it helps with

  • clear departed employees out of HubSpot owner lists
  • reassign contacts, companies and deals left behind by former owners
  • spot active HubSpot users who no longer work at the company
  • count how many records each stale owner still holds
  • verify no record is left without an owner after reassignment

Example prompts for the agent

  • List every HubSpot owner who is no longer an employee
  • Reassign the contacts and deals of departed owners by territory
  • Check that no deactivated owner still has contacts attached

How to install cleanup-lead-owners

1Skills CLI (Vercel)

npx skills add TomGranot/hubspot-admin-skills --skill cleanup-lead-owners -a claude-code

2Manually: put the files in place

~/.claude/skills/cleanup-lead-owners/SKILL.md

Copy the whole skill folder; for one project use .claude/skills/cleanup-lead-owners/

Step by step, with commands for each platform: How to install skills in Claude Code: five ways

Questions about cleanup-lead-owners

How do I install cleanup-lead-owners in Claude Code?

Run npx skills add TomGranot/hubspot-admin-skills --skill cleanup-lead-owners -a claude-code. The skill lands in ~/.claude/skills/cleanup-lead-owners/SKILL.md.

What does cleanup-lead-owners do?

It finds HubSpot owners who are no longer employees, reassigns their contacts, companies and deals, and tells you which users to deactivate.

What do I need before running cleanup-lead-owners?

A HubSpot service key in HUBSPOT_ACCESS_TOKEN with crm.objects.owners.read and write scopes for contacts, companies and deals, Python 3.10+ with uv, a current employee list, and a reassignment rule. Deactivating users requires Super Admin rights.

Source text

SKILL.md · MIT
---
name: cleanup-lead-owners
description: "Remove non-employee users from HubSpot and reassign their orphaned contacts, companies, and deals. Pairs with the assign-unowned-contacts skill for comprehensive ownership cleanup."
license: MIT
metadata:
  author: tomgranot
  version: "1.1"
  category: ongoing-maintenance
---

# Cleanup Lead Owners

Remove departed employees from HubSpot and reassign their CRM records. Orphaned records with no active owner fall through the cracks.

## Prerequisites

- A HubSpot service key (`HUBSPOT_ACCESS_TOKEN` in `.env`; an existing legacy private app token also works) with `crm.objects.owners.read` and contact/company/deal write scopes
- Python 3.10+ with [`uv`](https://github.com/astral-sh/uv)
- A list of current employees (to compare against HubSpot users)
- A default owner or round-robin assignment rule for orphaned records

## Step-by-Step Instructions

### Stage 1: Plan

Confirm with the user before starting:

1. Who receives reassigned records — a single default owner, or territory/round-robin rules?
2. Which flagged users should be deactivated vs merely stripped of records?

### Stage 2: Before

Identify non-employee owners via the Owners API:

```python
import os, requests
from dotenv import load_dotenv

load_dotenv()
TOKEN = os.environ["HUBSPOT_ACCESS_TOKEN"]
BASE = "https://api.hubapi.com"
HEADERS = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}

active = requests.get(f"{BASE}/crm/v3/owners", headers=HEADERS,
                      params={"limit": 100, "archived": "false"}).json()["results"]
deactivated = requests.get(f"{BASE}/crm/v3/owners", headers=HEADERS,
                           params={"limit": 100, "archived": "true"}).json()["results"]
```

Cross-reference with your current employee list. Flag:
- Deactivated HubSpot users who still own records
- Active HubSpot users who are no longer employees
- Contractors or vendors who should not own records

For each flagged owner, count how many contacts, companies, and deals they own.

### Stage 3: Execute

1. **Reassign records** owned by non-employees:
   - Use the batch update API to reassign contacts to the appropriate active owner
   - Apply round-robin or territory-based rules if no specific owner is obvious
   - Reassign companies and deals associated with the same contacts

2. **Deactivate users** who are no longer employees (requires Super Admin in HubSpot Settings > Users & Teams).

3. **Run `/assign-unowned-contacts`** after reassignment to catch any records that ended up without an owner.

### Stage 4: After

1. Search for contacts where `hubspot_owner_id` matches any deactivated owner ID — count should be zero.
2. Confirm all reassigned contacts have an active owner.
3. Check that no workflows broke due to owner changes (some workflows may filter by specific owners).

## Rollback

- Owner reassignments can be reversed by batch-updating the `hubspot_owner_id` back to the original value.
- Keep a log of original owner assignments before making changes.
- Deactivated users can be reactivated in HubSpot Settings if needed.

## Tips

- Run this whenever an employee leaves the company — do not wait for quarterly cleanup.
- Set up an offboarding checklist that includes HubSpot record reassignment.
- Pairs with `/assign-unowned-contacts` for comprehensive ownership hygiene.

© tomgranot · MIT · TomGranot/hubspot-admin-skills

Similar skills

All skills for Automation and no-code: n8n, Zapier, Make →

From the same set11

review-bounced-contacts A weekly manual pass over contacts with 3+ bounces: delete them or try to recover. Keeps suppression from going too far while bad records still leave. CX Codex +1 ★ 78repo stars new-contact-hygiene-workflow Builds a HubSpot workflow that stages every new contact and pulls company details from the associated company record. CX Codex +1 ★ 78repo stars enrich-company-name Copies the company name from a linked company record into empty contact fields in HubSpot. Useful when empty values break segmentation and personalization tokens. CX Codex +1 ★ 78repo stars create-segment-lists Builds a library of HubSpot segment lists — customers, partners, competitors, employees, ICP tiers, industries. Feeds targeting, suppression and reporting. CX Codex +1 ★ 78repo stars cleanup-workflows Audits HubSpot workflows and flags the ones worth deleting: never enrolled, switched off for 90+ days, or left over from testing. CX Codex +1 ★ 78repo stars cleanup-dashboards Walks you through auditing HubSpot dashboards: spots abandoned screens, duplicates and test copies, then helps merge reports into a few that people actually open. CX Codex +1 ★ 78repo stars bounce-monitoring-workflow The skill builds three HubSpot workflows that watch email bounces: it suppresses contacts past a set count, alerts on hard bounces, and flags addresses for a weekly review. CX Codex +1 ★ 78repo stars assign-unowned-contacts Gives every ownerless marketing contact in HubSpot an owner. Useful when owner-based reports and the actual contact list disagree. CX Codex +1 ★ 78repo stars

Project sponsors

Companies that keep this analytics open
Gold sponsor

Impressions, clicks and code copies — open statistics. We keep the numbers public for the same reason NeBlask itself is public. Become a sponsor