Loading...
Loading...
Build and maintain the Hermes Atlas ecosystem map with quality filtering, RAG chatbot, and live GitHub star tracking
npx skill4agent add aradotso/hermes-skills hermes-atlas-ecosystem-mapSkill by ara.so — Hermes Skills collection.
git clone https://github.com/ksimback/hermes-ecosystem.git
cd hermes-ecosystem
npm installopenairedishermes-ecosystem/
├── index.html # Main map UI (single-page app)
├── data/
│ ├── repos.json # Single source of truth (84 repos)
│ └── chunks.json # Pre-computed embeddings (283 chunks, 7MB)
├── api/
│ ├── stars.js # Live star counts (1hr cache)
│ ├── stars-history.js # 30-day sparkline data
│ └── chat.js # RAG chatbot with streaming
├── scripts/
│ ├── build-chunks.js # Rebuild embeddings from research/
│ └── test-rag.js # RAG quality tests (27 test cases)
├── research/ # 27 knowledge base files
└── lib/redis.js # Shared Redis clientdata/repos.json{
"categories": {
"skills": [
{
"name": "hermes-skill-example",
"url": "https://github.com/username/hermes-skill-example",
"description": "Brief description of what the skill does",
"tags": ["tag1", "tag2"]
}
]
}
}skillstoolspluginsdeploymentsframeworksintegrationsforksuidataresearchtemplatesmisc# Check JSON syntax
node -e "require('./data/repos.json')"
# Preview locally
open index.htmlresearch/# Set API key
export OPENROUTER_API_KEY=sk-or-v1-...
# Rebuild chunks.json (splits + embeds)
node scripts/build-chunks.js
# Test RAG quality
node scripts/test-rag.js.mdresearch/text-embedding-3-smalldata/chunks.jsonProcessing research/agent-architecture.md...
Processing research/hermes-skills.md...
...
✅ Built 283 chunks (7.2 MB)export OPENROUTER_API_KEY=sk-or-v1-...
node scripts/test-rag.js// scripts/test-rag.js excerpt
const tests = [
{
query: "How do I create a custom Hermes skill?",
expectedKeywords: ["skill.md", "yaml", "frontmatter", "triggers"]
},
{
query: "What's the difference between a skill and a tool?",
expectedKeywords: ["skill", "tool", "integration", "plugin"]
}
];Test 1/27: How do I create a custom Hermes skill?
✅ Found 4/4 keywords in context
...
27/27 passed (100%)repos.jsonGITHUB_TOKEN{
"username/repo": 142,
"anotheruser/hermes-skill": 89
}const response = await fetch('/api/stars');
const stars = await response.json();
document.querySelector('[data-repo="username/repo"]').textContent = stars['username/repo'];{
"user/repo1": [120, 122, 125, 128, 130, ...],
"user/repo2": [45, 47, 49, 51, 53, ...]
}{
"message": "How do I deploy Hermes Agent?",
"conversationHistory": [
{"role": "user", "content": "What is Hermes Agent?"},
{"role": "assistant", "content": "Hermes Agent is..."}
]
}data: {"type":"context","chunks":[{"text":"...","file":"deployment.md"}]}
data: {"type":"token","content":"To deploy"}
data: {"type":"token","content":" Hermes Agent"}
data: {"type":"done"}# Required
OPENROUTER_API_KEY=sk-or-v1-...
REDIS_URL=redis://default:password@host:port
# Optional
GITHUB_TOKEN=ghp_... # Fine-grained PAT (public read-only)
OPENROUTER_MODEL=google/gemma-4-31b-it:free # Primary LLM
OPENROUTER_FALLBACK_MODELS=google/gemma-4-26b-it:free,google/gemini-3-flash-1.5{
"functions": {
"api/**/*.js": {
"maxDuration": 30
}
},
"crons": [
{
"path": "/api/stars-daily-snapshot",
"schedule": "0 0 * * *"
}
]
}// scripts/batch-add.js (create this if needed)
const fs = require('fs');
const repos = require('../data/repos.json');
const newProjects = [
{ name: "hermes-skill-web-search", url: "https://github.com/...", category: "skills" },
{ name: "hermes-tool-calendar", url: "https://github.com/...", category: "tools" }
];
newProjects.forEach(proj => {
repos.categories[proj.category].push({
name: proj.name,
url: proj.url,
description: "", // Fill in manually
tags: []
});
});
fs.writeFileSync('./data/repos.json', JSON.stringify(repos, null, 2));// scripts/security-check.js (conceptual)
const checks = [
{
name: "No hardcoded credentials",
test: (code) => !/api[_-]?key\s*=\s*["'][^"']+["']/i.test(code)
},
{
name: "No eval() usage",
test: (code) => !/eval\(/.test(code)
},
{
name: "Dependencies up to date",
test: async (repo) => {
// Check package.json for known vulnerable versions
}
}
];// From index.html (adapted for skill documentation)
function renderSparkline(history) {
const max = Math.max(...history);
const min = Math.min(...history);
const range = max - min || 1;
const points = history.map((val, i) => {
const x = (i / (history.length - 1)) * 100;
const y = 100 - ((val - min) / range) * 100;
return `${x},${y}`;
}).join(' ');
return `<svg viewBox="0 0 100 100"><polyline points="${points}" /></svg>`;
}Error: 429 Too Many Requestsasync function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
for (const chunk of chunks) {
const embedding = await getEmbedding(chunk.text);
chunk.embedding = embedding;
await sleep(100); // 10 req/sec max
}ECONNREFUSEDETIMEDOUTREDIS_URL# Correct format
redis://default:password@host.region.cloud.redislabs.com:12345
# Common mistake (missing default user)
redis://:password@host...# Via Redis CLI
redis-cli -u $REDIS_URL
> DEL stars:cache// api/stars.js — force refresh
if (req.query.refresh === 'true') {
await redis.del('stars:cache');
}node scripts/test-rag.js --verbose
# Review chunks.json for short/low-quality chunks
node -e "
const chunks = require('./data/chunks.json');
const short = chunks.filter(c => c.text.length < 200);
console.log('Short chunks:', short.length);
"build-chunks.jsconst CHUNK_SIZE = 800; // was 500
const OVERLAP = 150; // was 100403 rate limit exceededGITHUB_TOKENGITHUB_TOKEN=ghp_...# Open the map in a browser (API endpoints won't work locally)
open index.html
# Test API endpoints locally (requires env vars)
export OPENROUTER_API_KEY=...
export REDIS_URL=...
vercel devvercel dev# Deploy to Vercel
vercel --prod
# Set environment variables
vercel env add OPENROUTER_API_KEY
vercel env add REDIS_URL
vercel env add GITHUB_TOKEN/api/stars-daily-snapshot