drillr — Power Terminal for Deep Financial Research
by @little-grebe
Access Drillr's financial research capabilities — agentic search over company financials, a high-signal market event feed, published analyst articles, and pe...
clawhub install drillr-agent📖 About This Skill
name: drillr description: Access Drillr's financial research capabilities — agentic search over company financials, a high-signal market event feed, published analyst articles, and persistent per-user watchlists. Use this whenever the user asks about stock prices, company fundamentals, earnings, SEC filings, market signals, sector trends, or wants to track tickers over time. Requires a user-specific API key obtainable at https://drillr.ai/developer/keys. version: 1.0.0 license: MIT homepage: https://drillr.ai metadata: openclaw: homepage: https://drillr.ai emoji: "📈"
Drillr — Financial Research for Agents
Drillr exposes its AI research agent and financial data pipeline to
external agents through three equivalent channels: MCP (Streamable
HTTP), REST API, and a command-line tool. All three accept the
same drl_* API key and expose the same data.
What you can do
Detecting the deployment context
Your onboarding path depends on ONE question:
> Can the user run shell commands on the machine where you are running, > and see the output directly in the same conversation?
Physical hardware doesn't matter. A Mac mini, MacBook, home NAS, Raspberry Pi, or cloud VM can all serve either path. What matters is whether the user's current channel to you is **co-located with your shell or relayed through a chat channel**.
Path A — Indirect (relayed)
Signals that suggest Path A:
ls ~/.config/ back to you→ Use Onboarding A below.
Path B — Direct (co-located)
Signals that suggest Path B:
export or config-edit→ Use Onboarding B below.
When unsure, ask the user
> Quick setup question: are you talking to me through a terminal on the > same machine I'm running on — where I can suggest shell commands for > you to run — or through a separate channel like Telegram / WhatsApp / > a web chat?
Prerequisites — getting an API key
Do NOT attempt any tool call until you have a drl_* key accessible to
your runtime. If it's missing, run the onboarding path that matches
your deployment context.
Onboarding A — Indirect (IM / web chat / remote host)
The user reaches you through a text-only relay and cannot touch your filesystem. They will complete the key creation from whatever browser they have (phone, tablet, or desktop) and paste the key back to you.
Step 1 — Tell the user (verbatim):
> To use Drillr I need an API key. From any browser (your phone is
> fine):
>
> 1. Open https://drillr.ai/developer/keys
> 2. Sign in — Google sign-in is the quickest; email/password also
> works
> 3. Tap "Create API key" → give it a name (e.g. "my-agent") → copy
> the drl_... string
> 4. Paste it back to me here. The key is shown only once.
>
> After I confirm it works, you can delete your message.
Step 2 — When the key arrives, persist it:
Write it to ~/.config/drillr/config.json with file mode 0600:
{ "api_key": "drl_..." }
Equivalent shell:
mkdir -p ~/.config/drillr
umask 077
cat > ~/.config/drillr/config.json <Step 3 — Verify the key works:
curl -sS -o /dev/null -w "%{http_code}\n" \
-H "Authorization: Bearer drl_..." \
https://gateway.drillr.ai/api/v1/watchlists
Expect HTTP 200. On 401, the key is invalid — apologize, ask the
user to regenerate, and rerun Step 1.
Step 4 — Confirm to the user, masked:
> Stored drl_xxxxxxxx_...e9f2. You can safely delete your message now.
Rules:
~/.config/drillr/config.jsonOnboarding B — Direct (terminal co-located with user)
The user can run shell commands and see their output. Pick ONE of the
three equivalent options and instruct the user accordingly. All three
expect the same drl_* key created at
B1. MCP via Claude Code (recommended for Claude Code users)
Tell the user:
> 1. Create an API key at ~/.claude.json (or merge into the existing mcpServers
> object):
>
>
>
> 3. Add > {
> "mcpServers": {
> "drillr": {
> "type": "http",
> "url": "https://gateway.drillr.ai/mcp",
> "headers": {
> "Authorization": "Bearer ${DRILLR_API_KEY}"
> }
> }
> }
> }
> export DRILLR_API_KEY=drl_... to your shell rc
> (~/.zshrc / ~/.bashrc) and restart the shell
> 4. Restart Claude Code. /mcp should list drillr as connected.
B2. CLI
npm install -g drillr-cli
drillr auth set-key drl_...
drillr watchlist list # verify: should list (or print "no watchlists yet")
B3. REST with env var
export DRILLR_API_KEY=drl_...
curl -H "Authorization: Bearer $DRILLR_API_KEY" \
https://gateway.drillr.ai/api/v1/watchlists
Choosing a channel (after onboarding completes)
Pick based on your runtime's capabilities:
| Runtime characteristic | Preferred channel | | ----------------------------------- | -------------------- | | Has native MCP client support | MCP | | HTTP only (no MCP, no shell) | REST | | Shell / subprocess available | CLI or REST |
All three are equivalent in data and rate limit. MCP tool names operate by natural names (e.g. watchlist by name); REST uses UUIDs.
Capabilities
Research & data lookup — search
Ask natural-language questions about companies, tickers, sectors, filings, earnings. Runs 5-15s server-side and returns markdown text with source references.
| Channel | Call |
| ------- | --------------------------------------------------------------- |
| MCP | search({ question, session_id?, context? }) |
| REST | POST /api/v1/search with { question, session_id?, stream? } |
| CLI | drillr search " |
Session continuity: pass the returned session_id in the next
call to continue the same research conversation. Use context to
pass background info that refines the answer.
Data coverage:
When to use search:
Example questions that work well:
Signals — signals
A curated investment-event feed. Each signal is one market event (one SUBJECT × one ACTION × one TIME), already aggregated across outlets — you get one record per event, not one per article.
Coverage — sources rolled into the feed:
Freshness: signals appear within ~3–5 minutes of the originating event.
| Channel | Call |
| ------- | ---------------------------------------------------------------------------- |
| MCP | signals({ tickers?, sector?, since?, limit?, offset? }) |
| REST | GET /api/v1/signals?tickers=AAPL,MSFT§or=Technology&since=...&limit=20 |
| CLI | drillr signals --tickers AAPL,MSFT --limit 5 |
Response shape: { headline, summary, suggested_tickers[], sector[], created_at }, ordered newest first.
Articles — article_list / article_get
Research articles spanning company-specific analysis, event coverage, and industry trackers.
What you'll find:
| Channel | Call |
| ------- | ------------------------------------------------------------------------ |
| MCP | article_list({ ticker?, tag?, limit?, offset? }) / article_get({ article_id }) |
| REST | GET /api/v1/articles?ticker=NVDA&limit=10 / GET /api/v1/articles/:id |
| CLI | drillr articles list --ticker NVDA / drillr articles get |
article_get returns the article body (markdown), plus topics and
references arrays. article_list returns 11 public fields per row
(id, title, summary, content, related_tickers, tags, sector, citation,
published_at, created_at, word_count).
Watchlists
Per-user ticker collections. Owner-isolated (RLS): each key only sees
and mutates its owner's watchlists. Attempting to access another user's
watchlist by UUID returns 404, not 403.
| MCP (by name) | REST (by UUID) |
| ---------------------------------------------------- | ------------------------------------------------- |
| watchlist_list | GET /api/v1/watchlists |
| watchlist_create({ name, tickers? }) | POST /api/v1/watchlists |
| watchlist_add({ ticker, watchlist_name? }) | POST /api/v1/watchlists/:id/tickers |
| watchlist_remove({ ticker, watchlist_name? }) | DELETE /api/v1/watchlists/:id/tickers/:ticker |
| watchlist_delete({ watchlist_name }) | DELETE /api/v1/watchlists/:id |
CLI: drillr watchlist {list|create|add|remove|delete} — see
drillr watchlist --help.
> MCP tools accept watchlist names (chat-friendly). REST uses
> UUIDs (URL-friendly). If watchlist_name is omitted on add, a
> default "My Watchlist" is used (created on miss).
Typical workflows
"Daily research briefing"
User: "Can you do a daily morning briefing on my portfolio?"
1. watchlist_list — see what tickers the user already tracks
2. If empty, ask the user for tickers; then watchlist_create
3. Each morning, execute in order:
- signals({ tickers: [...watchlist_tickers], since: "<24h-ago ISO>" })
- For any high-interest signal, search({ question: "Deeper context on
- article_list({ ticker: ... }) for any ticker with fresh activity
4. Synthesize into a chat-sized briefing (headline + 1-2 sentences + links)
"Quick lookup"
User: "What's Nvidia's market cap?"
1. search({ question: "What is NVDA's current market cap?" })
2. Relay the answer and any cited sources
"Sector scan"
User: "Any interesting biotech moves this week?"
1. signals({ sector: ["Health Care"], since: "<7d-ago ISO>", limit: 30 })
2. For each signal the user asks about, article_list({ ticker }) or
a follow-up search with session_id from the prior call
Error handling
| HTTP | code string | What to do |
| ---- | ---------------------------- | ------------------------------------------------------------------------------------------- |
| 400 | invalid_body / invalid_query / invalid_id | Fix parameter shape and retry (don't pester the user) |
| 401 | unauthenticated / key_invalid | Re-read the stored key; if still 401, rerun Prerequisites — the key is absent or wrong |
| 401 | key_revoked | Tell the user their key was revoked; they need to create a new one at the developer portal |
| 401 | key_expired | Tell the user their key expired; same fix |
| 403 | | Key is valid but lacks external scope — user needs to issue a different key |
| 404 | not_found | Resource doesn't exist, or RLS hides it (someone else's). Do NOT assume just-deleted |
| 429 | | Inspect retry_after_seconds in the body; sleep and retry |
| 502 | upstream_error | Transient data-source failure; retry once after 2-3s, then surface to user |
**On any 401: re-read ~/.config/drillr/config.json or the
DRILLR_API_KEY env var BEFORE asking the user.** You have the
configuration — diagnose first, then instruct.
Never tell the user to "check their configuration."
Rate limits
30 requests per minute per API key. On 429 the response body
includes retry_after_seconds (1-60s). For workflows that fan out
(e.g., scanning a 50-ticker watchlist), pace at ≤0.5 req/s or batch
via a single search or signals call with multiple tickers.
Advanced
Drillr also supports OAuth 2.1 for MCP clients that implement Dynamic Client Registration (e.g., Claude Code's built-in MCP OAuth). This skill deliberately does not cover that path because:
For agent automation, prefer the drl_* API key flow above. If you
are a human user setting up Claude Code on your own laptop and prefer
the OAuth UX, see the Drillr developer portal
(
Reference
https://gateway.drillr.aihttps://gateway.drillr.ai/mcpdrillr-cli (npm install -g drillr-cli)Tracks External API v1 (2026-04). Breaking changes will ship as
/api/v2/* alongside /api/v1/*.