Skip to content

fix(skills): centralized index + tree cache — eliminate rate-limit failures on install - #8575

Merged
teknium1 merged 2 commits into
mainfrom
hermes/hermes-e65b0b3a
Apr 12, 2026
Merged

fix(skills): centralized index + tree cache — eliminate rate-limit failures on install#8575
teknium1 merged 2 commits into
mainfrom
hermes/hermes-e65b0b3a

Conversation

@teknium1

@teknium1 teknium1 commented Apr 12, 2026

Copy link
Copy Markdown
Contributor

Problem

A community user in Vietnam (no GitHub auth) searched for a skill then tried to install it. The search consumed 23 GitHub API calls (scanning default taps) and the install needed 45 more (the same repo tree fetched 6 times redundantly). Total: 68 calls — exceeding the unauthenticated rate limit of 60/hr, causing Could not fetch with no explanation.

Solution: Two-layer fix

Layer 1: Tree cache (immediate — helps all users now)

  • GitHubSource._get_repo_tree() caches repo info + recursive tree per-instance
  • Eliminates 10 redundant API calls (6 tree + 4 candidate 404s)
  • Rate-limit detection + actionable error message when exhausted
  • 45 → 31 API calls per install

Layer 2: Centralized skills index (long-term — eliminates the problem)

  • CI-built JSON index served from the docs site (hermes-agent.nousresearch.com/docs/api/skills-index.json)
  • scripts/build_skills_index.py crawls all sources twice daily, batch-resolves GitHub paths via tree API
  • HermesIndexSource in tools/skills_hub.py — search/fetch/inspect backed by cached index
  • When index is available, parallel_search_sources() skips external API sources entirely
  • 68 → 6 total GitHub API calls (search + install)

Impact

Flow Before With tree cache With index
Search 23 calls 23 calls 0 calls
Install (discovery) 12 calls 2 calls 0 calls
Install (file downloads) 33 calls 29 calls 6 calls
Total 68 (exceeds 60/hr) 54 6

Graceful degradation: when the index is unavailable (first run, network issue), the tree-cached direct API path handles it (54 calls, under limit).

Files changed

File Change
tools/skills_hub.py Tree cache, rate-limit detection, HermesIndexSource, search optimization
hermes_cli/skills_hub.py Rate-limit hint in error message
scripts/build_skills_index.py Index builder (crawl + batch resolve)
.github/workflows/skills-index.yml Twice-daily CI build + deploy
.github/workflows/deploy-site.yml Build index during docs deploys
.gitignore Exclude generated index file

Test plan

  • 144 skills hub tests pass
  • E2E: search + install with index = 6 GitHub API calls
  • E2E: build script indexes 1839 skills in 60s (852 KB)
  • E2E: graceful fallback when index unavailable

…n install

Skills.sh installs hit the GitHub API 45 times per install because the
same repo tree was fetched 6 times redundantly. Combined with search
(23 API calls), this totals 68 — exceeding the unauthenticated rate
limit of 60 req/hr, causing 'Could not fetch' errors for users without
a GITHUB_TOKEN.

Changes:
- Add _get_repo_tree() cache to GitHubSource — repo info + recursive
  tree fetched once per repo per source instance, eliminating 10
  redundant API calls (6 tree + 4 candidate 404s)
- _download_directory_via_tree returns {} (not None) when cached tree
  shows path doesn't exist, skipping unnecessary Contents API fallback
- _check_rate_limit_response() detects exhausted quota and sets
  is_rate_limited flag
- do_install() shows actionable hint when rate limited: set
  GITHUB_TOKEN or install gh CLI

Before: 45 API calls per install (68 total with search)
After:  31 API calls per install (54 total with search — under 60/hr)

Reported by community user from Vietnam (no GitHub auth configured).
…or search/install

Add a CI-built skills index served from the docs site. The index is
crawled daily by GitHub Actions, resolves all GitHub paths upfront, and
is cached locally by the client. When the index is available:

- Search uses the cached index (0 GitHub API calls, was 23+)
- Install uses resolved paths from index (6 API calls for file
  downloads only, was 31-45 for discovery + downloads)

Total: 68 → 6 GitHub API calls for a typical search + install flow.
Unauthenticated users (60 req/hr) can now search and install without
hitting rate limits.

Components:
- scripts/build_skills_index.py: Crawl all sources (skills.sh, GitHub
  taps, official, clawhub, lobehub), batch-resolve GitHub paths via
  tree API, output JSON index
- tools/skills_hub.py: HermesIndexSource class — search/fetch/inspect
  backed by the index, with lazy GitHubSource for file downloads
- parallel_search_sources() skips external API sources when index is
  available (0 GitHub calls for search)
- .github/workflows/skills-index.yml: twice-daily CI build + deploy
- .github/workflows/deploy-site.yml: also builds index during docs deploy

Graceful degradation: when the index is unavailable (first run, network
down, stale), all methods return empty/None and downstream sources
handle the request via direct API as before.
@teknium1 teknium1 changed the title fix(skills): cache GitHub repo trees to avoid rate-limit exhaustion on install fix(skills): centralized index + tree cache — eliminate rate-limit failures on install Apr 12, 2026
@teknium1
teknium1 merged commit 7601932 into main Apr 12, 2026
4 of 6 checks passed
@teknium1
teknium1 deleted the hermes/hermes-e65b0b3a branch April 12, 2026 23:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant