Skip to content

Commit 111d97d

Browse files
oritwoenharlan-zw
andauthored
feat: crate package support (#4)
Co-authored-by: Harlan Wilton <harlan@harlanzw.com>
1 parent 6eb1708 commit 111d97d

18 files changed

Lines changed: 1027 additions & 114 deletions

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ skilld add npm:vue npm:nuxt npm:pinia
149149
# Add a pre-authored skill from a GitHub repo
150150
skilld add gh:vercel-labs/agent-skills
151151

152+
# Add a skill for a Rust crate (crates.io)
153+
skilld add crate:serde
154+
152155
# Update outdated skills
153156
skilld update
154157
skilld update tailwindcss
@@ -183,7 +186,7 @@ skilld config
183186
| Command | Description |
184187
|---------|-------------|
185188
| `skilld` | Interactive wizard (first run) or status menu (existing skills) |
186-
| `skilld add <source...>` | Add skills. Sources: `npm:<pkg>`, `gh:<owner/repo>`, or bare names (deprecated) |
189+
| `skilld add <source...>` | Add skills. Sources: `npm:<pkg>`, `crate:<name>`, `gh:<owner/repo>`, or bare names (deprecated) |
187190
| `skilld update [pkg]` | Update outdated skills (all or specific) |
188191
| `skilld search [query]` | Search indexed docs (`-p` package, `--filter` JSON, `--limit`, `--guide`) |
189192
| `skilld list` | List installed skills (`--json` for machine-readable output) |

src/commands/install.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import { defaultFeatures, readConfig } from '../core/config.ts'
4040
import { timedSpinner } from '../core/formatting.ts'
4141
import { mergeLocks, parsePackages, readLock, syncLockfilesToDirs, writeLock } from '../core/lockfile.ts'
4242
import { readPackageJsonSafe } from '../core/package-json.ts'
43+
import { toStoragePackageName } from '../core/prefix.ts'
4344
import { sanitizeMarkdown } from '../core/sanitize.ts'
4445
import { getSharedSkillsDir } from '../core/shared.ts'
4546
import { createIndex, SearchDepsUnavailableError } from '../retriv/index.ts'
@@ -118,7 +119,7 @@ export async function installCommand(opts: InstallOptions): Promise<void> {
118119
const needsRestore = !existsSync(skillDir)
119120
|| !existsSync(skillMdPath)
120121
|| !existsSync(referencesPath)
121-
|| hasStaleReferences(referencesPath, info.packageName || name, info.version!, features)
122+
|| hasStaleReferences(referencesPath, toStoragePackageName(info.packageName || name), info.version!, features)
122123

123124
if (needsRestore) {
124125
toRestore.push({ name, info })
@@ -138,7 +139,8 @@ export async function installCommand(opts: InstallOptions): Promise<void> {
138139

139140
for (const { name, info } of toRestore) {
140141
const version = info.version!
141-
const pkgName = info.packageName || unsanitizeName(name, info.source)
142+
const identityName = info.packageName || unsanitizeName(name, info.source)
143+
const pkgName = toStoragePackageName(identityName)
142144

143145
// Shipped skills: re-link from node_modules or cached dist
144146
if (info.source === 'shipped') {

src/commands/search-helpers.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { join } from 'pathe'
55
import { agents, detectTargetAgent } from '../agent/index.ts'
66
import { getPackageDbPath, REFERENCES_DIR } from '../cache/index.ts'
77
import { readLock } from '../core/index.ts'
8+
import { toStoragePackageName } from '../core/prefix.ts'
89
import { getSharedSkillsDir } from '../core/shared.ts'
910

1011
/** Collect search.db paths for packages installed in the current project (from skilld-lock.yaml) */
@@ -72,10 +73,11 @@ function filterLockDbs(lock: ReturnType<typeof readLock>, packageFilter?: string
7273
return filterTokens.every(ft => nameTokens.some(nt => nt.includes(ft) || ft.includes(nt)))
7374
})
7475
.map((info) => {
75-
const exact = getPackageDbPath(info.packageName!, info.version!)
76+
const storageName = toStoragePackageName(info.packageName!)
77+
const exact = getPackageDbPath(storageName, info.version!)
7678
if (existsSync(exact))
7779
return exact
78-
const fallback = findAnyPackageDb(info.packageName!)
80+
const fallback = findAnyPackageDb(storageName)
7981
if (fallback)
8082
p.log.warn(`Using cached search index for ${info.packageName} (v${info.version} not indexed). Run \`skilld update ${info.packageName}\` to re-index.`)
8183
return fallback

src/commands/status.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { sharedArgs } from '../cli-helpers.ts'
1111
import { defaultFeatures, hasConfig, readConfig } from '../core/config.ts'
1212
import { formatSource, timeAgo } from '../core/formatting.ts'
1313
import { parsePackages } from '../core/lockfile.ts'
14+
import { toStoragePackageName } from '../core/prefix.ts'
1415
import { getSharedSkillsDir, mapInsert } from '../core/shared.ts'
1516

1617
import { iterateSkills } from '../core/skills.ts'
@@ -211,7 +212,7 @@ export async function statusCommand(opts: StatusOptions = {}): Promise<void> {
211212
lines.push(parts.join(' '))
212213

213214
const meta: string[] = []
214-
const pkgName = info.packageName || pkg.name
215+
const pkgName = toStoragePackageName(info.packageName || pkg.name)
215216
const docs = countDocs(pkgName, info.version) || countRefDocs(join(
216217
pkg.scope === 'global'
217218
? agents[pkg.agents.values().next().value!].globalSkillsDir!

src/commands/sync-shared.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,8 @@ export async function selectLlmConfig(presetModel?: OptimizeModel, message?: str
13571357

13581358
export interface EnhanceOptions {
13591359
packageName: string
1360+
/** Storage/cache key (e.g. namespaced '@skilld-crate/serde'); defaults to packageName */
1361+
cachePackageName?: string
13601362
version: string
13611363
skillDir: string
13621364
dirName?: string
@@ -1381,15 +1383,16 @@ export interface EnhanceOptions {
13811383
}
13821384

13831385
export async function enhanceSkillWithLLM(opts: EnhanceOptions): Promise<void> {
1384-
const { packageName, version, skillDir, dirName, model, resolved, relatedSkills, hasIssues, hasDiscussions, hasReleases, hasChangelog, docsType, hasShippedDocs: shippedDocs, pkgFiles, force, debug, sections, customPrompt, packages, features, eject, overheadLines } = opts
1386+
const { packageName, cachePackageName, version, skillDir, dirName, model, resolved, relatedSkills, hasIssues, hasDiscussions, hasReleases, hasChangelog, docsType, hasShippedDocs: shippedDocs, pkgFiles, force, debug, sections, customPrompt, packages, features, eject, overheadLines } = opts
1387+
const cacheKey = cachePackageName || packageName
13851388

13861389
const effectiveFeatures = features
13871390

13881391
const llmLog = p.taskLog({ title: `Agent exploring ${packageName}`, limit: 3 })
13891392
const docFiles = listReferenceFiles(skillDir)
13901393
const hasGithub = hasIssues || hasDiscussions
13911394
const { optimized, wasOptimized, usage, cost, warnings, error, debugLogsDir } = await optimizeDocs({
1392-
packageName,
1395+
packageName: cacheKey,
13931396
skillDir,
13941397
model,
13951398
version,

0 commit comments

Comments
 (0)