Your battle cards are wrong and nobody told you

Over the past two months I wrote five competitive teardowns. Attio against Salesforce. Clay against ZoomInfo. Harvey against Thomson Reuters. Two more after those.

By the time the fifth one shipped, the first was already wrong.

The competitor had changed their pricing page. A gap I'd used as a clean "here's where we win" was now a feature they also shipped. My teardown still said the old thing, confidently, sitting in a doc a sales team was about to read out loud on a live call.

That's the problem with a battle card. It's a screenshot of a moving target. You do the deep work once, you feel good about it, and it starts rotting the day you save the file.

So I built something that keeps them current on their own. It's called the Competitive Intel Engine. It runs on Claude Code, and this week's release is the whole thing: the skill that writes the card, the monitor that watches the competitor, and the script that ties them together. Here is how it works and how to point it at your own market.

Why battle cards rot

Three failures, and every stale card has at least one.

They're ungrounded. "They're weak on security" is an opinion until it quotes the competitor's own words. Most cards are full of these. They sound confident and they fall apart the second a buyer pushes back, because the rep cannot say where the claim came from.

Here is what that looks like in the room. A rep says "they don't offer SSO." The buyer, who evaluated them last week, says "they added it in March." The rep has now lost the next twenty minutes, and the card lost every other claim on it too, because if that one was wrong, why trust the rest.

They're static. The competitor ships a feature, drops a price, lands a logo. The card still says what was true two quarters ago. Nobody re-opens a doc that already feels finished.

They're centralized. One person owns the file. Every update waits behind that person having a free afternoon to go re-read a competitor's website. They rarely do, and the card ages in the meantime.

The fix is to stop treating a battle card like a document and start treating it like monitored infrastructure. Grounded in cited sources. Watched for change. Rebuilt automatically when something moves.

What the engine actually does

You give it one file per competitor. It gives you back a card that cites its own claims, and it rewrites that card whenever the competitor changes something you're watching.

The input is a small profile, competitor.yaml:

name: "Northwind CRM"
your_product: "your CRM"
your_differentiators:
  - "usage-based pricing with no per-seat floor"
  - "native revenue attribution, not a paid add-on"
  - "SSO included on every paid tier"
sources:
  - label: "pricing"
    url: "<https://northwind.example/pricing>"
    type: "pricing"
  - label: "changelog"
    url: "<https://northwind.example/changelog>"
    type: "changelog"

Two things you edit, and they are the whole point of tuning this to your own market. The case you want the card to make lives in your_differentiators. The pages worth watching live in sources. Swap in your real competitor and their real URLs and the engine is live for you. Point it at the pages where competitive reality actually changes, which is almost always the pricing page and the changelog, plus a review profile and the newsroom.

The output is a card with a fixed shape, built so a rep can read it in ninety seconds before a call:

  1. What they are, one sentence.

  2. Where you win. Three specific advantages, each cited.

  3. Where they win. Two honest ones.

  4. The objections they create, with a calibrated response to each.

  5. Three landmine questions a rep can ask to expose a weak spot.

  6. A one-line verdict the rep can say out loud.

Section three is the one people want to skip, and it is the one that makes the card work. Two real strengths, stated plainly. A card that pretends the competitor is bad at everything gets ignored by the first rep who reads it, because reps know better and they can smell a hype doc. Honesty is what makes the rest of the card believable.

Every factual line ends with a citation like [pricing] that maps to a real URL at the bottom of the card. When a buyer says "that's not true anymore," the rep clicks the source instead of guessing.

The part that keeps it alive

A card that is right today and wrong in March is only half the job. The engine's other half is a watcher.

weekly-refresh.py walks every competitor you track, fetches each source, and compares it to a snapshot from the last run. Nothing exotic: it strips the page to text, hashes it, and diffs it against what it saw before. If a source changed, it flags that card as stale and prints exactly what to run to rebuild it.

$ python scripts/weekly-refresh.py
[STALE] Northwind CRM
    - pricing: changed
    - changelog: changed

Cards to regenerate:
  claude -p "/battlecard northwind"   # rewrites competitors/northwind/battlecard.md

There is a companion piece too, a source-monitor agent, whose only job is to fetch a competitor's pages and report what moved in plain language: a new pricing tier, a shipped feature, a leadership change. It is read-only on purpose. It reports; you and the script decide what to rebuild.

Set a Slack webhook and the script messages you the summary instead of waiting for you to check. Put it on a weekly cron with --auto-regen and it rebuilds the stale cards itself, so a competitor's pricing change reaches your reps the same week it happens instead of the quarter after someone notices. The script exits with code 1 when anything is stale, so you can wire it into a scheduler and treat "a competitor moved" as an event, not a chore you keep forgetting.

How to run it

Four steps to a first card.

git clone <https://github.com/tga-cheetung/competitive-intel-engine.git>
cd competitive-intel-engine
pip install -r requirements.txt
cp -r competitors/_template competitors/northwind

Fill in competitors/northwind/competitor.yaml with your competitor and your differentiators. Then:

claude -p "/battlecard northwind"
python scripts/weekly-refresh.py

The first run builds the card. Every run after that keeps it honest. The repo ships with a worked example, a fictional "Northwind CRM," so you can read the input and the output side by side before you touch a real competitor. The only dependency is PyYAML. Everything else is the Python standard library, so there is nothing to sign up for.

Why this matters more than it looks

A battle card is one of the few sales assets where being wrong is worse than being absent. A rep with no card knows they are winging it and plays careful. A rep with a stale card walks in armed with a claim the buyer can disprove in one sentence, and loses the room with their own ammunition.

The reason most teams live with stale cards is not laziness. It is that the update loop depends on a person remembering to care, on a Tuesday, about a pricing page they do not own. Remove the person from that loop and the problem stops existing. The card watches its own sources. It tells you when it is wrong. It fixes itself if you let it.

That is the whole idea behind everything I build. The system runs without you standing over it. A battle card that maintains itself is a small version of that, and it is the kind of thing you can stand up in an afternoon.

The full repo is this week's release, MIT licensed, on GitHub. Clone it, point it at the competitor you lose to most, and find out what your current card is already getting wrong.

If you want the rest of what I have shipped like this, the systems and skills behind the pipeline are all in one place. Subscribe and they land in your inbox as they go out.

Until next week,
The GTM Architects

Keep Reading