@smicolon/ai-kit 0.3.2 → 0.4.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 +73 -40
- package/dist/index.js +312 -127
- package/package.json +5 -5
- package/.claude-plugin/marketplace.json +0 -369
- package/packs/architect/CHANGELOG.md +0 -17
- package/packs/architect/README.md +0 -58
- package/packs/architect/agents/system-architect.md +0 -768
- package/packs/architect/commands/diagram-create.md +0 -300
- package/packs/better-auth/.mcp.json +0 -14
- package/packs/better-auth/CHANGELOG.md +0 -26
- package/packs/better-auth/README.md +0 -125
- package/packs/better-auth/agents/auth-architect.md +0 -278
- package/packs/better-auth/commands/auth-provider-add.md +0 -265
- package/packs/better-auth/commands/auth-setup.md +0 -298
- package/packs/better-auth/skills/auth-security/SKILL.md +0 -425
- package/packs/better-auth/skills/better-auth-patterns/SKILL.md +0 -455
- package/packs/dev-loop/CHANGELOG.md +0 -69
- package/packs/dev-loop/README.md +0 -155
- package/packs/dev-loop/commands/cancel-dev.md +0 -21
- package/packs/dev-loop/commands/dev-loop.md +0 -72
- package/packs/dev-loop/commands/dev-plan.md +0 -351
- package/packs/dev-loop/hooks/hooks.json +0 -15
- package/packs/dev-loop/hooks/stop-hook.sh +0 -178
- package/packs/dev-loop/scripts/setup-dev-loop.sh +0 -194
- package/packs/dev-loop/skills/tdd-planner/SKILL.md +0 -249
- package/packs/dev-loop/skills/tdd-planner/references/framework-patterns.md +0 -874
- package/packs/dev-loop/skills/tdd-planner/references/good-example.md +0 -260
- package/packs/dev-loop/skills/tdd-planner/references/plan-template.md +0 -275
- package/packs/django/CHANGELOG.md +0 -39
- package/packs/django/README.md +0 -92
- package/packs/django/agents/django-architect.md +0 -182
- package/packs/django/agents/django-builder.md +0 -250
- package/packs/django/agents/django-feature-based.md +0 -420
- package/packs/django/agents/django-reviewer.md +0 -253
- package/packs/django/agents/django-tester.md +0 -230
- package/packs/django/commands/api-endpoint.md +0 -285
- package/packs/django/commands/model-create.md +0 -178
- package/packs/django/commands/test-generate.md +0 -325
- package/packs/django/rules/migrations.md +0 -138
- package/packs/django/rules/models.md +0 -167
- package/packs/django/rules/serializers.md +0 -126
- package/packs/django/rules/services.md +0 -131
- package/packs/django/rules/tests.md +0 -140
- package/packs/django/rules/views.md +0 -102
- package/packs/django/skills/import-convention-enforcer/SKILL.md +0 -226
- package/packs/django/skills/import-convention-enforcer/patterns/django-imports.md +0 -343
- package/packs/django/skills/migration-safety-checker/SKILL.md +0 -375
- package/packs/django/skills/model-entity-validator/SKILL.md +0 -298
- package/packs/django/skills/performance-optimizer/SKILL.md +0 -447
- package/packs/django/skills/red-phase-verifier/SKILL.md +0 -180
- package/packs/django/skills/security-first-validator/SKILL.md +0 -435
- package/packs/django/skills/test-coverage-advisor/SKILL.md +0 -394
- package/packs/django/skills/test-validity-checker/SKILL.md +0 -194
- package/packs/failure-log/CHANGELOG.md +0 -20
- package/packs/failure-log/README.md +0 -168
- package/packs/failure-log/commands/failure-add.md +0 -106
- package/packs/failure-log/commands/failure-list.md +0 -89
- package/packs/failure-log/hooks/hooks.json +0 -16
- package/packs/failure-log/hooks/scripts/inject-failures.sh +0 -64
- package/packs/failure-log/skills/failure-log-manager/SKILL.md +0 -164
- package/packs/flutter/CHANGELOG.md +0 -19
- package/packs/flutter/README.md +0 -170
- package/packs/flutter/agents/flutter-architect.md +0 -166
- package/packs/flutter/agents/flutter-builder.md +0 -303
- package/packs/flutter/agents/release-manager.md +0 -355
- package/packs/flutter/commands/fastlane-setup.md +0 -188
- package/packs/flutter/commands/flutter-build.md +0 -90
- package/packs/flutter/commands/flutter-deploy.md +0 -133
- package/packs/flutter/commands/flutter-test.md +0 -117
- package/packs/flutter/commands/signing-setup.md +0 -209
- package/packs/flutter/hooks/hooks.json +0 -17
- package/packs/flutter/skills/fastlane-knowledge/SKILL.md +0 -193
- package/packs/flutter/skills/flutter-architecture/SKILL.md +0 -127
- package/packs/flutter/skills/store-publishing/SKILL.md +0 -163
- package/packs/hono/CHANGELOG.md +0 -19
- package/packs/hono/README.md +0 -143
- package/packs/hono/agents/hono-architect.md +0 -240
- package/packs/hono/agents/hono-builder.md +0 -285
- package/packs/hono/agents/hono-reviewer.md +0 -279
- package/packs/hono/agents/hono-tester.md +0 -346
- package/packs/hono/commands/middleware-create.md +0 -223
- package/packs/hono/commands/project-init.md +0 -306
- package/packs/hono/commands/route-create.md +0 -153
- package/packs/hono/commands/rpc-client.md +0 -263
- package/packs/hono/skills/cloudflare-bindings/SKILL.md +0 -408
- package/packs/hono/skills/hono-patterns/SKILL.md +0 -309
- package/packs/hono/skills/rpc-typesafe/SKILL.md +0 -388
- package/packs/hono/skills/zod-validation/SKILL.md +0 -332
- package/packs/nestjs/CHANGELOG.md +0 -29
- package/packs/nestjs/README.md +0 -75
- package/packs/nestjs/agents/nestjs-architect.md +0 -402
- package/packs/nestjs/agents/nestjs-builder.md +0 -301
- package/packs/nestjs/agents/nestjs-tester.md +0 -437
- package/packs/nestjs/commands/module-create.md +0 -369
- package/packs/nestjs/rules/controllers.md +0 -92
- package/packs/nestjs/rules/dto.md +0 -124
- package/packs/nestjs/rules/entities.md +0 -102
- package/packs/nestjs/rules/services.md +0 -106
- package/packs/nestjs/skills/barrel-export-manager/SKILL.md +0 -389
- package/packs/nestjs/skills/import-convention-enforcer/SKILL.md +0 -365
- package/packs/nextjs/CHANGELOG.md +0 -36
- package/packs/nextjs/README.md +0 -76
- package/packs/nextjs/agents/frontend-tester.md +0 -680
- package/packs/nextjs/agents/frontend-visual.md +0 -820
- package/packs/nextjs/agents/nextjs-architect.md +0 -331
- package/packs/nextjs/agents/nextjs-modular.md +0 -433
- package/packs/nextjs/commands/component-create.md +0 -398
- package/packs/nextjs/rules/api-routes.md +0 -129
- package/packs/nextjs/rules/components.md +0 -106
- package/packs/nextjs/rules/hooks.md +0 -132
- package/packs/nextjs/skills/accessibility-validator/SKILL.md +0 -445
- package/packs/nextjs/skills/import-convention-enforcer/SKILL.md +0 -399
- package/packs/nextjs/skills/react-form-validator/SKILL.md +0 -569
- package/packs/nuxtjs/CHANGELOG.md +0 -30
- package/packs/nuxtjs/README.md +0 -56
- package/packs/nuxtjs/agents/frontend-tester.md +0 -680
- package/packs/nuxtjs/agents/frontend-visual.md +0 -820
- package/packs/nuxtjs/agents/nuxtjs-architect.md +0 -537
- package/packs/nuxtjs/commands/component-create.md +0 -223
- package/packs/nuxtjs/rules/components.md +0 -101
- package/packs/nuxtjs/rules/composables.md +0 -118
- package/packs/nuxtjs/rules/server-routes.md +0 -127
- package/packs/nuxtjs/skills/accessibility-validator/SKILL.md +0 -183
- package/packs/nuxtjs/skills/import-convention-enforcer/SKILL.md +0 -196
- package/packs/nuxtjs/skills/veevalidate-form-validator/SKILL.md +0 -190
- package/packs/onboard/CHANGELOG.md +0 -22
- package/packs/onboard/README.md +0 -103
- package/packs/onboard/agents/onboard-guide.md +0 -118
- package/packs/onboard/commands/onboard.md +0 -313
- package/packs/onboard/skills/onboard-context-provider/SKILL.md +0 -98
- package/packs/tanstack-router/CHANGELOG.md +0 -30
- package/packs/tanstack-router/README.md +0 -113
- package/packs/tanstack-router/agents/tanstack-architect.md +0 -173
- package/packs/tanstack-router/agents/tanstack-builder.md +0 -360
- package/packs/tanstack-router/agents/tanstack-tester.md +0 -454
- package/packs/tanstack-router/commands/form-create.md +0 -313
- package/packs/tanstack-router/commands/query-create.md +0 -263
- package/packs/tanstack-router/commands/route-create.md +0 -190
- package/packs/tanstack-router/commands/table-create.md +0 -413
- package/packs/tanstack-router/skills/ai-patterns/SKILL.md +0 -370
- package/packs/tanstack-router/skills/db-patterns/SKILL.md +0 -346
- package/packs/tanstack-router/skills/devtools-patterns/SKILL.md +0 -415
- package/packs/tanstack-router/skills/form-patterns/SKILL.md +0 -425
- package/packs/tanstack-router/skills/pacer-patterns/SKILL.md +0 -341
- package/packs/tanstack-router/skills/query-patterns/SKILL.md +0 -359
- package/packs/tanstack-router/skills/router-patterns/SKILL.md +0 -285
- package/packs/tanstack-router/skills/store-patterns/SKILL.md +0 -351
- package/packs/tanstack-router/skills/table-patterns/SKILL.md +0 -531
- package/packs/tanstack-router/skills/tanstack-conventions/SKILL.md +0 -428
- package/packs/tanstack-router/skills/virtual-patterns/SKILL.md +0 -490
- package/packs/worktree/CHANGELOG.md +0 -45
- package/packs/worktree/README.md +0 -219
- package/packs/worktree/commands/wt.md +0 -93
- package/packs/worktree/scripts/wt.sh +0 -957
- package/packs/worktree/skills/worktree-manager/SKILL.md +0 -113
package/dist/index.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command8 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/init.ts
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
import * as p from "@clack/prompts";
|
|
9
9
|
import pc from "picocolors";
|
|
10
|
-
import
|
|
10
|
+
import path7 from "path";
|
|
11
11
|
|
|
12
12
|
// src/tools.ts
|
|
13
13
|
var TOOL_REGISTRY = {
|
|
@@ -154,29 +154,123 @@ var TOOL_IDS = Object.keys(TOOL_REGISTRY);
|
|
|
154
154
|
var CANONICAL_SKILLS_DIR = ".agents/skills";
|
|
155
155
|
|
|
156
156
|
// src/discovery.ts
|
|
157
|
+
import fs2 from "fs";
|
|
158
|
+
import path2 from "path";
|
|
159
|
+
|
|
160
|
+
// src/registry.ts
|
|
157
161
|
import fs from "fs";
|
|
158
162
|
import path from "path";
|
|
163
|
+
import os from "os";
|
|
164
|
+
import { execSync } from "child_process";
|
|
165
|
+
var REPO = "smicolon/ai-kit";
|
|
166
|
+
var DEFAULT_BRANCH = "main";
|
|
167
|
+
function getCacheDir() {
|
|
168
|
+
return path.join(os.homedir(), ".config", "ai-kit", "cache");
|
|
169
|
+
}
|
|
170
|
+
function getRepoDir() {
|
|
171
|
+
return path.join(getCacheDir(), "repo");
|
|
172
|
+
}
|
|
173
|
+
function getCachedMarketplacePath() {
|
|
174
|
+
return path.join(getCacheDir(), "marketplace.json");
|
|
175
|
+
}
|
|
176
|
+
function rawUrl(branch, filePath) {
|
|
177
|
+
return `https://raw.githubusercontent.com/${REPO}/${branch}/${filePath}`;
|
|
178
|
+
}
|
|
179
|
+
function tarballUrl(branch) {
|
|
180
|
+
return `https://github.com/${REPO}/archive/refs/heads/${branch}.tar.gz`;
|
|
181
|
+
}
|
|
182
|
+
async function fetchMarketplaceRaw(branch) {
|
|
183
|
+
const url = rawUrl(branch, ".claude-plugin/marketplace.json");
|
|
184
|
+
const res = await fetch(url);
|
|
185
|
+
if (!res.ok) {
|
|
186
|
+
throw new Error(`Failed to fetch marketplace.json: ${res.status} ${res.statusText}`);
|
|
187
|
+
}
|
|
188
|
+
return res.text();
|
|
189
|
+
}
|
|
190
|
+
async function downloadRepo(branch) {
|
|
191
|
+
const cacheDir = getCacheDir();
|
|
192
|
+
const repoDir = getRepoDir();
|
|
193
|
+
const tarPath = path.join(cacheDir, "repo.tar.gz");
|
|
194
|
+
if (fs.existsSync(repoDir)) {
|
|
195
|
+
fs.rmSync(repoDir, { recursive: true });
|
|
196
|
+
}
|
|
197
|
+
fs.mkdirSync(repoDir, { recursive: true });
|
|
198
|
+
const url = tarballUrl(branch);
|
|
199
|
+
const res = await fetch(url);
|
|
200
|
+
if (!res.ok) {
|
|
201
|
+
throw new Error(`Failed to download repo tarball: ${res.status} ${res.statusText}`);
|
|
202
|
+
}
|
|
203
|
+
const buffer = Buffer.from(await res.arrayBuffer());
|
|
204
|
+
fs.writeFileSync(tarPath, buffer);
|
|
205
|
+
execSync(`tar xzf "${tarPath}" --strip-components=1 -C "${repoDir}"`, {
|
|
206
|
+
stdio: "ignore"
|
|
207
|
+
});
|
|
208
|
+
fs.unlinkSync(tarPath);
|
|
209
|
+
}
|
|
210
|
+
async function ensureRepo(options = {}) {
|
|
211
|
+
const branch = options.branch ?? DEFAULT_BRANCH;
|
|
212
|
+
const cacheDir = getCacheDir();
|
|
213
|
+
const repoDir = getRepoDir();
|
|
214
|
+
const cachedMpPath = getCachedMarketplacePath();
|
|
215
|
+
fs.mkdirSync(cacheDir, { recursive: true });
|
|
216
|
+
if (options.noCache) {
|
|
217
|
+
const mpContent = await fetchMarketplaceRaw(branch);
|
|
218
|
+
await downloadRepo(branch);
|
|
219
|
+
fs.writeFileSync(cachedMpPath, mpContent);
|
|
220
|
+
return repoDir;
|
|
221
|
+
}
|
|
222
|
+
try {
|
|
223
|
+
const remoteMp = await fetchMarketplaceRaw(branch);
|
|
224
|
+
let needsDownload = true;
|
|
225
|
+
if (fs.existsSync(cachedMpPath) && fs.existsSync(repoDir)) {
|
|
226
|
+
const cachedMp = fs.readFileSync(cachedMpPath, "utf-8");
|
|
227
|
+
needsDownload = remoteMp !== cachedMp;
|
|
228
|
+
}
|
|
229
|
+
if (needsDownload) {
|
|
230
|
+
await downloadRepo(branch);
|
|
231
|
+
fs.writeFileSync(cachedMpPath, remoteMp);
|
|
232
|
+
}
|
|
233
|
+
return repoDir;
|
|
234
|
+
} catch (err) {
|
|
235
|
+
if (fs.existsSync(repoDir) && fs.existsSync(path.join(repoDir, ".claude-plugin", "marketplace.json"))) {
|
|
236
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
237
|
+
console.error(`Warning: Could not reach GitHub (${msg}). Using cached packs.`);
|
|
238
|
+
return repoDir;
|
|
239
|
+
}
|
|
240
|
+
throw new Error(
|
|
241
|
+
"Could not fetch packs from GitHub and no local cache exists. Check your internet connection and try again."
|
|
242
|
+
);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
function clearCache() {
|
|
246
|
+
const cacheDir = getCacheDir();
|
|
247
|
+
if (fs.existsSync(cacheDir)) {
|
|
248
|
+
fs.rmSync(cacheDir, { recursive: true });
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// src/discovery.ts
|
|
159
253
|
function findMarketplaceJson(startDir) {
|
|
160
254
|
let dir = startDir;
|
|
161
255
|
while (true) {
|
|
162
|
-
const candidate =
|
|
163
|
-
if (
|
|
164
|
-
const parent =
|
|
256
|
+
const candidate = path2.join(dir, ".claude-plugin", "marketplace.json");
|
|
257
|
+
if (fs2.existsSync(candidate)) return candidate;
|
|
258
|
+
const parent = path2.dirname(dir);
|
|
165
259
|
if (parent === dir) return null;
|
|
166
260
|
dir = parent;
|
|
167
261
|
}
|
|
168
262
|
}
|
|
169
263
|
function resolvePack(plugin, marketplaceDir) {
|
|
170
|
-
const sourceDir =
|
|
171
|
-
const resolveFiles = (files) => (files ?? []).map((f) =>
|
|
264
|
+
const sourceDir = path2.resolve(marketplaceDir, plugin.source);
|
|
265
|
+
const resolveFiles = (files) => (files ?? []).map((f) => path2.resolve(sourceDir, f));
|
|
172
266
|
let rules = [];
|
|
173
|
-
const rulesDir =
|
|
174
|
-
if (
|
|
175
|
-
rules =
|
|
267
|
+
const rulesDir = path2.join(sourceDir, "rules");
|
|
268
|
+
if (fs2.existsSync(rulesDir)) {
|
|
269
|
+
rules = fs2.readdirSync(rulesDir).filter((f) => f.endsWith(".md")).map((f) => path2.join(rulesDir, f));
|
|
176
270
|
}
|
|
177
271
|
const skills = (plugin.skills ?? []).map((s) => {
|
|
178
|
-
const skillMdPath =
|
|
179
|
-
return
|
|
272
|
+
const skillMdPath = path2.resolve(sourceDir, s);
|
|
273
|
+
return path2.dirname(skillMdPath);
|
|
180
274
|
});
|
|
181
275
|
return {
|
|
182
276
|
name: plugin.name,
|
|
@@ -190,39 +284,48 @@ function resolvePack(plugin, marketplaceDir) {
|
|
|
190
284
|
skills,
|
|
191
285
|
rules,
|
|
192
286
|
hooks: resolveFiles(plugin.hooks),
|
|
193
|
-
mcpServers: plugin.mcpServers ?
|
|
287
|
+
mcpServers: plugin.mcpServers ? path2.resolve(sourceDir, plugin.mcpServers) : void 0
|
|
194
288
|
};
|
|
195
289
|
}
|
|
196
|
-
function
|
|
197
|
-
const
|
|
198
|
-
const
|
|
199
|
-
|
|
290
|
+
function resolvePacksFromPath(marketplacePath) {
|
|
291
|
+
const marketplaceDir = path2.dirname(path2.dirname(marketplacePath));
|
|
292
|
+
const raw = JSON.parse(fs2.readFileSync(marketplacePath, "utf-8"));
|
|
293
|
+
return raw.plugins.map((p3) => resolvePack(p3, marketplaceDir)).filter((p3) => fs2.existsSync(p3.sourceDir));
|
|
294
|
+
}
|
|
295
|
+
async function discoverPacks(registryOptions) {
|
|
296
|
+
const start = path2.dirname(new URL(import.meta.url).pathname);
|
|
297
|
+
const localPath = findMarketplaceJson(start);
|
|
298
|
+
if (localPath) {
|
|
299
|
+
return resolvePacksFromPath(localPath);
|
|
300
|
+
}
|
|
301
|
+
const repoDir = await ensureRepo(registryOptions);
|
|
302
|
+
const remotePath = path2.join(repoDir, ".claude-plugin", "marketplace.json");
|
|
303
|
+
if (!fs2.existsSync(remotePath)) {
|
|
200
304
|
throw new Error(
|
|
201
|
-
"Could not find .claude-plugin/marketplace.json.
|
|
305
|
+
"Could not find .claude-plugin/marketplace.json in cached repo. Try running: ai-kit cache clear"
|
|
202
306
|
);
|
|
203
307
|
}
|
|
204
|
-
|
|
205
|
-
const raw = JSON.parse(fs.readFileSync(marketplacePath, "utf-8"));
|
|
206
|
-
return raw.plugins.map((p3) => resolvePack(p3, marketplaceDir)).filter((p3) => fs.existsSync(p3.sourceDir));
|
|
308
|
+
return resolvePacksFromPath(remotePath);
|
|
207
309
|
}
|
|
208
|
-
function findPack(name,
|
|
209
|
-
|
|
310
|
+
async function findPack(name, registryOptions) {
|
|
311
|
+
const packs = await discoverPacks(registryOptions);
|
|
312
|
+
return packs.find((p3) => p3.name === name);
|
|
210
313
|
}
|
|
211
314
|
|
|
212
315
|
// src/config.ts
|
|
213
|
-
import
|
|
214
|
-
import
|
|
316
|
+
import fs3 from "fs";
|
|
317
|
+
import path3 from "path";
|
|
215
318
|
var CONFIG_FILE = ".ai-kit.json";
|
|
216
319
|
function configPath(projectDir) {
|
|
217
|
-
return
|
|
320
|
+
return path3.join(projectDir, CONFIG_FILE);
|
|
218
321
|
}
|
|
219
322
|
function readConfig(projectDir) {
|
|
220
323
|
const fp = configPath(projectDir);
|
|
221
|
-
if (!
|
|
222
|
-
return JSON.parse(
|
|
324
|
+
if (!fs3.existsSync(fp)) return null;
|
|
325
|
+
return JSON.parse(fs3.readFileSync(fp, "utf-8"));
|
|
223
326
|
}
|
|
224
327
|
function writeConfig(projectDir, config) {
|
|
225
|
-
|
|
328
|
+
fs3.writeFileSync(configPath(projectDir), JSON.stringify(config, null, 2) + "\n");
|
|
226
329
|
}
|
|
227
330
|
function mergeInstall(config, result) {
|
|
228
331
|
const components = {};
|
|
@@ -257,8 +360,8 @@ function createDefaultConfig(tools) {
|
|
|
257
360
|
}
|
|
258
361
|
|
|
259
362
|
// src/gitignore.ts
|
|
260
|
-
import
|
|
261
|
-
import
|
|
363
|
+
import fs4 from "fs";
|
|
364
|
+
import path4 from "path";
|
|
262
365
|
var MANAGED_COMMENT = "# AI coding tools (managed by @smicolon/ai-kit)";
|
|
263
366
|
var LOCAL_PATTERNS = [
|
|
264
367
|
".ai-kit.json",
|
|
@@ -268,14 +371,14 @@ var LOCAL_PATTERNS = [
|
|
|
268
371
|
function findGitRoot(startDir) {
|
|
269
372
|
let dir = startDir;
|
|
270
373
|
while (true) {
|
|
271
|
-
if (
|
|
272
|
-
const parent =
|
|
374
|
+
if (fs4.existsSync(path4.join(dir, ".git"))) return dir;
|
|
375
|
+
const parent = path4.dirname(dir);
|
|
273
376
|
if (parent === dir) return null;
|
|
274
377
|
dir = parent;
|
|
275
378
|
}
|
|
276
379
|
}
|
|
277
380
|
function appendToGitignore(gitignorePath, entries) {
|
|
278
|
-
const existing =
|
|
381
|
+
const existing = fs4.existsSync(gitignorePath) ? fs4.readFileSync(gitignorePath, "utf-8") : "";
|
|
279
382
|
const lines = existing.split("\n");
|
|
280
383
|
const newEntries = entries.filter(
|
|
281
384
|
(entry) => !lines.some(
|
|
@@ -300,29 +403,29 @@ ${newEntries.join("\n")}
|
|
|
300
403
|
`;
|
|
301
404
|
updated = existing.endsWith("\n") ? existing + block : existing + "\n" + block;
|
|
302
405
|
}
|
|
303
|
-
|
|
406
|
+
fs4.writeFileSync(gitignorePath, updated);
|
|
304
407
|
}
|
|
305
408
|
function updateGitignore(projectDir) {
|
|
306
|
-
const projectGitignore =
|
|
409
|
+
const projectGitignore = path4.join(projectDir, ".gitignore");
|
|
307
410
|
appendToGitignore(projectGitignore, LOCAL_PATTERNS);
|
|
308
411
|
const gitRoot = findGitRoot(projectDir);
|
|
309
|
-
if (gitRoot &&
|
|
310
|
-
const relFromRoot =
|
|
412
|
+
if (gitRoot && path4.resolve(gitRoot) !== path4.resolve(projectDir)) {
|
|
413
|
+
const relFromRoot = path4.relative(gitRoot, projectDir);
|
|
311
414
|
const rootEntries = LOCAL_PATTERNS.map(
|
|
312
415
|
(e) => e.startsWith("**/") ? e : `${relFromRoot}/${e}`
|
|
313
416
|
);
|
|
314
|
-
appendToGitignore(
|
|
417
|
+
appendToGitignore(path4.join(gitRoot, ".gitignore"), rootEntries);
|
|
315
418
|
}
|
|
316
419
|
}
|
|
317
420
|
|
|
318
421
|
// src/installer.ts
|
|
319
|
-
import
|
|
320
|
-
import
|
|
422
|
+
import fs6 from "fs";
|
|
423
|
+
import path5 from "path";
|
|
321
424
|
|
|
322
425
|
// src/converters/cursor-mdc.ts
|
|
323
|
-
import
|
|
426
|
+
import fs5 from "fs";
|
|
324
427
|
function convertToMdc(mdFilePath, packName) {
|
|
325
|
-
const content =
|
|
428
|
+
const content = fs5.readFileSync(mdFilePath, "utf-8");
|
|
326
429
|
const { frontmatter, body } = parseFrontmatter(content);
|
|
327
430
|
const paths = frontmatter.paths;
|
|
328
431
|
const globs = paths && paths.length > 0 ? paths.length === 1 ? paths[0] : paths.join(", ") : "";
|
|
@@ -377,63 +480,63 @@ function parseFrontmatter(content) {
|
|
|
377
480
|
var trackedFiles = [];
|
|
378
481
|
var currentProjectDir = "";
|
|
379
482
|
function trackFile(absPath) {
|
|
380
|
-
trackedFiles.push(
|
|
483
|
+
trackedFiles.push(path5.relative(currentProjectDir, absPath));
|
|
381
484
|
}
|
|
382
485
|
function ensureDir(dir) {
|
|
383
|
-
|
|
486
|
+
fs6.mkdirSync(dir, { recursive: true });
|
|
384
487
|
}
|
|
385
488
|
function copyFile(src, dest) {
|
|
386
|
-
ensureDir(
|
|
387
|
-
|
|
489
|
+
ensureDir(path5.dirname(dest));
|
|
490
|
+
fs6.copyFileSync(src, dest);
|
|
388
491
|
trackFile(dest);
|
|
389
492
|
}
|
|
390
493
|
function copyDir(src, dest) {
|
|
391
494
|
ensureDir(dest);
|
|
392
|
-
for (const entry of
|
|
393
|
-
const srcPath =
|
|
394
|
-
const destPath =
|
|
495
|
+
for (const entry of fs6.readdirSync(src, { withFileTypes: true })) {
|
|
496
|
+
const srcPath = path5.join(src, entry.name);
|
|
497
|
+
const destPath = path5.join(dest, entry.name);
|
|
395
498
|
if (entry.isDirectory()) {
|
|
396
499
|
copyDir(srcPath, destPath);
|
|
397
500
|
} else {
|
|
398
|
-
|
|
501
|
+
fs6.copyFileSync(srcPath, destPath);
|
|
399
502
|
trackFile(destPath);
|
|
400
503
|
}
|
|
401
504
|
}
|
|
402
505
|
}
|
|
403
506
|
function createSymlink(target, linkPath) {
|
|
404
|
-
ensureDir(
|
|
405
|
-
if (
|
|
406
|
-
const stat =
|
|
407
|
-
if (stat.isSymbolicLink())
|
|
507
|
+
ensureDir(path5.dirname(linkPath));
|
|
508
|
+
if (fs6.existsSync(linkPath)) {
|
|
509
|
+
const stat = fs6.lstatSync(linkPath);
|
|
510
|
+
if (stat.isSymbolicLink()) fs6.unlinkSync(linkPath);
|
|
408
511
|
else return;
|
|
409
512
|
}
|
|
410
513
|
const type = process.platform === "win32" ? "junction" : void 0;
|
|
411
|
-
|
|
514
|
+
fs6.symlinkSync(target, linkPath, type);
|
|
412
515
|
trackFile(linkPath);
|
|
413
516
|
}
|
|
414
517
|
function installSkills(skillDirs, tools, projectDir) {
|
|
415
518
|
if (skillDirs.length === 0 || tools.length === 0) return 0;
|
|
416
519
|
const skillTools = tools.filter((t) => TOOL_REGISTRY[t].components.skills);
|
|
417
520
|
if (skillTools.length === 0) return 0;
|
|
418
|
-
const canonicalBase =
|
|
521
|
+
const canonicalBase = path5.join(projectDir, CANONICAL_SKILLS_DIR);
|
|
419
522
|
let count = 0;
|
|
420
523
|
for (const skillDir of skillDirs) {
|
|
421
|
-
const skillName =
|
|
422
|
-
const canonicalDest =
|
|
423
|
-
if (!
|
|
524
|
+
const skillName = path5.basename(skillDir);
|
|
525
|
+
const canonicalDest = path5.join(canonicalBase, skillName);
|
|
526
|
+
if (!fs6.existsSync(canonicalDest)) {
|
|
424
527
|
copyDir(skillDir, canonicalDest);
|
|
425
528
|
count++;
|
|
426
529
|
}
|
|
427
530
|
}
|
|
428
531
|
for (const toolId of skillTools) {
|
|
429
|
-
const toolSkillsDir =
|
|
430
|
-
if (
|
|
532
|
+
const toolSkillsDir = path5.join(projectDir, TOOL_REGISTRY[toolId].skillsDir);
|
|
533
|
+
if (path5.resolve(toolSkillsDir) === path5.resolve(canonicalBase)) continue;
|
|
431
534
|
ensureDir(toolSkillsDir);
|
|
432
535
|
for (const skillDir of skillDirs) {
|
|
433
|
-
const skillName =
|
|
434
|
-
const canonicalDest =
|
|
435
|
-
const linkPath =
|
|
436
|
-
const relTarget =
|
|
536
|
+
const skillName = path5.basename(skillDir);
|
|
537
|
+
const canonicalDest = path5.join(canonicalBase, skillName);
|
|
538
|
+
const linkPath = path5.join(toolSkillsDir, skillName);
|
|
539
|
+
const relTarget = path5.relative(path5.dirname(linkPath), canonicalDest);
|
|
437
540
|
createSymlink(relTarget, linkPath);
|
|
438
541
|
}
|
|
439
542
|
}
|
|
@@ -444,18 +547,18 @@ function installMdFiles(files, componentType, tools, projectDir, packName) {
|
|
|
444
547
|
for (const toolId of tools) {
|
|
445
548
|
const targetDir = TOOL_REGISTRY[toolId].components[componentType];
|
|
446
549
|
if (!targetDir) continue;
|
|
447
|
-
const dest =
|
|
550
|
+
const dest = path5.join(projectDir, targetDir);
|
|
448
551
|
ensureDir(dest);
|
|
449
552
|
for (const file of files) {
|
|
450
553
|
if (componentType === "rules" && toolId === "cursor") {
|
|
451
554
|
const mdcContent = convertToMdc(file, packName ?? "unknown");
|
|
452
|
-
const mdcName =
|
|
453
|
-
const destPath =
|
|
454
|
-
ensureDir(
|
|
455
|
-
|
|
555
|
+
const mdcName = path5.basename(file, ".md") + ".mdc";
|
|
556
|
+
const destPath = path5.join(dest, mdcName);
|
|
557
|
+
ensureDir(path5.dirname(destPath));
|
|
558
|
+
fs6.writeFileSync(destPath, mdcContent);
|
|
456
559
|
trackFile(destPath);
|
|
457
560
|
} else {
|
|
458
|
-
copyFile(file,
|
|
561
|
+
copyFile(file, path5.join(dest, path5.basename(file)));
|
|
459
562
|
}
|
|
460
563
|
}
|
|
461
564
|
}
|
|
@@ -465,24 +568,24 @@ function installHooks(hookFiles, tools, projectDir) {
|
|
|
465
568
|
if (hookFiles.length === 0) return 0;
|
|
466
569
|
if (!tools.includes("claude-code")) return 0;
|
|
467
570
|
let count = 0;
|
|
468
|
-
const targetHooksDir =
|
|
571
|
+
const targetHooksDir = path5.join(projectDir, ".claude", "hooks");
|
|
469
572
|
for (const hookFile of hookFiles) {
|
|
470
|
-
if (!
|
|
471
|
-
const raw = JSON.parse(
|
|
573
|
+
if (!fs6.existsSync(hookFile)) continue;
|
|
574
|
+
const raw = JSON.parse(fs6.readFileSync(hookFile, "utf-8"));
|
|
472
575
|
if (!raw.hooks || Object.keys(raw.hooks).length === 0) continue;
|
|
473
|
-
const hookSourceDir =
|
|
576
|
+
const hookSourceDir = path5.dirname(hookFile);
|
|
474
577
|
const scriptFiles = findScriptFiles(hookSourceDir);
|
|
475
578
|
for (const script of scriptFiles) {
|
|
476
|
-
const relPath =
|
|
477
|
-
const destPath =
|
|
579
|
+
const relPath = path5.relative(hookSourceDir, script);
|
|
580
|
+
const destPath = path5.join(targetHooksDir, relPath);
|
|
478
581
|
copyFile(script, destPath);
|
|
479
|
-
|
|
582
|
+
fs6.chmodSync(destPath, 493);
|
|
480
583
|
}
|
|
481
584
|
const rewritten = JSON.stringify(raw.hooks).replace(/\$\{CLAUDE_PLUGIN_ROOT\}\/hooks/g, ".claude/hooks");
|
|
482
|
-
const projectHooksPath =
|
|
585
|
+
const projectHooksPath = path5.join(projectDir, ".claude", "hooks.json");
|
|
483
586
|
let existing = {};
|
|
484
|
-
if (
|
|
485
|
-
const parsed = JSON.parse(
|
|
587
|
+
if (fs6.existsSync(projectHooksPath)) {
|
|
588
|
+
const parsed = JSON.parse(fs6.readFileSync(projectHooksPath, "utf-8"));
|
|
486
589
|
existing = parsed.hooks ?? parsed;
|
|
487
590
|
}
|
|
488
591
|
const newHooks = JSON.parse(rewritten);
|
|
@@ -490,8 +593,8 @@ function installHooks(hookFiles, tools, projectDir) {
|
|
|
490
593
|
if (!existing[event]) existing[event] = [];
|
|
491
594
|
existing[event].push(...handlers);
|
|
492
595
|
}
|
|
493
|
-
ensureDir(
|
|
494
|
-
|
|
596
|
+
ensureDir(path5.dirname(projectHooksPath));
|
|
597
|
+
fs6.writeFileSync(
|
|
495
598
|
projectHooksPath,
|
|
496
599
|
JSON.stringify({ hooks: existing }, null, 2) + "\n"
|
|
497
600
|
);
|
|
@@ -502,9 +605,9 @@ function installHooks(hookFiles, tools, projectDir) {
|
|
|
502
605
|
}
|
|
503
606
|
function findScriptFiles(dir) {
|
|
504
607
|
const scripts = [];
|
|
505
|
-
if (!
|
|
506
|
-
for (const entry of
|
|
507
|
-
const fullPath =
|
|
608
|
+
if (!fs6.existsSync(dir)) return scripts;
|
|
609
|
+
for (const entry of fs6.readdirSync(dir, { withFileTypes: true })) {
|
|
610
|
+
const fullPath = path5.join(dir, entry.name);
|
|
508
611
|
if (entry.isDirectory()) {
|
|
509
612
|
scripts.push(...findScriptFiles(fullPath));
|
|
510
613
|
} else if (/\.(sh|js|ts)$/.test(entry.name)) {
|
|
@@ -545,64 +648,64 @@ function installPack(options) {
|
|
|
545
648
|
function removePack2(projectDir, files) {
|
|
546
649
|
let removed = 0;
|
|
547
650
|
for (const relFile of files) {
|
|
548
|
-
const absPath =
|
|
549
|
-
if (!
|
|
651
|
+
const absPath = path5.join(projectDir, relFile);
|
|
652
|
+
if (!fs6.existsSync(absPath) && !isSymlink(absPath)) continue;
|
|
550
653
|
if (isSymlink(absPath)) {
|
|
551
|
-
|
|
552
|
-
} else if (
|
|
553
|
-
|
|
654
|
+
fs6.unlinkSync(absPath);
|
|
655
|
+
} else if (fs6.statSync(absPath).isDirectory()) {
|
|
656
|
+
fs6.rmSync(absPath, { recursive: true });
|
|
554
657
|
} else {
|
|
555
|
-
|
|
658
|
+
fs6.unlinkSync(absPath);
|
|
556
659
|
}
|
|
557
660
|
removed++;
|
|
558
|
-
let parent =
|
|
661
|
+
let parent = path5.dirname(absPath);
|
|
559
662
|
while (parent !== projectDir && parent.length > projectDir.length) {
|
|
560
663
|
try {
|
|
561
|
-
const entries =
|
|
664
|
+
const entries = fs6.readdirSync(parent);
|
|
562
665
|
if (entries.length === 0) {
|
|
563
|
-
|
|
666
|
+
fs6.rmdirSync(parent);
|
|
564
667
|
} else {
|
|
565
668
|
break;
|
|
566
669
|
}
|
|
567
670
|
} catch {
|
|
568
671
|
break;
|
|
569
672
|
}
|
|
570
|
-
parent =
|
|
673
|
+
parent = path5.dirname(parent);
|
|
571
674
|
}
|
|
572
675
|
}
|
|
573
676
|
return removed;
|
|
574
677
|
}
|
|
575
678
|
function isSymlink(p3) {
|
|
576
679
|
try {
|
|
577
|
-
return
|
|
680
|
+
return fs6.lstatSync(p3).isSymbolicLink();
|
|
578
681
|
} catch {
|
|
579
682
|
return false;
|
|
580
683
|
}
|
|
581
684
|
}
|
|
582
685
|
|
|
583
686
|
// src/global-config.ts
|
|
584
|
-
import
|
|
585
|
-
import
|
|
586
|
-
import
|
|
687
|
+
import fs7 from "fs";
|
|
688
|
+
import path6 from "path";
|
|
689
|
+
import os2 from "os";
|
|
587
690
|
function getConfigDir() {
|
|
588
|
-
return
|
|
691
|
+
return path6.join(os2.homedir(), ".config", "ai-kit");
|
|
589
692
|
}
|
|
590
693
|
function getConfigPath() {
|
|
591
|
-
return
|
|
694
|
+
return path6.join(getConfigDir(), "config.json");
|
|
592
695
|
}
|
|
593
696
|
function readGlobalConfig() {
|
|
594
697
|
const fp = getConfigPath();
|
|
595
|
-
if (!
|
|
698
|
+
if (!fs7.existsSync(fp)) return null;
|
|
596
699
|
try {
|
|
597
|
-
return JSON.parse(
|
|
700
|
+
return JSON.parse(fs7.readFileSync(fp, "utf-8"));
|
|
598
701
|
} catch {
|
|
599
702
|
return null;
|
|
600
703
|
}
|
|
601
704
|
}
|
|
602
705
|
function writeGlobalConfig(config) {
|
|
603
706
|
const dir = getConfigDir();
|
|
604
|
-
|
|
605
|
-
|
|
707
|
+
fs7.mkdirSync(dir, { recursive: true });
|
|
708
|
+
fs7.writeFileSync(getConfigPath(), JSON.stringify(config, null, 2) + "\n");
|
|
606
709
|
}
|
|
607
710
|
function getGlobalTools() {
|
|
608
711
|
const config = readGlobalConfig();
|
|
@@ -613,10 +716,19 @@ function saveGlobalTools(tools) {
|
|
|
613
716
|
writeGlobalConfig({ ...existing, tools });
|
|
614
717
|
}
|
|
615
718
|
|
|
719
|
+
// src/global-opts.ts
|
|
720
|
+
var _opts = {};
|
|
721
|
+
function setGlobalRegistryOptions(opts) {
|
|
722
|
+
_opts = opts;
|
|
723
|
+
}
|
|
724
|
+
function getRegistryOptions() {
|
|
725
|
+
return _opts;
|
|
726
|
+
}
|
|
727
|
+
|
|
616
728
|
// src/commands/init.ts
|
|
617
729
|
var initCommand = new Command("init").description("Interactive first-time setup").option("--cwd <dir>", "Project directory (for monorepo sub-packages)").action(async (opts) => {
|
|
618
730
|
p.intro(pc.bgCyan(pc.black(" ai-kit ")));
|
|
619
|
-
const projectDir = opts.cwd ?
|
|
731
|
+
const projectDir = opts.cwd ? path7.resolve(opts.cwd) : process.cwd();
|
|
620
732
|
const existing = readConfig(projectDir);
|
|
621
733
|
if (existing) {
|
|
622
734
|
const action = await p.select({
|
|
@@ -632,7 +744,58 @@ var initCommand = new Command("init").description("Interactive first-time setup"
|
|
|
632
744
|
return;
|
|
633
745
|
}
|
|
634
746
|
if (action === "add") {
|
|
635
|
-
p.
|
|
747
|
+
const s2 = p.spinner();
|
|
748
|
+
let packs2;
|
|
749
|
+
try {
|
|
750
|
+
s2.start("Fetching available packs...");
|
|
751
|
+
packs2 = await discoverPacks(getRegistryOptions());
|
|
752
|
+
s2.stop("Packs loaded.");
|
|
753
|
+
} catch {
|
|
754
|
+
s2.stop("Failed.");
|
|
755
|
+
p.log.error("Could not fetch packs.");
|
|
756
|
+
p.outro("Failed.");
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
const installedNames = Object.keys(existing.packs);
|
|
760
|
+
const available = packs2.filter((pk) => !installedNames.includes(pk.name));
|
|
761
|
+
if (available.length === 0) {
|
|
762
|
+
p.outro("All packs are already installed!");
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
const packSelection2 = await p.autocompleteMultiselect({
|
|
766
|
+
message: "Which packs do you want to add? (type to filter)",
|
|
767
|
+
options: available.map((pk) => ({
|
|
768
|
+
value: pk.name,
|
|
769
|
+
label: pk.name,
|
|
770
|
+
hint: pk.description
|
|
771
|
+
})),
|
|
772
|
+
required: true
|
|
773
|
+
});
|
|
774
|
+
if (p.isCancel(packSelection2)) {
|
|
775
|
+
p.outro("Cancelled.");
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
const selectedNames = packSelection2;
|
|
779
|
+
const installSpinner2 = p.spinner();
|
|
780
|
+
installSpinner2.start("Installing packs...");
|
|
781
|
+
let config2 = existing;
|
|
782
|
+
const selectedPacks2 = packs2.filter((pk) => selectedNames.includes(pk.name));
|
|
783
|
+
for (const pack of selectedPacks2) {
|
|
784
|
+
const result = installPack({
|
|
785
|
+
pack,
|
|
786
|
+
tools: existing.tools,
|
|
787
|
+
projectDir
|
|
788
|
+
});
|
|
789
|
+
config2 = mergeInstall(config2, result);
|
|
790
|
+
config2.packs[pack.name].version = pack.version;
|
|
791
|
+
}
|
|
792
|
+
writeConfig(projectDir, config2);
|
|
793
|
+
updateGitignore(projectDir);
|
|
794
|
+
installSpinner2.stop("Done!");
|
|
795
|
+
for (const pack of selectedPacks2) {
|
|
796
|
+
p.log.message(` ${pc.green("+")} ${pack.name} ${pc.dim(`v${pack.version}`)}`);
|
|
797
|
+
}
|
|
798
|
+
p.outro(`Added ${selectedPacks2.length} pack(s).`);
|
|
636
799
|
return;
|
|
637
800
|
}
|
|
638
801
|
}
|
|
@@ -653,10 +816,14 @@ var initCommand = new Command("init").description("Interactive first-time setup"
|
|
|
653
816
|
}
|
|
654
817
|
const selectedTools = toolSelection;
|
|
655
818
|
saveGlobalTools(selectedTools);
|
|
819
|
+
const s = p.spinner();
|
|
656
820
|
let packs;
|
|
657
821
|
try {
|
|
658
|
-
|
|
822
|
+
s.start("Fetching available packs...");
|
|
823
|
+
packs = await discoverPacks(getRegistryOptions());
|
|
824
|
+
s.stop("Packs loaded.");
|
|
659
825
|
} catch {
|
|
826
|
+
s.stop("Failed.");
|
|
660
827
|
p.log.error("Could not find marketplace.json. Is ai-kit installed correctly?");
|
|
661
828
|
p.outro("Setup failed.");
|
|
662
829
|
return;
|
|
@@ -708,8 +875,8 @@ var initCommand = new Command("init").description("Interactive first-time setup"
|
|
|
708
875
|
}
|
|
709
876
|
filter = components;
|
|
710
877
|
}
|
|
711
|
-
const
|
|
712
|
-
|
|
878
|
+
const installSpinner = p.spinner();
|
|
879
|
+
installSpinner.start("Installing packs...");
|
|
713
880
|
let config = createDefaultConfig(selectedTools);
|
|
714
881
|
const selectedPacks = packs.filter((p3) => selectedPackNames.includes(p3.name));
|
|
715
882
|
for (const pack of selectedPacks) {
|
|
@@ -723,7 +890,7 @@ var initCommand = new Command("init").description("Interactive first-time setup"
|
|
|
723
890
|
}
|
|
724
891
|
writeConfig(projectDir, config);
|
|
725
892
|
updateGitignore(projectDir);
|
|
726
|
-
|
|
893
|
+
installSpinner.stop("Done!");
|
|
727
894
|
p.log.success(`Installed ${selectedPacks.length} pack(s) for ${selectedTools.length} tool(s):`);
|
|
728
895
|
for (const pack of selectedPacks) {
|
|
729
896
|
p.log.message(` ${pc.green("+")} ${pack.name} ${pc.dim(`v${pack.version}`)}`);
|
|
@@ -733,7 +900,7 @@ var initCommand = new Command("init").description("Interactive first-time setup"
|
|
|
733
900
|
|
|
734
901
|
// src/commands/add.ts
|
|
735
902
|
import { Command as Command2 } from "commander";
|
|
736
|
-
import
|
|
903
|
+
import path8 from "path";
|
|
737
904
|
import pc2 from "picocolors";
|
|
738
905
|
import * as p2 from "@clack/prompts";
|
|
739
906
|
async function resolveTools(toolsFlag, projectDir) {
|
|
@@ -763,10 +930,11 @@ async function resolveTools(toolsFlag, projectDir) {
|
|
|
763
930
|
return tools;
|
|
764
931
|
}
|
|
765
932
|
var addCommand = new Command2("add").description("Add a pack to your project").argument("<pack>", "Pack name (e.g., django, nextjs)").option("--skills-only", "Only install skills").option("--agents-only", "Only install agents").option("--rules-only", "Only install rules").option("--commands-only", "Only install commands").option("--hooks-only", "Only install hooks").option("--tools <tools>", "Comma-separated tool IDs (overrides config)").option("--cwd <dir>", "Project directory (for monorepo sub-packages)").action(async (packName, opts) => {
|
|
766
|
-
const projectDir = opts.cwd ?
|
|
767
|
-
const
|
|
933
|
+
const projectDir = opts.cwd ? path8.resolve(opts.cwd) : process.cwd();
|
|
934
|
+
const registryOpts = getRegistryOptions();
|
|
935
|
+
const pack = await findPack(packName, registryOpts);
|
|
768
936
|
if (!pack) {
|
|
769
|
-
const available = discoverPacks().map((p3) => p3.name);
|
|
937
|
+
const available = (await discoverPacks(registryOpts)).map((p3) => p3.name);
|
|
770
938
|
console.error(
|
|
771
939
|
pc2.red(`Pack "${packName}" not found.`) + "\nAvailable: " + available.join(", ")
|
|
772
940
|
);
|
|
@@ -803,7 +971,7 @@ var addCommand = new Command2("add").description("Add a pack to your project").a
|
|
|
803
971
|
// src/commands/list.ts
|
|
804
972
|
import { Command as Command3 } from "commander";
|
|
805
973
|
import pc3 from "picocolors";
|
|
806
|
-
var listCommand = new Command3("list").description("List available or installed packs").option("--installed", "Show only installed packs").option("--cwd <dir>", "Project directory").action((opts) => {
|
|
974
|
+
var listCommand = new Command3("list").description("List available or installed packs").option("--installed", "Show only installed packs").option("--cwd <dir>", "Project directory").action(async (opts) => {
|
|
807
975
|
const projectDir = opts.cwd ? opts.cwd : process.cwd();
|
|
808
976
|
if (opts.installed) {
|
|
809
977
|
const config2 = readConfig(projectDir);
|
|
@@ -822,7 +990,7 @@ ${pc3.dim(`Tools: ${config2.tools.join(", ")}`)}`);
|
|
|
822
990
|
}
|
|
823
991
|
let packs;
|
|
824
992
|
try {
|
|
825
|
-
packs = discoverPacks();
|
|
993
|
+
packs = await discoverPacks(getRegistryOptions());
|
|
826
994
|
} catch {
|
|
827
995
|
console.error(pc3.red("Could not find marketplace.json."));
|
|
828
996
|
process.exit(1);
|
|
@@ -851,10 +1019,10 @@ ${pc3.dim(`${packs.length} packs available`)}`);
|
|
|
851
1019
|
|
|
852
1020
|
// src/commands/remove.ts
|
|
853
1021
|
import { Command as Command4 } from "commander";
|
|
854
|
-
import
|
|
1022
|
+
import path9 from "path";
|
|
855
1023
|
import pc4 from "picocolors";
|
|
856
1024
|
var removeCommand = new Command4("remove").description("Remove a pack from your project").argument("<pack>", "Pack name to remove").option("--cwd <dir>", "Project directory").action((packName, opts) => {
|
|
857
|
-
const projectDir = opts.cwd ?
|
|
1025
|
+
const projectDir = opts.cwd ? path9.resolve(opts.cwd) : process.cwd();
|
|
858
1026
|
const config = readConfig(projectDir);
|
|
859
1027
|
if (!config) {
|
|
860
1028
|
console.log(pc4.dim("No packs installed."));
|
|
@@ -881,16 +1049,17 @@ var removeCommand = new Command4("remove").description("Remove a pack from your
|
|
|
881
1049
|
|
|
882
1050
|
// src/commands/update.ts
|
|
883
1051
|
import { Command as Command5 } from "commander";
|
|
884
|
-
import
|
|
1052
|
+
import path10 from "path";
|
|
885
1053
|
import pc5 from "picocolors";
|
|
886
1054
|
var updateCommand = new Command5("update").description("Update installed packs").argument("[pack]", "Pack name (omit to update all)").option("--cwd <dir>", "Project directory").action(async (packName, opts) => {
|
|
887
|
-
const projectDir = opts.cwd ?
|
|
1055
|
+
const projectDir = opts.cwd ? path10.resolve(opts.cwd) : process.cwd();
|
|
888
1056
|
const config = readConfig(projectDir);
|
|
889
1057
|
if (!config || Object.keys(config.packs).length === 0) {
|
|
890
1058
|
console.log(pc5.dim("No packs installed yet. Starting setup...\n"));
|
|
891
1059
|
await initCommand.parseAsync(["init", ...opts.cwd ? ["--cwd", opts.cwd] : []], { from: "user" });
|
|
892
1060
|
return;
|
|
893
1061
|
}
|
|
1062
|
+
const registryOpts = { ...getRegistryOptions(), noCache: true };
|
|
894
1063
|
const packsToUpdate = packName ? [packName] : Object.keys(config.packs);
|
|
895
1064
|
let updated = 0;
|
|
896
1065
|
let skipped = 0;
|
|
@@ -901,7 +1070,7 @@ var updateCommand = new Command5("update").description("Update installed packs")
|
|
|
901
1070
|
skipped++;
|
|
902
1071
|
continue;
|
|
903
1072
|
}
|
|
904
|
-
const available = findPack(name);
|
|
1073
|
+
const available = await findPack(name, registryOpts);
|
|
905
1074
|
if (!available) {
|
|
906
1075
|
console.log(pc5.yellow(`"${name}" not found in marketplace, skipping.`));
|
|
907
1076
|
skipped++;
|
|
@@ -942,10 +1111,10 @@ Updated ${updated} pack(s).`));
|
|
|
942
1111
|
// src/commands/search.ts
|
|
943
1112
|
import { Command as Command6 } from "commander";
|
|
944
1113
|
import pc6 from "picocolors";
|
|
945
|
-
var searchCommand = new Command6("search").description("Search available packs by name or keyword").argument("<query>", "Search term (matches name, description, keywords)").action((query) => {
|
|
1114
|
+
var searchCommand = new Command6("search").description("Search available packs by name or keyword").argument("<query>", "Search term (matches name, description, keywords)").action(async (query) => {
|
|
946
1115
|
let packs;
|
|
947
1116
|
try {
|
|
948
|
-
packs = discoverPacks();
|
|
1117
|
+
packs = await discoverPacks(getRegistryOptions());
|
|
949
1118
|
} catch {
|
|
950
1119
|
console.error(pc6.red("Could not find marketplace.json."));
|
|
951
1120
|
process.exit(1);
|
|
@@ -984,12 +1153,28 @@ All packs: ${packs.map((p3) => p3.name).join(", ")}`));
|
|
|
984
1153
|
}
|
|
985
1154
|
});
|
|
986
1155
|
|
|
1156
|
+
// src/commands/cache.ts
|
|
1157
|
+
import { Command as Command7 } from "commander";
|
|
1158
|
+
import pc7 from "picocolors";
|
|
1159
|
+
var cacheCommand = new Command7("cache").description("Manage cached packs");
|
|
1160
|
+
cacheCommand.command("clear").description("Clear cached packs (forces re-download on next run)").action(() => {
|
|
1161
|
+
clearCache();
|
|
1162
|
+
console.log(pc7.green("Cache cleared.") + " Packs will be re-downloaded on next run.");
|
|
1163
|
+
});
|
|
1164
|
+
|
|
987
1165
|
// src/index.ts
|
|
988
|
-
var program = new
|
|
1166
|
+
var program = new Command8().name("ai-kit").description("AI coding tool pack manager").version("0.0.1").option("--no-cache", "Force re-download from GitHub (skip cache check)").option("--branch <branch>", "Use specific branch (default: main)").hook("preAction", () => {
|
|
1167
|
+
const opts = program.opts();
|
|
1168
|
+
setGlobalRegistryOptions({
|
|
1169
|
+
noCache: opts.cache === false,
|
|
1170
|
+
branch: opts.branch
|
|
1171
|
+
});
|
|
1172
|
+
});
|
|
989
1173
|
program.addCommand(initCommand);
|
|
990
1174
|
program.addCommand(addCommand);
|
|
991
1175
|
program.addCommand(listCommand);
|
|
992
1176
|
program.addCommand(removeCommand);
|
|
993
1177
|
program.addCommand(updateCommand);
|
|
994
1178
|
program.addCommand(searchCommand);
|
|
1179
|
+
program.addCommand(cacheCommand);
|
|
995
1180
|
program.parse();
|