@skunkceo/cli 1.0.0
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 +43 -0
- package/bin/skunk.js +178 -0
- package/package.json +16 -0
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Skunk CLI
|
|
2
|
+
|
|
3
|
+
Install and manage [Skunk Global](https://skunkglobal.com) skills for OpenClaw.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install -g @skunkglobal/cli
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Install a skill
|
|
15
|
+
skunk install wordpress-studio
|
|
16
|
+
|
|
17
|
+
# List installed skills
|
|
18
|
+
skunk list
|
|
19
|
+
|
|
20
|
+
# See available skills
|
|
21
|
+
skunk available
|
|
22
|
+
|
|
23
|
+
# Remove a skill
|
|
24
|
+
skunk remove wordpress-studio
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Available Skills
|
|
28
|
+
|
|
29
|
+
Browse all skills at: https://github.com/skunkceo/openclaw-skills
|
|
30
|
+
|
|
31
|
+
## What are Skills?
|
|
32
|
+
|
|
33
|
+
Skills teach OpenClaw how to use specific tools and services. Each skill contains instructions that help your AI assistant understand:
|
|
34
|
+
|
|
35
|
+
- What commands to run
|
|
36
|
+
- How to interpret results
|
|
37
|
+
- Best practices for the tool
|
|
38
|
+
|
|
39
|
+
## Links
|
|
40
|
+
|
|
41
|
+
- [Skunk Global](https://skunkglobal.com)
|
|
42
|
+
- [Skills Repository](https://github.com/skunkceo/openclaw-skills)
|
|
43
|
+
- [OpenClaw](https://openclaw.ai)
|
package/bin/skunk.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const { execSync } = require('child_process');
|
|
7
|
+
|
|
8
|
+
const SKILLS_REPO = 'skunkceo/openclaw-skills';
|
|
9
|
+
const SKILLS_BRANCH = 'main';
|
|
10
|
+
const OPENCLAW_DIR = path.join(process.env.HOME, '.openclaw', 'skills');
|
|
11
|
+
|
|
12
|
+
const commands = {
|
|
13
|
+
install: installSkill,
|
|
14
|
+
list: listSkills,
|
|
15
|
+
available: listAvailable,
|
|
16
|
+
remove: removeSkill,
|
|
17
|
+
help: showHelp,
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
const command = args[0] || 'help';
|
|
22
|
+
const skillName = args[1];
|
|
23
|
+
|
|
24
|
+
if (commands[command]) {
|
|
25
|
+
commands[command](skillName);
|
|
26
|
+
} else {
|
|
27
|
+
console.log(`Unknown command: ${command}`);
|
|
28
|
+
showHelp();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function showHelp() {
|
|
32
|
+
console.log(`
|
|
33
|
+
🦨 Skunk CLI - Install skills for OpenClaw
|
|
34
|
+
|
|
35
|
+
Usage:
|
|
36
|
+
skunk install <skill> Install a skill
|
|
37
|
+
skunk remove <skill> Remove an installed skill
|
|
38
|
+
skunk list List installed skills
|
|
39
|
+
skunk available List available skills
|
|
40
|
+
skunk help Show this help
|
|
41
|
+
|
|
42
|
+
Examples:
|
|
43
|
+
skunk install wordpress-studio
|
|
44
|
+
skunk install seo-analyzer
|
|
45
|
+
skunk list
|
|
46
|
+
|
|
47
|
+
Skills: https://github.com/skunkceo/openclaw-skills
|
|
48
|
+
`);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function listSkills() {
|
|
52
|
+
if (!fs.existsSync(OPENCLAW_DIR)) {
|
|
53
|
+
console.log('No skills installed yet.');
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const skills = fs.readdirSync(OPENCLAW_DIR).filter(f => {
|
|
58
|
+
const skillPath = path.join(OPENCLAW_DIR, f);
|
|
59
|
+
return fs.statSync(skillPath).isDirectory() &&
|
|
60
|
+
fs.existsSync(path.join(skillPath, 'SKILL.md'));
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
if (skills.length === 0) {
|
|
64
|
+
console.log('No skills installed yet.');
|
|
65
|
+
} else {
|
|
66
|
+
console.log('Installed skills:');
|
|
67
|
+
skills.forEach(s => console.log(` - ${s}`));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function listAvailable() {
|
|
72
|
+
console.log('Fetching available skills...\n');
|
|
73
|
+
|
|
74
|
+
const url = `https://api.github.com/repos/${SKILLS_REPO}/contents/skills?ref=${SKILLS_BRANCH}`;
|
|
75
|
+
|
|
76
|
+
https.get(url, { headers: { 'User-Agent': 'skunk-cli' } }, (res) => {
|
|
77
|
+
let data = '';
|
|
78
|
+
res.on('data', chunk => data += chunk);
|
|
79
|
+
res.on('end', () => {
|
|
80
|
+
try {
|
|
81
|
+
const skills = JSON.parse(data);
|
|
82
|
+
console.log('Available skills:');
|
|
83
|
+
skills.filter(s => s.type === 'dir').forEach(s => {
|
|
84
|
+
console.log(` - ${s.name}`);
|
|
85
|
+
});
|
|
86
|
+
console.log('\nInstall with: skunk install <skill-name>');
|
|
87
|
+
} catch (e) {
|
|
88
|
+
console.error('Failed to fetch skills list');
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}).on('error', (e) => {
|
|
92
|
+
console.error('Failed to fetch skills:', e.message);
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async function installSkill(name) {
|
|
97
|
+
if (!name) {
|
|
98
|
+
console.log('Usage: skunk install <skill-name>');
|
|
99
|
+
console.log('Run "skunk available" to see available skills');
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
console.log(`Installing ${name}...`);
|
|
104
|
+
|
|
105
|
+
// Create skills directory if it doesn't exist
|
|
106
|
+
if (!fs.existsSync(OPENCLAW_DIR)) {
|
|
107
|
+
fs.mkdirSync(OPENCLAW_DIR, { recursive: true });
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const skillDir = path.join(OPENCLAW_DIR, name);
|
|
111
|
+
|
|
112
|
+
if (fs.existsSync(skillDir)) {
|
|
113
|
+
console.log(`Skill ${name} is already installed. Remove it first with: skunk remove ${name}`);
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Fetch skill files from GitHub
|
|
118
|
+
const files = ['SKILL.md', 'config.json', 'README.md'];
|
|
119
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
120
|
+
|
|
121
|
+
let success = false;
|
|
122
|
+
|
|
123
|
+
for (const file of files) {
|
|
124
|
+
const url = `https://raw.githubusercontent.com/${SKILLS_REPO}/${SKILLS_BRANCH}/skills/${name}/${file}`;
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
const content = await fetchFile(url);
|
|
128
|
+
if (content) {
|
|
129
|
+
fs.writeFileSync(path.join(skillDir, file), content);
|
|
130
|
+
if (file === 'SKILL.md') success = true;
|
|
131
|
+
}
|
|
132
|
+
} catch (e) {
|
|
133
|
+
// README might not exist, that's ok
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (success) {
|
|
138
|
+
console.log(`✓ Installed ${name} to ${skillDir}`);
|
|
139
|
+
} else {
|
|
140
|
+
fs.rmSync(skillDir, { recursive: true, force: true });
|
|
141
|
+
console.log(`✗ Skill "${name}" not found. Run "skunk available" to see available skills.`);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function removeSkill(name) {
|
|
146
|
+
if (!name) {
|
|
147
|
+
console.log('Usage: skunk remove <skill-name>');
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const skillDir = path.join(OPENCLAW_DIR, name);
|
|
152
|
+
|
|
153
|
+
if (!fs.existsSync(skillDir)) {
|
|
154
|
+
console.log(`Skill ${name} is not installed.`);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
fs.rmSync(skillDir, { recursive: true, force: true });
|
|
159
|
+
console.log(`✓ Removed ${name}`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function fetchFile(url) {
|
|
163
|
+
return new Promise((resolve, reject) => {
|
|
164
|
+
https.get(url, { headers: { 'User-Agent': 'skunk-cli' } }, (res) => {
|
|
165
|
+
if (res.statusCode === 404) {
|
|
166
|
+
resolve(null);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (res.statusCode !== 200) {
|
|
170
|
+
reject(new Error(`HTTP ${res.statusCode}`));
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
let data = '';
|
|
174
|
+
res.on('data', chunk => data += chunk);
|
|
175
|
+
res.on('end', () => resolve(data));
|
|
176
|
+
}).on('error', reject);
|
|
177
|
+
});
|
|
178
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skunkceo/cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Install and manage Skunk Global skills for OpenClaw",
|
|
5
|
+
"bin": {
|
|
6
|
+
"skunk": "./bin/skunk.js"
|
|
7
|
+
},
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/skunkceo/skunk-cli"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["openclaw", "skills", "wordpress", "ai", "skunk"],
|
|
13
|
+
"author": "Skunk Global",
|
|
14
|
+
"license": "MIT",
|
|
15
|
+
"homepage": "https://skunkglobal.com/skills"
|
|
16
|
+
}
|