project-compass 2.1.0 โ†’ 2.2.0

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 CHANGED
@@ -1,4 +1,4 @@
1
- # Project Compass (v2.1.0)
1
+ # Project Compass (v2.2.0)
2
2
 
3
3
  Project Compass is a futuristic CLI navigator built with [Ink](https://github.com/vadimdemedes/ink) that scans your current folder tree for familiar code projects and gives you one-keystroke access to build, test, or run them.
4
4
 
@@ -8,8 +8,8 @@ Project Compass is a futuristic CLI navigator built with [Ink](https://github.co
8
8
  - ๐ŸŽจ Futuristic layout with glyph-based art board and split Projects/Details rows.
9
9
  - ๐Ÿš€ **New Keyboard-Centric UX**: Shortcuts now use **Shift** instead of Ctrl to avoid terminal interference.
10
10
  - ๐Ÿ’ก **Refined Output**: Improved stdin buffer with proper spacing and reliable scrolling (Shift+โ†‘/โ†“).
11
- - ๐Ÿง  **Smart Detection**: Support for 12+ frameworks with specialized build/run commands and setup hints.
12
- - ๐Ÿ”Œ **Extensible**: Add custom commands with **C** and frameworks via `plugins.json`.
11
+ - ๐Ÿง  **Smart Detection**: Support for 15+ frameworks (Vite, Prisma, Tailwind, etc.) with specialized build/run commands and setup hints.
12
+ - ๐Ÿ”Œ **Extensible**: Add custom commands with **Shift+C** and frameworks via `plugins.json`.
13
13
 
14
14
  ## Installation
15
15
 
@@ -30,7 +30,7 @@ project-compass [--dir /path/to/workspace]
30
30
  | โ†‘ / โ†“ | Move focus, **Enter**: toggle details |
31
31
  | B / T / R | Build / Test / Run |
32
32
  | 1โ€‘9 | Execute numbered detail commands |
33
- | C | Add a custom command (`label|cmd`) |
33
+ | **Shift+C** | Add a custom command (`label|cmd`) |
34
34
  | **Shift โ†‘ / โ†“** | Scroll output buffer |
35
35
  | **Shift+L** | Rerun last command |
36
36
  | **Shift+H** | Toggle help cards |
@@ -45,7 +45,7 @@ Project Compass features a split layout where Projects and Details stay paired w
45
45
 
46
46
  ## Frameworks
47
47
 
48
- Detects **Next.js**, **React**, **Vue**, **NestJS**, **FastAPI**, **Django**, and more. Recognizes frameworks and injects specialized commands automatically.
48
+ Detects **Next.js**, **React**, **Vue**, **NestJS**, **FastAPI**, **Django**, **Vite**, **Prisma**, **Tailwind**, and more. Recognizes frameworks and injects specialized commands automatically.
49
49
 
50
50
  ## License
51
51
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-compass",
3
- "version": "2.1.0",
3
+ "version": "2.2.0",
4
4
  "description": "Ink-based project explorer that detects local repos and lets you build/test/run them without memorizing commands.",
5
5
  "main": "src/cli.js",
6
6
  "type": "module",
package/src/cli.js CHANGED
@@ -306,11 +306,11 @@ function Compass({rootPath}) {
306
306
  }
307
307
 
308
308
  if (key.shift && key.upArrow) {
309
- scrollLogs(-1);
309
+ scrollLogs(1);
310
310
  return;
311
311
  }
312
312
  if (key.shift && key.downArrow) {
313
- scrollLogs(1);
313
+ scrollLogs(-1);
314
314
  return;
315
315
  }
316
316
 
@@ -342,7 +342,7 @@ function Compass({rootPath}) {
342
342
  exit();
343
343
  return;
344
344
  }
345
- if (normalizedInput === 'c' && viewMode === 'detail' && selectedProject) {
345
+ if (shiftCombo('c') && viewMode === 'detail' && selectedProject) {
346
346
  setCustomMode(true);
347
347
  setCustomInput('');
348
348
  return;
@@ -412,19 +412,19 @@ const projectRows = [];
412
412
  detailContent.push(create(Text, {bold: true, marginTop: 1}, 'Commands'));
413
413
  detailedIndexed.forEach((command) => {
414
414
  detailContent.push(
415
- create(Text, {key: `detail-${command.shortcut}-${command.label}`}, `${command.shortcut}. ${command.label} ${command.source === 'custom' ? kleur.magenta('(custom)') : command.source === 'framework' ? kleur.cyan('(framework)') : ''}`)
415
+ create(Text, {key: `detail-${command.shortcut}-${command.label}`}, `${command.shortcut}. ${command.label} ${command.source === 'custom' ? kleur.magenta('(custom)') : command.source === 'framework' ? kleur.cyan('(framework)') : command.source === 'plugin' ? kleur.green('(plugin)') : ''}`)
416
416
  );
417
417
  detailContent.push(create(Text, {dimColor: true}, ` โ†ณ ${command.command.join(' ')}`));
418
418
  });
419
419
  if (!detailedIndexed.length) {
420
- detailContent.push(create(Text, {dimColor: true}, 'No built-in commands yet. Add a custom command with C.'));
420
+ detailContent.push(create(Text, {dimColor: true}, 'No built-in commands yet. Add a custom command with Shift+C.'));
421
421
  }
422
422
  const setupHints = selectedProject.extra?.setupHints || [];
423
423
  if (setupHints.length) {
424
424
  detailContent.push(create(Text, {dimColor: true, marginTop: 1}, 'Setup hints:'));
425
425
  setupHints.forEach((hint) => detailContent.push(create(Text, {dimColor: true}, ` โ€ข ${hint}`)));
426
426
  }
427
- detailContent.push(create(Text, {dimColor: true}, 'Press C โ†’ label|cmd to save custom actions, Enter to close detail view.'));
427
+ detailContent.push(create(Text, {dimColor: true}, 'Press Shift+C โ†’ label|cmd to save custom actions, Enter to close detail view.'));
428
428
  } else {
429
429
  detailContent.push(create(Text, {dimColor: true}, 'Press Enter on a project to reveal details (icons, commands, frameworks, custom actions).'));
430
430
  }
@@ -546,7 +546,7 @@ const projectRows = [];
546
546
  body: [
547
547
  recentRuns.length ? `${recentRuns.length} runs recorded` : 'No runs yet ยท start with B/T/R',
548
548
  'Shift+S toggles structure guide',
549
- 'C save custom action',
549
+ 'Shift+C save custom action',
550
550
  'Shift+Q quit application'
551
551
  ]
552
552
  }
@@ -618,7 +618,7 @@ const projectRows = [];
618
618
 
619
619
  const toggleHint = showHelpCards ? 'Shift+H hides the help cards' : 'Shift+H shows the help cards';
620
620
  const headerHint = viewMode === 'detail'
621
- ? `Detail mode ยท 1-${Math.max(detailedIndexed.length, 1)} to execute, C: add custom commands, Enter: back to list, Shift+Q: quit ยท ${toggleHint}, Shift+S toggles structure guide`
621
+ ? `Detail mode ยท 1-${Math.max(detailedIndexed.length, 1)} to execute, Shift+C: add custom commands, Enter: back to list, Shift+Q: quit ยท ${toggleHint}, Shift+S toggles structure guide`
622
622
  : `Quick run ยท B/T/R to build/test/run, Enter: view details, Shift+Q: quit ยท ${toggleHint}, Shift+S toggles structure guide`;
623
623
 
624
624
  return create(
@@ -323,7 +323,7 @@ const builtInFrameworks = [
323
323
  priority: 105,
324
324
  match(project) {
325
325
  const entry = findPythonEntry(project.path);
326
- return Boolean(entry && dependencyMatches(project, 'flask'));
326
+ return Boolean(entry && (dependencyMatches(project, 'flask') || dependencyMatches(project, 'flask-restful') || dependencyMatches(project, 'flask-cors')));
327
327
  },
328
328
  commands(project) {
329
329
  const entry = findPythonEntry(project.path);
@@ -345,7 +345,7 @@ const builtInFrameworks = [
345
345
  priority: 105,
346
346
  match(project) {
347
347
  const entry = findPythonEntry(project.path);
348
- return Boolean(entry && dependencyMatches(project, 'fastapi'));
348
+ return Boolean(entry && (dependencyMatches(project, 'fastapi') || dependencyMatches(project, 'pydantic') || dependencyMatches(project, 'uvicorn')));
349
349
  },
350
350
  commands(project) {
351
351
  const entry = findPythonEntry(project.path);
@@ -359,6 +359,59 @@ const builtInFrameworks = [
359
359
  };
360
360
  }
361
361
  },
362
+ {
363
+ id: 'vite',
364
+ name: 'Vite',
365
+ icon: 'โšก',
366
+ description: 'Vite-powered frontend',
367
+ languages: ['Node.js'],
368
+ priority: 100,
369
+ match(project) {
370
+ return hasProjectFile(project.path, 'vite.config.js') || hasProjectFile(project.path, 'vite.config.ts') || dependencyMatches(project, 'vite');
371
+ },
372
+ commands(project) {
373
+ const commands = {};
374
+ const add = (key, label, fallback) => {
375
+ const tokens = resolveScriptCommand(project, key, fallback);
376
+ if (tokens) {
377
+ commands[key] = {label, command: tokens, source: 'framework'};
378
+ }
379
+ };
380
+ add('run', 'Vite dev', () => ['npx', 'vite']);
381
+ add('build', 'Vite build', () => ['npx', 'vite', 'build']);
382
+ add('preview', 'Vite preview', () => ['npx', 'vite', 'preview']);
383
+ return commands;
384
+ }
385
+ },
386
+ {
387
+ id: 'tailwind',
388
+ name: 'Tailwind CSS',
389
+ icon: '๐ŸŽจ',
390
+ description: 'Tailwind utility-first CSS',
391
+ languages: ['Node.js'],
392
+ priority: 50,
393
+ match(project) {
394
+ return hasProjectFile(project.path, 'tailwind.config.js') || hasProjectFile(project.path, 'tailwind.config.ts') || dependencyMatches(project, 'tailwindcss');
395
+ },
396
+ commands() { return {}; }
397
+ },
398
+ {
399
+ id: 'prisma',
400
+ name: 'Prisma',
401
+ icon: 'โ—ฎ',
402
+ description: 'Prisma ORM',
403
+ languages: ['Node.js'],
404
+ priority: 50,
405
+ match(project) {
406
+ return hasProjectFile(project.path, 'prisma/schema.prisma') || dependencyMatches(project, '@prisma/client');
407
+ },
408
+ commands() {
409
+ return {
410
+ generate: {label: 'Prisma generate', command: ['npx', 'prisma', 'generate'], source: 'framework'},
411
+ studio: {label: 'Prisma studio', command: ['npx', 'prisma', 'studio'], source: 'framework'}
412
+ };
413
+ }
414
+ },
362
415
  {
363
416
  id: 'spring',
364
417
  name: 'Spring Boot',