00-gtm-router
Plan and run the full API-first GTM chain - the orchestrator (step 00) that turns an ICP description plus optional budget, volume, and urgency into the right…
Turn a terminal records.jsonl into an owner-readable campaign sheet plus a HubSpot-import-shaped CSV - the chain's exit door. Use when a run is ready to hand to an owner: "build the campaign sheet", "export these for HubSpot", "who do I contact first", or as the final step of
$ npx -y skills add Zevenue/headless-gtm --skill 07-campaign-sheet --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
/07-campaign-sheetContext preview
The summary Claude sees to decide when to auto-load this skill.
Turn a terminal records.jsonl into an owner-readable campaign sheet plus a HubSpot-import-shaped CSV - the chain's exit door. Use when a run is ready to hand to an owner: "build the campaign sheet", "export these for HubSpot", "who do I contact first", or as the final step of
name: 07-campaign-sheet description: >- Turn a terminal records.jsonl into an owner-readable campaign sheet plus a HubSpot-import-shaped CSV - the chain's exit door. Use when a run is ready to hand to an owner: "build the campaign sheet", "export these for HubSpot", "who do I contact first", or as the final step of run-first-campaign. Reads whatever stage produced the records (qualified, signal-ranked, or fully resolved) and degrades gracefully on missing fields - no email column until 06 has run. Nothing sends and nothing downstream reads its output: the sheet and CSV are the human deliverable, approved on screen. To add verified emails first, run 06-resolution-email-person; to rank, 05-signal-builder.
The last step in the chain. Everything upstream produced `records.jsonl`; this turns those records into what an owner actually uses - a ranked "who to contact first and why" sheet, plus a CSV shaped for a one-click HubSpot import.
It **adds no fields to the chain and nothing reads its output.** The CSV is a derived, human-facing export (`headless-gtm-shared/CONVENTIONS.md`) - the canonical record stays `records.jsonl`, and re-running any upstream skill never depends on this sheet.
A terminal `records.jsonl` from any stage. The script tolerates every shape and degrades instead of failing:
`https://` + `domain`), **phone / city** from wherever the discovery step put them.
decides call order; its `signal_type`, `signal_sentence`, and `source_url` become the "why now" line, and its `approach` (or `fallback_approach`) the recommended angle. Records with no signals stay in the sheet, ranked last.
`verification_status`. When 06 has not run, the contact columns are dropped entirely rather than shipped empty.
drop them (a registry row with `domain` empty is still a real target).
`runs/<run-id>/` (via `common.runs_base()`, step prefix `07`):
(company, city, why now with source, approach, contact or "not resolved"), then a compact table for the rest, then a "before you send" note.
Name, Last Name, Email, Company Name, Website URL, Phone Number, Lifecycle Stage, Notes`. Every row is set to **Lifecycle Stage = Lead**; `Notes` carries the top signal and the recommended approach. First/Last/Email appear only when at least one record is resolved, and a `Listing URL` column appears only when at least one record carries one (directory-sourced runs) - so a phone-only registry row still exports a working link. The headers are HubSpot's defaults because it is the most common import target; every field is a plain column, so any other CRM (Salesforce, Pipedrive, Attio) takes the same file after a one-time header remap on import.
python3 scripts/campaign_sheet.py --records ./runs/<run-id>/records.jsonl --title "HVAC - Ontario"
Stdlib only - no API keys, no network. It runs on a synthetic fixture with zero accounts, so it is safe to demo before any real data exists.
Present both files on screen. **Nothing is send-ready until the owner approves the sheet there.** Nothing in this repo sends email - if asked to "just send it", say so plainly and point at the approved sheet and the drafted sequence. The import, and any send, is the owner's step after approval.
The default path is the CSV import - the owner uploads `campaign-sheet.csv` in HubSpot and maps the columns (all default properties, so mapping is automatic).
If a HubSpot MCP or connector is available in the session, offer an alternative: stage the approved rows directly as contacts with `lifecyclestage = lead`. Before any write, confirm the batch size and get an explicit go-ahead, then stage in batches and report what was created. Never create or modify HubSpot records without that on-screen approval, and never stage rows the owner has not approved on the sheet. If no connector is present, do not ask for one - the CSV is the complete path.
End with a one-paragraph recap: rows written, how many carry a resolved contact, the top 3 targets with their one-line reason, and the paths to the two files.
GTM without the SaaS layer. An outbound pipeline built as agent skills for Claude Code and Codex: describe an ICP in plain English and the chain takes it from company discovery to verified, signal-ranked contacts - every step running on raw vendor APIs, not
Plan and run the full API-first GTM chain - the orchestrator (step 00) that turns an ICP description plus optional budget, volume, and urgency into the right…
The qualification gate of the GTM chain - judges every discovered company against the client's ICP before any paid enrichment, so credits are spent only on…
B2B company discovery and list building via the Prospeo search API. Use when the user wants to find companies from an ICP, build a prospect or TAM list, search…
Seed-based B2B company discovery via the Prospeo company-lookalike API. Use when the user has example companies and wants more like them - "find companies…
Find local-business (SMB) prospects via Google Maps using the Apify Compass actor. Use for Zevenue Step-2 Discovery (Vertical) when the ICP is Maps-addressable…
Scrapes a company website into clean, page-typed markdown using Firecrawl map + scrape + extract. Triggers on: "scrape this company", "read their website",…