@peterson-benhame/agent-skills 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js.map ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../libs/core/src/lib/adapters/node-env.adapter.ts", "../../../libs/core/src/lib/adapters/node-filesystem.adapter.ts", "../../../libs/core/src/lib/adapters/node-http.adapter.ts", "../../../libs/core/src/lib/adapters/node-logger.adapter.ts", "../../../libs/core/src/lib/adapters/node-package-resolver.adapter.ts", "../../../libs/core/src/lib/adapters/node-paths.adapter.ts", "../../../libs/core/src/lib/adapters/node-shell.adapter.ts", "../../../libs/core/src/lib/adapters/index.ts", "../../../libs/core/src/lib/constants.ts", "../../../libs/core/src/lib/ports/env.port.ts", "../../../libs/core/src/lib/ports/filesystem.port.ts", "../../../libs/core/src/lib/ports/http.port.ts", "../../../libs/core/src/lib/ports/logger.port.ts", "../../../libs/core/src/lib/ports/package-resolver.port.ts", "../../../libs/core/src/lib/ports/paths.port.ts", "../../../libs/core/src/lib/ports/shell.port.ts", "../../../libs/core/src/lib/ports/index.ts", "../../../libs/core/src/lib/services/project-root.service.ts", "../../../libs/core/src/lib/services/agents.service.ts", "../../../libs/core/src/lib/services/audit-log.service.ts", "../../../libs/core/src/lib/utils.ts", "../../../libs/core/src/lib/services/categories.service.ts", "../../../libs/core/src/lib/services/global-path.service.ts", "../../../libs/core/src/lib/types.ts", "../../../libs/core/src/lib/services/lockfile.service.ts", "../../../libs/core/src/lib/services/registry.service.ts", "../../../libs/core/src/lib/services/installer.service.ts", "../../../libs/core/src/lib/services/markdown-parser.service.ts", "../../../libs/core/src/lib/services/skills-provider.service.ts", "../../../libs/core/src/lib/services/update.service.ts", "../../../libs/core/src/lib/services/index.ts", "../../../libs/core/src/index.ts", "../src/ports.ts", "../src/cli/install.ts", "../src/cli/remove.ts", "../src/cli/update.ts", "../src/cli/cache.ts", "../src/components/AuditLogViewer.tsx", "../src/cli/audit.ts", "../src/index.ts", "../src/app.tsx", "../src/hooks/useAgents.ts", "../src/hooks/useConfig.ts", "../src/utils/constants.ts", "../src/hooks/useFilter.ts", "../src/hooks/useInstaller.ts", "../src/hooks/useKonamiCode.ts", "../src/hooks/useRemover.ts", "../src/hooks/useSkillContent.ts", "../src/hooks/useSkills.ts", "../src/hooks/useWizardStep.ts", "../src/views/arcade/ArcadeMenu.tsx", "../src/components/FooterBar.tsx", "../src/theme/colors.ts", "../src/theme/symbols.ts", "../src/components/SelectPrompt.tsx", "../src/views/arcade/VibeInvaders.tsx", "../src/views/ActionSelector.tsx", "../src/components/Header.tsx", "../src/atoms/environmentCheck.ts", "../src/services/update-cache.ts", "../src/services/update-check.ts", "../src/services/package-info.ts", "../src/views/AgentSelector.tsx", "../src/components/KeyboardShortcutsOverlay.tsx", "../src/components/AnimatedTransition.tsx", "../src/components/MultiSelectPrompt.tsx", "../src/views/CreditsView.tsx", "../src/services/audio-player.ts", "../src/services/github-contributors.ts", "../src/views/InstallConfig.tsx", "../src/views/InstallWizard.tsx", "../src/atoms/installedSkills.ts", "../src/atoms/wizard.ts", "../src/components/InstallResults.tsx", "../src/views/RemoveWizard.tsx", "../src/atoms/deprecatedSkills.ts", "../src/views/SkillBrowser.tsx", "../src/components/CategoryHeader.tsx", "../src/services/badge-format.ts", "../src/components/ConfirmPrompt.tsx", "../src/components/SearchInput.tsx", "../src/components/SkillCard.tsx", "../src/components/StatusBadge.tsx", "../src/components/SkillDetailPanel.tsx", "../src/services/category-colors.ts", "../src/services/terminal-dimensions.ts", "../src/views/UpdateView.tsx", "../src/views/ListView.tsx"],
4
+ "sourcesContent": ["import { homedir, platform } from 'node:os'\n\nimport type { EnvPort } from '../ports'\n\n/**\n * Node.js implementation of {@link EnvPort} using process and os APIs.\n */\nexport class NodeEnvAdapter implements EnvPort {\n /**\n * @inheritdoc\n */\n public cwd(): string {\n return process.cwd()\n }\n\n /**\n * @inheritdoc\n */\n public homedir(): string {\n return homedir()\n }\n\n /**\n * @inheritdoc\n */\n public platform(): string {\n return platform()\n }\n\n /**\n * @inheritdoc\n */\n public getEnv(key: string): string | undefined {\n return process.env[key]\n }\n}\n", "import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs'\nimport {\n appendFile,\n cp,\n lstat,\n mkdir,\n readFile,\n readdir,\n readlink,\n rename,\n rm,\n symlink,\n writeFile,\n} from 'node:fs/promises'\n\nimport type { FileSystemPort } from '../ports'\n\n/**\n * Node.js implementation of {@link FileSystemPort}.\n *\n * This adapter is the single environment-specific implementation used by core\n * services for file system operations.\n */\nexport class NodeFileSystemAdapter implements FileSystemPort {\n /**\n * @inheritdoc\n */\n public async readFile(path: string, encoding: string): Promise<string> {\n return readFile(path, encoding as BufferEncoding)\n }\n\n /**\n * @inheritdoc\n */\n public async writeFile(path: string, content: string, encoding: string): Promise<void> {\n await writeFile(path, content, encoding as BufferEncoding)\n }\n\n /**\n * @inheritdoc\n */\n public writeFileSync(path: string, content: string, encoding: string): void {\n writeFileSync(path, content, encoding as BufferEncoding)\n }\n\n /**\n * @inheritdoc\n */\n public async appendFile(path: string, content: string, encoding: string): Promise<void> {\n await appendFile(path, content, encoding as BufferEncoding)\n }\n\n /**\n * @inheritdoc\n */\n public async mkdir(path: string, options?: { recursive?: boolean }): Promise<void> {\n await mkdir(path, options)\n }\n\n /**\n * @inheritdoc\n */\n public mkdirSync(path: string, options?: { recursive?: boolean }): void {\n mkdirSync(path, options)\n }\n\n /**\n * @inheritdoc\n */\n public async rm(path: string, options?: { recursive?: boolean; force?: boolean }): Promise<void> {\n await rm(path, options)\n }\n\n /**\n * @inheritdoc\n */\n public rmSync(path: string, options?: { recursive?: boolean; force?: boolean }): void {\n rmSync(path, options)\n }\n\n /**\n * @inheritdoc\n */\n public async rename(oldPath: string, newPath: string): Promise<void> {\n await rename(oldPath, newPath)\n }\n\n /**\n * @inheritdoc\n */\n public async cp(src: string, dest: string, options?: { recursive?: boolean }): Promise<void> {\n await cp(src, dest, options)\n }\n\n /**\n * @inheritdoc\n */\n public async symlink(target: string, linkPath: string, type?: string): Promise<void> {\n await symlink(target, linkPath, type)\n }\n\n /**\n * @inheritdoc\n */\n public async readlink(linkPath: string): Promise<string> {\n return readlink(linkPath)\n }\n\n /**\n * @inheritdoc\n */\n public async lstat(path: string): Promise<{ isDirectory(): boolean; isSymbolicLink(): boolean }> {\n return lstat(path)\n }\n\n /**\n * @inheritdoc\n */\n public async readdir(\n path: string,\n _options?: { withFileTypes: true },\n ): Promise<{ name: string; isDirectory(): boolean; isSymbolicLink?(): boolean }[]> {\n return readdir(path, { withFileTypes: true })\n }\n\n /**\n * @inheritdoc\n */\n public existsSync(path: string): boolean {\n return existsSync(path)\n }\n\n /**\n * @inheritdoc\n */\n public readFileSync(path: string, encoding: string): string {\n return readFileSync(path, encoding as BufferEncoding)\n }\n\n /**\n * @inheritdoc\n */\n public readdirSync(path: string, _options?: { withFileTypes: true }): { name: string; isDirectory(): boolean }[] {\n return readdirSync(path, { withFileTypes: true })\n }\n}\n", "import type { HttpPort } from '../ports'\n\n/**\n * Node.js implementation of {@link HttpPort} backed by native `fetch`.\n */\nexport class NodeHttpAdapter implements HttpPort {\n /**\n * @inheritdoc\n */\n public async get(\n url: string,\n ): Promise<{ ok: boolean; status: number; json(): Promise<unknown>; text(): Promise<string> }> {\n return fetch(url)\n }\n\n /**\n * @inheritdoc\n */\n public async getWithFallback(\n url: string,\n fallbackUrl?: string,\n ): Promise<{ ok: boolean; status: number; json(): Promise<unknown>; text(): Promise<string> }> {\n try {\n return await fetch(url)\n } catch (error) {\n if (fallbackUrl) return fetch(fallbackUrl)\n throw error\n }\n }\n}\n", "import type { LoggerPort } from '../ports'\n\n/**\n * Node.js implementation of {@link LoggerPort} using console methods.\n */\nexport class NodeLoggerAdapter implements LoggerPort {\n /**\n * @inheritdoc\n */\n public error(message: string): void {\n console.error(message)\n }\n\n /**\n * @inheritdoc\n */\n public warn(message: string): void {\n console.warn(message)\n }\n\n /**\n * @inheritdoc\n */\n public info(message: string): void {\n console.info(message)\n }\n\n /**\n * @inheritdoc\n */\n public debug(message: string): void {\n console.debug(message)\n }\n}\n", "import type { PackageResolverPort } from '../ports'\n\ntype PackageLookupResult = { version: string }\ntype PackageLookupFn = (packageName: string, options: { version: string }) => Promise<PackageLookupResult>\n\nconst defaultPackageLookup: PackageLookupFn = async (packageName, options) => {\n const module = await import('package-json')\n const lookup = module.default as PackageLookupFn\n return lookup(packageName, options)\n}\n\n/**\n * Node.js implementation of {@link PackageResolverPort} using `package-json`.\n */\nexport class NodePackageResolverAdapter implements PackageResolverPort {\n private readonly resolvePackage: PackageLookupFn\n\n /**\n * Creates a package resolver adapter.\n *\n * @param resolvePackage - Optional package lookup function for testing.\n */\n public constructor(resolvePackage: PackageLookupFn = defaultPackageLookup) {\n this.resolvePackage = resolvePackage\n }\n\n /**\n * @inheritdoc\n */\n public async getLatestVersion(packageName: string): Promise<string> {\n const pkg = await this.resolvePackage(packageName, { version: 'latest' })\n return pkg.version\n }\n}\n", "import { existsSync } from 'node:fs'\nimport { dirname, join, parse, resolve } from 'node:path'\n\nimport type { PathsPort } from '../ports'\n\nconst SKILLS_CATALOG_SEGMENTS = ['packages', 'skills-catalog', 'skills'] as const\n\ntype ExistsSyncFn = (path: string) => boolean\n\nfunction findWorkspaceRoot(startDir: string, existsSyncFn: ExistsSyncFn): string {\n const fallbackDir = resolve(startDir)\n let currentDir = fallbackDir\n const { root } = parse(currentDir)\n\n while (true) {\n if (existsSyncFn(join(currentDir, ...SKILLS_CATALOG_SEGMENTS))) return currentDir\n if (currentDir === root) return fallbackDir\n currentDir = dirname(currentDir)\n }\n}\n\n/**\n * Node.js implementation of {@link PathsPort} using filesystem lookups.\n */\nexport class NodePathsAdapter implements PathsPort {\n public constructor(\n private readonly startDir = process.cwd(),\n private readonly existsSyncFn: ExistsSyncFn = existsSync,\n ) {}\n\n /**\n * @inheritdoc\n */\n public getWorkspaceRoot(): string {\n return findWorkspaceRoot(this.startDir, this.existsSyncFn)\n }\n\n /**\n * @inheritdoc\n */\n public getSkillsCatalogPath(): string {\n return join(this.getWorkspaceRoot(), ...SKILLS_CATALOG_SEGMENTS)\n }\n\n /**\n * @inheritdoc\n */\n public getLocalSkillsDirectory(): string | null {\n const path = this.getSkillsCatalogPath()\n return this.existsSyncFn(path) ? path : null\n }\n}\n", "import { execSync } from 'node:child_process'\n\nimport type { ShellPort } from '../ports'\n\n/**\n * Node.js implementation of {@link ShellPort} using `execSync`.\n */\nexport class NodeShellAdapter implements ShellPort {\n /**\n * @inheritdoc\n */\n public exec(command: string, options?: { encoding?: string }): string {\n return execSync(command, {\n encoding: (options?.encoding ?? 'utf-8') as BufferEncoding,\n })\n }\n}\n", "import type { CorePorts } from '../ports'\n\nimport { NodeEnvAdapter } from './node-env.adapter'\nimport { NodeFileSystemAdapter } from './node-filesystem.adapter'\nimport { NodeHttpAdapter } from './node-http.adapter'\nimport { NodeLoggerAdapter } from './node-logger.adapter'\nimport { NodePackageResolverAdapter } from './node-package-resolver.adapter'\nimport { NodePathsAdapter } from './node-paths.adapter'\nimport { NodeShellAdapter } from './node-shell.adapter'\n\nexport * from './node-env.adapter'\nexport * from './node-filesystem.adapter'\nexport * from './node-http.adapter'\nexport * from './node-logger.adapter'\nexport * from './node-package-resolver.adapter'\nexport * from './node-paths.adapter'\nexport * from './node-shell.adapter'\n\n/**\n * Creates the default Node.js adapter set for all core infrastructure ports.\n *\n * @returns A fully wired {@link CorePorts} object backed by Node.js APIs.\n *\n * @example\n * ```ts\n * import { createNodeAdapters } from '@peterson-benhame/core'\n *\n * const ports = createNodeAdapters()\n * const cwd = ports.env.cwd()\n * const localDir = ports.paths.getLocalSkillsDirectory()\n * ```\n */\nexport function createNodeAdapters(): CorePorts {\n return {\n fs: new NodeFileSystemAdapter(),\n http: new NodeHttpAdapter(),\n shell: new NodeShellAdapter(),\n env: new NodeEnvAdapter(),\n logger: new NodeLoggerAdapter(),\n packageResolver: new NodePackageResolverAdapter(),\n paths: new NodePathsAdapter(),\n }\n}\n", "import type { CategoryInfo } from './types'\n\n/** Relative path to the local skills catalog in the monorepo. */\nexport const SKILLS_CATALOG_DIR = 'packages/skills-catalog/skills'\n/** Fallback category id used when a skill has no explicit category. */\nexport const DEFAULT_CATEGORY_ID = 'uncategorized'\n/** Matches category folder names such as `(frontend)` or `(quality-tools)`. */\nexport const CATEGORY_FOLDER_PATTERN = /^\\(([a-z][a-z0-9-]*)\\)$/\n/** File that stores category metadata overrides inside the skills catalog. */\nexport const CATEGORY_METADATA_FILE = '_category.json'\n\n/**\n * Default category object used when no category metadata is available.\n *\n * @example\n * ```ts\n * DEFAULT_CATEGORY.id // 'uncategorized'\n * ```\n */\nexport const DEFAULT_CATEGORY: CategoryInfo = {\n id: DEFAULT_CATEGORY_ID,\n name: 'Uncategorized',\n description: 'Skills without a specific category',\n priority: 999,\n}\n\n/** Package name for the CLI distribution. */\nexport const PACKAGE_NAME = '@peterson-benhame/agent-skills'\n/** Package name for the published skills catalog. */\nexport const SKILLS_CATALOG_PACKAGE = '@peterson-benhame/skills-catalog'\n/** Project directory used to store agent-specific state. */\nexport const AGENTS_DIR = '.agents'\n/** Canonical directory that stores local skill sources. */\nexport const CANONICAL_SKILLS_DIR = 'skills'\n/** Lockfile name used to track installed skills. */\nexport const LOCK_FILE = '.skill-lock.json'\n/** Backup filename created during atomic lockfile writes. */\nexport const LOCK_FILE_BACKUP = '.skill-lock.json.backup'\n/** Global configuration directory stored in the user home directory. */\nexport const GLOBAL_CONFIG_DIR = '.agent-skills'\n/** Audit log filename stored under the global config directory. */\nexport const AUDIT_LOG_FILE = 'audit.log'\n/** Base cache directory relative to the user home directory. */\nexport const CACHE_BASE_DIR = '.cache'\n/** Namespace folder nested under the base cache directory. */\nexport const CACHE_NAMESPACE = 'agent-skills'\n/** Skills cache subdirectory name. */\nexport const SKILLS_SUBDIR = 'skills'\n/** Filename for the cached registry payload. */\nexport const REGISTRY_CACHE_FILENAME = 'registry.json'\n/** Filename for per-skill cache metadata. */\nexport const SKILL_META_FILE = '.skill-meta.json'\n/** Registry cache time-to-live in milliseconds. */\nexport const REGISTRY_CACHE_TTL_MS = 24 * 60 * 60 * 1000\n/** HTTP fetch timeout in milliseconds for registry and skill downloads. */\nexport const FETCH_TIMEOUT_MS = 15_000\n/** Maximum number of HTTP retries for registry and skill downloads. */\nexport const MAX_RETRIES = 3\n/** Initial retry delay in milliseconds before exponential backoff. */\nexport const RETRY_BASE_DELAY_MS = 500\n/** Maximum number of concurrent file downloads per skill install. */\nexport const MAX_CONCURRENT_DOWNLOADS = 10\n", "/**\n * Environment and process information required by core services.\n */\nexport interface EnvPort {\n /**\n * Returns the current working directory.\n *\n * @returns The current working directory path.\n */\n cwd(): string\n\n /**\n * Returns the current user's home directory.\n *\n * @returns The home directory path.\n */\n homedir(): string\n\n /**\n * Returns the current operating system platform identifier.\n *\n * @returns The platform identifier.\n */\n platform(): string\n\n /**\n * Reads an environment variable.\n *\n * @param key - Environment variable name.\n * @returns The variable value when defined; otherwise `undefined`.\n */\n getEnv(key: string): string | undefined\n}\n", "/**\n * Filesystem operations required by core services.\n */\nexport interface FileSystemPort {\n /**\n * Reads a text file from disk.\n *\n * @param path - Absolute or relative file path to read.\n * @param encoding - Text encoding used to decode the file contents.\n * @returns A promise that resolves to the file contents.\n */\n readFile(path: string, encoding: string): Promise<string>\n\n /**\n * Writes a text file to disk, replacing any existing content.\n *\n * @param path - Absolute or relative file path to write.\n * @param content - Text content to persist.\n * @param encoding - Text encoding used to encode the file contents.\n * @returns A promise that resolves when the file has been written.\n */\n writeFile(path: string, content: string, encoding: string): Promise<void>\n\n /**\n * Writes a text file to disk synchronously, replacing any existing content.\n *\n * @param path - Absolute or relative file path to write.\n * @param content - Text content to persist.\n * @param encoding - Text encoding used to encode the file contents.\n */\n writeFileSync(path: string, content: string, encoding: string): void\n\n /**\n * Appends text content to an existing file.\n *\n * @param path - Absolute or relative file path to append to.\n * @param content - Text content to append.\n * @param encoding - Text encoding used to encode the appended content.\n * @returns A promise that resolves when the content has been appended.\n */\n appendFile(path: string, content: string, encoding: string): Promise<void>\n\n /**\n * Creates a directory.\n *\n * @param path - Directory path to create.\n * @param options - Optional directory creation behavior.\n * @returns A promise that resolves when the directory exists.\n */\n mkdir(path: string, options?: { recursive?: boolean }): Promise<void>\n\n /**\n * Creates a directory synchronously.\n *\n * @param path - Directory path to create.\n * @param options - Optional directory creation behavior.\n */\n mkdirSync(path: string, options?: { recursive?: boolean }): void\n\n /**\n * Removes a file system path.\n *\n * @param path - File or directory path to remove.\n * @param options - Optional removal behavior.\n * @returns A promise that resolves when the path has been removed.\n */\n rm(path: string, options?: { recursive?: boolean; force?: boolean }): Promise<void>\n\n /**\n * Removes a file system path synchronously.\n *\n * @param path - File or directory path to remove.\n * @param options - Optional removal behavior.\n */\n rmSync(path: string, options?: { recursive?: boolean; force?: boolean }): void\n\n /**\n * Renames or moves a file system path.\n *\n * @param oldPath - Existing file or directory path.\n * @param newPath - New file or directory path.\n * @returns A promise that resolves when the path has been renamed.\n */\n rename(oldPath: string, newPath: string): Promise<void>\n\n /**\n * Copies a file or directory.\n *\n * @param src - Source file or directory path.\n * @param dest - Destination file or directory path.\n * @param options - Optional copy behavior.\n * @returns A promise that resolves when the copy has completed.\n */\n cp(src: string, dest: string, options?: { recursive?: boolean }): Promise<void>\n\n /**\n * Creates a symbolic link.\n *\n * @param target - Target path the symlink should point to.\n * @param linkPath - Path where the symlink should be created.\n * @param type - Optional symlink type hint for the platform.\n * @returns A promise that resolves when the symlink has been created.\n */\n symlink(target: string, linkPath: string, type?: string): Promise<void>\n\n /**\n * Resolves the target of a symbolic link.\n *\n * @param linkPath - Symlink path to inspect.\n * @returns A promise that resolves to the symlink target path.\n */\n readlink(linkPath: string): Promise<string>\n\n /**\n * Retrieves file system metadata for a path without following symlinks.\n *\n * @param path - File or directory path to inspect.\n * @returns A promise that resolves to metadata helpers for the path.\n */\n lstat(path: string): Promise<{ isDirectory(): boolean; isSymbolicLink(): boolean }>\n\n /**\n * Lists the entries in a directory.\n *\n * @param path - Directory path to read.\n * @param options - Optional read behavior.\n * @returns A promise that resolves to the discovered directory entries.\n */\n readdir(\n path: string,\n options?: { withFileTypes: true },\n ): Promise<{ name: string; isDirectory(): boolean; isSymbolicLink?(): boolean }[]>\n\n /**\n * Checks whether a path exists.\n *\n * @param path - File or directory path to check.\n * @returns `true` when the path exists; otherwise `false`.\n */\n existsSync(path: string): boolean\n\n /**\n * Reads a text file synchronously.\n *\n * @param path - Absolute or relative file path to read.\n * @param encoding - Text encoding used to decode the file contents.\n * @returns The file contents.\n */\n readFileSync(path: string, encoding: string): string\n\n /**\n * Lists directory entries synchronously.\n *\n * @param path - Directory path to read.\n * @param options - Optional read behavior.\n * @returns The discovered directory entries.\n */\n readdirSync(path: string, options?: { withFileTypes: true }): { name: string; isDirectory(): boolean }[]\n}\n", "/**\n * HTTP operations required by core services.\n */\nexport interface HttpPort {\n /**\n * Performs an HTTP GET request.\n *\n * @param url - Absolute URL to request.\n * @returns A promise that resolves to a minimal response object.\n */\n get(url: string): Promise<{ ok: boolean; status: number; json(): Promise<unknown>; text(): Promise<string> }>\n\n /**\n * Performs an HTTP GET request and optionally retries against a fallback URL.\n *\n * @param url - Primary absolute URL to request.\n * @param fallbackUrl - Optional fallback URL used when the primary request fails.\n * @returns A promise that resolves to a minimal response object.\n */\n getWithFallback(\n url: string,\n fallbackUrl?: string,\n ): Promise<{ ok: boolean; status: number; json(): Promise<unknown>; text(): Promise<string> }>\n}\n", "/**\n * Logging methods required by core services.\n */\nexport interface LoggerPort {\n /**\n * Logs an error-level message.\n *\n * @param message - Message to record.\n * @returns Nothing.\n */\n error(message: string): void\n\n /**\n * Logs a warning-level message.\n *\n * @param message - Message to record.\n * @returns Nothing.\n */\n warn(message: string): void\n\n /**\n * Logs an info-level message.\n *\n * @param message - Message to record.\n * @returns Nothing.\n */\n info(message: string): void\n\n /**\n * Logs a debug-level message.\n *\n * @param message - Message to record.\n * @returns Nothing.\n */\n debug(message: string): void\n}\n", "/**\n * Package registry lookups required by core services.\n */\nexport interface PackageResolverPort {\n /**\n * Resolves the latest published version of a package.\n *\n * @param packageName - Package name to resolve.\n * @returns A promise that resolves to the latest version string.\n */\n getLatestVersion(packageName: string): Promise<string>\n}\n", "/**\n * Workspace and catalog path resolution required by core services.\n */\nexport interface PathsPort {\n /**\n * Returns the workspace root directory.\n *\n * @returns The resolved workspace root path.\n */\n getWorkspaceRoot(): string\n\n /**\n * Returns the local skills catalog path.\n *\n * @returns The absolute skills catalog path.\n */\n getSkillsCatalogPath(): string\n\n /**\n * Returns the local skills directory when available.\n *\n * @returns The local skills directory path or `null` when unavailable.\n */\n getLocalSkillsDirectory(): string | null\n}\n", "/**\n * Shell command execution required by core services.\n */\nexport interface ShellPort {\n /**\n * Executes a shell command synchronously.\n *\n * @param command - Shell command to execute.\n * @param options - Optional execution settings.\n * @returns The command output as text.\n */\n exec(command: string, options?: { encoding?: string }): string\n}\n", "export * from './env.port'\nexport * from './filesystem.port'\nexport * from './http.port'\nexport * from './logger.port'\nexport * from './package-resolver.port'\nexport * from './paths.port'\nexport * from './shell.port'\n\nimport type { EnvPort } from './env.port'\nimport type { FileSystemPort } from './filesystem.port'\nimport type { HttpPort } from './http.port'\nimport type { LoggerPort } from './logger.port'\nimport type { PackageResolverPort } from './package-resolver.port'\nimport type { PathsPort } from './paths.port'\nimport type { ShellPort } from './shell.port'\n\n/**\n * Aggregates all infrastructure ports required by core services.\n *\n * @example\n * ```ts\n * const ports: CorePorts = {\n * fs,\n * http,\n * shell,\n * env,\n * logger,\n * packageResolver,\n * paths,\n * }\n * ```\n */\nexport interface CorePorts {\n /** Filesystem adapter used by core services. */\n fs: FileSystemPort\n /** HTTP adapter used by core services. */\n http: HttpPort\n /** Shell adapter used by core services. */\n shell: ShellPort\n /** Environment adapter used by core services. */\n env: EnvPort\n /** Logger adapter used by core services. */\n logger: LoggerPort\n /** Package resolver adapter used by core services. */\n packageResolver: PackageResolverPort\n /** Path resolver adapter used by core services. */\n paths: PathsPort\n}\n", "import { dirname, join, parse, resolve, sep } from 'node:path'\nimport type { CorePorts } from '../ports'\n\nconst PROJECT_MARKERS = ['package.json', '.git'] as const\n\n/**\n * Locates the project root directory by walking upwards until a marker file or directory is found.\n *\n * @param ports - Core ports that expose filesystem and environment accessors.\n * @param startDir - Optional directory to start the search from. Defaults to the current working directory.\n * @returns The nearest directory containing {@link PROJECT_MARKERS} or the original search directory if nothing is found.\n * @example\n * ```ts\n * const root = findProjectRoot(ports, '/home/dev/agent-skills/packages/cli/src')\n * ```\n */\nexport function findProjectRoot(ports: CorePorts, startDir?: string): string {\n const fallbackDir = startDir ?? ports.env.cwd()\n let currentDir = resolve(fallbackDir)\n const { root } = parse(currentDir)\n const cliSuffix = `packages${sep}cli`\n\n while (currentDir !== root) {\n if (PROJECT_MARKERS.some((marker) => ports.fs.existsSync(join(currentDir, marker)))) {\n const isCliPackage = currentDir.endsWith(cliSuffix)\n if (!isCliPackage) return currentDir\n }\n\n currentDir = dirname(currentDir)\n }\n\n return fallbackDir\n}\n", "import { join } from 'node:path'\n\nimport type { CorePorts } from '../ports'\nimport type { AgentConfig, AgentType } from '../types'\n\nimport { findProjectRoot } from './project-root.service'\n\ntype AgentContext = {\n home: string\n projectRoot: string\n ports: CorePorts\n}\n\ntype AgentDefinition = {\n displayName: string\n description: string\n skillsDir: string\n globalSkillsDir: (home: string) => string\n detectInstalled: (context: AgentContext) => boolean\n}\n\nexport type AgentCatalogEntry = {\n type: AgentType\n displayName: string\n description: string\n skillsDir: string\n globalSkillsDir: string\n}\n\nconst agentDefinitions: Record<AgentType, AgentDefinition> = {\n // Tier 1: Most popular AI coding agents\n cursor: {\n displayName: 'Cursor',\n description: 'AI-first code editor built on VS Code',\n skillsDir: '.cursor/skills',\n globalSkillsDir: (home) => join(home, '.cursor/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.cursor')) || ports.fs.existsSync(join(projectRoot, '.cursor')),\n },\n 'claude-code': {\n displayName: 'Claude Code',\n description: \"Anthropic's agentic coding tool\",\n skillsDir: '.claude/skills',\n globalSkillsDir: (home) => join(home, '.claude/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.claude')) || ports.fs.existsSync(join(projectRoot, '.claude')),\n },\n 'github-copilot': {\n displayName: 'GitHub Copilot',\n description: 'AI pair programmer by GitHub/Microsoft',\n skillsDir: '.github/skills',\n globalSkillsDir: (home) => join(home, '.copilot/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.copilot')) || ports.fs.existsSync(join(projectRoot, '.github')),\n },\n windsurf: {\n displayName: 'Windsurf',\n description: 'AI IDE with Cascade flow (Codeium)',\n skillsDir: '.windsurf/skills',\n globalSkillsDir: (home) => join(home, '.codeium/windsurf/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.codeium/windsurf')) || ports.fs.existsSync(join(projectRoot, '.windsurf')),\n },\n cline: {\n displayName: 'Cline',\n description: 'Autonomous AI coding agent for VS Code',\n skillsDir: '.cline/skills',\n globalSkillsDir: (home) => join(home, '.cline/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.cline')) ||\n ports.fs.existsSync(join(projectRoot, '.cline')) ||\n isExtensionInstalled({ home, ports }, 'saoudrizwan', 'claude-dev'),\n },\n\n // Tier 2: Rising stars\n aider: {\n displayName: 'Aider',\n description: 'AI pair programming in terminal',\n skillsDir: '.aider/skills',\n globalSkillsDir: (home) => join(home, '.aider/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.aider')) || ports.fs.existsSync(join(projectRoot, '.aider')),\n },\n codex: {\n displayName: 'OpenAI Codex',\n description: \"OpenAI's coding agent\",\n skillsDir: '.codex/skills',\n globalSkillsDir: (home) => join(home, '.codex/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.codex')) || ports.fs.existsSync(join(projectRoot, '.codex')),\n },\n gemini: {\n displayName: 'Gemini CLI',\n description: \"Google's AI coding assistant\",\n skillsDir: '.gemini/skills',\n globalSkillsDir: (home) => join(home, '.gemini/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.gemini')) || ports.fs.existsSync(join(projectRoot, '.gemini')),\n },\n antigravity: {\n displayName: 'Antigravity',\n description: \"Google's agentic coding (VS Code)\",\n skillsDir: '.agent/skills',\n globalSkillsDir: (home) => join(home, '.gemini/antigravity/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.gemini/antigravity')) || ports.fs.existsSync(join(projectRoot, '.agent')),\n },\n roo: {\n displayName: 'Roo Code',\n description: 'AI coding assistant for VS Code',\n skillsDir: '.roo/skills',\n globalSkillsDir: (home) => join(home, '.roo/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.roo')) ||\n ports.fs.existsSync(join(projectRoot, '.roo')) ||\n isExtensionInstalled({ home, ports }, 'RooVetGit', 'roo-cline'),\n },\n kilocode: {\n displayName: 'Kilo Code',\n description: 'AI coding agent with auto-launch',\n skillsDir: '.kilocode/skills',\n globalSkillsDir: (home) => join(home, '.kilocode/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.kilocode')) || ports.fs.existsSync(join(projectRoot, '.kilocode')),\n },\n trae: {\n displayName: 'TRAE',\n description: 'AI IDE with SOLO mode and custom agents',\n skillsDir: '.trae/skills',\n globalSkillsDir: (home) => join(home, '.trae/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.trae')) || ports.fs.existsSync(join(projectRoot, '.trae')),\n },\n kiro: {\n displayName: 'Kiro',\n description: 'AI Agent with workspace and global skill scopes',\n skillsDir: '.kiro/skills',\n globalSkillsDir: (home) => join(home, '.kiro/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.kiro')) || ports.fs.existsSync(join(projectRoot, '.kiro')),\n },\n\n // Tier 3: Enterprise & specialized\n 'amazon-q': {\n displayName: 'Amazon Q',\n description: 'AWS AI coding assistant',\n skillsDir: '.amazonq/skills',\n globalSkillsDir: (home) => join(home, '.amazonq/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.amazonq')) || ports.fs.existsSync(join(projectRoot, '.amazonq')),\n },\n augment: {\n displayName: 'Augment',\n description: 'AI code assistant with context engine',\n skillsDir: '.augment/skills',\n globalSkillsDir: (home) => join(home, '.augment/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.augment')) || ports.fs.existsSync(join(projectRoot, '.augment')),\n },\n tabnine: {\n displayName: 'Tabnine',\n description: 'AI code completions with privacy focus',\n skillsDir: '.tabnine/skills',\n globalSkillsDir: (home) => join(home, '.tabnine/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.tabnine')) || ports.fs.existsSync(join(projectRoot, '.tabnine')),\n },\n opencode: {\n displayName: 'OpenCode',\n description: 'Open-source AI coding terminal',\n skillsDir: '.opencode/skills',\n globalSkillsDir: (home) => join(home, '.config/opencode/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.config/opencode')) ||\n ports.fs.existsSync(join(projectRoot, '.opencode')) ||\n ports.fs.existsSync(join(projectRoot, '.config/opencode')),\n },\n sourcegraph: {\n displayName: 'Sourcegraph Cody',\n description: 'AI assistant with codebase context',\n skillsDir: '.sourcegraph/skills',\n globalSkillsDir: (home) => join(home, '.sourcegraph/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.sourcegraph')) || ports.fs.existsSync(join(projectRoot, '.sourcegraph')),\n },\n droid: {\n displayName: 'Droid (Factory.ai)',\n description: 'AI software engineer by Factory.ai',\n skillsDir: '.factory/skills',\n globalSkillsDir: (home) => join(home, '.factory/skills'),\n detectInstalled: ({ home, projectRoot, ports }) =>\n ports.fs.existsSync(join(home, '.factory')) || ports.fs.existsSync(join(projectRoot, '.factory')),\n },\n}\n\nconst createAgentContext = (ports: CorePorts): AgentContext => ({\n home: ports.env.homedir(),\n projectRoot: findProjectRoot(ports),\n ports,\n})\n\n/**\n * Returns all supported agent types sorted alphabetically by display name.\n *\n * @returns All supported agent types in display-name order.\n * @example\n * ```ts\n * const agentTypes = getAllAgentTypes()\n * ```\n */\nexport function getAllAgentTypes(): AgentType[] {\n return (Object.keys(agentDefinitions) as AgentType[]).sort((a, b) =>\n agentDefinitions[a].displayName.localeCompare(agentDefinitions[b].displayName),\n )\n}\n\n/**\n * Returns the full configuration for a supported agent type.\n *\n * @param ports - Core ports used to resolve environment-dependent paths and checks.\n * @param type - The agent type to resolve.\n * @returns The full configuration for the requested agent type.\n * @example\n * ```ts\n * const config = getAgentConfig(ports, 'cursor')\n * ```\n */\n/**\n * Environment-independent view of every supported agent, for consumers that need the catalog\n * without a filesystem (docs generation, the marketplace site, static builds).\n *\n * why: `getAgentConfig` resolves paths against a real `$HOME` through ports, so build-time\n * consumers had no way to read agent metadata without faking an environment.\n *\n * @param homePlaceholder - Token substituted for the user's home directory in global paths.\n * @returns One entry per supported agent, in display-name order.\n * @example\n * ```ts\n * const catalog = getAgentCatalog()\n * ```\n */\nexport function getAgentCatalog(homePlaceholder = '~'): AgentCatalogEntry[] {\n return getAllAgentTypes().map((type) => {\n const definition = agentDefinitions[type]\n\n return {\n type,\n displayName: definition.displayName,\n description: definition.description,\n skillsDir: definition.skillsDir,\n globalSkillsDir: definition.globalSkillsDir(homePlaceholder),\n }\n })\n}\n\nexport function getAgentConfig(ports: CorePorts, type: AgentType): AgentConfig {\n const definition = agentDefinitions[type]\n const context = createAgentContext(ports)\n\n return {\n name: type,\n displayName: definition.displayName,\n description: definition.description,\n skillsDir: definition.skillsDir,\n globalSkillsDir: definition.globalSkillsDir(context.home),\n detectInstalled: () => definition.detectInstalled(context),\n }\n}\n\n/**\n * Detects which supported agents are installed on the current system.\n *\n * @param ports - Core ports used to check filesystem presence.\n * @returns The installed agent types.\n * @example\n * ```ts\n * const installedAgents = detectInstalledAgents(ports)\n * ```\n */\nexport function detectInstalledAgents(ports: CorePorts): AgentType[] {\n const context = createAgentContext(ports)\n\n return (Object.entries(agentDefinitions) as [AgentType, AgentDefinition][])\n .filter(([, definition]) => definition.detectInstalled(context))\n .map(([type]) => type)\n}\n\nconst isExtensionInstalled = (\n context: Pick<AgentContext, 'home' | 'ports'>,\n publisher: string,\n name: string,\n): boolean => {\n const extensionsDirs = [\n join(context.home, '.vscode/extensions'),\n join(context.home, '.vscode-server/extensions'),\n join(context.home, '.vscode-oss/extensions'),\n ]\n\n for (const dir of extensionsDirs) {\n if (context.ports.fs.existsSync(dir)) {\n try {\n const entries = context.ports.fs.readdirSync(dir)\n if (entries.some((entry) => entry.name.startsWith(`${publisher}.${name}-`))) {\n return true\n }\n } catch {\n // Ignore errors accessing extension dirs\n }\n }\n }\n\n return false\n}\n", "import { join } from 'node:path'\n\nimport { AUDIT_LOG_FILE, GLOBAL_CONFIG_DIR } from '../constants'\nimport type { CorePorts } from '../ports'\nimport type { AuditEntry } from '../types'\n\nfunction resolveBaseDir(ports: CorePorts, baseDir?: string): string {\n return baseDir ?? ports.env.homedir()\n}\n\n/**\n * Resolves the shared audit log path in the user's global agent-skills directory.\n *\n * @param ports - Core ports that expose environment access.\n * @param baseDir - Optional base directory override. Defaults to the current home directory.\n * @returns The absolute path to the shared audit log file.\n *\n * @example\n * ```ts\n * const auditLogPath = getAuditLogPath(ports)\n * const testAuditLogPath = getAuditLogPath(ports, '/tmp/test-home')\n * ```\n */\nexport function getAuditLogPath(ports: CorePorts, baseDir?: string): string {\n return join(resolveBaseDir(ports, baseDir), GLOBAL_CONFIG_DIR, AUDIT_LOG_FILE)\n}\n\n/**\n * Appends an audit entry to the shared JSON-lines audit log.\n *\n * The log write is intentionally best-effort: filesystem failures are ignored so\n * install, remove, and update flows do not fail because of audit logging.\n *\n * @param ports - Core ports that expose filesystem and environment access.\n * @param entry - Audit payload to append.\n * @param baseDir - Optional base directory override. Defaults to the current home directory.\n * @returns A promise that resolves when the write completes or is skipped after an error.\n *\n * @example\n * ```ts\n * await logAudit(\n * ports,\n * {\n * action: 'install',\n * skillName: 'accessibility',\n * agents: ['Cursor'],\n * success: 1,\n * failed: 0,\n * },\n * )\n * ```\n */\nexport async function logAudit(ports: CorePorts, entry: AuditEntry, baseDir?: string): Promise<void> {\n try {\n const resolvedBaseDir = resolveBaseDir(ports, baseDir)\n const logPath = getAuditLogPath(ports, resolvedBaseDir)\n const logDir = join(resolvedBaseDir, GLOBAL_CONFIG_DIR)\n const logLine = `${JSON.stringify({ ...entry, timestamp: new Date().toISOString() })}\\n`\n\n await ports.fs.mkdir(logDir, { recursive: true })\n await ports.fs.appendFile(logPath, logLine, 'utf-8')\n } catch {\n // Best-effort operation.\n }\n}\n\n/**\n * Reads recent audit log entries from the shared JSON-lines audit log.\n *\n * @param ports - Core ports that expose filesystem and environment access.\n * @param limit - Optional maximum number of most-recent entries to return.\n * @param baseDir - Optional base directory override. Defaults to the current home directory.\n * @returns A promise that resolves to parsed audit entries ordered from newest to oldest.\n *\n * @example\n * ```ts\n * const entries = await readAuditLog(ports, 10)\n * const testEntries = await readAuditLog(ports, undefined, '/tmp/test-home')\n * ```\n */\nexport async function readAuditLog(ports: CorePorts, limit?: number, baseDir?: string): Promise<AuditEntry[]> {\n try {\n const content = await ports.fs.readFile(getAuditLogPath(ports, baseDir), 'utf-8')\n const lines = content.trim().split('\\n').filter(Boolean)\n const entries = lines\n .map((line) => {\n try {\n return JSON.parse(line) as AuditEntry\n } catch {\n return null\n }\n })\n .filter((entry): entry is AuditEntry => entry !== null)\n .reverse()\n\n if (limit === undefined) {\n return entries\n }\n\n if (limit <= 0) {\n return []\n }\n\n return entries.slice(0, limit)\n } catch {\n return []\n }\n}\n", "import { join, normalize, resolve, sep } from 'node:path'\n\nimport { CACHE_BASE_DIR, CACHE_NAMESPACE } from './constants'\n\n/**\n * Converts a category id such as `core-migration` into a display label.\n *\n * @param categoryId - Hyphenated category identifier.\n * @returns Human-friendly title-cased category name.\n *\n * @example\n * ```ts\n * formatCategoryName('core-migration') // 'Core Migration'\n * ```\n */\nexport function formatCategoryName(categoryId: string): string {\n return categoryId\n .split('-')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ')\n}\n\n/**\n * Sanitizes a skill or file name so it can be safely used in filesystem paths.\n *\n * @param name - Raw skill or file name.\n * @returns Sanitized name with unsafe path characters removed.\n *\n * @example\n * ```ts\n * sanitizeName('../my-skill') // 'my-skill'\n * ```\n */\nexport function sanitizeName(name: string): string {\n const sanitized = name\n .replace(/[/\\\\]/g, '')\n .replace(/[\\0:*?\"<>|]/g, '')\n .replace(/^[.\\s]+|[.\\s]+$/g, '')\n .replace(/\\.{2,}/g, '')\n .replace(/^\\.+/, '')\n\n return (sanitized || 'unnamed-skill').substring(0, 255)\n}\n\n/**\n * Verifies that a target path stays within the provided base path.\n *\n * @param basePath - Allowed root path.\n * @param targetPath - Candidate path to validate.\n * @returns `true` when the resolved target stays inside the base path.\n *\n * @example\n * ```ts\n * isPathSafe('/repo/.agents', '/repo/.agents/skills/accessibility') // true\n * ```\n */\nexport function isPathSafe(basePath: string, targetPath: string): boolean {\n const normalizedBase = normalize(resolve(basePath))\n const normalizedTarget = normalize(resolve(targetPath))\n return normalizedTarget.startsWith(normalizedBase + sep) || normalizedTarget === normalizedBase\n}\n\n/**\n * Returns the relative cache directory used by registry and download services.\n *\n * @returns Cache path relative to the user's home directory.\n *\n * @example\n * ```ts\n * getCacheDir() // '.cache/agent-skills'\n * ```\n */\nexport function getCacheDir(): string {\n return join(CACHE_BASE_DIR, CACHE_NAMESPACE)\n}\n", "import { join } from 'node:path'\n\nimport { CATEGORY_FOLDER_PATTERN, CATEGORY_METADATA_FILE, DEFAULT_CATEGORY, DEFAULT_CATEGORY_ID } from '../constants'\nimport type { CorePorts } from '../ports'\nimport type { CategoryInfo, CategoryMetadata } from '../types'\nimport { formatCategoryName } from '../utils'\n\nfunction getSkillsDir(ports: CorePorts): string {\n return ports.paths.getSkillsCatalogPath()\n}\n\n/**\n * Extracts a category id from a folder name such as `(frontend)`.\n *\n * @param folderName - Folder name from the skills catalog.\n * @returns The extracted category id or `null` when the folder is not a category folder.\n *\n * @example\n * ```ts\n * extractCategoryId('(frontend)') // 'frontend'\n * ```\n */\nexport function extractCategoryId(folderName: string): string | null {\n const match = folderName.match(CATEGORY_FOLDER_PATTERN)\n return match ? match[1] : null\n}\n\n/**\n * Checks whether a folder name matches the category-folder convention.\n *\n * @param folderName - Folder name to validate.\n * @returns `true` when the folder name follows the `(category-id)` pattern.\n *\n * @example\n * ```ts\n * isCategoryFolder('(quality)') // true\n * ```\n */\nexport function isCategoryFolder(folderName: string): boolean {\n return CATEGORY_FOLDER_PATTERN.test(folderName)\n}\n\n/**\n * Converts a category id into its folder representation.\n *\n * @param categoryId - Category identifier.\n * @returns Category folder name used in the skills catalog.\n *\n * @example\n * ```ts\n * categoryIdToFolderName('quality') // '(quality)'\n * ```\n */\nexport function categoryIdToFolderName(categoryId: string): string {\n return `(${categoryId})`\n}\n\n/**\n * Loads category metadata overrides from the local skills catalog.\n *\n * @param ports - Core ports used to locate and read the catalog metadata file.\n * @returns Parsed category metadata or an empty object when the file is missing or invalid.\n *\n * @example\n * ```ts\n * const metadata = loadCategoryMetadata(ports)\n * ```\n */\nexport function loadCategoryMetadata(ports: CorePorts): CategoryMetadata {\n const skillsDir = getSkillsDir(ports)\n const metadataPath = join(skillsDir, CATEGORY_METADATA_FILE)\n if (!ports.fs.existsSync(metadataPath)) return {}\n\n try {\n const content = ports.fs.readFileSync(metadataPath, 'utf-8')\n return JSON.parse(content) as CategoryMetadata\n } catch {\n return {}\n }\n}\n\n/**\n * Persists category metadata overrides to the local skills catalog.\n *\n * @param ports - Core ports used to locate and write the catalog metadata file.\n * @param metadata - Category metadata keyed by category folder name.\n * @returns Nothing.\n *\n * @example\n * ```ts\n * saveCategoryMetadata(ports, {\n * '(quality)': { name: 'Quality' },\n * })\n * ```\n */\nexport function saveCategoryMetadata(ports: CorePorts, metadata: CategoryMetadata): void {\n const skillsDir = getSkillsDir(ports)\n const metadataPath = join(skillsDir, CATEGORY_METADATA_FILE)\n const content = JSON.stringify(metadata, null, 2)\n ports.fs.writeFileSync(metadataPath, content + '\\n', 'utf-8')\n}\n\n/**\n * Returns every category discovered in the local skills catalog.\n *\n * @param ports - Core ports used to resolve the catalog path and read directory entries.\n * @returns Categories sorted alphabetically by display name.\n *\n * @example\n * ```ts\n * const categories = getCategories(ports)\n * ```\n */\nexport function getCategories(ports: CorePorts): CategoryInfo[] {\n const skillsDir = getSkillsDir(ports)\n if (!ports.fs.existsSync(skillsDir)) return []\n\n const metadata = loadCategoryMetadata(ports)\n const entries = ports.fs.readdirSync(skillsDir, { withFileTypes: true })\n const categories: CategoryInfo[] = []\n\n let index = 0\n for (const entry of entries) {\n if (!entry.isDirectory() || !isCategoryFolder(entry.name)) continue\n\n const categoryId = extractCategoryId(entry.name)\n if (!categoryId) continue\n\n const meta = metadata[entry.name] ?? {}\n categories.push({\n id: categoryId,\n name: meta.name ?? formatCategoryName(categoryId),\n description: meta.description,\n priority: meta.priority ?? index,\n })\n index++\n }\n\n categories.sort((a, b) => a.name.localeCompare(b.name))\n return categories\n}\n\n/**\n * Looks up a category by its identifier.\n *\n * @param ports - Core ports used to read the available categories.\n * @param id - Category identifier to search for.\n * @returns The matching category or `undefined` when it does not exist.\n *\n * @example\n * ```ts\n * const category = getCategoryById(ports, 'quality')\n * ```\n */\nexport function getCategoryById(ports: CorePorts, id: string): CategoryInfo | undefined {\n return getCategories(ports).find((category) => category.id === id)\n}\n\n/**\n * Resolves the category id for a skill folder in the local catalog.\n *\n * @param ports - Core ports used to inspect the local skills catalog.\n * @param skillName - Skill folder name to search for.\n * @returns The matching category id or the default uncategorized id.\n *\n * @example\n * ```ts\n * const categoryId = getSkillCategoryId(ports, 'accessibility')\n * ```\n */\nexport function getSkillCategoryId(ports: CorePorts, skillName: string): string {\n const skillsDir = getSkillsDir(ports)\n if (!ports.fs.existsSync(skillsDir)) return DEFAULT_CATEGORY_ID\n\n const entries = ports.fs.readdirSync(skillsDir, { withFileTypes: true })\n\n for (const entry of entries) {\n if (!entry.isDirectory() || !isCategoryFolder(entry.name)) continue\n\n const categoryId = extractCategoryId(entry.name)\n if (!categoryId) continue\n\n const categoryPath = join(skillsDir, entry.name)\n const skillPath = join(categoryPath, skillName)\n if (ports.fs.existsSync(join(skillPath, 'SKILL.md'))) return categoryId\n }\n\n return DEFAULT_CATEGORY_ID\n}\n\n/**\n * Resolves the full category information for a skill.\n *\n * @param ports - Core ports used to inspect skills and categories.\n * @param skillName - Skill folder name to search for.\n * @returns The matching category or the default uncategorized category.\n *\n * @example\n * ```ts\n * const category = getSkillCategory(ports, 'accessibility')\n * ```\n */\nexport function getSkillCategory(ports: CorePorts, skillName: string): CategoryInfo {\n const categoryId = getSkillCategoryId(ports, skillName)\n return getCategoryById(ports, categoryId) ?? DEFAULT_CATEGORY\n}\n\n/**\n * Checks whether a category exists in the local catalog.\n *\n * @param ports - Core ports used to read the available categories.\n * @param categoryId - Category identifier to look up.\n * @returns `true` when the category exists.\n *\n * @example\n * ```ts\n * const exists = categoryExists(ports, 'quality')\n * ```\n */\nexport function categoryExists(ports: CorePorts, categoryId: string): boolean {\n return getCategories(ports).some((category) => category.id === categoryId)\n}\n\n/**\n * Groups skills by their category information.\n *\n * @typeParam T - Skill-like object that exposes a `name` and optional `category`.\n * @param ports - Core ports used to read local categories when available.\n * @param skills - Skills to group.\n * @returns A map keyed by category info with alphabetically sorted skill lists.\n *\n * @example\n * ```ts\n * const grouped = groupSkillsByCategory(ports, [\n * { name: 'a11y', category: 'quality' },\n * { name: 'seo', category: 'quality' },\n * ])\n * ```\n */\nexport function groupSkillsByCategory<T extends { name: string; category?: string; description?: string }>(\n ports: CorePorts,\n skills: T[],\n): Map<CategoryInfo, T[]> {\n // Try to get local categories, fall back to building from skills\n let categories = getCategories(ports)\n\n // If no local categories, build from skills data\n if (categories.length === 0) {\n const categoryIds = new Set(skills.map((skill) => skill.category).filter(Boolean) as string[])\n categories = Array.from(categoryIds).map((id, index) => ({\n id,\n name: formatCategoryName(id),\n priority: index,\n }))\n }\n\n const grouped = new Map<CategoryInfo, T[]>()\n\n for (const category of categories) {\n grouped.set(category, [])\n }\n\n grouped.set(DEFAULT_CATEGORY, [])\n\n for (const skill of skills) {\n const categoryId = skill.category ?? DEFAULT_CATEGORY_ID\n let category = categories.find((candidate) => candidate.id === categoryId)\n\n // If category not found, create it dynamically\n if (!category && categoryId !== DEFAULT_CATEGORY_ID) {\n category = {\n id: categoryId,\n name: formatCategoryName(categoryId),\n priority: 999,\n }\n categories.push(category)\n grouped.set(category, [])\n }\n\n const targetCategory = category ?? DEFAULT_CATEGORY\n const group = grouped.get(targetCategory) ?? []\n group.push(skill)\n grouped.set(targetCategory, group)\n }\n\n for (const [category, skillList] of grouped) {\n if (skillList.length === 0) grouped.delete(category)\n }\n\n const sortedGrouped = new Map<CategoryInfo, T[]>()\n const sortedCategories = Array.from(grouped.keys()).sort((a, b) => a.name.localeCompare(b.name))\n\n for (const category of sortedCategories) {\n const categorySkills = grouped.get(category)\n\n if (categorySkills) {\n categorySkills.sort((a, b) => a.name.localeCompare(b.name))\n sortedGrouped.set(category, categorySkills)\n }\n }\n\n return sortedGrouped\n}\n", "import { join } from 'node:path'\n\nimport { PACKAGE_NAME } from '../constants'\nimport type { CorePorts } from '../ports'\n\n/**\n * Queries npm for the globally configured root directory.\n *\n * @param ports - Core ports that expose shell execution.\n * @returns The npm global root path or `null` if npm cannot be executed.\n * @example\n * ```ts\n * const root = getNpmGlobalRoot(ports)\n * ```\n */\nexport function getNpmGlobalRoot(ports: CorePorts): string | null {\n try {\n return ports.shell.exec('npm root -g', { encoding: 'utf-8' }).trim()\n } catch {\n return null\n }\n}\n\n/**\n * Determines if the CLI package is installed under npm's global root.\n *\n * @param ports - Core ports that expose shell execution and filesystem checks.\n * @returns `true` when the package exists in the npm global root; otherwise `false`.\n * @example\n * ```ts\n * const globalInstall = isGloballyInstalled(ports)\n * ```\n */\nexport function isGloballyInstalled(ports: CorePorts): boolean {\n const npmGlobalRoot = getNpmGlobalRoot(ports)\n if (!npmGlobalRoot) return false\n\n const packagePath = join(npmGlobalRoot, PACKAGE_NAME)\n return ports.fs.existsSync(packagePath)\n}\n", "/**\n * Describes a skill category exposed by the catalog or registry.\n *\n * @example\n * ```ts\n * const category: CategoryInfo = {\n * id: 'frontend',\n * name: 'Frontend',\n * description: 'UI and UX related skills',\n * priority: 10,\n * }\n * ```\n */\nexport interface CategoryInfo {\n /** Stable identifier used in paths and registry payloads. */\n id: string\n /** Human-readable category name. */\n name: string\n /** Optional short description displayed in UIs. */\n description?: string\n /** Lower numbers sort first when ordering categories. */\n priority?: number\n}\n\n/**\n * Stores optional metadata overrides keyed by category folder name.\n *\n * @example\n * ```ts\n * const metadata: CategoryMetadata = {\n * '(frontend)': {\n * name: 'Frontend',\n * description: 'UI focused skills',\n * priority: 1,\n * },\n * }\n * ```\n */\nexport interface CategoryMetadata {\n /** Metadata indexed by folder names such as `(frontend)`. */\n [categoryFolder: string]: {\n /** Optional display name override. */\n name?: string\n /** Optional description override. */\n description?: string\n /** Optional ordering override. */\n priority?: number\n }\n}\n\n/**\n * List of supported AI agent identifiers used for integration and configuration.\n */\nexport const AGENT_TYPES = [\n 'cursor',\n 'claude-code',\n 'github-copilot',\n 'windsurf',\n 'cline',\n 'aider',\n 'codex',\n 'gemini',\n 'antigravity',\n 'roo',\n 'kilocode',\n 'amazon-q',\n 'augment',\n 'tabnine',\n 'opencode',\n 'sourcegraph',\n 'droid',\n 'trae',\n 'kiro',\n] as const\n\n/**\n * Union type representing a valid AI agent identifier derived from {@link AGENT_TYPES}.\n */\nexport type AgentType = (typeof AGENT_TYPES)[number]\n\n/**\n * Defines how a supported agent stores project and global skills.\n *\n * @example\n * ```ts\n * const config: AgentConfig = {\n * name: 'cursor',\n * displayName: 'Cursor',\n * description: 'Cursor editor',\n * skillsDir: '.cursor/skills',\n * globalSkillsDir: '/home/user/.cursor/skills',\n * detectInstalled: () => true,\n * }\n * ```\n */\nexport interface AgentConfig {\n /** Internal agent identifier. */\n name: AgentType\n /** User-facing agent name. */\n displayName: string\n /** Short description of the agent integration. */\n description: string\n /** Project-local skills directory relative to the project root. */\n skillsDir: string\n /** Global skills directory in the user home directory. */\n globalSkillsDir: string\n /** Returns whether the agent is installed in the current environment. */\n detectInstalled: () => boolean\n}\n\n/**\n * Minimal skill information used across discovery and install flows.\n *\n * @example\n * ```ts\n * const skill: SkillInfo = {\n * name: 'accessibility',\n * description: 'Audit and improve web accessibility',\n * path: '/repo/skills/(quality)/accessibility',\n * category: 'quality',\n * }\n * ```\n */\nexport interface SkillInfo {\n /** Unique skill name. */\n name: string\n /** Short description shown in selection lists. */\n description: string\n /** Absolute or resolved path to the skill directory. */\n path: string\n /** Optional category identifier. */\n category?: string\n}\n\n/**\n * Options used when installing one or more skills.\n *\n * @example\n * ```ts\n * const options: InstallOptions = {\n * global: false,\n * method: 'symlink',\n * agents: ['cursor', 'codex'],\n * skills: ['accessibility'],\n * forceUpdate: true,\n * }\n * ```\n */\nexport interface InstallOptions {\n /** Whether the install targets the global agent directory. */\n global: boolean\n /** Installation strategy used for agent skill directories. */\n method: 'symlink' | 'copy'\n /** Agents that should receive the skill. */\n agents: AgentType[]\n /** Requested skill names. */\n skills: string[]\n /** Whether already installed skills should be refreshed. */\n forceUpdate?: boolean\n /** Whether the operation is part of an update flow. */\n isUpdate?: boolean\n}\n\n/**\n * Outcome of a single skill installation attempt.\n *\n * @example\n * ```ts\n * const result: InstallResult = {\n * agent: 'Cursor',\n * skill: 'accessibility',\n * path: '/repo/.cursor/skills/accessibility',\n * method: 'symlink',\n * success: true,\n * }\n * ```\n */\nexport interface InstallResult {\n /** Display name of the target agent. */\n agent: string\n /** Installed skill name. */\n skill: string\n /** Final installation path. */\n path: string\n /** Installation method actually used. */\n method: 'symlink' | 'copy'\n /** Whether installation completed successfully. */\n success: boolean\n /** Failure message when installation does not succeed. */\n error?: string\n /** Indicates a shared global symlink was reused. */\n usedGlobalSymlink?: boolean\n /** Indicates symlink creation failed and copy fallback was used. */\n symlinkFailed?: boolean\n}\n\n/**\n * Options used when removing installed skills.\n *\n * @example\n * ```ts\n * const options: RemoveOptions = {\n * global: true,\n * force: false,\n * }\n * ```\n */\nexport interface RemoveOptions {\n /** When set, restricts removal to global or local installs. */\n global?: boolean\n /** Removes paths even when the lockfile entry is missing. */\n force?: boolean\n}\n\n/**\n * Outcome of removing a skill from a single agent.\n *\n * @example\n * ```ts\n * const result: RemoveResult = {\n * skill: 'accessibility',\n * agent: 'Cursor',\n * success: false,\n * error: 'Skill not found',\n * }\n * ```\n */\nexport interface RemoveResult {\n /** Removed skill name. */\n skill: string\n /** Display name of the target agent. */\n agent: string\n /** Whether the removal succeeded. */\n success: boolean\n /** Failure reason when removal does not succeed. */\n error?: string\n}\n\n/**\n * Entry recorded for an installed skill in the shared lockfile.\n *\n * @example\n * ```ts\n * const entry: SkillLockEntry = {\n * name: 'accessibility',\n * source: 'registry',\n * contentHash: 'abc123',\n * installedAt: '2026-03-05T12:00:00.000Z',\n * updatedAt: '2026-03-05T12:00:00.000Z',\n * agents: ['cursor'],\n * method: 'symlink',\n * global: false,\n * version: '1.2.0',\n * }\n * ```\n */\nexport interface SkillLockEntry {\n /** Canonical skill name. */\n name: string\n /** Source of the installed skill, such as `local` or `registry`. */\n source: string\n /** Optional content hash used for update detection. */\n contentHash?: string\n /** ISO timestamp for the first install. */\n installedAt: string\n /** ISO timestamp for the most recent update. */\n updatedAt: string\n /** Agents currently associated with this skill. */\n agents?: AgentType[]\n /** Installation strategy used for this lock entry. */\n method?: 'copy' | 'symlink'\n /** Whether the skill was installed globally. */\n global?: boolean\n /** Optional published version when known. */\n version?: string\n}\n\n/**\n * Root structure of the shared skill lockfile.\n *\n * @example\n * ```ts\n * const lock: SkillLockFile = {\n * version: 2,\n * skills: {\n * accessibility: {\n * name: 'accessibility',\n * source: 'local',\n * installedAt: '2026-03-05T12:00:00.000Z',\n * updatedAt: '2026-03-05T12:00:00.000Z',\n * },\n * },\n * }\n * ```\n */\nexport interface SkillLockFile {\n /** Lockfile schema version. */\n version: number\n /** Installed skills indexed by skill name. */\n skills: Record<string, SkillLockEntry>\n}\n\n/**\n * Registry metadata for a single downloadable skill.\n *\n * @example\n * ```ts\n * const metadata: SkillMetadata = {\n * name: 'accessibility',\n * description: 'Audit and improve web accessibility',\n * category: 'quality',\n * path: '(quality)/accessibility',\n * files: ['SKILL.md'],\n * author: 'tech-leads-club',\n * version: '1.0.0',\n * contentHash: 'abc123',\n * }\n * ```\n */\nexport interface SkillMetadata {\n /** Unique skill name. */\n name: string\n /** Short description displayed in registry UIs. */\n description: string\n /** Category identifier for grouping and filtering. */\n category: string\n /** Relative path inside the catalog package. */\n path: string\n /** Files that belong to the skill package. */\n files: string[]\n /** Optional author metadata. */\n author?: string\n /** Optional version metadata. */\n version?: string\n /** Optional content hash used for cache validation. */\n contentHash?: string\n}\n\n/**\n * Full registry payload downloaded from the catalog CDN.\n *\n * @example\n * ```ts\n * const registry: SkillsRegistry = {\n * version: '1.0.0',\n * generatedAt: '2026-03-05T12:00:00.000Z',\n * baseUrl: 'https://cdn.example.com/skills',\n * categories: {\n * quality: { name: 'Quality' },\n * },\n * skills: [],\n * deprecated: [],\n * }\n * ```\n */\nexport interface SkillsRegistry {\n /** Registry package version or CDN ref. */\n version: string\n /** ISO timestamp when the registry was generated. */\n generatedAt: string\n /** Base URL used to resolve registry assets. */\n baseUrl: string\n /** Category definitions indexed by category id. */\n categories: Record<string, { name: string; description?: string }>\n /** All published skills available for download. */\n skills: SkillMetadata[]\n /** Optional deprecated skills metadata. */\n deprecated?: DeprecatedEntry[]\n}\n\n/**\n * Detailed per-agent audit result for install, remove, or update operations.\n *\n * @example\n * ```ts\n * const detail: AuditResultDetail = {\n * skill: 'accessibility',\n * agent: 'Cursor',\n * success: true,\n * path: '/repo/.cursor/skills/accessibility',\n * }\n * ```\n */\nexport interface AuditResultDetail {\n /** Skill processed by the operation. */\n skill: string\n /** Agent display name. */\n agent: string\n /** Whether the individual operation succeeded. */\n success: boolean\n /** Optional failure message. */\n error?: string\n /** Optional install or removal path. */\n path?: string\n}\n\n/**\n * Audit log entry written for skill lifecycle operations.\n *\n * @example\n * ```ts\n * const entry: AuditEntry = {\n * action: 'install',\n * skillName: 'accessibility',\n * agents: ['Cursor'],\n * success: 1,\n * failed: 0,\n * timestamp: '2026-03-05T12:00:00.000Z',\n * }\n * ```\n */\nexport interface AuditEntry {\n /** Operation type recorded in the audit log. */\n action: 'install' | 'remove' | 'update'\n /** Skill name or comma-separated skill names for batch operations. */\n skillName: string\n /** Agent display names involved in the operation. */\n agents: string[]\n /** Number of successful operations in the batch. */\n success: number\n /** Number of failed operations in the batch. */\n failed: number\n /** Whether the operation was forced. */\n forced?: boolean\n /** ISO timestamp of the audit event. */\n timestamp?: string\n /** Optional per-result details. */\n details?: AuditResultDetail[]\n}\n\n/**\n * Block-level markdown token produced by the parser helpers.\n *\n * @example\n * ```ts\n * const token: MarkdownToken = {\n * type: 'heading',\n * level: 2,\n * text: 'Usage',\n * }\n * ```\n */\nexport type MarkdownToken =\n | { type: 'heading'; level: 1 | 2 | 3; text: string }\n | { type: 'paragraph'; text: string }\n | { type: 'list-item'; text: string; indent: number }\n | { type: 'code-block'; language: string; lines: string[] }\n | { type: 'hr' }\n | { type: 'blank' }\n\n/**\n * Inline markdown segment produced by `parseInline`.\n *\n * @example\n * ```ts\n * const segment: InlineSegment = {\n * text: 'npm install',\n * code: true,\n * }\n * ```\n */\nexport interface InlineSegment {\n /** Text content for the inline fragment. */\n text: string\n /** Whether the segment is bold text. */\n bold?: boolean\n /** Whether the segment is italic text. */\n italic?: boolean\n /** Whether the segment is inline code. */\n code?: boolean\n}\n\n/**\n * Selects whether skills are loaded from the local catalog or remote registry.\n *\n * @example\n * ```ts\n * const mode: SkillsMode = 'remote'\n * ```\n */\nexport type SkillsMode = 'local' | 'remote'\n\n/**\n * Describes a deprecated skill entry published in the registry.\n *\n * @example\n * ```ts\n * const deprecated: DeprecatedEntry = {\n * name: 'old-skill',\n * message: 'Use accessibility instead',\n * alternatives: ['accessibility'],\n * }\n * ```\n */\nexport interface DeprecatedEntry {\n /** Deprecated skill name. */\n name: string\n /** Deprecation message shown to the user. */\n message: string\n /** Suggested replacement skills. */\n alternatives?: string[]\n}\n", "import { dirname, join } from 'node:path'\n\nimport { z } from 'zod'\n\nimport { AGENTS_DIR, LOCK_FILE, LOCK_FILE_BACKUP } from '../constants'\nimport type { CorePorts } from '../ports'\nimport type { AgentType, SkillLockEntry, SkillLockFile } from '../types'\nimport { AGENT_TYPES } from '../types'\n\nimport { findProjectRoot } from './project-root.service'\n\nconst CURRENT_VERSION = 2\n\nconst AgentTypeSchema = z.enum(AGENT_TYPES as unknown as [string, ...string[]])\n\nconst SkillLockEntrySchema = z.object({\n name: z.string(),\n source: z.string(),\n contentHash: z.string().optional(),\n installedAt: z.string(),\n updatedAt: z.string(),\n agents: z.array(AgentTypeSchema).optional(),\n method: z.enum(['copy', 'symlink']).optional(),\n global: z.boolean().optional(),\n version: z.string().optional(),\n})\n\nconst SkillLockFileSchema = z.object({\n version: z.number(),\n skills: z.record(z.string(), SkillLockEntrySchema),\n})\n\nfunction getSkillLockPath(ports: CorePorts, global: boolean): string {\n if (global) return join(ports.env.homedir(), AGENTS_DIR, LOCK_FILE)\n const projectRoot = findProjectRoot(ports)\n return join(projectRoot, AGENTS_DIR, LOCK_FILE)\n}\n\nfunction getBackupPath(ports: CorePorts, global: boolean): string {\n if (global) return join(ports.env.homedir(), AGENTS_DIR, LOCK_FILE_BACKUP)\n const projectRoot = findProjectRoot(ports)\n return join(projectRoot, AGENTS_DIR, LOCK_FILE_BACKUP)\n}\n\nfunction createEmptyLockFile(): SkillLockFile {\n return { version: CURRENT_VERSION, skills: {} }\n}\n\nfunction migrateLockFile(data: unknown): SkillLockFile {\n try {\n const parsed = SkillLockFileSchema.parse(data)\n\n if (parsed.version === 1) {\n return {\n version: CURRENT_VERSION,\n skills: Object.fromEntries(\n Object.entries(parsed.skills).map(([key, entry]) => [\n key,\n {\n ...entry,\n agents: (entry.agents || []) as AgentType[],\n method: entry.method || 'copy',\n global: entry.global ?? false,\n },\n ]),\n ),\n } as SkillLockFile\n }\n\n return parsed as SkillLockFile\n } catch {\n return createEmptyLockFile()\n }\n}\n\n/**\n * Reads and validates the shared skill lockfile.\n *\n * Missing, unreadable, or corrupted lockfiles resolve to an empty v2 lockfile\n * so consumers can recover gracefully without throwing.\n *\n * @param ports - Core ports that expose filesystem and environment access.\n * @param global - When `true`, reads the global lockfile in the user's home directory.\n * @returns The parsed lockfile, migrated to the current schema version when needed.\n *\n * @example\n * ```ts\n * const lock = await readSkillLock(ports)\n * ```\n */\nexport async function readSkillLock(ports: CorePorts, global = false): Promise<SkillLockFile> {\n const lockPath = getSkillLockPath(ports, global)\n\n try {\n const content = await ports.fs.readFile(lockPath, 'utf-8')\n const parsed = JSON.parse(content)\n return migrateLockFile(parsed)\n } catch {\n return createEmptyLockFile()\n }\n}\n\n/**\n * Writes the shared skill lockfile using a temporary file and backup copy.\n *\n * @param ports - Core ports that expose filesystem and environment access.\n * @param lock - Lockfile payload to persist.\n * @param global - When `true`, writes the global lockfile in the user's home directory.\n * @returns A promise that resolves when the lockfile has been written atomically.\n * @throws {unknown} Rethrows filesystem errors after attempting temp-file cleanup.\n *\n * @example\n * ```ts\n * await writeSkillLock(ports, lock)\n * ```\n */\nexport async function writeSkillLock(ports: CorePorts, lock: SkillLockFile, global = false): Promise<void> {\n const lockPath = getSkillLockPath(ports, global)\n const backupPath = getBackupPath(ports, global)\n const tempPath = `${lockPath}.tmp`\n\n try {\n try {\n const existing = await ports.fs.readFile(lockPath, 'utf-8')\n await ports.fs.writeFile(backupPath, existing, 'utf-8')\n } catch {\n // No existing file to back up.\n }\n\n await ports.fs.mkdir(dirname(lockPath), { recursive: true })\n await ports.fs.writeFile(tempPath, JSON.stringify(lock, null, 2), 'utf-8')\n await ports.fs.rename(tempPath, lockPath)\n } catch (error) {\n try {\n await ports.fs.rm(tempPath, { force: true })\n } catch {\n // Ignore cleanup errors.\n }\n\n throw error\n }\n}\n\n/**\n * Adds or updates a skill entry in the shared lockfile.\n *\n * @param ports - Core ports that expose filesystem and environment access.\n * @param skillName - Canonical skill name to persist.\n * @param agents - Agents currently associated with the skill.\n * @param options - Optional metadata persisted with the lock entry.\n * @returns A promise that resolves when the lockfile update has been persisted.\n *\n * @example\n * ```ts\n * await addSkillToLock(ports, 'accessibility', ['cursor'], { source: 'local' })\n * ```\n */\nexport async function addSkillToLock(\n ports: CorePorts,\n skillName: string,\n agents: AgentType[],\n options: {\n source?: string\n contentHash?: string\n method?: 'copy' | 'symlink'\n global?: boolean\n version?: string\n } = {},\n): Promise<void> {\n const lock = await readSkillLock(ports, options.global)\n const now = new Date().toISOString()\n const existingEntry = lock.skills[skillName]\n const existingAgents = existingEntry?.agents || []\n const mergedAgents = Array.from(new Set([...existingAgents, ...agents]))\n\n lock.skills[skillName] = {\n name: skillName,\n source: options.source || 'local',\n contentHash: options.contentHash ?? existingEntry?.contentHash,\n installedAt: existingEntry?.installedAt ?? now,\n updatedAt: now,\n agents: mergedAgents,\n method: options.method || 'copy',\n global: options.global ?? false,\n version: options.version,\n }\n\n await writeSkillLock(ports, lock, options.global)\n}\n\n/**\n * Removes a specific agent from a skill entry in the shared lockfile.\n * Deletes the entire skill entry when no agents remain.\n *\n * @param ports - Core ports that expose filesystem and environment access.\n * @param skillName - Canonical skill name to update.\n * @param agent - Agent to remove from the skill entry.\n * @param global - When `true`, targets the global lockfile in the user's home directory.\n * @returns `true` when the agent was removed or the entry was deleted; otherwise `false`.\n *\n * @example\n * ```ts\n * const removed = await removeAgentFromLock(ports, 'accessibility', 'cursor')\n * ```\n */\nexport async function removeAgentFromLock(\n ports: CorePorts,\n skillName: string,\n agent: AgentType,\n global = false,\n): Promise<boolean> {\n const lock = await readSkillLock(ports, global)\n const entry = lock.skills[skillName]\n if (!entry) return false\n\n const agents = entry.agents || []\n const updatedAgents = agents.filter((a) => a !== agent)\n\n if (updatedAgents.length === agents.length) {\n return false\n }\n\n if (updatedAgents.length === 0) {\n delete lock.skills[skillName]\n } else {\n lock.skills[skillName] = {\n ...entry,\n agents: updatedAgents,\n updatedAt: new Date().toISOString(),\n }\n }\n\n await writeSkillLock(ports, lock, global)\n return true\n}\n\n/**\n * Removes a skill entry from the shared lockfile.\n *\n * @deprecated Use removeAgentFromLock to remove specific agents, or call this only when removing all agents.\n * @param ports - Core ports that expose filesystem and environment access.\n * @param skillName - Canonical skill name to remove.\n * @param global - When `true`, targets the global lockfile in the user's home directory.\n * @returns `true` when the skill existed and was removed; otherwise `false`.\n *\n * @example\n * ```ts\n * const removed = await removeSkillFromLock(ports, 'accessibility')\n * ```\n */\nexport async function removeSkillFromLock(ports: CorePorts, skillName: string, global = false): Promise<boolean> {\n const lock = await readSkillLock(ports, global)\n if (!(skillName in lock.skills)) return false\n\n delete lock.skills[skillName]\n await writeSkillLock(ports, lock, global)\n return true\n}\n\n/**\n * Looks up a single skill entry in the shared lockfile.\n *\n * @param ports - Core ports that expose filesystem and environment access.\n * @param skillName - Canonical skill name to look up.\n * @param global - When `true`, reads from the global lockfile in the user's home directory.\n * @returns The matching lock entry or `null` when no entry exists.\n *\n * @example\n * ```ts\n * const entry = await getSkillFromLock(ports, 'accessibility')\n * ```\n */\nexport async function getSkillFromLock(\n ports: CorePorts,\n skillName: string,\n global = false,\n): Promise<SkillLockEntry | null> {\n const lock = await readSkillLock(ports, global)\n return lock.skills[skillName] ?? null\n}\n\n/**\n * Returns all skill entries currently recorded in the shared lockfile.\n *\n * @param ports - Core ports that expose filesystem and environment access.\n * @param global - When `true`, reads from the global lockfile in the user's home directory.\n * @returns A record keyed by skill name containing all persisted lock entries.\n *\n * @example\n * ```ts\n * const skills = await getAllLockedSkills(ports)\n * ```\n */\nexport async function getAllLockedSkills(ports: CorePorts, global = false): Promise<Record<string, SkillLockEntry>> {\n const lock = await readSkillLock(ports, global)\n return lock.skills\n}\n", "import { createHash } from 'node:crypto'\nimport { join, relative } from 'node:path'\n\nimport {\n CACHE_BASE_DIR,\n CACHE_NAMESPACE,\n MAX_CONCURRENT_DOWNLOADS,\n REGISTRY_CACHE_FILENAME,\n REGISTRY_CACHE_TTL_MS,\n SKILL_META_FILE,\n SKILLS_CATALOG_PACKAGE,\n SKILLS_SUBDIR,\n} from '../constants'\nimport type { CorePorts } from '../ports'\nimport type { CategoryInfo, DeprecatedEntry, SkillInfo, SkillMetadata, SkillsRegistry } from '../types'\nimport { sanitizeName } from '../utils'\n\nlet cachedCdnRef: string | null = null\n\ntype CachedRegistry = {\n fetchedAt: number\n registry: SkillsRegistry\n}\n\ntype CachedSkillMeta = {\n contentHash: string\n downloadedAt: number\n}\n\n\nfunction getRegistryCachePath(ports: CorePorts): string {\n return join(getCacheDir(ports), REGISTRY_CACHE_FILENAME)\n}\n\nfunction isSkillCachedInternal(ports: CorePorts, skillName: string): boolean {\n try {\n return ports.fs.existsSync(join(getSkillCachePath(ports, skillName), 'SKILL.md'))\n } catch {\n return false\n }\n}\n\nfunction ensureCacheDir(ports: CorePorts): void {\n const cacheDir = getCacheDir(ports)\n const skillsCacheDir = join(cacheDir, SKILLS_SUBDIR)\n\n if (!ports.fs.existsSync(cacheDir)) {\n ports.fs.mkdirSync(cacheDir, { recursive: true })\n }\n\n if (!ports.fs.existsSync(skillsCacheDir)) {\n ports.fs.mkdirSync(skillsCacheDir, { recursive: true })\n }\n}\n\nfunction isCacheValid(fetchedAt: number): boolean {\n return Date.now() - fetchedAt < REGISTRY_CACHE_TTL_MS\n}\n\nfunction tryReadCachedRegistry(ports: CorePorts): CachedRegistry | null {\n const cachePath = getRegistryCachePath(ports)\n if (!ports.fs.existsSync(cachePath)) return null\n\n try {\n const content = ports.fs.readFileSync(cachePath, 'utf-8')\n return JSON.parse(content) as CachedRegistry\n } catch {\n return null\n }\n}\n\nfunction saveRegistryToCache(ports: CorePorts, registry: SkillsRegistry): void {\n const cachePath = getRegistryCachePath(ports)\n const payload: CachedRegistry = { fetchedAt: Date.now(), registry }\n ports.fs.writeFileSync(cachePath, JSON.stringify(payload, null, 2), 'utf-8')\n}\n\nasync function getResolvedCdnRef(ports: CorePorts): Promise<string> {\n const envRef = ports.env.getEnv('SKILLS_CDN_REF')\n if (envRef) return envRef\n\n if (cachedCdnRef) return cachedCdnRef\n\n try {\n cachedCdnRef = await ports.packageResolver.getLatestVersion(SKILLS_CATALOG_PACKAGE)\n return cachedCdnRef\n } catch (error) {\n // invariant: never silently bind skill downloads to mutable @latest\n throw new Error(\n `Failed to resolve pinned version for ${SKILLS_CATALOG_PACKAGE}. ` +\n `Set SKILLS_CDN_REF or fix package resolution. ${error instanceof Error ? error.message : String(error)}`,\n { cause: error },\n )\n }\n}\n\n/**\n * Computes contentHash for an in-memory skill file set.\n * Must match packages/skills-catalog computeSkillHash (sorted path + bytes).\n */\nfunction computeSkillContentHash(files: ReadonlyMap<string, string | Buffer>): string {\n const hash = createHash('sha256')\n for (const file of [...files.keys()].sort()) {\n const content = files.get(file)\n if (content === undefined) continue\n hash.update(file)\n hash.update(content)\n }\n return hash.digest('hex')\n}\n\nfunction buildUrls(cdnRef: string): {\n registry: string\n fallbackRegistry: string\n skillsBase: string\n fallbackSkillsBase: string\n} {\n const cdnBase = `https://cdn.jsdelivr.net/npm/${SKILLS_CATALOG_PACKAGE}@${cdnRef}`\n const fallbackCdnBase = `https://unpkg.com/${SKILLS_CATALOG_PACKAGE}@${cdnRef}`\n\n return {\n registry: `${cdnBase}/skills-registry.json`,\n fallbackRegistry: `${fallbackCdnBase}/skills-registry.json`,\n skillsBase: `${cdnBase}/skills`,\n fallbackSkillsBase: `${fallbackCdnBase}/skills`,\n }\n}\n\nfunction isPathSafe(basePath: string, targetPath: string): boolean {\n const resolvedBase = join(basePath, '.')\n const resolvedTarget = join(targetPath, '.')\n return resolvedTarget.startsWith(resolvedBase)\n}\n\nfunction saveCachedSkillMeta(ports: CorePorts, skillName: string, meta: CachedSkillMeta): void {\n try {\n const metaPath = join(getSkillCachePath(ports, skillName), SKILL_META_FILE)\n ports.fs.writeFileSync(metaPath, JSON.stringify(meta, null, 2), 'utf-8')\n } catch {\n // Non-critical metadata write failure.\n }\n}\n\nfunction readCachedSkillMeta(ports: CorePorts, skillName: string): CachedSkillMeta | null {\n try {\n const metaPath = join(getSkillCachePath(ports, skillName), SKILL_META_FILE)\n if (!ports.fs.existsSync(metaPath)) return null\n\n return JSON.parse(ports.fs.readFileSync(metaPath, 'utf-8')) as CachedSkillMeta\n } catch {\n return null\n }\n}\n\nfunction toPosixRelative(root: string, absolutePath: string): string {\n return relative(root, absolutePath).split('\\\\').join('/')\n}\n\nfunction collectCachedFiles(ports: CorePorts, dir: string, root: string): string[] {\n const result: string[] = []\n let entries: { name: string; isDirectory(): boolean }[]\n try {\n entries = ports.fs.readdirSync(dir, { withFileTypes: true })\n } catch {\n return result\n }\n\n for (const entry of entries) {\n const absolute = join(dir, entry.name)\n if (!isPathSafe(root, absolute)) continue\n\n if (entry.isDirectory()) {\n result.push(...collectCachedFiles(ports, absolute, root))\n } else {\n result.push(toPosixRelative(root, absolute))\n }\n }\n\n return result\n}\n\nfunction pruneEmptyDirectories(ports: CorePorts, dir: string, root: string): void {\n let entries: { name: string; isDirectory(): boolean }[]\n try {\n entries = ports.fs.readdirSync(dir, { withFileTypes: true })\n } catch {\n return\n }\n\n for (const entry of entries) {\n if (!entry.isDirectory()) continue\n const absolute = join(dir, entry.name)\n if (!isPathSafe(root, absolute)) continue\n pruneEmptyDirectories(ports, absolute, root)\n }\n\n if (dir === root) return\n\n try {\n const remaining = ports.fs.readdirSync(dir, { withFileTypes: true })\n if (remaining.length === 0) {\n ports.fs.rmSync(dir, { recursive: true, force: true })\n }\n } catch {\n // best-effort cleanup\n }\n}\n\n/**\n * Removes cached files that are no longer listed in the skill's registry file set.\n * Keeps `.skill-meta.json`. Runs only after a successful download so a failed\n * refresh never deletes the previous cache.\n */\nfunction pruneOrphanedSkillCacheFiles(\n ports: CorePorts,\n skillCachePath: string,\n keepFiles: readonly string[],\n): void {\n const keep = new Set<string>([...keepFiles, SKILL_META_FILE])\n const cachedFiles = collectCachedFiles(ports, skillCachePath, skillCachePath)\n\n for (const relativePath of cachedFiles) {\n if (keep.has(relativePath)) continue\n const absolute = join(skillCachePath, relativePath)\n if (!isPathSafe(skillCachePath, absolute)) continue\n try {\n ports.fs.rmSync(absolute, { force: true })\n } catch {\n // best-effort cleanup\n }\n }\n\n pruneEmptyDirectories(ports, skillCachePath, skillCachePath)\n}\n\nasync function downloadSkillFile(\n ports: CorePorts,\n skill: SkillMetadata,\n file: string,\n skillCachePath: string,\n): Promise<string | null> {\n const filePath = join(skillCachePath, file)\n\n if (!isPathSafe(skillCachePath, filePath)) {\n ports.logger.error(`Security: Skipping suspicious file path: ${file}`)\n return null\n }\n\n const parentDir = join(filePath, '..')\n if (!ports.fs.existsSync(parentDir)) {\n ports.fs.mkdirSync(parentDir, { recursive: true })\n }\n\n const resolvedRef = await getResolvedCdnRef(ports)\n const urls = buildUrls(resolvedRef)\n const fileUrl = `${urls.skillsBase}/${skill.path}/${file}`\n const fallbackUrl = `${urls.fallbackSkillsBase}/${skill.path}/${file}`\n const response = await ports.http.getWithFallback(fileUrl, fallbackUrl)\n\n if (!response.ok) {\n throw new Error(`Failed to download ${file}: HTTP ${response.status}`)\n }\n\n const content = await response.text()\n ports.fs.writeFileSync(filePath, content, 'utf-8')\n return content\n}\n\n/**\n * Fetches the remote skills registry using CDN fallback and local cache.\n *\n * @param ports - Core ports used for filesystem, HTTP, environment, package resolution, and logging.\n * @param forceRefresh - When `true`, bypasses TTL cache validation and fetches from remote.\n * @returns A registry payload, cached fallback payload, or `null` when no payload is available.\n *\n * @example\n * ```ts\n * const registry = await fetchRegistry(ports)\n * ```\n */\nexport async function fetchRegistry(ports: CorePorts, forceRefresh = false): Promise<SkillsRegistry | null> {\n ensureCacheDir(ports)\n const resolvedRef = await getResolvedCdnRef(ports)\n\n if (!forceRefresh) {\n const cached = tryReadCachedRegistry(ports)\n const versionChanged = cached && resolvedRef !== 'latest' && cached.registry.version !== resolvedRef\n\n if (cached && isCacheValid(cached.fetchedAt) && !versionChanged) {\n return cached.registry\n }\n }\n\n try {\n const urls = buildUrls(resolvedRef)\n const response = await ports.http.getWithFallback(urls.registry, urls.fallbackRegistry)\n const registry = (await response.json()) as SkillsRegistry\n saveRegistryToCache(ports, registry)\n return registry\n } catch (error) {\n const cached = tryReadCachedRegistry(ports)\n if (cached) return cached.registry\n\n ports.logger.error(`Failed to fetch registry: ${error instanceof Error ? error.message : String(error)}`)\n return null\n }\n}\n\n/**\n * Downloads a skill from the remote registry CDN into the local cache.\n *\n * @param ports - Core ports used for filesystem, HTTP, environment, package resolution, and logging.\n * @param skill - Skill metadata that describes source path and files to download.\n * @returns Absolute cache directory path on success, otherwise `null`.\n *\n * @example\n * ```ts\n * const cachedPath = await downloadSkill(ports, metadata)\n * ```\n */\nexport async function downloadSkill(ports: CorePorts, skill: SkillMetadata): Promise<string | null> {\n ensureCacheDir(ports)\n const skillCachePath = getSkillCachePath(ports, skill.name)\n\n if (!ports.fs.existsSync(skillCachePath)) {\n ports.fs.mkdirSync(skillCachePath, { recursive: true })\n }\n\n try {\n const files = [...skill.files]\n const downloadedContents = new Map<string, string>()\n\n for (let index = 0; index < files.length; index += MAX_CONCURRENT_DOWNLOADS) {\n const batch = files.slice(index, index + MAX_CONCURRENT_DOWNLOADS)\n const results = await Promise.all(batch.map((file) => downloadSkillFile(ports, skill, file, skillCachePath)))\n for (const [batchIndex, content] of results.entries()) {\n if (content === null) continue\n downloadedContents.set(batch[batchIndex], content)\n }\n }\n\n if (downloadedContents.size < files.length) {\n throw new Error(`Only ${downloadedContents.size}/${files.length} files downloaded successfully`)\n }\n\n if (skill.contentHash) {\n // why: verify bytes we just fetched, not a second disk read that mocks can desync\n const computedHash = computeSkillContentHash(downloadedContents)\n if (computedHash !== skill.contentHash) {\n throw new Error(\n `Checksum mismatch for skill '${skill.name}': expected ${skill.contentHash}, got ${computedHash}`,\n )\n }\n\n saveCachedSkillMeta(ports, skill.name, {\n contentHash: skill.contentHash,\n downloadedAt: Date.now(),\n })\n }\n\n // Drop files removed from the skill so install does not copy orphans.\n pruneOrphanedSkillCacheFiles(ports, skillCachePath, files)\n\n return skillCachePath\n } catch (error) {\n ports.logger.error(\n `Failed to download skill ${skill.name}: ${error instanceof Error ? error.message : String(error)}`,\n )\n return null\n }\n}\n\n/**\n * Lists all skills from the remote registry.\n *\n * @param ports - Core ports used to fetch the remote registry and inspect local cache state.\n * @returns Skill descriptors from the registry, with local cache paths when available.\n *\n * @example\n * ```ts\n * const skills = await getRemoteSkills(ports)\n * ```\n */\nexport async function getRemoteSkills(ports: CorePorts): Promise<SkillInfo[]> {\n const registry = await fetchRegistry(ports)\n if (!registry) return []\n\n return registry.skills.map((skill) => ({\n name: skill.name,\n description: skill.description,\n path: isSkillCachedInternal(ports, skill.name) ? getSkillCachePath(ports, skill.name) : '',\n category: skill.category,\n }))\n}\n\n/**\n * Lists all categories from the remote registry.\n *\n * @param ports - Core ports used to fetch the remote registry.\n * @returns Categories sorted alphabetically by display name.\n *\n * @example\n * ```ts\n * const categories = await getRemoteCategories(ports)\n * ```\n */\nexport async function getRemoteCategories(ports: CorePorts): Promise<CategoryInfo[]> {\n const registry = await fetchRegistry(ports)\n if (!registry) return []\n\n return Object.entries(registry.categories)\n .map(([id, meta]) => ({\n id,\n name: meta.name,\n description: meta.description,\n }))\n .sort((left, right) => left.name.localeCompare(right.name))\n}\n\n/**\n * Looks up metadata for a single skill in the remote registry.\n *\n * @param ports - Core ports used to fetch the remote registry.\n * @param name - Canonical skill name to search for.\n * @returns Matching skill metadata when found; otherwise `null`.\n *\n * @example\n * ```ts\n * const metadata = await getSkillMetadata(ports, 'accessibility')\n * ```\n */\nexport async function getSkillMetadata(ports: CorePorts, name: string): Promise<SkillMetadata | null> {\n const registry = await fetchRegistry(ports)\n return registry?.skills.find((skill) => skill.name === name) ?? null\n}\n\n/**\n * Returns all deprecated skill entries published by the remote registry.\n *\n * @param ports - Core ports used to fetch the remote registry.\n * @returns Deprecated skill entries or an empty list when none are defined.\n *\n * @example\n * ```ts\n * const deprecated = await getDeprecatedSkills(ports)\n * ```\n */\nexport async function getDeprecatedSkills(ports: CorePorts): Promise<DeprecatedEntry[]> {\n const registry = await fetchRegistry(ports)\n return registry?.deprecated ?? []\n}\n\n/**\n * Returns deprecated registry entries indexed by skill name.\n *\n * @param ports - Core ports used to fetch the remote registry.\n * @returns A map keyed by deprecated skill name.\n *\n * @example\n * ```ts\n * const deprecatedMap = await getDeprecatedMap(ports)\n * ```\n */\nexport async function getDeprecatedMap(ports: CorePorts): Promise<Map<string, DeprecatedEntry>> {\n const deprecated = await getDeprecatedSkills(ports)\n return new Map(deprecated.map((entry) => [entry.name, entry]))\n}\n\n/**\n * Checks whether a cached skill differs from the current remote registry metadata.\n *\n * @param ports - Core ports used for cache inspection and registry lookup.\n * @param skillName - Canonical skill name to compare.\n * @returns `true` when the skill should be updated, otherwise `false`.\n *\n * @example\n * ```ts\n * const shouldUpdate = await needsUpdate(ports, 'accessibility')\n * ```\n */\nexport async function needsUpdate(ports: CorePorts, skillName: string): Promise<boolean> {\n if (!isSkillCachedInternal(ports, skillName)) return true\n\n const metadata = await getSkillMetadata(ports, skillName)\n if (!metadata?.contentHash) return false\n\n const cached = readCachedSkillMeta(ports, skillName)\n if (!cached?.contentHash) return true\n\n return cached.contentHash !== metadata.contentHash\n}\n\n/**\n * Splits skill names into update-required and up-to-date groups.\n *\n * @param ports - Core ports used to compare cached and remote skill metadata.\n * @param names - Skill names to evaluate.\n * @returns Skill names grouped by update status.\n *\n * @example\n * ```ts\n * const result = await getUpdatableSkills(ports, ['accessibility'])\n * ```\n */\nexport async function getUpdatableSkills(\n ports: CorePorts,\n names: string[],\n): Promise<{ toUpdate: string[]; upToDate: string[] }> {\n const toUpdate: string[] = []\n const upToDate: string[] = []\n\n for (const name of names) {\n if (await needsUpdate(ports, name)) {\n toUpdate.push(name)\n } else {\n upToDate.push(name)\n }\n }\n\n return { toUpdate, upToDate }\n}\n\n/**\n * Checks whether a skill is available in the local cache.\n *\n * @param ports - Core ports used to inspect cache files.\n * @param skillName - Canonical skill name.\n * @returns `true` when `SKILL.md` exists in the cached skill directory.\n *\n * @example\n * ```ts\n * const cached = isSkillCached(ports, 'accessibility')\n * ```\n */\nexport function isSkillCached(ports: CorePorts, skillName: string): boolean {\n return isSkillCachedInternal(ports, skillName)\n}\n\n/**\n * Ensures a skill exists in local cache with current registry content.\n *\n * Returns the existing cache path when the skill is present and its content hash\n * matches the registry. Re-downloads when the skill is missing or stale so\n * callers like `install` pick up newer published versions without requiring\n * `--force` or a separate `update` invocation.\n *\n * Stale caches are overwritten in place and pruned after a successful download \u2014\n * never cleared beforehand \u2014 so a failed refresh leaves the previous usable\n * cache intact.\n *\n * @param ports - Core ports used for cache checks, metadata lookup, and downloads.\n * @param skillName - Canonical skill name.\n * @returns Absolute cached skill directory path or `null` when download fails\n * (or when the skill is missing from both cache and registry).\n *\n * @example\n * ```ts\n * const path = await ensureSkillDownloaded(ports, 'accessibility')\n * ```\n */\nexport async function ensureSkillDownloaded(ports: CorePorts, skillName: string): Promise<string | null> {\n const cached = isSkillCached(ports, skillName)\n const metadata = await getSkillMetadata(ports, skillName)\n\n // Offline / registry miss: keep a usable local cache when present.\n if (!metadata) {\n return cached ? getSkillCachePath(ports, skillName) : null\n }\n\n if (cached) {\n // Mirror needsUpdate(): no remote hash means we cannot prove staleness.\n if (!metadata.contentHash) {\n return getSkillCachePath(ports, skillName)\n }\n\n const cachedMeta = readCachedSkillMeta(ports, skillName)\n if (cachedMeta?.contentHash === metadata.contentHash) {\n return getSkillCachePath(ports, skillName)\n }\n }\n\n // Overwrite in place (no clear-first). downloadSkill prunes orphans on success.\n return downloadSkill(ports, metadata)\n}\n\n/**\n * Clears all registry cache content.\n *\n * @param ports - Core ports used to remove cache paths.\n * @returns Nothing.\n *\n * @example\n * ```ts\n * clearCache(ports)\n * ```\n */\nexport function clearCache(ports: CorePorts): void {\n try {\n ports.fs.rmSync(getCacheDir(ports), { recursive: true, force: true })\n } catch {\n // ignore\n }\n}\n\n/**\n * Clears cached files for a single skill.\n *\n * @param ports - Core ports used to remove cache paths.\n * @param skillName - Canonical skill name.\n * @returns Nothing.\n *\n * @example\n * ```ts\n * clearSkillCache(ports, 'accessibility')\n * ```\n */\nexport function clearSkillCache(ports: CorePorts, skillName: string): void {\n try {\n ports.fs.rmSync(getSkillCachePath(ports, skillName), { recursive: true, force: true })\n } catch {\n // ignore\n }\n}\n\n/**\n * Clears only the cached registry payload.\n *\n * @param ports - Core ports used to remove cache files.\n * @returns Nothing.\n *\n * @example\n * ```ts\n * clearRegistryCache(ports)\n * ```\n */\nexport function clearRegistryCache(ports: CorePorts): void {\n try {\n ports.fs.rmSync(getRegistryCachePath(ports), { force: true })\n } catch {\n // ignore\n }\n}\n\n/**\n * Forces a fresh download by clearing local cache for a skill first.\n *\n * @param ports - Core ports used to clear and redownload cache data.\n * @param skillName - Canonical skill name.\n * @returns Absolute cached skill directory path or `null`.\n *\n * @example\n * ```ts\n * const path = await forceDownloadSkill(ports, 'accessibility')\n * ```\n */\nexport async function forceDownloadSkill(ports: CorePorts, skillName: string): Promise<string | null> {\n clearSkillCache(ports, skillName)\n return ensureSkillDownloaded(ports, skillName)\n}\n\n/**\n * Returns the absolute base cache directory used by the registry service.\n *\n * @param ports - Core ports used to resolve the user home directory.\n * @returns Absolute cache directory path used to store registry and skill payloads.\n *\n * @example\n * ```ts\n * const cacheDir = getCacheDir(ports)\n * // /home/user/.cache/agent-skills\n * ```\n */\nexport function getCacheDir(ports: CorePorts): string {\n return join(ports.env.homedir(), CACHE_BASE_DIR, CACHE_NAMESPACE)\n}\n\n/**\n * Resolves the absolute local cache path for a skill.\n *\n * @param ports - Core ports used to resolve the user home directory.\n * @param skillName - Canonical skill name.\n * @returns Absolute cache path for the skill directory.\n * @throws {Error} Throws when the skill name is empty or unsafe after sanitization.\n *\n * @example\n * ```ts\n * const path = getSkillCachePath(ports, 'accessibility')\n * // /home/user/.cache/agent-skills/skills/accessibility\n * ```\n */\nexport function getSkillCachePath(ports: CorePorts, skillName: string): string {\n const safeName = sanitizeName(skillName)\n if (!safeName) throw new Error('Invalid skill name')\n\n return join(getCacheDir(ports), SKILLS_SUBDIR, safeName)\n}\n\n/**\n * Returns the persisted content hash for a previously downloaded skill.\n *\n * @param ports - Core ports used to read persisted cache metadata from disk.\n * @param skillName - Canonical skill name.\n * @returns The cached content hash when known; otherwise `undefined`.\n *\n * @example\n * ```ts\n * const hash = getCachedContentHash(ports, 'accessibility')\n * ```\n */\nexport function getCachedContentHash(ports: CorePorts, skillName: string): string | undefined {\n return readCachedSkillMeta(ports, skillName)?.contentHash\n}\n", "import { join, relative, resolve } from 'node:path'\n\nimport { AGENTS_DIR, CANONICAL_SKILLS_DIR } from '../constants'\nimport type { CorePorts } from '../ports'\nimport type { AgentType, InstallOptions, InstallResult, RemoveOptions, RemoveResult, SkillInfo } from '../types'\nimport { isPathSafe, sanitizeName } from '../utils'\n\nimport { getAgentConfig } from './agents.service'\nimport { logAudit } from './audit-log.service'\nimport { isGloballyInstalled } from './global-path.service'\nimport { addSkillToLock, getSkillFromLock, removeAgentFromLock } from './lockfile.service'\nimport { findProjectRoot } from './project-root.service'\nimport { getCachedContentHash } from './registry.service'\n\nconst CANONICAL_SKILLS_PATH = join(AGENTS_DIR, CANONICAL_SKILLS_DIR)\n\ntype InstallMode = 'symlink-global' | 'symlink-local' | 'copy-global' | 'copy-local'\n\ninterface InstallContext {\n skill: SkillInfo\n config: ReturnType<typeof getAgentConfig>\n safeSkillName: string\n skillTargetPath: string\n projectRoot: string\n}\n\nconst createSymlink = async (ports: CorePorts, target: string, linkPath: string): Promise<boolean> => {\n try {\n await cleanExistingPath(ports, linkPath, target)\n await ports.fs.mkdir(join(linkPath, '..'), { recursive: true })\n const relativePath = relative(join(linkPath, '..'), target)\n const type = ports.env.platform() === 'win32' ? 'junction' : undefined\n await ports.fs.symlink(relativePath, linkPath, type)\n return true\n } catch {\n return false\n }\n}\n\nconst cleanExistingPath = async (ports: CorePorts, linkPath: string, target: string): Promise<void> => {\n try {\n const stats = await ports.fs.lstat(linkPath)\n if (stats.isSymbolicLink()) {\n const existingTarget = await ports.fs.readlink(linkPath)\n if (resolve(existingTarget) === resolve(target)) return\n await ports.fs.rm(linkPath)\n } else {\n await ports.fs.rm(linkPath, { recursive: true })\n }\n } catch (err: unknown) {\n if ((err as { code?: string })?.code === 'ELOOP') await ports.fs.rm(linkPath, { force: true }).catch(() => {})\n }\n}\n\nconst copySkillDirectory = async (ports: CorePorts, src: string, dest: string): Promise<void> => {\n await ports.fs.rm(dest, { recursive: true, force: true })\n await ports.fs.mkdir(join(dest, '..'), { recursive: true })\n await ports.fs.cp(src, dest, { recursive: true })\n}\n\nconst getInstallMode = (method: 'symlink' | 'copy', global: boolean): InstallMode =>\n `${method}-${global ? 'global' : 'local'}` as InstallMode\n\nconst createSuccessResult = (\n ctx: InstallContext,\n method: 'symlink' | 'copy',\n extras: Partial<InstallResult> = {},\n): InstallResult => ({\n agent: ctx.config.displayName,\n skill: ctx.skill.name,\n path: ctx.skillTargetPath,\n method,\n success: true,\n ...extras,\n})\n\nconst createErrorResult = (ctx: InstallContext, method: 'symlink' | 'copy', error: unknown): InstallResult => ({\n agent: ctx.config.displayName,\n skill: ctx.skill.name,\n path: ctx.skillTargetPath,\n method,\n success: false,\n error: error instanceof Error ? error.message : String(error),\n})\n\nconst installHandlers: Record<InstallMode, (ports: CorePorts, ctx: InstallContext) => Promise<InstallResult>> = {\n 'symlink-global': async (ports, ctx) => {\n if (await createSymlink(ports, ctx.skill.path, ctx.skillTargetPath)) return createSuccessResult(ctx, 'symlink')\n await copySkillDirectory(ports, ctx.skill.path, ctx.skillTargetPath)\n return createSuccessResult(ctx, 'copy', { symlinkFailed: true })\n },\n\n 'symlink-local': async (ports, ctx) => {\n const canonicalDir = join(ctx.projectRoot, CANONICAL_SKILLS_PATH, ctx.safeSkillName)\n await copySkillDirectory(ports, ctx.skill.path, canonicalDir)\n\n if (await createSymlink(ports, canonicalDir, ctx.skillTargetPath)) {\n return createSuccessResult(ctx, 'symlink', { usedGlobalSymlink: false })\n }\n\n await copySkillDirectory(ports, ctx.skill.path, ctx.skillTargetPath)\n return createSuccessResult(ctx, 'copy', { symlinkFailed: true })\n },\n\n 'copy-global': async (ports, ctx) => {\n await copySkillDirectory(ports, ctx.skill.path, ctx.skillTargetPath)\n return createSuccessResult(ctx, 'copy')\n },\n\n 'copy-local': async (ports, ctx) => {\n await copySkillDirectory(ports, ctx.skill.path, ctx.skillTargetPath)\n return createSuccessResult(ctx, 'copy')\n },\n}\n\nconst validatePath = (\n targetDir: string,\n skillTargetPath: string,\n projectRoot: string,\n global: boolean,\n): string | null => {\n if (global) return null\n if (isPathSafe(targetDir, skillTargetPath)) return null\n if (isPathSafe(projectRoot, skillTargetPath)) return null\n return 'Security: Invalid skill destination path'\n}\n\nconst installSkillForAgent = async (\n ports: CorePorts,\n skill: SkillInfo,\n agent: AgentType,\n targetDir: string,\n method: 'symlink' | 'copy',\n projectRoot: string,\n global: boolean,\n): Promise<InstallResult> => {\n const config = getAgentConfig(ports, agent)\n const safeSkillName = sanitizeName(skill.name)\n const skillTargetPath = join(targetDir, safeSkillName)\n const ctx: InstallContext = { skill, config, safeSkillName, skillTargetPath, projectRoot }\n const validationError = validatePath(targetDir, skillTargetPath, projectRoot, global)\n\n if (validationError) return createErrorResult(ctx, method, validationError)\n\n try {\n const mode = getInstallMode(method, global)\n return await installHandlers[mode](ports, ctx)\n } catch (error) {\n return createErrorResult(ctx, method, error)\n }\n}\n\n/**\n * Installs one or more skills for the requested agents.\n *\n * @param ports - Core ports used for filesystem access, environment checks, and audit logging.\n * @param skills - Skills that should be installed.\n * @param options - Installation options including target agents, mode, and scope.\n * @returns Installation results for every agent and skill combination.\n *\n * @example\n * ```ts\n * const results = await installSkills(ports, [skill], {\n * agents: ['claude-code'],\n * method: 'copy',\n * global: false,\n * })\n * ```\n */\nexport const installSkills = async (\n ports: CorePorts,\n skills: SkillInfo[],\n options: InstallOptions,\n): Promise<InstallResult[]> => {\n const projectRoot = findProjectRoot(ports)\n const results: InstallResult[] = []\n\n for (const agent of options.agents) {\n const config = getAgentConfig(ports, agent)\n const targetDir = options.global ? config.globalSkillsDir : join(projectRoot, config.skillsDir)\n\n for (const skill of skills) {\n const result = await installSkillForAgent(\n ports,\n skill,\n agent,\n targetDir,\n options.method,\n projectRoot,\n options.global,\n )\n results.push(result)\n if (result.success) {\n await addSkillToLock(ports, skill.name, [agent], {\n source: 'local',\n contentHash: getCachedContentHash(ports, skill.name),\n method: options.method,\n global: options.global,\n })\n }\n }\n }\n\n await logAudit(ports, {\n action: 'install',\n skillName: skills.map((s) => s.name).join(', '),\n agents: options.agents.map((a) => getAgentConfig(ports, a).displayName),\n success: results.filter((r) => r.success).length,\n failed: results.filter((r) => !r.success).length,\n details: results.map((r) => ({\n skill: r.skill,\n agent: r.agent,\n success: r.success,\n error: r.error,\n path: r.path,\n })),\n })\n\n return results\n}\n\n/**\n * Lists installed skills for a single agent and scope.\n *\n * @param ports - Core ports used to resolve paths and read directory contents.\n * @param agent - Agent whose skills directory should be inspected.\n * @param global - Whether to inspect the global skills directory instead of the project-local one.\n * @returns Installed skill directory names, or an empty list when the directory does not exist.\n *\n * @example\n * ```ts\n * const installed = await listInstalledSkills(ports, 'claude-code', false)\n * ```\n */\nexport const listInstalledSkills = async (ports: CorePorts, agent: AgentType, global: boolean): Promise<string[]> => {\n const config = getAgentConfig(ports, agent)\n const targetDir = global ? config.globalSkillsDir : join(findProjectRoot(ports), config.skillsDir)\n\n try {\n const entries = await ports.fs.readdir(targetDir, { withFileTypes: true })\n return entries.filter((e) => e.isDirectory() || e.isSymbolicLink?.()).map((e) => e.name)\n } catch {\n return []\n }\n}\n\n/**\n * Checks whether a skill exists for a given agent.\n *\n * @param ports - Core ports used to resolve install paths and inspect the filesystem.\n * @param skillName - Canonical skill name to check.\n * @param agent - Agent whose install directory should be inspected.\n * @param options - Optional scope selector for global or local installs.\n * @returns `true` when the skill directory exists for the selected agent and scope.\n *\n * @example\n * ```ts\n * const installed = await isSkillInstalled(ports, 'accessibility', 'claude-code')\n * ```\n */\nexport const isSkillInstalled = async (\n ports: CorePorts,\n skillName: string,\n agent: AgentType,\n options: { global?: boolean } = {},\n): Promise<boolean> => {\n const config = getAgentConfig(ports, agent)\n const safeSkillName = sanitizeName(skillName)\n const targetBase = options.global ? config.globalSkillsDir : join(findProjectRoot(ports), config.skillsDir)\n const skillDir = join(targetBase, safeSkillName)\n if (!isPathSafe(targetBase, skillDir)) return false\n\n try {\n await ports.fs.lstat(skillDir)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Resolves the expected install path for a skill and agent.\n *\n * @param ports - Core ports used to resolve project paths.\n * @param skillName - Canonical skill name.\n * @param agent - Agent that owns the destination directory.\n * @param options - Optional scope selector for global or local installs.\n * @returns The absolute install path for the skill.\n * @throws {Error} Throws when the sanitized skill name would resolve outside the allowed install directory.\n *\n * @example\n * ```ts\n * const path = getInstallPath(ports, 'accessibility', 'claude-code')\n * ```\n */\nexport const getInstallPath = (\n ports: CorePorts,\n skillName: string,\n agent: AgentType,\n options: { global?: boolean } = {},\n): string => {\n const config = getAgentConfig(ports, agent)\n const safeSkillName = sanitizeName(skillName)\n const targetBase = options.global ? config.globalSkillsDir : join(findProjectRoot(ports), config.skillsDir)\n const installPath = join(targetBase, safeSkillName)\n\n if (!isPathSafe(targetBase, installPath)) {\n throw new Error('Invalid skill name: potential path traversal detected')\n }\n\n return installPath\n}\n\n/**\n * Resolves the canonical storage path used for copied local skill content.\n *\n * @param ports - Core ports used to resolve home and project directories.\n * @param skillName - Canonical skill name.\n * @param options - Optional scope selector for global or local canonical storage.\n * @returns The absolute canonical path for the skill.\n * @throws {Error} Throws when the sanitized skill name would resolve outside the canonical skills directory.\n *\n * @example\n * ```ts\n * const path = getCanonicalPath(ports, 'accessibility')\n * ```\n */\nexport const getCanonicalPath = (ports: CorePorts, skillName: string, options: { global?: boolean } = {}): string => {\n const safeSkillName = sanitizeName(skillName)\n const baseDir = options.global ? ports.env.homedir() : findProjectRoot(ports)\n const canonicalPath = join(baseDir, CANONICAL_SKILLS_PATH, safeSkillName)\n\n if (!isPathSafe(join(baseDir, CANONICAL_SKILLS_PATH), canonicalPath)) {\n throw new Error('Invalid skill name: potential path traversal detected')\n }\n\n return canonicalPath\n}\n\n/**\n * Removes an installed skill from one or more agents and updates the lockfile.\n *\n * @param ports - Core ports used for filesystem access, path resolution, and audit logging.\n * @param skillName - Canonical skill name to remove.\n * @param agents - Agents from which the skill should be removed.\n * @param options - Removal options controlling scope and forced cleanup behavior.\n * @returns Removal results for each requested agent.\n *\n * @example\n * ```ts\n * const results = await removeSkill(ports, 'accessibility', ['claude-code'])\n * ```\n */\nexport const removeSkill = async (\n ports: CorePorts,\n skillName: string,\n agents: AgentType[],\n options: RemoveOptions = {},\n): Promise<RemoveResult[]> => {\n const safeSkillName = sanitizeName(skillName)\n const projectRoot = findProjectRoot(ports)\n let lockEntry = await getSkillFromLock(ports, skillName, true)\n if (!lockEntry) lockEntry = await getSkillFromLock(ports, skillName, false)\n\n if (!lockEntry && !options.force) {\n return agents.map((agent) => ({\n skill: skillName,\n agent: getAgentConfig(ports, agent).displayName,\n success: false,\n error: 'Skill not found in lockfile',\n }))\n }\n\n const internalResults = await Promise.all(\n agents.map(async (agent) => {\n const config = getAgentConfig(ports, agent)\n const localPath = join(projectRoot, config.skillsDir, safeSkillName)\n const globalPath = join(config.globalSkillsDir, safeSkillName)\n\n const pathsToTry =\n options.global === undefined ? [localPath, globalPath] : options.global ? [globalPath] : [localPath]\n\n let removed = false\n let removedLocal = false\n let removedGlobal = false\n let lastError: string | undefined\n\n for (const path of pathsToTry) {\n const isGlobalPath = path.startsWith(config.globalSkillsDir)\n const baseDir = isGlobalPath ? config.globalSkillsDir : join(projectRoot, config.skillsDir)\n\n if (!isPathSafe(baseDir, path)) {\n lastError = 'Security: Invalid removal path'\n continue\n }\n\n try {\n await ports.fs.lstat(path)\n await ports.fs.rm(path, { recursive: true, force: true })\n removed = true\n if (isGlobalPath) {\n removedGlobal = true\n } else {\n removedLocal = true\n }\n } catch (error) {\n const err = error as { code?: string; message?: string }\n if (err.code !== 'ENOENT' && !lastError) lastError = error instanceof Error ? error.message : String(error)\n }\n }\n\n return {\n skill: skillName,\n agent: config.displayName,\n success: removed,\n error: removed ? undefined : lastError || 'Skill not found',\n removedLocal,\n removedGlobal,\n }\n }),\n )\n\n for (const result of internalResults) {\n if (result.success) {\n const agentType = agents.find((a) => getAgentConfig(ports, a).displayName === result.agent)\n if (agentType) {\n if (result.removedLocal) {\n await removeAgentFromLock(ports, skillName, agentType, false).catch(() => {})\n }\n if (result.removedGlobal) {\n await removeAgentFromLock(ports, skillName, agentType, true).catch(() => {})\n }\n }\n }\n }\n\n const localLockEntryAfter = await getSkillFromLock(ports, skillName, false)\n const localHasRemainingAgents = (localLockEntryAfter?.agents?.length ?? 0) > 0\n const hadLocalRemoval = internalResults.some((r) => r.removedLocal)\n\n if (!localHasRemainingAgents && hadLocalRemoval && lockEntry?.method === 'symlink') {\n const canonicalPath = getCanonicalPath(ports, skillName, { global: false })\n await ports.fs.rm(canonicalPath, { recursive: true, force: true }).catch(() => {})\n }\n\n const results: RemoveResult[] = internalResults.map(({ skill, agent, success, error }) => ({\n skill,\n agent,\n success,\n ...(error && { error }),\n }))\n\n await logAudit(ports, {\n action: 'remove',\n skillName,\n agents: agents.map((a) => getAgentConfig(ports, a).displayName),\n success: results.filter((r) => r.success).length,\n failed: results.filter((r) => !r.success).length,\n forced: options.force,\n details: results.map((r) => ({\n skill: r.skill,\n agent: r.agent,\n success: r.success,\n error: r.error,\n })),\n })\n\n return results\n}\n\n/**\n * Re-exports the global installation check used by installer workflows.\n */\nexport { isGloballyInstalled }\n", "import type { InlineSegment, MarkdownToken } from '../types'\n\n/**\n * Removes YAML frontmatter from the start of a markdown document when present.\n *\n * @param raw - Raw markdown string that may include frontmatter.\n * @returns Markdown body without the leading frontmatter block.\n * @throws {never} This helper does not throw exceptions.\n *\n * @example\n * ```ts\n * stripFrontmatter('---\\ntitle: Example\\n---\\n# Heading') // '# Heading'\n * ```\n */\nexport function stripFrontmatter(raw: string): string {\n if (!raw.startsWith('---')) return raw\n\n let offset = 0\n while (offset < raw.length) {\n const lineEnd = raw.indexOf('\\n', offset)\n const segmentEnd = lineEnd === -1 ? raw.length : lineEnd\n const contentEnd = raw[segmentEnd - 1] === '\\r' ? segmentEnd - 1 : segmentEnd\n const line = raw.slice(offset, contentEnd)\n\n if (offset === 0) {\n if (line !== '---') return raw\n } else if (line === '---') {\n return raw.slice(lineEnd === -1 ? raw.length : lineEnd + 1).trimStart()\n }\n\n if (lineEnd === -1) return raw\n offset = lineEnd + 1\n }\n\n return raw\n}\n\n/**\n * Parses block-level markdown into a compact token set used by skill viewers.\n *\n * @param raw - Raw markdown input that may include blank lines and frontmatter.\n * @returns Array of {@link MarkdownToken} objects describing the document structure.\n * @throws {never} This parser only performs in-memory string analysis.\n *\n * @example\n * ```ts\n * parseMarkdown('# Title\\n\\nParagraph')\n * ```\n */\nexport function parseMarkdown(raw: string): MarkdownToken[] {\n const body = stripFrontmatter(raw)\n const lines = body.split('\\n')\n const tokens: MarkdownToken[] = []\n\n let i = 0\n while (i < lines.length) {\n const line = lines[i]\n\n if (line.startsWith('```')) {\n const language = line.slice(3).trim()\n const codeLines: string[] = []\n i++\n\n while (i < lines.length && !lines[i].startsWith('```')) {\n codeLines.push(lines[i])\n i++\n }\n\n tokens.push({ type: 'code-block', language, lines: codeLines })\n i++\n continue\n }\n\n if (line.trim() === '') {\n tokens.push({ type: 'blank' })\n i++\n continue\n }\n\n if (/^(-{3,}|_{3,}|\\*{3,})$/.test(line.trim())) {\n tokens.push({ type: 'hr' })\n i++\n continue\n }\n\n const headingMatch = line.match(/^(#{1,3})\\s+(.+)$/)\n if (headingMatch) {\n tokens.push({\n type: 'heading',\n level: headingMatch[1].length as 1 | 2 | 3,\n text: headingMatch[2],\n })\n i++\n continue\n }\n\n const listMatch = line.match(/^(\\s*)([-*]|\\d+\\.)\\s+(.+)$/)\n if (listMatch) {\n const indent = Math.floor(listMatch[1].length / 2)\n tokens.push({ type: 'list-item', text: listMatch[3], indent })\n i++\n continue\n }\n\n tokens.push({ type: 'paragraph', text: line })\n i++\n }\n\n return tokens\n}\n\n/**\n * Parses inline markdown formatting (bold, italic, code) into segments.\n *\n * @param text - Inline markdown string.\n * @returns Ordered {@link InlineSegment} entries preserving raw text.\n * @throws {never} Inline parsing never throws.\n *\n * @example\n * ```ts\n * parseInline('Use **bold** and `code`')\n * ```\n */\nexport function parseInline(text: string): InlineSegment[] {\n const segments: InlineSegment[] = []\n const regex = /(`[^`]+`|\\*\\*[^*]+\\*\\*|\\*[^*]+\\*)/g\n let lastIndex = 0\n let match: RegExpExecArray | null\n\n while ((match = regex.exec(text)) !== null) {\n if (match.index > lastIndex) segments.push({ text: text.slice(lastIndex, match.index) })\n const token = match[0]\n\n if (token.startsWith('`')) {\n segments.push({ text: token.slice(1, -1), code: true })\n } else if (token.startsWith('**')) {\n segments.push({ text: token.slice(2, -2), bold: true })\n } else if (token.startsWith('*')) {\n segments.push({ text: token.slice(1, -1), italic: true })\n }\n\n lastIndex = match.index + token.length\n }\n\n if (lastIndex < text.length) segments.push({ text: text.slice(lastIndex) })\n if (segments.length === 0) segments.push({ text })\n return segments\n}\n", "import { basename, join } from 'node:path'\n\nimport { CATEGORY_FOLDER_PATTERN, CATEGORY_METADATA_FILE, DEFAULT_CATEGORY_ID } from '../constants'\nimport type { CorePorts } from '../ports'\nimport type { CategoryInfo, SkillInfo, SkillsMode } from '../types'\nimport { formatCategoryName } from '../utils'\n\nimport { ensureSkillDownloaded, getRemoteCategories, getRemoteSkills, getSkillMetadata } from './registry.service'\n\ninterface ModeCache {\n mode: SkillsMode | null\n localDir: string | null\n}\n\nconst cache = new Map<string, ModeCache>()\n\nfunction getCacheKey(ports: CorePorts): string {\n try {\n const root = ports.paths.getWorkspaceRoot()\n if (root) return root\n } catch {\n // ignore to allow fallback\n }\n return '__default__'\n}\n\nfunction getCacheEntry(ports: CorePorts): ModeCache {\n const key = getCacheKey(ports)\n let entry = cache.get(key)\n if (!entry) {\n entry = { mode: null, localDir: null }\n cache.set(key, entry)\n }\n return entry\n}\n\nfunction getLocalSkillsDirectory(ports: CorePorts): string | null {\n return ports.paths.getLocalSkillsDirectory()\n}\n\n/**\n * Detects whether the skills provider runs in local (monorepo catalog) or remote (CDN registry) mode.\n *\n * @param ports - Core ports used to probe the local filesystem for the skills catalog.\n * @returns `'local'` when the local skills catalog directory is found, otherwise `'remote'`.\n *\n * @example\n * ```ts\n * const mode = detectMode(ports)\n * if (mode === 'local') {\n * console.log('Using local catalog')\n * }\n * ```\n */\nexport function detectMode(ports: CorePorts): SkillsMode {\n const entry = getCacheEntry(ports)\n if (entry.mode) return entry.mode\n const localDir = getLocalSkillsDirectory(ports)\n\n if (localDir) {\n entry.localDir = localDir\n entry.mode = 'local'\n return 'local'\n }\n\n entry.mode = 'remote'\n return 'remote'\n}\n\n/**\n * Returns the resolved local skills catalog directory path.\n *\n * @param ports - Core ports used to locate the skills catalog.\n * @returns Absolute path to the local skills catalog directory.\n * @throws {Error} When no local catalog is found (remote mode).\n *\n * @example\n * ```ts\n * const dir = getSkillsDirectory(ports)\n * // '/workspace/packages/skills-catalog/skills'\n * ```\n */\nexport function getSkillsDirectory(ports: CorePorts): string {\n const mode = detectMode(ports)\n const entry = getCacheEntry(ports)\n if (mode === 'local' && entry.localDir) return entry.localDir\n throw new Error('Skills directory not found. Use remote mode or install skills locally.')\n}\n\nfunction isLocalMode(ports: CorePorts): boolean {\n const entry = getCacheEntry(ports)\n return detectMode(ports) === 'local' && entry.localDir !== null\n}\n\nfunction isCategoryFolder(folderName: string): boolean {\n return CATEGORY_FOLDER_PATTERN.test(folderName)\n}\n\nfunction extractCategoryId(folderName: string): string | null {\n const match = folderName.match(CATEGORY_FOLDER_PATTERN)\n return match?.[1] ?? null\n}\n\nfunction parseSkillFrontmatter(content: string): { name?: string; description?: string } {\n const frontmatterMatch = content.match(/^---\\n([\\s\\S]*?)\\n---/)\n if (!frontmatterMatch) return {}\n const frontmatter = frontmatterMatch[1]\n const nameMatch = frontmatter.match(/^name:\\s*(.+)$/m)\n const descMatch = frontmatter.match(/^description:\\s*(.+)$/m)\n return { name: nameMatch?.[1]?.trim(), description: descMatch?.[1]?.trim() }\n}\n\nfunction tryReadSkillFromPath(ports: CorePorts, skillPath: string, categoryId: string): SkillInfo | null {\n const skillMdPath = join(skillPath, 'SKILL.md')\n if (!ports.fs.existsSync(skillMdPath)) return null\n const content = ports.fs.readFileSync(skillMdPath, 'utf-8')\n const { name, description } = parseSkillFrontmatter(content)\n const folderName = basename(skillPath)\n\n return {\n name: name ?? folderName,\n description: description ?? 'No description',\n path: skillPath,\n category: categoryId,\n }\n}\n\nfunction scanLocalSkills(ports: CorePorts, dirPath: string, categoryId: string): SkillInfo[] {\n if (!ports.fs.existsSync(dirPath)) return []\n return ports.fs\n .readdirSync(dirPath, { withFileTypes: true })\n .filter((entry) => entry.isDirectory())\n .map((entry) => tryReadSkillFromPath(ports, join(dirPath, entry.name), categoryId))\n .filter((skill): skill is SkillInfo => skill !== null)\n}\n\nfunction discoverLocalSkills(ports: CorePorts, skillsDir: string): SkillInfo[] {\n if (!ports.fs.existsSync(skillsDir)) return []\n const entries = ports.fs.readdirSync(skillsDir, { withFileTypes: true })\n\n return entries\n .filter((entry) => entry.isDirectory())\n .flatMap((entry) => {\n if (isCategoryFolder(entry.name)) {\n const categoryId = extractCategoryId(entry.name)\n return categoryId ? scanLocalSkills(ports, join(skillsDir, entry.name), categoryId) : []\n }\n const skill = tryReadSkillFromPath(ports, join(skillsDir, entry.name), DEFAULT_CATEGORY_ID)\n return skill ? [skill] : []\n })\n}\n\n/**\n * Discovers skills from the local skills catalog synchronously.\n *\n * @param ports - Core ports used to read local filesystem entries.\n * @returns Skills found in the local catalog, or an empty array in remote mode.\n *\n * @example\n * ```ts\n * const skills = discoverSkills(ports)\n * // [{ name: 'accessibility', description: '...', path: '...', category: 'quality' }]\n * ```\n */\nexport function discoverSkills(ports: CorePorts): SkillInfo[] {\n const entry = getCacheEntry(ports)\n return isLocalMode(ports) ? discoverLocalSkills(ports, entry.localDir!) : []\n}\n\n/**\n * Discovers skills from local catalog or remote registry, depending on the detected mode.\n *\n * @param ports - Core ports used for filesystem access and HTTP registry fetching.\n * @returns Skills from the local catalog in local mode, or from the remote registry in remote mode.\n *\n * @example\n * ```ts\n * const skills = await discoverSkillsAsync(ports)\n * ```\n */\nexport async function discoverSkillsAsync(ports: CorePorts): Promise<SkillInfo[]> {\n const entry = getCacheEntry(ports)\n return isLocalMode(ports) ? discoverLocalSkills(ports, entry.localDir!) : getRemoteSkills(ports)\n}\n\nfunction loadLocalCategoryMetadata(\n ports: CorePorts,\n skillsDir: string,\n): Record<string, { name?: string; description?: string }> {\n const metadataPath = join(skillsDir, CATEGORY_METADATA_FILE)\n if (!ports.fs.existsSync(metadataPath)) return {}\n\n try {\n return JSON.parse(ports.fs.readFileSync(metadataPath, 'utf-8'))\n } catch {\n return {}\n }\n}\n\nfunction discoverLocalCategories(ports: CorePorts, skillsDir: string): CategoryInfo[] {\n if (!ports.fs.existsSync(skillsDir)) return []\n const metadata = loadLocalCategoryMetadata(ports, skillsDir)\n\n return ports.fs\n .readdirSync(skillsDir, { withFileTypes: true })\n .filter((entry) => entry.isDirectory() && isCategoryFolder(entry.name))\n .reduce<CategoryInfo[]>((acc, entry, _) => {\n const categoryId = extractCategoryId(entry.name)\n if (!categoryId) return acc\n const meta = metadata[entry.name] ?? {}\n acc.push({ id: categoryId, name: meta.name ?? formatCategoryName(categoryId), description: meta.description })\n return acc\n }, [])\n .sort((a, b) => a.name.localeCompare(b.name))\n}\n\n/**\n * Discovers skill categories from the local catalog synchronously.\n *\n * @param ports - Core ports used to read local filesystem entries.\n * @returns Categories found in the local catalog, or an empty array in remote mode.\n *\n * @example\n * ```ts\n * const categories = discoverCategories(ports)\n * ```\n */\nexport function discoverCategories(ports: CorePorts): CategoryInfo[] {\n const entry = getCacheEntry(ports)\n return isLocalMode(ports) ? discoverLocalCategories(ports, entry.localDir!) : []\n}\n\n/**\n * Discovers skill categories from local catalog or remote registry.\n *\n * @param ports - Core ports used for filesystem access and HTTP registry fetching.\n * @returns Categories from the local catalog in local mode, or from the remote registry in remote mode.\n *\n * @example\n * ```ts\n * const categories = await discoverCategoriesAsync(ports)\n * ```\n */\nexport async function discoverCategoriesAsync(ports: CorePorts): Promise<CategoryInfo[]> {\n const entry = getCacheEntry(ports)\n return isLocalMode(ports) ? discoverLocalCategories(ports, entry.localDir!) : getRemoteCategories(ports)\n}\n\n/**\n * Looks up a skill by name from the local catalog synchronously.\n *\n * @param ports - Core ports used to read local filesystem entries.\n * @param name - The skill name to find.\n * @returns The matching `SkillInfo` or `undefined` when not found.\n *\n * @example\n * ```ts\n * const skill = getSkillByName(ports, 'accessibility')\n * ```\n */\nexport function getSkillByName(ports: CorePorts, name: string): SkillInfo | undefined {\n return discoverSkills(ports).find((s) => s.name === name)\n}\n\n/**\n * Looks up a skill by name from the local catalog or remote registry asynchronously.\n *\n * @param ports - Core ports used for filesystem access and HTTP registry fetching.\n * @param name - The skill name to find.\n * @returns The matching `SkillInfo` or `undefined` when not found.\n *\n * @example\n * ```ts\n * const skill = await getSkillByNameAsync(ports, 'accessibility')\n * ```\n */\nexport async function getSkillByNameAsync(ports: CorePorts, name: string): Promise<SkillInfo | undefined> {\n const skills = await discoverSkillsAsync(ports)\n return skills.find((s) => s.name === name)\n}\n\n/**\n * Ensures a skill is locally available, downloading it from the registry when needed.\n *\n * @param ports - Core ports used for filesystem access and HTTP registry fetching.\n * @param skillName - The skill name to ensure is available.\n * @returns The absolute local path to the skill, or `null` when unavailable.\n *\n * @example\n * ```ts\n * const path = await ensureSkillAvailable(ports, 'accessibility')\n * ```\n */\nexport async function ensureSkillAvailable(ports: CorePorts, skillName: string): Promise<string | null> {\n if (isLocalMode(ports)) return getSkillByName(ports, skillName)?.path ?? null\n return ensureSkillDownloaded(ports, skillName)\n}\n\n/**\n * Returns skill information including the resolved local path.\n *\n * @param ports - Core ports used for filesystem access and HTTP registry fetching.\n * @param skillName - The skill name to retrieve with path.\n * @returns The `SkillInfo` with a resolved local path, or `null` when unavailable.\n *\n * @example\n * ```ts\n * const skill = await getSkillWithPath(ports, 'accessibility')\n * ```\n */\nexport async function getSkillWithPath(ports: CorePorts, skillName: string): Promise<SkillInfo | null> {\n if (isLocalMode(ports)) return getSkillByName(ports, skillName) ?? null\n const metadata = await getSkillMetadata(ports, skillName)\n if (!metadata) return null\n const localPath = await ensureSkillDownloaded(ports, skillName)\n if (!localPath) return null\n return { name: metadata.name, description: metadata.description, path: localPath, category: metadata.category }\n}\n", "import type { CorePorts } from '../ports'\nimport type { InstallResult, SkillInfo } from '../types'\n\nimport { installSkills } from './installer.service'\nimport { readSkillLock } from './lockfile.service'\nimport { forceDownloadSkill, getSkillMetadata } from './registry.service'\n\n/**\n * Updates skills by force-downloading fresh content from the remote registry and\n * reinstalling them to each agent and scope recorded in the lockfile.\n *\n * This is the correct update primitive: it both refreshes the local cache *and*\n * propagates the new content to every agent directory that previously received\n * the skill, preserving the original installation method (copy vs symlink) and scope\n * (local vs global) from the lockfile.\n *\n * @param ports - Core ports used for filesystem, HTTP, and environment access.\n * @param skillNames - Canonical skill names to update.\n * @returns Installation results for every agent/scope/skill combination updated.\n * An empty array means the skill was not found in any lockfile; the cache\n * was still refreshed.\n *\n * @example\n * ```ts\n * const results = await updateSkills(ports, ['pbs-spec-driven'])\n * const failed = results.filter((r) => !r.success)\n * ```\n */\nexport async function updateSkills(ports: CorePorts, skillNames: string[]): Promise<InstallResult[]> {\n const allResults: InstallResult[] = []\n\n for (const skillName of skillNames) {\n const freshPath = await forceDownloadSkill(ports, skillName)\n\n if (!freshPath) {\n allResults.push({\n agent: 'unknown',\n skill: skillName,\n path: '',\n method: 'copy',\n success: false,\n error: `Failed to download skill \"${skillName}\"`,\n })\n continue\n }\n\n const metadata = await getSkillMetadata(ports, skillName)\n const skillInfo: SkillInfo = {\n name: skillName,\n description: metadata?.description ?? '',\n path: freshPath,\n category: metadata?.category ?? '',\n }\n\n for (const global of [false, true] as const) {\n const lock = await readSkillLock(ports, global)\n const entry = lock.skills[skillName]\n if (!entry?.agents?.length) continue\n\n const results = await installSkills(ports, [skillInfo], {\n agents: entry.agents,\n method: entry.method ?? 'copy',\n global,\n skills: [skillName],\n })\n allResults.push(...results)\n }\n }\n\n return allResults\n}\n", "/**\n * Re-exports the public core service APIs.\n */\nexport * from './agents.service'\nexport * from './audit-log.service'\nexport * from './categories.service'\nexport * from './global-path.service'\nexport * from './installer.service'\nexport * from './lockfile.service'\nexport * from './markdown-parser.service'\nexport * from './project-root.service'\nexport * from './registry.service'\nexport * from './skills-provider.service'\nexport * from './update.service'\n", "/**\n * Exposes the complete public API for `@peterson-benhame/core`.\n */\nexport * from './lib/adapters'\nexport * from './lib/constants'\nexport * from './lib/ports'\nexport * from './lib/services'\nexport * from './lib/types'\nexport { formatCategoryName, isPathSafe, sanitizeName } from './lib/utils'\n", "import { createNodeAdapters } from '@peterson-benhame/core'\n\n/**\n * Shared Node.js adapter instances for all CLI services.\n *\n * This singleton provides a complete set of I/O ports (filesystem, HTTP, shell, environment, logger, package resolver)\n * that are injected into core business logic functions. By centralizing adapter creation, the CLI avoids\n * instantiating duplicate adapters across different command handlers.\n *\n * @example\n * ```typescript\n * import { ports } from './ports'\n * import { installSkills } from '@peterson-benhame/core'\n *\n * const result = await installSkills(ports, skillNames, agentType)\n * ```\n */\nexport const ports = createNodeAdapters()\n", "import chalk from 'chalk'\nimport {\n AGENT_TYPES,\n ensureSkillDownloaded,\n fetchRegistry,\n forceDownloadSkill,\n getRemoteSkills,\n installSkills,\n} from '@peterson-benhame/core'\nimport type { AgentType, InstallOptions, SkillInfo } from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\n\ninterface InstallCliOptions {\n skill?: string[]\n agent?: string[]\n global?: boolean\n symlink?: boolean\n force?: boolean\n}\n\nasync function downloadSkills(skillNames: string[], forceDownload: boolean): Promise<SkillInfo[]> {\n // Bypass the 24h registry TTL so re-install can see newly published content hashes.\n await fetchRegistry(ports, true)\n const allSkills = await getRemoteSkills(ports)\n const selectedSkills: SkillInfo[] = []\n\n for (const skillName of skillNames) {\n const skill = allSkills.find((s) => s.name === skillName)\n if (!skill) {\n console.error(chalk.red(`\u274C Skill \"${skillName}\" not found`))\n continue\n }\n\n const path = forceDownload ? await forceDownloadSkill(ports, skillName) : await ensureSkillDownloaded(ports, skillName)\n if (path) {\n selectedSkills.push({ ...skill, path })\n } else {\n console.error(chalk.red(`\u274C Failed to download skill \"${skillName}\"`))\n }\n }\n\n return selectedSkills\n}\n\nfunction showInstallResults(results: Awaited<ReturnType<typeof installSkills>>): void {\n const successful = results.filter((r) => r.success)\n const failed = results.filter((r) => !r.success)\n\n if (successful.length > 0) {\n console.log(chalk.green(`\\n\u2705 Successfully installed ${successful.length} skill(s):`))\n successful.forEach((r) => {\n console.log(chalk.dim(` \u2022 ${r.skill} \u2192 ${r.agent} (${r.method})`))\n })\n }\n\n if (failed.length > 0) {\n console.log(chalk.red(`\\n\u274C Failed to install ${failed.length} skill(s):`))\n failed.forEach((r) => {\n console.log(chalk.dim(` \u2022 ${r.skill} \u2192 ${r.agent}: ${r.error}`))\n })\n }\n}\n\nexport async function runCliInstall(options: InstallCliOptions): Promise<void> {\n if (!options.skill || options.skill.length === 0) {\n console.error(chalk.red('\u274C --skill is required in CLI mode'))\n console.error(\n chalk.dim('Usage: agent-skills install --skill <name1> [name2...] [--agent <agents...>] [--global] [--symlink]'),\n )\n process.exit(1)\n }\n\n const skillNames = Array.isArray(options.skill) ? options.skill : [options.skill]\n\n console.log(chalk.blue(`\u23F3 Loading ${skillNames.length} skill(s) from catalog...`))\n const skills = await downloadSkills(skillNames, options.force || false)\n\n if (skills.length === 0) {\n console.error(chalk.red('\u274C No skills were successfully downloaded'))\n process.exit(1)\n }\n\n const rawAgents = options.agent || ['cursor', 'claude-code', 'windsurf']\n const invalidAgents = rawAgents.filter((a) => !AGENT_TYPES.includes(a as AgentType))\n if (invalidAgents.length > 0) {\n console.error(chalk.red(`\u274C Unknown agent(s): ${invalidAgents.join(', ')}`))\n console.error(chalk.dim(` Valid agents: ${AGENT_TYPES.join(', ')}`))\n process.exit(1)\n }\n const agents = rawAgents as AgentType[]\n const method = options.symlink ? 'symlink' : 'copy'\n\n console.log(chalk.blue(`\u23F3 Installing ${skills.length} skill(s) to ${agents.length} agent(s)...`))\n\n const installOptions: InstallOptions = {\n agents,\n skills: skills.map((s) => s.name),\n method,\n global: options.global || false,\n }\n\n const results = await installSkills(ports, skills, installOptions)\n showInstallResults(results)\n\n if (results.some((r) => !r.success)) {\n process.exit(1)\n }\n}\n", "import chalk from 'chalk'\nimport { AGENT_TYPES, removeSkill } from '@peterson-benhame/core'\nimport type { AgentType } from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\n\ninterface RemoveCliOptions {\n skill?: string[]\n agent?: string[]\n global?: boolean\n force?: boolean\n}\n\nexport async function runCliRemove(options: RemoveCliOptions): Promise<void> {\n if (!options.skill || options.skill.length === 0) {\n console.error(chalk.red('\u274C --skill is required in CLI mode'))\n console.error(\n chalk.dim('Usage: agent-skills remove --skill <name1> [name2...] [--agent <agents...>] [--global] [--force]'),\n )\n process.exit(1)\n }\n\n const skillNames = Array.isArray(options.skill) ? options.skill : [options.skill]\n const rawAgents = options.agent || ['cursor', 'claude-code', 'windsurf']\n const invalidAgents = rawAgents.filter((a) => !AGENT_TYPES.includes(a as AgentType))\n if (invalidAgents.length > 0) {\n console.error(chalk.red(`\u274C Unknown agent(s): ${invalidAgents.join(', ')}`))\n console.error(chalk.dim(` Valid agents: ${AGENT_TYPES.join(', ')}`))\n process.exit(1)\n }\n const agents = rawAgents as AgentType[]\n\n if (options.force) {\n console.log(chalk.yellow('\u26A0\uFE0F Force mode enabled - bypassing lockfile check'))\n }\n\n console.log(chalk.blue(`\u23F3 Removing ${skillNames.length} skill(s) from ${agents.length} agent(s)...`))\n\n let totalSuccess = 0\n let totalFailed = 0\n let hasLockfileError = false\n\n for (const skillName of skillNames) {\n const results = await removeSkill(ports, skillName, agents, {\n global: options.global,\n force: options.force,\n })\n\n const successful = results.filter((r) => r.success)\n const failed = results.filter((r) => !r.success)\n\n if (successful.length > 0) {\n console.log(chalk.green(`\u2705 ${skillName}: Removed from ${successful.length} agent(s)`))\n successful.forEach((r) => console.log(chalk.dim(` \u2022 ${r.agent}`)))\n totalSuccess += successful.length\n }\n\n if (failed.length > 0) {\n console.log(chalk.red(`\u274C ${skillName}: Failed to remove from ${failed.length} agent(s)`))\n failed.forEach((r) => console.log(chalk.dim(` \u2022 ${r.agent}: ${r.error}`)))\n totalFailed += failed.length\n\n if (failed.some((r) => r.error?.includes('lockfile'))) {\n hasLockfileError = true\n }\n }\n }\n\n console.log(chalk.dim(`\\n${totalSuccess} succeeded, ${totalFailed} failed`))\n\n if (hasLockfileError && !options.force) {\n console.log(chalk.yellow('\\n\uD83D\uDCA1 Tip: Use --force to bypass lockfile check'))\n }\n\n if (totalFailed > 0) {\n process.exit(1)\n }\n}\n", "import chalk from 'chalk'\nimport {\n fetchRegistry,\n getDeprecatedMap,\n getRemoteSkills,\n getUpdatableSkills,\n needsUpdate,\n readSkillLock,\n updateSkills,\n} from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\n\ninterface UpdateCliOptions {\n skill?: string\n}\n\nexport async function runCliUpdate(options: UpdateCliOptions): Promise<void> {\n console.log(chalk.blue('\u23F3 Fetching latest registry...'))\n await fetchRegistry(ports, true)\n\n if (options.skill) {\n const outdated = await needsUpdate(ports, options.skill)\n if (!outdated) {\n console.log(chalk.green(`\u2705 ${options.skill} is already up to date`))\n return\n }\n\n console.log(chalk.blue(`\u23F3 Updating ${options.skill}...`))\n const results = await updateSkills(ports, [options.skill])\n\n if (results.length === 0) {\n // Skill was in the registry and its cache was refreshed, but it was not\n // recorded in any lockfile \u2014 nothing to reinstall.\n console.log(chalk.green(`\u2705 Cache updated for ${options.skill} (not installed in any agent)`))\n return\n }\n\n const failed = results.filter((r) => !r.success)\n if (failed.length === 0) {\n console.log(chalk.green(`\u2705 Updated ${options.skill}`))\n } else {\n failed.forEach((r) => console.error(chalk.red(` \u274C ${r.skill} \u2192 ${r.agent}: ${r.error}`)))\n process.exit(1)\n }\n } else {\n const lock = await readSkillLock(ports)\n const installedNames = Object.keys(lock.skills)\n\n if (installedNames.length === 0) {\n console.log(chalk.yellow('No installed skills found. Run agent-skills install first.'))\n return\n }\n\n const { toUpdate, upToDate } = await getUpdatableSkills(ports, installedNames)\n\n if (toUpdate.length === 0) {\n console.log(chalk.green(`\u2705 All ${upToDate.length} installed skills are up to date`))\n } else {\n console.log(chalk.blue(`\u23F3 Updating ${toUpdate.length} of ${installedNames.length} skills...`))\n\n const results = await updateSkills(ports, toUpdate)\n const successSkills = new Set(results.filter((r) => r.success).map((r) => r.skill))\n const failedResults = results.filter((r) => !r.success)\n\n // Skills with no lockfile entry get treated as cache-only updates (success)\n const noLockfileSkills = toUpdate.filter((name) => !results.some((r) => r.skill === name))\n const updated = successSkills.size + noLockfileSkills.length\n const failed = failedResults.length\n\n console.log(\n chalk.green(\n `\u2705 ${updated} updated, ${upToDate.length} already up to date${failed > 0 ? chalk.red(`, ${failed} failed`) : ''}`,\n ),\n )\n\n if (failed > 0) {\n failedResults.forEach((r) => console.error(chalk.red(` \u274C ${r.skill} \u2192 ${r.agent}: ${r.error}`)))\n }\n }\n\n // Check for deprecated/orphaned skills\n const deprecatedMap = await getDeprecatedMap(ports)\n const remoteSkills = await getRemoteSkills(ports)\n const registryNames = new Set(remoteSkills.map((s) => s.name))\n\n const deprecated = installedNames.filter((name) => deprecatedMap.has(name) || !registryNames.has(name))\n\n if (deprecated.length > 0) {\n console.log('')\n console.log(chalk.yellow(`\u26A0 ${deprecated.length} deprecated skill${deprecated.length > 1 ? 's' : ''} detected:`))\n\n const renderers: Record<\n 'withEntry' | 'noEntry',\n (name: string, entry?: { message: string; alternatives?: string[] }) => void\n > = {\n withEntry: (name, entry) => {\n console.log(chalk.yellow(` \u203A ${name} \u2014 ${entry!.message}`))\n if (entry!.alternatives?.length) {\n console.log(chalk.dim(` Try: agent-skills install --skill ${entry!.alternatives.join(', ')}`))\n }\n },\n noEntry: (name) => {\n console.log(chalk.yellow(` \u203A ${name} \u2014 no longer available in the registry`))\n },\n }\n\n deprecated.forEach((name) => {\n const entry = deprecatedMap.get(name)\n const rendererKey = entry ? 'withEntry' : 'noEntry'\n renderers[rendererKey](name, entry)\n })\n\n console.log(chalk.dim(` Run: agent-skills remove --skill <name> to clean up`))\n }\n }\n}\n", "import chalk from 'chalk'\nimport { clearCache, clearRegistryCache, getCacheDir } from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\n\ninterface CacheCliOptions {\n clear?: boolean\n clearRegistry?: boolean\n path?: boolean\n}\n\nexport function runCliCache(options: CacheCliOptions): void {\n if (options.clear) {\n clearCache(ports)\n console.log(chalk.green('\u2705 Cache cleared'))\n } else if (options.clearRegistry) {\n clearRegistryCache(ports)\n console.log(chalk.green('\u2705 Registry cache cleared'))\n } else if (options.path) {\n console.log(getCacheDir(ports))\n } else {\n console.log(chalk.bold('Cache management:'))\n console.log(` ${chalk.blue('--clear')} Clear all cached skills and registry`)\n console.log(` ${chalk.blue('--clear-registry')} Clear only the registry cache`)\n console.log(` ${chalk.blue('--path')} Show cache directory path`)\n console.log()\n console.log(chalk.dim(`Cache location: ${getCacheDir(ports)}`))\n }\n}\n", "import { Box, Text } from 'ink'\n\ninterface AuditEntry {\n action: 'install' | 'remove' | 'update'\n skillName: string\n agents: string[]\n success: number\n failed: number\n timestamp?: string\n forced?: boolean\n}\n\ninterface Props {\n entries: AuditEntry[]\n limit?: number\n}\n\nexport function AuditLogViewer({ entries, limit = 10 }: Props) {\n const displayEntries = entries.slice(0, limit)\n\n if (displayEntries.length === 0) {\n return (\n <Box flexDirection=\"column\" paddingY={1}>\n <Text dimColor>No audit log entries found</Text>\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"column\" paddingY={1}>\n <Box marginBottom={1}>\n <Text bold color=\"cyan\">\n \uD83D\uDCCB Audit Log\n </Text>\n <Text dimColor> (showing {displayEntries.length} most recent)</Text>\n </Box>\n\n {displayEntries.map((entry, idx) => {\n const date = entry.timestamp ? new Date(entry.timestamp) : new Date()\n const timeAgo = entry.timestamp ? getTimeAgo(date) : 'unknown time'\n const actionColor = entry.action === 'install' ? 'green' : entry.action === 'remove' ? 'red' : 'yellow'\n const statusIcon = entry.failed === 0 ? '\u2713' : entry.success > 0 ? '\u26A0' : '\u2717'\n\n return (\n <Box key={idx} flexDirection=\"column\" marginBottom={1} paddingLeft={2}>\n <Box>\n <Text color={actionColor} bold>\n {statusIcon} {entry.action.toUpperCase()}\n </Text>\n <Text dimColor> \u2022 {timeAgo}</Text>\n </Box>\n <Box paddingLeft={2}>\n <Text>Skills: </Text>\n <Text color=\"cyan\">{entry.skillName}</Text>\n </Box>\n <Box paddingLeft={2}>\n <Text>Agents: </Text>\n <Text dimColor>{entry.agents.join(', ')}</Text>\n </Box>\n <Box paddingLeft={2}>\n <Text color=\"green\">\u2713 {entry.success}</Text>\n {entry.failed > 0 && (\n <>\n <Text> \u2022 </Text>\n <Text color=\"red\">\u2717 {entry.failed}</Text>\n </>\n )}\n </Box>\n </Box>\n )\n })}\n </Box>\n )\n}\n\nfunction getTimeAgo(date: Date): string {\n const seconds = Math.floor((Date.now() - date.getTime()) / 1000)\n\n if (seconds < 60) return 'just now'\n if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`\n if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`\n if (seconds < 604800) return `${Math.floor(seconds / 86400)}d ago`\n\n return date.toLocaleDateString()\n}\n", "import { render } from 'ink'\nimport React from 'react'\nimport { getAuditLogPath, readAuditLog } from '@peterson-benhame/core'\n\nimport { AuditLogViewer } from '../components/AuditLogViewer'\nimport { ports } from '../ports'\n\ninterface AuditOptions {\n limit?: string\n path?: boolean\n}\n\nexport async function runCliAudit(options: AuditOptions) {\n if (options.path) {\n console.log(getAuditLogPath(ports))\n return\n }\n\n const limit = options.limit ? parseInt(options.limit, 10) : 10\n const entries = await readAuditLog(ports, limit)\n render(React.createElement(AuditLogViewer, { entries, limit }))\n}\n", "import { Command } from 'commander'\nimport { render } from 'ink'\nimport React from 'react'\n\nimport { App } from './app'\nimport { PACKAGE_VERSION } from './services/package-info'\n\nconst program = new Command()\n\n// Root command\nprogram\n .name('agent-skills')\n .description('CLI to install and manage skills for AI coding agents')\n .version(PACKAGE_VERSION)\n\nprogram.action(() => {\n render(React.createElement(App, { command: 'install' }))\n})\n\n// Install command\nprogram\n .command('install')\n .description('Install skills (interactive by default)')\n .option('-g, --global', 'Install globally to user home', false)\n .option('-s, --skill <names...>', 'Install one or more skills')\n .option('-a, --agent <agents...>', 'Target specific agents')\n .option('--symlink', 'Use symlink instead of copy', false)\n .option('-f, --force', 'Force re-download skills (bypass cache)', false)\n .action(async (options) => {\n if (shouldUseInteractiveMode(options)) {\n render(React.createElement(App, { command: 'install' }))\n return\n }\n\n // CLI mode - dynamic import\n const { runCliInstall } = await import('./cli/install')\n await runCliInstall(options)\n })\n\n// List command\nprogram\n .command('list')\n .alias('ls')\n .description('List available/installed agent skills')\n .action(() => {\n render(React.createElement(App, { command: 'list' }))\n })\n\n// Remove command\nprogram\n .command('remove')\n .alias('rm')\n .description('Remove installed skills')\n .option('-g, --global', 'Remove from global installation', false)\n .option('-s, --skill <names...>', 'Remove one or more skills')\n .option('-a, --agent <agents...>', 'Target specific agents')\n .option('-f, --force', 'Force removal even if not in lockfile', false)\n .action(async (options) => {\n if (shouldUseInteractiveMode(options)) {\n render(React.createElement(App, { command: 'remove' }))\n return\n }\n\n // CLI mode - dynamic import\n const { runCliRemove } = await import('./cli/remove')\n await runCliRemove(options)\n })\n\n// Update command\nprogram\n .command('update')\n .description('Update installed skills to the latest version')\n .option('-s, --skill <name>', 'Update a specific skill')\n .action(async (options) => {\n if (shouldUseInteractiveMode(options)) {\n render(React.createElement(App, { command: 'update' }))\n return\n }\n\n // CLI mode - dynamic import\n const { runCliUpdate } = await import('./cli/update')\n await runCliUpdate(options)\n })\n\n// Cache command\nprogram\n .command('cache')\n .description('Manage the skills cache')\n .option('--clear', 'Clear all cached skills and registry')\n .option('--clear-registry', 'Clear only the registry cache')\n .option('--path', 'Show cache directory path')\n .action(async (options) => {\n // CLI mode - dynamic import\n const { runCliCache } = await import('./cli/cache')\n runCliCache(options)\n })\n\n// Credits command\nprogram\n .command('credits')\n .description('Show project contributors and credits')\n .action(() => {\n render(React.createElement(App, { command: 'credits' }))\n })\n\n// Audit log command\nprogram\n .command('audit')\n .description('View audit log of skill operations')\n .option('-n, --limit <number>', 'Number of entries to show', '10')\n .option('--path', 'Show audit log file path')\n .action(async (options) => {\n const { runCliAudit } = await import('./cli/audit')\n await runCliAudit(options)\n })\n\nprogram.parse(process.argv)\n\nfunction shouldUseInteractiveMode(options: Record<string, unknown>): boolean {\n const optionKeys = Object.keys(options).filter((key) => key !== 'parent')\n return optionKeys.length === 0\n}\n", "import { Box, useApp } from 'ink'\nimport { useEffect, useState } from 'react'\n\nimport { useKonamiCode } from './hooks'\nimport { ArcadeMenu, CreditsView, InstallWizard, ListView, RemoveWizard, UpdateView } from './views'\n\ninterface AppProps {\n command?: string\n args?: string[]\n}\n\nexport const App = ({ command = 'install' }: AppProps) => {\n const { exit } = useApp()\n const [arcade, setArcade] = useState(command === 'arcade')\n const { activated, reset } = useKonamiCode()\n\n useEffect(() => {\n if (activated && !arcade) {\n setArcade(true)\n reset()\n }\n }, [activated, arcade, reset])\n\n if (command === 'credits') {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <CreditsView onExit={exit} />\n </Box>\n )\n }\n\n if (arcade) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <ArcadeMenu\n onExit={() => {\n if (command === 'arcade') {\n exit()\n } else {\n setArcade(false)\n }\n }}\n />\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"column\" padding={1}>\n {command === 'list' && <ListView onExit={exit} />}\n {command === 'remove' && <RemoveWizard onExit={exit} />}\n {command === 'update' && <UpdateView onExit={exit} />}\n {(command === 'install' || !command) && <InstallWizard onExit={exit} />}\n </Box>\n )\n}\n", "import { useEffect, useMemo, useState } from 'react'\nimport { detectInstalledAgents, getAllAgentTypes } from '@peterson-benhame/core'\nimport type { AgentType } from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\n\nexport function useAgents() {\n const [selectedAgents, setSelectedAgents] = useState<AgentType[]>([])\n const [installedAgents, setInstalledAgents] = useState<AgentType[]>([])\n const [loading, setLoading] = useState(true)\n const allAgents = useMemo(() => getAllAgentTypes(), [])\n\n useEffect(() => {\n const timer = setTimeout(() => {\n const detected = detectInstalledAgents(ports)\n setInstalledAgents(detected)\n setSelectedAgents(detected)\n setLoading(false)\n }, 800)\n\n return () => clearTimeout(timer)\n }, [])\n\n const toggleAgent = (agent: AgentType) => {\n setSelectedAgents((prev) => (prev.includes(agent) ? prev.filter((a) => a !== agent) : [...prev, agent]))\n }\n\n return { allAgents, installedAgents, selectedAgents, setSelectedAgents, toggleAgent, loading }\n}\n", "import { useEffect, useState } from 'react'\n\nimport type { UserConfig } from '../services/config'\nimport {\n hasShortcutsBeenDismissed,\n isFirstLaunch,\n loadConfig,\n markFirstLaunchComplete,\n markShortcutsDismissed,\n saveConfig,\n} from '../services/config'\n\ninterface UseConfigReturn {\n config: UserConfig | null\n loading: boolean\n error: string | null\n isFirstLaunch: boolean\n hasShortcutsBeenDismissed: boolean\n markFirstLaunchComplete: () => Promise<void>\n markShortcutsDismissed: () => Promise<void>\n updateConfig: (updates: Partial<UserConfig>) => Promise<void>\n}\n\nexport function useConfig(): UseConfigReturn {\n const [config, setConfig] = useState<UserConfig | null>(null)\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [isFirstLaunchState, setIsFirstLaunchState] = useState(false)\n const [hasShortcutsDismissedState, setHasShortcutsDismissedState] = useState(false)\n\n useEffect(() => {\n let mounted = true\n\n const load = async () => {\n try {\n const [configData, firstLaunch, shortcutsDismissed] = await Promise.all([\n loadConfig(),\n isFirstLaunch(),\n hasShortcutsBeenDismissed(),\n ])\n\n if (mounted) {\n setConfig(configData)\n setIsFirstLaunchState(firstLaunch)\n setHasShortcutsDismissedState(shortcutsDismissed)\n }\n } catch (err: unknown) {\n if (mounted) setError(err instanceof Error ? err.message : String(err))\n } finally {\n if (mounted) setLoading(false)\n }\n }\n\n load()\n\n return () => {\n mounted = false\n }\n }, [])\n\n const handleMarkFirstLaunchComplete = async () => {\n try {\n await markFirstLaunchComplete()\n setIsFirstLaunchState(false)\n const updatedConfig = await loadConfig()\n setConfig(updatedConfig)\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : String(err))\n throw err\n }\n }\n\n const handleMarkShortcutsDismissed = async () => {\n try {\n await markShortcutsDismissed()\n setHasShortcutsDismissedState(true)\n const updatedConfig = await loadConfig()\n setConfig(updatedConfig)\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : String(err))\n throw err\n }\n }\n\n const handleUpdateConfig = async (updates: Partial<UserConfig>) => {\n try {\n await saveConfig(updates)\n const updatedConfig = await loadConfig()\n setConfig(updatedConfig)\n\n if ('firstLaunchComplete' in updates) {\n setIsFirstLaunchState(!updates.firstLaunchComplete)\n }\n\n if ('shortcutsOverlayDismissed' in updates) {\n setHasShortcutsDismissedState(Boolean(updates.shortcutsOverlayDismissed))\n }\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : String(err))\n throw err\n }\n }\n\n return {\n config,\n loading,\n error,\n isFirstLaunch: isFirstLaunchState,\n hasShortcutsBeenDismissed: hasShortcutsDismissedState,\n markFirstLaunchComplete: handleMarkFirstLaunchComplete,\n markShortcutsDismissed: handleMarkShortcutsDismissed,\n updateConfig: handleUpdateConfig,\n }\n}\n", "// Package metadata\nexport const PACKAGE_NAME = '@peterson-benhame/agent-skills'\nexport const SKILLS_CATALOG_PACKAGE = '@peterson-benhame/skills-catalog'\n\n// Directory and file paths\nexport const CONFIG_DIR = '.agent-skills'\nexport const CACHE_FILE = 'cache.json'\nexport const CONFIG_FILE = 'config.json'\nexport const SKILL_META_FILE = '.skill-meta.json'\n\n// Project structure\nexport const AGENTS_DIR = '.agents'\nexport const CANONICAL_SKILLS_DIR = 'skills'\nexport const LOCK_FILE = '.skill-lock.json'\nexport const LOCK_FILE_BACKUP = '.skill-lock.json.backup'\n\n// Global configuration\nexport const GLOBAL_CONFIG_DIR = '.agent-skills'\nexport const AUDIT_LOG_FILE = 'audit.log'\n\n// Cache directory structure\nexport const CACHE_BASE_DIR = '.cache'\nexport const CACHE_NAMESPACE = 'agent-skills'\nexport const SKILLS_SUBDIR = 'skills'\nexport const REGISTRY_CACHE_FILENAME = 'registry.json'\n\n// Cache settings\nexport const UPDATE_CHECK_CACHE_TTL_MS = 24 * 60 * 60 * 1000 // 24 hours\nexport const UPDATE_CHECK_TIMEOUT_MS = 3_000 // 3 seconds\n\n// Registry/CDN settings\nexport const REGISTRY_CACHE_TTL_MS = 24 * 60 * 60 * 1000 // 24 hours\nexport const FETCH_TIMEOUT_MS = 15_000\nexport const MAX_RETRIES = 3\nexport const RETRY_BASE_DELAY_MS = 500\nexport const MAX_CONCURRENT_DOWNLOADS = 10\n\n// Versioning\nexport const CURRENT_CONFIG_VERSION = '1.0.0'\n\n// UI Messages\nexport const MESSAGES = {\n UPDATE_AVAILABLE: (current: string, update: string) => `Update available: ${current} \u2192 ${update}`,\n TIP_INSTALL_UPDATE: 'Tip: Install globally to update:',\n TIP_INSTALL_ACCESS: 'Tip: Install globally for easier access:',\n UPDATE_COMMAND: `npm update -g ${PACKAGE_NAME}`,\n INSTALL_COMMAND: `npm install -g ${PACKAGE_NAME}`,\n DESCRIPTION: 'Curated skills to power up your coding agents',\n} as const\n", "import { useMemo, useState } from 'react'\n\ninterface FilterOptions<T> {\n keys: (keyof T & string)[]\n}\n\nexport function useFilter<T>(items: T[], options: FilterOptions<T>) {\n const [query, setQuery] = useState('')\n\n const filtered = useMemo(() => {\n if (!query.trim()) return items\n\n const tokens = query\n .toLowerCase()\n .split(/\\s+/)\n .filter((t) => t.length > 0)\n\n return items.filter((item) => {\n const searchable = options.keys\n .map((key) => {\n const value = item[key]\n return typeof value === 'string' ? value.toLowerCase() : ''\n })\n .join(' ')\n\n return tokens.every((token) => searchable.includes(token))\n })\n }, [query, items, options.keys])\n\n return { query, setQuery, filtered, hasFilter: query.trim().length > 0 }\n}\n", "import { useState } from 'react'\nimport { ensureSkillDownloaded, fetchRegistry, forceDownloadSkill, installSkills } from '@peterson-benhame/core'\nimport type { InstallOptions, InstallResult, SkillInfo } from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\n\nexport function useInstaller() {\n const [progress, setProgress] = useState({ current: 0, total: 0, skill: '' })\n const [results, setResults] = useState<InstallResult[]>([])\n const [installing, setInstalling] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const install = async (skills: SkillInfo[], options: InstallOptions) => {\n setInstalling(true)\n setError(null)\n setProgress({ current: 0, total: skills.length * options.agents.length, skill: 'Downloading...' })\n\n // Bypass the 24h registry TTL so install/update see newly published content hashes.\n await fetchRegistry(ports, true)\n\n const resolvedSkills: SkillInfo[] = []\n for (const skill of skills) {\n // Never reuse skill.path from getRemoteSkills \u2014 it points at the local cache\n // whenever SKILL.md exists, even when the registry has a newer contentHash.\n // ensureSkillDownloaded refreshes stale cache; isUpdate always redownloads.\n const path = options.isUpdate\n ? await forceDownloadSkill(ports, skill.name)\n : await ensureSkillDownloaded(ports, skill.name)\n if (path) resolvedSkills.push({ ...skill, path })\n }\n\n setProgress({ current: 0, total: resolvedSkills.length * options.agents.length, skill: 'Installing...' })\n\n try {\n const res = await installSkills(ports, resolvedSkills, options)\n setResults(res)\n return res\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : String(err))\n return []\n } finally {\n setInstalling(false)\n }\n }\n\n return { install, progress, results, installing, error }\n}\n", "import { useInput } from 'ink'\nimport { useCallback, useRef, useState } from 'react'\n\nconst KONAMI_SEQUENCE = ['up', 'up', 'down', 'down', 'left', 'right', 'left', 'right', 'b', 'a'] as const\n\ntype KonamiKey = (typeof KONAMI_SEQUENCE)[number]\n\nexport function useKonamiCode() {\n const [activated, setActivated] = useState(false)\n const bufferRef = useRef<KonamiKey[]>([])\n\n useInput((input, key) => {\n if (activated) return\n let mapped: KonamiKey | null = null\n if (key.upArrow) mapped = 'up'\n else if (key.downArrow) mapped = 'down'\n else if (key.leftArrow) mapped = 'left'\n else if (key.rightArrow) mapped = 'right'\n else if (input.toLowerCase() === 'b') mapped = 'b'\n else if (input.toLowerCase() === 'a') mapped = 'a'\n\n if (!mapped) {\n bufferRef.current = []\n return\n }\n\n bufferRef.current.push(mapped)\n\n if (bufferRef.current.length > KONAMI_SEQUENCE.length) {\n bufferRef.current = bufferRef.current.slice(-KONAMI_SEQUENCE.length)\n }\n\n if (\n bufferRef.current.length === KONAMI_SEQUENCE.length &&\n bufferRef.current.every((k, i) => k === KONAMI_SEQUENCE[i])\n ) {\n setActivated(true)\n bufferRef.current = []\n }\n })\n\n const reset = useCallback(() => {\n setActivated(false)\n bufferRef.current = []\n }, [])\n\n return { activated, reset }\n}\n", "import { useState } from 'react'\nimport { removeSkill } from '@peterson-benhame/core'\nimport type { AgentType } from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\n\nexport interface RemoveResult {\n skill: string\n agent: string\n success: boolean\n error?: string\n}\n\nexport function useRemover() {\n const [progress, setProgress] = useState({ current: 0, total: 0, skill: '' })\n const [results, setResults] = useState<RemoveResult[]>([])\n const [removing, setRemoving] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const remove = async (skillName: string, agents: AgentType[], global = false) => {\n setRemoving(true)\n setProgress({ current: 0, total: agents.length, skill: skillName })\n setError(null)\n\n try {\n const res = await removeSkill(ports, skillName, agents, { global })\n setResults((prev) => [...prev, ...res])\n return res\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : String(err))\n return []\n } finally {\n setRemoving(false)\n }\n }\n\n const removeMultiple = async (skillsToRemove: { name: string; agents: AgentType[] }[]) => {\n setRemoving(true)\n const totalOps = skillsToRemove.reduce((acc, item) => acc + item.agents.length, 0)\n setProgress({ current: 0, total: totalOps, skill: 'Initializing...' })\n setResults([])\n setError(null)\n\n try {\n let completedOps = 0\n for (const item of skillsToRemove) {\n setProgress({ current: completedOps, total: totalOps, skill: item.name })\n const res = await removeSkill(ports, item.name, item.agents, {})\n setResults((prev) => [...prev, ...res])\n completedOps += item.agents.length\n }\n } catch (err: unknown) {\n setError(err instanceof Error ? err.message : String(err))\n } finally {\n setRemoving(false)\n }\n }\n\n return { remove, removeMultiple, progress, results, removing, error }\n}\n", "import { readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { useEffect, useState } from 'react'\nimport {\n ensureSkillDownloaded,\n getSkillCachePath,\n getSkillMetadata,\n isSkillCached,\n type SkillMetadata,\n} from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\n\nexport interface SkillContent {\n metadata: SkillMetadata | null\n content: string | null\n loading: boolean\n error: string | null\n}\n\nexport function useSkillContent(skillName: string | null): SkillContent {\n const [metadata, setMetadata] = useState<SkillMetadata | null>(null)\n const [content, setContent] = useState<string | null>(null)\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n useEffect(() => {\n if (!skillName) {\n setMetadata(null)\n setContent(null)\n setLoading(false)\n setError(null)\n return\n }\n\n let mounted = true\n setLoading(true)\n setError(null)\n\n const load = async () => {\n try {\n // Preview should not refresh stale cache \u2014 only download when missing.\n // Install/update own the freshness path via ensureSkillDownloaded.\n const cachePathPromise = isSkillCached(ports, skillName)\n ? Promise.resolve(getSkillCachePath(ports, skillName))\n : ensureSkillDownloaded(ports, skillName).catch(() => null)\n\n const [meta, cachePath] = await Promise.all([\n getSkillMetadata(ports, skillName).catch(() => null),\n cachePathPromise,\n ])\n\n if (!mounted) return\n if (meta) setMetadata(meta)\n\n const resolvedPath = cachePath ?? getSkillCachePath(ports, skillName)\n\n try {\n const skillMd = readFileSync(join(resolvedPath, 'SKILL.md'), 'utf-8')\n setContent(skillMd)\n } catch {\n setError('Failed to load skill content')\n }\n } catch (err: unknown) {\n if (mounted) {\n setError(err instanceof Error ? err.message : String(err))\n }\n } finally {\n if (mounted) setLoading(false)\n }\n }\n\n load()\n return () => {\n mounted = false\n }\n }, [skillName])\n\n return { metadata, content, loading, error }\n}\n", "import { useEffect, useState } from 'react'\nimport { discoverSkillsAsync, groupSkillsByCategory } from '@peterson-benhame/core'\nimport type { SkillInfo } from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\nimport type { GroupedSkills } from '../types'\n\nexport function useSkills() {\n const [skills, setSkills] = useState<SkillInfo[]>([])\n const [loading, setLoading] = useState(true)\n const [error, setError] = useState<string | null>(null)\n const [groupedSkills, setGroupedSkills] = useState<GroupedSkills>(new Map())\n\n useEffect(() => {\n let mounted = true\n\n const load = async () => {\n try {\n const data = await discoverSkillsAsync(ports)\n\n if (mounted) {\n setSkills(data)\n setGroupedSkills(groupSkillsByCategory(ports, data))\n }\n } catch (err: unknown) {\n if (mounted) setError(err instanceof Error ? err.message : String(err))\n } finally {\n if (mounted) setLoading(false)\n }\n }\n\n load()\n return () => {\n mounted = false\n }\n }, [])\n\n return { skills, loading, error, groupedSkills }\n}\n", "import { useState } from 'react'\n\nexport function useWizardStep(totalSteps: number) {\n const [step, setStep] = useState(1)\n\n const next = () => setStep((s) => Math.min(s + 1, totalSteps))\n const back = () => setStep((s) => Math.max(s - 1, 1))\n const goTo = (s: number) => setStep(s)\n\n return {\n step,\n next,\n back,\n goTo,\n isFirst: step === 1,\n isLast: step === totalSteps,\n progress: step / totalSteps,\n }\n}\n", "import { Box, Text } from 'ink'\nimport BigText from 'ink-big-text'\nimport Gradient from 'ink-gradient'\nimport { useEffect, useState } from 'react'\n\nimport { FooterBar } from '../../components/FooterBar'\nimport { SelectPrompt } from '../../components/SelectPrompt'\nimport { colors, symbols } from '../../theme'\nimport { VibeInvaders } from './VibeInvaders'\n\ntype ArcadeScreen = 'menu' | 'invaders'\n\ninterface ArcadeMenuProps {\n onExit: () => void\n}\n\nconst menuItems = [\n { label: 'Vibe Invaders', value: 'invaders' as const, hint: 'Fight vibe-coding!' },\n { label: 'Back', value: 'back' as const, hint: 'Return to CLI' },\n]\n\nconst SCANLINE = '\\u2591'.repeat(56)\n\nexport function ArcadeMenu({ onExit }: ArcadeMenuProps) {\n const [screen, setScreen] = useState<ArcadeScreen>('menu')\n const [blinkVisible, setBlinkVisible] = useState(true)\n\n useEffect(() => {\n const interval = setInterval(() => setBlinkVisible((v) => !v), 600)\n return () => clearInterval(interval)\n }, [])\n\n const handleSelect = (value: 'invaders' | 'back') => {\n if (value === 'back') {\n onExit()\n return\n }\n\n setScreen(value)\n }\n\n if (screen === 'invaders') return <VibeInvaders onExit={() => setScreen('menu')} />\n\n return (\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Box marginBottom={0}>\n <Gradient name=\"cristal\">\n <Text>{SCANLINE}</Text>\n </Gradient>\n </Box>\n\n <Box marginBottom={0}>\n <Gradient name=\"pastel\">\n <BigText text=\"ARCADE\" font=\"chrome\" />\n </Gradient>\n </Box>\n\n <Box marginBottom={0}>\n <Gradient name=\"cristal\">\n <Text>{SCANLINE}</Text>\n </Gradient>\n </Box>\n\n <Box marginBottom={1} marginTop={1}>\n <Text color={blinkVisible ? colors.warning : colors.bg} bold>\n {symbols.sparkle} SECRET UNLOCKED {symbols.sparkle}\n </Text>\n </Box>\n\n <Box marginBottom={1}>\n <Text color={colors.textDim}>\n {symbols.diamond} Choose your adventure {symbols.diamond}\n </Text>\n </Box>\n\n <Box width={50}>\n <SelectPrompt items={menuItems} onSelect={handleSelect} onCancel={onExit} hideFooter />\n </Box>\n\n <FooterBar\n hints={[\n { key: '\\u2191\\u2193', label: 'navigate' },\n { key: '\\u23CE', label: 'select' },\n { key: 'esc', label: 'back', color: colors.warning },\n ]}\n />\n </Box>\n )\n}\n", "import { Box, Text } from 'ink'\nimport { memo } from 'react'\n\nimport { colors, symbols } from '../theme'\n\nexport interface FooterHint {\n key: string\n label: string\n color?: string\n}\n\nexport interface FooterBarProps {\n hints: FooterHint[]\n status?: React.ReactNode\n}\n\nexport const FooterBar = memo(function FooterBar({ hints, status }: FooterBarProps) {\n return (\n <Box marginTop={1} borderStyle=\"round\" borderColor={colors.border} paddingX={1}>\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Text>\n {hints.map((hint, i) => (\n <Text key={hint.key}>\n {i > 0 && <Text color={colors.textDim}> {symbols.dot} </Text>}\n <Text color={hint.color ?? colors.accent} bold>\n {hint.key}\n </Text>\n <Text color={colors.textDim}> {hint.label}</Text>\n </Text>\n ))}\n </Text>\n {status && <Box>{status}</Box>}\n </Box>\n </Box>\n )\n})\n", "export const colors = {\n primary: '#3b82f6',\n primaryLight: '#60a5fa',\n primaryDark: '#1e3a8a',\n accent: '#06b6d4',\n accentLight: '#22d3ee',\n success: '#22c55e',\n warning: '#f59e0b',\n error: '#ef4444',\n text: '#f8fafc',\n textDim: '#94a3b8',\n textMuted: '#64748b',\n border: '#334155',\n bg: '#0f172a',\n bgLight: '#1e293b',\n} as const\n\nexport const gradientStops = [\n { color: '#1e3a8a', pos: 0 },\n { color: '#3b82f6', pos: 0.3 },\n { color: '#0ea5e9', pos: 0.5 },\n { color: '#06b6d4', pos: 0.7 },\n { color: '#22d3ee', pos: 1 },\n] as const\n", "export const symbols = {\n bar: '\u2502',\n barEnd: '\u2514',\n radioActive: '\u25CF',\n radioInactive: '\u25CB',\n checkboxActive: '\u25FC',\n checkboxInactive: '\u25FB',\n diamond: '\u25C6',\n arrow: '\u203A',\n arrowRight: '\u2192',\n arrowUp: '\u2191',\n arrowDown: '\u2193',\n dot: '\u00B7',\n bullet: '\u25B8',\n check: '\u2713',\n cross: '\u2717',\n star: '\u2605',\n sparkle: '\u2726',\n installed: '\u25CF',\n warning: '\u26A0',\n info: '\u2139',\n} as const\n", "import { Box, Text, useInput } from 'ink'\nimport { useMemo, useState } from 'react'\n\nimport { colors, symbols } from '../theme'\n\nexport interface SelectOption<T> {\n label: string\n value: T\n hint?: string\n}\n\ninterface SelectPromptProps<T> {\n items: SelectOption<T>[]\n onSelect: (value: T) => void\n onCancel?: () => void\n initialIndex?: number\n itemLimit?: number\n hideFooter?: boolean\n footerRight?: React.ReactNode\n}\n\nexport function SelectPrompt<T>({\n items,\n onSelect,\n onCancel,\n initialIndex = 0,\n itemLimit = 10,\n hideFooter,\n footerRight,\n}: SelectPromptProps<T>) {\n const [selectedIndex, setSelectedIndex] = useState(initialIndex)\n const [offset, setOffset] = useState(0)\n\n useInput((input, key) => {\n if (key.upArrow) {\n setSelectedIndex((prev) => Math.max(0, prev - 1))\n if (selectedIndex <= offset) setOffset((prev) => Math.max(0, prev - 1))\n }\n\n if (key.downArrow) {\n setSelectedIndex((prev) => Math.min(items.length - 1, prev + 1))\n if (selectedIndex >= offset + itemLimit - 1) setOffset((prev) => Math.min(items.length - itemLimit, prev + 1))\n }\n\n if (key.return) onSelect(items[selectedIndex].value)\n if (key.escape && onCancel) onCancel()\n })\n\n const visibleItems = useMemo(() => {\n return items.slice(offset, offset + itemLimit)\n }, [items, offset, itemLimit])\n\n return (\n <Box flexDirection=\"column\">\n {visibleItems.map((item, index) => {\n const isFocused = index + offset === selectedIndex\n return (\n <Box key={`${item.label}-${index}`} backgroundColor={isFocused ? colors.bgLight : undefined} paddingX={1}>\n <Box width={2}>\n <Text color={isFocused ? colors.accent : colors.textMuted}>{isFocused ? symbols.bullet : ' '}</Text>\n </Box>\n <Text color={isFocused ? colors.accent : colors.text} bold={isFocused}>\n {isFocused ? symbols.radioActive : symbols.radioInactive} {item.label}\n </Text>\n {isFocused && item.hint && (\n <Text color={colors.textDim}>\n {' '}\n {symbols.dot} {item.hint}\n </Text>\n )}\n </Box>\n )\n })}\n\n {items.length > itemLimit && (\n <Box marginTop={1} paddingX={1}>\n <Text color={colors.textDim}>\n {symbols.arrowUp}\n {symbols.arrowDown} {offset + 1}-{Math.min(offset + itemLimit, items.length)} of {items.length}\n </Text>\n </Box>\n )}\n\n {!hideFooter && (\n <Box marginTop={1} borderStyle=\"round\" borderColor={colors.border} paddingX={1}>\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Text>\n <Text color={colors.success} bold>\n enter\n </Text>\n <Text color={colors.textDim}> select</Text>\n {onCancel && (\n <>\n <Text color={colors.textDim}> {symbols.dot} </Text>\n <Text color={colors.warning} bold>\n esc\n </Text>\n <Text color={colors.textDim}> back</Text>\n </>\n )}\n </Text>\n {footerRight && <Box>{footerRight}</Box>}\n </Box>\n </Box>\n )}\n </Box>\n )\n}\n", "import { Box, Text, useInput, useStdout } from 'ink'\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nimport { colors } from '../../theme'\n\nconst MAX_WIDTH = 100\nconst GAME_HEIGHT = 16\nconst TICK_MS = 50\nconst BASE_MOVE_EVERY = 10\nconst RATE_LIMIT_PENALTY = 30\nconst SNIPER_MULTIPLIER = 5\n\nconst LOSE_MESSAGES = [\n 'BANKRUPT. Your burn rate was too high.',\n 'DOWN ROUND. Valuation dropped to zero.',\n 'RUNWAY EXPIRED. Back to living with parents.',\n 'SERVER COSTS > REVENUE. You are cooked.',\n 'AUDIT FAILED. Too much tech debt.',\n]\n\nconst WIN_MESSAGES = [\n 'ACQUIRED BY BIG TECH. Golden handcuffs on.',\n 'SERIES B SECURED. Keep burning cash!',\n 'IPO SUCCESSFUL. Time to buy a yacht.',\n 'PROFITABLE? No, but the vibes are great.',\n]\n\nconst INVADER_ROWS: string[][] = [\n ['AGI_SOON', '100x_DEV', 'LOVABLE', 'HYPE'],\n ['DEEPSEEK', 'GEMINI', 'GPT', 'V0_DEV'],\n ['TAB_SPAM', 'NO_READ', 'TRUST_ME', 'YOLO'],\n ['SLOP', 'SPAGHETTI', 'ANY_TYPE', 'BUG'],\n]\n\ninterface Position {\n x: number\n y: number\n}\n\ninterface Invader extends Position {\n label: string\n alive: boolean\n width: number\n}\n\ninterface GameState {\n player: Position\n playerBullets: Position[]\n enemyBullets: Position[]\n invaders: Invader[]\n score: number\n lives: number\n gameOver: boolean\n won: boolean\n invaderDirection: 1 | -1\n tickCount: number\n flash: boolean\n glitch: boolean\n rateLimited: number\n}\n\nfunction createInvaders(cols: number): Invader[] {\n const invaders: Invader[] = []\n const longestWord = Math.max(...INVADER_ROWS.flat().map((w) => w.length))\n const colSpacing = longestWord + 4\n const totalWidth = INVADER_ROWS[0].length * colSpacing\n const startX = Math.floor((cols - totalWidth) / 2)\n\n for (let row = 0; row < INVADER_ROWS.length; row++) {\n for (let col = 0; col < INVADER_ROWS[row].length; col++) {\n const label = INVADER_ROWS[row][col]\n invaders.push({\n x: Math.max(0, startX + col * colSpacing),\n y: 1 + row * 2,\n label,\n width: label.length,\n alive: true,\n })\n }\n }\n\n return invaders\n}\n\ninterface VibeInvadersProps {\n onExit: () => void\n}\n\nexport function VibeInvaders({ onExit }: VibeInvadersProps) {\n const { stdout } = useStdout()\n\n const terminalCols = stdout?.columns ?? 80\n const gameWidth = Math.max(60, Math.min(terminalCols - 4, MAX_WIDTH))\n const finalMessageRef = useRef<string>('')\n\n const [state, setState] = useState<GameState>(() => ({\n player: { x: Math.floor(gameWidth / 2), y: GAME_HEIGHT - 1 },\n playerBullets: [],\n enemyBullets: [],\n invaders: createInvaders(gameWidth),\n score: 0,\n lives: 5,\n gameOver: false,\n won: false,\n invaderDirection: 1,\n tickCount: 0,\n flash: false,\n glitch: false,\n rateLimited: 0,\n }))\n\n if ((state.gameOver || state.won) && !finalMessageRef.current) {\n const pool = state.won ? WIN_MESSAGES : LOSE_MESSAGES\n finalMessageRef.current = pool[Math.floor(Math.random() * pool.length)]\n }\n\n useInput((input, key) => {\n if (state.gameOver || state.won) {\n if (key.return || key.escape) onExit()\n return\n }\n\n if (key.escape) {\n onExit()\n return\n }\n\n setState((prev) => {\n let newX = prev.player.x\n if (key.leftArrow) newX = Math.max(0, prev.player.x - 2)\n if (key.rightArrow) newX = Math.min(gameWidth - 1, prev.player.x + 2)\n\n let newBullets = prev.playerBullets\n let currentRateLimit = prev.rateLimited\n\n if (input === ' ' && currentRateLimit === 0) {\n if (prev.playerBullets.length >= 2) {\n currentRateLimit = RATE_LIMIT_PENALTY\n newBullets = []\n } else {\n newBullets = [...prev.playerBullets, { x: newX, y: prev.player.y - 1 }]\n }\n }\n\n return { ...prev, player: { ...prev.player, x: newX }, playerBullets: newBullets, rateLimited: currentRateLimit }\n })\n })\n\n const tick = useCallback(() => {\n setState((prev) => {\n if (prev.gameOver || prev.won) return prev\n\n const tick = prev.tickCount + 1\n let score = prev.score\n let lives = prev.lives\n let gameOver: boolean = prev.gameOver\n let flash = false\n let glitch = false\n const rateLimited = prev.rateLimited > 0 ? prev.rateLimited - 1 : 0\n\n // Logic\n const aliveInvaders = prev.invaders.filter((i) => i.alive)\n const totalInvaders = INVADER_ROWS.flat().length\n const survivalRatio = aliveInvaders.length / totalInvaders\n const moveEvery = Math.max(2, Math.floor(BASE_MOVE_EVERY * survivalRatio) + 1)\n const shootChance = 0.02 + 0.08 * (1 - survivalRatio)\n\n // Bullets\n let pBullets = prev.playerBullets.map((b) => ({ ...b, y: b.y - 1 })).filter((b) => b.y >= 0)\n let eBullets = prev.enemyBullets.map((b) => ({ ...b, y: b.y + 1 })).filter((b) => b.y < GAME_HEIGHT)\n\n const invaders = prev.invaders.map((i) => ({ ...i }))\n\n // Collisions: Player -> Invader\n for (const b of pBullets) {\n if (b.y === -1) continue\n for (const inv of invaders) {\n if (!inv.alive) continue\n if (b.y === inv.y && b.x >= inv.x && b.x < inv.x + inv.width) {\n inv.alive = false\n b.y = -1\n score += 100\n flash = true\n break\n }\n }\n }\n\n pBullets = pBullets.filter((b) => b.y !== -1)\n\n // Collisions: Enemy -> Player\n if (eBullets.some((b) => b.x === prev.player.x && b.y === prev.player.y)) {\n lives -= 1\n flash = true\n glitch = true\n eBullets = []\n if (lives <= 0) gameOver = true\n }\n\n // Win?\n if (invaders.every((i) => !i.alive)) return { ...prev, won: true, score: score + lives * 1000, invaders }\n\n // Shoot\n if (aliveInvaders.length > 0) {\n const shooters = aliveInvaders.filter((inv) => {\n const inSight = prev.player.x >= inv.x - 1 && prev.player.x <= inv.x + inv.width + 1\n return Math.random() < (inSight ? shootChance * SNIPER_MULTIPLIER : shootChance)\n })\n\n if (shooters.length > 0) {\n const s = shooters[Math.floor(Math.random() * shooters.length)]\n eBullets.push({ x: s.x + Math.floor(s.width / 2), y: s.y + 1 })\n }\n }\n\n // Move\n let dir = prev.invaderDirection\n\n if (tick % moveEvery === 0) {\n const xs = invaders.filter((i) => i.alive).map((i) => i.x)\n const minX = Math.min(...xs)\n const maxX = Math.max(...invaders.filter((i) => i.alive).map((i) => i.x + i.width))\n if (maxX >= gameWidth - 2 && dir === 1) dir = -1\n if (minX <= 0 && dir === -1) dir = 1\n invaders.forEach((i) => i.alive && (i.x += dir))\n }\n\n // Drop\n if (tick % 45 === 0) {\n invaders.forEach((i) => i.alive && (i.y += 1))\n if (invaders.some((i) => i.alive && i.y >= GAME_HEIGHT - 1)) gameOver = true\n }\n\n return {\n ...prev,\n playerBullets: pBullets,\n enemyBullets: eBullets,\n invaders,\n score,\n lives,\n gameOver,\n invaderDirection: dir,\n tickCount: tick,\n flash,\n glitch,\n rateLimited,\n }\n })\n }, [gameWidth])\n\n useEffect(() => {\n const t = setInterval(tick, TICK_MS)\n return () => clearInterval(t)\n }, [tick])\n\n const renderGrid = () => {\n const rows = Array.from({ length: GAME_HEIGHT }, () => Array(gameWidth).fill(' '))\n\n state.invaders.forEach((inv) => {\n if (inv.alive) {\n for (let i = 0; i < inv.width; i++) {\n if (inv.x + i < gameWidth && inv.y < GAME_HEIGHT) rows[inv.y][inv.x + i] = state.glitch ? '?' : inv.label[i]\n }\n }\n })\n\n state.playerBullets.forEach((b) => {\n if (b.x < gameWidth && b.y < GAME_HEIGHT) rows[b.y][b.x] = '$'\n })\n\n state.enemyBullets.forEach((b) => {\n if (b.x < gameWidth && b.y < GAME_HEIGHT) rows[b.y][b.x] = '*'\n })\n\n const { x, y } = state.player\n if (x < gameWidth && y < GAME_HEIGHT) rows[y][x] = state.rateLimited > 0 ? 'X' : '^'\n return rows.map((r) => r.join('')).join('\\n')\n }\n\n const statusColor = state.rateLimited > 0 ? colors.error : colors.accent\n const gridColor = state.glitch ? colors.warning : state.flash ? colors.error : colors.success\n\n return (\n <Box width=\"100%\" alignItems=\"center\" flexDirection=\"column\">\n <Box width={gameWidth + 4} flexDirection=\"column\" alignItems=\"center\">\n <Box width={gameWidth} flexDirection=\"row\" paddingX={1}>\n <Box width=\"35%\">\n <Text color={statusColor} bold>\n {state.rateLimited > 0 ? `LIMIT (${state.rateLimited})` : `$${state.score}k`}\n </Text>\n </Box>\n <Box width=\"30%\" justifyContent=\"center\">\n <Text color={colors.warning} bold>\n VIBE INVADERS\n </Text>\n </Box>\n <Box width=\"35%\" justifyContent=\"flex-end\">\n <Text color={colors.success} bold>\n RUNWAY: {'$'.repeat(state.lives)}\n </Text>\n </Box>\n </Box>\n\n <Box\n borderStyle=\"round\"\n borderColor={state.rateLimited > 0 ? colors.error : colors.border}\n flexDirection=\"column\"\n width={gameWidth + 2}\n height={GAME_HEIGHT + 2}\n >\n <Text color={state.gameOver ? colors.error : gridColor}>{renderGrid()}</Text>\n </Box>\n\n <Box\n marginTop={0}\n width={gameWidth + 2}\n justifyContent=\"center\"\n borderStyle=\"round\"\n borderColor={colors.accent}\n >\n {state.gameOver || state.won ? (\n <Text color={state.won ? colors.success : colors.error} bold>\n {finalMessageRef.current} Val: ${state.score}k\n </Text>\n ) : (\n <Box gap={1}>\n <Text color={colors.accent}>\u2190\u2192</Text>\n <Text> move </Text>\n <Text color={colors.accent}>spc</Text>\n <Text> shoot </Text>\n <Text color={colors.accent}>esc</Text>\n <Text> quit</Text>\n </Box>\n )}\n </Box>\n </Box>\n </Box>\n )\n}\n", "import { Box, Text, useInput } from 'ink'\n\nimport { Header } from '../components/Header'\nimport { SelectPrompt } from '../components/SelectPrompt'\nimport { colors, symbols } from '../theme'\n\ninterface ActionSelectorProps {\n onSelect: (action: 'install' | 'update' | 'remove') => void\n onBack?: () => void\n onCredits?: () => void\n}\n\nexport function ActionSelector({ onSelect, onBack, onCredits }: ActionSelectorProps) {\n const items = [\n { label: 'Install new skills', value: 'install' as const, hint: 'browse and select skills to install' },\n { label: 'Update existing skills', value: 'update' as const, hint: 'check for content changes' },\n { label: 'Remove installed skills', value: 'remove' as const, hint: 'uninstall skills from agents' },\n ]\n\n useInput((input) => {\n if (input === 'c' && onCredits) onCredits()\n })\n\n const creditsHint = (\n <Text>\n <Text color={colors.accent} bold>\n c\n </Text>\n <Text color={colors.textDim}> credits</Text>\n </Text>\n )\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box marginBottom={1}>\n <Text bold color={colors.primary}>\n {symbols.diamond} What would you like to do?\n </Text>\n </Box>\n\n <SelectPrompt items={items} onSelect={onSelect} onCancel={onBack} footerRight={creditsHint} />\n </Box>\n )\n}\n", "import { Box, Text } from 'ink'\nimport BigText from 'ink-big-text'\nimport Gradient from 'ink-gradient'\nimport { useAtomValue } from 'jotai'\nimport { useMemo } from 'react'\n\nimport { environmentCheckAtom } from '../atoms/environmentCheck'\nimport { PACKAGE_VERSION } from '../services/package-info'\nimport { symbols } from '../theme/symbols'\nimport { MESSAGES } from '../utils/constants'\n\nconst crystalColors = ['#1e3a8a', '#3b82f6', '#0ea5e9', '#06b6d4', '#22d3ee']\nconst SEPARATOR_CHAR = '\u2500'\n\nexport const Header = ({ notification: overrideNotification }: { notification?: React.ReactNode }) => {\n const envCheck = useAtomValue(environmentCheckAtom)\n\n const notification = useMemo(() => {\n if (overrideNotification) return overrideNotification\n\n const { updateAvailable, currentVersion, isGlobal, isLoading } = envCheck\n\n if (isLoading) return null\n\n if (updateAvailable && !isGlobal) {\n return (\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Text color=\"yellow\">\n {symbols.warning} {MESSAGES.UPDATE_AVAILABLE(currentVersion, updateAvailable)}\n </Text>\n <Text color=\"blue\">\n {symbols.info} {MESSAGES.TIP_INSTALL_UPDATE} <Text bold>{MESSAGES.INSTALL_COMMAND}</Text>\n </Text>\n </Box>\n )\n }\n\n if (updateAvailable) {\n return (\n <Text color=\"yellow\">\n {symbols.warning} {MESSAGES.UPDATE_AVAILABLE(currentVersion, updateAvailable)} (run{' '}\n <Text bold>{MESSAGES.UPDATE_COMMAND}</Text>)\n </Text>\n )\n }\n\n if (!isGlobal) {\n return (\n <Text color=\"blue\">\n {symbols.info} {MESSAGES.TIP_INSTALL_ACCESS} <Text bold>{MESSAGES.INSTALL_COMMAND}</Text>\n </Text>\n )\n }\n\n return null\n }, [overrideNotification, envCheck])\n\n return (\n <Box flexDirection=\"column\" paddingBottom={1}>\n <Box flexDirection=\"column\" alignItems=\"center\" marginBottom={1}>\n <Box marginBottom={-1}>\n <Gradient colors={['#1e3a8a', '#3b82f6']}>\n <BigText text=\"TLC\" font=\"tiny\" />\n </Gradient>\n </Box>\n\n <Box>\n <Gradient colors={crystalColors}>\n <BigText text=\"AGENT SKILLS\" font=\"block\" />\n </Gradient>\n </Box>\n\n <Box marginTop={-1} alignItems=\"center\">\n <Text color=\"#334155\">\u2500\u2500\u2500\u2500\u2500\u2500 </Text>\n <Text color=\"white\" bold>\n VERSION {PACKAGE_VERSION}\n </Text>\n <Text color=\"#334155\"> \u2500\u2500\u2500\u2500\u2500\u2500</Text>\n </Box>\n\n <Box marginTop={1}>\n <Text color=\"#64748b\" italic>\n {MESSAGES.DESCRIPTION}\n </Text>\n </Box>\n\n {notification && <Box marginTop={1}>{notification}</Box>}\n </Box>\n\n <Box marginTop={notification ? 0 : 1} justifyContent=\"center\">\n <Gradient colors={crystalColors}>\n <Text>{SEPARATOR_CHAR.repeat(60)}</Text>\n </Gradient>\n </Box>\n </Box>\n )\n}\n", "import { atom } from 'jotai'\nimport { unwrap } from 'jotai/utils'\nimport { isGloballyInstalled } from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\nimport { getCachedUpdate, setCachedUpdate } from '../services/update-cache'\nimport { checkForUpdates, getCurrentVersion } from '../services/update-check'\nimport { UPDATE_CHECK_TIMEOUT_MS } from '../utils/constants'\n\nexport interface EnvironmentCheckState {\n updateAvailable: string | null\n currentVersion: string\n isGlobal: boolean\n isLoading?: boolean\n}\n\nasync function resolveUpdateAvailable(currentVersion: string): Promise<string | null> {\n const cached = await getCachedUpdate()\n const cachedUpdate = cached && cached.latestVersion !== currentVersion ? cached.latestVersion : null\n\n try {\n const update = await Promise.race([\n checkForUpdates(currentVersion),\n new Promise<string | null>((_, reject) =>\n setTimeout(() => reject(new Error('timeout')), UPDATE_CHECK_TIMEOUT_MS),\n ),\n ])\n\n setCachedUpdate(update ?? currentVersion).catch(() => {})\n return update\n } catch {\n return cachedUpdate\n }\n}\n\nconst runCheck = async (): Promise<EnvironmentCheckState> => {\n const currentVersion = getCurrentVersion()\n\n const [updateAvailable, isGlobal] = await Promise.all([\n resolveUpdateAvailable(currentVersion).catch(() => null),\n Promise.resolve(isGloballyInstalled(ports)).catch(() => false),\n ])\n\n return { updateAvailable, currentVersion, isGlobal: isGlobal as boolean, isLoading: false }\n}\n\nconst environmentCheckAsyncAtom = atom<Promise<EnvironmentCheckState>>(runCheck())\n\nexport const environmentCheckAtom = unwrap(\n environmentCheckAsyncAtom,\n (prev) => prev ?? { updateAvailable: null, currentVersion: getCurrentVersion(), isGlobal: false, isLoading: true },\n)\n", "import { mkdir, readFile, writeFile } from 'node:fs/promises'\nimport { homedir } from 'node:os'\nimport { dirname, join } from 'node:path'\n\nimport { CACHE_FILE, UPDATE_CHECK_CACHE_TTL_MS, CONFIG_DIR } from '../utils/constants'\n\nexport interface UpdateCache {\n lastUpdateCheck: number\n latestVersion: string | null\n}\n\nfunction getCachePath(): string {\n return join(homedir(), CONFIG_DIR, CACHE_FILE)\n}\n\nfunction validateCache(cache: unknown): UpdateCache | null {\n if (typeof cache !== 'object' || cache === null) return null\n const partial = cache as Partial<UpdateCache>\n if (typeof partial.lastUpdateCheck !== 'number') return null\n return { lastUpdateCheck: partial.lastUpdateCheck, latestVersion: partial.latestVersion ?? null }\n}\n\nexport async function getCachedUpdate(): Promise<UpdateCache | null> {\n const cachePath = getCachePath()\n\n try {\n const content = await readFile(cachePath, 'utf-8')\n const parsed = JSON.parse(content)\n return validateCache(parsed)\n } catch {\n // Return null if file doesn't exist or is invalid\n return null\n }\n}\n\nexport async function setCachedUpdate(version: string | null): Promise<void> {\n const cachePath = getCachePath()\n const cache: UpdateCache = {\n lastUpdateCheck: Date.now(),\n latestVersion: version,\n }\n\n // Ensure directory exists\n await mkdir(dirname(cachePath), { recursive: true })\n await writeFile(cachePath, JSON.stringify(cache, null, 2), 'utf-8')\n}\n\nexport async function isCacheValid(): Promise<boolean> {\n const cache = await getCachedUpdate()\n if (!cache) return false\n const now = Date.now()\n const age = now - cache.lastUpdateCheck\n return age < UPDATE_CHECK_CACHE_TTL_MS\n}\n\nexport async function clearCache(): Promise<void> {\n const cachePath = getCachePath()\n\n try {\n const { unlink } = await import('node:fs/promises')\n await unlink(cachePath)\n } catch {\n // Silently fail if file doesn't exist\n }\n}\n", "import packageJson from 'package-json'\n\nimport { PACKAGE_NAME } from '../utils/constants'\nimport { PACKAGE_VERSION } from './package-info'\n\nexport async function checkForUpdates(currentVersion: string): Promise<string | null> {\n try {\n // Don't check for updates if running a prerelease version\n if (isPrerelease(currentVersion)) return null\n\n const result = await packageJson(PACKAGE_NAME, { version: 'latest' })\n if (result.version !== currentVersion) return result.version\n return null\n } catch {\n // Silently fail if offline or registry unavailable\n return null\n }\n}\n\nfunction isPrerelease(version: string): boolean {\n return /-(alpha|beta|rc|snapshot|dev|canary|next)/i.test(version)\n}\n\nexport function getCurrentVersion(): string {\n return PACKAGE_VERSION\n}\n", "import { createRequire } from 'node:module'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __filename = fileURLToPath(import.meta.url)\nconst __dirname = dirname(__filename)\n\nconst require = createRequire(import.meta.url)\n\nlet pkg: { version?: string; description?: string }\n\ntry {\n pkg = require('./package.json')\n} catch {\n pkg = require(join(__dirname, '../../package.json'))\n}\n\nexport const PACKAGE_VERSION = pkg.version || '0.0.0'\nexport const PACKAGE_DESCRIPTION = pkg.description || 'CLI to install and manage skills for AI coding agents'\n", "import { Box, Text, useInput, useStdout } from 'ink'\nimport Spinner from 'ink-spinner'\nimport { useState } from 'react'\n\nimport { getAgentConfig } from '@peterson-benhame/core'\nimport type { AgentType } from '@peterson-benhame/core'\n\nimport { FooterBar } from '../components/FooterBar'\nimport { Header } from '../components/Header'\nimport { KeyboardShortcutsOverlay, type ShortcutEntry } from '../components/KeyboardShortcutsOverlay'\nimport { MultiSelectPrompt } from '../components/MultiSelectPrompt'\nimport { useAgents } from '../hooks/useAgents'\nimport { ports } from '../ports'\nimport { colors, symbols } from '../theme'\n\ninterface AgentSelectorProps {\n onSelect: (agents: AgentType[]) => void\n onBack?: () => void\n}\n\nconst CHROME_LINES = 28\n\nexport function AgentSelector({ onSelect, onBack }: AgentSelectorProps) {\n const { stdout } = useStdout()\n const termRows = stdout?.rows ?? 40\n const listLimit = Math.max(3, termRows - CHROME_LINES)\n\n const { allAgents, installedAgents, selectedAgents, setSelectedAgents, loading } = useAgents()\n\n const agentShortcuts: ShortcutEntry[] = [\n { key: 'space', description: 'Toggle selection' },\n { key: 'enter', description: 'Confirm' },\n { key: 'ctrl+a', description: 'Select all' },\n { key: 'esc', description: 'Go back' },\n ]\n\n const [showShortcuts, setShowShortcuts] = useState(false)\n useInput((input) => {\n if (input === '?') setShowShortcuts((prev) => !prev)\n })\n\n const items = allAgents.map((agent) => {\n const config = getAgentConfig(ports, agent)\n const isDetected = installedAgents.includes(agent)\n return { label: config.displayName, value: agent, hint: isDetected ? `${symbols.check} detected` : undefined }\n })\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box marginTop={1}>\n <Text color={colors.accent}>\n <Spinner type=\"dots\" /> Scanning for installed agents...\n </Text>\n </Box>\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"column\" paddingX={1} minHeight={20}>\n <Header />\n\n {showShortcuts ? (\n <>\n <Box flexDirection=\"column\" flexGrow={1} alignItems=\"center\" justifyContent=\"center\">\n <KeyboardShortcutsOverlay\n visible={showShortcuts}\n onDismiss={() => setShowShortcuts(false)}\n shortcuts={agentShortcuts}\n />\n </Box>\n\n <FooterBar\n hints={[\n { key: 'space', label: 'toggle' },\n { key: 'enter', label: 'confirm', color: colors.success },\n ...(onBack ? [{ key: 'esc', label: 'back', color: colors.warning }] : []),\n { key: '?', label: 'help' },\n ]}\n />\n </>\n ) : (\n <>\n <Box marginBottom={1}>\n <Text bold color={colors.primary}>\n {symbols.diamond} Where do you want to install skills?\n </Text>\n </Box>\n <Box marginBottom={1}>\n <Text color={colors.textDim}>{installedAgents.length} agents detected on this machine</Text>\n </Box>\n\n <MultiSelectPrompt\n items={items}\n initialSelected={selectedAgents}\n onSubmit={onSelect}\n onCancel={onBack}\n onChange={setSelectedAgents}\n limit={listLimit}\n />\n </>\n )}\n </Box>\n )\n}\n", "import { Box, Text, useInput } from 'ink'\nimport React, { useEffect } from 'react'\n\nimport { colors, symbols } from '../theme'\nimport { AnimatedTransition } from './AnimatedTransition'\n\nexport interface ShortcutEntry {\n key: string\n description: string\n}\n\nexport interface KeyboardShortcutsOverlayProps {\n visible: boolean\n onDismiss: () => void\n shortcuts: ShortcutEntry[]\n}\n\nexport const KeyboardShortcutsOverlay: React.FC<KeyboardShortcutsOverlayProps> = ({\n visible,\n onDismiss,\n shortcuts,\n}) => {\n useInput(\n () => {\n if (visible) onDismiss()\n },\n { isActive: visible },\n )\n\n useEffect(() => {\n let timer: NodeJS.Timeout\n\n if (visible) {\n timer = setTimeout(() => {\n onDismiss()\n }, 8000)\n }\n\n return () => {\n if (timer) clearTimeout(timer)\n }\n }, [visible, onDismiss])\n\n const mid = Math.ceil(shortcuts.length / 2)\n const leftColumn = shortcuts.slice(0, mid)\n const rightColumn = shortcuts.slice(mid)\n\n const KeyBadge = ({ label }: { label: string }) => (\n <Box flexShrink={0}>\n <Text backgroundColor={colors.bgLight} color={colors.accent} bold>\n {` ${label} `}\n </Text>\n </Box>\n )\n\n const ShortcutRow = ({ entry }: { entry: ShortcutEntry }) => (\n <Box marginBottom={0} gap={1}>\n <Box width={10} justifyContent=\"flex-end\" flexShrink={0}>\n <KeyBadge label={entry.key} />\n </Box>\n <Text color={colors.textDim}>{entry.description}</Text>\n </Box>\n )\n\n const divider = '\u2500'.repeat(48)\n\n return (\n <AnimatedTransition visible={visible} duration={200}>\n <Box\n borderStyle=\"round\"\n borderColor={colors.border}\n backgroundColor={colors.bg}\n paddingX={2}\n paddingY={1}\n flexDirection=\"column\"\n width={56}\n >\n <Box justifyContent=\"center\" marginBottom={1}>\n <Text color={colors.accent} bold>\n {symbols.sparkle} Keyboard Shortcuts\n </Text>\n </Box>\n\n <Box justifyContent=\"center\">\n <Text color={colors.border}>{divider}</Text>\n </Box>\n\n <Box marginTop={1} gap={2}>\n <Box flexDirection=\"column\" gap={1} flexGrow={1}>\n {leftColumn.map((entry) => (\n <ShortcutRow key={entry.key} entry={entry} />\n ))}\n </Box>\n\n <Box flexDirection=\"column\" gap={1} flexGrow={1}>\n {rightColumn.map((entry) => (\n <ShortcutRow key={entry.key} entry={entry} />\n ))}\n </Box>\n </Box>\n\n <Box justifyContent=\"center\" marginTop={1}>\n <Text color={colors.border}>{divider}</Text>\n </Box>\n\n <Box marginTop={1} justifyContent=\"center\">\n <Text color={colors.textMuted}>press any key to dismiss</Text>\n </Box>\n </Box>\n </AnimatedTransition>\n )\n}\n", "import React, { useEffect, useState } from 'react'\n\nexport interface AnimatedTransitionProps {\n visible: boolean\n duration?: number\n children: React.ReactNode\n}\n\nexport const AnimatedTransition: React.FC<AnimatedTransitionProps> = ({ visible, duration = 250, children }) => {\n const [opacity, setOpacity] = useState(visible ? 1 : 0)\n\n useEffect(() => {\n if ((visible && opacity === 1) || (!visible && opacity === 0)) return\n\n const startTime = Date.now()\n const startOpacity = opacity\n const targetOpacity = visible ? 1 : 0\n const frameDuration = 16\n\n const interval = setInterval(() => {\n const now = Date.now()\n const elapsed = now - startTime\n const progress = Math.min(elapsed / duration, 1)\n const currentOpacity = startOpacity + (visible ? progress : -progress) * Math.abs(targetOpacity - startOpacity)\n const clampedOpacity = Math.max(0, Math.min(1, currentOpacity))\n\n setOpacity(clampedOpacity)\n\n if (progress >= 1) {\n clearInterval(interval)\n setOpacity(targetOpacity)\n }\n }, frameDuration)\n\n return () => {\n clearInterval(interval)\n }\n }, [visible, duration])\n\n if (!visible && opacity <= 0.05) return null\n return <>{children}</>\n}\n", "import { Box, Text, useInput } from 'ink'\nimport { useEffect, useRef, useState } from 'react'\n\nimport { colors, symbols } from '../theme'\nimport { FooterBar, type FooterHint } from './FooterBar'\nimport { KeyboardShortcutsOverlay, type ShortcutEntry } from './KeyboardShortcutsOverlay'\n\nexport interface MultiSelectOption<T> {\n label: string\n value: T\n hint?: string\n}\n\ninterface MultiSelectPromptProps<T> {\n items: MultiSelectOption<T>[]\n onSubmit: (selected: T[]) => void\n onCancel?: () => void\n onChange?: (selected: T[]) => void\n initialSelected?: T[]\n limit?: number\n}\n\nexport function MultiSelectPrompt<T>({\n items,\n onSubmit,\n onCancel,\n onChange,\n initialSelected = [],\n limit = 10,\n}: MultiSelectPromptProps<T>) {\n const [selected, setSelected] = useState<T[]>(initialSelected)\n const [focusIndex, setFocusIndex] = useState(0)\n const [offset, setOffset] = useState(0)\n const [showShortcuts, setShowShortcuts] = useState(false)\n const prevInitialSelectedRef = useRef<T[]>(initialSelected)\n\n useEffect(() => {\n const prev = prevInitialSelectedRef.current\n const hasChanged = prev.length !== initialSelected.length || prev.some((v, i) => v !== initialSelected[i])\n\n if (hasChanged) {\n setSelected(initialSelected)\n prevInitialSelectedRef.current = initialSelected\n }\n }, [initialSelected])\n\n useInput((input, key) => {\n if (input === '?') {\n setShowShortcuts((prev) => !prev)\n return\n }\n\n if (showShortcuts) {\n setShowShortcuts(false)\n return\n }\n\n if (key.return) {\n onSubmit(selected)\n return\n }\n\n if (key.escape && onCancel) {\n onCancel()\n return\n }\n\n let newIndex = focusIndex\n let newOffset = offset\n\n if (key.upArrow) {\n newIndex = focusIndex > 0 ? focusIndex - 1 : items.length - 1\n } else if (key.downArrow) {\n newIndex = focusIndex < items.length - 1 ? focusIndex + 1 : 0\n }\n\n if (newIndex < newOffset) {\n newOffset = newIndex\n } else if (newIndex >= newOffset + limit) {\n newOffset = newIndex - limit + 1\n }\n\n if (key.upArrow && focusIndex === 0) {\n newOffset = Math.max(0, items.length - limit)\n } else if (key.downArrow && focusIndex === items.length - 1) {\n newOffset = 0\n }\n\n if (newIndex !== focusIndex) {\n setFocusIndex(newIndex)\n setOffset(newOffset)\n }\n\n if (input === ' ') {\n const item = items[focusIndex]\n\n if (selected.includes(item.value)) {\n const newSelected = selected.filter((v) => v !== item.value)\n setSelected(newSelected)\n onChange?.(newSelected)\n } else {\n const newSelected = [...selected, item.value]\n setSelected(newSelected)\n onChange?.(newSelected)\n }\n }\n\n if (input === 'a' && key.ctrl) {\n if (selected.length === items.length) {\n setSelected([])\n onChange?.([])\n } else {\n const all = items.map((i) => i.value)\n setSelected(all)\n onChange?.(all)\n }\n }\n })\n\n const visibleItems = items.slice(offset, offset + limit)\n const hasItemsAbove = offset > 0\n const hasItemsBelow = items.length > offset + limit\n\n const shortcuts: ShortcutEntry[] = [\n { key: '\u2191/\u2193', description: 'Navigate' },\n { key: 'space', description: 'Toggle selection' },\n { key: 'enter', description: 'Confirm' },\n { key: 'ctrl+a', description: 'Select all / none' },\n ...(onCancel ? [{ key: 'esc', description: 'Cancel' }] : []),\n ]\n\n if (showShortcuts) {\n return (\n <Box flexDirection=\"column\" flexGrow={1} alignItems=\"center\" justifyContent=\"center\">\n <KeyboardShortcutsOverlay\n visible={showShortcuts}\n onDismiss={() => setShowShortcuts(false)}\n shortcuts={shortcuts}\n />\n </Box>\n )\n }\n\n return (\n <Box flexDirection=\"column\">\n {hasItemsAbove && (\n <Box justifyContent=\"center\" marginBottom={1}>\n <Text color={colors.textDim}>\n {symbols.arrowUp} {symbols.arrowUp} {symbols.arrowUp}\n </Text>\n </Box>\n )}\n\n {visibleItems.map((item, index) => {\n const realIndex = index + offset\n const isFocused = realIndex === focusIndex\n const isSelected = selected.includes(item.value)\n\n const pointer = isFocused ? symbols.bullet : ' '\n const pointerColor = isSelected ? colors.success : colors.accent\n const checkbox = isSelected ? symbols.checkboxActive : symbols.checkboxInactive\n const checkboxColor = isSelected ? colors.success : colors.textMuted\n const textColor = isFocused ? colors.primary : isSelected ? colors.primaryLight : colors.text\n return (\n <Box\n key={`${String(item.value)}-${realIndex}`}\n backgroundColor={isFocused ? colors.bgLight : undefined}\n paddingX={1}\n >\n <Box width={2}>\n <Text color={pointerColor}>{pointer}</Text>\n </Box>\n <Box width={2}>\n <Text color={checkboxColor}>{checkbox}</Text>\n </Box>\n <Text color={textColor} bold={isFocused}>\n {item.label}\n </Text>\n {item.hint && (\n <Text color={isSelected ? colors.success : colors.textDim}>\n {' '}\n {symbols.dot} {item.hint}\n </Text>\n )}\n </Box>\n )\n })}\n\n {hasItemsBelow && (\n <Box justifyContent=\"center\" marginTop={1}>\n <Text color={colors.textDim}>\n {symbols.arrowDown} {symbols.arrowDown} {symbols.arrowDown}\n </Text>\n </Box>\n )}\n\n <FooterBar\n hints={\n [\n { key: 'space', label: 'toggle' },\n { key: 'enter', label: 'confirm', color: colors.success },\n ...(onCancel ? [{ key: 'esc', label: 'back', color: colors.warning }] : []),\n { key: '?', label: 'help' },\n ] satisfies FooterHint[]\n }\n status={\n selected.length > 0 ? (\n <Text>\n <Text color={colors.success} bold>\n {symbols.checkboxActive} {selected.length}\n </Text>\n <Text color={colors.textDim}> selected</Text>\n </Text>\n ) : undefined\n }\n />\n </Box>\n )\n}\n", "import { Box, Text, useInput, useStdout } from 'ink'\nimport BigText from 'ink-big-text'\nimport Gradient from 'ink-gradient'\nimport type { ChildProcess } from 'node:child_process'\nimport { existsSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { play, stop } from '../services/audio-player'\nimport { fetchContributors, fetchRepoStars } from '../services/github-contributors'\nimport { colors, symbols } from '../theme'\nimport type { GitHubContributor } from '../types'\n\ninterface CreditsViewProps {\n onExit: () => void\n}\n\nconst BASE_SPEED_MS = 220\nconst CONTENT_WIDTH = 52\nconst CRYSTAL_COLORS = ['#1e3a8a', '#3b82f6', '#0ea5e9', '#06b6d4', '#22d3ee']\nconst HEADER_HEIGHT = 14\nconst MAX_SPEED_MS = 500\nconst MIN_SPEED_MS = 60\nconst SEPARATOR = '\u2500'.repeat(CONTENT_WIDTH - 4)\nconst SPEED_STEP_MS = 40\nconst WARM_COLORS = ['#f59e0b', '#ef4444', '#ec4899', '#a855f7']\n\nconst RANK_DECORATORS: Record<number, { badge: string; color: string }> = {\n 1: { badge: `${symbols.star}${symbols.star}${symbols.star}`, color: '#f59e0b' },\n 2: { badge: `${symbols.star}${symbols.star}`, color: '#c0c0c0' },\n 3: { badge: symbols.star, color: '#cd7f32' },\n}\n\ntype CreditLine =\n | { type: 'blank' }\n | { type: 'text'; text: string; color: string; bold?: boolean }\n | { type: 'gradient'; text: string; gradientColors: readonly string[] }\n | { type: 'contributor'; rank: number; login: string; contributions: number }\n\nfunction buildCreditLines(contributors: GitHubContributor[], stars: number): CreditLine[] {\n const lines: CreditLine[] = []\n\n lines.push({ type: 'blank' })\n lines.push({ type: 'text', text: 'A Tech Leads Club Production', color: '#94a3b8' })\n lines.push({ type: 'blank' })\n lines.push({ type: 'blank' })\n\n lines.push({\n type: 'gradient',\n text: `${symbols.sparkle} C O N T R I B U T O R S ${symbols.sparkle}`,\n gradientColors: WARM_COLORS,\n })\n\n lines.push({ type: 'gradient', text: SEPARATOR, gradientColors: CRYSTAL_COLORS })\n lines.push({ type: 'blank' })\n\n for (let i = 0; i < contributors.length; i++) {\n const c = contributors[i]\n lines.push({ type: 'contributor', rank: i + 1, login: c.login, contributions: c.contributions })\n }\n\n lines.push({ type: 'blank' })\n lines.push({ type: 'blank' })\n\n lines.push({ type: 'gradient', text: `${symbols.star} S T A T S ${symbols.star}`, gradientColors: WARM_COLORS })\n lines.push({ type: 'gradient', text: SEPARATOR, gradientColors: CRYSTAL_COLORS })\n lines.push({ type: 'blank' })\n\n if (stars > 0) {\n lines.push({ type: 'text', text: `${symbols.star} GitHub Stars \u00B7\u00B7\u00B7\u00B7\u00B7 ${stars}`, color: '#f59e0b', bold: true })\n }\n\n lines.push({ type: 'text', text: `${symbols.diamond} Contributors \u00B7\u00B7\u00B7\u00B7\u00B7 ${contributors.length}`, color: '#06b6d4' })\n const totalContribs = contributors.reduce((sum, c) => sum + c.contributions, 0)\n lines.push({ type: 'text', text: `${symbols.check} Contributions \u00B7\u00B7\u00B7\u00B7 ${totalContribs}`, color: '#22c55e' })\n\n lines.push({ type: 'blank' })\n lines.push({ type: 'blank' })\n\n lines.push({\n type: 'gradient',\n text: `${symbols.sparkle} S P E C I A L T H A N K S ${symbols.sparkle}`,\n gradientColors: WARM_COLORS,\n })\n\n lines.push({ type: 'gradient', text: SEPARATOR, gradientColors: CRYSTAL_COLORS })\n lines.push({ type: 'blank' })\n lines.push({ type: 'text', text: 'To every contributor, stargazer,', color: '#94a3b8' })\n lines.push({ type: 'text', text: 'and community member who makes', color: '#94a3b8' })\n lines.push({ type: 'text', text: 'this project possible.', color: '#94a3b8' })\n lines.push({ type: 'blank' })\n lines.push({ type: 'text', text: 'Built with \\u2665 by the community', color: '#ef4444' })\n lines.push({ type: 'blank' })\n lines.push({ type: 'gradient', text: 'github.com/tech-leads-club/agent-skills', gradientColors: CRYSTAL_COLORS })\n lines.push({ type: 'blank' })\n lines.push({ type: 'blank' })\n lines.push({ type: 'blank' })\n\n return lines\n}\n\nfunction getAssetPath(): string | null {\n try {\n let dir = dirname(fileURLToPath(import.meta.url))\n for (let i = 0; i < 5; i++) {\n const candidate = join(dir, 'assets', 'chiptune.mp3')\n if (existsSync(candidate)) return candidate\n dir = dirname(dir)\n }\n return null\n } catch {\n return null\n }\n}\n\nfunction ContributorRow({ rank, login, contributions }: { rank: number; login: string; contributions: number }) {\n const decorator = RANK_DECORATORS[rank]\n const nameColor = decorator?.color ?? '#e2e8f0'\n const rankStr = rank.toString().padStart(2)\n const name = `@${login}`\n const contribStr = `${contributions}`\n const badgeSuffix = decorator ? ` ${decorator.badge}` : ''\n const usedLen = 4 + 1 + name.length + badgeSuffix.length + 1 + contribStr.length\n const dotsLen = Math.max(2, CONTENT_WIDTH - 4 - usedLen)\n const dots = '\\u00b7'.repeat(dotsLen)\n\n return (\n <Text>\n <Text color=\"#64748b\">{rankStr}. </Text>\n <Text color={nameColor} bold={!!decorator}>\n {name}\n </Text>\n <Text color={decorator?.color ?? '#94a3b8'}>{badgeSuffix}</Text>\n <Text color=\"#334155\"> {dots} </Text>\n <Text color=\"#22c55e\" bold>\n {contribStr}\n </Text>\n </Text>\n )\n}\n\nfunction CreditLineRenderer({ line }: { line: CreditLine }) {\n switch (line.type) {\n case 'blank':\n return <Text> </Text>\n case 'text':\n return (\n <Text color={line.color} bold={line.bold}>\n {line.text}\n </Text>\n )\n case 'gradient':\n return (\n <Gradient colors={[...line.gradientColors]}>\n <Text>{line.text}</Text>\n </Gradient>\n )\n case 'contributor':\n return <ContributorRow rank={line.rank} login={line.login} contributions={line.contributions} />\n }\n}\n\nfunction SpeedIndicator({ speed, paused }: { speed: number; paused: boolean }) {\n if (paused) {\n return (\n <Text color={colors.warning} bold>\n {' '}\n {symbols.bar}\n {symbols.bar} PAUSED\n </Text>\n )\n }\n\n const level = Math.round(((MAX_SPEED_MS - speed) / (MAX_SPEED_MS - MIN_SPEED_MS)) * 4) + 1\n const bars = '\\u25AE'.repeat(level) + '\\u25AF'.repeat(5 - level)\n return <Text color={colors.textMuted}> {bars}</Text>\n}\n\nexport function CreditsView({ onExit }: CreditsViewProps) {\n const { stdout } = useStdout()\n const termRows = stdout?.rows ?? 24\n const scrollAreaHeight = Math.max(6, termRows - HEADER_HEIGHT - 4)\n\n const [contributors, setContributors] = useState<GitHubContributor[]>([])\n const [stars, setStars] = useState(0)\n const [loading, setLoading] = useState(true)\n const [scrollOffset, setScrollOffset] = useState(0)\n const [speed, setSpeed] = useState(BASE_SPEED_MS)\n const [paused, setPaused] = useState(false)\n\n const audioRef = useRef<ChildProcess | null>(null)\n const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null)\n\n useEffect(() => {\n Promise.all([fetchContributors(), fetchRepoStars()]).then(([c, s]) => {\n setContributors(c)\n setStars(s)\n setLoading(false)\n })\n }, [])\n\n useEffect(() => {\n const assetPath = getAssetPath()\n if (assetPath) audioRef.current = play(assetPath)\n\n return () => {\n stop(audioRef.current)\n }\n }, [])\n\n const creditLines = useMemo(() => buildCreditLines(contributors, stars), [contributors, stars])\n const maxOffset = creditLines.length + scrollAreaHeight\n const finished = scrollOffset >= maxOffset\n\n const advance = useCallback(() => {\n setScrollOffset((prev) => (prev >= maxOffset ? prev : prev + 1))\n }, [maxOffset])\n\n useEffect(() => {\n if (loading || paused || finished) {\n if (intervalRef.current) clearInterval(intervalRef.current)\n intervalRef.current = null\n return\n }\n\n intervalRef.current = setInterval(advance, speed)\n return () => {\n if (intervalRef.current) clearInterval(intervalRef.current)\n }\n }, [loading, paused, finished, speed, advance])\n\n useEffect(() => {\n if (!finished) return\n const timer = setTimeout(() => {\n stop(audioRef.current)\n onExit()\n }, 3000)\n\n return () => clearTimeout(timer)\n }, [finished, onExit])\n\n useInput((input, key) => {\n if (key.escape) {\n stop(audioRef.current)\n onExit()\n return\n }\n\n if (input === ' ') {\n setPaused((p) => !p)\n return\n }\n\n if (key.upArrow) {\n setSpeed((s) => Math.max(MIN_SPEED_MS, s - SPEED_STEP_MS))\n return\n }\n\n if (key.downArrow) {\n setSpeed((s) => Math.min(MAX_SPEED_MS, s + SPEED_STEP_MS))\n return\n }\n })\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" alignItems=\"center\" padding={2}>\n <Text color={colors.accent}>Loading contributors...</Text>\n </Box>\n )\n }\n\n const blankLine: CreditLine = { type: 'blank' }\n const padTop = Array(scrollAreaHeight).fill(blankLine) as CreditLine[]\n const padBottom = Array(scrollAreaHeight).fill(blankLine) as CreditLine[]\n const allLines = [...padTop, ...creditLines, ...padBottom]\n const visibleSlice = allLines.slice(scrollOffset, scrollOffset + scrollAreaHeight)\n\n return (\n <Box flexDirection=\"column\" alignItems=\"center\">\n <Box marginBottom={-1}>\n <Gradient colors={['#1e3a8a', '#3b82f6']}>\n <BigText text=\"TLC\" font=\"tiny\" />\n </Gradient>\n </Box>\n <Box>\n <Gradient colors={[...CRYSTAL_COLORS]}>\n <BigText text=\"AGENT SKILLS\" font=\"block\" />\n </Gradient>\n </Box>\n <Box>\n <Gradient colors={[...CRYSTAL_COLORS]}>\n <Text>{'\\u2500'.repeat(60)}</Text>\n </Gradient>\n </Box>\n\n <Box flexDirection=\"column\" alignItems=\"center\" height={scrollAreaHeight} width={CONTENT_WIDTH}>\n {visibleSlice.map((line, i) => (\n <Box key={`cl-${scrollOffset}-${i}`} justifyContent=\"center\">\n <CreditLineRenderer line={line} />\n </Box>\n ))}\n </Box>\n\n <Box marginTop={1} gap={2}>\n <Text>\n <Text color={colors.accent} bold>\n space\n </Text>\n <Text color={colors.textDim}> pause</Text>\n </Text>\n <Text color={colors.textMuted}>{symbols.dot}</Text>\n <Text>\n <Text color={colors.accent} bold>\n {symbols.arrowUp}\n {symbols.arrowDown}\n </Text>\n <Text color={colors.textDim}> speed</Text>\n </Text>\n <SpeedIndicator speed={speed} paused={paused} />\n <Text color={colors.textMuted}>{symbols.dot}</Text>\n <Text>\n <Text color={colors.warning} bold>\n esc\n </Text>\n <Text color={colors.textDim}> back</Text>\n </Text>\n </Box>\n </Box>\n )\n}\n", "import { execSync, spawn, type ChildProcess } from 'node:child_process'\nimport { platform } from 'node:os'\n\nfunction commandExists(cmd: string): boolean {\n try {\n execSync(`which ${cmd}`, { stdio: 'ignore' })\n return true\n } catch {\n return false\n }\n}\n\nfunction spawnLinuxPlayer(filePath: string): ChildProcess {\n const players = [\n { cmd: 'mpv', args: ['--no-video', '--no-terminal', filePath] },\n { cmd: 'ffplay', args: ['-nodisp', '-autoexit', '-loglevel', 'quiet', filePath] },\n { cmd: 'paplay', args: [filePath] },\n { cmd: 'aplay', args: [filePath] },\n ]\n\n for (const { cmd, args } of players) {\n if (commandExists(cmd)) return spawn(cmd, args, { stdio: 'ignore' })\n }\n\n return spawn('mpv', ['--no-video', '--no-terminal', filePath], { stdio: 'ignore' })\n}\n\nexport function play(filePath: string): ChildProcess | null {\n try {\n const os = platform()\n let proc: ChildProcess\n\n if (os === 'darwin') {\n proc = spawn('afplay', [filePath], { stdio: 'ignore' })\n } else if (os === 'win32') {\n proc = spawn('powershell', ['-c', `(New-Object Media.SoundPlayer \"${filePath}\").PlaySync()`], {\n stdio: 'ignore',\n })\n } else {\n proc = spawnLinuxPlayer(filePath)\n }\n\n proc.on('error', () => {\n // Player not available, silently ignore\n })\n\n return proc\n } catch {\n return null\n }\n}\n\nexport function stop(proc: ChildProcess | null): void {\n if (proc && !proc.killed) proc.kill()\n}\n", "import ky from 'ky'\n\nimport type { GitHubContributor } from '../types'\n\nconst REPO_API = 'https://api.github.com/repos/tech-leads-club/agent-skills'\nconst CONTRIBUTORS_URL = `${REPO_API}/contributors`\n\nlet contributorsCache: GitHubContributor[] | null = null\nlet starsCache: number | null = null\n\nexport async function fetchContributors(): Promise<GitHubContributor[]> {\n if (contributorsCache) return contributorsCache\n\n try {\n const data = await ky\n .get(CONTRIBUTORS_URL, {\n headers: { Accept: 'application/vnd.github.v3+json' },\n timeout: 10_000,\n })\n .json<Array<{ login: string; avatar_url: string; contributions: number }>>()\n\n contributorsCache = data\n .filter(({ login }) => !isBot(login))\n .map(({ login, avatar_url, contributions }) => ({\n login,\n avatarUrl: avatar_url,\n contributions,\n }))\n\n return contributorsCache\n } catch {\n return []\n }\n}\n\nexport async function fetchRepoStars(): Promise<number> {\n if (starsCache !== null) return starsCache\n\n try {\n const data = await ky\n .get(REPO_API, {\n headers: { Accept: 'application/vnd.github.v3+json' },\n timeout: 10_000,\n })\n .json<{ stargazers_count: number }>()\n\n starsCache = data.stargazers_count\n return starsCache\n } catch {\n return 0\n }\n}\n\nfunction isBot(login: string): boolean {\n return login.endsWith('[bot]')\n}\n", "import { Box, Text, useInput } from 'ink'\nimport { useState } from 'react'\n\nimport { Header } from '../components/Header'\nimport { SelectPrompt } from '../components/SelectPrompt'\nimport { colors, symbols } from '../theme'\n\ninterface InstallConfigProps {\n onConfirm: (config: { method: 'copy' | 'symlink'; global: boolean }) => void\n onBack: () => void\n initialMethod?: 'copy' | 'symlink'\n initialGlobal?: boolean\n}\n\nexport function InstallConfig({\n onConfirm,\n onBack,\n initialMethod = 'copy',\n initialGlobal = false,\n}: InstallConfigProps) {\n const [step, setStep] = useState<'method' | 'scope' | 'confirm'>('method')\n const [method, setMethod] = useState<'copy' | 'symlink'>(initialMethod)\n const [isGlobal, setIsGlobal] = useState(initialGlobal)\n\n if (step === 'method') {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box marginBottom={1}>\n <Text bold color={colors.primary}>\n {symbols.diamond} Choose installation method:\n </Text>\n </Box>\n <SelectPrompt\n items={[\n { label: 'Copy', value: 'copy', hint: 'independent copies (recommended)' },\n { label: 'Symlink', value: 'symlink', hint: 'shared source (may not work with all agents)' },\n ]}\n onSelect={(val) => {\n setMethod(val as 'copy' | 'symlink')\n setStep('scope')\n }}\n onCancel={onBack}\n />\n </Box>\n )\n }\n\n if (step === 'scope') {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box marginBottom={1}>\n <Text bold color={colors.primary}>\n {symbols.diamond} Choose installation scope:\n </Text>\n </Box>\n <SelectPrompt\n items={[\n { label: 'Local', value: false, hint: 'this project only' },\n { label: 'Global', value: true, hint: 'user home directory' },\n ]}\n onSelect={(val) => {\n setIsGlobal(val as boolean)\n setStep('confirm')\n }}\n onCancel={() => setStep('method')}\n />\n </Box>\n )\n }\n\n return (\n <InstallSummary\n method={method}\n isGlobal={isGlobal}\n onConfirm={() => onConfirm({ method, global: isGlobal })}\n onBack={() => setStep('scope')}\n />\n )\n}\n\nfunction InstallSummary({\n method,\n isGlobal,\n onConfirm,\n onBack,\n}: {\n method: string\n isGlobal: boolean\n onConfirm: () => void\n onBack: () => void\n}) {\n useInput((input, key) => {\n if (key.return || input === 'y' || input === 'Y') onConfirm()\n if (key.escape || input === 'n' || input === 'N') onBack()\n })\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={colors.accent} paddingX={2} paddingY={1}>\n <Box marginBottom={1}>\n <Text bold color={colors.accent}>\n {symbols.diamond} Ready to install\n </Text>\n </Box>\n\n <Box>\n <Box width={10}>\n <Text color={colors.textDim}>Method</Text>\n </Box>\n <Text color={colors.text} bold>\n {method === 'copy' ? 'Copy' : 'Symlink'}\n </Text>\n <Text color={colors.textMuted}>\n {' '}\n {symbols.dot} {method === 'copy' ? 'Recommended' : 'Developer mode'}\n </Text>\n </Box>\n\n <Box>\n <Box width={10}>\n <Text color={colors.textDim}>Scope</Text>\n </Box>\n <Text color={colors.text} bold>\n {isGlobal ? 'Global' : 'Local'}\n </Text>\n <Text color={colors.textMuted}>\n {' '}\n {symbols.dot} {isGlobal ? 'User home' : 'This project'}\n </Text>\n </Box>\n </Box>\n\n <Box marginTop={1} borderStyle=\"round\" borderColor={colors.border} paddingX={1}>\n <Box justifyContent=\"space-between\" width=\"100%\">\n <Text>\n <Text color={colors.success} bold>\n Y\n </Text>\n <Text color={colors.textDim}> / </Text>\n <Text color={colors.success} bold>\n enter\n </Text>\n <Text color={colors.textDim}> confirm</Text>\n <Text color={colors.textDim}> {symbols.dot} </Text>\n <Text color={colors.warning} bold>\n N\n </Text>\n <Text color={colors.textDim}> / </Text>\n <Text color={colors.warning} bold>\n esc\n </Text>\n <Text color={colors.textDim}> back</Text>\n </Text>\n </Box>\n </Box>\n </Box>\n )\n}\n", "import { Box, Text, useInput } from 'ink'\nimport Spinner from 'ink-spinner'\nimport { useAtom, useAtomValue, useSetAtom } from 'jotai'\nimport { useEffect, useMemo, useState } from 'react'\n\nimport { installedSkillsAtom, installedSkillsRefreshAtom } from '../atoms/installedSkills'\nimport { selectedAgentsAtom, selectedSkillsAtom } from '../atoms/wizard'\nimport { Header } from '../components/Header'\nimport { InstallResults } from '../components/InstallResults'\nimport { useInstaller } from '../hooks/useInstaller'\nimport { useSkills } from '../hooks/useSkills'\nimport { useWizardStep } from '../hooks/useWizardStep'\nimport { colors, symbols } from '../theme'\nimport type { AgentType, SkillInfo } from '../types'\nimport { ActionSelector } from './ActionSelector'\nimport { AgentSelector } from './AgentSelector'\nimport { CreditsView } from './CreditsView'\nimport { InstallConfig } from './InstallConfig'\nimport { RemoveWizard } from './RemoveWizard'\nimport { SkillBrowser } from './SkillBrowser'\nimport { UpdateView } from './UpdateView'\n\nexport function InstallWizard({ onExit }: { onExit: () => void }) {\n const { step, next, back } = useWizardStep(5)\n const [selectedAgents, setSelectedAgents] = useAtom(selectedAgentsAtom)\n const [selectedSkills, setSelectedSkills] = useAtom(selectedSkillsAtom)\n const refreshInstalledSkills = useSetAtom(installedSkillsRefreshAtom)\n const installedSkills = useAtomValue(installedSkillsAtom)\n const [action, setAction] = useState<'install' | 'update' | 'remove'>('install')\n const [showCredits, setShowCredits] = useState(false)\n const [showUpdate, setShowUpdate] = useState(false)\n const [showRemove, setShowRemove] = useState(false)\n const [installConfig, setInstallConfig] = useState<{ method: 'copy' | 'symlink'; global: boolean }>({\n method: 'copy',\n global: false,\n })\n\n const { skills } = useSkills()\n const { install, progress, results, installing } = useInstaller()\n const [installStarted, setInstallStarted] = useState(false)\n const [installComplete, setInstallComplete] = useState(false)\n\n const handleAgentSelect = (agents: AgentType[]) => {\n if (agents.length === 0) return\n setSelectedAgents(agents)\n next()\n }\n\n const handleActionSelect = (act: 'install' | 'update' | 'remove') => {\n setAction(act)\n\n if (act === 'update') {\n setShowUpdate(true)\n return\n }\n\n if (act === 'remove') {\n setShowRemove(true)\n return\n }\n\n next()\n }\n\n const handleSkillSelect = (skills: SkillInfo[]) => {\n if (skills.length === 0) return\n setSelectedSkills(skills)\n next()\n }\n\n const handleConfigConfirm = (config: { method: 'copy' | 'symlink'; global: boolean }) => {\n setInstallConfig(config)\n next()\n }\n\n const visibleSkills = useMemo(() => {\n if (action === 'install') return undefined\n const installedOnSelected = new Set<string>()\n Object.entries(installedSkills).forEach(([skillName, agents]) => {\n if (agents.some((a) => selectedAgents.includes(a))) installedOnSelected.add(skillName)\n })\n return skills.filter((s) => installedOnSelected.has(s.name))\n }, [action, installedSkills, skills, selectedAgents])\n\n useEffect(() => {\n const runInstall = async () => {\n if (step === 5 && !installStarted && !installComplete) {\n setInstallStarted(true)\n await install(selectedSkills, {\n agents: selectedAgents,\n skills: selectedSkills.map((s) => s.name),\n method: installConfig.method,\n global: installConfig.global,\n })\n setInstallComplete(true)\n refreshInstalledSkills((prev) => prev + 1)\n }\n }\n runInstall()\n }, [step, installStarted, installComplete, install, selectedSkills, selectedAgents, refreshInstalledSkills])\n\n if (step === 5) {\n if (installComplete) {\n return <InstallResults results={results} onExit={onExit} title=\"Installation Complete\" successLabel=\"installed\" />\n }\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box marginTop={1}>\n <Text color={colors.accent}>\n <Spinner type=\"dots\" />{' '}\n </Text>\n <Text>\n Installing {selectedSkills.length} skills to {selectedAgents.length} agents...\n </Text>\n </Box>\n {installing && (\n <Box marginTop={1} paddingX={2}>\n <Text color={colors.textDim}>\n {symbols.arrow} {progress.skill} ({progress.current}/{progress.total})\n </Text>\n </Box>\n )}\n </Box>\n )\n }\n\n if (showUpdate) return <UpdateView selectedAgents={selectedAgents} onExit={() => setShowUpdate(false)} />\n if (showRemove) return <RemoveWizard selectedAgents={selectedAgents} onExit={() => setShowRemove(false)} />\n if (showCredits) return <CreditsView onExit={() => setShowCredits(false)} />\n\n return (\n <Box flexDirection=\"column\">\n {step === 1 && <AgentSelector onSelect={handleAgentSelect} onBack={onExit} />}\n\n {step === 2 && (\n <ActionSelector onSelect={handleActionSelect} onBack={back} onCredits={() => setShowCredits(true)} />\n )}\n\n {step === 3 && (action === 'install' || (visibleSkills && visibleSkills.length > 0)) && (\n <SkillBrowser onInstall={handleSkillSelect} onExit={back} overrideSkills={visibleSkills} />\n )}\n\n {step === 3 && action === 'update' && visibleSkills && visibleSkills.length === 0 && (\n <UpToDateMessage onBack={back} />\n )}\n\n {step === 4 && (\n <InstallConfig onConfirm={handleConfigConfirm} onBack={back} initialMethod=\"copy\" initialGlobal={false} />\n )}\n </Box>\n )\n}\n\nfunction UpToDateMessage({ onBack }: { onBack: () => void }) {\n useInput((input, key) => {\n if (key.escape || input === 'b' || key.backspace) onBack()\n })\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n\n <Box borderColor={colors.success} borderStyle=\"round\" paddingX={2} paddingY={1}>\n <Text color={colors.success} bold>\n {symbols.check} All skills are up to date on selected agents\n </Text>\n </Box>\n\n <Box marginTop={1} borderStyle=\"round\" borderColor={colors.border} paddingX={1}>\n <Text>\n <Text color={colors.warning} bold>\n esc\n </Text>\n <Text color={colors.textDim}> back</Text>\n </Text>\n </Box>\n </Box>\n )\n}\n", "import { atom } from 'jotai'\nimport { unwrap } from 'jotai/utils'\nimport { detectInstalledAgents, listInstalledSkills } from '@peterson-benhame/core'\nimport type { AgentType } from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\n\nexport type InstallationMap = Record<string, AgentType[]>\n\nconst fetchInstalledSkills = async (): Promise<InstallationMap> => {\n const agents = detectInstalledAgents(ports)\n const status: InstallationMap = {}\n\n for (const agent of agents) {\n const [local, global] = await Promise.all([\n listInstalledSkills(ports, agent, false).catch(() => []),\n listInstalledSkills(ports, agent, true).catch(() => []),\n ])\n\n for (const skill of new Set([...local, ...global])) {\n if (!status[skill]) status[skill] = []\n if (!status[skill].includes(agent)) status[skill].push(agent)\n }\n }\n\n return status\n}\n\nexport const installedSkillsRefreshAtom = atom(0)\n\nconst installedSkillsAsyncAtom = atom(async (get) => {\n get(installedSkillsRefreshAtom)\n return fetchInstalledSkills()\n})\n\nexport const installedSkillsAtom = unwrap(installedSkillsAsyncAtom, (prev) => prev ?? {})\n", "import { atom } from 'jotai'\n\nimport type { AgentType, SkillInfo } from '../types'\n\nexport const selectedAgentsAtom = atom<AgentType[]>([])\nexport const selectedSkillsAtom = atom<SkillInfo[]>([])\n", "import { Box, Text, useInput } from 'ink'\n\nimport { colors, symbols } from '../theme'\nimport { Header } from './Header'\n\ninterface InstallResultsProps {\n results: Array<{ success: boolean; skill: string; agent: string; error?: string }>\n onExit: () => void\n title?: string\n successLabel?: string\n}\n\nexport function InstallResults({\n results,\n onExit,\n title = 'Installation Complete',\n successLabel = 'succeeded',\n}: InstallResultsProps) {\n useInput((_, key) => {\n if (key.return || key.escape) onExit()\n })\n\n const uniqueSuccessSkills = new Set(results.filter((r) => r.success).map((r) => r.skill))\n const uniqueFailedSkills = new Set(results.filter((r) => !r.success).map((r) => r.skill))\n const successCount = uniqueSuccessSkills.size\n const failCount = uniqueFailedSkills.size\n\n const allFailed = successCount === 0 && failCount > 0\n const anyFailed = failCount > 0\n const borderColor = allFailed ? colors.error : anyFailed ? colors.warning : colors.success\n\n const displayTitle = allFailed\n ? `${symbols.cross} Installation Failed`\n : anyFailed\n ? `${symbols.warning} Partially Installed`\n : `${symbols.check} ${title}`\n\n const titleColor = allFailed ? colors.error : anyFailed ? colors.warning : colors.success\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={borderColor} paddingX={2} paddingY={1}>\n <Box marginBottom={1}>\n <Text color={titleColor} bold>\n {displayTitle}\n </Text>\n </Box>\n\n {results.map((res, i) => (\n <Box key={i} flexDirection=\"column\">\n <Box paddingX={1}>\n <Box width={2}>\n <Text color={res.success ? colors.success : colors.error}>\n {res.success ? symbols.check : symbols.cross}\n </Text>\n </Box>\n <Text color={res.success ? colors.text : colors.error}>{res.skill}</Text>\n <Text color={colors.textDim}>\n {' '}\n {symbols.arrow} {res.agent}\n </Text>\n </Box>\n {!res.success && res.error && (\n <Box paddingLeft={4}>\n <Text color={colors.error} dimColor>\n {res.error}\n </Text>\n </Box>\n )}\n </Box>\n ))}\n\n {(successCount > 0 || failCount > 0) && (\n <Box marginTop={1}>\n <Text color={colors.textDim}>\n {successCount > 0 && (\n <Text color={colors.success}>\n {successCount} {successLabel}\n </Text>\n )}\n {successCount > 0 && failCount > 0 && <Text> {symbols.dot} </Text>}\n {failCount > 0 && <Text color={colors.error}>{failCount} failed</Text>}\n </Text>\n </Box>\n )}\n\n <Box marginTop={1}>\n <Text color={colors.textDim}>\n View details: <Text color={colors.accent}>agent-skills audit</Text>\n </Text>\n </Box>\n </Box>\n\n <Box marginTop={1} borderStyle=\"round\" borderColor={colors.border} paddingX={1}>\n <Text>\n <Text color={colors.success} bold>\n enter\n </Text>\n <Text color={colors.textDim}> / </Text>\n <Text color={colors.warning} bold>\n esc\n </Text>\n <Text color={colors.textDim}> exit</Text>\n </Text>\n </Box>\n </Box>\n )\n}\n", "import { Box, Text, useInput } from 'ink'\nimport Spinner from 'ink-spinner'\nimport { useAtomValue } from 'jotai'\nimport { useMemo, useState } from 'react'\n\nimport { Header } from '../components/Header'\nimport { MultiSelectPrompt } from '../components/MultiSelectPrompt'\nimport { SelectPrompt } from '../components/SelectPrompt'\nimport { useRemover } from '../hooks/useRemover'\nimport { colors, symbols } from '../theme'\nimport type { AgentType } from '../types'\nimport { AgentSelector } from './AgentSelector'\n\nimport { deprecatedSkillsAtom } from '../atoms/deprecatedSkills'\nimport { installedSkillsAtom } from '../atoms/installedSkills'\n\nexport function RemoveWizard({ selectedAgents, onExit }: { selectedAgents?: AgentType[]; onExit: () => void }) {\n const [internalAgents, setInternalAgents] = useState<AgentType[]>(selectedAgents || [])\n const { removeMultiple, progress, results } = useRemover()\n\n const installedSkills = useAtomValue(installedSkillsAtom)\n const deprecatedMap = useAtomValue(deprecatedSkillsAtom)\n\n const [step, setStep] = useState<'agent-select' | 'select' | 'confirm' | 'removing' | 'done'>(\n selectedAgents ? 'select' : 'agent-select',\n )\n\n const [selectedToRemove, setSelectedToRemove] = useState<string[]>([])\n const activeAgents = selectedAgents || internalAgents\n\n const filteredSkills = useMemo(() => {\n const filtered: Record<string, AgentType[]> = {}\n Object.entries(installedSkills).forEach(([skillName, agents]) => {\n const matchingAgents = agents.filter((a: AgentType) => activeAgents.includes(a))\n if (matchingAgents.length > 0) filtered[skillName] = matchingAgents\n })\n return filtered\n }, [installedSkills, activeAgents])\n\n const skillNames = useMemo(() => Object.keys(filteredSkills), [filteredSkills])\n\n const selectItems = useMemo(() => {\n return skillNames.map((name) => {\n const isDeprecated = deprecatedMap instanceof Map && deprecatedMap.has(name)\n const agentHint = `${filteredSkills[name].length} agents: ${filteredSkills[name].join(', ')}`\n const hint = isDeprecated ? `${agentHint} \u26A0 deprecated` : agentHint\n return { label: name, value: name, hint }\n })\n }, [skillNames, filteredSkills, deprecatedMap])\n\n useInput((_, key) => {\n if (step === 'done' && (key.return || key.escape)) onExit()\n if (skillNames.length === 0 && key.escape) onExit()\n })\n\n if (step === 'agent-select') {\n return (\n <AgentSelector\n onSelect={(agents) => {\n setInternalAgents(agents)\n setStep('select')\n }}\n onBack={onExit}\n />\n )\n }\n\n if (skillNames.length === 0) {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box borderStyle=\"round\" borderColor={colors.warning} paddingX={2} paddingY={1}>\n <Text color={colors.warning}>No skills found to remove for the selected agents.</Text>\n </Box>\n <Box marginTop={1} borderStyle=\"round\" borderColor={colors.border} paddingX={1}>\n <Text>\n <Text color={colors.warning} bold>\n esc\n </Text>\n <Text color={colors.textDim}> exit</Text>\n </Text>\n </Box>\n </Box>\n )\n }\n\n const handleSelect = (selected: string[]) => {\n if (selected.length === 0) return\n setSelectedToRemove(selected)\n setStep('confirm')\n }\n\n const executeRemoval = async () => {\n setStep('removing')\n const targets = selectedToRemove.map((name) => ({ name, agents: filteredSkills[name] || [] }))\n await removeMultiple(targets)\n setStep('done')\n }\n\n if (step === 'select') {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box marginBottom={1}>\n <Text bold color={colors.error}>\n {symbols.diamond} Select skills to remove:\n </Text>\n </Box>\n <MultiSelectPrompt items={selectItems} onSubmit={handleSelect} onCancel={onExit} />\n </Box>\n )\n }\n\n if (step === 'confirm') {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={colors.error} paddingX={2} paddingY={1}>\n <Box marginBottom={1}>\n <Text color={colors.error} bold>\n {symbols.cross} Remove {selectedToRemove.length} skill{selectedToRemove.length > 1 ? 's' : ''}?\n </Text>\n </Box>\n\n {selectedToRemove.map((s) => (\n <Box key={s} paddingX={1}>\n <Box width={2}>\n <Text color={colors.error}>{symbols.dot}</Text>\n </Box>\n <Text color={colors.textDim}>{s}</Text>\n </Box>\n ))}\n </Box>\n\n <Box marginTop={1}>\n <SelectPrompt\n items={[\n { label: 'Yes, remove them', value: 'yes' },\n { label: 'No, cancel', value: 'no' },\n ]}\n onSelect={(val) => {\n if (val === 'yes') executeRemoval()\n else setStep('select')\n }}\n />\n </Box>\n </Box>\n )\n }\n\n if (step === 'removing') {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box marginTop={1}>\n <Text color={colors.accent}>\n <Spinner type=\"dots\" />{' '}\n </Text>\n <Text>Removing skills...</Text>\n </Box>\n <Box marginTop={1} paddingX={2}>\n <Text color={colors.textDim}>\n {symbols.arrow} {progress.skill} ({progress.current}/{progress.total})\n </Text>\n </Box>\n </Box>\n )\n }\n\n if (step === 'done') {\n const successCount = results.filter((r) => r.success).length\n const failCount = results.filter((r) => !r.success).length\n const allFailed = successCount === 0\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={allFailed ? colors.error : colors.success}\n paddingX={2}\n paddingY={1}\n >\n <Box marginBottom={1}>\n <Text color={allFailed ? colors.error : colors.success} bold>\n {allFailed ? symbols.cross : symbols.check} {allFailed ? 'Removal Failed' : 'Removal Complete'}\n </Text>\n </Box>\n\n {results.map((res, i) => (\n <Box key={i} paddingX={1}>\n <Box width={2}>\n <Text color={res.success ? colors.success : colors.error}>\n {res.success ? symbols.check : symbols.cross}\n </Text>\n </Box>\n <Text color={res.success ? colors.text : colors.error}>{res.skill}</Text>\n <Text color={colors.textDim}>\n {' '}\n {symbols.arrow} {res.agent}\n </Text>\n {!res.success && res.error && <Text color={colors.error}> ({res.error})</Text>}\n </Box>\n ))}\n\n {(successCount > 0 || failCount > 0) && (\n <Box marginTop={1}>\n <Text color={colors.textDim}>\n {successCount > 0 && <Text color={colors.success}>{successCount} succeeded</Text>}\n {successCount > 0 && failCount > 0 && <Text> {symbols.dot} </Text>}\n {failCount > 0 && <Text color={colors.error}>{failCount} failed</Text>}\n </Text>\n </Box>\n )}\n </Box>\n\n <Box marginTop={1} borderStyle=\"round\" borderColor={colors.border} paddingX={1}>\n <Text>\n <Text color={colors.success} bold>\n enter\n </Text>\n <Text color={colors.textDim}> / </Text>\n <Text color={colors.warning} bold>\n esc\n </Text>\n <Text color={colors.textDim}> exit</Text>\n </Text>\n </Box>\n </Box>\n )\n }\n\n return null\n}\n", "import { atom } from 'jotai'\nimport { unwrap } from 'jotai/utils'\nimport { getDeprecatedMap } from '@peterson-benhame/core'\nimport type { DeprecatedEntry } from '@peterson-benhame/core'\n\nimport { ports } from '../ports'\n\nconst deprecatedSkillsAsyncAtom = atom(async (): Promise<Map<string, DeprecatedEntry>> => {\n return getDeprecatedMap(ports)\n})\n\nexport const deprecatedSkillsAtom = unwrap(deprecatedSkillsAsyncAtom, (prev) => prev ?? new Map())\n", "import { Box, Text, useInput, useStdout } from 'ink'\nimport { useAtomValue } from 'jotai'\nimport { useMemo, useState } from 'react'\nimport { groupSkillsByCategory } from '@peterson-benhame/core'\nimport type { SkillInfo } from '@peterson-benhame/core'\n\nimport { CategoryHeader, Header, SearchInput, SkillCard, SkillDetailPanel } from '../components'\nimport { FooterBar } from '../components/FooterBar'\nimport { KeyboardShortcutsOverlay, type ShortcutEntry } from '../components/KeyboardShortcutsOverlay'\nimport { useFilter, useSkills } from '../hooks'\nimport { canShowDetailPanel } from '../services/terminal-dimensions'\nimport { colors, symbols } from '../theme'\nimport { ports } from '../ports'\n\nimport { deprecatedSkillsAtom } from '../atoms/deprecatedSkills'\nimport { installedSkillsAtom } from '../atoms/installedSkills'\nimport { selectedAgentsAtom } from '../atoms/wizard'\n\ninterface SkillBrowserProps {\n onInstall?: (selectedSkills: SkillInfo[]) => void\n onExit?: () => void\n overrideSkills?: SkillInfo[]\n readOnly?: boolean\n}\n\ntype VisualItem =\n | { type: 'header'; category: string; categoryId?: string; count: number; installedCount: number }\n | { type: 'skill'; skill: SkillInfo }\n\nconst MIN_VISIBLE = 5\nconst CHROME_LINES = 24\nconst PANEL_WIDTH_RATIO = 0.35\n\nconst getShortcuts = (readOnly: boolean): ShortcutEntry[] => {\n const common = [\n { key: '/', description: 'Filter skills' },\n { key: '\u2190/\u2192', description: 'Collapse / expand' },\n { key: 'tab/\u2192', description: 'Skill details' },\n { key: 'f', description: 'Expand / compact panel' },\n ]\n\n const exitKey = { key: 'esc', description: readOnly ? 'Exit / close panel' : 'Back / close panel' }\n\n if (readOnly) return [...common, exitKey]\n\n return [\n ...common,\n { key: 'space', description: 'Toggle / expand' },\n { key: 'enter', description: 'Install selected' },\n { key: 'ctrl+a', description: 'Select all' },\n exitKey,\n ]\n}\n\nexport const SkillBrowser = ({ onInstall, onExit, overrideSkills, readOnly = false }: SkillBrowserProps) => {\n const { skills: fetchedSkills, loading: fetching, error } = useSkills()\n const { stdout } = useStdout()\n\n const selectedAgents = useAtomValue(selectedAgentsAtom)\n const installedSkills = useAtomValue(installedSkillsAtom)\n const deprecatedMap = useAtomValue(deprecatedSkillsAtom)\n\n const skills = overrideSkills || fetchedSkills\n const loading = overrideSkills ? false : fetching\n\n const { query, setQuery, filtered } = useFilter(skills, {\n keys: ['name', 'description', 'category'],\n })\n\n const [selectedSet, setSelectedSet] = useState<Set<string>>(new Set())\n const [focusArea, setFocusArea] = useState<'search' | 'list'>('list')\n const [listIndex, setListIndex] = useState(0)\n const [offset, setOffset] = useState(0)\n const [showSearch, setShowSearch] = useState(false)\n const [showShortcuts, setShowShortcuts] = useState(false)\n const [detailSkill, setDetailSkill] = useState<SkillInfo | null>(null)\n const [drawerExpanded, setDrawerExpanded] = useState(false)\n const [expandedCategory, setExpandedCategory] = useState<string | null>(null)\n\n const canShowPanel = canShowDetailPanel()\n const terminalRows = stdout?.rows ?? 40\n const terminalCols = stdout?.columns ?? 120\n const VISIBLE_ITEMS = Math.max(MIN_VISIBLE, terminalRows - CHROME_LINES)\n const panelWidth = Math.max(30, Math.round(terminalCols * PANEL_WIDTH_RATIO))\n const contentAreaHeight = Math.max(10, terminalRows - 17)\n const isSearchExpanded = query.trim().length > 0\n\n const groupedMap = useMemo(() => groupSkillsByCategory(ports, filtered), [filtered])\n\n useMemo(() => {\n if (query) setShowSearch(true)\n }, [query])\n\n const isCategoryExpanded = (categoryName: string) => isSearchExpanded || expandedCategory === categoryName\n\n const toggleCategory = (categoryName: string) => {\n setExpandedCategory(isCategoryExpanded(categoryName) ? null : categoryName)\n }\n\n const visualList = useMemo(() => {\n const list: VisualItem[] = []\n\n for (const [category, categorySkills] of groupedMap.entries()) {\n const installedCount = categorySkills.filter((s) => {\n const agents = installedSkills[s.name] || []\n if (selectedAgents.length > 0) return agents.some((a) => selectedAgents.includes(a))\n return agents.length > 0\n }).length\n\n list.push({\n type: 'header',\n category: category.name,\n categoryId: category.id,\n count: categorySkills.length,\n installedCount,\n })\n\n if (isCategoryExpanded(category.name)) categorySkills.forEach((skill) => list.push({ type: 'skill', skill }))\n }\n\n return list\n }, [groupedMap, expandedCategory, isSearchExpanded, installedSkills, selectedAgents])\n\n const handleToggleShortcuts = () => setShowShortcuts((prev) => !prev)\n\n const handleEscape = () => {\n if (showSearch) {\n setShowSearch(false)\n setQuery('')\n setFocusArea('list')\n return\n }\n onExit?.()\n }\n\n const handleSelectAll = () => {\n const allSkillNames = filtered.map((s) => s.name)\n setSelectedSet(selectedSet.size === allSkillNames.length ? new Set() : new Set(allSkillNames))\n }\n\n const handleSearchNavigation = (key: { downArrow?: boolean; return?: boolean }) => {\n if ((key.downArrow || key.return) && visualList.length > 0) {\n setFocusArea('list')\n setListIndex(0)\n }\n }\n\n const handleUpArrow = () => {\n if (listIndex === 0 && showSearch) {\n setFocusArea('search')\n return\n }\n\n const newIndex = Math.max(0, listIndex - 1)\n setListIndex(newIndex)\n if (newIndex < offset) setOffset(newIndex)\n }\n\n const handleDownArrow = () => {\n const newIndex = Math.min(visualList.length - 1, listIndex + 1)\n setListIndex(newIndex)\n if (newIndex >= offset + VISIBLE_ITEMS) setOffset(newIndex - VISIBLE_ITEMS + 1)\n }\n\n const handleSpaceKey = () => {\n const item = visualList[listIndex]\n\n if (item.type === 'header') {\n toggleCategory(item.category)\n return\n }\n\n if (item.type === 'skill' && !readOnly) {\n const isInstalled =\n selectedAgents.length > 0\n ? (installedSkills[item.skill.name]?.some((a) => selectedAgents.includes(a)) ?? false)\n : (installedSkills[item.skill.name]?.length ?? 0) > 0\n\n if (isInstalled && !overrideSkills) return\n\n const newSet = new Set(selectedSet)\n if (newSet.has(item.skill.name)) {\n newSet.delete(item.skill.name)\n } else {\n newSet.add(item.skill.name)\n }\n setSelectedSet(newSet)\n }\n }\n\n const handleEnterKey = () => {\n const item = visualList[listIndex]\n\n if (item.type === 'header') {\n toggleCategory(item.category)\n return\n }\n\n if (readOnly) return\n\n const selectedSkills = skills.filter((s) => selectedSet.has(s.name))\n if (selectedSkills.length > 0) onInstall?.(selectedSkills)\n }\n\n const handleTabOrRightArrow = (isTab: boolean) => {\n const item = visualList[listIndex]\n\n if (item.type === 'skill' && canShowPanel) {\n setDetailSkill(item.skill)\n setDrawerExpanded(false)\n return\n }\n\n if (!isTab && item.type === 'header' && !isCategoryExpanded(item.category)) setExpandedCategory(item.category)\n }\n\n const handleLeftArrow = () => {\n const item = visualList[listIndex]\n if (item.type === 'header' && isCategoryExpanded(item.category)) setExpandedCategory(null)\n }\n\n const isRegularCharacter = (\n input: string,\n key: {\n ctrl?: boolean\n meta?: boolean\n upArrow?: boolean\n downArrow?: boolean\n leftArrow?: boolean\n rightArrow?: boolean\n },\n ) =>\n input.length === 1 && !key.ctrl && !key.meta && !key.upArrow && !key.downArrow && !key.leftArrow && !key.rightArrow\n\n useInput(\n (input, key) => {\n if (input === '?') return handleToggleShortcuts()\n if (showShortcuts) return setShowShortcuts(false)\n if (key.escape) return handleEscape()\n\n if (!showSearch && input === '/') {\n setShowSearch(true)\n setFocusArea('search')\n return\n }\n\n if (input === 'a' && key.ctrl && !readOnly) return handleSelectAll()\n if (focusArea === 'search') return handleSearchNavigation(key)\n\n if (focusArea === 'list') {\n if (key.upArrow) return handleUpArrow()\n if (key.downArrow) return handleDownArrow()\n if (input === ' ') return handleSpaceKey()\n if (key.return) return handleEnterKey()\n if (key.tab) return handleTabOrRightArrow(true)\n if (key.rightArrow) return handleTabOrRightArrow(false)\n if (key.leftArrow) return handleLeftArrow()\n\n if (isRegularCharacter(input, key)) {\n setShowSearch(true)\n setFocusArea('search')\n setQuery(input)\n }\n }\n },\n { isActive: !detailSkill },\n )\n\n const visibleWindow = visualList.slice(offset, offset + VISIBLE_ITEMS)\n const hasItemsAbove = offset > 0\n const hasItemsBelow = offset + VISIBLE_ITEMS < visualList.length\n const scrollPercent =\n visualList.length <= VISIBLE_ITEMS ? 100 : Math.round(((offset + VISIBLE_ITEMS) / visualList.length) * 100)\n const showSkillList = !detailSkill || !drawerExpanded\n\n if (loading) {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box flexDirection=\"column\" alignItems=\"center\" justifyContent=\"center\" paddingY={4}>\n <Text color={colors.accent}>Loading skills...</Text>\n </Box>\n </Box>\n )\n }\n\n if (error || (!loading && skills.length === 0)) {\n return (\n <Box flexDirection=\"column\" paddingX={1} minHeight={20}>\n <Header />\n <Box flexDirection=\"column\" alignItems=\"center\" justifyContent=\"center\" flexGrow={1}>\n <Box\n flexDirection=\"column\"\n borderStyle=\"round\"\n borderColor={colors.error}\n paddingX={3}\n paddingY={2}\n alignItems=\"center\"\n >\n <Text color={colors.error} bold>\n {symbols.cross} No Skills Available\n </Text>\n <Box marginTop={1}>\n <Text color={colors.textDim}>Check your internet connection and try again</Text>\n </Box>\n {error && (\n <Box marginTop={1}>\n <Text color={colors.textMuted} dimColor>\n {error}\n </Text>\n </Box>\n )}\n </Box>\n <Box marginTop={2}>\n <Text color={colors.textDim}>\n Press{' '}\n <Text color={colors.accent} bold>\n Esc\n </Text>{' '}\n to exit\n </Text>\n </Box>\n </Box>\n </Box>\n )\n }\n\n const renderSkillListItem = (item: VisualItem, index: number) => {\n const realIndex = offset + index\n const isFocused = focusArea === 'list' && realIndex === listIndex\n\n if (item.type === 'header') {\n return (\n <Box key={`cat-${item.category}`} marginTop={index === 0 ? 0 : 1}>\n <CategoryHeader\n name={item.category}\n categoryId={item.categoryId}\n totalCount={item.count}\n installedCount={item.installedCount}\n isExpanded={isCategoryExpanded(item.category)}\n isFocused={isFocused}\n />\n </Box>\n )\n }\n\n const isSelected = selectedSet.has(item.skill.name)\n const isInstalled =\n selectedAgents.length > 0\n ? (installedSkills[item.skill.name]?.some((a) => selectedAgents.includes(a)) ?? false)\n : (installedSkills[item.skill.name]?.length ?? 0) > 0\n const isDeprecated = deprecatedMap instanceof Map && deprecatedMap.has(item.skill.name)\n const status = isDeprecated ? 'deprecated' : isInstalled ? 'installed' : null\n\n return (\n <SkillCard\n key={item.skill.name}\n name={item.skill.name}\n description={item.skill.description}\n status={status}\n selected={isSelected}\n focused={isFocused}\n readOnly={readOnly}\n />\n )\n }\n\n const renderScrollIndicator = (direction: 'up' | 'down') => (\n <Box justifyContent=\"center\" marginBottom={direction === 'up' ? 1 : 0} marginTop={direction === 'down' ? 1 : 0}>\n <Text color={colors.textDim}>\n {direction === 'up' ? symbols.arrowUp : symbols.arrowDown}{' '}\n {direction === 'up' ? symbols.arrowUp : symbols.arrowDown}{' '}\n {direction === 'up' ? symbols.arrowUp : symbols.arrowDown}\n </Text>\n </Box>\n )\n\n const renderFooterHints = () => {\n if (detailSkill) {\n return [\n { key: '\u2191/\u2193', label: 'scroll' },\n { key: 'f', label: drawerExpanded ? 'compact' : 'expand' },\n { key: 'Esc', label: 'close', color: colors.warning },\n ]\n }\n\n if (readOnly) {\n return [\n { key: '/', label: 'filter' },\n { key: 'tab', label: 'detail' },\n { key: 'esc', label: 'exit', color: colors.warning },\n { key: '?', label: 'help' },\n ]\n }\n\n return [\n { key: 'space', label: 'toggle' },\n { key: 'enter', label: 'install', color: colors.success },\n { key: '/', label: 'filter' },\n { key: 'tab', label: 'detail' },\n { key: 'esc', label: 'exit', color: colors.warning },\n { key: '?', label: 'help' },\n ]\n }\n\n const renderFooterStatus = () => {\n if (detailSkill) return undefined\n\n return (\n <>\n {!readOnly && selectedSet.size > 0 && (\n <Text>\n <Text color={colors.success} bold>\n {symbols.checkboxActive} {selectedSet.size}\n </Text>\n <Text color={colors.textDim}> selected</Text>\n </Text>\n )}\n {visualList.length > VISIBLE_ITEMS && (\n <Text color={colors.textDim}>\n {!readOnly && selectedSet.size > 0 ? ` ${symbols.dot} ` : ''}\n {scrollPercent}%\n </Text>\n )}\n </>\n )\n }\n\n return (\n <Box flexDirection=\"column\" paddingX={1} minHeight={20}>\n <Header />\n\n {showShortcuts ? (\n <Box flexDirection=\"column\" flexGrow={1} alignItems=\"center\" justifyContent=\"center\">\n <KeyboardShortcutsOverlay\n visible={showShortcuts}\n onDismiss={() => setShowShortcuts(false)}\n shortcuts={getShortcuts(readOnly)}\n />\n </Box>\n ) : (\n <Box\n flexDirection=\"row\"\n height={detailSkill ? contentAreaHeight : undefined}\n flexGrow={detailSkill ? 0 : 1}\n overflow=\"hidden\"\n >\n {showSkillList && (\n <Box key=\"skill-list\" flexDirection=\"column\" flexGrow={1} flexShrink={1}>\n {showSearch && (\n <Box marginBottom={1}>\n <SearchInput\n query={query}\n onChange={(q) => {\n setQuery(q)\n setListIndex(0)\n setOffset(0)\n }}\n total={skills.length}\n filtered={filtered.length}\n isLoading={loading}\n focus={focusArea === 'search'}\n />\n </Box>\n )}\n\n <Box flexDirection=\"column\" flexGrow={1}>\n {hasItemsAbove && renderScrollIndicator('up')}\n {visibleWindow.map(renderSkillListItem)}\n {hasItemsBelow && renderScrollIndicator('down')}\n {visualList.length === 0 && (\n <Box paddingY={1}>\n <Text color={colors.textMuted}>No skills match \"{query}\"</Text>\n </Box>\n )}\n </Box>\n </Box>\n )}\n\n {detailSkill && (\n <Box\n key=\"detail-panel\"\n flexDirection=\"column\"\n width={drawerExpanded ? undefined : panelWidth}\n flexGrow={drawerExpanded ? 1 : 0}\n flexShrink={0}\n >\n <SkillDetailPanel\n skill={detailSkill}\n expanded={drawerExpanded}\n onClose={() => {\n setDetailSkill(null)\n setDrawerExpanded(false)\n }}\n onToggleExpand={() => setDrawerExpanded((prev) => !prev)}\n />\n </Box>\n )}\n </Box>\n )}\n\n <FooterBar hints={renderFooterHints()} status={renderFooterStatus()} />\n </Box>\n )\n}\n", "import { Box, Text } from 'ink'\nimport { useMemo } from 'react'\n\nimport { formatCategoryBadge } from '../services/badge-format'\nimport { colors, symbols } from '../theme'\n\ninterface CategoryHeaderProps {\n name: string\n categoryId?: string\n totalCount: number\n installedCount?: number\n isExpanded?: boolean\n isFocused?: boolean\n}\n\nexport const CategoryHeader = ({\n name,\n totalCount,\n installedCount = 0,\n isExpanded = false,\n isFocused = false,\n}: CategoryHeaderProps) => {\n const badge = useMemo(() => formatCategoryBadge(installedCount, totalCount), [installedCount, totalCount])\n const chevron = isExpanded ? '\\u25BE' : '\\u25B8'\n\n return (\n <Box>\n <Box width={2}>{isFocused ? <Text color={colors.accent}>{symbols.bullet}</Text> : <Text> </Text>}</Box>\n <Text color={isFocused ? colors.accent : colors.primaryLight} bold>\n {chevron}{' '}\n </Text>\n <Text color={isFocused ? colors.accent : colors.text} bold>\n {name}\n </Text>\n <Text color={installedCount > 0 ? colors.success : colors.textMuted}> {badge}</Text>\n {!isExpanded && isFocused && <Text color={colors.textDim}> {symbols.dot} press space to expand</Text>}\n </Box>\n )\n}\n", "export function formatCategoryBadge(installed: number, total: number): string {\n if (installed > 0) return `(${installed}/${total})`\n return `(${total})`\n}\n", "import { Box, Text, useInput } from 'ink'\nimport { useState } from 'react'\n\nimport { colors, symbols } from '../theme'\n\ninterface ConfirmPromptProps {\n message: string\n initialValue?: boolean\n onSubmit: (value: boolean) => void\n}\n\nexport const ConfirmPrompt = ({ message, initialValue = false, onSubmit }: ConfirmPromptProps) => {\n const [value, setValue] = useState(initialValue)\n\n useInput((input, key) => {\n if (key.leftArrow || key.rightArrow || input === 'y' || input === 'n') setValue((prev) => !prev)\n if (key.return) onSubmit(value)\n })\n\n return (\n <Box flexDirection=\"column\" marginTop={1}>\n <Text bold>{message}</Text>\n <Box marginTop={1}>\n <Text color={value ? colors.success : colors.textMuted} bold={value}>\n {value ? symbols.radioActive : symbols.radioInactive} Yes\n </Text>\n <Box width={2} />\n <Text color={!value ? colors.error : colors.textMuted} bold={!value}>\n {!value ? symbols.radioActive : symbols.radioInactive} No\n </Text>\n </Box>\n </Box>\n )\n}\n", "import { Box, Text } from 'ink'\nimport TextInput from 'ink-text-input'\n\nimport { colors } from '../theme'\n\ninterface SearchInputProps {\n query: string\n onChange: (query: string) => void\n total: number\n filtered: number\n isLoading?: boolean\n focus?: boolean\n}\n\nexport const SearchInput = ({\n query,\n onChange,\n total,\n filtered,\n isLoading = false,\n focus = true,\n}: SearchInputProps) => {\n return (\n <Box borderStyle=\"round\" borderColor={focus ? colors.accent : colors.border} paddingX={1}>\n <Box marginRight={1}>\n <Text>\uD83D\uDD0D</Text>\n </Box>\n <Box flexGrow={1}>\n <TextInput value={query} onChange={onChange} placeholder=\"Type to filter skills...\" focus={focus} />\n </Box>\n <Box marginLeft={1}>\n <Text color={colors.textDim}>{isLoading ? 'Loading...' : `${filtered}/${total} skills`}</Text>\n </Box>\n </Box>\n )\n}\n", "import { Box, Text } from 'ink'\n\nimport { colors } from '../theme/colors'\nimport { symbols } from '../theme/symbols'\nimport { StatusBadge, type StatusType } from './StatusBadge'\n\nexport interface SkillCardProps {\n name: string\n description: string\n status?: StatusType | null\n selected?: boolean\n focused?: boolean\n readOnly?: boolean\n}\n\nexport function SkillCard({\n name,\n description,\n status,\n selected = false,\n focused = false,\n readOnly = false,\n}: SkillCardProps) {\n const isInstalled = status === 'installed'\n\n const checkbox = isInstalled ? symbols.checkboxActive : selected ? symbols.checkboxActive : symbols.checkboxInactive\n const checkboxColor = isInstalled ? colors.textMuted : selected ? colors.success : colors.textMuted\n\n const pointer = focused ? symbols.bullet : ' '\n const pointerColor = isInstalled ? colors.textMuted : selected ? colors.success : colors.accent\n const nameColor = isInstalled\n ? colors.textDim\n : focused\n ? colors.primary\n : selected\n ? colors.primaryLight\n : colors.text\n const descColor = colors.textMuted\n const bgColor = focused ? colors.bgLight : undefined\n\n return (\n <Box flexDirection=\"column\" backgroundColor={bgColor}>\n <Box>\n <Box width={2} flexShrink={0}>\n <Text color={pointerColor}>{pointer}</Text>\n </Box>\n\n {!readOnly && (\n <Box width={2} flexShrink={0}>\n <Text color={checkboxColor}>{checkbox}</Text>\n </Box>\n )}\n\n <Box flexGrow={1}>\n <Text bold color={nameColor}>\n {name}\n </Text>\n </Box>\n\n {status && (\n <Box marginLeft={1} flexShrink={0}>\n <StatusBadge status={status} />\n </Box>\n )}\n </Box>\n\n <Box paddingLeft={readOnly ? 2 : 4}>\n <Text color={descColor} wrap=\"truncate\">\n {description}\n </Text>\n </Box>\n </Box>\n )\n}\n", "import { Box, Text } from 'ink'\n\nimport { colors } from '../theme/colors'\nimport { symbols } from '../theme/symbols'\n\nexport type StatusType = 'installed' | 'update' | 'new' | 'deprecated'\n\nexport interface StatusBadgeProps {\n status: StatusType\n}\n\nconst badgeConfig = {\n installed: { icon: symbols.check, label: 'installed', color: colors.success, bg: '#052e16' },\n update: { icon: symbols.arrowUp, label: 'update', color: colors.warning, bg: '#422006' },\n new: { icon: symbols.sparkle, label: 'new', color: colors.accent, bg: '#083344' },\n deprecated: { icon: symbols.warning, label: 'deprecated', color: colors.warning, bg: '#422006' },\n} as const\n\nexport function StatusBadge({ status }: StatusBadgeProps) {\n const config = badgeConfig[status]\n if (!config) return null\n\n return (\n <Box>\n <Text backgroundColor={config.bg} color={config.color}>\n {' '}\n {config.icon} {config.label}{' '}\n </Text>\n </Box>\n )\n}\n\nexport interface AgentBadgeProps {\n agents: string[]\n}\n\nexport function AgentBadge({ agents }: AgentBadgeProps) {\n if (!agents || agents.length === 0) return null\n\n return (\n <Text color={colors.textDim}>\n <Text color={colors.success}>{symbols.check}</Text> {agents.join(', ')}\n </Text>\n )\n}\n", "import chalk from 'chalk'\nimport { Box, Text, useInput, useStdout } from 'ink'\nimport Spinner from 'ink-spinner'\nimport React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'\n\nimport { useSkillContent } from '../hooks/useSkillContent'\nimport { getColorForCategory } from '../services/category-colors'\nimport { parseMarkdown, type MarkdownToken } from '@peterson-benhame/core'\nimport { colors, symbols } from '../theme'\nimport type { SkillInfo } from '../types'\n\nexport interface SkillDetailPanelProps {\n skill: SkillInfo | null\n expanded?: boolean\n onClose: () => void\n onToggleExpand?: () => void\n}\n\nconst FIXED_HEADER_LINES = 6\nconst BORDER_LINES = 2\nconst INDICATOR_LINES = 2\n\nconst fmt = {\n h1: (s: string) => chalk.hex(colors.primary).bold(s),\n h2: (s: string) => chalk.hex(colors.primaryLight).bold(s),\n h3: (s: string) => chalk.hex(colors.accent).bold(s),\n text: (s: string) => chalk.hex(colors.textDim)(s),\n muted: (s: string) => chalk.hex(colors.textMuted)(s),\n code: (s: string) => chalk.hex(colors.accent)(s),\n border: (s: string) => chalk.hex(colors.border)(s),\n bold: (s: string) => chalk.hex(colors.text).bold(s),\n dim: (s: string) => chalk.dim(s),\n indicator: (s: string) => chalk.hex(colors.textDim)(s),\n}\n\nfunction formatInline(text: string): string {\n return text\n .replace(/\\*\\*(.+?)\\*\\*/g, (_, t) => fmt.bold(t))\n .replace(/\\*(.+?)\\*/g, (_, t) => fmt.dim(t))\n .replace(/`(.+?)`/g, (_, t) => fmt.code(t))\n}\n\nfunction tokensToLines(tokens: MarkdownToken[]): string[] {\n const lines: string[] = []\n for (const token of tokens) {\n switch (token.type) {\n case 'heading': {\n const sym = token.level === 1 ? symbols.diamond : token.level === 2 ? symbols.arrow : symbols.dot\n const colorFn = token.level === 1 ? fmt.h1 : token.level === 2 ? fmt.h2 : fmt.h3\n if (token.level === 1 && lines.length > 0) lines.push('')\n lines.push(colorFn(`${sym} ${token.text}`))\n break\n }\n case 'paragraph':\n lines.push(fmt.text(formatInline(token.text)))\n break\n case 'list-item': {\n const indent = ' '.repeat(token.indent)\n lines.push(`${indent}${fmt.muted(symbols.bullet)} ${fmt.text(formatInline(token.text))}`)\n break\n }\n case 'code-block':\n if (token.language) lines.push(fmt.dim(` ${token.language}`))\n for (const line of token.lines) {\n lines.push(` ${fmt.border(symbols.bar)} ${fmt.code(line)}`)\n }\n break\n case 'hr':\n lines.push(fmt.border('\u2500'.repeat(30)))\n break\n case 'blank':\n lines.push('')\n break\n }\n }\n return lines\n}\n\nconst MetadataHeader = React.memo(\n ({ skill, metadata }: { skill: SkillInfo; metadata: { author?: string; files: string[] } | null }) => {\n const categoryColor = getColorForCategory(skill.category ?? 'default')\n const author = metadata?.author ? ` ${symbols.dot} @${metadata.author}` : ''\n const files = metadata?.files?.length\n ? ` ${symbols.dot} ${metadata.files.length} file${metadata.files.length !== 1 ? 's' : ''}`\n : ''\n\n return (\n <Box flexDirection=\"column\" marginBottom={1}>\n <Text bold color={colors.text}>\n {symbols.sparkle} {skill.name}\n </Text>\n <Text>\n <Text color={categoryColor} bold>\n {skill.category}\n </Text>\n <Text color={colors.textDim}>\n {author}\n {files}\n </Text>\n </Text>\n <Text color={colors.textDim} wrap=\"truncate\">\n {skill.description}\n </Text>\n </Box>\n )\n },\n)\nMetadataHeader.displayName = 'MetadataHeader'\n\nexport const SkillDetailPanel = React.memo(\n ({ skill, expanded = false, onClose, onToggleExpand }: SkillDetailPanelProps) => {\n const { metadata, content, loading, error } = useSkillContent(skill?.name ?? null)\n const { stdout } = useStdout()\n const [scrollOffset, setScrollOffset] = useState(0)\n\n const terminalRows = stdout?.rows ?? 24\n const formattedLines = useMemo(() => (content ? tokensToLines(parseMarkdown(content)) : []), [content])\n\n const containerHeight = Math.max(10, terminalRows - 17)\n const scrollAreaHeight = Math.max(3, containerHeight - FIXED_HEADER_LINES - BORDER_LINES)\n const contentVisibleLines = Math.max(1, scrollAreaHeight - INDICATOR_LINES)\n\n const maxScroll = Math.max(0, formattedLines.length - contentVisibleLines)\n const canScroll = maxScroll > 0\n\n const scrollPercent = canScroll\n ? Math.round(((scrollOffset + contentVisibleLines) / formattedLines.length) * 100)\n : 100\n\n const maxScrollRef = useRef(maxScroll)\n maxScrollRef.current = maxScroll\n const onCloseRef = useRef(onClose)\n onCloseRef.current = onClose\n const onToggleExpandRef = useRef(onToggleExpand)\n onToggleExpandRef.current = onToggleExpand\n\n const handleInput = useCallback(\n (\n input: string,\n key: { upArrow: boolean; downArrow: boolean; escape: boolean; tab: boolean; leftArrow: boolean },\n ) => {\n if (key.upArrow) {\n setScrollOffset((prev) => Math.max(0, prev - 1))\n } else if (key.downArrow) {\n setScrollOffset((prev) => Math.min(maxScrollRef.current, prev + 1))\n } else if (input === 'f') {\n onToggleExpandRef.current?.()\n } else if (key.escape || key.tab || key.leftArrow) {\n onCloseRef.current()\n }\n },\n [],\n )\n\n useInput(handleInput)\n\n useEffect(() => {\n setScrollOffset(0)\n }, [skill?.name])\n\n if (!skill) return null\n\n const hasAbove = scrollOffset > 0\n const hasMore = scrollOffset + contentVisibleLines < formattedLines.length\n const visibleSlice = formattedLines.slice(scrollOffset, scrollOffset + contentVisibleLines)\n\n return (\n <Box flexDirection=\"column\" borderStyle=\"round\" borderColor={colors.accent} paddingX={1} flexGrow={1}>\n <Box>\n <Text bold color={colors.accent}>\n {symbols.info} Skill Details\n </Text>\n <Box flexGrow={1} />\n <Text color={colors.textMuted}>\n {canScroll && (\n <Text color={colors.textDim}>\n {scrollPercent}% {symbols.dot}{' '}\n </Text>\n )}\n <Text color={colors.accent} bold>\n \u2191\u2193\n </Text>{' '}\n scroll {symbols.dot}{' '}\n <Text color={colors.accent} bold>\n f\n </Text>{' '}\n {expanded ? 'compact' : 'expand'} {symbols.dot}{' '}\n <Text color={colors.accent} bold>\n Esc\n </Text>{' '}\n close\n </Text>\n </Box>\n\n <Text color={colors.border} wrap=\"truncate\">\n {'\u2500'.repeat(200)}\n </Text>\n\n {loading ? (\n <Box alignItems=\"center\" justifyContent=\"center\" flexGrow={1}>\n <Text color={colors.accent}>\n <Spinner type=\"dots\" /> Loading\u2026\n </Text>\n </Box>\n ) : error ? (\n <Box alignItems=\"center\" justifyContent=\"center\" flexGrow={1}>\n <Text color={colors.error}>\n {symbols.cross} {error}\n </Text>\n </Box>\n ) : (\n <>\n <MetadataHeader skill={skill} metadata={metadata} />\n\n <Box flexDirection=\"column\" height={scrollAreaHeight} overflowY=\"hidden\">\n {hasAbove && (\n <Text color={colors.textDim}>{` ${symbols.arrowUp} ${symbols.arrowUp} ${symbols.arrowUp}`}</Text>\n )}\n <Text>{visibleSlice.join('\\n')}</Text>\n {hasMore && (\n <Text color={colors.textDim}>\n {` ${symbols.arrowDown} ${symbols.arrowDown} ${symbols.arrowDown}`}\n </Text>\n )}\n </Box>\n </>\n )}\n </Box>\n )\n },\n)\n\nSkillDetailPanel.displayName = 'SkillDetailPanel'\n", "export const categoryColors: Record<string, string> = {\n web: '#3b82f6',\n devops: '#10b981',\n data: '#8b5cf6',\n mobile: '#f59e0b',\n testing: '#ef4444',\n ai: '#06b6d4',\n security: '#ec4899',\n default: '#64748b',\n} as const\n\nexport function getColorForCategory(categoryId: string): string {\n if (Object.prototype.hasOwnProperty.call(categoryColors, categoryId)) return categoryColors[categoryId]\n return categoryColors.default\n}\n\nexport function getAllCategoryColors(): Record<string, string> {\n return { ...categoryColors }\n}\n", "export interface TerminalSize {\n width: number\n height: number\n}\n\nexport function getTerminalSize(): TerminalSize {\n return { width: process.stdout.columns || 80, height: process.stdout.rows || 24 }\n}\n\nexport function shouldUseBottomPanel(): boolean {\n const { width } = getTerminalSize()\n return width < 120\n}\n\nexport function canShowDetailPanel(): boolean {\n const { width, height } = getTerminalSize()\n return width >= 80 && height >= 24\n}\n", "import { Box, Text, useInput } from 'ink'\nimport Spinner from 'ink-spinner'\nimport { useAtomValue } from 'jotai'\nimport { useEffect, useMemo, useState } from 'react'\nimport { getUpdatableSkills } from '@peterson-benhame/core'\nimport type { AgentType, DeprecatedEntry, SkillInfo } from '@peterson-benhame/core'\n\nimport { deprecatedSkillsAtom } from '../atoms/deprecatedSkills'\nimport { installedSkillsAtom } from '../atoms/installedSkills'\nimport { Header } from '../components/Header'\nimport { InstallResults } from '../components/InstallResults'\nimport { MultiSelectPrompt } from '../components/MultiSelectPrompt'\nimport { useInstaller } from '../hooks/useInstaller'\nimport { useSkills } from '../hooks/useSkills'\nimport { ports } from '../ports'\nimport { colors, symbols } from '../theme'\nimport { AgentSelector } from './AgentSelector'\n\nexport function UpdateView({ selectedAgents, onExit }: { selectedAgents?: AgentType[]; onExit: () => void }) {\n const [checkingUpdates, setCheckingUpdates] = useState(false)\n const [updateCheckComplete, setUpdateCheckComplete] = useState(false)\n const [installComplete, setInstallComplete] = useState(false)\n const [internalAgents, setInternalAgents] = useState<AgentType[]>(selectedAgents || [])\n const [showAgentSelect, setShowAgentSelect] = useState(!selectedAgents)\n const [updatableSkills, setUpdatableSkills] = useState<SkillInfo[]>([])\n const { install, progress, results, installing } = useInstaller()\n const installedSkills = useAtomValue(installedSkillsAtom)\n const deprecatedMap = useAtomValue(deprecatedSkillsAtom)\n const { skills, loading: loadingSkills } = useSkills()\n\n const activeAgents = selectedAgents || internalAgents\n\n const installedList = useMemo(() => {\n if (loadingSkills) return []\n const installedNames = new Set(Object.keys(installedSkills))\n\n return skills.filter((s) => {\n if (!installedNames.has(s.name)) return false\n const agents = installedSkills[s.name] || []\n return agents.some((a: AgentType) => activeAgents.includes(a))\n })\n }, [installedSkills, skills, loadingSkills, activeAgents])\n\n const deprecatedInstalled = useMemo(() => {\n if (loadingSkills || !(deprecatedMap instanceof Map) || deprecatedMap.size === 0) return []\n const installedNames = new Set(Object.keys(installedSkills))\n const registryNames = new Set(skills.map((s) => s.name))\n\n const result: { name: string; entry?: DeprecatedEntry }[] = []\n\n for (const name of installedNames) {\n if (deprecatedMap.has(name)) result.push({ name, entry: deprecatedMap.get(name) })\n else if (!registryNames.has(name)) result.push({ name })\n }\n\n return result\n }, [installedSkills, skills, loadingSkills, deprecatedMap])\n\n useEffect(() => {\n if (installedList.length === 0) {\n setCheckingUpdates(false)\n setUpdateCheckComplete(true)\n return\n }\n\n setCheckingUpdates(true)\n const checkUpdates = async () => {\n const installedNames = installedList.map((s) => s.name)\n const { toUpdate } = await getUpdatableSkills(ports, installedNames)\n const skillsToUpdate = installedList.filter((s) => toUpdate.includes(s.name))\n setUpdatableSkills(skillsToUpdate)\n setCheckingUpdates(false)\n setUpdateCheckComplete(true)\n }\n\n checkUpdates()\n }, [installedList])\n\n useInput((_, key) => {\n if (\n key.escape &&\n !installing &&\n !installComplete &&\n !checkingUpdates &&\n updateCheckComplete &&\n updatableSkills.length === 0\n ) {\n onExit()\n }\n })\n\n if (showAgentSelect) {\n return (\n <AgentSelector\n onSelect={(agents) => {\n setInternalAgents(agents)\n setShowAgentSelect(false)\n }}\n onBack={onExit}\n />\n )\n }\n\n const handleUpdate = async (selectedSkills: SkillInfo[]) => {\n if (selectedSkills.length === 0) return\n\n const involvedAgents = new Set<AgentType>()\n selectedSkills.forEach((s) => {\n const agents = installedSkills[s.name] || []\n agents.forEach((a: AgentType) => {\n if (activeAgents.includes(a)) involvedAgents.add(a)\n })\n })\n\n await install(selectedSkills, {\n agents: Array.from(involvedAgents),\n method: 'copy',\n global: false,\n skills: selectedSkills.map((s) => s.name),\n isUpdate: true,\n })\n setInstallComplete(true)\n }\n\n if (installComplete) {\n return (\n <InstallResults results={results} onExit={onExit} title=\"Skills Updated Successfully\" successLabel=\"updated\" />\n )\n }\n\n if (installing) {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box marginTop={1}>\n <Text color={colors.accent}>\n <Spinner type=\"dots\" />{' '}\n </Text>\n <Text>Updating skills...</Text>\n </Box>\n <Box marginTop={1} paddingX={2}>\n <Text color={colors.textDim}>\n {symbols.arrow} {progress.skill} ({progress.current}/{progress.total})\n </Text>\n </Box>\n </Box>\n )\n }\n\n if (loadingSkills || checkingUpdates) {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box marginTop={1}>\n <Text color={colors.accent}>\n <Spinner type=\"dots\" /> {checkingUpdates ? 'Checking for updates...' : 'Loading...'}\n </Text>\n </Box>\n </Box>\n )\n }\n\n if (updateCheckComplete && updatableSkills.length === 0) {\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box borderStyle=\"round\" borderColor={colors.success} paddingX={2} paddingY={1}>\n <Text color={colors.success}>{symbols.check} All installed skills are up to date!</Text>\n </Box>\n\n {deprecatedInstalled.length > 0 && (\n <Box\n flexDirection=\"column\"\n marginTop={1}\n borderStyle=\"round\"\n borderColor={colors.warning}\n paddingX={2}\n paddingY={1}\n >\n <Box marginBottom={1}>\n <Text color={colors.warning} bold>\n {symbols.warning} {deprecatedInstalled.length} deprecated skill\n {deprecatedInstalled.length > 1 ? 's' : ''} detected:\n </Text>\n </Box>\n {deprecatedInstalled.map((d) => (\n <Box key={d.name} flexDirection=\"column\" paddingX={1} marginBottom={1}>\n <Text color={colors.warning}>\n {symbols.arrow} {d.name}\n </Text>\n {d.entry?.message && <Text color={colors.textDim}> {d.entry.message}</Text>}\n {!d.entry && <Text color={colors.textDim}> No longer available in the registry</Text>}\n {d.entry?.alternatives && d.entry.alternatives.length > 0 && (\n <Text color={colors.textDim}>\n {' '}Try: agent-skills install --skill {d.entry.alternatives.join(', ')}\n </Text>\n )}\n </Box>\n ))}\n <Text color={colors.textMuted}>Run: agent-skills remove --skill {'<name>'} to clean up</Text>\n </Box>\n )}\n\n <Box marginTop={1} borderStyle=\"round\" borderColor={colors.border} paddingX={1}>\n <Text>\n <Text color={colors.warning} bold>\n esc\n </Text>\n <Text color={colors.textDim}> exit</Text>\n </Text>\n </Box>\n </Box>\n )\n }\n\n return (\n <UpdateSelector\n skills={updatableSkills}\n installedSkills={installedSkills}\n selectedAgents={activeAgents}\n onUpdate={handleUpdate}\n onExit={onExit}\n />\n )\n}\n\nfunction UpdateSelector({\n skills,\n installedSkills,\n selectedAgents,\n onUpdate,\n onExit,\n}: {\n skills: SkillInfo[]\n installedSkills: Record<string, AgentType[]>\n selectedAgents: AgentType[]\n onUpdate: (skills: SkillInfo[]) => void\n onExit: () => void\n}) {\n const items = skills.map((s) => {\n const allAgents = installedSkills[s.name] || []\n const filteredAgents = allAgents.filter((a) => selectedAgents.includes(a))\n return {\n label: s.name,\n value: s.name,\n hint: `${filteredAgents.length} agent${filteredAgents.length > 1 ? 's' : ''}: ${filteredAgents.join(', ')}`,\n }\n })\n\n const allValues = skills.map((s) => s.name)\n\n const handleSubmit = (selectedNames: string[]) => {\n const selectedSkills = skills.filter((s) => selectedNames.includes(s.name))\n onUpdate(selectedSkills)\n }\n\n return (\n <Box flexDirection=\"column\" paddingX={1}>\n <Header />\n <Box marginBottom={1}>\n <Text bold color={colors.primary}>\n {symbols.diamond} Select skills to update:\n </Text>\n </Box>\n <Box marginBottom={1}>\n <Text color={colors.textDim}>\n {skills.length} installed skill{skills.length > 1 ? 's' : ''} found {symbols.dot} all pre-selected\n </Text>\n </Box>\n <MultiSelectPrompt items={items} initialSelected={allValues} onSubmit={handleSubmit} onCancel={onExit} />\n </Box>\n )\n}\n", "import { Box, Text } from 'ink'\nimport { useAtomValue } from 'jotai'\nimport { useMemo } from 'react'\n\nimport { installedSkillsAtom } from '../atoms/installedSkills'\nimport { Header } from '../components/Header'\nimport { useSkills } from '../hooks/useSkills'\nimport { colors } from '../theme'\nimport { SkillBrowser } from './SkillBrowser'\n\nexport function ListView({ onExit }: { onExit: () => void }) {\n const installedSkills = useAtomValue(installedSkillsAtom)\n const { skills, loading: loadingSkills } = useSkills()\n\n const installedList = useMemo(() => {\n if (loadingSkills) return []\n const installedNames = new Set(Object.keys(installedSkills))\n return skills.filter((s) => installedNames.has(s.name))\n }, [installedSkills, skills, loadingSkills])\n\n if (loadingSkills) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text>Loading...</Text>\n </Box>\n )\n }\n\n if (installedList.length === 0) {\n return (\n <Box flexDirection=\"column\" padding={1}>\n <Header />\n <Text color={colors.warning}>No skills installed.</Text>\n <Text color={colors.textDim}>(Press any key to exit)</Text>\n </Box>\n )\n }\n\n return <SkillBrowser onExit={onExit} readOnly={true} overrideSkills={installedList} />\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["homedir", "platform", "NodeEnvAdapter", "init_node_env_adapter", "__esmMin", "key", "existsSync", "mkdirSync", "readFileSync", "readdirSync", "rmSync", "writeFileSync", "appendFile", "cp", "lstat", "mkdir", "readFile", "readdir", "readlink", "rename", "rm", "symlink", "writeFile", "NodeFileSystemAdapter", "init_node_filesystem_adapter", "__esmMin", "path", "encoding", "content", "options", "oldPath", "newPath", "src", "dest", "target", "linkPath", "type", "_options", "NodeHttpAdapter", "init_node_http_adapter", "__esmMin", "url", "fallbackUrl", "error", "NodeLoggerAdapter", "init_node_logger_adapter", "__esmMin", "message", "defaultPackageLookup", "NodePackageResolverAdapter", "init_node_package_resolver_adapter", "__esmMin", "packageName", "options", "lookup", "resolvePackage", "existsSync", "dirname", "join", "parse", "resolve", "findWorkspaceRoot", "startDir", "existsSyncFn", "fallbackDir", "currentDir", "root", "SKILLS_CATALOG_SEGMENTS", "NodePathsAdapter", "init_node_paths_adapter", "__esmMin", "path", "execSync", "NodeShellAdapter", "init_node_shell_adapter", "__esmMin", "command", "options", "createNodeAdapters", "NodeFileSystemAdapter", "NodeHttpAdapter", "NodeShellAdapter", "NodeEnvAdapter", "NodeLoggerAdapter", "NodePackageResolverAdapter", "NodePathsAdapter", "init_adapters", "__esmMin", "init_node_env_adapter", "init_node_filesystem_adapter", "init_node_http_adapter", "init_node_logger_adapter", "init_node_package_resolver_adapter", "init_node_paths_adapter", "init_node_shell_adapter", "DEFAULT_CATEGORY_ID", "CATEGORY_FOLDER_PATTERN", "CATEGORY_METADATA_FILE", "DEFAULT_CATEGORY", "PACKAGE_NAME", "SKILLS_CATALOG_PACKAGE", "AGENTS_DIR", "CANONICAL_SKILLS_DIR", "LOCK_FILE", "LOCK_FILE_BACKUP", "GLOBAL_CONFIG_DIR", "AUDIT_LOG_FILE", "CACHE_BASE_DIR", "CACHE_NAMESPACE", "SKILLS_SUBDIR", "REGISTRY_CACHE_FILENAME", "SKILL_META_FILE", "REGISTRY_CACHE_TTL_MS", "MAX_CONCURRENT_DOWNLOADS", "init_constants", "__esmMin", "init_env_port", "__esmMin", "init_filesystem_port", "__esmMin", "init_http_port", "__esmMin", "init_logger_port", "__esmMin", "init_package_resolver_port", "__esmMin", "init_paths_port", "__esmMin", "init_shell_port", "__esmMin", "init_ports", "__esmMin", "init_env_port", "init_filesystem_port", "init_http_port", "init_logger_port", "init_package_resolver_port", "init_paths_port", "init_shell_port", "dirname", "join", "parse", "resolve", "sep", "findProjectRoot", "ports", "startDir", "fallbackDir", "currentDir", "root", "cliSuffix", "PROJECT_MARKERS", "marker", "init_project_root_service", "__esmMin", "join", "getAllAgentTypes", "agentDefinitions", "a", "b", "getAgentConfig", "ports", "type", "definition", "context", "createAgentContext", "detectInstalledAgents", "isExtensionInstalled", "init_agents_service", "__esmMin", "init_project_root_service", "home", "projectRoot", "findProjectRoot", "publisher", "name", "extensionsDirs", "dir", "entry", "join", "resolveBaseDir", "ports", "baseDir", "getAuditLogPath", "GLOBAL_CONFIG_DIR", "AUDIT_LOG_FILE", "logAudit", "entry", "resolvedBaseDir", "logPath", "logDir", "logLine", "readAuditLog", "limit", "entries", "line", "init_audit_log_service", "__esmMin", "init_constants", "join", "normalize", "resolve", "sep", "formatCategoryName", "categoryId", "word", "sanitizeName", "name", "isPathSafe", "basePath", "targetPath", "normalizedBase", "normalizedTarget", "init_utils", "__esmMin", "init_constants", "join", "getSkillsDir", "ports", "extractCategoryId", "folderName", "match", "CATEGORY_FOLDER_PATTERN", "isCategoryFolder", "loadCategoryMetadata", "skillsDir", "metadataPath", "CATEGORY_METADATA_FILE", "content", "getCategories", "metadata", "entries", "categories", "index", "entry", "categoryId", "meta", "formatCategoryName", "a", "b", "groupSkillsByCategory", "skills", "categoryIds", "skill", "id", "grouped", "category", "DEFAULT_CATEGORY", "DEFAULT_CATEGORY_ID", "candidate", "targetCategory", "group", "skillList", "sortedGrouped", "sortedCategories", "categorySkills", "init_categories_service", "__esmMin", "init_constants", "init_utils", "join", "getNpmGlobalRoot", "ports", "isGloballyInstalled", "npmGlobalRoot", "packagePath", "PACKAGE_NAME", "init_global_path_service", "__esmMin", "init_constants", "AGENT_TYPES", "init_types", "__esmMin", "dirname", "join", "z", "getSkillLockPath", "ports", "global", "AGENTS_DIR", "LOCK_FILE", "projectRoot", "findProjectRoot", "getBackupPath", "LOCK_FILE_BACKUP", "createEmptyLockFile", "CURRENT_VERSION", "migrateLockFile", "data", "parsed", "SkillLockFileSchema", "key", "entry", "readSkillLock", "lockPath", "content", "writeSkillLock", "lock", "backupPath", "tempPath", "existing", "error", "addSkillToLock", "skillName", "agents", "options", "now", "existingEntry", "existingAgents", "mergedAgents", "removeAgentFromLock", "agent", "updatedAgents", "getSkillFromLock", "AgentTypeSchema", "SkillLockEntrySchema", "init_lockfile_service", "__esmMin", "init_constants", "init_types", "init_project_root_service", "AGENT_TYPES", "createHash", "join", "relative", "getRegistryCachePath", "ports", "getCacheDir", "REGISTRY_CACHE_FILENAME", "isSkillCachedInternal", "skillName", "getSkillCachePath", "ensureCacheDir", "cacheDir", "skillsCacheDir", "SKILLS_SUBDIR", "isCacheValid", "fetchedAt", "REGISTRY_CACHE_TTL_MS", "tryReadCachedRegistry", "cachePath", "content", "saveRegistryToCache", "registry", "payload", "getResolvedCdnRef", "envRef", "cachedCdnRef", "SKILLS_CATALOG_PACKAGE", "error", "computeSkillContentHash", "files", "hash", "file", "buildUrls", "cdnRef", "cdnBase", "fallbackCdnBase", "isPathSafe", "basePath", "targetPath", "resolvedBase", "saveCachedSkillMeta", "meta", "metaPath", "SKILL_META_FILE", "readCachedSkillMeta", "toPosixRelative", "root", "absolutePath", "collectCachedFiles", "dir", "result", "entries", "entry", "absolute", "pruneEmptyDirectories", "pruneOrphanedSkillCacheFiles", "skillCachePath", "keepFiles", "keep", "cachedFiles", "relativePath", "downloadSkillFile", "skill", "filePath", "parentDir", "resolvedRef", "urls", "fileUrl", "fallbackUrl", "response", "fetchRegistry", "forceRefresh", "cached", "versionChanged", "downloadSkill", "downloadedContents", "index", "MAX_CONCURRENT_DOWNLOADS", "batch", "results", "batchIndex", "computedHash", "getRemoteSkills", "getSkillMetadata", "name", "getDeprecatedSkills", "getDeprecatedMap", "deprecated", "needsUpdate", "metadata", "getUpdatableSkills", "names", "toUpdate", "upToDate", "isSkillCached", "ensureSkillDownloaded", "clearCache", "clearSkillCache", "clearRegistryCache", "forceDownloadSkill", "CACHE_BASE_DIR", "CACHE_NAMESPACE", "safeName", "sanitizeName", "getCachedContentHash", "init_registry_service", "__esmMin", "init_constants", "init_utils", "join", "relative", "resolve", "CANONICAL_SKILLS_PATH", "createSymlink", "cleanExistingPath", "copySkillDirectory", "getInstallMode", "createSuccessResult", "createErrorResult", "installHandlers", "validatePath", "installSkillForAgent", "installSkills", "listInstalledSkills", "getCanonicalPath", "removeSkill", "init_installer_service", "__esmMin", "init_constants", "init_utils", "init_agents_service", "init_audit_log_service", "init_global_path_service", "init_lockfile_service", "init_project_root_service", "init_registry_service", "AGENTS_DIR", "CANONICAL_SKILLS_DIR", "ports", "target", "linkPath", "relativePath", "type", "existingTarget", "err", "src", "dest", "method", "global", "ctx", "extras", "error", "canonicalDir", "targetDir", "skillTargetPath", "projectRoot", "isPathSafe", "skill", "agent", "config", "getAgentConfig", "safeSkillName", "sanitizeName", "validationError", "mode", "skills", "options", "findProjectRoot", "results", "result", "addSkillToLock", "getCachedContentHash", "logAudit", "s", "a", "r", "e", "skillName", "baseDir", "canonicalPath", "agents", "lockEntry", "getSkillFromLock", "internalResults", "localPath", "globalPath", "pathsToTry", "removed", "removedLocal", "removedGlobal", "lastError", "path", "isGlobalPath", "agentType", "removeAgentFromLock", "localHasRemainingAgents", "hadLocalRemoval", "success", "stripFrontmatter", "raw", "offset", "lineEnd", "segmentEnd", "contentEnd", "line", "parseMarkdown", "lines", "tokens", "i", "language", "codeLines", "headingMatch", "listMatch", "indent", "init_markdown_parser_service", "__esmMin", "basename", "join", "getCacheKey", "ports", "root", "getCacheEntry", "key", "entry", "cache", "getLocalSkillsDirectory", "detectMode", "localDir", "isLocalMode", "isCategoryFolder", "folderName", "CATEGORY_FOLDER_PATTERN", "extractCategoryId", "parseSkillFrontmatter", "content", "frontmatterMatch", "frontmatter", "nameMatch", "descMatch", "tryReadSkillFromPath", "skillPath", "categoryId", "skillMdPath", "name", "description", "scanLocalSkills", "dirPath", "skill", "discoverLocalSkills", "skillsDir", "DEFAULT_CATEGORY_ID", "discoverSkillsAsync", "getRemoteSkills", "init_skills_provider_service", "__esmMin", "init_constants", "init_utils", "init_registry_service", "updateSkills", "ports", "skillNames", "allResults", "skillName", "freshPath", "forceDownloadSkill", "metadata", "getSkillMetadata", "skillInfo", "global", "entry", "readSkillLock", "results", "installSkills", "init_update_service", "__esmMin", "init_installer_service", "init_lockfile_service", "init_registry_service", "init_services", "__esmMin", "init_agents_service", "init_audit_log_service", "init_categories_service", "init_global_path_service", "init_installer_service", "init_lockfile_service", "init_markdown_parser_service", "init_project_root_service", "init_registry_service", "init_skills_provider_service", "init_update_service", "init_src", "__esmMin", "init_adapters", "init_constants", "init_ports", "init_services", "init_types", "init_utils", "ports", "init_ports", "__esmMin", "init_src", "createNodeAdapters", "install_exports", "__export", "runCliInstall", "chalk", "downloadSkills", "skillNames", "forceDownload", "fetchRegistry", "ports", "allSkills", "getRemoteSkills", "selectedSkills", "skillName", "skill", "s", "path", "forceDownloadSkill", "ensureSkillDownloaded", "showInstallResults", "results", "successful", "failed", "options", "skills", "rawAgents", "invalidAgents", "a", "AGENT_TYPES", "agents", "method", "installOptions", "installSkills", "r", "init_install", "__esmMin", "init_src", "init_ports", "remove_exports", "__export", "runCliRemove", "chalk", "options", "skillNames", "rawAgents", "invalidAgents", "AGENT_TYPES", "agents", "totalSuccess", "totalFailed", "hasLockfileError", "skillName", "results", "removeSkill", "ports", "successful", "r", "failed", "init_remove", "__esmMin", "init_src", "init_ports", "update_exports", "__export", "runCliUpdate", "chalk", "options", "fetchRegistry", "ports", "needsUpdate", "results", "updateSkills", "failed", "r", "lock", "readSkillLock", "installedNames", "toUpdate", "upToDate", "getUpdatableSkills", "successSkills", "failedResults", "noLockfileSkills", "name", "updated", "deprecatedMap", "getDeprecatedMap", "remoteSkills", "getRemoteSkills", "registryNames", "s", "deprecated", "renderers", "entry", "init_update", "__esmMin", "init_src", "init_ports", "cache_exports", "__export", "runCliCache", "chalk", "options", "clearCache", "ports", "clearRegistryCache", "getCacheDir", "init_cache", "__esmMin", "init_src", "init_ports", "Box", "Text", "Fragment", "jsx", "jsxs", "AuditLogViewer", "entries", "limit", "displayEntries", "entry", "idx", "date", "timeAgo", "getTimeAgo", "actionColor", "statusIcon", "seconds", "init_AuditLogViewer", "__esmMin", "audit_exports", "__export", "runCliAudit", "render", "React", "options", "getAuditLogPath", "ports", "limit", "entries", "readAuditLog", "AuditLogViewer", "init_audit", "__esmMin", "init_src", "init_AuditLogViewer", "init_ports", "Command", "render", "React", "Box", "useApp", "useEffect", "useState", "init_src", "init_ports", "useEffect", "useMemo", "useState", "useAgents", "selectedAgents", "setSelectedAgents", "installedAgents", "setInstalledAgents", "loading", "setLoading", "allAgents", "getAllAgentTypes", "timer", "detected", "detectInstalledAgents", "ports", "agent", "prev", "a", "useEffect", "useState", "PACKAGE_NAME", "CONFIG_DIR", "CACHE_FILE", "MESSAGES", "current", "update", "PACKAGE_NAME", "useMemo", "useState", "useFilter", "items", "options", "query", "setQuery", "filtered", "tokens", "t", "item", "searchable", "key", "value", "token", "init_src", "init_ports", "useState", "useInstaller", "progress", "setProgress", "results", "setResults", "installing", "setInstalling", "error", "setError", "skills", "options", "fetchRegistry", "ports", "resolvedSkills", "skill", "path", "forceDownloadSkill", "ensureSkillDownloaded", "res", "installSkills", "err", "useInput", "useCallback", "useRef", "useState", "KONAMI_SEQUENCE", "useKonamiCode", "activated", "setActivated", "bufferRef", "input", "key", "mapped", "k", "i", "reset", "init_src", "init_ports", "useState", "useRemover", "progress", "setProgress", "results", "setResults", "removing", "setRemoving", "error", "setError", "skillName", "agents", "global", "res", "removeSkill", "ports", "prev", "err", "skillsToRemove", "totalOps", "acc", "item", "completedOps", "init_src", "init_ports", "readFileSync", "join", "useEffect", "useState", "useSkillContent", "skillName", "metadata", "setMetadata", "content", "setContent", "loading", "setLoading", "error", "setError", "mounted", "cachePathPromise", "isSkillCached", "ports", "getSkillCachePath", "ensureSkillDownloaded", "meta", "cachePath", "getSkillMetadata", "resolvedPath", "skillMd", "err", "init_src", "init_ports", "useEffect", "useState", "useSkills", "skills", "setSkills", "loading", "setLoading", "error", "setError", "groupedSkills", "setGroupedSkills", "mounted", "data", "discoverSkillsAsync", "ports", "groupSkillsByCategory", "err", "useState", "useWizardStep", "totalSteps", "step", "setStep", "s", "Box", "Text", "BigText", "Gradient", "useEffect", "useState", "Box", "Text", "memo", "colors", "symbols", "jsx", "jsxs", "FooterBar", "memo", "hints", "status", "Box", "colors", "Text", "hint", "i", "symbols", "Box", "Text", "useInput", "useMemo", "useState", "Fragment", "jsx", "jsxs", "SelectPrompt", "items", "onSelect", "onCancel", "initialIndex", "itemLimit", "hideFooter", "footerRight", "selectedIndex", "setSelectedIndex", "useState", "offset", "setOffset", "useInput", "input", "key", "prev", "visibleItems", "useMemo", "Box", "item", "index", "isFocused", "colors", "Text", "symbols", "Box", "Text", "useInput", "useStdout", "useCallback", "useEffect", "useRef", "useState", "jsx", "jsxs", "MAX_WIDTH", "GAME_HEIGHT", "TICK_MS", "BASE_MOVE_EVERY", "RATE_LIMIT_PENALTY", "SNIPER_MULTIPLIER", "LOSE_MESSAGES", "WIN_MESSAGES", "INVADER_ROWS", "createInvaders", "cols", "invaders", "colSpacing", "w", "totalWidth", "startX", "row", "col", "label", "VibeInvaders", "onExit", "stdout", "useStdout", "terminalCols", "gameWidth", "finalMessageRef", "useRef", "state", "setState", "useState", "pool", "useInput", "input", "key", "prev", "newX", "newBullets", "currentRateLimit", "tick", "useCallback", "score", "lives", "gameOver", "flash", "glitch", "rateLimited", "aliveInvaders", "i", "totalInvaders", "survivalRatio", "moveEvery", "shootChance", "pBullets", "b", "eBullets", "inv", "shooters", "inSight", "s", "dir", "xs", "minX", "useEffect", "t", "renderGrid", "rows", "x", "y", "r", "statusColor", "colors", "gridColor", "Box", "Text", "jsx", "jsxs", "menuItems", "SCANLINE", "ArcadeMenu", "onExit", "screen", "setScreen", "useState", "blinkVisible", "setBlinkVisible", "useEffect", "interval", "v", "handleSelect", "value", "VibeInvaders", "Box", "Gradient", "Text", "BigText", "colors", "symbols", "SelectPrompt", "FooterBar", "Box", "Text", "useInput", "Box", "Text", "BigText", "Gradient", "useAtomValue", "useMemo", "init_src", "init_ports", "atom", "unwrap", "mkdir", "readFile", "writeFile", "homedir", "dirname", "join", "getCachePath", "join", "homedir", "CONFIG_DIR", "CACHE_FILE", "validateCache", "cache", "partial", "getCachedUpdate", "cachePath", "content", "readFile", "parsed", "setCachedUpdate", "version", "mkdir", "dirname", "writeFile", "packageJson", "createRequire", "dirname", "join", "fileURLToPath", "__filename", "__dirname", "require", "pkg", "PACKAGE_VERSION", "PACKAGE_DESCRIPTION", "checkForUpdates", "currentVersion", "isPrerelease", "result", "packageJson", "PACKAGE_NAME", "version", "getCurrentVersion", "PACKAGE_VERSION", "resolveUpdateAvailable", "currentVersion", "cached", "getCachedUpdate", "cachedUpdate", "update", "checkForUpdates", "_", "reject", "setCachedUpdate", "runCheck", "getCurrentVersion", "updateAvailable", "isGlobal", "isGloballyInstalled", "ports", "environmentCheckAsyncAtom", "atom", "environmentCheckAtom", "unwrap", "prev", "jsx", "jsxs", "crystalColors", "SEPARATOR_CHAR", "Header", "overrideNotification", "envCheck", "useAtomValue", "environmentCheckAtom", "notification", "useMemo", "updateAvailable", "currentVersion", "isGlobal", "isLoading", "Box", "Text", "symbols", "MESSAGES", "Gradient", "BigText", "PACKAGE_VERSION", "jsx", "jsxs", "ActionSelector", "onSelect", "onBack", "onCredits", "items", "useInput", "input", "creditsHint", "Text", "colors", "Box", "Header", "symbols", "SelectPrompt", "init_src", "Box", "Text", "useInput", "useStdout", "Spinner", "useState", "Box", "Text", "useInput", "useEffect", "useEffect", "useState", "Fragment", "jsx", "AnimatedTransition", "visible", "duration", "children", "opacity", "setOpacity", "startTime", "startOpacity", "targetOpacity", "interval", "elapsed", "progress", "currentOpacity", "clampedOpacity", "jsx", "jsxs", "KeyboardShortcutsOverlay", "visible", "onDismiss", "shortcuts", "useInput", "useEffect", "timer", "mid", "leftColumn", "rightColumn", "KeyBadge", "label", "Box", "Text", "colors", "ShortcutRow", "entry", "divider", "AnimatedTransition", "symbols", "Box", "Text", "useInput", "useEffect", "useRef", "useState", "jsx", "jsxs", "MultiSelectPrompt", "items", "onSubmit", "onCancel", "onChange", "initialSelected", "limit", "selected", "setSelected", "useState", "focusIndex", "setFocusIndex", "offset", "setOffset", "showShortcuts", "setShowShortcuts", "prevInitialSelectedRef", "useRef", "useEffect", "prev", "v", "i", "useInput", "input", "key", "newIndex", "newOffset", "item", "newSelected", "all", "visibleItems", "hasItemsAbove", "hasItemsBelow", "shortcuts", "Box", "KeyboardShortcutsOverlay", "Text", "colors", "symbols", "index", "realIndex", "isFocused", "isSelected", "pointer", "pointerColor", "checkbox", "checkboxColor", "textColor", "FooterBar", "init_ports", "Fragment", "jsx", "jsxs", "CHROME_LINES", "AgentSelector", "onSelect", "onBack", "stdout", "useStdout", "termRows", "listLimit", "allAgents", "installedAgents", "selectedAgents", "setSelectedAgents", "loading", "useAgents", "agentShortcuts", "showShortcuts", "setShowShortcuts", "useState", "useInput", "input", "prev", "items", "agent", "config", "getAgentConfig", "ports", "isDetected", "symbols", "Box", "Header", "Text", "colors", "Spinner", "KeyboardShortcutsOverlay", "FooterBar", "MultiSelectPrompt", "Box", "Text", "useInput", "useStdout", "BigText", "Gradient", "existsSync", "dirname", "join", "fileURLToPath", "useCallback", "useEffect", "useMemo", "useRef", "useState", "execSync", "spawn", "platform", "commandExists", "cmd", "spawnLinuxPlayer", "filePath", "players", "args", "play", "os", "proc", "stop", "ky", "REPO_API", "CONTRIBUTORS_URL", "contributorsCache", "starsCache", "fetchContributors", "login", "isBot", "avatar_url", "contributions", "fetchRepoStars", "jsx", "jsxs", "BASE_SPEED_MS", "CONTENT_WIDTH", "CRYSTAL_COLORS", "HEADER_HEIGHT", "MAX_SPEED_MS", "MIN_SPEED_MS", "SEPARATOR", "SPEED_STEP_MS", "WARM_COLORS", "RANK_DECORATORS", "symbols", "buildCreditLines", "contributors", "stars", "lines", "i", "c", "totalContribs", "sum", "getAssetPath", "dir", "dirname", "fileURLToPath", "candidate", "join", "existsSync", "ContributorRow", "rank", "login", "contributions", "decorator", "nameColor", "rankStr", "name", "contribStr", "badgeSuffix", "usedLen", "dotsLen", "dots", "Text", "CreditLineRenderer", "line", "Gradient", "SpeedIndicator", "speed", "paused", "colors", "level", "bars", "CreditsView", "onExit", "stdout", "useStdout", "termRows", "scrollAreaHeight", "setContributors", "useState", "setStars", "loading", "setLoading", "scrollOffset", "setScrollOffset", "setSpeed", "setPaused", "audioRef", "useRef", "intervalRef", "useEffect", "fetchContributors", "fetchRepoStars", "s", "assetPath", "play", "stop", "creditLines", "useMemo", "maxOffset", "finished", "advance", "useCallback", "prev", "timer", "useInput", "input", "key", "p", "Box", "blankLine", "padTop", "padBottom", "visibleSlice", "BigText", "Box", "Text", "useInput", "useState", "jsx", "jsxs", "InstallConfig", "onConfirm", "onBack", "initialMethod", "initialGlobal", "step", "setStep", "useState", "method", "setMethod", "isGlobal", "setIsGlobal", "Box", "Header", "Text", "colors", "symbols", "SelectPrompt", "val", "InstallSummary", "useInput", "input", "key", "Box", "Text", "useInput", "Spinner", "useAtom", "useAtomValue", "useSetAtom", "useEffect", "useMemo", "useState", "init_src", "init_ports", "atom", "unwrap", "fetchInstalledSkills", "agents", "detectInstalledAgents", "ports", "status", "agent", "local", "global", "listInstalledSkills", "skill", "installedSkillsRefreshAtom", "installedSkillsAsyncAtom", "get", "installedSkillsAtom", "prev", "atom", "selectedAgentsAtom", "selectedSkillsAtom", "Box", "Text", "useInput", "jsx", "jsxs", "InstallResults", "results", "onExit", "title", "successLabel", "useInput", "_", "key", "uniqueSuccessSkills", "r", "uniqueFailedSkills", "successCount", "failCount", "allFailed", "anyFailed", "borderColor", "colors", "displayTitle", "symbols", "titleColor", "Box", "Header", "Text", "res", "i", "Box", "Text", "useInput", "Spinner", "useAtomValue", "useMemo", "useState", "init_src", "init_ports", "atom", "unwrap", "deprecatedSkillsAsyncAtom", "getDeprecatedMap", "ports", "deprecatedSkillsAtom", "prev", "jsx", "jsxs", "RemoveWizard", "selectedAgents", "onExit", "internalAgents", "setInternalAgents", "useState", "removeMultiple", "progress", "results", "useRemover", "installedSkills", "useAtomValue", "installedSkillsAtom", "deprecatedMap", "deprecatedSkillsAtom", "step", "setStep", "selectedToRemove", "setSelectedToRemove", "activeAgents", "filteredSkills", "useMemo", "filtered", "skillName", "agents", "matchingAgents", "a", "skillNames", "selectItems", "name", "isDeprecated", "agentHint", "hint", "useInput", "_", "key", "AgentSelector", "Box", "Header", "colors", "Text", "handleSelect", "selected", "executeRemoval", "targets", "symbols", "MultiSelectPrompt", "s", "SelectPrompt", "val", "Spinner", "successCount", "r", "failCount", "allFailed", "res", "i", "init_src", "Box", "Text", "useInput", "useStdout", "useAtomValue", "useMemo", "useState", "Box", "Text", "useMemo", "formatCategoryBadge", "installed", "total", "jsx", "jsxs", "CategoryHeader", "name", "totalCount", "installedCount", "isExpanded", "isFocused", "badge", "useMemo", "formatCategoryBadge", "chevron", "Box", "Text", "colors", "symbols", "Box", "Text", "useInput", "useState", "jsx", "jsxs", "Box", "Text", "TextInput", "jsx", "jsxs", "SearchInput", "query", "onChange", "total", "filtered", "isLoading", "focus", "Box", "colors", "Text", "TextInput", "Box", "Text", "Box", "Text", "jsx", "jsxs", "badgeConfig", "symbols", "colors", "StatusBadge", "status", "config", "Box", "Text", "jsx", "jsxs", "SkillCard", "name", "description", "status", "selected", "focused", "readOnly", "isInstalled", "checkbox", "symbols", "checkboxColor", "colors", "pointer", "pointerColor", "nameColor", "descColor", "bgColor", "Box", "Text", "StatusBadge", "chalk", "Box", "Text", "useInput", "useStdout", "Spinner", "React", "useCallback", "useEffect", "useMemo", "useRef", "useState", "categoryColors", "getColorForCategory", "categoryId", "init_src", "Fragment", "jsx", "jsxs", "FIXED_HEADER_LINES", "BORDER_LINES", "INDICATOR_LINES", "fmt", "s", "chalk", "colors", "formatInline", "text", "_", "t", "tokensToLines", "tokens", "lines", "token", "sym", "symbols", "colorFn", "indent", "line", "MetadataHeader", "React", "skill", "metadata", "categoryColor", "getColorForCategory", "author", "files", "Box", "Text", "SkillDetailPanel", "expanded", "onClose", "onToggleExpand", "content", "loading", "error", "useSkillContent", "stdout", "useStdout", "scrollOffset", "setScrollOffset", "useState", "terminalRows", "formattedLines", "useMemo", "parseMarkdown", "containerHeight", "scrollAreaHeight", "contentVisibleLines", "maxScroll", "canScroll", "scrollPercent", "maxScrollRef", "useRef", "onCloseRef", "onToggleExpandRef", "handleInput", "useCallback", "input", "key", "prev", "useInput", "useEffect", "hasAbove", "hasMore", "visibleSlice", "Spinner", "getTerminalSize", "canShowDetailPanel", "width", "height", "getTerminalSize", "init_ports", "Fragment", "jsx", "jsxs", "MIN_VISIBLE", "CHROME_LINES", "PANEL_WIDTH_RATIO", "getShortcuts", "readOnly", "common", "exitKey", "SkillBrowser", "onInstall", "onExit", "overrideSkills", "fetchedSkills", "fetching", "error", "useSkills", "stdout", "useStdout", "selectedAgents", "useAtomValue", "selectedAgentsAtom", "installedSkills", "installedSkillsAtom", "deprecatedMap", "deprecatedSkillsAtom", "skills", "loading", "query", "setQuery", "filtered", "useFilter", "selectedSet", "setSelectedSet", "useState", "focusArea", "setFocusArea", "listIndex", "setListIndex", "offset", "setOffset", "showSearch", "setShowSearch", "showShortcuts", "setShowShortcuts", "detailSkill", "setDetailSkill", "drawerExpanded", "setDrawerExpanded", "expandedCategory", "setExpandedCategory", "canShowPanel", "canShowDetailPanel", "terminalRows", "terminalCols", "VISIBLE_ITEMS", "panelWidth", "contentAreaHeight", "isSearchExpanded", "groupedMap", "useMemo", "groupSkillsByCategory", "ports", "isCategoryExpanded", "categoryName", "toggleCategory", "visualList", "list", "category", "categorySkills", "installedCount", "s", "agents", "a", "skill", "handleToggleShortcuts", "prev", "handleEscape", "handleSelectAll", "allSkillNames", "handleSearchNavigation", "key", "handleUpArrow", "newIndex", "handleDownArrow", "handleSpaceKey", "item", "newSet", "handleEnterKey", "selectedSkills", "handleTabOrRightArrow", "isTab", "handleLeftArrow", "isRegularCharacter", "input", "useInput", "visibleWindow", "hasItemsAbove", "hasItemsBelow", "scrollPercent", "showSkillList", "Box", "Header", "Text", "colors", "symbols", "renderSkillListItem", "index", "realIndex", "isFocused", "CategoryHeader", "isSelected", "isInstalled", "status", "SkillCard", "renderScrollIndicator", "direction", "renderFooterHints", "renderFooterStatus", "KeyboardShortcutsOverlay", "SearchInput", "q", "SkillDetailPanel", "FooterBar", "init_src", "Box", "Text", "useInput", "Spinner", "useAtomValue", "useEffect", "useMemo", "useState", "init_ports", "jsx", "jsxs", "UpdateView", "selectedAgents", "onExit", "checkingUpdates", "setCheckingUpdates", "useState", "updateCheckComplete", "setUpdateCheckComplete", "installComplete", "setInstallComplete", "internalAgents", "setInternalAgents", "showAgentSelect", "setShowAgentSelect", "updatableSkills", "setUpdatableSkills", "install", "progress", "results", "installing", "useInstaller", "installedSkills", "useAtomValue", "installedSkillsAtom", "deprecatedMap", "deprecatedSkillsAtom", "skills", "loadingSkills", "useSkills", "activeAgents", "installedList", "useMemo", "installedNames", "s", "a", "deprecatedInstalled", "registryNames", "result", "name", "useEffect", "toUpdate", "getUpdatableSkills", "ports", "skillsToUpdate", "useInput", "_", "key", "AgentSelector", "agents", "handleUpdate", "selectedSkills", "involvedAgents", "InstallResults", "Box", "Header", "Text", "colors", "Spinner", "symbols", "d", "UpdateSelector", "onUpdate", "items", "filteredAgents", "allValues", "handleSubmit", "selectedNames", "MultiSelectPrompt", "jsx", "jsxs", "InstallWizard", "onExit", "step", "next", "back", "useWizardStep", "selectedAgents", "setSelectedAgents", "useAtom", "selectedAgentsAtom", "selectedSkills", "setSelectedSkills", "selectedSkillsAtom", "refreshInstalledSkills", "useSetAtom", "installedSkillsRefreshAtom", "installedSkills", "useAtomValue", "installedSkillsAtom", "action", "setAction", "useState", "showCredits", "setShowCredits", "showUpdate", "setShowUpdate", "showRemove", "setShowRemove", "installConfig", "setInstallConfig", "skills", "useSkills", "install", "progress", "results", "installing", "useInstaller", "installStarted", "setInstallStarted", "installComplete", "setInstallComplete", "handleAgentSelect", "agents", "handleActionSelect", "act", "handleSkillSelect", "handleConfigConfirm", "config", "visibleSkills", "useMemo", "installedOnSelected", "skillName", "a", "s", "useEffect", "prev", "InstallResults", "Box", "Header", "Text", "colors", "Spinner", "symbols", "UpdateView", "RemoveWizard", "CreditsView", "AgentSelector", "ActionSelector", "SkillBrowser", "UpToDateMessage", "InstallConfig", "onBack", "useInput", "input", "key", "Box", "Text", "useAtomValue", "useMemo", "jsx", "jsxs", "ListView", "onExit", "installedSkills", "useAtomValue", "installedSkillsAtom", "skills", "loadingSkills", "useSkills", "installedList", "useMemo", "installedNames", "s", "Box", "Header", "Text", "colors", "SkillBrowser", "jsx", "jsxs", "App", "command", "exit", "useApp", "arcade", "setArcade", "useState", "activated", "reset", "useKonamiCode", "useEffect", "Box", "CreditsView", "ArcadeMenu", "ListView", "RemoveWizard", "UpdateView", "InstallWizard", "program", "Command", "PACKAGE_VERSION", "render", "React", "App", "options", "shouldUseInteractiveMode", "runCliInstall", "runCliRemove", "runCliUpdate", "runCliCache", "runCliAudit", "key"]
7
+ }