@fermindi/pwn-cli 0.1.0 → 0.1.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/cli/inject.js +15 -1
- package/package.json +1 -1
- package/src/core/inject.js +81 -5
- package/src/index.js +1 -1
package/cli/inject.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { existsSync, readFileSync } from 'fs';
|
|
3
3
|
import { join } from 'path';
|
|
4
|
-
import { inject } from '../src/core/inject.js';
|
|
4
|
+
import { inject, detectKnownAIFiles } from '../src/core/inject.js';
|
|
5
5
|
|
|
6
6
|
export default async function injectCommand(args = []) {
|
|
7
7
|
const force = args.includes('--force') || args.includes('-f');
|
|
@@ -10,6 +10,20 @@ export default async function injectCommand(args = []) {
|
|
|
10
10
|
|
|
11
11
|
const result = await inject({ force });
|
|
12
12
|
|
|
13
|
+
// Show detected AI files (before success/failure message)
|
|
14
|
+
if (result.detected && result.detected.length > 0) {
|
|
15
|
+
console.log('⚠️ Detected existing AI instruction files:\n');
|
|
16
|
+
for (const file of result.detected) {
|
|
17
|
+
console.log(` 📄 ${file.file}`);
|
|
18
|
+
console.log(` Type: ${file.type} - ${file.description}`);
|
|
19
|
+
}
|
|
20
|
+
console.log('\n 💡 Consider migrating content to .ai/ structure:');
|
|
21
|
+
console.log(' - Instructions → .ai/agents/claude.md');
|
|
22
|
+
console.log(' - Decisions → .ai/memory/decisions.md');
|
|
23
|
+
console.log(' - Patterns → .ai/memory/patterns.md');
|
|
24
|
+
console.log(' - Tasks → .ai/tasks/active.md\n');
|
|
25
|
+
}
|
|
26
|
+
|
|
13
27
|
if (!result.success) {
|
|
14
28
|
if (result.error === 'ALREADY_EXISTS') {
|
|
15
29
|
console.log('❌ .ai/ directory already exists in this project');
|
package/package.json
CHANGED
package/src/core/inject.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, cpSync, renameSync, readFileSync, appendFileSync, writeFileSync } from 'fs';
|
|
1
|
+
import { existsSync, cpSync, renameSync, readFileSync, appendFileSync, writeFileSync, readdirSync } from 'fs';
|
|
2
2
|
import { join, dirname } from 'path';
|
|
3
3
|
import { fileURLToPath } from 'url';
|
|
4
4
|
import { randomUUID } from 'crypto';
|
|
@@ -6,6 +6,74 @@ import { initState } from './state.js';
|
|
|
6
6
|
|
|
7
7
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
8
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Known AI instruction files in the industry
|
|
11
|
+
* PWN should detect these and warn/offer migration
|
|
12
|
+
*/
|
|
13
|
+
export const KNOWN_AI_FILES = [
|
|
14
|
+
// Claude Code
|
|
15
|
+
{ pattern: 'CLAUDE.md', type: 'claude', description: 'Claude Code instructions' },
|
|
16
|
+
{ pattern: 'claude.md', type: 'claude', description: 'Claude Code instructions' },
|
|
17
|
+
{ pattern: '.claude', type: 'claude', description: 'Claude config directory' },
|
|
18
|
+
|
|
19
|
+
// Cursor
|
|
20
|
+
{ pattern: '.cursorrules', type: 'cursor', description: 'Cursor AI rules' },
|
|
21
|
+
{ pattern: '.cursorignore', type: 'cursor', description: 'Cursor ignore file' },
|
|
22
|
+
|
|
23
|
+
// GitHub Copilot
|
|
24
|
+
{ pattern: '.github/copilot-instructions.md', type: 'copilot', description: 'GitHub Copilot instructions' },
|
|
25
|
+
|
|
26
|
+
// Session files (common pattern)
|
|
27
|
+
{ pattern: 'session.*.md', type: 'session', description: 'Session file (legacy pattern)' },
|
|
28
|
+
|
|
29
|
+
// Other AI tools
|
|
30
|
+
{ pattern: '.aider', type: 'aider', description: 'Aider AI config' },
|
|
31
|
+
{ pattern: '.continue', type: 'continue', description: 'Continue AI config' },
|
|
32
|
+
{ pattern: '.codeium', type: 'codeium', description: 'Codeium config' },
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Detect known AI instruction files in a directory
|
|
37
|
+
* @param {string} cwd - Directory to scan
|
|
38
|
+
* @returns {Object[]} Array of detected files with metadata
|
|
39
|
+
*/
|
|
40
|
+
export function detectKnownAIFiles(cwd = process.cwd()) {
|
|
41
|
+
const detected = [];
|
|
42
|
+
|
|
43
|
+
for (const known of KNOWN_AI_FILES) {
|
|
44
|
+
// Handle glob patterns like session.*.md
|
|
45
|
+
if (known.pattern.includes('*')) {
|
|
46
|
+
const regex = new RegExp('^' + known.pattern.replace('.', '\\.').replace('*', '.*') + '$');
|
|
47
|
+
try {
|
|
48
|
+
const files = readdirSync(cwd);
|
|
49
|
+
for (const file of files) {
|
|
50
|
+
if (regex.test(file)) {
|
|
51
|
+
detected.push({
|
|
52
|
+
...known,
|
|
53
|
+
file,
|
|
54
|
+
path: join(cwd, file)
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
} catch {
|
|
59
|
+
// Ignore read errors
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
// Direct file check
|
|
63
|
+
const filePath = join(cwd, known.pattern);
|
|
64
|
+
if (existsSync(filePath)) {
|
|
65
|
+
detected.push({
|
|
66
|
+
...known,
|
|
67
|
+
file: known.pattern,
|
|
68
|
+
path: filePath
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return detected;
|
|
75
|
+
}
|
|
76
|
+
|
|
9
77
|
/**
|
|
10
78
|
* Get the path to the workspace template
|
|
11
79
|
* @returns {string} Path to template directory
|
|
@@ -20,13 +88,15 @@ export function getTemplatePath() {
|
|
|
20
88
|
* @param {string} options.cwd - Target directory (defaults to process.cwd())
|
|
21
89
|
* @param {boolean} options.force - Force overwrite existing .ai/ directory
|
|
22
90
|
* @param {boolean} options.silent - Suppress console output
|
|
91
|
+
* @param {boolean} options.skipDetection - Skip detection of known AI files
|
|
23
92
|
* @returns {object} Result with success status and message
|
|
24
93
|
*/
|
|
25
94
|
export async function inject(options = {}) {
|
|
26
95
|
const {
|
|
27
96
|
cwd = process.cwd(),
|
|
28
97
|
force = false,
|
|
29
|
-
silent = false
|
|
98
|
+
silent = false,
|
|
99
|
+
skipDetection = false
|
|
30
100
|
} = options;
|
|
31
101
|
|
|
32
102
|
const templateDir = getTemplatePath();
|
|
@@ -34,12 +104,16 @@ export async function inject(options = {}) {
|
|
|
34
104
|
|
|
35
105
|
const log = silent ? () => {} : console.log;
|
|
36
106
|
|
|
107
|
+
// Detect known AI instruction files
|
|
108
|
+
const detectedFiles = skipDetection ? [] : detectKnownAIFiles(cwd);
|
|
109
|
+
|
|
37
110
|
// Check if .ai/ already exists
|
|
38
111
|
if (existsSync(targetDir) && !force) {
|
|
39
112
|
return {
|
|
40
113
|
success: false,
|
|
41
114
|
error: 'ALREADY_EXISTS',
|
|
42
|
-
message: '.ai/ directory already exists. Use --force to overwrite.'
|
|
115
|
+
message: '.ai/ directory already exists. Use --force to overwrite.',
|
|
116
|
+
detected: detectedFiles
|
|
43
117
|
};
|
|
44
118
|
}
|
|
45
119
|
|
|
@@ -74,14 +148,16 @@ export async function inject(options = {}) {
|
|
|
74
148
|
return {
|
|
75
149
|
success: true,
|
|
76
150
|
message: 'PWN workspace injected successfully',
|
|
77
|
-
path: targetDir
|
|
151
|
+
path: targetDir,
|
|
152
|
+
detected: detectedFiles
|
|
78
153
|
};
|
|
79
154
|
|
|
80
155
|
} catch (error) {
|
|
81
156
|
return {
|
|
82
157
|
success: false,
|
|
83
158
|
error: 'INJECTION_FAILED',
|
|
84
|
-
message: error.message
|
|
159
|
+
message: error.message,
|
|
160
|
+
detected: detectedFiles
|
|
85
161
|
};
|
|
86
162
|
}
|
|
87
163
|
}
|
package/src/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// PWN Core - Main exports
|
|
2
|
-
export { inject } from './core/inject.js';
|
|
2
|
+
export { inject, detectKnownAIFiles, KNOWN_AI_FILES } from './core/inject.js';
|
|
3
3
|
export { getState, updateState, initState } from './core/state.js';
|
|
4
4
|
export { validate } from './core/validate.js';
|
|
5
5
|
export { getWorkspaceInfo } from './core/workspace.js';
|