(options: InstallSkillsOptions)
| 188 | } |
| 189 | |
| 190 | async function installSkills(options: InstallSkillsOptions): Promise<void> { |
| 191 | const isGlobal = !!options.global |
| 192 | const baseDir = isGlobal ? os.homedir() : process.cwd() |
| 193 | const skillDir = getSkillDir() |
| 194 | |
| 195 | debug(`Base directory: ${baseDir}`) |
| 196 | debug(`Skill source: ${skillDir}`) |
| 197 | debug(`Mode: ${isGlobal ? 'global' : 'project'}`) |
| 198 | |
| 199 | try { |
| 200 | await fs.access(skillDir) |
| 201 | } catch { |
| 202 | throw new Error(`Skill source directory not found: ${skillDir}`) |
| 203 | } |
| 204 | |
| 205 | const agents = await detectAgents(baseDir, isGlobal, options.agent) |
| 206 | |
| 207 | if (agents.length === 0) { |
| 208 | logError('No agents detected. Use --agent to specify one.') |
| 209 | process.exit(ExitCode.InvalidUsage) |
| 210 | } |
| 211 | |
| 212 | // Read all files from the skill directory recursively |
| 213 | const skillContents = await readDirRecursive(skillDir) |
| 214 | |
| 215 | const results: InstallResult[] = [] |
| 216 | const installedDirs = new Set<string>() |
| 217 | |
| 218 | for (const agent of agents) { |
| 219 | const agentSkillDir = isGlobal ? agent.globalSkillDir : agent.projectSkillDir |
| 220 | if (!agentSkillDir) { |
| 221 | continue |
| 222 | } |
| 223 | const targetDir = path.join(baseDir, agentSkillDir, 'deepnote') |
| 224 | |
| 225 | // Deduplicate: universal agents share the same project skill directory |
| 226 | if (installedDirs.has(targetDir)) { |
| 227 | continue |
| 228 | } |
| 229 | installedDirs.add(targetDir) |
| 230 | |
| 231 | const skillPath = path.join(agentSkillDir, 'deepnote', 'SKILL.md') |
| 232 | |
| 233 | if (options.dryRun) { |
| 234 | const status = await getInstallStatus(targetDir, skillContents) |
| 235 | results.push({ agent, status, skillPath }) |
| 236 | continue |
| 237 | } |
| 238 | |
| 239 | const status = await installSkillFiles(targetDir, skillContents) |
| 240 | results.push({ agent, status, skillPath }) |
| 241 | } |
| 242 | |
| 243 | const c = getChalk() |
| 244 | |
| 245 | if (options.dryRun) { |
| 246 | output(c.bold('Dry run — no files written:')) |
| 247 | } else { |
no test coverage detected