Annotate Paper
54yyyu/zotero-mcp
Read the open paper and write study annotations into its PDF with zotero-cli - a context box on the title, a four-part summary on the abstract, role-coded abstract highlights, one box per figure…
Full-featured CLI for Zotero reference management. An agent skill from PiaoyangGuohai1/cli-anything-zotero.
$ npx skills add PiaoyangGuohai1/cli-anything-zotero --skill cli-anything-zotero -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install PiaoyangGuohai1/cli-anything-zotero cli-anything-zotero --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/PiaoyangGuohai1/cli-anything-zotero.git skills-src && mkdir -p .claude/skills && cp -r skills-src/cli_anything/zotero/skills .claude/skills/cli-anything-zotero && 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 "cli-anything-zotero" agent skill from https://github.com/PiaoyangGuohai1/cli-anything-zotero/tree/main/cli_anything/zotero/skills into .claude/skills/cli-anything-zotero/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cli-anything-zotero", 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/PiaoyangGuohai1/cli-anything-zotero/tree/main/cli_anything/zotero/skillsType 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 PiaoyangGuohai1/cli-anything-zotero --skill cli-anything-zotero -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install PiaoyangGuohai1/cli-anything-zotero cli-anything-zotero --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PiaoyangGuohai1/cli-anything-zotero.git skills-src && mkdir -p .agents/skills && cp -r skills-src/cli_anything/zotero/skills .agents/skills/cli-anything-zotero && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "cli-anything-zotero" agent skill from https://github.com/PiaoyangGuohai1/cli-anything-zotero/tree/main/cli_anything/zotero/skills into .agents/skills/cli-anything-zotero/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cli-anything-zotero", 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 PiaoyangGuohai1/cli-anything-zotero --skill cli-anything-zotero -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install PiaoyangGuohai1/cli-anything-zotero cli-anything-zotero --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PiaoyangGuohai1/cli-anything-zotero.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/cli_anything/zotero/skills .cursor/skills/cli-anything-zotero && 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 "cli-anything-zotero" agent skill from https://github.com/PiaoyangGuohai1/cli-anything-zotero/tree/main/cli_anything/zotero/skills into .cursor/skills/cli-anything-zotero/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cli-anything-zotero", 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/PiaoyangGuohai1/cli-anything-zotero.git --path cli_anything/zotero/skills--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 PiaoyangGuohai1/cli-anything-zotero --skill cli-anything-zotero -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install PiaoyangGuohai1/cli-anything-zotero cli-anything-zotero --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PiaoyangGuohai1/cli-anything-zotero.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/cli_anything/zotero/skills .gemini/skills/cli-anything-zotero && 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 "cli-anything-zotero" agent skill from https://github.com/PiaoyangGuohai1/cli-anything-zotero/tree/main/cli_anything/zotero/skills into .gemini/skills/cli-anything-zotero/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cli-anything-zotero", 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 PiaoyangGuohai1/cli-anything-zotero cli-anything-zoteroInstalls 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 PiaoyangGuohai1/cli-anything-zotero --skill cli-anything-zotero -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/PiaoyangGuohai1/cli-anything-zotero.git skills-src && mkdir -p .github/skills && cp -r skills-src/cli_anything/zotero/skills .github/skills/cli-anything-zotero && 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 "cli-anything-zotero" agent skill from https://github.com/PiaoyangGuohai1/cli-anything-zotero/tree/main/cli_anything/zotero/skills into .github/skills/cli-anything-zotero/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cli-anything-zotero", 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 PiaoyangGuohai1/cli-anything-zotero --skill cli-anything-zotero -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install PiaoyangGuohai1/cli-anything-zotero cli-anything-zotero --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/PiaoyangGuohai1/cli-anything-zotero.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/cli_anything/zotero/skills .opencode/skills/cli-anything-zotero && 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 "cli-anything-zotero" agent skill from https://github.com/PiaoyangGuohai1/cli-anything-zotero/tree/main/cli_anything/zotero/skills into .opencode/skills/cli-anything-zotero/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "cli-anything-zotero", 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.
cli-anything-zoteroFull-featured CLI for Zotero reference management. An agent skill from PiaoyangGuohai1/cli-anything-zotero.
CLI Anything Zotero is an agent skill from PiaoyangGuohai1/cli-anything-zotero. Full-featured CLI for Zotero reference management. Search, import by DOI/PMID, export BibTeX, attach PDFs, semantic search, manage tags/collections, and more. Use this tool whenever you need to interact with a Zotero library programmatically.
Its SKILL.md is about 2.6k 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 Citation management. It works with Zotero, LaTeX, Model Context Protocol and OpenAI. The repository describes itself as: CLI server for Zotero 7/8/9 — let AI manage your library. 70+ CLI commands for search, import, PDF, BibTeX, notes, and more. Works with Claude, Cursor, ChatGPT. The licence is Apache-2.0.
4 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit e42a930. 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.
No scripts in the folder and no shell commands in SKILL.md (its code samples are bash).
From 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:
doi.orgFrom URLs in SKILL.md, links to its own repository left out.
Names these keys or tokens, usually read from environment variables:
ITEM_KEYCOLLECTION_KEYZOTERO_EMBED_KEYFrom names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
CLI Anything Zotero loads about 2.6k tokens when it runs. Until then it costs about 66 tokens; SKILL.md has 406 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 PiaoyangGuohai1/cli-anything-zotero at commit e42a930, republished under its Apache-2.0 licence (© PiaoyangGuohai1). 406 words, ~2,598 tokens.
.claude/skills/cli-anything-zotero/SKILL.md (or your agent's skills folder).Agent-native CLI for Zotero 7/8/9 desktop. 40+ commands across four backends.
zotero-cli --json app doctor first. If write_ready is false, follow next_steps (start Zotero / install plugin / enable Local API).zotero-cli --json ... for machine-readable results (ok, status, code, key).zotero-cli --json audit tail --limit 20 / audit path.zotero-cli app check-update once per session.# Keyword search
zotero-cli item find "query" --limit 10
# Search all Zotero fields, tags, notes, and annotations
zotero-cli item find "query" --scope fields --limit 10
# Search everything Zotero can search, including full content
zotero-cli item find "query" --scope everything --limit 10
# Full-text search inside PDFs
zotero-cli item search-fulltext "query" --limit 10
# Semantic search (requires ZOTERO_EMBED_* env vars)
zotero-cli item semantic-search "natural language query" --top-k 10
# Find papers similar to a known item
zotero-cli item similar ITEM_KEY --top-k 5
# Search annotations/highlights by keyword or color
zotero-cli item search-annotations "keyword" --color "#ff6666" --limit 10
# Find duplicates
zotero-cli --json item duplicates --by doi --limit 20
zotero-cli --json item merge KEEP OTHER1 OTHER2 # dry-run default; --confirm to apply# Full item metadata (returns JSON with title, creators, DOI, tags, attachments, etc.)
zotero-cli --json item get ITEM_KEY
# List attachments
zotero-cli --json item attachments ITEM_KEY
# View PDF annotations
zotero-cli --json item annotations ITEM_KEY
# Citation metrics from NIH iCite
zotero-cli --json item metrics PMID --pmid
# Or by Zotero item key (auto-extracts PMID from extra field)
zotero-cli --json item metrics ITEM_KEY# Preferred: unified add
zotero-cli --json add doi "10.1038/s41586-024-07871-6" --tag "review" --collection COLLECTION_KEY --fetch-pdf
zotero-cli --json add arxiv 2602.02093 --collection COLLECTION_KEY
zotero-cli --json add file ./paper.pdf --collection COLLECTION_KEY
zotero-cli --json add bibtex ./references.bib --collection COLLECTION_KEY
zotero-cli --json add url https://doi.org/10.1038/s41586-021-03819-2
# Lower-level DOI import still available
zotero-cli --json import doi "10.1038/s41586-024-07871-6" --if-exists file --no-translator
zotero-cli import pmid "38551621" --tag "epidemiology"# Export one item in BibTeX
zotero-cli item export ITEM_KEY --format bibtex
# Export a standalone BibTeX file for downstream tools
zotero-cli export bib --items KEY1,KEY2 --output refs.bib
zotero-cli export bib --collection COLLECTION_KEY --output refs.bib
# Other formats: ris, biblatex, csljson, csv, mods, refer
zotero-cli item export ITEM_KEY --format ris
# Render citation preview (static HTML, not a refreshable DOCX field)
zotero-cli item citation ITEM_KEY --style apa
# Render bibliography preview (static HTML, not a refreshable DOCX field)
zotero-cli item bibliography ITEM_KEY --style apa
# Inspect citation fields inside a DOCX before mixing Zotero/EndNote/static references
zotero-cli --json docx inspect-citations manuscript.docx
# AI-authored DOCX citations must use real Zotero placeholders, then validate them
zotero-cli --json docx inspect-placeholders manuscript.docx
zotero-cli --json docx validate-placeholders manuscript.docx
# Static final DOCX: replace placeholders with ordinary text citations and bibliography
zotero-cli --json docx render-citations manuscript.docx --output manuscript-static.docx --force
# Preferred one-shot pipeline (auto: dynamic if LibreOffice ready, else static)
zotero-cli --json docx cite manuscript.docx --output manuscript-cited.docx --mode auto --force
# Dynamic final DOCX: use Zotero/LibreOffice fields when the user needs Refresh
zotero-cli --json docx doctor
zotero-cli --json docx insert-citations manuscript.docx --output manuscript-zotero.docx --force
### AI DOCX Citation Decision Flow
When the user provides a DOCX draft that contains citations, follow this explicit branch:
- Ask for intent if mode is unclear:
- "Do you want static references (final text now), or dynamic references (refreshable in Zotero/LibreOffice)?"
- Preferred default for agents:
- `zotero-cli --json docx cite <docx> --output <final.docx> --mode auto --force`
- If static is explicitly requested:
- `zotero-cli --json docx cite <docx> --output <final.docx> --mode static --force`
- If dynamic is explicitly requested or user mentions later editing/refresh:
- `zotero-cli --json docx cite <docx> --output <final.docx> --mode dynamic --force`
- or lower-level: validate → doctor → insert-citations
- If dynamic conversion returns environment errors:
- do not retry blindly
- report exact error context from `docx doctor`/`docx zoterify-probe`
- offer fallback to static mode (`render-citations`)
Keep only user-facing outputs:
- input placeholder DOCX
- final converted DOCX
- debug artifacts only if user explicitly asked for `--debug-dir`
Behavior note:
- `item citation` and `item bibliography` are static previews and must **not** be used as a replacement for DOCX writing conversion.
- `docx prepare-zotero-import` remains experimental and should not be called in normal user workflows.When drafting DOCX content with AI, never invent final static citations such as
(Author, 2024) unless the user explicitly asks for static prose. Insert
{{zotero:ITEMKEY}} or {{zotero:KEY1,KEY2}} placeholders from real Zotero
items and validate the document before handoff. When the user asks to insert
citations without specifying a mode, ask whether they want static citations
(docx render-citations, simplest) or dynamic Zotero fields
(docx insert-citations, refreshable but requires LibreOffice).
# Attach a local PDF to an existing item
zotero-cli item attach ITEM_KEY /path/to/paper.pdf
# Zotero-only find PDF
zotero-cli --json item find-pdf ITEM_KEY
# Cascade: Zotero → Unpaywall → EuropePMC → bioRxiv → arXiv
zotero-cli --json item fetch-pdf ITEM_KEY --sources zotero,unpaywall,epmc,biorxiv,arxiv
# Batch cascade for a collection (JSONL progress optional)
zotero-cli --json collection fetch-pdfs COLLECTION_KEY --limit 20 --jsonl-progress --resume# Update metadata fields
zotero-cli item update ITEM_KEY --field title="New Title" --field DOI="10.1234/xxx"
# Add/remove tags
zotero-cli item tag ITEM_KEY --add "important" --remove "unread"
# Delete item (requires --confirm)
zotero-cli item delete ITEM_KEY --confirm# List all collections
zotero-cli collection list
# Collection hierarchy
zotero-cli collection tree
# Find collection by name
zotero-cli collection find "query"
# Items in a collection (includes DOI, hasPdf, date)
zotero-cli --json collection items COLLECTION_KEY
# Collection statistics (total items, PDF coverage, year/journal distribution)
zotero-cli --json collection stats COLLECTION_KEY
# Create / rename / delete collection
zotero-cli collection create "New Collection"
zotero-cli collection rename COLLECTION_KEY --name "New Name"
zotero-cli collection delete COLLECTION_KEY --confirm
# Add/remove items from collection
zotero-cli item add-to-collection ITEM_KEY COLLECTION_KEY
zotero-cli collection remove-item COLLECTION_KEY ITEM_KEY# Trigger Zotero sync
zotero-cli sync
# Execute arbitrary Zotero JavaScript
zotero-cli js "return Zotero.Items.getAll(1).length;" --wait 5
# Interactive REPL
zotero-cli repl--json flag on the root command for machine-readable JSON output:zotero-cli --json item find "query"--json, output is human-readable text.zotero-cli --json app doctor / app launch if it is closed. Do not invent cloud-only or read-only degraded workflows.zotero-cli app install-plugin. Once installed, all JS bridge commands work silently.ZOTERO_EMBED_API, ZOTERO_EMBED_MODEL, and ZOTERO_EMBED_KEY environment variables, plus a pre-built vector index at ZOTERO_VECTOR_DB.9LPV3KTS), title fragment, or numeric ID.zotero-cli --json item find "X" --limit 20
# Pick relevant keys from output, then:
zotero-cli export bib --items KEY1,KEY2 --output refs.bibzotero-cli import doi "10.xxxx/yyyy"
# Note the item key from output, then:
zotero-cli item attach ITEM_KEY /path/to/paper.pdfzotero-cli --json collection stats COLLECTION_KEY
# Shows total vs withPDF vs noPDF count
# Then batch-find:
zotero-cli collection find-pdfs COLLECTION_KEYzotero-cli --json item similar ITEM_KEY --top-k 101.2.1+ (see package __version__ / PyPI). Roadmap: repo docs/ROADMAP.md.
© PiaoyangGuohai1, 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 cli_anything/zotero/skills of PiaoyangGuohai1/cli-anything-zotero.
Open the folder on GitHubat commit e42a930
CLI Anything Zotero 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 |
|---|---|---|---|---|---|---|
| CLI Anything Zotero this skillPiaoyangGuohai1/cli-anything-zotero | 138 | — | ~2.6k | Automated safety check: Pass | Apache-2.0 | |
| Annotate Paper54yyyu/zotero-mcp | 5.3k | — | ~1.5k | Automated safety check: Pass | MIT | |
| NSFC Literature Review WriterHuiyuLi-2000/Chinese-Grant-Writer-Skills | 439 | 1 repos | ~1.4k | Automated safety check: Notes | MIT | |
| Autonomous Researchfedericodeponte/opendraft | 507 | — | ~8.2k | Automated safety check: Pass | Apache-2.0 | |
| Arxiv MCP Serverblazickjp/arxiv-mcp-server | 3.2k | — | ~353 | Automated safety check: Pass | Apache-2.0 | |
| Zoterocongcongwang0122/zotero-skill | 200 | — | ~1.6k | Automated safety check: Pass | None |
54yyyu/zotero-mcp
Read the open paper and write study annotations into its PDF with zotero-cli - a context box on the title, a four-part summary on the abstract, role-coded abstract highlights, one box per figure…
HuiyuLi-2000/Chinese-Grant-Writer-Skills
Writes the research-status literature review and critique section of an NSFC grant proposal, backed by a bundled multi-source literature search.
federicodeponte/opendraft
An 18-agent pipeline that turns one topic line into a drafted research paper, literature review, or thesis chapter.
blazickjp/arxiv-mcp-server
A skill your agent uses when finding, comparing, reading, or monitoring arXiv papers, including requests for abstracts, citation graphs, original LaTeX, section-level technical details, or…
congcongwang0122/zotero-skill
Use Zotero Desktop to enable/probe the local API, search a local Zotero library, list items/collections/tags, export BibTeX, insert citation keys into LaTeX or Markdown drafts, read indexed full…
lin1111-1/academic-integrity-rewrite
Revise Chinese or English academic writing for lower unnecessary textual overlap while preserving meaning, evidence, numbers, equations, terminology, and citations.
Categories
Full-featured CLI for Zotero reference management. An agent skill from PiaoyangGuohai1/cli-anything-zotero. CLI Anything Zotero is an agent skill from PiaoyangGuohai1/cli-anything-zotero. Full-featured CLI for Zotero reference management.
CLI Anything Zotero fits situations like: tasks that involve Citation management.
Run `npx skills add PiaoyangGuohai1/cli-anything-zotero --skill cli-anything-zotero -a claude-code`. Or copy the skill folder (cli_anything/zotero/skills in PiaoyangGuohai1/cli-anything-zotero) into .claude/skills/cli-anything-zotero in your project. Claude Code loads it when a task matches its description.
Run `npx skills add PiaoyangGuohai1/cli-anything-zotero --skill cli-anything-zotero -a codex`. Or copy the skill folder (cli_anything/zotero/skills in PiaoyangGuohai1/cli-anything-zotero) into .agents/skills/cli-anything-zotero 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 PiaoyangGuohai1/cli-anything-zotero --skill cli-anything-zotero -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/cli-anything-zotero, .gemini/skills/cli-anything-zotero, .github/skills/cli-anything-zotero and .opencode/skills/cli-anything-zotero in your project.
Going by SKILL.md and its folder, CLI Anything Zotero needs credentials named ITEM_KEY, COLLECTION_KEY and ZOTERO_EMBED_KEY. Our summary lists: A credential in ITEM_KEY; A credential in COLLECTION_KEY.
SKILL.md names 1 domain. In commands or code: doi.org; the agent is likely to contact it when it follows the instructions. 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.
CLI Anything Zotero is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 2.6k tokens (SKILL.md is roughly 10k 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 CLI Anything Zotero: Annotate Paper (54yyyu/zotero-mcp, 5.3k stars), NSFC Literature Review Writer (HuiyuLi-2000/Chinese-Grant-Writer-Skills, 439 stars), Autonomous Research (federicodeponte/opendraft, 507 stars) and Arxiv MCP Server (blazickjp/arxiv-mcp-server, 3.2k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
PiaoyangGuohai1 (a GitHub user) maintains it in PiaoyangGuohai1/cli-anything-zotero, which has 138 GitHub stars. The repository was last updated on July 28, 2026.
Source: PiaoyangGuohai1/cli-anything-zotero on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.