{"id":"6de7add7-cf46-49d6-9cc5-511aa712996f","slug":"milkclouds-paperstack","kind":"skill","name":"paperstack","summary":"Open-source CLI for maintaining, querying, and publishing independent research corpora","owner":"MilkClouds","repoUrl":"https://github.com/MilkClouds/paperstack","license":"Apache-2.0","licenseTier":"permissive","trust":"community","stars":7,"match":null,"fewStars":false,"format":"skill","createdAt":"2026-08-14T10:00:14.000Z","addedAt":"2026-10-21T23:38:09.351Z","logoUrl":"https://avatars.githubusercontent.com/u/26109705?u=99c7666536117f9883515e52bc27672b9b93973d&v=4","linkOnly":false,"collection":null,"skillPath":null,"categories":["writing"],"tags":[],"runtime":"python","local":true,"cloudCapable":false,"cloudCapability":"unknown","cloudReadyOnPlatform":false,"needsApiKey":false,"reviewed":false,"syncedAt":"2026-10-25T18:50:12.541Z","sample":false,"url":"https://conduits.dev/tools/milkclouds-paperstack","language":"Python","transports":["stdio"],"install":{"pypi":"paperstack-cli"},"requirements":{"env":[],"upstreamMayCharge":false},"tools":null,"readme":"# Paperstack\n\n[![CI](https://github.com/MilkClouds/paperstack/actions/workflows/ci.yml/badge.svg)](https://github.com/MilkClouds/paperstack/actions/workflows/ci.yml) [![PyPI version](https://img.shields.io/pypi/v/paperstack-cli.svg)](https://pypi.org/project/paperstack-cli/) [![Python versions](https://img.shields.io/pypi/pyversions/paperstack-cli.svg)](https://pypi.org/project/paperstack-cli/) [![License](https://img.shields.io/pypi/l/paperstack-cli.svg)](https://github.com/MilkClouds/paperstack/blob/main/LICENSE)\n\nPaperstack is an open-source CLI for maintaining, querying, and publishing an independently authored research corpus.\nThe software and corpus are separate: Paperstack can be public while each corpus and its editorial judgments remain\nunder its maintainer's control.\n\nIt can search typed reviews, initialize and validate entries, inspect external paper metadata, read arXiv sources,\nmanage a selected-venue DBLP index, and build a static viewer. A synthetic corpus lives in\n[`examples/corpus`](https://github.com/MilkClouds/paperstack/tree/main/examples/corpus); no assessment of real work is\nbundled with the package.\n\n## Install\n\n```bash\nuv tool install paperstack-cli\n```\n\nPDF conversion is optional:\n\n```bash\nuv tool install 'paperstack-cli[pdf]'\n```\n\nThe PDF extra uses `pdf-inspector` for native extraction and selective OCR.\nClean text PDFs need no external runtime, while routed OCR pages require the pinned PDFium and ONNX Runtime libraries described in the [OCR runtime guide](https://github.com/firecrawl/pdf-inspector/blob/main/docs/ocr-runtime.md).\nThe first routed page downloads and verifies the pinned OCR model set unless an offline model directory is configured.\nWhen the shared libraries are not on the platform search path, point `pdf-inspector` at the extracted files:\n\n```bash\nexport PDFIUM_LIB_PATH=/absolute/path/to/libpdfium.so\nexport ORT_DYLIB_PATH=/absolute/path/to/libonnxruntime.so\n```\n\nThe runtime guide lists the matching downloads and filenames for Linux, macOS, and Windows.\n\n## AI agent skill\n\nPaperstack ships an [Agent Skills](https://agentskills.io)-compatible skill for Codex, Claude Code, and other\ncompatible agents. Install the CLI first, then add the skill globally with the open\n[`skills`](https://github.com/vercel-labs/skills) CLI:\n\n```bash\nnpx skills add MilkClouds/paperstack --skill paperstack -g\n```\n\nThe installer detects supported agents such as Codex and Claude Code; pass `-a codex -a claude-code` to target them\nexplicitly, or omit `-g` for a project-local installation. The shared [`SKILL.md`](skills/paperstack/SKILL.md) keeps\ncorpus selection, source inspection, entry authoring, validation, and viewer workflows consistent without exposing a\nprivate corpus. Use `npx skills update paperstack -g` to update it later.\n\n## Choose a corpus\n\nRegister either a local working tree or a GitHub repository. The first registered corpus becomes active.\n\n```bash\npaperstack corpus add work --path ~/research/reviews\npaperstack corpus init new --path ~/research/new-corpus\npaperstack corpus add private --repo OWNER/private-reviews\npaperstack corpus list\npaperstack corpus use private\npaperstack corpus remove work\npaperstack corpus remove private --purge-cache --yes\n```\n\nPrivate GitHub repositories use the existing `gh` login without storing its token:\n\n```bash\ngh auth login\npaperstack review sync\n```\n\n`PAPERSTACK_DIR` and `PAPERSTACK_REPO` remain available for automation. Explicit environment variables take priority,\nthen a surrounding corpus working tree, then the active profile. Profiles are stored in\n`${XDG_CONFIG_HOME:-~/.config}/paperstack/config.json`.\n\nProvider credentials can be stored once without adding them to a project `.env`:\n\n```bash\npaperstack config set semantic-scholar.api-key\npaperstack config status\npaperstack config paths\npaperstack config unset semantic-scholar.api-key\n```\n\n`set` prompts without echoing the value; use `--stdin` to pipe it from a password manager. Credentials are written\natomically to `${XDG_CONFIG_HOME:-~/.config}/paperstack/credentials.json`, with mode `0600` on POSIX systems.\nExported environment variables take priority, followed by the nearest `.env`, then the credential store. GitHub\nActions can therefore keep using repository secrets through environment variables.\n\n## Review corpus\n\n```bash\npaperstack review show example2026paperstack --brief\npaperstack review show arxiv:2410.24164 --json\npaperstack review list --quality good --tag vla\npaperstack review search \"flow matching\"\npaperstack review init <key> --id arxiv:NNNN.NNNNN --title \"Verbatim title\" --editor <name>\npaperstack review check --style\npaperstack review audit\npaperstack review citations --fetch\n```\n\nPaper entries, talks, and posts use separate contracts under `entries/{papers,talks,posts}/`. The complete schemas,\nwriting guide, and source-reading workflow are in\n[Entry authoring](https://github.com/MilkClouds/paperstack/blob/main/docs/ENTRIES.md).\n\n## Inspect papers\n\nThese commands use external source records and do not select a citation or make an editorial judgment:\n\n```bash\npaperstack paper search \"Attention Is All You Need\" --source dblp\npaperstack paper search \"Exact Paper Title\" --source openreview --exact-title --openreview-status accepted\npaperstack paper search \"robot learning\" --source semantic-scholar --year 2024-2026\npaperstack paper search 'ti:\"robot learning\"' --source arxiv --category cs.RO --sort date\npaperstack paper metadata arxiv:2106.09685\npaperstack paper metadata doi:10.1109/CVPR.2016.90 --source crossref\npaperstack paper citations arxiv:2106.09685 --limit 50\npaperstack paper references doi:10.48550/arXiv.2106.09685 --limit 50\npaperstack paper read arxiv:2604.23073 --outline\npaperstack paper read arxiv:2604.23073 --section 6\npaperstack paper pdf arxiv:2602.09017\n```\n\n`metadata` accepts `arxiv:`, `doi:`, `dblp:`, and `openreview:` references. `read` and `pdf`\naccept arXiv references directly; other identifiers require an explicit primary-source HTTPS `--pdf-url`. `authors`, `citations`, and `references` use Semantic Scholar and also accept its `s2:`, `corpus:`, `acl:`,\n`pmid:`, and `mag:` identifiers. Structured commands expose scoped `--json` flags; networked commands expose scoped\n`--offline` flags. Paperstack reports source records but does not synthesize a citation entry or choose which version\nof a work should be cited.\n\n### Source reading\n\n- Pin `arxiv:IDvN` for version-specific downloads and caches. Metadata lookup remains work-level.\n  Unversioned reads may use stale cached content; `--refresh` refetches, `--offline` never does.\n- `read ... --documents` lists source files. Multiple TeX roots require `--document FILE`;\n  inspect relevant supplements separately. `--outline`/`--section` apply to that document.\n- DOI/OpenReview/DBLP reads require `--pdf-url https://...` pointing to the primary PDF.\n  `read` prints Markdown; `pdf` prints its cache path. New conversions need the PDF extra.\n- Partial PDF extraction returns failure unless `--allow-partial` is explicit, even offline.\n  Check `meta.json` and the PDF before using numbers. Converter quality does not certify accuracy.\n- PDF caches verify original and Markdown hashes. Old caches without PDF hashes need rebuilding.\n\n\nOpenReview exact-title search uses its title-only exact mode and verifies a normalized title match locally. Status\nfiltering is conservative because venues encode decisions and withdrawals differently; Paperstack infers it from\npublic invitation, venue, decision, and status fields rather than treating it as a universal field.\n\n## Build a viewer\n\n```bash\npaperstack viewer build\npaperstack viewer serve --port 8000\n```\n\nThe viewer is generated from the selected corpus. Source Markdown remains available alongside the rendered pages.\n\n## DBLP index\n\nThe optional selected-venue index accelerates DBLP search and is required by `review audit`:\n\n```bash\npaperstack index dblp status\npaperstack index dblp install\npaperstack index dblp update\n```\n\nInstalled snapshots are content-addressed and verified by SHA-256, schema, and embedded metadata before an atomic\npointer switch. See\n[DBLP snapshot releases](https://github.com/MilkClouds/paperstack/blob/main/docs/DBLP_RELEASES.md) for maintenance.\n\n## Configuration\n\n| Variable | Purpose |\n|---|---|\n| `PAPERSTACK_DIR` | Explicit local corpus working tree |\n| `PAPERSTACK_REPO` | Explicit GitHub corpus in `OWNER/REPO` form |\n| `PAPERSTACK_TTL` | Remote corpus cache refresh interval; default `3600` seconds |\n| `PAPERSTACK_PAPERS_DIR` | arXiv source and PDF cache |\n| `SEMANTIC_SCHOLAR_API_KEY` | Optional higher-rate Semantic Scholar access |\n| `OPENREVIEW_ACCESS_TOKEN` | Optional OpenReview access cookie value |\n| `XDG_CONFIG_HOME` | Corpus profile and credential configuration root |\n| `XDG_CACHE_HOME` | Remote corpus and paper cache root |\n| `XDG_DATA_HOME` | DBLP index root |\n\nThe console entry point also loads the nearest `.env` without overriding exported variables. Review exit codes are\n`0` for hits, `1` for no match, `2` for ambiguity, and `3` for unavailable data or invalid configuration.\n\n## Development\n\n```bash\nuv run --group lint ruff check .\nuv run --group lint ruff format --check .\nuv run --group test pytest -q\nPAPERSTACK_DIR=examples/corpus uv run paperstack viewer build --output /tmp/paperstack-site\n```\n\nPaperstack is licensed under Apache-2.0. Corpora are separate works and may use their own terms.\n"}