Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/agent/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export { detectInstalledAgents, detectProjectAgents, detectTargetAgent, getAgent
export { computeSkillDirName, installSkillForAgents, linkSkillToAgents, sanitizeName, unlinkSkillFromAgents } from './install.ts'

// Skill generation
export { extractMarkedSections, generateSkillMd, getSectionValidator, portabilizePrompt, wrapSection } from './prompts/index.ts'
export { extractMarkedSections, generateSkillMd, getSectionValidator, portabilizePrompt, wrapSection, writeGeneratedSkillMd, writeSkillMd } from './prompts/index.ts'

export type { SkillOptions } from './prompts/index.ts'
// Registry
Expand Down
2 changes: 1 addition & 1 deletion src/agent/prompts/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
export type { CustomPrompt, SectionValidationWarning } from './optional/index.ts'
export { buildAllSectionPrompts, buildSectionPrompt, extractMarkedSections, getSectionValidator, portabilizePrompt, SECTION_MERGE_ORDER, SECTION_OUTPUT_FILES, wrapSection } from './prompt.ts'
export type { BuildSkillPromptOptions, SkillSection } from './prompt.ts'
export { generateSkillMd } from './skill.ts'
export { generateSkillMd, writeGeneratedSkillMd, writeSkillMd } from './skill.ts'
export type { SkillOptions } from './skill.ts'
12 changes: 12 additions & 0 deletions src/agent/prompts/skill.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*/

import type { FeaturesConfig } from '../../core/config.ts'
import { writeFileSync } from 'node:fs'
import { join } from 'pathe'
import { repairMarkdown, sanitizeMarkdown } from '../../core/sanitize.ts'
import { resolveSkilldCommand } from '../../core/shared.ts'
import { yamlEscape } from '../../core/yaml.ts'
Expand Down Expand Up @@ -42,6 +44,16 @@ export interface SkillOptions {
eject?: boolean
}

export function writeSkillMd(skillDir: string, content: string): void {
writeFileSync(join(skillDir, 'SKILL.md'), content)
}

export function writeGeneratedSkillMd(skillDir: string, opts: SkillOptions): string {
const content = generateSkillMd(opts)
writeSkillMd(skillDir, content)
return content
}

export function generateSkillMd(opts: SkillOptions): string {
const header = generatePackageHeader(opts)
const search = !opts.eject && opts.features?.search !== false ? generateSearchBlock(opts.name) : ''
Expand Down
7 changes: 3 additions & 4 deletions src/commands/author.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import type { OptimizeModel } from '../agent/index.ts'
import type { FeaturesConfig } from '../core/config.ts'
import type { LlmConfig } from './sync-shared.ts'
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync } from 'node:fs'
import * as p from '@clack/prompts'
import { defineCommand } from 'citty'
import { join, relative, resolve } from 'pathe'
import {
computeSkillDirName,
generateSkillMd,
getModelLabel,
writeGeneratedSkillMd,
} from '../agent/index.ts'
import {
ensureCacheDir,
Expand Down Expand Up @@ -421,7 +421,7 @@ async function authorSinglePackage(opts: {
const hasReleases = existsSync(join(cacheDir, 'releases'))

// Generate base SKILL.md
const baseSkillMd = generateSkillMd({
writeGeneratedSkillMd(outDir, {
name: packageName,
version,
description: opts.description,
Expand All @@ -438,7 +438,6 @@ async function authorSinglePackage(opts: {
features,
eject: true,
})
writeFileSync(join(outDir, 'SKILL.md'), baseSkillMd)
p.log.success(`Created base skill: ${relative(packageDir, outDir)}`)

// LLM enhancement (config resolved by caller)
Expand Down
12 changes: 5 additions & 7 deletions src/commands/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import * as p from '@clack/prompts'
import { defineCommand } from 'citty'
import { dirname, join } from 'pathe'
import { agents, createToolProgress, getModelLabel, linkSkillToAgents, optimizeDocs } from '../agent/index.ts'
import { generateSkillMd } from '../agent/prompts/skill.ts'
import { writeGeneratedSkillMd, writeSkillMd } from '../agent/prompts/skill.ts'
import {
hasShippedDocs as checkShippedDocs,
ensureCacheDir,
Expand Down Expand Up @@ -172,7 +172,7 @@ export async function installCommand(opts: InstallOptions): Promise<void> {
if (match) {
const skillDir = join(skillsDir, name)
mkdirSync(skillDir, { recursive: true })
writeFileSync(join(skillDir, 'SKILL.md'), sanitizeMarkdown(match.content))
writeSkillMd(skillDir, sanitizeMarkdown(match.content))
for (const f of match.files) {
const filePath = join(skillDir, f.path)
mkdirSync(dirname(filePath), { recursive: true })
Expand Down Expand Up @@ -586,7 +586,7 @@ async function enhanceRegenerated(
const dirName = skillDir.split('/').pop()

const allPackages = parsePackageNames(packages)
const skillMd = generateSkillMd({
writeGeneratedSkillMd(skillDir, {
name: pkgName,
version,
description,
Expand All @@ -602,7 +602,6 @@ async function enhanceRegenerated(
packages: allPackages.length > 1 ? allPackages : undefined,
features,
})
writeFileSync(join(skillDir, 'SKILL.md'), skillMd)
}
else {
llmLog.message('Enhancement skipped')
Expand Down Expand Up @@ -674,7 +673,8 @@ function regenerateBaseSkillMd(
// Build multi-package list from lockfile packages field
const allPackages = parsePackageNames(packages)

const content = generateSkillMd({
mkdirSync(skillDir, { recursive: true })
writeGeneratedSkillMd(skillDir, {
name: pkgName,
version,
description,
Expand All @@ -690,8 +690,6 @@ function regenerateBaseSkillMd(
features: readConfig().features ?? defaultFeatures,
})

mkdirSync(skillDir, { recursive: true })
writeFileSync(skillMdPath, content)
return true
}

Expand Down
8 changes: 4 additions & 4 deletions src/commands/sync-git.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import * as p from '@clack/prompts'
import { dirname, join, relative } from 'pathe'
import {
agents,
generateSkillMd,
getModelLabel,
linkSkillToAgents,
sanitizeName,
writeGeneratedSkillMd,
writeSkillMd,
} from '../agent/index.ts'
import {
CACHE_DIR,
Expand Down Expand Up @@ -134,7 +135,7 @@ export async function syncGitSkills(opts: GitSyncOptions): Promise<void> {
mkdirSync(skillDir, { recursive: true })

// Sanitize and write SKILL.md
writeFileSync(join(skillDir, 'SKILL.md'), sanitizeMarkdown(skill.content))
writeSkillMd(skillDir, sanitizeMarkdown(skill.content))

// Write supporting files directly in skill dir (not under .skilld/)
// so SKILL.md relative paths like ./references/docs/guide.md resolve correctly
Expand Down Expand Up @@ -275,7 +276,7 @@ async function syncGitHubRepo(opts: GitSyncOptions): Promise<void> {
})

// Write base SKILL.md
const baseSkillMd = generateSkillMd({
writeGeneratedSkillMd(skillDir, {
name: packageName,
version,
releasedAt: resolved.releasedAt,
Expand All @@ -292,7 +293,6 @@ async function syncGitHubRepo(opts: GitSyncOptions): Promise<void> {
repoUrl,
features,
})
writeFileSync(join(skillDir, 'SKILL.md'), baseSkillMd)

p.log.success(`Created base skill: ${relative(cwd, skillDir)}`)

Expand Down
13 changes: 5 additions & 8 deletions src/commands/sync-parallel.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { AgentType, CustomPrompt, OptimizeModel, SkillSection } from '../agent/index.ts'
import type { FeaturesConfig } from '../core/config.ts'
import type { ResolvedPackage } from '../sources/index.ts'
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
import { existsSync, mkdirSync, readFileSync } from 'node:fs'
import * as p from '@clack/prompts'
import logUpdate from 'log-update'
import pLimit from 'p-limit'
Expand All @@ -10,13 +10,13 @@ import {
agents,
computeSkillDirName,

generateSkillMd,
getModelLabel,
linkSkillToAgents,
optimizeDocs,
SECTION_MERGE_ORDER,
SECTION_OUTPUT_FILES,
wrapSection,
writeGeneratedSkillMd,

} from '../agent/index.ts'
import {
Expand Down Expand Up @@ -263,7 +263,7 @@ export async function syncPackagesParallel(config: ParallelSyncConfig): Promise<
}
const cachedBody = cachedParts.join('\n\n')

const skillMd = generateSkillMd({
writeGeneratedSkillMd(skillDir, {
name: resolvedName,
version: data.version,
releasedAt: data.resolved.releasedAt,
Expand All @@ -284,7 +284,6 @@ export async function syncPackagesParallel(config: ParallelSyncConfig): Promise<
repoUrl: data.resolved.repoUrl,
features: data.features,
})
writeFileSync(join(skillDir, 'SKILL.md'), skillMd)
cachedPkgs.push(pkg)
}
}
Expand Down Expand Up @@ -575,7 +574,7 @@ async function syncBaseSkill(
const updatedLock = readLock(baseDir)?.skills[skillDirName]
const allPackages = parsePackageNames(updatedLock?.packages)

const skillMd = generateSkillMd({
const skillMd = writeGeneratedSkillMd(skillDir, {
name: packageName,
version,
releasedAt: resolved.releasedAt,
Expand All @@ -595,7 +594,6 @@ async function syncBaseSkill(
repoUrl: resolved.repoUrl,
features,
})
writeFileSync(join(skillDir, 'SKILL.md'), skillMd)
const overheadLines = skillMd.split('\n').length

// Link shared dir to per-agent dirs
Expand Down Expand Up @@ -683,7 +681,7 @@ async function enhanceWithLLM(
}

if (wasOptimized) {
const skillMd = generateSkillMd({
writeGeneratedSkillMd(skillDir, {
name: packageName,
version: data.version,
releasedAt: data.resolved.releasedAt,
Expand All @@ -702,7 +700,6 @@ async function enhanceWithLLM(
repoUrl: data.resolved.repoUrl,
features: data.features,
})
writeFileSync(join(skillDir, 'SKILL.md'), skillMd)
}

update(packageName, 'done', 'Skill optimized', versionKey)
Expand Down
5 changes: 3 additions & 2 deletions src/commands/sync-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@

import type { AgentType } from '../agent/index.ts'
import type { RegistrySkill } from '../registry/client.ts'
import { mkdirSync, writeFileSync } from 'node:fs'
import { mkdirSync } from 'node:fs'
import { join } from 'pathe'
import { linkSkillToAgents } from '../agent/install.ts'
import { writeSkillMd } from '../agent/prompts/skill.ts'
import { writeLock } from '../core/lockfile.ts'
import { SHARED_SKILLS_DIR } from '../core/shared.ts'
import { fetchRegistrySkill } from '../registry/client.ts'
Expand All @@ -38,7 +39,7 @@ export async function syncRegistrySkill(opts: SyncRegistryOptions): Promise<Regi
const sharedDir = join(cwd, SHARED_SKILLS_DIR)
const skillDir = join(sharedDir, skill.name)
mkdirSync(skillDir, { recursive: true })
writeFileSync(join(skillDir, 'SKILL.md'), skill.content)
writeSkillMd(skillDir, skill.content)

// Update lockfile
const baseDir = join(cwd, '.claude', 'skills')
Expand Down
5 changes: 2 additions & 3 deletions src/commands/sync-shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ import {
agents,
buildAllSectionPrompts,
createToolProgress,
generateSkillMd,
getAvailableModels,
getModelLabel,
getModelName,
optimizeDocs,
SECTION_OUTPUT_FILES,
writeGeneratedSkillMd,
} from '../agent/index.ts'
import { maxItems, maxLines } from '../agent/prompts/optional/budget.ts'
import {
Expand Down Expand Up @@ -1430,7 +1430,7 @@ export async function enhanceSkillWithLLM(opts: EnhanceOptions): Promise<void> {
for (const w of warnings)
p.log.warn(`\x1B[33m${w}\x1B[0m`)
}
const skillMd = generateSkillMd({
writeGeneratedSkillMd(skillDir, {
name: packageName,
version,
releasedAt: resolved.releasedAt,
Expand All @@ -1452,7 +1452,6 @@ export async function enhanceSkillWithLLM(opts: EnhanceOptions): Promise<void> {
features,
eject,
})
writeFileSync(join(skillDir, 'SKILL.md'), skillMd)
}
else {
if (error && /\b429\b|rate.?limit|exhausted.*capacity|quota.*reset/i.test(error))
Expand Down
14 changes: 5 additions & 9 deletions src/commands/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import {
buildAllSectionPrompts,
computeSkillDirName,
detectImportedPackages,
generateSkillMd,
getAvailableModels,
getModelLabel,
linkSkillToAgents,
Expand All @@ -20,6 +19,7 @@ import {
SECTION_MERGE_ORDER,
SECTION_OUTPUT_FILES,
wrapSection,
writeGeneratedSkillMd,
} from '../agent/index.ts'
import {
ensureCacheDir,
Expand Down Expand Up @@ -480,7 +480,7 @@ async function syncSinglePackage(packageSpec: string, config: SyncConfig): Promi
const shippedDocs = hasShippedDocs(existingStorageName, cwd, existingLock.version)

const mergeFeatures = readConfig().features ?? defaultFeatures
const skillMd = generateSkillMd({
writeGeneratedSkillMd(skillDir, {
name: existingLock.packageName!,
version: existingLock.version,
relatedSkills,
Expand All @@ -494,7 +494,6 @@ async function syncSinglePackage(packageSpec: string, config: SyncConfig): Promi
packages: allPackages,
features: mergeFeatures,
})
writeFileSync(join(skillDir, 'SKILL.md'), skillMd)

const mergeShared = !config.global && getSharedSkillsDir(cwd)
if (mergeShared)
Expand Down Expand Up @@ -605,7 +604,7 @@ async function syncSinglePackage(packageSpec: string, config: SyncConfig): Promi
const allPackages = parsePackageNames(updatedLock?.packages)

const isEject = !!config.eject
const baseSkillMd = generateSkillMd({
const baseSkillMd = writeGeneratedSkillMd(skillDir, {
name: identityPackageName,
version,
releasedAt: resolved.releasedAt,
Expand All @@ -626,7 +625,6 @@ async function syncSinglePackage(packageSpec: string, config: SyncConfig): Promi
features,
eject: isEject,
})
writeFileSync(join(skillDir, 'SKILL.md'), baseSkillMd)
const overheadLines = baseSkillMd.split('\n').length

p.log.success(config.mode === 'update' ? `Updated skill: ${relative(cwd, skillDir)}` : `Created base skill: ${relative(cwd, skillDir)}`)
Expand All @@ -650,7 +648,7 @@ async function syncSinglePackage(packageSpec: string, config: SyncConfig): Promi
}
const cachedBody = cachedParts.join('\n\n')

const skillMd = generateSkillMd({
writeGeneratedSkillMd(skillDir, {
name: identityPackageName,
version,
releasedAt: resolved.releasedAt,
Expand All @@ -673,7 +671,6 @@ async function syncSinglePackage(packageSpec: string, config: SyncConfig): Promi
features,
eject: isEject,
})
writeFileSync(join(skillDir, 'SKILL.md'), skillMd)
p.log.success('Applied cached SKILL.md sections')
}

Expand Down Expand Up @@ -1231,7 +1228,7 @@ export async function exportPortablePrompts(packageSpec: string, opts: {

// Generate SKILL.md (ejected — uses ./references/ paths)
const relatedSkills = await findRelatedSkills(packageName, join(skillDir, '..'))
const skillMd = generateSkillMd({
writeGeneratedSkillMd(skillDir, {
name: packageName,
version,
releasedAt: resolved.releasedAt,
Expand All @@ -1250,7 +1247,6 @@ export async function exportPortablePrompts(packageSpec: string, opts: {
features,
eject: true,
})
writeFileSync(join(skillDir, 'SKILL.md'), skillMd)

// Write lockfile so skilld list/update/assemble can discover this skill
const repoSlug = parseGitHubRepoSlug(resolved.repoUrl)
Expand Down
Loading
Loading