
Research Report
- 46 installs
- 6 repo stars
- Updated July 22, 2026
- julianobarbosa/claude-code-skills
Summarise completed deep-research run into single markdown report - full coverage of every defined field, automatic skipping of uncertain values.
About
Summarise deep-research run into markdown report - full field coverage, automatic skipping of uncertain values, navigable table of contents.. Generates fresh generate_report.py per run.
- intermediate skill
- core: ai & agent building
Research Report by the numbers
- 46 all-time installs (skills.sh)
- +3 installs in the week ending Aug 2, 2026 (Skillselion tracking)
- Ranked #7,568 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 3, 2026 (Skillselion catalog sync)
npx skills add https://github.com/julianobarbosa/claude-code-skills --skill research-reportAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 46 |
|---|---|
| repo stars | ★ 6 |
| Last updated | July 22, 2026 |
| Repository | julianobarbosa/claude-code-skills ↗ |
What it does
Summarise completed deep-research run into single markdown report - full coverage of every defined field, automatic skipping of uncertain values.
Files
Research Report — Summary Report
Reads the JSON files produced by /research-deep and emits a single markdown report at {topic}/report.md.
Trigger
/research-report
Pipeline position
/research-outline → /research-add-* → /research-deep → ► /research-report ◄Workflow
Step 1 — Locate results directory
Glob */outline.yaml in the current working directory. Read it to get topic and execution.output_dir.
Step 2 — Scan optional summary fields
Read every JSON under output_dir. Collect candidate fields suitable for the table-of-contents column — short, numeric, or scalar metrics. Typical candidates:
github_starsgoogle_scholar_citesswe_bench_scoreuser_scalevaluationrelease_date
AskUserQuestion: "Which of these summary fields do you want next to each item in the TOC?" — present the dynamic list of fields you actually found in this run's JSON files.
AskUserQuestion has a hard cap of four options per question. If you found more than four candidates, either ask twice (covering different field groups), or pick the four most informative-looking candidates yourself and ask the user to confirm or override.
Step 3 — Generate the report script
Write {topic}/generate_report.py. The script's behaviour is specified in `references/report-generation-spec.md` — read that file before writing the script. It covers JSON shape compatibility, category-name multi-language mapping, complex value formatting, extra-fields collection, uncertain-value skipping, and TOC formatting.
Why the script is regenerated each run instead of bundled as-is: each topic has slightly different field categories and value shapes. Letting the model write the script per run lets it adapt the formatting choices to what the JSON actually contains, while the spec ensures every script meets the same minimum contract.
Step 4 — Execute the script
Run python {topic}/generate_report.py. Check the resulting {topic}/report.md exists and is non-empty; report the path back to the user.
Output
{topic}/generate_report.py— per-run conversion script{topic}/report.md— summary report
Gotchas
- The `CATEGORY_MAPPING` lives in two places: in the generated
generate_report.pyand in~/.claude/skills/research-outline/validate_json.py. They must agree, or the report will skip categories the validator just accepted. If you add a new category infields.yaml, update both files (seereferences/report-generation-spec.mdfor the canonical mapping). - `AskUserQuestion` caps at four options. If Step 2 turns up more than four summary-field candidates, you need to either chunk the question into multiple rounds or pre-filter the list yourself before asking. Don't silently truncate to four — the user needs to know what was left off.
- `[uncertain]` in a value and presence in the `uncertain` array are both skip-triggers, and either alone is enough. Don't AND them.
- Anchor slugs are markdown's auto-slug, not your own slugifier. Make sure your TOC link
#xxxmatches what the markdown renderer derives from your## Item Nameheader — lowercase, spaces → hyphens, most punctuation stripped. If item names have unusual characters, render the section with a known-safe heading text. - Empty `output_dir` means
/research-deepeither hasn't run or hasn't completed any items. Don't generate an empty report — surface the state to the user.
Report-Generation Spec
This file is the contract the Python script generated by /research-report must satisfy. The skill instructs the model to write generate_report.py each run (so it can adapt to per-topic quirks), but every generated script must implement the requirements below or the resulting markdown will be incomplete or wrong.
Inputs
output_dir/*.json— one JSON per item, produced by/research-deep.fields.yaml— field schema produced by/research-outline, with the same shapevalidate_json.pyexpects (field_categories[].fields[]).- User selection from
AskUserQuestion— which short / numeric fields to include in the table-of-contents alongside each item's name.
Output
{topic}/report.md — single markdown file with:
1. A table of contents listing every item with an anchor link and the user-chosen summary fields. 2. A detailed section per item, organised by field_categories from fields.yaml.
Requirements
1. JSON structure compatibility
Per-item JSON may be flat or nested. Support both:
- Flat — fields at top level:
{"name": "xxx", "release_date": "yyy", ...} - Nested — fields grouped under category keys:
{"basic_info": {"name": "xxx"}, "technical_features": {...}}
Field lookup order:
1. Top level 2. Category key per CATEGORY_MAPPING (below) 3. Recursively traverse any nested dicts as a last resort
2. Category multi-language mapping
fields.yaml category labels and JSON keys can be any mix of English snake_case and other naming. Establish a bidirectional mapping. Keep it aligned with the same mapping in validate_json.py — those two files are the only places this mapping lives. If you change one, mirror it in the other.
CATEGORY_MAPPING = {
"Basic Info": ["basic_info", "Basic Info"],
"Technical Features": ["technical_features", "technical_characteristics", "Technical Features"],
"Performance Metrics": ["performance_metrics", "performance", "Performance Metrics"],
"Milestone Significance": ["milestone_significance", "milestones", "Milestone Significance"],
"Business Info": ["business_info", "commercial_info", "Business Info"],
"Competition & Ecosystem": ["competition_ecosystem", "competition", "Competition & Ecosystem"],
"History": ["history", "History"],
"Market Positioning": ["market_positioning", "market", "Market Positioning"],
}3. Complex value formatting
- List of dicts (e.g.
key_events,funding_history): one dict per line, separatekey | value | key | value. - Plain list: short → comma-joined inline; long → one per line as a bullet list.
- Nested dict: recursive format, separate keys with
;inline or use line breaks for readability. - Long string (>100 chars): line breaks with
<br>or use blockquote (> ...) so the markdown renders cleanly.
4. Extra fields (defined in JSON but not in fields.yaml)
Collect anything that's in a per-item JSON but not declared in fields.yaml. Put them under a final ## Other Info heading per item. Filter out:
- Internal keys:
_source_file,uncertain. - Category-key wrappers when the JSON is nested (e.g. don't render the literal string
basic_infoas a field — its children are already rendered above). - The
uncertainarray — display each entry on its own line; never compress to a single comma line.
5. Uncertain-value skipping
Skip the field entirely (don't print the label) if any of:
- The value (after string-cast) contains the literal substring
[uncertain]. - The field name appears in the item's
uncertainarray. - The value is
None,"", or an empty list/dict.
6. Table of contents
- One row per item, every item included.
- Each row shows:
1. [Item Name](#item-name-anchor) — Field1: value | Field2: value. - Use the same slug for the anchor as you used for the item's section header (markdown auto-generates anchors from headers — lowercase, spaces → hyphens, punctuation stripped).
Anchor for design intent
The report is for humans skimming first, then reading. Optimise for: (a) at-a-glance comparison via TOC, (b) clean per-item sections that don't drown the reader in [uncertain] placeholders. If you find yourself printing more [uncertain] than real values, the upstream deep-research run probably needs more passes — that's not a report problem.