cleanup-properties — Claude Code skill: what it does, how to install
Audits and archives unused custom properties across HubSpot contacts, companies, and deals. Prevents property bloat through the Properties API.
npx skills add TomGranot/hubspot-admin-skills --skill cleanup-properties -a claude-codeWhat cleanup-properties does
The skill inventories custom fields for contacts, companies, and deals via HubSpot Properties API v3. It checks for filled values across records and inspects references inside active forms, lists, or workflows.
Attributes with zero filled records or names containing test, temp, or old_ are queued for cleanup. Salesforce sync properties with the hs_salesforce_* prefix and calculated fields require explicit confirmation. The process archives fields first via API so historical data stays recoverable.
Execution requires Python 3.10+ with uv alongside a HUBSPOT_ACCESS_TOKEN set in .env. Without crm.schemas.*.read and crm.schemas.*.write scopes, the HubSpot API will reject the schema requests.
What it helps with
- audit unused custom properties across HubSpot records
- archive obsolete fields without losing reporting history
- inspect field dependencies in forms and automation workflows
- flag Salesforce sync properties before accidental removal
Example prompts for the agent
- Scan deals for empty custom properties and prepare an archive list
- Find all contact properties containing test or temp in their names
- Check custom company properties before removing legacy integration fields
How to install cleanup-properties
1Skills CLI (Vercel)
npx skills add TomGranot/hubspot-admin-skills --skill cleanup-properties -a claude-code2Manually: put the files in place
~/.claude/skills/cleanup-properties/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/cleanup-properties/
1Skills CLI (Vercel)
npx skills add TomGranot/hubspot-admin-skills --skill cleanup-properties -a codex2Manually: put the files in place
.agents/skills/cleanup-properties/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add TomGranot/hubspot-admin-skills --skill cleanup-properties -a cursor2Manually: put the files in place
.cursor/skills/cleanup-properties/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install TomGranot/hubspot-admin-skills cleanup-properties2Manually: put the files in place
.github/skills/cleanup-properties/SKILL.md1Skills CLI (Vercel)
npx skills add TomGranot/hubspot-admin-skills --skill cleanup-properties -a gemini-cli2Platform CLI
gemini skills install https://github.com/TomGranot/hubspot-admin-skills --path skills/cleanup-propertiesManually: put the files in place
.devin/skills/cleanup-properties/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add TomGranot/hubspot-admin-skills --skill cleanup-properties -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about cleanup-properties
How to install cleanup-properties in Claude Code?
Run npx skills add TomGranot/hubspot-admin-skills --skill cleanup-properties -a claude-code. This downloads the skill into ~/.claude/skills/cleanup-properties/SKILL.md.
What does cleanup-properties do?
It inventories custom properties in HubSpot, flags unused or test attributes, and archives them safely via the Properties API.
Can deleted properties be recovered?
Archived properties can be unarchived whenever needed. Once permanently deleted, property definitions and all stored data are lost.
Source text
SKILL.md · MIT
---
name: cleanup-properties
description: "Archive or delete unused custom properties across all HubSpot object types (contacts, companies, deals). Identifies Salesforce sync properties, test/temp properties, and obsolete form fields."
license: MIT
metadata:
author: tomgranot
version: "1.1"
category: ongoing-maintenance
---
# Cleanup Properties
Remove or archive unused custom properties. Property bloat slows down forms, confuses users, and makes data mapping harder.
## Prerequisites
- A HubSpot service key (`HUBSPOT_ACCESS_TOKEN` in `.env`; an existing legacy private app token also works) with `crm.schemas.*.read` and `crm.schemas.*.write` scopes
- Python 3.10+ with [`uv`](https://github.com/astral-sh/uv)
## Step-by-Step Instructions
### Stage 1: Plan
Confirm with the user before starting:
1. Archive-first policy (recommended) or direct deletion for clearly dead test properties?
2. Is a Salesforce (or other CRM) sync active? If yes, get the sync property mapping before touching anything.
### Stage 2: Before
Inventory custom properties for each object type via the Properties API (v3):
```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"}
for obj_type in ["contacts", "companies", "deals"]:
resp = requests.get(f"{BASE}/crm/v3/properties/{obj_type}", headers=HEADERS)
resp.raise_for_status()
custom_props = [p for p in resp.json()["results"] if not p.get("hubspotDefined")]
```
For each custom property, record: name, label, object type, type, group, number of records with a value (requires search queries), whether it is used in any form/workflow/list.
### Stage 3: Execute
**Safe to delete:**
- Properties with zero populated records and not used in any form, workflow, or list
- Properties with names containing "test", "temp", "old_", "copy_of"
- Properties created by deactivated integrations
**Handle with care:**
- **Salesforce sync properties** (`hs_salesforce_*` prefix or mapped in sync settings) — do not delete without coordinating with the Salesforce admin
- **Form fields** — check if the property is used on any active form before deleting
- **Workflow dependencies** — check if any workflow reads or sets this property
- **Calculated properties** — check if other calculated properties reference this one
**Archive instead of delete** when:
- The property has historical data that might be needed for reporting
- You are unsure whether anything depends on it
Archive candidates via `DELETE /crm/v3/properties/{objectType}/{propertyName}` (this archives — the property moves to the archived state) after presenting the list to the user and getting explicit confirmation.
### Stage 4: After
1. Archive properties first (HubSpot supports property archiving).
2. Wait 30 days, then delete archived properties that caused no issues.
3. Document all changes in a cleanup log.
## Rollback
- Archived properties can be unarchived at any time.
- Deleted properties cannot be restored. The property definition and all associated data are permanently lost.
- Always archive before deleting to provide a safety window.
## Tips
- Run this quarterly as part of the database cleanup routine.
- Establish a property naming convention going forward (e.g., `team_purpose_detail`).
- Limit who can create custom properties to prevent sprawl.
- HubSpot has a property limit per object type — cleanup prevents hitting it.
© tomgranot · MIT · TomGranot/hubspot-admin-skills