@skill-hq/cli 0.1.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/dist/commands/auth.d.ts +3 -0
- package/dist/commands/auth.d.ts.map +1 -0
- package/dist/commands/auth.js +114 -0
- package/dist/commands/auth.js.map +1 -0
- package/dist/commands/install.d.ts +3 -0
- package/dist/commands/install.d.ts.map +1 -0
- package/dist/commands/install.js +103 -0
- package/dist/commands/install.js.map +1 -0
- package/dist/commands/manage.d.ts +6 -0
- package/dist/commands/manage.d.ts.map +1 -0
- package/dist/commands/manage.js +156 -0
- package/dist/commands/manage.js.map +1 -0
- package/dist/commands/marketplace.d.ts +4 -0
- package/dist/commands/marketplace.d.ts.map +1 -0
- package/dist/commands/marketplace.js +88 -0
- package/dist/commands/marketplace.js.map +1 -0
- package/dist/commands/publish.d.ts +3 -0
- package/dist/commands/publish.d.ts.map +1 -0
- package/dist/commands/publish.js +105 -0
- package/dist/commands/publish.js.map +1 -0
- package/dist/commands/validate.d.ts +16 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +155 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/utils/api.d.ts +9 -0
- package/dist/utils/api.d.ts.map +1 -0
- package/dist/utils/api.js +42 -0
- package/dist/utils/api.js.map +1 -0
- package/dist/utils/config.d.ts +19 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +61 -0
- package/dist/utils/config.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AASpC,eAAO,MAAM,WAAW,SACe,CAAC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { createServer } from 'http';
|
|
3
|
+
import { randomBytes } from 'crypto';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import open from 'open';
|
|
7
|
+
import { getAuthConfig, saveAuthConfig, deleteAuthConfig, getApiUrl } from '../utils/config.js';
|
|
8
|
+
import { apiFetch } from '../utils/api.js';
|
|
9
|
+
export const authCommand = new Command('auth')
|
|
10
|
+
.description('Manage authentication');
|
|
11
|
+
authCommand
|
|
12
|
+
.command('login')
|
|
13
|
+
.description('Log in to SkillHQ via browser')
|
|
14
|
+
.action(async () => {
|
|
15
|
+
const existing = getAuthConfig();
|
|
16
|
+
if (existing) {
|
|
17
|
+
console.log(chalk.yellow('Already logged in. Use `skillhq auth logout` first to switch accounts.'));
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const nonce = randomBytes(32).toString('hex');
|
|
21
|
+
const spinner = ora('Waiting for browser authentication...').start();
|
|
22
|
+
const server = createServer();
|
|
23
|
+
const tokenPromise = new Promise((resolve, reject) => {
|
|
24
|
+
const timeout = setTimeout(() => {
|
|
25
|
+
server.close();
|
|
26
|
+
reject(new Error('Authentication timed out after 60 seconds'));
|
|
27
|
+
}, 60_000);
|
|
28
|
+
server.on('request', async (req, res) => {
|
|
29
|
+
const url = new URL(req.url, `http://localhost`);
|
|
30
|
+
if (url.pathname === '/callback') {
|
|
31
|
+
const code = url.searchParams.get('code');
|
|
32
|
+
const error = url.searchParams.get('error');
|
|
33
|
+
if (error) {
|
|
34
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
35
|
+
res.end('<html><body><h1>Authentication failed</h1><p>You can close this tab.</p></body></html>');
|
|
36
|
+
clearTimeout(timeout);
|
|
37
|
+
server.close();
|
|
38
|
+
reject(new Error(`Authentication failed: ${error}`));
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (!code) {
|
|
42
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
43
|
+
res.end('<html><body><h1>Missing authorization code</h1></body></html>');
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const result = await apiFetch('/api/cli/token', {
|
|
48
|
+
method: 'POST',
|
|
49
|
+
body: { code, nonce },
|
|
50
|
+
});
|
|
51
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
52
|
+
res.end('<html><body><h1>Authenticated!</h1><p>You can close this tab and return to the terminal.</p></body></html>');
|
|
53
|
+
clearTimeout(timeout);
|
|
54
|
+
server.close();
|
|
55
|
+
resolve(result);
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
res.writeHead(500, { 'Content-Type': 'text/html' });
|
|
59
|
+
res.end('<html><body><h1>Token exchange failed</h1></body></html>');
|
|
60
|
+
clearTimeout(timeout);
|
|
61
|
+
server.close();
|
|
62
|
+
reject(err);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
server.listen(0, async () => {
|
|
68
|
+
const address = server.address();
|
|
69
|
+
if (!address || typeof address === 'string') {
|
|
70
|
+
spinner.fail('Failed to start local server');
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const port = address.port;
|
|
74
|
+
const authUrl = `${getApiUrl()}/cli/auth?redirect=http://localhost:${port}/callback&nonce=${nonce}`;
|
|
75
|
+
spinner.text = 'Opening browser for authentication...';
|
|
76
|
+
await open(authUrl);
|
|
77
|
+
spinner.text = 'Waiting for browser authentication...';
|
|
78
|
+
});
|
|
79
|
+
try {
|
|
80
|
+
const result = await tokenPromise;
|
|
81
|
+
saveAuthConfig(result);
|
|
82
|
+
spinner.succeed(chalk.green('Successfully logged in!'));
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
spinner.fail(chalk.red(`Login failed: ${err.message}`));
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
authCommand
|
|
90
|
+
.command('logout')
|
|
91
|
+
.description('Log out of SkillHQ')
|
|
92
|
+
.action(() => {
|
|
93
|
+
deleteAuthConfig();
|
|
94
|
+
console.log(chalk.green('Logged out successfully.'));
|
|
95
|
+
});
|
|
96
|
+
authCommand
|
|
97
|
+
.command('status')
|
|
98
|
+
.description('Show current authentication status')
|
|
99
|
+
.action(async () => {
|
|
100
|
+
const config = getAuthConfig();
|
|
101
|
+
if (!config) {
|
|
102
|
+
console.log(chalk.yellow('Not logged in.'));
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
const user = await apiFetch('/api/cli/me', { token: config.token });
|
|
107
|
+
console.log(chalk.green(`Logged in as ${user.name || user.email}`));
|
|
108
|
+
console.log(` Token expires: ${new Date(config.expiresAt).toLocaleDateString()}`);
|
|
109
|
+
}
|
|
110
|
+
catch {
|
|
111
|
+
console.log(chalk.yellow('Token may be invalid. Try logging in again.'));
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4CpC,eAAO,MAAM,cAAc,SAoEvB,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync, rmSync } from 'fs';
|
|
3
|
+
import { join, resolve, normalize } from 'path';
|
|
4
|
+
import { homedir } from 'os';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import ora from 'ora';
|
|
7
|
+
import JSZip from 'jszip';
|
|
8
|
+
import { requireAuth, getInstalledSkills, saveInstalledSkills } from '../utils/config.js';
|
|
9
|
+
import { apiFetch } from '../utils/api.js';
|
|
10
|
+
function safePath(installDir, entryPath) {
|
|
11
|
+
const resolved = resolve(installDir, normalize(entryPath));
|
|
12
|
+
if (!resolved.startsWith(resolve(installDir))) {
|
|
13
|
+
throw new Error(`Zip entry path escapes install directory: ${entryPath}`);
|
|
14
|
+
}
|
|
15
|
+
return resolved;
|
|
16
|
+
}
|
|
17
|
+
async function downloadAndExtract(downloadUrl, installDir) {
|
|
18
|
+
const res = await fetch(downloadUrl);
|
|
19
|
+
if (!res.ok)
|
|
20
|
+
throw new Error(`Download failed: ${res.status}`);
|
|
21
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
22
|
+
const zip = await JSZip.loadAsync(buffer);
|
|
23
|
+
// Clean existing directory
|
|
24
|
+
if (existsSync(installDir)) {
|
|
25
|
+
rmSync(installDir, { recursive: true });
|
|
26
|
+
}
|
|
27
|
+
mkdirSync(installDir, { recursive: true });
|
|
28
|
+
for (const [path, file] of Object.entries(zip.files)) {
|
|
29
|
+
const fullPath = safePath(installDir, path);
|
|
30
|
+
if (file.dir) {
|
|
31
|
+
mkdirSync(fullPath, { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
const dir = join(fullPath, '..');
|
|
35
|
+
mkdirSync(dir, { recursive: true });
|
|
36
|
+
const content = await file.async('nodebuffer');
|
|
37
|
+
writeFileSync(fullPath, content);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
export const installCommand = new Command('install')
|
|
42
|
+
.description('Install a skill from the SkillHQ marketplace')
|
|
43
|
+
.argument('<name>', 'Skill name or slug')
|
|
44
|
+
.option('--global', 'Install to ~/.claude/skills/ (default)', true)
|
|
45
|
+
.option('--project', 'Install to ./.claude/skills/ in current project')
|
|
46
|
+
.action(async (name, options) => {
|
|
47
|
+
const auth = requireAuth();
|
|
48
|
+
const baseDir = options.project
|
|
49
|
+
? join(process.cwd(), '.claude', 'skills')
|
|
50
|
+
: join(homedir(), '.claude', 'skills');
|
|
51
|
+
const installDir = join(baseDir, name);
|
|
52
|
+
// Check if already installed
|
|
53
|
+
const installed = getInstalledSkills();
|
|
54
|
+
if (installed[name]) {
|
|
55
|
+
console.log(chalk.yellow(` ${name} is already installed at ${installed[name].path}`));
|
|
56
|
+
console.log(` Use ${chalk.bold('skillhq update ' + name)} to update, or reinstall with ${chalk.bold('skillhq remove ' + name)} first.`);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Request download URL
|
|
60
|
+
const spinner = ora(`Fetching ${name}...`).start();
|
|
61
|
+
let downloadUrl;
|
|
62
|
+
let version;
|
|
63
|
+
try {
|
|
64
|
+
const result = await apiFetch('/api/skills/download', {
|
|
65
|
+
method: 'POST',
|
|
66
|
+
token: auth.token,
|
|
67
|
+
body: { slug: name },
|
|
68
|
+
});
|
|
69
|
+
downloadUrl = result.downloadUrl;
|
|
70
|
+
version = result.version;
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
spinner.fail(`Failed to fetch ${name}`);
|
|
74
|
+
const msg = err.message;
|
|
75
|
+
if (msg.includes('404')) {
|
|
76
|
+
console.log(chalk.red(` Skill "${name}" not found.`));
|
|
77
|
+
}
|
|
78
|
+
else if (msg.includes('403')) {
|
|
79
|
+
console.log(chalk.red(` You haven't purchased "${name}". Visit the marketplace to buy it.`));
|
|
80
|
+
}
|
|
81
|
+
else if (msg.includes('429')) {
|
|
82
|
+
console.log(chalk.red(` Download limit reached for "${name}". Contact support for assistance.`));
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
console.log(chalk.red(` ${msg}`));
|
|
86
|
+
}
|
|
87
|
+
process.exit(1);
|
|
88
|
+
}
|
|
89
|
+
spinner.succeed(`Found ${name} v${version}`);
|
|
90
|
+
// Download and extract
|
|
91
|
+
const dlSpinner = ora('Downloading and installing...').start();
|
|
92
|
+
await downloadAndExtract(downloadUrl, installDir);
|
|
93
|
+
dlSpinner.succeed('Installed successfully');
|
|
94
|
+
// Update tracking
|
|
95
|
+
installed[name] = {
|
|
96
|
+
version,
|
|
97
|
+
installedAt: new Date().toISOString(),
|
|
98
|
+
path: installDir,
|
|
99
|
+
};
|
|
100
|
+
saveInstalledSkills(installed);
|
|
101
|
+
console.log(chalk.green(`\n ✓ ${name} v${version} installed to ${installDir}\n`));
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage.d.ts","sourceRoot":"","sources":["../../src/commands/manage.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgBpC,eAAO,MAAM,WAAW,SAqBpB,CAAC;AAEL,eAAO,MAAM,eAAe,SA+CxB,CAAC;AAEL,eAAO,MAAM,aAAa,SA2DtB,CAAC;AAEL,eAAO,MAAM,aAAa,SAkCtB,CAAC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { existsSync, rmSync } from 'fs';
|
|
3
|
+
import { resolve, normalize } from 'path';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import { getInstalledSkills, saveInstalledSkills, requireAuth } from '../utils/config.js';
|
|
7
|
+
import { apiFetch } from '../utils/api.js';
|
|
8
|
+
function safePath(baseDir, entryPath) {
|
|
9
|
+
const resolved = resolve(baseDir, normalize(entryPath));
|
|
10
|
+
if (!resolved.startsWith(resolve(baseDir))) {
|
|
11
|
+
throw new Error(`Zip entry path escapes install directory: ${entryPath}`);
|
|
12
|
+
}
|
|
13
|
+
return resolved;
|
|
14
|
+
}
|
|
15
|
+
export const listCommand = new Command('list')
|
|
16
|
+
.description('List installed skills')
|
|
17
|
+
.action(() => {
|
|
18
|
+
const skills = getInstalledSkills();
|
|
19
|
+
const entries = Object.entries(skills);
|
|
20
|
+
if (entries.length === 0) {
|
|
21
|
+
console.log(chalk.yellow('\n No skills installed.\n'));
|
|
22
|
+
console.log(` Use ${chalk.bold('skillhq search <query>')} to find skills.`);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
console.log(chalk.bold('\n Installed Skills\n'));
|
|
26
|
+
console.log(` ${'Name'.padEnd(25)} ${'Version'.padEnd(12)} ${'Installed'.padEnd(14)} Path`);
|
|
27
|
+
console.log(` ${'─'.repeat(25)} ${'─'.repeat(12)} ${'─'.repeat(14)} ${'─'.repeat(30)}`);
|
|
28
|
+
for (const [name, info] of entries) {
|
|
29
|
+
const date = new Date(info.installedAt).toLocaleDateString();
|
|
30
|
+
console.log(` ${name.padEnd(25)} ${info.version.padEnd(12)} ${date.padEnd(14)} ${info.path}`);
|
|
31
|
+
}
|
|
32
|
+
console.log();
|
|
33
|
+
});
|
|
34
|
+
export const outdatedCommand = new Command('outdated')
|
|
35
|
+
.description('Check for available skill updates')
|
|
36
|
+
.action(async () => {
|
|
37
|
+
const auth = requireAuth();
|
|
38
|
+
const skills = getInstalledSkills();
|
|
39
|
+
const entries = Object.entries(skills);
|
|
40
|
+
if (entries.length === 0) {
|
|
41
|
+
console.log(chalk.yellow('\n No skills installed.\n'));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const spinner = ora('Checking for updates...').start();
|
|
45
|
+
const results = [];
|
|
46
|
+
for (const [name, info] of entries) {
|
|
47
|
+
try {
|
|
48
|
+
const remote = await apiFetch(`/api/skills/${name}`, { token: auth.token });
|
|
49
|
+
results.push({
|
|
50
|
+
name,
|
|
51
|
+
installed: info.version,
|
|
52
|
+
latest: remote.version,
|
|
53
|
+
hasUpdate: remote.version !== info.version,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
catch {
|
|
57
|
+
results.push({ name, installed: info.version, latest: '?', hasUpdate: false });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
spinner.stop();
|
|
61
|
+
const updatable = results.filter(r => r.hasUpdate);
|
|
62
|
+
if (updatable.length === 0) {
|
|
63
|
+
console.log(chalk.green('\n All skills are up to date!\n'));
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
console.log(chalk.bold('\n Updates Available\n'));
|
|
67
|
+
console.log(` ${'Name'.padEnd(25)} ${'Installed'.padEnd(12)} ${'Latest'.padEnd(12)} Status`);
|
|
68
|
+
console.log(` ${'─'.repeat(25)} ${'─'.repeat(12)} ${'─'.repeat(12)} ${'─'.repeat(16)}`);
|
|
69
|
+
for (const r of results) {
|
|
70
|
+
const status = r.hasUpdate
|
|
71
|
+
? chalk.yellow('update available')
|
|
72
|
+
: chalk.green('up to date');
|
|
73
|
+
console.log(` ${r.name.padEnd(25)} ${r.installed.padEnd(12)} ${r.latest.padEnd(12)} ${status}`);
|
|
74
|
+
}
|
|
75
|
+
console.log(`\n Run ${chalk.bold('skillhq update <name>')} to update.\n`);
|
|
76
|
+
});
|
|
77
|
+
export const updateCommand = new Command('update')
|
|
78
|
+
.description('Update an installed skill to the latest version')
|
|
79
|
+
.argument('<name>', 'Skill name to update')
|
|
80
|
+
.option('--all', 'Update all outdated skills')
|
|
81
|
+
.action(async (name) => {
|
|
82
|
+
const auth = requireAuth();
|
|
83
|
+
const skills = getInstalledSkills();
|
|
84
|
+
if (!skills[name]) {
|
|
85
|
+
console.log(chalk.red(`\n "${name}" is not installed.\n`));
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
88
|
+
const spinner = ora(`Updating ${name}...`).start();
|
|
89
|
+
try {
|
|
90
|
+
const { downloadUrl, version } = await apiFetch('/api/skills/download', { method: 'POST', token: auth.token, body: { slug: name } });
|
|
91
|
+
if (version === skills[name].version) {
|
|
92
|
+
spinner.succeed(`${name} is already at the latest version (${version})`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Download and extract using same logic as install
|
|
96
|
+
const JSZip = (await import('jszip')).default;
|
|
97
|
+
const { mkdirSync, writeFileSync, rmSync: rm } = await import('fs');
|
|
98
|
+
const { join } = await import('path');
|
|
99
|
+
const res = await fetch(downloadUrl);
|
|
100
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
101
|
+
const zip = await JSZip.loadAsync(buffer);
|
|
102
|
+
const installDir = skills[name].path;
|
|
103
|
+
rm(installDir, { recursive: true, force: true });
|
|
104
|
+
mkdirSync(installDir, { recursive: true });
|
|
105
|
+
for (const [path, file] of Object.entries(zip.files)) {
|
|
106
|
+
const fullPath = safePath(installDir, path);
|
|
107
|
+
if (file.dir) {
|
|
108
|
+
mkdirSync(fullPath, { recursive: true });
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
mkdirSync(join(fullPath, '..'), { recursive: true });
|
|
112
|
+
writeFileSync(fullPath, await file.async('nodebuffer'));
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
skills[name].version = version;
|
|
116
|
+
skills[name].installedAt = new Date().toISOString();
|
|
117
|
+
saveInstalledSkills(skills);
|
|
118
|
+
spinner.succeed(`Updated ${name} to v${version}`);
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
spinner.fail(`Failed to update ${name}`);
|
|
122
|
+
console.log(chalk.red(` ${err.message}`));
|
|
123
|
+
process.exit(1);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
export const removeCommand = new Command('remove')
|
|
127
|
+
.description('Remove an installed skill')
|
|
128
|
+
.argument('<name>', 'Skill name to remove')
|
|
129
|
+
.option('--force', 'Skip confirmation')
|
|
130
|
+
.action(async (name, options) => {
|
|
131
|
+
const skills = getInstalledSkills();
|
|
132
|
+
if (!skills[name]) {
|
|
133
|
+
console.log(chalk.red(`\n "${name}" is not installed.\n`));
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
if (!options.force) {
|
|
137
|
+
const { default: Enquirer } = await import('enquirer');
|
|
138
|
+
const enquirer = new Enquirer();
|
|
139
|
+
const response = await enquirer.prompt({
|
|
140
|
+
type: 'confirm',
|
|
141
|
+
name: 'confirm',
|
|
142
|
+
message: `Remove ${name} from ${skills[name].path}?`,
|
|
143
|
+
});
|
|
144
|
+
if (!response.confirm) {
|
|
145
|
+
console.log('Cancelled.');
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (existsSync(skills[name].path)) {
|
|
150
|
+
rmSync(skills[name].path, { recursive: true });
|
|
151
|
+
}
|
|
152
|
+
delete skills[name];
|
|
153
|
+
saveInstalledSkills(skills);
|
|
154
|
+
console.log(chalk.green(`\n ✓ Removed ${name}\n`));
|
|
155
|
+
});
|
|
156
|
+
//# sourceMappingURL=manage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manage.js","sourceRoot":"","sources":["../../src/commands/manage.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marketplace.d.ts","sourceRoot":"","sources":["../../src/commands/marketplace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,eAAO,MAAM,aAAa,SA+CtB,CAAC;AAEL,eAAO,MAAM,WAAW,SA4CpB,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import ora from 'ora';
|
|
4
|
+
import { getAuthConfig } from '../utils/config.js';
|
|
5
|
+
import { apiFetch } from '../utils/api.js';
|
|
6
|
+
export const searchCommand = new Command('search')
|
|
7
|
+
.description('Search the SkillHQ marketplace')
|
|
8
|
+
.argument('<query>', 'Search query')
|
|
9
|
+
.option('--category <category>', 'Filter by category')
|
|
10
|
+
.option('--min-price <price>', 'Minimum price in USD')
|
|
11
|
+
.option('--max-price <price>', 'Maximum price in USD')
|
|
12
|
+
.option('--limit <n>', 'Max results', '10')
|
|
13
|
+
.action(async (query, options) => {
|
|
14
|
+
const spinner = ora('Searching...').start();
|
|
15
|
+
const params = new URLSearchParams({ q: query, limit: options.limit });
|
|
16
|
+
if (options.category)
|
|
17
|
+
params.set('category', options.category);
|
|
18
|
+
if (options.minPrice)
|
|
19
|
+
params.set('min_price', String(Math.round(parseFloat(options.minPrice) * 100)));
|
|
20
|
+
if (options.maxPrice)
|
|
21
|
+
params.set('max_price', String(Math.round(parseFloat(options.maxPrice) * 100)));
|
|
22
|
+
const auth = getAuthConfig();
|
|
23
|
+
try {
|
|
24
|
+
const results = await apiFetch(`/api/skills?${params.toString()}`, { token: auth?.token });
|
|
25
|
+
spinner.stop();
|
|
26
|
+
if (results.skills.length === 0) {
|
|
27
|
+
console.log(chalk.yellow(`\n No skills found for "${query}".\n`));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
console.log(chalk.bold(`\n Results for "${query}"\n`));
|
|
31
|
+
console.log(` ${'Name'.padEnd(22)} ${'Price'.padEnd(10)} ${'Rating'.padEnd(8)} ${'Sales'.padEnd(8)} Description`);
|
|
32
|
+
console.log(` ${'─'.repeat(22)} ${'─'.repeat(10)} ${'─'.repeat(8)} ${'─'.repeat(8)} ${'─'.repeat(30)}`);
|
|
33
|
+
for (const skill of results.skills) {
|
|
34
|
+
const price = skill.price_cents === 0 ? 'Free' : `$${(skill.price_cents / 100).toFixed(2)}`;
|
|
35
|
+
const rating = skill.rating ? `${skill.rating.toFixed(1)}★` : '—';
|
|
36
|
+
const desc = skill.description.length > 40
|
|
37
|
+
? skill.description.slice(0, 37) + '...'
|
|
38
|
+
: skill.description;
|
|
39
|
+
console.log(` ${skill.name.padEnd(22)} ${price.padEnd(10)} ${rating.padEnd(8)} ${String(skill.sales_count).padEnd(8)} ${desc}`);
|
|
40
|
+
}
|
|
41
|
+
console.log();
|
|
42
|
+
}
|
|
43
|
+
catch (err) {
|
|
44
|
+
spinner.fail('Search failed');
|
|
45
|
+
console.log(chalk.red(` ${err.message}`));
|
|
46
|
+
process.exit(1);
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
export const infoCommand = new Command('info')
|
|
50
|
+
.description('Show detailed information about a skill')
|
|
51
|
+
.argument('<name>', 'Skill name or slug')
|
|
52
|
+
.action(async (name) => {
|
|
53
|
+
const spinner = ora(`Fetching ${name}...`).start();
|
|
54
|
+
const auth = getAuthConfig();
|
|
55
|
+
try {
|
|
56
|
+
const skill = await apiFetch(`/api/skills/${name}`, { token: auth?.token });
|
|
57
|
+
spinner.stop();
|
|
58
|
+
const price = skill.priceCents === 0 ? 'Free' : `$${(skill.priceCents / 100).toFixed(2)}`;
|
|
59
|
+
console.log(chalk.bold(`\n ${skill.name}`));
|
|
60
|
+
console.log(` ${skill.description}\n`);
|
|
61
|
+
console.log(` Price: ${price}`);
|
|
62
|
+
console.log(` Seller: ${skill.sellerName}`);
|
|
63
|
+
console.log(` Version: ${skill.version}`);
|
|
64
|
+
if (skill.compatibleWith.length > 0) {
|
|
65
|
+
console.log(` Works with: ${skill.compatibleWith.join(', ')}`);
|
|
66
|
+
}
|
|
67
|
+
if (skill.versions.length > 0) {
|
|
68
|
+
console.log(chalk.bold('\n Version History'));
|
|
69
|
+
for (const v of skill.versions.slice(0, 5)) {
|
|
70
|
+
const date = new Date(v.created_at).toLocaleDateString();
|
|
71
|
+
console.log(` ${v.version.padEnd(12)} ${date}${v.changelog ? ' ' + v.changelog : ''}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
console.log(`\n Install: ${chalk.bold(`skillhq install ${skill.slug}`)}\n`);
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
spinner.fail(`Failed to fetch ${name}`);
|
|
78
|
+
const msg = err.message;
|
|
79
|
+
if (msg.includes('404')) {
|
|
80
|
+
console.log(chalk.red(` Skill "${name}" not found.`));
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.log(chalk.red(` ${msg}`));
|
|
84
|
+
}
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
//# sourceMappingURL=marketplace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marketplace.js","sourceRoot":"","sources":["../../src/commands/marketplace.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.d.ts","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA+BpC,eAAO,MAAM,cAAc,SAgFvB,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { readdirSync, readFileSync } from 'fs';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import ora from 'ora';
|
|
5
|
+
import JSZip from 'jszip';
|
|
6
|
+
import { join } from 'path';
|
|
7
|
+
import { validateSkillDirectory } from './validate.js';
|
|
8
|
+
import { requireAuth, getApiUrl } from '../utils/config.js';
|
|
9
|
+
async function createZipBuffer(dir) {
|
|
10
|
+
const zip = new JSZip();
|
|
11
|
+
function addDir(currentDir, zipFolder) {
|
|
12
|
+
const entries = readdirSync(currentDir, { withFileTypes: true });
|
|
13
|
+
for (const entry of entries) {
|
|
14
|
+
if (entry.name.startsWith('.'))
|
|
15
|
+
continue;
|
|
16
|
+
const fullPath = join(currentDir, entry.name);
|
|
17
|
+
if (entry.isDirectory()) {
|
|
18
|
+
const folder = zipFolder.folder(entry.name);
|
|
19
|
+
if (folder)
|
|
20
|
+
addDir(fullPath, folder);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
zipFolder.file(entry.name, readFileSync(fullPath));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
addDir(dir, zip);
|
|
28
|
+
const buf = await zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE' });
|
|
29
|
+
return buf;
|
|
30
|
+
}
|
|
31
|
+
export const publishCommand = new Command('publish')
|
|
32
|
+
.description('Publish a skill to the SkillHQ marketplace')
|
|
33
|
+
.argument('<dir>', 'Path to skill directory')
|
|
34
|
+
.requiredOption('--price <amount>', 'Price in USD (e.g., 4.99)')
|
|
35
|
+
.requiredOption('--category <category>', 'Skill category')
|
|
36
|
+
.option('--tags <tags>', 'Comma-separated tags')
|
|
37
|
+
.option('--demo <text>', 'Demo output text or file path')
|
|
38
|
+
.option('--update', 'Update an existing listing')
|
|
39
|
+
.option('--changelog <text>', 'Changelog for updates')
|
|
40
|
+
.action(async (dir, options) => {
|
|
41
|
+
const auth = requireAuth();
|
|
42
|
+
// Validate locally first
|
|
43
|
+
const spinner = ora('Validating skill...').start();
|
|
44
|
+
const validation = validateSkillDirectory(dir);
|
|
45
|
+
if (validation.errors.length > 0) {
|
|
46
|
+
spinner.fail('Validation failed');
|
|
47
|
+
for (const error of validation.errors) {
|
|
48
|
+
console.log(chalk.red(` ✗ ${error}`));
|
|
49
|
+
}
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
spinner.succeed('Validation passed');
|
|
53
|
+
// Create ZIP in memory
|
|
54
|
+
const zipSpinner = ora('Creating package...').start();
|
|
55
|
+
const zipBuffer = await createZipBuffer(dir);
|
|
56
|
+
zipSpinner.succeed(`Package created (${(zipBuffer.length / 1024).toFixed(1)}KB)`);
|
|
57
|
+
// Send ZIP + metadata to server — validation and R2 upload happen server-side
|
|
58
|
+
const submitSpinner = ora('Uploading and publishing...').start();
|
|
59
|
+
const priceCents = Math.round(parseFloat(options.price) * 100);
|
|
60
|
+
const tags = options.tags ? options.tags.split(',').map((t) => t.trim()) : [];
|
|
61
|
+
const form = new FormData();
|
|
62
|
+
form.append('file', new Blob([new Uint8Array(zipBuffer)], { type: 'application/zip' }), 'skill.zip');
|
|
63
|
+
form.append('priceCents', String(priceCents));
|
|
64
|
+
form.append('compatibleWith', JSON.stringify(['claude-code']));
|
|
65
|
+
form.append('category', options.category);
|
|
66
|
+
if (tags.length)
|
|
67
|
+
form.append('tags', JSON.stringify(tags));
|
|
68
|
+
if (options.demo)
|
|
69
|
+
form.append('demoOutput', options.demo);
|
|
70
|
+
const res = await fetch(`${getApiUrl()}/api/skills/validate`, {
|
|
71
|
+
method: 'POST',
|
|
72
|
+
headers: { Authorization: `Bearer ${auth.token}` },
|
|
73
|
+
body: form,
|
|
74
|
+
});
|
|
75
|
+
if (!res.ok) {
|
|
76
|
+
submitSpinner.fail('Publish failed');
|
|
77
|
+
const text = await res.text();
|
|
78
|
+
let message;
|
|
79
|
+
try {
|
|
80
|
+
const json = JSON.parse(text);
|
|
81
|
+
if (json.errors) {
|
|
82
|
+
for (const err of json.errors) {
|
|
83
|
+
console.log(chalk.red(` ✗ ${err.message}`));
|
|
84
|
+
}
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
message = json.error || json.message || text;
|
|
88
|
+
}
|
|
89
|
+
catch {
|
|
90
|
+
message = text;
|
|
91
|
+
}
|
|
92
|
+
console.log(chalk.red(` ${message}`));
|
|
93
|
+
process.exit(1);
|
|
94
|
+
}
|
|
95
|
+
const result = await res.json();
|
|
96
|
+
submitSpinner.succeed('Skill published!');
|
|
97
|
+
if (result.warnings?.length) {
|
|
98
|
+
for (const w of result.warnings) {
|
|
99
|
+
console.log(chalk.yellow(` ⚠ ${w.message}`));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
console.log(chalk.green(`\n ✓ Published successfully!`));
|
|
103
|
+
console.log(` ${chalk.bold('URL:')} ${getApiUrl()}/skills/${result.slug}\n`);
|
|
104
|
+
});
|
|
105
|
+
//# sourceMappingURL=publish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"publish.js","sourceRoot":"","sources":["../../src/commands/publish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
export interface ValidationResult {
|
|
3
|
+
errors: string[];
|
|
4
|
+
warnings: string[];
|
|
5
|
+
metadata: {
|
|
6
|
+
name?: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
version?: string;
|
|
9
|
+
fileCount: number;
|
|
10
|
+
totalSize: number;
|
|
11
|
+
estimatedTokens: number;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare function validateSkillDirectory(dir: string): ValidationResult;
|
|
15
|
+
export declare const validateCommand: Command;
|
|
16
|
+
//# sourceMappingURL=validate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,QAAQ,EAAE;QACR,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,MAAM,CAAC;QAClB,SAAS,EAAE,MAAM,CAAC;QAClB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAkBD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,gBAAgB,CA2FpE;AAED,eAAO,MAAM,eAAe,SAmCxB,CAAC"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { readFileSync, existsSync, statSync, readdirSync } from 'fs';
|
|
3
|
+
import { join, extname, relative } from 'path';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import matter from 'gray-matter';
|
|
7
|
+
import { z } from 'zod';
|
|
8
|
+
const SKILL_MD = 'SKILL.md';
|
|
9
|
+
const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB per file
|
|
10
|
+
const MAX_TOTAL_SIZE = 50 * 1024 * 1024; // 50MB total
|
|
11
|
+
const MAX_DEPTH = 5;
|
|
12
|
+
const MIN_BODY_LENGTH = 200;
|
|
13
|
+
const BLOCKED_EXTENSIONS = ['.exe', '.dll', '.so', '.dylib'];
|
|
14
|
+
const ALLOWED_SCRIPT_EXTENSIONS = ['.js', '.ts', '.py', '.mjs', '.cjs'];
|
|
15
|
+
const frontmatterSchema = z.object({
|
|
16
|
+
name: z.string()
|
|
17
|
+
.min(3, 'Name must be at least 3 characters')
|
|
18
|
+
.max(80, 'Name must be at most 80 characters')
|
|
19
|
+
.regex(/^[a-z0-9][a-z0-9-]*[a-z0-9]$/, 'Name must be lowercase alphanumeric with hyphens, not starting/ending with hyphen'),
|
|
20
|
+
description: z.string().min(50, 'Description must be at least 50 characters').max(2000),
|
|
21
|
+
version: z.string().regex(/^\d+\.\d+\.\d+$/, 'Version must be semver (e.g., 1.0.0)').optional().default('1.0.0'),
|
|
22
|
+
license: z.string().optional(),
|
|
23
|
+
author: z.string().optional(),
|
|
24
|
+
tags: z.array(z.string()).optional(),
|
|
25
|
+
});
|
|
26
|
+
function walkDir(dir, depth = 0) {
|
|
27
|
+
if (depth > MAX_DEPTH)
|
|
28
|
+
return [];
|
|
29
|
+
const entries = readdirSync(dir, { withFileTypes: true });
|
|
30
|
+
const files = [];
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
const fullPath = join(dir, entry.name);
|
|
33
|
+
if (entry.name.startsWith('.'))
|
|
34
|
+
continue;
|
|
35
|
+
if (entry.isDirectory()) {
|
|
36
|
+
files.push(...walkDir(fullPath, depth + 1));
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
files.push(fullPath);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return files;
|
|
43
|
+
}
|
|
44
|
+
export function validateSkillDirectory(dir) {
|
|
45
|
+
const errors = [];
|
|
46
|
+
const warnings = [];
|
|
47
|
+
const metadata = {
|
|
48
|
+
fileCount: 0,
|
|
49
|
+
totalSize: 0,
|
|
50
|
+
estimatedTokens: 0,
|
|
51
|
+
};
|
|
52
|
+
// Check directory exists
|
|
53
|
+
if (!existsSync(dir) || !statSync(dir).isDirectory()) {
|
|
54
|
+
errors.push(`Directory does not exist: ${dir}`);
|
|
55
|
+
return { errors, warnings, metadata };
|
|
56
|
+
}
|
|
57
|
+
// Check SKILL.md exists
|
|
58
|
+
const skillMdPath = join(dir, SKILL_MD);
|
|
59
|
+
if (!existsSync(skillMdPath)) {
|
|
60
|
+
errors.push(`Missing ${SKILL_MD} file`);
|
|
61
|
+
return { errors, warnings, metadata };
|
|
62
|
+
}
|
|
63
|
+
// Parse and validate frontmatter
|
|
64
|
+
const skillMdContent = readFileSync(skillMdPath, 'utf-8');
|
|
65
|
+
const { data: frontmatter, content: body } = matter(skillMdContent);
|
|
66
|
+
const fmResult = frontmatterSchema.safeParse(frontmatter);
|
|
67
|
+
if (!fmResult.success) {
|
|
68
|
+
for (const issue of fmResult.error.issues) {
|
|
69
|
+
errors.push(`Frontmatter: ${issue.path.join('.')}: ${issue.message}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
metadata.name = fmResult.data.name;
|
|
74
|
+
metadata.description = fmResult.data.description;
|
|
75
|
+
metadata.version = fmResult.data.version;
|
|
76
|
+
}
|
|
77
|
+
// Content validation
|
|
78
|
+
const trimmedBody = body.trim();
|
|
79
|
+
if (trimmedBody.length < MIN_BODY_LENGTH) {
|
|
80
|
+
errors.push(`SKILL.md body must be at least ${MIN_BODY_LENGTH} characters (got ${trimmedBody.length})`);
|
|
81
|
+
}
|
|
82
|
+
if (!/^#{1,6}\s+.+/m.test(trimmedBody)) {
|
|
83
|
+
warnings.push('SKILL.md body should have at least one markdown heading');
|
|
84
|
+
}
|
|
85
|
+
// Check for large base64
|
|
86
|
+
if (/data:[^;]+;base64,[A-Za-z0-9+/=]{1000,}/.test(skillMdContent)) {
|
|
87
|
+
errors.push('SKILL.md contains large base64-encoded data');
|
|
88
|
+
}
|
|
89
|
+
// Walk all files
|
|
90
|
+
const allFiles = walkDir(dir);
|
|
91
|
+
metadata.fileCount = allFiles.length;
|
|
92
|
+
for (const filePath of allFiles) {
|
|
93
|
+
const relPath = relative(dir, filePath);
|
|
94
|
+
const ext = extname(filePath).toLowerCase();
|
|
95
|
+
const stat = statSync(filePath);
|
|
96
|
+
// Size checks
|
|
97
|
+
if (stat.size > MAX_FILE_SIZE) {
|
|
98
|
+
errors.push(`File too large: ${relPath} (${(stat.size / 1024).toFixed(0)}KB > ${MAX_FILE_SIZE / 1024}KB)`);
|
|
99
|
+
}
|
|
100
|
+
metadata.totalSize += stat.size;
|
|
101
|
+
// Blocked extensions
|
|
102
|
+
if (BLOCKED_EXTENSIONS.includes(ext)) {
|
|
103
|
+
errors.push(`Blocked file type: ${relPath} (${ext})`);
|
|
104
|
+
}
|
|
105
|
+
// Script extension check
|
|
106
|
+
if (ext && !ALLOWED_SCRIPT_EXTENSIONS.includes(ext) && ext !== '.md' && ext !== '.json' && ext !== '.yaml' && ext !== '.yml' && ext !== '.txt' && ext !== '.toml') {
|
|
107
|
+
warnings.push(`Unusual file type: ${relPath} (${ext})`);
|
|
108
|
+
}
|
|
109
|
+
// Estimate tokens (~4 chars per token for text files)
|
|
110
|
+
try {
|
|
111
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
112
|
+
metadata.estimatedTokens += Math.ceil(content.length / 4);
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Binary file, skip token estimation
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (metadata.totalSize > MAX_TOTAL_SIZE) {
|
|
119
|
+
errors.push(`Total size exceeds limit: ${(metadata.totalSize / 1024 / 1024).toFixed(1)}MB > ${MAX_TOTAL_SIZE / 1024 / 1024}MB`);
|
|
120
|
+
}
|
|
121
|
+
return { errors, warnings, metadata };
|
|
122
|
+
}
|
|
123
|
+
export const validateCommand = new Command('validate')
|
|
124
|
+
.description('Validate a skill directory before publishing')
|
|
125
|
+
.argument('<dir>', 'Path to skill directory')
|
|
126
|
+
.action((dir) => {
|
|
127
|
+
const spinner = ora('Validating skill directory...').start();
|
|
128
|
+
const result = validateSkillDirectory(dir);
|
|
129
|
+
spinner.stop();
|
|
130
|
+
// Display metadata
|
|
131
|
+
if (result.metadata.name) {
|
|
132
|
+
console.log(chalk.bold(`\n Skill: ${result.metadata.name} v${result.metadata.version || '?'}`));
|
|
133
|
+
console.log(` ${result.metadata.description || ''}\n`);
|
|
134
|
+
}
|
|
135
|
+
console.log(` Files: ${result.metadata.fileCount}`);
|
|
136
|
+
console.log(` Size: ${(result.metadata.totalSize / 1024).toFixed(1)}KB`);
|
|
137
|
+
console.log(` Tokens: ~${result.metadata.estimatedTokens.toLocaleString()}\n`);
|
|
138
|
+
// Display errors
|
|
139
|
+
for (const error of result.errors) {
|
|
140
|
+
console.log(chalk.red(` ✗ ${error}`));
|
|
141
|
+
}
|
|
142
|
+
// Display warnings
|
|
143
|
+
for (const warning of result.warnings) {
|
|
144
|
+
console.log(chalk.yellow(` ⚠ ${warning}`));
|
|
145
|
+
}
|
|
146
|
+
// Summary
|
|
147
|
+
if (result.errors.length === 0) {
|
|
148
|
+
console.log(chalk.green('\n ✓ Ready to publish!\n'));
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
console.log(chalk.red(`\n ${result.errors.length} error(s) found. Fix them before publishing.\n`));
|
|
152
|
+
process.exit(1);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
//# sourceMappingURL=validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,IAAI,CAAC;AACrE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,MAAM,CAAC;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,GAAG,MAAM,KAAK,CAAC;AACtB,OAAO,MAAM,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,QAAQ,GAAG,UAAU,CAAC;AAC5B,MAAM,aAAa,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,gBAAgB;AACxD,MAAM,cAAc,GAAG,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,aAAa;AACtD,MAAM,SAAS,GAAG,CAAC,CAAC;AACpB,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,MAAM,kBAAkB,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC;AAC7D,MAAM,yBAAyB,GAAG,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AAExE,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACjC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE;SACb,GAAG,CAAC,CAAC,EAAE,oCAAoC,CAAC;SAC5C,GAAG,CAAC,EAAE,EAAE,oCAAoC,CAAC;SAC7C,KAAK,CAAC,8BAA8B,EAAE,mFAAmF,CAAC;IAC7H,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,4CAA4C,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;IACvF,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,iBAAiB,EAAE,sCAAsC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC;IAChH,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC7B,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACrC,CAAC,CAAC;AAeH,SAAS,OAAO,CAAC,GAAW,EAAE,KAAK,GAAG,CAAC;IACrC,IAAI,KAAK,GAAG,SAAS;QAAE,OAAO,EAAE,CAAC;IACjC,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QACzC,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,KAAK,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,QAAQ,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACvB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,GAAW;IAChD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAiC;QAC7C,SAAS,EAAE,CAAC;QACZ,SAAS,EAAE,CAAC;QACZ,eAAe,EAAE,CAAC;KACnB,CAAC;IAEF,yBAAyB;IACzB,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC;QACrD,MAAM,CAAC,IAAI,CAAC,6BAA6B,GAAG,EAAE,CAAC,CAAC;QAChD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACxC,CAAC;IAED,wBAAwB;IACxB,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACxC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC7B,MAAM,CAAC,IAAI,CAAC,WAAW,QAAQ,OAAO,CAAC,CAAC;QACxC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACxC,CAAC;IAED,iCAAiC;IACjC,MAAM,cAAc,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IAC1D,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;IAEpE,MAAM,QAAQ,GAAG,iBAAiB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAC1D,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;QACtB,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC1C,MAAM,CAAC,IAAI,CAAC,gBAAgB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;QACxE,CAAC;IACH,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;QACnC,QAAQ,CAAC,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC;QACjD,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;IAC3C,CAAC;IAED,qBAAqB;IACrB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAChC,IAAI,WAAW,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,kCAAkC,eAAe,oBAAoB,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1G,CAAC;IAED,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACvC,QAAQ,CAAC,IAAI,CAAC,yDAAyD,CAAC,CAAC;IAC3E,CAAC;IAED,yBAAyB;IACzB,IAAI,yCAAyC,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;QACnE,MAAM,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;IAC7D,CAAC;IAED,iBAAiB;IACjB,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;IAC9B,QAAQ,CAAC,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC;IAErC,KAAK,MAAM,QAAQ,IAAI,QAAQ,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;QACxC,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAEhC,cAAc;QACd,IAAI,IAAI,CAAC,IAAI,GAAG,aAAa,EAAE,CAAC;YAC9B,MAAM,CAAC,IAAI,CAAC,mBAAmB,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,aAAa,GAAG,IAAI,KAAK,CAAC,CAAC;QAC7G,CAAC;QACD,QAAQ,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC;QAEhC,qBAAqB;QACrB,IAAI,kBAAkB,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;YACrC,MAAM,CAAC,IAAI,CAAC,sBAAsB,OAAO,KAAK,GAAG,GAAG,CAAC,CAAC;QACxD,CAAC;QAED,yBAAyB;QACzB,IAAI,GAAG,IAAI,CAAC,yBAAyB,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,OAAO,EAAE,CAAC;YAClK,QAAQ,CAAC,IAAI,CAAC,sBAAsB,OAAO,KAAK,GAAG,GAAG,CAAC,CAAC;QAC1D,CAAC;QAED,sDAAsD;QACtD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChD,QAAQ,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,qCAAqC;QACvC,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,CAAC,SAAS,GAAG,cAAc,EAAE,CAAC;QACxC,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,QAAQ,CAAC,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,cAAc,GAAG,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC;IAClI,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,OAAO,CAAC,UAAU,CAAC;KACnD,WAAW,CAAC,8CAA8C,CAAC;KAC3D,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;KAC5C,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE;IACtB,MAAM,OAAO,GAAG,GAAG,CAAC,+BAA+B,CAAC,CAAC,KAAK,EAAE,CAAC;IAC7D,MAAM,MAAM,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAC3C,OAAO,CAAC,IAAI,EAAE,CAAC;IAEf,mBAAmB;IACnB,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,MAAM,CAAC,QAAQ,CAAC,IAAI,KAAK,MAAM,CAAC,QAAQ,CAAC,OAAO,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC;QACjG,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,QAAQ,CAAC,WAAW,IAAI,EAAE,IAAI,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,YAAY,MAAM,CAAC,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAEhF,iBAAiB;IACjB,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC;IACzC,CAAC;IAED,mBAAmB;IACnB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,OAAO,EAAE,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,UAAU;IACV,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC,CAAC;IACxD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,gDAAgD,CAAC,CAAC,CAAC;QACpG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from 'commander';
|
|
3
|
+
import { authCommand } from './commands/auth.js';
|
|
4
|
+
import { validateCommand } from './commands/validate.js';
|
|
5
|
+
import { publishCommand } from './commands/publish.js';
|
|
6
|
+
import { installCommand } from './commands/install.js';
|
|
7
|
+
import { listCommand, outdatedCommand, updateCommand, removeCommand } from './commands/manage.js';
|
|
8
|
+
import { searchCommand, infoCommand } from './commands/marketplace.js';
|
|
9
|
+
const program = new Command();
|
|
10
|
+
program
|
|
11
|
+
.name('skillhq')
|
|
12
|
+
.description('CLI for the SkillHQ marketplace — publish, install, and manage AI skills')
|
|
13
|
+
.version('0.1.0');
|
|
14
|
+
program.addCommand(authCommand);
|
|
15
|
+
program.addCommand(validateCommand);
|
|
16
|
+
program.addCommand(publishCommand);
|
|
17
|
+
program.addCommand(installCommand);
|
|
18
|
+
program.addCommand(listCommand);
|
|
19
|
+
program.addCommand(outdatedCommand);
|
|
20
|
+
program.addCommand(updateCommand);
|
|
21
|
+
program.addCommand(removeCommand);
|
|
22
|
+
program.addCommand(searchCommand);
|
|
23
|
+
program.addCommand(infoCommand);
|
|
24
|
+
program.parse();
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAClG,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAEvE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,SAAS,CAAC;KACf,WAAW,CAAC,0EAA0E,CAAC;KACvF,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC;AACnC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAChC,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC;AACpC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;AAClC,OAAO,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAEhC,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface FetchOptions {
|
|
2
|
+
method?: string;
|
|
3
|
+
body?: unknown;
|
|
4
|
+
token?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function apiFetch<T>(path: string, options?: FetchOptions): Promise<T>;
|
|
7
|
+
export declare function uploadToPresignedUrl(url: string, data: Buffer): Promise<void>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/utils/api.ts"],"names":[],"mappings":"AAEA,UAAU,YAAY;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAsB,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,CA8BtF;AAED,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAYnF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { getApiUrl } from './config.js';
|
|
2
|
+
export async function apiFetch(path, options = {}) {
|
|
3
|
+
const { method = 'GET', body, token } = options;
|
|
4
|
+
const url = `${getApiUrl()}${path}`;
|
|
5
|
+
const headers = {
|
|
6
|
+
'Content-Type': 'application/json',
|
|
7
|
+
};
|
|
8
|
+
if (token) {
|
|
9
|
+
headers['Authorization'] = `Bearer ${token}`;
|
|
10
|
+
}
|
|
11
|
+
const res = await fetch(url, {
|
|
12
|
+
method,
|
|
13
|
+
headers,
|
|
14
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
15
|
+
});
|
|
16
|
+
if (!res.ok) {
|
|
17
|
+
const text = await res.text();
|
|
18
|
+
let message;
|
|
19
|
+
try {
|
|
20
|
+
const json = JSON.parse(text);
|
|
21
|
+
message = json.error || json.message || text;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
message = text;
|
|
25
|
+
}
|
|
26
|
+
throw new Error(`API error (${res.status}): ${message}`);
|
|
27
|
+
}
|
|
28
|
+
return res.json();
|
|
29
|
+
}
|
|
30
|
+
export async function uploadToPresignedUrl(url, data) {
|
|
31
|
+
const res = await fetch(url, {
|
|
32
|
+
method: 'PUT',
|
|
33
|
+
body: new Uint8Array(data),
|
|
34
|
+
headers: {
|
|
35
|
+
'Content-Type': 'application/zip',
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
if (!res.ok) {
|
|
39
|
+
throw new Error(`Upload failed (${res.status}): ${await res.text()}`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/utils/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAQxC,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAI,IAAY,EAAE,UAAwB,EAAE;IACxE,MAAM,EAAE,MAAM,GAAG,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;IAChD,MAAM,GAAG,GAAG,GAAG,SAAS,EAAE,GAAG,IAAI,EAAE,CAAC;IAEpC,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;KACnC,CAAC;IACF,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAC;IAC/C,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM;QACN,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS;KAC9C,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC9B,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,GAAG,IAAI,CAAC;QACjB,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,cAAc,GAAG,CAAC,MAAM,MAAM,OAAO,EAAE,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;AAClC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,GAAW,EAAE,IAAY;IAClE,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAC3B,MAAM,EAAE,KAAK;QACb,IAAI,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC;QAC1B,OAAO,EAAE;YACP,cAAc,EAAE,iBAAiB;SAClC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,kBAAkB,GAAG,CAAC,MAAM,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACxE,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface AuthConfig {
|
|
2
|
+
token: string;
|
|
3
|
+
userId: string;
|
|
4
|
+
expiresAt: string;
|
|
5
|
+
}
|
|
6
|
+
export interface InstalledSkill {
|
|
7
|
+
version: string;
|
|
8
|
+
installedAt: string;
|
|
9
|
+
path: string;
|
|
10
|
+
}
|
|
11
|
+
export type InstalledSkills = Record<string, InstalledSkill>;
|
|
12
|
+
export declare function getAuthConfig(): AuthConfig | null;
|
|
13
|
+
export declare function saveAuthConfig(config: AuthConfig): void;
|
|
14
|
+
export declare function deleteAuthConfig(): void;
|
|
15
|
+
export declare function getInstalledSkills(): InstalledSkills;
|
|
16
|
+
export declare function saveInstalledSkills(skills: InstalledSkills): void;
|
|
17
|
+
export declare function getApiUrl(): string;
|
|
18
|
+
export declare function requireAuth(): AuthConfig;
|
|
19
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAQ7D,wBAAgB,aAAa,IAAI,UAAU,GAAG,IAAI,CAWjD;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAGvD;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAMvC;AAED,wBAAgB,kBAAkB,IAAI,eAAe,CAOpD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,CAGjE;AAED,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,wBAAgB,WAAW,IAAI,UAAU,CAOxC"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { homedir } from 'os';
|
|
4
|
+
const CONFIG_DIR = join(homedir(), '.skillhq');
|
|
5
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
6
|
+
const INSTALLED_FILE = join(CONFIG_DIR, 'installed.json');
|
|
7
|
+
function ensureConfigDir() {
|
|
8
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
9
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export function getAuthConfig() {
|
|
13
|
+
try {
|
|
14
|
+
const raw = readFileSync(CONFIG_FILE, 'utf-8');
|
|
15
|
+
const config = JSON.parse(raw);
|
|
16
|
+
if (config.expiresAt && new Date(config.expiresAt) < new Date()) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
return config;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function saveAuthConfig(config) {
|
|
26
|
+
ensureConfigDir();
|
|
27
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 0o600 });
|
|
28
|
+
}
|
|
29
|
+
export function deleteAuthConfig() {
|
|
30
|
+
try {
|
|
31
|
+
unlinkSync(CONFIG_FILE);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
// Already deleted or doesn't exist
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function getInstalledSkills() {
|
|
38
|
+
try {
|
|
39
|
+
const raw = readFileSync(INSTALLED_FILE, 'utf-8');
|
|
40
|
+
return JSON.parse(raw);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return {};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function saveInstalledSkills(skills) {
|
|
47
|
+
ensureConfigDir();
|
|
48
|
+
writeFileSync(INSTALLED_FILE, JSON.stringify(skills, null, 2));
|
|
49
|
+
}
|
|
50
|
+
export function getApiUrl() {
|
|
51
|
+
return process.env.SKILLHQ_API_URL || 'https://skillhq.dev';
|
|
52
|
+
}
|
|
53
|
+
export function requireAuth() {
|
|
54
|
+
const config = getAuthConfig();
|
|
55
|
+
if (!config) {
|
|
56
|
+
console.error('Not logged in. Run `skillhq auth login` first.');
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
return config;
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AACpF,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAE7B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAC;AAC/C,MAAM,WAAW,GAAG,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AACpD,MAAM,cAAc,GAAG,IAAI,CAAC,UAAU,EAAE,gBAAgB,CAAC,CAAC;AAgB1D,SAAS,eAAe;IACtB,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;QAC7C,IAAI,MAAM,CAAC,SAAS,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,IAAI,IAAI,EAAE,EAAE,CAAC;YAChE,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,MAAkB;IAC/C,eAAe,EAAE,CAAC;IAClB,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC/E,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC9B,IAAI,CAAC;QACH,UAAU,CAAC,WAAW,CAAC,CAAC;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,mCAAmC;IACrC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC;QAClD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAuB;IACzD,eAAe,EAAE,CAAC;IAClB,aAAa,CAAC,cAAc,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,qBAAqB,CAAC;AAC9D,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,MAAM,MAAM,GAAG,aAAa,EAAE,CAAC;IAC/B,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;QAChE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@skill-hq/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI for the SkillHQ marketplace - publish, install, and manage AI skills",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"skillhq": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"files": [
|
|
12
|
+
"dist"
|
|
13
|
+
],
|
|
14
|
+
"scripts": {
|
|
15
|
+
"build": "tsc && node scripts/add-shebang.js",
|
|
16
|
+
"dev": "tsc --watch",
|
|
17
|
+
"prepublishOnly": "npm run build"
|
|
18
|
+
},
|
|
19
|
+
"engines": {
|
|
20
|
+
"node": ">=18"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"claude",
|
|
24
|
+
"skills",
|
|
25
|
+
"marketplace",
|
|
26
|
+
"cli"
|
|
27
|
+
],
|
|
28
|
+
"license": "MIT",
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"chalk": "^5.4.1",
|
|
31
|
+
"commander": "^13.1.0",
|
|
32
|
+
"enquirer": "^2.4.1",
|
|
33
|
+
"gray-matter": "^4.0.3",
|
|
34
|
+
"jszip": "^3.10.1",
|
|
35
|
+
"open": "^10.1.0",
|
|
36
|
+
"ora": "^8.2.0",
|
|
37
|
+
"zod": "^3.24.0"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/node": "^22.0.0",
|
|
41
|
+
"typescript": "^5.7.0"
|
|
42
|
+
}
|
|
43
|
+
}
|