@supercorks/skills-installer 1.6.0 → 1.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -3
- package/bin/install.js +15 -8
- package/lib/git.js +9 -1
- package/lib/prompts.js +14 -11
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,9 +17,8 @@ npx @supercorks/skills-installer install
|
|
|
17
17
|
## What it does
|
|
18
18
|
|
|
19
19
|
1. **Choose installation path(s)** - Select one or more locations where skills should be installed:
|
|
20
|
-
- `.github/skills/` (
|
|
21
|
-
-
|
|
22
|
-
- `/etc/codex/skills/` (System-level skills)
|
|
20
|
+
- `.github/skills/` (Copilot)
|
|
21
|
+
- `~/.codex/skills/` (Codex)
|
|
23
22
|
- `.claude/skills/` (Claude)
|
|
24
23
|
- Custom path of your choice
|
|
25
24
|
|
package/bin/install.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import { existsSync, appendFileSync, readFileSync, writeFileSync } from 'fs';
|
|
11
11
|
import { resolve, join } from 'path';
|
|
12
|
+
import { homedir } from 'os';
|
|
12
13
|
import {
|
|
13
14
|
promptInstallType,
|
|
14
15
|
promptInstallPath,
|
|
@@ -40,8 +41,14 @@ const require = createRequire(import.meta.url);
|
|
|
40
41
|
const { version: VERSION } = require('../package.json');
|
|
41
42
|
|
|
42
43
|
// Common installation paths to check for existing installations
|
|
43
|
-
const SKILL_PATHS = ['.github/skills/', '
|
|
44
|
-
const AGENT_PATHS = ['.github/agents/', '.claude/agents/'];
|
|
44
|
+
const SKILL_PATHS = ['.github/skills/', '~/.codex/skills/', '.claude/skills/'];
|
|
45
|
+
const AGENT_PATHS = ['.github/agents/', '.agents/agents/', '.claude/agents/'];
|
|
46
|
+
|
|
47
|
+
function resolveInstallPath(path) {
|
|
48
|
+
if (path === '~') return homedir();
|
|
49
|
+
if (path.startsWith('~/')) return resolve(homedir(), path.slice(2));
|
|
50
|
+
return resolve(process.cwd(), path);
|
|
51
|
+
}
|
|
45
52
|
|
|
46
53
|
/**
|
|
47
54
|
* Detect existing skill installations in common paths
|
|
@@ -51,7 +58,7 @@ async function detectExistingSkillInstallations() {
|
|
|
51
58
|
const installations = [];
|
|
52
59
|
|
|
53
60
|
for (const path of SKILL_PATHS) {
|
|
54
|
-
const absolutePath =
|
|
61
|
+
const absolutePath = resolveInstallPath(path);
|
|
55
62
|
const gitDir = join(absolutePath, '.git');
|
|
56
63
|
|
|
57
64
|
if (existsSync(gitDir)) {
|
|
@@ -79,7 +86,7 @@ async function detectExistingAgentInstallations() {
|
|
|
79
86
|
const installations = [];
|
|
80
87
|
|
|
81
88
|
for (const path of AGENT_PATHS) {
|
|
82
|
-
const absolutePath =
|
|
89
|
+
const absolutePath = resolveInstallPath(path);
|
|
83
90
|
const gitDir = join(absolutePath, '.git');
|
|
84
91
|
|
|
85
92
|
if (existsSync(gitDir)) {
|
|
@@ -227,7 +234,7 @@ async function runSkillsInstall() {
|
|
|
227
234
|
*/
|
|
228
235
|
async function runSkillsInstallForTarget(skills, existingInstalls, target) {
|
|
229
236
|
const { path: installPath, isExisting } = target;
|
|
230
|
-
const absoluteInstallPath =
|
|
237
|
+
const absoluteInstallPath = resolveInstallPath(installPath);
|
|
231
238
|
|
|
232
239
|
// Get currently installed skills if managing existing installation
|
|
233
240
|
let installedSkills = [];
|
|
@@ -266,7 +273,7 @@ async function runSkillsInstallForTarget(skills, existingInstalls, target) {
|
|
|
266
273
|
|
|
267
274
|
// Ask about .gitignore (only for fresh installs and if not already in .gitignore)
|
|
268
275
|
let shouldGitignore = false;
|
|
269
|
-
const gitignorePath =
|
|
276
|
+
const gitignorePath = resolveInstallPath('.gitignore');
|
|
270
277
|
if (!isManageMode && !isInGitignore(gitignorePath, installPath)) {
|
|
271
278
|
shouldGitignore = await promptGitignore(installPath);
|
|
272
279
|
}
|
|
@@ -374,7 +381,7 @@ async function runSubagentsInstall() {
|
|
|
374
381
|
*/
|
|
375
382
|
async function runSubagentsInstallForTarget(subagents, existingInstalls, target) {
|
|
376
383
|
const { path: installPath, isExisting } = target;
|
|
377
|
-
const absoluteInstallPath =
|
|
384
|
+
const absoluteInstallPath = resolveInstallPath(installPath);
|
|
378
385
|
|
|
379
386
|
// Get currently installed subagents if managing existing installation
|
|
380
387
|
let installedAgents = [];
|
|
@@ -413,7 +420,7 @@ async function runSubagentsInstallForTarget(subagents, existingInstalls, target)
|
|
|
413
420
|
|
|
414
421
|
// Ask about .gitignore (only for fresh installs and if not already in .gitignore)
|
|
415
422
|
let shouldGitignore = false;
|
|
416
|
-
const gitignorePath =
|
|
423
|
+
const gitignorePath = resolveInstallPath('.gitignore');
|
|
417
424
|
if (!isManageMode && !isInGitignore(gitignorePath, installPath)) {
|
|
418
425
|
shouldGitignore = await promptGitignore(installPath);
|
|
419
426
|
}
|
package/lib/git.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { execSync, spawn } from 'child_process';
|
|
6
|
-
import { existsSync, mkdirSync, rmSync, writeFileSync, readFileSync, appendFileSync } from 'fs';
|
|
6
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync, readFileSync, appendFileSync, readdirSync } from 'fs';
|
|
7
7
|
import { join, resolve } from 'path';
|
|
8
8
|
import { getRepoUrl } from './skills.js';
|
|
9
9
|
import { getSubagentsRepoUrl } from './subagents.js';
|
|
@@ -71,6 +71,10 @@ export async function sparseCloneSkills(targetPath, skillFolders, onProgress = (
|
|
|
71
71
|
if (existsSync(gitDir)) {
|
|
72
72
|
throw new Error(`Directory "${targetPath}" already contains a git repository. Please remove it first or choose a different path.`);
|
|
73
73
|
}
|
|
74
|
+
const entries = readdirSync(absolutePath).filter(name => name !== '.DS_Store');
|
|
75
|
+
if (entries.length > 0) {
|
|
76
|
+
throw new Error(`Directory "${targetPath}" already exists and is not empty. Choose an empty directory or an existing managed installation.`);
|
|
77
|
+
}
|
|
74
78
|
}
|
|
75
79
|
|
|
76
80
|
// Create target directory
|
|
@@ -328,6 +332,10 @@ export async function sparseCloneSubagents(targetPath, agentFilenames, onProgres
|
|
|
328
332
|
if (existsSync(gitDir)) {
|
|
329
333
|
throw new Error(`Directory "${targetPath}" already contains a git repository. Please remove it first or choose a different path.`);
|
|
330
334
|
}
|
|
335
|
+
const entries = readdirSync(absolutePath).filter(name => name !== '.DS_Store');
|
|
336
|
+
if (entries.length > 0) {
|
|
337
|
+
throw new Error(`Directory "${targetPath}" already exists and is not empty. Choose an empty directory or an existing managed installation.`);
|
|
338
|
+
}
|
|
331
339
|
}
|
|
332
340
|
|
|
333
341
|
// Create target directory
|
package/lib/prompts.js
CHANGED
|
@@ -7,14 +7,14 @@ import * as readline from 'readline';
|
|
|
7
7
|
|
|
8
8
|
const SKILL_PATH_CHOICES = {
|
|
9
9
|
GITHUB: '.github/skills/',
|
|
10
|
-
|
|
11
|
-
ETC: '/etc/codex/skills/',
|
|
10
|
+
CODEX_HOME: '~/.codex/skills/',
|
|
12
11
|
CLAUDE: '.claude/skills/',
|
|
13
12
|
CUSTOM: '__custom__'
|
|
14
13
|
};
|
|
15
14
|
|
|
16
15
|
const AGENT_PATH_CHOICES = {
|
|
17
16
|
GITHUB: '.github/agents/',
|
|
17
|
+
CODEX: '.agents/agents/',
|
|
18
18
|
CLAUDE: '.claude/agents/',
|
|
19
19
|
CUSTOM: '__custom__'
|
|
20
20
|
};
|
|
@@ -80,15 +80,14 @@ export async function promptInstallPath(existingInstalls = []) {
|
|
|
80
80
|
|
|
81
81
|
// Standard path options
|
|
82
82
|
const standardPaths = [
|
|
83
|
-
SKILL_PATH_CHOICES.GITHUB,
|
|
84
|
-
SKILL_PATH_CHOICES.
|
|
85
|
-
SKILL_PATH_CHOICES.
|
|
86
|
-
SKILL_PATH_CHOICES.CLAUDE
|
|
83
|
+
{ path: SKILL_PATH_CHOICES.GITHUB, label: `${SKILL_PATH_CHOICES.GITHUB} (Copilot)` },
|
|
84
|
+
{ path: SKILL_PATH_CHOICES.CODEX_HOME, label: `${SKILL_PATH_CHOICES.CODEX_HOME} (Codex)` },
|
|
85
|
+
{ path: SKILL_PATH_CHOICES.CLAUDE, label: `${SKILL_PATH_CHOICES.CLAUDE} (Claude)` }
|
|
87
86
|
];
|
|
88
87
|
|
|
89
|
-
standardPaths.forEach(path => {
|
|
88
|
+
standardPaths.forEach(({ path, label }) => {
|
|
90
89
|
if (!existingPaths.includes(path)) {
|
|
91
|
-
choices.push({ name:
|
|
90
|
+
choices.push({ name: label, value: path });
|
|
92
91
|
}
|
|
93
92
|
});
|
|
94
93
|
|
|
@@ -163,11 +162,15 @@ export async function promptAgentInstallPath(existingInstalls = []) {
|
|
|
163
162
|
}
|
|
164
163
|
|
|
165
164
|
// Standard path options
|
|
166
|
-
const standardPaths = [
|
|
165
|
+
const standardPaths = [
|
|
166
|
+
{ path: AGENT_PATH_CHOICES.GITHUB, label: `${AGENT_PATH_CHOICES.GITHUB} (Copilot)` },
|
|
167
|
+
{ path: AGENT_PATH_CHOICES.CODEX, label: `${AGENT_PATH_CHOICES.CODEX} (Codex)` },
|
|
168
|
+
{ path: AGENT_PATH_CHOICES.CLAUDE, label: `${AGENT_PATH_CHOICES.CLAUDE} (Claude)` }
|
|
169
|
+
];
|
|
167
170
|
|
|
168
|
-
standardPaths.forEach(path => {
|
|
171
|
+
standardPaths.forEach(({ path, label }) => {
|
|
169
172
|
if (!existingPaths.includes(path)) {
|
|
170
|
-
choices.push({ name:
|
|
173
|
+
choices.push({ name: label, value: path });
|
|
171
174
|
}
|
|
172
175
|
});
|
|
173
176
|
|