Skip to Content

gtmesh pull

pull is the one verb for get data from an external source, split by channel — what the data is. Every channel appends an immutable, timestamped export under data/raw/.

gtmesh pull demand --topic slack --dry-run # report the planned pulls, spend nothing gtmesh pull demand --topic slack # pull one root topic gtmesh pull demand # every root topic in the graph gtmesh pull performance # every configured performance provider gtmesh pull serp "water pump" # one keyword's SERP
ChannelWhat it writes
pull demandThe keyword bag (data/raw/keywords/) — the one channel plan reads
pull aiAI-answer citation counts per provider (data/raw/ai/)
pull performanceSearch-performance snapshots + the index sweep (data/raw/performance/)
pull linksBacklinks, domain rating, referring domains (data/raw/links/)
pull serp <keyword>One keyword’s SERP (data/raw/serp/)
pull top-pages <domain>A competitor’s top organic pages (data/raw/top-pages/)

Two modifiers are shared by every channel:

  • --dry-run — report the planned request and spend nothing. Run it first; Ahrefs credits are real money.
  • --stage — write to the git-ignored staging area (.gtmesh/staging) instead of the committed bag. plan ignores staged demand until gtmesh stage admit promotes the keepers.

--source <provider> constrains a channel to one provider.

The Ahrefs-backed channels spend API credits. Run with --dry-run first to see exactly which pulls will fire, and --stage when you’re exploring rather than committing.

pull demand

The keyword channel — raw exports are immutable and timestamped, and plan reads the frozen bag and never re-fetches. That is what keeps the pipeline deterministic.

Four ways in, all writing the same bag:

gtmesh pull demand # every root topic in the graph gtmesh pull demand --keyword "pump,water pump" --bag pumps # explicit terms, expanded gtmesh pull demand --keyword "pc pump" --bag glossary --pull overview # explicit terms, EXACT Vol/KD gtmesh pull demand --source csv --input export.csv --topic slack # import a CSV, no API budget gtmesh pull demand --source seeds --discovery-class glossary # refresh a curated term list
OptionDescriptionDefault
--source <source>Demand adapter (ahrefs | csv | seeds)ahrefs
--topic <value>Root topic to pullevery root topic in the graph
--keyword <kw>Comma-separated explicit terms to pull instead of the graph’s root seeds
--label <label>The bag-path label an explicit-term pull writes under (required with --keyword)
--pull <kind>Single pull (matching-terms | questions | overview)configured pulls
--input <file>Source CSV (for --source csv)
--discovery-class <id>Discovery class to refresh (for --source seeds)all configured
--country <cc>ISO alpha-2 country overridethe configured market
--dry-runReport the planned pulls without spending API creditsoff
--stageWrite to the staging area, not the committed bagoff

With no --topic and no --keyword, the pull covers every root topic in the committed graph: each root’s seed_terms are the pull heads, and its exclusions layer onto the global adapters.ahrefs.exclude_substrings for that pull.

Explicit terms (--keyword) take their seeds straight from the flag, so a demand pull works during discovery cycle 0 — before gtmesh init exists — and during harvest, when candidates aren’t committed to seeds/<class>.csv yet. --pull overview swaps expansion for exact per-term Vol/KD, which is what harvest ranks brainstormed candidates on.

A pull writes the committed bag by default, so the next gtmesh apply catalogues every term as a page. To rank and cut candidates without committing them, add --stage — the pull lands in the git-ignored staging area, plan ignores it, and gtmesh stage admit promotes only the keepers.

pull serp <keyword>

Pull a keyword’s SERP from Ahrefs (serp-overview); append a timestamped export to data/raw/serp/. The operator skill reads it to decide a cluster’s comparison model from evidence.

Argument / OptionDescriptionDefault
<keyword>The keyword to pull the SERP for (a discovery cluster head)
--country <cc>ISO alpha-2 countrytaxonomy.markets[0]; required pre-init
--limit <n>Limit to the top N organic positionsall
--dry-runReport the planned pull without spending API creditsoff
--stageWrite to the staging area, not the committed bagoff

pull top-pages <domain>

Pull a competitor domain’s top organic pages from Ahrefs; append a timestamped export to data/raw/top-pages/. Feeds the operator skill’s competitor analysis.

Argument / OptionDescriptionDefault
<domain>The competitor domain to pull top pages for (e.g. example.com)
--country <cc>ISO alpha-2 countrytaxonomy.markets[0]; required pre-init
--date <yyyy-mm-dd>Metrics reporting datetoday (UTC)
--mode <scope>Search scope: exact | prefix | domain | subdomainssubdomains
--limit <n>Max pages to pullall
--dry-runReport the planned pull without spending API creditsoff
--stageWrite to the staging area, not the committed bagoff

The observation channels

pull ai, pull performance, and pull links snapshot how the live site is doing. They are read-time observations: the snapshots never enter plan/apply, they are joined at read time by topic performance and the ui. Each fans out to every configured provider of its channel; --source <provider> constrains the fan-out. See the CLI reference for their full option tables and one-time setup.

Reads & writes

  • Reads: the adapters.* config, the committed graph’s root topics (and --input for the CSV source). Ahrefs-backed channels need AHREFS_API_TOKEN set.
  • Writes: timestamped exports under data/raw/<channel>/<provider>/ — or .gtmesh/staging/ with --stage.
  • Committed: yes — the raw exports are diffable and committed (staged pulls are git-ignored).
Last updated on