From prontonlp-plugin
Generates a full intelligence report for a single named company or ticker — covering earnings sentiment, investment score, stock performance, analyst and executive sentiment, trending topics, risk factors, and financial forecasts. Use when the user mentions one specific company name or ticker and asks about analysis, earnings, sentiment, financials, investment potential, stock performance, risks, or analyst opinions for that company. Triggers on phrases like: 'how is [company] doing', 'analyze [ticker]', '[company] earnings', 'should I buy [company]', 'what do analysts say about [company]', 'deep dive on [company]', '[company] sentiment', '[company] risks', '[ticker] outlook', 'give me a report on [company]'. Do not use when the user asks to compare two or more companies — use the compare-companies skill instead. Do not use for broad market overviews or sector-wide questions.
How this skill is triggered — by the user, by Claude, or both
Slash command
/prontonlp-plugin:pronto-company-intelligenceThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Produces a single-company intelligence report. Centerpiece: **quarter-over-quarter comparison of every earnings call in the past year**, explicitly showing whether sentiment, investment scores, and stock price reaction are RISING or FALLING. Layered on top: analyst forecasts, competitive benchmarks, trending topics, management quotes, and risk factors.
Produces a single-company intelligence report. Centerpiece: quarter-over-quarter comparison of every earnings call in the past year, explicitly showing whether sentiment, investment scores, and stock price reaction are RISING or FALLING. Layered on top: analyst forecasts, competitive benchmarks, trending topics, management quotes, and risk factors.
Data gathering and per-quarter analysis live here; final output is a regular standalone HTML report delegated to the pronto-html-renderer agent. This skill is not a live artifact.
⛔ TOOL RESTRICTION: Never call
showDocumentMindMapordeepResearch. These are user-triggered only.
| Mode | Use when | Tool calls | Sections included (payload keys) |
|---|---|---|---|
| Full Report (default) | Deep dive, no specific focus | ~40 | meta, kpi, quartersChart, stockChart, competitors, trends, speakers, quotes, predictions, risks |
| Quick Report | "quick", "overview", "brief" | ~13 | meta, kpi, stockChart, predictions |
| Sentiment Report | Earnings/sentiment focus | ~25 | meta, kpi, quartersChart, speakers, trends, quotes (bull/bear/forecast) |
| Competitive Report | Competitor/peer focus | ~15 | meta, kpi, stockChart, competitors |
| Risk Assessment | Downside focus | ~20 | meta, kpi, quartersChart, risks, quotes (bear/risk), speakers (analysts only) |
Default to Full Report unless the user signals a narrower scope. See reference/report-template-guide.md for per-mode batch plans.
After Step 0, before calling any tools, present a short summary and wait for the user to confirm.
Show the user:
Then ask: "Ready to generate the report. Reply yes to continue, or clarify anything above."
Do not call any tools until the user confirms.
| # | Tool | Purpose | Company param |
|---|---|---|---|
| 1 | getCompanies | Company profile — companyId, sector, description | companyNameOrTicker |
| 2 | getCompanyPeers | Competitor/peer list | companiesIds |
| 3 | getDocuments | Earnings calls, 10-K, 10-Q — transcriptIds | companiesIds |
| 4 | getStockPrices | Historical OHLC price series | companiesIds |
| 5 | getStockChange | Price % change over a period | companiesIds |
| 6 | getCompanyConsensus | Analyst consensus estimates — all metrics in one call | companiesIds |
| 7 | getDocumentSummary (focus: 'key risks') | Risk factors from latest earnings call | transcriptsIds |
| 8 | getAnalytics | Sentiment scores, events, aspects | companiesIds |
| 9 | getTrends | Trending topics | companiesIds |
| 10 | getSpeakers (entityType: 'speaker') | Per-executive/analyst individual sentiment | companiesIds |
| 11 | getSpeakers (entityType: 'company') | Analyst firm aggregate sentiment | companiesIds |
| 12 | searchSentences | Key quotes from filings (via search-summarizer) | — |
getCompanies(companyNameOrTicker: ...) → companyId → pass to getStockPrices, getStockChange, getCompanyConsensus, getCompanyPeersgetCompanyPeers(companiesIds: [companyId]) → peer companyIds → pass to getStockChange per competitorgetDocuments(companiesIds: [companyId], ...) → transcriptId per doc → pass to getAnalytics, getDocumentSummary, and searchSentences per quarterAlways use companiesIds arrays (not companyName) when a tool accepts them.
Batches run sequentially; within a batch, fire all calls simultaneously.
Batch 1 — foundation:
getCompanies(companyNameOrTicker: ...) → save companyId, sector, description
getCompanyPeers(companiesIds: [companyId]) → save peer companyIds[]
Batch 2 — data collection (needs companyId):
getDocuments(companiesIds: [companyId], documentTypes: ['Earnings Calls'], excludeFutureDocuments: true)
→ save transcriptId per earnings call
getStockPrices(companiesIds: [companyId], dateRange: {gte: 'now-1y/d', lte: 'now'}, interval: 'week')
getStockChange(companiesIds: [companyId]) ×3 (set dateRange per period: YTD / 6M / 1Y)
getCompanyConsensus(companiesIds: [companyId], metrics: ['revenue', 'epsGaap', 'ebitda', 'netIncomeGaap', 'freeCashFlow', 'capitalExpenditure'], timeframeInterval: 'quarter')
getTrends(companiesIds: [companyId], dateRange: {gte, lte})
Batch 3 — deep analysis (needs transcriptIds):
getAnalytics ×4 (one per earnings call, pass transcriptsIds: [transcriptId])
getStockPrices(companiesIds: [companyId]) ×4 (1 week window around each call date, interval: 'day')
getDocumentSummary(focus: 'key risks and risk factors mentioned by management', transcriptsIds: [doc_q1, doc_q2, doc_q3, doc_q4], corpus: ['S&P Transcripts'])
→ pass all available transcripts (max 5) for comprehensive multi-quarter risk view
getSpeakers(entityType: 'speaker', speakerTypes: ['Executives'], sortBy: 'count', companiesIds: [companyId])
getSpeakers(entityType: 'speaker', speakerTypes: ['Executives_CEO'], companiesIds: [companyId])
getSpeakers(entityType: 'speaker', speakerTypes: ['Executives_CFO'], companiesIds: [companyId])
getSpeakers(entityType: 'speaker', speakerTypes: ['Analysts'], sortBy: 'sentiment', sortOrder: 'desc', companiesIds: [companyId])
getSpeakers(entityType: 'company', speakerTypes: ['Analysts'], companiesIds: [companyId])
getStockChange(companiesIds: [peer1, peer2, peer3, ...], dateRange: {gte: 'now-1y/d', lte: 'now'})
→ ONE call with all peer IDs — not one call per peer
Batch 4 — quotes and forecasts (REQUIRED — do not render before this completes):
Delegate to ONE pronto-search-summarizer (subagent_type: prontonlp-plugin:pronto-search-summarizer):
Fetch all quotes needed for the [company] intelligence report. Run these searches:
1. Forecast/guidance quotes across all quarters — transcriptsIds: [doc_q1, doc_q2, doc_q3, doc_q4],
topicSearchQuery: 'forecast guidance outlook', DLSentiment: ['positive'], size: 8
→ ONE call spanning all quarters (not 4 separate calls)
2. Most bullish executive quotes — companiesIds: [companyId], speakerTypes: Executives,
DLSentiment: ['positive'], documentTypes: ["Earnings Calls"], size: 5
3. Top risk/bearish quotes — companiesIds: [companyId], topicSearchQuery: 'risk challenge headwind',
DLSentiment: ['negative'], documentTypes: ["Earnings Calls"], size: 5
4. Notable analyst questions — companiesIds: [companyId], sections: EarningsCalls_Question,
documentTypes: ["Earnings Calls"], size: 5
Return with speaker name, role, date. Citation link is already embedded in the text field.
Save the top 1–2 quotes per task, tagging each by section (bull, bear, forecast, risk).
Batch 5 — render (see Step 4 below).
This is the heart of the report. Run getAnalytics separately for each of the past year's earnings calls — the only way to produce RISING/FALLING comparisons.
For each earnings call:
getAnalytics:
companiesIds: ["<companyId>"]
transcriptsIds: ["<transcriptId>"]
documentTypes: ["Earnings Calls"]
dateRange: { gte: "<quarter start>", lte: "<quarter end>" }
analyticsType: ["scores", "eventTypes", "aspects", "patternSentiment", "importance"]
→ extract: sentimentScore, investmentScore, patternSentiment, top events, top aspects
getStockPrices (1 week window around call):
companiesIds: ["<companyId>"]
dateRange: { gte: "<7 days before call date>", lte: "<7 days after call date>" }
interval: "day"
→ compute: % change before vs after = stock reaction
Compute for each quarter: sentimentDirection, investmentDirection, stockReaction. Compare first vs last quarter for overall trajectory.
Always surface in the narrative:
Divergences are the most valuable insights. Flag them in the executive summary:
After Batch 3 completes, compute and include in the narrative:
> +0.10 = management may be over-optimistic; < -0.10 = street sees more upsideDelegate the HTML output to pronto-html-renderer (subagent_type: prontonlp-plugin:pronto-html-renderer). Do not render HTML here.
report_type: company
filename: <TICKER>-report-<YYYYMMDD>.html
title: "<Company Name> (<Ticker>) — Intelligence Report"
subtitle: "Generated: <date> · Sector: <sector> · Market Cap: <cap>"
data:
meta: { ticker, companyId, companyName, sector, subSector, asOfDate }
kpi: { investmentScore, investmentScoreChange, sentimentScore, sentimentScoreChange,
stockChangeYTD, stockChange6M, stockChange1Y }
quartersChart:
quarters: [ "Q1 2025", "Q2 2025", ... ]
sentimentScores: [ ... ]
investmentScores: [ ... ]
stockReactions: [ ... ]
positiveEvents: [ ... ]
negativeEvents: [ ... ]
quarterCards: [ { label, date, sentiment, sentimentArrow, investment, investmentArrow,
patternPos, patternNeg, revenue, badge, notes, isLatest } ]
stockChart: { dates: [...], prices: [...], earningsCallIndices: [...] }
competitors: [ { name, ticker, return1Y, isTarget } ] # sorted desc, target first
trends: [ { name, score, change, hits, explanation } ]
speakers:
executives: [ { name, role, sentiment, sentenceCount } ] # incl. CEO, CFO, execAvg rows
analysts: [ { name, firm, sentiment, sentenceCount } ]
gap: { execAvg, analystAvg, interpretation }
quotes: [ { text, speakerName, role, company, date, section } ] # section ∈ {bull, bear, forecast, risk}; text ends with "[Source](url)"
predictions: { revenue: [...], epsGaap: [...], ebitda: [...],
netIncomeGaap: [...], freeCashFlow: [...], capitalExpenditure: [...] }
risks: [ { title, evidence } ] # evidence contains "[Source](url)" if present
narrative:
executiveSummary: "<2–3 paragraphs that explicitly state all RISING/FALLING verdicts, the exec-vs-analyst gap, and the thesis>"
verdict: "<bullish / bearish / neutral + 3 supporting points>"
Report section order (renderer follows this sequence):
The renderer applies shared conventions (color rule, score display, company/citation links, chart palette, quarter-card styling, badge rules). For narrower report modes, omit payload keys that were not gathered — the renderer skips absent sections.
After the HTML renderer reports success, ask the user:
"Your report is ready:
<filename>.html. Want this also as an XLSX file? (yes/no)"
Skip the prompt if the user explicitly asked for XLSX up front (e.g. "give me the Tesla report as xlsx", "in spreadsheet form") — in that case generate both formats automatically.
If the user answers yes (or pre-asked), invoke anthropic-skills:xlsx directly from this skill (not via a sub-agent) using the same data you already built for the HTML renderer.
Filename: same as the HTML file but .xlsx extension.
Sheets to create (skip any whose source data is missing or empty):
#205262, no autofilter) — meta fields as Key / Value rows, then narrative.executiveSummary and narrative.verdict as wrapped text blocksstockChart dates × prices, followed by a separator and YTD / 6M / 1Y stock-change KPI rowspredictions flattened: one row per (Metric, Period, Estimate, Low, High, Actual) across all 6 metricsquarterCards entry: Quarter, Date, Sentiment, Investment, Revenue, Badge, NotesisTarget)#ED4545) — Risk, Evidence (with embedded Source link)Styling (every sheet):
#205262, white bold text, height 22pt, frozen so it stays visible when scrolling#6AA64A (green) · Negative → #ED4545 (red)0.00 · Change/% columns: 0.0% · Counts: whole numbersReport the saved filename to the user when complete.
If the user answers no, end the skill normally.
Past year: dateRange: { gte: "now-1y/d", lte: "now" }
Past quarter: dateRange: { gte: "now-90d/d", lte: "now" }
YTD: dateRange: { gte: "<YYYY>-01-01", lte: "now" }
Past 6 months: dateRange: { gte: "now-6M/d", lte: "now" }
Always pass dateRange with explicit gte and lte to every tool call that accepts it.
getAnalytics max range: 1 year — split longer requests into multiple yearly calls.
| Problem | What to do |
|---|---|
| Company not found | Try ticker instead of name (or vice versa); check spelling |
getCompanies returns no match | Ask user to verify; do not proceed without companyId |
| Fewer than 4 earnings calls | Work with available quarters; note the gap in the payload |
| No predictions for a metric | Omit from payload; renderer skips absent rows |
| Analytics returns empty | Verify date range ≤ 1 year; try without transcriptsIds filter |
| No competitors returned | Omit competitors from payload |
| No quotes returned | Omit quotes — never fabricate |
| Private/unlisted company | ProntoNLP covers public companies only — tell the user |
| companyId missing from response | Inspect the full object for id or nested field |
companyId the moment you get it from getCompanies.0.71, not 7.1 or 7.1/10 (renderer enforces).companiesIds: [companyId] (array) — never pass a bare companyId string to tools.npx claudepluginhub prontonlp/prontonlp-plugin --plugin prontonlp-pluginGuides creation, editing, and verification of skills for AI coding agents using test-driven development with subagent scenarios. Use when authoring or debugging skills.