territory-gtm
Claude Code plugin · Python · free public data

From a county tax roll to a ranked call list

territory-gtm finds every commercial property with grounds worth servicing in a county, traces each one to the company that actually signs the contract, and scores it 0–100 with a one-line outreach angle. Built for tree care; adaptable to landscaping, roofing, paving and other field services.

1.6 Mcounty accounts read
78,481in a target segment
32,317with 1+ acre of grounds
9,890buyer accounts
169tier-A accounts to call first

Harris County, TX with the bundled config: about 2½ minutes on a laptop after the download, $0 in data costs.

What you get

A list your team can work on Monday

Everything lands in runs/<county>/output/. Every value carries a source column, so anyone can check where a number came from.

Lead workbook

One tab per segment, management companies, managed communities, contacts, method, rules and sources.

Top-50 call sheet

Who to call, why them, and the angle, written from each account's own acreage, canopy and storm history.

Clay-ready tables

Companies, people and communities as linked CSVs with stable ids, ready to import as Clay tables.

Contact shortlist

The accounts worth researching, with the credit estimate you approve before anything is spent.

Storm alerts

A weekly list of accounts with a property near a new National Weather Service damage report.

Checkpoints

Samples and top-buyer lists to review with Claude before you trust the list.

Quick start

Install, then run the demo

You need Claude Code (the desktop app or the CLI) and Python 3.10+. For contacts you'll also want Apollo and/or Clay connected in Claude; they're optional and never used without your approval.

  1. Add the marketplace and install the plugin. In Claude Code, type:
    /plugin marketplace add qdevery/territory-gtm
    /plugin install territory-gtm@territory-gtm
  2. Open a working folder. Start Claude Code in an empty folder where your county projects will live, for example ~/territory. Projects go in runs/ inside it.
  3. Run the demo. It builds a synthetic county end to end, offline, in about a minute, and walks you through the output. Claude sets up the Python tool the first time.
    /territory-gtm:demo
  4. Build a real county. Ask in plain words, or use the command:

    “Build a tree-care account list for Harris County, TX.”

    /territory-gtm:build Harris County, TX

Install trouble with GDAL or rasterio? See the FAQ.

How it works

Seven steps, two checkpoints

The pipeline is plain Python driven by two YAML files: county.yaml (where the data is and what the local codes mean) and trade.yaml (segments, rules, scoring, angles). Claude runs it, stops at the checkpoints, and explains the result.

1NormalizeRead the county roll into one standard parcel table.
2 · checkClassifyRules put each parcel in a segment. First match wins.
3CanopyTree cover averaged over each parcel outline.
4 · checkWho buysRoll parcels up to the company that signs.
5StormsExposure to the region's defining storms.
6Score0–100, tier, and an outreach angle.
7ExportWorkbook, call sheet, Clay CSVs, alert points.
Classify rules over tags + keywords

Each county uses its own codes, so county.yaml translates them into shared tags (state class B1 → multifamily, building type 4389 → country_club_golf). The trade's rules only talk about tags and name keywords, so the same rules work in any county. For tree care the order is:

Districts → Cemeteries → Golf → Senior living → Churches → HOAs → Apartments → Other commercial, with cities, school districts, condo units and homes excluded.

Checkpoint 1 writes counts, 25 samples per segment and the 200 largest uncertain parcels. Claude reviews them with you and fixes misfires, such as “HOA” read as a given name.

Who buys the step that makes the list useful

The owner on the deed is often an LLC that never hires anyone. Each parcel's buyer is the first of:

  • the district itself (utility districts buy by board vote and public bids)
  • the operator on a state licensed-facility list (senior living)
  • a verified management firm from your firm_aliases.csv
  • the care-of business on the tax bill's mailing line
  • the firm most often named at that mailing address county-wide
  • an owner group sharing a mailing address, or the owner

Checkpoint 2 lists the top buyers and the firms worth verifying. Claude checks the largest on their own websites and adds them to firm_aliases.csv.

Storms NWS Local Storm Reports

Each county lists its defining storms with a method: gust_field estimates the peak gust at each property from measured gusts (hurricanes); nearest_report uses the distance to the nearest damage report (derechos, tornado outbreaks, ice); recent keeps the score current with the last 12 months. Reports come from the Iowa Environmental Mesonet archive, because the Storm Prediction Center's pages disallow automated access.

The score

A60+ · call first
B45–59 · nurture
Cunder 45 · mail / later

Every weight, cap and cut-off is in trade.yaml. A paving trade sets canopy to 0 points; roofing raises storm and adds a hail event.

Sample output

What the top of the list looks like

From the synthetic demo county. Every name is invented. A real county looks the same, with real management firms, operators and clubs.

AccountSegmentScorePropsAcresCanopy acStorm
Pinecone Community ManagementHOA – ManagedA 86832215069
Bluebird Association ServicesHOA – ManagedA 86828912970
Copperleaf HOA ManagementHOA – ManagedA 83723810365
Heron Landing Country ClubGolfA 80125813277
Summit Hollow ResidentialApartmentsA 77152663565

“Pinecone Community Management manages 8 associations here with about 150 canopy acres of common area, many inside the Spring 2024 derecho damage area, so pitch one portfolio-wide tree-risk inventory and pre-storm-season pruning bid its managers can take to each board this budget season.”

The outreach angle for the top account, written from its own row.

Build a county

A real county, step by step

With the plugin, Claude drives these steps and pauses where your judgment matters. The commands are shown so you can run or rerun any step yourself.

  1. Pick the county and trade. Bundled: harris_tx and the demo county; tree care. For anything else Claude writes the configs with you (see New county / trade).
    tgtm init runs/harris --county harris_tx --trade tree_care
  2. Download the public data. The roll and parcel outlines from the appraisal district, a tree-canopy clip from MRLC, and storm reports from the Iowa Mesonet. Claude checks each source's terms first.
    tgtm fetch runs/harris
  3. Checkpoint 1: is every parcel in the right bucket? Review the samples with Claude and fix the rules until they read right.
    tgtm normalize runs/harris && tgtm classify runs/harris
    # output/checkpoints/1_classification_counts.csv, 1_samples_by_segment.csv
  4. Checkpoint 2: who actually buys? Verify the biggest management firms on their own sites, add them to firm_aliases.csv, rerun.
    tgtm canopy runs/harris && tgtm rollup runs/harris
    # output/checkpoints/2_top_buyers_by_acres.csv, 2_firm_alias_candidates.csv
  5. Score and export.
    tgtm storms runs/harris && tgtm score runs/harris && tgtm export runs/harris
    # or everything from a step on:  tgtm run runs/harris --from score
Contacts

Cheapest first, and no yes, no spend

Contacts are optional. Claude uses your own Apollo and Clay connections, starts with the free lookups, and stops for your approval before every paid batch. The result is one file, contacts.csv, merged into the workbook on the next export.

1 · ShortlistTier-A accounts, minus segments with no people search. tgtm shortlist
2 · MatchFind each account's real company and domain. Free.
3 · CountPeople search by buyer title returns names, no emails. Free.
4 · You approve“N people at M accounts, about N credits.” Nothing runs until you say yes.

“Find contacts for the tier-A accounts. Show me the count and the credit estimate first.”

Self-managed HOAs and public districts are never people-searched: their boards are volunteers. They get public websites, office lines and the operator firm instead.

Storm alerts

Know which accounts got hit this week

The alert pulls the National Weather Service's Local Storm Reports for your county's offices and keeps the ones that matter for grounds: wind damage, tornadoes, ice, tropical damage, 50+ mph gusts, large hail, and remarks that mention trees. Every property within 3 km is listed, closest damage and highest score first.

Run it after a storm, replay a past one to test your pitch, or ask Claude to schedule it every Monday.

tgtm alert runs/harris                    # last 7 days
tgtm alert runs/harris --days 14 --km 3
tgtm alert runs/harris --start 2024-05-16 --end 2024-05-18
/territory-gtm:storm-alert runs/harris
New county / new trade

Two YAML files, written with Claude

A new county

Ask “Add Travis County, TX.” Claude finds the appraisal district's bulk download, inspects the columns and code tables, and writes county.yaml. Most counties fit the generic adapter: one parcel layer with owner and land-use fields.

adapter: generic
source: {parcels: parcels.shp}
columns: {parcel_id: PROP_ID, owner_name: OWNER,
          mailto: MAIL_NAME, acreage: ACRES}
code_columns: {state_class: STATE_CD}
codes:
  state_class: {B1: multifamily, X3: religious_exempt}
nws_offices: [EWX]

A new trade

Ask “Make a roofing version.” Claude interviews you (who buys, what makes a good prospect, the smallest job worth a visit) and edits a copy of tree_care.yaml: segments, fit, buyer titles, angles and score weights.

score:
  canopy: {points: 0}        # roofs, not trees
  storm:  {points: 35}       # + a hail event in county.yaml
  acreage: {points: 20, full_at: 50}
segments:
  - id: apartments
    fit: 0.9
    buyer_titles: Regional Maintenance Director
Guardrails

Research and files only

These are written into the skills, and the plugin's hook enforces the first and last while Claude works in a project folder.

Nothing is sent. No emails, sequences, campaigns or CRM records. The hook blocks those tools.
Public data only. Never around a login, paywall, CAPTCHA, robots.txt or a site's terms.
Business contacts only. No personal emails or cells, no home addresses, no skip tracing. Free-mail addresses are dropped on export.
No volunteers. HOA board members and other private individuals are never looked up.
Don't guess. A missing value stays missing, with a suggested source to fill it.
Ask before spending. Count and estimate first; the hook asks again before any credit-spending tool runs.

The hook only acts inside a folder that holds county.yaml and trade.yaml. TGTM_GUARDRAILS=always applies it everywhere; TGTM_ALLOW_OUTREACH=1 lifts the outreach block in a session where you've decided to do outreach.

Data sources

Where every number comes from

SourceUsed forCost
County appraisal district / assessor bulk data (e.g. HCAD)Owners, mailing and care-of lines, acreage, land and building codes, parcel outlinesFree
USFS / NLCD Tree Canopy Cover (30 m)Canopy share and canopy acres per parcelFree
NWS Local Storm Reports, Iowa Environmental MesonetStorm exposure and weekly alertsFree
State licensed-facility lists (e.g. Texas HHSC)Senior living operators and facility phonesFree
Organizations' own websitesVerifying management firms; office linesFree
Apollo, Clay (your accounts)Business contacts, behind the credit gateYour credits

Terms change. Check each source's terms of use before commercial use.

FAQ & troubleshooting

When something doesn't work

pip install fails on GDAL, rasterio or pyogrio

Recent Python versions on macOS, Windows and Linux get prebuilt wheels. If yours doesn't, install the geo stack from conda-forge, then the package without dependencies:

conda install -c conda-forge geopandas rasterio rasterstats pyyaml openpyxl
pip install --no-deps -e .
“MRLC returned an error instead of a GeoTIFF”

The county's box is too large for one request, or the service is down. Shrink bbox in county.yaml, or download Tree Canopy Cover from mrlc.gov/data and save it as raw/canopy.tif. Any canopy raster with 0–100 values works.

My county's data is behind a login or an order form

The pipeline never gets around a login, paywall or CAPTCHA. Many districts provide the same files free through a public records request; once you have them, put them in raw/ and point county.yaml at them.

Small HOA parcels have no canopy reading

The canopy raster is 30 m, so parcels smaller than about one pixel get no reading. Those accounts score on canopy from their other parcels. A finer raster fixes it: convert a 1 m canopy height map (Meta and WRI publish one free on AWS Open Data) to percent cover and save it as raw/canopy.tif.

Lots of “Unnamed Manager @ …” accounts

That's an office mailing address shared by five or more associations whose care-of line doesn't name the firm. Open 2_firm_alias_candidates.csv, check the firm on its website, add a row to firm_aliases.csv, and rerun from rollup.

Can I use it outside Texas?

Yes. Canopy and storm data are national. You need the county's parcel data and a county.yaml mapping its codes; the add-county skill walks Claude through it. Texas-only extras (HHSC, TCEQ) are simply left out.

Where is my data stored?

On your machine, in the project folder. runs/, contacts.csv and firm_aliases.csv are git-ignored, so lead lists don't end up in a repository by accident.