skillhub/cli/src/commands/search.ts
dongmucat 351dddc912 feat(cli): add SkillHub CLI v1 with full command suite
Implement complete CLI tool for SkillHub with 12 commands, 7 backend API endpoints, and comprehensive documentation.

CLI Commands:
- help, version: Basic information
- login, logout, whoami: Authentication management
- search: Discover published skills
- install: Install skills to agent directories (14 Tier 1 agents supported)
- list, remove, doctor: Local skill management
- publish: Publish skill packages
- update: Self-update mechanism

Backend API:
- Add /api/cli/v1 endpoints for auth, search, resolve, download, delete, publish
- Implement CliAuthController and CliSkillController
- Add security policies for CLI routes
- Full test coverage (19 backend tests)

CLI Implementation:
- TypeScript with strict mode, Bun runtime
- Pure JS zip handling (fflate) for cross-platform compatibility
- 15 agent profiles (14 Tier 1 + generic fallback)
- Secure token storage (0600 permissions)
- Path safety validation for remove operations
- Comprehensive error handling (404/403/network distinction)
- 41 unit and integration tests

Documentation:
- CLI user guide (Chinese and English)
- README updates with quick start
- GitHub Actions workflow for cross-platform CI

Quality:
- lint: 0 errors
- typecheck: pass
- test: 41/41 pass
- build: 0.30 MB (target=node for npm/npx compatibility)
2026-04-29 15:37:04 +08:00

27 lines
1.1 KiB
TypeScript

import { SkillHubClient } from '../clients/skillhub-client'
import { ConfigStore } from '../stores/config-store'
import { CredentialsStore } from '../stores/credentials-store'
import { resolveRegistry, resolveToken } from '../services/registry-service'
export interface SearchCommandOptions {
registry?: string
token?: string
limit?: number
json?: boolean
}
export async function searchCommand(query: string, options: SearchCommandOptions): Promise<string> {
const configStore = new ConfigStore()
const credentialsStore = new CredentialsStore()
const registry = resolveRegistry(options, process.env, await configStore.read())
const token = resolveToken(options, process.env, await credentialsStore.getToken(registry))
const client = new SkillHubClient(registry, token)
const result = await client.search(query ?? '', options.limit ?? 20)
if (options.json) {
return JSON.stringify({ ok: true, items: result.items, total: result.total })
}
if (result.items.length === 0) return 'No skills found.'
return result.items
.map(item => `${item.namespace}/${item.slug} ${item.latestVersion ?? '-'} ${item.summary ?? ''}`)
.join('\n')
}