Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Search, download, and summarize academic papers from arXiv. Use when user says "search arxiv", "download paper", "fetch arxiv", "arxiv search", "get paper pdf", or wants to find and save papers from arXiv to the local paper library.
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-04 | ✗→✓ | ▲ Improved | 227% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 53% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 85% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 87% | 0% |
| case-11 | ✗→✓ | ▲ Improved | 30% | 0% |
Search topic or arXiv paper ID: $ARGUMENTS
papers/ in the current project directory.arxiv_fetch.py, resolved pershared-references/integration-contract.md §2 (Codex-side chain: $ARIS_REPO/tools/ → tools/ → ~/.codex/skills/arxiv/). Policy D1 — if unresolved (canonical chain exhausted), fall back to inline Python.
> Overrides (append to arguments): > - /arxiv "attention mechanism" - max: 20 - return up to 20 results > - /arxiv "2301.07041" - download - download a specific paper by ID > - /arxiv "query" - dir: literature/ - save PDFs to a custom directory > - /arxiv "query" - download: all - download all result PDFs
Parse $ARGUMENTS for directives:
2301.07041 or cs/0601001- max: N: override MAX_RESULTS (e.g., - max: 20)- dir: PATH: override PAPER_DIR (e.g., - dir: literature/)- download: download the first result's PDF after listing- download: all: download PDFs for all resultsIf the argument matches an arXiv ID pattern (YYMM.NNNNN or category/NNNNNNN), skip the search and go directly to Step 3.
Resolve $ARXIV_FETCHER via the canonical strict-safe Codex chain (see shared-references/integration-contract.md §2):
bashif [ -z "${ARIS_REPO:-}" ] && [ -f .aris/installed-skills-codex.txt ]; then ARIS_REPO=$(awk -F'\t' '$1=="repo_root"{print $2; exit}' .aris/installed-skills-codex.txt 2>/dev/null) || true fi ARXIV_FETCHER="" [ -n "${ARIS_REPO:-}" ] && [ -f "$ARIS_REPO/tools/arxiv_fetch.py" ] && ARXIV_FETCHER="$ARIS_REPO/tools/arxiv_fetch.py" [ -z "$ARXIV_FETCHER" ] && [ -f tools/arxiv_fetch.py ] && ARXIV_FETCHER="tools/arxiv_fetch.py" [ -z "$ARXIV_FETCHER" ] && [ -f ~/.codex/skills/arxiv/arxiv_fetch.py ] && ARXIV_FETCHER="$HOME/.codex/skills/arxiv/arxiv_fetch.py"
If $ARXIV_FETCHER is non-empty, run:
bashpython3 "$ARXIV_FETCHER" search "QUERY" --max MAX_RESULTS
If $ARXIV_FETCHER is empty (Policy D1 cascade), fall back to inline Python:
bashpython3 - <<'PYEOF' import json import urllib.parse import urllib.request import xml.etree.ElementTree as ET NS = "http://www.w3.org/2005/Atom" query = urllib.parse.quote("QUERY") url = (f"http://export.arxiv.org/api/query" f"?search_query={query}&start=0&max_results=MAX_RESULTS" f"&sortBy=relevance&sortOrder=descending") with urllib.request.urlopen(url, timeout=30) as r: root = ET.fromstring(r.read()) papers = [] for entry in root.findall(f"{{{NS}}}entry"): aid = entry.findtext(f"{{{NS}}}id", "").split("/abs/")[-1].split("v")[0] title = (entry.findtext(f"{{{NS}}}title", "") or "").strip().replace("\n", " ") abstract = (entry.findtext(f"{{{NS}}}summary", "") or "").strip().replace("\n", " ") authors = [a.findtext(f"{{{NS}}}name", "") for a in entry.findall(f"{{{NS}}}author")] published = entry.findtext(f"{{{NS}}}published", "")[:10] cats = [c.get("term", "") for c in entry.findall(f"{{{NS}}}category")] papers.append({ "id": aid, "title": title, "authors": authors, "abstract": abstract, "published": published, "categories": cats, "pdf_url": f"https://arxiv.org/pdf/{aid}.pdf", "abs_url": f"https://arxiv.org/abs/{aid}", }) print(json.dumps(papers, ensure_ascii=False, indent=2)) PYEOF
Present results as a table:
text| # | arXiv ID | Title | Authors | Date | Category | |---|------------|---------------------|----------------|------------|----------| | 1 | 2301.07041 | Attention Is All... | Vaswani et al. | 2017-06-12 | cs.LG |
When a single paper ID is requested (either directly or from Step 2):
bash[ -n "$ARXIV_FETCHER" ] && python3 "$ARXIV_FETCHER" search "id:ARXIV_ID" --max 1 # or fallback: python3 -c " import urllib.request, xml.etree.ElementTree as ET NS = 'http://www.w3.org/2005/Atom' url = 'http://export.arxiv.org/api/query?id_list=ARXIV_ID' with urllib.request.urlopen(url, timeout=30) as r: root = ET.fromstring(r.read()) # print full details ... "
Display: title, all authors, categories, full abstract, published date, PDF URL, abstract URL.
When download is requested, for each paper ID to download:
bash# Using fetch script: [ -n "$ARXIV_FETCHER" ] && python3 "$ARXIV_FETCHER" download ARXIV_ID --dir PAPER_DIR # Fallback: mkdir -p PAPER_DIR && python3 -c " import pathlib import sys import urllib.request out = pathlib.Path('PAPER_DIR/ARXIV_ID.pdf') if out.exists(): print(f'Already exists: {out}') sys.exit(0) req = urllib.request.Request( 'https://arxiv.org/pdf/ARXIV_ID.pdf', headers={'User-Agent': 'arxiv-skill/1.0'}, ) with urllib.request.urlopen(req, timeout=60) as r: out.write_bytes(r.read()) print(f'Downloaded: {out} ({out.stat().st_size // 1024} KB)') "
After each download:
Downloaded: papers/2301.07041.pdf (842 KB)For each paper (downloaded or fetched by API):
markdown## [Title] - **arXiv**: [ID] - [abs_url] - **Authors**: [full author list] - **Date**: [published] - **Categories**: [cs.LG, cs.AI, ...] - **Abstract**: [full abstract] - **Key contributions** (extracted from abstract): - [contribution 1] - [contribution 2] - [contribution 3] - **Local PDF**: papers/[ID].pdf (if downloaded)
If the project has an active research wiki, update it after search or download:
shared-references/integration-contract.md.Summarize what was done:
Found N papers for "query"Downloaded: papers/2301.07041.pdf (842 KB) (for each download)Suggest follow-up skills:
text/research-lit "topic" - multi-source review: Zotero + Obsidian + local PDFs + web /novelty-check "idea" - verify your idea is novel against these papers
2301.07041) and old (cs/0601001)/research-lit with - sources: web as a fallbackOther measured skills in the registry, with their headline benchmark lift.