UniProt Database Access
davila7/claude-code-templates
Queries the UniProt REST API directly to search proteins, fetch FASTA sequences, map IDs between databases and read Swiss-Prot and TrEMBL entries.
Query EBI QuickGO REST API for GO terms and protein annotations.
$ npx skills add jaechang-hits/SciAgent-Skills --skill quickgo-database -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install jaechang-hits/SciAgent-Skills quickgo-database --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/jaechang-hits/SciAgent-Skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/genomics-bioinformatics/databases/quickgo-database .claude/skills/quickgo-database && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "quickgo-database" agent skill from https://github.com/jaechang-hits/SciAgent-Skills/tree/main/skills/genomics-bioinformatics/databases/quickgo-database into .claude/skills/quickgo-database/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "quickgo-database", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/jaechang-hits/SciAgent-Skills/tree/main/skills/genomics-bioinformatics/databases/quickgo-databaseType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add jaechang-hits/SciAgent-Skills --skill quickgo-database -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install jaechang-hits/SciAgent-Skills quickgo-database --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jaechang-hits/SciAgent-Skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/genomics-bioinformatics/databases/quickgo-database .agents/skills/quickgo-database && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "quickgo-database" agent skill from https://github.com/jaechang-hits/SciAgent-Skills/tree/main/skills/genomics-bioinformatics/databases/quickgo-database into .agents/skills/quickgo-database/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "quickgo-database", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add jaechang-hits/SciAgent-Skills --skill quickgo-database -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install jaechang-hits/SciAgent-Skills quickgo-database --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jaechang-hits/SciAgent-Skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/genomics-bioinformatics/databases/quickgo-database .cursor/skills/quickgo-database && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "quickgo-database" agent skill from https://github.com/jaechang-hits/SciAgent-Skills/tree/main/skills/genomics-bioinformatics/databases/quickgo-database into .cursor/skills/quickgo-database/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "quickgo-database", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/jaechang-hits/SciAgent-Skills.git --path skills/genomics-bioinformatics/databases/quickgo-database--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add jaechang-hits/SciAgent-Skills --skill quickgo-database -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install jaechang-hits/SciAgent-Skills quickgo-database --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jaechang-hits/SciAgent-Skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/genomics-bioinformatics/databases/quickgo-database .gemini/skills/quickgo-database && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "quickgo-database" agent skill from https://github.com/jaechang-hits/SciAgent-Skills/tree/main/skills/genomics-bioinformatics/databases/quickgo-database into .gemini/skills/quickgo-database/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "quickgo-database", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install jaechang-hits/SciAgent-Skills quickgo-databaseInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add jaechang-hits/SciAgent-Skills --skill quickgo-database -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/jaechang-hits/SciAgent-Skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/genomics-bioinformatics/databases/quickgo-database .github/skills/quickgo-database && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "quickgo-database" agent skill from https://github.com/jaechang-hits/SciAgent-Skills/tree/main/skills/genomics-bioinformatics/databases/quickgo-database into .github/skills/quickgo-database/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "quickgo-database", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add jaechang-hits/SciAgent-Skills --skill quickgo-database -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install jaechang-hits/SciAgent-Skills quickgo-database --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/jaechang-hits/SciAgent-Skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/genomics-bioinformatics/databases/quickgo-database .opencode/skills/quickgo-database && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "quickgo-database" agent skill from https://github.com/jaechang-hits/SciAgent-Skills/tree/main/skills/genomics-bioinformatics/databases/quickgo-database into .opencode/skills/quickgo-database/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "quickgo-database", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
quickgo-databaseQuery EBI QuickGO REST API for GO terms and protein annotations.
Quickgo Database is an agent skill from jaechang-hits/SciAgent-Skills. Query EBI QuickGO REST API for GO terms and protein annotations. Fetch term metadata by ID, search by keyword, walk ancestor/descendant hierarchies, download annotations filtered by taxon, evidence code, aspect. Use for GO resolution, ontology traversal, annotation retrieval before enrichment. Use gseapy-gene-enrichment for enrichment; uniprot-protein-database for proteins.
Its SKILL.md is about 6.9k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Research & Science, covering Bioinformatics and REST APIs. It works with UniProt. The repository describes itself as: 197 bioinformatics & life science skills for Claude Code and AI agents — BixBench 92.0% accuracy. RNA-seq, single-cell, drug discovery, proteomics, and more. Powers OmicsHorizon. The licence is Apache-2.0.
5 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 82c862c. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
pipFrom the folder's file list and the shell code blocks in SKILL.md.
Hosts in commands or code, which the agent is likely to contact:
ebi.ac.ukAlso links to:
doi.orggeneontology.orgFrom URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Quickgo Database loads about 6.9k tokens when it runs. Until then it costs about 98 tokens; SKILL.md has 1,198 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from jaechang-hits/SciAgent-Skills at commit 82c862c, republished under its Apache-2.0 licence (© jaechang-hits). 1,198 words, ~6,928 tokens.
.claude/skills/quickgo-database/SKILL.md (or your agent's skills folder).QuickGO is the EBI's Gene Ontology annotation browser and REST API. It provides programmatic access to the GO ontology (terms, synonyms, hierarchies) and to the manually curated and electronic GO annotations for proteins across all species. The API is free, requires no authentication, and returns JSON responses. All endpoints live under https://www.ebi.ac.uk/QuickGO/services/.
GO:0006915) to its name, definition, and aspect (biological_process, molecular_function, cellular_component)gseapy-gene-enrichment; QuickGO provides the raw annotation datauniprot-protein-databaserequests, pandas, matplotlibGO:XXXXXXX) or UniProt accessions; taxon IDs (e.g., 9606 for human)time.sleep(1.0) between requests in batch loops for polite accesspip install requests pandas matplotlibimport requests
import time
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
def quickgo_get(endpoint: str, params: dict = None) -> dict:
"""Send a GET request to a QuickGO endpoint and return parsed JSON."""
url = f"{QUICKGO_BASE}/{endpoint}"
headers = {"Accept": "application/json"}
r = requests.get(url, params=params, headers=headers, timeout=30)
r.raise_for_status()
return r.json()
# Fetch metadata for the apoptotic process GO term
result = quickgo_get("ontology/go/terms/GO:0006915")
term = result["results"][0]
print(f"ID : {term['id']}")
print(f"Name : {term['name']}")
print(f"Aspect : {term['aspect']}")
print(f"Def : {term['definition']['text'][:100]}...")
# ID : GO:0006915
# Name : apoptotic process
# Aspect : biological_process
# Def : A programmed cell death process which begins when a cell receives ...Fetch term metadata — name, definition, aspect, synonyms, and is-obsolete status — for one or more GO IDs.
import requests
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
def get_go_term(go_id: str) -> dict:
"""Retrieve metadata for a single GO term by ID."""
headers = {"Accept": "application/json"}
r = requests.get(
f"{QUICKGO_BASE}/ontology/go/terms/{go_id}",
headers=headers, timeout=30
)
r.raise_for_status()
results = r.json().get("results", [])
return results[0] if results else {}
term = get_go_term("GO:0005515")
print(f"Name : {term['name']}")
print(f"Aspect : {term['aspect']}")
print(f"Obsolete: {term.get('isObsolete', False)}")
print(f"Synonyms: {[s['name'] for s in term.get('synonyms', [])[:3]]}")
# Name : protein binding
# Aspect : molecular_function
# Obsolete: False
# Synonyms: ['protein-protein interaction', 'protein binding activity']# Batch lookup: resolve multiple GO IDs in one request
go_ids = ["GO:0006915", "GO:0005515", "GO:0016020"]
ids_param = ",".join(go_ids)
r = requests.get(
f"{QUICKGO_BASE}/ontology/go/terms/{ids_param}",
headers={"Accept": "application/json"}, timeout=30
)
r.raise_for_status()
for t in r.json().get("results", []):
print(f"{t['id']} {t['aspect']:<25} {t['name']}")
# GO:0006915 biological_process apoptotic process
# GO:0005515 molecular_function protein binding
# GO:0016020 cellular_component membraneRetrieve GO annotations for a protein or a set of proteins. Filter by evidence code and taxon.
import requests
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
def get_protein_annotations(uniprot_id: str, evidence_codes: list = None,
limit: int = 100) -> list:
"""Fetch GO annotations for a UniProt protein."""
params = {
"geneProductId": f"UniProtKB:{uniprot_id}",
"limit": limit,
"page": 1,
}
if evidence_codes:
params["evidenceCode"] = ",".join(evidence_codes)
headers = {"Accept": "application/json"}
r = requests.get(
f"{QUICKGO_BASE}/annotation/search",
params=params, headers=headers, timeout=30
)
r.raise_for_status()
return r.json().get("results", [])
# Fetch experimental annotations for TP53 (P04637)
annotations = get_protein_annotations(
"P04637",
evidence_codes=["EXP", "IDA", "IPI", "IMP", "IGI", "IEP"]
)
print(f"Experimental annotations for TP53: {len(annotations)}")
for ann in annotations[:4]:
print(f" {ann['goId']} {ann['goName']:<40} {ann['evidenceCode']}")
# Experimental annotations for TP53: 87
# GO:0006977 DNA damage response, ... IDA
# GO:0043065 positive regulation of apoptosis IMP# Annotations for a taxon (human, 9606) + specific GO term
params = {
"goId": "GO:0006915",
"taxonId": "9606",
"evidenceCode": "EXP,IDA,IPI,IMP,IGI,IEP",
"limit": 100,
"page": 1,
}
r = requests.get(
f"{QUICKGO_BASE}/annotation/search",
params=params,
headers={"Accept": "application/json"},
timeout=30
)
r.raise_for_status()
data = r.json()
print(f"Total annotations: {data.get('numberOfHits', 'N/A')}")
print(f"Retrieved : {len(data.get('results', []))}")
for ann in data["results"][:3]:
print(f" {ann['geneProductId']} {ann['goId']} {ann['evidenceCode']}")Get ancestors (terms more general than the query term) or descendants (more specific terms) by traversing the GO DAG.
import requests
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
def get_ancestors(go_id: str, relations: str = "is_a,part_of") -> list:
"""Return ancestor GO IDs for a term via the ontology hierarchy."""
r = requests.get(
f"{QUICKGO_BASE}/ontology/go/terms/{go_id}/ancestors",
params={"relations": relations},
headers={"Accept": "application/json"},
timeout=30
)
r.raise_for_status()
results = r.json().get("results", [])
return results[0].get("ancestors", []) if results else []
def get_descendants(go_id: str, relations: str = "is_a,part_of") -> list:
"""Return descendant GO IDs for a term via the ontology hierarchy."""
r = requests.get(
f"{QUICKGO_BASE}/ontology/go/terms/{go_id}/descendants",
params={"relations": relations},
headers={"Accept": "application/json"},
timeout=30
)
r.raise_for_status()
results = r.json().get("results", [])
return results[0].get("descendants", []) if results else []
ancestors = get_ancestors("GO:0006915")
descendants = get_descendants("GO:0006915")
print(f"Ancestors of GO:0006915 (apoptotic process): {len(ancestors)}")
print(f"Descendants of GO:0006915 : {len(descendants)}")
print(f"First 5 ancestors : {ancestors[:5]}")
# Ancestors of GO:0006915 (apoptotic process): 6
# Descendants of GO:0006915 : 53
# First 5 ancestors : ['GO:0008219', 'GO:0009987', ...]Text-search for GO terms by keyword. Useful for discovering relevant GO IDs before building annotation queries.
import requests
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
def search_go_terms(query: str, limit: int = 20) -> list:
"""Search GO terms by keyword; returns list of term dicts."""
r = requests.get(
f"{QUICKGO_BASE}/ontology/go/search",
params={"query": query, "limit": limit, "page": 1},
headers={"Accept": "application/json"},
timeout=30
)
r.raise_for_status()
return r.json().get("results", [])
hits = search_go_terms("autophagy")
print(f"GO terms matching 'autophagy': {len(hits)}")
for h in hits[:5]:
print(f" {h['id']} {h['aspect']:<25} {h['name']}")
# GO terms matching 'autophagy': 20
# GO:0006914 biological_process autophagy
# GO:0016236 biological_process macroautophagy
# GO:0061709 biological_process reticulophagyGet counts of annotations grouped by evidence code, GO aspect, or taxon for a gene product or GO term.
import requests
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
def get_annotation_stats(uniprot_id: str) -> dict:
"""Retrieve annotation counts by evidence type and GO aspect."""
params = {
"geneProductId": f"UniProtKB:{uniprot_id}",
"limit": 200,
"page": 1,
}
r = requests.get(
f"{QUICKGO_BASE}/annotation/search",
params=params,
headers={"Accept": "application/json"},
timeout=30
)
r.raise_for_status()
results = r.json().get("results", [])
by_evidence = {}
by_aspect = {}
for ann in results:
ec = ann.get("evidenceCode", "unknown")
asp = ann.get("goAspect", "unknown")
by_evidence[ec] = by_evidence.get(ec, 0) + 1
by_aspect[asp] = by_aspect.get(asp, 0) + 1
return {"by_evidence": by_evidence, "by_aspect": by_aspect,
"total": len(results)}
stats = get_annotation_stats("P04637") # TP53
print(f"Total annotations (first page): {stats['total']}")
print("\nBy evidence code:")
for ec, n in sorted(stats["by_evidence"].items(), key=lambda x: -x[1]):
print(f" {ec:<5} : {n}")
print("\nBy GO aspect:")
for asp, n in stats["by_aspect"].items():
print(f" {asp}: {n}")Resolve a list of GO IDs to their names and aspects in a single API call (up to ~200 IDs per request).
import requests
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
def batch_resolve_go_terms(go_ids: list) -> dict:
"""Resolve a list of GO IDs → {id: {name, aspect, definition}} in one call."""
ids_param = ",".join(go_ids)
r = requests.get(
f"{QUICKGO_BASE}/ontology/go/terms/{ids_param}",
headers={"Accept": "application/json"},
timeout=60
)
r.raise_for_status()
return {
t["id"]: {
"name": t["name"],
"aspect": t["aspect"],
"definition": t.get("definition", {}).get("text", ""),
"obsolete": t.get("isObsolete", False),
}
for t in r.json().get("results", [])
}
go_ids = ["GO:0006915", "GO:0005515", "GO:0016020", "GO:0006281", "GO:0051301"]
resolved = batch_resolve_go_terms(go_ids)
print(f"Resolved {len(resolved)}/{len(go_ids)} GO IDs")
for gid, info in resolved.items():
print(f" {gid} [{info['aspect'][:2].upper()}] {info['name']}")
# Resolved 5/5 GO IDs
# GO:0006915 [BI] apoptotic process
# GO:0005515 [MO] protein binding
# GO:0016020 [CE] membraneThe Gene Ontology is a directed acyclic graph (DAG) organized into three independent root aspects:
| Aspect code | Aspect name | Root term |
|---|---|---|
biological_process | Biological process (BP) | GO:0008150 |
molecular_function | Molecular function (MF) | GO:0003674 |
cellular_component | Cellular component (CC) | GO:0005575 |
Terms are connected by two primary relation types: is_a (subclass) and part_of (mereological). When filtering annotation enrichment results, always check the aspect field to avoid mixing BP, MF, and CC terms.
The evidence code determines annotation reliability. Filter to experimental codes for high-confidence annotations; exclude IEA in clinical or mechanistic analyses.
| Category | Codes | Meaning |
|---|---|---|
| Experimental | EXP, IDA, IPI, IMP, IGI, IEP | Direct biochemical or genetic experiments |
| Computational/similarity | ISS, ISO, ISA, IBA, RCA | Inferred by sequence or phylogenetic similarity |
| Author statement | TAS, IC | Curator or author assertion without experiment |
| Electronic | IEA | Automated; no human review — lowest confidence |
| High throughput | HTP, HDA, HMP, HGI, HEP | High-throughput experimental methods |
QuickGO annotation searches return paginated results. The numberOfHits field in the response gives the total count. Use the page parameter to iterate through all results when numberOfHits > limit.
import requests, time
def get_all_annotations(go_id: str, taxon_id: str = "9606",
evidence_codes: str = "EXP,IDA,IPI,IMP",
page_size: int = 100) -> list:
"""Retrieve all annotation pages for a GO term + taxon combination."""
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
all_results = []
page = 1
while True:
params = {"goId": go_id, "taxonId": taxon_id,
"evidenceCode": evidence_codes, "limit": page_size,
"page": page}
r = requests.get(f"{QUICKGO_BASE}/annotation/search",
params=params, headers={"Accept": "application/json"},
timeout=30)
r.raise_for_status()
data = r.json()
results = data.get("results", [])
all_results.extend(results)
total = data.get("numberOfHits", 0)
if len(all_results) >= total or not results:
break
page += 1
time.sleep(1.0) # polite delay
return all_resultsGoal: Retrieve all GO annotations for a protein, split by aspect and evidence category, and visualize the evidence code distribution.
import requests, time
import pandas as pd
import matplotlib.pyplot as plt
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
def get_all_annotations_for_protein(uniprot_id: str, page_size: int = 200) -> list:
all_results = []
page = 1
while True:
params = {"geneProductId": f"UniProtKB:{uniprot_id}",
"limit": page_size, "page": page}
r = requests.get(f"{QUICKGO_BASE}/annotation/search",
params=params, headers={"Accept": "application/json"},
timeout=30)
r.raise_for_status()
data = r.json()
results = data.get("results", [])
all_results.extend(results)
if len(all_results) >= data.get("numberOfHits", 0) or not results:
break
page += 1
time.sleep(1.0)
return all_results
UNIPROT_ID = "P04637" # TP53 human
annotations = get_all_annotations_for_protein(UNIPROT_ID)
print(f"Total annotations for {UNIPROT_ID}: {len(annotations)}")
df = pd.DataFrame([{
"goId": a["goId"],
"goName": a.get("goName", ""),
"aspect": a.get("goAspect", ""),
"evidenceCode": a.get("evidenceCode", ""),
"reference": a.get("reference", ""),
"assignedBy": a.get("assignedBy", ""),
} for a in annotations])
# Evidence code distribution bar chart
ec_counts = df["evidenceCode"].value_counts()
fig, ax = plt.subplots(figsize=(9, 4))
bars = ax.bar(ec_counts.index, ec_counts.values, color="#2171B5", edgecolor="white")
ax.bar_label(bars, fontsize=8, padding=2)
ax.set_xlabel("Evidence Code")
ax.set_ylabel("Annotation Count")
ax.set_title(f"GO Annotation Evidence Codes — {UNIPROT_ID} (TP53)")
plt.tight_layout()
plt.savefig(f"{UNIPROT_ID}_evidence_codes.png", dpi=150, bbox_inches="tight")
print(f"Saved {UNIPROT_ID}_evidence_codes.png")
print(df.groupby(["aspect", "evidenceCode"]).size().to_string())Goal: For a GO term of interest, find all descendant terms and then retrieve annotations for all of them combined — capturing the full semantic scope.
import requests, time, pandas as pd
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
def quickgo_get(endpoint, params=None):
r = requests.get(f"{QUICKGO_BASE}/{endpoint}",
params=params, headers={"Accept": "application/json"},
timeout=30)
r.raise_for_status()
return r.json()
# Step 1: Get all descendants of "cell death" (GO:0008219)
parent_go_id = "GO:0008219"
desc_data = quickgo_get(f"ontology/go/terms/{parent_go_id}/descendants",
params={"relations": "is_a,part_of"})
descendants = desc_data["results"][0]["descendants"] if desc_data["results"] else []
all_ids = [parent_go_id] + descendants
print(f"GO terms in '{parent_go_id}' subtree: {len(all_ids)}")
# Step 2: Batch-resolve term names (chunk to ≤ 100 per request)
resolved = {}
chunk_size = 100
for i in range(0, len(all_ids), chunk_size):
chunk = all_ids[i:i + chunk_size]
data = quickgo_get(f"ontology/go/terms/{','.join(chunk)}")
for t in data.get("results", []):
resolved[t["id"]] = t["name"]
time.sleep(1.0)
print(f"Resolved {len(resolved)} term names")
# Step 3: Fetch experimental annotations for human for all descendant terms
rows = []
for go_id in all_ids[:10]: # limit for demo; remove slice for full run
params = {"goId": go_id, "taxonId": "9606",
"evidenceCode": "EXP,IDA,IPI,IMP,IGI,IEP",
"limit": 100, "page": 1}
data = quickgo_get("annotation/search", params=params)
for ann in data.get("results", []):
rows.append({
"query_go_id": go_id,
"query_go_name": resolved.get(go_id, ""),
"protein": ann["geneProductId"],
"evidence": ann["evidenceCode"],
})
time.sleep(1.0)
df = pd.DataFrame(rows)
df.to_csv("cell_death_annotations.csv", index=False)
print(f"Saved {len(df)} annotation rows → cell_death_annotations.csv")Goal: Compare GO term coverage across a list of proteins and export a presence/absence matrix.
import requests, time, pandas as pd
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
proteins = {
"TP53": "P04637",
"BRCA1": "P38398",
"MDM2": "Q00987",
"BCL2": "P10415",
}
records = {}
for gene, uniprot_id in proteins.items():
params = {"geneProductId": f"UniProtKB:{uniprot_id}",
"evidenceCode": "EXP,IDA,IPI,IMP,IGI,IEP",
"limit": 200, "page": 1}
r = requests.get(f"{QUICKGO_BASE}/annotation/search",
params=params, headers={"Accept": "application/json"},
timeout=30)
r.raise_for_status()
go_ids = {ann["goId"] for ann in r.json().get("results", [])}
records[gene] = go_ids
print(f"{gene}: {len(go_ids)} experimental GO annotations")
time.sleep(1.0)
# Build presence/absence matrix
all_terms = sorted(set().union(*records.values()))
matrix = pd.DataFrame(
{gene: [1 if t in s else 0 for t in all_terms] for gene, s in records.items()},
index=all_terms
)
shared = matrix[matrix.sum(axis=1) == len(proteins)]
print(f"\nGO terms shared by all {len(proteins)} proteins: {len(shared)}")
print(shared.index.tolist()[:10])
matrix.to_csv("protein_go_matrix.csv")
print(f"Saved protein_go_matrix.csv ({matrix.shape[0]} GO terms)")| Parameter | Endpoint | Default | Range / Options | Effect |
|---|---|---|---|---|
goId | annotation/search | — | GO:XXXXXXX | Filter annotations to a specific GO term |
geneProductId | annotation/search | — | UniProtKB:ACCESSION | Filter to a specific protein |
taxonId | annotation/search | — | NCBI taxon integer (e.g., 9606) | Filter annotations by species |
evidenceCode | annotation/search | — | Comma-separated codes, e.g., EXP,IDA | Filter by annotation evidence type |
goAspect | annotation/search | — | biological_process, molecular_function, cellular_component | Filter by ontology namespace |
relations | terms/{id}/ancestors, terms/{id}/descendants | is_a | is_a, part_of, occurs_in, regulates | Relation types for hierarchy traversal |
limit | annotation/search, ontology/go/search | 25 | 1–200 | Results per page |
page | annotation/search, ontology/go/search | 1 | positive integer | Pagination control |
query | ontology/go/search | — | free-text string | Keyword search across GO term names and definitions |
Use batch_resolve_go_terms instead of per-ID loops: The terms endpoint accepts a comma-separated list of IDs and resolves all in one round trip. For lists of up to 200 IDs this is 100× faster than one request per term.
Exclude IEA for mechanistic conclusions: Electronic annotations (IEA) are assigned by automated pipelines without manual review. They can inflate annotation counts and introduce false positives. Set evidenceCode=EXP,IDA,IPI,IMP,IGI,IEP,TAS for curated-only results.
Add time.sleep(1.0) in batch loops: QuickGO is shared EBI infrastructure with no published hard limit. One request per second keeps your scripts well within fair-use bounds.
Use descendants for ontology-aware queries: Searching only the exact goId misses proteins annotated to more specific child terms. Retrieve descendants first, then query each or combine into an evidenceCode-filtered batch.
Check numberOfHits before assuming completeness: The default limit=25 often returns a fraction of total annotations. Always inspect numberOfHits and paginate when numberOfHits > limit.
When to use: Convert a list of GO IDs returned by gseapy or another enrichment tool to human-readable names.
import requests
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
def resolve_go_names(go_ids: list) -> dict:
"""Return {go_id: name} for a list of GO IDs (single batch call)."""
ids_str = ",".join(go_ids)
r = requests.get(
f"{QUICKGO_BASE}/ontology/go/terms/{ids_str}",
headers={"Accept": "application/json"}, timeout=60
)
r.raise_for_status()
return {t["id"]: t["name"] for t in r.json().get("results", [])}
# Example: map enrichment result GO IDs
enriched_ids = ["GO:0006915", "GO:0043066", "GO:0097553", "GO:0008219", "GO:0006281"]
names = resolve_go_names(enriched_ids)
for gid, name in names.items():
print(f"{gid} {name}")
# GO:0006915 apoptotic process
# GO:0043066 negative regulation of apoptotic processWhen to use: Pull curated evidence for a protein before manually reviewing its GO function landscape.
import requests, time
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
EXP_CODES = "EXP,IDA,IPI,IMP,IGI,IEP"
def get_experimental_annotations(uniprot_id: str) -> list:
results, page = [], 1
while True:
r = requests.get(
f"{QUICKGO_BASE}/annotation/search",
params={"geneProductId": f"UniProtKB:{uniprot_id}",
"evidenceCode": EXP_CODES,
"limit": 200, "page": page},
headers={"Accept": "application/json"}, timeout=30
)
r.raise_for_status()
data = r.json()
batch = data.get("results", [])
results.extend(batch)
if not batch or len(results) >= data.get("numberOfHits", 0):
break
page += 1
time.sleep(1.0)
return results
anns = get_experimental_annotations("P04637") # TP53
print(f"Experimental GO annotations for TP53: {len(anns)}")
for a in anns[:5]:
print(f" {a['goId']} {a.get('goName', '')[:40]} ({a['evidenceCode']})")When to use: Quickly decide whether an annotation is trustworthy before including it in a pathway model.
import requests
QUICKGO_BASE = "https://www.ebi.ac.uk/QuickGO/services"
EXPERIMENTAL = {"EXP", "IDA", "IPI", "IMP", "IGI", "IEP",
"HTP", "HDA", "HMP", "HGI", "HEP"}
def annotation_is_experimental(uniprot_id: str, go_id: str) -> bool:
"""Return True if any experimental annotation exists for protein + GO term."""
r = requests.get(
f"{QUICKGO_BASE}/annotation/search",
params={"geneProductId": f"UniProtKB:{uniprot_id}",
"goId": go_id, "limit": 10, "page": 1},
headers={"Accept": "application/json"}, timeout=30
)
r.raise_for_status()
return any(a["evidenceCode"] in EXPERIMENTAL
for a in r.json().get("results", []))
print(annotation_is_experimental("P04637", "GO:0006977")) # True
print(annotation_is_experimental("P04637", "GO:0016020")) # False (membrane — IEA only)| Problem | Cause | Solution |
|---|---|---|
HTTP 400 on term lookup | Malformed GO ID (spaces, wrong prefix) | Ensure format is GO:XXXXXXX (7 digits, colon, uppercase GO) |
results: [] for a known GO ID | Term is obsolete or merged into another | Check isObsolete field; look up the replacement in consider or replacedBy |
| Annotation search returns 0 hits for a protein | UniProt accession format wrong | Prefix with UniProtKB: (case-sensitive), e.g., UniProtKB:P04637 |
numberOfHits >> len(results) | Default limit=25 is too small | Set limit=200 and implement pagination with page parameter |
| Batch term resolve returns fewer than expected | Some IDs are obsolete or malformed | Check returned id set against input; missing IDs are invalid or obsolete |
Rate limit / 503 Service Unavailable | Too many rapid requests | Add time.sleep(1.0) between paged calls; backoff on 5xx errors |
| Descendant list is very large (1000+) | Broad root term selected | Use a more specific child term, or process descendants in chunks of 100 |
gseapy-gene-enrichment — ORA and GSEA enrichment analysis against GO and other gene set databases; use QuickGO to resolve term IDs from gseapy outputuniprot-protein-database — UniProt REST API for Swiss-Prot GO annotations integrated with protein sequence and feature dataensembl-database — Ensembl REST API for variant-level GO annotations and cross-species gene lookupskegg-database — KEGG pathways as an alternative functional annotation vocabulary© jaechang-hits, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in skills/genomics-bioinformatics/databases/quickgo-database of jaechang-hits/SciAgent-Skills.
Open the folder on GitHubat commit 82c862c
We found 1 copy of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in jaechang-hits/SciAgent-Skills, which our catalogue first saw on October 7, 2026.
Quickgo Database next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Quickgo Database this skilljaechang-hits/SciAgent-Skills | 370 | 1 repos | ~6.9k | Automated safety check: Pass | Apache-2.0 | |
| UniProt Database Accessdavila7/claude-code-templates | 32k | 15 repos | ~1.7k | Automated safety check: Pass | MIT | |
| Pride Databasemajiayu000/claude-skill-registry | 666 | 2 repos | ~8.2k | Automated safety check: Pass | Apache-2.0 | |
| Database Lookupmajiayu000/claude-skill-registry | 666 | 1 repos | ~7k | Automated safety check: Notes | MIT | |
| Bio Ensembl RESTGPTomics/bioSkills | 1.2k | 2 repos | ~3.6k | Automated safety check: Pass | MIT | |
| Ensembl Databaseaipoch/medical-research-skills | 2k | — | ~1.5k | Automated safety check: Pass | MIT |
davila7/claude-code-templates
Queries the UniProt REST API directly to search proteins, fetch FASTA sequences, map IDs between databases and read Swiss-Prot and TrEMBL entries.
majiayu000/claude-skill-registry
Search the PRIDE Archive v3 REST API for proteomics datasets: discover projects by keyword + faceted filters (organism, instrument, disease, software), fetch project metadata, list and download…
majiayu000/claude-skill-registry
Search 78 public scientific, biomedical, materials science, and economic databases via REST APIs.
GPTomics/bioSkills
Query the Ensembl REST API for gene/transcript/protein lookup, sequence retrieval, comparative genomics (Compara), variant effect prediction (VEP), regulatory features, and cross-species…
aipoch/medical-research-skills
Access Ensembl REST API for vertebrate genomic data; use when you need gene/ID lookups, sequence retrieval, variant effect prediction (VEP), or homology/assembly coordinate mapping.
aipoch/medical-research-skills
Programmatically query public single-cell study metadata from the Broad Institute Single Cell Portal REST API when you need to search and filter datasets by organism, tissue, disease, or cell type…
jaechang-hits/SciAgent-Skills
NEB-IRC activation energy pipeline for reaction barriers using GFN2-xTB and pysisyphus.
jaechang-hits/SciAgent-Skills
3Dmol.js WebGL molecular visualization emitted as self-contained HTML.
jaechang-hits/SciAgent-Skills
Constraint-based (COBRA) analysis of genome-scale metabolic models: FBA, FVA, knockouts, flux sampling, production envelopes, gapfilling, media optimization.
jaechang-hits/SciAgent-Skills
Read, write, and edit ChemDraw CDX/CDXML files with RDKit's rdkit.Chem.rdChemDraw plus direct XML editing, always paired with a rendered PNG.
jaechang-hits/SciAgent-Skills
Programmatic PubMed access via NCBI E-utilities REST API. An agent skill from jaechang-hits/SciAgent-Skills.
jaechang-hits/SciAgent-Skills
Scaffold a new SciAgent-Skills entry. An agent skill from jaechang-hits/SciAgent-Skills.
Works with
Categories
Query EBI QuickGO REST API for GO terms and protein annotations. Quickgo Database is an agent skill from jaechang-hits/SciAgent-Skills. Query EBI QuickGO REST API for GO terms and protein annotations.
Quickgo Database fits situations like: ontology traversal; annotation retrieval before enrichment.
Run `npx skills add jaechang-hits/SciAgent-Skills --skill quickgo-database -a claude-code`. Or copy the skill folder (skills/genomics-bioinformatics/databases/quickgo-database in jaechang-hits/SciAgent-Skills) into .claude/skills/quickgo-database in your project. Claude Code loads it when a task matches its description.
Run `npx skills add jaechang-hits/SciAgent-Skills --skill quickgo-database -a codex`. Or copy the skill folder (skills/genomics-bioinformatics/databases/quickgo-database in jaechang-hits/SciAgent-Skills) into .agents/skills/quickgo-database in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add jaechang-hits/SciAgent-Skills --skill quickgo-database -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/quickgo-database, .gemini/skills/quickgo-database, .github/skills/quickgo-database and .opencode/skills/quickgo-database in your project.
Going by SKILL.md and its folder, Quickgo Database needs the command-line tools its instructions call (pip). Our summary lists: Python 3.
SKILL.md names 3 domains. In commands or code: ebi.ac.uk; the agent is likely to contact it when it follows the instructions. As links in the text: doi.org and geneontology.org. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Quickgo Database is published under the Apache-2.0 licence (declared in SKILL.md). It allows redistribution, so the full SKILL.md is shown on this page.
About 6.9k tokens (SKILL.md is roughly 28k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Quickgo Database: UniProt Database Access (davila7/claude-code-templates, 32k stars), Pride Database (majiayu000/claude-skill-registry, 666 stars), Database Lookup (majiayu000/claude-skill-registry, 666 stars) and Bio Ensembl REST (GPTomics/bioSkills, 1.2k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
jaechang-hits (a GitHub user) maintains it in jaechang-hits/SciAgent-Skills, which has 370 GitHub stars. The repository holds 165 skills in this directory. The repository was last updated on September 29, 2026.
Source: jaechang-hits/SciAgent-Skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.