skilld 1.2.0 → 1.2.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"detect.mjs","names":["configHome","home","home","home","home","home","configHome","home","agents"],"sources":["../../src/agent/targets/base.ts","../../src/agent/targets/amp.ts","../../src/agent/targets/antigravity.ts","../../src/agent/targets/claude-code.ts","../../src/agent/targets/cline.ts","../../src/agent/targets/codex.ts","../../src/agent/targets/cursor.ts","../../src/agent/targets/gemini-cli.ts","../../src/agent/targets/github-copilot.ts","../../src/agent/targets/goose.ts","../../src/agent/targets/opencode.ts","../../src/agent/targets/roo.ts","../../src/agent/targets/windsurf.ts","../../src/agent/targets/registry.ts","../../src/agent/detect.ts"],"sourcesContent":["/**\n * Shared defaults and factory for agent target definitions.\n * All targets share identical skillFilename, nameMatchesDir, namePattern,\n * and common frontmatter fields from the agentskills.io spec.\n */\n\nimport type { AgentTarget, FrontmatterField } from './types.ts'\n\n/** Common frontmatter fields from agentskills.io spec */\nexport const SPEC_FRONTMATTER: Record<string, FrontmatterField> = {\n 'name': { name: 'name', required: true, description: 'Skill identifier. Must match parent directory name.', constraints: '1-64 chars, lowercase alphanumeric + hyphens' },\n 'description': { name: 'description', required: true, description: 'What the skill does and when to use it.', constraints: '1-1024 chars' },\n 'license': { name: 'license', required: false, description: 'License reference' },\n 'compatibility': { name: 'compatibility', required: false, description: 'Environment requirements', constraints: 'max 500 chars' },\n 'metadata': { name: 'metadata', required: false, description: 'Arbitrary key-value pairs' },\n 'allowed-tools': { name: 'allowed-tools', required: false, description: 'Space-delimited pre-approved tools (experimental)' },\n}\n\n/** Shared defaults for all agent targets */\nconst BASE_DEFAULTS = {\n skillFilename: 'SKILL.md' as const,\n nameMatchesDir: true,\n namePattern: '^[a-z0-9]+(-[a-z0-9]+)*$',\n additionalSkillsDirs: [] as string[],\n extensions: [] as string[],\n notes: [] as string[],\n} satisfies Partial<AgentTarget>\n\ntype DefaultedFields = 'skillFilename' | 'nameMatchesDir' | 'namePattern' | 'additionalSkillsDirs' | 'extensions' | 'notes'\n\n/** Define an agent target with shared defaults applied */\nexport function defineTarget(\n target: Omit<AgentTarget, DefaultedFields> & Partial<Pick<AgentTarget, DefaultedFields>>,\n): AgentTarget {\n return { ...BASE_DEFAULTS, ...target }\n}\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst configHome = process.env.XDG_CONFIG_HOME || join(homedir(), '.config')\n\n/**\n * Amp (Sourcegraph)\n *\n * Uses .agents/skills/ as primary project path. Also reads .claude/skills/.\n * Skills can bundle MCP servers via mcp.json in the skill directory.\n *\n * AGENTS.md (or AGENT.md / CLAUDE.md fallback) for general instructions,\n * supports @-mentions to reference other files and glob-based conditional includes.\n *\n * @see https://ampcode.com/news/agent-skills\n * @see https://ampcode.com/manual\n */\nexport const amp = defineTarget({\n agent: 'amp',\n displayName: 'Amp',\n detectInstalled: () => existsSync(join(configHome, 'amp')),\n detectEnv: () => !!process.env.AMP_SESSION,\n detectProject: cwd => existsSync(join(cwd, '.agents', 'AGENTS.md')),\n instructionFile: 'AGENTS.md',\n\n skillsDir: '.agents/skills',\n globalSkillsDir: join(configHome, 'agents/skills'),\n additionalSkillsDirs: [\n '.claude/skills',\n '~/.config/amp/skills',\n '~/.claude/skills',\n ],\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Unique identifier. Project skills override user-wide ones with same name.' },\n { ...SPEC_FRONTMATTER.description!, description: 'Always visible to the model; determines when skill is invoked.' },\n ],\n\n discoveryStrategy: 'lazy',\n discoveryNotes: 'Names + descriptions visible at startup. Full SKILL.md body loads only when agent decides to invoke based on description match.',\n\n agentSkillsSpec: false,\n extensions: [\n 'mcp.json for bundling MCP server configurations',\n ],\n\n docs: 'https://ampcode.com/news/agent-skills',\n notes: [\n 'Reads .claude/skills/ natively — emitting there covers Claude Code, Cursor, Cline, Copilot, AND Amp.',\n 'Skills can bundle MCP servers via mcp.json in the skill directory.',\n 'AGENTS.md supports @-mentions to reference files (e.g. @doc/style.md, @doc/*.md globs).',\n 'AGENTS.md files with globs frontmatter are conditionally included only when Amp reads matching files.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Antigravity (Google)\n *\n * Agent-first IDE (VS Code fork) powered by Gemini. Skills live in\n * .agent/skills/ (workspace) or ~/.gemini/antigravity/skills/ (global).\n * Uses semantic matching on description to auto-invoke skills.\n *\n * Adopted the Agent Skills open standard (agentskills.io) in Jan 2026.\n * Only `name` and `description` are used for routing; body loads on demand.\n *\n * @see https://antigravity.google/docs/skills\n * @see https://codelabs.developers.google.com/getting-started-with-antigravity-skills\n */\nexport const antigravity = defineTarget({\n agent: 'antigravity',\n displayName: 'Antigravity',\n detectInstalled: () => existsSync(join(home, '.gemini/antigravity')),\n detectEnv: () => !!process.env.ANTIGRAVITY_CLI_ALIAS,\n detectProject: cwd => existsSync(join(cwd, '.agent')),\n instructionFile: 'GEMINI.md',\n\n skillsDir: '.agent/skills',\n globalSkillsDir: join(home, '.gemini/antigravity/skills'),\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Skill identifier. Defaults to directory name if omitted.' },\n { ...SPEC_FRONTMATTER.description!, description: 'Semantic trigger for agent routing. Must be descriptive enough for LLM matching.' },\n ],\n\n discoveryStrategy: 'lazy',\n discoveryNotes: 'Indexes name + description at startup. Full SKILL.md body loads on demand when agent semantic-matches description against user prompt.',\n\n agentSkillsSpec: true,\n\n docs: 'https://antigravity.google/docs/skills',\n notes: [\n 'Only `name` and `description` are used for routing; other frontmatter fields are accepted but not used for matching.',\n 'Skill directories can include scripts/, resources/, and assets/ subdirectories for supporting files.',\n 'GEMINI.md instruction file is shared with Gemini CLI. .agent/rules/*.md for always-on workspace rules.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst claudeHome = process.env.CLAUDE_CONFIG_DIR || join(homedir(), '.claude')\n\n/**\n * Claude Code (Anthropic CLI)\n *\n * Follows the Agent Skills open standard (agentskills.io) plus Claude-specific\n * extensions like `disable-model-invocation`, `user-invocable`, `context`, etc.\n *\n * Skills are discovered at startup — only `name` + `description` are read initially.\n * Full SKILL.md body loads when the agent invokes the skill (via Skill tool or auto-match).\n *\n * @see https://code.claude.com/docs/en/skills\n * @see https://agentskills.io/specification\n */\nexport const claudeCode = defineTarget({\n agent: 'claude-code',\n displayName: 'Claude Code',\n detectInstalled: () => existsSync(claudeHome),\n detectEnv: () => !!(process.env.CLAUDE_CODE || process.env.CLAUDECODE || process.env.CLAUDE_CODE_ENTRYPOINT || process.env.CLAUDE_CONFIG_DIR),\n detectProject: cwd => existsSync(join(cwd, '.claude')) || existsSync(join(cwd, 'CLAUDE.md')),\n cli: 'claude',\n instructionFile: 'CLAUDE.md',\n\n skillsDir: '.claude/skills',\n globalSkillsDir: join(claudeHome, 'skills'),\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, required: false, description: 'Skill identifier, becomes /slash-command. Defaults to directory name if omitted.', constraints: '1-64 chars, ^[a-z0-9]+(-[a-z0-9]+)*$' },\n { ...SPEC_FRONTMATTER.description!, description: 'What the skill does and when to use it. Used for auto-discovery matching.' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER.compatibility!,\n SPEC_FRONTMATTER.metadata!,\n SPEC_FRONTMATTER['allowed-tools']!,\n { name: 'disable-model-invocation', required: false, description: 'When true, skill only loads via explicit /name invocation' },\n { name: 'user-invocable', required: false, description: 'When false, hides from / menu but still auto-loads' },\n { name: 'argument-hint', required: false, description: 'Hint shown during autocomplete, e.g. [issue-number]' },\n { name: 'model', required: false, description: 'Model to use when skill is active' },\n { name: 'context', required: false, description: 'Set to \"fork\" to run in a forked subagent context' },\n { name: 'agent', required: false, description: 'Subagent type when context: fork (e.g. Explore, Plan)' },\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Scans skill dirs at startup, reads name + description only. Full body loads on invocation. Budget: 2% of context window for all skill descriptions.',\n\n agentSkillsSpec: true,\n extensions: [\n 'disable-model-invocation',\n 'user-invocable',\n 'argument-hint',\n 'model',\n 'context',\n 'agent',\n 'hooks',\n '$ARGUMENTS substitution',\n '!`command` dynamic context',\n ],\n\n docs: 'https://code.claude.com/docs/en/skills',\n notes: [\n '`globs` is NOT a valid frontmatter field for skills (only for rules). Unknown fields are silently ignored.',\n '`version` and `generated_by` should go under `metadata` map, not as top-level fields.',\n 'Skill descriptions have a char budget of 2% of context window (~16k chars fallback). Override with SLASH_COMMAND_TOOL_CHAR_BUDGET env var.',\n 'Keep SKILL.md under 500 lines. Move detailed reference to separate files.',\n 'Supports monorepo auto-discovery: nested .claude/skills/ dirs in subdirectories.',\n 'Supporting dirs: scripts/, references/, assets/ alongside SKILL.md.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Cline (VS Code extension)\n *\n * Has TWO systems: Rules (.clinerules/) and Skills (.cline/skills/).\n * We target Skills. Cline also reads .claude/skills/ as a fallback,\n * so emitting to .claude/skills/ covers both Claude Code and Cline.\n *\n * Only `name` and `description` are parsed from frontmatter.\n * All other fields are stripped/ignored.\n *\n * @see https://docs.cline.bot/features/skills\n * @see https://docs.cline.bot/features/cline-rules\n */\nexport const cline = defineTarget({\n agent: 'cline',\n displayName: 'Cline',\n detectInstalled: () => existsSync(join(home, '.cline')),\n detectEnv: () => !!process.env.CLINE_TASK_ID,\n detectProject: cwd => existsSync(join(cwd, '.cline')),\n instructionFile: '.clinerules',\n\n skillsDir: '.cline/skills',\n globalSkillsDir: join(home, '.cline/skills'),\n additionalSkillsDirs: [\n '.clinerules/skills',\n '.claude/skills',\n ],\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Must exactly match the directory name.' },\n { ...SPEC_FRONTMATTER.description!, description: 'When to activate. Used for matching.' },\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'At startup reads name + description from each skill. Full content loads on-demand via use_skill tool. Dozens of skills have near-zero context cost.',\n\n agentSkillsSpec: false,\n\n docs: 'https://docs.cline.bot/features/skills',\n notes: [\n 'Only `name` and `description` are parsed. `version`, `globs`, etc. are silently ignored.',\n 'Cline reads .claude/skills/ as a fallback — emitting there covers both Claude Code and Cline.',\n 'Rules system (.clinerules/) is separate: always-on behavioral constraints with globs/tags frontmatter.',\n 'Global skills override project skills when names conflict.',\n 'Supporting dirs: docs/, scripts/, templates/ alongside SKILL.md.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst codexHome = process.env.CODEX_HOME || join(homedir(), '.codex')\n\n/**\n * OpenAI Codex CLI\n *\n * IMPORTANT: Codex uses `.agents/skills/` for project-level skills,\n * NOT `.codex/skills/`. The `.codex/` directory is for config (config.toml).\n * `~/.codex/skills/` works only as a legacy user-global path.\n *\n * Codex also has AGENTS.md (or AGENTS.override.md) for general instructions,\n * which walks from git root to CWD concatenating found files.\n *\n * @see https://developers.openai.com/codex/skills\n * @see https://developers.openai.com/codex/guides/agents-md/\n */\nexport const codex = defineTarget({\n agent: 'codex',\n displayName: 'Codex',\n detectInstalled: () => existsSync(codexHome),\n detectEnv: () => !!(process.env.CODEX_HOME || process.env.CODEX_SESSION),\n detectProject: cwd => existsSync(join(cwd, '.codex')),\n cli: 'codex',\n instructionFile: 'AGENTS.md',\n\n skillsDir: '.agents/skills',\n globalSkillsDir: join(homedir(), '.agents/skills'),\n additionalSkillsDirs: [\n '~/.codex/skills',\n '/etc/codex/skills',\n ],\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Skill identifier.', constraints: '1-64 chars, ^[a-z0-9-]+$, no leading/trailing/consecutive hyphens' },\n { ...SPEC_FRONTMATTER.description!, description: 'Must include when-to-use criteria. Primary triggering mechanism.', constraints: '1-1024 chars, no angle brackets (< or >)' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER['allowed-tools']!,\n SPEC_FRONTMATTER.metadata!,\n ],\n\n discoveryStrategy: 'lazy',\n discoveryNotes: 'Startup scan reads name + description + optional agents/openai.yaml. Full body loads only on invocation. Supports $1-$9 and $ARGUMENTS placeholders.',\n\n agentSkillsSpec: true,\n extensions: [\n 'agents/openai.yaml (UI metadata + MCP dependencies)',\n '$1-$9 positional argument placeholders',\n 'AGENTS.override.md for temporary overrides',\n ],\n\n docs: 'https://developers.openai.com/codex/skills',\n notes: [\n 'BUG IN CURRENT CODE: skillsDir is .codex/skills/ but should be .agents/skills/. The .codex/ directory is for config, not skills.',\n 'Description field cannot contain angle brackets (< or >).',\n 'Optional agents/openai.yaml provides UI metadata: display_name, icon, brand_color, default_prompt.',\n 'AGENTS.md walks from git root to CWD, concatenating all found files.',\n 'Live reload: detects skill file changes without restart (v0.95.0+).',\n 'Size limit: 32 KiB default (project_doc_max_bytes), configurable in ~/.codex/config.toml.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Cursor (AI code editor)\n *\n * Has TWO systems: Rules (.cursor/rules/*.mdc) and Skills (.cursor/skills/).\n * We target the Skills system which follows the Agent Skills spec.\n *\n * Cursor natively scans .claude/skills/ and .codex/skills/ in addition to\n * its own .cursor/skills/ — so .claude/skills/ output works for both\n * Claude Code and Cursor with zero duplication.\n *\n * @see https://cursor.com/docs/context/skills\n * @see https://cursor.com/docs/context/rules\n */\nexport const cursor = defineTarget({\n agent: 'cursor',\n displayName: 'Cursor',\n detectInstalled: () => existsSync(join(home, '.cursor')),\n detectEnv: () => !!(process.env.CURSOR_SESSION || process.env.CURSOR_TRACE_ID),\n detectProject: cwd => existsSync(join(cwd, '.cursor')) || existsSync(join(cwd, '.cursorrules')),\n instructionFile: '.cursorrules',\n\n skillsDir: '.cursor/skills',\n globalSkillsDir: join(home, '.cursor/skills'),\n additionalSkillsDirs: [\n '.claude/skills',\n '.codex/skills',\n '~/.claude/skills',\n '~/.codex/skills',\n ],\n\n frontmatter: [\n SPEC_FRONTMATTER.name!,\n { ...SPEC_FRONTMATTER.description!, description: 'Agent uses this to decide relevance for auto-invocation.' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER.compatibility!,\n SPEC_FRONTMATTER.metadata!,\n { name: 'disable-model-invocation', required: false, description: 'When true, only loads via explicit /skill-name' },\n ],\n\n discoveryStrategy: 'lazy',\n discoveryNotes: 'Reads name + description at conversation start. Full SKILL.md body loads only when agent determines relevance. Users can also invoke via /skill-name.',\n\n agentSkillsSpec: true,\n extensions: [\n 'disable-model-invocation',\n ],\n\n docs: 'https://cursor.com/docs/context/skills',\n notes: [\n 'Cursor scans .claude/skills/ and .codex/skills/ natively — emitting to .claude/skills/ covers both Claude Code and Cursor.',\n 'The Rules system (.cursor/rules/*.mdc) is separate and uses different frontmatter (trigger, globs, alwaysApply).',\n 'Skills appear in Settings > Rules > Agent Decides section.',\n 'Supporting dirs: scripts/, references/, assets/ alongside SKILL.md.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Google Gemini CLI\n *\n * Follows the Agent Skills open standard (agentskills.io).\n * Skills are activated via `activate_skill` tool with user confirmation.\n *\n * Also has GEMINI.md context files (analogous to CLAUDE.md) which support\n * @file.md import syntax for modular composition.\n *\n * @see https://geminicli.com/docs/cli/skills/\n * @see https://geminicli.com/docs/cli/creating-skills/\n */\nexport const geminiCli = defineTarget({\n agent: 'gemini-cli',\n displayName: 'Gemini CLI',\n detectInstalled: () => existsSync(join(home, '.gemini')),\n detectEnv: () => !!(process.env.GEMINI_API_KEY && process.env.GEMINI_SESSION),\n detectProject: cwd => existsSync(join(cwd, '.gemini')) || existsSync(join(cwd, 'AGENTS.md')),\n cli: 'gemini',\n instructionFile: 'GEMINI.md',\n\n skillsDir: '.gemini/skills',\n globalSkillsDir: join(home, '.gemini/skills'),\n\n frontmatter: [\n SPEC_FRONTMATTER.name!,\n { ...SPEC_FRONTMATTER.description!, description: 'Primary trigger — agent uses this to match tasks.' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER.compatibility!,\n SPEC_FRONTMATTER.metadata!,\n SPEC_FRONTMATTER['allowed-tools']!,\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Scans at session start, injects ~100 tokens per skill (name+description). Activation via activate_skill tool requires user confirmation. Skill stays active for session duration.',\n\n agentSkillsSpec: true,\n\n docs: 'https://geminicli.com/docs/cli/skills/',\n notes: [\n 'Management commands: /skills list, /skills enable <name>, /skills disable <name>, /skills reload.',\n 'GEMINI.md context files are separate from skills — support @file.md import syntax.',\n 'settings.json can configure additional context filenames: [\"AGENTS.md\", \"CONTEXT.md\", \"GEMINI.md\"].',\n 'scripts/, references/, assets/ directories are defined by spec but implementation is still incomplete (issue #15895).',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * GitHub Copilot\n *\n * Has TWO systems: Instructions (.github/instructions/*.instructions.md)\n * and Skills (.github/skills/). We target Skills.\n *\n * Copilot also auto-detects .claude/skills/ as a legacy path,\n * so .claude/skills/ output works for Claude Code, Cursor, Cline, AND Copilot.\n *\n * @see https://docs.github.com/en/copilot/concepts/agents/about-agent-skills\n * @see https://docs.github.com/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot\n */\nexport const githubCopilot = defineTarget({\n agent: 'github-copilot',\n displayName: 'GitHub Copilot',\n detectInstalled: () => existsSync(join(home, '.copilot')),\n detectEnv: () => !!process.env.GITHUB_COPILOT_SESSION,\n detectProject: cwd => existsSync(join(cwd, '.github', 'copilot-instructions.md')),\n instructionFile: '.github/copilot-instructions.md',\n\n skillsDir: '.github/skills',\n globalSkillsDir: join(home, '.copilot/skills'),\n additionalSkillsDirs: [\n '.claude/skills',\n '~/.claude/skills',\n ],\n\n frontmatter: [\n SPEC_FRONTMATTER.name!,\n { ...SPEC_FRONTMATTER.description!, description: 'What the skill does AND when to use it.' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER.compatibility!,\n { ...SPEC_FRONTMATTER.metadata!, description: 'Arbitrary key-value pairs (e.g. version, author)' },\n SPEC_FRONTMATTER['allowed-tools']!,\n ],\n\n discoveryStrategy: 'lazy',\n discoveryNotes: '3-level progressive disclosure: (1) ~100 tokens for name+description, (2) full SKILL.md body <5000 tokens on activation, (3) resources from scripts/references/assets/ on demand.',\n\n agentSkillsSpec: true,\n\n docs: 'https://docs.github.com/en/copilot/concepts/agents/about-agent-skills',\n notes: [\n 'Copilot auto-detects .claude/skills/ as a legacy path — emitting there covers multiple agents.',\n 'Instructions system (.github/instructions/*.instructions.md) is separate, uses applyTo globs.',\n 'copilot-instructions.md at .github/ root is always applied (repo-wide).',\n 'AGENTS.md also recognized as of Aug 2025.',\n 'excludeAgent property in instructions can hide from code-review or coding-agent.',\n 'Keep SKILL.md under 500 lines / 5000 tokens for optimal loading.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst configHome = process.env.XDG_CONFIG_HOME || join(homedir(), '.config')\n\n/**\n * Goose (Block)\n *\n * Scans 6 directories for skills, including .claude/skills/ and .agents/skills/\n * for cross-agent compatibility. Later directories override earlier ones on\n * name conflict.\n *\n * @see https://block.github.io/goose/docs/guides/context-engineering/using-skills/\n */\nexport const goose = defineTarget({\n agent: 'goose',\n displayName: 'Goose',\n detectInstalled: () => existsSync(join(configHome, 'goose')),\n detectEnv: () => !!process.env.GOOSE_SESSION,\n detectProject: cwd => existsSync(join(cwd, '.goose')),\n cli: 'goose',\n instructionFile: '.goosehints',\n\n skillsDir: '.goose/skills',\n globalSkillsDir: join(configHome, 'goose/skills'),\n additionalSkillsDirs: [\n '.claude/skills',\n '.agents/skills',\n '~/.claude/skills',\n '~/.config/agents/skills',\n ],\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Skill identifier.' },\n { ...SPEC_FRONTMATTER.description!, description: 'Brief purpose statement; used for matching.' },\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Scans all 6 directories at startup, merges discovered skills. Later directories override earlier ones on name conflict.',\n\n agentSkillsSpec: false,\n\n docs: 'https://block.github.io/goose/docs/guides/context-engineering/using-skills/',\n notes: [\n 'Reads .claude/skills/ natively — emitting there covers both Claude Code and Goose.',\n 'Also supports .goosehints / .goosehints.local for general project instructions (separate from skills).',\n 'Supporting files alongside SKILL.md (scripts, templates, configs) are accessible.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst configHome = process.env.XDG_CONFIG_HOME || join(homedir(), '.config')\n\n/**\n * OpenCode (SST)\n *\n * Walks from CWD up to git worktree root searching for skill dirs.\n * Reads .claude/skills/ and .agents/skills/ in addition to .opencode/skills/.\n *\n * Has a rich agent system: .opencode/agents/ with per-agent model/tool configuration.\n * Skills can be permission-controlled per-agent with allow/deny/ask + glob patterns.\n *\n * @see https://opencode.ai/docs/skills/\n * @see https://opencode.ai/docs/rules/\n */\nexport const opencode = defineTarget({\n agent: 'opencode',\n displayName: 'OpenCode',\n detectInstalled: () => existsSync(join(configHome, 'opencode')),\n detectEnv: () => !!process.env.OPENCODE_SESSION,\n detectProject: cwd => existsSync(join(cwd, '.opencode')),\n instructionFile: 'AGENTS.md',\n\n skillsDir: '.opencode/skills',\n globalSkillsDir: join(configHome, 'opencode/skills'),\n additionalSkillsDirs: [\n '.claude/skills',\n '.agents/skills',\n '~/.claude/skills',\n '~/.agents/skills',\n ],\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Must match directory name.' },\n { ...SPEC_FRONTMATTER.description!, description: 'Used for matching.' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER.compatibility!,\n SPEC_FRONTMATTER.metadata!,\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Walks from CWD to git worktree root, then loads global definitions. Agents access skills via native skill tool. Skills can be permission-controlled per-agent.',\n\n agentSkillsSpec: true,\n extensions: [\n 'Per-agent skill permissions (allow/deny/ask with glob patterns)',\n ],\n\n docs: 'https://opencode.ai/docs/skills/',\n notes: [\n 'Reads .claude/skills/ and .agents/skills/ natively — emitting to .claude/skills/ covers multiple agents.',\n 'Custom agents in .opencode/agents/ have rich config: model, temperature, tools, permission, color.',\n 'opencode.json supports an instructions field with glob patterns pointing to instruction files.',\n 'AGENTS.md (or CLAUDE.md fallback) for general instructions.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Roo Code (VS Code extension)\n *\n * IMPORTANT: Roo does NOT read .claude/skills/ or .agents/skills/.\n * It requires its own .roo/skills/ directory — no cross-compat shortcuts.\n *\n * Unique feature: mode-specific skill directories (.roo/skills-{modeSlug}/)\n * allow targeting skills to specific modes (code, architect, etc.).\n *\n * @see https://docs.roocode.com/features/skills\n * @see https://docs.roocode.com/features/custom-instructions\n */\nexport const roo = defineTarget({\n agent: 'roo',\n displayName: 'Roo Code',\n detectInstalled: () => existsSync(join(home, '.roo')),\n detectEnv: () => !!process.env.ROO_SESSION,\n detectProject: cwd => existsSync(join(cwd, '.roo')),\n instructionFile: '.roorules',\n\n skillsDir: '.roo/skills',\n globalSkillsDir: join(home, '.roo/skills'),\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Must exactly match the directory name.' },\n { ...SPEC_FRONTMATTER.description!, description: 'When to activate.' },\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Reads all SKILL.md files at startup. File watchers detect changes during session. Uses read_file to load full content on activation.',\n\n agentSkillsSpec: false,\n extensions: [\n 'Mode-specific skill directories: .roo/skills-{modeSlug}/',\n ],\n\n docs: 'https://docs.roocode.com/features/skills',\n notes: [\n 'Does NOT read .claude/skills/ or .agents/skills/ — requires its own .roo/skills/ directory.',\n 'Mode-specific dirs: .roo/skills-code/, .roo/skills-architect/ etc. target specific modes.',\n 'Override priority: project mode-specific > project generic > global mode-specific > global generic.',\n 'Supports symlinks for shared skill libraries across projects.',\n 'Rules system (.roo/rules/) is separate — .md/.txt files loaded alphabetically into system prompt.',\n 'Legacy fallback: .roorules file if .roo/rules/ is empty.',\n 'Skills manageable from Settings panel (v3.46.0+).',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Windsurf (Codeium editor)\n *\n * Has TWO systems: Rules (.windsurf/rules/*.md) and Skills (.windsurf/skills/).\n * We target Skills. Rules have a separate frontmatter schema with trigger/globs.\n *\n * Skills only document `name` and `description` as frontmatter fields.\n * Cascade uses \"progressive disclosure\" for supporting files.\n *\n * @see https://docs.windsurf.com/windsurf/cascade/skills\n * @see https://docs.windsurf.com/windsurf/cascade/memories\n */\nexport const windsurf = defineTarget({\n agent: 'windsurf',\n displayName: 'Windsurf',\n detectInstalled: () => existsSync(join(home, '.codeium/windsurf')),\n detectEnv: () => !!process.env.WINDSURF_SESSION,\n detectProject: cwd => existsSync(join(cwd, '.windsurf')) || existsSync(join(cwd, '.windsurfrules')),\n instructionFile: '.windsurfrules',\n\n skillsDir: '.windsurf/skills',\n globalSkillsDir: join(home, '.codeium/windsurf/skills'),\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Skill identifier.', constraints: 'Lowercase, numbers, hyphens only' },\n { ...SPEC_FRONTMATTER.description!, description: 'Used by Cascade for automatic invocation matching.' },\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Cascade matches description against user requests for auto-invocation. Manual invocation via @skill-name.',\n\n agentSkillsSpec: false,\n\n docs: 'https://docs.windsurf.com/windsurf/cascade/skills',\n notes: [\n 'Only `name` and `description` are documented as frontmatter fields. Other fields may be silently ignored.',\n 'Rules system is separate: .windsurf/rules/*.md with trigger/globs/alwaysApply frontmatter.',\n 'Rules have a 6,000 char per-file limit and 12,000 char total limit. Skills have no documented limit.',\n 'Legacy .windsurfrules at project root still supported but deprecated.',\n 'Supporting files alongside SKILL.md are loaded via progressive disclosure.',\n ],\n})\n","/**\n * Agent targets registry — all supported agents and their skill conventions\n */\n\nimport type { AgentType } from '../types.ts'\nimport type { AgentTarget } from './types.ts'\nimport { amp } from './amp.ts'\nimport { antigravity } from './antigravity.ts'\nimport { claudeCode } from './claude-code.ts'\nimport { cline } from './cline.ts'\nimport { codex } from './codex.ts'\nimport { cursor } from './cursor.ts'\nimport { geminiCli } from './gemini-cli.ts'\nimport { githubCopilot } from './github-copilot.ts'\nimport { goose } from './goose.ts'\nimport { opencode } from './opencode.ts'\nimport { roo } from './roo.ts'\nimport { windsurf } from './windsurf.ts'\n\nexport const targets: Record<AgentType, AgentTarget> = {\n 'claude-code': claudeCode,\n 'cursor': cursor,\n 'windsurf': windsurf,\n 'cline': cline,\n 'codex': codex,\n 'github-copilot': githubCopilot,\n 'gemini-cli': geminiCli,\n 'goose': goose,\n 'amp': amp,\n 'opencode': opencode,\n 'roo': roo,\n 'antigravity': antigravity,\n}\n","/**\n * Agent detection - identify installed and active agents\n */\n\nimport type { AgentType } from './types.ts'\nimport { spawnSync } from 'node:child_process'\nimport { isWindows } from 'std-env'\nimport { agents } from './registry.ts'\n\n/**\n * Detect which agents are installed on the system\n */\nexport function detectInstalledAgents(): AgentType[] {\n return Object.entries(agents)\n .filter(([_, config]) => config.detectInstalled())\n .map(([type]) => type as AgentType)\n}\n\n/**\n * Detect the target agent (where skills are installed) from env vars and cwd.\n * This is NOT the generator LLM — it determines the skills directory.\n *\n * Priority: env vars first (running inside agent), then project dirs.\n * Iteration order of the agents record determines priority.\n */\nexport function detectTargetAgent(): AgentType | null {\n for (const [type, target] of Object.entries(agents)) {\n if (target.detectEnv())\n return type as AgentType\n }\n\n const cwd = process.cwd()\n for (const [type, target] of Object.entries(agents)) {\n if (target.detectProject(cwd))\n return type as AgentType\n }\n\n return null\n}\n\n/**\n * Get the version of an agent's CLI (if available)\n */\nexport function getAgentVersion(agentType: AgentType): string | null {\n const agent = agents[agentType]\n if (!agent.cli)\n return null\n\n try {\n const result = spawnSync(agent.cli, ['--version'], {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n shell: isWindows,\n })\n if (result.status !== 0)\n return null\n const output = (result.stdout || '').trim()\n\n // Extract version number from output\n // Common formats: \"v1.2.3\", \"1.2.3\", \"cli 1.2.3\", \"name v1.2.3\"\n const match = output.match(/v?(\\d+\\.\\d+\\.\\d+(?:-[a-z0-9.]+)?)/)\n return match ? match[1] : output.split('\\n')[0]\n }\n catch {\n return null\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"detect.mjs","names":["configHome","home","home","home","home","home","configHome","home","agents"],"sources":["../../src/agent/targets/base.ts","../../src/agent/targets/amp.ts","../../src/agent/targets/antigravity.ts","../../src/agent/targets/claude-code.ts","../../src/agent/targets/cline.ts","../../src/agent/targets/codex.ts","../../src/agent/targets/cursor.ts","../../src/agent/targets/gemini-cli.ts","../../src/agent/targets/github-copilot.ts","../../src/agent/targets/goose.ts","../../src/agent/targets/opencode.ts","../../src/agent/targets/roo.ts","../../src/agent/targets/windsurf.ts","../../src/agent/targets/registry.ts","../../src/agent/detect.ts"],"sourcesContent":["/**\n * Shared defaults and factory for agent target definitions.\n * All targets share identical skillFilename, nameMatchesDir, namePattern,\n * and common frontmatter fields from the agentskills.io spec.\n */\n\nimport type { AgentTarget, FrontmatterField } from './types.ts'\n\n/** Common frontmatter fields from agentskills.io spec */\nexport const SPEC_FRONTMATTER: Record<string, FrontmatterField> = {\n 'name': { name: 'name', required: true, description: 'Skill identifier. Must match parent directory name.', constraints: '1-64 chars, lowercase alphanumeric + hyphens' },\n 'description': { name: 'description', required: true, description: 'What the skill does and when to use it.', constraints: '1-1024 chars' },\n 'license': { name: 'license', required: false, description: 'License reference' },\n 'compatibility': { name: 'compatibility', required: false, description: 'Environment requirements', constraints: 'max 500 chars' },\n 'metadata': { name: 'metadata', required: false, description: 'Arbitrary key-value pairs' },\n 'allowed-tools': { name: 'allowed-tools', required: false, description: 'Space-delimited pre-approved tools (experimental)' },\n}\n\n/** Shared defaults for all agent targets */\nconst BASE_DEFAULTS = {\n skillFilename: 'SKILL.md' as const,\n nameMatchesDir: true,\n namePattern: '^[a-z0-9]+(-[a-z0-9]+)*$',\n additionalSkillsDirs: [] as string[],\n extensions: [] as string[],\n notes: [] as string[],\n} satisfies Partial<AgentTarget>\n\ntype DefaultedFields = 'skillFilename' | 'nameMatchesDir' | 'namePattern' | 'additionalSkillsDirs' | 'extensions' | 'notes'\n\n/** Define an agent target with shared defaults applied */\nexport function defineTarget(\n target: Omit<AgentTarget, DefaultedFields> & Partial<Pick<AgentTarget, DefaultedFields>>,\n): AgentTarget {\n return { ...BASE_DEFAULTS, ...target }\n}\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst configHome = process.env.XDG_CONFIG_HOME || join(homedir(), '.config')\n\n/**\n * Amp (Sourcegraph)\n *\n * Uses .agents/skills/ as primary project path. Also reads .claude/skills/.\n * Skills can bundle MCP servers via mcp.json in the skill directory.\n *\n * AGENTS.md (or AGENT.md / CLAUDE.md fallback) for general instructions,\n * supports @-mentions to reference other files and glob-based conditional includes.\n *\n * @see https://ampcode.com/news/agent-skills\n * @see https://ampcode.com/manual\n */\nexport const amp = defineTarget({\n agent: 'amp',\n displayName: 'Amp',\n detectInstalled: () => existsSync(join(configHome, 'amp')),\n detectEnv: () => !!process.env.AMP_SESSION,\n detectProject: cwd => existsSync(join(cwd, '.agents', 'AGENTS.md')),\n instructionFile: 'AGENTS.md',\n\n skillsDir: '.agents/skills',\n globalSkillsDir: join(configHome, 'agents/skills'),\n additionalSkillsDirs: [\n '.claude/skills',\n '~/.config/amp/skills',\n '~/.claude/skills',\n ],\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Unique identifier. Project skills override user-wide ones with same name.' },\n { ...SPEC_FRONTMATTER.description!, description: 'Always visible to the model; determines when skill is invoked.' },\n ],\n\n discoveryStrategy: 'lazy',\n discoveryNotes: 'Names + descriptions visible at startup. Full SKILL.md body loads only when agent decides to invoke based on description match.',\n\n agentSkillsSpec: false,\n extensions: [\n 'mcp.json for bundling MCP server configurations',\n ],\n\n docs: 'https://ampcode.com/news/agent-skills',\n notes: [\n 'Reads .claude/skills/ natively — emitting there covers Claude Code, Cursor, Cline, Copilot, AND Amp.',\n 'Skills can bundle MCP servers via mcp.json in the skill directory.',\n 'AGENTS.md supports @-mentions to reference files (e.g. @doc/style.md, @doc/*.md globs).',\n 'AGENTS.md files with globs frontmatter are conditionally included only when Amp reads matching files.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Antigravity (Google)\n *\n * Agent-first IDE (VS Code fork) powered by Gemini. Skills live in\n * .agent/skills/ (workspace) or ~/.gemini/antigravity/skills/ (global).\n * Uses semantic matching on description to auto-invoke skills.\n *\n * Adopted the Agent Skills open standard (agentskills.io) in Jan 2026.\n * Only `name` and `description` are used for routing; body loads on demand.\n *\n * @see https://antigravity.google/docs/skills\n * @see https://codelabs.developers.google.com/getting-started-with-antigravity-skills\n */\nexport const antigravity = defineTarget({\n agent: 'antigravity',\n displayName: 'Antigravity',\n detectInstalled: () => existsSync(join(home, '.gemini/antigravity')),\n detectEnv: () => !!process.env.ANTIGRAVITY_CLI_ALIAS,\n detectProject: cwd => existsSync(join(cwd, '.agent')),\n instructionFile: 'GEMINI.md',\n\n skillsDir: '.agent/skills',\n globalSkillsDir: join(home, '.gemini/antigravity/skills'),\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Skill identifier. Defaults to directory name if omitted.' },\n { ...SPEC_FRONTMATTER.description!, description: 'Semantic trigger for agent routing. Must be descriptive enough for LLM matching.' },\n ],\n\n discoveryStrategy: 'lazy',\n discoveryNotes: 'Indexes name + description at startup. Full SKILL.md body loads on demand when agent semantic-matches description against user prompt.',\n\n agentSkillsSpec: true,\n\n docs: 'https://antigravity.google/docs/skills',\n notes: [\n 'Only `name` and `description` are used for routing; other frontmatter fields are accepted but not used for matching.',\n 'Skill directories can include scripts/, resources/, and assets/ subdirectories for supporting files.',\n 'GEMINI.md instruction file is shared with Gemini CLI. .agent/rules/*.md for always-on workspace rules.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst claudeHome = process.env.CLAUDE_CONFIG_DIR || join(homedir(), '.claude')\n\n/**\n * Claude Code (Anthropic CLI)\n *\n * Follows the Agent Skills open standard (agentskills.io) plus Claude-specific\n * extensions like `disable-model-invocation`, `user-invocable`, `context`, etc.\n *\n * Skills are discovered at startup — only `name` + `description` are read initially.\n * Full SKILL.md body loads when the agent invokes the skill (via Skill tool or auto-match).\n *\n * @see https://code.claude.com/docs/en/skills\n * @see https://agentskills.io/specification\n */\nexport const claudeCode = defineTarget({\n agent: 'claude-code',\n displayName: 'Claude Code',\n detectInstalled: () => existsSync(claudeHome),\n detectEnv: () => !!(process.env.CLAUDE_CODE || process.env.CLAUDECODE || process.env.CLAUDE_CODE_ENTRYPOINT || process.env.CLAUDE_CONFIG_DIR),\n detectProject: cwd => existsSync(join(cwd, '.claude')) || existsSync(join(cwd, 'CLAUDE.md')),\n cli: 'claude',\n instructionFile: 'CLAUDE.md',\n\n skillsDir: '.claude/skills',\n globalSkillsDir: join(claudeHome, 'skills'),\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, required: false, description: 'Skill identifier, becomes /slash-command. Defaults to directory name if omitted.', constraints: '1-64 chars, ^[a-z0-9]+(-[a-z0-9]+)*$' },\n { ...SPEC_FRONTMATTER.description!, description: 'What the skill does and when to use it. Used for auto-discovery matching.' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER.compatibility!,\n SPEC_FRONTMATTER.metadata!,\n SPEC_FRONTMATTER['allowed-tools']!,\n { name: 'disable-model-invocation', required: false, description: 'When true, skill only loads via explicit /name invocation' },\n { name: 'user-invocable', required: false, description: 'When false, hides from / menu but still auto-loads' },\n { name: 'argument-hint', required: false, description: 'Hint shown during autocomplete, e.g. [issue-number]' },\n { name: 'model', required: false, description: 'Model to use when skill is active' },\n { name: 'context', required: false, description: 'Set to \"fork\" to run in a forked subagent context' },\n { name: 'agent', required: false, description: 'Subagent type when context: fork (e.g. Explore, Plan)' },\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Scans skill dirs at startup, reads name + description only. Full body loads on invocation. Budget: 2% of context window for all skill descriptions.',\n\n agentSkillsSpec: true,\n extensions: [\n 'disable-model-invocation',\n 'user-invocable',\n 'argument-hint',\n 'model',\n 'context',\n 'agent',\n 'hooks',\n '$ARGUMENTS substitution',\n '!`command` dynamic context',\n ],\n\n docs: 'https://code.claude.com/docs/en/skills',\n notes: [\n '`globs` is NOT a valid frontmatter field for skills (only for rules). Unknown fields are silently ignored.',\n '`version` and `generated_by` should go under `metadata` map, not as top-level fields.',\n 'Skill descriptions have a char budget of 2% of context window (~16k chars fallback). Override with SLASH_COMMAND_TOOL_CHAR_BUDGET env var.',\n 'Keep SKILL.md under 500 lines. Move detailed reference to separate files.',\n 'Supports monorepo auto-discovery: nested .claude/skills/ dirs in subdirectories.',\n 'Supporting dirs: scripts/, references/, assets/ alongside SKILL.md.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Cline (VS Code extension)\n *\n * Has TWO systems: Rules (.clinerules/) and Skills (.cline/skills/).\n * We target Skills. Cline also reads .claude/skills/ as a fallback,\n * so emitting to .claude/skills/ covers both Claude Code and Cline.\n *\n * Only `name` and `description` are parsed from frontmatter.\n * All other fields are stripped/ignored.\n *\n * @see https://docs.cline.bot/features/skills\n * @see https://docs.cline.bot/features/cline-rules\n */\nexport const cline = defineTarget({\n agent: 'cline',\n displayName: 'Cline',\n detectInstalled: () => existsSync(join(home, '.cline')),\n detectEnv: () => !!(process.env.CLINE_TASK_ID || process.env.CLINE_ACTIVE),\n detectProject: cwd => existsSync(join(cwd, '.cline')),\n instructionFile: '.clinerules',\n\n skillsDir: '.cline/skills',\n globalSkillsDir: join(home, '.cline/skills'),\n additionalSkillsDirs: [\n '.clinerules/skills',\n '.claude/skills',\n ],\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Must exactly match the directory name.' },\n { ...SPEC_FRONTMATTER.description!, description: 'When to activate. Used for matching.' },\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'At startup reads name + description from each skill. Full content loads on-demand via use_skill tool. Dozens of skills have near-zero context cost.',\n\n agentSkillsSpec: false,\n\n docs: 'https://docs.cline.bot/features/skills',\n notes: [\n 'Only `name` and `description` are parsed. `version`, `globs`, etc. are silently ignored.',\n 'Cline reads .claude/skills/ as a fallback — emitting there covers both Claude Code and Cline.',\n 'Rules system (.clinerules/) is separate: always-on behavioral constraints with globs/tags frontmatter.',\n 'Global skills override project skills when names conflict.',\n 'Supporting dirs: docs/, scripts/, templates/ alongside SKILL.md.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst codexHome = process.env.CODEX_HOME || join(homedir(), '.codex')\n\n/**\n * OpenAI Codex CLI\n *\n * IMPORTANT: Codex uses `.agents/skills/` for project-level skills,\n * NOT `.codex/skills/`. The `.codex/` directory is for config (config.toml).\n * `~/.codex/skills/` works only as a legacy user-global path.\n *\n * Codex also has AGENTS.md (or AGENTS.override.md) for general instructions,\n * which walks from git root to CWD concatenating found files.\n *\n * @see https://developers.openai.com/codex/skills\n * @see https://developers.openai.com/codex/guides/agents-md/\n */\nexport const codex = defineTarget({\n agent: 'codex',\n displayName: 'Codex',\n detectInstalled: () => existsSync(codexHome),\n detectEnv: () => !!process.env.CODEX_HOME,\n detectProject: cwd => existsSync(join(cwd, '.codex')),\n cli: 'codex',\n instructionFile: 'AGENTS.md',\n\n skillsDir: '.agents/skills',\n globalSkillsDir: join(homedir(), '.agents/skills'),\n additionalSkillsDirs: [\n '~/.codex/skills',\n '/etc/codex/skills',\n ],\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Skill identifier.', constraints: '1-64 chars, ^[a-z0-9-]+$, no leading/trailing/consecutive hyphens' },\n { ...SPEC_FRONTMATTER.description!, description: 'Must include when-to-use criteria. Primary triggering mechanism.', constraints: '1-1024 chars, no angle brackets (< or >)' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER['allowed-tools']!,\n SPEC_FRONTMATTER.metadata!,\n ],\n\n discoveryStrategy: 'lazy',\n discoveryNotes: 'Startup scan reads name + description + optional agents/openai.yaml. Full body loads only on invocation. Supports $1-$9 and $ARGUMENTS placeholders.',\n\n agentSkillsSpec: true,\n extensions: [\n 'agents/openai.yaml (UI metadata + MCP dependencies)',\n '$1-$9 positional argument placeholders',\n 'AGENTS.override.md for temporary overrides',\n ],\n\n docs: 'https://developers.openai.com/codex/skills',\n notes: [\n 'BUG IN CURRENT CODE: skillsDir is .codex/skills/ but should be .agents/skills/. The .codex/ directory is for config, not skills.',\n 'Description field cannot contain angle brackets (< or >).',\n 'Optional agents/openai.yaml provides UI metadata: display_name, icon, brand_color, default_prompt.',\n 'AGENTS.md walks from git root to CWD, concatenating all found files.',\n 'Live reload: detects skill file changes without restart (v0.95.0+).',\n 'Size limit: 32 KiB default (project_doc_max_bytes), configurable in ~/.codex/config.toml.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Cursor (AI code editor)\n *\n * Has TWO systems: Rules (.cursor/rules/*.mdc) and Skills (.cursor/skills/).\n * We target the Skills system which follows the Agent Skills spec.\n *\n * Cursor natively scans .claude/skills/ and .codex/skills/ in addition to\n * its own .cursor/skills/ — so .claude/skills/ output works for both\n * Claude Code and Cursor with zero duplication.\n *\n * @see https://cursor.com/docs/context/skills\n * @see https://cursor.com/docs/context/rules\n */\nexport const cursor = defineTarget({\n agent: 'cursor',\n displayName: 'Cursor',\n detectInstalled: () => existsSync(join(home, '.cursor')),\n detectEnv: () => !!(process.env.CURSOR_SESSION || process.env.CURSOR_TRACE_ID),\n detectProject: cwd => existsSync(join(cwd, '.cursor')) || existsSync(join(cwd, '.cursorrules')),\n instructionFile: '.cursorrules',\n\n skillsDir: '.cursor/skills',\n globalSkillsDir: join(home, '.cursor/skills'),\n additionalSkillsDirs: [\n '.claude/skills',\n '.codex/skills',\n '~/.claude/skills',\n '~/.codex/skills',\n ],\n\n frontmatter: [\n SPEC_FRONTMATTER.name!,\n { ...SPEC_FRONTMATTER.description!, description: 'Agent uses this to decide relevance for auto-invocation.' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER.compatibility!,\n SPEC_FRONTMATTER.metadata!,\n { name: 'disable-model-invocation', required: false, description: 'When true, only loads via explicit /skill-name' },\n ],\n\n discoveryStrategy: 'lazy',\n discoveryNotes: 'Reads name + description at conversation start. Full SKILL.md body loads only when agent determines relevance. Users can also invoke via /skill-name.',\n\n agentSkillsSpec: true,\n extensions: [\n 'disable-model-invocation',\n ],\n\n docs: 'https://cursor.com/docs/context/skills',\n notes: [\n 'Cursor scans .claude/skills/ and .codex/skills/ natively — emitting to .claude/skills/ covers both Claude Code and Cursor.',\n 'The Rules system (.cursor/rules/*.mdc) is separate and uses different frontmatter (trigger, globs, alwaysApply).',\n 'Skills appear in Settings > Rules > Agent Decides section.',\n 'Supporting dirs: scripts/, references/, assets/ alongside SKILL.md.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Google Gemini CLI\n *\n * Follows the Agent Skills open standard (agentskills.io).\n * Skills are activated via `activate_skill` tool with user confirmation.\n *\n * Also has GEMINI.md context files (analogous to CLAUDE.md) which support\n * @file.md import syntax for modular composition.\n *\n * @see https://geminicli.com/docs/cli/skills/\n * @see https://geminicli.com/docs/cli/creating-skills/\n */\nexport const geminiCli = defineTarget({\n agent: 'gemini-cli',\n displayName: 'Gemini CLI',\n detectInstalled: () => existsSync(join(home, '.gemini')),\n detectEnv: () => !!process.env.GEMINI_CLI,\n detectProject: cwd => existsSync(join(cwd, '.gemini')) || existsSync(join(cwd, 'AGENTS.md')),\n cli: 'gemini',\n instructionFile: 'GEMINI.md',\n\n skillsDir: '.gemini/skills',\n globalSkillsDir: join(home, '.gemini/skills'),\n\n frontmatter: [\n SPEC_FRONTMATTER.name!,\n { ...SPEC_FRONTMATTER.description!, description: 'Primary trigger — agent uses this to match tasks.' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER.compatibility!,\n SPEC_FRONTMATTER.metadata!,\n SPEC_FRONTMATTER['allowed-tools']!,\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Scans at session start, injects ~100 tokens per skill (name+description). Activation via activate_skill tool requires user confirmation. Skill stays active for session duration.',\n\n agentSkillsSpec: true,\n\n docs: 'https://geminicli.com/docs/cli/skills/',\n notes: [\n 'Management commands: /skills list, /skills enable <name>, /skills disable <name>, /skills reload.',\n 'GEMINI.md context files are separate from skills — support @file.md import syntax.',\n 'settings.json can configure additional context filenames: [\"AGENTS.md\", \"CONTEXT.md\", \"GEMINI.md\"].',\n 'scripts/, references/, assets/ directories are defined by spec but implementation is still incomplete (issue #15895).',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * GitHub Copilot\n *\n * Has TWO systems: Instructions (.github/instructions/*.instructions.md)\n * and Skills (.github/skills/). We target Skills.\n *\n * Copilot also auto-detects .claude/skills/ as a legacy path,\n * so .claude/skills/ output works for Claude Code, Cursor, Cline, AND Copilot.\n *\n * @see https://docs.github.com/en/copilot/concepts/agents/about-agent-skills\n * @see https://docs.github.com/copilot/customizing-copilot/adding-custom-instructions-for-github-copilot\n */\nexport const githubCopilot = defineTarget({\n agent: 'github-copilot',\n displayName: 'GitHub Copilot',\n detectInstalled: () => existsSync(join(home, '.copilot')),\n detectEnv: () => !!process.env.COPILOT_RUN_APP,\n detectProject: cwd => existsSync(join(cwd, '.github', 'copilot-instructions.md')),\n instructionFile: '.github/copilot-instructions.md',\n\n skillsDir: '.github/skills',\n globalSkillsDir: join(home, '.copilot/skills'),\n additionalSkillsDirs: [\n '.claude/skills',\n '~/.claude/skills',\n ],\n\n frontmatter: [\n SPEC_FRONTMATTER.name!,\n { ...SPEC_FRONTMATTER.description!, description: 'What the skill does AND when to use it.' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER.compatibility!,\n { ...SPEC_FRONTMATTER.metadata!, description: 'Arbitrary key-value pairs (e.g. version, author)' },\n SPEC_FRONTMATTER['allowed-tools']!,\n ],\n\n discoveryStrategy: 'lazy',\n discoveryNotes: '3-level progressive disclosure: (1) ~100 tokens for name+description, (2) full SKILL.md body <5000 tokens on activation, (3) resources from scripts/references/assets/ on demand.',\n\n agentSkillsSpec: true,\n\n docs: 'https://docs.github.com/en/copilot/concepts/agents/about-agent-skills',\n notes: [\n 'Copilot auto-detects .claude/skills/ as a legacy path — emitting there covers multiple agents.',\n 'Instructions system (.github/instructions/*.instructions.md) is separate, uses applyTo globs.',\n 'copilot-instructions.md at .github/ root is always applied (repo-wide).',\n 'AGENTS.md also recognized as of Aug 2025.',\n 'excludeAgent property in instructions can hide from code-review or coding-agent.',\n 'Keep SKILL.md under 500 lines / 5000 tokens for optimal loading.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst configHome = process.env.XDG_CONFIG_HOME || join(homedir(), '.config')\n\n/**\n * Goose (Block)\n *\n * Scans 6 directories for skills, including .claude/skills/ and .agents/skills/\n * for cross-agent compatibility. Later directories override earlier ones on\n * name conflict.\n *\n * @see https://block.github.io/goose/docs/guides/context-engineering/using-skills/\n */\nexport const goose = defineTarget({\n agent: 'goose',\n displayName: 'Goose',\n detectInstalled: () => existsSync(join(configHome, 'goose')),\n detectEnv: () => !!(process.env.GOOSE_SESSION || process.env.AGENT_SESSION_ID),\n detectProject: cwd => existsSync(join(cwd, '.goose')),\n cli: 'goose',\n instructionFile: '.goosehints',\n\n skillsDir: '.goose/skills',\n globalSkillsDir: join(configHome, 'goose/skills'),\n additionalSkillsDirs: [\n '.claude/skills',\n '.agents/skills',\n '~/.claude/skills',\n '~/.config/agents/skills',\n ],\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Skill identifier.' },\n { ...SPEC_FRONTMATTER.description!, description: 'Brief purpose statement; used for matching.' },\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Scans all 6 directories at startup, merges discovered skills. Later directories override earlier ones on name conflict.',\n\n agentSkillsSpec: false,\n\n docs: 'https://block.github.io/goose/docs/guides/context-engineering/using-skills/',\n notes: [\n 'Reads .claude/skills/ natively — emitting there covers both Claude Code and Goose.',\n 'Also supports .goosehints / .goosehints.local for general project instructions (separate from skills).',\n 'Supporting files alongside SKILL.md (scripts, templates, configs) are accessible.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst configHome = process.env.XDG_CONFIG_HOME || join(homedir(), '.config')\n\n/**\n * OpenCode (SST)\n *\n * Walks from CWD up to git worktree root searching for skill dirs.\n * Reads .claude/skills/ and .agents/skills/ in addition to .opencode/skills/.\n *\n * Has a rich agent system: .opencode/agents/ with per-agent model/tool configuration.\n * Skills can be permission-controlled per-agent with allow/deny/ask + glob patterns.\n *\n * @see https://opencode.ai/docs/skills/\n * @see https://opencode.ai/docs/rules/\n */\nexport const opencode = defineTarget({\n agent: 'opencode',\n displayName: 'OpenCode',\n detectInstalled: () => existsSync(join(configHome, 'opencode')),\n detectEnv: () => !!(process.env.OPENCODE_SESSION || process.env.OPENCODE_SESSION_ID),\n detectProject: cwd => existsSync(join(cwd, '.opencode')),\n instructionFile: 'AGENTS.md',\n\n skillsDir: '.opencode/skills',\n globalSkillsDir: join(configHome, 'opencode/skills'),\n additionalSkillsDirs: [\n '.claude/skills',\n '.agents/skills',\n '~/.claude/skills',\n '~/.agents/skills',\n ],\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Must match directory name.' },\n { ...SPEC_FRONTMATTER.description!, description: 'Used for matching.' },\n SPEC_FRONTMATTER.license!,\n SPEC_FRONTMATTER.compatibility!,\n SPEC_FRONTMATTER.metadata!,\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Walks from CWD to git worktree root, then loads global definitions. Agents access skills via native skill tool. Skills can be permission-controlled per-agent.',\n\n agentSkillsSpec: true,\n extensions: [\n 'Per-agent skill permissions (allow/deny/ask with glob patterns)',\n ],\n\n docs: 'https://opencode.ai/docs/skills/',\n notes: [\n 'Reads .claude/skills/ and .agents/skills/ natively — emitting to .claude/skills/ covers multiple agents.',\n 'Custom agents in .opencode/agents/ have rich config: model, temperature, tools, permission, color.',\n 'opencode.json supports an instructions field with glob patterns pointing to instruction files.',\n 'AGENTS.md (or CLAUDE.md fallback) for general instructions.',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Roo Code (VS Code extension)\n *\n * IMPORTANT: Roo does NOT read .claude/skills/ or .agents/skills/.\n * It requires its own .roo/skills/ directory — no cross-compat shortcuts.\n *\n * Unique feature: mode-specific skill directories (.roo/skills-{modeSlug}/)\n * allow targeting skills to specific modes (code, architect, etc.).\n *\n * @see https://docs.roocode.com/features/skills\n * @see https://docs.roocode.com/features/custom-instructions\n */\nexport const roo = defineTarget({\n agent: 'roo',\n displayName: 'Roo Code',\n detectInstalled: () => existsSync(join(home, '.roo')),\n detectEnv: () => !!process.env.ROO_SESSION,\n detectProject: cwd => existsSync(join(cwd, '.roo')),\n instructionFile: '.roorules',\n\n skillsDir: '.roo/skills',\n globalSkillsDir: join(home, '.roo/skills'),\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Must exactly match the directory name.' },\n { ...SPEC_FRONTMATTER.description!, description: 'When to activate.' },\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Reads all SKILL.md files at startup. File watchers detect changes during session. Uses read_file to load full content on activation.',\n\n agentSkillsSpec: false,\n extensions: [\n 'Mode-specific skill directories: .roo/skills-{modeSlug}/',\n ],\n\n docs: 'https://docs.roocode.com/features/skills',\n notes: [\n 'Does NOT read .claude/skills/ or .agents/skills/ — requires its own .roo/skills/ directory.',\n 'Mode-specific dirs: .roo/skills-code/, .roo/skills-architect/ etc. target specific modes.',\n 'Override priority: project mode-specific > project generic > global mode-specific > global generic.',\n 'Supports symlinks for shared skill libraries across projects.',\n 'Rules system (.roo/rules/) is separate — .md/.txt files loaded alphabetically into system prompt.',\n 'Legacy fallback: .roorules file if .roo/rules/ is empty.',\n 'Skills manageable from Settings panel (v3.46.0+).',\n ],\n})\n","import { existsSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'pathe'\nimport { defineTarget, SPEC_FRONTMATTER } from './base.ts'\n\nconst home = homedir()\n\n/**\n * Windsurf (Codeium editor)\n *\n * Has TWO systems: Rules (.windsurf/rules/*.md) and Skills (.windsurf/skills/).\n * We target Skills. Rules have a separate frontmatter schema with trigger/globs.\n *\n * Skills only document `name` and `description` as frontmatter fields.\n * Cascade uses \"progressive disclosure\" for supporting files.\n *\n * @see https://docs.windsurf.com/windsurf/cascade/skills\n * @see https://docs.windsurf.com/windsurf/cascade/memories\n */\nexport const windsurf = defineTarget({\n agent: 'windsurf',\n displayName: 'Windsurf',\n detectInstalled: () => existsSync(join(home, '.codeium/windsurf')),\n detectEnv: () => !!process.env.WINDSURF_SESSION,\n detectProject: cwd => existsSync(join(cwd, '.windsurf')) || existsSync(join(cwd, '.windsurfrules')),\n instructionFile: '.windsurfrules',\n\n skillsDir: '.windsurf/skills',\n globalSkillsDir: join(home, '.codeium/windsurf/skills'),\n\n frontmatter: [\n { ...SPEC_FRONTMATTER.name!, description: 'Skill identifier.', constraints: 'Lowercase, numbers, hyphens only' },\n { ...SPEC_FRONTMATTER.description!, description: 'Used by Cascade for automatic invocation matching.' },\n ],\n\n discoveryStrategy: 'eager',\n discoveryNotes: 'Cascade matches description against user requests for auto-invocation. Manual invocation via @skill-name.',\n\n agentSkillsSpec: false,\n\n docs: 'https://docs.windsurf.com/windsurf/cascade/skills',\n notes: [\n 'Only `name` and `description` are documented as frontmatter fields. Other fields may be silently ignored.',\n 'Rules system is separate: .windsurf/rules/*.md with trigger/globs/alwaysApply frontmatter.',\n 'Rules have a 6,000 char per-file limit and 12,000 char total limit. Skills have no documented limit.',\n 'Legacy .windsurfrules at project root still supported but deprecated.',\n 'Supporting files alongside SKILL.md are loaded via progressive disclosure.',\n ],\n})\n","/**\n * Agent targets registry — all supported agents and their skill conventions\n */\n\nimport type { AgentType } from '../types.ts'\nimport type { AgentTarget } from './types.ts'\nimport { amp } from './amp.ts'\nimport { antigravity } from './antigravity.ts'\nimport { claudeCode } from './claude-code.ts'\nimport { cline } from './cline.ts'\nimport { codex } from './codex.ts'\nimport { cursor } from './cursor.ts'\nimport { geminiCli } from './gemini-cli.ts'\nimport { githubCopilot } from './github-copilot.ts'\nimport { goose } from './goose.ts'\nimport { opencode } from './opencode.ts'\nimport { roo } from './roo.ts'\nimport { windsurf } from './windsurf.ts'\n\nexport const targets: Record<AgentType, AgentTarget> = {\n 'claude-code': claudeCode,\n 'cursor': cursor,\n 'windsurf': windsurf,\n 'cline': cline,\n 'codex': codex,\n 'github-copilot': githubCopilot,\n 'gemini-cli': geminiCli,\n 'goose': goose,\n 'amp': amp,\n 'opencode': opencode,\n 'roo': roo,\n 'antigravity': antigravity,\n}\n","/**\n * Agent detection - identify installed and active agents\n */\n\nimport type { AgentType } from './types.ts'\nimport { spawnSync } from 'node:child_process'\nimport { isWindows } from 'std-env'\nimport { agents } from './registry.ts'\n\n/**\n * Detect which agents are installed on the system\n */\nexport function detectInstalledAgents(): AgentType[] {\n return Object.entries(agents)\n .filter(([_, config]) => config.detectInstalled())\n .map(([type]) => type as AgentType)\n}\n\n/**\n * Detect the target agent (where skills are installed) from env vars and cwd.\n * This is NOT the generator LLM — it determines the skills directory.\n *\n * Priority: env vars first (running inside agent), then project dirs.\n * Iteration order of the agents record determines priority.\n */\nexport function detectTargetAgent(): AgentType | null {\n for (const [type, target] of Object.entries(agents)) {\n if (target.detectEnv())\n return type as AgentType\n }\n\n const cwd = process.cwd()\n for (const [type, target] of Object.entries(agents)) {\n if (target.detectProject(cwd))\n return type as AgentType\n }\n\n return null\n}\n\n/**\n * Get the version of an agent's CLI (if available)\n */\nexport function getAgentVersion(agentType: AgentType): string | null {\n const agent = agents[agentType]\n if (!agent.cli)\n return null\n\n try {\n const result = spawnSync(agent.cli, ['--version'], {\n encoding: 'utf-8',\n timeout: 3000,\n stdio: ['pipe', 'pipe', 'pipe'],\n shell: isWindows,\n })\n if (result.status !== 0)\n return null\n const output = (result.stdout || '').trim()\n\n // Extract version number from output\n // Common formats: \"v1.2.3\", \"1.2.3\", \"cli 1.2.3\", \"name v1.2.3\"\n const match = output.match(/v?(\\d+\\.\\d+\\.\\d+(?:-[a-z0-9.]+)?)/)\n return match ? match[1] : output.split('\\n')[0]\n }\n catch {\n return null\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index2.d.mts","names":[],"sources":["../../src/sources/blog-releases.ts","../../src/sources/crawl.ts","../../src/sources/discussions.ts","../../src/sources/docs.ts","../../src/sources/entries.ts","../../src/sources/git-skills.ts","../../src/sources/types.ts","../../src/sources/github.ts","../../src/sources/issues.ts","../../src/sources/llms.ts","../../src/sources/npm.ts","../../src/sources/package-registry.ts","../../src/sources/releases.ts","../../src/sources/utils.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index2.d.mts","names":[],"sources":["../../src/sources/blog-releases.ts","../../src/sources/crawl.ts","../../src/sources/discussions.ts","../../src/sources/docs.ts","../../src/sources/entries.ts","../../src/sources/git-skills.ts","../../src/sources/types.ts","../../src/sources/github.ts","../../src/sources/issues.ts","../../src/sources/llms.ts","../../src/sources/npm.ts","../../src/sources/package-registry.ts","../../src/sources/releases.ts","../../src/sources/utils.ts"],"mappings":"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"}
@@ -36,6 +36,9 @@ const SKILL_FM_KEYS = [
36
36
  "ref",
37
37
  "commit"
38
38
  ];
39
+ function isSkillInfoKey(key) {
40
+ return SKILL_FM_KEYS.includes(key);
41
+ }
39
42
  function parseSkillFrontmatter(skillPath) {
40
43
  if (!existsSync(skillPath)) return null;
41
44
  const fm = parseFrontmatter(readFileSync(skillPath, "utf-8"));
@@ -59,7 +62,7 @@ function readLock(skillsDir) {
59
62
  }
60
63
  if (currentSkill && line.startsWith(" ")) {
61
64
  const kv = yamlParseKV(line);
62
- if (kv) skills[currentSkill][kv[0]] = kv[1];
65
+ if (kv && isSkillInfoKey(kv[0])) skills[currentSkill][kv[0]] = kv[1];
63
66
  }
64
67
  }
65
68
  return { skills };
@@ -68,16 +71,7 @@ function serializeLock(lock) {
68
71
  let yaml = "skills:\n";
69
72
  for (const [name, skill] of Object.entries(lock.skills)) {
70
73
  yaml += ` ${name}:\n`;
71
- if (skill.packageName) yaml += ` packageName: ${yamlEscape(skill.packageName)}\n`;
72
- if (skill.version) yaml += ` version: ${yamlEscape(skill.version)}\n`;
73
- if (skill.packages) yaml += ` packages: ${yamlEscape(skill.packages)}\n`;
74
- if (skill.repo) yaml += ` repo: ${yamlEscape(skill.repo)}\n`;
75
- if (skill.source) yaml += ` source: ${yamlEscape(skill.source)}\n`;
76
- if (skill.syncedAt) yaml += ` syncedAt: ${yamlEscape(skill.syncedAt)}\n`;
77
- if (skill.generator) yaml += ` generator: ${yamlEscape(skill.generator)}\n`;
78
- if (skill.path) yaml += ` path: ${yamlEscape(skill.path)}\n`;
79
- if (skill.ref) yaml += ` ref: ${yamlEscape(skill.ref)}\n`;
80
- if (skill.commit) yaml += ` commit: ${yamlEscape(skill.commit)}\n`;
74
+ for (const key of SKILL_FM_KEYS) if (skill[key]) yaml += ` ${key}: ${yamlEscape(skill[key])}\n`;
81
75
  }
82
76
  return yaml;
83
77
  }
@@ -1 +1 @@
1
- {"version":3,"file":"skills.mjs","names":["agents"],"sources":["../../src/core/lockfile.ts","../../src/core/skills.ts"],"sourcesContent":["import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { join } from 'pathe'\nimport { parseFrontmatter } from './markdown.ts'\nimport { yamlEscape, yamlParseKV } from './yaml.ts'\n\nexport interface SkillInfo {\n packageName?: string\n version?: string\n /** All tracked packages as comma-separated \"name@version\" pairs (multi-package skills) */\n packages?: string\n repo?: string\n source?: string\n syncedAt?: string\n generator?: string\n /** Skill path within repo (git-sourced skills) */\n path?: string\n /** Git ref tracked for updates */\n ref?: string\n /** Git commit SHA at install time */\n commit?: string\n}\n\nexport function parsePackages(packages?: string): Array<{ name: string, version: string }> {\n if (!packages)\n return []\n return packages.split(',').map((s) => {\n const trimmed = s.trim()\n const atIdx = trimmed.lastIndexOf('@')\n if (atIdx <= 0)\n return { name: trimmed, version: '' }\n return { name: trimmed.slice(0, atIdx), version: trimmed.slice(atIdx + 1) }\n }).filter(p => p.name)\n}\n\nexport function serializePackages(pkgs: Array<{ name: string, version: string }>): string {\n return pkgs.map(p => `${p.name}@${p.version}`).join(', ')\n}\n\nexport interface SkilldLock {\n skills: Record<string, SkillInfo>\n}\n\nconst SKILL_FM_KEYS: (keyof SkillInfo)[] = ['packageName', 'version', 'packages', 'repo', 'source', 'syncedAt', 'generator', 'path', 'ref', 'commit']\n\nexport function parseSkillFrontmatter(skillPath: string): SkillInfo | null {\n if (!existsSync(skillPath))\n return null\n const content = readFileSync(skillPath, 'utf-8')\n const fm = parseFrontmatter(content)\n if (Object.keys(fm).length === 0)\n return null\n\n const info: SkillInfo = {}\n for (const key of SKILL_FM_KEYS) {\n if (fm[key])\n info[key] = fm[key]\n }\n return info\n}\n\nexport function readLock(skillsDir: string): SkilldLock | null {\n const lockPath = join(skillsDir, 'skilld-lock.yaml')\n if (!existsSync(lockPath))\n return null\n const content = readFileSync(lockPath, 'utf-8')\n\n const skills: Record<string, SkillInfo> = {}\n let currentSkill: string | null = null\n\n for (const line of content.split('\\n')) {\n const skillMatch = line.match(/^ {2}(\\S+):$/)\n if (skillMatch) {\n currentSkill = skillMatch[1]\n skills[currentSkill] = {}\n continue\n }\n if (currentSkill && line.startsWith(' ')) {\n const kv = yamlParseKV(line)\n if (kv)\n (skills[currentSkill] as any)[kv[0]] = kv[1]\n }\n }\n return { skills }\n}\n\nfunction serializeLock(lock: SkilldLock): string {\n let yaml = 'skills:\\n'\n for (const [name, skill] of Object.entries(lock.skills)) {\n yaml += ` ${name}:\\n`\n if (skill.packageName)\n yaml += ` packageName: ${yamlEscape(skill.packageName)}\\n`\n if (skill.version)\n yaml += ` version: ${yamlEscape(skill.version)}\\n`\n if (skill.packages)\n yaml += ` packages: ${yamlEscape(skill.packages)}\\n`\n if (skill.repo)\n yaml += ` repo: ${yamlEscape(skill.repo)}\\n`\n if (skill.source)\n yaml += ` source: ${yamlEscape(skill.source)}\\n`\n if (skill.syncedAt)\n yaml += ` syncedAt: ${yamlEscape(skill.syncedAt)}\\n`\n if (skill.generator)\n yaml += ` generator: ${yamlEscape(skill.generator)}\\n`\n if (skill.path)\n yaml += ` path: ${yamlEscape(skill.path)}\\n`\n if (skill.ref)\n yaml += ` ref: ${yamlEscape(skill.ref)}\\n`\n if (skill.commit)\n yaml += ` commit: ${yamlEscape(skill.commit)}\\n`\n }\n return yaml\n}\n\nexport function writeLock(skillsDir: string, skillName: string, info: SkillInfo): void {\n const lockPath = join(skillsDir, 'skilld-lock.yaml')\n let lock: SkilldLock = { skills: {} }\n if (existsSync(lockPath)) {\n lock = readLock(skillsDir) || { skills: {} }\n }\n\n const existing = lock.skills[skillName]\n if (existing && info.packageName) {\n // Merge packages list\n const existingPkgs = parsePackages(existing.packages)\n // Also include existing primary if not yet in packages list\n if (existing.packageName && !existingPkgs.some(p => p.name === existing.packageName)) {\n existingPkgs.unshift({ name: existing.packageName, version: existing.version || '' })\n }\n // Add/update new package\n const idx = existingPkgs.findIndex(p => p.name === info.packageName)\n if (idx >= 0) {\n existingPkgs[idx]!.version = info.version || ''\n }\n else {\n existingPkgs.push({ name: info.packageName, version: info.version || '' })\n }\n info.packages = serializePackages(existingPkgs)\n // Keep primary as first package\n info.packageName = existingPkgs[0]!.name\n info.version = existingPkgs[0]!.version\n // Preserve fields from existing entry that aren't in new info\n if (!info.repo && existing.repo)\n info.repo = existing.repo\n if (!info.source && existing.source)\n info.source = existing.source\n if (!info.generator && existing.generator)\n info.generator = existing.generator\n }\n\n lock.skills[skillName] = info\n writeFileSync(lockPath, serializeLock(lock))\n}\n\n/**\n * Merge multiple lockfiles, preferring the most recently synced entry per skill.\n */\nexport function mergeLocks(locks: SkilldLock[]): SkilldLock {\n const merged: Record<string, SkillInfo> = {}\n for (const lock of locks) {\n for (const [name, info] of Object.entries(lock.skills)) {\n const existing = merged[name]\n if (!existing || (info.syncedAt && (!existing.syncedAt || info.syncedAt > existing.syncedAt)))\n merged[name] = info\n }\n }\n return { skills: merged }\n}\n\n/**\n * Sync a lockfile to all other dirs that already have a skilld-lock.yaml.\n * Only updates existing lockfiles — does not create new ones.\n */\nexport function syncLockfilesToDirs(sourceLock: SkilldLock, dirs: string[]): void {\n for (const dir of dirs) {\n const lockPath = join(dir, 'skilld-lock.yaml')\n if (!existsSync(lockPath))\n continue\n const existing = readLock(dir)\n if (!existing)\n continue\n // Merge source into existing\n const merged = mergeLocks([existing, sourceLock])\n writeFileSync(lockPath, serializeLock(merged))\n }\n}\n\nexport function removeLockEntry(skillsDir: string, skillName: string): void {\n const lockPath = join(skillsDir, 'skilld-lock.yaml')\n const lock = readLock(skillsDir)\n if (!lock)\n return\n\n delete lock.skills[skillName]\n\n if (Object.keys(lock.skills).length === 0) {\n unlinkSync(lockPath)\n return\n }\n\n writeFileSync(lockPath, serializeLock(lock))\n}\n","import type { AgentType } from '../agent/index.ts'\nimport type { SkillInfo } from './lockfile.ts'\nimport { existsSync, readdirSync } from 'node:fs'\nimport { join } from 'pathe'\nimport { agents } from '../agent/index.ts'\nimport { readLocalDependencies } from '../sources/index.ts'\nimport { parsePackages, parseSkillFrontmatter, readLock } from './lockfile.ts'\nimport { getSharedSkillsDir, semverGt } from './shared.ts'\n\nexport interface SkillEntry {\n name: string\n dir: string\n agent: AgentType\n info: SkillInfo | null\n scope: 'local' | 'global'\n /** Original package name from package.json (e.g., @scope/pkg) */\n packageName?: string\n /** Latest version from package.json deps */\n latestVersion?: string\n}\n\nexport interface ProjectState {\n skills: SkillEntry[]\n deps: Map<string, string>\n missing: string[]\n outdated: SkillEntry[]\n synced: SkillEntry[]\n /** Skills in lockfile but not matched to any local dep */\n unmatched: SkillEntry[]\n}\n\nexport interface IterateSkillsOptions {\n scope?: 'local' | 'global' | 'all'\n agents?: AgentType[]\n cwd?: string\n}\n\nexport function* iterateSkills(opts: IterateSkillsOptions = {}): Generator<SkillEntry> {\n const { scope = 'all', cwd = process.cwd() } = opts\n const agentTypes = opts.agents ?? (Object.keys(agents) as AgentType[])\n\n // When shared dir exists, read local skills from there (avoid duplicates from agent symlinks)\n const sharedDir = getSharedSkillsDir(cwd)\n let yieldedLocal = false\n\n if (sharedDir && (scope === 'local' || scope === 'all')) {\n yieldedLocal = true\n const lock = readLock(sharedDir)\n const entries = readdirSync(sharedDir).filter(f => !f.startsWith('.') && f !== 'skilld-lock.yaml')\n // Use first detected agent as the representative\n const firstAgent = agentTypes[0] ?? (Object.keys(agents) as AgentType[])[0]!\n for (const name of entries) {\n const dir = join(sharedDir, name)\n if (lock?.skills[name]) {\n yield { name, dir, agent: firstAgent, info: lock.skills[name], scope: 'local' }\n }\n else {\n const info = parseSkillFrontmatter(join(dir, '.skilld', '_SKILL.md'))\n if (info?.generator === 'skilld') {\n yield { name, dir, agent: firstAgent, info, scope: 'local' }\n }\n }\n }\n }\n\n for (const agentType of agentTypes) {\n const agent = agents[agentType]\n\n // Local skills (skip if already yielded from shared dir)\n if (!yieldedLocal && (scope === 'local' || scope === 'all')) {\n const localDir = join(cwd, agent.skillsDir)\n if (existsSync(localDir)) {\n const lock = readLock(localDir)\n const entries = readdirSync(localDir).filter(f => !f.startsWith('.') && f !== 'skilld-lock.yaml')\n for (const name of entries) {\n const dir = join(localDir, name)\n // Only track skills in lockfile OR with generator: \"skilld\"\n if (lock?.skills[name]) {\n yield { name, dir, agent: agentType, info: lock.skills[name], scope: 'local' }\n }\n else {\n const info = parseSkillFrontmatter(join(dir, '.skilld', '_SKILL.md'))\n if (info?.generator === 'skilld') {\n yield { name, dir, agent: agentType, info, scope: 'local' }\n }\n }\n }\n }\n }\n\n // Global skills\n if ((scope === 'global' || scope === 'all') && agent.globalSkillsDir) {\n const globalDir = agent.globalSkillsDir\n if (existsSync(globalDir)) {\n const lock = readLock(globalDir)\n const entries = readdirSync(globalDir).filter(f => !f.startsWith('.') && f !== 'skilld-lock.yaml')\n for (const name of entries) {\n const dir = join(globalDir, name)\n // Only track skills in lockfile OR with generator: \"skilld\"\n if (lock?.skills[name]) {\n yield { name, dir, agent: agentType, info: lock.skills[name], scope: 'global' }\n }\n else {\n const info = parseSkillFrontmatter(join(dir, '.skilld', '_SKILL.md'))\n if (info?.generator === 'skilld') {\n yield { name, dir, agent: agentType, info, scope: 'global' }\n }\n }\n }\n }\n }\n }\n}\n\nexport function isOutdated(skill: SkillEntry, depVersion: string): boolean {\n if (!skill.info?.version)\n return true\n\n const depClean = depVersion.replace(/^[\\^~]/, '')\n\n return semverGt(depClean, skill.info.version)\n}\n\nexport async function getProjectState(cwd: string = process.cwd()): Promise<ProjectState> {\n const skills = [...iterateSkills({ scope: 'local', cwd })]\n\n // Get package.json deps\n const localDeps = await readLocalDependencies(cwd).catch(() => [])\n const deps = new Map(localDeps.map(d => [d.name, d.version]))\n\n // Build skill name -> entry map (for lookup by package name)\n const skillByName = new Map(skills.map(s => [s.name, s]))\n\n // Secondary lookup: packageName from lockfile (shipped skills have different names)\n // Also includes all packages from multi-package skills\n const skillByPkgName = new Map<string, SkillEntry>()\n for (const s of skills) {\n if (s.info?.packageName)\n skillByPkgName.set(s.info.packageName, s)\n for (const pkg of parsePackages(s.info?.packages))\n skillByPkgName.set(pkg.name, s)\n }\n\n const missing: string[] = []\n const outdated: SkillEntry[] = []\n const synced: SkillEntry[] = []\n const matchedSkillNames = new Set<string>()\n\n for (const [pkgName, version] of deps) {\n // Normalize package name (e.g., @scope/pkg -> scope-pkg)\n const normalizedName = pkgName.replace(/^@/, '').replace(/\\//g, '-')\n const skill = skillByName.get(`${normalizedName}-skilld`) || skillByName.get(normalizedName) || skillByName.get(pkgName) || skillByPkgName.get(pkgName)\n\n if (!skill) {\n missing.push(pkgName)\n }\n else {\n matchedSkillNames.add(skill.name)\n if (isOutdated(skill, version)) {\n outdated.push({ ...skill, packageName: pkgName, latestVersion: version })\n }\n else {\n synced.push({ ...skill, packageName: pkgName, latestVersion: version })\n }\n }\n }\n\n // Skills in lockfile but not matched to any local dep\n const unmatched = skills.filter(s => !matchedSkillNames.has(s.name))\n\n return { skills, deps, missing, outdated, synced, unmatched }\n}\n\nexport function getSkillsDir(agent: AgentType, scope: 'local' | 'global', cwd: string = process.cwd()): string {\n const agentConfig = agents[agent]\n if (scope === 'global') {\n if (!agentConfig.globalSkillsDir) {\n throw new Error(`Agent ${agent} does not support global skills`)\n }\n return agentConfig.globalSkillsDir\n }\n return getSharedSkillsDir(cwd) || join(cwd, agentConfig.skillsDir)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"skills.mjs","names":["agents"],"sources":["../../src/core/lockfile.ts","../../src/core/skills.ts"],"sourcesContent":["import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs'\nimport { join } from 'pathe'\nimport { parseFrontmatter } from './markdown.ts'\nimport { yamlEscape, yamlParseKV } from './yaml.ts'\n\nexport interface SkillInfo {\n packageName?: string\n version?: string\n /** All tracked packages as comma-separated \"name@version\" pairs (multi-package skills) */\n packages?: string\n repo?: string\n source?: string\n syncedAt?: string\n generator?: string\n /** Skill path within repo (git-sourced skills) */\n path?: string\n /** Git ref tracked for updates */\n ref?: string\n /** Git commit SHA at install time */\n commit?: string\n}\n\nexport function parsePackages(packages?: string): Array<{ name: string, version: string }> {\n if (!packages)\n return []\n return packages.split(',').map((s) => {\n const trimmed = s.trim()\n const atIdx = trimmed.lastIndexOf('@')\n if (atIdx <= 0)\n return { name: trimmed, version: '' }\n return { name: trimmed.slice(0, atIdx), version: trimmed.slice(atIdx + 1) }\n }).filter(p => p.name)\n}\n\nexport function serializePackages(pkgs: Array<{ name: string, version: string }>): string {\n return pkgs.map(p => `${p.name}@${p.version}`).join(', ')\n}\n\nexport interface SkilldLock {\n skills: Record<string, SkillInfo>\n}\n\nconst SKILL_FM_KEYS: (keyof SkillInfo)[] = ['packageName', 'version', 'packages', 'repo', 'source', 'syncedAt', 'generator', 'path', 'ref', 'commit']\n\nfunction isSkillInfoKey(key: string): key is keyof SkillInfo {\n return (SKILL_FM_KEYS as readonly string[]).includes(key)\n}\n\nexport function parseSkillFrontmatter(skillPath: string): SkillInfo | null {\n if (!existsSync(skillPath))\n return null\n const content = readFileSync(skillPath, 'utf-8')\n const fm = parseFrontmatter(content)\n if (Object.keys(fm).length === 0)\n return null\n\n const info: SkillInfo = {}\n for (const key of SKILL_FM_KEYS) {\n if (fm[key])\n info[key] = fm[key]\n }\n return info\n}\n\nexport function readLock(skillsDir: string): SkilldLock | null {\n const lockPath = join(skillsDir, 'skilld-lock.yaml')\n if (!existsSync(lockPath))\n return null\n const content = readFileSync(lockPath, 'utf-8')\n\n const skills: Record<string, SkillInfo> = {}\n let currentSkill: string | null = null\n\n for (const line of content.split('\\n')) {\n const skillMatch = line.match(/^ {2}(\\S+):$/)\n if (skillMatch) {\n currentSkill = skillMatch[1]\n skills[currentSkill] = {}\n continue\n }\n if (currentSkill && line.startsWith(' ')) {\n const kv = yamlParseKV(line)\n if (kv && isSkillInfoKey(kv[0]))\n skills[currentSkill]![kv[0]] = kv[1]\n }\n }\n return { skills }\n}\n\nfunction serializeLock(lock: SkilldLock): string {\n let yaml = 'skills:\\n'\n for (const [name, skill] of Object.entries(lock.skills)) {\n yaml += ` ${name}:\\n`\n for (const key of SKILL_FM_KEYS) {\n if (skill[key])\n yaml += ` ${key}: ${yamlEscape(skill[key])}\\n`\n }\n }\n return yaml\n}\n\nexport function writeLock(skillsDir: string, skillName: string, info: SkillInfo): void {\n const lockPath = join(skillsDir, 'skilld-lock.yaml')\n let lock: SkilldLock = { skills: {} }\n if (existsSync(lockPath)) {\n lock = readLock(skillsDir) || { skills: {} }\n }\n\n const existing = lock.skills[skillName]\n if (existing && info.packageName) {\n // Merge packages list\n const existingPkgs = parsePackages(existing.packages)\n // Also include existing primary if not yet in packages list\n if (existing.packageName && !existingPkgs.some(p => p.name === existing.packageName)) {\n existingPkgs.unshift({ name: existing.packageName, version: existing.version || '' })\n }\n // Add/update new package\n const idx = existingPkgs.findIndex(p => p.name === info.packageName)\n if (idx >= 0) {\n existingPkgs[idx]!.version = info.version || ''\n }\n else {\n existingPkgs.push({ name: info.packageName, version: info.version || '' })\n }\n info.packages = serializePackages(existingPkgs)\n // Keep primary as first package\n info.packageName = existingPkgs[0]!.name\n info.version = existingPkgs[0]!.version\n // Preserve fields from existing entry that aren't in new info\n if (!info.repo && existing.repo)\n info.repo = existing.repo\n if (!info.source && existing.source)\n info.source = existing.source\n if (!info.generator && existing.generator)\n info.generator = existing.generator\n }\n\n lock.skills[skillName] = info\n writeFileSync(lockPath, serializeLock(lock))\n}\n\n/**\n * Merge multiple lockfiles, preferring the most recently synced entry per skill.\n */\nexport function mergeLocks(locks: SkilldLock[]): SkilldLock {\n const merged: Record<string, SkillInfo> = {}\n for (const lock of locks) {\n for (const [name, info] of Object.entries(lock.skills)) {\n const existing = merged[name]\n if (!existing || (info.syncedAt && (!existing.syncedAt || info.syncedAt > existing.syncedAt)))\n merged[name] = info\n }\n }\n return { skills: merged }\n}\n\n/**\n * Sync a lockfile to all other dirs that already have a skilld-lock.yaml.\n * Only updates existing lockfiles — does not create new ones.\n */\nexport function syncLockfilesToDirs(sourceLock: SkilldLock, dirs: string[]): void {\n for (const dir of dirs) {\n const lockPath = join(dir, 'skilld-lock.yaml')\n if (!existsSync(lockPath))\n continue\n const existing = readLock(dir)\n if (!existing)\n continue\n // Merge source into existing\n const merged = mergeLocks([existing, sourceLock])\n writeFileSync(lockPath, serializeLock(merged))\n }\n}\n\nexport function removeLockEntry(skillsDir: string, skillName: string): void {\n const lockPath = join(skillsDir, 'skilld-lock.yaml')\n const lock = readLock(skillsDir)\n if (!lock)\n return\n\n delete lock.skills[skillName]\n\n if (Object.keys(lock.skills).length === 0) {\n unlinkSync(lockPath)\n return\n }\n\n writeFileSync(lockPath, serializeLock(lock))\n}\n","import type { AgentType } from '../agent/index.ts'\nimport type { SkillInfo } from './lockfile.ts'\nimport { existsSync, readdirSync } from 'node:fs'\nimport { join } from 'pathe'\nimport { agents } from '../agent/index.ts'\nimport { readLocalDependencies } from '../sources/index.ts'\nimport { parsePackages, parseSkillFrontmatter, readLock } from './lockfile.ts'\nimport { getSharedSkillsDir, semverGt } from './shared.ts'\n\nexport interface SkillEntry {\n name: string\n dir: string\n agent: AgentType\n info: SkillInfo | null\n scope: 'local' | 'global'\n /** Original package name from package.json (e.g., @scope/pkg) */\n packageName?: string\n /** Latest version from package.json deps */\n latestVersion?: string\n}\n\nexport interface ProjectState {\n skills: SkillEntry[]\n deps: Map<string, string>\n missing: string[]\n outdated: SkillEntry[]\n synced: SkillEntry[]\n /** Skills in lockfile but not matched to any local dep */\n unmatched: SkillEntry[]\n}\n\nexport interface IterateSkillsOptions {\n scope?: 'local' | 'global' | 'all'\n agents?: AgentType[]\n cwd?: string\n}\n\nexport function* iterateSkills(opts: IterateSkillsOptions = {}): Generator<SkillEntry> {\n const { scope = 'all', cwd = process.cwd() } = opts\n const agentTypes = opts.agents ?? (Object.keys(agents) as AgentType[])\n\n // When shared dir exists, read local skills from there (avoid duplicates from agent symlinks)\n const sharedDir = getSharedSkillsDir(cwd)\n let yieldedLocal = false\n\n if (sharedDir && (scope === 'local' || scope === 'all')) {\n yieldedLocal = true\n const lock = readLock(sharedDir)\n const entries = readdirSync(sharedDir).filter(f => !f.startsWith('.') && f !== 'skilld-lock.yaml')\n // Use first detected agent as the representative\n const firstAgent = agentTypes[0] ?? (Object.keys(agents) as AgentType[])[0]!\n for (const name of entries) {\n const dir = join(sharedDir, name)\n if (lock?.skills[name]) {\n yield { name, dir, agent: firstAgent, info: lock.skills[name], scope: 'local' }\n }\n else {\n const info = parseSkillFrontmatter(join(dir, '.skilld', '_SKILL.md'))\n if (info?.generator === 'skilld') {\n yield { name, dir, agent: firstAgent, info, scope: 'local' }\n }\n }\n }\n }\n\n for (const agentType of agentTypes) {\n const agent = agents[agentType]\n\n // Local skills (skip if already yielded from shared dir)\n if (!yieldedLocal && (scope === 'local' || scope === 'all')) {\n const localDir = join(cwd, agent.skillsDir)\n if (existsSync(localDir)) {\n const lock = readLock(localDir)\n const entries = readdirSync(localDir).filter(f => !f.startsWith('.') && f !== 'skilld-lock.yaml')\n for (const name of entries) {\n const dir = join(localDir, name)\n // Only track skills in lockfile OR with generator: \"skilld\"\n if (lock?.skills[name]) {\n yield { name, dir, agent: agentType, info: lock.skills[name], scope: 'local' }\n }\n else {\n const info = parseSkillFrontmatter(join(dir, '.skilld', '_SKILL.md'))\n if (info?.generator === 'skilld') {\n yield { name, dir, agent: agentType, info, scope: 'local' }\n }\n }\n }\n }\n }\n\n // Global skills\n if ((scope === 'global' || scope === 'all') && agent.globalSkillsDir) {\n const globalDir = agent.globalSkillsDir\n if (existsSync(globalDir)) {\n const lock = readLock(globalDir)\n const entries = readdirSync(globalDir).filter(f => !f.startsWith('.') && f !== 'skilld-lock.yaml')\n for (const name of entries) {\n const dir = join(globalDir, name)\n // Only track skills in lockfile OR with generator: \"skilld\"\n if (lock?.skills[name]) {\n yield { name, dir, agent: agentType, info: lock.skills[name], scope: 'global' }\n }\n else {\n const info = parseSkillFrontmatter(join(dir, '.skilld', '_SKILL.md'))\n if (info?.generator === 'skilld') {\n yield { name, dir, agent: agentType, info, scope: 'global' }\n }\n }\n }\n }\n }\n }\n}\n\nexport function isOutdated(skill: SkillEntry, depVersion: string): boolean {\n if (!skill.info?.version)\n return true\n\n const depClean = depVersion.replace(/^[\\^~]/, '')\n\n return semverGt(depClean, skill.info.version)\n}\n\nexport async function getProjectState(cwd: string = process.cwd()): Promise<ProjectState> {\n const skills = [...iterateSkills({ scope: 'local', cwd })]\n\n // Get package.json deps\n const localDeps = await readLocalDependencies(cwd).catch(() => [])\n const deps = new Map(localDeps.map(d => [d.name, d.version]))\n\n // Build skill name -> entry map (for lookup by package name)\n const skillByName = new Map(skills.map(s => [s.name, s]))\n\n // Secondary lookup: packageName from lockfile (shipped skills have different names)\n // Also includes all packages from multi-package skills\n const skillByPkgName = new Map<string, SkillEntry>()\n for (const s of skills) {\n if (s.info?.packageName)\n skillByPkgName.set(s.info.packageName, s)\n for (const pkg of parsePackages(s.info?.packages))\n skillByPkgName.set(pkg.name, s)\n }\n\n const missing: string[] = []\n const outdated: SkillEntry[] = []\n const synced: SkillEntry[] = []\n const matchedSkillNames = new Set<string>()\n\n for (const [pkgName, version] of deps) {\n // Normalize package name (e.g., @scope/pkg -> scope-pkg)\n const normalizedName = pkgName.replace(/^@/, '').replace(/\\//g, '-')\n const skill = skillByName.get(`${normalizedName}-skilld`) || skillByName.get(normalizedName) || skillByName.get(pkgName) || skillByPkgName.get(pkgName)\n\n if (!skill) {\n missing.push(pkgName)\n }\n else {\n matchedSkillNames.add(skill.name)\n if (isOutdated(skill, version)) {\n outdated.push({ ...skill, packageName: pkgName, latestVersion: version })\n }\n else {\n synced.push({ ...skill, packageName: pkgName, latestVersion: version })\n }\n }\n }\n\n // Skills in lockfile but not matched to any local dep\n const unmatched = skills.filter(s => !matchedSkillNames.has(s.name))\n\n return { skills, deps, missing, outdated, synced, unmatched }\n}\n\nexport function getSkillsDir(agent: AgentType, scope: 'local' | 'global', cwd: string = process.cwd()): string {\n const agentConfig = agents[agent]\n if (scope === 'global') {\n if (!agentConfig.globalSkillsDir) {\n throw new Error(`Agent ${agent} does not support global skills`)\n }\n return agentConfig.globalSkillsDir\n }\n return getSharedSkillsDir(cwd) || join(cwd, agentConfig.skillsDir)\n}\n"],"mappings":"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"}
@@ -34,6 +34,35 @@ function buildFrontmatter(fields) {
34
34
  lines.push("---");
35
35
  return lines.join("\n");
36
36
  }
37
+ /** Check if body contains a code block */
38
+ function hasCodeBlock(text) {
39
+ return /```[\s\S]*?```/.test(text) || /`[^`]+`/.test(text);
40
+ }
41
+ /** Noise patterns in comments — filter these out */
42
+ const COMMENT_NOISE_RE = /^(?:\+1|👍|same here|any update|bump|following|is there any progress|when will this|me too|i have the same|same issue|thanks|thank you)[\s!?.]*$/i;
43
+ /**
44
+ * Smart body truncation — preserves code blocks and error messages.
45
+ * Instead of slicing at a char limit, finds a safe break point.
46
+ */
47
+ function truncateBody(body, limit) {
48
+ if (body.length <= limit) return body;
49
+ const codeBlockRe = /```[\s\S]*?```/g;
50
+ let lastSafeEnd = limit;
51
+ let match;
52
+ while ((match = codeBlockRe.exec(body)) !== null) {
53
+ const blockStart = match.index;
54
+ const blockEnd = blockStart + match[0].length;
55
+ if (blockStart < limit && blockEnd > limit) {
56
+ if (blockEnd <= limit + 500) lastSafeEnd = blockEnd;
57
+ else lastSafeEnd = blockStart;
58
+ break;
59
+ }
60
+ }
61
+ const slice = body.slice(0, lastSafeEnd);
62
+ const lastParagraph = slice.lastIndexOf("\n\n");
63
+ if (lastParagraph > lastSafeEnd * .6) return `${slice.slice(0, lastParagraph)}\n\n...`;
64
+ return `${slice}...`;
65
+ }
37
66
  let _ghToken;
38
67
  /**
39
68
  * Get GitHub auth token from gh CLI (cached).
@@ -767,10 +796,6 @@ function isNoiseIssue(issue) {
767
796
  if (issue.title.startsWith("☂️") || issue.title.startsWith("[META]") || issue.title.startsWith("[Tracking]")) return true;
768
797
  return false;
769
798
  }
770
- /** Check if body contains a code block */
771
- function hasCodeBlock$1(text) {
772
- return /```[\s\S]*?```/.test(text) || /`[^`]+`/.test(text);
773
- }
774
799
  /**
775
800
  * Detect non-technical issues: fan mail, showcases, sentiment.
776
801
  * Short body + no code + high reactions = likely non-technical.
@@ -778,8 +803,8 @@ function hasCodeBlock$1(text) {
778
803
  */
779
804
  function isNonTechnical(issue) {
780
805
  const body = (issue.body || "").trim();
781
- if (body.length < 200 && !hasCodeBlock$1(body) && issue.reactions > 50) return true;
782
- if (/\b(?:love|thank|awesome|great work)\b/i.test(issue.title) && !hasCodeBlock$1(body)) return true;
806
+ if (body.length < 200 && !hasCodeBlock(body) && issue.reactions > 50) return true;
807
+ if (/\b(?:love|thank|awesome|great work)\b/i.test(issue.title) && !hasCodeBlock(body)) return true;
783
808
  return false;
784
809
  }
785
810
  /**
@@ -836,29 +861,6 @@ function bodyLimit(reactions) {
836
861
  return 800;
837
862
  }
838
863
  /**
839
- * Smart body truncation — preserves code blocks and error messages.
840
- * Instead of slicing at a char limit, finds a safe break point.
841
- */
842
- function truncateBody$1(body, limit) {
843
- if (body.length <= limit) return body;
844
- const codeBlockRe = /```[\s\S]*?```/g;
845
- let lastSafeEnd = limit;
846
- let match;
847
- while ((match = codeBlockRe.exec(body)) !== null) {
848
- const blockStart = match.index;
849
- const blockEnd = blockStart + match[0].length;
850
- if (blockStart < limit && blockEnd > limit) {
851
- if (blockEnd <= limit + 500) lastSafeEnd = blockEnd;
852
- else lastSafeEnd = blockStart;
853
- break;
854
- }
855
- }
856
- const slice = body.slice(0, lastSafeEnd);
857
- const lastParagraph = slice.lastIndexOf("\n\n");
858
- if (lastParagraph > lastSafeEnd * .6) return `${slice.slice(0, lastParagraph)}\n\n...`;
859
- return `${slice}...`;
860
- }
861
- /**
862
864
  * Fetch issues for a state using GitHub Search API sorted by reactions
863
865
  */
864
866
  function fetchIssuesByState(owner, repo, state, count, releasedAt, fromDate) {
@@ -905,8 +907,6 @@ function oneYearAgo() {
905
907
  d.setFullYear(d.getFullYear() - 1);
906
908
  return isoDate(d.toISOString());
907
909
  }
908
- /** Noise patterns in comments — filter these out */
909
- const COMMENT_NOISE_RE$1 = /^(?:\+1|👍|same here|any update|bump|following|is there any progress|when will this|me too|i have the same|same issue)[\s!?.]*$/i;
910
910
  /**
911
911
  * Batch-fetch top comments for issues via GraphQL.
912
912
  * Enriches the top N highest-score issues with their best comments.
@@ -938,7 +938,7 @@ function enrichWithComments(owner, repo, issues, topN = 15) {
938
938
  const nodes = repo_[`i${i}`]?.comments?.nodes;
939
939
  if (!Array.isArray(nodes)) continue;
940
940
  const issue = worth[i];
941
- const comments = nodes.filter((c) => c.author && !BOT_USERS.has(c.author.login)).filter((c) => !COMMENT_NOISE_RE$1.test((c.body || "").trim())).map((c) => {
941
+ const comments = nodes.filter((c) => c.author && !BOT_USERS.has(c.author.login)).filter((c) => !COMMENT_NOISE_RE.test((c.body || "").trim())).map((c) => {
942
942
  const isMaintainer = [
943
943
  "OWNER",
944
944
  "MEMBER",
@@ -946,7 +946,7 @@ function enrichWithComments(owner, repo, issues, topN = 15) {
946
946
  ].includes(c.authorAssociation);
947
947
  const body = c.body || "";
948
948
  const reactions = c.reactions?.totalCount || 0;
949
- const _score = (isMaintainer ? 3 : 1) * (hasCodeBlock$1(body) ? 2 : 1) * (1 + reactions);
949
+ const _score = (isMaintainer ? 3 : 1) * (hasCodeBlock(body) ? 2 : 1) * (1 + reactions);
950
950
  return {
951
951
  body,
952
952
  author: c.author.login,
@@ -1017,7 +1017,7 @@ function formatIssueAsMarkdown(issue) {
1017
1017
  `# ${issue.title}`
1018
1018
  ];
1019
1019
  if (issue.body) {
1020
- const body = truncateBody$1(issue.body, limit);
1020
+ const body = truncateBody(issue.body, limit);
1021
1021
  lines.push("", body);
1022
1022
  }
1023
1023
  if (issue.topComments.length > 0) {
@@ -1025,7 +1025,7 @@ function formatIssueAsMarkdown(issue) {
1025
1025
  for (const c of issue.topComments) {
1026
1026
  const reactions = c.reactions > 0 ? ` (+${c.reactions})` : "";
1027
1027
  const maintainer = c.isMaintainer ? " [maintainer]" : "";
1028
- const commentBody = truncateBody$1(c.body, 600);
1028
+ const commentBody = truncateBody(c.body, 600);
1029
1029
  lines.push("", `**@${c.author}**${maintainer}${reactions}:`, "", commentBody);
1030
1030
  }
1031
1031
  }
@@ -1098,35 +1098,6 @@ const LOW_VALUE_CATEGORIES = new Set([
1098
1098
  "ideas",
1099
1099
  "polls"
1100
1100
  ]);
1101
- /** Noise patterns in comments — filter these out */
1102
- const COMMENT_NOISE_RE = /^(?:\+1|👍|same here|any update|bump|following|is there any progress|when will this|me too|i have the same|same issue|thanks|thank you)[\s!?.]*$/i;
1103
- /** Check if body contains a code block */
1104
- function hasCodeBlock(text) {
1105
- return /```[\s\S]*?```/.test(text) || /`[^`]+`/.test(text);
1106
- }
1107
- /**
1108
- * Smart body truncation — preserves code blocks and error messages.
1109
- * Instead of slicing at a char limit, finds a safe break point.
1110
- */
1111
- function truncateBody(body, limit) {
1112
- if (body.length <= limit) return body;
1113
- const codeBlockRe = /```[\s\S]*?```/g;
1114
- let lastSafeEnd = limit;
1115
- let match;
1116
- while ((match = codeBlockRe.exec(body)) !== null) {
1117
- const blockStart = match.index;
1118
- const blockEnd = blockStart + match[0].length;
1119
- if (blockStart < limit && blockEnd > limit) {
1120
- if (blockEnd <= limit + 500) lastSafeEnd = blockEnd;
1121
- else lastSafeEnd = blockStart;
1122
- break;
1123
- }
1124
- }
1125
- const slice = body.slice(0, lastSafeEnd);
1126
- const lastParagraph = slice.lastIndexOf("\n\n");
1127
- if (lastParagraph > lastSafeEnd * .6) return `${slice.slice(0, lastParagraph)}\n\n...`;
1128
- return `${slice}...`;
1129
- }
1130
1101
  /** Off-topic or spam title patterns — instant reject */
1131
1102
  const TITLE_NOISE_RE = /looking .*(?:developer|engineer|freelanc)|hiring|job post|guide me to (?:complete|finish|build)|help me (?:complete|finish|build)|seeking .* tutorial|recommend.* course/i;
1132
1103
  /** Minimum score for a discussion to be included */
@@ -2545,7 +2516,7 @@ function parseVersionSpecifier(name, version, cwd) {
2545
2516
  };
2546
2517
  if (/^[\^~>=<\d]/.test(version)) return {
2547
2518
  name,
2548
- version: version.replace(/^[\^~>=<]/, "")
2519
+ version: version.replace(/^[\^~>=<]+/, "")
2549
2520
  };
2550
2521
  if (version.startsWith("catalog:") || version.startsWith("workspace:")) return {
2551
2522
  name,
@@ -2668,9 +2639,10 @@ async function fetchPkgDist(name, version) {
2668
2639
  } });
2669
2640
  writable.on("finish", () => {
2670
2641
  fileStream.end();
2671
- res();
2672
2642
  });
2643
+ fileStream.on("close", () => res());
2673
2644
  writable.on("error", reject);
2645
+ fileStream.on("error", reject);
2674
2646
  function pump() {
2675
2647
  reader.read().then(({ done, value }) => {
2676
2648
  if (done) {