Skip to content
customer-retention logo

Customer Retention

customer-retention

Identify inactive/at-risk customers via CRM filters and create follow-up tasks at scale. Builds on `bulk-operations`; defers activity-creation specifics to `sales-execution`.

hubspot/agent-cli-skills1.5Kinstalls26stars

SKILL.md

Full skill instructions

Resources

FileWhen to use
resources/​customer-health-signals.mdFilter cookbook of churn signals — --filter expressions for notes_last_contacted, hs_last_sales_activity_date, hs_email_optout, stale tickets, subscription status.

Prereqs

Read bulk-operations/​SKILL.md first — every read/​write below uses its JSONL pipe, pagination, and dry-run/​digest patterns. Activity-property tables and association rules live in sales-execution/​SKILL.md.

Schema is portal-specific. Verify each property before filtering — e.g. hubspot properties get --type contacts notes_last_contacted, ... hs_last_sales_activity_date, ... --type subscriptions hs_subscription_status. If subscriptions returns 403, your token lacks subscriptions-read — use a private-app token with that scope.

1 — Find inactive customers

CUTOFF=$(date -v-60d +%Y-%m-%d 2>/​dev/​null || date -d '60 days ago' +%Y-%m-%d)

# No outreach in 60d (calls/​notes/​meetings update notes_last_contacted)
hubspot objects search --type contacts \
  --filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF" \
  --properties email,firstname,notes_last_contacted,hubspot_owner_id

# No sales activity in 60d (broader — also catches emails/​tasks)
hubspot objects search --type contacts \
  --filter "lifecyclestage=customer AND hs_last_sales_activity_date<$CUTOFF" \
  --properties email,firstname,hs_last_sales_activity_date

# Never contacted
hubspot objects search --type contacts \
  --filter "lifecyclestage=customer AND !notes_last_contacted" \
  --properties email,firstname

For more signals (email opt-out, stale tickets, no open deals) see resources/​customer-health-signals.md. For >100 hits, use the pagination loop from bulk-operations.

To audit why a customer churned or moved stage — which workflow, integration, import, or UI edit last changed lifecyclestage — use hubspot objects history --type contacts --properties lifecyclestage [--id <recordId>] [--include-ui]. It flattens each property's source history into one row per change.

2 — Flag at-risk subscriptions

subscriptions is a standard object (hubspot objects types confirms). Enum values for hs_subscription_status are portal-specific — verify before filtering, then plug the exact value in:

hubspot properties options-list --type subscriptions hs_subscription_status   # allowed values

# Past-due — revenue at immediate risk (substitute your verified value)
hubspot objects search --type subscriptions \
  --filter "hs_subscription_status=past_due" \
  --properties hs_recurring_billing_total,hs_subscription_status

# Map an at-risk subscription to its contact for outreach
hubspot associations list --from subscriptions:<sub_id> --to contacts --format jsonl

3 — Create a follow-up task or check-in note

Activity creation lives in sales-execution (full property tables, note + meeting flows). One anchor example — unassociated tasks are invisible in the CRM UI, so always associate:

task_id=$(hubspot objects create --type tasks \
  --property hs_task_subject="Q1 retention check-in" \
  --property hs_task_priority=HIGH --property hs_task_status=NOT_STARTED \
  --property hs_task_type=CALL --property hs_timestamp=$(date +%s)000 \
  --format json | jq -r '.id')
hubspot associations create --from tasks:$task_id --to contacts:<contact_id>

4 — Bulk task creation for a cohort

Pipe a search through jq into one objects create call, then associate. objects create is Additive — never digest-gated — so --dry-run is a plain preview and you execute by dropping it (no digest/​confirm). The digest flow only applies to the irreversible writes in bulk-operations/​SKILL.md.

DUE_MS=$(( ($(date +%s) + 2*86400) * 1000 ))   # due in 2 days

# 1. Capture the cohort (same file feeds both create + associate)
hubspot objects search --type contacts \
  --filter "lifecyclestage=customer AND notes_last_contacted<$CUTOFF" \
  --properties firstname > /​tmp/​inactive.jsonl

# 2. Build task payloads — one per contact
jq -c --arg due "$DUE_MS" '{
  contact_id: .id,
  properties: {
    hs_task_subject: ("Re-engage: " + (.properties.firstname // "customer")),
    hs_task_priority: "HIGH", hs_task_status: "NOT_STARTED",
    hs_task_type: "CALL", hs_timestamp: $due
  }
}' /​tmp/​inactive.jsonl > /​tmp/​task_payloads.jsonl

# 3. Dry-run, then create (drop contact_id before piping)
jq -c '{properties}' /​tmp/​task_payloads.jsonl | hubspot objects create --type tasks --dry-run | head
jq -c '{properties}' /​tmp/​task_payloads.jsonl | hubspot objects create --type tasks > /​tmp/​created.jsonl

# 4. Associate each new task to its contact — one piped call (associations create batches 100 pairs/​API call; paste preserves order)
paste <(jq -r '.id' /​tmp/​created.jsonl) <(jq -r '.contact_id' /​tmp/​task_payloads.jsonl) \
  | jq -cR 'split("\t") | {from:("tasks:" + .[0]), to:("contacts:" + .[1])}' \
  | hubspot associations create

One CLI call for the search, one for the create, and one for all associations — no xargs -I{} per record. The output-order guarantee of objects create (one result per stdin line, in order — see bulk-operations "Output shape") is what makes the paste correct.

Known gaps

  • No native churn-score / health-score property — track via a custom property.
  • hubspot segments provides CRM lists for re-engagement cohorts — segments members-list pulls a list's members, and segments create / update-filters save an at-risk audience as a reusable list. Re-engagement enrollment can be built as a workflow via hubspot workflows create / update (see workflow-automation/​SKILL.md).
  • hubspot sequences reads Sales Hub sequences (read-only): use sequences enrollments <contact_id> to see whether an at-risk customer was ever engaged through a sales sequence. Sequences are a product API (Sales Hub Professional+, automation.sequences.read scope), not a CRM object type — the CLI cannot create sequences or enroll contacts. This list grows over time; recheck hubspot --help / CHANGELOG.md rather than assuming an API is absent.
  • hubspot associations create batches stdin JSONL (up to 100 pairs per API call) — pipe the pairs in one call instead of looping.

More skills from hubspot

workflow-automation logo
hubspot/agent-cli-skills

workflow-automation

List, inspect, create, update, and delete HubSpot workflows (v4 flows API) from the `hubspot` agent CLI, not the `hs` developer CLI.

26 1.6K
View
deal-management logo
hubspot/agent-cli-skills

deal-management

Run the full deal lifecycle from CLI — discover pipelines/stages, qualify MQLs into deals with associations, advance/reassign in bulk, hunt stalled deals, and close.

26 1.6K
View
sales-reporting logo
hubspot/agent-cli-skills

sales-reporting

Daily briefings, pipeline snapshots, and win/loss analysis from the terminal — closing-this-week, open pipeline by stage/owner, and closed-won vs closed-lost over a period.

26 1.6K
View
custom-object-management logo
hubspot/agent-cli-skills

custom-object-management

Discover, create, update, and delete custom CRM object schemas. Use when defining a new object type, inspecting existing schemas, or removing one. Record CRUD on custom objects is identical to standard objects — see `bulk-operations`.

26 1.6K
View
data-enrichment logo
hubspot/agent-cli-skills

data-enrichment

Match external CSV/JSONL records to CRM contacts (by email) or companies (by domain) and write enriched data back in one pass using `hubspot objects upsert`.

26 1.6K
View
communication-history logo
hubspot/agent-cli-skills

communication-history

Retrieve activity history (calls, emails, notes, meetings, tasks) for a CRM record and assemble pre-call briefs.

26 1.6K
View
sales-execution logo
hubspot/agent-cli-skills

sales-execution

Log sales activities — calls, notes, meetings, tasks — against contacts and deals, with the mandatory create-then-associate step that makes them visible in the CRM.

26 1.6K
View
team-ownership logo
hubspot/agent-cli-skills

team-ownership

Assign and reassign CRM record ownership, audit who-owns-what across object types, and handle rep transitions. Built on `bulk-operations`.

26 1.6K
View
audience-targeting logo
hubspot/agent-cli-skills

audience-targeting

Build a targeted contact segment by filtering on lifecycle, engagement, jobtitle, geography, or firmographics — then export it as JSONL for a campaign or downstream tool.

26 1.5K
View
quote-to-cash logo
hubspot/agent-cli-skills

quote-to-cash

Build the product catalog, assemble quotes (line items + associations to deals), and track invoices and subscriptions through to revenue.

26 1.5K
View

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View