{"owner":"virattt","repo":"dexter","hasSkills":true,"totalSkillsCount":7,"totalTokensCount":9831,"categories":["anthropic-skill","root-instruction"],"hasMcp":false,"mcpConfig":null,"found":["src/skills/write-memo/examples.md","src/skills/dcf/sector-wacc.md","src/skills/x-research/SKILL.md","AGENTS.md","src/skills/write-memo/memo-style.md","src/skills/dcf/SKILL.md","src/skills/write-memo/SKILL.md"],"skills":{"src/skills/write-memo/examples.md":"# Example Memo (for tone calibration)\n\nThis is a worked example for `NFLX LONG · 12mo`. Use it to pattern-match tone, density, and structure when drafting. **Do not copy the numbers** — fetch fresh data via the tools for any actual memo.\n\nThe example is shown as the content that would fill the template slots, not the final HTML.\n\n---\n\n**Header strip values**\n- Ticker: NFLX\n- Company: Netflix, Inc.\n- Direction: LONG\n- Conviction: HIGH\n- Horizon: 12mo\n- Current price: $620\n- Base target: $785\n- Upside: +27%\n- Asymmetry: 2.4x\n- Prob-weighted return: +18%\n\n---\n\n**`{{variant_view}}`**\n\nConsensus models ad-tier as a single-digit revenue line for the next three years. We think it is a 20%+ contributor to '27 revenue and the primary multiple-rerate catalyst. The Street is anchored to subscription-only unit economics and has not updated for ad-tier ARPU running 30% above their first-year assumption.\n\n---\n\n**`{{thesis_bullets}}`** (HTML list items)\n\n- **Ad-tier reaches 18% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; at current adds and a 65% mix of new signups going to the ad tier, we model 51M ad-tier subs by end-'27. *Wrong if ad-tier mix of new signups falls below 50% for two consecutive quarters.*\n- **Ad-tier ARPU sustains $9+** — current ad CPMs of $35-45 imply $9-11 ARPU at 5 ad-min/hr inventory; management called out upfront commitments doubling YoY. *Wrong if disclosed ad ARPU prints below $8 in any quarterly disclosure.*\n- **Operating margin expands 600bps to 28% by '27** — content amortization peaks in '25 per management; incremental ad revenue is 70%+ margin. *Wrong if content spend grows above $20B in any year.*\n- **Multiple rerates from 28x to 35x as ad revenue mix exceeds 15%** — comparable transition (Spotify ad-tier, Roku) saw 25-40% multiple expansion when ad revenue crossed 15% of total. *Wrong if ad revenue stalls below 12% of total through '27.*\n\n---\n\n**`{{business_snapshot}}`**\n\nNetflix is a global subscription video streaming service with 270M paid memberships across 190+ countries. The company licenses and produces original content; \"we have one of the largest libraries of TV series and films, with content available in over 30 languages\" (10-K Item 1). Two membership tiers contribute differently: standard and premium subscriptions (~$15-23/mo) drive 92% of revenue today; the ad-supported tier (~$7/mo plus advertising) launched late '22 and is now the company's stated highest-growth tier. Unit economics differ: ad-tier subs carry lower subscription ARPU but ad revenue at ~70% incremental margin lifts blended contribution above the standard tier by year two of a sub's life.\n\n---\n\n**`{{whats_priced_in}}`**\n\nAt $620, NFLX trades at 28x consensus '26 EPS of $22.10. Consensus models 11% revenue growth and 23% operating margin in '27 — implying the Street is pricing in the subscription business compounding low-teens with modest margin expansion. Sellside ad-tier revenue estimates cluster around $4-5B for '27 (consensus mean $4.6B). Our '27 model puts ad revenue at $8.2B (+78% vs. consensus) on higher ad-tier sub adds and sustained ARPU. EPS divergence: our $29.50 vs. consensus $24.80, a +19% delta.\n\n---\n\n**`{{scenario_table}}`**\n\n| | Bear (20%) | Base (55%) | Bull (25%) |\n|---|---|---|---|\n| Revenue '27 | $42B | $52B | $61B |\n| Revenue growth | +6% | +14% | +20% |\n| EBIT margin | 22% | 28% | 32% |\n| EPS '27 | $19.50 | $29.50 | $38.20 |\n| Exit multiple | 22x | 28x | 35x |\n| Price target | $430 | $785 | $1,205 |\n| Return | -31% | +27% | +94% |\n\nProb-weighted return: +18% · Upside / downside: 2.4x\n\n---\n\n**`{{bull_narrative}}`**\n\nAd-tier inflects faster than we model. Disney+ pulls back on ad-tier pricing competition, leaving NFLX as the premium ad-supported inventory option for upfront buyers. Live programming (NFL, boxing, WWE) drives ad-tier mix of new signups above 70%, and ad CPMs sustain in the $40s as inventory stays scarce relative to demand. Content cost discipline holds — total content spend stays flat at $17B even as subs grow — and operating margin reaches 32% by '27. The Street rerates the stock to 35x as ad revenue crosses 20% of total, reclassifying NFLX from subscription business to dual-revenue media platform. EPS compounds 25%+ for three years.\n\n---\n\n**`{{base_narrative}}`**\n\nAd-tier grows roughly in line with current trajectory and reaches 50M+ subs by '27. ARPU holds at $9-10 as content investment in live and originals supports pricing. Content amortization peaks in '25 and rolls off, lifting operating margin to 28% by '27 even with $18-19B of content spend. Subscription business compounds high single digits globally with the bulk of net adds from APAC and LatAm at lower ARPU. The Street partially rerates the stock as ad mix exceeds 15%, multiple expands to 28x — in line with current level but on materially higher EPS.\n\n---\n\n**`{{bear_narrative}}`**\n\nDisney+ and Amazon's Prime Video ad tier compete aggressively on price; Disney+ ad-tier subs cross 100M globally by end-'26 and Amazon bundles ad-supported streaming into Prime at no incremental cost. Ad-tier CPMs compress 25% to the high $20s as inventory floods the market and brand advertisers consolidate spend on retail media platforms (Amazon, Walmart Connect) rather than streaming. NFLX ad revenue stalls at $3-3.5B for '27 vs. street $4.6B. Content spend creeps to $20B as the live programming push (NFL, boxing) proves more expensive to renew than initial deals suggested. Operating margin compresses to 22% as fixed content costs deleverage on slower revenue growth. The multiple compresses to 22x — Disney's current multiple — as the market reclassifies NFLX as a mature subscription business with declining incremental returns on content spend. Stock retraces to the low $400s.\n\n---\n\n**`{{catalysts_table}}`**\n\n| Event | Date | Expected Impact |\n|---|---|---|\n| Q2 '26 earnings — ad-tier sub disclosure | Jul '26 | Ad-tier sub count vs. our 45M target |\n| Upfront ad commitments | Apr-May '26 | Total committed dollars; vs. $1B+ '25 baseline |\n| NFL Christmas Day games viewership | Dec '26 | Concurrent viewers; ad-load testing |\n| FY27 guidance | Jan '27 | First explicit ad revenue guide |\n\n---\n\n**`{{risks_table}}`**\n\n| Risk | Mitigant | Tripwire |\n|---|---|---|\n| Ad-tier ARPU compression | Premium inventory (live sports) supports CPMs | Disclosed ad ARPU < $8 in any quarter |\n| Content cost re-acceleration | Management explicit guide of $17B '26 cap | Content spend > $19B in any year |\n| Competitive ad-tier launch from Amazon | Amazon ad-tier already live; share gains modest | NFLX ad-tier net adds < 5M in any quarter |\n| Subscription growth stalls in APAC | Pricing flexibility, mobile-only tier | Net adds < 4M globally in two consecutive quarters |\n| Multiple compression on rate environment | EPS growth outpaces multiple compression risk | Multiple < 24x with no operational miss |\n\n---\n\n**`{{position_management}}`**\n\nSuggested sizing: 4% NAV — high conviction × 2.4x asymmetry. Entry: current ($620) or scale-in below $590 on multiple compression. Stop / reduce: trim 50% if ad-tier ARPU prints below $8 in any quarter; full exit if content spend guide steps above $19B.\n\n---\n\n**`{{monitoring_kpis}}`**\n\n1. Ad-tier subscriber count (quarterly disclosure)\n2. Ad-tier ARPU or implied ARPU (calc: ad revenue / avg ad-tier subs)\n3. Content cash spend YTD vs. annual guide\n4. Operating margin (quarterly) — trajectory to 28% by '27\n5. Upfront commitment dollars (annual) — vs. prior year\n\n---\n\n## Why this example works\n\n- **Variant view is specific and contradictable.** It names a number (20%+ revenue contribution by '27) and a divergence (Street models single-digit). A PM can disagree with it precisely.\n- **Every thesis bullet has a \"wrong if\".** None of them are unfalsifiable platitudes.\n- **Bear case names competitors and mechanisms.** Disney+, Amazon, retail media, NFL renewal costs. Not \"competition intensifies\".\n- **Tripwires are observable.** \"Disclosed ad ARPU < $8 in any quarter\" is a data point the analyst can monitor; \"macro deteriorates\" is not.\n- **No padding.** No founding history, no \"in an ever-evolving streaming landscape\", no closing summary paragraph.\n\nWhen you draft a real memo, match this density and specificity, not the surface aesthetics. The aesthetics come from the template; the substance comes from the thinking.\n","src/skills/dcf/sector-wacc.md":"# Sector WACC Adjustments\n\nUse these typical WACC ranges as starting points, then adjust based on company-specific factors.\n\n## Determining Company Sector\n\nUse `get_financials` with query `\"[TICKER] company facts\"` to retrieve the company's `sector`. Match the returned sector to the table below.\n\n## WACC by Sector\n\n| Sector | Typical WACC Range | Notes |\n|--------|-------------------|-------|\n| Communication Services | 8-10% | Mix of stable telecom and growth media |\n| Consumer Discretionary | 8-10% | Cyclical exposure |\n| Consumer Staples | 7-8% | Defensive, stable demand |\n| Energy | 9-11% | Commodity price exposure |\n| Financials | 8-10% | Leverage already in business model |\n| Health Care | 8-10% | Regulatory and pipeline risk |\n| Industrials | 8-9% | Moderate cyclicality |\n| Information Technology | 8-12% | Assess growth stage; higher for high-growth |\n| Materials | 8-10% | Cyclical, commodity exposure |\n| Real Estate | 7-9% | Interest rate sensitivity |\n| Utilities | 6-7% | Regulated, stable cash flows |\n\n## Adjustment Factors\n\nAdd to base WACC:\n- **High debt (D/E > 1.5)**: +1-2%\n- **Small cap (< $2B market cap)**: +1-2%\n- **Emerging markets exposure**: +1-3%\n- **Concentrated customer base**: +0.5-1%\n- **Regulatory uncertainty**: +0.5-1.5%\n\nSubtract from base WACC:\n- **Market leader with moat**: -0.5-1%\n- **Recurring revenue model**: -0.5-1%\n- **Investment grade credit rating**: -0.5%\n\n## Reasonableness Checks\n\n- WACC should typically be 2-4% below ROIC for value-creating companies\n- If calculated WACC > ROIC, the company may be destroying value\n- Compare to sector peers if available\n","src/skills/x-research/SKILL.md":"---\nname: x-research\ndescription: >\n  X/Twitter public sentiment research. Searches X for real-time perspectives,\n  market sentiment, expert opinions, breaking news, and community discourse.\n  Use when: user asks \"what are people saying about\", \"X/Twitter sentiment\",\n  \"check X for\", \"search twitter for\", \"what's CT saying about\", or wants\n  public opinion on a stock, sector, company, or market event.\n---\n\n# X Research Skill\n\nAgentic research over X/Twitter using the `x_search` tool. Decompose the\nresearch question into targeted searches, iterate to refine signal, and\nsynthesize into a sourced sentiment briefing.\n\n## Research Loop\n\n### 1. Decompose into Queries\n\nTurn the research question into 3–5 targeted queries using X operators:\n\n- **Core query**: Direct keywords or `$TICKER` cashtag\n- **Expert voices**: `from:username` for known analysts or accounts\n- **Bearish signal**: keywords like `(overvalued OR bubble OR risk OR concern)`\n- **Bullish signal**: keywords like `(bullish OR upside OR catalyst OR beat)`\n- **News/links**: add `has:links` to surface tweets with sources\n- **Noise reduction**: `-is:reply` to focus on original posts; `-airdrop -giveaway` for crypto topics\n\n### 2. Execute Searches\n\nUse the `x_search` tool with `command: \"search\"`. For each query:\n\n- Start with `sort: \"likes\"` and `limit: 15` to surface highest-signal tweets\n- Add `min_likes: 5` or higher to filter noise for broad topics\n- Use `since: \"1d\"` or `\"7d\"` depending on how time-sensitive the topic is\n- If a query returns too much noise, narrow with more operators or raise `min_likes`\n- If too few results, broaden with `OR` terms or remove restrictive operators\n\n### 3. Check Key Accounts (Optional)\n\nFor well-known analysts, fund managers, or company executives, use\n`command: \"profile\"` to see their recent posts directly.\n\n### 4. Follow Threads (Optional)\n\nWhen a high-engagement tweet appears to be a thread starter, use\n`command: \"thread\"` with the tweet ID to get full context.\n\n### 5. Synthesize\n\nGroup findings by theme (bullish, bearish, neutral, news/catalysts):\n\n```\n### [Theme]\n\n[1–2 sentence summary of the theme]\n\n- @username: \"[key quote]\" — [likes]♥ [Tweet](url)\n- @username2: \"[another perspective]\" — [likes]♥ [Tweet](url)\n```\n\nEnd with an **Overall Sentiment** paragraph: predominant tone (bullish/bearish/\nmixed/neutral), confidence level, and any notable divergence between retail and\ninstitutional voices.\n\n## Refinement Heuristics\n\n| Problem | Fix |\n|---|---|\n| Too much noise | Raise `min_likes`, add `-is:reply`, narrow keywords |\n| Too few results | Broaden with `OR`, remove restrictive operators |\n| Crypto spam | Add `-airdrop -giveaway -whitelist` |\n| Want expert takes only | Use `from:` or `min_likes: 50` |\n| Want substance over hot takes | Add `has:links` |\n\n## Output Format\n\nPresent a structured briefing:\n\n1. **Query Summary**: what was searched and time window\n2. **Sentiment Themes**: grouped findings with sourced quotes and tweet links\n3. **Overall Sentiment**: tone, confidence, key voices\n4. **Caveats**: X sentiment is not a reliable predictor; sample bias toward vocal minorities; last-7-days window only\n","AGENTS.md":"# Repository Guidelines\n\n- Repo: https://github.com/virattt/dexter\n- Dexter is a CLI-based AI agent for deep financial research, built with TypeScript, Ink (React for CLI), and LangChain.\n\n## Project Structure\n\n- Source code: `src/`\n  - Agent core: `src/agent/` (agent loop, prompts, scratchpad, token counting, types)\n  - CLI interface: `src/cli.tsx` (Ink/React), entry point: `src/index.tsx`\n  - Components: `src/components/` (Ink UI components)\n  - Hooks: `src/hooks/` (React hooks for agent runner, model selection, input history)\n  - Model/LLM: `src/model/llm.ts` (multi-provider LLM abstraction)\n  - Tools: `src/tools/` (financial search, web search, browser, skill tool)\n  - Tool descriptions: `src/tools/descriptions/` (rich descriptions injected into system prompt)\n  - Finance tools: `src/tools/finance/` (prices, fundamentals, filings, insider trades, etc.)\n  - Search tools: `src/tools/search/` (Exa preferred, Tavily fallback)\n  - Browser: `src/tools/browser/` (Playwright-based web scraping)\n  - Skills: `src/skills/` (SKILL.md-based extensible workflows, e.g. DCF valuation)\n  - Utils: `src/utils/` (env, config, caching, token estimation, markdown tables)\n  - Evals: `src/evals/` (LangSmith evaluation runner with Ink UI)\n- Config: `.dexter/settings.json` (persisted model/provider selection)\n- Environment: `.env` (API keys; see `env.example`)\n- Scripts: `scripts/release.sh`\n\n## Build, Test, and Development Commands\n\n- Runtime: Bun (primary). Use `bun` for all commands.\n- Install deps: `bun install`\n- Run: `bun run start` or `bun run src/index.tsx`\n- Dev (watch mode): `bun run dev`\n- Type-check: `bun run typecheck`\n- Tests: `bun test`\n- Evals: `bun run src/evals/run.ts` (full) or `bun run src/evals/run.ts --sample 10` (sampled)\n- CI runs `bun run typecheck` and `bun test` on push/PR.\n\n## Coding Style & Conventions\n\n- Language: TypeScript (ESM, strict mode). JSX via React (Ink for CLI rendering).\n- Prefer strict typing; avoid `any`.\n- Keep files concise; extract helpers rather than duplicating code.\n- Add brief comments for tricky or non-obvious logic.\n- Do not add logging unless explicitly asked.\n- Do not create README or documentation files unless explicitly asked.\n\n## LLM Providers\n\n- Supported: OpenAI (default), Anthropic, Google, xAI (Grok), OpenRouter, Ollama (local).\n- Default model: `gpt-5.5`. Provider detection is prefix-based (`claude-` -> Anthropic, `gemini-` -> Google, etc.).\n- Fast models for lightweight tasks: see `FAST_MODELS` map in `src/model/llm.ts`.\n- Anthropic uses explicit `cache_control` on system prompt for prompt caching cost savings.\n- Users switch providers/models via `/model` command in the CLI.\n\n## Tools\n\n- `financial_search`: primary tool for all financial data queries (prices, metrics, filings). Delegates to multiple sub-tools internally.\n- `financial_metrics`: direct metric lookups (revenue, market cap, etc.).\n- `read_filings`: SEC filing reader for 10-K, 10-Q, 8-K documents.\n- `web_search`: general web search (Exa if `EXASEARCH_API_KEY` set, else Tavily if `TAVILY_API_KEY` set).\n- `browser`: Playwright-based web scraping for reading pages the agent discovers.\n- `skill`: invokes SKILL.md-defined workflows (e.g. DCF valuation). Each skill runs at most once per query.\n- Tool registry: `src/tools/registry.ts`. Tools are conditionally included based on env vars.\n\n## Skills\n\n- Skills live as `SKILL.md` files with YAML frontmatter (`name`, `description`) and markdown body (instructions).\n- Built-in skills: `src/skills/dcf/SKILL.md`.\n- Discovery: `src/skills/registry.ts` scans for SKILL.md files at startup.\n- Skills are exposed to the LLM as metadata in the system prompt; the LLM invokes them via the `skill` tool.\n\n## Agent Architecture\n\n- Agent loop: `src/agent/agent.ts`. Iterative tool-calling loop with configurable max iterations (default 10).\n- Scratchpad: `src/agent/scratchpad.ts`. Single source of truth for all tool results within a query.\n- Context management: Anthropic-style. Full tool results kept in context; oldest results cleared when token threshold exceeded.\n- Final answer: generated in a separate LLM call with full scratchpad context (no tools bound).\n- Events: agent yields typed events (`tool_start`, `tool_end`, `thinking`, `answer_start`, `done`, etc.) for real-time UI updates.\n\n## Environment Variables\n\n- LLM keys: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY`, `XAI_API_KEY`, `OPENROUTER_API_KEY`\n- Ollama: `OLLAMA_BASE_URL` (default `http://127.0.0.1:11434`)\n- Finance: `FINANCIAL_DATASETS_API_KEY`\n- Search: `EXASEARCH_API_KEY` (preferred), `TAVILY_API_KEY` (fallback)\n- Tracing: `LANGSMITH_API_KEY`, `LANGSMITH_ENDPOINT`, `LANGSMITH_PROJECT`, `LANGSMITH_TRACING`\n- Never commit `.env` files or real API keys.\n\n## Version & Release\n\n- Version format: SemVer `MAJOR.MINOR.PATCH`. Tag prefix: `v`.\n- Release script: `bash scripts/release.sh [version]` (defaults to today's date).\n- Release flow: bump version in `package.json`, create git tag, push tag, create GitHub release via `gh`.\n- Do not push or publish without user confirmation.\n\n## Testing\n\n- Framework: Bun's built-in test runner (primary), Jest config exists for legacy compatibility.\n- Tests colocated as `*.test.ts`.\n- Run `bun test` before pushing when you touch logic.\n\n## Security\n\n- API keys stored in `.env` (gitignored). Users can also enter keys interactively via the CLI.\n- Config stored in `.dexter/settings.json` (gitignored).\n- Never commit or expose real API keys, tokens, or credentials.\n","src/skills/write-memo/memo-style.md":"# Investment Memo Style Guide\n\nRules the memo must follow. These mirror buyside writing conventions and avoid the tells that mark a document as AI-generated.\n\n## Voice\n\n- **First person plural** (\"we believe\", \"our base case\") — that's how a buyside team writes.\n- **Direct, not hedging.** \"Margins compress 200bps in '27\" beats \"margins could potentially face some pressure in 2027\".\n- **Confidence calibrated by evidence.** State the view, then state the evidence. Hedge once with a \"wrong if\" — not in every sentence.\n- **One sentence per idea** in narrative sections. Long sentences with comma chains and parentheticals signal AI drift.\n\n## Banned vocabulary\n\nNever use these words. They are AI-generated tells:\n\n- \"delve\", \"delves\", \"delving\"\n- \"leverage\" as a verb (\"we leverage X to do Y\")\n- \"robust\", \"comprehensive\", \"holistic\", \"seamless\"\n- \"navigate the landscape\", \"navigate the challenges\"\n- \"in today's fast-paced\", \"in an ever-evolving\"\n- \"stands out\", \"sets itself apart\"\n- \"deep dive\", \"unpack\", \"double-click\"\n- \"moreover\", \"furthermore\", \"additionally\" (use a new sentence)\n- \"It's worth noting that\" (just say the thing)\n\n## Banned constructions\n\n- **Tricolons** — three-item lists for rhythmic effect (\"fast, scalable, and reliable\"). One AI tell.\n- **Em dash abuse** — at most one em dash per paragraph. Prefer periods or commas.\n- **\"Not just X but Y\"** — overused contrast structure.\n- **Generic closing summaries** — \"In conclusion, this is a compelling opportunity that...\" Don't write these. End on a specific claim or a tripwire.\n- **Hedge stacking** — \"could potentially possibly maybe\". Pick one or zero.\n\n## Numbers\n\n- **Quantify everything.** \"Margins expanded 380bps\" not \"margins improved meaningfully\".\n- **Percentages with explicit base.** \"Revenue grew 28% YoY\" not \"revenue saw strong growth\".\n- **Multiples in line.** \"Trading at 18x FY26 EPS\" not \"trading at attractive multiples\".\n- **Don't invent numbers.** If you don't have it from a tool call, write \"not disclosed\" or omit the line. Never fabricate consensus figures.\n\n## Thesis bullet format\n\nEvery thesis bullet must be a complete falsifiable claim:\n\n> **[Specific claim with a number]** — [Evidence with a specific number, ideally citing the data point]. *Wrong if [specific observable would happen].*\n\nGood:\n> **Ad-tier reaches 15% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; trajectory implies 15% mix at constant adds. *Wrong if ad-tier ARPU compresses below $8 due to inventory glut.*\n\nBad (vague claim, no falsifier):\n> **Strong product-market fit in ad tier** — Management has emphasized this is a key growth area going forward.\n\n## Bear case requirements\n\nThe bear paragraph is the highest-stakes paragraph in the memo. Rules:\n\n1. **Steelmanned.** Written as if you actually believed it. If you can't, you don't understand the trade.\n2. **Specific competitor / customer / regulator named.** Not \"competition intensifies\" — name the company and the product.\n3. **Coherent world, not a list.** The bear case is a story where the thesis is wrong. Connect the dots.\n4. **Read the bull paragraph and the bear paragraph back to back.** If bear reads weaker, rewrite. This is the single most common failure mode.\n\n## Tripwires\n\nEvery risk row in the risks table must have a tripwire. A tripwire is **an observable data point that would invalidate the thesis** within the holding period.\n\nGood tripwires:\n- \"Q3 ad-tier ARPU prints below $8\"\n- \"Top customer announces in-sourcing on Q2 call\"\n- \"Gross margin contracts more than 150bps in any quarter\"\n- \"Insider sales exceed $50M in any rolling 90-day window\"\n\nBad tripwires (not observable / not actionable):\n- \"Macro deteriorates\"\n- \"Competition increases\"\n- \"Sentiment shifts negatively\"\n\n## What to pull from filings\n\nWhen summarizing the business, pull verbatim from the 10-K Item 1 where the company's own language is tighter than rewriting it. Quote with quotes and source: `\"[exact phrase]\" (10-K Item 1)`.\n\nFor risks, prefer pulling from Item 1A and the company's own disclosure language — it's the most defensible risk framing in the memo.\n\n## Closing the memo\n\nMemos do not need a \"conclusion\" section. The header already states the recommendation; the thesis bullets state the view; the scenarios state the math. A closing paragraph that restates these is padding.\n\nThe last section in the body is **Monitoring KPIs** — the specific metrics that confirm or kill the thesis. That's the right note to end on: what to watch.\n","src/skills/dcf/SKILL.md":"---\nname: dcf-valuation\ndescription: Performs discounted cash flow (DCF) valuation analysis to estimate intrinsic value per share. Triggers when user asks for fair value, intrinsic value, DCF, valuation, \"what is X worth\", price target, undervalued/overvalued analysis, or wants to compare current price to fundamental value.\n---\n\n# DCF Valuation Skill\n\n## Workflow Checklist\n\nCopy and track progress:\n```\nDCF Analysis Progress:\n- [ ] Step 1: Gather financial data\n- [ ] Step 2: Calculate FCF growth rate\n- [ ] Step 3: Estimate discount rate (WACC)\n- [ ] Step 4: Project future cash flows (Years 1-5 + Terminal)\n- [ ] Step 5: Calculate present value and fair value per share\n- [ ] Step 6: Run sensitivity analysis\n- [ ] Step 7: Validate results\n- [ ] Step 8: Present results with caveats\n```\n\n## Step 1: Gather Financial Data\n\nCall the `get_financials` tool with these queries:\n\n### 1.1 Cash Flow History\n**Query:** `\"[TICKER] annual cash flow statements for the last 5 years\"`\n\n**Extract:** `free_cash_flow`, `net_cash_flow_from_operations`, `capital_expenditure`\n\n**Fallback:** If `free_cash_flow` missing, calculate: `net_cash_flow_from_operations - capital_expenditure`\n\n### 1.2 Financial Metrics\n**Query:** `\"[TICKER] financial metrics snapshot\"`\n\n**Extract:** `market_cap`, `enterprise_value`, `free_cash_flow_growth`, `revenue_growth`, `return_on_invested_capital`, `debt_to_equity`, `free_cash_flow_per_share`\n\n### 1.3 Balance Sheet\n**Query:** `\"[TICKER] latest balance sheet\"`\n\n**Extract:** `total_debt`, `cash_and_equivalents`, `current_investments`, `outstanding_shares`\n\n**Fallback:** If `current_investments` missing, use 0\n\n### 1.4 Current Price\nCall the `get_market_data` tool:\n\n**Query:** `\"[TICKER] price snapshot\"`\n\n**Extract:** `price`\n\n### 1.5 Company Facts\nCall the `get_financials` tool:\n\n**Query:** `\"[TICKER] company facts\"`\n\n**Extract:** `sector`, `industry`, `market_cap`\n\n**Use:** Determine appropriate WACC range from [sector-wacc.md](sector-wacc.md)\n\n## Step 2: Calculate FCF Growth Rate\n\nCalculate 5-year FCF CAGR from cash flow history.\n\n**Cross-validate with:** `free_cash_flow_growth` (YoY), `revenue_growth`\n\n**Growth rate selection:**\n- Stable FCF history → Use CAGR with 10-20% haircut\n- **Cap at 15%** (sustained higher growth is rare)\n\n## Step 3: Estimate Discount Rate (WACC)\n\n**Use the `sector` from company facts** to select the appropriate base WACC range from [sector-wacc.md](sector-wacc.md).\n\n**Default assumptions:**\n- Risk-free rate: 4%\n- Equity risk premium: 5-6%\n- Cost of debt: 5-6% pre-tax (~4% after-tax at 30% tax rate)\n\nCalculate WACC using `debt_to_equity` for capital structure weights.\n\n**Reasonableness check:** WACC should be 2-4% below `return_on_invested_capital` for value-creating companies.\n\n**Sector adjustments:** Apply adjustment factors from [sector-wacc.md](sector-wacc.md) based on company-specific characteristics.\n\n## Step 4: Project Future Cash Flows\n\n**Years 1-5:** Apply growth rate with 5% annual decay (multiply growth rate by 0.95, 0.90, 0.85, 0.80 for years 2-5). This reflects competitive dynamics.\n\n**Terminal value:** Use Gordon Growth Model with 2.5% terminal growth (GDP proxy).\n\n## Step 5: Calculate Present Value\n\nDiscount all FCFs → sum for Enterprise Value → subtract Net Debt → divide by `outstanding_shares` for fair value per share.\n\n## Step 6: Sensitivity Analysis\n\nCreate 3×3 matrix: WACC (base ±1%) vs terminal growth (2.0%, 2.5%, 3.0%).\n\n## Step 7: Validate Results\n\nBefore presenting, verify these sanity checks:\n\n1. **EV comparison**: Calculated EV should be within 30% of reported `enterprise_value`\n   - If off by >30%, revisit WACC or growth assumptions\n\n2. **Terminal value ratio**: Terminal value should be 50-80% of total EV for mature companies\n   - If >90%, growth rate may be too high\n   - If <40%, near-term projections may be aggressive\n\n3. **Per-share cross-check**: Compare to `free_cash_flow_per_share × 15-25` as rough sanity check\n\nIf validation fails, reconsider assumptions before presenting results.\n\n## Step 8: Output Format\n\nPresent a structured summary including:\n1. **Valuation Summary**: Current price vs. fair value, upside/downside percentage\n2. **Key Inputs Table**: All assumptions with their sources\n3. **Projected FCF Table**: 5-year projections with present values\n4. **Sensitivity Matrix**: 3×3 grid varying WACC (±1%) and terminal growth (2.0%, 2.5%, 3.0%)\n5. **Caveats**: Standard DCF limitations plus company-specific risks\n","src/skills/write-memo/SKILL.md":"---\nname: write-memo\ndescription: Drafts a professional investment memo (HTML output) for a long or short equity idea, structured the way a hedge fund analyst would present a thesis to a PM. Triggers when the user asks to \"write a memo\", \"draft an investment memo\", \"write up a thesis\", \"pitch this stock\", \"memo on [ticker]\", \"long writeup\", \"short writeup\", or similar. Produces a 1-page HTML file at .dexter/memos/.\n---\n\n# Write Investment Memo Skill\n\nProduces a buyside-quality investment memo as a self-contained HTML file. The memo is opinionated and falsifiable — it leads with a variant view and steelmans the bear case. The output is the deliverable; the chat response is just a header summary plus the file path.\n\n## Workflow Checklist\n\nCopy and track progress:\n```\nInvestment Memo Progress:\n- [ ] Step 1: Frame the trade (direction, horizon, variant view)\n- [ ] Step 2: Gather data (financials, market, filings)\n- [ ] Step 3: Build Bear / Base / Bull scenarios\n- [ ] Step 4: Optional DCF anchor for base case\n- [ ] Step 5: Draft memo content (fill all slots)\n- [ ] Step 6: Self-critique pass\n- [ ] Step 7: Render HTML to .dexter/memos/\n- [ ] Step 8: Report header summary + file path\n```\n\n## Step 1: Frame the Trade\n\nConfirm or ask for the following before drafting:\n\n- **Ticker** (required)\n- **Direction**: long or short (required)\n- **Horizon**: 3mo / 6mo / 12mo / 2yr+ (default 12mo if not specified)\n- **Conviction**: high / medium / low (default medium)\n- **Variant view**: one sentence — what the analyst sees that consensus doesn't\n\n**If the user does not provide a variant view**: do not ask repeatedly. Gather data in Step 2 first, then derive a candidate variant view from where your model meaningfully diverges from consensus (e.g., \"our '27 EPS is $X vs consensus $Y because [driver]\"). Present it as a draft and let the analyst accept, refine, or replace before you proceed to Step 5.\n\n## Step 2: Gather Data (Parallel)\n\nIssue these tool calls in parallel:\n\n### 2.1 Financials\nCall `get_financials`:\n- `\"[TICKER] annual income statements last 5 years\"` — revenue, operating income, net income, EPS, margins\n- `\"[TICKER] annual cash flow statements last 5 years\"` — operating CF, capex, FCF\n- `\"[TICKER] latest balance sheet\"` — debt, cash, shares outstanding\n- `\"[TICKER] financial metrics snapshot\"` — P/E, EV, ROIC, FCF growth, debt/equity, margins\n- `\"[TICKER] segmented financials\"` — segment revenue, segment margins (if multi-segment)\n- `\"[TICKER] earnings history last 8 quarters\"` — beats/misses, surprises\n- `\"[TICKER] company facts\"` — sector, industry, market cap\n- `\"[TICKER] KPI guidance\"` and `\"[TICKER] KPI metrics\"` — management-provided KPIs and guidance\n\n### 2.2 Market & Ownership\nCall `get_market_data`:\n- `\"[TICKER] price snapshot\"` — current price, 52-week range, market cap\n- `\"[TICKER] historical prices last 12 months\"` — for return / multiple compression context\n- `\"[TICKER] insider trades last 6 months\"` — recent buys/sells, dollar amounts\n- `\"[TICKER] institutional holdings\"` — top holders, recent additions / reductions\n- `\"[TICKER] news last 30 days\"` — recent material events\n\n### 2.3 Filings\nCall `read_filings`:\n- Most recent 10-K Item 1 (Business) — for business snapshot language\n- Most recent 10-K Item 1A (Risk Factors) — to source risks from the company itself\n- Most recent 10-Q — recent quarterly trajectory\n\n### 2.4 Memory (optional)\nCall `memory_search` with the ticker — surfaces any prior notes, prior memos, or user-provided constraints (e.g., risk tolerance, sector exposure already in book).\n\n### 2.5 Sentiment (optional, only if time-sensitive)\nCall `x_search` for recent material chatter on the ticker. Skip if the thesis is fundamental and not catalyst-driven this week.\n\n## Step 3: Build Scenarios\n\nConstruct Bear / Base / Bull scenarios. Each scenario is **driver-based**, not a single number pulled from the air.\n\nFor each scenario specify:\n- **Revenue growth** (forecast year, 2-3 years out)\n- **EBIT / operating margin** at that point\n- **Exit multiple** (P/E, EV/EBITDA, or EV/Sales as appropriate for the sector)\n- **Probability weight** (the three must sum to 100%)\n- **Price target** (derived from the above)\n- **Return** vs. current price (with sign)\n\nThen compute:\n- **Probability-weighted return** = sum(prob × return) across scenarios\n- **Upside / downside ratio** = |bull return| / |bear return|\n\n**Asymmetry check**: if upside/downside < 2x, flag this prominently. A weak-asymmetry setup is a coin flip, not a trade. Either revise the scenarios honestly, or note the weak asymmetry in the memo (do not hide it).\n\n## Step 4: Optional DCF Anchor\n\nFor base case, optionally invoke the `dcf-valuation` skill via the `skill` tool to produce an intrinsic value anchor. Use it as a cross-check against your base-case price target, not as a replacement.\n\n## Step 5: Draft Memo Content\n\nRead the template and style guide:\n- [memo-template.html](memo-template.html)\n- [memo-style.md](memo-style.md)\n- [examples.md](examples.md) — pattern-match tone and density\n\nFill every slot. Slots are listed in the template — do not skip any. Slot-specific guidance:\n\n### `{{variant_view}}`\nThree sentences max. Lead with the divergence from consensus: *what we see, why we think it, why the market hasn't priced it*. If the user did not provide one, this is where your derived candidate goes.\n\n### `{{thesis_bullets}}`\n3-5 bullets, each in this format:\n> **[Claim]** — [Evidence with a specific number]. *Wrong if [observable falsifier].*\n\nExample:\n> **Ad-tier reaches 15% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; trajectory implies 15% mix at constant adds. *Wrong if ad-tier ARPU compresses below $8 due to inventory glut.*\n\nEach bullet must be **falsifiable**. No \"great management\", \"strong moat\", \"wide TAM\" without a specific operational metric behind it.\n\n### `{{business_snapshot}}`\n4-5 lines max. What they sell, how they make money, segment mix, unit economics that matter for the thesis. **No founding-year boilerplate.** Pull verbatim from the 10-K Item 1 where it tightens the language.\n\n### `{{whats_priced_in}}`\nCurrent multiple, implied growth or margin assumption embedded in that multiple, sellside consensus numbers (revenue, EPS for FY+1 and FY+2). Then one sentence on where your model diverges and by how much.\n\n### `{{scenario_table}}`\nRender as an HTML table. Columns: Bear / Base / Bull. Rows: Probability, Revenue growth (FY27), EBIT margin (FY27), Exit multiple, Price target, Return. Color returns: positive `class=\"pos\"`, negative `class=\"neg\"`.\n\n### `{{bull_narrative}}`, `{{base_narrative}}`, `{{bear_narrative}}`\nOne paragraph each (3-5 sentences). Each is a *coherent world*, not a list of factors:\n- **Bull**: what has to be true. Specific operational wins that compound. Tied to evidence we'd see in quarterly data.\n- **Base**: the thesis playing out as written.\n- **Bear**: steelmanned — written as if you believed it. Specific competitive losses, customer concentration risk materializing, multiple compression to a lower peer group. **If the bear paragraph reads weaker than the bull paragraph, rewrite it.**\n\n### `{{catalysts_table}}`\nTable with columns: Event, Date / Quarter, Expected Impact. 3-5 entries. Dates should be specific (Q3 '26, Aug '26 earnings, Investor Day Nov '26).\n\n### `{{risks_table}}`\nTable with columns: Risk, Mitigant, Tripwire. The tripwire is the **observable data point that would invalidate the thesis** (e.g., \"Q3 ad-tier ARPU prints below $8\", \"top customer renewal pushed past Q4\"). Tripwires distinguish a hedge fund memo from a sellside report.\n\n### `{{position_management}}`\nThree short lines: suggested sizing (% NAV) anchored to conviction × asymmetry; entry price (current or limit); stop level or scale-out trigger.\n\n### `{{monitoring_kpis}}`\n3-5 KPIs to track quarterly. These are the metrics that confirm or kill the thesis — not generic ones (revenue growth, EPS) but specific ones tied to your variant view.\n\n## Step 6: Self-Critique Pass (Mandatory)\n\nBefore rendering, verify every check. If any fail, revise the relevant section before continuing.\n\n1. **Variant view is actually variant.** Not a restatement of consensus dressed up as a view. The test: can you point to specific sellside notes / consensus numbers your view contradicts?\n2. **Every thesis bullet is falsifiable.** Each has a \"wrong if\" clause naming a specific observable.\n3. **Numbers behind every adjective.** No \"strong growth\" without the bps / %. No \"expanding margins\" without the basis point delta.\n4. **Bear case is steelmanned.** Read the bear paragraph aloud. If it reads weaker than the bull, rewrite.\n5. **Asymmetry ≥ 2x.** If not, the memo flags this in the header rather than hiding it.\n6. **Probability weights sum to 100%.**\n7. **Tripwires are observable.** Each risk has a data point an analyst could watch for, not a vibe.\n\n## Step 7: Render HTML\n\n1. Read `memo-template.html` via `read_file`\n2. Replace every `{{slot}}` placeholder with the content you drafted\n3. Set `{{date}}` to today's date in YYYY-MM-DD format\n4. Set `{{analyst}}` from memory if known, otherwise blank\n5. Write to `.dexter/memos/[TICKER]_[DIRECTION]_[YYYY-MM-DD].html` via `write_file`\n   - Direction is `LONG` or `SHORT` (uppercase)\n   - Example: `.dexter/memos/NFLX_LONG_2026-05-24.html`\n6. **Only** write a `.md` source file if the user explicitly requested one\n\nThe path uses forward slashes. The `write_file` tool will create the `.dexter/memos/` directory if it does not exist.\n\n## Step 8: Report to Chat\n\nFinal chat response should be exactly this format and nothing more:\n\n```\n[TICKER] · [LONG/SHORT] · Target $X (+Y% / -Y%) · Asymmetry [N.Nx] · [Conviction]\n\nMemo saved to .dexter/memos/[FILENAME].html\nOpen with: open .dexter/memos/[FILENAME].html\n```\n\nDo not paste the full memo content into the chat. The file is the deliverable. The chat output is a scannable header.\n\n## Critical Don'ts\n\n- Do not paste the full memo as a chat response in addition to writing the file\n- Do not write a `.md` file alongside unless explicitly requested\n- Do not include charts, sparklines, scenario bars, or any visual element beyond tables\n- Do not add emoji anywhere — not in the memo, not in the chat response\n- Do not include a prominent \"AI-generated\" footer or branding\n- Do not skip the self-critique pass in Step 6\n- Do not invent consensus numbers — if you do not have them from a tool call, say so in the memo\n"},"files":{"src/skills/write-memo/examples.md":"# Example Memo (for tone calibration)\n\nThis is a worked example for `NFLX LONG · 12mo`. Use it to pattern-match tone, density, and structure when drafting. **Do not copy the numbers** — fetch fresh data via the tools for any actual memo.\n\nThe example is shown as the content that would fill the template slots, not the final HTML.\n\n---\n\n**Header strip values**\n- Ticker: NFLX\n- Company: Netflix, Inc.\n- Direction: LONG\n- Conviction: HIGH\n- Horizon: 12mo\n- Current price: $620\n- Base target: $785\n- Upside: +27%\n- Asymmetry: 2.4x\n- Prob-weighted return: +18%\n\n---\n\n**`{{variant_view}}`**\n\nConsensus models ad-tier as a single-digit revenue line for the next three years. We think it is a 20%+ contributor to '27 revenue and the primary multiple-rerate catalyst. The Street is anchored to subscription-only unit economics and has not updated for ad-tier ARPU running 30% above their first-year assumption.\n\n---\n\n**`{{thesis_bullets}}`** (HTML list items)\n\n- **Ad-tier reaches 18% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; at current adds and a 65% mix of new signups going to the ad tier, we model 51M ad-tier subs by end-'27. *Wrong if ad-tier mix of new signups falls below 50% for two consecutive quarters.*\n- **Ad-tier ARPU sustains $9+** — current ad CPMs of $35-45 imply $9-11 ARPU at 5 ad-min/hr inventory; management called out upfront commitments doubling YoY. *Wrong if disclosed ad ARPU prints below $8 in any quarterly disclosure.*\n- **Operating margin expands 600bps to 28% by '27** — content amortization peaks in '25 per management; incremental ad revenue is 70%+ margin. *Wrong if content spend grows above $20B in any year.*\n- **Multiple rerates from 28x to 35x as ad revenue mix exceeds 15%** — comparable transition (Spotify ad-tier, Roku) saw 25-40% multiple expansion when ad revenue crossed 15% of total. *Wrong if ad revenue stalls below 12% of total through '27.*\n\n---\n\n**`{{business_snapshot}}`**\n\nNetflix is a global subscription video streaming service with 270M paid memberships across 190+ countries. The company licenses and produces original content; \"we have one of the largest libraries of TV series and films, with content available in over 30 languages\" (10-K Item 1). Two membership tiers contribute differently: standard and premium subscriptions (~$15-23/mo) drive 92% of revenue today; the ad-supported tier (~$7/mo plus advertising) launched late '22 and is now the company's stated highest-growth tier. Unit economics differ: ad-tier subs carry lower subscription ARPU but ad revenue at ~70% incremental margin lifts blended contribution above the standard tier by year two of a sub's life.\n\n---\n\n**`{{whats_priced_in}}`**\n\nAt $620, NFLX trades at 28x consensus '26 EPS of $22.10. Consensus models 11% revenue growth and 23% operating margin in '27 — implying the Street is pricing in the subscription business compounding low-teens with modest margin expansion. Sellside ad-tier revenue estimates cluster around $4-5B for '27 (consensus mean $4.6B). Our '27 model puts ad revenue at $8.2B (+78% vs. consensus) on higher ad-tier sub adds and sustained ARPU. EPS divergence: our $29.50 vs. consensus $24.80, a +19% delta.\n\n---\n\n**`{{scenario_table}}`**\n\n| | Bear (20%) | Base (55%) | Bull (25%) |\n|---|---|---|---|\n| Revenue '27 | $42B | $52B | $61B |\n| Revenue growth | +6% | +14% | +20% |\n| EBIT margin | 22% | 28% | 32% |\n| EPS '27 | $19.50 | $29.50 | $38.20 |\n| Exit multiple | 22x | 28x | 35x |\n| Price target | $430 | $785 | $1,205 |\n| Return | -31% | +27% | +94% |\n\nProb-weighted return: +18% · Upside / downside: 2.4x\n\n---\n\n**`{{bull_narrative}}`**\n\nAd-tier inflects faster than we model. Disney+ pulls back on ad-tier pricing competition, leaving NFLX as the premium ad-supported inventory option for upfront buyers. Live programming (NFL, boxing, WWE) drives ad-tier mix of new signups above 70%, and ad CPMs sustain in the $40s as inventory stays scarce relative to demand. Content cost discipline holds — total content spend stays flat at $17B even as subs grow — and operating margin reaches 32% by '27. The Street rerates the stock to 35x as ad revenue crosses 20% of total, reclassifying NFLX from subscription business to dual-revenue media platform. EPS compounds 25%+ for three years.\n\n---\n\n**`{{base_narrative}}`**\n\nAd-tier grows roughly in line with current trajectory and reaches 50M+ subs by '27. ARPU holds at $9-10 as content investment in live and originals supports pricing. Content amortization peaks in '25 and rolls off, lifting operating margin to 28% by '27 even with $18-19B of content spend. Subscription business compounds high single digits globally with the bulk of net adds from APAC and LatAm at lower ARPU. The Street partially rerates the stock as ad mix exceeds 15%, multiple expands to 28x — in line with current level but on materially higher EPS.\n\n---\n\n**`{{bear_narrative}}`**\n\nDisney+ and Amazon's Prime Video ad tier compete aggressively on price; Disney+ ad-tier subs cross 100M globally by end-'26 and Amazon bundles ad-supported streaming into Prime at no incremental cost. Ad-tier CPMs compress 25% to the high $20s as inventory floods the market and brand advertisers consolidate spend on retail media platforms (Amazon, Walmart Connect) rather than streaming. NFLX ad revenue stalls at $3-3.5B for '27 vs. street $4.6B. Content spend creeps to $20B as the live programming push (NFL, boxing) proves more expensive to renew than initial deals suggested. Operating margin compresses to 22% as fixed content costs deleverage on slower revenue growth. The multiple compresses to 22x — Disney's current multiple — as the market reclassifies NFLX as a mature subscription business with declining incremental returns on content spend. Stock retraces to the low $400s.\n\n---\n\n**`{{catalysts_table}}`**\n\n| Event | Date | Expected Impact |\n|---|---|---|\n| Q2 '26 earnings — ad-tier sub disclosure | Jul '26 | Ad-tier sub count vs. our 45M target |\n| Upfront ad commitments | Apr-May '26 | Total committed dollars; vs. $1B+ '25 baseline |\n| NFL Christmas Day games viewership | Dec '26 | Concurrent viewers; ad-load testing |\n| FY27 guidance | Jan '27 | First explicit ad revenue guide |\n\n---\n\n**`{{risks_table}}`**\n\n| Risk | Mitigant | Tripwire |\n|---|---|---|\n| Ad-tier ARPU compression | Premium inventory (live sports) supports CPMs | Disclosed ad ARPU < $8 in any quarter |\n| Content cost re-acceleration | Management explicit guide of $17B '26 cap | Content spend > $19B in any year |\n| Competitive ad-tier launch from Amazon | Amazon ad-tier already live; share gains modest | NFLX ad-tier net adds < 5M in any quarter |\n| Subscription growth stalls in APAC | Pricing flexibility, mobile-only tier | Net adds < 4M globally in two consecutive quarters |\n| Multiple compression on rate environment | EPS growth outpaces multiple compression risk | Multiple < 24x with no operational miss |\n\n---\n\n**`{{position_management}}`**\n\nSuggested sizing: 4% NAV — high conviction × 2.4x asymmetry. Entry: current ($620) or scale-in below $590 on multiple compression. Stop / reduce: trim 50% if ad-tier ARPU prints below $8 in any quarter; full exit if content spend guide steps above $19B.\n\n---\n\n**`{{monitoring_kpis}}`**\n\n1. Ad-tier subscriber count (quarterly disclosure)\n2. Ad-tier ARPU or implied ARPU (calc: ad revenue / avg ad-tier subs)\n3. Content cash spend YTD vs. annual guide\n4. Operating margin (quarterly) — trajectory to 28% by '27\n5. Upfront commitment dollars (annual) — vs. prior year\n\n---\n\n## Why this example works\n\n- **Variant view is specific and contradictable.** It names a number (20%+ revenue contribution by '27) and a divergence (Street models single-digit). A PM can disagree with it precisely.\n- **Every thesis bullet has a \"wrong if\".** None of them are unfalsifiable platitudes.\n- **Bear case names competitors and mechanisms.** Disney+, Amazon, retail media, NFL renewal costs. Not \"competition intensifies\".\n- **Tripwires are observable.** \"Disclosed ad ARPU < $8 in any quarter\" is a data point the analyst can monitor; \"macro deteriorates\" is not.\n- **No padding.** No founding history, no \"in an ever-evolving streaming landscape\", no closing summary paragraph.\n\nWhen you draft a real memo, match this density and specificity, not the surface aesthetics. The aesthetics come from the template; the substance comes from the thinking.\n","src/skills/dcf/sector-wacc.md":"# Sector WACC Adjustments\n\nUse these typical WACC ranges as starting points, then adjust based on company-specific factors.\n\n## Determining Company Sector\n\nUse `get_financials` with query `\"[TICKER] company facts\"` to retrieve the company's `sector`. Match the returned sector to the table below.\n\n## WACC by Sector\n\n| Sector | Typical WACC Range | Notes |\n|--------|-------------------|-------|\n| Communication Services | 8-10% | Mix of stable telecom and growth media |\n| Consumer Discretionary | 8-10% | Cyclical exposure |\n| Consumer Staples | 7-8% | Defensive, stable demand |\n| Energy | 9-11% | Commodity price exposure |\n| Financials | 8-10% | Leverage already in business model |\n| Health Care | 8-10% | Regulatory and pipeline risk |\n| Industrials | 8-9% | Moderate cyclicality |\n| Information Technology | 8-12% | Assess growth stage; higher for high-growth |\n| Materials | 8-10% | Cyclical, commodity exposure |\n| Real Estate | 7-9% | Interest rate sensitivity |\n| Utilities | 6-7% | Regulated, stable cash flows |\n\n## Adjustment Factors\n\nAdd to base WACC:\n- **High debt (D/E > 1.5)**: +1-2%\n- **Small cap (< $2B market cap)**: +1-2%\n- **Emerging markets exposure**: +1-3%\n- **Concentrated customer base**: +0.5-1%\n- **Regulatory uncertainty**: +0.5-1.5%\n\nSubtract from base WACC:\n- **Market leader with moat**: -0.5-1%\n- **Recurring revenue model**: -0.5-1%\n- **Investment grade credit rating**: -0.5%\n\n## Reasonableness Checks\n\n- WACC should typically be 2-4% below ROIC for value-creating companies\n- If calculated WACC > ROIC, the company may be destroying value\n- Compare to sector peers if available\n","src/skills/x-research/SKILL.md":"---\nname: x-research\ndescription: >\n  X/Twitter public sentiment research. Searches X for real-time perspectives,\n  market sentiment, expert opinions, breaking news, and community discourse.\n  Use when: user asks \"what are people saying about\", \"X/Twitter sentiment\",\n  \"check X for\", \"search twitter for\", \"what's CT saying about\", or wants\n  public opinion on a stock, sector, company, or market event.\n---\n\n# X Research Skill\n\nAgentic research over X/Twitter using the `x_search` tool. Decompose the\nresearch question into targeted searches, iterate to refine signal, and\nsynthesize into a sourced sentiment briefing.\n\n## Research Loop\n\n### 1. Decompose into Queries\n\nTurn the research question into 3–5 targeted queries using X operators:\n\n- **Core query**: Direct keywords or `$TICKER` cashtag\n- **Expert voices**: `from:username` for known analysts or accounts\n- **Bearish signal**: keywords like `(overvalued OR bubble OR risk OR concern)`\n- **Bullish signal**: keywords like `(bullish OR upside OR catalyst OR beat)`\n- **News/links**: add `has:links` to surface tweets with sources\n- **Noise reduction**: `-is:reply` to focus on original posts; `-airdrop -giveaway` for crypto topics\n\n### 2. Execute Searches\n\nUse the `x_search` tool with `command: \"search\"`. For each query:\n\n- Start with `sort: \"likes\"` and `limit: 15` to surface highest-signal tweets\n- Add `min_likes: 5` or higher to filter noise for broad topics\n- Use `since: \"1d\"` or `\"7d\"` depending on how time-sensitive the topic is\n- If a query returns too much noise, narrow with more operators or raise `min_likes`\n- If too few results, broaden with `OR` terms or remove restrictive operators\n\n### 3. Check Key Accounts (Optional)\n\nFor well-known analysts, fund managers, or company executives, use\n`command: \"profile\"` to see their recent posts directly.\n\n### 4. Follow Threads (Optional)\n\nWhen a high-engagement tweet appears to be a thread starter, use\n`command: \"thread\"` with the tweet ID to get full context.\n\n### 5. Synthesize\n\nGroup findings by theme (bullish, bearish, neutral, news/catalysts):\n\n```\n### [Theme]\n\n[1–2 sentence summary of the theme]\n\n- @username: \"[key quote]\" — [likes]♥ [Tweet](url)\n- @username2: \"[another perspective]\" — [likes]♥ [Tweet](url)\n```\n\nEnd with an **Overall Sentiment** paragraph: predominant tone (bullish/bearish/\nmixed/neutral), confidence level, and any notable divergence between retail and\ninstitutional voices.\n\n## Refinement Heuristics\n\n| Problem | Fix |\n|---|---|\n| Too much noise | Raise `min_likes`, add `-is:reply`, narrow keywords |\n| Too few results | Broaden with `OR`, remove restrictive operators |\n| Crypto spam | Add `-airdrop -giveaway -whitelist` |\n| Want expert takes only | Use `from:` or `min_likes: 50` |\n| Want substance over hot takes | Add `has:links` |\n\n## Output Format\n\nPresent a structured briefing:\n\n1. **Query Summary**: what was searched and time window\n2. **Sentiment Themes**: grouped findings with sourced quotes and tweet links\n3. **Overall Sentiment**: tone, confidence, key voices\n4. **Caveats**: X sentiment is not a reliable predictor; sample bias toward vocal minorities; last-7-days window only\n","AGENTS.md":"# Repository Guidelines\n\n- Repo: https://github.com/virattt/dexter\n- Dexter is a CLI-based AI agent for deep financial research, built with TypeScript, Ink (React for CLI), and LangChain.\n\n## Project Structure\n\n- Source code: `src/`\n  - Agent core: `src/agent/` (agent loop, prompts, scratchpad, token counting, types)\n  - CLI interface: `src/cli.tsx` (Ink/React), entry point: `src/index.tsx`\n  - Components: `src/components/` (Ink UI components)\n  - Hooks: `src/hooks/` (React hooks for agent runner, model selection, input history)\n  - Model/LLM: `src/model/llm.ts` (multi-provider LLM abstraction)\n  - Tools: `src/tools/` (financial search, web search, browser, skill tool)\n  - Tool descriptions: `src/tools/descriptions/` (rich descriptions injected into system prompt)\n  - Finance tools: `src/tools/finance/` (prices, fundamentals, filings, insider trades, etc.)\n  - Search tools: `src/tools/search/` (Exa preferred, Tavily fallback)\n  - Browser: `src/tools/browser/` (Playwright-based web scraping)\n  - Skills: `src/skills/` (SKILL.md-based extensible workflows, e.g. DCF valuation)\n  - Utils: `src/utils/` (env, config, caching, token estimation, markdown tables)\n  - Evals: `src/evals/` (LangSmith evaluation runner with Ink UI)\n- Config: `.dexter/settings.json` (persisted model/provider selection)\n- Environment: `.env` (API keys; see `env.example`)\n- Scripts: `scripts/release.sh`\n\n## Build, Test, and Development Commands\n\n- Runtime: Bun (primary). Use `bun` for all commands.\n- Install deps: `bun install`\n- Run: `bun run start` or `bun run src/index.tsx`\n- Dev (watch mode): `bun run dev`\n- Type-check: `bun run typecheck`\n- Tests: `bun test`\n- Evals: `bun run src/evals/run.ts` (full) or `bun run src/evals/run.ts --sample 10` (sampled)\n- CI runs `bun run typecheck` and `bun test` on push/PR.\n\n## Coding Style & Conventions\n\n- Language: TypeScript (ESM, strict mode). JSX via React (Ink for CLI rendering).\n- Prefer strict typing; avoid `any`.\n- Keep files concise; extract helpers rather than duplicating code.\n- Add brief comments for tricky or non-obvious logic.\n- Do not add logging unless explicitly asked.\n- Do not create README or documentation files unless explicitly asked.\n\n## LLM Providers\n\n- Supported: OpenAI (default), Anthropic, Google, xAI (Grok), OpenRouter, Ollama (local).\n- Default model: `gpt-5.5`. Provider detection is prefix-based (`claude-` -> Anthropic, `gemini-` -> Google, etc.).\n- Fast models for lightweight tasks: see `FAST_MODELS` map in `src/model/llm.ts`.\n- Anthropic uses explicit `cache_control` on system prompt for prompt caching cost savings.\n- Users switch providers/models via `/model` command in the CLI.\n\n## Tools\n\n- `financial_search`: primary tool for all financial data queries (prices, metrics, filings). Delegates to multiple sub-tools internally.\n- `financial_metrics`: direct metric lookups (revenue, market cap, etc.).\n- `read_filings`: SEC filing reader for 10-K, 10-Q, 8-K documents.\n- `web_search`: general web search (Exa if `EXASEARCH_API_KEY` set, else Tavily if `TAVILY_API_KEY` set).\n- `browser`: Playwright-based web scraping for reading pages the agent discovers.\n- `skill`: invokes SKILL.md-defined workflows (e.g. DCF valuation). Each skill runs at most once per query.\n- Tool registry: `src/tools/registry.ts`. Tools are conditionally included based on env vars.\n\n## Skills\n\n- Skills live as `SKILL.md` files with YAML frontmatter (`name`, `description`) and markdown body (instructions).\n- Built-in skills: `src/skills/dcf/SKILL.md`.\n- Discovery: `src/skills/registry.ts` scans for SKILL.md files at startup.\n- Skills are exposed to the LLM as metadata in the system prompt; the LLM invokes them via the `skill` tool.\n\n## Agent Architecture\n\n- Agent loop: `src/agent/agent.ts`. Iterative tool-calling loop with configurable max iterations (default 10).\n- Scratchpad: `src/agent/scratchpad.ts`. Single source of truth for all tool results within a query.\n- Context management: Anthropic-style. Full tool results kept in context; oldest results cleared when token threshold exceeded.\n- Final answer: generated in a separate LLM call with full scratchpad context (no tools bound).\n- Events: agent yields typed events (`tool_start`, `tool_end`, `thinking`, `answer_start`, `done`, etc.) for real-time UI updates.\n\n## Environment Variables\n\n- LLM keys: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY`, `XAI_API_KEY`, `OPENROUTER_API_KEY`\n- Ollama: `OLLAMA_BASE_URL` (default `http://127.0.0.1:11434`)\n- Finance: `FINANCIAL_DATASETS_API_KEY`\n- Search: `EXASEARCH_API_KEY` (preferred), `TAVILY_API_KEY` (fallback)\n- Tracing: `LANGSMITH_API_KEY`, `LANGSMITH_ENDPOINT`, `LANGSMITH_PROJECT`, `LANGSMITH_TRACING`\n- Never commit `.env` files or real API keys.\n\n## Version & Release\n\n- Version format: SemVer `MAJOR.MINOR.PATCH`. Tag prefix: `v`.\n- Release script: `bash scripts/release.sh [version]` (defaults to today's date).\n- Release flow: bump version in `package.json`, create git tag, push tag, create GitHub release via `gh`.\n- Do not push or publish without user confirmation.\n\n## Testing\n\n- Framework: Bun's built-in test runner (primary), Jest config exists for legacy compatibility.\n- Tests colocated as `*.test.ts`.\n- Run `bun test` before pushing when you touch logic.\n\n## Security\n\n- API keys stored in `.env` (gitignored). Users can also enter keys interactively via the CLI.\n- Config stored in `.dexter/settings.json` (gitignored).\n- Never commit or expose real API keys, tokens, or credentials.\n","src/skills/write-memo/memo-style.md":"# Investment Memo Style Guide\n\nRules the memo must follow. These mirror buyside writing conventions and avoid the tells that mark a document as AI-generated.\n\n## Voice\n\n- **First person plural** (\"we believe\", \"our base case\") — that's how a buyside team writes.\n- **Direct, not hedging.** \"Margins compress 200bps in '27\" beats \"margins could potentially face some pressure in 2027\".\n- **Confidence calibrated by evidence.** State the view, then state the evidence. Hedge once with a \"wrong if\" — not in every sentence.\n- **One sentence per idea** in narrative sections. Long sentences with comma chains and parentheticals signal AI drift.\n\n## Banned vocabulary\n\nNever use these words. They are AI-generated tells:\n\n- \"delve\", \"delves\", \"delving\"\n- \"leverage\" as a verb (\"we leverage X to do Y\")\n- \"robust\", \"comprehensive\", \"holistic\", \"seamless\"\n- \"navigate the landscape\", \"navigate the challenges\"\n- \"in today's fast-paced\", \"in an ever-evolving\"\n- \"stands out\", \"sets itself apart\"\n- \"deep dive\", \"unpack\", \"double-click\"\n- \"moreover\", \"furthermore\", \"additionally\" (use a new sentence)\n- \"It's worth noting that\" (just say the thing)\n\n## Banned constructions\n\n- **Tricolons** — three-item lists for rhythmic effect (\"fast, scalable, and reliable\"). One AI tell.\n- **Em dash abuse** — at most one em dash per paragraph. Prefer periods or commas.\n- **\"Not just X but Y\"** — overused contrast structure.\n- **Generic closing summaries** — \"In conclusion, this is a compelling opportunity that...\" Don't write these. End on a specific claim or a tripwire.\n- **Hedge stacking** — \"could potentially possibly maybe\". Pick one or zero.\n\n## Numbers\n\n- **Quantify everything.** \"Margins expanded 380bps\" not \"margins improved meaningfully\".\n- **Percentages with explicit base.** \"Revenue grew 28% YoY\" not \"revenue saw strong growth\".\n- **Multiples in line.** \"Trading at 18x FY26 EPS\" not \"trading at attractive multiples\".\n- **Don't invent numbers.** If you don't have it from a tool call, write \"not disclosed\" or omit the line. Never fabricate consensus figures.\n\n## Thesis bullet format\n\nEvery thesis bullet must be a complete falsifiable claim:\n\n> **[Specific claim with a number]** — [Evidence with a specific number, ideally citing the data point]. *Wrong if [specific observable would happen].*\n\nGood:\n> **Ad-tier reaches 15% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; trajectory implies 15% mix at constant adds. *Wrong if ad-tier ARPU compresses below $8 due to inventory glut.*\n\nBad (vague claim, no falsifier):\n> **Strong product-market fit in ad tier** — Management has emphasized this is a key growth area going forward.\n\n## Bear case requirements\n\nThe bear paragraph is the highest-stakes paragraph in the memo. Rules:\n\n1. **Steelmanned.** Written as if you actually believed it. If you can't, you don't understand the trade.\n2. **Specific competitor / customer / regulator named.** Not \"competition intensifies\" — name the company and the product.\n3. **Coherent world, not a list.** The bear case is a story where the thesis is wrong. Connect the dots.\n4. **Read the bull paragraph and the bear paragraph back to back.** If bear reads weaker, rewrite. This is the single most common failure mode.\n\n## Tripwires\n\nEvery risk row in the risks table must have a tripwire. A tripwire is **an observable data point that would invalidate the thesis** within the holding period.\n\nGood tripwires:\n- \"Q3 ad-tier ARPU prints below $8\"\n- \"Top customer announces in-sourcing on Q2 call\"\n- \"Gross margin contracts more than 150bps in any quarter\"\n- \"Insider sales exceed $50M in any rolling 90-day window\"\n\nBad tripwires (not observable / not actionable):\n- \"Macro deteriorates\"\n- \"Competition increases\"\n- \"Sentiment shifts negatively\"\n\n## What to pull from filings\n\nWhen summarizing the business, pull verbatim from the 10-K Item 1 where the company's own language is tighter than rewriting it. Quote with quotes and source: `\"[exact phrase]\" (10-K Item 1)`.\n\nFor risks, prefer pulling from Item 1A and the company's own disclosure language — it's the most defensible risk framing in the memo.\n\n## Closing the memo\n\nMemos do not need a \"conclusion\" section. The header already states the recommendation; the thesis bullets state the view; the scenarios state the math. A closing paragraph that restates these is padding.\n\nThe last section in the body is **Monitoring KPIs** — the specific metrics that confirm or kill the thesis. That's the right note to end on: what to watch.\n","src/skills/dcf/SKILL.md":"---\nname: dcf-valuation\ndescription: Performs discounted cash flow (DCF) valuation analysis to estimate intrinsic value per share. Triggers when user asks for fair value, intrinsic value, DCF, valuation, \"what is X worth\", price target, undervalued/overvalued analysis, or wants to compare current price to fundamental value.\n---\n\n# DCF Valuation Skill\n\n## Workflow Checklist\n\nCopy and track progress:\n```\nDCF Analysis Progress:\n- [ ] Step 1: Gather financial data\n- [ ] Step 2: Calculate FCF growth rate\n- [ ] Step 3: Estimate discount rate (WACC)\n- [ ] Step 4: Project future cash flows (Years 1-5 + Terminal)\n- [ ] Step 5: Calculate present value and fair value per share\n- [ ] Step 6: Run sensitivity analysis\n- [ ] Step 7: Validate results\n- [ ] Step 8: Present results with caveats\n```\n\n## Step 1: Gather Financial Data\n\nCall the `get_financials` tool with these queries:\n\n### 1.1 Cash Flow History\n**Query:** `\"[TICKER] annual cash flow statements for the last 5 years\"`\n\n**Extract:** `free_cash_flow`, `net_cash_flow_from_operations`, `capital_expenditure`\n\n**Fallback:** If `free_cash_flow` missing, calculate: `net_cash_flow_from_operations - capital_expenditure`\n\n### 1.2 Financial Metrics\n**Query:** `\"[TICKER] financial metrics snapshot\"`\n\n**Extract:** `market_cap`, `enterprise_value`, `free_cash_flow_growth`, `revenue_growth`, `return_on_invested_capital`, `debt_to_equity`, `free_cash_flow_per_share`\n\n### 1.3 Balance Sheet\n**Query:** `\"[TICKER] latest balance sheet\"`\n\n**Extract:** `total_debt`, `cash_and_equivalents`, `current_investments`, `outstanding_shares`\n\n**Fallback:** If `current_investments` missing, use 0\n\n### 1.4 Current Price\nCall the `get_market_data` tool:\n\n**Query:** `\"[TICKER] price snapshot\"`\n\n**Extract:** `price`\n\n### 1.5 Company Facts\nCall the `get_financials` tool:\n\n**Query:** `\"[TICKER] company facts\"`\n\n**Extract:** `sector`, `industry`, `market_cap`\n\n**Use:** Determine appropriate WACC range from [sector-wacc.md](sector-wacc.md)\n\n## Step 2: Calculate FCF Growth Rate\n\nCalculate 5-year FCF CAGR from cash flow history.\n\n**Cross-validate with:** `free_cash_flow_growth` (YoY), `revenue_growth`\n\n**Growth rate selection:**\n- Stable FCF history → Use CAGR with 10-20% haircut\n- **Cap at 15%** (sustained higher growth is rare)\n\n## Step 3: Estimate Discount Rate (WACC)\n\n**Use the `sector` from company facts** to select the appropriate base WACC range from [sector-wacc.md](sector-wacc.md).\n\n**Default assumptions:**\n- Risk-free rate: 4%\n- Equity risk premium: 5-6%\n- Cost of debt: 5-6% pre-tax (~4% after-tax at 30% tax rate)\n\nCalculate WACC using `debt_to_equity` for capital structure weights.\n\n**Reasonableness check:** WACC should be 2-4% below `return_on_invested_capital` for value-creating companies.\n\n**Sector adjustments:** Apply adjustment factors from [sector-wacc.md](sector-wacc.md) based on company-specific characteristics.\n\n## Step 4: Project Future Cash Flows\n\n**Years 1-5:** Apply growth rate with 5% annual decay (multiply growth rate by 0.95, 0.90, 0.85, 0.80 for years 2-5). This reflects competitive dynamics.\n\n**Terminal value:** Use Gordon Growth Model with 2.5% terminal growth (GDP proxy).\n\n## Step 5: Calculate Present Value\n\nDiscount all FCFs → sum for Enterprise Value → subtract Net Debt → divide by `outstanding_shares` for fair value per share.\n\n## Step 6: Sensitivity Analysis\n\nCreate 3×3 matrix: WACC (base ±1%) vs terminal growth (2.0%, 2.5%, 3.0%).\n\n## Step 7: Validate Results\n\nBefore presenting, verify these sanity checks:\n\n1. **EV comparison**: Calculated EV should be within 30% of reported `enterprise_value`\n   - If off by >30%, revisit WACC or growth assumptions\n\n2. **Terminal value ratio**: Terminal value should be 50-80% of total EV for mature companies\n   - If >90%, growth rate may be too high\n   - If <40%, near-term projections may be aggressive\n\n3. **Per-share cross-check**: Compare to `free_cash_flow_per_share × 15-25` as rough sanity check\n\nIf validation fails, reconsider assumptions before presenting results.\n\n## Step 8: Output Format\n\nPresent a structured summary including:\n1. **Valuation Summary**: Current price vs. fair value, upside/downside percentage\n2. **Key Inputs Table**: All assumptions with their sources\n3. **Projected FCF Table**: 5-year projections with present values\n4. **Sensitivity Matrix**: 3×3 grid varying WACC (±1%) and terminal growth (2.0%, 2.5%, 3.0%)\n5. **Caveats**: Standard DCF limitations plus company-specific risks\n","src/skills/write-memo/SKILL.md":"---\nname: write-memo\ndescription: Drafts a professional investment memo (HTML output) for a long or short equity idea, structured the way a hedge fund analyst would present a thesis to a PM. Triggers when the user asks to \"write a memo\", \"draft an investment memo\", \"write up a thesis\", \"pitch this stock\", \"memo on [ticker]\", \"long writeup\", \"short writeup\", or similar. Produces a 1-page HTML file at .dexter/memos/.\n---\n\n# Write Investment Memo Skill\n\nProduces a buyside-quality investment memo as a self-contained HTML file. The memo is opinionated and falsifiable — it leads with a variant view and steelmans the bear case. The output is the deliverable; the chat response is just a header summary plus the file path.\n\n## Workflow Checklist\n\nCopy and track progress:\n```\nInvestment Memo Progress:\n- [ ] Step 1: Frame the trade (direction, horizon, variant view)\n- [ ] Step 2: Gather data (financials, market, filings)\n- [ ] Step 3: Build Bear / Base / Bull scenarios\n- [ ] Step 4: Optional DCF anchor for base case\n- [ ] Step 5: Draft memo content (fill all slots)\n- [ ] Step 6: Self-critique pass\n- [ ] Step 7: Render HTML to .dexter/memos/\n- [ ] Step 8: Report header summary + file path\n```\n\n## Step 1: Frame the Trade\n\nConfirm or ask for the following before drafting:\n\n- **Ticker** (required)\n- **Direction**: long or short (required)\n- **Horizon**: 3mo / 6mo / 12mo / 2yr+ (default 12mo if not specified)\n- **Conviction**: high / medium / low (default medium)\n- **Variant view**: one sentence — what the analyst sees that consensus doesn't\n\n**If the user does not provide a variant view**: do not ask repeatedly. Gather data in Step 2 first, then derive a candidate variant view from where your model meaningfully diverges from consensus (e.g., \"our '27 EPS is $X vs consensus $Y because [driver]\"). Present it as a draft and let the analyst accept, refine, or replace before you proceed to Step 5.\n\n## Step 2: Gather Data (Parallel)\n\nIssue these tool calls in parallel:\n\n### 2.1 Financials\nCall `get_financials`:\n- `\"[TICKER] annual income statements last 5 years\"` — revenue, operating income, net income, EPS, margins\n- `\"[TICKER] annual cash flow statements last 5 years\"` — operating CF, capex, FCF\n- `\"[TICKER] latest balance sheet\"` — debt, cash, shares outstanding\n- `\"[TICKER] financial metrics snapshot\"` — P/E, EV, ROIC, FCF growth, debt/equity, margins\n- `\"[TICKER] segmented financials\"` — segment revenue, segment margins (if multi-segment)\n- `\"[TICKER] earnings history last 8 quarters\"` — beats/misses, surprises\n- `\"[TICKER] company facts\"` — sector, industry, market cap\n- `\"[TICKER] KPI guidance\"` and `\"[TICKER] KPI metrics\"` — management-provided KPIs and guidance\n\n### 2.2 Market & Ownership\nCall `get_market_data`:\n- `\"[TICKER] price snapshot\"` — current price, 52-week range, market cap\n- `\"[TICKER] historical prices last 12 months\"` — for return / multiple compression context\n- `\"[TICKER] insider trades last 6 months\"` — recent buys/sells, dollar amounts\n- `\"[TICKER] institutional holdings\"` — top holders, recent additions / reductions\n- `\"[TICKER] news last 30 days\"` — recent material events\n\n### 2.3 Filings\nCall `read_filings`:\n- Most recent 10-K Item 1 (Business) — for business snapshot language\n- Most recent 10-K Item 1A (Risk Factors) — to source risks from the company itself\n- Most recent 10-Q — recent quarterly trajectory\n\n### 2.4 Memory (optional)\nCall `memory_search` with the ticker — surfaces any prior notes, prior memos, or user-provided constraints (e.g., risk tolerance, sector exposure already in book).\n\n### 2.5 Sentiment (optional, only if time-sensitive)\nCall `x_search` for recent material chatter on the ticker. Skip if the thesis is fundamental and not catalyst-driven this week.\n\n## Step 3: Build Scenarios\n\nConstruct Bear / Base / Bull scenarios. Each scenario is **driver-based**, not a single number pulled from the air.\n\nFor each scenario specify:\n- **Revenue growth** (forecast year, 2-3 years out)\n- **EBIT / operating margin** at that point\n- **Exit multiple** (P/E, EV/EBITDA, or EV/Sales as appropriate for the sector)\n- **Probability weight** (the three must sum to 100%)\n- **Price target** (derived from the above)\n- **Return** vs. current price (with sign)\n\nThen compute:\n- **Probability-weighted return** = sum(prob × return) across scenarios\n- **Upside / downside ratio** = |bull return| / |bear return|\n\n**Asymmetry check**: if upside/downside < 2x, flag this prominently. A weak-asymmetry setup is a coin flip, not a trade. Either revise the scenarios honestly, or note the weak asymmetry in the memo (do not hide it).\n\n## Step 4: Optional DCF Anchor\n\nFor base case, optionally invoke the `dcf-valuation` skill via the `skill` tool to produce an intrinsic value anchor. Use it as a cross-check against your base-case price target, not as a replacement.\n\n## Step 5: Draft Memo Content\n\nRead the template and style guide:\n- [memo-template.html](memo-template.html)\n- [memo-style.md](memo-style.md)\n- [examples.md](examples.md) — pattern-match tone and density\n\nFill every slot. Slots are listed in the template — do not skip any. Slot-specific guidance:\n\n### `{{variant_view}}`\nThree sentences max. Lead with the divergence from consensus: *what we see, why we think it, why the market hasn't priced it*. If the user did not provide one, this is where your derived candidate goes.\n\n### `{{thesis_bullets}}`\n3-5 bullets, each in this format:\n> **[Claim]** — [Evidence with a specific number]. *Wrong if [observable falsifier].*\n\nExample:\n> **Ad-tier reaches 15% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; trajectory implies 15% mix at constant adds. *Wrong if ad-tier ARPU compresses below $8 due to inventory glut.*\n\nEach bullet must be **falsifiable**. No \"great management\", \"strong moat\", \"wide TAM\" without a specific operational metric behind it.\n\n### `{{business_snapshot}}`\n4-5 lines max. What they sell, how they make money, segment mix, unit economics that matter for the thesis. **No founding-year boilerplate.** Pull verbatim from the 10-K Item 1 where it tightens the language.\n\n### `{{whats_priced_in}}`\nCurrent multiple, implied growth or margin assumption embedded in that multiple, sellside consensus numbers (revenue, EPS for FY+1 and FY+2). Then one sentence on where your model diverges and by how much.\n\n### `{{scenario_table}}`\nRender as an HTML table. Columns: Bear / Base / Bull. Rows: Probability, Revenue growth (FY27), EBIT margin (FY27), Exit multiple, Price target, Return. Color returns: positive `class=\"pos\"`, negative `class=\"neg\"`.\n\n### `{{bull_narrative}}`, `{{base_narrative}}`, `{{bear_narrative}}`\nOne paragraph each (3-5 sentences). Each is a *coherent world*, not a list of factors:\n- **Bull**: what has to be true. Specific operational wins that compound. Tied to evidence we'd see in quarterly data.\n- **Base**: the thesis playing out as written.\n- **Bear**: steelmanned — written as if you believed it. Specific competitive losses, customer concentration risk materializing, multiple compression to a lower peer group. **If the bear paragraph reads weaker than the bull paragraph, rewrite it.**\n\n### `{{catalysts_table}}`\nTable with columns: Event, Date / Quarter, Expected Impact. 3-5 entries. Dates should be specific (Q3 '26, Aug '26 earnings, Investor Day Nov '26).\n\n### `{{risks_table}}`\nTable with columns: Risk, Mitigant, Tripwire. The tripwire is the **observable data point that would invalidate the thesis** (e.g., \"Q3 ad-tier ARPU prints below $8\", \"top customer renewal pushed past Q4\"). Tripwires distinguish a hedge fund memo from a sellside report.\n\n### `{{position_management}}`\nThree short lines: suggested sizing (% NAV) anchored to conviction × asymmetry; entry price (current or limit); stop level or scale-out trigger.\n\n### `{{monitoring_kpis}}`\n3-5 KPIs to track quarterly. These are the metrics that confirm or kill the thesis — not generic ones (revenue growth, EPS) but specific ones tied to your variant view.\n\n## Step 6: Self-Critique Pass (Mandatory)\n\nBefore rendering, verify every check. If any fail, revise the relevant section before continuing.\n\n1. **Variant view is actually variant.** Not a restatement of consensus dressed up as a view. The test: can you point to specific sellside notes / consensus numbers your view contradicts?\n2. **Every thesis bullet is falsifiable.** Each has a \"wrong if\" clause naming a specific observable.\n3. **Numbers behind every adjective.** No \"strong growth\" without the bps / %. No \"expanding margins\" without the basis point delta.\n4. **Bear case is steelmanned.** Read the bear paragraph aloud. If it reads weaker than the bull, rewrite.\n5. **Asymmetry ≥ 2x.** If not, the memo flags this in the header rather than hiding it.\n6. **Probability weights sum to 100%.**\n7. **Tripwires are observable.** Each risk has a data point an analyst could watch for, not a vibe.\n\n## Step 7: Render HTML\n\n1. Read `memo-template.html` via `read_file`\n2. Replace every `{{slot}}` placeholder with the content you drafted\n3. Set `{{date}}` to today's date in YYYY-MM-DD format\n4. Set `{{analyst}}` from memory if known, otherwise blank\n5. Write to `.dexter/memos/[TICKER]_[DIRECTION]_[YYYY-MM-DD].html` via `write_file`\n   - Direction is `LONG` or `SHORT` (uppercase)\n   - Example: `.dexter/memos/NFLX_LONG_2026-05-24.html`\n6. **Only** write a `.md` source file if the user explicitly requested one\n\nThe path uses forward slashes. The `write_file` tool will create the `.dexter/memos/` directory if it does not exist.\n\n## Step 8: Report to Chat\n\nFinal chat response should be exactly this format and nothing more:\n\n```\n[TICKER] · [LONG/SHORT] · Target $X (+Y% / -Y%) · Asymmetry [N.Nx] · [Conviction]\n\nMemo saved to .dexter/memos/[FILENAME].html\nOpen with: open .dexter/memos/[FILENAME].html\n```\n\nDo not paste the full memo content into the chat. The file is the deliverable. The chat output is a scannable header.\n\n## Critical Don'ts\n\n- Do not paste the full memo as a chat response in addition to writing the file\n- Do not write a `.md` file alongside unless explicitly requested\n- Do not include charts, sparklines, scenario bars, or any visual element beyond tables\n- Do not add emoji anywhere — not in the memo, not in the chat response\n- Do not include a prominent \"AI-generated\" footer or branding\n- Do not skip the self-critique pass in Step 6\n- Do not invent consensus numbers — if you do not have them from a tool call, say so in the memo\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/virattt/dexter/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# Repository Guidelines\n\n- Repo: https://github.com/virattt/dexter\n- Dexter is a CLI-based AI agent for deep financial research, built with TypeScript, Ink (React for CLI), and LangChain.\n\n## Project Structure\n\n- Source code: `src/`\n  - Agent core: `src/agent/` (agent loop, prompts, scratchpad, token counting, types)\n  - CLI interface: `src/cli.tsx` (Ink/React), entry point: `src/index.tsx`\n  - Components: `src/components/` (Ink UI components)\n  - Hooks: `src/hooks/` (React hooks for agent runner, model selection, input history)\n  - Model/LLM: `src/model/llm.ts` (multi-provider LLM abstraction)\n  - Tools: `src/tools/` (financial search, web search, browser, skill tool)\n  - Tool descriptions: `src/tools/descriptions/` (rich descriptions injected into system prompt)\n  - Finance tools: `src/tools/finance/` (prices, fundamentals, filings, insider trades, etc.)\n  - Search tools: `src/tools/search/` (Exa preferred, Tavily fallback)\n  - Browser: `src/tools/browser/` (Playwright-based web scraping)\n  - Skills: `src/skills/` (SKILL.md-based extensible workflows, e.g. DCF valuation)\n  - Utils: `src/utils/` (env, config, caching, token estimation, markdown tables)\n  - Evals: `src/evals/` (LangSmith evaluation runner with Ink UI)\n- Config: `.dexter/settings.json` (persisted model/provider selection)\n- Environment: `.env` (API keys; see `env.example`)\n- Scripts: `scripts/release.sh`\n\n## Build, Test, and Development Commands\n\n- Runtime: Bun (primary). Use `bun` for all commands.\n- Install deps: `bun install`\n- Run: `bun run start` or `bun run src/index.tsx`\n- Dev (watch mode): `bun run dev`\n- Type-check: `bun run typecheck`\n- Tests: `bun test`\n- Evals: `bun run src/evals/run.ts` (full) or `bun run src/evals/run.ts --sample 10` (sampled)\n- CI runs `bun run typecheck` and `bun test` on push/PR.\n\n## Coding Style & Conventions\n\n- Language: TypeScript (ESM, strict mode). JSX via React (Ink for CLI rendering).\n- Prefer strict typing; avoid `any`.\n- Keep files concise; extract helpers rather than duplicating code.\n- Add brief comments for tricky or non-obvious logic.\n- Do not add logging unless explicitly asked.\n- Do not create README or documentation files unless explicitly asked.\n\n## LLM Providers\n\n- Supported: OpenAI (default), Anthropic, Google, xAI (Grok), OpenRouter, Ollama (local).\n- Default model: `gpt-5.5`. Provider detection is prefix-based (`claude-` -> Anthropic, `gemini-` -> Google, etc.).\n- Fast models for lightweight tasks: see `FAST_MODELS` map in `src/model/llm.ts`.\n- Anthropic uses explicit `cache_control` on system prompt for prompt caching cost savings.\n- Users switch providers/models via `/model` command in the CLI.\n\n## Tools\n\n- `financial_search`: primary tool for all financial data queries (prices, metrics, filings). Delegates to multiple sub-tools internally.\n- `financial_metrics`: direct metric lookups (revenue, market cap, etc.).\n- `read_filings`: SEC filing reader for 10-K, 10-Q, 8-K documents.\n- `web_search`: general web search (Exa if `EXASEARCH_API_KEY` set, else Tavily if `TAVILY_API_KEY` set).\n- `browser`: Playwright-based web scraping for reading pages the agent discovers.\n- `skill`: invokes SKILL.md-defined workflows (e.g. DCF valuation). Each skill runs at most once per query.\n- Tool registry: `src/tools/registry.ts`. Tools are conditionally included based on env vars.\n\n## Skills\n\n- Skills live as `SKILL.md` files with YAML frontmatter (`name`, `description`) and markdown body (instructions).\n- Built-in skills: `src/skills/dcf/SKILL.md`.\n- Discovery: `src/skills/registry.ts` scans for SKILL.md files at startup.\n- Skills are exposed to the LLM as metadata in the system prompt; the LLM invokes them via the `skill` tool.\n\n## Agent Architecture\n\n- Agent loop: `src/agent/agent.ts`. Iterative tool-calling loop with configurable max iterations (default 10).\n- Scratchpad: `src/agent/scratchpad.ts`. Single source of truth for all tool results within a query.\n- Context management: Anthropic-style. Full tool results kept in context; oldest results cleared when token threshold exceeded.\n- Final answer: generated in a separate LLM call with full scratchpad context (no tools bound).\n- Events: agent yields typed events (`tool_start`, `tool_end`, `thinking`, `answer_start`, `done`, etc.) for real-time UI updates.\n\n## Environment Variables\n\n- LLM keys: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY`, `XAI_API_KEY`, `OPENROUTER_API_KEY`\n- Ollama: `OLLAMA_BASE_URL` (default `http://127.0.0.1:11434`)\n- Finance: `FINANCIAL_DATASETS_API_KEY`\n- Search: `EXASEARCH_API_KEY` (preferred), `TAVILY_API_KEY` (fallback)\n- Tracing: `LANGSMITH_API_KEY`, `LANGSMITH_ENDPOINT`, `LANGSMITH_PROJECT`, `LANGSMITH_TRACING`\n- Never commit `.env` files or real API keys.\n\n## Version & Release\n\n- Version format: SemVer `MAJOR.MINOR.PATCH`. Tag prefix: `v`.\n- Release script: `bash scripts/release.sh [version]` (defaults to today's date).\n- Release flow: bump version in `package.json`, create git tag, push tag, create GitHub release via `gh`.\n- Do not push or publish without user confirmation.\n\n## Testing\n\n- Framework: Bun's built-in test runner (primary), Jest config exists for legacy compatibility.\n- Tests colocated as `*.test.ts`.\n- Run `bun test` before pushing when you touch logic.\n\n## Security\n\n- API keys stored in `.env` (gitignored). Users can also enter keys interactively via the CLI.\n- Config stored in `.dexter/settings.json` (gitignored).\n- Never commit or expose real API keys, tokens, or credentials.\n","isInternal":false,"tokens":1455,"sizeBytes":5491},{"name":"sector-wacc.md","path":"src/skills/dcf/sector-wacc.md","rawUrl":"https://raw.githubusercontent.com/virattt/dexter/HEAD/src/skills/dcf/sector-wacc.md","title":"Dcf Skill","category":"anthropic-skill","format":"markdown","content":"# Sector WACC Adjustments\n\nUse these typical WACC ranges as starting points, then adjust based on company-specific factors.\n\n## Determining Company Sector\n\nUse `get_financials` with query `\"[TICKER] company facts\"` to retrieve the company's `sector`. Match the returned sector to the table below.\n\n## WACC by Sector\n\n| Sector | Typical WACC Range | Notes |\n|--------|-------------------|-------|\n| Communication Services | 8-10% | Mix of stable telecom and growth media |\n| Consumer Discretionary | 8-10% | Cyclical exposure |\n| Consumer Staples | 7-8% | Defensive, stable demand |\n| Energy | 9-11% | Commodity price exposure |\n| Financials | 8-10% | Leverage already in business model |\n| Health Care | 8-10% | Regulatory and pipeline risk |\n| Industrials | 8-9% | Moderate cyclicality |\n| Information Technology | 8-12% | Assess growth stage; higher for high-growth |\n| Materials | 8-10% | Cyclical, commodity exposure |\n| Real Estate | 7-9% | Interest rate sensitivity |\n| Utilities | 6-7% | Regulated, stable cash flows |\n\n## Adjustment Factors\n\nAdd to base WACC:\n- **High debt (D/E > 1.5)**: +1-2%\n- **Small cap (< $2B market cap)**: +1-2%\n- **Emerging markets exposure**: +1-3%\n- **Concentrated customer base**: +0.5-1%\n- **Regulatory uncertainty**: +0.5-1.5%\n\nSubtract from base WACC:\n- **Market leader with moat**: -0.5-1%\n- **Recurring revenue model**: -0.5-1%\n- **Investment grade credit rating**: -0.5%\n\n## Reasonableness Checks\n\n- WACC should typically be 2-4% below ROIC for value-creating companies\n- If calculated WACC > ROIC, the company may be destroying value\n- Compare to sector peers if available\n","isInternal":false,"tokens":452,"sizeBytes":1617},{"name":"SKILL.md","path":"src/skills/dcf/SKILL.md","rawUrl":"https://raw.githubusercontent.com/virattt/dexter/HEAD/src/skills/dcf/SKILL.md","title":"dcf-valuation","category":"anthropic-skill","format":"markdown","content":"---\nname: dcf-valuation\ndescription: Performs discounted cash flow (DCF) valuation analysis to estimate intrinsic value per share. Triggers when user asks for fair value, intrinsic value, DCF, valuation, \"what is X worth\", price target, undervalued/overvalued analysis, or wants to compare current price to fundamental value.\n---\n\n# DCF Valuation Skill\n\n## Workflow Checklist\n\nCopy and track progress:\n```\nDCF Analysis Progress:\n- [ ] Step 1: Gather financial data\n- [ ] Step 2: Calculate FCF growth rate\n- [ ] Step 3: Estimate discount rate (WACC)\n- [ ] Step 4: Project future cash flows (Years 1-5 + Terminal)\n- [ ] Step 5: Calculate present value and fair value per share\n- [ ] Step 6: Run sensitivity analysis\n- [ ] Step 7: Validate results\n- [ ] Step 8: Present results with caveats\n```\n\n## Step 1: Gather Financial Data\n\nCall the `get_financials` tool with these queries:\n\n### 1.1 Cash Flow History\n**Query:** `\"[TICKER] annual cash flow statements for the last 5 years\"`\n\n**Extract:** `free_cash_flow`, `net_cash_flow_from_operations`, `capital_expenditure`\n\n**Fallback:** If `free_cash_flow` missing, calculate: `net_cash_flow_from_operations - capital_expenditure`\n\n### 1.2 Financial Metrics\n**Query:** `\"[TICKER] financial metrics snapshot\"`\n\n**Extract:** `market_cap`, `enterprise_value`, `free_cash_flow_growth`, `revenue_growth`, `return_on_invested_capital`, `debt_to_equity`, `free_cash_flow_per_share`\n\n### 1.3 Balance Sheet\n**Query:** `\"[TICKER] latest balance sheet\"`\n\n**Extract:** `total_debt`, `cash_and_equivalents`, `current_investments`, `outstanding_shares`\n\n**Fallback:** If `current_investments` missing, use 0\n\n### 1.4 Current Price\nCall the `get_market_data` tool:\n\n**Query:** `\"[TICKER] price snapshot\"`\n\n**Extract:** `price`\n\n### 1.5 Company Facts\nCall the `get_financials` tool:\n\n**Query:** `\"[TICKER] company facts\"`\n\n**Extract:** `sector`, `industry`, `market_cap`\n\n**Use:** Determine appropriate WACC range from [sector-wacc.md](sector-wacc.md)\n\n## Step 2: Calculate FCF Growth Rate\n\nCalculate 5-year FCF CAGR from cash flow history.\n\n**Cross-validate with:** `free_cash_flow_growth` (YoY), `revenue_growth`\n\n**Growth rate selection:**\n- Stable FCF history → Use CAGR with 10-20% haircut\n- **Cap at 15%** (sustained higher growth is rare)\n\n## Step 3: Estimate Discount Rate (WACC)\n\n**Use the `sector` from company facts** to select the appropriate base WACC range from [sector-wacc.md](sector-wacc.md).\n\n**Default assumptions:**\n- Risk-free rate: 4%\n- Equity risk premium: 5-6%\n- Cost of debt: 5-6% pre-tax (~4% after-tax at 30% tax rate)\n\nCalculate WACC using `debt_to_equity` for capital structure weights.\n\n**Reasonableness check:** WACC should be 2-4% below `return_on_invested_capital` for value-creating companies.\n\n**Sector adjustments:** Apply adjustment factors from [sector-wacc.md](sector-wacc.md) based on company-specific characteristics.\n\n## Step 4: Project Future Cash Flows\n\n**Years 1-5:** Apply growth rate with 5% annual decay (multiply growth rate by 0.95, 0.90, 0.85, 0.80 for years 2-5). This reflects competitive dynamics.\n\n**Terminal value:** Use Gordon Growth Model with 2.5% terminal growth (GDP proxy).\n\n## Step 5: Calculate Present Value\n\nDiscount all FCFs → sum for Enterprise Value → subtract Net Debt → divide by `outstanding_shares` for fair value per share.\n\n## Step 6: Sensitivity Analysis\n\nCreate 3×3 matrix: WACC (base ±1%) vs terminal growth (2.0%, 2.5%, 3.0%).\n\n## Step 7: Validate Results\n\nBefore presenting, verify these sanity checks:\n\n1. **EV comparison**: Calculated EV should be within 30% of reported `enterprise_value`\n   - If off by >30%, revisit WACC or growth assumptions\n\n2. **Terminal value ratio**: Terminal value should be 50-80% of total EV for mature companies\n   - If >90%, growth rate may be too high\n   - If <40%, near-term projections may be aggressive\n\n3. **Per-share cross-check**: Compare to `free_cash_flow_per_share × 15-25` as rough sanity check\n\nIf validation fails, reconsider assumptions before presenting results.\n\n## Step 8: Output Format\n\nPresent a structured summary including:\n1. **Valuation Summary**: Current price vs. fair value, upside/downside percentage\n2. **Key Inputs Table**: All assumptions with their sources\n3. **Projected FCF Table**: 5-year projections with present values\n4. **Sensitivity Matrix**: 3×3 grid varying WACC (±1%) and terminal growth (2.0%, 2.5%, 3.0%)\n5. **Caveats**: Standard DCF limitations plus company-specific risks\n","frontmatter":{"name":"dcf-valuation","description":"Performs discounted cash flow (DCF) valuation analysis to estimate intrinsic value per share. Triggers when user asks for fair value, intrinsic value, DCF, valuation, \"what is X worth\", price target, undervalued/overvalued analysis, or wants to compare current price to fundamental value."},"isInternal":false,"tokens":1192,"sizeBytes":4469},{"name":"examples.md","path":"src/skills/write-memo/examples.md","rawUrl":"https://raw.githubusercontent.com/virattt/dexter/HEAD/src/skills/write-memo/examples.md","title":"Write-memo Skill","category":"anthropic-skill","format":"markdown","content":"# Example Memo (for tone calibration)\n\nThis is a worked example for `NFLX LONG · 12mo`. Use it to pattern-match tone, density, and structure when drafting. **Do not copy the numbers** — fetch fresh data via the tools for any actual memo.\n\nThe example is shown as the content that would fill the template slots, not the final HTML.\n\n---\n\n**Header strip values**\n- Ticker: NFLX\n- Company: Netflix, Inc.\n- Direction: LONG\n- Conviction: HIGH\n- Horizon: 12mo\n- Current price: $620\n- Base target: $785\n- Upside: +27%\n- Asymmetry: 2.4x\n- Prob-weighted return: +18%\n\n---\n\n**`{{variant_view}}`**\n\nConsensus models ad-tier as a single-digit revenue line for the next three years. We think it is a 20%+ contributor to '27 revenue and the primary multiple-rerate catalyst. The Street is anchored to subscription-only unit economics and has not updated for ad-tier ARPU running 30% above their first-year assumption.\n\n---\n\n**`{{thesis_bullets}}`** (HTML list items)\n\n- **Ad-tier reaches 18% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; at current adds and a 65% mix of new signups going to the ad tier, we model 51M ad-tier subs by end-'27. *Wrong if ad-tier mix of new signups falls below 50% for two consecutive quarters.*\n- **Ad-tier ARPU sustains $9+** — current ad CPMs of $35-45 imply $9-11 ARPU at 5 ad-min/hr inventory; management called out upfront commitments doubling YoY. *Wrong if disclosed ad ARPU prints below $8 in any quarterly disclosure.*\n- **Operating margin expands 600bps to 28% by '27** — content amortization peaks in '25 per management; incremental ad revenue is 70%+ margin. *Wrong if content spend grows above $20B in any year.*\n- **Multiple rerates from 28x to 35x as ad revenue mix exceeds 15%** — comparable transition (Spotify ad-tier, Roku) saw 25-40% multiple expansion when ad revenue crossed 15% of total. *Wrong if ad revenue stalls below 12% of total through '27.*\n\n---\n\n**`{{business_snapshot}}`**\n\nNetflix is a global subscription video streaming service with 270M paid memberships across 190+ countries. The company licenses and produces original content; \"we have one of the largest libraries of TV series and films, with content available in over 30 languages\" (10-K Item 1). Two membership tiers contribute differently: standard and premium subscriptions (~$15-23/mo) drive 92% of revenue today; the ad-supported tier (~$7/mo plus advertising) launched late '22 and is now the company's stated highest-growth tier. Unit economics differ: ad-tier subs carry lower subscription ARPU but ad revenue at ~70% incremental margin lifts blended contribution above the standard tier by year two of a sub's life.\n\n---\n\n**`{{whats_priced_in}}`**\n\nAt $620, NFLX trades at 28x consensus '26 EPS of $22.10. Consensus models 11% revenue growth and 23% operating margin in '27 — implying the Street is pricing in the subscription business compounding low-teens with modest margin expansion. Sellside ad-tier revenue estimates cluster around $4-5B for '27 (consensus mean $4.6B). Our '27 model puts ad revenue at $8.2B (+78% vs. consensus) on higher ad-tier sub adds and sustained ARPU. EPS divergence: our $29.50 vs. consensus $24.80, a +19% delta.\n\n---\n\n**`{{scenario_table}}`**\n\n| | Bear (20%) | Base (55%) | Bull (25%) |\n|---|---|---|---|\n| Revenue '27 | $42B | $52B | $61B |\n| Revenue growth | +6% | +14% | +20% |\n| EBIT margin | 22% | 28% | 32% |\n| EPS '27 | $19.50 | $29.50 | $38.20 |\n| Exit multiple | 22x | 28x | 35x |\n| Price target | $430 | $785 | $1,205 |\n| Return | -31% | +27% | +94% |\n\nProb-weighted return: +18% · Upside / downside: 2.4x\n\n---\n\n**`{{bull_narrative}}`**\n\nAd-tier inflects faster than we model. Disney+ pulls back on ad-tier pricing competition, leaving NFLX as the premium ad-supported inventory option for upfront buyers. Live programming (NFL, boxing, WWE) drives ad-tier mix of new signups above 70%, and ad CPMs sustain in the $40s as inventory stays scarce relative to demand. Content cost discipline holds — total content spend stays flat at $17B even as subs grow — and operating margin reaches 32% by '27. The Street rerates the stock to 35x as ad revenue crosses 20% of total, reclassifying NFLX from subscription business to dual-revenue media platform. EPS compounds 25%+ for three years.\n\n---\n\n**`{{base_narrative}}`**\n\nAd-tier grows roughly in line with current trajectory and reaches 50M+ subs by '27. ARPU holds at $9-10 as content investment in live and originals supports pricing. Content amortization peaks in '25 and rolls off, lifting operating margin to 28% by '27 even with $18-19B of content spend. Subscription business compounds high single digits globally with the bulk of net adds from APAC and LatAm at lower ARPU. The Street partially rerates the stock as ad mix exceeds 15%, multiple expands to 28x — in line with current level but on materially higher EPS.\n\n---\n\n**`{{bear_narrative}}`**\n\nDisney+ and Amazon's Prime Video ad tier compete aggressively on price; Disney+ ad-tier subs cross 100M globally by end-'26 and Amazon bundles ad-supported streaming into Prime at no incremental cost. Ad-tier CPMs compress 25% to the high $20s as inventory floods the market and brand advertisers consolidate spend on retail media platforms (Amazon, Walmart Connect) rather than streaming. NFLX ad revenue stalls at $3-3.5B for '27 vs. street $4.6B. Content spend creeps to $20B as the live programming push (NFL, boxing) proves more expensive to renew than initial deals suggested. Operating margin compresses to 22% as fixed content costs deleverage on slower revenue growth. The multiple compresses to 22x — Disney's current multiple — as the market reclassifies NFLX as a mature subscription business with declining incremental returns on content spend. Stock retraces to the low $400s.\n\n---\n\n**`{{catalysts_table}}`**\n\n| Event | Date | Expected Impact |\n|---|---|---|\n| Q2 '26 earnings — ad-tier sub disclosure | Jul '26 | Ad-tier sub count vs. our 45M target |\n| Upfront ad commitments | Apr-May '26 | Total committed dollars; vs. $1B+ '25 baseline |\n| NFL Christmas Day games viewership | Dec '26 | Concurrent viewers; ad-load testing |\n| FY27 guidance | Jan '27 | First explicit ad revenue guide |\n\n---\n\n**`{{risks_table}}`**\n\n| Risk | Mitigant | Tripwire |\n|---|---|---|\n| Ad-tier ARPU compression | Premium inventory (live sports) supports CPMs | Disclosed ad ARPU < $8 in any quarter |\n| Content cost re-acceleration | Management explicit guide of $17B '26 cap | Content spend > $19B in any year |\n| Competitive ad-tier launch from Amazon | Amazon ad-tier already live; share gains modest | NFLX ad-tier net adds < 5M in any quarter |\n| Subscription growth stalls in APAC | Pricing flexibility, mobile-only tier | Net adds < 4M globally in two consecutive quarters |\n| Multiple compression on rate environment | EPS growth outpaces multiple compression risk | Multiple < 24x with no operational miss |\n\n---\n\n**`{{position_management}}`**\n\nSuggested sizing: 4% NAV — high conviction × 2.4x asymmetry. Entry: current ($620) or scale-in below $590 on multiple compression. Stop / reduce: trim 50% if ad-tier ARPU prints below $8 in any quarter; full exit if content spend guide steps above $19B.\n\n---\n\n**`{{monitoring_kpis}}`**\n\n1. Ad-tier subscriber count (quarterly disclosure)\n2. Ad-tier ARPU or implied ARPU (calc: ad revenue / avg ad-tier subs)\n3. Content cash spend YTD vs. annual guide\n4. Operating margin (quarterly) — trajectory to 28% by '27\n5. Upfront commitment dollars (annual) — vs. prior year\n\n---\n\n## Why this example works\n\n- **Variant view is specific and contradictable.** It names a number (20%+ revenue contribution by '27) and a divergence (Street models single-digit). A PM can disagree with it precisely.\n- **Every thesis bullet has a \"wrong if\".** None of them are unfalsifiable platitudes.\n- **Bear case names competitors and mechanisms.** Disney+, Amazon, retail media, NFL renewal costs. Not \"competition intensifies\".\n- **Tripwires are observable.** \"Disclosed ad ARPU < $8 in any quarter\" is a data point the analyst can monitor; \"macro deteriorates\" is not.\n- **No padding.** No founding history, no \"in an ever-evolving streaming landscape\", no closing summary paragraph.\n\nWhen you draft a real memo, match this density and specificity, not the surface aesthetics. The aesthetics come from the template; the substance comes from the thinking.\n","isInternal":false,"tokens":2142,"sizeBytes":8411},{"name":"memo-style.md","path":"src/skills/write-memo/memo-style.md","rawUrl":"https://raw.githubusercontent.com/virattt/dexter/HEAD/src/skills/write-memo/memo-style.md","title":"Write-memo Skill","category":"anthropic-skill","format":"markdown","content":"# Investment Memo Style Guide\n\nRules the memo must follow. These mirror buyside writing conventions and avoid the tells that mark a document as AI-generated.\n\n## Voice\n\n- **First person plural** (\"we believe\", \"our base case\") — that's how a buyside team writes.\n- **Direct, not hedging.** \"Margins compress 200bps in '27\" beats \"margins could potentially face some pressure in 2027\".\n- **Confidence calibrated by evidence.** State the view, then state the evidence. Hedge once with a \"wrong if\" — not in every sentence.\n- **One sentence per idea** in narrative sections. Long sentences with comma chains and parentheticals signal AI drift.\n\n## Banned vocabulary\n\nNever use these words. They are AI-generated tells:\n\n- \"delve\", \"delves\", \"delving\"\n- \"leverage\" as a verb (\"we leverage X to do Y\")\n- \"robust\", \"comprehensive\", \"holistic\", \"seamless\"\n- \"navigate the landscape\", \"navigate the challenges\"\n- \"in today's fast-paced\", \"in an ever-evolving\"\n- \"stands out\", \"sets itself apart\"\n- \"deep dive\", \"unpack\", \"double-click\"\n- \"moreover\", \"furthermore\", \"additionally\" (use a new sentence)\n- \"It's worth noting that\" (just say the thing)\n\n## Banned constructions\n\n- **Tricolons** — three-item lists for rhythmic effect (\"fast, scalable, and reliable\"). One AI tell.\n- **Em dash abuse** — at most one em dash per paragraph. Prefer periods or commas.\n- **\"Not just X but Y\"** — overused contrast structure.\n- **Generic closing summaries** — \"In conclusion, this is a compelling opportunity that...\" Don't write these. End on a specific claim or a tripwire.\n- **Hedge stacking** — \"could potentially possibly maybe\". Pick one or zero.\n\n## Numbers\n\n- **Quantify everything.** \"Margins expanded 380bps\" not \"margins improved meaningfully\".\n- **Percentages with explicit base.** \"Revenue grew 28% YoY\" not \"revenue saw strong growth\".\n- **Multiples in line.** \"Trading at 18x FY26 EPS\" not \"trading at attractive multiples\".\n- **Don't invent numbers.** If you don't have it from a tool call, write \"not disclosed\" or omit the line. Never fabricate consensus figures.\n\n## Thesis bullet format\n\nEvery thesis bullet must be a complete falsifiable claim:\n\n> **[Specific claim with a number]** — [Evidence with a specific number, ideally citing the data point]. *Wrong if [specific observable would happen].*\n\nGood:\n> **Ad-tier reaches 15% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; trajectory implies 15% mix at constant adds. *Wrong if ad-tier ARPU compresses below $8 due to inventory glut.*\n\nBad (vague claim, no falsifier):\n> **Strong product-market fit in ad tier** — Management has emphasized this is a key growth area going forward.\n\n## Bear case requirements\n\nThe bear paragraph is the highest-stakes paragraph in the memo. Rules:\n\n1. **Steelmanned.** Written as if you actually believed it. If you can't, you don't understand the trade.\n2. **Specific competitor / customer / regulator named.** Not \"competition intensifies\" — name the company and the product.\n3. **Coherent world, not a list.** The bear case is a story where the thesis is wrong. Connect the dots.\n4. **Read the bull paragraph and the bear paragraph back to back.** If bear reads weaker, rewrite. This is the single most common failure mode.\n\n## Tripwires\n\nEvery risk row in the risks table must have a tripwire. A tripwire is **an observable data point that would invalidate the thesis** within the holding period.\n\nGood tripwires:\n- \"Q3 ad-tier ARPU prints below $8\"\n- \"Top customer announces in-sourcing on Q2 call\"\n- \"Gross margin contracts more than 150bps in any quarter\"\n- \"Insider sales exceed $50M in any rolling 90-day window\"\n\nBad tripwires (not observable / not actionable):\n- \"Macro deteriorates\"\n- \"Competition increases\"\n- \"Sentiment shifts negatively\"\n\n## What to pull from filings\n\nWhen summarizing the business, pull verbatim from the 10-K Item 1 where the company's own language is tighter than rewriting it. Quote with quotes and source: `\"[exact phrase]\" (10-K Item 1)`.\n\nFor risks, prefer pulling from Item 1A and the company's own disclosure language — it's the most defensible risk framing in the memo.\n\n## Closing the memo\n\nMemos do not need a \"conclusion\" section. The header already states the recommendation; the thesis bullets state the view; the scenarios state the math. A closing paragraph that restates these is padding.\n\nThe last section in the body is **Monitoring KPIs** — the specific metrics that confirm or kill the thesis. That's the right note to end on: what to watch.\n","isInternal":false,"tokens":1105,"sizeBytes":4539},{"name":"SKILL.md","path":"src/skills/write-memo/SKILL.md","rawUrl":"https://raw.githubusercontent.com/virattt/dexter/HEAD/src/skills/write-memo/SKILL.md","title":"write-memo","category":"anthropic-skill","format":"markdown","content":"---\nname: write-memo\ndescription: Drafts a professional investment memo (HTML output) for a long or short equity idea, structured the way a hedge fund analyst would present a thesis to a PM. Triggers when the user asks to \"write a memo\", \"draft an investment memo\", \"write up a thesis\", \"pitch this stock\", \"memo on [ticker]\", \"long writeup\", \"short writeup\", or similar. Produces a 1-page HTML file at .dexter/memos/.\n---\n\n# Write Investment Memo Skill\n\nProduces a buyside-quality investment memo as a self-contained HTML file. The memo is opinionated and falsifiable — it leads with a variant view and steelmans the bear case. The output is the deliverable; the chat response is just a header summary plus the file path.\n\n## Workflow Checklist\n\nCopy and track progress:\n```\nInvestment Memo Progress:\n- [ ] Step 1: Frame the trade (direction, horizon, variant view)\n- [ ] Step 2: Gather data (financials, market, filings)\n- [ ] Step 3: Build Bear / Base / Bull scenarios\n- [ ] Step 4: Optional DCF anchor for base case\n- [ ] Step 5: Draft memo content (fill all slots)\n- [ ] Step 6: Self-critique pass\n- [ ] Step 7: Render HTML to .dexter/memos/\n- [ ] Step 8: Report header summary + file path\n```\n\n## Step 1: Frame the Trade\n\nConfirm or ask for the following before drafting:\n\n- **Ticker** (required)\n- **Direction**: long or short (required)\n- **Horizon**: 3mo / 6mo / 12mo / 2yr+ (default 12mo if not specified)\n- **Conviction**: high / medium / low (default medium)\n- **Variant view**: one sentence — what the analyst sees that consensus doesn't\n\n**If the user does not provide a variant view**: do not ask repeatedly. Gather data in Step 2 first, then derive a candidate variant view from where your model meaningfully diverges from consensus (e.g., \"our '27 EPS is $X vs consensus $Y because [driver]\"). Present it as a draft and let the analyst accept, refine, or replace before you proceed to Step 5.\n\n## Step 2: Gather Data (Parallel)\n\nIssue these tool calls in parallel:\n\n### 2.1 Financials\nCall `get_financials`:\n- `\"[TICKER] annual income statements last 5 years\"` — revenue, operating income, net income, EPS, margins\n- `\"[TICKER] annual cash flow statements last 5 years\"` — operating CF, capex, FCF\n- `\"[TICKER] latest balance sheet\"` — debt, cash, shares outstanding\n- `\"[TICKER] financial metrics snapshot\"` — P/E, EV, ROIC, FCF growth, debt/equity, margins\n- `\"[TICKER] segmented financials\"` — segment revenue, segment margins (if multi-segment)\n- `\"[TICKER] earnings history last 8 quarters\"` — beats/misses, surprises\n- `\"[TICKER] company facts\"` — sector, industry, market cap\n- `\"[TICKER] KPI guidance\"` and `\"[TICKER] KPI metrics\"` — management-provided KPIs and guidance\n\n### 2.2 Market & Ownership\nCall `get_market_data`:\n- `\"[TICKER] price snapshot\"` — current price, 52-week range, market cap\n- `\"[TICKER] historical prices last 12 months\"` — for return / multiple compression context\n- `\"[TICKER] insider trades last 6 months\"` — recent buys/sells, dollar amounts\n- `\"[TICKER] institutional holdings\"` — top holders, recent additions / reductions\n- `\"[TICKER] news last 30 days\"` — recent material events\n\n### 2.3 Filings\nCall `read_filings`:\n- Most recent 10-K Item 1 (Business) — for business snapshot language\n- Most recent 10-K Item 1A (Risk Factors) — to source risks from the company itself\n- Most recent 10-Q — recent quarterly trajectory\n\n### 2.4 Memory (optional)\nCall `memory_search` with the ticker — surfaces any prior notes, prior memos, or user-provided constraints (e.g., risk tolerance, sector exposure already in book).\n\n### 2.5 Sentiment (optional, only if time-sensitive)\nCall `x_search` for recent material chatter on the ticker. Skip if the thesis is fundamental and not catalyst-driven this week.\n\n## Step 3: Build Scenarios\n\nConstruct Bear / Base / Bull scenarios. Each scenario is **driver-based**, not a single number pulled from the air.\n\nFor each scenario specify:\n- **Revenue growth** (forecast year, 2-3 years out)\n- **EBIT / operating margin** at that point\n- **Exit multiple** (P/E, EV/EBITDA, or EV/Sales as appropriate for the sector)\n- **Probability weight** (the three must sum to 100%)\n- **Price target** (derived from the above)\n- **Return** vs. current price (with sign)\n\nThen compute:\n- **Probability-weighted return** = sum(prob × return) across scenarios\n- **Upside / downside ratio** = |bull return| / |bear return|\n\n**Asymmetry check**: if upside/downside < 2x, flag this prominently. A weak-asymmetry setup is a coin flip, not a trade. Either revise the scenarios honestly, or note the weak asymmetry in the memo (do not hide it).\n\n## Step 4: Optional DCF Anchor\n\nFor base case, optionally invoke the `dcf-valuation` skill via the `skill` tool to produce an intrinsic value anchor. Use it as a cross-check against your base-case price target, not as a replacement.\n\n## Step 5: Draft Memo Content\n\nRead the template and style guide:\n- [memo-template.html](memo-template.html)\n- [memo-style.md](memo-style.md)\n- [examples.md](examples.md) — pattern-match tone and density\n\nFill every slot. Slots are listed in the template — do not skip any. Slot-specific guidance:\n\n### `{{variant_view}}`\nThree sentences max. Lead with the divergence from consensus: *what we see, why we think it, why the market hasn't priced it*. If the user did not provide one, this is where your derived candidate goes.\n\n### `{{thesis_bullets}}`\n3-5 bullets, each in this format:\n> **[Claim]** — [Evidence with a specific number]. *Wrong if [observable falsifier].*\n\nExample:\n> **Ad-tier reaches 15% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; trajectory implies 15% mix at constant adds. *Wrong if ad-tier ARPU compresses below $8 due to inventory glut.*\n\nEach bullet must be **falsifiable**. No \"great management\", \"strong moat\", \"wide TAM\" without a specific operational metric behind it.\n\n### `{{business_snapshot}}`\n4-5 lines max. What they sell, how they make money, segment mix, unit economics that matter for the thesis. **No founding-year boilerplate.** Pull verbatim from the 10-K Item 1 where it tightens the language.\n\n### `{{whats_priced_in}}`\nCurrent multiple, implied growth or margin assumption embedded in that multiple, sellside consensus numbers (revenue, EPS for FY+1 and FY+2). Then one sentence on where your model diverges and by how much.\n\n### `{{scenario_table}}`\nRender as an HTML table. Columns: Bear / Base / Bull. Rows: Probability, Revenue growth (FY27), EBIT margin (FY27), Exit multiple, Price target, Return. Color returns: positive `class=\"pos\"`, negative `class=\"neg\"`.\n\n### `{{bull_narrative}}`, `{{base_narrative}}`, `{{bear_narrative}}`\nOne paragraph each (3-5 sentences). Each is a *coherent world*, not a list of factors:\n- **Bull**: what has to be true. Specific operational wins that compound. Tied to evidence we'd see in quarterly data.\n- **Base**: the thesis playing out as written.\n- **Bear**: steelmanned — written as if you believed it. Specific competitive losses, customer concentration risk materializing, multiple compression to a lower peer group. **If the bear paragraph reads weaker than the bull paragraph, rewrite it.**\n\n### `{{catalysts_table}}`\nTable with columns: Event, Date / Quarter, Expected Impact. 3-5 entries. Dates should be specific (Q3 '26, Aug '26 earnings, Investor Day Nov '26).\n\n### `{{risks_table}}`\nTable with columns: Risk, Mitigant, Tripwire. The tripwire is the **observable data point that would invalidate the thesis** (e.g., \"Q3 ad-tier ARPU prints below $8\", \"top customer renewal pushed past Q4\"). Tripwires distinguish a hedge fund memo from a sellside report.\n\n### `{{position_management}}`\nThree short lines: suggested sizing (% NAV) anchored to conviction × asymmetry; entry price (current or limit); stop level or scale-out trigger.\n\n### `{{monitoring_kpis}}`\n3-5 KPIs to track quarterly. These are the metrics that confirm or kill the thesis — not generic ones (revenue growth, EPS) but specific ones tied to your variant view.\n\n## Step 6: Self-Critique Pass (Mandatory)\n\nBefore rendering, verify every check. If any fail, revise the relevant section before continuing.\n\n1. **Variant view is actually variant.** Not a restatement of consensus dressed up as a view. The test: can you point to specific sellside notes / consensus numbers your view contradicts?\n2. **Every thesis bullet is falsifiable.** Each has a \"wrong if\" clause naming a specific observable.\n3. **Numbers behind every adjective.** No \"strong growth\" without the bps / %. No \"expanding margins\" without the basis point delta.\n4. **Bear case is steelmanned.** Read the bear paragraph aloud. If it reads weaker than the bull, rewrite.\n5. **Asymmetry ≥ 2x.** If not, the memo flags this in the header rather than hiding it.\n6. **Probability weights sum to 100%.**\n7. **Tripwires are observable.** Each risk has a data point an analyst could watch for, not a vibe.\n\n## Step 7: Render HTML\n\n1. Read `memo-template.html` via `read_file`\n2. Replace every `{{slot}}` placeholder with the content you drafted\n3. Set `{{date}}` to today's date in YYYY-MM-DD format\n4. Set `{{analyst}}` from memory if known, otherwise blank\n5. Write to `.dexter/memos/[TICKER]_[DIRECTION]_[YYYY-MM-DD].html` via `write_file`\n   - Direction is `LONG` or `SHORT` (uppercase)\n   - Example: `.dexter/memos/NFLX_LONG_2026-05-24.html`\n6. **Only** write a `.md` source file if the user explicitly requested one\n\nThe path uses forward slashes. The `write_file` tool will create the `.dexter/memos/` directory if it does not exist.\n\n## Step 8: Report to Chat\n\nFinal chat response should be exactly this format and nothing more:\n\n```\n[TICKER] · [LONG/SHORT] · Target $X (+Y% / -Y%) · Asymmetry [N.Nx] · [Conviction]\n\nMemo saved to .dexter/memos/[FILENAME].html\nOpen with: open .dexter/memos/[FILENAME].html\n```\n\nDo not paste the full memo content into the chat. The file is the deliverable. The chat output is a scannable header.\n\n## Critical Don'ts\n\n- Do not paste the full memo as a chat response in addition to writing the file\n- Do not write a `.md` file alongside unless explicitly requested\n- Do not include charts, sparklines, scenario bars, or any visual element beyond tables\n- Do not add emoji anywhere — not in the memo, not in the chat response\n- Do not include a prominent \"AI-generated\" footer or branding\n- Do not skip the self-critique pass in Step 6\n- Do not invent consensus numbers — if you do not have them from a tool call, say so in the memo\n","frontmatter":{"name":"write-memo","description":"Drafts a professional investment memo (HTML output) for a long or short equity idea, structured the way a hedge fund analyst would present a thesis to a PM. Triggers when the user asks to \"write a memo\", \"draft an investment memo\", \"write up a thesis\", \"pitch this stock\", \"memo on [ticker]\", \"long writeup\", \"short writeup\", or similar. Produces a 1-page HTML file at .dexter/memos/."},"isInternal":false,"tokens":2703,"sizeBytes":10524},{"name":"SKILL.md","path":"src/skills/x-research/SKILL.md","rawUrl":"https://raw.githubusercontent.com/virattt/dexter/HEAD/src/skills/x-research/SKILL.md","title":"x-research","category":"anthropic-skill","format":"markdown","content":"---\nname: x-research\ndescription: >\n  X/Twitter public sentiment research. Searches X for real-time perspectives,\n  market sentiment, expert opinions, breaking news, and community discourse.\n  Use when: user asks \"what are people saying about\", \"X/Twitter sentiment\",\n  \"check X for\", \"search twitter for\", \"what's CT saying about\", or wants\n  public opinion on a stock, sector, company, or market event.\n---\n\n# X Research Skill\n\nAgentic research over X/Twitter using the `x_search` tool. Decompose the\nresearch question into targeted searches, iterate to refine signal, and\nsynthesize into a sourced sentiment briefing.\n\n## Research Loop\n\n### 1. Decompose into Queries\n\nTurn the research question into 3–5 targeted queries using X operators:\n\n- **Core query**: Direct keywords or `$TICKER` cashtag\n- **Expert voices**: `from:username` for known analysts or accounts\n- **Bearish signal**: keywords like `(overvalued OR bubble OR risk OR concern)`\n- **Bullish signal**: keywords like `(bullish OR upside OR catalyst OR beat)`\n- **News/links**: add `has:links` to surface tweets with sources\n- **Noise reduction**: `-is:reply` to focus on original posts; `-airdrop -giveaway` for crypto topics\n\n### 2. Execute Searches\n\nUse the `x_search` tool with `command: \"search\"`. For each query:\n\n- Start with `sort: \"likes\"` and `limit: 15` to surface highest-signal tweets\n- Add `min_likes: 5` or higher to filter noise for broad topics\n- Use `since: \"1d\"` or `\"7d\"` depending on how time-sensitive the topic is\n- If a query returns too much noise, narrow with more operators or raise `min_likes`\n- If too few results, broaden with `OR` terms or remove restrictive operators\n\n### 3. Check Key Accounts (Optional)\n\nFor well-known analysts, fund managers, or company executives, use\n`command: \"profile\"` to see their recent posts directly.\n\n### 4. Follow Threads (Optional)\n\nWhen a high-engagement tweet appears to be a thread starter, use\n`command: \"thread\"` with the tweet ID to get full context.\n\n### 5. Synthesize\n\nGroup findings by theme (bullish, bearish, neutral, news/catalysts):\n\n```\n### [Theme]\n\n[1–2 sentence summary of the theme]\n\n- @username: \"[key quote]\" — [likes]♥ [Tweet](url)\n- @username2: \"[another perspective]\" — [likes]♥ [Tweet](url)\n```\n\nEnd with an **Overall Sentiment** paragraph: predominant tone (bullish/bearish/\nmixed/neutral), confidence level, and any notable divergence between retail and\ninstitutional voices.\n\n## Refinement Heuristics\n\n| Problem | Fix |\n|---|---|\n| Too much noise | Raise `min_likes`, add `-is:reply`, narrow keywords |\n| Too few results | Broaden with `OR`, remove restrictive operators |\n| Crypto spam | Add `-airdrop -giveaway -whitelist` |\n| Want expert takes only | Use `from:` or `min_likes: 50` |\n| Want substance over hot takes | Add `has:links` |\n\n## Output Format\n\nPresent a structured briefing:\n\n1. **Query Summary**: what was searched and time window\n2. **Sentiment Themes**: grouped findings with sourced quotes and tweet links\n3. **Overall Sentiment**: tone, confidence, key voices\n4. **Caveats**: X sentiment is not a reliable predictor; sample bias toward vocal minorities; last-7-days window only\n","frontmatter":{"name":"x-research","description":"X/Twitter public sentiment research. Searches X for real-time perspectives, market sentiment, expert opinions, breaking news, and community discourse. Use when: user asks \"what are people saying about\", \"X/Twitter sentiment\", \"check X for\", \"search twitter for\", \"what's CT saying about\", or wants public opinion on a stock, sector, company, or market event.\n"},"isInternal":false,"tokens":782,"sizeBytes":3165}],"systemPromptSnippet":"<yakaai_skills repo=\"virattt/dexter\">\n<!-- File: AGENTS.md (Tokens: ~1455 | Category: root-instruction) -->\n# Repository Guidelines\n\n- Repo: https://github.com/virattt/dexter\n- Dexter is a CLI-based AI agent for deep financial research, built with TypeScript, Ink (React for CLI), and LangChain.\n\n## Project Structure\n\n- Source code: `src/`\n  - Agent core: `src/agent/` (agent loop, prompts, scratchpad, token counting, types)\n  - CLI interface: `src/cli.tsx` (Ink/React), entry point: `src/index.tsx`\n  - Components: `src/components/` (Ink UI components)\n  - Hooks: `src/hooks/` (React hooks for agent runner, model selection, input history)\n  - Model/LLM: `src/model/llm.ts` (multi-provider LLM abstraction)\n  - Tools: `src/tools/` (financial search, web search, browser, skill tool)\n  - Tool descriptions: `src/tools/descriptions/` (rich descriptions injected into system prompt)\n  - Finance tools: `src/tools/finance/` (prices, fundamentals, filings, insider trades, etc.)\n  - Search tools: `src/tools/search/` (Exa preferred, Tavily fallback)\n  - Browser: `src/tools/browser/` (Playwright-based web scraping)\n  - Skills: `src/skills/` (SKILL.md-based extensible workflows, e.g. DCF valuation)\n  - Utils: `src/utils/` (env, config, caching, token estimation, markdown tables)\n  - Evals: `src/evals/` (LangSmith evaluation runner with Ink UI)\n- Config: `.dexter/settings.json` (persisted model/provider selection)\n- Environment: `.env` (API keys; see `env.example`)\n- Scripts: `scripts/release.sh`\n\n## Build, Test, and Development Commands\n\n- Runtime: Bun (primary). Use `bun` for all commands.\n- Install deps: `bun install`\n- Run: `bun run start` or `bun run src/index.tsx`\n- Dev (watch mode): `bun run dev`\n- Type-check: `bun run typecheck`\n- Tests: `bun test`\n- Evals: `bun run src/evals/run.ts` (full) or `bun run src/evals/run.ts --sample 10` (sampled)\n- CI runs `bun run typecheck` and `bun test` on push/PR.\n\n## Coding Style & Conventions\n\n- Language: TypeScript (ESM, strict mode). JSX via React (Ink for CLI rendering).\n- Prefer strict typing; avoid `any`.\n- Keep files concise; extract helpers rather than duplicating code.\n- Add brief comments for tricky or non-obvious logic.\n- Do not add logging unless explicitly asked.\n- Do not create README or documentation files unless explicitly asked.\n\n## LLM Providers\n\n- Supported: OpenAI (default), Anthropic, Google, xAI (Grok), OpenRouter, Ollama (local).\n- Default model: `gpt-5.5`. Provider detection is prefix-based (`claude-` -> Anthropic, `gemini-` -> Google, etc.).\n- Fast models for lightweight tasks: see `FAST_MODELS` map in `src/model/llm.ts`.\n- Anthropic uses explicit `cache_control` on system prompt for prompt caching cost savings.\n- Users switch providers/models via `/model` command in the CLI.\n\n## Tools\n\n- `financial_search`: primary tool for all financial data queries (prices, metrics, filings). Delegates to multiple sub-tools internally.\n- `financial_metrics`: direct metric lookups (revenue, market cap, etc.).\n- `read_filings`: SEC filing reader for 10-K, 10-Q, 8-K documents.\n- `web_search`: general web search (Exa if `EXASEARCH_API_KEY` set, else Tavily if `TAVILY_API_KEY` set).\n- `browser`: Playwright-based web scraping for reading pages the agent discovers.\n- `skill`: invokes SKILL.md-defined workflows (e.g. DCF valuation). Each skill runs at most once per query.\n- Tool registry: `src/tools/registry.ts`. Tools are conditionally included based on env vars.\n\n## Skills\n\n- Skills live as `SKILL.md` files with YAML frontmatter (`name`, `description`) and markdown body (instructions).\n- Built-in skills: `src/skills/dcf/SKILL.md`.\n- Discovery: `src/skills/registry.ts` scans for SKILL.md files at startup.\n- Skills are exposed to the LLM as metadata in the system prompt; the LLM invokes them via the `skill` tool.\n\n## Agent Architecture\n\n- Agent loop: `src/agent/agent.ts`. Iterative tool-calling loop with configurable max iterations (default 10).\n- Scratchpad: `src/agent/scratchpad.ts`. Single source of truth for all tool results within a query.\n- Context management: Anthropic-style. Full tool results kept in context; oldest results cleared when token threshold exceeded.\n- Final answer: generated in a separate LLM call with full scratchpad context (no tools bound).\n- Events: agent yields typed events (`tool_start`, `tool_end`, `thinking`, `answer_start`, `done`, etc.) for real-time UI updates.\n\n## Environment Variables\n\n- LLM keys: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY`, `XAI_API_KEY`, `OPENROUTER_API_KEY`\n- Ollama: `OLLAMA_BASE_URL` (default `http://127.0.0.1:11434`)\n- Finance: `FINANCIAL_DATASETS_API_KEY`\n- Search: `EXASEARCH_API_KEY` (preferred), `TAVILY_API_KEY` (fallback)\n- Tracing: `LANGSMITH_API_KEY`, `LANGSMITH_ENDPOINT`, `LANGSMITH_PROJECT`, `LANGSMITH_TRACING`\n- Never commit `.env` files or real API keys.\n\n## Version & Release\n\n- Version format: SemVer `MAJOR.MINOR.PATCH`. Tag prefix: `v`.\n- Release script: `bash scripts/release.sh [version]` (defaults to today's date).\n- Release flow: bump version in `package.json`, create git tag, push tag, create GitHub release via `gh`.\n- Do not push or publish without user confirmation.\n\n## Testing\n\n- Framework: Bun's built-in test runner (primary), Jest config exists for legacy compatibility.\n- Tests colocated as `*.test.ts`.\n- Run `bun test` before pushing when you touch logic.\n\n## Security\n\n- API keys stored in `.env` (gitignored). Users can also enter keys interactively via the CLI.\n- Config stored in `.dexter/settings.json` (gitignored).\n- Never commit or expose real API keys, tokens, or credentials.\n\n<!-- File: src/skills/dcf/sector-wacc.md (Tokens: ~452 | Category: anthropic-skill) -->\n# Sector WACC Adjustments\n\nUse these typical WACC ranges as starting points, then adjust based on company-specific factors.\n\n## Determining Company Sector\n\nUse `get_financials` with query `\"[TICKER] company facts\"` to retrieve the company's `sector`. Match the returned sector to the table below.\n\n## WACC by Sector\n\n| Sector | Typical WACC Range | Notes |\n|--------|-------------------|-------|\n| Communication Services | 8-10% | Mix of stable telecom and growth media |\n| Consumer Discretionary | 8-10% | Cyclical exposure |\n| Consumer Staples | 7-8% | Defensive, stable demand |\n| Energy | 9-11% | Commodity price exposure |\n| Financials | 8-10% | Leverage already in business model |\n| Health Care | 8-10% | Regulatory and pipeline risk |\n| Industrials | 8-9% | Moderate cyclicality |\n| Information Technology | 8-12% | Assess growth stage; higher for high-growth |\n| Materials | 8-10% | Cyclical, commodity exposure |\n| Real Estate | 7-9% | Interest rate sensitivity |\n| Utilities | 6-7% | Regulated, stable cash flows |\n\n## Adjustment Factors\n\nAdd to base WACC:\n- **High debt (D/E > 1.5)**: +1-2%\n- **Small cap (< $2B market cap)**: +1-2%\n- **Emerging markets exposure**: +1-3%\n- **Concentrated customer base**: +0.5-1%\n- **Regulatory uncertainty**: +0.5-1.5%\n\nSubtract from base WACC:\n- **Market leader with moat**: -0.5-1%\n- **Recurring revenue model**: -0.5-1%\n- **Investment grade credit rating**: -0.5%\n\n## Reasonableness Checks\n\n- WACC should typically be 2-4% below ROIC for value-creating companies\n- If calculated WACC > ROIC, the company may be destroying value\n- Compare to sector peers if available\n\n<!-- File: src/skills/dcf/SKILL.md (Tokens: ~1192 | Category: anthropic-skill) -->\n---\nname: dcf-valuation\ndescription: Performs discounted cash flow (DCF) valuation analysis to estimate intrinsic value per share. Triggers when user asks for fair value, intrinsic value, DCF, valuation, \"what is X worth\", price target, undervalued/overvalued analysis, or wants to compare current price to fundamental value.\n---\n\n# DCF Valuation Skill\n\n## Workflow Checklist\n\nCopy and track progress:\n```\nDCF Analysis Progress:\n- [ ] Step 1: Gather financial data\n- [ ] Step 2: Calculate FCF growth rate\n- [ ] Step 3: Estimate discount rate (WACC)\n- [ ] Step 4: Project future cash flows (Years 1-5 + Terminal)\n- [ ] Step 5: Calculate present value and fair value per share\n- [ ] Step 6: Run sensitivity analysis\n- [ ] Step 7: Validate results\n- [ ] Step 8: Present results with caveats\n```\n\n## Step 1: Gather Financial Data\n\nCall the `get_financials` tool with these queries:\n\n### 1.1 Cash Flow History\n**Query:** `\"[TICKER] annual cash flow statements for the last 5 years\"`\n\n**Extract:** `free_cash_flow`, `net_cash_flow_from_operations`, `capital_expenditure`\n\n**Fallback:** If `free_cash_flow` missing, calculate: `net_cash_flow_from_operations - capital_expenditure`\n\n### 1.2 Financial Metrics\n**Query:** `\"[TICKER] financial metrics snapshot\"`\n\n**Extract:** `market_cap`, `enterprise_value`, `free_cash_flow_growth`, `revenue_growth`, `return_on_invested_capital`, `debt_to_equity`, `free_cash_flow_per_share`\n\n### 1.3 Balance Sheet\n**Query:** `\"[TICKER] latest balance sheet\"`\n\n**Extract:** `total_debt`, `cash_and_equivalents`, `current_investments`, `outstanding_shares`\n\n**Fallback:** If `current_investments` missing, use 0\n\n### 1.4 Current Price\nCall the `get_market_data` tool:\n\n**Query:** `\"[TICKER] price snapshot\"`\n\n**Extract:** `price`\n\n### 1.5 Company Facts\nCall the `get_financials` tool:\n\n**Query:** `\"[TICKER] company facts\"`\n\n**Extract:** `sector`, `industry`, `market_cap`\n\n**Use:** Determine appropriate WACC range from [sector-wacc.md](sector-wacc.md)\n\n## Step 2: Calculate FCF Growth Rate\n\nCalculate 5-year FCF CAGR from cash flow history.\n\n**Cross-validate with:** `free_cash_flow_growth` (YoY), `revenue_growth`\n\n**Growth rate selection:**\n- Stable FCF history → Use CAGR with 10-20% haircut\n- **Cap at 15%** (sustained higher growth is rare)\n\n## Step 3: Estimate Discount Rate (WACC)\n\n**Use the `sector` from company facts** to select the appropriate base WACC range from [sector-wacc.md](sector-wacc.md).\n\n**Default assumptions:**\n- Risk-free rate: 4%\n- Equity risk premium: 5-6%\n- Cost of debt: 5-6% pre-tax (~4% after-tax at 30% tax rate)\n\nCalculate WACC using `debt_to_equity` for capital structure weights.\n\n**Reasonableness check:** WACC should be 2-4% below `return_on_invested_capital` for value-creating companies.\n\n**Sector adjustments:** Apply adjustment factors from [sector-wacc.md](sector-wacc.md) based on company-specific characteristics.\n\n## Step 4: Project Future Cash Flows\n\n**Years 1-5:** Apply growth rate with 5% annual decay (multiply growth rate by 0.95, 0.90, 0.85, 0.80 for years 2-5). This reflects competitive dynamics.\n\n**Terminal value:** Use Gordon Growth Model with 2.5% terminal growth (GDP proxy).\n\n## Step 5: Calculate Present Value\n\nDiscount all FCFs → sum for Enterprise Value → subtract Net Debt → divide by `outstanding_shares` for fair value per share.\n\n## Step 6: Sensitivity Analysis\n\nCreate 3×3 matrix: WACC (base ±1%) vs terminal growth (2.0%, 2.5%, 3.0%).\n\n## Step 7: Validate Results\n\nBefore presenting, verify these sanity checks:\n\n1. **EV comparison**: Calculated EV should be within 30% of reported `enterprise_value`\n   - If off by >30%, revisit WACC or growth assumptions\n\n2. **Terminal value ratio**: Terminal value should be 50-80% of total EV for mature companies\n   - If >90%, growth rate may be too high\n   - If <40%, near-term projections may be aggressive\n\n3. **Per-share cross-check**: Compare to `free_cash_flow_per_share × 15-25` as rough sanity check\n\nIf validation fails, reconsider assumptions before presenting results.\n\n## Step 8: Output Format\n\nPresent a structured summary including:\n1. **Valuation Summary**: Current price vs. fair value, upside/downside percentage\n2. **Key Inputs Table**: All assumptions with their sources\n3. **Projected FCF Table**: 5-year projections with present values\n4. **Sensitivity Matrix**: 3×3 grid varying WACC (±1%) and terminal growth (2.0%, 2.5%, 3.0%)\n5. **Caveats**: Standard DCF limitations plus company-specific risks\n\n<!-- File: src/skills/write-memo/examples.md (Tokens: ~2142 | Category: anthropic-skill) -->\n# Example Memo (for tone calibration)\n\nThis is a worked example for `NFLX LONG · 12mo`. Use it to pattern-match tone, density, and structure when drafting. **Do not copy the numbers** — fetch fresh data via the tools for any actual memo.\n\nThe example is shown as the content that would fill the template slots, not the final HTML.\n\n---\n\n**Header strip values**\n- Ticker: NFLX\n- Company: Netflix, Inc.\n- Direction: LONG\n- Conviction: HIGH\n- Horizon: 12mo\n- Current price: $620\n- Base target: $785\n- Upside: +27%\n- Asymmetry: 2.4x\n- Prob-weighted return: +18%\n\n---\n\n**`{{variant_view}}`**\n\nConsensus models ad-tier as a single-digit revenue line for the next three years. We think it is a 20%+ contributor to '27 revenue and the primary multiple-rerate catalyst. The Street is anchored to subscription-only unit economics and has not updated for ad-tier ARPU running 30% above their first-year assumption.\n\n---\n\n**`{{thesis_bullets}}`** (HTML list items)\n\n- **Ad-tier reaches 18% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; at current adds and a 65% mix of new signups going to the ad tier, we model 51M ad-tier subs by end-'27. *Wrong if ad-tier mix of new signups falls below 50% for two consecutive quarters.*\n- **Ad-tier ARPU sustains $9+** — current ad CPMs of $35-45 imply $9-11 ARPU at 5 ad-min/hr inventory; management called out upfront commitments doubling YoY. *Wrong if disclosed ad ARPU prints below $8 in any quarterly disclosure.*\n- **Operating margin expands 600bps to 28% by '27** — content amortization peaks in '25 per management; incremental ad revenue is 70%+ margin. *Wrong if content spend grows above $20B in any year.*\n- **Multiple rerates from 28x to 35x as ad revenue mix exceeds 15%** — comparable transition (Spotify ad-tier, Roku) saw 25-40% multiple expansion when ad revenue crossed 15% of total. *Wrong if ad revenue stalls below 12% of total through '27.*\n\n---\n\n**`{{business_snapshot}}`**\n\nNetflix is a global subscription video streaming service with 270M paid memberships across 190+ countries. The company licenses and produces original content; \"we have one of the largest libraries of TV series and films, with content available in over 30 languages\" (10-K Item 1). Two membership tiers contribute differently: standard and premium subscriptions (~$15-23/mo) drive 92% of revenue today; the ad-supported tier (~$7/mo plus advertising) launched late '22 and is now the company's stated highest-growth tier. Unit economics differ: ad-tier subs carry lower subscription ARPU but ad revenue at ~70% incremental margin lifts blended contribution above the standard tier by year two of a sub's life.\n\n---\n\n**`{{whats_priced_in}}`**\n\nAt $620, NFLX trades at 28x consensus '26 EPS of $22.10. Consensus models 11% revenue growth and 23% operating margin in '27 — implying the Street is pricing in the subscription business compounding low-teens with modest margin expansion. Sellside ad-tier revenue estimates cluster around $4-5B for '27 (consensus mean $4.6B). Our '27 model puts ad revenue at $8.2B (+78% vs. consensus) on higher ad-tier sub adds and sustained ARPU. EPS divergence: our $29.50 vs. consensus $24.80, a +19% delta.\n\n---\n\n**`{{scenario_table}}`**\n\n| | Bear (20%) | Base (55%) | Bull (25%) |\n|---|---|---|---|\n| Revenue '27 | $42B | $52B | $61B |\n| Revenue growth | +6% | +14% | +20% |\n| EBIT margin | 22% | 28% | 32% |\n| EPS '27 | $19.50 | $29.50 | $38.20 |\n| Exit multiple | 22x | 28x | 35x |\n| Price target | $430 | $785 | $1,205 |\n| Return | -31% | +27% | +94% |\n\nProb-weighted return: +18% · Upside / downside: 2.4x\n\n---\n\n**`{{bull_narrative}}`**\n\nAd-tier inflects faster than we model. Disney+ pulls back on ad-tier pricing competition, leaving NFLX as the premium ad-supported inventory option for upfront buyers. Live programming (NFL, boxing, WWE) drives ad-tier mix of new signups above 70%, and ad CPMs sustain in the $40s as inventory stays scarce relative to demand. Content cost discipline holds — total content spend stays flat at $17B even as subs grow — and operating margin reaches 32% by '27. The Street rerates the stock to 35x as ad revenue crosses 20% of total, reclassifying NFLX from subscription business to dual-revenue media platform. EPS compounds 25%+ for three years.\n\n---\n\n**`{{base_narrative}}`**\n\nAd-tier grows roughly in line with current trajectory and reaches 50M+ subs by '27. ARPU holds at $9-10 as content investment in live and originals supports pricing. Content amortization peaks in '25 and rolls off, lifting operating margin to 28% by '27 even with $18-19B of content spend. Subscription business compounds high single digits globally with the bulk of net adds from APAC and LatAm at lower ARPU. The Street partially rerates the stock as ad mix exceeds 15%, multiple expands to 28x — in line with current level but on materially higher EPS.\n\n---\n\n**`{{bear_narrative}}`**\n\nDisney+ and Amazon's Prime Video ad tier compete aggressively on price; Disney+ ad-tier subs cross 100M globally by end-'26 and Amazon bundles ad-supported streaming into Prime at no incremental cost. Ad-tier CPMs compress 25% to the high $20s as inventory floods the market and brand advertisers consolidate spend on retail media platforms (Amazon, Walmart Connect) rather than streaming. NFLX ad revenue stalls at $3-3.5B for '27 vs. street $4.6B. Content spend creeps to $20B as the live programming push (NFL, boxing) proves more expensive to renew than initial deals suggested. Operating margin compresses to 22% as fixed content costs deleverage on slower revenue growth. The multiple compresses to 22x — Disney's current multiple — as the market reclassifies NFLX as a mature subscription business with declining incremental returns on content spend. Stock retraces to the low $400s.\n\n---\n\n**`{{catalysts_table}}`**\n\n| Event | Date | Expected Impact |\n|---|---|---|\n| Q2 '26 earnings — ad-tier sub disclosure | Jul '26 | Ad-tier sub count vs. our 45M target |\n| Upfront ad commitments | Apr-May '26 | Total committed dollars; vs. $1B+ '25 baseline |\n| NFL Christmas Day games viewership | Dec '26 | Concurrent viewers; ad-load testing |\n| FY27 guidance | Jan '27 | First explicit ad revenue guide |\n\n---\n\n**`{{risks_table}}`**\n\n| Risk | Mitigant | Tripwire |\n|---|---|---|\n| Ad-tier ARPU compression | Premium inventory (live sports) supports CPMs | Disclosed ad ARPU < $8 in any quarter |\n| Content cost re-acceleration | Management explicit guide of $17B '26 cap | Content spend > $19B in any year |\n| Competitive ad-tier launch from Amazon | Amazon ad-tier already live; share gains modest | NFLX ad-tier net adds < 5M in any quarter |\n| Subscription growth stalls in APAC | Pricing flexibility, mobile-only tier | Net adds < 4M globally in two consecutive quarters |\n| Multiple compression on rate environment | EPS growth outpaces multiple compression risk | Multiple < 24x with no operational miss |\n\n---\n\n**`{{position_management}}`**\n\nSuggested sizing: 4% NAV — high conviction × 2.4x asymmetry. Entry: current ($620) or scale-in below $590 on multiple compression. Stop / reduce: trim 50% if ad-tier ARPU prints below $8 in any quarter; full exit if content spend guide steps above $19B.\n\n---\n\n**`{{monitoring_kpis}}`**\n\n1. Ad-tier subscriber count (quarterly disclosure)\n2. Ad-tier ARPU or implied ARPU (calc: ad revenue / avg ad-tier subs)\n3. Content cash spend YTD vs. annual guide\n4. Operating margin (quarterly) — trajectory to 28% by '27\n5. Upfront commitment dollars (annual) — vs. prior year\n\n---\n\n## Why this example works\n\n- **Variant view is specific and contradictable.** It names a number (20%+ revenue contribution by '27) and a divergence (Street models single-digit). A PM can disagree with it precisely.\n- **Every thesis bullet has a \"wrong if\".** None of them are unfalsifiable platitudes.\n- **Bear case names competitors and mechanisms.** Disney+, Amazon, retail media, NFL renewal costs. Not \"competition intensifies\".\n- **Tripwires are observable.** \"Disclosed ad ARPU < $8 in any quarter\" is a data point the analyst can monitor; \"macro deteriorates\" is not.\n- **No padding.** No founding history, no \"in an ever-evolving streaming landscape\", no closing summary paragraph.\n\nWhen you draft a real memo, match this density and specificity, not the surface aesthetics. The aesthetics come from the template; the substance comes from the thinking.\n\n<!-- File: src/skills/write-memo/memo-style.md (Tokens: ~1105 | Category: anthropic-skill) -->\n# Investment Memo Style Guide\n\nRules the memo must follow. These mirror buyside writing conventions and avoid the tells that mark a document as AI-generated.\n\n## Voice\n\n- **First person plural** (\"we believe\", \"our base case\") — that's how a buyside team writes.\n- **Direct, not hedging.** \"Margins compress 200bps in '27\" beats \"margins could potentially face some pressure in 2027\".\n- **Confidence calibrated by evidence.** State the view, then state the evidence. Hedge once with a \"wrong if\" — not in every sentence.\n- **One sentence per idea** in narrative sections. Long sentences with comma chains and parentheticals signal AI drift.\n\n## Banned vocabulary\n\nNever use these words. They are AI-generated tells:\n\n- \"delve\", \"delves\", \"delving\"\n- \"leverage\" as a verb (\"we leverage X to do Y\")\n- \"robust\", \"comprehensive\", \"holistic\", \"seamless\"\n- \"navigate the landscape\", \"navigate the challenges\"\n- \"in today's fast-paced\", \"in an ever-evolving\"\n- \"stands out\", \"sets itself apart\"\n- \"deep dive\", \"unpack\", \"double-click\"\n- \"moreover\", \"furthermore\", \"additionally\" (use a new sentence)\n- \"It's worth noting that\" (just say the thing)\n\n## Banned constructions\n\n- **Tricolons** — three-item lists for rhythmic effect (\"fast, scalable, and reliable\"). One AI tell.\n- **Em dash abuse** — at most one em dash per paragraph. Prefer periods or commas.\n- **\"Not just X but Y\"** — overused contrast structure.\n- **Generic closing summaries** — \"In conclusion, this is a compelling opportunity that...\" Don't write these. End on a specific claim or a tripwire.\n- **Hedge stacking** — \"could potentially possibly maybe\". Pick one or zero.\n\n## Numbers\n\n- **Quantify everything.** \"Margins expanded 380bps\" not \"margins improved meaningfully\".\n- **Percentages with explicit base.** \"Revenue grew 28% YoY\" not \"revenue saw strong growth\".\n- **Multiples in line.** \"Trading at 18x FY26 EPS\" not \"trading at attractive multiples\".\n- **Don't invent numbers.** If you don't have it from a tool call, write \"not disclosed\" or omit the line. Never fabricate consensus figures.\n\n## Thesis bullet format\n\nEvery thesis bullet must be a complete falsifiable claim:\n\n> **[Specific claim with a number]** — [Evidence with a specific number, ideally citing the data point]. *Wrong if [specific observable would happen].*\n\nGood:\n> **Ad-tier reaches 15% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; trajectory implies 15% mix at constant adds. *Wrong if ad-tier ARPU compresses below $8 due to inventory glut.*\n\nBad (vague claim, no falsifier):\n> **Strong product-market fit in ad tier** — Management has emphasized this is a key growth area going forward.\n\n## Bear case requirements\n\nThe bear paragraph is the highest-stakes paragraph in the memo. Rules:\n\n1. **Steelmanned.** Written as if you actually believed it. If you can't, you don't understand the trade.\n2. **Specific competitor / customer / regulator named.** Not \"competition intensifies\" — name the company and the product.\n3. **Coherent world, not a list.** The bear case is a story where the thesis is wrong. Connect the dots.\n4. **Read the bull paragraph and the bear paragraph back to back.** If bear reads weaker, rewrite. This is the single most common failure mode.\n\n## Tripwires\n\nEvery risk row in the risks table must have a tripwire. A tripwire is **an observable data point that would invalidate the thesis** within the holding period.\n\nGood tripwires:\n- \"Q3 ad-tier ARPU prints below $8\"\n- \"Top customer announces in-sourcing on Q2 call\"\n- \"Gross margin contracts more than 150bps in any quarter\"\n- \"Insider sales exceed $50M in any rolling 90-day window\"\n\nBad tripwires (not observable / not actionable):\n- \"Macro deteriorates\"\n- \"Competition increases\"\n- \"Sentiment shifts negatively\"\n\n## What to pull from filings\n\nWhen summarizing the business, pull verbatim from the 10-K Item 1 where the company's own language is tighter than rewriting it. Quote with quotes and source: `\"[exact phrase]\" (10-K Item 1)`.\n\nFor risks, prefer pulling from Item 1A and the company's own disclosure language — it's the most defensible risk framing in the memo.\n\n## Closing the memo\n\nMemos do not need a \"conclusion\" section. The header already states the recommendation; the thesis bullets state the view; the scenarios state the math. A closing paragraph that restates these is padding.\n\nThe last section in the body is **Monitoring KPIs** — the specific metrics that confirm or kill the thesis. That's the right note to end on: what to watch.\n\n<!-- File: src/skills/write-memo/SKILL.md (Tokens: ~2703 | Category: anthropic-skill) -->\n---\nname: write-memo\ndescription: Drafts a professional investment memo (HTML output) for a long or short equity idea, structured the way a hedge fund analyst would present a thesis to a PM. Triggers when the user asks to \"write a memo\", \"draft an investment memo\", \"write up a thesis\", \"pitch this stock\", \"memo on [ticker]\", \"long writeup\", \"short writeup\", or similar. Produces a 1-page HTML file at .dexter/memos/.\n---\n\n# Write Investment Memo Skill\n\nProduces a buyside-quality investment memo as a self-contained HTML file. The memo is opinionated and falsifiable — it leads with a variant view and steelmans the bear case. The output is the deliverable; the chat response is just a header summary plus the file path.\n\n## Workflow Checklist\n\nCopy and track progress:\n```\nInvestment Memo Progress:\n- [ ] Step 1: Frame the trade (direction, horizon, variant view)\n- [ ] Step 2: Gather data (financials, market, filings)\n- [ ] Step 3: Build Bear / Base / Bull scenarios\n- [ ] Step 4: Optional DCF anchor for base case\n- [ ] Step 5: Draft memo content (fill all slots)\n- [ ] Step 6: Self-critique pass\n- [ ] Step 7: Render HTML to .dexter/memos/\n- [ ] Step 8: Report header summary + file path\n```\n\n## Step 1: Frame the Trade\n\nConfirm or ask for the following before drafting:\n\n- **Ticker** (required)\n- **Direction**: long or short (required)\n- **Horizon**: 3mo / 6mo / 12mo / 2yr+ (default 12mo if not specified)\n- **Conviction**: high / medium / low (default medium)\n- **Variant view**: one sentence — what the analyst sees that consensus doesn't\n\n**If the user does not provide a variant view**: do not ask repeatedly. Gather data in Step 2 first, then derive a candidate variant view from where your model meaningfully diverges from consensus (e.g., \"our '27 EPS is $X vs consensus $Y because [driver]\"). Present it as a draft and let the analyst accept, refine, or replace before you proceed to Step 5.\n\n## Step 2: Gather Data (Parallel)\n\nIssue these tool calls in parallel:\n\n### 2.1 Financials\nCall `get_financials`:\n- `\"[TICKER] annual income statements last 5 years\"` — revenue, operating income, net income, EPS, margins\n- `\"[TICKER] annual cash flow statements last 5 years\"` — operating CF, capex, FCF\n- `\"[TICKER] latest balance sheet\"` — debt, cash, shares outstanding\n- `\"[TICKER] financial metrics snapshot\"` — P/E, EV, ROIC, FCF growth, debt/equity, margins\n- `\"[TICKER] segmented financials\"` — segment revenue, segment margins (if multi-segment)\n- `\"[TICKER] earnings history last 8 quarters\"` — beats/misses, surprises\n- `\"[TICKER] company facts\"` — sector, industry, market cap\n- `\"[TICKER] KPI guidance\"` and `\"[TICKER] KPI metrics\"` — management-provided KPIs and guidance\n\n### 2.2 Market & Ownership\nCall `get_market_data`:\n- `\"[TICKER] price snapshot\"` — current price, 52-week range, market cap\n- `\"[TICKER] historical prices last 12 months\"` — for return / multiple compression context\n- `\"[TICKER] insider trades last 6 months\"` — recent buys/sells, dollar amounts\n- `\"[TICKER] institutional holdings\"` — top holders, recent additions / reductions\n- `\"[TICKER] news last 30 days\"` — recent material events\n\n### 2.3 Filings\nCall `read_filings`:\n- Most recent 10-K Item 1 (Business) — for business snapshot language\n- Most recent 10-K Item 1A (Risk Factors) — to source risks from the company itself\n- Most recent 10-Q — recent quarterly trajectory\n\n### 2.4 Memory (optional)\nCall `memory_search` with the ticker — surfaces any prior notes, prior memos, or user-provided constraints (e.g., risk tolerance, sector exposure already in book).\n\n### 2.5 Sentiment (optional, only if time-sensitive)\nCall `x_search` for recent material chatter on the ticker. Skip if the thesis is fundamental and not catalyst-driven this week.\n\n## Step 3: Build Scenarios\n\nConstruct Bear / Base / Bull scenarios. Each scenario is **driver-based**, not a single number pulled from the air.\n\nFor each scenario specify:\n- **Revenue growth** (forecast year, 2-3 years out)\n- **EBIT / operating margin** at that point\n- **Exit multiple** (P/E, EV/EBITDA, or EV/Sales as appropriate for the sector)\n- **Probability weight** (the three must sum to 100%)\n- **Price target** (derived from the above)\n- **Return** vs. current price (with sign)\n\nThen compute:\n- **Probability-weighted return** = sum(prob × return) across scenarios\n- **Upside / downside ratio** = |bull return| / |bear return|\n\n**Asymmetry check**: if upside/downside < 2x, flag this prominently. A weak-asymmetry setup is a coin flip, not a trade. Either revise the scenarios honestly, or note the weak asymmetry in the memo (do not hide it).\n\n## Step 4: Optional DCF Anchor\n\nFor base case, optionally invoke the `dcf-valuation` skill via the `skill` tool to produce an intrinsic value anchor. Use it as a cross-check against your base-case price target, not as a replacement.\n\n## Step 5: Draft Memo Content\n\nRead the template and style guide:\n- [memo-template.html](memo-template.html)\n- [memo-style.md](memo-style.md)\n- [examples.md](examples.md) — pattern-match tone and density\n\nFill every slot. Slots are listed in the template — do not skip any. Slot-specific guidance:\n\n### `{{variant_view}}`\nThree sentences max. Lead with the divergence from consensus: *what we see, why we think it, why the market hasn't priced it*. If the user did not provide one, this is where your derived candidate goes.\n\n### `{{thesis_bullets}}`\n3-5 bullets, each in this format:\n> **[Claim]** — [Evidence with a specific number]. *Wrong if [observable falsifier].*\n\nExample:\n> **Ad-tier reaches 15% of subs by '27** — Q1 disclosed 40M ad-tier subs (+85% YoY) on a 270M base; trajectory implies 15% mix at constant adds. *Wrong if ad-tier ARPU compresses below $8 due to inventory glut.*\n\nEach bullet must be **falsifiable**. No \"great management\", \"strong moat\", \"wide TAM\" without a specific operational metric behind it.\n\n### `{{business_snapshot}}`\n4-5 lines max. What they sell, how they make money, segment mix, unit economics that matter for the thesis. **No founding-year boilerplate.** Pull verbatim from the 10-K Item 1 where it tightens the language.\n\n### `{{whats_priced_in}}`\nCurrent multiple, implied growth or margin assumption embedded in that multiple, sellside consensus numbers (revenue, EPS for FY+1 and FY+2). Then one sentence on where your model diverges and by how much.\n\n### `{{scenario_table}}`\nRender as an HTML table. Columns: Bear / Base / Bull. Rows: Probability, Revenue growth (FY27), EBIT margin (FY27), Exit multiple, Price target, Return. Color returns: positive `class=\"pos\"`, negative `class=\"neg\"`.\n\n### `{{bull_narrative}}`, `{{base_narrative}}`, `{{bear_narrative}}`\nOne paragraph each (3-5 sentences). Each is a *coherent world*, not a list of factors:\n- **Bull**: what has to be true. Specific operational wins that compound. Tied to evidence we'd see in quarterly data.\n- **Base**: the thesis playing out as written.\n- **Bear**: steelmanned — written as if you believed it. Specific competitive losses, customer concentration risk materializing, multiple compression to a lower peer group. **If the bear paragraph reads weaker than the bull paragraph, rewrite it.**\n\n### `{{catalysts_table}}`\nTable with columns: Event, Date / Quarter, Expected Impact. 3-5 entries. Dates should be specific (Q3 '26, Aug '26 earnings, Investor Day Nov '26).\n\n### `{{risks_table}}`\nTable with columns: Risk, Mitigant, Tripwire. The tripwire is the **observable data point that would invalidate the thesis** (e.g., \"Q3 ad-tier ARPU prints below $8\", \"top customer renewal pushed past Q4\"). Tripwires distinguish a hedge fund memo from a sellside report.\n\n### `{{position_management}}`\nThree short lines: suggested sizing (% NAV) anchored to conviction × asymmetry; entry price (current or limit); stop level or scale-out trigger.\n\n### `{{monitoring_kpis}}`\n3-5 KPIs to track quarterly. These are the metrics that confirm or kill the thesis — not generic ones (revenue growth, EPS) but specific ones tied to your variant view.\n\n## Step 6: Self-Critique Pass (Mandatory)\n\nBefore rendering, verify every check. If any fail, revise the relevant section before continuing.\n\n1. **Variant view is actually variant.** Not a restatement of consensus dressed up as a view. The test: can you point to specific sellside notes / consensus numbers your view contradicts?\n2. **Every thesis bullet is falsifiable.** Each has a \"wrong if\" clause naming a specific observable.\n3. **Numbers behind every adjective.** No \"strong growth\" without the bps / %. No \"expanding margins\" without the basis point delta.\n4. **Bear case is steelmanned.** Read the bear paragraph aloud. If it reads weaker than the bull, rewrite.\n5. **Asymmetry ≥ 2x.** If not, the memo flags this in the header rather than hiding it.\n6. **Probability weights sum to 100%.**\n7. **Tripwires are observable.** Each risk has a data point an analyst could watch for, not a vibe.\n\n## Step 7: Render HTML\n\n1. Read `memo-template.html` via `read_file`\n2. Replace every `{{slot}}` placeholder with the content you drafted\n3. Set `{{date}}` to today's date in YYYY-MM-DD format\n4. Set `{{analyst}}` from memory if known, otherwise blank\n5. Write to `.dexter/memos/[TICKER]_[DIRECTION]_[YYYY-MM-DD].html` via `write_file`\n   - Direction is `LONG` or `SHORT` (uppercase)\n   - Example: `.dexter/memos/NFLX_LONG_2026-05-24.html`\n6. **Only** write a `.md` source file if the user explicitly requested one\n\nThe path uses forward slashes. The `write_file` tool will create the `.dexter/memos/` directory if it does not exist.\n\n## Step 8: Report to Chat\n\nFinal chat response should be exactly this format and nothing more:\n\n```\n[TICKER] · [LONG/SHORT] · Target $X (+Y% / -Y%) · Asymmetry [N.Nx] · [Conviction]\n\nMemo saved to .dexter/memos/[FILENAME].html\nOpen with: open .dexter/memos/[FILENAME].html\n```\n\nDo not paste the full memo content into the chat. The file is the deliverable. The chat output is a scannable header.\n\n## Critical Don'ts\n\n- Do not paste the full memo as a chat response in addition to writing the file\n- Do not write a `.md` file alongside unless explicitly requested\n- Do not include charts, sparklines, scenario bars, or any visual element beyond tables\n- Do not add emoji anywhere — not in the memo, not in the chat response\n- Do not include a prominent \"AI-generated\" footer or branding\n- Do not skip the self-critique pass in Step 6\n- Do not invent consensus numbers — if you do not have them from a tool call, say so in the memo\n\n<!-- File: src/skills/x-research/SKILL.md (Tokens: ~782 | Category: anthropic-skill) -->\n---\nname: x-research\ndescription: >\n  X/Twitter public sentiment research. Searches X for real-time perspectives,\n  market sentiment, expert opinions, breaking news, and community discourse.\n  Use when: user asks \"what are people saying about\", \"X/Twitter sentiment\",\n  \"check X for\", \"search twitter for\", \"what's CT saying about\", or wants\n  public opinion on a stock, sector, company, or market event.\n---\n\n# X Research Skill\n\nAgentic research over X/Twitter using the `x_search` tool. Decompose the\nresearch question into targeted searches, iterate to refine signal, and\nsynthesize into a sourced sentiment briefing.\n\n## Research Loop\n\n### 1. Decompose into Queries\n\nTurn the research question into 3–5 targeted queries using X operators:\n\n- **Core query**: Direct keywords or `$TICKER` cashtag\n- **Expert voices**: `from:username` for known analysts or accounts\n- **Bearish signal**: keywords like `(overvalued OR bubble OR risk OR concern)`\n- **Bullish signal**: keywords like `(bullish OR upside OR catalyst OR beat)`\n- **News/links**: add `has:links` to surface tweets with sources\n- **Noise reduction**: `-is:reply` to focus on original posts; `-airdrop -giveaway` for crypto topics\n\n### 2. Execute Searches\n\nUse the `x_search` tool with `command: \"search\"`. For each query:\n\n- Start with `sort: \"likes\"` and `limit: 15` to surface highest-signal tweets\n- Add `min_likes: 5` or higher to filter noise for broad topics\n- Use `since: \"1d\"` or `\"7d\"` depending on how time-sensitive the topic is\n- If a query returns too much noise, narrow with more operators or raise `min_likes`\n- If too few results, broaden with `OR` terms or remove restrictive operators\n\n### 3. Check Key Accounts (Optional)\n\nFor well-known analysts, fund managers, or company executives, use\n`command: \"profile\"` to see their recent posts directly.\n\n### 4. Follow Threads (Optional)\n\nWhen a high-engagement tweet appears to be a thread starter, use\n`command: \"thread\"` with the tweet ID to get full context.\n\n### 5. Synthesize\n\nGroup findings by theme (bullish, bearish, neutral, news/catalysts):\n\n```\n### [Theme]\n\n[1–2 sentence summary of the theme]\n\n- @username: \"[key quote]\" — [likes]♥ [Tweet](url)\n- @username2: \"[another perspective]\" — [likes]♥ [Tweet](url)\n```\n\nEnd with an **Overall Sentiment** paragraph: predominant tone (bullish/bearish/\nmixed/neutral), confidence level, and any notable divergence between retail and\ninstitutional voices.\n\n## Refinement Heuristics\n\n| Problem | Fix |\n|---|---|\n| Too much noise | Raise `min_likes`, add `-is:reply`, narrow keywords |\n| Too few results | Broaden with `OR`, remove restrictive operators |\n| Crypto spam | Add `-airdrop -giveaway -whitelist` |\n| Want expert takes only | Use `from:` or `min_likes: 50` |\n| Want substance over hot takes | Add `has:links` |\n\n## Output Format\n\nPresent a structured briefing:\n\n1. **Query Summary**: what was searched and time window\n2. **Sentiment Themes**: grouped findings with sourced quotes and tweet links\n3. **Overall Sentiment**: tone, confidence, key voices\n4. **Caveats**: X sentiment is not a reliable predictor; sample bias toward vocal minorities; last-7-days window only\n</yakaai_skills>"}