{"owner":"wilsonfreitas","repo":"awesome-quant","hasSkills":true,"totalSkillsCount":11,"totalTokensCount":10802,"categories":["anthropic-skill","claude-rule","root-instruction"],"hasMcp":false,"mcpConfig":null,"found":[".claude/skills/sprr/SKILL.md",".claude/skills/update-pypi-dates/SKILL.md",".agents/skills/bprr/SKILL.md",".agents/skills/update-pypi-dates/SKILL.md",".claude/skills/bprr/SKILL.md",".agents/skills/sprr/SKILL.md",".claude/skills/update-pypi-dates/README.md","CLAUDE.md",".claude/skills/update-pypi-dates/scripts/check_pypi_dates.py","AGENTS.md",".claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh"],"skills":{".claude/skills/sprr/SKILL.md":"---\nname: sprr\ndescription: Single PR reviewer for awesome-quant. Use when the user asks to review, validate, comment on, label, close, or merge one specific pull request that adds README.md entries. Triggers include \"sprr\", \"review PR\", \"check PR\", and \"validate contribution\".\n---\n\n# SPRR: Single PR Reviewer\n\nReview one pull request that adds entries to `README.md`.\n\n## Hard Rules\n\n1. Review only the PR number the user requested. If no PR number is given, ask for one.\n2. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n3. Do not modify the PR until the user explicitly approves that action.\n4. Always present findings before asking whether to comment, label, close, or merge.\n5. Always ask before merging.\n6. Enforce `CONTRIBUTING.md` and `AGENTS.md` strictly for new entries.\n\nIf GitHub MCP tools are unavailable, report that PR operations are blocked and point the user to `docs/codex-setup.md`.\n\n## Workflow\n\n1. Fetch PR details, current head SHA, files changed, labels, comments, and diff with GitHub MCP.\n2. Confirm whether the `reviewed` label or prior maintainer comments exist, then proceed with full validation anyway.\n3. Fetch the latest `Validate PR` workflow/check attempt for the current head SHA and apply the CI evidence rules below.\n4. Focus on added lines in `README.md`. Flag any other changed files as unusual for a normal contribution.\n5. When mechanical validation is not established by current-head CI, save or reconstruct the PR diff locally only if needed, then validate added README entries with:\n\n```bash\nuv run python scripts/validate_readme.py --diff-from <base-ref>\n```\n\nIf a base ref is not locally available, apply the same checks manually from the fetched diff.\n\n## CI Evidence Rules\n\nUse only the latest attempt whose commit SHA exactly matches the PR's current head SHA. A newer\nqueued or pending attempt supersedes an older successful attempt for the same SHA.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not rerun those mechanical checks. |\n| `failure` | Inspect the failing job or step. Return `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Report the review as incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Treat mechanical validation as unverified and reproduce it before deciding. |\n| success on an older SHA | Ignore it and evaluate the current SHA using these rules. |\n\nCI never replaces inspection of the diff or the manual checks below. A successful check confirms\nonly mechanical rules; it does not establish tag meaning or concision, description quality,\nrelevance, semantic section suitability, commercial classification, repository quality,\ncross-PR uniqueness, or multi-project relatedness. Search open PRs and PRs closed within the\nlast 365 days for duplicate names and URLs.\n\nFor repository substance and linked commercial services, apply the **Repository Substance and\nLinked Services** investigation in `.agents/skills/sprr/SKILL.md`, including its evidence,\nservice-first link, and eligibility verdict rules.\n\n## Validation Checklist\n\nFor every added entry:\n\n- It matches `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`.\n- New non-commercial entries include one or more backtick tags followed by ` - `. Treat these\n  as a compact tag cloud: accept concise languages, runtimes, protocols, interfaces, data\n  types, and domain terms.\n- Separate concepts use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not reject a tag\n  merely because it is not a programming language.\n- Description ends with a period before optional `[GitHub](...)`.\n- URLs use `https://`.\n- Optional GitHub link uses `[GitHub](https://github.com/owner/repo)`.\n- Section placement matches the project's purpose.\n- Commercial/proprietary projects are under `Commercial & Proprietary Services`.\n- Project name and URLs are not duplicates of existing README entries.\n- A verifiable GitHub repository containing substantive implementation, mentioned as the main URL\n  or exact `[GitHub](...)` suffix, is a strong positive relevance signal.\n- GitHub projects are checked for source availability, activity, archived status,\n  documentation, and community evidence. GitHub relevance does not waive duplicate, format,\n  or quality checks.\n- Multiple projects in one PR are closely related and explained in the PR body.\n\n## Verdicts\n\nUse these verdicts:\n\n- `APPROVE`: entry is ready to merge.\n- `NEEDS CHANGES`: fixable format, section, URL, description, or documentation issue.\n- `REJECT`: duplicate, unrelated multi-project PR, empty PR description, archived/abandoned project, or other hard rejection.\n\n## Output Shape\n\nReport:\n\n```text\nPR #<number>: <title>\nAuthor: <author>\nPrior review: YES/NO\nFiles changed: <files>\nEntries reviewed: <count>\n\nAutomated validation:\n- Validate PR: PASS | FAIL | PENDING | UNVERIFIED\n- Commit: <checked-sha> (CURRENT | STALE)\n- Mechanical checks: accepted from CI | reproduced manually | incomplete\n\nFindings:\n- <entry>: <status and reason>\n\nVerdict: APPROVE | NEEDS CHANGES | REJECT\nRecommended action: <merge/comment/close/no action>\n```\n\nThen ask for explicit approval before doing the recommended action.\n\n## Approved Actions After User Consent\n\n- If approved and user says to merge: merge with squash unless user requests otherwise.\n- If needs changes and user says to comment: leave one concise comment with all requested fixes, then add `reviewed` if available.\n- If rejected and user says to close: leave a polite rejection comment and close the PR.\n",".claude/skills/update-pypi-dates/SKILL.md":"---\nname: update-pypi-dates\ndescription: Check PyPI projects for last updated dates and update README.md entries. Use this skill to keep PyPI project information current with latest release dates from PyPI. Run periodically to maintain up-to-date metadata on Python packages listed in awesome-quant.\n---\n\n# Update PyPI Dates\n\nAutomatically check PyPI projects for their latest update dates and update corresponding README.md entries with the \"(Last updated: YYYY-MM-DD)\" information.\n\n## How it works\n\nThe skill maintains a list of PyPI projects in awesome-quant and:\n1. Queries the PyPI JSON API for each package\n2. Extracts the last release date\n3. Updates README.md entries with the new date if changed\n4. Commits changes to git if updates were made\n\n## PyPI Projects to Track\n\nCurrent projects tracked:\n- qfrm\n- chinesestockapi\n- tushare\n- metatrader5\n\n## Steps\n\n### 1. Fetch PyPI data for each project\n\nFor each PyPI project, query: `https://pypi.org/pypi/{package_name}/json`\n\nExtract the last release date from the releases data.\n\n### 2. Update README.md entries\n\nFor each project with a new date:\n- Find the entry in README.md\n- Update or add the \"(Last updated: YYYY-MM-DD)\" note\n- Use the exact entry format: `(Last updated: 2024-08-27)`\n\n### 3. Verify changes\n\nShow the user:\n- Which packages were checked\n- Which packages have new update dates\n- The differences (old date → new date)\n\n### 4. Commit if changes detected\n\nIf any updates were made:\n```bash\ngit add README.md non-github-urls.md\ngit commit -m \"Update PyPI project last updated dates\"\ngit push origin main\n```\n\n## Usage\n\nThe user can:\n- Run the skill directly: `/update-pypi-dates`\n- Schedule it to run weekly/monthly via cron\n- Include it in CI/CD pipelines to keep data fresh\n\n## Script\n\nUse `scripts/check_pypi_dates.sh` for the core update logic.\n",".agents/skills/bprr/SKILL.md":"---\nname: bprr\ndescription: Bulk PR reviewer for awesome-quant. Use when the user asks to review all open PRs, review unreviewed PRs, bulk review, or mentions \"bprr\". Reviews open PRs lacking the reviewed label and presents a summary before any merge/comment/label action.\n---\n\n# BPRR: Bulk PR Reviewer\n\nReview multiple open pull requests for README entry contributions.\n\n**REQUIRED SUB-SKILL:** Use `sprr` as the canonical policy for reviewing each pull request. Read\nit before starting the bulk review and apply its hard rules, workflow evidence rules, validation\nchecklist, verdicts, output fields, and approved-action rules unless this skill defines a\nbulk-specific presentation step.\n\n## Hard Rules\n\n1. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels,\n   closing, or merging.\n2. Filter out PRs with the `reviewed` label unless the user asks to re-review them.\n3. Apply `sprr` independently to every PR. Shared retrieval may reduce repeated work, but evidence,\n   findings, and verdicts never carry from one PR to another.\n4. Do not comment, label, close, or merge until the user explicitly approves each action.\n5. Do not auto-merge all approved PRs unless the user explicitly selects that option.\n6. If GitHub MCP tools are unavailable, report the blocker and point to `docs/codex-setup.md`.\n\n## Bulk Workflow\n\n1. List open PRs sorted oldest first and filter to unreviewed PRs by default.\n2. Fetch the default-branch `README.md` once and reuse it where `sprr` requires a base-README\n   duplicate check.\n3. For every included PR, fetch the data and both required workflow attempts specified by `sprr`.\n4. Apply `sprr` independently to every PR, including its manual checks and cross-PR duplicate\n   search over open PRs and PRs closed within the last 365 days.\n5. Present the bulk summary below before asking the user to select any actions.\n\n## Summary Output\n\nPresent a table:\n\n```text\n| PR | Title | Author | Head | Validate PR | PR Review | Entries | Format/URL | Section | Duplicate | Verdict |\n|----|-------|--------|------|-------------|-----------|---------|------------|---------|-----------|---------|\n```\n\nFor each row, copy the workflow states, mechanical-check result, and verdict from that PR's `sprr`\nreview. `Section` remains a manual semantic judgment. In `Duplicate`, report both\n`README PASS|FAIL` and `PR SEARCH PASS|FAIL`.\n\nAfter the table, list any PRs that need detailed notes. Include failed workflow steps, reasons\nworkflow evidence was not accepted, manual findings, and commercial free-tier or transparency\nevidence when it affects the verdict.\n\nAsk what to do next. Accept selections such as:\n\n- `merge 123, 124`\n- `comment 125`\n- `close 126`\n- `all approved`\n- `none`\n\nApply `sprr`'s approved-action rules to each selected PR. Confirm every merge before executing it.\n",".agents/skills/update-pypi-dates/SKILL.md":"---\nname: update-pypi-dates\ndescription: Refresh tracked PyPI last-updated dates in awesome-quant README.md. Use when the user asks to update PyPI dates, refresh PyPI metadata, or run update-pypi-dates.\n---\n\n# Update PyPI Dates\n\nRefresh last release dates for selected PyPI packages listed in `README.md`.\n\n## Workflow\n\n1. Run the checker:\n\n```bash\nuv run python .agents/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n2. Show the user which packages changed.\n3. Run README validation:\n\n```bash\nuv run python scripts/validate_readme.py\n```\n\n4. If the user asked for a commit, stage only the relevant files and commit.\n5. Do not push unless the user explicitly asks.\n\n## Tracked Packages\n\nThe script currently tracks:\n\n- `qfrm`\n- `chinesestockapi`\n- `tushare`\n- `metatrader5` / `MetaTrader5`\n\nTo add packages, edit `PYPI_PROJECTS` in `scripts/check_pypi_dates.py`.\n",".claude/skills/bprr/SKILL.md":"---\nname: bprr\ndescription: Bulk PR reviewer for awesome-quant. Use when the user asks to review all open PRs, review unreviewed PRs, bulk review, or mentions \"bprr\". Reviews open PRs lacking the reviewed label and presents a summary before any merge/comment/label action.\n---\n\n# BPRR: Bulk PR Reviewer\n\nReview multiple open pull requests for README entry contributions.\n\n## Hard Rules\n\n1. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n2. Filter out PRs with the `reviewed` label unless the user asks to re-review them.\n3. Do not comment, label, close, or merge until the user explicitly approves each action.\n4. Do not auto-merge all approved PRs unless the user explicitly selects that option.\n5. If GitHub MCP tools are unavailable, report the blocker and point to `docs/codex-setup.md`.\n\n## Workflow\n\n1. List open PRs sorted oldest first.\n2. Filter to unreviewed PRs by default.\n3. Fetch the default-branch `README.md` once for duplicate checks.\n4. For each PR, fetch details, current head SHA, labels, files, body, diff, and the latest `Validate PR` workflow/check attempt for that SHA.\n5. Review only added `README.md` entries unless the PR changes other files; flag other file changes as unusual.\n6. Apply the CI evidence rules below, then perform the remaining `$sprr` checks. Use `scripts/validate_readme.py --diff-from <base-ref>` only when current-head CI does not establish mechanical validity and the PR branch is available locally; otherwise apply the validator's rules manually from the MCP diff.\n\n## CI Evidence Rules\n\nEvaluate each PR independently. Use only the latest attempt for the current head SHA; a newer\nqueued or pending attempt supersedes an older success for that SHA. A result for one PR or\ncommit never applies to another.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not repeat those mechanical checks. |\n| `failure` | Inspect the failing job or step. Use `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Mark the review incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Treat mechanical validation as unverified and reproduce it before deciding. |\n| success only on an older SHA | Report `STALE`, ignore it, and reproduce mechanical validation for the current head SHA. |\n\nFor every PR, still inspect the diff and manually review tag meaning and concision, description\nquality, relevance, semantic section suitability, commercial classification, repository\nactivity/archive/documentation/community evidence, duplicates in open PRs and PRs closed\nwithin the last 365 days, and multi-project relatedness.\n\n## Validation Checklist\n\nFor each added entry, check:\n\n- Parser regex match.\n- Required backtick tags for new non-commercial entries. Treat them as a compact tag cloud:\n  accept concise languages, runtimes, protocols, interfaces, data types, and domain terms.\n- Separate concepts must use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not require\n  every tag to be a programming language.\n- Description period before optional `[GitHub](...)`.\n- `https://` URLs.\n- Exact optional `[GitHub](https://github.com/owner/repo)` format.\n- Correct category section.\n- Commercial placement under `Commercial & Proprietary Services`.\n- Duplicate project names or URLs.\n- Treat any verifiable GitHub repository mentioned as the main URL or exact `[GitHub](...)`\n  suffix as a strong positive relevance signal.\n- For GitHub repos, check source availability, activity, archived status, documentation, and\n  community evidence. GitHub relevance does not waive duplicate, format, or quality checks.\n- Clear rationale for multiple related projects in one PR.\n\n## Summary Output\n\nPresent a table:\n\n```text\n| PR | Title | Author | Head | Validate PR | Entries | Format/URL | Section | Duplicate | Verdict |\n|----|-------|--------|------|-------------|---------|------------|---------|-----------|---------|\n```\n\nUse the entry count in `Entries`. Use `PASS`, `FAIL`, `PENDING`, `UNVERIFIED`, or\n`STALE` in `Validate PR`. Use `CI PASS`, `CI FAIL`, `REPRODUCED PASS`,\n`REPRODUCED FAIL`, or `INCOMPLETE` in `Format/URL`. `Section` remains a manual\nsemantic judgment. In `Duplicate`, report both `README PASS|FAIL` and\n`PR SEARCH PASS|FAIL`.\n\nAfter the table, list any PRs that need detailed notes, including the failing workflow step or the reason CI evidence was not accepted.\n\nAsk what to do next. Accept selections like:\n\n- `merge 123, 124`\n- `comment 125`\n- `close 126`\n- `all approved`\n- `none`\n\nConfirm each merge before executing it.\n",".agents/skills/sprr/SKILL.md":"---\nname: sprr\ndescription: Single PR reviewer for awesome-quant. Use when the user asks to review, validate, comment on, label, close, or merge one specific pull request that adds README.md entries. Triggers include \"sprr\", \"review PR\", \"check PR\", and \"validate contribution\".\n---\n\n# SPRR: Single PR Reviewer\n\nReview one pull request that adds entries to `README.md`.\n\n## Hard Rules\n\n1. Review only the PR number the user requested. If no PR number is given, ask for one.\n2. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n3. Do not modify the PR until the user explicitly approves that action.\n4. Always present findings before asking whether to comment, label, close, or merge.\n5. Always ask before merging.\n6. Enforce `CONTRIBUTING.md` and `AGENTS.md` strictly for new entries, using the\n   sentence-count interpretation in the Validation Checklist below.\n7. Both `Validate PR` and `PR Review` must pass before returning `APPROVE`.\n\nIf GitHub MCP tools are unavailable, report that PR operations are blocked and point the user to `docs/codex-setup.md`.\n\n## Workflow\n\n1. Fetch PR details, current head SHA, files changed, labels, comments, and diff with GitHub MCP.\n2. Confirm whether the `reviewed` label or prior maintainer comments exist, then proceed with full validation anyway.\n3. Fetch the latest `Validate PR` workflow/check attempt for the current head SHA and apply the CI evidence rules below.\n4. Fetch the latest `PR Review` workflow/check attempt associated with the pull request and apply\n   the required workflow rules below.\n5. Focus on added lines in `README.md`. Flag any other changed files as unusual for a normal contribution.\n6. When mechanical validation is not established by current-head CI, save or reconstruct the PR diff locally only if needed, then validate added README entries with:\n\n```bash\nuv run python scripts/validate_readme.py --diff-from <base-ref>\n```\n\nIf a base ref is not locally available, apply the same checks manually from the fetched diff.\n\n## CI Evidence Rules\n\nUse only the latest attempt whose commit SHA exactly matches the PR's current head SHA. A newer\nqueued or pending attempt supersedes an older successful attempt for the same SHA.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not rerun those mechanical checks. |\n| `failure` | Inspect the failing job or step. Return `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Report the review as incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Report the review as incomplete and do not return `APPROVE`; reproduce mechanical validation only to provide useful findings. |\n| success on an older SHA | Report the result as stale and do not return `APPROVE`; require a successful attempt for the current SHA. |\n\nCI never replaces inspection of the diff or the manual checks below. A successful check confirms\nonly mechanical rules; it does not establish tag meaning or concision, description quality,\nrelevance, semantic section suitability, commercial classification, repository quality,\ncommercial free-tier eligibility or transparency, URL tracking, cross-PR uniqueness, or\nmulti-project relatedness. CI cannot establish any of these manual criteria. Search open PRs and PRs\nclosed within the last 365 days for duplicate names and URLs.\n\n`PR Review` runs on `pull_request_target`, so use the latest attempt associated with the pull\nrequest without applying the current-head SHA rule used for `Validate PR`. A successful attempt is\nrequired but does not prove that current-head mechanical validation passed. If the latest attempt\nfails, inspect its failing job or step. Return `NEEDS CHANGES` when the review reports a PR defect;\notherwise report the review as incomplete. If it is queued, pending, cancelled, skipped, or\nmissing, report the review as incomplete and do not return `APPROVE`.\n\n## Validation Checklist\n\nFor every added entry:\n\n- It matches `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`.\n- New non-commercial entries include one or more backtick tags followed by ` - `. Treat these\n  as a compact tag cloud: accept concise languages, runtimes, protocols, interfaces, data\n  types, and domain terms.\n- Separate concepts use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not reject a tag\n  merely because it is not a programming language.\n- Description ends with a period before optional `[GitHub](...)`.\n- Treat `CONTRIBUTING.md`'s \"one sentence\" wording as concision guidance, not a sentence-count\n  gate. Accept two or more short sentences when the overall description remains concise, factual,\n  relevant, and non-promotional. Never return `NEEDS CHANGES` solely because of sentence count;\n  request wording changes only for actual quality problems such as verbosity, repetition,\n  unsupported claims, promotional language, or poor readability.\n- URLs use `https://`.\n- Optional GitHub link uses `[GitHub](https://github.com/owner/repo)`.\n- Section placement matches the project's purpose.\n- Distinguish repositories containing substantive implementation from thin SDK, integration,\n  examples, generated-data, or marketing repositories.\n- Hosted proprietary products without substantive public source are under\n  `Commercial & Proprietary Services`, even when a thin repository exists.\n- For repository-less commercial entries, verify a useful permanent free tier for quantitative\n  finance that requires no payment information and is not a trial, demo, or waitlist.\n- Treat a commercial service with only a thin SDK, integration, examples, generated-data, or\n  marketing repository as repository-less for every eligibility check.\n- Verify that these commercial entries publish pricing and free-tier limits plus public\n  documentation, methodology, or usage examples; use a stable HTTPS URL without affiliate or\n  tracking parameters; and have a concise, factual, non-promotional description.\n- Project name and URLs are not duplicates of existing README entries.\n- A verifiable GitHub repository containing substantive implementation, mentioned as the main URL\n  or exact `[GitHub](...)` suffix, is a strong positive relevance signal. Repository existence\n  alone does not establish commercial eligibility or functional-section placement.\n- GitHub projects are checked for source availability, activity, archived status,\n  documentation, and community evidence. GitHub relevance does not waive duplicate, format,\n  or quality checks.\n- Multiple projects in one PR are closely related and explained in the PR body.\n\n## Repository Substance and Linked Services\n\nFor every added entry with a repository, investigate what the public source actually provides:\n\n1. Inspect representative implementation files behind the advertised functionality. A README,\n   license, tests, file count, or stars alone do not establish substance.\n2. Trace whether core functionality is implemented publicly or depends on a proprietary service.\n   Identify code that only calls a vendor API, integrates a service, downloads generated output,\n   or provides examples or marketing. External dependencies alone do not make a project thin;\n   assess where the advertised functionality is implemented.\n3. Follow linked service websites, public documentation, and pricing/free-tier pages. Establish\n   the repository's relationship to the service and verify eligibility under `CONTRIBUTING.md`,\n   including useful permanent free access without payment information.\n4. Report concrete evidence: representative source-file links, API dependencies, and relevant\n   service/pricing/documentation links. State unavailable or inconclusive evidence explicitly.\n   Small size, few stars, or recent creation alone do not imply poor quality or commercial status.\n\nWhen a repository mainly supports a qualifying commercial service, place the entry in\n`Commercial & Proprietary Services`. Use the service name and stable service website as the main\nlink, and retain the repository only as the exact `[GitHub](...)` suffix:\n\n```markdown\n- [Service Name](https://service.example) - Factual service description with relevant free-tier limits. [GitHub](https://github.com/owner/client)\n```\n\nDescribe the service, not merely its SDK. An open-source client license does not make the hosted\nservice open source. Substantive public implementation can qualify for a functional section even\nwhen its maintainers also sell a hosted service.\n\n- Qualifying service with incorrect placement or a thin repository as its main link:\n  `NEEDS CHANGES`, with a proposed corrected README entry.\n- Confirmed paid-only, trial-only, demo-only, waitlist-only, or otherwise non-qualifying free\n  access: `REJECT`; moving the entry does not fix eligibility.\n- Insufficient evidence of repository substance or service eligibility: `NEEDS CHANGES`, naming\n  the missing evidence without claiming that the service qualifies.\n\n## Verdicts\n\nUse these verdicts:\n\n- `APPROVE`: both required workflows pass and the entry is ready to merge after manual review.\n- Sentence count alone does not affect the verdict; evaluate description quality using the criteria\n  in the Validation Checklist.\n- Commercial submissions without a qualifying permanent free tier—including paid-only,\n  trial-only, demo-only, and waitlist-only offerings—are `REJECT`.\n- Reserve `NEEDS CHANGES` for correctable evidence or disclosure, wording, URL, documentation, or\n  placement defects when the underlying offering can qualify.\n- Other `REJECT` cases include duplicates, unrelated multi-project PRs, empty PR descriptions,\n  archived or abandoned projects, and other hard rejections.\n\n## Output Shape\n\nReport:\n\n```text\nPR #<number>: <title>\nAuthor: <author>\nPrior review: YES/NO\nFiles changed: <files>\nEntries reviewed: <count>\n\nAutomated validation:\n- Validate PR: PASS | FAIL | PENDING | UNVERIFIED\n- PR Review: PASS | FAIL | PENDING | UNVERIFIED\n- Commit: <checked-sha> (CURRENT | STALE)\n- Mechanical checks: accepted from CI | reproduced manually | incomplete\n\nFindings:\n- <entry>: <status and reason>\n\nVerdict: APPROVE | NEEDS CHANGES | REJECT\nRecommended action: <merge/comment/close/no action>\n```\n\nThen ask for explicit approval before doing the recommended action.\n\n## Approved Actions After User Consent\n\n- If approved and user says to merge: merge with squash unless user requests otherwise.\n- If needs changes and user says to comment: leave one concise comment with all requested fixes, then add `reviewed` if available.\n- If rejected and user says to close: leave a polite rejection comment and close the PR.\n",".claude/skills/update-pypi-dates/README.md":"# Update PyPI Dates Skill\n\nAutomatically check PyPI projects for their latest update dates and keep README.md entries current.\n\n## Overview\n\nThis skill monitors Python packages listed in awesome-quant and updates their entries with the latest release dates from PyPI. This ensures that outdated project information is easily identifiable.\n\n## Features\n\n- ✅ Checks 4 PyPI projects: qfrm, chinesestockapi, tushare, metatrader5\n- ✅ Fetches latest release dates from PyPI API\n- ✅ Updates README.md entries with `(Last updated: YYYY-MM-DD)` format\n- ✅ Commits changes automatically when updates found\n- ✅ No dependencies beyond Python standard library\n\n## Usage\n\n### Invoke from Claude Code\n\n```bash\n/update-pypi-dates\n```\n\nOr call the script directly:\n\n```bash\n./.claude/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n### Manual Python Execution\n\n```bash\npython3 .claude/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n### Bash Wrapper\n\n```bash\n./.claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh\n```\n\n## How It Works\n\n1. **Queries PyPI API** for each tracked package\n2. **Extracts last release date** from the releases data\n3. **Updates README.md** entries with format: `(Last updated: 2024-08-27)`\n4. **Commits changes** if any updates were found\n\n## Adding New Packages\n\nTo track additional PyPI packages, edit the `PYPI_PROJECTS` dictionary in `scripts/check_pypi_dates.py`:\n\n```python\nPYPI_PROJECTS = {\n    \"display_name\": \"pypi_package_name\",\n    # Add new entries here\n}\n```\n\nThen update the skill description if needed.\n\n## Output Examples\n\n### No Changes\n```\n📦 Checking PyPI projects for last updated dates...\n\nChecking qfrm...\n  ✓ 2015-12-12 (no change)\n\n✓ All packages up to date!\n```\n\n### With Updates\n```\n📦 Checking PyPI projects for last updated dates...\n\nChecking tushare...\n  ✓ 2024-08-27 (no change)\nChecking metatrader5...\n  ✅ Updated to 2026-02-20\n\n📝 Found 1 update(s):\n  - metatrader5: 2026-02-20\n\n✅ Updated README.md\n```\n\n## Configuration\n\n### Periodic Execution\n\nSet up a cron job to run weekly:\n\n```bash\n# Add to crontab (runs Monday at 2 AM)\n0 2 * * 1 cd /path/to/awesome-quant && ./.claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh\n```\n\nOr use Claude Code's scheduling:\n\n```bash\n/loop 1w /update-pypi-dates\n```\n\n## Files\n\n- `SKILL.md` - Skill definition and documentation\n- `scripts/check_pypi_dates.py` - Main Python script\n- `scripts/update_pypi_dates.sh` - Bash wrapper with git integration\n- `README.md` - This file\n\n## Requirements\n\n- Python 3.6+\n- Network access to PyPI API\n- Git (for automatic commits)\n\n## Error Handling\n\n- Network timeouts: Gracefully skipped with warning\n- Package not found: Skipped with message\n- API errors: Logged and continued with other packages\n\n## Future Enhancements\n\n- [ ] Support for more PyPI packages\n- [ ] GitHub Actions workflow integration\n- [ ] Email notifications on updates\n- [ ] Comparison with published versions in README\n- [ ] Support for other package registries (npm, Ruby Gems, etc.)\n","CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\n**awesome-quant** is a curated list of quantitative finance libraries, packages, and resources. The primary content lives in `README.md` — a large markdown file **organized by category** (Numerical Libraries, Trading & Backtesting, Market Data, etc.) with inline language tags that identify which programming languages each project supports.\n\nA companion website is generated from this data and deployed to GitHub Pages.\n\n## Architecture\n\nThe pipeline works as follows:\n\n1. **`README.md`** — The source of truth. All library entries follow the format: `- [name](url) - \\`Language\\` - Description.`\n   - Entries are grouped under category headings (`##`), not language headings\n   - Language is identified via inline backtick tags (e.g., `` `Python` ``, `` `Rust` ``) in the description\n   - Multi-language projects have multiple tags (e.g., `` `Python` `Rust` ``)\n\n2. **`parse.py`** — Parses `README.md`, extracts language from backtick tags, fetches last commit dates and stars via the GitHub API (using `PyGithub` with multithreading), and writes `site/projects.csv` with a `languages` column (comma-separated).\n\n3. **`site/generate.py`** — Reads `site/projects.csv` (or parses `README.md` directly) and generates a static HTML site (`site/index.html`) with search, filtering by language/category/source, sorting, and dark mode. Front-end assets live in `site/static/` (`main.js`, `style.css`).\n\n4. **CI** (`.github/workflows/build.yml`, workflow name \"Update site\") — Runs daily (cron `0 1 * * *`) and on push to `main` touching `README.md`, `parse.py`, or `site/**`: runs `parse.py`, runs `site/generate.py`, and deploys the `site/` directory to GitHub Pages via `peaceiris/actions-gh-pages`.\n\nSupporting scripts:\n- `cranscrape.py` — Scrapes CRAN package pages to find associated GitHub repos; writes `cran.csv`.\n- `topic.py` — Searches GitHub for repos tagged with a topic (e.g., \"quant\") above a star threshold.\n- `scripts/migrate_readme.py` — One-off migration that converted `README.md` from language-first to category-first organization (kept for reference).\n\n## Commands\n\n```bash\n# Install dependencies (uses uv, requires Python 3.11+)\nuv sync --no-install-project\n\n# Run the parser (requires GITHUB_ACCESS_TOKEN env var)\nGITHUB_ACCESS_TOKEN=<token> uv run python parse.py\n\n# Generate the static site\nuv run python site/generate.py\n```\n\n## Contributing Entries\n\nSee `CONTRIBUTING.md` for full guidelines. All entries must include language tags:\n\n```\n- [Project Name](https://github.com/owner/repo) - `Python` - Description ending with a period.\n- [Project Name](https://github.com/owner/repo) - `Python` `Rust` - Multi-language project description.\n- [Project Name](https://site.com) - `Python` - Description ending with a period. [GitHub](https://github.com/owner/repo)\n- [Package Name](https://cran.r-project.org/package=pkg) - `R` - Description ending with a period.\n- [package-name](https://pypi.org/project/pkg/) - `Python` - Description ending with a period.\n```\n\nCRAN and PyPI entries may optionally append `[GitHub](url)` after the description.\n\nEntries are grouped under category headings (`##`), not language headings. Language is identified via inline backtick tags. Commercial/proprietary projects go under `## Commercial & Proprietary Services`.\n\n`parse.py` and `site/generate.py` rely on this regex to extract entries: `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`\n\nThe description text (group 3) may start with language tags in the format `` `Language1` `Language2` - `` followed by the actual description.\n\n## PR Reviews\n\nThis repo receives most contributions as pull requests adding new entries. Use the **GitHub MCP tools** (e.g. `list_pull_requests`, `pull_request_read`, `merge_pull_request`, `add_issue_comment`, `update_pull_request`), **not** the `gh` CLI, for PR operations.\n\nDedicated skills drive the review workflow:\n- `sprr` — Single PR reviewer: validate one PR's entry against the format rules.\n- `bprr` — Bulk PR reviewer: review all open PRs lacking the \"reviewed\" label, then present a summary for selection before merging.\n- `update-pypi-dates` — Refresh last-updated dates for PyPI entries in `README.md`.\n\nReview checklist: always ask before merging; verify section placement (commercial entries belong under \"Commercial & Proprietary Services\", not Market Data); check for duplicates in `README.md`; apply the \"reviewed\" label after commenting.\n\nSee `AGENTS.md` for the agent-facing command and tool summary, and `CONTRIBUTING.md` for contributor guidelines.\n",".claude/skills/update-pypi-dates/scripts/check_pypi_dates.py":"#!/usr/bin/env python3\n\"\"\"\nCheck PyPI projects for last updated dates and update README.md entries.\n\"\"\"\n\nimport json\nimport re\nimport subprocess\nimport sys\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Dict, Optional, Tuple\nfrom urllib.request import urlopen\n\n# PyPI projects to track\nPYPI_PROJECTS = {\n    \"qfrm\": \"qfrm\",\n    \"chinesestockapi\": \"chinesestockapi\",\n    \"tushare\": \"tushare\",\n    \"metatrader5\": \"MetaTrader5\",\n}\n\nREADME_PATH = Path(__file__).parent.parent.parent.parent.parent / \"README.md\"\n\n\ndef get_pypi_last_updated(package_name: str) -> Optional[str]:\n    \"\"\"\n    Fetch the last updated date for a PyPI package.\n\n    Returns: date string in format \"YYYY-MM-DD\" or None if not found\n    \"\"\"\n    try:\n        url = f\"https://pypi.org/pypi/{package_name}/json\"\n        with urlopen(url, timeout=5) as response:\n            data = json.loads(response.read().decode())\n\n        # Get releases (ordered dict, latest first after sorting)\n        releases = data.get(\"releases\", {})\n        if not releases:\n            return None\n\n        # Find the latest release with upload time\n        for version in sorted(releases.keys(), reverse=True):\n            release_data = releases[version]\n            if release_data and len(release_data) > 0:\n                upload_time = release_data[0].get(\"upload_time_iso_8601\")\n                if upload_time:\n                    # Extract just the date part (YYYY-MM-DD)\n                    return upload_time.split(\"T\")[0]\n\n        return None\n    except Exception as e:\n        print(f\"  ❌ Error fetching {package_name}: {e}\", file=sys.stderr)\n        return None\n\n\ndef find_readme_entry(readme_content: str, package_display_name: str) -> Tuple[Optional[int], Optional[str]]:\n    \"\"\"\n    Find a README entry for a package.\n\n    Returns: (line_number, match_text) or (None, None)\n    \"\"\"\n    # Pattern to match the entry - look for [package_name](pypi.org...)\n    pattern = rf\"\\- \\[{re.escape(package_display_name)}\\]\\(https://pypi\\.org/project/\\w+/\\)[^\\n]*\"\n\n    for line_num, line in enumerate(readme_content.split(\"\\n\"), 1):\n        if re.search(pattern, line):\n            return line_num, line.strip()\n\n    return None, None\n\n\ndef update_readme_entry(readme_content: str, package_display_name: str, new_date: str) -> Tuple[str, bool]:\n    \"\"\"\n    Update or add the last updated date to a README entry.\n\n    Returns: (updated_content, was_changed)\n    \"\"\"\n    lines = readme_content.split(\"\\n\")\n    line_num, entry_text = find_readme_entry(readme_content, package_display_name)\n\n    if line_num is None:\n        return readme_content, False\n\n    old_line = lines[line_num - 1]\n\n    # Check if entry already has a date\n    existing_date_pattern = r\"\\(Last updated: \\d{4}-\\d{2}-\\d{2}\\)\"\n    existing_match = re.search(existing_date_pattern, old_line)\n\n    if existing_match:\n        old_date = existing_match.group(0)\n        new_date_str = f\"(Last updated: {new_date})\"\n        if old_date == new_date_str:\n            return readme_content, False  # No change needed\n        new_line = old_line.replace(old_date, new_date_str)\n    else:\n        # Add date to the end of the entry (before period if present)\n        if old_line.endswith(\".\"):\n            new_line = old_line[:-1] + f\" (Last updated: {new_date}).\"\n        else:\n            new_line = old_line + f\" (Last updated: {new_date})\"\n\n    lines[line_num - 1] = new_line\n    return \"\\n\".join(lines), True\n\n\ndef main():\n    \"\"\"Check PyPI projects and update README.md.\"\"\"\n    if not README_PATH.exists():\n        print(f\"❌ README.md not found at {README_PATH}\")\n        sys.exit(1)\n\n    readme_content = README_PATH.read_text(encoding=\"utf-8\")\n    updated_content = readme_content\n    changes_made = []\n\n    print(\"📦 Checking PyPI projects for last updated dates...\\n\")\n\n    for display_name, pypi_name in PYPI_PROJECTS.items():\n        print(f\"Checking {display_name}...\")\n\n        last_updated = get_pypi_last_updated(pypi_name)\n        if last_updated is None:\n            print(f\"  ⚠️  Could not find last updated date\")\n            continue\n\n        updated_content, was_changed = update_readme_entry(\n            updated_content, display_name, last_updated\n        )\n\n        if was_changed:\n            print(f\"  ✅ Updated to {last_updated}\")\n            changes_made.append((display_name, last_updated))\n        else:\n            print(f\"  ✓ {last_updated} (no change)\")\n\n    print()\n\n    if changes_made:\n        print(f\"📝 Found {len(changes_made)} update(s):\")\n        for pkg_name, date in changes_made:\n            print(f\"  - {pkg_name}: {date}\")\n\n        README_PATH.write_text(updated_content, encoding=\"utf-8\")\n        print(f\"\\n✅ Updated {README_PATH.name}\")\n        return 0\n    else:\n        print(\"✓ All packages up to date!\")\n        return 0\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n","AGENTS.md":"# AGENTS.md\n\n## Project Overview\n\n`awesome-quant` is a curated list of quantitative finance libraries, packages,\nand resources. The source of truth is `README.md`; the static website is\ngenerated into `site/index.html`.\n\nThe README is organized by category headings (`##`), not by language headings.\nProject metadata is stored in inline backtick tags inside each entry. Tags commonly identify\nlanguages, but may also identify runtimes, protocols, interfaces, data types, or domains.\n\n## Architecture\n\n1. `README.md` contains curated entries.\n2. `parse.py` parses `README.md`, enriches GitHub/CRAN/PyPI metadata, and writes\n   `site/projects.csv`.\n3. `site/generate.py` reads `site/projects.csv` when present, otherwise parses\n   `README.md` directly for local previews, then writes `site/index.html`.\n4. `.github/workflows/build.yml` runs the parser and generator, then deploys\n   `site/` to GitHub Pages.\n\n## Work Tracking and Planning\n\n- Linear is the system of record for issues, prioritization, specifications,\n  designs, and implementation plans.\n- Manage GitHub-originated issues through their synced Linear issues. Do not\n  create a second internal tracker for the same work.\n- Store each specification, design, and implementation plan as a Linear\n  document attached to the corresponding Linear issue. Do not add task-specific\n  planning documents to the repository.\n- Keep repository documentation for durable project and user documentation only.\n- GitHub remains the public contribution surface for pull requests and public\n  issue discussion; use Linear for internal status, priority, and planning.\n\n## Commands\n\n```bash\n# Install deps (requires Python 3.11+)\nuv sync --no-install-project\n\n# Validate README entries changed in a PR\nuv run python scripts/validate_readme.py --diff-from origin/main\n\n# Validate the full README; legacy format/duplicate/URL issues are warnings by default\nuv run python scripts/validate_readme.py\n\n# Run parser (requires GitHub token)\nGITHUB_ACCESS_TOKEN=<token> uv run python parse.py\n\n# Generate static site\nuv run python site/generate.py\n```\n\n## Entry Format\n\nThe critical parser regex is:\n\n```text\n^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$\n```\n\nAccepted entry examples:\n\n```markdown\n- [Project Name](https://github.com/owner/repo) - `Python` - Description ending with a period.\n- [Project Name](https://github.com/owner/repo) - `Python` `Rust` - Description ending with a period.\n- [Project Name](https://site.com) - `Python` - Description ending with a period. [GitHub](https://github.com/owner/repo)\n- [Package Name](https://cran.r-project.org/package=pkg) - `R` - Description ending with a period.\n- [package-name](https://pypi.org/project/pkg/) - `Python` - Description ending with a period.\n```\n\nRules:\n\n- New non-commercial entries must include one or more concise backtick tags followed by ` - `.\n  Tags form a compact tag cloud and are not restricted to programming languages.\n- Each tag must use its own backtick pair, for example `` `Python` `C++` `MCP` ``.\n- Descriptions must end with a period before the optional `[GitHub](...)` link.\n- URLs in new entries must use `https://`.\n- A valid GitHub repository used as the main URL or exact `[GitHub](...)` suffix is preferred\n  and is a strong positive relevance signal, but it is not universally required. Functional\n  section placement requires a repository containing substantive implementation; a thin SDK,\n  integration, examples, generated-data, or marketing repository does not qualify.\n- Hosted commercial/proprietary products without substantive public source belong in\n  `## Commercial & Proprietary Services`, even when a thin repository exists. Repository-less\n  services qualify only under the permanent free tier and transparency rules in\n  `CONTRIBUTING.md`.\n- Treat a commercial service with only a thin SDK, integration, examples, generated-data, or\n  marketing repository as repository-less for every eligibility check.\n- Backtick tags are optional only for commercial services and other metadata-free\n  sections such as `Related Lists`.\n- `Historical & Archived Projects` is the documented exception to normal activity and\n  archive-state requirements. Entries still require substantive, reachable, documented source\n  and the `Historical` tag; use `CONTRIBUTING.md` for eligibility.\n- Use `CONTRIBUTING.md` as the user-facing source for contribution rules.\n\n## PR Review Workflow\n\nThis repo receives most contributions as pull requests adding README entries.\nUse Codex repo skills for repeatable review workflows:\n\n- `$sprr` - single PR reviewer.\n- `$bprr` - bulk PR reviewer.\n- `$update-pypi-dates` - refresh tracked PyPI last-updated dates.\n- `$create-entry` - draft or add README entries from a URL, GitHub issue, or Linear issue.\n\nReview requirements:\n\n1. Only review the PRs the user asked you to review.\n2. Use GitHub MCP tools for PR operations, not the `gh` CLI.\n3. Present findings before any PR-modifying action.\n4. Always ask the user before commenting, labeling, closing, or merging.\n5. Check section placement, duplicates in `README.md`, entry format, URL format,\n   and project activity/documentation. Give substantial positive weight to a verifiable\n   GitHub repository mentioned as either the main URL or exact suffix, while confirming that\n   functional-section repositories contain substantive implementation.\n6. Manually assess commercial entries for free-tier usefulness, payment information,\n   public pricing and limits, public documentation/methodology/examples, stable non-tracking\n   URLs, concise factual description tone, and repository substance.\n7. Commercial submissions without a qualifying permanent free tier—including paid-only,\n   trial-only, demo-only, and waitlist-only offerings—are `REJECT`. Reserve `NEEDS CHANGES` for\n   correctable evidence or disclosure, wording, URL, documentation, or placement defects when\n   the underlying offering can qualify.\n8. Use the `reviewed` label only after the user approves a review comment.\n\n## GitHub MCP Tools\n\nThis project expects Codex to have a GitHub MCP server configured for PR work.\nUseful tool capabilities include:\n\n- List open pull requests.\n- Get PR details, files, comments, labels, and diffs.\n- Fetch `README.md` from the default branch for duplicate checks.\n- Add PR comments and labels.\n- Merge pull requests after explicit user approval.\n\nSee `docs/codex-setup.md` for local Codex setup notes. If GitHub MCP tools are\nnot available in a session, report that PR operations are blocked and ask the\nuser to configure the MCP server.\n\n## Local Validation Notes\n\n- `scripts/validate_readme.py --diff-from <ref>` is intended for PR checks. It\n  validates only added README entries and treats duplicates/URL issues as errors\n  for those additions.\n- `scripts/validate_readme.py` validates the full README. Legacy format, duplicate, and\n  URL problems are reported as warnings unless strict flags are used.\n- `parse.py` requires `GITHUB_ACCESS_TOKEN`; `site/generate.py` can run without\n  the token if `site/projects.csv` already exists or if it falls back to direct\n  README parsing.\n",".claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh":"#!/bin/bash\n# Wrapper script to check PyPI dates and update README.md\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_ROOT=\"$(cd \"$SCRIPT_DIR/../../../../..\" && pwd)\"\n\ncd \"$PROJECT_ROOT\" || exit 1\n\necho \"🚀 Starting PyPI date update check...\"\npython3 \"$SCRIPT_DIR/check_pypi_dates.py\"\nexit_code=$?\n\nif [ $exit_code -eq 0 ]; then\n    # Check if there are any changes to commit\n    if git diff --quiet README.md; then\n        echo \"✓ No changes needed\"\n    else\n        echo \"\"\n        echo \"📝 Changes detected, committing...\"\n        git add README.md\n        git commit -m \"Update PyPI project last updated dates\"\n        git push origin main\n        echo \"✅ Changes pushed to remote\"\n    fi\nfi\n\nexit $exit_code\n"},"files":{".claude/skills/sprr/SKILL.md":"---\nname: sprr\ndescription: Single PR reviewer for awesome-quant. Use when the user asks to review, validate, comment on, label, close, or merge one specific pull request that adds README.md entries. Triggers include \"sprr\", \"review PR\", \"check PR\", and \"validate contribution\".\n---\n\n# SPRR: Single PR Reviewer\n\nReview one pull request that adds entries to `README.md`.\n\n## Hard Rules\n\n1. Review only the PR number the user requested. If no PR number is given, ask for one.\n2. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n3. Do not modify the PR until the user explicitly approves that action.\n4. Always present findings before asking whether to comment, label, close, or merge.\n5. Always ask before merging.\n6. Enforce `CONTRIBUTING.md` and `AGENTS.md` strictly for new entries.\n\nIf GitHub MCP tools are unavailable, report that PR operations are blocked and point the user to `docs/codex-setup.md`.\n\n## Workflow\n\n1. Fetch PR details, current head SHA, files changed, labels, comments, and diff with GitHub MCP.\n2. Confirm whether the `reviewed` label or prior maintainer comments exist, then proceed with full validation anyway.\n3. Fetch the latest `Validate PR` workflow/check attempt for the current head SHA and apply the CI evidence rules below.\n4. Focus on added lines in `README.md`. Flag any other changed files as unusual for a normal contribution.\n5. When mechanical validation is not established by current-head CI, save or reconstruct the PR diff locally only if needed, then validate added README entries with:\n\n```bash\nuv run python scripts/validate_readme.py --diff-from <base-ref>\n```\n\nIf a base ref is not locally available, apply the same checks manually from the fetched diff.\n\n## CI Evidence Rules\n\nUse only the latest attempt whose commit SHA exactly matches the PR's current head SHA. A newer\nqueued or pending attempt supersedes an older successful attempt for the same SHA.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not rerun those mechanical checks. |\n| `failure` | Inspect the failing job or step. Return `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Report the review as incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Treat mechanical validation as unverified and reproduce it before deciding. |\n| success on an older SHA | Ignore it and evaluate the current SHA using these rules. |\n\nCI never replaces inspection of the diff or the manual checks below. A successful check confirms\nonly mechanical rules; it does not establish tag meaning or concision, description quality,\nrelevance, semantic section suitability, commercial classification, repository quality,\ncross-PR uniqueness, or multi-project relatedness. Search open PRs and PRs closed within the\nlast 365 days for duplicate names and URLs.\n\nFor repository substance and linked commercial services, apply the **Repository Substance and\nLinked Services** investigation in `.agents/skills/sprr/SKILL.md`, including its evidence,\nservice-first link, and eligibility verdict rules.\n\n## Validation Checklist\n\nFor every added entry:\n\n- It matches `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`.\n- New non-commercial entries include one or more backtick tags followed by ` - `. Treat these\n  as a compact tag cloud: accept concise languages, runtimes, protocols, interfaces, data\n  types, and domain terms.\n- Separate concepts use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not reject a tag\n  merely because it is not a programming language.\n- Description ends with a period before optional `[GitHub](...)`.\n- URLs use `https://`.\n- Optional GitHub link uses `[GitHub](https://github.com/owner/repo)`.\n- Section placement matches the project's purpose.\n- Commercial/proprietary projects are under `Commercial & Proprietary Services`.\n- Project name and URLs are not duplicates of existing README entries.\n- A verifiable GitHub repository containing substantive implementation, mentioned as the main URL\n  or exact `[GitHub](...)` suffix, is a strong positive relevance signal.\n- GitHub projects are checked for source availability, activity, archived status,\n  documentation, and community evidence. GitHub relevance does not waive duplicate, format,\n  or quality checks.\n- Multiple projects in one PR are closely related and explained in the PR body.\n\n## Verdicts\n\nUse these verdicts:\n\n- `APPROVE`: entry is ready to merge.\n- `NEEDS CHANGES`: fixable format, section, URL, description, or documentation issue.\n- `REJECT`: duplicate, unrelated multi-project PR, empty PR description, archived/abandoned project, or other hard rejection.\n\n## Output Shape\n\nReport:\n\n```text\nPR #<number>: <title>\nAuthor: <author>\nPrior review: YES/NO\nFiles changed: <files>\nEntries reviewed: <count>\n\nAutomated validation:\n- Validate PR: PASS | FAIL | PENDING | UNVERIFIED\n- Commit: <checked-sha> (CURRENT | STALE)\n- Mechanical checks: accepted from CI | reproduced manually | incomplete\n\nFindings:\n- <entry>: <status and reason>\n\nVerdict: APPROVE | NEEDS CHANGES | REJECT\nRecommended action: <merge/comment/close/no action>\n```\n\nThen ask for explicit approval before doing the recommended action.\n\n## Approved Actions After User Consent\n\n- If approved and user says to merge: merge with squash unless user requests otherwise.\n- If needs changes and user says to comment: leave one concise comment with all requested fixes, then add `reviewed` if available.\n- If rejected and user says to close: leave a polite rejection comment and close the PR.\n",".claude/skills/update-pypi-dates/SKILL.md":"---\nname: update-pypi-dates\ndescription: Check PyPI projects for last updated dates and update README.md entries. Use this skill to keep PyPI project information current with latest release dates from PyPI. Run periodically to maintain up-to-date metadata on Python packages listed in awesome-quant.\n---\n\n# Update PyPI Dates\n\nAutomatically check PyPI projects for their latest update dates and update corresponding README.md entries with the \"(Last updated: YYYY-MM-DD)\" information.\n\n## How it works\n\nThe skill maintains a list of PyPI projects in awesome-quant and:\n1. Queries the PyPI JSON API for each package\n2. Extracts the last release date\n3. Updates README.md entries with the new date if changed\n4. Commits changes to git if updates were made\n\n## PyPI Projects to Track\n\nCurrent projects tracked:\n- qfrm\n- chinesestockapi\n- tushare\n- metatrader5\n\n## Steps\n\n### 1. Fetch PyPI data for each project\n\nFor each PyPI project, query: `https://pypi.org/pypi/{package_name}/json`\n\nExtract the last release date from the releases data.\n\n### 2. Update README.md entries\n\nFor each project with a new date:\n- Find the entry in README.md\n- Update or add the \"(Last updated: YYYY-MM-DD)\" note\n- Use the exact entry format: `(Last updated: 2024-08-27)`\n\n### 3. Verify changes\n\nShow the user:\n- Which packages were checked\n- Which packages have new update dates\n- The differences (old date → new date)\n\n### 4. Commit if changes detected\n\nIf any updates were made:\n```bash\ngit add README.md non-github-urls.md\ngit commit -m \"Update PyPI project last updated dates\"\ngit push origin main\n```\n\n## Usage\n\nThe user can:\n- Run the skill directly: `/update-pypi-dates`\n- Schedule it to run weekly/monthly via cron\n- Include it in CI/CD pipelines to keep data fresh\n\n## Script\n\nUse `scripts/check_pypi_dates.sh` for the core update logic.\n",".agents/skills/bprr/SKILL.md":"---\nname: bprr\ndescription: Bulk PR reviewer for awesome-quant. Use when the user asks to review all open PRs, review unreviewed PRs, bulk review, or mentions \"bprr\". Reviews open PRs lacking the reviewed label and presents a summary before any merge/comment/label action.\n---\n\n# BPRR: Bulk PR Reviewer\n\nReview multiple open pull requests for README entry contributions.\n\n**REQUIRED SUB-SKILL:** Use `sprr` as the canonical policy for reviewing each pull request. Read\nit before starting the bulk review and apply its hard rules, workflow evidence rules, validation\nchecklist, verdicts, output fields, and approved-action rules unless this skill defines a\nbulk-specific presentation step.\n\n## Hard Rules\n\n1. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels,\n   closing, or merging.\n2. Filter out PRs with the `reviewed` label unless the user asks to re-review them.\n3. Apply `sprr` independently to every PR. Shared retrieval may reduce repeated work, but evidence,\n   findings, and verdicts never carry from one PR to another.\n4. Do not comment, label, close, or merge until the user explicitly approves each action.\n5. Do not auto-merge all approved PRs unless the user explicitly selects that option.\n6. If GitHub MCP tools are unavailable, report the blocker and point to `docs/codex-setup.md`.\n\n## Bulk Workflow\n\n1. List open PRs sorted oldest first and filter to unreviewed PRs by default.\n2. Fetch the default-branch `README.md` once and reuse it where `sprr` requires a base-README\n   duplicate check.\n3. For every included PR, fetch the data and both required workflow attempts specified by `sprr`.\n4. Apply `sprr` independently to every PR, including its manual checks and cross-PR duplicate\n   search over open PRs and PRs closed within the last 365 days.\n5. Present the bulk summary below before asking the user to select any actions.\n\n## Summary Output\n\nPresent a table:\n\n```text\n| PR | Title | Author | Head | Validate PR | PR Review | Entries | Format/URL | Section | Duplicate | Verdict |\n|----|-------|--------|------|-------------|-----------|---------|------------|---------|-----------|---------|\n```\n\nFor each row, copy the workflow states, mechanical-check result, and verdict from that PR's `sprr`\nreview. `Section` remains a manual semantic judgment. In `Duplicate`, report both\n`README PASS|FAIL` and `PR SEARCH PASS|FAIL`.\n\nAfter the table, list any PRs that need detailed notes. Include failed workflow steps, reasons\nworkflow evidence was not accepted, manual findings, and commercial free-tier or transparency\nevidence when it affects the verdict.\n\nAsk what to do next. Accept selections such as:\n\n- `merge 123, 124`\n- `comment 125`\n- `close 126`\n- `all approved`\n- `none`\n\nApply `sprr`'s approved-action rules to each selected PR. Confirm every merge before executing it.\n",".agents/skills/update-pypi-dates/SKILL.md":"---\nname: update-pypi-dates\ndescription: Refresh tracked PyPI last-updated dates in awesome-quant README.md. Use when the user asks to update PyPI dates, refresh PyPI metadata, or run update-pypi-dates.\n---\n\n# Update PyPI Dates\n\nRefresh last release dates for selected PyPI packages listed in `README.md`.\n\n## Workflow\n\n1. Run the checker:\n\n```bash\nuv run python .agents/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n2. Show the user which packages changed.\n3. Run README validation:\n\n```bash\nuv run python scripts/validate_readme.py\n```\n\n4. If the user asked for a commit, stage only the relevant files and commit.\n5. Do not push unless the user explicitly asks.\n\n## Tracked Packages\n\nThe script currently tracks:\n\n- `qfrm`\n- `chinesestockapi`\n- `tushare`\n- `metatrader5` / `MetaTrader5`\n\nTo add packages, edit `PYPI_PROJECTS` in `scripts/check_pypi_dates.py`.\n",".claude/skills/bprr/SKILL.md":"---\nname: bprr\ndescription: Bulk PR reviewer for awesome-quant. Use when the user asks to review all open PRs, review unreviewed PRs, bulk review, or mentions \"bprr\". Reviews open PRs lacking the reviewed label and presents a summary before any merge/comment/label action.\n---\n\n# BPRR: Bulk PR Reviewer\n\nReview multiple open pull requests for README entry contributions.\n\n## Hard Rules\n\n1. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n2. Filter out PRs with the `reviewed` label unless the user asks to re-review them.\n3. Do not comment, label, close, or merge until the user explicitly approves each action.\n4. Do not auto-merge all approved PRs unless the user explicitly selects that option.\n5. If GitHub MCP tools are unavailable, report the blocker and point to `docs/codex-setup.md`.\n\n## Workflow\n\n1. List open PRs sorted oldest first.\n2. Filter to unreviewed PRs by default.\n3. Fetch the default-branch `README.md` once for duplicate checks.\n4. For each PR, fetch details, current head SHA, labels, files, body, diff, and the latest `Validate PR` workflow/check attempt for that SHA.\n5. Review only added `README.md` entries unless the PR changes other files; flag other file changes as unusual.\n6. Apply the CI evidence rules below, then perform the remaining `$sprr` checks. Use `scripts/validate_readme.py --diff-from <base-ref>` only when current-head CI does not establish mechanical validity and the PR branch is available locally; otherwise apply the validator's rules manually from the MCP diff.\n\n## CI Evidence Rules\n\nEvaluate each PR independently. Use only the latest attempt for the current head SHA; a newer\nqueued or pending attempt supersedes an older success for that SHA. A result for one PR or\ncommit never applies to another.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not repeat those mechanical checks. |\n| `failure` | Inspect the failing job or step. Use `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Mark the review incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Treat mechanical validation as unverified and reproduce it before deciding. |\n| success only on an older SHA | Report `STALE`, ignore it, and reproduce mechanical validation for the current head SHA. |\n\nFor every PR, still inspect the diff and manually review tag meaning and concision, description\nquality, relevance, semantic section suitability, commercial classification, repository\nactivity/archive/documentation/community evidence, duplicates in open PRs and PRs closed\nwithin the last 365 days, and multi-project relatedness.\n\n## Validation Checklist\n\nFor each added entry, check:\n\n- Parser regex match.\n- Required backtick tags for new non-commercial entries. Treat them as a compact tag cloud:\n  accept concise languages, runtimes, protocols, interfaces, data types, and domain terms.\n- Separate concepts must use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not require\n  every tag to be a programming language.\n- Description period before optional `[GitHub](...)`.\n- `https://` URLs.\n- Exact optional `[GitHub](https://github.com/owner/repo)` format.\n- Correct category section.\n- Commercial placement under `Commercial & Proprietary Services`.\n- Duplicate project names or URLs.\n- Treat any verifiable GitHub repository mentioned as the main URL or exact `[GitHub](...)`\n  suffix as a strong positive relevance signal.\n- For GitHub repos, check source availability, activity, archived status, documentation, and\n  community evidence. GitHub relevance does not waive duplicate, format, or quality checks.\n- Clear rationale for multiple related projects in one PR.\n\n## Summary Output\n\nPresent a table:\n\n```text\n| PR | Title | Author | Head | Validate PR | Entries | Format/URL | Section | Duplicate | Verdict |\n|----|-------|--------|------|-------------|---------|------------|---------|-----------|---------|\n```\n\nUse the entry count in `Entries`. Use `PASS`, `FAIL`, `PENDING`, `UNVERIFIED`, or\n`STALE` in `Validate PR`. Use `CI PASS`, `CI FAIL`, `REPRODUCED PASS`,\n`REPRODUCED FAIL`, or `INCOMPLETE` in `Format/URL`. `Section` remains a manual\nsemantic judgment. In `Duplicate`, report both `README PASS|FAIL` and\n`PR SEARCH PASS|FAIL`.\n\nAfter the table, list any PRs that need detailed notes, including the failing workflow step or the reason CI evidence was not accepted.\n\nAsk what to do next. Accept selections like:\n\n- `merge 123, 124`\n- `comment 125`\n- `close 126`\n- `all approved`\n- `none`\n\nConfirm each merge before executing it.\n",".agents/skills/sprr/SKILL.md":"---\nname: sprr\ndescription: Single PR reviewer for awesome-quant. Use when the user asks to review, validate, comment on, label, close, or merge one specific pull request that adds README.md entries. Triggers include \"sprr\", \"review PR\", \"check PR\", and \"validate contribution\".\n---\n\n# SPRR: Single PR Reviewer\n\nReview one pull request that adds entries to `README.md`.\n\n## Hard Rules\n\n1. Review only the PR number the user requested. If no PR number is given, ask for one.\n2. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n3. Do not modify the PR until the user explicitly approves that action.\n4. Always present findings before asking whether to comment, label, close, or merge.\n5. Always ask before merging.\n6. Enforce `CONTRIBUTING.md` and `AGENTS.md` strictly for new entries, using the\n   sentence-count interpretation in the Validation Checklist below.\n7. Both `Validate PR` and `PR Review` must pass before returning `APPROVE`.\n\nIf GitHub MCP tools are unavailable, report that PR operations are blocked and point the user to `docs/codex-setup.md`.\n\n## Workflow\n\n1. Fetch PR details, current head SHA, files changed, labels, comments, and diff with GitHub MCP.\n2. Confirm whether the `reviewed` label or prior maintainer comments exist, then proceed with full validation anyway.\n3. Fetch the latest `Validate PR` workflow/check attempt for the current head SHA and apply the CI evidence rules below.\n4. Fetch the latest `PR Review` workflow/check attempt associated with the pull request and apply\n   the required workflow rules below.\n5. Focus on added lines in `README.md`. Flag any other changed files as unusual for a normal contribution.\n6. When mechanical validation is not established by current-head CI, save or reconstruct the PR diff locally only if needed, then validate added README entries with:\n\n```bash\nuv run python scripts/validate_readme.py --diff-from <base-ref>\n```\n\nIf a base ref is not locally available, apply the same checks manually from the fetched diff.\n\n## CI Evidence Rules\n\nUse only the latest attempt whose commit SHA exactly matches the PR's current head SHA. A newer\nqueued or pending attempt supersedes an older successful attempt for the same SHA.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not rerun those mechanical checks. |\n| `failure` | Inspect the failing job or step. Return `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Report the review as incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Report the review as incomplete and do not return `APPROVE`; reproduce mechanical validation only to provide useful findings. |\n| success on an older SHA | Report the result as stale and do not return `APPROVE`; require a successful attempt for the current SHA. |\n\nCI never replaces inspection of the diff or the manual checks below. A successful check confirms\nonly mechanical rules; it does not establish tag meaning or concision, description quality,\nrelevance, semantic section suitability, commercial classification, repository quality,\ncommercial free-tier eligibility or transparency, URL tracking, cross-PR uniqueness, or\nmulti-project relatedness. CI cannot establish any of these manual criteria. Search open PRs and PRs\nclosed within the last 365 days for duplicate names and URLs.\n\n`PR Review` runs on `pull_request_target`, so use the latest attempt associated with the pull\nrequest without applying the current-head SHA rule used for `Validate PR`. A successful attempt is\nrequired but does not prove that current-head mechanical validation passed. If the latest attempt\nfails, inspect its failing job or step. Return `NEEDS CHANGES` when the review reports a PR defect;\notherwise report the review as incomplete. If it is queued, pending, cancelled, skipped, or\nmissing, report the review as incomplete and do not return `APPROVE`.\n\n## Validation Checklist\n\nFor every added entry:\n\n- It matches `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`.\n- New non-commercial entries include one or more backtick tags followed by ` - `. Treat these\n  as a compact tag cloud: accept concise languages, runtimes, protocols, interfaces, data\n  types, and domain terms.\n- Separate concepts use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not reject a tag\n  merely because it is not a programming language.\n- Description ends with a period before optional `[GitHub](...)`.\n- Treat `CONTRIBUTING.md`'s \"one sentence\" wording as concision guidance, not a sentence-count\n  gate. Accept two or more short sentences when the overall description remains concise, factual,\n  relevant, and non-promotional. Never return `NEEDS CHANGES` solely because of sentence count;\n  request wording changes only for actual quality problems such as verbosity, repetition,\n  unsupported claims, promotional language, or poor readability.\n- URLs use `https://`.\n- Optional GitHub link uses `[GitHub](https://github.com/owner/repo)`.\n- Section placement matches the project's purpose.\n- Distinguish repositories containing substantive implementation from thin SDK, integration,\n  examples, generated-data, or marketing repositories.\n- Hosted proprietary products without substantive public source are under\n  `Commercial & Proprietary Services`, even when a thin repository exists.\n- For repository-less commercial entries, verify a useful permanent free tier for quantitative\n  finance that requires no payment information and is not a trial, demo, or waitlist.\n- Treat a commercial service with only a thin SDK, integration, examples, generated-data, or\n  marketing repository as repository-less for every eligibility check.\n- Verify that these commercial entries publish pricing and free-tier limits plus public\n  documentation, methodology, or usage examples; use a stable HTTPS URL without affiliate or\n  tracking parameters; and have a concise, factual, non-promotional description.\n- Project name and URLs are not duplicates of existing README entries.\n- A verifiable GitHub repository containing substantive implementation, mentioned as the main URL\n  or exact `[GitHub](...)` suffix, is a strong positive relevance signal. Repository existence\n  alone does not establish commercial eligibility or functional-section placement.\n- GitHub projects are checked for source availability, activity, archived status,\n  documentation, and community evidence. GitHub relevance does not waive duplicate, format,\n  or quality checks.\n- Multiple projects in one PR are closely related and explained in the PR body.\n\n## Repository Substance and Linked Services\n\nFor every added entry with a repository, investigate what the public source actually provides:\n\n1. Inspect representative implementation files behind the advertised functionality. A README,\n   license, tests, file count, or stars alone do not establish substance.\n2. Trace whether core functionality is implemented publicly or depends on a proprietary service.\n   Identify code that only calls a vendor API, integrates a service, downloads generated output,\n   or provides examples or marketing. External dependencies alone do not make a project thin;\n   assess where the advertised functionality is implemented.\n3. Follow linked service websites, public documentation, and pricing/free-tier pages. Establish\n   the repository's relationship to the service and verify eligibility under `CONTRIBUTING.md`,\n   including useful permanent free access without payment information.\n4. Report concrete evidence: representative source-file links, API dependencies, and relevant\n   service/pricing/documentation links. State unavailable or inconclusive evidence explicitly.\n   Small size, few stars, or recent creation alone do not imply poor quality or commercial status.\n\nWhen a repository mainly supports a qualifying commercial service, place the entry in\n`Commercial & Proprietary Services`. Use the service name and stable service website as the main\nlink, and retain the repository only as the exact `[GitHub](...)` suffix:\n\n```markdown\n- [Service Name](https://service.example) - Factual service description with relevant free-tier limits. [GitHub](https://github.com/owner/client)\n```\n\nDescribe the service, not merely its SDK. An open-source client license does not make the hosted\nservice open source. Substantive public implementation can qualify for a functional section even\nwhen its maintainers also sell a hosted service.\n\n- Qualifying service with incorrect placement or a thin repository as its main link:\n  `NEEDS CHANGES`, with a proposed corrected README entry.\n- Confirmed paid-only, trial-only, demo-only, waitlist-only, or otherwise non-qualifying free\n  access: `REJECT`; moving the entry does not fix eligibility.\n- Insufficient evidence of repository substance or service eligibility: `NEEDS CHANGES`, naming\n  the missing evidence without claiming that the service qualifies.\n\n## Verdicts\n\nUse these verdicts:\n\n- `APPROVE`: both required workflows pass and the entry is ready to merge after manual review.\n- Sentence count alone does not affect the verdict; evaluate description quality using the criteria\n  in the Validation Checklist.\n- Commercial submissions without a qualifying permanent free tier—including paid-only,\n  trial-only, demo-only, and waitlist-only offerings—are `REJECT`.\n- Reserve `NEEDS CHANGES` for correctable evidence or disclosure, wording, URL, documentation, or\n  placement defects when the underlying offering can qualify.\n- Other `REJECT` cases include duplicates, unrelated multi-project PRs, empty PR descriptions,\n  archived or abandoned projects, and other hard rejections.\n\n## Output Shape\n\nReport:\n\n```text\nPR #<number>: <title>\nAuthor: <author>\nPrior review: YES/NO\nFiles changed: <files>\nEntries reviewed: <count>\n\nAutomated validation:\n- Validate PR: PASS | FAIL | PENDING | UNVERIFIED\n- PR Review: PASS | FAIL | PENDING | UNVERIFIED\n- Commit: <checked-sha> (CURRENT | STALE)\n- Mechanical checks: accepted from CI | reproduced manually | incomplete\n\nFindings:\n- <entry>: <status and reason>\n\nVerdict: APPROVE | NEEDS CHANGES | REJECT\nRecommended action: <merge/comment/close/no action>\n```\n\nThen ask for explicit approval before doing the recommended action.\n\n## Approved Actions After User Consent\n\n- If approved and user says to merge: merge with squash unless user requests otherwise.\n- If needs changes and user says to comment: leave one concise comment with all requested fixes, then add `reviewed` if available.\n- If rejected and user says to close: leave a polite rejection comment and close the PR.\n",".claude/skills/update-pypi-dates/README.md":"# Update PyPI Dates Skill\n\nAutomatically check PyPI projects for their latest update dates and keep README.md entries current.\n\n## Overview\n\nThis skill monitors Python packages listed in awesome-quant and updates their entries with the latest release dates from PyPI. This ensures that outdated project information is easily identifiable.\n\n## Features\n\n- ✅ Checks 4 PyPI projects: qfrm, chinesestockapi, tushare, metatrader5\n- ✅ Fetches latest release dates from PyPI API\n- ✅ Updates README.md entries with `(Last updated: YYYY-MM-DD)` format\n- ✅ Commits changes automatically when updates found\n- ✅ No dependencies beyond Python standard library\n\n## Usage\n\n### Invoke from Claude Code\n\n```bash\n/update-pypi-dates\n```\n\nOr call the script directly:\n\n```bash\n./.claude/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n### Manual Python Execution\n\n```bash\npython3 .claude/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n### Bash Wrapper\n\n```bash\n./.claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh\n```\n\n## How It Works\n\n1. **Queries PyPI API** for each tracked package\n2. **Extracts last release date** from the releases data\n3. **Updates README.md** entries with format: `(Last updated: 2024-08-27)`\n4. **Commits changes** if any updates were found\n\n## Adding New Packages\n\nTo track additional PyPI packages, edit the `PYPI_PROJECTS` dictionary in `scripts/check_pypi_dates.py`:\n\n```python\nPYPI_PROJECTS = {\n    \"display_name\": \"pypi_package_name\",\n    # Add new entries here\n}\n```\n\nThen update the skill description if needed.\n\n## Output Examples\n\n### No Changes\n```\n📦 Checking PyPI projects for last updated dates...\n\nChecking qfrm...\n  ✓ 2015-12-12 (no change)\n\n✓ All packages up to date!\n```\n\n### With Updates\n```\n📦 Checking PyPI projects for last updated dates...\n\nChecking tushare...\n  ✓ 2024-08-27 (no change)\nChecking metatrader5...\n  ✅ Updated to 2026-02-20\n\n📝 Found 1 update(s):\n  - metatrader5: 2026-02-20\n\n✅ Updated README.md\n```\n\n## Configuration\n\n### Periodic Execution\n\nSet up a cron job to run weekly:\n\n```bash\n# Add to crontab (runs Monday at 2 AM)\n0 2 * * 1 cd /path/to/awesome-quant && ./.claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh\n```\n\nOr use Claude Code's scheduling:\n\n```bash\n/loop 1w /update-pypi-dates\n```\n\n## Files\n\n- `SKILL.md` - Skill definition and documentation\n- `scripts/check_pypi_dates.py` - Main Python script\n- `scripts/update_pypi_dates.sh` - Bash wrapper with git integration\n- `README.md` - This file\n\n## Requirements\n\n- Python 3.6+\n- Network access to PyPI API\n- Git (for automatic commits)\n\n## Error Handling\n\n- Network timeouts: Gracefully skipped with warning\n- Package not found: Skipped with message\n- API errors: Logged and continued with other packages\n\n## Future Enhancements\n\n- [ ] Support for more PyPI packages\n- [ ] GitHub Actions workflow integration\n- [ ] Email notifications on updates\n- [ ] Comparison with published versions in README\n- [ ] Support for other package registries (npm, Ruby Gems, etc.)\n","CLAUDE.md":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\n**awesome-quant** is a curated list of quantitative finance libraries, packages, and resources. The primary content lives in `README.md` — a large markdown file **organized by category** (Numerical Libraries, Trading & Backtesting, Market Data, etc.) with inline language tags that identify which programming languages each project supports.\n\nA companion website is generated from this data and deployed to GitHub Pages.\n\n## Architecture\n\nThe pipeline works as follows:\n\n1. **`README.md`** — The source of truth. All library entries follow the format: `- [name](url) - \\`Language\\` - Description.`\n   - Entries are grouped under category headings (`##`), not language headings\n   - Language is identified via inline backtick tags (e.g., `` `Python` ``, `` `Rust` ``) in the description\n   - Multi-language projects have multiple tags (e.g., `` `Python` `Rust` ``)\n\n2. **`parse.py`** — Parses `README.md`, extracts language from backtick tags, fetches last commit dates and stars via the GitHub API (using `PyGithub` with multithreading), and writes `site/projects.csv` with a `languages` column (comma-separated).\n\n3. **`site/generate.py`** — Reads `site/projects.csv` (or parses `README.md` directly) and generates a static HTML site (`site/index.html`) with search, filtering by language/category/source, sorting, and dark mode. Front-end assets live in `site/static/` (`main.js`, `style.css`).\n\n4. **CI** (`.github/workflows/build.yml`, workflow name \"Update site\") — Runs daily (cron `0 1 * * *`) and on push to `main` touching `README.md`, `parse.py`, or `site/**`: runs `parse.py`, runs `site/generate.py`, and deploys the `site/` directory to GitHub Pages via `peaceiris/actions-gh-pages`.\n\nSupporting scripts:\n- `cranscrape.py` — Scrapes CRAN package pages to find associated GitHub repos; writes `cran.csv`.\n- `topic.py` — Searches GitHub for repos tagged with a topic (e.g., \"quant\") above a star threshold.\n- `scripts/migrate_readme.py` — One-off migration that converted `README.md` from language-first to category-first organization (kept for reference).\n\n## Commands\n\n```bash\n# Install dependencies (uses uv, requires Python 3.11+)\nuv sync --no-install-project\n\n# Run the parser (requires GITHUB_ACCESS_TOKEN env var)\nGITHUB_ACCESS_TOKEN=<token> uv run python parse.py\n\n# Generate the static site\nuv run python site/generate.py\n```\n\n## Contributing Entries\n\nSee `CONTRIBUTING.md` for full guidelines. All entries must include language tags:\n\n```\n- [Project Name](https://github.com/owner/repo) - `Python` - Description ending with a period.\n- [Project Name](https://github.com/owner/repo) - `Python` `Rust` - Multi-language project description.\n- [Project Name](https://site.com) - `Python` - Description ending with a period. [GitHub](https://github.com/owner/repo)\n- [Package Name](https://cran.r-project.org/package=pkg) - `R` - Description ending with a period.\n- [package-name](https://pypi.org/project/pkg/) - `Python` - Description ending with a period.\n```\n\nCRAN and PyPI entries may optionally append `[GitHub](url)` after the description.\n\nEntries are grouped under category headings (`##`), not language headings. Language is identified via inline backtick tags. Commercial/proprietary projects go under `## Commercial & Proprietary Services`.\n\n`parse.py` and `site/generate.py` rely on this regex to extract entries: `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`\n\nThe description text (group 3) may start with language tags in the format `` `Language1` `Language2` - `` followed by the actual description.\n\n## PR Reviews\n\nThis repo receives most contributions as pull requests adding new entries. Use the **GitHub MCP tools** (e.g. `list_pull_requests`, `pull_request_read`, `merge_pull_request`, `add_issue_comment`, `update_pull_request`), **not** the `gh` CLI, for PR operations.\n\nDedicated skills drive the review workflow:\n- `sprr` — Single PR reviewer: validate one PR's entry against the format rules.\n- `bprr` — Bulk PR reviewer: review all open PRs lacking the \"reviewed\" label, then present a summary for selection before merging.\n- `update-pypi-dates` — Refresh last-updated dates for PyPI entries in `README.md`.\n\nReview checklist: always ask before merging; verify section placement (commercial entries belong under \"Commercial & Proprietary Services\", not Market Data); check for duplicates in `README.md`; apply the \"reviewed\" label after commenting.\n\nSee `AGENTS.md` for the agent-facing command and tool summary, and `CONTRIBUTING.md` for contributor guidelines.\n",".claude/skills/update-pypi-dates/scripts/check_pypi_dates.py":"#!/usr/bin/env python3\n\"\"\"\nCheck PyPI projects for last updated dates and update README.md entries.\n\"\"\"\n\nimport json\nimport re\nimport subprocess\nimport sys\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Dict, Optional, Tuple\nfrom urllib.request import urlopen\n\n# PyPI projects to track\nPYPI_PROJECTS = {\n    \"qfrm\": \"qfrm\",\n    \"chinesestockapi\": \"chinesestockapi\",\n    \"tushare\": \"tushare\",\n    \"metatrader5\": \"MetaTrader5\",\n}\n\nREADME_PATH = Path(__file__).parent.parent.parent.parent.parent / \"README.md\"\n\n\ndef get_pypi_last_updated(package_name: str) -> Optional[str]:\n    \"\"\"\n    Fetch the last updated date for a PyPI package.\n\n    Returns: date string in format \"YYYY-MM-DD\" or None if not found\n    \"\"\"\n    try:\n        url = f\"https://pypi.org/pypi/{package_name}/json\"\n        with urlopen(url, timeout=5) as response:\n            data = json.loads(response.read().decode())\n\n        # Get releases (ordered dict, latest first after sorting)\n        releases = data.get(\"releases\", {})\n        if not releases:\n            return None\n\n        # Find the latest release with upload time\n        for version in sorted(releases.keys(), reverse=True):\n            release_data = releases[version]\n            if release_data and len(release_data) > 0:\n                upload_time = release_data[0].get(\"upload_time_iso_8601\")\n                if upload_time:\n                    # Extract just the date part (YYYY-MM-DD)\n                    return upload_time.split(\"T\")[0]\n\n        return None\n    except Exception as e:\n        print(f\"  ❌ Error fetching {package_name}: {e}\", file=sys.stderr)\n        return None\n\n\ndef find_readme_entry(readme_content: str, package_display_name: str) -> Tuple[Optional[int], Optional[str]]:\n    \"\"\"\n    Find a README entry for a package.\n\n    Returns: (line_number, match_text) or (None, None)\n    \"\"\"\n    # Pattern to match the entry - look for [package_name](pypi.org...)\n    pattern = rf\"\\- \\[{re.escape(package_display_name)}\\]\\(https://pypi\\.org/project/\\w+/\\)[^\\n]*\"\n\n    for line_num, line in enumerate(readme_content.split(\"\\n\"), 1):\n        if re.search(pattern, line):\n            return line_num, line.strip()\n\n    return None, None\n\n\ndef update_readme_entry(readme_content: str, package_display_name: str, new_date: str) -> Tuple[str, bool]:\n    \"\"\"\n    Update or add the last updated date to a README entry.\n\n    Returns: (updated_content, was_changed)\n    \"\"\"\n    lines = readme_content.split(\"\\n\")\n    line_num, entry_text = find_readme_entry(readme_content, package_display_name)\n\n    if line_num is None:\n        return readme_content, False\n\n    old_line = lines[line_num - 1]\n\n    # Check if entry already has a date\n    existing_date_pattern = r\"\\(Last updated: \\d{4}-\\d{2}-\\d{2}\\)\"\n    existing_match = re.search(existing_date_pattern, old_line)\n\n    if existing_match:\n        old_date = existing_match.group(0)\n        new_date_str = f\"(Last updated: {new_date})\"\n        if old_date == new_date_str:\n            return readme_content, False  # No change needed\n        new_line = old_line.replace(old_date, new_date_str)\n    else:\n        # Add date to the end of the entry (before period if present)\n        if old_line.endswith(\".\"):\n            new_line = old_line[:-1] + f\" (Last updated: {new_date}).\"\n        else:\n            new_line = old_line + f\" (Last updated: {new_date})\"\n\n    lines[line_num - 1] = new_line\n    return \"\\n\".join(lines), True\n\n\ndef main():\n    \"\"\"Check PyPI projects and update README.md.\"\"\"\n    if not README_PATH.exists():\n        print(f\"❌ README.md not found at {README_PATH}\")\n        sys.exit(1)\n\n    readme_content = README_PATH.read_text(encoding=\"utf-8\")\n    updated_content = readme_content\n    changes_made = []\n\n    print(\"📦 Checking PyPI projects for last updated dates...\\n\")\n\n    for display_name, pypi_name in PYPI_PROJECTS.items():\n        print(f\"Checking {display_name}...\")\n\n        last_updated = get_pypi_last_updated(pypi_name)\n        if last_updated is None:\n            print(f\"  ⚠️  Could not find last updated date\")\n            continue\n\n        updated_content, was_changed = update_readme_entry(\n            updated_content, display_name, last_updated\n        )\n\n        if was_changed:\n            print(f\"  ✅ Updated to {last_updated}\")\n            changes_made.append((display_name, last_updated))\n        else:\n            print(f\"  ✓ {last_updated} (no change)\")\n\n    print()\n\n    if changes_made:\n        print(f\"📝 Found {len(changes_made)} update(s):\")\n        for pkg_name, date in changes_made:\n            print(f\"  - {pkg_name}: {date}\")\n\n        README_PATH.write_text(updated_content, encoding=\"utf-8\")\n        print(f\"\\n✅ Updated {README_PATH.name}\")\n        return 0\n    else:\n        print(\"✓ All packages up to date!\")\n        return 0\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n","AGENTS.md":"# AGENTS.md\n\n## Project Overview\n\n`awesome-quant` is a curated list of quantitative finance libraries, packages,\nand resources. The source of truth is `README.md`; the static website is\ngenerated into `site/index.html`.\n\nThe README is organized by category headings (`##`), not by language headings.\nProject metadata is stored in inline backtick tags inside each entry. Tags commonly identify\nlanguages, but may also identify runtimes, protocols, interfaces, data types, or domains.\n\n## Architecture\n\n1. `README.md` contains curated entries.\n2. `parse.py` parses `README.md`, enriches GitHub/CRAN/PyPI metadata, and writes\n   `site/projects.csv`.\n3. `site/generate.py` reads `site/projects.csv` when present, otherwise parses\n   `README.md` directly for local previews, then writes `site/index.html`.\n4. `.github/workflows/build.yml` runs the parser and generator, then deploys\n   `site/` to GitHub Pages.\n\n## Work Tracking and Planning\n\n- Linear is the system of record for issues, prioritization, specifications,\n  designs, and implementation plans.\n- Manage GitHub-originated issues through their synced Linear issues. Do not\n  create a second internal tracker for the same work.\n- Store each specification, design, and implementation plan as a Linear\n  document attached to the corresponding Linear issue. Do not add task-specific\n  planning documents to the repository.\n- Keep repository documentation for durable project and user documentation only.\n- GitHub remains the public contribution surface for pull requests and public\n  issue discussion; use Linear for internal status, priority, and planning.\n\n## Commands\n\n```bash\n# Install deps (requires Python 3.11+)\nuv sync --no-install-project\n\n# Validate README entries changed in a PR\nuv run python scripts/validate_readme.py --diff-from origin/main\n\n# Validate the full README; legacy format/duplicate/URL issues are warnings by default\nuv run python scripts/validate_readme.py\n\n# Run parser (requires GitHub token)\nGITHUB_ACCESS_TOKEN=<token> uv run python parse.py\n\n# Generate static site\nuv run python site/generate.py\n```\n\n## Entry Format\n\nThe critical parser regex is:\n\n```text\n^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$\n```\n\nAccepted entry examples:\n\n```markdown\n- [Project Name](https://github.com/owner/repo) - `Python` - Description ending with a period.\n- [Project Name](https://github.com/owner/repo) - `Python` `Rust` - Description ending with a period.\n- [Project Name](https://site.com) - `Python` - Description ending with a period. [GitHub](https://github.com/owner/repo)\n- [Package Name](https://cran.r-project.org/package=pkg) - `R` - Description ending with a period.\n- [package-name](https://pypi.org/project/pkg/) - `Python` - Description ending with a period.\n```\n\nRules:\n\n- New non-commercial entries must include one or more concise backtick tags followed by ` - `.\n  Tags form a compact tag cloud and are not restricted to programming languages.\n- Each tag must use its own backtick pair, for example `` `Python` `C++` `MCP` ``.\n- Descriptions must end with a period before the optional `[GitHub](...)` link.\n- URLs in new entries must use `https://`.\n- A valid GitHub repository used as the main URL or exact `[GitHub](...)` suffix is preferred\n  and is a strong positive relevance signal, but it is not universally required. Functional\n  section placement requires a repository containing substantive implementation; a thin SDK,\n  integration, examples, generated-data, or marketing repository does not qualify.\n- Hosted commercial/proprietary products without substantive public source belong in\n  `## Commercial & Proprietary Services`, even when a thin repository exists. Repository-less\n  services qualify only under the permanent free tier and transparency rules in\n  `CONTRIBUTING.md`.\n- Treat a commercial service with only a thin SDK, integration, examples, generated-data, or\n  marketing repository as repository-less for every eligibility check.\n- Backtick tags are optional only for commercial services and other metadata-free\n  sections such as `Related Lists`.\n- `Historical & Archived Projects` is the documented exception to normal activity and\n  archive-state requirements. Entries still require substantive, reachable, documented source\n  and the `Historical` tag; use `CONTRIBUTING.md` for eligibility.\n- Use `CONTRIBUTING.md` as the user-facing source for contribution rules.\n\n## PR Review Workflow\n\nThis repo receives most contributions as pull requests adding README entries.\nUse Codex repo skills for repeatable review workflows:\n\n- `$sprr` - single PR reviewer.\n- `$bprr` - bulk PR reviewer.\n- `$update-pypi-dates` - refresh tracked PyPI last-updated dates.\n- `$create-entry` - draft or add README entries from a URL, GitHub issue, or Linear issue.\n\nReview requirements:\n\n1. Only review the PRs the user asked you to review.\n2. Use GitHub MCP tools for PR operations, not the `gh` CLI.\n3. Present findings before any PR-modifying action.\n4. Always ask the user before commenting, labeling, closing, or merging.\n5. Check section placement, duplicates in `README.md`, entry format, URL format,\n   and project activity/documentation. Give substantial positive weight to a verifiable\n   GitHub repository mentioned as either the main URL or exact suffix, while confirming that\n   functional-section repositories contain substantive implementation.\n6. Manually assess commercial entries for free-tier usefulness, payment information,\n   public pricing and limits, public documentation/methodology/examples, stable non-tracking\n   URLs, concise factual description tone, and repository substance.\n7. Commercial submissions without a qualifying permanent free tier—including paid-only,\n   trial-only, demo-only, and waitlist-only offerings—are `REJECT`. Reserve `NEEDS CHANGES` for\n   correctable evidence or disclosure, wording, URL, documentation, or placement defects when\n   the underlying offering can qualify.\n8. Use the `reviewed` label only after the user approves a review comment.\n\n## GitHub MCP Tools\n\nThis project expects Codex to have a GitHub MCP server configured for PR work.\nUseful tool capabilities include:\n\n- List open pull requests.\n- Get PR details, files, comments, labels, and diffs.\n- Fetch `README.md` from the default branch for duplicate checks.\n- Add PR comments and labels.\n- Merge pull requests after explicit user approval.\n\nSee `docs/codex-setup.md` for local Codex setup notes. If GitHub MCP tools are\nnot available in a session, report that PR operations are blocked and ask the\nuser to configure the MCP server.\n\n## Local Validation Notes\n\n- `scripts/validate_readme.py --diff-from <ref>` is intended for PR checks. It\n  validates only added README entries and treats duplicates/URL issues as errors\n  for those additions.\n- `scripts/validate_readme.py` validates the full README. Legacy format, duplicate, and\n  URL problems are reported as warnings unless strict flags are used.\n- `parse.py` requires `GITHUB_ACCESS_TOKEN`; `site/generate.py` can run without\n  the token if `site/projects.csv` already exists or if it falls back to direct\n  README parsing.\n",".claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh":"#!/bin/bash\n# Wrapper script to check PyPI dates and update README.md\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_ROOT=\"$(cd \"$SCRIPT_DIR/../../../../..\" && pwd)\"\n\ncd \"$PROJECT_ROOT\" || exit 1\n\necho \"🚀 Starting PyPI date update check...\"\npython3 \"$SCRIPT_DIR/check_pypi_dates.py\"\nexit_code=$?\n\nif [ $exit_code -eq 0 ]; then\n    # Check if there are any changes to commit\n    if git diff --quiet README.md; then\n        echo \"✓ No changes needed\"\n    else\n        echo \"\"\n        echo \"📝 Changes detected, committing...\"\n        git add README.md\n        git commit -m \"Update PyPI project last updated dates\"\n        git push origin main\n        echo \"✅ Changes pushed to remote\"\n    fi\nfi\n\nexit $exit_code\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/wilsonfreitas/awesome-quant/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# AGENTS.md\n\n## Project Overview\n\n`awesome-quant` is a curated list of quantitative finance libraries, packages,\nand resources. The source of truth is `README.md`; the static website is\ngenerated into `site/index.html`.\n\nThe README is organized by category headings (`##`), not by language headings.\nProject metadata is stored in inline backtick tags inside each entry. Tags commonly identify\nlanguages, but may also identify runtimes, protocols, interfaces, data types, or domains.\n\n## Architecture\n\n1. `README.md` contains curated entries.\n2. `parse.py` parses `README.md`, enriches GitHub/CRAN/PyPI metadata, and writes\n   `site/projects.csv`.\n3. `site/generate.py` reads `site/projects.csv` when present, otherwise parses\n   `README.md` directly for local previews, then writes `site/index.html`.\n4. `.github/workflows/build.yml` runs the parser and generator, then deploys\n   `site/` to GitHub Pages.\n\n## Work Tracking and Planning\n\n- Linear is the system of record for issues, prioritization, specifications,\n  designs, and implementation plans.\n- Manage GitHub-originated issues through their synced Linear issues. Do not\n  create a second internal tracker for the same work.\n- Store each specification, design, and implementation plan as a Linear\n  document attached to the corresponding Linear issue. Do not add task-specific\n  planning documents to the repository.\n- Keep repository documentation for durable project and user documentation only.\n- GitHub remains the public contribution surface for pull requests and public\n  issue discussion; use Linear for internal status, priority, and planning.\n\n## Commands\n\n```bash\n# Install deps (requires Python 3.11+)\nuv sync --no-install-project\n\n# Validate README entries changed in a PR\nuv run python scripts/validate_readme.py --diff-from origin/main\n\n# Validate the full README; legacy format/duplicate/URL issues are warnings by default\nuv run python scripts/validate_readme.py\n\n# Run parser (requires GitHub token)\nGITHUB_ACCESS_TOKEN=<token> uv run python parse.py\n\n# Generate static site\nuv run python site/generate.py\n```\n\n## Entry Format\n\nThe critical parser regex is:\n\n```text\n^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$\n```\n\nAccepted entry examples:\n\n```markdown\n- [Project Name](https://github.com/owner/repo) - `Python` - Description ending with a period.\n- [Project Name](https://github.com/owner/repo) - `Python` `Rust` - Description ending with a period.\n- [Project Name](https://site.com) - `Python` - Description ending with a period. [GitHub](https://github.com/owner/repo)\n- [Package Name](https://cran.r-project.org/package=pkg) - `R` - Description ending with a period.\n- [package-name](https://pypi.org/project/pkg/) - `Python` - Description ending with a period.\n```\n\nRules:\n\n- New non-commercial entries must include one or more concise backtick tags followed by ` - `.\n  Tags form a compact tag cloud and are not restricted to programming languages.\n- Each tag must use its own backtick pair, for example `` `Python` `C++` `MCP` ``.\n- Descriptions must end with a period before the optional `[GitHub](...)` link.\n- URLs in new entries must use `https://`.\n- A valid GitHub repository used as the main URL or exact `[GitHub](...)` suffix is preferred\n  and is a strong positive relevance signal, but it is not universally required. Functional\n  section placement requires a repository containing substantive implementation; a thin SDK,\n  integration, examples, generated-data, or marketing repository does not qualify.\n- Hosted commercial/proprietary products without substantive public source belong in\n  `## Commercial & Proprietary Services`, even when a thin repository exists. Repository-less\n  services qualify only under the permanent free tier and transparency rules in\n  `CONTRIBUTING.md`.\n- Treat a commercial service with only a thin SDK, integration, examples, generated-data, or\n  marketing repository as repository-less for every eligibility check.\n- Backtick tags are optional only for commercial services and other metadata-free\n  sections such as `Related Lists`.\n- `Historical & Archived Projects` is the documented exception to normal activity and\n  archive-state requirements. Entries still require substantive, reachable, documented source\n  and the `Historical` tag; use `CONTRIBUTING.md` for eligibility.\n- Use `CONTRIBUTING.md` as the user-facing source for contribution rules.\n\n## PR Review Workflow\n\nThis repo receives most contributions as pull requests adding README entries.\nUse Codex repo skills for repeatable review workflows:\n\n- `$sprr` - single PR reviewer.\n- `$bprr` - bulk PR reviewer.\n- `$update-pypi-dates` - refresh tracked PyPI last-updated dates.\n- `$create-entry` - draft or add README entries from a URL, GitHub issue, or Linear issue.\n\nReview requirements:\n\n1. Only review the PRs the user asked you to review.\n2. Use GitHub MCP tools for PR operations, not the `gh` CLI.\n3. Present findings before any PR-modifying action.\n4. Always ask the user before commenting, labeling, closing, or merging.\n5. Check section placement, duplicates in `README.md`, entry format, URL format,\n   and project activity/documentation. Give substantial positive weight to a verifiable\n   GitHub repository mentioned as either the main URL or exact suffix, while confirming that\n   functional-section repositories contain substantive implementation.\n6. Manually assess commercial entries for free-tier usefulness, payment information,\n   public pricing and limits, public documentation/methodology/examples, stable non-tracking\n   URLs, concise factual description tone, and repository substance.\n7. Commercial submissions without a qualifying permanent free tier—including paid-only,\n   trial-only, demo-only, and waitlist-only offerings—are `REJECT`. Reserve `NEEDS CHANGES` for\n   correctable evidence or disclosure, wording, URL, documentation, or placement defects when\n   the underlying offering can qualify.\n8. Use the `reviewed` label only after the user approves a review comment.\n\n## GitHub MCP Tools\n\nThis project expects Codex to have a GitHub MCP server configured for PR work.\nUseful tool capabilities include:\n\n- List open pull requests.\n- Get PR details, files, comments, labels, and diffs.\n- Fetch `README.md` from the default branch for duplicate checks.\n- Add PR comments and labels.\n- Merge pull requests after explicit user approval.\n\nSee `docs/codex-setup.md` for local Codex setup notes. If GitHub MCP tools are\nnot available in a session, report that PR operations are blocked and ask the\nuser to configure the MCP server.\n\n## Local Validation Notes\n\n- `scripts/validate_readme.py --diff-from <ref>` is intended for PR checks. It\n  validates only added README entries and treats duplicates/URL issues as errors\n  for those additions.\n- `scripts/validate_readme.py` validates the full README. Legacy format, duplicate, and\n  URL problems are reported as warnings unless strict flags are used.\n- `parse.py` requires `GITHUB_ACCESS_TOKEN`; `site/generate.py` can run without\n  the token if `site/projects.csv` already exists or if it falls back to direct\n  README parsing.\n","isInternal":false,"tokens":1553,"sizeBytes":7089},{"name":"SKILL.md","path":".agents/skills/bprr/SKILL.md","rawUrl":"https://raw.githubusercontent.com/wilsonfreitas/awesome-quant/HEAD/.agents/skills/bprr/SKILL.md","title":"bprr","category":"anthropic-skill","format":"markdown","content":"---\nname: bprr\ndescription: Bulk PR reviewer for awesome-quant. Use when the user asks to review all open PRs, review unreviewed PRs, bulk review, or mentions \"bprr\". Reviews open PRs lacking the reviewed label and presents a summary before any merge/comment/label action.\n---\n\n# BPRR: Bulk PR Reviewer\n\nReview multiple open pull requests for README entry contributions.\n\n**REQUIRED SUB-SKILL:** Use `sprr` as the canonical policy for reviewing each pull request. Read\nit before starting the bulk review and apply its hard rules, workflow evidence rules, validation\nchecklist, verdicts, output fields, and approved-action rules unless this skill defines a\nbulk-specific presentation step.\n\n## Hard Rules\n\n1. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels,\n   closing, or merging.\n2. Filter out PRs with the `reviewed` label unless the user asks to re-review them.\n3. Apply `sprr` independently to every PR. Shared retrieval may reduce repeated work, but evidence,\n   findings, and verdicts never carry from one PR to another.\n4. Do not comment, label, close, or merge until the user explicitly approves each action.\n5. Do not auto-merge all approved PRs unless the user explicitly selects that option.\n6. If GitHub MCP tools are unavailable, report the blocker and point to `docs/codex-setup.md`.\n\n## Bulk Workflow\n\n1. List open PRs sorted oldest first and filter to unreviewed PRs by default.\n2. Fetch the default-branch `README.md` once and reuse it where `sprr` requires a base-README\n   duplicate check.\n3. For every included PR, fetch the data and both required workflow attempts specified by `sprr`.\n4. Apply `sprr` independently to every PR, including its manual checks and cross-PR duplicate\n   search over open PRs and PRs closed within the last 365 days.\n5. Present the bulk summary below before asking the user to select any actions.\n\n## Summary Output\n\nPresent a table:\n\n```text\n| PR | Title | Author | Head | Validate PR | PR Review | Entries | Format/URL | Section | Duplicate | Verdict |\n|----|-------|--------|------|-------------|-----------|---------|------------|---------|-----------|---------|\n```\n\nFor each row, copy the workflow states, mechanical-check result, and verdict from that PR's `sprr`\nreview. `Section` remains a manual semantic judgment. In `Duplicate`, report both\n`README PASS|FAIL` and `PR SEARCH PASS|FAIL`.\n\nAfter the table, list any PRs that need detailed notes. Include failed workflow steps, reasons\nworkflow evidence was not accepted, manual findings, and commercial free-tier or transparency\nevidence when it affects the verdict.\n\nAsk what to do next. Accept selections such as:\n\n- `merge 123, 124`\n- `comment 125`\n- `close 126`\n- `all approved`\n- `none`\n\nApply `sprr`'s approved-action rules to each selected PR. Confirm every merge before executing it.\n","frontmatter":{"name":"bprr","description":"Bulk PR reviewer for awesome-quant. Use when the user asks to review all open PRs, review unreviewed PRs, bulk review, or mentions \"bprr\". Reviews open PRs lacking the reviewed label and presents a summary before any merge/comment/label action."},"isInternal":false,"tokens":661,"sizeBytes":2841},{"name":"SKILL.md","path":".agents/skills/sprr/SKILL.md","rawUrl":"https://raw.githubusercontent.com/wilsonfreitas/awesome-quant/HEAD/.agents/skills/sprr/SKILL.md","title":"sprr","category":"anthropic-skill","format":"markdown","content":"---\nname: sprr\ndescription: Single PR reviewer for awesome-quant. Use when the user asks to review, validate, comment on, label, close, or merge one specific pull request that adds README.md entries. Triggers include \"sprr\", \"review PR\", \"check PR\", and \"validate contribution\".\n---\n\n# SPRR: Single PR Reviewer\n\nReview one pull request that adds entries to `README.md`.\n\n## Hard Rules\n\n1. Review only the PR number the user requested. If no PR number is given, ask for one.\n2. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n3. Do not modify the PR until the user explicitly approves that action.\n4. Always present findings before asking whether to comment, label, close, or merge.\n5. Always ask before merging.\n6. Enforce `CONTRIBUTING.md` and `AGENTS.md` strictly for new entries, using the\n   sentence-count interpretation in the Validation Checklist below.\n7. Both `Validate PR` and `PR Review` must pass before returning `APPROVE`.\n\nIf GitHub MCP tools are unavailable, report that PR operations are blocked and point the user to `docs/codex-setup.md`.\n\n## Workflow\n\n1. Fetch PR details, current head SHA, files changed, labels, comments, and diff with GitHub MCP.\n2. Confirm whether the `reviewed` label or prior maintainer comments exist, then proceed with full validation anyway.\n3. Fetch the latest `Validate PR` workflow/check attempt for the current head SHA and apply the CI evidence rules below.\n4. Fetch the latest `PR Review` workflow/check attempt associated with the pull request and apply\n   the required workflow rules below.\n5. Focus on added lines in `README.md`. Flag any other changed files as unusual for a normal contribution.\n6. When mechanical validation is not established by current-head CI, save or reconstruct the PR diff locally only if needed, then validate added README entries with:\n\n```bash\nuv run python scripts/validate_readme.py --diff-from <base-ref>\n```\n\nIf a base ref is not locally available, apply the same checks manually from the fetched diff.\n\n## CI Evidence Rules\n\nUse only the latest attempt whose commit SHA exactly matches the PR's current head SHA. A newer\nqueued or pending attempt supersedes an older successful attempt for the same SHA.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not rerun those mechanical checks. |\n| `failure` | Inspect the failing job or step. Return `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Report the review as incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Report the review as incomplete and do not return `APPROVE`; reproduce mechanical validation only to provide useful findings. |\n| success on an older SHA | Report the result as stale and do not return `APPROVE`; require a successful attempt for the current SHA. |\n\nCI never replaces inspection of the diff or the manual checks below. A successful check confirms\nonly mechanical rules; it does not establish tag meaning or concision, description quality,\nrelevance, semantic section suitability, commercial classification, repository quality,\ncommercial free-tier eligibility or transparency, URL tracking, cross-PR uniqueness, or\nmulti-project relatedness. CI cannot establish any of these manual criteria. Search open PRs and PRs\nclosed within the last 365 days for duplicate names and URLs.\n\n`PR Review` runs on `pull_request_target`, so use the latest attempt associated with the pull\nrequest without applying the current-head SHA rule used for `Validate PR`. A successful attempt is\nrequired but does not prove that current-head mechanical validation passed. If the latest attempt\nfails, inspect its failing job or step. Return `NEEDS CHANGES` when the review reports a PR defect;\notherwise report the review as incomplete. If it is queued, pending, cancelled, skipped, or\nmissing, report the review as incomplete and do not return `APPROVE`.\n\n## Validation Checklist\n\nFor every added entry:\n\n- It matches `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`.\n- New non-commercial entries include one or more backtick tags followed by ` - `. Treat these\n  as a compact tag cloud: accept concise languages, runtimes, protocols, interfaces, data\n  types, and domain terms.\n- Separate concepts use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not reject a tag\n  merely because it is not a programming language.\n- Description ends with a period before optional `[GitHub](...)`.\n- Treat `CONTRIBUTING.md`'s \"one sentence\" wording as concision guidance, not a sentence-count\n  gate. Accept two or more short sentences when the overall description remains concise, factual,\n  relevant, and non-promotional. Never return `NEEDS CHANGES` solely because of sentence count;\n  request wording changes only for actual quality problems such as verbosity, repetition,\n  unsupported claims, promotional language, or poor readability.\n- URLs use `https://`.\n- Optional GitHub link uses `[GitHub](https://github.com/owner/repo)`.\n- Section placement matches the project's purpose.\n- Distinguish repositories containing substantive implementation from thin SDK, integration,\n  examples, generated-data, or marketing repositories.\n- Hosted proprietary products without substantive public source are under\n  `Commercial & Proprietary Services`, even when a thin repository exists.\n- For repository-less commercial entries, verify a useful permanent free tier for quantitative\n  finance that requires no payment information and is not a trial, demo, or waitlist.\n- Treat a commercial service with only a thin SDK, integration, examples, generated-data, or\n  marketing repository as repository-less for every eligibility check.\n- Verify that these commercial entries publish pricing and free-tier limits plus public\n  documentation, methodology, or usage examples; use a stable HTTPS URL without affiliate or\n  tracking parameters; and have a concise, factual, non-promotional description.\n- Project name and URLs are not duplicates of existing README entries.\n- A verifiable GitHub repository containing substantive implementation, mentioned as the main URL\n  or exact `[GitHub](...)` suffix, is a strong positive relevance signal. Repository existence\n  alone does not establish commercial eligibility or functional-section placement.\n- GitHub projects are checked for source availability, activity, archived status,\n  documentation, and community evidence. GitHub relevance does not waive duplicate, format,\n  or quality checks.\n- Multiple projects in one PR are closely related and explained in the PR body.\n\n## Repository Substance and Linked Services\n\nFor every added entry with a repository, investigate what the public source actually provides:\n\n1. Inspect representative implementation files behind the advertised functionality. A README,\n   license, tests, file count, or stars alone do not establish substance.\n2. Trace whether core functionality is implemented publicly or depends on a proprietary service.\n   Identify code that only calls a vendor API, integrates a service, downloads generated output,\n   or provides examples or marketing. External dependencies alone do not make a project thin;\n   assess where the advertised functionality is implemented.\n3. Follow linked service websites, public documentation, and pricing/free-tier pages. Establish\n   the repository's relationship to the service and verify eligibility under `CONTRIBUTING.md`,\n   including useful permanent free access without payment information.\n4. Report concrete evidence: representative source-file links, API dependencies, and relevant\n   service/pricing/documentation links. State unavailable or inconclusive evidence explicitly.\n   Small size, few stars, or recent creation alone do not imply poor quality or commercial status.\n\nWhen a repository mainly supports a qualifying commercial service, place the entry in\n`Commercial & Proprietary Services`. Use the service name and stable service website as the main\nlink, and retain the repository only as the exact `[GitHub](...)` suffix:\n\n```markdown\n- [Service Name](https://service.example) - Factual service description with relevant free-tier limits. [GitHub](https://github.com/owner/client)\n```\n\nDescribe the service, not merely its SDK. An open-source client license does not make the hosted\nservice open source. Substantive public implementation can qualify for a functional section even\nwhen its maintainers also sell a hosted service.\n\n- Qualifying service with incorrect placement or a thin repository as its main link:\n  `NEEDS CHANGES`, with a proposed corrected README entry.\n- Confirmed paid-only, trial-only, demo-only, waitlist-only, or otherwise non-qualifying free\n  access: `REJECT`; moving the entry does not fix eligibility.\n- Insufficient evidence of repository substance or service eligibility: `NEEDS CHANGES`, naming\n  the missing evidence without claiming that the service qualifies.\n\n## Verdicts\n\nUse these verdicts:\n\n- `APPROVE`: both required workflows pass and the entry is ready to merge after manual review.\n- Sentence count alone does not affect the verdict; evaluate description quality using the criteria\n  in the Validation Checklist.\n- Commercial submissions without a qualifying permanent free tier—including paid-only,\n  trial-only, demo-only, and waitlist-only offerings—are `REJECT`.\n- Reserve `NEEDS CHANGES` for correctable evidence or disclosure, wording, URL, documentation, or\n  placement defects when the underlying offering can qualify.\n- Other `REJECT` cases include duplicates, unrelated multi-project PRs, empty PR descriptions,\n  archived or abandoned projects, and other hard rejections.\n\n## Output Shape\n\nReport:\n\n```text\nPR #<number>: <title>\nAuthor: <author>\nPrior review: YES/NO\nFiles changed: <files>\nEntries reviewed: <count>\n\nAutomated validation:\n- Validate PR: PASS | FAIL | PENDING | UNVERIFIED\n- PR Review: PASS | FAIL | PENDING | UNVERIFIED\n- Commit: <checked-sha> (CURRENT | STALE)\n- Mechanical checks: accepted from CI | reproduced manually | incomplete\n\nFindings:\n- <entry>: <status and reason>\n\nVerdict: APPROVE | NEEDS CHANGES | REJECT\nRecommended action: <merge/comment/close/no action>\n```\n\nThen ask for explicit approval before doing the recommended action.\n\n## Approved Actions After User Consent\n\n- If approved and user says to merge: merge with squash unless user requests otherwise.\n- If needs changes and user says to comment: leave one concise comment with all requested fixes, then add `reviewed` if available.\n- If rejected and user says to close: leave a polite rejection comment and close the PR.\n","frontmatter":{"name":"sprr","description":"Single PR reviewer for awesome-quant. Use when the user asks to review, validate, comment on, label, close, or merge one specific pull request that adds README.md entries. Triggers include \"sprr\", \"review PR\", \"check PR\", and \"validate contribution\"."},"isInternal":false,"tokens":2259,"sizeBytes":10852},{"name":"SKILL.md","path":".agents/skills/update-pypi-dates/SKILL.md","rawUrl":"https://raw.githubusercontent.com/wilsonfreitas/awesome-quant/HEAD/.agents/skills/update-pypi-dates/SKILL.md","title":"update-pypi-dates","category":"anthropic-skill","format":"markdown","content":"---\nname: update-pypi-dates\ndescription: Refresh tracked PyPI last-updated dates in awesome-quant README.md. Use when the user asks to update PyPI dates, refresh PyPI metadata, or run update-pypi-dates.\n---\n\n# Update PyPI Dates\n\nRefresh last release dates for selected PyPI packages listed in `README.md`.\n\n## Workflow\n\n1. Run the checker:\n\n```bash\nuv run python .agents/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n2. Show the user which packages changed.\n3. Run README validation:\n\n```bash\nuv run python scripts/validate_readme.py\n```\n\n4. If the user asked for a commit, stage only the relevant files and commit.\n5. Do not push unless the user explicitly asks.\n\n## Tracked Packages\n\nThe script currently tracks:\n\n- `qfrm`\n- `chinesestockapi`\n- `tushare`\n- `metatrader5` / `MetaTrader5`\n\nTo add packages, edit `PYPI_PROJECTS` in `scripts/check_pypi_dates.py`.\n","frontmatter":{"name":"update-pypi-dates","description":"Refresh tracked PyPI last-updated dates in awesome-quant README.md. Use when the user asks to update PyPI dates, refresh PyPI metadata, or run update-pypi-dates."},"isInternal":false,"tokens":226,"sizeBytes":874},{"name":"SKILL.md","path":".claude/skills/bprr/SKILL.md","rawUrl":"https://raw.githubusercontent.com/wilsonfreitas/awesome-quant/HEAD/.claude/skills/bprr/SKILL.md","title":"bprr","category":"anthropic-skill","format":"markdown","content":"---\nname: bprr\ndescription: Bulk PR reviewer for awesome-quant. Use when the user asks to review all open PRs, review unreviewed PRs, bulk review, or mentions \"bprr\". Reviews open PRs lacking the reviewed label and presents a summary before any merge/comment/label action.\n---\n\n# BPRR: Bulk PR Reviewer\n\nReview multiple open pull requests for README entry contributions.\n\n## Hard Rules\n\n1. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n2. Filter out PRs with the `reviewed` label unless the user asks to re-review them.\n3. Do not comment, label, close, or merge until the user explicitly approves each action.\n4. Do not auto-merge all approved PRs unless the user explicitly selects that option.\n5. If GitHub MCP tools are unavailable, report the blocker and point to `docs/codex-setup.md`.\n\n## Workflow\n\n1. List open PRs sorted oldest first.\n2. Filter to unreviewed PRs by default.\n3. Fetch the default-branch `README.md` once for duplicate checks.\n4. For each PR, fetch details, current head SHA, labels, files, body, diff, and the latest `Validate PR` workflow/check attempt for that SHA.\n5. Review only added `README.md` entries unless the PR changes other files; flag other file changes as unusual.\n6. Apply the CI evidence rules below, then perform the remaining `$sprr` checks. Use `scripts/validate_readme.py --diff-from <base-ref>` only when current-head CI does not establish mechanical validity and the PR branch is available locally; otherwise apply the validator's rules manually from the MCP diff.\n\n## CI Evidence Rules\n\nEvaluate each PR independently. Use only the latest attempt for the current head SHA; a newer\nqueued or pending attempt supersedes an older success for that SHA. A result for one PR or\ncommit never applies to another.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not repeat those mechanical checks. |\n| `failure` | Inspect the failing job or step. Use `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Mark the review incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Treat mechanical validation as unverified and reproduce it before deciding. |\n| success only on an older SHA | Report `STALE`, ignore it, and reproduce mechanical validation for the current head SHA. |\n\nFor every PR, still inspect the diff and manually review tag meaning and concision, description\nquality, relevance, semantic section suitability, commercial classification, repository\nactivity/archive/documentation/community evidence, duplicates in open PRs and PRs closed\nwithin the last 365 days, and multi-project relatedness.\n\n## Validation Checklist\n\nFor each added entry, check:\n\n- Parser regex match.\n- Required backtick tags for new non-commercial entries. Treat them as a compact tag cloud:\n  accept concise languages, runtimes, protocols, interfaces, data types, and domain terms.\n- Separate concepts must use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not require\n  every tag to be a programming language.\n- Description period before optional `[GitHub](...)`.\n- `https://` URLs.\n- Exact optional `[GitHub](https://github.com/owner/repo)` format.\n- Correct category section.\n- Commercial placement under `Commercial & Proprietary Services`.\n- Duplicate project names or URLs.\n- Treat any verifiable GitHub repository mentioned as the main URL or exact `[GitHub](...)`\n  suffix as a strong positive relevance signal.\n- For GitHub repos, check source availability, activity, archived status, documentation, and\n  community evidence. GitHub relevance does not waive duplicate, format, or quality checks.\n- Clear rationale for multiple related projects in one PR.\n\n## Summary Output\n\nPresent a table:\n\n```text\n| PR | Title | Author | Head | Validate PR | Entries | Format/URL | Section | Duplicate | Verdict |\n|----|-------|--------|------|-------------|---------|------------|---------|-----------|---------|\n```\n\nUse the entry count in `Entries`. Use `PASS`, `FAIL`, `PENDING`, `UNVERIFIED`, or\n`STALE` in `Validate PR`. Use `CI PASS`, `CI FAIL`, `REPRODUCED PASS`,\n`REPRODUCED FAIL`, or `INCOMPLETE` in `Format/URL`. `Section` remains a manual\nsemantic judgment. In `Duplicate`, report both `README PASS|FAIL` and\n`PR SEARCH PASS|FAIL`.\n\nAfter the table, list any PRs that need detailed notes, including the failing workflow step or the reason CI evidence was not accepted.\n\nAsk what to do next. Accept selections like:\n\n- `merge 123, 124`\n- `comment 125`\n- `close 126`\n- `all approved`\n- `none`\n\nConfirm each merge before executing it.\n","frontmatter":{"name":"bprr","description":"Bulk PR reviewer for awesome-quant. Use when the user asks to review all open PRs, review unreviewed PRs, bulk review, or mentions \"bprr\". Reviews open PRs lacking the reviewed label and presents a summary before any merge/comment/label action."},"isInternal":false,"tokens":1104,"sizeBytes":4871},{"name":"SKILL.md","path":".claude/skills/sprr/SKILL.md","rawUrl":"https://raw.githubusercontent.com/wilsonfreitas/awesome-quant/HEAD/.claude/skills/sprr/SKILL.md","title":"sprr","category":"anthropic-skill","format":"markdown","content":"---\nname: sprr\ndescription: Single PR reviewer for awesome-quant. Use when the user asks to review, validate, comment on, label, close, or merge one specific pull request that adds README.md entries. Triggers include \"sprr\", \"review PR\", \"check PR\", and \"validate contribution\".\n---\n\n# SPRR: Single PR Reviewer\n\nReview one pull request that adds entries to `README.md`.\n\n## Hard Rules\n\n1. Review only the PR number the user requested. If no PR number is given, ask for one.\n2. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n3. Do not modify the PR until the user explicitly approves that action.\n4. Always present findings before asking whether to comment, label, close, or merge.\n5. Always ask before merging.\n6. Enforce `CONTRIBUTING.md` and `AGENTS.md` strictly for new entries.\n\nIf GitHub MCP tools are unavailable, report that PR operations are blocked and point the user to `docs/codex-setup.md`.\n\n## Workflow\n\n1. Fetch PR details, current head SHA, files changed, labels, comments, and diff with GitHub MCP.\n2. Confirm whether the `reviewed` label or prior maintainer comments exist, then proceed with full validation anyway.\n3. Fetch the latest `Validate PR` workflow/check attempt for the current head SHA and apply the CI evidence rules below.\n4. Focus on added lines in `README.md`. Flag any other changed files as unusual for a normal contribution.\n5. When mechanical validation is not established by current-head CI, save or reconstruct the PR diff locally only if needed, then validate added README entries with:\n\n```bash\nuv run python scripts/validate_readme.py --diff-from <base-ref>\n```\n\nIf a base ref is not locally available, apply the same checks manually from the fetched diff.\n\n## CI Evidence Rules\n\nUse only the latest attempt whose commit SHA exactly matches the PR's current head SHA. A newer\nqueued or pending attempt supersedes an older successful attempt for the same SHA.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not rerun those mechanical checks. |\n| `failure` | Inspect the failing job or step. Return `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Report the review as incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Treat mechanical validation as unverified and reproduce it before deciding. |\n| success on an older SHA | Ignore it and evaluate the current SHA using these rules. |\n\nCI never replaces inspection of the diff or the manual checks below. A successful check confirms\nonly mechanical rules; it does not establish tag meaning or concision, description quality,\nrelevance, semantic section suitability, commercial classification, repository quality,\ncross-PR uniqueness, or multi-project relatedness. Search open PRs and PRs closed within the\nlast 365 days for duplicate names and URLs.\n\nFor repository substance and linked commercial services, apply the **Repository Substance and\nLinked Services** investigation in `.agents/skills/sprr/SKILL.md`, including its evidence,\nservice-first link, and eligibility verdict rules.\n\n## Validation Checklist\n\nFor every added entry:\n\n- It matches `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`.\n- New non-commercial entries include one or more backtick tags followed by ` - `. Treat these\n  as a compact tag cloud: accept concise languages, runtimes, protocols, interfaces, data\n  types, and domain terms.\n- Separate concepts use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not reject a tag\n  merely because it is not a programming language.\n- Description ends with a period before optional `[GitHub](...)`.\n- URLs use `https://`.\n- Optional GitHub link uses `[GitHub](https://github.com/owner/repo)`.\n- Section placement matches the project's purpose.\n- Commercial/proprietary projects are under `Commercial & Proprietary Services`.\n- Project name and URLs are not duplicates of existing README entries.\n- A verifiable GitHub repository containing substantive implementation, mentioned as the main URL\n  or exact `[GitHub](...)` suffix, is a strong positive relevance signal.\n- GitHub projects are checked for source availability, activity, archived status,\n  documentation, and community evidence. GitHub relevance does not waive duplicate, format,\n  or quality checks.\n- Multiple projects in one PR are closely related and explained in the PR body.\n\n## Verdicts\n\nUse these verdicts:\n\n- `APPROVE`: entry is ready to merge.\n- `NEEDS CHANGES`: fixable format, section, URL, description, or documentation issue.\n- `REJECT`: duplicate, unrelated multi-project PR, empty PR description, archived/abandoned project, or other hard rejection.\n\n## Output Shape\n\nReport:\n\n```text\nPR #<number>: <title>\nAuthor: <author>\nPrior review: YES/NO\nFiles changed: <files>\nEntries reviewed: <count>\n\nAutomated validation:\n- Validate PR: PASS | FAIL | PENDING | UNVERIFIED\n- Commit: <checked-sha> (CURRENT | STALE)\n- Mechanical checks: accepted from CI | reproduced manually | incomplete\n\nFindings:\n- <entry>: <status and reason>\n\nVerdict: APPROVE | NEEDS CHANGES | REJECT\nRecommended action: <merge/comment/close/no action>\n```\n\nThen ask for explicit approval before doing the recommended action.\n\n## Approved Actions After User Consent\n\n- If approved and user says to merge: merge with squash unless user requests otherwise.\n- If needs changes and user says to comment: leave one concise comment with all requested fixes, then add `reviewed` if available.\n- If rejected and user says to close: leave a polite rejection comment and close the PR.\n","frontmatter":{"name":"sprr","description":"Single PR reviewer for awesome-quant. Use when the user asks to review, validate, comment on, label, close, or merge one specific pull request that adds README.md entries. Triggers include \"sprr\", \"review PR\", \"check PR\", and \"validate contribution\"."},"isInternal":false,"tokens":1279,"sizeBytes":5823},{"name":"README.md","path":".claude/skills/update-pypi-dates/README.md","rawUrl":"https://raw.githubusercontent.com/wilsonfreitas/awesome-quant/HEAD/.claude/skills/update-pypi-dates/README.md","title":"Update-pypi-dates Skill","category":"anthropic-skill","format":"markdown","content":"# Update PyPI Dates Skill\n\nAutomatically check PyPI projects for their latest update dates and keep README.md entries current.\n\n## Overview\n\nThis skill monitors Python packages listed in awesome-quant and updates their entries with the latest release dates from PyPI. This ensures that outdated project information is easily identifiable.\n\n## Features\n\n- ✅ Checks 4 PyPI projects: qfrm, chinesestockapi, tushare, metatrader5\n- ✅ Fetches latest release dates from PyPI API\n- ✅ Updates README.md entries with `(Last updated: YYYY-MM-DD)` format\n- ✅ Commits changes automatically when updates found\n- ✅ No dependencies beyond Python standard library\n\n## Usage\n\n### Invoke from Claude Code\n\n```bash\n/update-pypi-dates\n```\n\nOr call the script directly:\n\n```bash\n./.claude/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n### Manual Python Execution\n\n```bash\npython3 .claude/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n### Bash Wrapper\n\n```bash\n./.claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh\n```\n\n## How It Works\n\n1. **Queries PyPI API** for each tracked package\n2. **Extracts last release date** from the releases data\n3. **Updates README.md** entries with format: `(Last updated: 2024-08-27)`\n4. **Commits changes** if any updates were found\n\n## Adding New Packages\n\nTo track additional PyPI packages, edit the `PYPI_PROJECTS` dictionary in `scripts/check_pypi_dates.py`:\n\n```python\nPYPI_PROJECTS = {\n    \"display_name\": \"pypi_package_name\",\n    # Add new entries here\n}\n```\n\nThen update the skill description if needed.\n\n## Output Examples\n\n### No Changes\n```\n📦 Checking PyPI projects for last updated dates...\n\nChecking qfrm...\n  ✓ 2015-12-12 (no change)\n\n✓ All packages up to date!\n```\n\n### With Updates\n```\n📦 Checking PyPI projects for last updated dates...\n\nChecking tushare...\n  ✓ 2024-08-27 (no change)\nChecking metatrader5...\n  ✅ Updated to 2026-02-20\n\n📝 Found 1 update(s):\n  - metatrader5: 2026-02-20\n\n✅ Updated README.md\n```\n\n## Configuration\n\n### Periodic Execution\n\nSet up a cron job to run weekly:\n\n```bash\n# Add to crontab (runs Monday at 2 AM)\n0 2 * * 1 cd /path/to/awesome-quant && ./.claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh\n```\n\nOr use Claude Code's scheduling:\n\n```bash\n/loop 1w /update-pypi-dates\n```\n\n## Files\n\n- `SKILL.md` - Skill definition and documentation\n- `scripts/check_pypi_dates.py` - Main Python script\n- `scripts/update_pypi_dates.sh` - Bash wrapper with git integration\n- `README.md` - This file\n\n## Requirements\n\n- Python 3.6+\n- Network access to PyPI API\n- Git (for automatic commits)\n\n## Error Handling\n\n- Network timeouts: Gracefully skipped with warning\n- Package not found: Skipped with message\n- API errors: Logged and continued with other packages\n\n## Future Enhancements\n\n- [ ] Support for more PyPI packages\n- [ ] GitHub Actions workflow integration\n- [ ] Email notifications on updates\n- [ ] Comparison with published versions in README\n- [ ] Support for other package registries (npm, Ruby Gems, etc.)\n","isInternal":false,"tokens":788,"sizeBytes":3033},{"name":"SKILL.md","path":".claude/skills/update-pypi-dates/SKILL.md","rawUrl":"https://raw.githubusercontent.com/wilsonfreitas/awesome-quant/HEAD/.claude/skills/update-pypi-dates/SKILL.md","title":"update-pypi-dates","category":"anthropic-skill","format":"markdown","content":"---\nname: update-pypi-dates\ndescription: Check PyPI projects for last updated dates and update README.md entries. Use this skill to keep PyPI project information current with latest release dates from PyPI. Run periodically to maintain up-to-date metadata on Python packages listed in awesome-quant.\n---\n\n# Update PyPI Dates\n\nAutomatically check PyPI projects for their latest update dates and update corresponding README.md entries with the \"(Last updated: YYYY-MM-DD)\" information.\n\n## How it works\n\nThe skill maintains a list of PyPI projects in awesome-quant and:\n1. Queries the PyPI JSON API for each package\n2. Extracts the last release date\n3. Updates README.md entries with the new date if changed\n4. Commits changes to git if updates were made\n\n## PyPI Projects to Track\n\nCurrent projects tracked:\n- qfrm\n- chinesestockapi\n- tushare\n- metatrader5\n\n## Steps\n\n### 1. Fetch PyPI data for each project\n\nFor each PyPI project, query: `https://pypi.org/pypi/{package_name}/json`\n\nExtract the last release date from the releases data.\n\n### 2. Update README.md entries\n\nFor each project with a new date:\n- Find the entry in README.md\n- Update or add the \"(Last updated: YYYY-MM-DD)\" note\n- Use the exact entry format: `(Last updated: 2024-08-27)`\n\n### 3. Verify changes\n\nShow the user:\n- Which packages were checked\n- Which packages have new update dates\n- The differences (old date → new date)\n\n### 4. Commit if changes detected\n\nIf any updates were made:\n```bash\ngit add README.md non-github-urls.md\ngit commit -m \"Update PyPI project last updated dates\"\ngit push origin main\n```\n\n## Usage\n\nThe user can:\n- Run the skill directly: `/update-pypi-dates`\n- Schedule it to run weekly/monthly via cron\n- Include it in CI/CD pipelines to keep data fresh\n\n## Script\n\nUse `scripts/check_pypi_dates.sh` for the core update logic.\n","frontmatter":{"name":"update-pypi-dates","description":"Check PyPI projects for last updated dates and update README.md entries. Use this skill to keep PyPI project information current with latest release dates from PyPI. Run periodically to maintain up-to-date metadata on Python packages listed in awesome-quant."},"isInternal":false,"tokens":448,"sizeBytes":1826},{"name":"check_pypi_dates.py","path":".claude/skills/update-pypi-dates/scripts/check_pypi_dates.py","rawUrl":"https://raw.githubusercontent.com/wilsonfreitas/awesome-quant/HEAD/.claude/skills/update-pypi-dates/scripts/check_pypi_dates.py","title":"Claude Directive: check_pypi_dates.py","category":"claude-rule","format":"markdown","content":"#!/usr/bin/env python3\n\"\"\"\nCheck PyPI projects for last updated dates and update README.md entries.\n\"\"\"\n\nimport json\nimport re\nimport subprocess\nimport sys\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Dict, Optional, Tuple\nfrom urllib.request import urlopen\n\n# PyPI projects to track\nPYPI_PROJECTS = {\n    \"qfrm\": \"qfrm\",\n    \"chinesestockapi\": \"chinesestockapi\",\n    \"tushare\": \"tushare\",\n    \"metatrader5\": \"MetaTrader5\",\n}\n\nREADME_PATH = Path(__file__).parent.parent.parent.parent.parent / \"README.md\"\n\n\ndef get_pypi_last_updated(package_name: str) -> Optional[str]:\n    \"\"\"\n    Fetch the last updated date for a PyPI package.\n\n    Returns: date string in format \"YYYY-MM-DD\" or None if not found\n    \"\"\"\n    try:\n        url = f\"https://pypi.org/pypi/{package_name}/json\"\n        with urlopen(url, timeout=5) as response:\n            data = json.loads(response.read().decode())\n\n        # Get releases (ordered dict, latest first after sorting)\n        releases = data.get(\"releases\", {})\n        if not releases:\n            return None\n\n        # Find the latest release with upload time\n        for version in sorted(releases.keys(), reverse=True):\n            release_data = releases[version]\n            if release_data and len(release_data) > 0:\n                upload_time = release_data[0].get(\"upload_time_iso_8601\")\n                if upload_time:\n                    # Extract just the date part (YYYY-MM-DD)\n                    return upload_time.split(\"T\")[0]\n\n        return None\n    except Exception as e:\n        print(f\"  ❌ Error fetching {package_name}: {e}\", file=sys.stderr)\n        return None\n\n\ndef find_readme_entry(readme_content: str, package_display_name: str) -> Tuple[Optional[int], Optional[str]]:\n    \"\"\"\n    Find a README entry for a package.\n\n    Returns: (line_number, match_text) or (None, None)\n    \"\"\"\n    # Pattern to match the entry - look for [package_name](pypi.org...)\n    pattern = rf\"\\- \\[{re.escape(package_display_name)}\\]\\(https://pypi\\.org/project/\\w+/\\)[^\\n]*\"\n\n    for line_num, line in enumerate(readme_content.split(\"\\n\"), 1):\n        if re.search(pattern, line):\n            return line_num, line.strip()\n\n    return None, None\n\n\ndef update_readme_entry(readme_content: str, package_display_name: str, new_date: str) -> Tuple[str, bool]:\n    \"\"\"\n    Update or add the last updated date to a README entry.\n\n    Returns: (updated_content, was_changed)\n    \"\"\"\n    lines = readme_content.split(\"\\n\")\n    line_num, entry_text = find_readme_entry(readme_content, package_display_name)\n\n    if line_num is None:\n        return readme_content, False\n\n    old_line = lines[line_num - 1]\n\n    # Check if entry already has a date\n    existing_date_pattern = r\"\\(Last updated: \\d{4}-\\d{2}-\\d{2}\\)\"\n    existing_match = re.search(existing_date_pattern, old_line)\n\n    if existing_match:\n        old_date = existing_match.group(0)\n        new_date_str = f\"(Last updated: {new_date})\"\n        if old_date == new_date_str:\n            return readme_content, False  # No change needed\n        new_line = old_line.replace(old_date, new_date_str)\n    else:\n        # Add date to the end of the entry (before period if present)\n        if old_line.endswith(\".\"):\n            new_line = old_line[:-1] + f\" (Last updated: {new_date}).\"\n        else:\n            new_line = old_line + f\" (Last updated: {new_date})\"\n\n    lines[line_num - 1] = new_line\n    return \"\\n\".join(lines), True\n\n\ndef main():\n    \"\"\"Check PyPI projects and update README.md.\"\"\"\n    if not README_PATH.exists():\n        print(f\"❌ README.md not found at {README_PATH}\")\n        sys.exit(1)\n\n    readme_content = README_PATH.read_text(encoding=\"utf-8\")\n    updated_content = readme_content\n    changes_made = []\n\n    print(\"📦 Checking PyPI projects for last updated dates...\\n\")\n\n    for display_name, pypi_name in PYPI_PROJECTS.items():\n        print(f\"Checking {display_name}...\")\n\n        last_updated = get_pypi_last_updated(pypi_name)\n        if last_updated is None:\n            print(f\"  ⚠️  Could not find last updated date\")\n            continue\n\n        updated_content, was_changed = update_readme_entry(\n            updated_content, display_name, last_updated\n        )\n\n        if was_changed:\n            print(f\"  ✅ Updated to {last_updated}\")\n            changes_made.append((display_name, last_updated))\n        else:\n            print(f\"  ✓ {last_updated} (no change)\")\n\n    print()\n\n    if changes_made:\n        print(f\"📝 Found {len(changes_made)} update(s):\")\n        for pkg_name, date in changes_made:\n            print(f\"  - {pkg_name}: {date}\")\n\n        README_PATH.write_text(updated_content, encoding=\"utf-8\")\n        print(f\"\\n✅ Updated {README_PATH.name}\")\n        return 0\n    else:\n        print(\"✓ All packages up to date!\")\n        return 0\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n","isInternal":false,"tokens":1182,"sizeBytes":4879},{"name":"update_pypi_dates.sh","path":".claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh","rawUrl":"https://raw.githubusercontent.com/wilsonfreitas/awesome-quant/HEAD/.claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh","title":"Claude Directive: update_pypi_dates.sh","category":"claude-rule","format":"markdown","content":"#!/bin/bash\n# Wrapper script to check PyPI dates and update README.md\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_ROOT=\"$(cd \"$SCRIPT_DIR/../../../../..\" && pwd)\"\n\ncd \"$PROJECT_ROOT\" || exit 1\n\necho \"🚀 Starting PyPI date update check...\"\npython3 \"$SCRIPT_DIR/check_pypi_dates.py\"\nexit_code=$?\n\nif [ $exit_code -eq 0 ]; then\n    # Check if there are any changes to commit\n    if git diff --quiet README.md; then\n        echo \"✓ No changes needed\"\n    else\n        echo \"\"\n        echo \"📝 Changes detected, committing...\"\n        git add README.md\n        git commit -m \"Update PyPI project last updated dates\"\n        git push origin main\n        echo \"✅ Changes pushed to remote\"\n    fi\nfi\n\nexit $exit_code\n","isInternal":false,"tokens":190,"sizeBytes":741},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/wilsonfreitas/awesome-quant/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\n**awesome-quant** is a curated list of quantitative finance libraries, packages, and resources. The primary content lives in `README.md` — a large markdown file **organized by category** (Numerical Libraries, Trading & Backtesting, Market Data, etc.) with inline language tags that identify which programming languages each project supports.\n\nA companion website is generated from this data and deployed to GitHub Pages.\n\n## Architecture\n\nThe pipeline works as follows:\n\n1. **`README.md`** — The source of truth. All library entries follow the format: `- [name](url) - \\`Language\\` - Description.`\n   - Entries are grouped under category headings (`##`), not language headings\n   - Language is identified via inline backtick tags (e.g., `` `Python` ``, `` `Rust` ``) in the description\n   - Multi-language projects have multiple tags (e.g., `` `Python` `Rust` ``)\n\n2. **`parse.py`** — Parses `README.md`, extracts language from backtick tags, fetches last commit dates and stars via the GitHub API (using `PyGithub` with multithreading), and writes `site/projects.csv` with a `languages` column (comma-separated).\n\n3. **`site/generate.py`** — Reads `site/projects.csv` (or parses `README.md` directly) and generates a static HTML site (`site/index.html`) with search, filtering by language/category/source, sorting, and dark mode. Front-end assets live in `site/static/` (`main.js`, `style.css`).\n\n4. **CI** (`.github/workflows/build.yml`, workflow name \"Update site\") — Runs daily (cron `0 1 * * *`) and on push to `main` touching `README.md`, `parse.py`, or `site/**`: runs `parse.py`, runs `site/generate.py`, and deploys the `site/` directory to GitHub Pages via `peaceiris/actions-gh-pages`.\n\nSupporting scripts:\n- `cranscrape.py` — Scrapes CRAN package pages to find associated GitHub repos; writes `cran.csv`.\n- `topic.py` — Searches GitHub for repos tagged with a topic (e.g., \"quant\") above a star threshold.\n- `scripts/migrate_readme.py` — One-off migration that converted `README.md` from language-first to category-first organization (kept for reference).\n\n## Commands\n\n```bash\n# Install dependencies (uses uv, requires Python 3.11+)\nuv sync --no-install-project\n\n# Run the parser (requires GITHUB_ACCESS_TOKEN env var)\nGITHUB_ACCESS_TOKEN=<token> uv run python parse.py\n\n# Generate the static site\nuv run python site/generate.py\n```\n\n## Contributing Entries\n\nSee `CONTRIBUTING.md` for full guidelines. All entries must include language tags:\n\n```\n- [Project Name](https://github.com/owner/repo) - `Python` - Description ending with a period.\n- [Project Name](https://github.com/owner/repo) - `Python` `Rust` - Multi-language project description.\n- [Project Name](https://site.com) - `Python` - Description ending with a period. [GitHub](https://github.com/owner/repo)\n- [Package Name](https://cran.r-project.org/package=pkg) - `R` - Description ending with a period.\n- [package-name](https://pypi.org/project/pkg/) - `Python` - Description ending with a period.\n```\n\nCRAN and PyPI entries may optionally append `[GitHub](url)` after the description.\n\nEntries are grouped under category headings (`##`), not language headings. Language is identified via inline backtick tags. Commercial/proprietary projects go under `## Commercial & Proprietary Services`.\n\n`parse.py` and `site/generate.py` rely on this regex to extract entries: `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`\n\nThe description text (group 3) may start with language tags in the format `` `Language1` `Language2` - `` followed by the actual description.\n\n## PR Reviews\n\nThis repo receives most contributions as pull requests adding new entries. Use the **GitHub MCP tools** (e.g. `list_pull_requests`, `pull_request_read`, `merge_pull_request`, `add_issue_comment`, `update_pull_request`), **not** the `gh` CLI, for PR operations.\n\nDedicated skills drive the review workflow:\n- `sprr` — Single PR reviewer: validate one PR's entry against the format rules.\n- `bprr` — Bulk PR reviewer: review all open PRs lacking the \"reviewed\" label, then present a summary for selection before merging.\n- `update-pypi-dates` — Refresh last-updated dates for PyPI entries in `README.md`.\n\nReview checklist: always ask before merging; verify section placement (commercial entries belong under \"Commercial & Proprietary Services\", not Market Data); check for duplicates in `README.md`; apply the \"reviewed\" label after commenting.\n\nSee `AGENTS.md` for the agent-facing command and tool summary, and `CONTRIBUTING.md` for contributor guidelines.\n","isInternal":false,"tokens":1112,"sizeBytes":4653}],"systemPromptSnippet":"<yakaai_skills repo=\"wilsonfreitas/awesome-quant\">\n<!-- File: AGENTS.md (Tokens: ~1553 | Category: root-instruction) -->\n# AGENTS.md\n\n## Project Overview\n\n`awesome-quant` is a curated list of quantitative finance libraries, packages,\nand resources. The source of truth is `README.md`; the static website is\ngenerated into `site/index.html`.\n\nThe README is organized by category headings (`##`), not by language headings.\nProject metadata is stored in inline backtick tags inside each entry. Tags commonly identify\nlanguages, but may also identify runtimes, protocols, interfaces, data types, or domains.\n\n## Architecture\n\n1. `README.md` contains curated entries.\n2. `parse.py` parses `README.md`, enriches GitHub/CRAN/PyPI metadata, and writes\n   `site/projects.csv`.\n3. `site/generate.py` reads `site/projects.csv` when present, otherwise parses\n   `README.md` directly for local previews, then writes `site/index.html`.\n4. `.github/workflows/build.yml` runs the parser and generator, then deploys\n   `site/` to GitHub Pages.\n\n## Work Tracking and Planning\n\n- Linear is the system of record for issues, prioritization, specifications,\n  designs, and implementation plans.\n- Manage GitHub-originated issues through their synced Linear issues. Do not\n  create a second internal tracker for the same work.\n- Store each specification, design, and implementation plan as a Linear\n  document attached to the corresponding Linear issue. Do not add task-specific\n  planning documents to the repository.\n- Keep repository documentation for durable project and user documentation only.\n- GitHub remains the public contribution surface for pull requests and public\n  issue discussion; use Linear for internal status, priority, and planning.\n\n## Commands\n\n```bash\n# Install deps (requires Python 3.11+)\nuv sync --no-install-project\n\n# Validate README entries changed in a PR\nuv run python scripts/validate_readme.py --diff-from origin/main\n\n# Validate the full README; legacy format/duplicate/URL issues are warnings by default\nuv run python scripts/validate_readme.py\n\n# Run parser (requires GitHub token)\nGITHUB_ACCESS_TOKEN=<token> uv run python parse.py\n\n# Generate static site\nuv run python site/generate.py\n```\n\n## Entry Format\n\nThe critical parser regex is:\n\n```text\n^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$\n```\n\nAccepted entry examples:\n\n```markdown\n- [Project Name](https://github.com/owner/repo) - `Python` - Description ending with a period.\n- [Project Name](https://github.com/owner/repo) - `Python` `Rust` - Description ending with a period.\n- [Project Name](https://site.com) - `Python` - Description ending with a period. [GitHub](https://github.com/owner/repo)\n- [Package Name](https://cran.r-project.org/package=pkg) - `R` - Description ending with a period.\n- [package-name](https://pypi.org/project/pkg/) - `Python` - Description ending with a period.\n```\n\nRules:\n\n- New non-commercial entries must include one or more concise backtick tags followed by ` - `.\n  Tags form a compact tag cloud and are not restricted to programming languages.\n- Each tag must use its own backtick pair, for example `` `Python` `C++` `MCP` ``.\n- Descriptions must end with a period before the optional `[GitHub](...)` link.\n- URLs in new entries must use `https://`.\n- A valid GitHub repository used as the main URL or exact `[GitHub](...)` suffix is preferred\n  and is a strong positive relevance signal, but it is not universally required. Functional\n  section placement requires a repository containing substantive implementation; a thin SDK,\n  integration, examples, generated-data, or marketing repository does not qualify.\n- Hosted commercial/proprietary products without substantive public source belong in\n  `## Commercial & Proprietary Services`, even when a thin repository exists. Repository-less\n  services qualify only under the permanent free tier and transparency rules in\n  `CONTRIBUTING.md`.\n- Treat a commercial service with only a thin SDK, integration, examples, generated-data, or\n  marketing repository as repository-less for every eligibility check.\n- Backtick tags are optional only for commercial services and other metadata-free\n  sections such as `Related Lists`.\n- `Historical & Archived Projects` is the documented exception to normal activity and\n  archive-state requirements. Entries still require substantive, reachable, documented source\n  and the `Historical` tag; use `CONTRIBUTING.md` for eligibility.\n- Use `CONTRIBUTING.md` as the user-facing source for contribution rules.\n\n## PR Review Workflow\n\nThis repo receives most contributions as pull requests adding README entries.\nUse Codex repo skills for repeatable review workflows:\n\n- `$sprr` - single PR reviewer.\n- `$bprr` - bulk PR reviewer.\n- `$update-pypi-dates` - refresh tracked PyPI last-updated dates.\n- `$create-entry` - draft or add README entries from a URL, GitHub issue, or Linear issue.\n\nReview requirements:\n\n1. Only review the PRs the user asked you to review.\n2. Use GitHub MCP tools for PR operations, not the `gh` CLI.\n3. Present findings before any PR-modifying action.\n4. Always ask the user before commenting, labeling, closing, or merging.\n5. Check section placement, duplicates in `README.md`, entry format, URL format,\n   and project activity/documentation. Give substantial positive weight to a verifiable\n   GitHub repository mentioned as either the main URL or exact suffix, while confirming that\n   functional-section repositories contain substantive implementation.\n6. Manually assess commercial entries for free-tier usefulness, payment information,\n   public pricing and limits, public documentation/methodology/examples, stable non-tracking\n   URLs, concise factual description tone, and repository substance.\n7. Commercial submissions without a qualifying permanent free tier—including paid-only,\n   trial-only, demo-only, and waitlist-only offerings—are `REJECT`. Reserve `NEEDS CHANGES` for\n   correctable evidence or disclosure, wording, URL, documentation, or placement defects when\n   the underlying offering can qualify.\n8. Use the `reviewed` label only after the user approves a review comment.\n\n## GitHub MCP Tools\n\nThis project expects Codex to have a GitHub MCP server configured for PR work.\nUseful tool capabilities include:\n\n- List open pull requests.\n- Get PR details, files, comments, labels, and diffs.\n- Fetch `README.md` from the default branch for duplicate checks.\n- Add PR comments and labels.\n- Merge pull requests after explicit user approval.\n\nSee `docs/codex-setup.md` for local Codex setup notes. If GitHub MCP tools are\nnot available in a session, report that PR operations are blocked and ask the\nuser to configure the MCP server.\n\n## Local Validation Notes\n\n- `scripts/validate_readme.py --diff-from <ref>` is intended for PR checks. It\n  validates only added README entries and treats duplicates/URL issues as errors\n  for those additions.\n- `scripts/validate_readme.py` validates the full README. Legacy format, duplicate, and\n  URL problems are reported as warnings unless strict flags are used.\n- `parse.py` requires `GITHUB_ACCESS_TOKEN`; `site/generate.py` can run without\n  the token if `site/projects.csv` already exists or if it falls back to direct\n  README parsing.\n\n<!-- File: .agents/skills/bprr/SKILL.md (Tokens: ~661 | Category: anthropic-skill) -->\n---\nname: bprr\ndescription: Bulk PR reviewer for awesome-quant. Use when the user asks to review all open PRs, review unreviewed PRs, bulk review, or mentions \"bprr\". Reviews open PRs lacking the reviewed label and presents a summary before any merge/comment/label action.\n---\n\n# BPRR: Bulk PR Reviewer\n\nReview multiple open pull requests for README entry contributions.\n\n**REQUIRED SUB-SKILL:** Use `sprr` as the canonical policy for reviewing each pull request. Read\nit before starting the bulk review and apply its hard rules, workflow evidence rules, validation\nchecklist, verdicts, output fields, and approved-action rules unless this skill defines a\nbulk-specific presentation step.\n\n## Hard Rules\n\n1. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels,\n   closing, or merging.\n2. Filter out PRs with the `reviewed` label unless the user asks to re-review them.\n3. Apply `sprr` independently to every PR. Shared retrieval may reduce repeated work, but evidence,\n   findings, and verdicts never carry from one PR to another.\n4. Do not comment, label, close, or merge until the user explicitly approves each action.\n5. Do not auto-merge all approved PRs unless the user explicitly selects that option.\n6. If GitHub MCP tools are unavailable, report the blocker and point to `docs/codex-setup.md`.\n\n## Bulk Workflow\n\n1. List open PRs sorted oldest first and filter to unreviewed PRs by default.\n2. Fetch the default-branch `README.md` once and reuse it where `sprr` requires a base-README\n   duplicate check.\n3. For every included PR, fetch the data and both required workflow attempts specified by `sprr`.\n4. Apply `sprr` independently to every PR, including its manual checks and cross-PR duplicate\n   search over open PRs and PRs closed within the last 365 days.\n5. Present the bulk summary below before asking the user to select any actions.\n\n## Summary Output\n\nPresent a table:\n\n```text\n| PR | Title | Author | Head | Validate PR | PR Review | Entries | Format/URL | Section | Duplicate | Verdict |\n|----|-------|--------|------|-------------|-----------|---------|------------|---------|-----------|---------|\n```\n\nFor each row, copy the workflow states, mechanical-check result, and verdict from that PR's `sprr`\nreview. `Section` remains a manual semantic judgment. In `Duplicate`, report both\n`README PASS|FAIL` and `PR SEARCH PASS|FAIL`.\n\nAfter the table, list any PRs that need detailed notes. Include failed workflow steps, reasons\nworkflow evidence was not accepted, manual findings, and commercial free-tier or transparency\nevidence when it affects the verdict.\n\nAsk what to do next. Accept selections such as:\n\n- `merge 123, 124`\n- `comment 125`\n- `close 126`\n- `all approved`\n- `none`\n\nApply `sprr`'s approved-action rules to each selected PR. Confirm every merge before executing it.\n\n<!-- File: .agents/skills/sprr/SKILL.md (Tokens: ~2259 | Category: anthropic-skill) -->\n---\nname: sprr\ndescription: Single PR reviewer for awesome-quant. Use when the user asks to review, validate, comment on, label, close, or merge one specific pull request that adds README.md entries. Triggers include \"sprr\", \"review PR\", \"check PR\", and \"validate contribution\".\n---\n\n# SPRR: Single PR Reviewer\n\nReview one pull request that adds entries to `README.md`.\n\n## Hard Rules\n\n1. Review only the PR number the user requested. If no PR number is given, ask for one.\n2. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n3. Do not modify the PR until the user explicitly approves that action.\n4. Always present findings before asking whether to comment, label, close, or merge.\n5. Always ask before merging.\n6. Enforce `CONTRIBUTING.md` and `AGENTS.md` strictly for new entries, using the\n   sentence-count interpretation in the Validation Checklist below.\n7. Both `Validate PR` and `PR Review` must pass before returning `APPROVE`.\n\nIf GitHub MCP tools are unavailable, report that PR operations are blocked and point the user to `docs/codex-setup.md`.\n\n## Workflow\n\n1. Fetch PR details, current head SHA, files changed, labels, comments, and diff with GitHub MCP.\n2. Confirm whether the `reviewed` label or prior maintainer comments exist, then proceed with full validation anyway.\n3. Fetch the latest `Validate PR` workflow/check attempt for the current head SHA and apply the CI evidence rules below.\n4. Fetch the latest `PR Review` workflow/check attempt associated with the pull request and apply\n   the required workflow rules below.\n5. Focus on added lines in `README.md`. Flag any other changed files as unusual for a normal contribution.\n6. When mechanical validation is not established by current-head CI, save or reconstruct the PR diff locally only if needed, then validate added README entries with:\n\n```bash\nuv run python scripts/validate_readme.py --diff-from <base-ref>\n```\n\nIf a base ref is not locally available, apply the same checks manually from the fetched diff.\n\n## CI Evidence Rules\n\nUse only the latest attempt whose commit SHA exactly matches the PR's current head SHA. A newer\nqueued or pending attempt supersedes an older successful attempt for the same SHA.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not rerun those mechanical checks. |\n| `failure` | Inspect the failing job or step. Return `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Report the review as incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Report the review as incomplete and do not return `APPROVE`; reproduce mechanical validation only to provide useful findings. |\n| success on an older SHA | Report the result as stale and do not return `APPROVE`; require a successful attempt for the current SHA. |\n\nCI never replaces inspection of the diff or the manual checks below. A successful check confirms\nonly mechanical rules; it does not establish tag meaning or concision, description quality,\nrelevance, semantic section suitability, commercial classification, repository quality,\ncommercial free-tier eligibility or transparency, URL tracking, cross-PR uniqueness, or\nmulti-project relatedness. CI cannot establish any of these manual criteria. Search open PRs and PRs\nclosed within the last 365 days for duplicate names and URLs.\n\n`PR Review` runs on `pull_request_target`, so use the latest attempt associated with the pull\nrequest without applying the current-head SHA rule used for `Validate PR`. A successful attempt is\nrequired but does not prove that current-head mechanical validation passed. If the latest attempt\nfails, inspect its failing job or step. Return `NEEDS CHANGES` when the review reports a PR defect;\notherwise report the review as incomplete. If it is queued, pending, cancelled, skipped, or\nmissing, report the review as incomplete and do not return `APPROVE`.\n\n## Validation Checklist\n\nFor every added entry:\n\n- It matches `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`.\n- New non-commercial entries include one or more backtick tags followed by ` - `. Treat these\n  as a compact tag cloud: accept concise languages, runtimes, protocols, interfaces, data\n  types, and domain terms.\n- Separate concepts use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not reject a tag\n  merely because it is not a programming language.\n- Description ends with a period before optional `[GitHub](...)`.\n- Treat `CONTRIBUTING.md`'s \"one sentence\" wording as concision guidance, not a sentence-count\n  gate. Accept two or more short sentences when the overall description remains concise, factual,\n  relevant, and non-promotional. Never return `NEEDS CHANGES` solely because of sentence count;\n  request wording changes only for actual quality problems such as verbosity, repetition,\n  unsupported claims, promotional language, or poor readability.\n- URLs use `https://`.\n- Optional GitHub link uses `[GitHub](https://github.com/owner/repo)`.\n- Section placement matches the project's purpose.\n- Distinguish repositories containing substantive implementation from thin SDK, integration,\n  examples, generated-data, or marketing repositories.\n- Hosted proprietary products without substantive public source are under\n  `Commercial & Proprietary Services`, even when a thin repository exists.\n- For repository-less commercial entries, verify a useful permanent free tier for quantitative\n  finance that requires no payment information and is not a trial, demo, or waitlist.\n- Treat a commercial service with only a thin SDK, integration, examples, generated-data, or\n  marketing repository as repository-less for every eligibility check.\n- Verify that these commercial entries publish pricing and free-tier limits plus public\n  documentation, methodology, or usage examples; use a stable HTTPS URL without affiliate or\n  tracking parameters; and have a concise, factual, non-promotional description.\n- Project name and URLs are not duplicates of existing README entries.\n- A verifiable GitHub repository containing substantive implementation, mentioned as the main URL\n  or exact `[GitHub](...)` suffix, is a strong positive relevance signal. Repository existence\n  alone does not establish commercial eligibility or functional-section placement.\n- GitHub projects are checked for source availability, activity, archived status,\n  documentation, and community evidence. GitHub relevance does not waive duplicate, format,\n  or quality checks.\n- Multiple projects in one PR are closely related and explained in the PR body.\n\n## Repository Substance and Linked Services\n\nFor every added entry with a repository, investigate what the public source actually provides:\n\n1. Inspect representative implementation files behind the advertised functionality. A README,\n   license, tests, file count, or stars alone do not establish substance.\n2. Trace whether core functionality is implemented publicly or depends on a proprietary service.\n   Identify code that only calls a vendor API, integrates a service, downloads generated output,\n   or provides examples or marketing. External dependencies alone do not make a project thin;\n   assess where the advertised functionality is implemented.\n3. Follow linked service websites, public documentation, and pricing/free-tier pages. Establish\n   the repository's relationship to the service and verify eligibility under `CONTRIBUTING.md`,\n   including useful permanent free access without payment information.\n4. Report concrete evidence: representative source-file links, API dependencies, and relevant\n   service/pricing/documentation links. State unavailable or inconclusive evidence explicitly.\n   Small size, few stars, or recent creation alone do not imply poor quality or commercial status.\n\nWhen a repository mainly supports a qualifying commercial service, place the entry in\n`Commercial & Proprietary Services`. Use the service name and stable service website as the main\nlink, and retain the repository only as the exact `[GitHub](...)` suffix:\n\n```markdown\n- [Service Name](https://service.example) - Factual service description with relevant free-tier limits. [GitHub](https://github.com/owner/client)\n```\n\nDescribe the service, not merely its SDK. An open-source client license does not make the hosted\nservice open source. Substantive public implementation can qualify for a functional section even\nwhen its maintainers also sell a hosted service.\n\n- Qualifying service with incorrect placement or a thin repository as its main link:\n  `NEEDS CHANGES`, with a proposed corrected README entry.\n- Confirmed paid-only, trial-only, demo-only, waitlist-only, or otherwise non-qualifying free\n  access: `REJECT`; moving the entry does not fix eligibility.\n- Insufficient evidence of repository substance or service eligibility: `NEEDS CHANGES`, naming\n  the missing evidence without claiming that the service qualifies.\n\n## Verdicts\n\nUse these verdicts:\n\n- `APPROVE`: both required workflows pass and the entry is ready to merge after manual review.\n- Sentence count alone does not affect the verdict; evaluate description quality using the criteria\n  in the Validation Checklist.\n- Commercial submissions without a qualifying permanent free tier—including paid-only,\n  trial-only, demo-only, and waitlist-only offerings—are `REJECT`.\n- Reserve `NEEDS CHANGES` for correctable evidence or disclosure, wording, URL, documentation, or\n  placement defects when the underlying offering can qualify.\n- Other `REJECT` cases include duplicates, unrelated multi-project PRs, empty PR descriptions,\n  archived or abandoned projects, and other hard rejections.\n\n## Output Shape\n\nReport:\n\n```text\nPR #<number>: <title>\nAuthor: <author>\nPrior review: YES/NO\nFiles changed: <files>\nEntries reviewed: <count>\n\nAutomated validation:\n- Validate PR: PASS | FAIL | PENDING | UNVERIFIED\n- PR Review: PASS | FAIL | PENDING | UNVERIFIED\n- Commit: <checked-sha> (CURRENT | STALE)\n- Mechanical checks: accepted from CI | reproduced manually | incomplete\n\nFindings:\n- <entry>: <status and reason>\n\nVerdict: APPROVE | NEEDS CHANGES | REJECT\nRecommended action: <merge/comment/close/no action>\n```\n\nThen ask for explicit approval before doing the recommended action.\n\n## Approved Actions After User Consent\n\n- If approved and user says to merge: merge with squash unless user requests otherwise.\n- If needs changes and user says to comment: leave one concise comment with all requested fixes, then add `reviewed` if available.\n- If rejected and user says to close: leave a polite rejection comment and close the PR.\n\n<!-- File: .agents/skills/update-pypi-dates/SKILL.md (Tokens: ~226 | Category: anthropic-skill) -->\n---\nname: update-pypi-dates\ndescription: Refresh tracked PyPI last-updated dates in awesome-quant README.md. Use when the user asks to update PyPI dates, refresh PyPI metadata, or run update-pypi-dates.\n---\n\n# Update PyPI Dates\n\nRefresh last release dates for selected PyPI packages listed in `README.md`.\n\n## Workflow\n\n1. Run the checker:\n\n```bash\nuv run python .agents/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n2. Show the user which packages changed.\n3. Run README validation:\n\n```bash\nuv run python scripts/validate_readme.py\n```\n\n4. If the user asked for a commit, stage only the relevant files and commit.\n5. Do not push unless the user explicitly asks.\n\n## Tracked Packages\n\nThe script currently tracks:\n\n- `qfrm`\n- `chinesestockapi`\n- `tushare`\n- `metatrader5` / `MetaTrader5`\n\nTo add packages, edit `PYPI_PROJECTS` in `scripts/check_pypi_dates.py`.\n\n<!-- File: .claude/skills/bprr/SKILL.md (Tokens: ~1104 | Category: anthropic-skill) -->\n---\nname: bprr\ndescription: Bulk PR reviewer for awesome-quant. Use when the user asks to review all open PRs, review unreviewed PRs, bulk review, or mentions \"bprr\". Reviews open PRs lacking the reviewed label and presents a summary before any merge/comment/label action.\n---\n\n# BPRR: Bulk PR Reviewer\n\nReview multiple open pull requests for README entry contributions.\n\n## Hard Rules\n\n1. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n2. Filter out PRs with the `reviewed` label unless the user asks to re-review them.\n3. Do not comment, label, close, or merge until the user explicitly approves each action.\n4. Do not auto-merge all approved PRs unless the user explicitly selects that option.\n5. If GitHub MCP tools are unavailable, report the blocker and point to `docs/codex-setup.md`.\n\n## Workflow\n\n1. List open PRs sorted oldest first.\n2. Filter to unreviewed PRs by default.\n3. Fetch the default-branch `README.md` once for duplicate checks.\n4. For each PR, fetch details, current head SHA, labels, files, body, diff, and the latest `Validate PR` workflow/check attempt for that SHA.\n5. Review only added `README.md` entries unless the PR changes other files; flag other file changes as unusual.\n6. Apply the CI evidence rules below, then perform the remaining `$sprr` checks. Use `scripts/validate_readme.py --diff-from <base-ref>` only when current-head CI does not establish mechanical validity and the PR branch is available locally; otherwise apply the validator's rules manually from the MCP diff.\n\n## CI Evidence Rules\n\nEvaluate each PR independently. Use only the latest attempt for the current head SHA; a newer\nqueued or pending attempt supersedes an older success for that SHA. A result for one PR or\ncommit never applies to another.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not repeat those mechanical checks. |\n| `failure` | Inspect the failing job or step. Use `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Mark the review incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Treat mechanical validation as unverified and reproduce it before deciding. |\n| success only on an older SHA | Report `STALE`, ignore it, and reproduce mechanical validation for the current head SHA. |\n\nFor every PR, still inspect the diff and manually review tag meaning and concision, description\nquality, relevance, semantic section suitability, commercial classification, repository\nactivity/archive/documentation/community evidence, duplicates in open PRs and PRs closed\nwithin the last 365 days, and multi-project relatedness.\n\n## Validation Checklist\n\nFor each added entry, check:\n\n- Parser regex match.\n- Required backtick tags for new non-commercial entries. Treat them as a compact tag cloud:\n  accept concise languages, runtimes, protocols, interfaces, data types, and domain terms.\n- Separate concepts must use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not require\n  every tag to be a programming language.\n- Description period before optional `[GitHub](...)`.\n- `https://` URLs.\n- Exact optional `[GitHub](https://github.com/owner/repo)` format.\n- Correct category section.\n- Commercial placement under `Commercial & Proprietary Services`.\n- Duplicate project names or URLs.\n- Treat any verifiable GitHub repository mentioned as the main URL or exact `[GitHub](...)`\n  suffix as a strong positive relevance signal.\n- For GitHub repos, check source availability, activity, archived status, documentation, and\n  community evidence. GitHub relevance does not waive duplicate, format, or quality checks.\n- Clear rationale for multiple related projects in one PR.\n\n## Summary Output\n\nPresent a table:\n\n```text\n| PR | Title | Author | Head | Validate PR | Entries | Format/URL | Section | Duplicate | Verdict |\n|----|-------|--------|------|-------------|---------|------------|---------|-----------|---------|\n```\n\nUse the entry count in `Entries`. Use `PASS`, `FAIL`, `PENDING`, `UNVERIFIED`, or\n`STALE` in `Validate PR`. Use `CI PASS`, `CI FAIL`, `REPRODUCED PASS`,\n`REPRODUCED FAIL`, or `INCOMPLETE` in `Format/URL`. `Section` remains a manual\nsemantic judgment. In `Duplicate`, report both `README PASS|FAIL` and\n`PR SEARCH PASS|FAIL`.\n\nAfter the table, list any PRs that need detailed notes, including the failing workflow step or the reason CI evidence was not accepted.\n\nAsk what to do next. Accept selections like:\n\n- `merge 123, 124`\n- `comment 125`\n- `close 126`\n- `all approved`\n- `none`\n\nConfirm each merge before executing it.\n\n<!-- File: .claude/skills/sprr/SKILL.md (Tokens: ~1279 | Category: anthropic-skill) -->\n---\nname: sprr\ndescription: Single PR reviewer for awesome-quant. Use when the user asks to review, validate, comment on, label, close, or merge one specific pull request that adds README.md entries. Triggers include \"sprr\", \"review PR\", \"check PR\", and \"validate contribution\".\n---\n\n# SPRR: Single PR Reviewer\n\nReview one pull request that adds entries to `README.md`.\n\n## Hard Rules\n\n1. Review only the PR number the user requested. If no PR number is given, ask for one.\n2. Use GitHub MCP tools for PR operations. Do not use `gh` for PR review, comments, labels, closing, or merging.\n3. Do not modify the PR until the user explicitly approves that action.\n4. Always present findings before asking whether to comment, label, close, or merge.\n5. Always ask before merging.\n6. Enforce `CONTRIBUTING.md` and `AGENTS.md` strictly for new entries.\n\nIf GitHub MCP tools are unavailable, report that PR operations are blocked and point the user to `docs/codex-setup.md`.\n\n## Workflow\n\n1. Fetch PR details, current head SHA, files changed, labels, comments, and diff with GitHub MCP.\n2. Confirm whether the `reviewed` label or prior maintainer comments exist, then proceed with full validation anyway.\n3. Fetch the latest `Validate PR` workflow/check attempt for the current head SHA and apply the CI evidence rules below.\n4. Focus on added lines in `README.md`. Flag any other changed files as unusual for a normal contribution.\n5. When mechanical validation is not established by current-head CI, save or reconstruct the PR diff locally only if needed, then validate added README entries with:\n\n```bash\nuv run python scripts/validate_readme.py --diff-from <base-ref>\n```\n\nIf a base ref is not locally available, apply the same checks manually from the fetched diff.\n\n## CI Evidence Rules\n\nUse only the latest attempt whose commit SHA exactly matches the PR's current head SHA. A newer\nqueued or pending attempt supersedes an older successful attempt for the same SHA.\n\n| Current-head result | Review behavior |\n|---|---|\n| `success` | Accept parser format, tag syntax, separators, the required final period, HTTPS, GitHub-link syntax, recognized section, and base-README duplicate checks as passed. Do not rerun those mechanical checks. |\n| `failure` | Inspect the failing job or step. Return `NEEDS CHANGES` when validation failed; if another step failed or details are unavailable, reproduce mechanical validation before deciding. |\n| queued, pending, awaiting approval | Report the review as incomplete and do not return `APPROVE`. |\n| skipped, cancelled, missing | Treat mechanical validation as unverified and reproduce it before deciding. |\n| success on an older SHA | Ignore it and evaluate the current SHA using these rules. |\n\nCI never replaces inspection of the diff or the manual checks below. A successful check confirms\nonly mechanical rules; it does not establish tag meaning or concision, description quality,\nrelevance, semantic section suitability, commercial classification, repository quality,\ncross-PR uniqueness, or multi-project relatedness. Search open PRs and PRs closed within the\nlast 365 days for duplicate names and URLs.\n\nFor repository substance and linked commercial services, apply the **Repository Substance and\nLinked Services** investigation in `.agents/skills/sprr/SKILL.md`, including its evidence,\nservice-first link, and eligibility verdict rules.\n\n## Validation Checklist\n\nFor every added entry:\n\n- It matches `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`.\n- New non-commercial entries include one or more backtick tags followed by ` - `. Treat these\n  as a compact tag cloud: accept concise languages, runtimes, protocols, interfaces, data\n  types, and domain terms.\n- Separate concepts use adjacent tags, such as `` `Python` `C++` `MCP` ``; do not reject a tag\n  merely because it is not a programming language.\n- Description ends with a period before optional `[GitHub](...)`.\n- URLs use `https://`.\n- Optional GitHub link uses `[GitHub](https://github.com/owner/repo)`.\n- Section placement matches the project's purpose.\n- Commercial/proprietary projects are under `Commercial & Proprietary Services`.\n- Project name and URLs are not duplicates of existing README entries.\n- A verifiable GitHub repository containing substantive implementation, mentioned as the main URL\n  or exact `[GitHub](...)` suffix, is a strong positive relevance signal.\n- GitHub projects are checked for source availability, activity, archived status,\n  documentation, and community evidence. GitHub relevance does not waive duplicate, format,\n  or quality checks.\n- Multiple projects in one PR are closely related and explained in the PR body.\n\n## Verdicts\n\nUse these verdicts:\n\n- `APPROVE`: entry is ready to merge.\n- `NEEDS CHANGES`: fixable format, section, URL, description, or documentation issue.\n- `REJECT`: duplicate, unrelated multi-project PR, empty PR description, archived/abandoned project, or other hard rejection.\n\n## Output Shape\n\nReport:\n\n```text\nPR #<number>: <title>\nAuthor: <author>\nPrior review: YES/NO\nFiles changed: <files>\nEntries reviewed: <count>\n\nAutomated validation:\n- Validate PR: PASS | FAIL | PENDING | UNVERIFIED\n- Commit: <checked-sha> (CURRENT | STALE)\n- Mechanical checks: accepted from CI | reproduced manually | incomplete\n\nFindings:\n- <entry>: <status and reason>\n\nVerdict: APPROVE | NEEDS CHANGES | REJECT\nRecommended action: <merge/comment/close/no action>\n```\n\nThen ask for explicit approval before doing the recommended action.\n\n## Approved Actions After User Consent\n\n- If approved and user says to merge: merge with squash unless user requests otherwise.\n- If needs changes and user says to comment: leave one concise comment with all requested fixes, then add `reviewed` if available.\n- If rejected and user says to close: leave a polite rejection comment and close the PR.\n\n<!-- File: .claude/skills/update-pypi-dates/README.md (Tokens: ~788 | Category: anthropic-skill) -->\n# Update PyPI Dates Skill\n\nAutomatically check PyPI projects for their latest update dates and keep README.md entries current.\n\n## Overview\n\nThis skill monitors Python packages listed in awesome-quant and updates their entries with the latest release dates from PyPI. This ensures that outdated project information is easily identifiable.\n\n## Features\n\n- ✅ Checks 4 PyPI projects: qfrm, chinesestockapi, tushare, metatrader5\n- ✅ Fetches latest release dates from PyPI API\n- ✅ Updates README.md entries with `(Last updated: YYYY-MM-DD)` format\n- ✅ Commits changes automatically when updates found\n- ✅ No dependencies beyond Python standard library\n\n## Usage\n\n### Invoke from Claude Code\n\n```bash\n/update-pypi-dates\n```\n\nOr call the script directly:\n\n```bash\n./.claude/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n### Manual Python Execution\n\n```bash\npython3 .claude/skills/update-pypi-dates/scripts/check_pypi_dates.py\n```\n\n### Bash Wrapper\n\n```bash\n./.claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh\n```\n\n## How It Works\n\n1. **Queries PyPI API** for each tracked package\n2. **Extracts last release date** from the releases data\n3. **Updates README.md** entries with format: `(Last updated: 2024-08-27)`\n4. **Commits changes** if any updates were found\n\n## Adding New Packages\n\nTo track additional PyPI packages, edit the `PYPI_PROJECTS` dictionary in `scripts/check_pypi_dates.py`:\n\n```python\nPYPI_PROJECTS = {\n    \"display_name\": \"pypi_package_name\",\n    # Add new entries here\n}\n```\n\nThen update the skill description if needed.\n\n## Output Examples\n\n### No Changes\n```\n📦 Checking PyPI projects for last updated dates...\n\nChecking qfrm...\n  ✓ 2015-12-12 (no change)\n\n✓ All packages up to date!\n```\n\n### With Updates\n```\n📦 Checking PyPI projects for last updated dates...\n\nChecking tushare...\n  ✓ 2024-08-27 (no change)\nChecking metatrader5...\n  ✅ Updated to 2026-02-20\n\n📝 Found 1 update(s):\n  - metatrader5: 2026-02-20\n\n✅ Updated README.md\n```\n\n## Configuration\n\n### Periodic Execution\n\nSet up a cron job to run weekly:\n\n```bash\n# Add to crontab (runs Monday at 2 AM)\n0 2 * * 1 cd /path/to/awesome-quant && ./.claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh\n```\n\nOr use Claude Code's scheduling:\n\n```bash\n/loop 1w /update-pypi-dates\n```\n\n## Files\n\n- `SKILL.md` - Skill definition and documentation\n- `scripts/check_pypi_dates.py` - Main Python script\n- `scripts/update_pypi_dates.sh` - Bash wrapper with git integration\n- `README.md` - This file\n\n## Requirements\n\n- Python 3.6+\n- Network access to PyPI API\n- Git (for automatic commits)\n\n## Error Handling\n\n- Network timeouts: Gracefully skipped with warning\n- Package not found: Skipped with message\n- API errors: Logged and continued with other packages\n\n## Future Enhancements\n\n- [ ] Support for more PyPI packages\n- [ ] GitHub Actions workflow integration\n- [ ] Email notifications on updates\n- [ ] Comparison with published versions in README\n- [ ] Support for other package registries (npm, Ruby Gems, etc.)\n\n<!-- File: .claude/skills/update-pypi-dates/SKILL.md (Tokens: ~448 | Category: anthropic-skill) -->\n---\nname: update-pypi-dates\ndescription: Check PyPI projects for last updated dates and update README.md entries. Use this skill to keep PyPI project information current with latest release dates from PyPI. Run periodically to maintain up-to-date metadata on Python packages listed in awesome-quant.\n---\n\n# Update PyPI Dates\n\nAutomatically check PyPI projects for their latest update dates and update corresponding README.md entries with the \"(Last updated: YYYY-MM-DD)\" information.\n\n## How it works\n\nThe skill maintains a list of PyPI projects in awesome-quant and:\n1. Queries the PyPI JSON API for each package\n2. Extracts the last release date\n3. Updates README.md entries with the new date if changed\n4. Commits changes to git if updates were made\n\n## PyPI Projects to Track\n\nCurrent projects tracked:\n- qfrm\n- chinesestockapi\n- tushare\n- metatrader5\n\n## Steps\n\n### 1. Fetch PyPI data for each project\n\nFor each PyPI project, query: `https://pypi.org/pypi/{package_name}/json`\n\nExtract the last release date from the releases data.\n\n### 2. Update README.md entries\n\nFor each project with a new date:\n- Find the entry in README.md\n- Update or add the \"(Last updated: YYYY-MM-DD)\" note\n- Use the exact entry format: `(Last updated: 2024-08-27)`\n\n### 3. Verify changes\n\nShow the user:\n- Which packages were checked\n- Which packages have new update dates\n- The differences (old date → new date)\n\n### 4. Commit if changes detected\n\nIf any updates were made:\n```bash\ngit add README.md non-github-urls.md\ngit commit -m \"Update PyPI project last updated dates\"\ngit push origin main\n```\n\n## Usage\n\nThe user can:\n- Run the skill directly: `/update-pypi-dates`\n- Schedule it to run weekly/monthly via cron\n- Include it in CI/CD pipelines to keep data fresh\n\n## Script\n\nUse `scripts/check_pypi_dates.sh` for the core update logic.\n\n<!-- File: .claude/skills/update-pypi-dates/scripts/check_pypi_dates.py (Tokens: ~1182 | Category: claude-rule) -->\n#!/usr/bin/env python3\n\"\"\"\nCheck PyPI projects for last updated dates and update README.md entries.\n\"\"\"\n\nimport json\nimport re\nimport subprocess\nimport sys\nfrom datetime import datetime\nfrom pathlib import Path\nfrom typing import Dict, Optional, Tuple\nfrom urllib.request import urlopen\n\n# PyPI projects to track\nPYPI_PROJECTS = {\n    \"qfrm\": \"qfrm\",\n    \"chinesestockapi\": \"chinesestockapi\",\n    \"tushare\": \"tushare\",\n    \"metatrader5\": \"MetaTrader5\",\n}\n\nREADME_PATH = Path(__file__).parent.parent.parent.parent.parent / \"README.md\"\n\n\ndef get_pypi_last_updated(package_name: str) -> Optional[str]:\n    \"\"\"\n    Fetch the last updated date for a PyPI package.\n\n    Returns: date string in format \"YYYY-MM-DD\" or None if not found\n    \"\"\"\n    try:\n        url = f\"https://pypi.org/pypi/{package_name}/json\"\n        with urlopen(url, timeout=5) as response:\n            data = json.loads(response.read().decode())\n\n        # Get releases (ordered dict, latest first after sorting)\n        releases = data.get(\"releases\", {})\n        if not releases:\n            return None\n\n        # Find the latest release with upload time\n        for version in sorted(releases.keys(), reverse=True):\n            release_data = releases[version]\n            if release_data and len(release_data) > 0:\n                upload_time = release_data[0].get(\"upload_time_iso_8601\")\n                if upload_time:\n                    # Extract just the date part (YYYY-MM-DD)\n                    return upload_time.split(\"T\")[0]\n\n        return None\n    except Exception as e:\n        print(f\"  ❌ Error fetching {package_name}: {e}\", file=sys.stderr)\n        return None\n\n\ndef find_readme_entry(readme_content: str, package_display_name: str) -> Tuple[Optional[int], Optional[str]]:\n    \"\"\"\n    Find a README entry for a package.\n\n    Returns: (line_number, match_text) or (None, None)\n    \"\"\"\n    # Pattern to match the entry - look for [package_name](pypi.org...)\n    pattern = rf\"\\- \\[{re.escape(package_display_name)}\\]\\(https://pypi\\.org/project/\\w+/\\)[^\\n]*\"\n\n    for line_num, line in enumerate(readme_content.split(\"\\n\"), 1):\n        if re.search(pattern, line):\n            return line_num, line.strip()\n\n    return None, None\n\n\ndef update_readme_entry(readme_content: str, package_display_name: str, new_date: str) -> Tuple[str, bool]:\n    \"\"\"\n    Update or add the last updated date to a README entry.\n\n    Returns: (updated_content, was_changed)\n    \"\"\"\n    lines = readme_content.split(\"\\n\")\n    line_num, entry_text = find_readme_entry(readme_content, package_display_name)\n\n    if line_num is None:\n        return readme_content, False\n\n    old_line = lines[line_num - 1]\n\n    # Check if entry already has a date\n    existing_date_pattern = r\"\\(Last updated: \\d{4}-\\d{2}-\\d{2}\\)\"\n    existing_match = re.search(existing_date_pattern, old_line)\n\n    if existing_match:\n        old_date = existing_match.group(0)\n        new_date_str = f\"(Last updated: {new_date})\"\n        if old_date == new_date_str:\n            return readme_content, False  # No change needed\n        new_line = old_line.replace(old_date, new_date_str)\n    else:\n        # Add date to the end of the entry (before period if present)\n        if old_line.endswith(\".\"):\n            new_line = old_line[:-1] + f\" (Last updated: {new_date}).\"\n        else:\n            new_line = old_line + f\" (Last updated: {new_date})\"\n\n    lines[line_num - 1] = new_line\n    return \"\\n\".join(lines), True\n\n\ndef main():\n    \"\"\"Check PyPI projects and update README.md.\"\"\"\n    if not README_PATH.exists():\n        print(f\"❌ README.md not found at {README_PATH}\")\n        sys.exit(1)\n\n    readme_content = README_PATH.read_text(encoding=\"utf-8\")\n    updated_content = readme_content\n    changes_made = []\n\n    print(\"📦 Checking PyPI projects for last updated dates...\\n\")\n\n    for display_name, pypi_name in PYPI_PROJECTS.items():\n        print(f\"Checking {display_name}...\")\n\n        last_updated = get_pypi_last_updated(pypi_name)\n        if last_updated is None:\n            print(f\"  ⚠️  Could not find last updated date\")\n            continue\n\n        updated_content, was_changed = update_readme_entry(\n            updated_content, display_name, last_updated\n        )\n\n        if was_changed:\n            print(f\"  ✅ Updated to {last_updated}\")\n            changes_made.append((display_name, last_updated))\n        else:\n            print(f\"  ✓ {last_updated} (no change)\")\n\n    print()\n\n    if changes_made:\n        print(f\"📝 Found {len(changes_made)} update(s):\")\n        for pkg_name, date in changes_made:\n            print(f\"  - {pkg_name}: {date}\")\n\n        README_PATH.write_text(updated_content, encoding=\"utf-8\")\n        print(f\"\\n✅ Updated {README_PATH.name}\")\n        return 0\n    else:\n        print(\"✓ All packages up to date!\")\n        return 0\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n\n<!-- File: .claude/skills/update-pypi-dates/scripts/update_pypi_dates.sh (Tokens: ~190 | Category: claude-rule) -->\n#!/bin/bash\n# Wrapper script to check PyPI dates and update README.md\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"${BASH_SOURCE[0]}\")\" && pwd)\"\nPROJECT_ROOT=\"$(cd \"$SCRIPT_DIR/../../../../..\" && pwd)\"\n\ncd \"$PROJECT_ROOT\" || exit 1\n\necho \"🚀 Starting PyPI date update check...\"\npython3 \"$SCRIPT_DIR/check_pypi_dates.py\"\nexit_code=$?\n\nif [ $exit_code -eq 0 ]; then\n    # Check if there are any changes to commit\n    if git diff --quiet README.md; then\n        echo \"✓ No changes needed\"\n    else\n        echo \"\"\n        echo \"📝 Changes detected, committing...\"\n        git add README.md\n        git commit -m \"Update PyPI project last updated dates\"\n        git push origin main\n        echo \"✅ Changes pushed to remote\"\n    fi\nfi\n\nexit $exit_code\n\n<!-- File: CLAUDE.md (Tokens: ~1112 | Category: claude-rule) -->\n# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n## Project Overview\n\n**awesome-quant** is a curated list of quantitative finance libraries, packages, and resources. The primary content lives in `README.md` — a large markdown file **organized by category** (Numerical Libraries, Trading & Backtesting, Market Data, etc.) with inline language tags that identify which programming languages each project supports.\n\nA companion website is generated from this data and deployed to GitHub Pages.\n\n## Architecture\n\nThe pipeline works as follows:\n\n1. **`README.md`** — The source of truth. All library entries follow the format: `- [name](url) - \\`Language\\` - Description.`\n   - Entries are grouped under category headings (`##`), not language headings\n   - Language is identified via inline backtick tags (e.g., `` `Python` ``, `` `Rust` ``) in the description\n   - Multi-language projects have multiple tags (e.g., `` `Python` `Rust` ``)\n\n2. **`parse.py`** — Parses `README.md`, extracts language from backtick tags, fetches last commit dates and stars via the GitHub API (using `PyGithub` with multithreading), and writes `site/projects.csv` with a `languages` column (comma-separated).\n\n3. **`site/generate.py`** — Reads `site/projects.csv` (or parses `README.md` directly) and generates a static HTML site (`site/index.html`) with search, filtering by language/category/source, sorting, and dark mode. Front-end assets live in `site/static/` (`main.js`, `style.css`).\n\n4. **CI** (`.github/workflows/build.yml`, workflow name \"Update site\") — Runs daily (cron `0 1 * * *`) and on push to `main` touching `README.md`, `parse.py`, or `site/**`: runs `parse.py`, runs `site/generate.py`, and deploys the `site/` directory to GitHub Pages via `peaceiris/actions-gh-pages`.\n\nSupporting scripts:\n- `cranscrape.py` — Scrapes CRAN package pages to find associated GitHub repos; writes `cran.csv`.\n- `topic.py` — Searches GitHub for repos tagged with a topic (e.g., \"quant\") above a star threshold.\n- `scripts/migrate_readme.py` — One-off migration that converted `README.md` from language-first to category-first organization (kept for reference).\n\n## Commands\n\n```bash\n# Install dependencies (uses uv, requires Python 3.11+)\nuv sync --no-install-project\n\n# Run the parser (requires GITHUB_ACCESS_TOKEN env var)\nGITHUB_ACCESS_TOKEN=<token> uv run python parse.py\n\n# Generate the static site\nuv run python site/generate.py\n```\n\n## Contributing Entries\n\nSee `CONTRIBUTING.md` for full guidelines. All entries must include language tags:\n\n```\n- [Project Name](https://github.com/owner/repo) - `Python` - Description ending with a period.\n- [Project Name](https://github.com/owner/repo) - `Python` `Rust` - Multi-language project description.\n- [Project Name](https://site.com) - `Python` - Description ending with a period. [GitHub](https://github.com/owner/repo)\n- [Package Name](https://cran.r-project.org/package=pkg) - `R` - Description ending with a period.\n- [package-name](https://pypi.org/project/pkg/) - `Python` - Description ending with a period.\n```\n\nCRAN and PyPI entries may optionally append `[GitHub](url)` after the description.\n\nEntries are grouped under category headings (`##`), not language headings. Language is identified via inline backtick tags. Commercial/proprietary projects go under `## Commercial & Proprietary Services`.\n\n`parse.py` and `site/generate.py` rely on this regex to extract entries: `^\\s*- \\[(.*)\\]\\((.*)\\) - (.*)$`\n\nThe description text (group 3) may start with language tags in the format `` `Language1` `Language2` - `` followed by the actual description.\n\n## PR Reviews\n\nThis repo receives most contributions as pull requests adding new entries. Use the **GitHub MCP tools** (e.g. `list_pull_requests`, `pull_request_read`, `merge_pull_request`, `add_issue_comment`, `update_pull_request`), **not** the `gh` CLI, for PR operations.\n\nDedicated skills drive the review workflow:\n- `sprr` — Single PR reviewer: validate one PR's entry against the format rules.\n- `bprr` — Bulk PR reviewer: review all open PRs lacking the \"reviewed\" label, then present a summary for selection before merging.\n- `update-pypi-dates` — Refresh last-updated dates for PyPI entries in `README.md`.\n\nReview checklist: always ask before merging; verify section placement (commercial entries belong under \"Commercial & Proprietary Services\", not Market Data); check for duplicates in `README.md`; apply the \"reviewed\" label after commenting.\n\nSee `AGENTS.md` for the agent-facing command and tool summary, and `CONTRIBUTING.md` for contributor guidelines.\n</yakaai_skills>"}