Stale Detection: - Detect skills removed/moved from GitHub (3 consecutive 404s threshold) - Hide stale skills from browse/search, show warning banner on detail page - Serve cached files with isStale flag when GitHub returns 404 - Add stale-check crawler command for batch verification - CLI shows warning when installing stale skills from cache Sentry & Error Handling: - Filter browser extension errors and add denyUrls - Anti-inflation measures and sentinel recalibration for curation Claim & Removal: - Enhanced ClaimForm with repo-level removal support - Add repo-removal-request API endpoint with tests - Improved owner page with bilingual content Review Pipeline: - Review version and reviewer tracking in submit API - Source format filter for pending reviews - Updated review tests Other: - Updated i18n strings (en/fa) - BrowseFilters improvements - Dockerfile updates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5.0 KiB
CLAUDE.md
Project Overview
SkillHub is an open-source marketplace for Agent Skills — folders containing a SKILL.md file with instructions that AI agents can load dynamically.
Live Site: https://skills.palebluedot.live | Status: Production (GET /api/stats)
Components:
- Web App (
apps/web): Next.js 15 marketplace - CLI (
apps/cli): Skill installer (npm install -g skillhub) - Indexer (
services/indexer): GitHub crawler - Packages (
packages/*): Core logic, DB, UI components
Common Commands
pnpm install # Install dependencies
pnpm dev # Start all apps
pnpm --filter @skillhub/web dev # Start only web app
pnpm build # Build all packages
pnpm test # Run all tests (248 total)
pnpm --filter @skillhub/web test:e2e # E2E tests (requires running app)
pnpm db:push # Push schema changes
docker compose up -d # Start all services
Architecture
skillhub/
├── apps/
│ ├── web/ # Next.js 15 + App Router + next-intl (i18n)
│ └── cli/ # Commander.js CLI, builds with tsup
├── packages/
│ ├── core/ # SKILL.md parser, validator, security scanner
│ ├── db/ # Drizzle ORM schema and queries
│ └── ui/ # Shared shadcn/ui components
├── services/
│ └── indexer/ # BullMQ worker for GitHub crawling
└── scripts/ # Database initialization scripts
Database
Schema files (keep in sync):
scripts/init-db.sql— SQL schemapackages/db/src/schema.ts— Drizzle ORM schemascripts/categories.sql— Production categoriesscripts/seed-data.sql— Dev sample data
Caching: Skill files cached in cached_files JSONB column, invalidated when commitSha changes.
Important Patterns
Next.js 15 Async Params
params and searchParams are Promises:
export default async function Page({ params }: { params: Promise<{ locale: string }> }) {
const { locale } = await params;
}
i18n (next-intl)
Routes use [locale] segment. Use setRequestLocale(locale) for static rendering.
Dynamic Rendering
Add export const dynamic = 'force-dynamic' to pages that fetch from database.
Package Imports
skillhub-core— Parser/validator@skillhub/db— Database@skillhub/ui— UI components
API Route Pattern
Skill IDs = owner/repo/skill-name. Use catch-all: /api/skills/[...id]/route.ts
CLI Skill ID Encoding
const encodedPath = id.split('/').map(encodeURIComponent).join('/');
Meilisearch IDs
Sanitized: anthropics/skills/pdf → anthropics__skills__pdf
Environment Variables
DATABASE_URL, REDIS_URL, GITHUB_TOKEN, MEILI_URL (optional), MEILI_MASTER_KEY, GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, AUTH_SECRET
Indexer
docker compose exec indexer node dist/crawl.js full # Full crawl
docker compose exec indexer node dist/crawl.js incremental # Last 24h
docker compose exec indexer node dist/crawl.js sync-meili # Sync to Meilisearch
docker compose exec indexer node dist/crawl.js deep-scan # Scan discovered repos
docker compose exec indexer node dist/crawl.js add-repo <owner/repo> # Manually add a repo to DB
docker compose exec indexer node dist/crawl.js process-add-requests # Process user-submitted add requests
Database Migration (container)
# Add new columns (run when schema changes are deployed)
docker compose exec db psql -U skillhub -d skillhub -c "ALTER TABLE skills ADD COLUMN IF NOT EXISTS is_owner_claimed boolean NOT NULL DEFAULT false;"
docker compose exec db psql -U skillhub -d skillhub -c "ALTER TABLE discovered_repos ADD COLUMN IF NOT EXISTS is_blocked boolean NOT NULL DEFAULT false;"
docker compose exec db psql -U skillhub -d skillhub -c "CREATE INDEX IF NOT EXISTS idx_skills_owner_claimed ON skills(is_owner_claimed) WHERE is_owner_claimed = true;"
docker compose exec db psql -U skillhub -d skillhub -c "CREATE INDEX IF NOT EXISTS idx_discovered_repos_blocked ON discovered_repos(is_blocked) WHERE is_blocked = true;"
Security
Status stored in security_status column: PASS (green) / WARNING (yellow) / FAIL (red). Indexer scans for dangerous commands, prompt injection, and data exfiltration.
Critical Files
| Category | Files |
|---|---|
| Database | packages/db/src/schema.ts, packages/db/src/queries.ts |
| API Routes | apps/web/app/api/skills/route.ts, apps/web/app/api/skill-files/route.ts |
| Auth | apps/web/lib/auth.ts, apps/web/components/AuthButton.tsx |
| Caching | apps/web/lib/cache.ts (Redis with TTL) |
| Rate Limiting | apps/web/lib/rate-limit.ts |
| Indexer | services/indexer/src/crawler.ts, services/indexer/src/strategies/ |
| CLI | apps/cli/src/commands/install.ts, apps/cli/src/utils/api.ts |