@fyow/copilot-everything 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/package.json +2 -1
- package/scripts/hooks/evaluate-session.js +78 -0
- package/scripts/hooks/post-tool-use.ps1 +55 -0
- package/scripts/hooks/post-tool-use.sh +68 -0
- package/scripts/hooks/pre-compact.js +48 -0
- package/scripts/hooks/session-end.js +82 -0
- package/scripts/hooks/session-start.js +61 -0
- package/scripts/hooks/suggest-compact.js +60 -0
- package/scripts/lib/package-manager.js +390 -0
- package/scripts/lib/utils.js +368 -0
- package/scripts/migrate-to-copilot.js +247 -0
- package/scripts/setup-package-manager.js +206 -0
|
@@ -0,0 +1,390 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Package Manager Detection and Selection
|
|
3
|
+
* Automatically detects the preferred package manager or lets user choose
|
|
4
|
+
*
|
|
5
|
+
* Supports: npm, pnpm, yarn, bun
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { commandExists, getClaudeDir, readFile, writeFile, log, runCommand } = require('./utils');
|
|
11
|
+
|
|
12
|
+
// Package manager definitions
|
|
13
|
+
const PACKAGE_MANAGERS = {
|
|
14
|
+
npm: {
|
|
15
|
+
name: 'npm',
|
|
16
|
+
lockFile: 'package-lock.json',
|
|
17
|
+
installCmd: 'npm install',
|
|
18
|
+
runCmd: 'npm run',
|
|
19
|
+
execCmd: 'npx',
|
|
20
|
+
testCmd: 'npm test',
|
|
21
|
+
buildCmd: 'npm run build',
|
|
22
|
+
devCmd: 'npm run dev'
|
|
23
|
+
},
|
|
24
|
+
pnpm: {
|
|
25
|
+
name: 'pnpm',
|
|
26
|
+
lockFile: 'pnpm-lock.yaml',
|
|
27
|
+
installCmd: 'pnpm install',
|
|
28
|
+
runCmd: 'pnpm',
|
|
29
|
+
execCmd: 'pnpm dlx',
|
|
30
|
+
testCmd: 'pnpm test',
|
|
31
|
+
buildCmd: 'pnpm build',
|
|
32
|
+
devCmd: 'pnpm dev'
|
|
33
|
+
},
|
|
34
|
+
yarn: {
|
|
35
|
+
name: 'yarn',
|
|
36
|
+
lockFile: 'yarn.lock',
|
|
37
|
+
installCmd: 'yarn',
|
|
38
|
+
runCmd: 'yarn',
|
|
39
|
+
execCmd: 'yarn dlx',
|
|
40
|
+
testCmd: 'yarn test',
|
|
41
|
+
buildCmd: 'yarn build',
|
|
42
|
+
devCmd: 'yarn dev'
|
|
43
|
+
},
|
|
44
|
+
bun: {
|
|
45
|
+
name: 'bun',
|
|
46
|
+
lockFile: 'bun.lockb',
|
|
47
|
+
installCmd: 'bun install',
|
|
48
|
+
runCmd: 'bun run',
|
|
49
|
+
execCmd: 'bunx',
|
|
50
|
+
testCmd: 'bun test',
|
|
51
|
+
buildCmd: 'bun run build',
|
|
52
|
+
devCmd: 'bun run dev'
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// Priority order for detection
|
|
57
|
+
const DETECTION_PRIORITY = ['pnpm', 'bun', 'yarn', 'npm'];
|
|
58
|
+
|
|
59
|
+
// Config file path
|
|
60
|
+
function getConfigPath() {
|
|
61
|
+
return path.join(getClaudeDir(), 'package-manager.json');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Load saved package manager configuration
|
|
66
|
+
*/
|
|
67
|
+
function loadConfig() {
|
|
68
|
+
const configPath = getConfigPath();
|
|
69
|
+
const content = readFile(configPath);
|
|
70
|
+
|
|
71
|
+
if (content) {
|
|
72
|
+
try {
|
|
73
|
+
return JSON.parse(content);
|
|
74
|
+
} catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Save package manager configuration
|
|
83
|
+
*/
|
|
84
|
+
function saveConfig(config) {
|
|
85
|
+
const configPath = getConfigPath();
|
|
86
|
+
writeFile(configPath, JSON.stringify(config, null, 2));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Detect package manager from lock file in project directory
|
|
91
|
+
*/
|
|
92
|
+
function detectFromLockFile(projectDir = process.cwd()) {
|
|
93
|
+
for (const pmName of DETECTION_PRIORITY) {
|
|
94
|
+
const pm = PACKAGE_MANAGERS[pmName];
|
|
95
|
+
const lockFilePath = path.join(projectDir, pm.lockFile);
|
|
96
|
+
|
|
97
|
+
if (fs.existsSync(lockFilePath)) {
|
|
98
|
+
return pmName;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Detect package manager from package.json packageManager field
|
|
106
|
+
*/
|
|
107
|
+
function detectFromPackageJson(projectDir = process.cwd()) {
|
|
108
|
+
const packageJsonPath = path.join(projectDir, 'package.json');
|
|
109
|
+
const content = readFile(packageJsonPath);
|
|
110
|
+
|
|
111
|
+
if (content) {
|
|
112
|
+
try {
|
|
113
|
+
const pkg = JSON.parse(content);
|
|
114
|
+
if (pkg.packageManager) {
|
|
115
|
+
// Format: "pnpm@8.6.0" or just "pnpm"
|
|
116
|
+
const pmName = pkg.packageManager.split('@')[0];
|
|
117
|
+
if (PACKAGE_MANAGERS[pmName]) {
|
|
118
|
+
return pmName;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
} catch {
|
|
122
|
+
// Invalid package.json
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Get available package managers (installed on system)
|
|
130
|
+
*/
|
|
131
|
+
function getAvailablePackageManagers() {
|
|
132
|
+
const available = [];
|
|
133
|
+
|
|
134
|
+
for (const pmName of Object.keys(PACKAGE_MANAGERS)) {
|
|
135
|
+
if (commandExists(pmName)) {
|
|
136
|
+
available.push(pmName);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return available;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Get the package manager to use for current project
|
|
145
|
+
*
|
|
146
|
+
* Detection priority:
|
|
147
|
+
* 1. Environment variable CLAUDE_PACKAGE_MANAGER
|
|
148
|
+
* 2. Project-specific config (in .claude/package-manager.json)
|
|
149
|
+
* 3. package.json packageManager field
|
|
150
|
+
* 4. Lock file detection
|
|
151
|
+
* 5. Global user preference (in ~/.claude/package-manager.json)
|
|
152
|
+
* 6. First available package manager (by priority)
|
|
153
|
+
*
|
|
154
|
+
* @param {object} options - { projectDir, fallbackOrder }
|
|
155
|
+
* @returns {object} - { name, config, source }
|
|
156
|
+
*/
|
|
157
|
+
function getPackageManager(options = {}) {
|
|
158
|
+
const { projectDir = process.cwd(), fallbackOrder = DETECTION_PRIORITY } = options;
|
|
159
|
+
|
|
160
|
+
// 1. Check environment variable
|
|
161
|
+
const envPm = process.env.CLAUDE_PACKAGE_MANAGER;
|
|
162
|
+
if (envPm && PACKAGE_MANAGERS[envPm]) {
|
|
163
|
+
return {
|
|
164
|
+
name: envPm,
|
|
165
|
+
config: PACKAGE_MANAGERS[envPm],
|
|
166
|
+
source: 'environment'
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// 2. Check project-specific config
|
|
171
|
+
const projectConfigPath = path.join(projectDir, '.claude', 'package-manager.json');
|
|
172
|
+
const projectConfig = readFile(projectConfigPath);
|
|
173
|
+
if (projectConfig) {
|
|
174
|
+
try {
|
|
175
|
+
const config = JSON.parse(projectConfig);
|
|
176
|
+
if (config.packageManager && PACKAGE_MANAGERS[config.packageManager]) {
|
|
177
|
+
return {
|
|
178
|
+
name: config.packageManager,
|
|
179
|
+
config: PACKAGE_MANAGERS[config.packageManager],
|
|
180
|
+
source: 'project-config'
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
} catch {
|
|
184
|
+
// Invalid config
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// 3. Check package.json packageManager field
|
|
189
|
+
const fromPackageJson = detectFromPackageJson(projectDir);
|
|
190
|
+
if (fromPackageJson) {
|
|
191
|
+
return {
|
|
192
|
+
name: fromPackageJson,
|
|
193
|
+
config: PACKAGE_MANAGERS[fromPackageJson],
|
|
194
|
+
source: 'package.json'
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// 4. Check lock file
|
|
199
|
+
const fromLockFile = detectFromLockFile(projectDir);
|
|
200
|
+
if (fromLockFile) {
|
|
201
|
+
return {
|
|
202
|
+
name: fromLockFile,
|
|
203
|
+
config: PACKAGE_MANAGERS[fromLockFile],
|
|
204
|
+
source: 'lock-file'
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// 5. Check global user preference
|
|
209
|
+
const globalConfig = loadConfig();
|
|
210
|
+
if (globalConfig && globalConfig.packageManager && PACKAGE_MANAGERS[globalConfig.packageManager]) {
|
|
211
|
+
return {
|
|
212
|
+
name: globalConfig.packageManager,
|
|
213
|
+
config: PACKAGE_MANAGERS[globalConfig.packageManager],
|
|
214
|
+
source: 'global-config'
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// 6. Use first available package manager
|
|
219
|
+
const available = getAvailablePackageManagers();
|
|
220
|
+
for (const pmName of fallbackOrder) {
|
|
221
|
+
if (available.includes(pmName)) {
|
|
222
|
+
return {
|
|
223
|
+
name: pmName,
|
|
224
|
+
config: PACKAGE_MANAGERS[pmName],
|
|
225
|
+
source: 'fallback'
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Default to npm (always available with Node.js)
|
|
231
|
+
return {
|
|
232
|
+
name: 'npm',
|
|
233
|
+
config: PACKAGE_MANAGERS.npm,
|
|
234
|
+
source: 'default'
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Set user's preferred package manager (global)
|
|
240
|
+
*/
|
|
241
|
+
function setPreferredPackageManager(pmName) {
|
|
242
|
+
if (!PACKAGE_MANAGERS[pmName]) {
|
|
243
|
+
throw new Error(`Unknown package manager: ${pmName}`);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
const config = loadConfig() || {};
|
|
247
|
+
config.packageManager = pmName;
|
|
248
|
+
config.setAt = new Date().toISOString();
|
|
249
|
+
saveConfig(config);
|
|
250
|
+
|
|
251
|
+
return config;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Set project's preferred package manager
|
|
256
|
+
*/
|
|
257
|
+
function setProjectPackageManager(pmName, projectDir = process.cwd()) {
|
|
258
|
+
if (!PACKAGE_MANAGERS[pmName]) {
|
|
259
|
+
throw new Error(`Unknown package manager: ${pmName}`);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const configDir = path.join(projectDir, '.claude');
|
|
263
|
+
const configPath = path.join(configDir, 'package-manager.json');
|
|
264
|
+
|
|
265
|
+
const config = {
|
|
266
|
+
packageManager: pmName,
|
|
267
|
+
setAt: new Date().toISOString()
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
writeFile(configPath, JSON.stringify(config, null, 2));
|
|
271
|
+
return config;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Get the command to run a script
|
|
276
|
+
* @param {string} script - Script name (e.g., "dev", "build", "test")
|
|
277
|
+
* @param {object} options - { projectDir }
|
|
278
|
+
*/
|
|
279
|
+
function getRunCommand(script, options = {}) {
|
|
280
|
+
const pm = getPackageManager(options);
|
|
281
|
+
|
|
282
|
+
switch (script) {
|
|
283
|
+
case 'install':
|
|
284
|
+
return pm.config.installCmd;
|
|
285
|
+
case 'test':
|
|
286
|
+
return pm.config.testCmd;
|
|
287
|
+
case 'build':
|
|
288
|
+
return pm.config.buildCmd;
|
|
289
|
+
case 'dev':
|
|
290
|
+
return pm.config.devCmd;
|
|
291
|
+
default:
|
|
292
|
+
return `${pm.config.runCmd} ${script}`;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Get the command to execute a package binary
|
|
298
|
+
* @param {string} binary - Binary name (e.g., "prettier", "eslint")
|
|
299
|
+
* @param {string} args - Arguments to pass
|
|
300
|
+
*/
|
|
301
|
+
function getExecCommand(binary, args = '', options = {}) {
|
|
302
|
+
const pm = getPackageManager(options);
|
|
303
|
+
return `${pm.config.execCmd} ${binary}${args ? ' ' + args : ''}`;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Interactive prompt for package manager selection
|
|
308
|
+
* Returns a message for Claude to show to user
|
|
309
|
+
*/
|
|
310
|
+
function getSelectionPrompt() {
|
|
311
|
+
const available = getAvailablePackageManagers();
|
|
312
|
+
const current = getPackageManager();
|
|
313
|
+
|
|
314
|
+
let message = '[PackageManager] Available package managers:\n';
|
|
315
|
+
|
|
316
|
+
for (const pmName of available) {
|
|
317
|
+
const indicator = pmName === current.name ? ' (current)' : '';
|
|
318
|
+
message += ` - ${pmName}${indicator}\n`;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
message += '\nTo set your preferred package manager:\n';
|
|
322
|
+
message += ' - Global: Set CLAUDE_PACKAGE_MANAGER environment variable\n';
|
|
323
|
+
message += ' - Or add to ~/.claude/package-manager.json: {"packageManager": "pnpm"}\n';
|
|
324
|
+
message += ' - Or add to package.json: {"packageManager": "pnpm@8"}\n';
|
|
325
|
+
|
|
326
|
+
return message;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/**
|
|
330
|
+
* Generate a regex pattern that matches commands for all package managers
|
|
331
|
+
* @param {string} action - Action pattern (e.g., "run dev", "install", "test")
|
|
332
|
+
*/
|
|
333
|
+
function getCommandPattern(action) {
|
|
334
|
+
const patterns = [];
|
|
335
|
+
|
|
336
|
+
if (action === 'dev') {
|
|
337
|
+
patterns.push(
|
|
338
|
+
'npm run dev',
|
|
339
|
+
'pnpm( run)? dev',
|
|
340
|
+
'yarn dev',
|
|
341
|
+
'bun run dev'
|
|
342
|
+
);
|
|
343
|
+
} else if (action === 'install') {
|
|
344
|
+
patterns.push(
|
|
345
|
+
'npm install',
|
|
346
|
+
'pnpm install',
|
|
347
|
+
'yarn( install)?',
|
|
348
|
+
'bun install'
|
|
349
|
+
);
|
|
350
|
+
} else if (action === 'test') {
|
|
351
|
+
patterns.push(
|
|
352
|
+
'npm test',
|
|
353
|
+
'pnpm test',
|
|
354
|
+
'yarn test',
|
|
355
|
+
'bun test'
|
|
356
|
+
);
|
|
357
|
+
} else if (action === 'build') {
|
|
358
|
+
patterns.push(
|
|
359
|
+
'npm run build',
|
|
360
|
+
'pnpm( run)? build',
|
|
361
|
+
'yarn build',
|
|
362
|
+
'bun run build'
|
|
363
|
+
);
|
|
364
|
+
} else {
|
|
365
|
+
// Generic run command
|
|
366
|
+
patterns.push(
|
|
367
|
+
`npm run ${action}`,
|
|
368
|
+
`pnpm( run)? ${action}`,
|
|
369
|
+
`yarn ${action}`,
|
|
370
|
+
`bun run ${action}`
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return `(${patterns.join('|')})`;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
module.exports = {
|
|
378
|
+
PACKAGE_MANAGERS,
|
|
379
|
+
DETECTION_PRIORITY,
|
|
380
|
+
getPackageManager,
|
|
381
|
+
setPreferredPackageManager,
|
|
382
|
+
setProjectPackageManager,
|
|
383
|
+
getAvailablePackageManagers,
|
|
384
|
+
detectFromLockFile,
|
|
385
|
+
detectFromPackageJson,
|
|
386
|
+
getRunCommand,
|
|
387
|
+
getExecCommand,
|
|
388
|
+
getSelectionPrompt,
|
|
389
|
+
getCommandPattern
|
|
390
|
+
};
|