kirorepo 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/bin/kirorepo.js +168 -0
- package/package.json +14 -0
package/bin/kirorepo.js
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
|
|
8
|
+
const API = 'https://api.kirorepository.online';
|
|
9
|
+
const KIRO_DIR = path.join(os.homedir(), '.kiro');
|
|
10
|
+
|
|
11
|
+
// ── Colors ────────────────────────────────────────────────
|
|
12
|
+
const c = {
|
|
13
|
+
reset: '\x1b[0m',
|
|
14
|
+
bold: '\x1b[1m',
|
|
15
|
+
dim: '\x1b[2m',
|
|
16
|
+
green: '\x1b[32m',
|
|
17
|
+
cyan: '\x1b[36m',
|
|
18
|
+
yellow: '\x1b[33m',
|
|
19
|
+
red: '\x1b[31m',
|
|
20
|
+
magenta: '\x1b[35m',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// ── HTTP helper ───────────────────────────────────────────
|
|
24
|
+
function get(url) {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
https.get(url, (res) => {
|
|
27
|
+
let data = '';
|
|
28
|
+
res.on('data', (chunk) => data += chunk);
|
|
29
|
+
res.on('end', () => {
|
|
30
|
+
if (res.statusCode >= 400) reject(new Error(`HTTP ${res.statusCode}: ${data}`));
|
|
31
|
+
else resolve(data);
|
|
32
|
+
});
|
|
33
|
+
}).on('error', reject);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// ── Commands ──────────────────────────────────────────────
|
|
38
|
+
async function add(name) {
|
|
39
|
+
if (!name) {
|
|
40
|
+
console.log(`${c.red}✗${c.reset} Usage: ${c.cyan}npx kirorepo add <skill-name>${c.reset}`);
|
|
41
|
+
console.log(` Example: ${c.dim}npx kirorepo add systematic-debugging${c.reset}`);
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log(`\n${c.magenta}⬡${c.reset} ${c.bold}KiroRepo${c.reset} — Installing ${c.cyan}${name}${c.reset}\n`);
|
|
46
|
+
|
|
47
|
+
// Try skills first, then agents
|
|
48
|
+
let resource = null;
|
|
49
|
+
let type = 'skills';
|
|
50
|
+
|
|
51
|
+
try {
|
|
52
|
+
const data = await get(`${API}/api/skills/${name}`);
|
|
53
|
+
resource = JSON.parse(data);
|
|
54
|
+
} catch {
|
|
55
|
+
try {
|
|
56
|
+
const data = await get(`${API}/api/agents/${name}`);
|
|
57
|
+
resource = JSON.parse(data);
|
|
58
|
+
type = 'agents';
|
|
59
|
+
} catch {
|
|
60
|
+
console.log(`${c.red}✗${c.reset} Resource "${name}" not found in KiroRepository.`);
|
|
61
|
+
console.log(` ${c.dim}Browse available resources at https://agents.kirorepository.online/search${c.reset}`);
|
|
62
|
+
process.exit(1);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (!resource.s3DownloadUrl) {
|
|
67
|
+
console.log(`${c.red}✗${c.reset} No download URL available for "${name}".`);
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Download content
|
|
72
|
+
console.log(` ${c.dim}↓ Downloading ${name}.md...${c.reset}`);
|
|
73
|
+
let content;
|
|
74
|
+
try {
|
|
75
|
+
content = await get(resource.s3DownloadUrl);
|
|
76
|
+
} catch (e) {
|
|
77
|
+
console.log(`${c.red}✗${c.reset} Failed to download: ${e.message}`);
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Determine install path
|
|
82
|
+
const folder = type === 'skills' ? 'skills' : 'agents';
|
|
83
|
+
const destDir = path.join(KIRO_DIR, folder);
|
|
84
|
+
const destFile = path.join(destDir, `${name}.md`);
|
|
85
|
+
|
|
86
|
+
// Create directory if needed
|
|
87
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
88
|
+
|
|
89
|
+
// Write file
|
|
90
|
+
fs.writeFileSync(destFile, content, 'utf-8');
|
|
91
|
+
|
|
92
|
+
console.log(` ${c.green}✓${c.reset} Installed to ${c.cyan}~/.kiro/${folder}/${name}.md${c.reset}`);
|
|
93
|
+
console.log(`\n ${c.dim}${resource.description}${c.reset}`);
|
|
94
|
+
|
|
95
|
+
if (type === 'skills') {
|
|
96
|
+
console.log(`\n ${c.dim}Use in Kiro: reference with ${c.cyan}#${name}${c.reset}`);
|
|
97
|
+
} else {
|
|
98
|
+
console.log(`\n ${c.dim}Use in Kiro: invoke with ${c.cyan}/${name}${c.reset}`);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Increment download counter
|
|
102
|
+
try {
|
|
103
|
+
const url = `${API}/api/${type}/${name}/download`;
|
|
104
|
+
await new Promise((resolve) => {
|
|
105
|
+
const req = https.request(url, { method: 'POST' }, resolve);
|
|
106
|
+
req.end();
|
|
107
|
+
});
|
|
108
|
+
} catch {} // silent
|
|
109
|
+
|
|
110
|
+
console.log(`\n${c.green}Done!${c.reset}\n`);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async function list(type) {
|
|
114
|
+
const endpoint = type === 'agents' ? 'agents' : 'skills';
|
|
115
|
+
console.log(`\n${c.magenta}⬡${c.reset} ${c.bold}KiroRepo${c.reset} — Available ${endpoint}\n`);
|
|
116
|
+
|
|
117
|
+
try {
|
|
118
|
+
const data = await get(`${API}/api/${endpoint}`);
|
|
119
|
+
const items = JSON.parse(data);
|
|
120
|
+
items.forEach((item) => {
|
|
121
|
+
console.log(` ${c.cyan}${item.name}${c.reset} ${c.dim}— ${item.description.slice(0, 80)}${c.reset}`);
|
|
122
|
+
});
|
|
123
|
+
console.log(`\n ${c.dim}${items.length} ${endpoint} available. Install with: npx kirorepo add <name>${c.reset}\n`);
|
|
124
|
+
} catch (e) {
|
|
125
|
+
console.log(`${c.red}✗${c.reset} Failed to fetch: ${e.message}`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function help() {
|
|
130
|
+
console.log(`
|
|
131
|
+
${c.magenta}⬡${c.reset} ${c.bold}KiroRepo${c.reset} — Install Kiro skills & agents with one command
|
|
132
|
+
|
|
133
|
+
${c.bold}Usage:${c.reset}
|
|
134
|
+
npx kirorepo add <name> Install a skill or agent
|
|
135
|
+
npx kirorepo list skills List all available skills
|
|
136
|
+
npx kirorepo list agents List all available agents
|
|
137
|
+
npx kirorepo help Show this help
|
|
138
|
+
|
|
139
|
+
${c.bold}Examples:${c.reset}
|
|
140
|
+
${c.cyan}npx kirorepo add systematic-debugging${c.reset}
|
|
141
|
+
${c.cyan}npx kirorepo add react-best-practices${c.reset}
|
|
142
|
+
${c.cyan}npx kirorepo add code-reviewer${c.reset}
|
|
143
|
+
|
|
144
|
+
${c.dim}Files are installed to ~/.kiro/skills/ or ~/.kiro/agents/${c.reset}
|
|
145
|
+
${c.dim}Browse all resources: https://agents.kirorepository.online${c.reset}
|
|
146
|
+
`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ── Main ──────────────────────────────────────────────────
|
|
150
|
+
const [,, cmd, arg] = process.argv;
|
|
151
|
+
|
|
152
|
+
switch (cmd) {
|
|
153
|
+
case 'add':
|
|
154
|
+
case 'install':
|
|
155
|
+
case 'i':
|
|
156
|
+
add(arg);
|
|
157
|
+
break;
|
|
158
|
+
case 'list':
|
|
159
|
+
case 'ls':
|
|
160
|
+
list(arg || 'skills');
|
|
161
|
+
break;
|
|
162
|
+
case 'help':
|
|
163
|
+
case '--help':
|
|
164
|
+
case '-h':
|
|
165
|
+
default:
|
|
166
|
+
help();
|
|
167
|
+
break;
|
|
168
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kirorepo",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Install Kiro skills and agents from KiroRepository with one command",
|
|
5
|
+
"bin": {
|
|
6
|
+
"kirorepo": "./bin/kirorepo.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": ["kiro", "kiro-skills", "kiro-agents", "cli", "kirorepo"],
|
|
9
|
+
"author": "KiroRepository",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"engines": {
|
|
12
|
+
"node": ">=16"
|
|
13
|
+
}
|
|
14
|
+
}
|