port-nuker 1.0.0 → 1.0.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 +47 -2
- package/index.js +342 -10
- package/package.json +8 -4
- package/.agent/skills/.github/CODEOWNERS +0 -8
- package/.agent/skills/.github/ISSUE_TEMPLATE/bug_report.md +0 -33
- package/.agent/skills/.github/ISSUE_TEMPLATE/feature_request.md +0 -19
- package/.agent/skills/.github/MAINTENANCE.md +0 -230
- package/.agent/skills/.github/PULL_REQUEST_TEMPLATE.md +0 -23
- package/.agent/skills/.github/workflows/ci.yml +0 -38
- package/.agent/skills/CHANGELOG.md +0 -359
- package/.agent/skills/CONTRIBUTING.md +0 -236
- package/.agent/skills/FAQ.md +0 -178
- package/.agent/skills/GETTING_STARTED.md +0 -108
- package/.agent/skills/LICENSE +0 -21
- package/.agent/skills/README.md +0 -527
- package/.agent/skills/SECURITY.md +0 -19
- package/.agent/skills/docs/BUNDLES.md +0 -124
- package/.agent/skills/docs/CI_DRIFT_FIX.md +0 -38
- package/.agent/skills/docs/COMMUNITY_GUIDELINES.md +0 -33
- package/.agent/skills/docs/EXAMPLES.md +0 -56
- package/.agent/skills/docs/QUALITY_BAR.md +0 -64
- package/.agent/skills/docs/SECURITY_GUARDRAILS.md +0 -51
- package/.agent/skills/docs/SKILL_ANATOMY.md +0 -605
- package/.agent/skills/docs/SOURCES.md +0 -21
- package/.agent/skills/docs/VISUAL_GUIDE.md +0 -512
package/README.md
CHANGED
|
@@ -26,11 +26,20 @@ npx port-nuker 3000
|
|
|
26
26
|
## Usage
|
|
27
27
|
|
|
28
28
|
```bash
|
|
29
|
+
# Kill process on specific port
|
|
29
30
|
nuke <PORT>
|
|
31
|
+
|
|
32
|
+
# Kill and wait until port is actually free
|
|
33
|
+
nuke <PORT> --wait
|
|
34
|
+
|
|
35
|
+
# List all active ports and select one to kill interactively
|
|
36
|
+
nuke list
|
|
30
37
|
```
|
|
31
38
|
|
|
32
39
|
### Examples
|
|
33
40
|
|
|
41
|
+
**Direct Port Killing:**
|
|
42
|
+
|
|
34
43
|
```bash
|
|
35
44
|
# Kill process on port 3000
|
|
36
45
|
nuke 3000
|
|
@@ -42,12 +51,48 @@ nuke 8080
|
|
|
42
51
|
npx port-nuker 3000
|
|
43
52
|
```
|
|
44
53
|
|
|
54
|
+
**Interactive Port Selection:**
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# List all active ports with details
|
|
58
|
+
nuke list
|
|
59
|
+
|
|
60
|
+
# You'll see a table like this:
|
|
61
|
+
# ┌──────┬──────────┬──────────┬──────────────────────────────┬───────────────┬────────────┐
|
|
62
|
+
# │ Port │ PID │ Protocol │ Command │ User │ Memory │
|
|
63
|
+
# ├──────┼──────────┼──────────┼──────────────────────────────┼───────────────┼────────────┤
|
|
64
|
+
# │ 3000 │ 12345 │ TCP │ node.exe │ username │ 45,232 K │
|
|
65
|
+
# │ 8080 │ 67890 │ TCP │ java.exe │ username │ 128,456 K │
|
|
66
|
+
# └──────┴──────────┴──────────┴──────────────────────────────┴───────────────┴────────────┘
|
|
67
|
+
#
|
|
68
|
+
# Use arrow keys to select a process and press Enter to kill it
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
**Wait Mode (Command Chaining):**
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
# Kill and wait for port to be released (polls every 500ms)
|
|
75
|
+
nuke 3000 --wait
|
|
76
|
+
|
|
77
|
+
# Chain commands - start dev server only after port is free
|
|
78
|
+
nuke 3000 --wait && npm run dev
|
|
79
|
+
|
|
80
|
+
# Works with stubborn processes that take time to release sockets
|
|
81
|
+
nuke 8080 --wait && docker-compose up
|
|
82
|
+
|
|
83
|
+
# Timeout after 30 seconds if port isn't released
|
|
84
|
+
nuke 5000 --wait && echo "Port is free!"
|
|
85
|
+
```
|
|
86
|
+
|
|
45
87
|
## Features
|
|
46
88
|
|
|
47
89
|
- **Cross-Platform**: Works on Windows (using `netstat` + `taskkill`) and Unix-like systems (Linux/macOS using `lsof` + `kill`)
|
|
90
|
+
- **Interactive Mode**: Browse all active ports with `nuke list` and select which one to kill
|
|
91
|
+
- **Wait Mode**: Block until port is actually released with `--wait` flag for safe command chaining
|
|
92
|
+
- **Detailed Process Info**: See PID, command name, user, memory usage, and protocol for each port
|
|
48
93
|
- **Fast**: Instantly frees up your port
|
|
49
|
-
- **Safe**:
|
|
50
|
-
- **
|
|
94
|
+
- **Safe**: Confirmation prompt before killing processes in interactive mode
|
|
95
|
+
- **Exact Port Matching**: `nuke 80` won't kill processes on `8080`
|
|
51
96
|
- **Simple**: Just one command to remember
|
|
52
97
|
|
|
53
98
|
## Common Use Cases
|
package/index.js
CHANGED
|
@@ -1,21 +1,346 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
1
|
+
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const { exec } = require('child_process');
|
|
4
4
|
const os = require('os');
|
|
5
|
+
const inquirer = require('inquirer');
|
|
6
|
+
const Table = require('cli-table3');
|
|
5
7
|
|
|
6
|
-
const
|
|
8
|
+
const args = process.argv.slice(2);
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
// Parse arguments
|
|
11
|
+
let port = null;
|
|
12
|
+
let shouldWait = false;
|
|
13
|
+
let command = null;
|
|
14
|
+
|
|
15
|
+
for (let i = 0; i < args.length; i++) {
|
|
16
|
+
if (args[i] === '--wait') {
|
|
17
|
+
shouldWait = true;
|
|
18
|
+
} else if (args[i] === 'list') {
|
|
19
|
+
command = 'list';
|
|
20
|
+
} else if (!isNaN(args[i])) {
|
|
21
|
+
port = args[i];
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Handle different commands
|
|
26
|
+
if (command === 'list') {
|
|
27
|
+
listPorts();
|
|
28
|
+
} else if (port) {
|
|
29
|
+
// nuke <PORT> [--wait]
|
|
30
|
+
nukePort(port, shouldWait);
|
|
31
|
+
} else {
|
|
32
|
+
console.error('Usage:');
|
|
33
|
+
console.error(' nuke <PORT> Kill process on specific port');
|
|
34
|
+
console.error(' nuke <PORT> --wait Kill process and wait until port is free');
|
|
35
|
+
console.error(' nuke list List all active ports and select one to kill');
|
|
10
36
|
process.exit(1);
|
|
11
37
|
}
|
|
12
38
|
|
|
13
|
-
|
|
39
|
+
// List all active ports with process details
|
|
40
|
+
function listPorts() {
|
|
41
|
+
const platform = os.platform();
|
|
42
|
+
let listCommand;
|
|
43
|
+
|
|
44
|
+
if (platform === 'win32') {
|
|
45
|
+
// Get network connections and process details
|
|
46
|
+
listCommand = 'netstat -ano';
|
|
47
|
+
} else {
|
|
48
|
+
// Unix-like: get detailed process info
|
|
49
|
+
listCommand = 'lsof -i -P -n';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log('Scanning for active ports...\n');
|
|
53
|
+
|
|
54
|
+
exec(listCommand, (error, stdout, stderr) => {
|
|
55
|
+
if (error) {
|
|
56
|
+
console.error(`Error scanning ports: ${error.message}`);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const processes = parseProcessList(stdout, platform);
|
|
61
|
+
|
|
62
|
+
if (processes.length === 0) {
|
|
63
|
+
console.log('No active ports found.');
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
displayPortsTable(processes);
|
|
68
|
+
promptKillProcess(processes);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Parse process list based on platform
|
|
73
|
+
function parseProcessList(output, platform) {
|
|
74
|
+
const processMap = new Map();
|
|
75
|
+
|
|
76
|
+
if (platform === 'win32') {
|
|
77
|
+
const lines = output.trim().split('\n');
|
|
78
|
+
|
|
79
|
+
lines.forEach(line => {
|
|
80
|
+
const parts = line.trim().split(/\s+/);
|
|
81
|
+
// Proto Local-Address Foreign-Address State PID
|
|
82
|
+
// TCP 0.0.0.0:3000 0.0.0.0:0 LISTENING 1234
|
|
83
|
+
|
|
84
|
+
if (parts.length >= 5 && (parts[0] === 'TCP' || parts[0] === 'UDP')) {
|
|
85
|
+
const localAddress = parts[1];
|
|
86
|
+
const state = parts[3];
|
|
87
|
+
const pid = parts[4];
|
|
88
|
+
|
|
89
|
+
// Only show LISTENING ports
|
|
90
|
+
if (state === 'LISTENING') {
|
|
91
|
+
const lastColonIndex = localAddress.lastIndexOf(':');
|
|
92
|
+
const port = localAddress.substring(lastColonIndex + 1);
|
|
93
|
+
const protocol = parts[0];
|
|
94
|
+
|
|
95
|
+
const key = `${pid}-${port}`;
|
|
96
|
+
if (!processMap.has(key)) {
|
|
97
|
+
processMap.set(key, {
|
|
98
|
+
pid,
|
|
99
|
+
port,
|
|
100
|
+
protocol,
|
|
101
|
+
command: 'Loading...',
|
|
102
|
+
user: os.userInfo().username,
|
|
103
|
+
memory: 'N/A'
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// Get process details for each PID
|
|
111
|
+
const pids = [...new Set([...processMap.values()].map(p => p.pid))];
|
|
112
|
+
getWindowsProcessDetails(pids, processMap);
|
|
113
|
+
|
|
114
|
+
} else {
|
|
115
|
+
// Unix-like systems
|
|
116
|
+
const lines = output.trim().split('\n');
|
|
117
|
+
|
|
118
|
+
lines.forEach((line, index) => {
|
|
119
|
+
if (index === 0) return; // Skip header
|
|
120
|
+
|
|
121
|
+
const parts = line.trim().split(/\s+/);
|
|
122
|
+
// COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
|
|
123
|
+
|
|
124
|
+
if (parts.length >= 9) {
|
|
125
|
+
const command = parts[0];
|
|
126
|
+
const pid = parts[1];
|
|
127
|
+
const user = parts[2];
|
|
128
|
+
const name = parts[parts.length - 1];
|
|
129
|
+
|
|
130
|
+
// Parse port from NAME (e.g., *:3000, 127.0.0.1:8080)
|
|
131
|
+
const portMatch = name.match(/:(\d+)$/);
|
|
132
|
+
if (portMatch) {
|
|
133
|
+
const port = portMatch[1];
|
|
134
|
+
const protocol = parts[7] === 'TCP' ? 'TCP' : 'UDP';
|
|
135
|
+
|
|
136
|
+
const key = `${pid}-${port}`;
|
|
137
|
+
if (!processMap.has(key)) {
|
|
138
|
+
processMap.set(key, {
|
|
139
|
+
pid,
|
|
140
|
+
port,
|
|
141
|
+
protocol,
|
|
142
|
+
command,
|
|
143
|
+
user,
|
|
144
|
+
memory: 'N/A'
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
return Array.from(processMap.values()).sort((a, b) =>
|
|
153
|
+
parseInt(a.port) - parseInt(b.port)
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Get detailed process info on Windows
|
|
158
|
+
function getWindowsProcessDetails(pids, processMap) {
|
|
159
|
+
if (pids.length === 0) return;
|
|
160
|
+
|
|
161
|
+
const tasklistCmd = `tasklist /FI "PID eq ${pids.join('" /FI "PID eq ')}" /FO CSV /NH`;
|
|
162
|
+
|
|
163
|
+
exec(tasklistCmd, (error, stdout) => {
|
|
164
|
+
if (!error && stdout) {
|
|
165
|
+
const lines = stdout.trim().split('\n');
|
|
166
|
+
|
|
167
|
+
lines.forEach(line => {
|
|
168
|
+
// "Image Name","PID","Session Name","Session#","Mem Usage"
|
|
169
|
+
const matches = line.match(/"([^"]+)"/g);
|
|
170
|
+
if (matches && matches.length >= 5) {
|
|
171
|
+
const imageName = matches[0].replace(/"/g, '');
|
|
172
|
+
const pid = matches[1].replace(/"/g, '');
|
|
173
|
+
const memory = matches[4].replace(/"/g, '');
|
|
174
|
+
|
|
175
|
+
// Update all entries with this PID
|
|
176
|
+
processMap.forEach(process => {
|
|
177
|
+
if (process.pid === pid) {
|
|
178
|
+
process.command = imageName;
|
|
179
|
+
process.memory = memory;
|
|
180
|
+
}
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Display ports in a formatted table
|
|
189
|
+
function displayPortsTable(processes) {
|
|
190
|
+
const table = new Table({
|
|
191
|
+
head: ['Port', 'PID', 'Protocol', 'Command', 'User', 'Memory'],
|
|
192
|
+
colWidths: [8, 10, 10, 30, 15, 12],
|
|
193
|
+
style: {
|
|
194
|
+
head: ['cyan', 'bold'],
|
|
195
|
+
border: ['gray']
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
processes.forEach(p => {
|
|
200
|
+
table.push([
|
|
201
|
+
p.port,
|
|
202
|
+
p.pid,
|
|
203
|
+
p.protocol,
|
|
204
|
+
p.command.length > 28 ? p.command.substring(0, 25) + '...' : p.command,
|
|
205
|
+
p.user.length > 13 ? p.user.substring(0, 10) + '...' : p.user,
|
|
206
|
+
p.memory
|
|
207
|
+
]);
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
console.log(table.toString());
|
|
211
|
+
console.log('');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Prompt user to select and kill a process
|
|
215
|
+
async function promptKillProcess(processes) {
|
|
216
|
+
const choices = processes.map(p => ({
|
|
217
|
+
name: `Port ${p.port} - ${p.command} (PID: ${p.pid})`,
|
|
218
|
+
value: p.pid
|
|
219
|
+
}));
|
|
220
|
+
|
|
221
|
+
choices.push(new inquirer.Separator());
|
|
222
|
+
choices.push({ name: 'Cancel', value: null });
|
|
223
|
+
|
|
224
|
+
try {
|
|
225
|
+
const answer = await inquirer.prompt([
|
|
226
|
+
{
|
|
227
|
+
type: 'list',
|
|
228
|
+
name: 'pid',
|
|
229
|
+
message: 'Select a process to kill:',
|
|
230
|
+
choices,
|
|
231
|
+
pageSize: 15
|
|
232
|
+
}
|
|
233
|
+
]);
|
|
234
|
+
|
|
235
|
+
if (answer.pid) {
|
|
236
|
+
const selectedProcess = processes.find(p => p.pid === answer.pid);
|
|
237
|
+
|
|
238
|
+
const confirm = await inquirer.prompt([
|
|
239
|
+
{
|
|
240
|
+
type: 'confirm',
|
|
241
|
+
name: 'confirmed',
|
|
242
|
+
message: `Kill process ${selectedProcess.command} (PID: ${answer.pid}) on port ${selectedProcess.port}?`,
|
|
243
|
+
default: false
|
|
244
|
+
}
|
|
245
|
+
]);
|
|
14
246
|
|
|
15
|
-
|
|
247
|
+
if (confirm.confirmed) {
|
|
248
|
+
console.log(`\nNuking process ${answer.pid}...`);
|
|
249
|
+
killPid(answer.pid);
|
|
250
|
+
} else {
|
|
251
|
+
console.log('Cancelled.');
|
|
252
|
+
}
|
|
253
|
+
} else {
|
|
254
|
+
console.log('Cancelled.');
|
|
255
|
+
}
|
|
256
|
+
} catch (error) {
|
|
257
|
+
if (error.isTtyError) {
|
|
258
|
+
console.error('Interactive mode not supported in this environment.');
|
|
259
|
+
} else {
|
|
260
|
+
console.error('Selection cancelled.');
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// Check if a port is currently in use
|
|
266
|
+
function checkPortInUse(port, callback) {
|
|
267
|
+
const platform = os.platform();
|
|
268
|
+
let checkCommand;
|
|
269
|
+
|
|
270
|
+
if (platform === 'win32') {
|
|
271
|
+
checkCommand = `netstat -ano | findstr :${port}`;
|
|
272
|
+
} else {
|
|
273
|
+
checkCommand = `lsof -i :${port} -t`;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
exec(checkCommand, (error, stdout) => {
|
|
277
|
+
if (error || !stdout) {
|
|
278
|
+
// Port is free
|
|
279
|
+
callback(false);
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// Check if it's the exact port (for Windows)
|
|
284
|
+
if (platform === 'win32') {
|
|
285
|
+
const lines = stdout.trim().split('\n');
|
|
286
|
+
let found = false;
|
|
287
|
+
|
|
288
|
+
lines.forEach(line => {
|
|
289
|
+
const parts = line.trim().split(/\s+/);
|
|
290
|
+
if (parts.length > 1) {
|
|
291
|
+
const localAddress = parts[1];
|
|
292
|
+
const lastColonIndex = localAddress.lastIndexOf(':');
|
|
293
|
+
const portFound = localAddress.substring(lastColonIndex + 1);
|
|
294
|
+
|
|
295
|
+
if (portFound === port) {
|
|
296
|
+
found = true;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
callback(found);
|
|
302
|
+
} else {
|
|
303
|
+
// Unix: lsof -t returns PIDs if port is in use
|
|
304
|
+
callback(stdout.trim().length > 0);
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Poll port until it's free
|
|
310
|
+
function pollPortUntilFree(port, maxWaitSeconds = 30) {
|
|
311
|
+
console.log(`Waiting for port ${port} to be released...`);
|
|
312
|
+
|
|
313
|
+
const pollInterval = 500; // ms
|
|
314
|
+
const maxAttempts = (maxWaitSeconds * 1000) / pollInterval;
|
|
315
|
+
let attempts = 0;
|
|
316
|
+
|
|
317
|
+
const interval = setInterval(() => {
|
|
318
|
+
checkPortInUse(port, (inUse) => {
|
|
319
|
+
if (!inUse) {
|
|
320
|
+
clearInterval(interval);
|
|
321
|
+
console.log(`\nPort ${port} is now free!`);
|
|
322
|
+
process.exit(0);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
attempts++;
|
|
326
|
+
process.stdout.write('.');
|
|
327
|
+
|
|
328
|
+
if (attempts >= maxAttempts) {
|
|
329
|
+
clearInterval(interval);
|
|
330
|
+
console.error(`\nTimeout: Port ${port} is still in use after ${maxWaitSeconds} seconds`);
|
|
331
|
+
process.exit(1);
|
|
332
|
+
}
|
|
333
|
+
});
|
|
334
|
+
}, pollInterval);
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// Original nuke port function
|
|
338
|
+
function nukePort(port, shouldWait = false) {
|
|
16
339
|
const platform = os.platform();
|
|
17
340
|
let findCommand;
|
|
18
341
|
|
|
342
|
+
console.log(`Searching for process holding port ${port}...`);
|
|
343
|
+
|
|
19
344
|
if (platform === 'win32') {
|
|
20
345
|
findCommand = `netstat -ano | findstr :${port}`;
|
|
21
346
|
} else {
|
|
@@ -79,12 +404,19 @@ function nukePort(port) {
|
|
|
79
404
|
|
|
80
405
|
pids.forEach(pid => {
|
|
81
406
|
console.log(`Found process with PID: ${pid}. Nuking it...`);
|
|
82
|
-
killPid(pid)
|
|
407
|
+
killPid(pid, () => {
|
|
408
|
+
if (shouldWait) {
|
|
409
|
+
// Wait a moment for the process to fully terminate
|
|
410
|
+
setTimeout(() => {
|
|
411
|
+
pollPortUntilFree(port);
|
|
412
|
+
}, 1000);
|
|
413
|
+
}
|
|
414
|
+
});
|
|
83
415
|
});
|
|
84
416
|
});
|
|
85
417
|
}
|
|
86
418
|
|
|
87
|
-
function killPid(pid) {
|
|
419
|
+
function killPid(pid, callback) {
|
|
88
420
|
const platform = os.platform();
|
|
89
421
|
let killCommand;
|
|
90
422
|
|
|
@@ -97,10 +429,10 @@ function killPid(pid) {
|
|
|
97
429
|
exec(killCommand, (error, stdout, stderr) => {
|
|
98
430
|
if (error) {
|
|
99
431
|
console.error(`Failed to kill process ${pid}: ${error.message}`);
|
|
432
|
+
if (callback) callback(error);
|
|
100
433
|
return;
|
|
101
434
|
}
|
|
102
435
|
console.log(`Successfully nuked process ${pid}.`);
|
|
436
|
+
if (callback) callback(null);
|
|
103
437
|
});
|
|
104
438
|
}
|
|
105
|
-
|
|
106
|
-
nukePort(port);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "port-nuker",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "A simple CLI utility to kill processes holding a specific port. Solves EADDRINUSE errors instantly.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -27,13 +27,17 @@
|
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"repository": {
|
|
29
29
|
"type": "git",
|
|
30
|
-
"url": "https://github.com/
|
|
30
|
+
"url": "https://github.com/alexgutscher26/Port-Nuker.git"
|
|
31
31
|
},
|
|
32
32
|
"bugs": {
|
|
33
|
-
"url": "https://github.com/
|
|
33
|
+
"url": "https://github.com/alexgutscher26/port-nuker/issues"
|
|
34
34
|
},
|
|
35
|
-
"homepage": "https://github.com/
|
|
35
|
+
"homepage": "https://github.com/alexgutscher26/port-nuker#readme",
|
|
36
36
|
"engines": {
|
|
37
37
|
"node": ">=12.0.0"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"inquirer": "^8.2.6",
|
|
41
|
+
"cli-table3": "^0.6.3"
|
|
38
42
|
}
|
|
39
43
|
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Bug Report
|
|
3
|
-
about: Create a report to help us improve the skills
|
|
4
|
-
title: "[BUG] "
|
|
5
|
-
labels: bug
|
|
6
|
-
assignees: sickn33
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
**Describe the bug**
|
|
10
|
-
A clear and concise description of what the bug is.
|
|
11
|
-
|
|
12
|
-
**To Reproduce**
|
|
13
|
-
Steps to reproduce the behavior:
|
|
14
|
-
|
|
15
|
-
1. Go to '...'
|
|
16
|
-
2. Click on '...'
|
|
17
|
-
3. Scroll down to '...'
|
|
18
|
-
4. See error
|
|
19
|
-
|
|
20
|
-
**Expected behavior**
|
|
21
|
-
A clear and concise description of what you expected to happen.
|
|
22
|
-
|
|
23
|
-
**Screenshots**
|
|
24
|
-
If applicable, add screenshots to help explain your problem.
|
|
25
|
-
|
|
26
|
-
**Environment (please complete the following information):**
|
|
27
|
-
|
|
28
|
-
- OS: [e.g. macOS, Windows]
|
|
29
|
-
- Tool: [e.g. Claude Code, Antigravity]
|
|
30
|
-
- Version [if known]
|
|
31
|
-
|
|
32
|
-
**Additional context**
|
|
33
|
-
Add any other context about the problem here.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: Skill Request
|
|
3
|
-
about: Suggest a new skill for the collection
|
|
4
|
-
title: "[REQ] "
|
|
5
|
-
labels: enhancement
|
|
6
|
-
assignees: sickn33
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
**Is your feature request related to a problem? Please describe.**
|
|
10
|
-
A clear and concise description of what the problem is. Ex: I'm always frustrated when [...]
|
|
11
|
-
|
|
12
|
-
**Describe the solution you'd like**
|
|
13
|
-
A description of the skill you want. What trigger should it have? What files should it effect?
|
|
14
|
-
|
|
15
|
-
**Describe alternatives you've considered**
|
|
16
|
-
A clear and concise description of any alternative solutions or features you've considered.
|
|
17
|
-
|
|
18
|
-
**Additional context**
|
|
19
|
-
Add any other context or screenshots about the feature request here.
|