ai-slash-commands 2026.1.3 → 2026.1.4
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 +7 -0
- package/package.json +2 -1
- package/prompts/commit.md +0 -0
- package/scripts/cli.mjs +7 -6
- package/scripts/gen.mjs +0 -0
- package/scripts/install.mjs +0 -0
- package/scripts/link-windsurf.mjs +0 -0
- package/scripts/uninstall.mjs +99 -0
package/README.md
CHANGED
|
@@ -28,6 +28,11 @@ npm run install
|
|
|
28
28
|
```
|
|
29
29
|
|
|
30
30
|
## NPX
|
|
31
|
+
По умолчанию можно установить команды из встроенной папки `./prompts`:
|
|
32
|
+
```bash
|
|
33
|
+
npx ai-slash-commands
|
|
34
|
+
```
|
|
35
|
+
|
|
31
36
|
Можно установить команды из любой папки с `*.md` файлами:
|
|
32
37
|
```bash
|
|
33
38
|
npx ai-slash-commands ./path/to/commands
|
|
@@ -62,6 +67,8 @@ npm run link:windsurf
|
|
|
62
67
|
- `~/.windsurf/workflows` (хранилище, дальше линк)
|
|
63
68
|
- `${CODEX_HOME:-~/.codex}/prompts`
|
|
64
69
|
|
|
70
|
+
- `npm run uninstall` - удаляет из целевых папок файлы команд, перечисленные в `dist/**`
|
|
71
|
+
|
|
65
72
|
- `npm run link:windsurf` - делает `.windsurf/workflows` -> `~/.windsurf/workflows` (symlink/junction)
|
|
66
73
|
|
|
67
74
|
## Примечания по папкам (ссылки на доки)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-slash-commands",
|
|
3
|
-
"version": "2026.1.
|
|
3
|
+
"version": "2026.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"ai-slash-commands": "scripts/cli.mjs"
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"scripts": {
|
|
9
9
|
"gen": "node scripts/gen.mjs",
|
|
10
10
|
"install": "node scripts/install.mjs",
|
|
11
|
+
"uninstall": "node scripts/uninstall.mjs",
|
|
11
12
|
"link:windsurf": "node scripts/link-windsurf.mjs"
|
|
12
13
|
}
|
|
13
14
|
}
|
package/prompts/commit.md
CHANGED
|
File without changes
|
package/scripts/cli.mjs
CHANGED
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
4
5
|
import { generate } from "./gen.mjs";
|
|
5
6
|
import { install } from "./install.mjs";
|
|
6
7
|
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = path.dirname(__filename);
|
|
10
|
+
const repoRoot = path.resolve(__dirname, "..");
|
|
11
|
+
const defaultPromptsDir = path.join(repoRoot, "prompts");
|
|
12
|
+
|
|
7
13
|
function parseArgs() {
|
|
8
14
|
const args = process.argv.slice(2);
|
|
9
15
|
let targetsRaw = null;
|
|
@@ -27,17 +33,12 @@ function parseArgs() {
|
|
|
27
33
|
commandsDir = a;
|
|
28
34
|
}
|
|
29
35
|
|
|
30
|
-
if (!commandsDir) {
|
|
31
|
-
console.error("Usage: ai-slash-commands <commands-dir> [--targets claude,cursor,windsurf,codex]");
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
36
|
const targets = (targetsRaw ?? "claude,cursor,windsurf,codex")
|
|
36
37
|
.split(",")
|
|
37
38
|
.map(s => s.trim())
|
|
38
39
|
.filter(Boolean);
|
|
39
40
|
|
|
40
|
-
return { commandsDir: path.resolve(commandsDir), targets };
|
|
41
|
+
return { commandsDir: commandsDir ? path.resolve(commandsDir) : defaultPromptsDir, targets };
|
|
41
42
|
}
|
|
42
43
|
|
|
43
44
|
async function ensureCommandsDir(commandsDir) {
|
package/scripts/gen.mjs
CHANGED
|
File without changes
|
package/scripts/install.mjs
CHANGED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import fs from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = path.dirname(__filename);
|
|
8
|
+
|
|
9
|
+
const repoRoot = path.resolve(__dirname, "..");
|
|
10
|
+
const distDir = path.join(repoRoot, "dist");
|
|
11
|
+
|
|
12
|
+
const home = os.homedir();
|
|
13
|
+
|
|
14
|
+
// Uninstall locations (home-based)
|
|
15
|
+
const DEST = {
|
|
16
|
+
claude: path.join(home, ".claude", "commands"),
|
|
17
|
+
cursor: path.join(home, ".cursor", "commands"),
|
|
18
|
+
// Windsurf does not (currently) document a global workflows directory.
|
|
19
|
+
// We install to ~/.windsurf/workflows and provide a separate link script
|
|
20
|
+
// to link this folder into the current workspace as .windsurf/workflows.
|
|
21
|
+
windsurf: path.join(home, ".windsurf", "workflows"),
|
|
22
|
+
// Codex supports CODEX_HOME (defaults to ~/.codex). Prompts live under $CODEX_HOME/prompts.
|
|
23
|
+
codex: path.join(process.env.CODEX_HOME ?? path.join(home, ".codex"), "prompts"),
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const SRC = {
|
|
27
|
+
claude: path.join(distDir, "claude", "commands"),
|
|
28
|
+
cursor: path.join(distDir, "cursor", "commands"),
|
|
29
|
+
windsurf: path.join(distDir, "windsurf", "workflows"),
|
|
30
|
+
codex: path.join(distDir, "codex", "prompts"),
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
async function listMd(dir) {
|
|
34
|
+
try {
|
|
35
|
+
const entries = await fs.readdir(dir, { withFileTypes: true });
|
|
36
|
+
return entries
|
|
37
|
+
.filter(e => e.isFile() && e.name.toLowerCase().endsWith(".md"))
|
|
38
|
+
.map(e => e.name);
|
|
39
|
+
} catch (err) {
|
|
40
|
+
if (err.code === "ENOENT") {
|
|
41
|
+
return [];
|
|
42
|
+
}
|
|
43
|
+
throw err;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function removeAll(srcDir, dstDir) {
|
|
48
|
+
const files = await listMd(srcDir);
|
|
49
|
+
let removed = 0;
|
|
50
|
+
|
|
51
|
+
for (const f of files) {
|
|
52
|
+
const dstPath = path.join(dstDir, f);
|
|
53
|
+
try {
|
|
54
|
+
await fs.unlink(dstPath);
|
|
55
|
+
removed += 1;
|
|
56
|
+
} catch (err) {
|
|
57
|
+
if (err.code !== "ENOENT") {
|
|
58
|
+
throw err;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { removed, total: files.length };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function parseArgs() {
|
|
67
|
+
const idx = process.argv.indexOf("--targets");
|
|
68
|
+
const raw = idx >= 0 ? process.argv[idx + 1] : "claude,cursor,windsurf,codex";
|
|
69
|
+
const targets = raw.split(",").map(s => s.trim()).filter(Boolean);
|
|
70
|
+
return { targets };
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function uninstall({ targets }) {
|
|
74
|
+
for (const t of targets) {
|
|
75
|
+
if (!SRC[t] || !DEST[t]) {
|
|
76
|
+
console.error(`Unknown target: ${t}. Allowed: ${Object.keys(SRC).join(", ")}`);
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
for (const t of targets) {
|
|
82
|
+
const { removed, total } = await removeAll(SRC[t], DEST[t]);
|
|
83
|
+
const note = total === 0 ? " (no source prompts found)" : "";
|
|
84
|
+
console.log(`${t}: removed ${removed}/${total} prompt(s) from ${DEST[t]}${note}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async function main() {
|
|
89
|
+
const { targets } = parseArgs();
|
|
90
|
+
await uninstall({ targets });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const isMain = process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
94
|
+
if (isMain) {
|
|
95
|
+
main().catch((err) => {
|
|
96
|
+
console.error(err);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
});
|
|
99
|
+
}
|