From polecat-x
Generate a standalone, publishable HTML report with D3 visualisations from PolecatX media monitoring data. Use when the user asks for a PolecatX report, a media or reputational analysis of an entity over a date range, or wants events data fetched, analysed, and rendered as a shareable HTML page.
How this skill is triggered — by the user, by Claude, or both
Slash command
/polecat-x:reportThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate a standalone HTML report from PolecatX media monitoring data, with bespoke D3 visualisations and analysis.
Generate a standalone HTML report from PolecatX media monitoring data, with bespoke D3 visualisations and analysis.
POLECATX_API_KEY is set. If not, tell the user to add it to .claude/settings.local.json under "env" and stop.templates/report-shell.html — the canonical page shell (chrome, CSS, helpers). Copied verbatim.templates/components.md — suggested body snippets (sections, cards, tables).design-tokens.md — palette and conventions for the chart code you write.Ask for anything not already provided:
2024-01-01T00:00:00Z (required). Never invent or guess a range. If the user hasn't given one and none is clearly implied by their request (e.g. "last week", "Q1 2026"), stop and explicitly ask for it before fetching.sentiment, esg_controversies, locations, source_categories, etc.If given a name (not an ID starting with organization_ / person_ / topic_):
curl -s -X POST -H "Authorization: Bearer $POLECATX_API_KEY" -H "Content-Type: application/json" \
-d '{"name": "<name>", "limit": 5}' \
"https://x.polecat.com/beta/entities/search"
If no match, offer to create the entity (see polecat-x-api skill for the create call) before continuing.
POST /events triggers a scan and returns fresh data. Pipe directly to file — do not load the full response into context:
curl -s -X POST -H "Authorization: Bearer $POLECATX_API_KEY" -H "Content-Type: application/json" \
-d '{ "entity": ["<entity-id>"], "start": "<start>", "end": "<end>" }' \
"https://x.polecat.com/beta/events" > <slug>.json
Filename convention: {entity-slug}-{start-date}--{end-date}.json
where entity-slug = entity name lowercased with spaces replaced by hyphens, dates are YYYY-MM-DD only (e.g. spacex-2026-06-09--2026-06-15.json).
Add optional filter fields to the JSON body as needed. Then read a lightweight summary for analysis:
cat <slug>.json | python3 -c "
import json,sys
d = json.load(sys.stdin)
for e in sorted(d['data']['events'], key=lambda x: -x['score']):
print(f\"{e['score']:.1f} {e['sentiment'][:3]} {e['summary'][:80]}\")
print('timeSeries points:', len(d['data']['timeSeries']))
"
What the score is. Each event's score is the Net Sentiment Score, a 0–100 sentiment scale: 0 = very negative, 50 = neutral, 100 = very positive (docs). It is not a measure of importance or prominence — a 100 means most positive, not most newsworthy. Reach/prominence comes from the number of sources and the scoringFactors (traffic, spread, tier, credibility). The timeSeries is the Net Sentiment Score trended over the period.
Examine data.events and data.timeSeries. Apply the focus prompt if provided, otherwise look for:
spread/trafficIdentify 2–4 narrative threads that will become report sections.
Build the report from the templates — don't write the page from scratch:
cp templates/report-shell.html <slug>.html. The shell carries the canonical <style>, header, lede, stat row, data note, tooltip, and standard JS helpers. Leave all of that as-is — it's what keeps every report visually identical.{{PLACEHOLDERS}} in the header, lede, stat row and data note with real values (all derivable from DATA).<main id="report-body"> using the snippets in templates/components.md. Pick the sections, order, and charts that fit the data and the narrative — this is the part that should vary between reports. Drop or adapt any snippet; if the user asked for a specific structure, follow that.<script> block where marked, drawing each chart into its .chart-wrap container. Follow the chart conventions in design-tokens.md.python3 -c "
f = '<slug>.html'
open(f, 'w').write(open(f).read().replace('__POLECAT_DATA__', open('<slug>.json').read()))
"
This replaces the placeholder with the raw file contents in one operation — no reading JSON into context, no risk of mangling special characters.
Lead with what the data makes most striking — the strongest sentiment (very positive or very negative), the highest-reach story, a major ESG controversy, or a sharp move in the time series. Don't assume a high score means "biggest story" (see the score note above). Give each phenomenon the chart that shows it best:
| Phenomenon | Good chart type |
|---|---|
| Net Sentiment Score over time | Line chart with sentiment-coloured dots |
| Sentiment split | Donut or horizontal stacked bar |
| Source breadth / reach | Horizontal bar (events or hostnames by count) |
| ESG breakdown | Bar or grouped bar by controversy type |
| Score distribution | Histogram |
| Top events | Styled table (no chart needed) |
<style>, container width, header, lede, stat-row, data-note or tooltip unless the user explicitly asks — these are the consistency anchor.DATA — no hardcoded counts or scores.events / timeSeries — never from numbers copied out of the data.design-tokens.md; categorical series use the 12-colour palette in order.Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub polecat-dev/polecat-claude-plugins --plugin polecat-x