[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M73GVZRS7ZPJS78WEER2395N":3,"skill-same:01M73GVZRS7ZPJS78WEER2395N":48},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":18,"publishedAt":19,"linkOnly":20,"markdownContent":21,"markdownBody":22,"frontMatter":23,"refName":24,"commitSha":25,"skillDirectory":26,"forksCount":27,"repositoryHtmlUrl":28,"repositoryHomepageUrl":29,"ownerHtmlUrl":30,"ownerBlogUrl":31,"ownerDescription":32,"updatedAt":33,"install":34,"resources":47},"01M73GVZRS7ZPJS78WEER2395N","homer-motif-analysis",null,"De novo and known TF motif enrichment in ChIP-seq\u002FATAC-seq peaks via HOMER. findMotifsGenome.pl finds over-represented patterns vs background; annotatePeaks.pl assigns context (TSS distance, gene, repeat). Use after MACS3 to identify enriched TFs, annotate peaks with nearest genes, and validate ChIP-seq via the target motif.","bg-szy\u002FTOP-SKILLS","bg-szy","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F106576190?v=4","01M73A4E8KPV67SFXRY8XZGNBX","ShuZhiyong","01M73A4E96MQ294MHM74TZBVQD",6,"GPL-3.0","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fawesome-skills\u002Fhomer-motif-analysis\u002FSKILL.md",[],[],"2026-11-11 15:11:14",false,"---\nname: \"homer-motif-analysis\"\ndescription: \"De novo and known TF motif enrichment in ChIP-seq\u002FATAC-seq peaks via HOMER. findMotifsGenome.pl finds over-represented patterns vs background; annotatePeaks.pl assigns context (TSS distance, gene, repeat). Use after MACS3 to identify enriched TFs, annotate peaks with nearest genes, and validate ChIP-seq via the target motif.\"\nlicense: \"GPL-3.0\"\n---\n\n# HOMER — Motif Analysis and Peak Annotation\n\n## Overview\n\nHOMER (Hypergeometric Optimization of Motif EnRichment) is a suite of Perl\u002FC++ tools for analyzing genomic regulatory elements. Its two primary commands are `findMotifsGenome.pl`, which performs de novo motif discovery and known motif enrichment against JASPAR\u002FHOMER databases, and `annotatePeaks.pl`, which maps each peak to the nearest gene, distance to TSS, and genomic feature class (promoter, intron, intergenic, repeat). HOMER takes BED-format peak files from MACS3 or similar peak callers and a reference genome assembly as input, and outputs HTML\u002Ftext reports ranking enriched motifs by p-value and fold enrichment over a matched background.\n\n## When to Use\n\n- Identifying which transcription factors are bound in a ChIP-seq peak set by enriching their known motifs from JASPAR or the HOMER motif library\n- Discovering novel sequence motifs de novo in open chromatin regions from ATAC-seq without prior knowledge of the binding TF\n- Comparing motif landscapes between two conditions (e.g., treated vs. untreated peak sets) by running HOMER with one set as target and the other as background\n- Annotating genomic peaks with nearest genes and distance to TSS for downstream functional analysis or integration with DESeq2 results\n- Validating ChIP-seq experiment quality: a successful pull-down should show the target TF's canonical motif as the top hit\n- Use `macs3-peak-calling` first to generate the peak BED files that serve as input to HOMER\n- Use `jaspar-database` to cross-reference HOMER-discovered motifs with JASPAR IDs and additional TF metadata\n- Use `MEME-CHIP` (web or local) when you need a more probabilistic ZOOPS\u002FTCM model or the MEME Suite ecosystem\n- Use `AME` (part of MEME Suite) as a faster alternative for known motif scanning without de novo discovery\n\n## Prerequisites\n\n- **Software**: HOMER (Perl + compiled binaries), conda or manual install\n- **Genomes**: must download genome sequence via `installGenome.pl` after HOMER install\n- **Input**: BED file of peaks (at minimum: chr, start, end columns); ideally summit-centered peaks from MACS3\n- **Python packages** (for parsing\u002Fvisualization): `pandas`, `matplotlib`, `seaborn`\n\n> **Check before installing**: The tool may already be available in the current environment (e.g., inside a `pixi` \u002F `conda` env). Run `command -v findMotifsGenome.pl` first and skip the install commands below if it returns a path. When running inside a pixi project, invoke the tool via `pixi run findMotifsGenome.pl` rather than bare `findMotifsGenome.pl`.\n\n```bash\n# Install HOMER via conda (recommended — handles Perl dependencies)\nconda install -c bioconda homer\n\n# Verify installation\nfindMotifsGenome.pl 2>&1 | head -3\n# Usage: findMotifsGenome.pl \u003Cpeak\u002FBED file> \u003Cgenome> \u003Coutput directory> [options]\n\nannotatePeaks.pl 2>&1 | head -3\n# Usage: annotatePeaks.pl \u003Cpeak\u002FBED file> \u003Cgenome> [options]\n\n# Install reference genomes (downloads 2-way masker + sequence; ~3–10 GB each)\ninstallGenome.pl hg38\ninstallGenome.pl mm10\n\n# Install Python parsing dependencies\npip install pandas matplotlib seaborn\n```\n\n## Pre-flight Interview\n\nSettle these with the user before writing any analysis code.\n\n```yaml\ndecisions:\n  - id: D1\n    param: genomeAssembly\n    kind: derived\n    source: upstream\n    ask: \"Which assembly are the peak coordinates on?\"\n    default: \"carried from the peak-calling stage\"\n\n  - id: D2\n    param: searchWindow\n    kind: required\n    source: user\n    ask: \"How wide a window around each peak centre should be searched?\"\n    default: \"200 bp for TF ChIP, 150 bp for ATAC\"\n\n  - id: D3\n    param: backgroundRegions\n    kind: required\n    source: user\n    ask: \"Compare peaks against GC-matched random genomic regions, or against a specific control set?\"\n    default: \"auto-generated GC-matched background\"\n\n  - id: D4\n    param: repeatMasking\n    kind: required\n    source: user\n    ask: \"Mask repetitive sequence, which otherwise dominates the enrichment as false positives?\"\n    default: \"masked\"\n\n  - id: D5\n    param: denovoDiscovery\n    kind: required\n    source: user\n    ask: \"Search for previously undescribed motifs, or only test the known-motif library?\"\n    default: \"known motifs only - de novo discovery is roughly ten times slower\"\n\n  - id: D6\n    param: motifLengths\n    kind: optional\n    source: user\n    depends_on: [D5]\n    ask: \"Which motif widths should the de novo search try?\"\n    default: \"8, 10, 12\"\n    skip_if: \"de novo discovery disabled\"\n\n  - id: D7\n    param: numDenovoMotifs\n    kind: optional\n    source: user\n    depends_on: [D5]\n    ask: \"How many de novo motifs should be reported?\"\n    default: 25\n    skip_if: \"de novo discovery disabled\"\n\n  - id: D8\n    param: knownMotifMismatches\n    kind: optional\n    source: user\n    ask: \"How loosely may a sequence match a known motif and still count?\"\n    default: 2\n\n  - id: D9\n    param: threads\n    kind: never_ask\n    source: data\n    reason: \"Affects runtime only, not the enrichment\"\n    default: \"min(8, available_cores)\"\n```\n\nD1 is derived rather than asked: peak coordinates are meaningless outside the\nassembly they were called on, so the answer is whatever the upstream stage used,\nnot a preference. D3 is the decision most often left at its default without\nthought - a background that does not match the peaks in GC content produces\nenrichment for GC content rather than for biology.\n\n## Quick Start\n\n```bash\n# Run de novo + known motif enrichment on TF ChIP-seq peaks (hg38, 200 bp window)\nfindMotifsGenome.pl peaks\u002Ftf_chip_summits.bed hg38 motif_output\u002F \\\n    -size 200 -mask -p 4\n\n# Annotate peaks with nearest genes and genomic features\nannotatePeaks.pl peaks\u002Ftf_chip_peaks.narrowPeak hg38 > annotated_peaks.txt\n\necho \"Top known motif:\"\nhead -2 motif_output\u002FknownResults.txt | tail -1 | cut -f1-4\n\necho \"Annotated peaks: $(wc -l \u003C annotated_peaks.txt) lines\"\n```\n\n## Workflow\n\n### Step 1: Installation and Genome Setup\n\nInstall HOMER and download the reference genome sequence required for motif analysis.\n\n```bash\n# Activate conda environment (or use existing env)\nconda create -n homer_env -c bioconda homer python=3.10 -y\nconda activate homer_env\n\n# List available genomes\ninstallGenome.pl list\n\n# Install human (hg38) and mouse (mm10) genomes\n# Downloads masked genome sequence and annotation files\ninstallGenome.pl hg38\n# Output: Installing hg38... Done. (3-5 min, ~3 GB)\n\ninstallGenome.pl mm10\n# Output: Installing mm10... Done. (3-5 min, ~2.5 GB)\n\n# Verify genome is installed\nls ~\u002F.homer\u002Fdata\u002Fgenomes\u002Fhg38\u002F\n# genome.fa  chrom.sizes  ...\n\n# Check HOMER motif database\nls ~\u002F.homer\u002Fdata\u002FknownTFs\u002F\n# vertebrates.motifs  jaspar.motifs  ...\n```\n\n### Step 2: Prepare Input Peak File\n\nPrepare a summit-centered BED file from MACS3 output for optimal motif resolution.\n\n```bash\n# Option A: Use MACS3 summit file directly (already 1 bp summit positions)\n# Expand summits to ±100 bp (200 bp total) centered on summit\nawk 'BEGIN{OFS=\"\\t\"} {\n    start = ($2 - 100 \u003C 0) ? 0 : $2 - 100;\n    print $1, start, $2 + 100, $4, $5\n}' peaks\u002Ftf_chip_summits.bed > peaks\u002Ftf_chip_200bp.bed\n\necho \"Summit-centered peaks: $(wc -l \u003C peaks\u002Ftf_chip_200bp.bed)\"\n# Summit-centered peaks: 12453\n\n# Option B: Use narrowPeak file directly (HOMER accepts multi-column BED)\n# HOMER uses columns 1-3 (chr, start, end) and centers internally with -size\ncp peaks\u002Ftf_chip_peaks.narrowPeak peaks\u002Finput_peaks.bed\n\n# Option C: Prepare a custom background region file (matched GC content)\n# HOMER auto-generates background if not provided, but explicit background\n# is recommended when comparing two peak sets\n# Use the control peak set or random genomic regions as background:\nbedtools shuffle -i peaks\u002Ftf_chip_peaks.narrowPeak \\\n    -g ~\u002F.homer\u002Fdata\u002Fgenomes\u002Fhg38\u002Fchrom.sizes \\\n    -excl peaks\u002Ftf_chip_peaks.narrowPeak > peaks\u002Fbackground_regions.bed\n\necho \"Background regions: $(wc -l \u003C peaks\u002Fbackground_regions.bed)\"\n# Background regions: 12453\n```\n\n### Step 3: De Novo Motif Discovery\n\nRun `findMotifsGenome.pl` for de novo motif discovery and known motif enrichment simultaneously.\n\n```bash\nmkdir -p motif_output\u002F\n\n# Full run: de novo + known motif enrichment\n# -size 200: use 200 bp window centered on peak midpoint\n# -mask: mask repetitive elements (recommended for clean motifs)\n# -p 4: use 4 CPU threads\n# -S 25: find top 25 de novo motifs (default)\nfindMotifsGenome.pl peaks\u002Ftf_chip_200bp.bed hg38 motif_output\u002F \\\n    -size 200 \\\n    -mask \\\n    -p 4 \\\n    -S 25\n\n# Check progress output:\n# Reading genome sizes for hg38 ...\n# Scanning for motifs...\n# Optimizing 25 motifs...\n# Done! Output in motif_output\u002F\n\necho \"Known results: $(wc -l \u003C motif_output\u002FknownResults.txt) motifs\"\necho \"De novo motifs: $(ls motif_output\u002FhomerResults\u002F*.motif 2>\u002Fdev\u002Fnull | wc -l) motifs\"\n# Known results: 392 motifs\n# De novo motifs: 25 motifs\n\n# For mouse peaks (mm10)\n# findMotifsGenome.pl peaks\u002Fatac_peaks.bed mm10 motif_output_mm10\u002F \\\n#     -size 200 -mask -p 4\n```\n\n### Step 4: Known Motif Enrichment Only\n\nScan peaks for occurrences of a specific known motif or skip de novo discovery for speed.\n\n```bash\n# Skip de novo discovery (faster when you only need known motifs)\nfindMotifsGenome.pl peaks\u002Ftf_chip_200bp.bed hg38 motif_output_known\u002F \\\n    -size 200 \\\n    -mask \\\n    -p 4 \\\n    -nomotif\n\necho \"Known motif results: $(wc -l \u003C motif_output_known\u002FknownResults.txt)\"\n# Known motif results: 392\n\n# Find occurrences of a specific motif across peaks (outputs peak-level annotation)\n# Extract the motif matrix file for the TF of interest from homerResults\u002F\nfindMotifsGenome.pl peaks\u002Ftf_chip_200bp.bed hg38 motif_scan_out\u002F \\\n    -size 200 \\\n    -mask \\\n    -find motif_output\u002FhomerResults\u002Fmotif1.motif \\\n    > peaks_with_motif1.txt\n\necho \"Peaks containing motif1: $(wc -l \u003C peaks_with_motif1.txt)\"\n# Peaks containing motif1: 8941\n\n# Custom background: compare treated vs. control peak sets\nfindMotifsGenome.pl peaks\u002Ftreated_peaks.bed hg38 motif_treated_vs_ctrl\u002F \\\n    -size 200 \\\n    -mask \\\n    -p 4 \\\n    -bg peaks\u002Fcontrol_peaks.bed\n```\n\n### Step 5: Peak Annotation\n\nUse `annotatePeaks.pl` to assign each peak to a genomic feature and nearest gene.\n\n```bash\n# Annotate peaks with nearest gene and TSS distance\n# Outputs a tab-delimited file with genomic context for each peak\nannotatePeaks.pl peaks\u002Ftf_chip_peaks.narrowPeak hg38 \\\n    > annotated_peaks.txt\n\necho \"Annotated peaks: $(($(wc -l \u003C annotated_peaks.txt) - 1)) peaks\"\n# Annotated peaks: 12453 peaks\n\n# Preview column headers and first peak\nhead -2 annotated_peaks.txt | cut -f1-10\n\n# Annotate ATAC-seq peaks (same command, different input)\nannotatePeaks.pl peaks\u002Fatac_sample_peaks.narrowPeak hg38 \\\n    > annotated_atac.txt\n\n# Generate TSS-distance histogram (for tag density plots)\n# annotatePeaks.pl can compute read density around peaks with -d flag\n# annotatePeaks.pl tss hg38 -size 4000 -hist 10 \\\n#     -d chip_tagdir\u002F > tss_histogram.txt\n```\n\n### Step 6: Parse HOMER Results with Python\n\nRead `knownResults.txt` and de novo motif files into pandas for downstream analysis.\n\n```python\nimport pandas as pd\nimport subprocess\nimport io\n\n# --- Parse known motif enrichment results ---\n# knownResults.txt columns:\n# Motif Name | Consensus | P-value | Log P-value | q-value | # Target Seqs w\u002F motif | % Target | # Bg Seqs w\u002F motif | % Bg\nknown_cols = [\n    \"motif_name\", \"consensus\", \"pvalue\", \"log_pvalue\",\n    \"qvalue\", \"n_target_seqs\", \"pct_target\",\n    \"n_bg_seqs\", \"pct_bg\"\n]\nknown = pd.read_csv(\n    \"motif_output\u002FknownResults.txt\",\n    sep=\"\\t\", header=0, names=known_cols\n)\n\n# Convert string percentages to floats\nknown[\"pct_target\"] = known[\"pct_target\"].str.rstrip(\"%\").astype(float)\nknown[\"pct_bg\"] = known[\"pct_bg\"].str.rstrip(\"%\").astype(float)\nknown[\"fold_enrichment\"] = known[\"pct_target\"] \u002F known[\"pct_bg\"].replace(0, 0.001)\nknown[\"-log10_pvalue\"] = -known[\"log_pvalue\"] \u002F 2.303  # log10 from natural log\n\nprint(f\"Total known motifs tested: {len(known)}\")\nprint(f\"Significant (p \u003C 1e-5): {(known['pvalue'].astype(float) \u003C 1e-5).sum()}\")\nprint(\"\\nTop 5 enriched motifs:\")\nprint(\n    known[[\"motif_name\", \"pct_target\", \"pct_bg\", \"fold_enrichment\", \"-log10_pvalue\"]]\n    .head(5)\n    .to_string(index=False)\n)\n# Total known motifs tested: 391\n# Significant (p \u003C 1e-5): 47\n# Top 5 enriched motifs:\n#  motif_name  pct_target  pct_bg  fold_enrichment  -log10_pvalue\n#  CTCF(Zf)\u002FGM12878-CTCF-ChIP-Seq...   78.21    8.32           9.40         312.4\n#  ZNF143(Zf)\u002F...                        42.11    5.10           8.26         188.7\n#  ...\n```\n\n### Step 7: Parse Peak Annotations and Visualize\n\nRead annotated peak output, summarize genomic feature distribution, and plot motif enrichments.\n\n```python\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as mpatches\nimport seaborn as sns\n\n# --- Parse annotated peaks ---\n# annotatePeaks.pl output header: PeakID chr start end strand score ...\n# Key columns: \"Annotation\", \"Distance to TSS\", \"Nearest RefSeq\", \"Gene Name\"\nannot = pd.read_csv(\"annotated_peaks.txt\", sep=\"\\t\", header=0, low_memory=False)\nannot.columns = annot.columns.str.strip()\n\n# Simplify annotation categories\ndef simplify_annotation(ann):\n    if pd.isna(ann):\n        return \"Other\"\n    ann = str(ann)\n    if \"promoter\" in ann.lower():\n        return \"Promoter (\u003C2 kb)\"\n    elif \"exon\" in ann.lower():\n        return \"Exon\"\n    elif \"intron\" in ann.lower():\n        return \"Intron\"\n    elif \"tts\" in ann.lower() or \"downstream\" in ann.lower():\n        return \"Downstream\"\n    elif \"intergenic\" in ann.lower():\n        return \"Intergenic\"\n    else:\n        return \"Other\"\n\nannot[\"simple_ann\"] = annot[\"Annotation\"].apply(simplify_annotation)\nann_counts = annot[\"simple_ann\"].value_counts()\n\nprint(\"Peak annotation summary:\")\nprint(ann_counts.to_string())\n# Peak annotation summary:\n# Intron             5832\n# Intergenic         3102\n# Promoter (\u003C2 kb)   2218\n# Exon                891\n# Downstream          287\n# Other               123\n\n# --- Plot 1: Annotation pie chart ---\nfig, axes = plt.subplots(1, 2, figsize=(14, 5))\n\ncolors = [\"#E41A1C\", \"#377EB8\", \"#4DAF4A\", \"#984EA3\", \"#FF7F00\", \"#A65628\"]\naxes[0].pie(\n    ann_counts.values,\n    labels=ann_counts.index,\n    colors=colors[:len(ann_counts)],\n    autopct=\"%1.1f%%\",\n    startangle=140,\n    textprops={\"fontsize\": 9}\n)\naxes[0].set_title(\"Peak Genomic Annotation\\n(n=12,453 peaks)\", fontsize=11)\n\n# --- Plot 2: Top known motif enrichments ---\nknown = pd.read_csv(\"motif_output\u002FknownResults.txt\", sep=\"\\t\", header=0)\nknown.columns = [\n    \"motif_name\", \"consensus\", \"pvalue\", \"log_pvalue\",\n    \"qvalue\", \"n_target_seqs\", \"pct_target\", \"n_bg_seqs\", \"pct_bg\"\n]\nknown[\"pct_target\"] = known[\"pct_target\"].str.rstrip(\"%\").astype(float)\nknown[\"pct_bg\"] = known[\"pct_bg\"].str.rstrip(\"%\").astype(float)\nknown[\"-log10_p\"] = (-known[\"log_pvalue\"].astype(float)) \u002F 2.303\nknown[\"short_name\"] = known[\"motif_name\"].str.split(\"\u002F\").str[0]\n\ntop_motifs = known.head(15).copy()\nsns.barplot(\n    data=top_motifs,\n    x=\"-log10_p\",\n    y=\"short_name\",\n    palette=\"Blues_r\",\n    ax=axes[1]\n)\naxes[1].set_xlabel(\"-log10(p-value)\", fontsize=10)\naxes[1].set_ylabel(\"Motif\", fontsize=10)\naxes[1].set_title(\"Top 15 Enriched Known Motifs\\n(HOMER\u002FJASPAR database)\", fontsize=11)\naxes[1].axvline(x=5, color=\"red\", linestyle=\"--\", linewidth=0.8, label=\"p=1e-5\")\naxes[1].legend(fontsize=8)\n\nplt.tight_layout()\nplt.savefig(\"homer_summary.png\", dpi=150, bbox_inches=\"tight\")\nplt.close()\nprint(\"Saved: homer_summary.png\")\n```\n\n## Key Parameters\n\n| Parameter | Default | Range \u002F Options | Effect |\n|-----------|---------|-----------------|--------|\n| `-size` | `200` | 50–1000 | Window size (bp) centered on peak midpoint for motif search; 200 for TF ChIP-seq, 150 for ATAC-seq |\n| `-mask` | off | flag | Mask repetitive elements (N-mask); strongly recommended to reduce false positives |\n| `-p` | `1` | 1–64 | Number of parallel CPU threads; use 4–8 for typical datasets |\n| `-S` | `25` | 1–100 | Number of de novo motifs to find; 25 is usually sufficient |\n| `-nomotif` | off | flag | Skip de novo motif discovery; only perform known motif enrichment (10× faster) |\n| `-bg` | auto-generated | BED file path | Custom background region file; auto-background is GC-matched if omitted |\n| `-find` | — | `.motif` file path | Scan peaks for occurrences of a specific motif matrix; outputs per-peak annotation |\n| `-mis` | `2` | 0–4 | Maximum mismatches allowed when matching known motifs |\n| `-len` | `8,10,12` | comma-separated integers | Motif lengths to try for de novo search; adding `6` finds shorter motifs |\n| `genome` | required | `hg38`, `mm10`, `hg19`, `dm6`, `ce11`, etc. | Reference genome assembly; must be installed with `installGenome.pl` |\n\n## Common Recipes\n\n### Recipe 1: Python subprocess Wrapper for findMotifsGenome.pl\n\nRun HOMER from a Python script and capture completion status.\n\n```python\nimport subprocess\nimport sys\nfrom pathlib import Path\n\ndef run_homer_motifs(\n    peaks_bed: str,\n    genome: str,\n    output_dir: str,\n    size: int = 200,\n    mask: bool = True,\n    cpus: int = 4,\n    n_motifs: int = 25,\n    denovo: bool = True,\n    bg_bed: str = None\n) -> int:\n    \"\"\"Run findMotifsGenome.pl and return exit code.\"\"\"\n    Path(output_dir).mkdir(parents=True, exist_ok=True)\n    cmd = [\n        \"findMotifsGenome.pl\", peaks_bed, genome, output_dir,\n        \"-size\", str(size),\n        \"-p\", str(cpus),\n        \"-S\", str(n_motifs),\n    ]\n    if mask:\n        cmd.append(\"-mask\")\n    if not denovo:\n        cmd.append(\"-nomotif\")\n    if bg_bed:\n        cmd.extend([\"-bg\", bg_bed])\n\n    print(f\"Running: {' '.join(cmd)}\")\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    if result.returncode != 0:\n        print(f\"HOMER stderr:\\n{result.stderr[-2000:]}\", file=sys.stderr)\n        return result.returncode\n    print(f\"Done. Output in {output_dir}\u002F\")\n    return 0\n\n# Usage\nexit_code = run_homer_motifs(\n    peaks_bed=\"peaks\u002Ftf_chip_200bp.bed\",\n    genome=\"hg38\",\n    output_dir=\"motif_output\u002F\",\n    size=200, mask=True, cpus=4, n_motifs=25\n)\nprint(f\"Exit code: {exit_code}\")\n# Running: findMotifsGenome.pl peaks\u002Ftf_chip_200bp.bed hg38 motif_output\u002F -size 200 -p 4 -S 25 -mask\n# Done. Output in motif_output\u002F\n# Exit code: 0\n```\n\n### Recipe 2: Batch Motif Analysis Across Multiple Peak Sets\n\nRun HOMER on multiple ChIP-seq samples in a loop.\n\n```bash\n#!\u002Fbin\u002Fbash\n# Batch motif analysis for several ChIP-seq experiments (same genome)\nGENOME=\"hg38\"\nPEAK_DIR=\"peaks\"\nMOTIF_DIR=\"motif_results\"\nmkdir -p \"$MOTIF_DIR\"\n\nSAMPLES=(CTCF H3K4me3 FOXA2 RUNX1)\n\nfor sample in \"${SAMPLES[@]}\"; do\n    echo \"=== Processing $sample ===\"\n    peak_file=\"${PEAK_DIR}\u002F${sample}_summits.bed\"\n\n    if [ ! -f \"$peak_file\" ]; then\n        echo \"  Skipping $sample: $peak_file not found\"\n        continue\n    fi\n\n    # Center on summit ±100 bp\n    awk 'BEGIN{OFS=\"\\t\"} {s=$2-100\u003C0?0:$2-100; print $1,s,$2+100,$4,$5}' \\\n        \"$peak_file\" > \"${PEAK_DIR}\u002F${sample}_200bp.bed\"\n\n    findMotifsGenome.pl \"${PEAK_DIR}\u002F${sample}_200bp.bed\" \"$GENOME\" \\\n        \"${MOTIF_DIR}\u002F${sample}\u002F\" \\\n        -size 200 -mask -p 4 -nomotif \\\n        2> \"${MOTIF_DIR}\u002F${sample}.log\"\n\n    n=$(wc -l \u003C \"${MOTIF_DIR}\u002F${sample}\u002FknownResults.txt\")\n    echo \"  $sample: $n motifs tested. Top hit: $(sed -n '2p' \"${MOTIF_DIR}\u002F${sample}\u002FknownResults.txt\" | cut -f1)\"\ndone\n# === Processing CTCF ===\n#   CTCF: 392 motifs tested. Top hit: CTCF(Zf)\u002FGM12878-CTCF-ChIP-Seq(GSE32465)\u002FHomer\n# === Processing FOXA2 ===\n#   FOXA2: 392 motifs tested. Top hit: Foxa2(Forkhead)\u002FLiver-Foxa2-ChIP-Seq(GSE25694)\u002FHomer\n```\n\n### Recipe 3: Parse De Novo Motif Matrices from homerResults\u002F\n\nLoad de novo motif PWM matrices for downstream comparison or plotting.\n\n```python\nimport os\nimport re\nimport pandas as pd\n\ndef parse_homer_motif(motif_file: str) -> dict:\n    \"\"\"Parse a HOMER .motif file into name, log_odds_threshold, and PWM.\"\"\"\n    with open(motif_file) as f:\n        header = f.readline().strip()  # >motif_name\\tlog_odds\\tlog_p-value\\t0\\tnucs\n        rows = []\n        for line in f:\n            line = line.strip()\n            if line:\n                rows.append([float(x) for x in line.split(\"\\t\")])\n    parts = header.lstrip(\">\").split(\"\\t\")\n    name = parts[0]\n    log_odds = float(parts[1]) if len(parts) > 1 else 0.0\n    log_p = float(parts[2]) if len(parts) > 2 else 0.0\n    pwm = pd.DataFrame(rows, columns=[\"A\", \"C\", \"G\", \"T\"])\n    return {\"name\": name, \"log_odds\": log_odds, \"log_p\": log_p, \"pwm\": pwm}\n\n# Load all de novo motifs\nmotif_dir = \"motif_output\u002FhomerResults\u002F\"\nmotifs = []\nfor fn in sorted(os.listdir(motif_dir)):\n    if fn.endswith(\".motif\"):\n        motif = parse_homer_motif(os.path.join(motif_dir, fn))\n        motifs.append(motif)\n        print(f\"{fn}: {motif['name']} ({len(motif['pwm'])} positions, log_p={motif['log_p']:.1f})\")\n\nprint(f\"\\nLoaded {len(motifs)} de novo motifs\")\n# motif1.motif: CTCF-motif (19 positions, log_p=-8234.1)\n# motif2.motif: CTCFL-motif (17 positions, log_p=-3421.7)\n# ...\n# Loaded 25 de novo motifs\n```\n\n### Recipe 4: Annotate Peaks and Join with Differential Expression Results\n\nCombine peak annotations with RNA-seq DE results to find regulated genes near peaks.\n\n```python\nimport pandas as pd\n\n# Load annotated peaks\nannot = pd.read_csv(\"annotated_peaks.txt\", sep=\"\\t\", header=0, low_memory=False)\nannot.columns = annot.columns.str.strip()\n\n# Key columns from HOMER annotation\npeak_genes = annot[[\"PeakID (cmd=annotatePeaks.pl peaks.bed hg38)\",\n                     \"Chr\", \"Start\", \"End\",\n                     \"Annotation\", \"Distance to TSS\",\n                     \"Nearest RefSeq\", \"Gene Name\"]].copy()\npeak_genes.columns = [\"peak_id\", \"chr\", \"start\", \"end\",\n                      \"annotation\", \"tss_dist\", \"refseq\", \"gene_name\"]\n\n# Filter promoter-proximal peaks (within 2 kb of TSS)\npromoter_peaks = peak_genes[peak_genes[\"tss_dist\"].abs() \u003C 2000].copy()\nprint(f\"Promoter-proximal peaks (|TSS| \u003C 2kb): {len(promoter_peaks)}\")\n# Promoter-proximal peaks (|TSS| \u003C 2kb): 2218\n\n# Load DESeq2 results (gene_name, log2FC, padj)\nde_results = pd.read_csv(\"deseq2_results.csv\")\nde_sig = de_results[de_results[\"padj\"] \u003C 0.05].copy()\n\n# Merge: find DE genes with a nearby peak\nmerged = promoter_peaks.merge(de_sig, on=\"gene_name\", how=\"inner\")\nprint(f\"DE genes with promoter-proximal peak: {len(merged)}\")\nprint(merged[[\"gene_name\", \"tss_dist\", \"annotation\", \"log2FC\", \"padj\"]].head())\n# DE genes with promoter-proximal peak: 347\n```\n\n## Expected Outputs\n\n| Output | Format | Description |\n|--------|--------|-------------|\n| `motif_output\u002FknownResults.txt` | TSV | All known motifs tested: name, p-value, q-value, % target, % background; primary result file |\n| `motif_output\u002FknownResults.html` | HTML | Interactive HTML report with motif logos, statistics, and links |\n| `motif_output\u002FhomerResults\u002F` | Directory | De novo motifs: `motifN.motif` (PWM matrix), `motifN.logo.png`, `similar.motifs.txt` |\n| `motif_output\u002FhomerResults.html` | HTML | Interactive HTML report for de novo motifs |\n| `annotated_peaks.txt` | TSV | One row per peak: chr, start, end, annotation, TSS distance, nearest gene, RefSeq ID |\n| `peaks_with_motif1.txt` | TSV | Per-peak motif occurrence scores (from `-find` mode) |\n\n## Troubleshooting\n\n| Problem | Cause | Solution |\n|---------|-------|----------|\n| `ERROR: Genome not found` | Genome not installed via `installGenome.pl` | Run `installGenome.pl hg38`; confirm `~\u002F.homer\u002Fdata\u002Fgenomes\u002Fhg38\u002F` exists |\n| `command not found: findMotifsGenome.pl` | HOMER binaries not in `$PATH` | Add HOMER bin directory to PATH: `export PATH=~\u002F.homer\u002Fbin:$PATH` (or activate conda env) |\n| Poor de novo motif quality (GC-rich artifacts) | Unmasked repetitive elements | Always use `-mask`; also try increasing `-size` to 300 or reducing to 150 |\n| No significant known motifs (all p > 0.01) | Too few peaks or wrong peak size | Ensure ≥500 peaks; check `-size` matches expected binding footprint (150–200 for TFs) |\n| Conda HOMER conflicts (Perl module errors) | HOMER's Perl scripts conflict with conda environment Perl | Install HOMER in a dedicated conda env: `conda create -n homer_only -c bioconda homer` |\n| `annotatePeaks.pl` gives all \"Intergenic\" | Genome annotation not installed | HOMER annotation requires `installGenome.pl` which downloads GTF; check `~\u002F.homer\u002Fdata\u002Fgenomes\u002Fhg38\u002F` contains `*.ann` files |\n| Very slow run time (>2 hr) | Single-threaded or large peak set | Add `-p 8`; reduce `-S` to 10 for speed; use `-nomotif` for known-only runs |\n| `-bg` custom background gives poor motifs | Background regions have very different GC content | Use a GC-matched background; run `bedtools shuffle` with `-noOverlapping` to generate random same-size regions |\n\n## References\n\n- [HOMER official documentation](http:\u002F\u002Fhomer.ucsd.edu\u002Fhomer\u002F) — comprehensive guide to all HOMER commands, parameters, and output formats\n- Heinz S et al. (2010) \"Simple Combinations of Lineage-Determining Transcription Factors Prime cis-Regulatory Elements Required for Macrophage and B Cell Identities.\" *Molecular Cell* 38(4):576–589. [DOI:10.1016\u002Fj.molcel.2010.05.004](https:\u002F\u002Fdoi.org\u002F10.1016\u002Fj.molcel.2010.05.004)\n- [HOMER GitHub: samtools\u002Fhomer](https:\u002F\u002Fgithub.com\u002Fsamtools\u002Fhomer) — source code and issue tracker\n- [JASPAR 2024 database](https:\u002F\u002Fjaspar.elixir.no\u002F) — curated TF binding motif database used by HOMER for known motif enrichment\n","# HOMER — Motif Analysis and Peak Annotation\n\n## Overview\n\nHOMER (Hypergeometric Optimization of Motif EnRichment) is a suite of Perl\u002FC++ tools for analyzing genomic regulatory elements. Its two primary commands are `findMotifsGenome.pl`, which performs de novo motif discovery and known motif enrichment against JASPAR\u002FHOMER databases, and `annotatePeaks.pl`, which maps each peak to the nearest gene, distance to TSS, and genomic feature class (promoter, intron, intergenic, repeat). HOMER takes BED-format peak files from MACS3 or similar peak callers and a reference genome assembly as input, and outputs HTML\u002Ftext reports ranking enriched motifs by p-value and fold enrichment over a matched background.\n\n## When to Use\n\n- Identifying which transcription factors are bound in a ChIP-seq peak set by enriching their known motifs from JASPAR or the HOMER motif library\n- Discovering novel sequence motifs de novo in open chromatin regions from ATAC-seq without prior knowledge of the binding TF\n- Comparing motif landscapes between two conditions (e.g., treated vs. untreated peak sets) by running HOMER with one set as target and the other as background\n- Annotating genomic peaks with nearest genes and distance to TSS for downstream functional analysis or integration with DESeq2 results\n- Validating ChIP-seq experiment quality: a successful pull-down should show the target TF's canonical motif as the top hit\n- Use `macs3-peak-calling` first to generate the peak BED files that serve as input to HOMER\n- Use `jaspar-database` to cross-reference HOMER-discovered motifs with JASPAR IDs and additional TF metadata\n- Use `MEME-CHIP` (web or local) when you need a more probabilistic ZOOPS\u002FTCM model or the MEME Suite ecosystem\n- Use `AME` (part of MEME Suite) as a faster alternative for known motif scanning without de novo discovery\n\n## Prerequisites\n\n- **Software**: HOMER (Perl + compiled binaries), conda or manual install\n- **Genomes**: must download genome sequence via `installGenome.pl` after HOMER install\n- **Input**: BED file of peaks (at minimum: chr, start, end columns); ideally summit-centered peaks from MACS3\n- **Python packages** (for parsing\u002Fvisualization): `pandas`, `matplotlib`, `seaborn`\n\n> **Check before installing**: The tool may already be available in the current environment (e.g., inside a `pixi` \u002F `conda` env). Run `command -v findMotifsGenome.pl` first and skip the install commands below if it returns a path. When running inside a pixi project, invoke the tool via `pixi run findMotifsGenome.pl` rather than bare `findMotifsGenome.pl`.\n\n```bash\n# Install HOMER via conda (recommended — handles Perl dependencies)\nconda install -c bioconda homer\n\n# Verify installation\nfindMotifsGenome.pl 2>&1 | head -3\n# Usage: findMotifsGenome.pl \u003Cpeak\u002FBED file> \u003Cgenome> \u003Coutput directory> [options]\n\nannotatePeaks.pl 2>&1 | head -3\n# Usage: annotatePeaks.pl \u003Cpeak\u002FBED file> \u003Cgenome> [options]\n\n# Install reference genomes (downloads 2-way masker + sequence; ~3–10 GB each)\ninstallGenome.pl hg38\ninstallGenome.pl mm10\n\n# Install Python parsing dependencies\npip install pandas matplotlib seaborn\n```\n\n## Pre-flight Interview\n\nSettle these with the user before writing any analysis code.\n\n```yaml\ndecisions:\n  - id: D1\n    param: genomeAssembly\n    kind: derived\n    source: upstream\n    ask: \"Which assembly are the peak coordinates on?\"\n    default: \"carried from the peak-calling stage\"\n\n  - id: D2\n    param: searchWindow\n    kind: required\n    source: user\n    ask: \"How wide a window around each peak centre should be searched?\"\n    default: \"200 bp for TF ChIP, 150 bp for ATAC\"\n\n  - id: D3\n    param: backgroundRegions\n    kind: required\n    source: user\n    ask: \"Compare peaks against GC-matched random genomic regions, or against a specific control set?\"\n    default: \"auto-generated GC-matched background\"\n\n  - id: D4\n    param: repeatMasking\n    kind: required\n    source: user\n    ask: \"Mask repetitive sequence, which otherwise dominates the enrichment as false positives?\"\n    default: \"masked\"\n\n  - id: D5\n    param: denovoDiscovery\n    kind: required\n    source: user\n    ask: \"Search for previously undescribed motifs, or only test the known-motif library?\"\n    default: \"known motifs only - de novo discovery is roughly ten times slower\"\n\n  - id: D6\n    param: motifLengths\n    kind: optional\n    source: user\n    depends_on: [D5]\n    ask: \"Which motif widths should the de novo search try?\"\n    default: \"8, 10, 12\"\n    skip_if: \"de novo discovery disabled\"\n\n  - id: D7\n    param: numDenovoMotifs\n    kind: optional\n    source: user\n    depends_on: [D5]\n    ask: \"How many de novo motifs should be reported?\"\n    default: 25\n    skip_if: \"de novo discovery disabled\"\n\n  - id: D8\n    param: knownMotifMismatches\n    kind: optional\n    source: user\n    ask: \"How loosely may a sequence match a known motif and still count?\"\n    default: 2\n\n  - id: D9\n    param: threads\n    kind: never_ask\n    source: data\n    reason: \"Affects runtime only, not the enrichment\"\n    default: \"min(8, available_cores)\"\n```\n\nD1 is derived rather than asked: peak coordinates are meaningless outside the\nassembly they were called on, so the answer is whatever the upstream stage used,\nnot a preference. D3 is the decision most often left at its default without\nthought - a background that does not match the peaks in GC content produces\nenrichment for GC content rather than for biology.\n\n## Quick Start\n\n```bash\n# Run de novo + known motif enrichment on TF ChIP-seq peaks (hg38, 200 bp window)\nfindMotifsGenome.pl peaks\u002Ftf_chip_summits.bed hg38 motif_output\u002F \\\n    -size 200 -mask -p 4\n\n# Annotate peaks with nearest genes and genomic features\nannotatePeaks.pl peaks\u002Ftf_chip_peaks.narrowPeak hg38 > annotated_peaks.txt\n\necho \"Top known motif:\"\nhead -2 motif_output\u002FknownResults.txt | tail -1 | cut -f1-4\n\necho \"Annotated peaks: $(wc -l \u003C annotated_peaks.txt) lines\"\n```\n\n## Workflow\n\n### Step 1: Installation and Genome Setup\n\nInstall HOMER and download the reference genome sequence required for motif analysis.\n\n```bash\n# Activate conda environment (or use existing env)\nconda create -n homer_env -c bioconda homer python=3.10 -y\nconda activate homer_env\n\n# List available genomes\ninstallGenome.pl list\n\n# Install human (hg38) and mouse (mm10) genomes\n# Downloads masked genome sequence and annotation files\ninstallGenome.pl hg38\n# Output: Installing hg38... Done. (3-5 min, ~3 GB)\n\ninstallGenome.pl mm10\n# Output: Installing mm10... Done. (3-5 min, ~2.5 GB)\n\n# Verify genome is installed\nls ~\u002F.homer\u002Fdata\u002Fgenomes\u002Fhg38\u002F\n# genome.fa  chrom.sizes  ...\n\n# Check HOMER motif database\nls ~\u002F.homer\u002Fdata\u002FknownTFs\u002F\n# vertebrates.motifs  jaspar.motifs  ...\n```\n\n### Step 2: Prepare Input Peak File\n\nPrepare a summit-centered BED file from MACS3 output for optimal motif resolution.\n\n```bash\n# Option A: Use MACS3 summit file directly (already 1 bp summit positions)\n# Expand summits to ±100 bp (200 bp total) centered on summit\nawk 'BEGIN{OFS=\"\\t\"} {\n    start = ($2 - 100 \u003C 0) ? 0 : $2 - 100;\n    print $1, start, $2 + 100, $4, $5\n}' peaks\u002Ftf_chip_summits.bed > peaks\u002Ftf_chip_200bp.bed\n\necho \"Summit-centered peaks: $(wc -l \u003C peaks\u002Ftf_chip_200bp.bed)\"\n# Summit-centered peaks: 12453\n\n# Option B: Use narrowPeak file directly (HOMER accepts multi-column BED)\n# HOMER uses columns 1-3 (chr, start, end) and centers internally with -size\ncp peaks\u002Ftf_chip_peaks.narrowPeak peaks\u002Finput_peaks.bed\n\n# Option C: Prepare a custom background region file (matched GC content)\n# HOMER auto-generates background if not provided, but explicit background\n# is recommended when comparing two peak sets\n# Use the control peak set or random genomic regions as background:\nbedtools shuffle -i peaks\u002Ftf_chip_peaks.narrowPeak \\\n    -g ~\u002F.homer\u002Fdata\u002Fgenomes\u002Fhg38\u002Fchrom.sizes \\\n    -excl peaks\u002Ftf_chip_peaks.narrowPeak > peaks\u002Fbackground_regions.bed\n\necho \"Background regions: $(wc -l \u003C peaks\u002Fbackground_regions.bed)\"\n# Background regions: 12453\n```\n\n### Step 3: De Novo Motif Discovery\n\nRun `findMotifsGenome.pl` for de novo motif discovery and known motif enrichment simultaneously.\n\n```bash\nmkdir -p motif_output\u002F\n\n# Full run: de novo + known motif enrichment\n# -size 200: use 200 bp window centered on peak midpoint\n# -mask: mask repetitive elements (recommended for clean motifs)\n# -p 4: use 4 CPU threads\n# -S 25: find top 25 de novo motifs (default)\nfindMotifsGenome.pl peaks\u002Ftf_chip_200bp.bed hg38 motif_output\u002F \\\n    -size 200 \\\n    -mask \\\n    -p 4 \\\n    -S 25\n\n# Check progress output:\n# Reading genome sizes for hg38 ...\n# Scanning for motifs...\n# Optimizing 25 motifs...\n# Done! Output in motif_output\u002F\n\necho \"Known results: $(wc -l \u003C motif_output\u002FknownResults.txt) motifs\"\necho \"De novo motifs: $(ls motif_output\u002FhomerResults\u002F*.motif 2>\u002Fdev\u002Fnull | wc -l) motifs\"\n# Known results: 392 motifs\n# De novo motifs: 25 motifs\n\n# For mouse peaks (mm10)\n# findMotifsGenome.pl peaks\u002Fatac_peaks.bed mm10 motif_output_mm10\u002F \\\n#     -size 200 -mask -p 4\n```\n\n### Step 4: Known Motif Enrichment Only\n\nScan peaks for occurrences of a specific known motif or skip de novo discovery for speed.\n\n```bash\n# Skip de novo discovery (faster when you only need known motifs)\nfindMotifsGenome.pl peaks\u002Ftf_chip_200bp.bed hg38 motif_output_known\u002F \\\n    -size 200 \\\n    -mask \\\n    -p 4 \\\n    -nomotif\n\necho \"Known motif results: $(wc -l \u003C motif_output_known\u002FknownResults.txt)\"\n# Known motif results: 392\n\n# Find occurrences of a specific motif across peaks (outputs peak-level annotation)\n# Extract the motif matrix file for the TF of interest from homerResults\u002F\nfindMotifsGenome.pl peaks\u002Ftf_chip_200bp.bed hg38 motif_scan_out\u002F \\\n    -size 200 \\\n    -mask \\\n    -find motif_output\u002FhomerResults\u002Fmotif1.motif \\\n    > peaks_with_motif1.txt\n\necho \"Peaks containing motif1: $(wc -l \u003C peaks_with_motif1.txt)\"\n# Peaks containing motif1: 8941\n\n# Custom background: compare treated vs. control peak sets\nfindMotifsGenome.pl peaks\u002Ftreated_peaks.bed hg38 motif_treated_vs_ctrl\u002F \\\n    -size 200 \\\n    -mask \\\n    -p 4 \\\n    -bg peaks\u002Fcontrol_peaks.bed\n```\n\n### Step 5: Peak Annotation\n\nUse `annotatePeaks.pl` to assign each peak to a genomic feature and nearest gene.\n\n```bash\n# Annotate peaks with nearest gene and TSS distance\n# Outputs a tab-delimited file with genomic context for each peak\nannotatePeaks.pl peaks\u002Ftf_chip_peaks.narrowPeak hg38 \\\n    > annotated_peaks.txt\n\necho \"Annotated peaks: $(($(wc -l \u003C annotated_peaks.txt) - 1)) peaks\"\n# Annotated peaks: 12453 peaks\n\n# Preview column headers and first peak\nhead -2 annotated_peaks.txt | cut -f1-10\n\n# Annotate ATAC-seq peaks (same command, different input)\nannotatePeaks.pl peaks\u002Fatac_sample_peaks.narrowPeak hg38 \\\n    > annotated_atac.txt\n\n# Generate TSS-distance histogram (for tag density plots)\n# annotatePeaks.pl can compute read density around peaks with -d flag\n# annotatePeaks.pl tss hg38 -size 4000 -hist 10 \\\n#     -d chip_tagdir\u002F > tss_histogram.txt\n```\n\n### Step 6: Parse HOMER Results with Python\n\nRead `knownResults.txt` and de novo motif files into pandas for downstream analysis.\n\n```python\nimport pandas as pd\nimport subprocess\nimport io\n\n# --- Parse known motif enrichment results ---\n# knownResults.txt columns:\n# Motif Name | Consensus | P-value | Log P-value | q-value | # Target Seqs w\u002F motif | % Target | # Bg Seqs w\u002F motif | % Bg\nknown_cols = [\n    \"motif_name\", \"consensus\", \"pvalue\", \"log_pvalue\",\n    \"qvalue\", \"n_target_seqs\", \"pct_target\",\n    \"n_bg_seqs\", \"pct_bg\"\n]\nknown = pd.read_csv(\n    \"motif_output\u002FknownResults.txt\",\n    sep=\"\\t\", header=0, names=known_cols\n)\n\n# Convert string percentages to floats\nknown[\"pct_target\"] = known[\"pct_target\"].str.rstrip(\"%\").astype(float)\nknown[\"pct_bg\"] = known[\"pct_bg\"].str.rstrip(\"%\").astype(float)\nknown[\"fold_enrichment\"] = known[\"pct_target\"] \u002F known[\"pct_bg\"].replace(0, 0.001)\nknown[\"-log10_pvalue\"] = -known[\"log_pvalue\"] \u002F 2.303  # log10 from natural log\n\nprint(f\"Total known motifs tested: {len(known)}\")\nprint(f\"Significant (p \u003C 1e-5): {(known['pvalue'].astype(float) \u003C 1e-5).sum()}\")\nprint(\"\\nTop 5 enriched motifs:\")\nprint(\n    known[[\"motif_name\", \"pct_target\", \"pct_bg\", \"fold_enrichment\", \"-log10_pvalue\"]]\n    .head(5)\n    .to_string(index=False)\n)\n# Total known motifs tested: 391\n# Significant (p \u003C 1e-5): 47\n# Top 5 enriched motifs:\n#  motif_name  pct_target  pct_bg  fold_enrichment  -log10_pvalue\n#  CTCF(Zf)\u002FGM12878-CTCF-ChIP-Seq...   78.21    8.32           9.40         312.4\n#  ZNF143(Zf)\u002F...                        42.11    5.10           8.26         188.7\n#  ...\n```\n\n### Step 7: Parse Peak Annotations and Visualize\n\nRead annotated peak output, summarize genomic feature distribution, and plot motif enrichments.\n\n```python\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport matplotlib.patches as mpatches\nimport seaborn as sns\n\n# --- Parse annotated peaks ---\n# annotatePeaks.pl output header: PeakID chr start end strand score ...\n# Key columns: \"Annotation\", \"Distance to TSS\", \"Nearest RefSeq\", \"Gene Name\"\nannot = pd.read_csv(\"annotated_peaks.txt\", sep=\"\\t\", header=0, low_memory=False)\nannot.columns = annot.columns.str.strip()\n\n# Simplify annotation categories\ndef simplify_annotation(ann):\n    if pd.isna(ann):\n        return \"Other\"\n    ann = str(ann)\n    if \"promoter\" in ann.lower():\n        return \"Promoter (\u003C2 kb)\"\n    elif \"exon\" in ann.lower():\n        return \"Exon\"\n    elif \"intron\" in ann.lower():\n        return \"Intron\"\n    elif \"tts\" in ann.lower() or \"downstream\" in ann.lower():\n        return \"Downstream\"\n    elif \"intergenic\" in ann.lower():\n        return \"Intergenic\"\n    else:\n        return \"Other\"\n\nannot[\"simple_ann\"] = annot[\"Annotation\"].apply(simplify_annotation)\nann_counts = annot[\"simple_ann\"].value_counts()\n\nprint(\"Peak annotation summary:\")\nprint(ann_counts.to_string())\n# Peak annotation summary:\n# Intron             5832\n# Intergenic         3102\n# Promoter (\u003C2 kb)   2218\n# Exon                891\n# Downstream          287\n# Other               123\n\n# --- Plot 1: Annotation pie chart ---\nfig, axes = plt.subplots(1, 2, figsize=(14, 5))\n\ncolors = [\"#E41A1C\", \"#377EB8\", \"#4DAF4A\", \"#984EA3\", \"#FF7F00\", \"#A65628\"]\naxes[0].pie(\n    ann_counts.values,\n    labels=ann_counts.index,\n    colors=colors[:len(ann_counts)],\n    autopct=\"%1.1f%%\",\n    startangle=140,\n    textprops={\"fontsize\": 9}\n)\naxes[0].set_title(\"Peak Genomic Annotation\\n(n=12,453 peaks)\", fontsize=11)\n\n# --- Plot 2: Top known motif enrichments ---\nknown = pd.read_csv(\"motif_output\u002FknownResults.txt\", sep=\"\\t\", header=0)\nknown.columns = [\n    \"motif_name\", \"consensus\", \"pvalue\", \"log_pvalue\",\n    \"qvalue\", \"n_target_seqs\", \"pct_target\", \"n_bg_seqs\", \"pct_bg\"\n]\nknown[\"pct_target\"] = known[\"pct_target\"].str.rstrip(\"%\").astype(float)\nknown[\"pct_bg\"] = known[\"pct_bg\"].str.rstrip(\"%\").astype(float)\nknown[\"-log10_p\"] = (-known[\"log_pvalue\"].astype(float)) \u002F 2.303\nknown[\"short_name\"] = known[\"motif_name\"].str.split(\"\u002F\").str[0]\n\ntop_motifs = known.head(15).copy()\nsns.barplot(\n    data=top_motifs,\n    x=\"-log10_p\",\n    y=\"short_name\",\n    palette=\"Blues_r\",\n    ax=axes[1]\n)\naxes[1].set_xlabel(\"-log10(p-value)\", fontsize=10)\naxes[1].set_ylabel(\"Motif\", fontsize=10)\naxes[1].set_title(\"Top 15 Enriched Known Motifs\\n(HOMER\u002FJASPAR database)\", fontsize=11)\naxes[1].axvline(x=5, color=\"red\", linestyle=\"--\", linewidth=0.8, label=\"p=1e-5\")\naxes[1].legend(fontsize=8)\n\nplt.tight_layout()\nplt.savefig(\"homer_summary.png\", dpi=150, bbox_inches=\"tight\")\nplt.close()\nprint(\"Saved: homer_summary.png\")\n```\n\n## Key Parameters\n\n| Parameter | Default | Range \u002F Options | Effect |\n|-----------|---------|-----------------|--------|\n| `-size` | `200` | 50–1000 | Window size (bp) centered on peak midpoint for motif search; 200 for TF ChIP-seq, 150 for ATAC-seq |\n| `-mask` | off | flag | Mask repetitive elements (N-mask); strongly recommended to reduce false positives |\n| `-p` | `1` | 1–64 | Number of parallel CPU threads; use 4–8 for typical datasets |\n| `-S` | `25` | 1–100 | Number of de novo motifs to find; 25 is usually sufficient |\n| `-nomotif` | off | flag | Skip de novo motif discovery; only perform known motif enrichment (10× faster) |\n| `-bg` | auto-generated | BED file path | Custom background region file; auto-background is GC-matched if omitted |\n| `-find` | — | `.motif` file path | Scan peaks for occurrences of a specific motif matrix; outputs per-peak annotation |\n| `-mis` | `2` | 0–4 | Maximum mismatches allowed when matching known motifs |\n| `-len` | `8,10,12` | comma-separated integers | Motif lengths to try for de novo search; adding `6` finds shorter motifs |\n| `genome` | required | `hg38`, `mm10`, `hg19`, `dm6`, `ce11`, etc. | Reference genome assembly; must be installed with `installGenome.pl` |\n\n## Common Recipes\n\n### Recipe 1: Python subprocess Wrapper for findMotifsGenome.pl\n\nRun HOMER from a Python script and capture completion status.\n\n```python\nimport subprocess\nimport sys\nfrom pathlib import Path\n\ndef run_homer_motifs(\n    peaks_bed: str,\n    genome: str,\n    output_dir: str,\n    size: int = 200,\n    mask: bool = True,\n    cpus: int = 4,\n    n_motifs: int = 25,\n    denovo: bool = True,\n    bg_bed: str = None\n) -> int:\n    \"\"\"Run findMotifsGenome.pl and return exit code.\"\"\"\n    Path(output_dir).mkdir(parents=True, exist_ok=True)\n    cmd = [\n        \"findMotifsGenome.pl\", peaks_bed, genome, output_dir,\n        \"-size\", str(size),\n        \"-p\", str(cpus),\n        \"-S\", str(n_motifs),\n    ]\n    if mask:\n        cmd.append(\"-mask\")\n    if not denovo:\n        cmd.append(\"-nomotif\")\n    if bg_bed:\n        cmd.extend([\"-bg\", bg_bed])\n\n    print(f\"Running: {' '.join(cmd)}\")\n    result = subprocess.run(cmd, capture_output=True, text=True)\n    if result.returncode != 0:\n        print(f\"HOMER stderr:\\n{result.stderr[-2000:]}\", file=sys.stderr)\n        return result.returncode\n    print(f\"Done. Output in {output_dir}\u002F\")\n    return 0\n\n# Usage\nexit_code = run_homer_motifs(\n    peaks_bed=\"peaks\u002Ftf_chip_200bp.bed\",\n    genome=\"hg38\",\n    output_dir=\"motif_output\u002F\",\n    size=200, mask=True, cpus=4, n_motifs=25\n)\nprint(f\"Exit code: {exit_code}\")\n# Running: findMotifsGenome.pl peaks\u002Ftf_chip_200bp.bed hg38 motif_output\u002F -size 200 -p 4 -S 25 -mask\n# Done. Output in motif_output\u002F\n# Exit code: 0\n```\n\n### Recipe 2: Batch Motif Analysis Across Multiple Peak Sets\n\nRun HOMER on multiple ChIP-seq samples in a loop.\n\n```bash\n#!\u002Fbin\u002Fbash\n# Batch motif analysis for several ChIP-seq experiments (same genome)\nGENOME=\"hg38\"\nPEAK_DIR=\"peaks\"\nMOTIF_DIR=\"motif_results\"\nmkdir -p \"$MOTIF_DIR\"\n\nSAMPLES=(CTCF H3K4me3 FOXA2 RUNX1)\n\nfor sample in \"${SAMPLES[@]}\"; do\n    echo \"=== Processing $sample ===\"\n    peak_file=\"${PEAK_DIR}\u002F${sample}_summits.bed\"\n\n    if [ ! -f \"$peak_file\" ]; then\n        echo \"  Skipping $sample: $peak_file not found\"\n        continue\n    fi\n\n    # Center on summit ±100 bp\n    awk 'BEGIN{OFS=\"\\t\"} {s=$2-100\u003C0?0:$2-100; print $1,s,$2+100,$4,$5}' \\\n        \"$peak_file\" > \"${PEAK_DIR}\u002F${sample}_200bp.bed\"\n\n    findMotifsGenome.pl \"${PEAK_DIR}\u002F${sample}_200bp.bed\" \"$GENOME\" \\\n        \"${MOTIF_DIR}\u002F${sample}\u002F\" \\\n        -size 200 -mask -p 4 -nomotif \\\n        2> \"${MOTIF_DIR}\u002F${sample}.log\"\n\n    n=$(wc -l \u003C \"${MOTIF_DIR}\u002F${sample}\u002FknownResults.txt\")\n    echo \"  $sample: $n motifs tested. Top hit: $(sed -n '2p' \"${MOTIF_DIR}\u002F${sample}\u002FknownResults.txt\" | cut -f1)\"\ndone\n# === Processing CTCF ===\n#   CTCF: 392 motifs tested. Top hit: CTCF(Zf)\u002FGM12878-CTCF-ChIP-Seq(GSE32465)\u002FHomer\n# === Processing FOXA2 ===\n#   FOXA2: 392 motifs tested. Top hit: Foxa2(Forkhead)\u002FLiver-Foxa2-ChIP-Seq(GSE25694)\u002FHomer\n```\n\n### Recipe 3: Parse De Novo Motif Matrices from homerResults\u002F\n\nLoad de novo motif PWM matrices for downstream comparison or plotting.\n\n```python\nimport os\nimport re\nimport pandas as pd\n\ndef parse_homer_motif(motif_file: str) -> dict:\n    \"\"\"Parse a HOMER .motif file into name, log_odds_threshold, and PWM.\"\"\"\n    with open(motif_file) as f:\n        header = f.readline().strip()  # >motif_name\\tlog_odds\\tlog_p-value\\t0\\tnucs\n        rows = []\n        for line in f:\n            line = line.strip()\n            if line:\n                rows.append([float(x) for x in line.split(\"\\t\")])\n    parts = header.lstrip(\">\").split(\"\\t\")\n    name = parts[0]\n    log_odds = float(parts[1]) if len(parts) > 1 else 0.0\n    log_p = float(parts[2]) if len(parts) > 2 else 0.0\n    pwm = pd.DataFrame(rows, columns=[\"A\", \"C\", \"G\", \"T\"])\n    return {\"name\": name, \"log_odds\": log_odds, \"log_p\": log_p, \"pwm\": pwm}\n\n# Load all de novo motifs\nmotif_dir = \"motif_output\u002FhomerResults\u002F\"\nmotifs = []\nfor fn in sorted(os.listdir(motif_dir)):\n    if fn.endswith(\".motif\"):\n        motif = parse_homer_motif(os.path.join(motif_dir, fn))\n        motifs.append(motif)\n        print(f\"{fn}: {motif['name']} ({len(motif['pwm'])} positions, log_p={motif['log_p']:.1f})\")\n\nprint(f\"\\nLoaded {len(motifs)} de novo motifs\")\n# motif1.motif: CTCF-motif (19 positions, log_p=-8234.1)\n# motif2.motif: CTCFL-motif (17 positions, log_p=-3421.7)\n# ...\n# Loaded 25 de novo motifs\n```\n\n### Recipe 4: Annotate Peaks and Join with Differential Expression Results\n\nCombine peak annotations with RNA-seq DE results to find regulated genes near peaks.\n\n```python\nimport pandas as pd\n\n# Load annotated peaks\nannot = pd.read_csv(\"annotated_peaks.txt\", sep=\"\\t\", header=0, low_memory=False)\nannot.columns = annot.columns.str.strip()\n\n# Key columns from HOMER annotation\npeak_genes = annot[[\"PeakID (cmd=annotatePeaks.pl peaks.bed hg38)\",\n                     \"Chr\", \"Start\", \"End\",\n                     \"Annotation\", \"Distance to TSS\",\n                     \"Nearest RefSeq\", \"Gene Name\"]].copy()\npeak_genes.columns = [\"peak_id\", \"chr\", \"start\", \"end\",\n                      \"annotation\", \"tss_dist\", \"refseq\", \"gene_name\"]\n\n# Filter promoter-proximal peaks (within 2 kb of TSS)\npromoter_peaks = peak_genes[peak_genes[\"tss_dist\"].abs() \u003C 2000].copy()\nprint(f\"Promoter-proximal peaks (|TSS| \u003C 2kb): {len(promoter_peaks)}\")\n# Promoter-proximal peaks (|TSS| \u003C 2kb): 2218\n\n# Load DESeq2 results (gene_name, log2FC, padj)\nde_results = pd.read_csv(\"deseq2_results.csv\")\nde_sig = de_results[de_results[\"padj\"] \u003C 0.05].copy()\n\n# Merge: find DE genes with a nearby peak\nmerged = promoter_peaks.merge(de_sig, on=\"gene_name\", how=\"inner\")\nprint(f\"DE genes with promoter-proximal peak: {len(merged)}\")\nprint(merged[[\"gene_name\", \"tss_dist\", \"annotation\", \"log2FC\", \"padj\"]].head())\n# DE genes with promoter-proximal peak: 347\n```\n\n## Expected Outputs\n\n| Output | Format | Description |\n|--------|--------|-------------|\n| `motif_output\u002FknownResults.txt` | TSV | All known motifs tested: name, p-value, q-value, % target, % background; primary result file |\n| `motif_output\u002FknownResults.html` | HTML | Interactive HTML report with motif logos, statistics, and links |\n| `motif_output\u002FhomerResults\u002F` | Directory | De novo motifs: `motifN.motif` (PWM matrix), `motifN.logo.png`, `similar.motifs.txt` |\n| `motif_output\u002FhomerResults.html` | HTML | Interactive HTML report for de novo motifs |\n| `annotated_peaks.txt` | TSV | One row per peak: chr, start, end, annotation, TSS distance, nearest gene, RefSeq ID |\n| `peaks_with_motif1.txt` | TSV | Per-peak motif occurrence scores (from `-find` mode) |\n\n## Troubleshooting\n\n| Problem | Cause | Solution |\n|---------|-------|----------|\n| `ERROR: Genome not found` | Genome not installed via `installGenome.pl` | Run `installGenome.pl hg38`; confirm `~\u002F.homer\u002Fdata\u002Fgenomes\u002Fhg38\u002F` exists |\n| `command not found: findMotifsGenome.pl` | HOMER binaries not in `$PATH` | Add HOMER bin directory to PATH: `export PATH=~\u002F.homer\u002Fbin:$PATH` (or activate conda env) |\n| Poor de novo motif quality (GC-rich artifacts) | Unmasked repetitive elements | Always use `-mask`; also try increasing `-size` to 300 or reducing to 150 |\n| No significant known motifs (all p > 0.01) | Too few peaks or wrong peak size | Ensure ≥500 peaks; check `-size` matches expected binding footprint (150–200 for TFs) |\n| Conda HOMER conflicts (Perl module errors) | HOMER's Perl scripts conflict with conda environment Perl | Install HOMER in a dedicated conda env: `conda create -n homer_only -c bioconda homer` |\n| `annotatePeaks.pl` gives all \"Intergenic\" | Genome annotation not installed | HOMER annotation requires `installGenome.pl` which downloads GTF; check `~\u002F.homer\u002Fdata\u002Fgenomes\u002Fhg38\u002F` contains `*.ann` files |\n| Very slow run time (>2 hr) | Single-threaded or large peak set | Add `-p 8`; reduce `-S` to 10 for speed; use `-nomotif` for known-only runs |\n| `-bg` custom background gives poor motifs | Background regions have very different GC content | Use a GC-matched background; run `bedtools shuffle` with `-noOverlapping` to generate random same-size regions |\n\n## References\n\n- [HOMER official documentation](http:\u002F\u002Fhomer.ucsd.edu\u002Fhomer\u002F) — comprehensive guide to all HOMER commands, parameters, and output formats\n- Heinz S et al. (2010) \"Simple Combinations of Lineage-Determining Transcription Factors Prime cis-Regulatory Elements Required for Macrophage and B Cell Identities.\" *Molecular Cell* 38(4):576–589. [DOI:10.1016\u002Fj.molcel.2010.05.004](https:\u002F\u002Fdoi.org\u002F10.1016\u002Fj.molcel.2010.05.004)\n- [HOMER GitHub: samtools\u002Fhomer](https:\u002F\u002Fgithub.com\u002Fsamtools\u002Fhomer) — source code and issue tracker\n- [JASPAR 2024 database](https:\u002F\u002Fjaspar.elixir.no\u002F) — curated TF binding motif database used by HOMER for known motif enrichment\n",{"name":5,"license":15,"description":7},"master","fd76f882a04e445e899d5cfb2732f2105ea054ee","skills\u002Fawesome-skills\u002Fhomer-motif-analysis",0,"https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS","https:\u002F\u002Fbg-szy.github.io\u002FTOP-SKILLS\u002F","https:\u002F\u002Fgithub.com\u002Fbg-szy","https:\u002F\u002Fwww.ecust.edu.cn\u002F","a student of East China University of Science and Technology","2026-11-12 05:55:03",{"source":8,"skillName":5,"commands":35,"prompt":45,"zipAvailable":46},[36,39,42],{"tool":37,"command":38},"npx","npx skills add bg-szy\u002FTOP-SKILLS --skill homer-motif-analysis",{"tool":40,"command":41},"bunx","bunx skills add bg-szy\u002FTOP-SKILLS --skill homer-motif-analysis",{"tool":43,"command":44},"pnpm","pnpm dlx skills add bg-szy\u002FTOP-SKILLS --skill homer-motif-analysis","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fawesome-skills\u002Fhomer-motif-analysis\u002FSKILL.md",true,[],[49,57,64,73,81,89],{"skillNo":50,"name":51,"nameZh":6,"description":52,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":53,"licenseFileUrl":6,"sourceHtmlUrl":54,"categories":55,"keywords":56,"publishedAt":19},"01M748C5DS5BQBVBMG22FCGG34","branding","When the user wants to define, audit, or apply brand strategy—purpose, values, positioning, storytelling, voice, narrative (not only visuals). Also use when the user mentions \"brand strategy\", \"brand story\", \"brand storytelling\" or \"brand voice\". For typography, colors, design tokens, and frontend visuals, use brand-visual-generator.","MIT","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fsuperskills\u002Fbranding\u002FSKILL.md",[],[],{"skillNo":58,"name":59,"nameZh":6,"description":60,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":53,"licenseFileUrl":6,"sourceHtmlUrl":61,"categories":62,"keywords":63,"publishedAt":19},"01M748C1GXJ9WRKP18X45DKP6G","brand-visual-generator","When the user wants to define, audit, or apply visual identity (typography, colors, spacing, design tokens, frontend aesthetics). Also use when the user mentions \"brand style guide\", \"visual identity\", \"design system\" or \"typography\". For brand story, positioning, and voice, use branding.","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fsuperskills\u002Fbrand-visual-generator\u002FSKILL.md",[],[],{"skillNo":65,"name":66,"nameZh":6,"description":67,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":68,"licenseFileUrl":69,"sourceHtmlUrl":70,"categories":71,"keywords":72,"publishedAt":19},"01M747T565TFEP3RAVWM0Y899Y","mcp-builder","Guide for creating high-quality MCP (Model Context Protocol) servers that enable LLMs to interact with external services through well-designed tools. Use when building MCP servers to integrate external APIs or services, whether in Python (FastMCP) or Node\u002FTypeScript (MCP SDK).","Apache-2.0","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Fmcp-builder\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Fmcp-builder\u002FSKILL.md",[],[],{"skillNo":74,"name":75,"nameZh":6,"description":76,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":68,"licenseFileUrl":77,"sourceHtmlUrl":78,"categories":79,"keywords":80,"publishedAt":19},"01M747RAJGMBZ2QN4563STB5SH","frontend-design","Guidance for distinctive, intentional visual design when building new UI or reshaping an existing one. Helps with aesthetic direction, typography, and making choices that don't read as templated defaults.","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Ffrontend-design\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Ffrontend-design\u002FSKILL.md",[],[],{"skillNo":82,"name":83,"nameZh":6,"description":84,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":68,"licenseFileUrl":85,"sourceHtmlUrl":86,"categories":87,"keywords":88,"publishedAt":19},"01M747NHAY5BE9GXEB31H255R1","claude-api","Reference for the Claude API \u002F Anthropic SDK — model ids, pricing, params, streaming, tool use, MCP, agents, caching, token counting, model migration.\nTRIGGER — read BEFORE opening the target file; don't skip because it \"looks like a one-liner\" — whenever: the prompt names Claude\u002FAnthropic in any form (Claude, Anthropic, Fable, Opus, Sonnet, Haiku, `anthropic`, `@anthropic-ai`, `claude-*`, `us.anthropic.*`, `[1m]`); the user asks about an LLM (pricing\u002Fmodel choice\u002Flimits\u002Fcaching) — never answer from memory; OR the task is LLM-shaped with provider unstated (agent\u002FMCP\u002Ftool-definition\u002Fmulti-agent\u002FRAG\u002FLLM-judge\u002Fcomputer-use; generate\u002Fsummarize\u002Fextract\u002Fclassify\u002Frewrite\u002Fconverse over NL; debugging refusals\u002Fcutoffs\u002Fstreaming\u002Ftool-calls\u002Ftokens).\nSKIP only when another provider is being worked on (overrides all triggers): OpenAI\u002FGPT\u002FGemini\u002FLlama\u002FMistral\u002FCohere\u002FOllama named in the query; OR `grep -rE 'openai|langchain_openai|google.generativeai|genai|mistralai|cohere|ollama'` over the project hits (run this grep FIRST if no provider named — don't Read the file).","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Fclaude-api\u002FLICENSE.txt","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fskills\u002Fclaude-api\u002FSKILL.md",[],[],{"skillNo":90,"name":91,"nameZh":6,"description":92,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":53,"licenseFileUrl":93,"sourceHtmlUrl":94,"categories":95,"keywords":96,"publishedAt":19},"01M73WM4TPHEJ57D7G2AZ0ABVT","inbox-guardian-for-gmail","Review a personal Gmail inbox with local, owner-approved spam rules. Use for audit-first quarantine, Trash, repeated-evidence sender learning, and header review. Do not use for automatic unsubscribe requests or unreviewed mailbox actions.","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fmarketplace\u002Finbox-guardian-for-gmail\u002FLICENSE","https:\u002F\u002Fgithub.com\u002Fbg-szy\u002FTOP-SKILLS\u002Fblob\u002Fmaster\u002Fskills\u002Fmarketplace\u002Finbox-guardian-for-gmail\u002FSKILL.md",[],[]]