Resources
Foundations
Read bulk-operations/SKILL.md first — JSONL piping, batch read, pagination, and the dry-run/digest/confirm flow live there. Reshape recipes are in bulk-operations/resources/json-patterns.md. hubspot <command> --help is the source of truth. Object types are plural (contacts, deals, companies). For property reference: hubspot properties list --type deals — don't hardcode property tables.
1. Discover pipelines and stages
Pipeline and stage IDs are portal-specific. Always discover at runtime — never hardcode across portals.
pipelines list/get embed each pipeline's stages, so a single call gives you the
stage id -> label map you need to translate a deal's dealstage GUID:
Grab a specific stage ID by label:
The IDs shown above (appointmentscheduled, closedwon, etc.) are HubSpot's standard default deal pipeline stages — but discover yours every run since portals can rename or remove them.
2. Qualify an MQL into a deal
Find connected MQLs without a deal, then for each: create the deal, associate to contact + company, promote lifecycle.
Bulk pattern — many MQLs at once
objects create returns one result line per stdin line, in input order. Capture both streams and join by line for associations:
Company associations need a separate per-contact pass via hubspot associations list --from contacts:<id> --to companies — a contact may have zero or many companies.
Pre-qualification checks are just filters on the search: has email, has a company, no open deal, has an owner — all in the --filter already. See resources/lifecycle-stage-progression.md for the full stage progression and contact-side updates.
3. Advance or reassign in bulk
The dry-run emits a digest at every size (confirm = the row count for a batch, the record ID for a single); re-pipe with --digest <hash> --confirm <value> lifted from the preview line. Full flow in bulk-operations/SKILL.md.
4. Find stalled deals
Filter cookbook with dynamic dates lives in resources/stalled-deal-queries.md. The core query:
Pipe the result into an update (extend close dates, move stage, set a flag) or into task creation. For follow-up tasks/calls/notes against stalled deals, see the sales-execution skill — don't duplicate activity-object property handling here.
5. Close
Closing is a stage update + closedate (YYYY-MM-DD). hs_is_closed and hs_is_closed_won are read-only — HubSpot derives them from the stage.
Win/loss analysis (close reasons, win rate, ARR roll-up) is in the sales-reporting skill.
Known constraints
- Bulk MQL → deal needs a two-pass shell flow: associations must be built from
objects createoutput, not in the same pipe. lifecyclestageis forward-only in most portal settings — backward transitions may be rejected.closedateis a date string (YYYY-MM-DD). Datetime activity props (hs_last_activity_date) also accept a date string for</>comparisons.hubspot sequencesreads Sales Hub sequences (list/get/enrollments) but is read-only — the CLI cannot enroll a contact in a sequence, so create a follow-up task viasales-executioninstead.sequences enrollments <contact_id>is useful for win/loss context on a deal's contacts.

