agentleFS
zamushwanizamushwani/biomedical-ai-skills/skills/variant-annotation/SKILL.md

variant-annotation

Skill1 starsChanged 3 months agoMITView on GitHub

Annotation and clinical interpretation of DNA variants in cancer. Covers VCF normalization and filtering, functional annotation with VEP, germline classification under ACMG/AMP, somatic classification under the AMP/ASCO/CAP tiers and the ClinGen/CGC/VICC oncogenicity standard, tumor mutational burden, microsatellite instability, and neoantigen prediction. Activate when the user requests: - VCF filtering, normalization, or merging - Functional annotation (VEP, SnpEff, ANNOVAR) - Germline variant classification (ACMG/AMP, pathogenic vs benign) - Somatic variant classification (tiers, oncogenicity, actionability) - Driver vs passenger discrimination - OncoKB…

2 other projects use a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

1 rule. About 0 are common, 0 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈0

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Treat the output as a ranked hypothesis list for experimental testing, in the same way in-silico perturbation output is treated in …

    line 402

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Variant Annotation

Annotation and clinical interpretation of DNA variants in cancer. Covers VCF normalization and filtering, functional annotation with VEP, germline classification under ACMG/AMP, somatic classification under the AMP/ASCO/CAP tiers and the ClinGen/CGC/VICC oncogenicity standard, tumor mutational burden, microsatellite instability, and neoantigen prediction.

When to Use This Skill

Activate when the user requests:

  • VCF filtering, normalization, or merging
  • Functional annotation (VEP, SnpEff, ANNOVAR)
  • Germline variant classification (ACMG/AMP, pathogenic vs benign)
  • Somatic variant classification (tiers, oncogenicity, actionability)
  • Driver vs passenger discrimination
  • OncoKB or CIViC evidence lookup
  • Tumor mutational burden calculation
  • Microsatellite instability estimation
  • Neoantigen prediction or HLA binding
  • Interpreting a variant of uncertain significance

Inputs

Data TypeFormatSource
Variant callsVCF 4.2+, bgzipped and indexedGATK, Mutect2, DeepVariant, Strelka2
Reference genomeFASTA with .faiGRCh38 (or GRCh37 for legacy cohorts)
Somatic MAFMutation Annotation FormatTCGA GDC, cBioPortal
Panel definitionBEDAssay manufacturer, for TMB denominators
HLA type4-digit allelesOptiType, HLA-HD, arcasHLA

Environment

Versions verified 2026-08.

bcftools            1.24        VCF manipulation, normalization
Ensembl VEP         116.1       functional annotation, the current default
SnpEff              5.4c        alternative annotator
ANNOVAR             current     still distributed, registration required

Bioconductor
  VariantAnnotation 1.58.0      VCF parsing and coding consequences in R
  maftools          2.28.0      somatic MAF summarization, TMB, signatures

Neoantigens
  pVACtools         7.1.2       neoantigen pipeline (griffithlab)
  NetMHCpan         4.1+        MHC class I binding; academic licence
Microsatellite instability, and which tool is still alive:

  msisensor       ARCHIVED. ding-lab/msisensor was archived, last push 2021.
                  Do not start new work on it.
  msisensor-pro   v1.3.0 (2024-09). Current choice, tumor-only or paired.
  msisensor2      last push 2024-04. Tumor-only, no matched normal.
  MANTIS          paired tumor/normal, still used in clinical settings.

All four are read-based. MSI can also be inferred from a panel using
MSIsensor-pro's baseline mode, but the baseline must be built on the same
assay or the calls are not comparable.

The Three Frameworks

This is the part that gets conflated, and conflating it produces reports that are wrong in a way reviewers notice.

GERMLINE PATHOGENICITY            ACMG/AMP 2015
  Question: does this inherited variant cause disease?
  Output:   Pathogenic / Likely pathogenic / VUS / Likely benign / Benign
  Applies:  germline findings only

SOMATIC ONCOGENICITY              ClinGen/CGC/VICC 2022 SOP
  Question: is this variant driving the cancer?
  Output:   Oncogenic / Likely oncogenic / VUS / Likely benign / Benign
  Applies:  somatic variants, biology only, no treatment implication

SOMATIC CLINICAL SIGNIFICANCE     AMP/ASCO/CAP 2017 tiers
  Question: does this variant change patient management?
  Output:   Tier I (strong) / II (potential) / III (unknown) / IV (benign)
  Applies:  somatic variants, actionability in a given tumour type
Oncogenicity and clinical significance are DIFFERENT AXES, not alternatives.

  A KRAS G12D is clearly oncogenic and may still be Tier III in a tumour type
  with no approved KRAS-directed option.

  A variant may be Tier I because it predicts resistance, without being a
  driver at all.

ClinGen's own guidance is that somatic expert panels should apply BOTH the
oncogenicity SOP and the AMP/ASCO/CAP guidelines, not choose between them.
Report both, and say which is which.

Never apply ACMG/AMP to a somatic variant. The criteria assume germline
inheritance, population frequency in gnomAD as evidence of benignity, and
segregation data. None of that transfers.

VCF Processing

Normalize before anything else

Un-normalized VCFs are the single largest source of silent annotation failure. The same variant can be written several ways, and a lookup against a knowledgebase misses every representation but one.

# Split multiallelic sites, left-align, and trim to the minimal representation
bcftools norm -m -any -f GRCh38.fa -Oz -o normalized.vcf.gz input.vcf.gz
bcftools index normalized.vcf.gz
What each part fixes:

  -m -any      splits multiallelic records into one ALT per line. A
               knowledgebase keyed on a single ALT never matches a
               multiallelic record.
  -f <ref>     left-aligns indels against the reference. AAT->AT and
               ATT->AT can describe the same deletion; only one is canonical.
  trimming     removes shared leading/trailing bases so the representation
               is minimal.

Skipping this does not raise an error. It produces annotations that are
simply absent, and absent looks like "not in the database".

Filtering

# Keep PASS calls only, then apply depth and allele fraction thresholds
bcftools view -f PASS normalized.vcf.gz \
  | bcftools filter -i 'FORMAT/DP >= 20 && FORMAT/AF >= 0.05' -Oz -o filtered.vcf.gz
Thresholds are assay-dependent, not universal:

  Germline, WGS/WES     DP >= 10-20, AF >= 0.25 for het calls
  Somatic, tumour-only  DP >= 50, AF >= 0.05, and a panel of normals
  Somatic, deep panel   DP >= 500, AF >= 0.01 possible; below 0.05 needs UMIs
  ctDNA                 AF >= 0.001 with UMI consensus, otherwise noise

Tumour-only calling without a matched normal cannot separate somatic from
germline. Expect 30-60% of calls to be germline unless you filter against
gnomAD and a panel of normals, and say in the report that you did so.

Reference genome

GRCh37 and GRCh38 coordinates are NOT interchangeable. A position annotated
against the wrong build silently lands in a different gene.

Check the VCF header contig lines before annotating. If the source is TCGA
legacy data it is GRCh37; current GDC releases are GRCh38.

Chromosome naming also differs: "1" (Ensembl) vs "chr1" (UCSC/GDC). A build
mismatch usually errors; a naming mismatch often just returns nothing.

Functional Annotation

VEP

vep --input_file filtered.vcf.gz --output_file annotated.vcf \
    --vcf --cache --offline --assembly GRCh38 \
    --everything \
    --pick_allele_gene \
    --fasta GRCh38.fa \
    --plugin dbNSFP,dbNSFP.gz,SIFT_score,Polyphen2_HDIV_score,REVEL_score,CADD_phred \
    --plugin SpliceAI,snv=spliceai_snv.vcf.gz,indel=spliceai_indel.vcf.gz
The transcript choice is a scientific decision, not a formatting one.

  (no flag)          one line per transcript. Complete, but a variant can
                     appear 30 times with different consequences.
  --pick             ONE consequence per variant, chosen by VEP's ordering.
                     Convenient and lossy.
  --pick_allele_gene one per allele per gene. Usually the right default for
                     clinical reporting.
  --flag_pick        annotates everything but marks the picked one. Best when
                     you want the full picture and a canonical choice.

Reporting "the" consequence of a variant without stating the transcript is
ambiguous. MANE Select is the current convention for a canonical human
transcript; state which transcript the report used.

Choosing an annotator

VEP        Ensembl, release 116.1, updated with each Ensembl release.
           Richest plugin ecosystem (dbNSFP, SpliceAI, LoFtee, AlphaMissense).
           Default choice.

SnpEff     5.4c. Fast, self-contained, easy to run on non-model organisms.
           Fewer clinical plugins.

ANNOVAR    Still distributed and widely cited. Registration required, and
           its database bundles are updated on their own schedule rather
           than with a genome release. Check the date on any -operation
           database you use.

Germline Classification

ACMG/AMP 2015 remains the framework. ClinGen has not replaced it; it publishes criterion-level refinements that supersede the original wording.

Evidence strength combines into a classification:

  Pathogenic       1 Very strong + >=1 Strong, or other documented combinations
  Likely path.     combinations one step weaker
  VUS              insufficient or conflicting evidence
  Likely benign / Benign   BA1, BS, BP criteria

Refinements to apply, from ClinGen (current as of the July 2025 guidance page):

  PM2      absence/rarity recalibrated to SUPPORTING strength, not moderate
  PS2/PM6  de novo criteria, with a points table by phenotype specificity
  PM3      in trans observations, scaled by how well the second variant is
           classified
  BA1      has an exception list; some variants exceed 5% and are still
           pathogenic in specific populations
  splicing recommendations updated March 2024
  gnomAD   v4-specific guidance issued March 2024

A points-based formulation (Tavtigian et al.) is ENDORSED by ClinGen, not
mandated. Using it is defensible; claiming it is the official replacement
for the 2015 rules is not.
Population frequency, done correctly:

  Use the popmax (grpmax) filtering allele frequency, not the global AF.
  A variant at 0.1% globally can be 4% in one ancestry group, which is
  strong evidence of benignity that a global AF hides.

  gnomAD v4 separates exomes and genomes; check which subset supports the
  count, and check the allele NUMBER. A frequency computed from 4 alleles
  is not evidence.

Somatic Classification

Oncogenicity: is it a driver?

ClinGen/CGC/VICC 2022 SOP. Evidence weighted very strong / strong /
moderate / supporting, in the spirit of ACMG/AMP but with cancer-specific
criteria and a points-based sum.

Signals that carry weight:
  Null variant in a bona fide TUMOUR SUPPRESSOR       strong
  Well-established hotspot in an ONCOGENE             strong
  Functional data showing gain or loss of function    strong to moderate
  Recurrence across independent tumours (COSMIC)      moderate
  Computational prediction alone                      supporting at best

The gene's mechanism decides which criteria apply. A truncating variant is
strong evidence in a tumour suppressor and usually irrelevant in an oncogene.
Applying tumour-suppressor logic to an oncogene is the most common error here.

Clinical significance: does it change management?

AMP/ASCO/CAP 2017 tiers, always tumour-type specific:

  Tier I    Strong clinical significance
            IA: FDA-approved therapy or professional guideline, THIS tumour type
            IB: well-powered studies with consensus
  Tier II   Potential clinical significance
            IIC: approved for a DIFFERENT tumour type, or in trial eligibility
            IID: plausible from smaller studies
  Tier III  Unknown clinical significance
  Tier IV   Benign or likely benign

BRAF V600E is Tier IA in melanoma and Tier IIC in colorectal cancer, where
single-agent BRAF inhibition fails because of EGFR feedback. Same variant,
same oncogenicity, different tier. Tier assignment without naming the tumour
type is meaningless.

Knowledgebases

# OncoKB: therapeutic levels of evidence, requires a free academic token
curl -H "Authorization: Bearer $ONCOKB_TOKEN" \
  "https://www.oncokb.org/api/v1/annotate/mutations/byGenomicChange?genomicLocation=7,140453136,140453136,A,T"

# CIViC: open, no token
curl "https://civicdb.org/api/variants?count=1&name=V600E"
OncoKB levels are not AMP tiers, though they map roughly:
  Level 1  FDA-recognized biomarker for an approved drug, this indication
  Level 2  standard care biomarker per guidelines
  Level 3A clinical evidence in this indication
  Level 3B clinical evidence in a different indication
  Level 4  compelling biological evidence
  R1/R2    resistance

Both databases are curated snapshots. Record the version or access date in
the report, because a Tier III today can become Tier I after an approval.

Tumour Mutational Burden

TMB = eligible somatic mutations / eligible megabases of the panel.

Every term is assay-specific, which is why panel TMB values are not
comparable across assays without harmonization:

  numerator    Are synonymous variants counted? FMI counts them; many
               pipelines do not. Including them raises TMB by roughly 20-30%.
               Are indels counted? Are hotspots removed?
  denominator  The callable territory of THAT panel, not the panel's
               nominal size.
  germline     Tumour-only assays must filter germline variants; the method
               used changes the count materially.

The Friends of Cancer Research TMB Harmonization Project exists precisely
because panel TMB did not agree across vendors. A "TMB-high" call is only
interpretable alongside the assay and its cutoff.
library(maftools)   # v2.28.0

maf <- read.maf("cohort.maf")
tmb_res <- tmb(maf, captureSize = 50, logScale = TRUE)
# captureSize is the panel's callable Mb. The default is NOT your panel.
# Passing the wrong captureSize scales every TMB value linearly.

The FDA approval for pembrolizumab in TMB-high solid tumours uses ≥10 mutations/Mb as measured by FoundationOne CDx. That threshold is tied to that assay. Applying 10 mut/Mb to a different panel, or to WES, is an extrapolation and should be stated as one.

Microsatellite Instability

# msisensor-pro, paired tumour/normal
msisensor-pro msi -d microsatellites.list -n normal.bam -t tumor.bam -o msi_out

# tumour-only requires a baseline built from normals ON THE SAME ASSAY
msisensor-pro baseline -d microsatellites.list -i normal_configure.txt -o baseline_dir
msisensor-pro pro -d baseline_dir/*.baseline -t tumor.bam -o msi_out
Interpretation:
  MSI-H     typically >= 20% of evaluated microsatellite loci unstable
  MSS       stable

The 20% cutoff is convention, not a law, and depends on the locus panel.
Report the number of loci evaluated alongside the percentage: a 20% call
from 15 informative loci is not the same evidence as 20% from 2000.

MSI-H, dMMR by IHC, and high TMB overlap but are not interchangeable. A
tumour can be MSI-H with unremarkable TMB and vice versa. If a therapy
decision rests on it, confirm with an orthogonal assay.

Neoantigen Prediction

pvacseq run annotated.vcf SAMPLE \
  HLA-A*02:01,HLA-B*07:02,HLA-C*07:02 \
  MHCflurry NetMHCpan BigMHC_EL \
  output_dir/ \
  --binding-threshold 500 --iedb-install-directory /path/to/iedb
What binding prediction does and does not tell you:

  Predicts    peptide-MHC binding affinity, and increasingly presentation
              likelihood (eluted-ligand models beat affinity-only models)
  Does NOT    predict immunogenicity. Most predicted binders elicit no T cell
              response. Validation rates in the literature are low single
              digits to low tens of percent.

Requirements that are easy to get wrong:
  HLA typing must be 4-digit and from the patient, not imputed
  Expression matters: a neoantigen from an unexpressed transcript is not a
  neoantigen. Filter on tumour RNA-seq.
  Variant allele fraction matters: subclonal neoantigens are weaker targets
  Run several predictors and use the consensus, not one tool's top hit

Treat the output as a ranked hypothesis list for experimental testing, in the same way in-silico perturbation output is treated in foundation-models.

Output Specification

OutputFormatDescription
normalized.vcf.gzVCFLeft-aligned, multiallelics split, indexed
annotated.vcfVCFVEP consequences, one per allele per gene
variants.mafMAFSomatic calls in MAF format for cohort tools
germline_classification.csvCSVVariant, ACMG criteria applied, final class
somatic_oncogenicity.csvCSVVariant, ClinGen/CGC/VICC criteria, oncogenicity
somatic_tiers.csvCSVVariant, AMP tier, tumour type, evidence source
tmb.csvCSVSample, count, callable Mb, TMB, assay name, cutoff used
msi.csvCSVSample, loci evaluated, unstable loci, percentage, call
neoantigens.tsvTSVPeptide, HLA allele, predicted affinity, expression, VAF
knowledgebase_versions.txtTextOncoKB and CIViC access dates, VEP cache version

Validation Checks

VCF integrity
  Reference build recorded and matches the annotation source.
  Chromosome naming consistent between VCF, reference, and cache.
  Normalization applied: no multiallelic records remain, indels left-aligned.
  Records before and after normalization counted; splitting increases the count.

Annotation
  Fraction of variants receiving any consequence is near 1. A low rate
  usually means a build or naming mismatch, not a rare cohort.
  Transcript selection flag recorded, and the transcript reported per variant.
  Known positive controls annotate as expected: BRAF V600E as missense,
  TP53 R175H as missense, a known nonsense as stop_gained.

Germline classification
  Population frequency uses popmax with the allele number reported.
  Criteria applied are listed per variant, not just the final class.
  PM2 applied at supporting strength, per current ClinGen guidance.

Somatic classification
  Oncogenicity and clinical tier reported SEPARATELY.
  Tier assignment names the tumour type.
  Knowledgebase access date recorded.
  ACMG/AMP criteria not applied to somatic variants.

TMB
  Numerator rule stated: synonymous included or excluded, indels counted.
  Denominator is the callable Mb of the actual assay.
  Cutoff cited with the assay it was validated on.

MSI
  Loci evaluated reported alongside the unstable percentage.
  Tumour-only calls state which baseline was used.

Neoantigens
  Expression filter applied from matched RNA-seq.
  HLA type is patient-derived and 4-digit.
  Consensus across predictors reported, not a single tool's ranking.

Common Pitfalls

VCF handling

  1. Annotating without normalizing: multiallelic and non-left-aligned records fail knowledgebase lookups silently. The variant appears absent from the database rather than raising an error. Run bcftools norm -m -any -f ref first, always.
  2. Build mismatch: GRCh37 coordinates annotated against GRCh38 land in a different gene. Read the VCF header contigs before annotating, and note that TCGA legacy data is GRCh37 while current GDC is GRCh38.
  3. Chromosome naming mismatch: 1 versus chr1 typically returns no annotations rather than erroring, which reads as a rare cohort instead of a bug.
  4. Tumour-only calling reported as somatic: without a matched normal, a large fraction of calls are germline. Filter against gnomAD and a panel of normals, and state that the calls are inferred somatic.

Annotation

  1. Reporting a consequence without the transcript: a variant can be missense in one transcript and intronic in another. Name the transcript, and prefer MANE Select as the canonical choice.
  2. Using --pick and treating the result as complete: it collapses to one consequence by VEP's internal ordering. For clinical reporting use --pick_allele_gene, or --flag_pick to keep everything.
  3. Trusting an ANNOVAR database bundle without checking its date: those databases update on their own schedule, not with the genome release.

Classification

  1. Applying ACMG/AMP to somatic variants: the criteria assume germline inheritance, segregation, and population frequency as benign evidence. Use the ClinGen/CGC/VICC oncogenicity SOP and the AMP/ASCO/CAP tiers instead.
  2. Treating oncogenicity and clinical significance as one axis: a clearly oncogenic variant can be Tier III where nothing acts on it, and a Tier I variant may not be a driver at all. Report both.
  3. Assigning a tier without naming the tumour type: BRAF V600E is Tier IA in melanoma and Tier IIC in colorectal cancer. The tier is a property of the variant in a context.
  4. Applying tumour-suppressor logic to an oncogene: a truncating variant is strong evidence of oncogenicity in a tumour suppressor and generally uninformative in an oncogene. The gene's mechanism selects the criteria.
  5. Using global allele frequency instead of popmax: a variant at 0.1% globally may be 4% in one ancestry group. Global AF hides the evidence of benignity, and it is how VUS accumulate disproportionately in under-represented populations.
  6. Applying PM2 at moderate strength: ClinGen recalibrated absence/rarity to supporting. Using the 2015 wording overweights it.
  7. Citing the points-based system as the official replacement for ACMG/AMP 2015: it is endorsed by ClinGen, not mandated. The 2015 framework with ClinGen's criterion-level refinements is the current standard.

TMB and MSI

  1. Comparing TMB across assays: numerator rules, denominators, and germline filtering all differ by vendor. The Friends of Cancer Research harmonization effort exists because they disagreed.
  2. Applying the 10 mut/Mb cutoff to any assay: that threshold was validated on FoundationOne CDx. Using it for WES or another panel is an extrapolation and must be labelled as one.
  3. Passing the default captureSize to maftools::tmb(): it scales every value linearly. Pass the callable megabases of the actual panel.
  4. Reporting an MSI percentage without the locus count: 20% of 15 loci and 20% of 2000 loci are not the same evidence.
  5. Treating MSI-H, dMMR and TMB-high as interchangeable: they overlap and disagree often enough to matter for a therapy decision.
  6. Starting new work on msisensor: the original ding-lab repository is archived. Use msisensor-pro or msisensor2.

Neoantigens

  1. Reading binding affinity as immunogenicity: most predicted binders provoke no T cell response. Validation rates are low.
  2. Predicting neoantigens from unexpressed transcripts: filter on matched tumour RNA-seq, or the peptide is never presented.
  3. Using imputed rather than patient HLA types: HLA is the most polymorphic region in the genome. Type it from the patient's own data at 4-digit resolution.

Related Skills

  • cancer-multiomics: MAF-level cohort summarization, mutational signatures, driver detection
  • survival-analysis: testing whether a classified variant or TMB stratum is prognostic
  • foundation-models: the same hypothesis-ranking caveat applies to in-silico predictions

Public Datasets for Testing

DatasetContentUse Case
TCGA-LUAD (GDC)Somatic MAF, GRCh38TMB distribution, driver frequencies
TCGA-UCECSomatic MAFMSI-H enriched, TMB-high tail
GIAB HG002Germline truth set VCFNormalization and annotation correctness
ClinVar VCFClassified germline variantsACMG classification benchmarking
COSMIC Cancer Mutation CensusCurated somatic variantsOncogenicity evidence
CIViC (open API)Curated clinical evidenceTier assignment testing

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.