workflow-automation
List, inspect, create, update, and delete HubSpot workflows (v4 flows API) from the `hubspot` agent CLI, not the `hs` developer CLI.
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.
Full skill instructions
Read bulk-operations/SKILL.md first — pagination, JSONL piping, destructive-op safety. Reshape recipes in bulk-operations/resources/json-patterns.md. Resource: resources/contact-segmentation-filters.md is the filter-expression cookbook (lifecycle, lead status, email engagement, activity, deals, owner).
Source of truth: hubspot objects search --help.
--filter flag = one AND group: --filter "lifecyclestage=lead AND !hubspot_owner_id".--filter flags are OR'd. Use for enum-OR-enum.=, !=, >, >=, <, <=, ~ (CONTAINS_TOKEN — whole-word, NOT substring), @= (IN), @!= (NOT_IN).name or name?. NOT_HAS_PROPERTY: !name. Dates: YYYY-MM-DD.--filter flags, max 6 conditions per flag, max 18 conditions total. Prefer @= / @!= for enum lists — lifecyclestage@=lead,customer is one condition, --filter "lifecyclestage=lead" --filter "lifecyclestage=customer" is two groups.@!= skips records where the property is unset, so OR in a !name group and repeat the shared conditions in both:
--filter "hubspot_owner_id=123 AND lifecyclestage@!=customer,evangelist" --filter "hubspot_owner_id=123 AND !lifecyclestage"~ gotcha: jobtitle~director matches the token "director", not arbitrary substrings. No regex operator — search broadly, post-filter with jq.
Full live list: hubspot properties list --type contacts. Enum options: hubspot properties options-list --type contacts <name> | jq -r '.value'. As a fallback (e.g. to see which values are actually in use), read live records: hubspot objects list --type contacts --properties <name> --limit 100 --format json | jq -r '.data[].properties.<name> // empty' | sort -u.
Core fields used here: lifecyclestage, hubspot_owner_id (bare/! for owned/unowned; hubspot owners list for IDs), hs_email_optout (!=true excludes opted-out), hs_email_last_open_date / notes_last_contacted (recency), jobtitle / country / city (string = or ~), num_associated_deals (0 net-new, >=1 has-pipeline).
Firmographics (industry, numberofemployees, annualrevenue) live on companies — see cross-object section.
# Recent leads (this quarter, not yet owned)
hubspot objects search --type contacts \
--filter "lifecyclestage=lead AND createdate>2026-01-01 AND !hubspot_owner_id" \
--properties email,firstname,lastname,createdate
# Decision-makers by jobtitle (OR across tokens)
hubspot objects search --type contacts \
--filter "jobtitle~director" --filter "jobtitle~vp" --filter "jobtitle~chief" \
--properties email,jobtitle,company
# Engaged but not yet MQL (opened recently, still lead, opted in)
hubspot objects search --type contacts \
--filter "lifecyclestage=lead AND hs_email_last_open_date>2026-04-01 AND hs_email_optout!=true" \
--properties email,firstname,hs_email_last_open_date
# Geographic — US contacts opted in
hubspot objects search --type contacts \
--filter "country=United States AND hs_email_optout!=true" \
--properties email,state,city
More patterns (lead status, deals, owners, combined AND/OR) in resources/contact-segmentation-filters.md.
industry/numberofemployees/annualrevenue live on the company. Build the company set, then traverse — never xargs -I{} hubspot objects get per company. associations list emits {"id":"...","labels":[...],"associationTypes":[...]} — {id} feeds directly into a single batched objects get.
# Step 1: target companies. Industry options are portal-specific — discover with:
# hubspot objects list --type companies --properties industry --limit 100 --format json \
# | jq -r '.data[].properties.industry // empty' | sort -u
hubspot objects search --type companies \
--filter "industry=SOFTWARE AND numberofemployees>=100" \
--properties name,industry,numberofemployees \
> target_companies.jsonl
# Step 2: gather association IDs (associations list has no batch --from), then ONE batched
# objects get for all contacts. Page each company with --limit/--after — a company with >100
# associated contacts truncates silently on a single call.
while read -r cid; do
after=""
while :; do
page=$(hubspot associations list --from "companies:$cid" --to contacts --limit 100 ${after:+--after "$after"} --format json)
echo "$page" | jq -c '.data[]?'
after=$(echo "$page" | jq -r '.meta.next // empty')
[ -z "$after" ] && break
done
done \
< <(jq -r '.id' target_companies.jsonl) \
| jq -c '{id}' | sort -u \
| hubspot objects get --type contacts --properties email,firstname,jobtitle,hs_email_optout \
> target_contacts.jsonl
# Optional: drop opted-out
jq -c 'select(.properties.hs_email_optout != "true")' target_contacts.jsonl > campaign_audience.jsonl
A segment is a JSONL file. Re-use for updates, exports, or re-fetches:
# Save
hubspot objects search --type contacts \
--filter "lifecyclestage=lead AND hs_email_optout!=true" \
--properties email,firstname,lastname,jobtitle \
> segments/opted_in_leads.jsonl
# Assign owner (dry-run first per bulk-operations/SKILL.md)
jq -c '{id, properties:{hubspot_owner_id:"12345"}}' segments/opted_in_leads.jsonl \
| hubspot objects update --type contacts --dry-run
# Re-fetch with different properties later
jq -c '{id}' segments/opted_in_leads.jsonl \
| hubspot objects get --type contacts --properties email,lifecyclestage,hs_lead_status
Destructive ops on a saved segment follow the dry-run → digest → confirm flow in bulk-operations/SKILL.md.
A JSONL segment is portable, but you can also persist an audience in HubSpot:
hubspot segments create saves a list; segments get / list inspect it; segments members-list reads members; segments members-add / members-remove manage membership. Use segments update-filters to set a dynamic list's filter criteria.hubspot views create --type <t> --name "..." --columns a,b [--filters-file filters.json] [--sort prop:asc] saves a filter set as a reusable object view; views list / get / update / replace-field / delete manage it.hubspot objects count --type contacts --filter "..." returns {"object_type":"contacts","total":N} without paging, so you can size an audience before saving or exporting it.hubspot buyer-intent — visiting-company intent signals (read-only). Requires OAuth login (hubspot auth login); service keys are NOT supported.hubspot analytics traffic sources — where sessions/contacts came from, for source-based segmentation.hubspot marketing forms list — form definitions, to segment by which form a contact converted on.Run each command's --help for the full surface.
~ is token-match, not substring. No regex operator.hubspot properties options-list --type contacts <name> (fallback: read live records via objects list + jq).associations list has no batch --from, and returns one page (default 100) per call. Loop to gather IDs and page each call with --limit/--after until .meta.next is null, then batch the downstream objects get — otherwise a company with >100 associated contacts truncates silently.bulk-operations/SKILL.md.List, inspect, create, update, and delete HubSpot workflows (v4 flows API) from the `hubspot` agent CLI, not the `hs` developer CLI.
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.
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.
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`.
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`.
Retrieve activity history (calls, emails, notes, meetings, tasks) for a CRM record and assemble pre-call briefs.
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.
Assign and reassign CRM record ownership, audit who-owns-what across object types, and handle rep transitions. Built on `bulk-operations`.
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`.
Build the product catalog, assemble quotes (line items + associations to deals), and track invoices and subscriptions through to revenue.
Generate, edit, and beat-sync AI video with leading models in one workspace.
The world's fastest calendar for remote work
Transform Your Design with AI Designer by ImgCreator.ai
Revolutionizing Video Production with AI-Powered Creativity
Extend an image past the frame and let AI fill the new aspect ratio.
Discover your celebrity doppelgänger with StarByFace!
ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.
Opus.ai: Revolutionize Your Web Experience