Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Tools and pipelines for automating systematic literature reviews
.claude/skills/brycewang-stanford-slr-automation-guide/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-10 | ✗→✓ | ▲ Improved | 57% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 25% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 146% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 27% | 0% |
| case-07 | ✗→✓ | ▲ Improved | 60% | 0% |
Systematic Literature Reviews (SLRs) are rigorous, reproducible surveys of research evidence following protocols like PRISMA and Cochrane. This guide covers tools that automate the most time-consuming steps — deduplication, title/abstract screening, full-text assessment, and data extraction — using active learning, NLP, and AI agents. Key tools include ASReview, Rayyan, and custom pipelines.
Protocol Definition (PICO, inclusion/exclusion criteria)
↓
Database Search (PubMed, Scopus, Web of Science)
↓
Deduplication (ASReview, Rayyan, or custom)
↓
Title/Abstract Screening (AI-assisted prioritization)
↓
Full-text Assessment (relevance + quality)
↓
Data Extraction (structured tables)
↓
Quality Assessment (risk of bias)
↓
Synthesis + PRISMA Reportbash# Install ASReview pip install asreview # Launch web interface asreview lab # CLI screening asreview simulate benchmark:van_de_Schoot_2017 \ -m nb -e tfidf \ --n_prior_included 5 --n_prior_excluded 5 \ -o results/simulation.asreview
pythonimport asreview from asreview import ASReviewData, ReviewSimulate # Load dataset (RIS, CSV, or Excel) data = ASReviewData.from_file("search_results.ris") print(f"Records: {len(data)}") # Active learning simulation sim = ReviewSimulate( data, model="nb", # Naive Bayes classifier feature_extraction="tfidf", query_strategy="max", # Show most likely relevant first n_prior_included=5, n_prior_excluded=5, ) sim.review() # Results: screening order optimized by relevance print(f"Work saved: {sim.work_saved():.1%}") # Typically 80-95% of irrelevant papers screened out early
python# ASReview deduplication from asreview.data import ASReviewData # Merge results from multiple databases datasets = [ ASReviewData.from_file("pubmed_results.ris"), ASReviewData.from_file("scopus_results.ris"), ASReviewData.from_file("wos_results.ris"), ] merged = ASReviewData.from_dataframe( pd.concat([d.df for d in datasets]) ) print(f"Before dedup: {len(merged)}") # Fuzzy matching on title + DOI deduplicated = merged.deduplicate() print(f"After dedup: {len(deduplicated)}")
python# Custom LLM screening pipeline from slr_tools import LLMScreener screener = LLMScreener( llm_provider="anthropic", criteria={ "population": "Adults with type 2 diabetes", "intervention": "SGLT2 inhibitors", "outcomes": "Cardiovascular events", "study_types": ["RCT", "cohort", "meta-analysis"], "exclusions": ["animal studies", "in vitro", "pediatric"], }, ) # Screen abstracts results = screener.screen_batch( records=search_results, fields=["title", "abstract"], threshold=0.5, # Include if P(relevant) > 0.5 ) for r in results: print(f"[{'INCLUDE' if r.include else 'EXCLUDE'}] " f"(p={r.confidence:.2f}) {r.title[:60]}...") print(f" Reason: {r.reason}")
python# Structured data extraction from full-text papers from slr_tools import DataExtractor extractor = DataExtractor( llm_provider="anthropic", schema={ "study_design": "str", "sample_size": "int", "population_description": "str", "intervention_details": "str", "primary_outcome": "str", "effect_size": "float", "confidence_interval": "str", "p_value": "float", "follow_up_duration": "str", "risk_of_bias": "str", }, ) # Extract from PDF extracted = extractor.extract("paper.pdf") print(extracted.to_dict()) # Batch extraction results_df = extractor.extract_batch("fulltext_papers/") results_df.to_csv("extraction_table.csv")
python# Generate PRISMA 2020 flow diagram from slr_tools import PRISMAFlow flow = PRISMAFlow( identification={ "databases": {"PubMed": 1200, "Scopus": 890, "WoS": 650}, "other_sources": {"citation_search": 45}, }, screening={ "after_dedup": 1850, "excluded_title_abstract": 1620, "sought_fulltext": 230, "not_retrieved": 12, }, included={ "assessed_fulltext": 218, "excluded_fulltext": { "wrong_population": 45, "wrong_intervention": 32, "wrong_outcome": 28, "wrong_study_type": 15, }, "final_included": 98, }, ) flow.save_svg("prisma_flow.svg") flow.save_latex("prisma_flow.tex")
python# Risk of Bias assessment (Cochrane RoB 2) from slr_tools import RiskOfBias rob = RiskOfBias(tool="rob2") # or "robins_i" for non-RCTs assessment = rob.assess( paper="paper.pdf", domains=[ "randomization_process", "deviations_from_intervention", "missing_outcome_data", "outcome_measurement", "selection_of_reported_result", ], ) print(f"Overall: {assessment.overall_judgment}") for domain, judgment in assessment.domain_judgments.items(): print(f" {domain}: {judgment}")
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-10 | fail→pass | 11,888 | 5,692 | -52% | 1 | 1 | 0% | 1,834 | 2,874 | +57% | 0 | 0 | — |
case-15 | fail→fail | 19,746 | 12,083 | -39% | 1 | 1 | 0% | 2,915 | 3,989 | +37% | 0 | 0 | — |
case-09 | fail→pass | 15,192 | 11,954 | -21% | 1 | 1 | 0% | 3,006 | 3,771 | +25% | 0 | 0 | — |
case-01 | fail→fail | 30,932 | 43,742 | +41% | 1 | 1 | 0% | 5,067 | 5,912 | +17% | 0 | 0 | — |
case-02 | fail→pass | 10,536 | 19,775 | +88% | 1 | 1 | 0% | 2,319 | 5,712 | +146% | 0 | 0 | — |
case-03 | fail→pass | 23,770 | 30,291 | +27% | 1 | 1 | 0% | 5,462 | 6,956 | +27% | 0 | 0 | — |
case-04 | pass→pass | 7,418 | 4,520 | -39% | 1 | 1 | 0% | 1,413 | 2,585 | +83% | 0 | 0 | — |
case-05 | pass→pass | 8,079 | 5,093 | -37% | 1 | 1 | 0% | 1,608 | 2,392 | +49% | 0 | 0 | — |
case-06 | fail→fail | 18,930 | 13,492 | -29% | 1 | 1 | 0% | 3,503 | 4,440 | +27% | 0 | 0 | — |
case-07 | fail→pass | 10,782 | 8,510 | -21% | 1 | 1 | 0% | 2,143 | 3,424 | +60% | 0 | 0 | — |
case-08 | fail→pass | 11,947 | 6,932 | -42% | 1 | 1 | 0% | 2,348 | 3,052 | +30% | 0 | 0 | — |
case-11 | pass→pass | 1,834 | 1,170 | -36% | 1 | 1 | 0% | 299 | 1,891 | +532% | 0 | 0 | — |
case-12 | pass→pass | 2,634 | 2,407 | -9% | 1 | 1 | 0% | 390 | 1,948 | +399% | 0 | 0 | — |
case-13 | fail→pass | 8,670 | 5,084 | -41% | 1 | 1 | 0% | 1,546 | 2,618 | +69% | 0 | 0 | — |
case-14 | fail→pass | 13,119 | 8,074 | -38% | 1 | 1 | 0% | 2,336 | 2,907 | +24% | 0 | 0 | — |
case-16 | pass→pass | 14,532 | 14,037 | -3% | 1 | 1 | 0% | 2,091 | 4,317 | +106% | 0 | 0 | — |
case-17 | pass→pass | 9,489 | 11,549 | +22% | 1 | 1 | 0% | 1,628 | 3,636 | +123% | 0 | 0 | — |
case-18 | fail→pass | 5,134 | 2,862 | -44% | 1 | 1 | 0% | 857 | 2,135 | +149% | 0 | 0 | — |
case-19 | fail→pass | 7,850 | 2,236 | -72% | 1 | 1 | 0% | 1,296 | 2,146 | +66% | 0 | 0 | — |
case-20 | pass→pass | 23,816 | 23,912 | +0% | 1 | 1 | 0% | 4,504 | 6,473 | +44% | 0 | 0 | — |
case-21 | pass→pass | 15,503 | 18,331 | +18% | 1 | 1 | 0% | 2,795 | 4,673 | +67% | 0 | 0 | — |
case-22 | pass→pass | 15,976 | 14,709 | -8% | 1 | 1 | 0% | 2,974 | 4,645 | +56% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +45 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.