SkillHub is an enterprise-grade, self-hosted agent skill registry for publishing, discovering, and managing reusable skill packages across an organization. It provides a REST API backend, a React web UI, a security scanner, and a ClawHub CLI compatibility layer.
| Item | Value |
|---|---|
| Backend | Spring Boot 3.2.3, Java 21, Maven multi-module (7 modules) |
| Frontend | React 19, TypeScript, Vite, pnpm |
| Scanner | Python (FastAPI), port 8000 |
| Database | PostgreSQL 16 (Flyway migrations) |
| Cache | Redis 7 (sessions, distributed locks, idempotency) |
| Storage | LocalFile (dev) / S3/MinIO (prod) |
| Build | make dev-all (dev), make staging (pre-PR) |
| Docs | docs/ (design), document/ (VitePress user guide) |
| CI | GitHub Actions (.github/workflows/) |
skillhub/
├── server/ # Maven multi-module Spring Boot backend
│ ├── skillhub-app/ # Application layer: bootstrap, controllers, assembly
│ │ ├── bootstrap/ # Bootstrap admin & local dev data initializers
│ │ ├── compat/ # ClawHub CLI compatibility layer controllers
│ │ ├── config/ # Spring configuration classes
│ │ ├── controller/ # REST controllers (transport only)
│ │ │ ├── admin/ # Admin controllers (user mgmt, labels, search)
│ │ │ ├── portal/ # Portal controllers (skills, governance, security)
│ │ │ └── support/ # Package extractors (zip, multipart)
│ │ ├── dto/ # Request/response DTOs
│ │ ├── exception/ # Exception handling
│ │ ├── filter/ # Servlet filters (auth context, rate limiting)
│ │ ├── listener/ # Event listeners (notification recipients, etc.)
│ │ ├── metrics/ # Micrometer metrics
│ │ ├── projection/ # Lifecycle projection models
│ │ ├── ratelimit/ # Rate limiting logic
│ │ ├── repository/ # Query repositories (read-model assembly)
│ │ ├── security/ # Security configuration
│ │ ├── service/ # App services (workflow orchestration)
│ │ ├── stream/ # SSE streaming endpoints
│ │ ├── task/ # Background task scheduling
│ │ └── SkillhubApplication.java # Spring Boot entry point
│ │
│ ├── skillhub-domain/ # Domain layer: entities, rules, services (innermost)
│ │ ├── audit/ # AuditLog entity, repository, service
│ │ ├── auth/ # Password reset entities
│ │ ├── event/ # Domain event classes (SkillPublishedEvent, etc.)
│ │ ├── governance/ # Governance notification service
│ │ ├── idempotency/ # Idempotency records
│ │ ├── label/ # Skill label management
│ │ ├── namespace/ # Namespace, members, roles, policies
│ │ ├── report/ # Skill reporting/governance
│ │ ├── review/ # Review tasks, promotion requests
│ │ ├── security/ # Security scanning domain model
│ │ ├── shared/ # Shared domain utilities
│ │ │ └── exception/ # Domain exceptions (LocalizedDomainException, etc.)
│ │ ├── skill/ # Core skill entities and services
│ │ │ ├── metadata/ # SKILL.md frontmatter parsing
│ │ │ ├── service/ # Skill domain services (publish, query, governance)
│ │ │ └── validation/ # Package validation (SkillPackagePolicy, etc.)
│ │ ├── social/ # Star, rating, subscription entities
│ │ └── user/ # UserAccount, profile moderation
│ │
│ ├── skillhub-auth/ # Authentication & authorization
│ │ ├── config/ # Spring Security configuration
│ │ ├── device/ # OAuth Device Flow for CLI auth
│ │ ├── identity/ # Identity binding service
│ │ ├── local/ # Local (password) auth
│ │ ├── merge/ # Account merging
│ │ ├── oauth/ # OAuth2 login handlers
│ │ ├── policy/ # Route security policies
│ │ ├── rbac/ # RBAC service and role definitions
│ │ ├── token/ # API token management
│ │ └── user/ # User-related auth services
│ │
│ ├── skillhub-search/ # Search SPI + PostgreSQL full-text implementation
│ │ ├── postgres/ # PostgresFullTextIndexService, QueryService
│ │ └── service/ # Search SPI interfaces
│ │
│ ├── skillhub-storage/ # Object storage SPI
│ │ ├── local/ # LocalFileStorageService
│ │ └── s3/ # S3StorageService (AWS SDK v2)
│ │
│ ├── skillhub-infra/ # Infrastructure: JPA repos, utilities
│ │ └── repository/ # Spring Data JPA repository implementations
│ │
│ ├── skillhub-notification/ # Notification service (SSE, email)
│ │ ├── domain/ # Notification domain model
│ │ ├── service/ # Notification delivery services
│ │ └── sse/ # SSE endpoint support
│ │
│ ├── Dockerfile.dev # Dockerfile for staging builds
│ ├── Dockerfile # Production multi-stage build
│ ├── pom.xml # Parent POM (Spring Boot 3.2.3 parent)
│ └── scripts/
│ └── run-dev-app.sh # Local dev startup script
│
├── web/ # React frontend (Vite + pnpm)
│ ├── src/
│ │ ├── api/ # OpenAPI-generated types + fetch client
│ │ │ └── generated/
│ │ │ └── schema.d.ts # Generated OpenAPI types (CHECKED IN)
│ │ ├── app/ # Router, layout, global providers
│ │ ├── docs/ # In-app documentation pages
│ │ ├── entities/ # Domain entity display logic
│ │ │ ├── skill/ # Skill card, detail components
│ │ │ ├── user/ # User profile components
│ │ │ └── namespace/ # Namespace display components
│ │ ├── features/ # Business feature modules
│ │ │ ├── admin/ # Admin panel features
│ │ │ ├── auth/ # Login, OAuth flows
│ │ │ ├── governance/ # Skill governance actions
│ │ │ ├── namespace/ # Namespace management
│ │ │ ├── notification/ # User notifications
│ │ │ ├── promotion/ # Skill promotion workflows
│ │ │ ├── publish/ # Skill upload/publish UI
│ │ │ ├── report/ # Skill reporting
│ │ │ ├── review/ # Review workflow UI
│ │ │ ├── search/ # Skill search and filtering
│ │ │ ├── security-audit/ # Security audit viewer
│ │ │ ├── skill/ # Skill detail, listing
│ │ │ ├── social/ # Stars, ratings, subscriptions
│ │ │ └── token/ # API token management
│ │ ├── i18n/ # Internationalization
│ │ ├── pages/ # Route-level page components
│ │ ├── shared/ # Shared UI, hooks, utilities
│ │ │ ├── components/ # Reusable UI components
│ │ │ ├── hooks/ # Custom React hooks
│ │ │ ├── lib/
│ │ │ │ └── utils.ts # cn() class merging utility
│ │ │ └── ui/ # Radix UI-based primitives
│ │ └── types/ # Additional TypeScript types
│ ├── e2e/ # Playwright E2E tests
│ ├── nginx.conf.template # Nginx runtime config template
│ ├── Dockerfile # Multi-stage build (Node → Nginx)
│ └── package.json # Dependencies (React 19, TanStack Query, Radix UI, etc.)
│
├── scanner/ # Security scanner (Python/FastAPI)
│ ├── docs/ # Scanner documentation
│ ├── examples/ # Example scan inputs/outputs
│ └── Dockerfile # Scanner container build
│
├── docs/ # Design documents (source of truth)
│ ├── prds/ # Product requirement documents
│ ├── skillhub/ # VitePress user guide source
│ └── superpowers/ # Internal tooling docs
│
├── document/ # VitePress documentation site (published)
│ ├── docs/ # Markdown documentation
│ ├── src/ # VitePress theme
│ └── i18n/ # Internationalization
│
├── deploy/k8s/ # Kubernetes manifests (basic)
├── monitoring/ # Prometheus + Grafana stack
├── scripts/ # Build, test, and deployment scripts
│ ├── smoke-test.sh # Basic API smoke test
│ ├── namespace-smoke-test.sh # Namespace workflow smoke test
│ ├── governance-smoke-test.sh # Governance flow smoke test
│ ├── promotion-smoke-test.sh # Promotion flow smoke test
│ ├── check-openapi-generated.sh # Verify OpenAPI SDK is not stale
│ ├── validate-release-config.sh # Validate release env configuration
│ ├── dev-process.sh # Local process manager (PID-based)
│ ├── runtime.sh # Runtime deployment script
│ ├── parallel-init.sh # Parallel worktree initialization
│ ├── parallel-sync.sh # Merge worktrees in integration branch
│ ├── parallel-up.sh # Merge + start dev environment
│ ├── parallel-down.sh # Stop parallel dev environment
│ └── prepare-pr-batch.sh # Batch PR preparation
│
├── .github/
│ ├── workflows/ # GitHub Actions CI/CD
│ ├── ISSUE_TEMPLATE/ # Issue templates
│ └── scripts/ # Deno scripts for triage, release notes, rewards
│
├── AGENTS.md # AI agent rules (this file)
├── .agents/skills/ # Focused AI skill definitions
├── Makefile # Top-level build/test/dev orchestration
├── docker-compose.yml # Local dev dependency services
├── compose.release.yml # Production release compose file
├── CONTRIBUTING.md # Contribution guidelines
├── CODE_OF_CONDUCT.md # Community standards
└── README.md # Project overview
Key Locations for Common Tasks:
| Task | Where to Look |
|---|---|
| Add REST endpoint | server/skillhub-app/src/main/java/com/iflytek/skillhub/controller/ |
| Add domain entity/service | server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/ |
| Add auth logic | server/skillhub-auth/src/main/java/com/iflytek/skillhub/auth/ |
| Add search logic | server/skillhub-search/src/main/java/com/iflytek/skillhub/search/ |
| Add query repository | server/skillhub-app/src/main/java/com/iflytek/skillhub/repository/ |
| Change RBAC/roles | server/skillhub-auth/src/main/java/com/iflytek/skillhub/auth/rbac/ |
| Change skill validation | server/skillhub-domain/src/main/java/com/iflytek/skillhub/domain/skill/validation/ |
| Add frontend page | web/src/pages/ |
| Add frontend feature | web/src/features/ |
| Add shared component | web/src/shared/components/ |
| Change API contract | Backend controller → run make generate-api → commit generated file |
| Add smoke test | scripts/ (new .sh file) |
| Add E2E test | web/e2e/ (Playwright) |
| Add backend test | server/skillhub-*/src/test/java/ (alongside source module) |
web/src/api/generated/schema.d.ts— regenerated viamake generate-apidocument/docs/— auto-generated user documentation (VitePress)server/skillhub-app/src/main/java/com/iflytek/skillhub/dto/— some DTOs may be generated
Backend changes:
- Edit Java code →
make dev-server-restart(local dev) - Add/modify controller →
make generate-apito regenerate frontend types - Add/modify domain service →
make test-backend-appto verify tests
Frontend changes:
- Edit TypeScript/React → Vite HMR handles reload automatically
- After
make generate-api→ commit updatedweb/src/api/generated/schema.d.ts
Always run before PR:
make test-backend-app # Backend tests (with dependent modules)
make typecheck-web # Frontend type check
make lint-web # Frontend lint
make staging # Full staging regression + smoke test- Controllers (
skillhub-app/controller/) are transport only: extract auth context, bind request params, wrap responses. No business logic. - App Services (
skillhub-app/service/) orchestrate workflows. Do not embed complex read-model assembly here — extract to query repositories. - Query Repositories (
skillhub-app/repository/) handle read-model joins and presentation projection. Named like*QueryRepository. - Domain Services (
skillhub-domain/*/service/) contain business rules and state transitions. Return domain objects, not DTOs. - Repository Interfaces are defined in
skillhub-domain, implemented inskillhub-infra. - Domain Exceptions use
LocalizedDomainExceptionfor user-facing messages with i18n keys. - Package-info files (
package-info.java) should exist for all packages.
make dev-all # Start full stack: Postgres, Redis, MinIO, backend, frontend
make dev-all-down # Stop everything
make dev-all-reset # Full reset (clears data volumes)
make dev-status # Check service status
make dev-server-restart # Restart backend after Java changesAccess points:
- Web UI:
http://localhost:3000 - Backend API:
http://localhost:8080 - Scanner:
http://localhost:8000
Local mock users (no password needed):
| User ID | Role | Header |
|---|---|---|
local-user |
Regular user | X-Mock-User-Id: local-user |
local-admin |
Super admin | X-Mock-User-Id: local-admin |
Bootstrap admin (password-based, local profile):
- Username:
admin/ Password:ChangeMe!2026 - Disable with
BOOTSTRAP_ADMIN_ENABLED=false
# Backend: enforced by Maven build (no separate lint target)
# Frontend:
make lint-web # ESLint check
make typecheck-web # TypeScript checkmake test-backend-app # Backend unit tests (skillhub-app + dependencies)
make test-backend # All backend module tests
make test-frontend # Frontend unit tests (Vitest)
make test-e2e-frontend # Frontend E2E tests (Playwright)
make test-e2e-smoke-frontend # Frontend E2E smoke tests
./scripts/smoke-test.sh # API smoke test
make namespace-smoke # Namespace workflow smoke testmake staging # Build backend Docker image + frontend static + smoke test
make staging-down # Tear down
SERVICE=web make staging-logs # View Nginx logsStaging validates the containerized deployment path:
- Backend: built as Docker image from local source
- Frontend: built as static files, served by Nginx
- Dependencies: same Postgres/Redis/MinIO as local dev
For parallel development with isolated worktrees:
make parallel-init TASK=feature-nameCreates dedicated Claude, Codex, and integration worktrees as sibling directories.
See docs/13-parallel-workflow.md for details.
Use conventional commit style:
<type>(<scope>): <description>
Types:
feat: New featurefix: Bug fixdocs: Documentation changestest: Adding or updating testsrefactor: Code restructuring (no behavior change)chore: Build, CI, or maintenance tasks
Scopes: Module or domain name (e.g., auth, search, publish, review, namespace)
Examples:
feat(auth): add local account login
fix(publish): resolve null pointer in skill validation
docs(deploy): clarify runtime image usage
test(namespace): add membership service tests
refactor(review): extract query repository for governance list
chore(ci): add parallel workflow scripts
- Backend tests pass:
make test-backend-app - Frontend typecheck passes:
make typecheck-web - If API changed:
make generate-apiwas run andweb/src/api/generated/schema.d.tsis committed - Smoke test passes:
make staging - Follow existing module boundaries and dependency direction
- Add/update tests for new behavior
- Update docs when APIs, auth flows, deployment, or operator workflows change
app → domain, auth, search, storage, infra, notification
infra → domain # implements domain repository interfaces
auth → domain
search → domain
notification → domain
storage → (independent) # pure SPI
Design intent: skillhub-domain is the innermost layer. It defines entities, repository
interfaces, and domain services without depending on infra, auth, search, or storage.
Code reality: skillhub-domain declares a Maven dependency on skillhub-storage, and several
domain services (SkillHardDeleteService, SkillDownloadService, SkillPublishService,
SkillGovernanceService, SkillQueryService, SkillStorageDeletionCompensationService) import
com.iflytek.skillhub.storage.ObjectStorageService. This is an existing deviation from the ideal.
New code should avoid adding further cross-module dependencies from domain.
When adding new read logic, follow these rules:
- Domain repository ports (
skillhub-domain): Aggregate reads, state transitions, rule evaluation. Used by domain services. - App query repositories (
com.iflytek.skillhub.repository): Read-model assembly that joins multiple sources, presentation projection. Used by controllers and app services. - App services (
com.iflytek.skillhub.service): Workflow orchestration. Should express "what this endpoint does", not "how it assembles DTOs". - Direct SQL / EntityManager: Only when necessary, with class-level comment explaining why.
Do not add complex read-model assembly logic inside app services. Extract it into a query repository when it joins multiple sources, does presentation projection, or is reused across services.
SkillVersionStatus values: DRAFT, SCANNING, SCAN_FAILED, UPLOADED, PENDING_REVIEW,
PUBLISHED, REJECTED, YANKED.
SkillStatus enum values: ACTIVE, HIDDEN, ARCHIVED.
The design doc (docs/14-skill-lifecycle.md) specifies that hidden should be treated as a
governance overlay rather than a lifecycle state. The current code still defines
SkillStatus.HIDDEN in the enum. Follow the design doc's intent for new code.
Key transitions:
- Normal user first upload →
PENDING_REVIEW(no initial DRAFT) - SUPER_ADMIN first upload →
PUBLISHED(direct publish) - Review approve →
PENDING_REVIEW→PUBLISHED(updateslatestVersionId) - Review reject →
PENDING_REVIEW→REJECTED - Withdraw review →
PENDING_REVIEW→UPLOADED(also deletes pending review_task) - Yank →
PUBLISHED→YANKED(must recalculatelatestVersionId) - Hide/restore → independent
hiddenflag (governance overlay) - Archive/Unarchive →
ACTIVE↔ARCHIVED(container state)
SkillHub uses @{namespace_slug}/{skill_slug}:
@global/my-skill— Platform-level public namespace@my-team/my-skill— Team/department namespace
ClawHub CLI compatibility maps:
| SkillHub | Canonical Slug |
|---|---|
@global/my-skill |
my-skill |
@team-name/my-skill |
team-name--my-skill |
- Web: OAuth2 (GitHub) + local password auth
- CLI: OAuth Device Flow (web authorization → CLI credentials)
- Programmatic: API tokens (prefix-based secure hashing)
- Session: Spring Session + Redis
Platform roles: SUPER_ADMIN, SKILL_ADMIN, USER_ADMIN, AUDITOR
Namespace roles: OWNER, ADMIN, MEMBER
- Root:
SKILL.mdwith YAML frontmatter (name,descriptionrequired) - Allowed extensions (50+ types):
.md,.txt,.json,.yaml,.yml,.js,.ts,.py,.sh,.png,.jpg,.svg, and many more (seeSkillPackagePolicy.ALLOWED_EXTENSIONS) - Limits: 10MB per file, 100MB total, 500 files max
- File type signatures validated (PNG magic bytes, SVG content check, etc.)
- TanStack Query (
@tanstack/react-query): All server state (API data) - Zustand: Local/UI state (theme, sidebar, modals)
- Never use
useEffectfor data fetching
- Radix UI primitives:
@radix-ui/react-dropdown-menu,@radix-ui/react-select - class-variance-authority (cva) for component variants
- clsx + tailwind-merge for class merging
cn()utility:web/src/shared/lib/utils.ts- shadcn/ui is NOT used as a library — only Radix primitives + utility composition
Java:
- User identity type is always
Stringthroughout the codebase - Use Java 21 features (records, pattern matching, virtual threads)
- Follow existing naming patterns in the domain layer
- Error strings for
DomainBadRequestException, etc. should be clear and actionable
TypeScript:
- Strict mode. No
anytypes. - Use generated OpenAPI types for all API interactions.
- Feature-Sliced Design: place code at the lowest appropriate layer.
- Backend: JUnit 5 + Mockito + AssertJ
- Frontend: Vitest for unit tests, Playwright for E2E
- Use
make test-backend-app(includes-amfor dependent modules) — never run./mvnw -pl skillhub-app clean testdirectly, as it can use stale Maven cache artifacts - Test behaviors, not implementations
- Use Spring Boot test slices where possible (
@WebMvcTest,@DataJpaTest)
make test-frontend # Vitest unit tests
make test-e2e-frontend # Playwright E2E
make test-e2e-smoke-frontend # Playwright smoke (subset of E2E)- Backend: SLF4J + Spring Boot logging. Use structured logging with MDC for request tracing.
- Frontend:
console.errorfor errors,console.warnfor deprecations, avoidconsole.login production code. - Scanner: Python logging module with structured JSON output.
- API tokens are stored as prefix-based secure hashes, never in plaintext
- OAuth2 client secrets and other secrets must not be logged or committed
- User identity is
String(supports external SSO/OIDC/SCIM identity sources) - The bootstrap admin (
BOOTSTRAP_ADMIN_ENABLED) is for zero-config quickstart only
# Find all REST endpoints
rg "@(Get|Post|Put|Delete|Patch)Mapping" --type java
# Find domain services
rg "class.*Service" server/skillhub-domain/
# Find query repositories
rg "QueryRepository" server/skillhub-app/
# Find controllers
rg "@RestController" server/skillhub-app/
# Find RBAC role checks
rg "@PreAuthorize" server/skillhub-app/
# Find skill validation logic
rg "SkillPackage" server/skillhub-domain/
# Find frontend features
rg "export" web/src/features/
# Find OpenAPI type generation script
rg "generate-api" web/package.json
# Find event listeners
rg "@EventListener" server/- Hub first: The server-side registry is the core product; CLI and agent integrations are entry capabilities
- Compatibility first: Support
SKILL.mdformat and common directory conventions - Layered architecture: Search and object storage must have replaceable boundaries (SPI pattern)
- Open authentication: OAuth2-based, extensible to multiple providers beyond GitHub
- Audit first: Enterprise distribution requires audit trails for publish, download, delete, and authorization
Makefile— All build/test/dev automation targetsCONTRIBUTING.md— Contribution guidelines and commit styleCODE_OF_CONDUCT.md— Community standardsserver/pom.xml— Maven parent POM, module definitions, dependency versionsweb/package.json— Frontend dependencies and scripts.github/workflows/pr-tests.yml— PR test pipeline.github/workflows/publish-images.yml— Docker image publish to GHCR
server/skillhub-domain/— Core domain (entities, services, rules)server/skillhub-app/controller/— REST API endpointsserver/skillhub-app/repository/— Query repositoriesserver/skillhub-app/compat/— ClawHub CLI compatibility layerserver/skillhub-auth/— Authentication and authorizationweb/src/features/— Frontend feature modulesweb/src/api/generated/— Generated OpenAPI typesdocs/— Design documentsscripts/— Build, test, and deployment scripts
scripts/smoke-test.sh— Basic API smoke testscripts/namespace-smoke-test.sh— Namespace workflow testscripts/check-openapi-generated.sh— Verify frontend SDK is currentscripts/validate-release-config.sh— Validate production env configscripts/dev-process.sh— Local process manager (PID-based lifecycle)scripts/parallel-init.sh— Create isolated worktrees for parallel development
00-product-direction.md— Product positioning, MVP scope, coordinate system01-system-architecture.md— System architecture, module structure, dependency rules02-domain-model.md— Domain entities and relationships03-authentication-design.md— OAuth2, CLI Device Flow, API tokens04-search-architecture.md— Search SPI and implementations05-business-flows.md— Business process flows06-api-design.md— API contract specifications07-skill-protocol.md— SKILL.md format, package structure, CLI compatibility08-frontend-architecture.md— Frontend patterns and conventions14-skill-lifecycle.md— Skill state model (authoritative)dev-workflow.md— Local development workflow guide
- SkillHub Docs: https://iflytek.github.io/skillhub/
- DeepWiki: https://deepwiki.com/iflytek/skillhub
- Discord: https://discord.gg/qHYvtDNPHS
- OpenSkills: https://agents.md/ (skill package format reference)
- OpenClaw: https://github.com/openclaw/openclaw (CLI compatibility)
- AstronClaw: https://agent.xfyun.cn/astron-claw (cloud AI assistant integration)