claude/plugins/local/todoist-flow/skills/research/SKILL.md
Multi-source research orchestrator scoped to the todoist-flow plugin so profiles like `dots profile launch claude todo` can do fact checks without enabling cheese-flow. Spawns parallel fetch sub-agents for Context7 (library docs), Tavily (technical content), Serper (facts/SERP), and `gh` CLI (GitHub patterns). Fetchers write findings to scratch files; a single synthesis sub-agent reads them and returns a compact answer, keeping the caller's context clean. Use when the user is mid-task-triage and needs external facts before deciding whether to keep, reword, or extract a Todoist task, or invokes /todoist-flow:research directly. Do NOT use for single-source lookups (use Context7 directly for library docs alone). For coding sessions outside the todo profile, prefer cheese-flow's /briesearch instead.
npx skillsauth add paulnsorensen/dotfiles researchInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Multi-source research. Route sources once, spawn in parallel, synthesize in a sub-agent with mechanical confidence scoring.
This skill runs inline in the caller's context so its fetcher Agent()
calls are first-level and work (Claude Code only permits 1 level of sub-agent
nesting). To keep the caller's context clean despite running inline:
$TMPDIR and returns only a
one-line done: <path> or unavailable: <reason>.--report mode
the same sub-agent also assembles the Sources appendix from the scratch
files, so the skill itself never needs to read them.--report
mode, the skill writes the sub-agent's report body to the target path and
still cleans up the scratch dir (the report itself is the durable
artifact).Net effect: caller sees ~5 "fetcher done" lines plus one compact synthesis. No evidence tables, snippets, or URLs bloat the main context.
The skill prints exactly these blocks to the caller's context — nothing else:
<path>" if --report was set.Do NOT print: fetcher narration, intermediate debug output, raw scratch-file
contents, or scratch file paths except inside the FETCHER STATUS block
(where done: <path> is bounded internal bookkeeping). If something doesn't
fit the four blocks above, it stays silent.
Parse $ARGUMENTS for these flags:
--report or --report <filepath> — Save findings as a markdown report.
Default path: .claude/research/<slugified-topic>.md (create dir if needed).Everything after flag extraction is the research question.
Compute the scratch directory for this run:
RUN_ID="$(date +%Y%m%d-%H%M%S)-<slug>"
RUN_DIR="${TMPDIR:-/tmp}/claude-research-${RUN_ID}"
mkdir -p "$RUN_DIR"
$TMPDIR is always writable inside sandboxed sessions (ccw worktrees);
.claude/ may not be. Scratch files are ephemeral — only --report output
lands in .claude/research/.
Where <slug> is a 4-6 word kebab-case of the topic. The RUN_DIR value is
passed to every fetcher and to the synthesis sub-agent.
Identify:
Select sources using the decision tree below. Output an explicit committed list — these are the sources you will spawn in Phase 3. No "maybe," no "if needed," no re-decision later.
Is it about a specific library API?
YES → Context7 (+ gh CLI for real-world usage if needed)
Is it a factual lookup, entity, or "what/who/when" question?
YES → Serper (fast, structured, cheap)
Is it a "how should I..." or best practices question?
YES → Tavily (synthesized content) + maybe Serper (for People Also Ask breadth)
Is it about patterns in our codebase?
YES → Codebase Fetcher (+ gh CLI if comparing to industry patterns)
Is it about how open-source projects solve X?
YES → gh CLI (+ Tavily if needing written analysis/articles about the approach)
| Source | Best for | Cost | |--------|----------|------| | Context7 | Specific library API, config, version migration | Free (1K/mo) | | Serper | Facts, entities, recency, "what/who/when" | ~$0.001/query | | Tavily | How-to, best practices, technical analysis | ~$0.003-0.008/query | | Codebase | Internal patterns and constraints | Free | | gh CLI | Real-world OSS usage patterns | Free |
| Complexity | Sources | Example | |-----------|---------|---------| | Simple fact | 1-2 | "What's the latest version of Prisma?" | | Focused how-to | 2-3 | "How do I set up connection pooling in sqlx?" | | Comparison | 3-4 | "What are the tradeoffs between Axum and Actix?" | | Deep research | 4-5 | "How should we architect real-time notifications?" |
Write out the committed routing decision in chat:
ROUTING DECISION:
- Tavily: YES (transformed query: "<query>")
- Serper: YES (transformed query: "<query>")
- Context7: NO (not a library API question)
- Codebase: NO (external question)
- gh-github: NO
HARD RULE — the cardinal rule of this skill:
If a source was committed in Phase 2, you MUST spawn it in Phase 3. "Marginal value," "local evidence is enough," "would add little" are NOT reasons to skip. Those judgments belonged in Phase 2 routing. Once committed, execution is mechanical.
If you find yourself wanting to skip a committed source mid-execution, STOP. Either (a) spawn it anyway, or (b) explicitly back out — say "I'm revising the routing decision because <reason>" and re-do Phase 2 with the new plan. Silent skipping is the #1 failure mode of this skill.
Launch all committed fetchers in a single message with parallel Agent
calls. Use subagent_type="general-purpose", model="haiku", and pass the
fetcher prompt templates below.
Every fetcher prompt MUST instruct the sub-agent to:
Call only the specified MCP tools. Do NOT use WebSearch or WebFetch. Sub-agents default to those fallbacks, which produce weaker results.
Write findings to <RUN_DIR>/<source>.md (absolute path) using the
schema below.
Return to the skill only one of these two lines:
done: <RUN_DIR>/<source>.mdunavailable: <one-line reason>Nothing else. No evidence tables, no URLs, no snippets in the return text.
Each fetcher writes a markdown file with this shape:
# <source> — <topic>
_Confidence: <0-100>_ _Status: <ok|unavailable>_
## Direct answer
<1-2 sentences>
## Evidence
<quotes, snippets, key facts — whatever the source schema asks for>
## Sources
- <URLs, file:line refs, library IDs>
Each source performs best with a different query format:
| Source | Query style | Example |
|--------|-------------|---------|
| Context7 | Library + focused API question | libraryName="express", query="rate limiting middleware" |
| Serper | Short Google keywords | "express 5 rate-limit middleware 2026" |
| Tavily | Natural language question | "How to implement rate limiting in Express 5 with middleware best practices" |
| Codebase | Symbol / pattern description | "rate limiting middleware" |
| gh CLI | Short repo/code search terms | gh search code 'express rate-limit middleware --language ts' |
Substitute <RUN_DIR> with the absolute path computed in Phase 0.
You are fetching library documentation via Context7.
Do NOT use WebSearch or WebFetch. Use ONLY the MCP tools below.
Steps:
1. Call mcp__context7__resolve-library-id(libraryName="<library>", query="<question>")
2. Call mcp__context7__query-docs(libraryId="<resolved-id>", query="<focused question>")
3. Max 3 Context7 calls total.
4. Write findings to <RUN_DIR>/context7.md using the scratch file schema
(Direct answer, Evidence with code/version caveats, Sources).
5. Return ONLY: "done: <RUN_DIR>/context7.md"
If the MCP returns no results or errors:
- Write a 1-line note to <RUN_DIR>/context7.md: "Context7 unavailable: <reason>"
- Return ONLY: "unavailable: <reason>"
- Do NOT fall back to local knowledge.
Do not print evidence, URLs, or snippets in your return message.
You are retrieving structured Google SERP data via Serper.
Do NOT use WebSearch or WebFetch. Use ONLY the MCP tools below.
Tools:
- mcp__serper__google_search(q="<keywords>", gl="us", hl="en")
- mcp__serper__scrape(url="<url>")
Query style: SHORT keyword queries.
BAD: "How do I implement rate limiting in Express 5 with middleware?"
GOOD: "express 5 rate-limit middleware 2026"
Steps:
1. Search with keyword query
2. Check answerBox and knowledgeGraph for direct answers
3. Note peopleAlsoAsk if relevant
4. If a result needs deeper content, use mcp__serper__scrape(url="<url>")
5. Max 3 Serper calls total.
6. Write findings to <RUN_DIR>/serper.md using the scratch file schema
(answerBox/KG answer, top 2-3 organic results with snippets, URLs).
7. Return ONLY: "done: <RUN_DIR>/serper.md"
If the MCP returns no results or errors:
- Write a 1-line note to <RUN_DIR>/serper.md: "Serper unavailable: <reason>"
- Return ONLY: "unavailable: <reason>"
- Do NOT fall back to local knowledge.
Do not print evidence, URLs, or snippets in your return message.
You are researching technical concepts via Tavily AI search.
Do NOT use WebSearch or WebFetch. Use ONLY the MCP tools below.
Tools:
- mcp__tavily__tavily_search(query="<natural language>", search_depth="basic"|"advanced")
- mcp__tavily__tavily_extract(urls=["..."], query="<question>")
Query style: NATURAL LANGUAGE.
BAD: "express rate-limit 2026"
GOOD: "How to implement rate limiting in Express 5 with middleware best practices"
Depth:
- Quick factual → search_depth="basic" [1 credit]
- How-to/analysis → search_depth="advanced" [2 credits]
- Full page content → add include_raw_content=true
- DO NOT use tavily_research (15-250 credits) without explicit coordinator OK.
Steps:
1. Search with appropriate depth
2. If snippets insufficient, extract from 1 promising URL
3. Max 3 Tavily calls.
4. Write findings to <RUN_DIR>/tavily.md using the scratch file schema
(Direct answer, key supporting detail or code pattern, Source URLs).
5. Return ONLY: "done: <RUN_DIR>/tavily.md"
If the MCP returns no results or errors:
- Write a 1-line note to <RUN_DIR>/tavily.md: "Tavily unavailable: <reason>"
- Return ONLY: "unavailable: <reason>"
- Do NOT fall back to local knowledge.
Do not print evidence, URLs, or snippets in your return message.
You are analyzing the local codebase for patterns and usage.
Do NOT use WebSearch or WebFetch.
Question: <question>
Use Grep, Glob, and Read to discover:
- How is this pattern used in our code?
- What constraints exist?
- Precedents or similar code?
Steps:
1. Run the searches needed to answer.
2. Write findings to <RUN_DIR>/codebase.md using the scratch file schema
(Findings, file:line references, confidence).
3. Return ONLY: "done: <RUN_DIR>/codebase.md"
If you find nothing relevant:
- Write "No relevant patterns found" to <RUN_DIR>/codebase.md with confidence 25.
- Return ONLY: "done: <RUN_DIR>/codebase.md"
Do not print findings or file contents in your return message.
You are searching GitHub for real-world OSS patterns via the gh CLI.
Do NOT use WebSearch or WebFetch. Use ONLY the Bash tool with gh commands.
Topic: <topic>
Question: <question>
Find:
- 2-3 popular public repo examples
- How they solve this problem
- Observable best practices
Steps:
1. `gh search code '<query>' --language=<lang>` — find relevant files. Keep flags OUTSIDE the quoted query (e.g. `gh search code 'rate limit middleware' --language=ts`); flags inside the quotes become literal search terms.
2. `gh search repos '<topic>' --sort stars` — discover canonical repos.
3. `gh repo view owner/repo` — read README for promising hits.
4. Max 5 gh calls total.
5. Write findings to <RUN_DIR>/gh-github.md using the scratch file schema
(Key patterns as bullets, 1-2 code snippets with repo links).
6. Return ONLY: "done: <RUN_DIR>/gh-github.md"
If gh returns no results or errors:
- Write a 1-line note to <RUN_DIR>/gh-github.md: "gh unavailable: <reason>"
- Return ONLY: "unavailable: <reason>"
- Do NOT fall back to local knowledge.
Empty results are NOT failures. If gh runs but finds no matches for a
niche query, write "No public examples found" to the scratch file with
confidence 25 and return "done: <RUN_DIR>/gh-github.md".
Do not print evidence, URLs, or snippets in your return message.
All fetchers run in parallel via a single-message batch of Agent calls. Each
returns one short line. Assemble a status map:
FETCHER STATUS:
- context7: done: <RUN_DIR>/context7.md
- serper: done: <RUN_DIR>/serper.md
- tavily: unavailable: MCP not reachable
- codebase: done: <RUN_DIR>/codebase.md
- gh-github: done: <RUN_DIR>/gh-github.md
Do NOT read the scratch files yourself. They go to the synthesis sub-agent.
Spawn one Agent call with subagent_type="general-purpose",
model="opus". The synthesis sub-agent is the part that thinks hard — it
reads every scratch file, cross-checks sources, applies the mechanical cap,
and emits a compact answer. Give it permission and budget to reason
carefully; do not constrain it to a fast-and-loose summary.
If --report was passed in Phase 0, include the line REPORT_MODE: true
in the synthesis prompt (see template below). The sub-agent then emits a
complete report body in addition to the synthesis; the skill writes that
body to disk without ever reading scratch files itself.
You are the synthesis stage of a multi-source research run. Think carefully
before writing — this is the reasoning-heavy part of the pipeline.
Question: <original research question>
REPORT_MODE: <true|false> # true when caller passed --report
Fetcher status (from the skill):
- context7: <done|unavailable|not-routed> [path or reason]
- serper: ...
- tavily: ...
- codebase: ...
- gh-github: ...
Read each "done" file with the Read tool. Ignore "unavailable" and
"not-routed" entries for content purposes but count them in the cap below.
Task:
1. Build an evidence table with one row per ROUTED source (not just "done"
ones). Columns: Source | Finding (1 sentence) | Score (0-100) | Notes.
For sources marked unavailable or not-routed, put "N/A — <reason>" in
Score.
2. Apply the MECHANICAL confidence cap:
- failures = count of rows where Score is "N/A" OR Notes contain
`not spawned`, `unavailable`, `failed`, `skipped`, `not fetched`, `error`
- If failures > 0:
* Overall Confidence starts with `≤49 (INCOMPLETE — <N> sources missing)`
* Prepend synthesis with: `⚠️ INCOMPLETE RESEARCH — <names> not reached.`
* This cap is non-negotiable. Do not reclassify failures as intentional.
- Else:
* 3+ sources agree → 85-100
* 2 sources agree → 60-84
* Disagreement → cap at 49 and note why
* 1 source only → inherit that source's score
3. Emit the synthesis in exactly this format:
## Research: <Question>
[⚠️ INCOMPLETE RESEARCH line if applicable]
### Finding
<1-3 paragraphs, synthesized from all available sources. No raw snippets.>
### Evidence by Source
| Source | Finding | Score | Notes |
|---|---|---|---|
| ... |
### Implications
<How this affects the caller's task, 2-4 sentences.>
### Overall Confidence
**<score>** — <justification based on source agreement and completeness>
Keep the synthesis tight. The caller does NOT need to see raw evidence —
only the distilled answer, the table, and the confidence line.
Do not reference the scratch file paths in the synthesis. Cite concrete
URLs / file:line refs / library doc refs from the scratch files instead.
4. **If `--report` mode is set** (the skill will tell you via a `REPORT_MODE:
true` line in this prompt): after the synthesis block, append a complete
report body ready to be written to disk. The report body is the ONLY
place raw URLs / file refs / repo links go. Format:
```markdown
# Research Report: <Topic>
_Generated: <YYYY-MM-DD>_
<full synthesis block you just wrote>
## Sources
### Documentation
- <Context7 doc refs from scratch files>
### Web
- <URLs from Serper / Tavily scratch files>
### Codebase
- <file:line references from codebase scratch file>
### Open Source
- <GitHub repo / file links from gh-github scratch file>
```
Only include source sections that have entries. Extract the URLs / refs
by reading the `## Sources` block of each scratch file you have access
to. Wrap the report body in a fenced block labelled `report-body` so the
skill can split it from the synthesis cleanly:
```report-body
<report markdown here>
```
The sub-agent returns the full synthesis block (and, if --report was set, a
fenced report-body block after it). Pass the synthesis block through to the
user verbatim (do not re-summarize). In --report mode, hand the
report-body contents to Phase 5 without reading/inspecting them in the
skill's own context.
If --report was specified in Phase 0:
The synthesis sub-agent from Phase 4 returned a report-body fenced
block. Write that block's contents verbatim to the target path. Do NOT
read scratch files in this phase — the synthesis sub-agent already
assembled the Sources appendix.
Tell the user where the report was saved.
rm -rf "$RUN_DIR" once the synthesis (and, in --report mode,
the report write) is complete. Scratch files in $TMPDIR are throwaway —
the durable artifacts are the synthesis in the caller's message history
and, optionally, the report file under .claude/research/.--report modestavily_research (15-250 credits) without explicit user requestRead on a fetcher output, stop — that raw data
belongs in the synthesis sub-agent's context, not yours.tavily_research is expensive (15-250 credits vs 1-2 for
tavily_search). Only when the user explicitly opts in.include_raw_content on Tavily search combines search + extract in one
call — saves a tavily_extract call.tools
Reconstruct what a past coding-agent session was doing so you can resume it — goal, files touched, last verified state, and the next step — by querying the session logs. Use when the user says "what was I working on", "recover that session", "reconstruct where I left off", "resume my last session", "what did that session change", "rebuild context from logs", or invokes /work-recovery. Report-only — it never scores or judges. Do NOT use for usage scoring (that is /skill-improver, /tool-efficiency, /prompt-analytics) or one-off interactive log queries (that is /session-analytics).
development
Curate this repo's hallouminate wiki (.hallouminate/wiki/, the repo:dotfiles:wiki corpus) — add or update architecture pages, per-harness docs, and gotchas. Use when the user says "update the wiki", "document this in the wiki", "refresh the harness docs", "add a wiki page", "curate the wiki", "the wiki is stale", or invokes /wiki-curator. Also use at session end to write back a non-obvious decision or gotcha worth preserving. Grounds the existing wiki first, follows one-topic-per-file conventions, verifies every external doc URL before writing, and reindexes. Do NOT use for general code search (that is cheez-search) or for editing AGENTS.md command reference.
tools
Audit how a tool, command, or MCP server is actually used across coding-agent sessions and produce calibrated recommendations — tool-vs-task fit, error forensics, fix recommendations, permission friction, MCP health, and token economics. Use when the user says "tool efficiency", "am I using X efficiently", "audit tool usage", "why does X keep failing", "how do I fix this error", "what should I change", "permission friction", "is this MCP worth it", "tool error rate", "fix recommendations", or invokes /tool-efficiency. Do NOT use for auditing a skill or agent definition (that is /skill-improver) or for one-off interactive log queries (that is /session-analytics).
tools
Analyze how prompts and skill routing behave across coding-agent sessions and produce calibrated recommendations — prompt-pattern analysis, routing accuracy, and knowledge gaps. Use when the user says "analyze my prompts", "prompt patterns", "is routing working", "which skill should have fired", "knowledge gaps", "what do I keep asking", or invokes /prompt-analytics. Do NOT use for auditing a single skill/agent definition (that is /skill-improver), tool/MCP efficiency (that is /tool-efficiency), or one-off interactive log queries (that is /session-analytics).