arxiv · wanshuiyin — Claude Code skill: search and download papers
Searches arXiv, downloads PDFs into a local folder and writes a short summary. Handy when you need literature on a topic without leaving the chat.
npx skills add wanshuiyin/Auto-claude-code-research-in-sleep --skill arxiv -a claude-codeWhat arxiv does
The skill takes a query or a bare arXiv ID like 2301.07041. It hits the arXiv API, prints a table with ID, title, authors, date and category, and for a single ID shows the full author list plus the abstract. Downloaded PDFs land in papers/ inside the project, and you can point it elsewhere.
Under the hood there is a Python script, arxiv_fetch.py, with an inline Python fallback when the script cannot be found. Options go straight into the arguments: - max: 20 raises the result count, - dir: literature/ sets another folder, - download grabs the first result's PDF, - download: all grabs every one. Default is 10 results, and the skill advises a one-second pause between downloads — arXiv starts throttling otherwise.
You need Python 3 and network access. Files under 10 KB get rejected, since they are usually an error page rather than a paper. If the project has a research-wiki/ folder, results are also ingested there.
What it helps with
- find recent papers on a topic without browsing arXiv by hand
- download a specific paper's PDF by its ID
- keep a set of papers inside the project folder
- read an abstract and author list without opening the full paper
- feed found papers into the project's research wiki
Example prompts for the agent
- /arxiv "attention mechanism" - max: 20
- /arxiv "2301.07041" - download
- /arxiv "graph neural networks" - dir: literature/ - download: all
How to install arxiv
1Skills CLI (Vercel)
npx skills add wanshuiyin/Auto-claude-code-research-in-sleep --skill arxiv -a claude-code2Manually: put the files in place
~/.claude/skills/arxiv/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/arxiv/
1Skills CLI (Vercel)
npx skills add wanshuiyin/Auto-claude-code-research-in-sleep --skill arxiv -a codex2Manually: put the files in place
.agents/skills/arxiv/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add wanshuiyin/Auto-claude-code-research-in-sleep --skill arxiv -a cursor2Manually: put the files in place
.cursor/skills/arxiv/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install wanshuiyin/Auto-claude-code-research-in-sleep arxiv2Manually: put the files in place
.github/skills/arxiv/SKILL.md1Skills CLI (Vercel)
npx skills add wanshuiyin/Auto-claude-code-research-in-sleep --skill arxiv -a gemini-cli2Platform CLI
gemini skills install https://github.com/wanshuiyin/Auto-claude-code-research-in-sleep --path skills/arxivManually: put the files in place
.devin/skills/arxiv/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add wanshuiyin/Auto-claude-code-research-in-sleep --skill arxiv -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
Step by step, with commands for each platform: How to install skills in Claude Code: five ways
Questions about arxiv
How do I install arxiv in Claude?
Run npx skills add wanshuiyin/Auto-claude-code-research-in-sleep --skill arxiv -a claude-code. The skill lands at ~/.claude/skills/arxiv/SKILL.md.
What does the arxiv skill do?
It searches arXiv by query or ID, shows a results table, downloads PDFs to a local folder and builds a short summary with the abstract and key points.
What does the arxiv skill need to run?
Python 3 and network access to the arXiv API. Downloads under 10 KB are dropped as error pages, and the skill advises a one-second gap between fetches.
Source text
SKILL.md · MIT
---
name: arxiv
description: 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.
argument-hint: "[query-or-arxiv-id]"
allowed-tools: Bash(*), Read, Write
---
# arXiv Paper Search & Download
Search topic or arXiv paper ID: $ARGUMENTS
## Constants
- **PAPER_DIR** - Local directory to save downloaded PDFs. Default: `papers/` in the current project directory.
- **MAX_RESULTS = 10** - Default number of search results.
- **ARXIV_FETCHER** — canonical name `arxiv_fetch.py`, resolved per
[`shared-references/integration-contract.md`](../shared-references/integration-contract.md) §2
(Policy D1 — primary + fallback cascade). If unresolved (canonical
chain exhausted), fall back to the inline Python alternative
documented in Step 2.
> 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
## Workflow
### Step 1: Parse Arguments
Parse `$ARGUMENTS` for directives:
- **Query or ID**: main search term or a bare arXiv ID such as `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 results
If the argument matches an arXiv ID pattern (`YYMM.NNNNN` or `category/NNNNNNN`), skip the search and go directly to Step 3.
### Step 2: Search arXiv
Resolve `$ARXIV_FETCHER` via the canonical strict-safe chain (see
[`shared-references/integration-contract.md`](../shared-references/integration-contract.md) §2):
```bash
cd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)" || exit 1
if [ -z "${ARIS_REPO:-}" ] && [ -f .aris/installed-skills.txt ]; then
ARIS_REPO=$(awk -F'\t' '$1=="repo_root"{print $2; exit}' .aris/installed-skills.txt 2>/dev/null) || true
fi
if [ -z "${ARIS_REPO:-}" ] && [ -f "$HOME/.aris/repo" ]; then
ARIS_REPO=$(cat "$HOME/.aris/repo" 2>/dev/null) || true
fi
ARXIV_FETCHER=".aris/tools/arxiv_fetch.py"
[ -f "$ARXIV_FETCHER" ] || ARXIV_FETCHER="tools/arxiv_fetch.py"
[ -f "$ARXIV_FETCHER" ] || { [ -n "${ARIS_REPO:-}" ] && ARXIV_FETCHER="$ARIS_REPO/tools/arxiv_fetch.py"; }
[ -f "$ARXIV_FETCHER" ] || ARXIV_FETCHER=""
```
**If `$ARXIV_FETCHER` is non-empty**, run:
```bash
python3 "$ARXIV_FETCHER" search "QUERY" --max MAX_RESULTS
```
**If `$ARXIV_FETCHER` is empty** (Policy D1 cascade), fall back to inline Python:
```bash
python3 - <<'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 |
```
### Step 3: Fetch Details for a Specific ID
When a single paper ID is requested (either directly or from Step 2):
```bash
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.
### Step 4: Download PDFs
When download is requested, for each paper ID to download:
```bash
# Using fetch script:
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:
- Confirm file size > 10 KB (reject smaller files - likely an error HTML page)
- Add a 1-second delay between consecutive downloads to avoid rate limiting
- Report: `Downloaded: papers/2301.07041.pdf (842 KB)`
### Step 5: Summarize
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)
```
### Step 6: Update Research Wiki (if active)
**Required when `research-wiki/` exists in the project**; skip silently
otherwise. When the wiki dir exists, resolve `$WIKI_SCRIPT` per the
canonical chain at
[`shared-references/wiki-helper-resolution.md`](../shared-references/wiki-helper-resolution.md)
(Variant B — warn-and-skip), then ingest every paper returned by this
invocation:
```bash
if [ -d research-wiki/ ]; then
cd "$(git rev-parse --show-toplevel 2>/dev/null || pwd)" || exit 1
ARIS_REPO="${ARIS_REPO:-$(awk -F'\t' '$1=="repo_root"{print $2; exit}' .aris/installed-skills.txt 2>/dev/null)}"
if [ -z "${ARIS_REPO:-}" ] && [ -f "$HOME/.aris/repo" ]; then
ARIS_REPO=$(cat "$HOME/.aris/repo" 2>/dev/null) || true
fi
WIKI_SCRIPT=".aris/tools/research_wiki.py"
[ -f "$WIKI_SCRIPT" ] || WIKI_SCRIPT="tools/research_wiki.py"
[ -f "$WIKI_SCRIPT" ] || { [ -n "${ARIS_REPO:-}" ] && WIKI_SCRIPT="$ARIS_REPO/tools/research_wiki.py"; }
[ -f "$WIKI_SCRIPT" ] || {
echo "WARN: research_wiki.py not found; arxiv results delivered, wiki ingest skipped. Fix: bash tools/install_aris.sh or smart_update.sh (refreshes ~/.aris/repo), export ARIS_REPO, or cp <ARIS-repo>/tools/research_wiki.py tools/." >&2
WIKI_SCRIPT=""
}
if [ -n "$WIKI_SCRIPT" ]; then
for each arxiv_id in results:
python3 "$WIKI_SCRIPT" ingest_paper research-wiki/ \
--arxiv-id "<arxiv_id>"
fi
fi
```
The helper handles metadata fetch, slug, dedup, page creation, index
rebuild, and log append in a single call — **do not handwrite
`papers/<slug>.md`**. See
[`shared-references/integration-contract.md`](../shared-references/integration-contract.md)
for the canonical-helper rule. Missed ingests can be backfilled later
with `python3 "$WIKI_SCRIPT" sync research-wiki/ --arxiv-ids <id1>,<id2>,...`
after resolving `$WIKI_SCRIPT` as above.
### Step 7: Final Output
Summarize what was done:
- `Found N papers for "query"`
- `Downloaded: papers/2301.07041.pdf (842 KB)` (for each download)
- `Wiki-ingested N papers` (if `research-wiki/` was present)
- Any warnings (rate limit hit, file too small, already exists)
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
```
## Key Rules
- Always show the arXiv ID prominently - users need it for citations and reproducibility
- Verify downloaded PDFs: file must be > 10 KB; warn and delete if smaller
- Rate limit: wait 1 second between consecutive PDF downloads; retry once after 5 seconds on HTTP 429
- Never overwrite an existing PDF at the same path - skip it and report "already exists"
- Handle both arXiv ID formats: new (`2301.07041`) and old (`cs/0601001`)
- PAPER_DIR is created automatically if it does not exist
- If the arXiv API is unreachable, report the error clearly and suggest using `/research-lit` with `- sources: web` as a fallback
© wanshuiyin · MIT · wanshuiyin/Auto-claude-code-research-in-sleep
Similar skills
Everything for Science and research →arxiv by other authors comes first.