GTM as code

gtme is a CLI for GTM data pipelines: a small YAML file describes a campaign, the runner executes it against vendor adapters, and an append-only ledger remembers every fact, so re-runs cost less and nothing is delivered twice.

name: apollo-to-instantly
version: 1

source:
  use: apollo/search
  with:
    query: "saas"
    titles: ["vp marketing", "head of marketing"]
    employee_ranges: ["50,200"]
    limit: 5

steps:
  - id: icp-filter
    use: ai/filter
    uses: [first_name, title, company_name]
    with:
      template: >
        Keep only contacts likely to own outbound tooling decisions.
      batch_size: 25

  ...

  - id: personalize
    use: ai/compose
    when: icp-filter.passed
    uses: [recent_posts, role_history]
    with:
      template: >
        Write first_line and ps_line using recent_posts and role_history.
        first_line references something specific and recent; ps_line is one
        short, low-pressure sentence. No flattery, no exclamation marks.
      batch_size: 25

  - id: send
    use: instantly/add-to-campaign
    with:
      campaign: 0198a0b1-2c3d-4e5f-8a9b-0c1d2e3f4a5b   # the campaign id
    variables:
      first_line: first_line
      ps_line: ps_line
    idempotency: email
run 01M3D1ZTKBQBS57C9WPK8NQM60 — done (dry run — nothing sent)
step         adapter                    in  out  empty  cached  filtered  failed  cost     avoided
source       apollo/search              0   5    -      0       -         -       $0       -
icp-filter   ai/filter                  5   5    -      0       -         -       $0.0105  -
reveal       apollo/enrich              5   5    -      0       -         -       $0.0500  -
linkedin     harvest/profile            5   5    -      0       -         -       $0.0600  -
personalize  ai/compose                 5   5    -      0       -         -       $0.0232  -
send         instantly/add-to-campaign  5   0    -      0       -         -       $0       -
send: preflight ok — campaign "Q3 VP Marketing" (0198a0b1-2c3d-4e5f-8a9b-0c1d2e3f4a5b) — 3 check(s) (✓ campaign active, ✓ variable first_line referenced, ✓ variable ps_line referenced)
total: $0.1437 (estimated) spent

That's a dry run against live Apollo, Harvest, Anthropic, and Instantly. Apollo returned five people by title and company size, and the AI judge kept all five. Apollo revealed their contact details, Harvest pulled their LinkedIn profiles, and the model wrote two lines for each. The send step checked the campaign and held all five, so nothing went out. The run cost fourteen cents.

After an armed run adds the five to the campaign, run it again and the paid steps come back from the ledger:

step         adapter                    in  out  empty  cached  filtered  failed  cost  avoided
source       apollo/search              0   5    -      0       -         -       $0    -
icp-filter   ai/filter                  5   0    -      5       -         -       $0    ?
reveal       apollo/enrich              5   0    -      5       -         -       $0    $0.0500
linkedin     harvest/profile            5   0    -      5       -         -       $0    $0.0600
personalize  ai/compose                 5   0    -      5       -         -       $0    ?
send         instantly/add-to-campaign  5   0    -      0       -         -       $0    -
send: 5 already delivered
total: $0 (estimated) spent, $0.1100+? avoided via cache (20 records skipped)

Every paid step reads cached 5 and spends $0. The Apollo and Harvest rows show their dollars under avoided, and the AI rows show a ?, which is why the total ends in +?. The send step reads 5 already delivered: the five are already in the campaign, and idempotency: email keeps a re-run from adding anyone twice. That isn't a saving, so it isn't counted as cached.

Install

brew install gtme-run/tap/gtme     # macOS and Linux, arm64 and amd64

The formula installs one static binary. Nothing runs in the background, and there's no account to create. The example runs five people because that's the size we recommend for a first run; limit: is the line to raise after that. Install covers the release tarball, go install, and building from a checkout.

Start has four ways to begin, sorted by what you have on hand. The first needs no keys and spends nothing.