feat(skills): curated GitHub catalog redesign (#3016)

* feat(skills): remove ClawHub catalog integration

Drop the ClawHub registry as a skills catalog source across web server,
shared UI, VS Code, docs, and locales. The catalog now serves git-based
sources only: the curated Anthropic repo and user-defined repositories.
Also removes the now-unused adm-zip dependency.

* feat(skills): redesign catalog around curated GitHub repositories

Replace the single-source dropdown with a card grid of curated GitHub
repositories (Anthropic, OpenAI, Cursor pstack/skills, Matt Pocock) plus
user-defined sources. Source cards show skill counts, GitHub stars, and
last-updated time; a global search covers all loaded sources.

Server: curated sources gain GitHub repo metadata (stars, pushed_at)
fetched best-effort with a 3-hour in-memory and on-disk cache; scans
run through a concurrency-limited, deduplicated cache with 3-hour TTL
persisted across restarts. Refresh still bypasses the cache.

Shared UI: source cards, global search with clear button, per-skill
GitHub links, install/installed states. VS Code curated list updated
to match. All new copy translated across 12 locales.

* fix(skills): address catalog review findings

- GitHub metadata fetch timeout drops to 1.5s (under the catalog
  client's 3s deadline) and failed lookups cache briefly (5 min) so
  repeated catalog loads do not re-hit a failing API.
- Disk cache files are written with owner-only permissions (0o600);
  rename preserves the mode.
- loadSource deduplicates concurrent in-flight requests per source and
  the shared isLoadingSource flag now clears only when the last active
  source load finishes.
This commit is contained in:
Bohdan Triapitsyn
2026-08-20 01:40:10 +03:00
committed by GitHub
parent 90d8868bfc
commit 1ed3f1f575
45 changed files with 1143 additions and 1286 deletions
+5 -22
View File
@@ -1247,7 +1247,7 @@ export type RuntimeAPISelector<TValue> = (apis: RuntimeAPIs) => TValue;
type SkillsCatalogSourceId = string;
type SkillsCatalogSourceType = 'github' | 'clawdhub';
type SkillsCatalogSourceType = 'github';
export interface SkillsCatalogSource {
id: SkillsCatalogSourceId;
@@ -1256,6 +1256,10 @@ export interface SkillsCatalogSource {
source: string;
defaultSubpath?: string;
sourceType?: SkillsCatalogSourceType;
/** GitHub repository star count (null when unavailable) */
stars?: number | null;
/** GitHub repository last-push timestamp, ISO (null when unavailable) */
repoUpdatedAt?: string | null;
}
interface SkillsCatalogItemInstalledBadge {
@@ -1264,18 +1268,6 @@ interface SkillsCatalogItemInstalledBadge {
source?: 'opencode' | 'agents' | 'claude';
}
interface ClawdHubSkillMetadata {
slug: string;
version: string;
displayName?: string;
owner?: string;
downloads?: number;
stars?: number;
versionsCount?: number;
createdAt?: number;
updatedAt?: number;
}
export interface SkillsCatalogItem {
sourceId: SkillsCatalogSourceId;
repoSource: string;
@@ -1288,22 +1280,18 @@ export interface SkillsCatalogItem {
installable: boolean;
warnings?: string[];
installed?: SkillsCatalogItemInstalledBadge;
/** ClawdHub-specific metadata (present only for ClawdHub sources) */
clawdhub?: ClawdHubSkillMetadata;
}
export interface SkillsCatalogResponse {
ok: boolean;
sources?: SkillsCatalogSource[];
itemsBySource?: Record<SkillsCatalogSourceId, SkillsCatalogItem[]>;
pageInfoBySource?: Record<SkillsCatalogSourceId, { nextCursor?: string | null }>;
error?: { kind: string; message: string };
}
export interface SkillsCatalogSourceResponse {
ok: boolean;
items?: SkillsCatalogItem[];
nextCursor?: string | null;
error?: { kind: string; message: string };
}
@@ -1328,11 +1316,6 @@ export interface SkillsRepoScanResponse {
interface SkillsInstallSelection {
skillDir: string;
/** ClawdHub-specific metadata for installation */
clawdhub?: {
slug: string;
version: string;
};
}
export interface SkillsInstallRequest {