project-compass 2.0.1 → 2.0.2

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
@@ -79,7 +79,7 @@ Projects and details now occupy the same row, while the output panel takes its o
79
79
 
80
80
  ## Structure guide
81
81
 
82
- Press `S` to reveal the structure guide that lists which manifest files trigger each language detection (Node.js looks for `package.json`, Python looks for `pyproject.toml` or `requirements.txt`, Rust needs `Cargo.toml`, etc.). Use `H` to hide the help cards if you need every pixel for your output, then bring them back when you want a refresher.
82
+ Press `Ctrl+S` to reveal the structure guide that lists which manifest files trigger each language detection (Node.js looks for `package.json`, Python looks for `pyproject.toml` or `requirements.txt`, Rust needs `Cargo.toml`, etc.). Use `Ctrl+H` to hide the help cards if you need every pixel for your output, then bring them back when you want a refresher.
83
83
 
84
84
  ## Detection & setup hints
85
85
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-compass",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
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",
Binary file
package/src/cli.js CHANGED
@@ -524,9 +524,8 @@ const projectRows = [];
524
524
  label: 'Navigation',
525
525
  color: 'magenta',
526
526
  body: [
527
- '↑ / ↓ move the project focus',
528
- 'Enter opens or closes details',
529
- 'Shift + ↑ / ↓ scrolls only the log buffer',
527
+ '↑ / ↓ move the project focus, Enter toggles details',
528
+ 'Shift+↑ / Shift+↓ scroll only the output buffer',
530
529
  'Ctrl+H toggles cards, ? opens the overlay'
531
530
  ]
532
531
  },
@@ -534,10 +533,10 @@ const projectRows = [];
534
533
  label: 'Command flow',
535
534
  color: 'cyan',
536
535
  body: [
537
- 'B / T / R trigger build/test/run',
536
+ 'B / T / R trigger build/test/run shortcuts',
538
537
  '1-9 execute detail commands in order',
539
538
  'Ctrl+L reruns the last command you launched',
540
- 'Ctrl+C aborts, typing feeds stdin (buffer mirrors it)'
539
+ 'Ctrl+C aborts; typing feeds stdin (buffer mirrors it)'
541
540
  ]
542
541
  },
543
542
  {
@@ -545,8 +544,8 @@ const projectRows = [];
545
544
  color: 'yellow',
546
545
  body: [
547
546
  recentRuns.length ? `${recentRuns.length} runs recorded` : 'No runs yet · start with B/T/R',
548
- 'Ctrl+S shows the structure guide when unsure',
549
- 'Save custom commands with C → label|cmd'
547
+ 'Ctrl+S toggles the structure guide when unsure',
548
+ 'C → label|cmd saves a custom action'
550
549
  ]
551
550
  }
552
551
  ];
@@ -575,7 +574,7 @@ const projectRows = [];
575
574
  )
576
575
  )
577
576
  )
578
- : create(Text, {dimColor: true, marginTop: 1}, 'Help cards hidden · press H to show navigation, command flow, and recent runs.');
577
+ : create(Text, {dimColor: true, marginTop: 1}, 'Help cards hidden · press Ctrl+H to show navigation, command flow, and recent runs.');
579
578
 
580
579
  const structureGuide = showStructureGuide
581
580
  ? create(
@@ -587,7 +586,7 @@ const projectRows = [];
587
586
  marginTop: 1,
588
587
  padding: 1
589
588
  },
590
- create(Text, {color: 'cyan', bold: true}, 'Project structure guide · press S to hide'),
589
+ create(Text, {color: 'cyan', bold: true}, 'Project structure guide · press Ctrl+S to hide'),
591
590
  ...SCHEMA_GUIDE.map((entry) =>
592
591
  create(Text, {key: entry.type, dimColor: true}, `• ${entry.icon} ${entry.label}: ${entry.files.join(', ')}`)
593
592
  ),
@@ -606,18 +605,18 @@ const projectRows = [];
606
605
  padding: 1
607
606
  },
608
607
  create(Text, {color: 'cyan', bold: true}, 'Help overlay · press ? to hide'),
609
- create(Text, null, 'Shift+arrows scroll the output buffer.'),
610
- create(Text, null, 'Run commands and type to feed stdin (buffer mirrors your keystrokes, Enter submits, Ctrl+C aborts).'),
611
- create(Text, null, 'Ctrl+H toggles the navigation cards, Ctrl+S shows structure tips, Ctrl+L reruns the previous command, Ctrl+Q quits.'),
612
- create(Text, null, 'Projects + Details stay side-by-side while Output and the log buffer stay fixed in their own band.'),
613
- create(Text, null, 'Structure guide lists the manifests that trigger each language detection (press Ctrl+S to toggle).')
608
+ create(Text, null, 'Shift+↑/↓ scrolls the log buffer while commands stream; type to feed stdin (Enter submits, Ctrl+C aborts).'),
609
+ create(Text, null, 'B/T/R run build/test/run; 1-9 executes detail commands; Ctrl+L reruns the previous command.'),
610
+ create(Text, null, 'Ctrl+H toggles these help cards, Ctrl+S toggles the structure guide, ? toggles this overlay, Ctrl+Q quits.'),
611
+ create(Text, null, 'Projects + Details stay paired while Output keeps its own full-width band.'),
612
+ create(Text, null, 'Structure guide lists the manifests that trigger each language detection (Ctrl+S to toggle).')
614
613
  )
615
614
  : null;
616
615
 
617
616
  const toggleHint = showHelpCards ? 'Ctrl+H hides the help cards' : 'Ctrl+H shows the help cards';
618
617
  const headerHint = viewMode === 'detail'
619
- ? `Detail mode · 1-${Math.max(detailedIndexed.length, 1)} to execute, C: add custom commands, Enter: back to list, Ctrl+Q: quit · ${toggleHint}, Ctrl+S shows structure guide`
620
- : `Quick run · B/T/R to build/test/run, Enter: view details, Ctrl+Q: quit · ${toggleHint}, Ctrl+S shows structure guide`;
618
+ ? `Detail mode · 1-${Math.max(detailedIndexed.length, 1)} to execute, C: add custom commands, Enter: back to list, Ctrl+Q: quit · ${toggleHint}, Ctrl+S toggles structure guide`
619
+ : `Quick run · B/T/R to build/test/run, Enter: view details, Ctrl+Q: quit · ${toggleHint}, Ctrl+S toggles structure guide`;
621
620
 
622
621
  return create(
623
622
  Box,
@@ -702,7 +701,7 @@ const projectRows = [];
702
701
  Box,
703
702
  {marginTop: 1, flexDirection: 'row', justifyContent: 'space-between'},
704
703
  create(Text, {dimColor: true}, running ? 'Type to feed stdin; Enter submits, Ctrl+C aborts.' : 'Run a command or press ? for extra help.'),
705
- create(Text, {dimColor: true}, `${toggleHint}, S toggles the structure guide`)
704
+ create(Text, {dimColor: true}, `${toggleHint}, Ctrl+S toggles the structure guide`)
706
705
  ),
707
706
  create(
708
707
  Box,
@@ -5,6 +5,12 @@ import {ensureConfigDir, PLUGIN_FILE} from './configPaths.js';
5
5
 
6
6
  const IGNORE_PATTERNS = ['**/node_modules/**', '**/.git/**', '**/dist/**', '**/build/**', '**/target/**'];
7
7
 
8
+ const PYTHON_ENTRY_FILES = ['main.py', 'app.py', 'src/main.py', 'src/app.py'];
9
+
10
+ function findPythonEntry(projectPath) {
11
+ return PYTHON_ENTRY_FILES.find((file) => hasProjectFile(projectPath, file)) || null;
12
+ }
13
+
8
14
  function hasProjectFile(projectPath, file) {
9
15
  return fs.existsSync(path.join(projectPath, file));
10
16
  }
@@ -316,10 +322,14 @@ const builtInFrameworks = [
316
322
  languages: ['Python'],
317
323
  priority: 105,
318
324
  match(project) {
319
- return dependencyMatches(project, 'flask') || hasProjectFile(project.path, 'app.py');
325
+ const entry = findPythonEntry(project.path);
326
+ return Boolean(entry && dependencyMatches(project, 'flask'));
320
327
  },
321
328
  commands(project) {
322
- const entry = hasProjectFile(project.path, 'app.py') ? 'app.py' : 'main.py';
329
+ const entry = findPythonEntry(project.path);
330
+ if (!entry) {
331
+ return {};
332
+ }
323
333
  return {
324
334
  run: {label: 'Flask app', command: ['python', entry], source: 'framework'},
325
335
  test: {label: 'Pytest', command: ['pytest'], source: 'framework'}
@@ -334,12 +344,17 @@ const builtInFrameworks = [
334
344
  languages: ['Python'],
335
345
  priority: 105,
336
346
  match(project) {
337
- return dependencyMatches(project, 'fastapi');
347
+ const entry = findPythonEntry(project.path);
348
+ return Boolean(entry && dependencyMatches(project, 'fastapi'));
338
349
  },
339
350
  commands(project) {
340
- const entry = hasProjectFile(project.path, 'main.py') ? 'main.py' : 'app.py';
351
+ const entry = findPythonEntry(project.path);
352
+ if (!entry) {
353
+ return {};
354
+ }
355
+ const moduleName = entry.split('.').slice(0, -1).join('.') || entry;
341
356
  return {
342
- run: {label: 'Uvicorn reload', command: ['uvicorn', `${entry.split('.')[0]}:app`, '--reload'], source: 'framework'},
357
+ run: {label: 'Uvicorn reload', command: ['uvicorn', `${moduleName}:app`, '--reload'], source: 'framework'},
343
358
  test: {label: 'Pytest', command: ['pytest'], source: 'framework'}
344
359
  };
345
360
  }
@@ -458,7 +473,7 @@ class SchemaRegistry {
458
473
  commands.test = {label: 'Unittest', command: ['python', '-m', 'unittest', 'discover']};
459
474
  }
460
475
 
461
- const entry = this.findPythonEntry(projectPath);
476
+ const entry = findPythonEntry(projectPath);
462
477
  if (entry) {
463
478
  commands.run = {label: 'Run', command: ['python', entry]};
464
479
  }
@@ -492,15 +507,6 @@ class SchemaRegistry {
492
507
  }
493
508
  };
494
509
  },
495
- findPythonEntry(projectPath) {
496
- const candidates = ['main.py', 'app.py', 'src/main.py', 'src/app.py'];
497
- for (const candidate of candidates) {
498
- if (hasProjectFile(projectPath, candidate)) {
499
- return candidate;
500
- }
501
- }
502
- return null;
503
- }
504
510
  },
505
511
  {
506
512
  type: 'rust',