| name | company-research |
| platforms | ["claude-code"] |
| description | Research any company from the public web — pricing, customers, recent launches, hires, blog activity, headline/positioning, exec team — and audit AEO basics (homepage rendering, schema, robots.txt, llms.txt, sitemaps). Simulates a fresh LLM crawler hitting the site for the first time so you can see what answer engines actually learn about the company. Use when the user asks to research a company, run an AEO audit, check what LLMs can see about [company], audit a website for answer-engine visibility, profile a competitor or prospect from the public web, or says 'pretend you've never heard of [company]'. Produces a markdown report with a data-point/source table, AEO findings, easy/hard/impossible summary, and a fix list. Bash-only — needs curl for bot UA negotiation tests, so claude-code platform only. |
Company Research
Research any company from a fresh LLM crawler's perspective. Simulates how an answer engine (ChatGPT, Claude, Perplexity, Google AI Overviews) would see the site if it had no prior knowledge, then audits the AEO fundamentals — JS rendering, structured data, robots.txt, llms.txt, sitemaps.
Use this for:
- Auditing your own company's AEO readiness
- Profiling a competitor or prospect from the public web
- Spot-checking what answer engines actually surface about a brand
- Diagnosing why a company is invisible to LLMs
This skill is external-only — it does not fetch Tiger Den reference docs. But it still runs the standard pre-flight for usage attribution.
When to use this skill
- "Run an AEO audit on [url]"
- "Pretend you've never heard of [company] and research them"
- "What can LLMs see about [company]?"
- "Profile [competitor/prospect] from the public web"
- "Check [company]'s answer-engine visibility"
- "Audit [url] for LLM crawler discoverability"
Step 0: Pre-flight check
Invoke the marketing-preflight skill via the Skill tool, passing this skill's name: field value (company-research) as the args. Do not proceed until it completes successfully. If it stops with an error, follow its instructions and stop.
If marketing-preflight returned a stale-connector footer note, append it verbatim at the end of your final response to the user.
Inputs
Ask only what you need:
- Target URL (required) — e.g.,
https://www.example.com
- Company type hint (optional) — OSS-first, SaaS, marketplace, agency, etc. Affects the Wikipedia recommendation pattern (see "Known patterns" below).
- Output file path (optional) — default:
~/Desktop/<domain>-company-research.md
If the user gave just a URL, run with defaults. Don't pepper them with questions.
Methodology
Run the AEO basics checks and the public-web reconnaissance in parallel wherever possible — these are independent fetches.
Bot user-agent negotiation test (the most important AEO check)
Many modern sites do content negotiation by user-agent. Test the homepage with multiple UAs and compare response sizes and content-type:
URL="https://www.example.com"
for UA in \
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36" \
"Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" \
"Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)" \
"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; PerplexityBot/1.0)" \
"Mozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; GPTBot/1.2; +https://openai.com/gptbot)" \
"Mozilla/5.0 (compatible; ClaudeBot/1.0; +claudebot@anthropic.com)" \
""; do
SIZE=$(curl -sL -A "$UA" "$URL" | wc -c)
CT=$(curl -sIL -A "$UA" "$URL" | grep -i "^content-type:" | tr -d '\r')
XMP=$(curl -sIL -A "$UA" "$URL" | grep -i "^x-matched-path:" | tr -d '\r')
echo "UA: ${UA:0:50}... | size=$SIZE | $CT | $XMP"
done
Flag any of these patterns:
- Bot UAs get dramatically smaller responses → site is serving a markdown/text shell to LLMs (good AEO play, like Tiger Data does)
- Bot UAs get the same JS-shell as everything else → site is JS-rendered and bots can't see content
- Bot UAs get blocked (403/429) → site is hostile to LLM crawlers (often unintentional)
JS-rendering and content shell check
curl -sL -A "Mozilla/5.0 (compatible; ClaudeBot/1.0)" "$URL" -o /tmp/cr_home.html
echo "Size: $(wc -c < /tmp/cr_home.html) bytes"
If the body is a JS shell, also try the browser UA:
curl -sL -A "Mozilla/5.0 ... Chrome/120.0 Safari/537.36" "$URL" -o /tmp/cr_browser.html
echo "Browser size: $(wc -c < /tmp/cr_browser.html) bytes"
A big delta between bot and browser sizes is the smoking gun: bots are seeing nothing.
Schema / JSON-LD extraction
python3 -c "
import re, json
html = open('/tmp/cr_browser.html').read()
blocks = re.findall(r'<script type=\"application/ld\+json\"[^>]*>(.*?)</script>', html, re.DOTALL)
print(f'Found {len(blocks)} JSON-LD blocks')
for i, b in enumerate(blocks):
try:
parsed = json.loads(b)
types = parsed.get('@type') if isinstance(parsed, dict) else [x.get('@type') for x in parsed]
print(f'Block {i+1}: @type={types}')
print(json.dumps(parsed, indent=2)[:1500])
except Exception as e:
print(f'Block {i+1} parse error: {e}')"
Record:
- How many JSON-LD blocks exist
- Which
@types are present (Organization, Product, WebSite, BreadcrumbList, FAQPage, Article, SoftwareApplication)
- Whether
sameAs includes Wikipedia, GitHub, LinkedIn, X, YouTube
- For
Organization: legalName, alternateName, founder, foundingDate, logo, contactPoint
Meta tag inspection
python3 -c "
import re
html = open('/tmp/cr_browser.html').read()
print('TITLE:', re.search(r'<title>([^<]*)</title>', html).group(1) if re.search(r'<title>([^<]*)</title>', html) else 'NONE')
metas = re.findall(r'<meta[^>]+>', html)
for m in metas[:30]:
if any(k in m for k in ['description', 'og:', 'twitter:', 'robots', 'canonical']):
print(m[:250])"
robots.txt
curl -sL "$URL/robots.txt"
Look for:
- Explicit rules (Allow/Disallow) for: GPTBot, ClaudeBot, anthropic-ai, CCBot, PerplexityBot, Google-Extended, Bytespider, Amazonbot, Applebot-Extended, OAI-SearchBot, ChatGPT-User, Diffbot, Omgilibot
- Declared sitemaps
- Any unusual disallow paths
llms.txt and llms-full.txt
curl -sI "$URL/llms.txt" | head -3
curl -sI "$URL/llms-full.txt" | head -3
If either returns 200, fetch and note the size. These are LLM-specific overview files — having them is a strong AEO signal.
Sitemap analysis
curl -sL "$URL/sitemap.xml" | head -50
curl -sL "$URL/blog/sitemap.xml" | grep -c '<url>'
curl -sL "$URL/blog/sitemap.xml" | python3 -c "
import sys, re
data = sys.stdin.read()
urls = re.findall(r'<url>\s*<loc>([^<]+)</loc>\s*<lastmod>([^<]+)</lastmod>', data)
urls.sort(key=lambda x: x[1], reverse=True)
for u, d in urls[:10]:
print(f'{d[:10]} {u}')"
Per-page bot UA spot checks
The homepage's negotiation behavior may not apply to all pages. Test these specifically with a bot UA:
/pricing
/about
/customers or /case-studies
/blog (index)
/careers or /team
If some return markdown and others return full HTML, that's an inconsistency flag — call it out in the fix list.
Public-web reconnaissance (run in parallel with the above)
Use WebSearch to find data points the site itself won't surface:
| Data point | Query template |
|---|
| Pricing (third-party confirmation) | "<company>" pricing |
| Customers | "<company>" customers case studies |
| Recent launches | "<company>" launch announcement <year> new product |
| Recent news | "<company>" news <year> |
| Funding | "<company>" funding round Series investors |
| Hires | "<company>" hires hired joins announcement <year> |
| Exec team | "<company>" CEO founder leadership team |
| Competitive comparisons | "<company>" vs <known competitor> |
| Reviews | "<company>" reviews G2 Gartner |
If the company has a generic name (e.g., "Tiger Data" collides with "Tiger Analytics" / "TigerGraph"), add disambiguating terms — product name, founder name, industry — to filter noise. If a search returns mostly unrelated companies, stop and tell the user.
Use WebFetch for pages that need parsed extraction (e.g., /about for exec team bios).
Data points to gather
For every audit, fill out this table — one row per dimension, with a "how I found it" column so the user can trust and reproduce each finding:
| Dimension | What I learned | How I found it |
|---|
| Headline / positioning | | |
| Title / meta description | | |
| Pricing | | |
| Customers (named) | | |
| Customer logos (visual) | | |
| Recent launches | | |
| Exec team | | |
| Funding | | |
| Blog activity (count + cadence) | | |
| New hires | | |
Social presence (sameAs) | | |
If a row is empty, say so explicitly with a note about why (e.g., "no PR found," "gated behind PitchBook," "no clear naming convention to search by"). Empty rows are signal.
AEO basics section
Always include these three subsections:
Homepage rendering
Present the bot UA negotiation results as a table. Highlight any divergence.
| User-agent | Response size | Format | x-matched-path |
|---|
| Browser (Chrome) | | | |
| Googlebot | | | |
| Bingbot | | | |
| PerplexityBot | | | |
| GPTBot | | | |
| ClaudeBot | | | |
State the headline finding in one sentence (e.g., "Site serves clean markdown to GPT/Claude bots and full HTML to everyone else" or "Site is a JS shell — bots see nothing").
Schema markup
- Number of JSON-LD blocks
@types present
- Notable fields in
Organization schema (founders, sameAs, alternateName)
- Gaps (no
Product, no FAQPage, no WebSite, etc.)
robots.txt
- Permissive vs restrictive
- Explicit AI bot rules (or absence thereof)
- Sitemaps declared
Output format
Write a markdown report following exactly this structure:
# <Company> AEO Audit
*Fresh-crawler perspective — what an LLM hitting <domain> for the first time can actually see.*
**Audit date:** <YYYY-MM-DD>
## What I found, and how
<data-points table>
## AEO basics
### Homepage rendering — <one-line summary of the headline finding>
<UA table + commentary>
### Schema markup
<bullets>
### robots.txt
<bullets>
## Summary: easy, hard, impossible
**Easy** (one fetch or one search away):
- ...
**Hard** (took multiple queries, fragmented):
- ...
**Impossible/blocked**:
- ...
## What to fix
1. ...
2. ...
(numbered list of concrete, actionable recommendations)
## Methods used
<bullets describing the techniques applied>
## Sources
<markdown link list>
Save to the user's chosen path. Default: ~/Desktop/<domain-stripped>-company-research.md.
Known patterns
OSS-first companies and Wikipedia
If the target is an open-source-first company (HashiCorp-style, ClickHouse, Confluent, Redpanda, Timescale/Tiger Data), do not recommend creating a separate company Wikipedia page. These companies are handled at the product level on Wikipedia, and standalone company entries usually get merged or redirected.
Instead, recommend:
- Updating the existing product article (e.g.,
TimescaleDB) to reflect the current company name and history
- Creating a redirect from the company name → the product article
- Updating JSON-LD
sameAs to point to the (now-rebrand-aware) product article
This applies any time the company has a more famous OSS product than corporate brand.
JS-shell sites
If the homepage is a JS shell (under ~5KB to bots, large to browsers), do not recommend "just add SSR" — that's a multi-quarter engineering project. Practical recommendations:
- Add
/llms.txt and /llms-full.txt as a markdown content layer
- Implement bot UA negotiation (like Tiger Data does, rewriting GPTBot/ClaudeBot to a
/md route)
- Pre-render the most important pages (homepage, pricing, top blog posts) at build time
- At minimum, ensure
<title>, <meta name="description">, and JSON-LD are in the initial HTML payload
Inconsistent bot negotiation
If the homepage serves markdown to bots but /about (or /case-studies, etc.) serves full HTML, recommend extending the /md rewrite rule to cover those routes. This is the most common gap in otherwise-good AEO setups.
Funding number drift
If multiple funding numbers surface across blog posts ($40M, $110M, $180M), the older post titles often still rank. Recommend:
- Stating the cumulative total prominently in
/llms.txt
- Updating
/about and the JSON-LD description
- Adding a current "About" snippet to recent blog posts' author bio sections
Anti-patterns
- Don't trust a single WebFetch result for the homepage. WebFetch may pull a rendered/cached version that doesn't reflect what bots actually see. Always verify with
curl + bot UAs.
- Don't claim something is missing without checking the bot UA variant. If
/pricing looks empty in one fetch, try a different UA.
- Don't make up data. If you can't find a hire, exec, or funding number, say so. Empty rows in the data table are the point.
- Don't recommend fixes the company has already done. If they have
/llms.txt, don't say "add an llms.txt file." Read what's there first.
- Don't burn searches on a polluted name. If "Tiger Data" returns mostly Tiger Analytics, stop and ask the user for a disambiguator (product name, founder, industry).
Reporting back
After saving the file, output a short summary to the user:
- Path to the saved report
- One-sentence headline finding (e.g., "Site is doing sophisticated bot UA negotiation but
/about slips through")
- The top 3 fix recommendations as bullets
Don't paste the full report inline — they have the file.