ai-slash-commands 2026.1.3 → 2026.1.5
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/.vscode/launch.json +42 -0
- package/README.md +16 -0
- package/package.json +2 -1
- package/prompts/README.md +36 -0
- package/prompts/audit-packages.md +11 -0
- package/prompts/commit.md +17 -5
- package/prompts/feat.md +68 -0
- package/prompts/learn.md +3 -0
- package/prompts/refactoring.md +3 -0
- package/scripts/cli.mjs +7 -6
- package/scripts/gen.mjs +41 -0
- package/scripts/install.mjs +7 -13
- package/scripts/uninstall.mjs +99 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"name": "npm: gen",
|
|
6
|
+
"type": "node",
|
|
7
|
+
"request": "launch",
|
|
8
|
+
"runtimeExecutable": "npm",
|
|
9
|
+
"runtimeArgs": ["run", "gen"],
|
|
10
|
+
"console": "integratedTerminal",
|
|
11
|
+
"internalConsoleOptions": "neverOpen"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"name": "npm: install",
|
|
15
|
+
"type": "node",
|
|
16
|
+
"request": "launch",
|
|
17
|
+
"runtimeExecutable": "npm",
|
|
18
|
+
"runtimeArgs": ["run", "install"],
|
|
19
|
+
"console": "integratedTerminal",
|
|
20
|
+
"internalConsoleOptions": "neverOpen"
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "npm: uninstall",
|
|
24
|
+
"type": "node",
|
|
25
|
+
"request": "launch",
|
|
26
|
+
"runtimeExecutable": "npm",
|
|
27
|
+
"runtimeArgs": ["run", "uninstall"],
|
|
28
|
+
"console": "integratedTerminal",
|
|
29
|
+
"internalConsoleOptions": "neverOpen"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
"name": "npm: link:windsurf",
|
|
33
|
+
"type": "node",
|
|
34
|
+
"request": "launch",
|
|
35
|
+
"runtimeExecutable": "npm",
|
|
36
|
+
"runtimeArgs": ["run", "link:windsurf"],
|
|
37
|
+
"console": "integratedTerminal",
|
|
38
|
+
"internalConsoleOptions": "neverOpen"
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}
|
|
42
|
+
|
package/README.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# ai-slash-commands
|
|
2
2
|
|
|
3
|
+
A tool for managing AI slash commands and prompts across multiple AI-powered editors. Write prompts once in markdown, and install them to Claude Code, Cursor, Windsurf, and Codex.
|
|
4
|
+
|
|
5
|
+
**Quick start:**
|
|
6
|
+
```bash
|
|
7
|
+
npx ai-slash-commands
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
[Prompts list](prompts/)
|
|
11
|
+
|
|
3
12
|
Один набор markdown-промптов в `./prompts/*.md`, генерация в `./dist/**` и установка в домашние папки для:
|
|
4
13
|
- Claude Code
|
|
5
14
|
- Cursor
|
|
@@ -28,6 +37,11 @@ npm run install
|
|
|
28
37
|
```
|
|
29
38
|
|
|
30
39
|
## NPX
|
|
40
|
+
По умолчанию можно установить команды из встроенной папки `./prompts`:
|
|
41
|
+
```bash
|
|
42
|
+
npx ai-slash-commands
|
|
43
|
+
```
|
|
44
|
+
|
|
31
45
|
Можно установить команды из любой папки с `*.md` файлами:
|
|
32
46
|
```bash
|
|
33
47
|
npx ai-slash-commands ./path/to/commands
|
|
@@ -62,6 +76,8 @@ npm run link:windsurf
|
|
|
62
76
|
- `~/.windsurf/workflows` (хранилище, дальше линк)
|
|
63
77
|
- `${CODEX_HOME:-~/.codex}/prompts`
|
|
64
78
|
|
|
79
|
+
- `npm run uninstall` - удаляет из целевых папок файлы команд, перечисленные в `dist/**`
|
|
80
|
+
|
|
65
81
|
- `npm run link:windsurf` - делает `.windsurf/workflows` -> `~/.windsurf/workflows` (symlink/junction)
|
|
66
82
|
|
|
67
83
|
## Примечания по папкам (ссылки на доки)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-slash-commands",
|
|
3
|
-
"version": "2026.1.
|
|
3
|
+
"version": "2026.1.5",
|
|
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
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Commands
|
|
2
|
+
|
|
3
|
+
This directory contains AI slash command prompts.
|
|
4
|
+
|
|
5
|
+
## Available Commands
|
|
6
|
+
|
|
7
|
+
### `/audit-packages`
|
|
8
|
+
|
|
9
|
+
# audit-packages - update packages
|
|
10
|
+
|
|
11
|
+
*Source: [audit-packages.md](audit-packages.md)*
|
|
12
|
+
|
|
13
|
+
### `/commit`
|
|
14
|
+
|
|
15
|
+
# commit - make a commit
|
|
16
|
+
|
|
17
|
+
*Source: [commit.md](commit.md)*
|
|
18
|
+
|
|
19
|
+
### `/feat`
|
|
20
|
+
|
|
21
|
+
# feat - add a new feature
|
|
22
|
+
|
|
23
|
+
*Source: [feat.md](feat.md)*
|
|
24
|
+
|
|
25
|
+
### `/learn`
|
|
26
|
+
|
|
27
|
+
# learn - add agents knowledge
|
|
28
|
+
|
|
29
|
+
*Source: [learn.md](learn.md)*
|
|
30
|
+
|
|
31
|
+
### `/refactoring`
|
|
32
|
+
|
|
33
|
+
Review the codebase, find files with many lines or a lot of duplicate code, suggest 2-3 refactoring tasks to improve the code.
|
|
34
|
+
|
|
35
|
+
*Source: [refactoring.md](refactoring.md)*
|
|
36
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# audit-packages - update packages
|
|
2
|
+
|
|
3
|
+
Check package versions for known vulnerabilities. Update vulnerable packages.
|
|
4
|
+
|
|
5
|
+
Verify the application works.
|
|
6
|
+
|
|
7
|
+
If it's quick, update all packages to the latest versions. If updating all packages isn't feasible, update only vulnerable ones.
|
|
8
|
+
|
|
9
|
+
When changing major versions, check for breaking changes and review code that uses them.
|
|
10
|
+
|
|
11
|
+
for package.json: run `npm audit fix --force`, verify the application works. First update dependencies, then devDependencies. If all packages couldn't be updated, update only vulnerable ones. When changing major versions, check for breaking changes and review code that uses them.
|
package/prompts/commit.md
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
# commit - make a commit
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
-
|
|
3
|
+
Act as a senior software engineer to commit changes to the repository in this format:
|
|
4
|
+
"$type${[(scope)]}{[!]}: $description"
|
|
5
|
+
# Notes:
|
|
6
|
+
# - Square brackets [] indicate optional parts.
|
|
7
|
+
# - "!" marks a breaking change.
|
|
8
|
+
|
|
9
|
+
Types: fix | feat | chore | docs | refactor | test | perf | build | ci | style | revert | other
|
|
10
|
+
|
|
11
|
+
Constraints {
|
|
12
|
+
When committing, don't log about logging in the commit message.
|
|
13
|
+
Use multiple -m flags, one for each log entry.
|
|
14
|
+
Limit the first commit message line to 50 characters.
|
|
15
|
+
Use conventional commits with a scope, title, and body.
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
If there are tests in project, run them before committing.
|
package/prompts/feat.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# feat - add a new feature
|
|
2
|
+
|
|
3
|
+
Act as a senior software engineer to add a new feature to the repository.
|
|
4
|
+
|
|
5
|
+
### 0) Inputs and constraints
|
|
6
|
+
|
|
7
|
+
* Feature request (user description)
|
|
8
|
+
* Repo context (structure, stack, conventions, CI)
|
|
9
|
+
* Constraints (deadline, “no refactors”, compatibility, platforms, versions)
|
|
10
|
+
|
|
11
|
+
If critical info is missing, ask only the minimum set of questions required to proceed. Otherwise, make reasonable assumptions and clearly list them.
|
|
12
|
+
|
|
13
|
+
### 1) Define the feature
|
|
14
|
+
|
|
15
|
+
Produce:
|
|
16
|
+
|
|
17
|
+
* A 1-2 sentence goal statement
|
|
18
|
+
* Primary user flows (happy path + 2-3 important edge cases)
|
|
19
|
+
* Definition of Done (clear acceptance criteria)
|
|
20
|
+
* Constraints and compatibility notes (APIs, data, platforms, versions)
|
|
21
|
+
|
|
22
|
+
### 2) Codebase reconnaissance
|
|
23
|
+
|
|
24
|
+
Before editing:
|
|
25
|
+
|
|
26
|
+
* Identify where this feature should live (files/modules)
|
|
27
|
+
* List integration points (API/UI/CLI/config/DB)
|
|
28
|
+
* Call out risks (breaking changes, migrations, flags, performance, security)
|
|
29
|
+
|
|
30
|
+
### 3) Implementation plan
|
|
31
|
+
|
|
32
|
+
Create a small-step plan:
|
|
33
|
+
|
|
34
|
+
* What changes by file/module
|
|
35
|
+
* New entities/interfaces/types/endpoints/tables (if any)
|
|
36
|
+
* Minimal incremental approach: skeleton first, then expand
|
|
37
|
+
* Rollback strategy and/or feature flag if risk is non-trivial
|
|
38
|
+
|
|
39
|
+
### 4) Implement
|
|
40
|
+
|
|
41
|
+
Make changes carefully:
|
|
42
|
+
|
|
43
|
+
* Follow existing architecture and style
|
|
44
|
+
* Avoid duplication; extract shared logic
|
|
45
|
+
* Use clear names; add comments only when they add real value
|
|
46
|
+
* Preserve backward compatibility unless explicitly instructed otherwise
|
|
47
|
+
* Keep diffs focused; avoid unrelated refactors
|
|
48
|
+
|
|
49
|
+
### 5) Tests
|
|
50
|
+
|
|
51
|
+
* Add/update tests (unit/integration) for key flows, if tests are present in the project.
|
|
52
|
+
* Include regression coverage for the behavior this feature is meant to address (when applicable)
|
|
53
|
+
* If tests are difficult, explain why and provide an alternative verification plan (smoke/e2e/manual checklist)
|
|
54
|
+
|
|
55
|
+
### 6) Documentation and developer experience
|
|
56
|
+
|
|
57
|
+
* Update README/docs/examples as needed
|
|
58
|
+
* Document new config/env variables and defaults
|
|
59
|
+
* Add “How to verify locally”: commands and a couple of usage examples
|
|
60
|
+
|
|
61
|
+
### 7) Final summary
|
|
62
|
+
|
|
63
|
+
End with:
|
|
64
|
+
|
|
65
|
+
* What changed (brief)
|
|
66
|
+
* Files touched (grouped by purpose)
|
|
67
|
+
* Commands to verify (lint/test/build/run)
|
|
68
|
+
* Known limitations / follow-ups (if any)
|
package/prompts/learn.md
ADDED
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
|
@@ -38,6 +38,41 @@ async function listPromptFiles(promptsDir) {
|
|
|
38
38
|
.map(e => e.name);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
async function generateCommandsReadme(promptsDir) {
|
|
42
|
+
const promptFiles = await listPromptFiles(promptsDir);
|
|
43
|
+
const commands = [];
|
|
44
|
+
|
|
45
|
+
for (const name of promptFiles) {
|
|
46
|
+
if (name.toLowerCase() === "readme.md") {
|
|
47
|
+
continue; // Skip README.md itself
|
|
48
|
+
}
|
|
49
|
+
const srcPath = path.join(promptsDir, name);
|
|
50
|
+
const content = await fs.readFile(srcPath, "utf8");
|
|
51
|
+
const commandName = name.replace(/\.md$/i, "");
|
|
52
|
+
const firstLine = content.split("\n")[0].trim();
|
|
53
|
+
const description = firstLine || "No description";
|
|
54
|
+
commands.push({ name: commandName, description, filename: name });
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Sort commands alphabetically by name
|
|
58
|
+
commands.sort((a, b) => a.name.localeCompare(b.name));
|
|
59
|
+
|
|
60
|
+
// Generate README content
|
|
61
|
+
let readmeContent = "# Commands\n\n";
|
|
62
|
+
readmeContent += "This directory contains AI slash command prompts.\n\n";
|
|
63
|
+
readmeContent += "## Available Commands\n\n";
|
|
64
|
+
|
|
65
|
+
for (const cmd of commands) {
|
|
66
|
+
readmeContent += `### \`/${cmd.name}\`\n\n`;
|
|
67
|
+
readmeContent += `${cmd.description}\n\n`;
|
|
68
|
+
readmeContent += `*Source: [${cmd.filename}](${cmd.filename})*\n\n`;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const readmePath = path.join(promptsDir, "README.md");
|
|
72
|
+
await fs.writeFile(readmePath, readmeContent, "utf8");
|
|
73
|
+
console.log(`Generated: ${path.relative(repoRoot, readmePath)}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
41
76
|
export async function generate({ targets, promptsDir }) {
|
|
42
77
|
const promptFiles = await listPromptFiles(promptsDir);
|
|
43
78
|
if (promptFiles.length === 0) {
|
|
@@ -54,6 +89,9 @@ export async function generate({ targets, promptsDir }) {
|
|
|
54
89
|
}
|
|
55
90
|
|
|
56
91
|
for (const name of promptFiles) {
|
|
92
|
+
if (name.toLowerCase() === "readme.md") {
|
|
93
|
+
continue; // Skip README.md
|
|
94
|
+
}
|
|
57
95
|
const srcPath = path.join(promptsDir, name);
|
|
58
96
|
const content = await fs.readFile(srcPath, "utf8");
|
|
59
97
|
|
|
@@ -63,6 +101,9 @@ export async function generate({ targets, promptsDir }) {
|
|
|
63
101
|
}
|
|
64
102
|
}
|
|
65
103
|
|
|
104
|
+
// Generate commands README in prompts directory
|
|
105
|
+
await generateCommandsReadme(promptsDir);
|
|
106
|
+
|
|
66
107
|
console.log("Generated:");
|
|
67
108
|
for (const t of targets) {
|
|
68
109
|
console.log(`- dist/${TARGETS[t].out}/`);
|
package/scripts/install.mjs
CHANGED
|
@@ -65,7 +65,9 @@ function parseArgs() {
|
|
|
65
65
|
return { targets };
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
68
|
+
async function main() {
|
|
69
|
+
const { targets } = parseArgs();
|
|
70
|
+
|
|
69
71
|
for (const t of targets) {
|
|
70
72
|
if (!SRC[t] || !DEST[t]) {
|
|
71
73
|
console.error(`Unknown target: ${t}. Allowed: ${Object.keys(SRC).join(", ")}`);
|
|
@@ -79,15 +81,7 @@ export async function install({ targets }) {
|
|
|
79
81
|
}
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const isMain = process.argv[1] && fileURLToPath(import.meta.url) === path.resolve(process.argv[1]);
|
|
88
|
-
if (isMain) {
|
|
89
|
-
main().catch((err) => {
|
|
90
|
-
console.error(err);
|
|
91
|
-
process.exit(1);
|
|
92
|
-
});
|
|
93
|
-
}
|
|
84
|
+
main().catch((err) => {
|
|
85
|
+
console.error(err);
|
|
86
|
+
process.exit(1);
|
|
87
|
+
});
|
|
@@ -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
|
+
}
|