skilld 0.0.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.
- package/README.md +171 -0
- package/dist/agents.d.mts +56 -0
- package/dist/agents.d.mts.map +1 -0
- package/dist/agents.mjs +148 -0
- package/dist/agents.mjs.map +1 -0
- package/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +503 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +14 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +181 -0
- package/dist/index.mjs.map +1 -0
- package/dist/npm.d.mts +48 -0
- package/dist/npm.d.mts.map +1 -0
- package/dist/npm.mjs +90 -0
- package/dist/npm.mjs.map +1 -0
- package/dist/split-text.d.mts +24 -0
- package/dist/split-text.d.mts.map +1 -0
- package/dist/split-text.mjs +87 -0
- package/dist/split-text.mjs.map +1 -0
- package/dist/types.d.mts +37 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
<h1>skilld</h1>
|
|
2
|
+
|
|
3
|
+
[](https://npmjs.com/package/skilld)
|
|
4
|
+
[](https://npm.chart.dev/skilld)
|
|
5
|
+
[](https://github.com/harlan-zw/skilld/blob/main/LICENSE.md)
|
|
6
|
+
|
|
7
|
+
> A global database of searchable skills generated from live NPM package documentation.
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<table>
|
|
11
|
+
<tbody>
|
|
12
|
+
<td align="center">
|
|
13
|
+
<sub>Made possible by my <a href="https://github.com/sponsors/harlan-zw">Sponsor Program 💖</a><br> Follow me <a href="https://twitter.com/harlan_zw">@harlan_zw</a> 🐦 • Join <a href="https://discord.gg/275MBUBvgP">Discord</a> for help</sub><br>
|
|
14
|
+
</td>
|
|
15
|
+
</tbody>
|
|
16
|
+
</table>
|
|
17
|
+
</p>
|
|
18
|
+
|
|
19
|
+
## Features
|
|
20
|
+
|
|
21
|
+
- 🌐 **Global Skill DB** - Centralized, searchable skills for any NPM package
|
|
22
|
+
- 📚 **Live Docs** - Fetches from `llms.txt` or crawls documentation sites
|
|
23
|
+
- 🔍 **Vector Search** - SQLite-vec powered semantic search with transformers embeddings
|
|
24
|
+
- ✂️ **Smart Chunking** - Markdown-aware recursive text splitting (LangChain-style)
|
|
25
|
+
- 🚀 **Zero Config** - Point at a URL, get a searchable skill
|
|
26
|
+
|
|
27
|
+
## How It Works
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
Package name → Resolve docs → Fetch → Install to agent directories
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
1. **Resolve** - Looks up npm registry for homepage, repository URL
|
|
34
|
+
2. **Fetch** - Tries llms.txt → docs site → GitHub README (via ungh)
|
|
35
|
+
3. **Install** - Writes SKILL.md to each detected agent's skill directory
|
|
36
|
+
|
|
37
|
+
Supported agents: Claude Code, Cursor, Windsurf, Cline, Codex, GitHub Copilot, Gemini CLI, Goose, Amp, OpenCode, Roo Code
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pnpm add -g skilld
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## CLI Usage
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Auto-discover from package.json dependencies
|
|
49
|
+
skilld
|
|
50
|
+
|
|
51
|
+
# Generate skill from specific package name
|
|
52
|
+
skilld vueuse
|
|
53
|
+
skilld @nuxt/kit
|
|
54
|
+
|
|
55
|
+
# Generate skill from URL
|
|
56
|
+
skilld https://nuxt.com/docs
|
|
57
|
+
|
|
58
|
+
# Custom output directory
|
|
59
|
+
skilld -o ./my-skills
|
|
60
|
+
|
|
61
|
+
# Concurrent processing (default: 3)
|
|
62
|
+
skilld -c 5
|
|
63
|
+
|
|
64
|
+
# Skip llms.txt and always crawl
|
|
65
|
+
skilld --crawl
|
|
66
|
+
|
|
67
|
+
# Limit pages fetched per package
|
|
68
|
+
skilld -m 50
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### CLI Options
|
|
72
|
+
|
|
73
|
+
| Option | Alias | Default | Description |
|
|
74
|
+
|--------|-------|---------|-------------|
|
|
75
|
+
| `--output` | `-o` | `.skilld` | Output directory |
|
|
76
|
+
| `--maxPages` | `-m` | `100` | Max pages to fetch |
|
|
77
|
+
| `--chunkSize` | | `1000` | Chunk size in characters |
|
|
78
|
+
| `--model` | | `Xenova/bge-small-en-v1.5` | Embedding model |
|
|
79
|
+
| `--crawl` | | `false` | Skip llms.txt, always crawl |
|
|
80
|
+
| `--concurrency` | `-c` | `3` | Concurrent package processing |
|
|
81
|
+
|
|
82
|
+
## Programmatic Usage
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
import { generateSkill } from 'skilld'
|
|
86
|
+
|
|
87
|
+
const result = await generateSkill({
|
|
88
|
+
url: 'https://nuxt.com/docs',
|
|
89
|
+
outputDir: '.skilld',
|
|
90
|
+
maxPages: 100,
|
|
91
|
+
chunkSize: 1000,
|
|
92
|
+
chunkOverlap: 200,
|
|
93
|
+
}, ({ url, count, phase }) => {
|
|
94
|
+
console.log(`[${phase}] ${count}: ${url}`)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
console.log(result)
|
|
98
|
+
// {
|
|
99
|
+
// siteName: 'nuxt.com',
|
|
100
|
+
// skillPath: '.skilld/nuxt.com/SKILL.md',
|
|
101
|
+
// referencesDir: '.skilld/nuxt.com/references',
|
|
102
|
+
// dbPath: '.skilld/nuxt.com/search.db',
|
|
103
|
+
// chunkCount: 847
|
|
104
|
+
// }
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Output Structure
|
|
108
|
+
|
|
109
|
+
Skills are installed directly to each agent's skill directory:
|
|
110
|
+
|
|
111
|
+
```
|
|
112
|
+
.claude/skills/
|
|
113
|
+
└── vueuse/
|
|
114
|
+
└── SKILL.md # Package documentation
|
|
115
|
+
|
|
116
|
+
.cursor/skills/
|
|
117
|
+
└── vueuse/
|
|
118
|
+
└── SKILL.md # Same content, separate copy
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Each SKILL.md includes frontmatter for agent discovery:
|
|
122
|
+
|
|
123
|
+
```yaml
|
|
124
|
+
---
|
|
125
|
+
name: vueuse
|
|
126
|
+
description: Collection of Vue Composition Utilities
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
# VueUse
|
|
130
|
+
...README content...
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Package.json Auto-Discovery
|
|
134
|
+
|
|
135
|
+
Run `skilld` without arguments to generate skills for all dependencies:
|
|
136
|
+
|
|
137
|
+
```bash
|
|
138
|
+
cd my-project
|
|
139
|
+
pnpx skilld
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
This will:
|
|
143
|
+
1. Read `package.json` dependencies and devDependencies
|
|
144
|
+
2. Resolve documentation URL for each package (llms.txt → homepage → GitHub README)
|
|
145
|
+
3. Generate searchable skills in `.skilld/`
|
|
146
|
+
|
|
147
|
+
Skips `@types/*` and common dev tools (typescript, eslint, vitest, etc).
|
|
148
|
+
|
|
149
|
+
## NPM Package Skills
|
|
150
|
+
|
|
151
|
+
Generate skills for specific packages by name or URL:
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
# By package name (auto-resolves docs)
|
|
155
|
+
skilld vueuse
|
|
156
|
+
skilld @vueuse/core
|
|
157
|
+
skilld defu
|
|
158
|
+
|
|
159
|
+
# By URL
|
|
160
|
+
skilld https://vueuse.org
|
|
161
|
+
skilld https://nuxt.com # Uses /llms.txt automatically
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Related
|
|
165
|
+
|
|
166
|
+
- [mdream](https://github.com/harlan-zw/mdream) - HTML to Markdown converter used for crawling
|
|
167
|
+
- [retriv](https://github.com/harlan-zw/retriv) - Vector database abstraction layer
|
|
168
|
+
|
|
169
|
+
## License
|
|
170
|
+
|
|
171
|
+
Licensed under the [MIT license](https://github.com/harlan-zw/skilld/blob/main/LICENSE.md).
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//#region src/agents.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Agent detection and skill installation
|
|
4
|
+
* Writes directly to agent skill directories in the project
|
|
5
|
+
*/
|
|
6
|
+
type AgentType = 'claude-code' | 'cursor' | 'windsurf' | 'cline' | 'codex' | 'github-copilot' | 'gemini-cli' | 'goose' | 'amp' | 'opencode' | 'roo';
|
|
7
|
+
interface AgentConfig {
|
|
8
|
+
name: AgentType;
|
|
9
|
+
displayName: string;
|
|
10
|
+
/** Project-level skills directory (e.g., .claude/skills) */
|
|
11
|
+
skillsDir: string;
|
|
12
|
+
/** Global skills directory (e.g., ~/.claude/skills) */
|
|
13
|
+
globalSkillsDir: string | undefined;
|
|
14
|
+
/** Check if agent is installed on the system */
|
|
15
|
+
detectInstalled: () => boolean;
|
|
16
|
+
}
|
|
17
|
+
declare const agents: Record<AgentType, AgentConfig>;
|
|
18
|
+
/**
|
|
19
|
+
* Detect which agents are installed on the system
|
|
20
|
+
*/
|
|
21
|
+
declare function detectInstalledAgents(): AgentType[];
|
|
22
|
+
/**
|
|
23
|
+
* Detect which agent is currently running this command
|
|
24
|
+
* Returns the active agent based on environment variables and context
|
|
25
|
+
*/
|
|
26
|
+
declare function detectCurrentAgent(): AgentType | null;
|
|
27
|
+
/**
|
|
28
|
+
* Sanitize skill name for filesystem
|
|
29
|
+
*/
|
|
30
|
+
declare function sanitizeName(name: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Install a skill directly to agent skill directories
|
|
33
|
+
* Writes to each agent's skill folder in the project (e.g., .claude/skills/package-name/)
|
|
34
|
+
*/
|
|
35
|
+
declare function installSkillForAgents(skillName: string, skillContent: string, options?: {
|
|
36
|
+
global?: boolean;
|
|
37
|
+
cwd?: string;
|
|
38
|
+
agents?: AgentType[]; /** Additional files to write (filename -> content) */
|
|
39
|
+
files?: Record<string, string>;
|
|
40
|
+
}): {
|
|
41
|
+
installed: AgentType[];
|
|
42
|
+
paths: string[];
|
|
43
|
+
};
|
|
44
|
+
interface SkillMetadata {
|
|
45
|
+
name: string;
|
|
46
|
+
version?: string;
|
|
47
|
+
description?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Generate SKILL.md frontmatter content
|
|
51
|
+
* The description tells the agent when to use this skill
|
|
52
|
+
*/
|
|
53
|
+
declare function generateSkillMd(meta: SkillMetadata, body: string): string;
|
|
54
|
+
//#endregion
|
|
55
|
+
export { AgentConfig, AgentType, SkillMetadata, agents, detectCurrentAgent, detectInstalledAgents, generateSkillMd, installSkillForAgents, sanitizeName };
|
|
56
|
+
//# sourceMappingURL=agents.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.d.mts","names":[],"sources":["../src/agents.ts"],"mappings":";;AAcA;;;KAAY,SAAA;AAAA,UAaK,WAAA;EACf,IAAA,EAAM,SAAA;EACN,WAAA;;EAEA,SAAA;EAHA;EAKA,eAAA;EAJA;EAMA,eAAA;AAAA;AAAA,cAGW,MAAA,EAAQ,MAAA,CAAO,SAAA,EAAW,WAAA;;;AAAvC;iBAmFgB,qBAAA,CAAA,GAAyB,SAAA;;;;;iBAUzB,kBAAA,CAAA,GAAsB,SAAA;;;;iBAyDtB,YAAA,CAAa,IAAA;;;AAnE7B;;iBA+EgB,qBAAA,CACd,SAAA,UACA,YAAA,UACA,OAAA;EACE,MAAA;EACA,GAAA;EACA,MAAA,GAAS,SAAA,IA3EqB;EA6E9B,KAAA,GAAQ,MAAA;AAAA;EAEP,SAAA,EAAW,SAAA;EAAa,KAAA;AAAA;AAAA,UAuCZ,aAAA;EACf,IAAA;EACA,OAAA;EACA,WAAA;AAAA;;;;;iBAOc,eAAA,CACd,IAAA,EAAM,aAAA,EACN,IAAA"}
|
package/dist/agents.mjs
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
|
+
const home = homedir();
|
|
5
|
+
const configHome = process.env.XDG_CONFIG_HOME || join(home, ".config");
|
|
6
|
+
const claudeHome = process.env.CLAUDE_CONFIG_DIR || join(home, ".claude");
|
|
7
|
+
const codexHome = process.env.CODEX_HOME || join(home, ".codex");
|
|
8
|
+
const agents = {
|
|
9
|
+
"claude-code": {
|
|
10
|
+
name: "claude-code",
|
|
11
|
+
displayName: "Claude Code",
|
|
12
|
+
skillsDir: ".claude/skills",
|
|
13
|
+
globalSkillsDir: join(claudeHome, "skills"),
|
|
14
|
+
detectInstalled: () => existsSync(claudeHome)
|
|
15
|
+
},
|
|
16
|
+
cursor: {
|
|
17
|
+
name: "cursor",
|
|
18
|
+
displayName: "Cursor",
|
|
19
|
+
skillsDir: ".cursor/skills",
|
|
20
|
+
globalSkillsDir: join(home, ".cursor/skills"),
|
|
21
|
+
detectInstalled: () => existsSync(join(home, ".cursor"))
|
|
22
|
+
},
|
|
23
|
+
windsurf: {
|
|
24
|
+
name: "windsurf",
|
|
25
|
+
displayName: "Windsurf",
|
|
26
|
+
skillsDir: ".windsurf/skills",
|
|
27
|
+
globalSkillsDir: join(home, ".codeium/windsurf/skills"),
|
|
28
|
+
detectInstalled: () => existsSync(join(home, ".codeium/windsurf"))
|
|
29
|
+
},
|
|
30
|
+
cline: {
|
|
31
|
+
name: "cline",
|
|
32
|
+
displayName: "Cline",
|
|
33
|
+
skillsDir: ".cline/skills",
|
|
34
|
+
globalSkillsDir: join(home, ".cline/skills"),
|
|
35
|
+
detectInstalled: () => existsSync(join(home, ".cline"))
|
|
36
|
+
},
|
|
37
|
+
codex: {
|
|
38
|
+
name: "codex",
|
|
39
|
+
displayName: "Codex",
|
|
40
|
+
skillsDir: ".codex/skills",
|
|
41
|
+
globalSkillsDir: join(codexHome, "skills"),
|
|
42
|
+
detectInstalled: () => existsSync(codexHome)
|
|
43
|
+
},
|
|
44
|
+
"github-copilot": {
|
|
45
|
+
name: "github-copilot",
|
|
46
|
+
displayName: "GitHub Copilot",
|
|
47
|
+
skillsDir: ".github/skills",
|
|
48
|
+
globalSkillsDir: join(home, ".copilot/skills"),
|
|
49
|
+
detectInstalled: () => existsSync(join(home, ".copilot"))
|
|
50
|
+
},
|
|
51
|
+
"gemini-cli": {
|
|
52
|
+
name: "gemini-cli",
|
|
53
|
+
displayName: "Gemini CLI",
|
|
54
|
+
skillsDir: ".gemini/skills",
|
|
55
|
+
globalSkillsDir: join(home, ".gemini/skills"),
|
|
56
|
+
detectInstalled: () => existsSync(join(home, ".gemini"))
|
|
57
|
+
},
|
|
58
|
+
goose: {
|
|
59
|
+
name: "goose",
|
|
60
|
+
displayName: "Goose",
|
|
61
|
+
skillsDir: ".goose/skills",
|
|
62
|
+
globalSkillsDir: join(configHome, "goose/skills"),
|
|
63
|
+
detectInstalled: () => existsSync(join(configHome, "goose"))
|
|
64
|
+
},
|
|
65
|
+
amp: {
|
|
66
|
+
name: "amp",
|
|
67
|
+
displayName: "Amp",
|
|
68
|
+
skillsDir: ".agents/skills",
|
|
69
|
+
globalSkillsDir: join(configHome, "agents/skills"),
|
|
70
|
+
detectInstalled: () => existsSync(join(configHome, "amp"))
|
|
71
|
+
},
|
|
72
|
+
opencode: {
|
|
73
|
+
name: "opencode",
|
|
74
|
+
displayName: "OpenCode",
|
|
75
|
+
skillsDir: ".opencode/skills",
|
|
76
|
+
globalSkillsDir: join(configHome, "opencode/skills"),
|
|
77
|
+
detectInstalled: () => existsSync(join(configHome, "opencode"))
|
|
78
|
+
},
|
|
79
|
+
roo: {
|
|
80
|
+
name: "roo",
|
|
81
|
+
displayName: "Roo Code",
|
|
82
|
+
skillsDir: ".roo/skills",
|
|
83
|
+
globalSkillsDir: join(home, ".roo/skills"),
|
|
84
|
+
detectInstalled: () => existsSync(join(home, ".roo"))
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
function detectInstalledAgents() {
|
|
88
|
+
return Object.entries(agents).filter(([_, config]) => config.detectInstalled()).map(([type]) => type);
|
|
89
|
+
}
|
|
90
|
+
function detectCurrentAgent() {
|
|
91
|
+
if (process.env.CLAUDE_CODE || process.env.CLAUDE_CONFIG_DIR) return "claude-code";
|
|
92
|
+
if (process.env.CURSOR_SESSION || process.env.CURSOR_TRACE_ID) return "cursor";
|
|
93
|
+
if (process.env.WINDSURF_SESSION) return "windsurf";
|
|
94
|
+
if (process.env.CLINE_TASK_ID) return "cline";
|
|
95
|
+
if (process.env.CODEX_HOME || process.env.CODEX_SESSION) return "codex";
|
|
96
|
+
if (process.env.GITHUB_COPILOT_SESSION) return "github-copilot";
|
|
97
|
+
if (process.env.GEMINI_API_KEY && process.env.GEMINI_SESSION) return "gemini-cli";
|
|
98
|
+
if (process.env.GOOSE_SESSION) return "goose";
|
|
99
|
+
if (process.env.AMP_SESSION) return "amp";
|
|
100
|
+
if (process.env.OPENCODE_SESSION) return "opencode";
|
|
101
|
+
if (process.env.ROO_SESSION) return "roo";
|
|
102
|
+
const cwd = process.cwd();
|
|
103
|
+
if (existsSync(join(cwd, ".claude"))) return "claude-code";
|
|
104
|
+
if (existsSync(join(cwd, ".cursor"))) return "cursor";
|
|
105
|
+
if (existsSync(join(cwd, ".windsurf"))) return "windsurf";
|
|
106
|
+
if (existsSync(join(cwd, ".cline"))) return "cline";
|
|
107
|
+
return null;
|
|
108
|
+
}
|
|
109
|
+
function sanitizeName(name) {
|
|
110
|
+
return name.toLowerCase().replace(/[^a-z0-9._]+/g, "-").replace(/^[.\-]+|[.\-]+$/g, "").slice(0, 255) || "unnamed-skill";
|
|
111
|
+
}
|
|
112
|
+
function installSkillForAgents(skillName, skillContent, options = {}) {
|
|
113
|
+
const isGlobal = options.global ?? false;
|
|
114
|
+
const cwd = options.cwd || process.cwd();
|
|
115
|
+
const sanitized = sanitizeName(skillName);
|
|
116
|
+
const targetAgents = options.agents || detectInstalledAgents();
|
|
117
|
+
const installed = [];
|
|
118
|
+
const paths = [];
|
|
119
|
+
for (const agentType of targetAgents) {
|
|
120
|
+
const agent = agents[agentType];
|
|
121
|
+
if (isGlobal && !agent.globalSkillsDir) continue;
|
|
122
|
+
const skillDir = join(isGlobal ? agent.globalSkillsDir : join(cwd, agent.skillsDir), sanitized);
|
|
123
|
+
mkdirSync(skillDir, { recursive: true });
|
|
124
|
+
writeFileSync(join(skillDir, "SKILL.md"), skillContent);
|
|
125
|
+
if (options.files) for (const [filename, content] of Object.entries(options.files)) writeFileSync(join(skillDir, filename), content);
|
|
126
|
+
installed.push(agentType);
|
|
127
|
+
paths.push(skillDir);
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
installed,
|
|
131
|
+
paths
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function generateSkillMd(meta, body) {
|
|
135
|
+
const { name, version, description: packageDescription } = meta;
|
|
136
|
+
const description = packageDescription ? `${packageDescription} Use this skill when working with ${name}, importing from "${name}", or when the user asks about ${name} features, API, or usage.` : `Documentation for ${name}. Use this skill when working with ${name} or importing from "${name}".`;
|
|
137
|
+
const frontmatter = [
|
|
138
|
+
"---",
|
|
139
|
+
`name: ${name}`,
|
|
140
|
+
`description: ${description}`
|
|
141
|
+
];
|
|
142
|
+
if (version) frontmatter.push(`version: "${version}"`);
|
|
143
|
+
frontmatter.push("---");
|
|
144
|
+
return frontmatter.join("\n") + "\n\n" + body;
|
|
145
|
+
}
|
|
146
|
+
export { agents, detectCurrentAgent, detectInstalledAgents, generateSkillMd, installSkillForAgents, sanitizeName };
|
|
147
|
+
|
|
148
|
+
//# sourceMappingURL=agents.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.mjs","names":[],"sources":["../src/agents.ts"],"sourcesContent":["/**\n * Agent detection and skill installation\n * Writes directly to agent skill directories in the project\n */\n\nimport { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { homedir } from 'node:os'\n\nconst home = homedir()\nconst configHome = process.env.XDG_CONFIG_HOME || join(home, '.config')\nconst claudeHome = process.env.CLAUDE_CONFIG_DIR || join(home, '.claude')\nconst codexHome = process.env.CODEX_HOME || join(home, '.codex')\n\nexport type AgentType =\n | 'claude-code'\n | 'cursor'\n | 'windsurf'\n | 'cline'\n | 'codex'\n | 'github-copilot'\n | 'gemini-cli'\n | 'goose'\n | 'amp'\n | 'opencode'\n | 'roo'\n\nexport interface AgentConfig {\n name: AgentType\n displayName: string\n /** Project-level skills directory (e.g., .claude/skills) */\n skillsDir: string\n /** Global skills directory (e.g., ~/.claude/skills) */\n globalSkillsDir: string | undefined\n /** Check if agent is installed on the system */\n detectInstalled: () => boolean\n}\n\nexport const agents: Record<AgentType, AgentConfig> = {\n 'claude-code': {\n name: 'claude-code',\n displayName: 'Claude Code',\n skillsDir: '.claude/skills',\n globalSkillsDir: join(claudeHome, 'skills'),\n detectInstalled: () => existsSync(claudeHome),\n },\n cursor: {\n name: 'cursor',\n displayName: 'Cursor',\n skillsDir: '.cursor/skills',\n globalSkillsDir: join(home, '.cursor/skills'),\n detectInstalled: () => existsSync(join(home, '.cursor')),\n },\n windsurf: {\n name: 'windsurf',\n displayName: 'Windsurf',\n skillsDir: '.windsurf/skills',\n globalSkillsDir: join(home, '.codeium/windsurf/skills'),\n detectInstalled: () => existsSync(join(home, '.codeium/windsurf')),\n },\n cline: {\n name: 'cline',\n displayName: 'Cline',\n skillsDir: '.cline/skills',\n globalSkillsDir: join(home, '.cline/skills'),\n detectInstalled: () => existsSync(join(home, '.cline')),\n },\n codex: {\n name: 'codex',\n displayName: 'Codex',\n skillsDir: '.codex/skills',\n globalSkillsDir: join(codexHome, 'skills'),\n detectInstalled: () => existsSync(codexHome),\n },\n 'github-copilot': {\n name: 'github-copilot',\n displayName: 'GitHub Copilot',\n skillsDir: '.github/skills',\n globalSkillsDir: join(home, '.copilot/skills'),\n detectInstalled: () => existsSync(join(home, '.copilot')),\n },\n 'gemini-cli': {\n name: 'gemini-cli',\n displayName: 'Gemini CLI',\n skillsDir: '.gemini/skills',\n globalSkillsDir: join(home, '.gemini/skills'),\n detectInstalled: () => existsSync(join(home, '.gemini')),\n },\n goose: {\n name: 'goose',\n displayName: 'Goose',\n skillsDir: '.goose/skills',\n globalSkillsDir: join(configHome, 'goose/skills'),\n detectInstalled: () => existsSync(join(configHome, 'goose')),\n },\n amp: {\n name: 'amp',\n displayName: 'Amp',\n skillsDir: '.agents/skills',\n globalSkillsDir: join(configHome, 'agents/skills'),\n detectInstalled: () => existsSync(join(configHome, 'amp')),\n },\n opencode: {\n name: 'opencode',\n displayName: 'OpenCode',\n skillsDir: '.opencode/skills',\n globalSkillsDir: join(configHome, 'opencode/skills'),\n detectInstalled: () => existsSync(join(configHome, 'opencode')),\n },\n roo: {\n name: 'roo',\n displayName: 'Roo Code',\n skillsDir: '.roo/skills',\n globalSkillsDir: join(home, '.roo/skills'),\n detectInstalled: () => existsSync(join(home, '.roo')),\n },\n}\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 which agent is currently running this command\n * Returns the active agent based on environment variables and context\n */\nexport function detectCurrentAgent(): AgentType | null {\n // Check environment variables set by agents\n if (process.env.CLAUDE_CODE || process.env.CLAUDE_CONFIG_DIR) {\n return 'claude-code'\n }\n if (process.env.CURSOR_SESSION || process.env.CURSOR_TRACE_ID) {\n return 'cursor'\n }\n if (process.env.WINDSURF_SESSION) {\n return 'windsurf'\n }\n if (process.env.CLINE_TASK_ID) {\n return 'cline'\n }\n if (process.env.CODEX_HOME || process.env.CODEX_SESSION) {\n return 'codex'\n }\n if (process.env.GITHUB_COPILOT_SESSION) {\n return 'github-copilot'\n }\n if (process.env.GEMINI_API_KEY && process.env.GEMINI_SESSION) {\n return 'gemini-cli'\n }\n if (process.env.GOOSE_SESSION) {\n return 'goose'\n }\n if (process.env.AMP_SESSION) {\n return 'amp'\n }\n if (process.env.OPENCODE_SESSION) {\n return 'opencode'\n }\n if (process.env.ROO_SESSION) {\n return 'roo'\n }\n\n // Check for project-level agent config directories\n const cwd = process.cwd()\n if (existsSync(join(cwd, '.claude'))) {\n return 'claude-code'\n }\n if (existsSync(join(cwd, '.cursor'))) {\n return 'cursor'\n }\n if (existsSync(join(cwd, '.windsurf'))) {\n return 'windsurf'\n }\n if (existsSync(join(cwd, '.cline'))) {\n return 'cline'\n }\n\n return null\n}\n\n/**\n * Sanitize skill name for filesystem\n */\nexport function sanitizeName(name: string): string {\n return name\n .toLowerCase()\n .replace(/[^a-z0-9._]+/g, '-')\n .replace(/^[.\\-]+|[.\\-]+$/g, '')\n .slice(0, 255) || 'unnamed-skill'\n}\n\n/**\n * Install a skill directly to agent skill directories\n * Writes to each agent's skill folder in the project (e.g., .claude/skills/package-name/)\n */\nexport function installSkillForAgents(\n skillName: string,\n skillContent: string,\n options: {\n global?: boolean\n cwd?: string\n agents?: AgentType[]\n /** Additional files to write (filename -> content) */\n files?: Record<string, string>\n } = {},\n): { installed: AgentType[], paths: string[] } {\n const isGlobal = options.global ?? false\n const cwd = options.cwd || process.cwd()\n const sanitized = sanitizeName(skillName)\n\n // Use specified agents or detect installed\n const targetAgents = options.agents || detectInstalledAgents()\n\n const installed: AgentType[] = []\n const paths: string[] = []\n\n for (const agentType of targetAgents) {\n const agent = agents[agentType]\n\n // Skip if agent doesn't support global installation\n if (isGlobal && !agent.globalSkillsDir) continue\n\n // Determine target directory\n const baseDir = isGlobal ? agent.globalSkillsDir! : join(cwd, agent.skillsDir)\n const skillDir = join(baseDir, sanitized)\n\n // Create directory and write files\n mkdirSync(skillDir, { recursive: true })\n writeFileSync(join(skillDir, 'SKILL.md'), skillContent)\n\n // Write additional files\n if (options.files) {\n for (const [filename, content] of Object.entries(options.files)) {\n writeFileSync(join(skillDir, filename), content)\n }\n }\n\n installed.push(agentType)\n paths.push(skillDir)\n }\n\n return { installed, paths }\n}\n\nexport interface SkillMetadata {\n name: string\n version?: string\n description?: string\n}\n\n/**\n * Generate SKILL.md frontmatter content\n * The description tells the agent when to use this skill\n */\nexport function generateSkillMd(\n meta: SkillMetadata,\n body: string,\n): string {\n const { name, version, description: packageDescription } = meta\n\n // Create an actionable description that tells the agent when to use this skill\n const description = packageDescription\n ? `${packageDescription} Use this skill when working with ${name}, importing from \"${name}\", or when the user asks about ${name} features, API, or usage.`\n : `Documentation for ${name}. Use this skill when working with ${name} or importing from \"${name}\".`\n\n const frontmatter = [\n '---',\n `name: ${name}`,\n `description: ${description}`,\n ]\n\n if (version) {\n frontmatter.push(`version: \"${version}\"`)\n }\n\n frontmatter.push('---')\n\n return frontmatter.join('\\n') + '\\n\\n' + body\n}\n"],"mappings":"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"}
|
package/dist/cli.d.mts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|