@sporesec/arcana 2.3.1 → 3.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/dist/cli.d.ts +0 -1
- package/dist/cli.js +140 -10
- package/dist/command-registry.d.ts +10 -0
- package/dist/command-registry.js +65 -0
- package/dist/commands/audit.d.ts +0 -1
- package/dist/commands/audit.js +16 -6
- package/dist/commands/benchmark.d.ts +4 -0
- package/dist/commands/benchmark.js +178 -0
- package/dist/commands/clean.d.ts +2 -1
- package/dist/commands/clean.js +198 -47
- package/dist/commands/compact.d.ts +6 -0
- package/dist/commands/compact.js +239 -0
- package/dist/commands/completions.d.ts +3 -0
- package/dist/commands/completions.js +104 -0
- package/dist/commands/config.d.ts +0 -1
- package/dist/commands/config.js +15 -6
- package/dist/commands/create.d.ts +0 -1
- package/dist/commands/create.js +1 -1
- package/dist/commands/diff.d.ts +4 -0
- package/dist/commands/diff.js +166 -0
- package/dist/commands/doctor.d.ts +0 -1
- package/dist/commands/doctor.js +153 -24
- package/dist/commands/export-cmd.d.ts +4 -0
- package/dist/commands/export-cmd.js +66 -0
- package/dist/commands/import-cmd.d.ts +4 -0
- package/dist/commands/import-cmd.js +131 -0
- package/dist/commands/info.d.ts +0 -1
- package/dist/commands/info.js +29 -4
- package/dist/commands/init.d.ts +0 -1
- package/dist/commands/init.js +156 -117
- package/dist/commands/install.d.ts +1 -1
- package/dist/commands/install.js +118 -205
- package/dist/commands/list.d.ts +0 -1
- package/dist/commands/list.js +12 -4
- package/dist/commands/lock.d.ts +4 -0
- package/dist/commands/lock.js +171 -0
- package/dist/commands/optimize.d.ts +3 -0
- package/dist/commands/optimize.js +356 -0
- package/dist/commands/outdated.d.ts +4 -0
- package/dist/commands/outdated.js +159 -0
- package/dist/commands/profile.d.ts +3 -0
- package/dist/commands/profile.js +274 -0
- package/dist/commands/providers.d.ts +0 -1
- package/dist/commands/providers.js +1 -4
- package/dist/commands/recommend.d.ts +5 -0
- package/dist/commands/recommend.js +96 -0
- package/dist/commands/scan.d.ts +0 -1
- package/dist/commands/scan.js +13 -7
- package/dist/commands/search.d.ts +2 -1
- package/dist/commands/search.js +32 -9
- package/dist/commands/stats.d.ts +0 -1
- package/dist/commands/stats.js +83 -16
- package/dist/commands/team.d.ts +3 -0
- package/dist/commands/team.js +291 -0
- package/dist/commands/uninstall.d.ts +0 -1
- package/dist/commands/uninstall.js +18 -4
- package/dist/commands/update.d.ts +0 -1
- package/dist/commands/update.js +155 -155
- package/dist/commands/validate.d.ts +0 -1
- package/dist/commands/validate.js +14 -6
- package/dist/commands/verify.d.ts +4 -0
- package/dist/commands/verify.js +116 -0
- package/dist/constants.d.ts +10 -0
- package/dist/constants.js +13 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/interactive/browse.d.ts +4 -0
- package/dist/interactive/browse.js +103 -0
- package/dist/interactive/categories.d.ts +4 -0
- package/dist/interactive/categories.js +87 -0
- package/dist/interactive/health.d.ts +1 -0
- package/dist/interactive/health.js +57 -0
- package/dist/interactive/helpers.d.ts +11 -0
- package/dist/interactive/helpers.js +66 -0
- package/dist/interactive/index.d.ts +1 -0
- package/dist/interactive/index.js +1 -0
- package/dist/interactive/manage.d.ts +2 -0
- package/dist/interactive/manage.js +187 -0
- package/dist/interactive/menu.d.ts +1 -0
- package/dist/interactive/menu.js +107 -0
- package/dist/interactive/search.d.ts +2 -0
- package/dist/interactive/search.js +66 -0
- package/dist/interactive/setup.d.ts +2 -0
- package/dist/interactive/setup.js +48 -0
- package/dist/interactive/skill-detail.d.ts +5 -0
- package/dist/interactive/skill-detail.js +126 -0
- package/dist/interactive.d.ts +0 -1
- package/dist/interactive.js +89 -66
- package/dist/providers/arcana.d.ts +0 -1
- package/dist/providers/arcana.js +0 -1
- package/dist/providers/base.d.ts +0 -1
- package/dist/providers/base.js +0 -1
- package/dist/providers/github.d.ts +0 -1
- package/dist/providers/github.js +8 -3
- package/dist/registry.d.ts +0 -1
- package/dist/registry.js +1 -4
- package/dist/types.d.ts +10 -1
- package/dist/types.js +0 -1
- package/dist/utils/atomic.d.ts +0 -1
- package/dist/utils/atomic.js +3 -2
- package/dist/utils/cache.d.ts +0 -1
- package/dist/utils/cache.js +3 -2
- package/dist/utils/config.d.ts +2 -1
- package/dist/utils/config.js +30 -5
- package/dist/utils/conflict-check.d.ts +8 -0
- package/dist/utils/conflict-check.js +72 -0
- package/dist/utils/errors.d.ts +0 -1
- package/dist/utils/errors.js +0 -1
- package/dist/utils/frontmatter.d.ts +0 -1
- package/dist/utils/frontmatter.js +37 -10
- package/dist/utils/fs.d.ts +19 -1
- package/dist/utils/fs.js +105 -8
- package/dist/utils/help.d.ts +0 -1
- package/dist/utils/help.js +15 -28
- package/dist/utils/history.d.ts +0 -1
- package/dist/utils/history.js +0 -1
- package/dist/utils/http.d.ts +0 -1
- package/dist/utils/http.js +14 -5
- package/dist/utils/install-core.d.ts +48 -0
- package/dist/utils/install-core.js +108 -0
- package/dist/utils/integrity.d.ts +17 -0
- package/dist/utils/integrity.js +84 -0
- package/dist/utils/parallel.d.ts +0 -1
- package/dist/utils/parallel.js +0 -1
- package/dist/utils/project-context.d.ts +19 -0
- package/dist/utils/project-context.js +283 -0
- package/dist/utils/scanner.d.ts +0 -1
- package/dist/utils/scanner.js +138 -10
- package/dist/utils/scoring.d.ts +10 -0
- package/dist/utils/scoring.js +84 -0
- package/dist/utils/ui.d.ts +0 -1
- package/dist/utils/ui.js +11 -4
- package/dist/utils/validate.d.ts +0 -1
- package/dist/utils/validate.js +4 -1
- package/package.json +19 -7
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/commands/audit.d.ts.map +0 -1
- package/dist/commands/audit.js.map +0 -1
- package/dist/commands/audit.test.d.ts +0 -2
- package/dist/commands/audit.test.d.ts.map +0 -1
- package/dist/commands/audit.test.js +0 -217
- package/dist/commands/audit.test.js.map +0 -1
- package/dist/commands/clean.d.ts.map +0 -1
- package/dist/commands/clean.js.map +0 -1
- package/dist/commands/config.d.ts.map +0 -1
- package/dist/commands/config.js.map +0 -1
- package/dist/commands/create.d.ts.map +0 -1
- package/dist/commands/create.js.map +0 -1
- package/dist/commands/doctor.d.ts.map +0 -1
- package/dist/commands/doctor.js.map +0 -1
- package/dist/commands/info.d.ts.map +0 -1
- package/dist/commands/info.js.map +0 -1
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/install.d.ts.map +0 -1
- package/dist/commands/install.js.map +0 -1
- package/dist/commands/list.d.ts.map +0 -1
- package/dist/commands/list.js.map +0 -1
- package/dist/commands/providers.d.ts.map +0 -1
- package/dist/commands/providers.js.map +0 -1
- package/dist/commands/scan.d.ts.map +0 -1
- package/dist/commands/scan.js.map +0 -1
- package/dist/commands/search.d.ts.map +0 -1
- package/dist/commands/search.js.map +0 -1
- package/dist/commands/stats.d.ts.map +0 -1
- package/dist/commands/stats.js.map +0 -1
- package/dist/commands/uninstall.d.ts.map +0 -1
- package/dist/commands/uninstall.js.map +0 -1
- package/dist/commands/update.d.ts.map +0 -1
- package/dist/commands/update.js.map +0 -1
- package/dist/commands/validate.d.ts.map +0 -1
- package/dist/commands/validate.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/interactive.d.ts.map +0 -1
- package/dist/interactive.js.map +0 -1
- package/dist/providers/arcana.d.ts.map +0 -1
- package/dist/providers/arcana.js.map +0 -1
- package/dist/providers/base.d.ts.map +0 -1
- package/dist/providers/base.js.map +0 -1
- package/dist/providers/github.d.ts.map +0 -1
- package/dist/providers/github.js.map +0 -1
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/utils/atomic.d.ts.map +0 -1
- package/dist/utils/atomic.js.map +0 -1
- package/dist/utils/atomic.test.d.ts +0 -2
- package/dist/utils/atomic.test.d.ts.map +0 -1
- package/dist/utils/atomic.test.js +0 -31
- package/dist/utils/atomic.test.js.map +0 -1
- package/dist/utils/cache.d.ts.map +0 -1
- package/dist/utils/cache.js.map +0 -1
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/config.test.d.ts +0 -2
- package/dist/utils/config.test.d.ts.map +0 -1
- package/dist/utils/config.test.js +0 -38
- package/dist/utils/config.test.js.map +0 -1
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/frontmatter.d.ts.map +0 -1
- package/dist/utils/frontmatter.js.map +0 -1
- package/dist/utils/frontmatter.test.d.ts +0 -2
- package/dist/utils/frontmatter.test.d.ts.map +0 -1
- package/dist/utils/frontmatter.test.js +0 -152
- package/dist/utils/frontmatter.test.js.map +0 -1
- package/dist/utils/fs.d.ts.map +0 -1
- package/dist/utils/fs.js.map +0 -1
- package/dist/utils/fs.test.d.ts +0 -2
- package/dist/utils/fs.test.d.ts.map +0 -1
- package/dist/utils/fs.test.js +0 -145
- package/dist/utils/fs.test.js.map +0 -1
- package/dist/utils/help.d.ts.map +0 -1
- package/dist/utils/help.js.map +0 -1
- package/dist/utils/help.test.d.ts +0 -2
- package/dist/utils/help.test.d.ts.map +0 -1
- package/dist/utils/help.test.js +0 -66
- package/dist/utils/help.test.js.map +0 -1
- package/dist/utils/history.d.ts.map +0 -1
- package/dist/utils/history.js.map +0 -1
- package/dist/utils/http.d.ts.map +0 -1
- package/dist/utils/http.js.map +0 -1
- package/dist/utils/http.test.d.ts +0 -2
- package/dist/utils/http.test.d.ts.map +0 -1
- package/dist/utils/http.test.js +0 -55
- package/dist/utils/http.test.js.map +0 -1
- package/dist/utils/parallel.d.ts.map +0 -1
- package/dist/utils/parallel.js.map +0 -1
- package/dist/utils/scanner.d.ts.map +0 -1
- package/dist/utils/scanner.js.map +0 -1
- package/dist/utils/ui.d.ts.map +0 -1
- package/dist/utils/ui.js.map +0 -1
- package/dist/utils/ui.test.d.ts +0 -2
- package/dist/utils/ui.test.d.ts.map +0 -1
- package/dist/utils/ui.test.js +0 -31
- package/dist/utils/ui.test.js.map +0 -1
- package/dist/utils/validate.d.ts.map +0 -1
- package/dist/utils/validate.js.map +0 -1
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { getProvider } from "../registry.js";
|
|
3
|
+
import { installSkill, writeSkillMeta } from "../utils/fs.js";
|
|
4
|
+
import { loadConfig } from "../utils/config.js";
|
|
5
|
+
import { updateLockEntry } from "../utils/integrity.js";
|
|
6
|
+
import { validateSlug } from "../utils/validate.js";
|
|
7
|
+
function parseManifest(raw) {
|
|
8
|
+
const parsed = JSON.parse(raw);
|
|
9
|
+
if (typeof parsed !== "object" || parsed === null || !Array.isArray(parsed.skills)) {
|
|
10
|
+
throw new Error("Invalid manifest: expected object with 'skills' array");
|
|
11
|
+
}
|
|
12
|
+
const obj = parsed;
|
|
13
|
+
const skills = obj.skills.map((entry, i) => {
|
|
14
|
+
if (typeof entry !== "object" || entry === null) {
|
|
15
|
+
throw new Error(`Invalid manifest entry at index ${i}`);
|
|
16
|
+
}
|
|
17
|
+
const e = entry;
|
|
18
|
+
if (typeof e.name !== "string" || e.name.length === 0) {
|
|
19
|
+
throw new Error(`Invalid manifest entry at index ${i}: missing name`);
|
|
20
|
+
}
|
|
21
|
+
return {
|
|
22
|
+
name: e.name,
|
|
23
|
+
version: typeof e.version === "string" ? e.version : undefined,
|
|
24
|
+
source: typeof e.source === "string" ? e.source : undefined,
|
|
25
|
+
description: typeof e.description === "string" ? e.description : undefined,
|
|
26
|
+
};
|
|
27
|
+
});
|
|
28
|
+
return { skills };
|
|
29
|
+
}
|
|
30
|
+
export async function importCommand(file, opts) {
|
|
31
|
+
if (!existsSync(file)) {
|
|
32
|
+
if (opts.json) {
|
|
33
|
+
console.log(JSON.stringify({ error: `File not found: ${file}` }));
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.error(`Error: File not found: ${file}`);
|
|
37
|
+
}
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
let manifest;
|
|
41
|
+
try {
|
|
42
|
+
const raw = readFileSync(file, "utf-8");
|
|
43
|
+
manifest = parseManifest(raw);
|
|
44
|
+
}
|
|
45
|
+
catch (err) {
|
|
46
|
+
const msg = err instanceof Error ? err.message : "Failed to parse manifest";
|
|
47
|
+
if (opts.json) {
|
|
48
|
+
console.log(JSON.stringify({ error: msg }));
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.error(`Error: ${msg}`);
|
|
52
|
+
}
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
if (manifest.skills.length === 0) {
|
|
56
|
+
if (opts.json) {
|
|
57
|
+
console.log(JSON.stringify({ installed: [], skipped: [], failed: [], message: "No skills in manifest" }));
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
console.log("No skills found in manifest.");
|
|
61
|
+
}
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
const config = loadConfig();
|
|
65
|
+
const installed = [];
|
|
66
|
+
const skipped = [];
|
|
67
|
+
const failed = [];
|
|
68
|
+
const errors = {};
|
|
69
|
+
for (const entry of manifest.skills) {
|
|
70
|
+
// Validate skill name
|
|
71
|
+
try {
|
|
72
|
+
validateSlug(entry.name, "skill name");
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const msg = err instanceof Error ? err.message : "Invalid skill name";
|
|
76
|
+
failed.push(entry.name);
|
|
77
|
+
errors[entry.name] = msg;
|
|
78
|
+
if (!opts.json) {
|
|
79
|
+
console.error(`Skipping ${entry.name}: ${msg}`);
|
|
80
|
+
}
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
// Check if already installed (skip unless --force)
|
|
84
|
+
const { isSkillInstalled } = await import("../utils/fs.js");
|
|
85
|
+
if (isSkillInstalled(entry.name) && !opts.force) {
|
|
86
|
+
skipped.push(entry.name);
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
// Fetch and install
|
|
90
|
+
try {
|
|
91
|
+
const providerName = entry.source ?? config.defaultProvider;
|
|
92
|
+
const provider = getProvider(providerName);
|
|
93
|
+
const files = await provider.fetch(entry.name);
|
|
94
|
+
installSkill(entry.name, files);
|
|
95
|
+
const remote = await provider.info(entry.name);
|
|
96
|
+
const version = remote?.version ?? entry.version ?? "0.0.0";
|
|
97
|
+
writeSkillMeta(entry.name, {
|
|
98
|
+
version,
|
|
99
|
+
installedAt: new Date().toISOString(),
|
|
100
|
+
source: provider.name,
|
|
101
|
+
description: remote?.description ?? entry.description,
|
|
102
|
+
fileCount: files.length,
|
|
103
|
+
sizeBytes: files.reduce((s, f) => s + f.content.length, 0),
|
|
104
|
+
});
|
|
105
|
+
updateLockEntry(entry.name, version, provider.name, files);
|
|
106
|
+
installed.push(entry.name);
|
|
107
|
+
if (!opts.json) {
|
|
108
|
+
console.log(`Installed ${entry.name}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
const msg = err instanceof Error ? err.message : "unknown error";
|
|
113
|
+
failed.push(entry.name);
|
|
114
|
+
errors[entry.name] = msg;
|
|
115
|
+
if (!opts.json) {
|
|
116
|
+
console.error(`Failed to install ${entry.name}: ${msg}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (opts.json) {
|
|
121
|
+
const result = { installed, skipped, failed };
|
|
122
|
+
if (Object.keys(errors).length > 0)
|
|
123
|
+
result.errors = errors;
|
|
124
|
+
console.log(JSON.stringify(result));
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
console.log(`Import complete: ${installed.length} installed, ${skipped.length} skipped, ${failed.length} failed`);
|
|
128
|
+
}
|
|
129
|
+
if (failed.length > 0)
|
|
130
|
+
process.exit(1);
|
|
131
|
+
}
|
package/dist/commands/info.d.ts
CHANGED
package/dist/commands/info.js
CHANGED
|
@@ -39,7 +39,12 @@ export async function infoCommand(skillName, opts) {
|
|
|
39
39
|
installedVersion: meta?.version,
|
|
40
40
|
source: skill.source,
|
|
41
41
|
repo: skill.repo,
|
|
42
|
-
|
|
42
|
+
tags: skill.tags,
|
|
43
|
+
verified: skill.verified,
|
|
44
|
+
author: skill.author,
|
|
45
|
+
companions: skill.companions,
|
|
46
|
+
conflicts: skill.conflicts,
|
|
47
|
+
},
|
|
43
48
|
}));
|
|
44
49
|
return;
|
|
45
50
|
}
|
|
@@ -47,11 +52,32 @@ export async function infoCommand(skillName, opts) {
|
|
|
47
52
|
if (installed) {
|
|
48
53
|
const meta = readSkillMeta(skillName);
|
|
49
54
|
const localVersion = meta?.version ?? "unknown";
|
|
50
|
-
console.log(" " +
|
|
55
|
+
console.log(" " +
|
|
56
|
+
ui.success("Installed") +
|
|
57
|
+
(localVersion !== skill.version ? ui.warn(` (local: v${localVersion})`) : ""));
|
|
51
58
|
}
|
|
52
59
|
console.log();
|
|
53
60
|
console.log(" " + skill.description);
|
|
54
61
|
console.log();
|
|
62
|
+
if (skill.verified) {
|
|
63
|
+
console.log(" " + ui.success("[Verified]") + " Official skill");
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.log(ui.dim(" Community skill"));
|
|
67
|
+
}
|
|
68
|
+
if (skill.author) {
|
|
69
|
+
console.log(ui.dim(` Author: ${skill.author}`));
|
|
70
|
+
}
|
|
71
|
+
if (skill.tags && skill.tags.length > 0) {
|
|
72
|
+
console.log(ui.dim(` Tags: ${skill.tags.join(", ")}`));
|
|
73
|
+
}
|
|
74
|
+
if (skill.companions && skill.companions.length > 0) {
|
|
75
|
+
console.log(ui.dim(` Works with: ${skill.companions.join(", ")}`));
|
|
76
|
+
}
|
|
77
|
+
if (skill.conflicts && skill.conflicts.length > 0) {
|
|
78
|
+
console.log(ui.warn(` Conflicts: ${skill.conflicts.join(", ")}`));
|
|
79
|
+
}
|
|
80
|
+
console.log();
|
|
55
81
|
console.log(ui.dim(` Source: ${skill.source}`));
|
|
56
82
|
if (skill.repo) {
|
|
57
83
|
console.log(ui.dim(` Repo: ${skill.repo}`));
|
|
@@ -77,7 +103,7 @@ export async function infoCommand(skillName, opts) {
|
|
|
77
103
|
installed: true,
|
|
78
104
|
source: meta?.source ?? "local",
|
|
79
105
|
offline: true,
|
|
80
|
-
}
|
|
106
|
+
},
|
|
81
107
|
}));
|
|
82
108
|
return;
|
|
83
109
|
}
|
|
@@ -111,4 +137,3 @@ export async function infoCommand(skillName, opts) {
|
|
|
111
137
|
}
|
|
112
138
|
process.exit(1);
|
|
113
139
|
}
|
|
114
|
-
//# sourceMappingURL=info.js.map
|
package/dist/commands/init.d.ts
CHANGED
package/dist/commands/init.js
CHANGED
|
@@ -1,139 +1,122 @@
|
|
|
1
1
|
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
2
|
-
import { join,
|
|
2
|
+
import { join, dirname } from "node:path";
|
|
3
3
|
import * as p from "@clack/prompts";
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { renderBanner } from "../utils/help.js";
|
|
6
|
+
import { detectProjectContext } from "../utils/project-context.js";
|
|
6
7
|
export function detectProject(cwd) {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
return { name, type: "Go", lang: "go" };
|
|
10
|
-
if (existsSync(join(cwd, "Cargo.toml")))
|
|
11
|
-
return { name, type: "Rust", lang: "rust" };
|
|
12
|
-
if (existsSync(join(cwd, "requirements.txt")) || existsSync(join(cwd, "pyproject.toml")))
|
|
13
|
-
return { name, type: "Python", lang: "python" };
|
|
14
|
-
if (existsSync(join(cwd, "package.json"))) {
|
|
15
|
-
try {
|
|
16
|
-
const raw = readFileSync(join(cwd, "package.json"), "utf-8");
|
|
17
|
-
const pkg = JSON.parse(raw);
|
|
18
|
-
if (pkg.dependencies?.next || pkg.devDependencies?.next)
|
|
19
|
-
return { name, type: "Next.js", lang: "typescript" };
|
|
20
|
-
if (pkg.dependencies?.react || pkg.devDependencies?.react)
|
|
21
|
-
return { name, type: "React", lang: "typescript" };
|
|
22
|
-
}
|
|
23
|
-
catch { /* ignore */ }
|
|
24
|
-
return { name, type: "Node.js", lang: "typescript" };
|
|
25
|
-
}
|
|
26
|
-
return { name, type: "Unknown", lang: "general" };
|
|
8
|
+
const ctx = detectProjectContext(cwd);
|
|
9
|
+
return { name: ctx.name, type: ctx.type, lang: ctx.lang };
|
|
27
10
|
}
|
|
28
11
|
function claudeTemplate(proj) {
|
|
29
|
-
return `# CLAUDE.md - ${proj.name}
|
|
30
|
-
|
|
31
|
-
## Project
|
|
32
|
-
- **Type:** ${proj.type}
|
|
33
|
-
- **Language:** ${proj.lang}
|
|
34
|
-
|
|
35
|
-
## Coding Preferences
|
|
36
|
-
- Follow existing patterns in the codebase
|
|
37
|
-
- Handle errors explicitly
|
|
38
|
-
- Use meaningful variable names, no abbreviations
|
|
39
|
-
|
|
40
|
-
## Build & Test
|
|
41
|
-
<!-- Add build/test commands so Claude can verify changes -->
|
|
42
|
-
<!-- Example: npm test, go test ./..., pytest -->
|
|
43
|
-
|
|
44
|
-
## Project Structure
|
|
45
|
-
<!-- Describe your project structure here -->
|
|
12
|
+
return `# CLAUDE.md - ${proj.name}
|
|
13
|
+
|
|
14
|
+
## Project
|
|
15
|
+
- **Type:** ${proj.type}
|
|
16
|
+
- **Language:** ${proj.lang}
|
|
17
|
+
|
|
18
|
+
## Coding Preferences
|
|
19
|
+
- Follow existing patterns in the codebase
|
|
20
|
+
- Handle errors explicitly
|
|
21
|
+
- Use meaningful variable names, no abbreviations
|
|
22
|
+
|
|
23
|
+
## Build & Test
|
|
24
|
+
<!-- Add build/test commands so Claude can verify changes -->
|
|
25
|
+
<!-- Example: npm test, go test ./..., pytest -->
|
|
26
|
+
|
|
27
|
+
## Project Structure
|
|
28
|
+
<!-- Describe your project structure here -->
|
|
46
29
|
`;
|
|
47
30
|
}
|
|
48
31
|
function cursorTemplate(proj) {
|
|
49
|
-
return `---
|
|
50
|
-
description: Project conventions for ${proj.name}
|
|
51
|
-
globs:
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
# ${proj.name} (${proj.type})
|
|
55
|
-
|
|
56
|
-
## Language
|
|
57
|
-
${proj.lang}
|
|
58
|
-
|
|
59
|
-
## Coding Standards
|
|
60
|
-
- Follow existing patterns in the codebase
|
|
61
|
-
- Handle errors explicitly
|
|
62
|
-
- Use meaningful variable names
|
|
32
|
+
return `---
|
|
33
|
+
description: Project conventions for ${proj.name}
|
|
34
|
+
globs:
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
# ${proj.name} (${proj.type})
|
|
38
|
+
|
|
39
|
+
## Language
|
|
40
|
+
${proj.lang}
|
|
41
|
+
|
|
42
|
+
## Coding Standards
|
|
43
|
+
- Follow existing patterns in the codebase
|
|
44
|
+
- Handle errors explicitly
|
|
45
|
+
- Use meaningful variable names
|
|
63
46
|
`;
|
|
64
47
|
}
|
|
65
48
|
function codexTemplate(proj) {
|
|
66
|
-
return `# AGENTS.md - ${proj.name}
|
|
67
|
-
|
|
68
|
-
## Project
|
|
69
|
-
Type: ${proj.type} | Language: ${proj.lang}
|
|
70
|
-
|
|
71
|
-
## Sandbox
|
|
72
|
-
Codex runs in a sandboxed environment with no network access.
|
|
73
|
-
All dependencies must be pre-installed before the session.
|
|
74
|
-
|
|
75
|
-
## Guidelines
|
|
76
|
-
- Follow existing patterns in the codebase
|
|
77
|
-
- Handle errors explicitly
|
|
78
|
-
- Use meaningful variable names
|
|
49
|
+
return `# AGENTS.md - ${proj.name}
|
|
50
|
+
|
|
51
|
+
## Project
|
|
52
|
+
Type: ${proj.type} | Language: ${proj.lang}
|
|
53
|
+
|
|
54
|
+
## Sandbox
|
|
55
|
+
Codex runs in a sandboxed environment with no network access.
|
|
56
|
+
All dependencies must be pre-installed before the session.
|
|
57
|
+
|
|
58
|
+
## Guidelines
|
|
59
|
+
- Follow existing patterns in the codebase
|
|
60
|
+
- Handle errors explicitly
|
|
61
|
+
- Use meaningful variable names
|
|
79
62
|
`;
|
|
80
63
|
}
|
|
81
64
|
function geminiTemplate(proj) {
|
|
82
|
-
return `# GEMINI.md - ${proj.name}
|
|
83
|
-
|
|
84
|
-
## Project Context
|
|
85
|
-
This is a ${proj.type} project using ${proj.lang}.
|
|
86
|
-
|
|
87
|
-
## Project Files
|
|
88
|
-
<!-- List key files and directories so Gemini can navigate the codebase -->
|
|
89
|
-
<!-- Example: src/ - main source, tests/ - test files -->
|
|
90
|
-
|
|
91
|
-
## Instructions
|
|
92
|
-
- Follow existing patterns in the codebase
|
|
93
|
-
- Handle errors explicitly
|
|
94
|
-
- Use meaningful variable names
|
|
65
|
+
return `# GEMINI.md - ${proj.name}
|
|
66
|
+
|
|
67
|
+
## Project Context
|
|
68
|
+
This is a ${proj.type} project using ${proj.lang}.
|
|
69
|
+
|
|
70
|
+
## Project Files
|
|
71
|
+
<!-- List key files and directories so Gemini can navigate the codebase -->
|
|
72
|
+
<!-- Example: src/ - main source, tests/ - test files -->
|
|
73
|
+
|
|
74
|
+
## Instructions
|
|
75
|
+
- Follow existing patterns in the codebase
|
|
76
|
+
- Handle errors explicitly
|
|
77
|
+
- Use meaningful variable names
|
|
95
78
|
`;
|
|
96
79
|
}
|
|
97
80
|
function antigravityTemplate(proj) {
|
|
98
|
-
return `# Antigravity - ${proj.name}
|
|
99
|
-
|
|
100
|
-
## Project Context
|
|
101
|
-
This is a ${proj.type} project using ${proj.lang}.
|
|
102
|
-
Antigravity workspace: \`.agent/\` (rules, workflows, skills)
|
|
103
|
-
|
|
104
|
-
## Project Files
|
|
105
|
-
<!-- List key files and directories so the agent can navigate the codebase -->
|
|
106
|
-
<!-- Example: src/ - main source, tests/ - test files -->
|
|
107
|
-
|
|
108
|
-
## Instructions
|
|
109
|
-
- Follow existing patterns in the codebase
|
|
110
|
-
- Handle errors explicitly
|
|
111
|
-
- Use meaningful variable names
|
|
81
|
+
return `# Antigravity - ${proj.name}
|
|
82
|
+
|
|
83
|
+
## Project Context
|
|
84
|
+
This is a ${proj.type} project using ${proj.lang}.
|
|
85
|
+
Antigravity workspace: \`.agent/\` (rules, workflows, skills)
|
|
86
|
+
|
|
87
|
+
## Project Files
|
|
88
|
+
<!-- List key files and directories so the agent can navigate the codebase -->
|
|
89
|
+
<!-- Example: src/ - main source, tests/ - test files -->
|
|
90
|
+
|
|
91
|
+
## Instructions
|
|
92
|
+
- Follow existing patterns in the codebase
|
|
93
|
+
- Handle errors explicitly
|
|
94
|
+
- Use meaningful variable names
|
|
112
95
|
`;
|
|
113
96
|
}
|
|
114
97
|
function windsurfTemplate(proj) {
|
|
115
|
-
return `# Windsurf Cascades Rules - ${proj.name}
|
|
116
|
-
|
|
117
|
-
Project: ${proj.name} (${proj.type})
|
|
118
|
-
Language: ${proj.lang}
|
|
119
|
-
|
|
120
|
-
## Rules
|
|
121
|
-
- Follow existing patterns in the codebase
|
|
122
|
-
- Handle errors explicitly
|
|
123
|
-
- Use meaningful variable names
|
|
124
|
-
- Always explain changes before applying them
|
|
98
|
+
return `# Windsurf Cascades Rules - ${proj.name}
|
|
99
|
+
|
|
100
|
+
Project: ${proj.name} (${proj.type})
|
|
101
|
+
Language: ${proj.lang}
|
|
102
|
+
|
|
103
|
+
## Rules
|
|
104
|
+
- Follow existing patterns in the codebase
|
|
105
|
+
- Handle errors explicitly
|
|
106
|
+
- Use meaningful variable names
|
|
107
|
+
- Always explain changes before applying them
|
|
125
108
|
`;
|
|
126
109
|
}
|
|
127
110
|
function aiderTemplate(_proj) {
|
|
128
|
-
return `# Aider Configuration
|
|
129
|
-
model: sonnet
|
|
130
|
-
auto-commits: true
|
|
131
|
-
auto-test: false
|
|
132
|
-
# Add conventions below
|
|
133
|
-
conventions:
|
|
134
|
-
- Follow existing patterns in the codebase
|
|
135
|
-
- Write clean, maintainable code
|
|
136
|
-
- Handle errors explicitly
|
|
111
|
+
return `# Aider Configuration
|
|
112
|
+
model: sonnet
|
|
113
|
+
auto-commits: true
|
|
114
|
+
auto-test: false
|
|
115
|
+
# Add conventions below
|
|
116
|
+
conventions:
|
|
117
|
+
- Follow existing patterns in the codebase
|
|
118
|
+
- Write clean, maintainable code
|
|
119
|
+
- Handle errors explicitly
|
|
137
120
|
`;
|
|
138
121
|
}
|
|
139
122
|
const TOOL_FILES = {
|
|
@@ -150,14 +133,19 @@ const TOOL_FILES = {
|
|
|
150
133
|
aider: { path: ".aider.conf.yml", template: aiderTemplate, label: "Aider" },
|
|
151
134
|
};
|
|
152
135
|
export const SKILL_SUGGESTIONS = {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
136
|
+
Go: ["golang-pro", "go-linter-configuration", "testing-strategy", "security-review"],
|
|
137
|
+
Rust: ["rust-best-practices", "testing-strategy", "security-review"],
|
|
138
|
+
Python: ["python-best-practices", "testing-strategy", "security-review"],
|
|
156
139
|
"Next.js": ["typescript", "typescript-advanced", "frontend-design", "performance-optimization", "security-review"],
|
|
157
|
-
|
|
140
|
+
React: ["typescript", "frontend-design", "frontend-code-review", "testing-strategy"],
|
|
158
141
|
"Node.js": ["typescript", "npm-package", "testing-strategy", "security-review"],
|
|
159
142
|
};
|
|
160
|
-
export const SKILL_SUGGESTIONS_DEFAULT = [
|
|
143
|
+
export const SKILL_SUGGESTIONS_DEFAULT = [
|
|
144
|
+
"code-reviewer",
|
|
145
|
+
"security-review",
|
|
146
|
+
"codebase-dissection",
|
|
147
|
+
"testing-strategy",
|
|
148
|
+
];
|
|
161
149
|
export async function initCommand(opts) {
|
|
162
150
|
console.log(renderBanner());
|
|
163
151
|
console.log();
|
|
@@ -208,9 +196,60 @@ export async function initCommand(opts) {
|
|
|
208
196
|
}
|
|
209
197
|
if (skipped > 0)
|
|
210
198
|
p.log.info(`${skipped} skipped (already exist)`);
|
|
199
|
+
// Offer to install PreCompact hook for context preservation
|
|
200
|
+
const globalSettings = join(process.env.HOME || process.env.USERPROFILE || "", ".claude", "settings.json");
|
|
201
|
+
let hasPreCompactHook = false;
|
|
202
|
+
if (existsSync(globalSettings)) {
|
|
203
|
+
try {
|
|
204
|
+
const settings = JSON.parse(readFileSync(globalSettings, "utf-8"));
|
|
205
|
+
hasPreCompactHook = Array.isArray(settings?.hooks?.PreCompact) && settings.hooks.PreCompact.length > 0;
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
/* ignore */
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
if (!hasPreCompactHook) {
|
|
212
|
+
const installHook = await p.confirm({
|
|
213
|
+
message: "Install PreCompact hook? (preserves context before auto-compaction)",
|
|
214
|
+
initialValue: true,
|
|
215
|
+
});
|
|
216
|
+
if (p.isCancel(installHook)) {
|
|
217
|
+
p.cancel("Cancelled");
|
|
218
|
+
process.exit(0);
|
|
219
|
+
}
|
|
220
|
+
if (installHook) {
|
|
221
|
+
try {
|
|
222
|
+
let settings = {};
|
|
223
|
+
if (existsSync(globalSettings)) {
|
|
224
|
+
settings = JSON.parse(readFileSync(globalSettings, "utf-8"));
|
|
225
|
+
}
|
|
226
|
+
const hooks = (settings.hooks ?? {});
|
|
227
|
+
hooks.PreCompact = [
|
|
228
|
+
{
|
|
229
|
+
matcher: "",
|
|
230
|
+
hooks: [
|
|
231
|
+
{
|
|
232
|
+
type: "command",
|
|
233
|
+
command: 'bash -c \'PROJ_DIR="$HOME/.claude/projects"; for d in "$PROJ_DIR"/*/memory; do if [ -d "$d" ]; then echo "## Handover $(date +%Y-%m-%d_%H%M)" >> "$d/HANDOVER.md"; echo "Auto-compaction triggered. Review MEMORY.md for preserved context." >> "$d/HANDOVER.md"; echo "" >> "$d/HANDOVER.md"; fi; done\'',
|
|
234
|
+
timeout: 10,
|
|
235
|
+
},
|
|
236
|
+
],
|
|
237
|
+
},
|
|
238
|
+
];
|
|
239
|
+
settings.hooks = hooks;
|
|
240
|
+
writeFileSync(globalSettings, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
241
|
+
p.log.success("Installed PreCompact hook in ~/.claude/settings.json");
|
|
242
|
+
}
|
|
243
|
+
catch (err) {
|
|
244
|
+
p.log.warn(`Could not install hook: ${err instanceof Error ? err.message : "unknown"}`);
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
else {
|
|
249
|
+
p.log.info("PreCompact hook already installed");
|
|
250
|
+
}
|
|
211
251
|
const suggestions = SKILL_SUGGESTIONS[proj.type] || SKILL_SUGGESTIONS_DEFAULT;
|
|
212
252
|
const skillList = suggestions.map((s) => `arcana install ${s}`).join("\n");
|
|
213
253
|
p.note(skillList, "Recommended skills");
|
|
214
254
|
p.outro(`Next: ${chalk.cyan("arcana install <skill>")} or ${chalk.cyan("arcana install --all")}`);
|
|
215
255
|
}
|
|
216
|
-
//# sourceMappingURL=init.js.map
|