project-compass 2.9.2 โ†’ 3.0.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.8.0)
1
+ # Project Compass (v2.9.2)
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
 
@@ -14,6 +14,7 @@ Project Compass is a futuristic CLI navigator built with [Ink](https://github.co
14
14
  - ๐Ÿ’Ž **Omni-Studio**: A new interactive environment intelligence mode to see all installed runtimes and versions.
15
15
  - ๐Ÿ“‚ **Log Management**: Clear output with **Shift+X** or export logs to a text file with **Shift+E**.
16
16
  - ๐Ÿ”Œ **Extensible**: Add custom commands with **Shift+C** and frameworks via `plugins.json`.
17
+ - ๐Ÿ’พ **Persistence**: Saves your UI preferences (Art Board, Help, Structure Guide) globally in `~/.project-compass/config.json`.
17
18
 
18
19
  ## Installation
19
20
 
@@ -37,20 +38,26 @@ project-compass [--dir /path/to/workspace] [--studio]
37
38
  | **Shift+T** | Open **Orbit Task Manager** |
38
39
  | **Shift+D** | **Detach** from active task (runs in background) |
39
40
  | **Shift+A** | Open **Omni-Studio** (Environment View) |
41
+ | **Shift+B** | Toggle **Art Board** visibility |
42
+ | **Shift+H** | Toggle **Help Cards** visibility |
43
+ | **Shift+S** | Toggle **Structure Guide** visibility |
40
44
  | **Shift+C** | Add a custom command (`label|cmd`) |
41
45
  | **Shift+X** | **Clear output logs** |
42
46
  | **Shift+E** | **Export logs to .txt** |
43
47
  | **Shift โ†‘ / โ†“** | Scroll output buffer |
44
48
  | **Shift+L** | Rerun last command |
45
- | **Shift+H** | Toggle help cards |
46
- | **Shift+S** | Toggle structure guide |
47
- | **Shift+Q** | Quit app |
49
+ | **Shift+Q** | Quit app (with confirmation if tasks run) |
48
50
  | ? | Toggle help overlay |
49
51
  | Ctrl+C | Interrupt running command |
50
52
 
51
53
  ## Orbit Task Manager
52
54
 
53
- Project Compass v2.8 introduces background task management. You can start a build, press **Shift+D** to detach and return to the navigator, then start another task. Switch between them or view logs via the Task Manager (**Shift+T**).
55
+ Project Compass introduces background task management. You can start a build, press **Shift+D** to detach and return to the navigator, then start another task.
56
+
57
+ Inside the Task Manager (**Shift+T**):
58
+ - **Shift+K**: Kill a running process or remove a task from history.
59
+ - **Shift+R**: Rename a task for better organization.
60
+ - **Enter**: Switch back to the Navigator with the selected task's logs.
54
61
 
55
62
  ## Omni-Studio
56
63
 
package/commands.md ADDED
@@ -0,0 +1,72 @@
1
+ # Project Compass ยท Commands & Shortcuts
2
+
3
+ This document lists all supported languages, frameworks, and their built-in commands and keyboard shortcuts.
4
+
5
+ ## Keyboard Guide (Navigator)
6
+
7
+ | Key | Action |
8
+ | --- | --- |
9
+ | โ†‘ / โ†“ | Move project focus |
10
+ | Enter | Toggle detail view for selected project / Switch back from Tasks |
11
+ | **Shift+A** | Open **Omni-Studio** (Environment intelligence) |
12
+ | **Shift+T** | Open **Orbit Task Manager** |
13
+ | **Shift+D** | **Detach** from active task (runs in background) |
14
+ | **Shift+B** | Toggle **Art Board** visibility (Saved to config) |
15
+ | **Shift+H** | Toggle **Help Cards** visibility (Saved to config) |
16
+ | **Shift+S** | Toggle **Structure Guide** visibility (Saved to config) |
17
+ | **Shift+X** | **Clear** active task output logs |
18
+ | **Shift+E** | **Export** logs to a timestamped `.txt` file |
19
+ | **Shift+L** | **Rerun** the last executed command |
20
+ | **Shift+C** | Add a **Custom Command** (`label|cmd`) in detail view |
21
+ | **Shift+Q** | **Quit** application (Confirms if tasks are running) |
22
+ | Shift+โ†‘ / โ†“ | Scroll output logs (Intuitive direction) |
23
+ | ? | Toggle help overlay |
24
+ | Ctrl+C | Interrupt running command |
25
+
26
+ ## Supported Languages & Runtimes
27
+
28
+ Compass scans for the following manifests and requires their binaries in your PATH:
29
+
30
+ - **Node.js** (`node`, `npm`): `package.json`
31
+ - **Python** (`python3`, `pip`): `pyproject.toml`, `requirements.txt`, `Pipfile`, `setup.py`
32
+ - **Rust** (`cargo`): `Cargo.toml`
33
+ - **Go** (`go`): `go.mod`
34
+ - **Java/Kotlin** (`java`, `mvn`, `gradle`): `pom.xml`, `build.gradle`
35
+ - **Scala** (`sbt`): `build.sbt`
36
+ - **PHP** (`php`, `composer`): `composer.json`
37
+ - **Ruby** (`ruby`, `bundle`): `Gemfile`
38
+ - **.NET** (`dotnet`): `*.csproj`
39
+ - **Shell** (`sh`, `make`): `Makefile`, `build.sh`
40
+
41
+ ## Built-in Framework Intelligence
42
+
43
+ When a framework is detected, specialized commands are injected automatically:
44
+
45
+ | Framework | Icon | Commands |
46
+ | --- | --- | --- |
47
+ | **Next.js** | ๐Ÿงญ | install, dev, build, test, start |
48
+ | **React** | โš›๏ธ | install, dev, build, test |
49
+ | **Vue.js** | ๐ŸŸฉ | install, dev, build, test |
50
+ | **NestJS** | ๐Ÿ›ก๏ธ | install, dev (start:dev), build, test |
51
+ | **Angular** | ๐Ÿ…ฐ๏ธ | install, serve, build, test |
52
+ | **SvelteKit** | ๐ŸŒ€ | install, dev, build, test, preview |
53
+ | **Nuxt** | ๐Ÿช„ | install, dev, build, start |
54
+ | **Astro** | โœจ | install, dev, build, preview |
55
+ | **Django** | ๐ŸŒฟ | pip install, runserver, test, migrate |
56
+ | **Flask** | ๐Ÿถ | pip install, run, pytest |
57
+ | **FastAPI** | โšก | pip install, uvicorn reload, pytest |
58
+ | **Vite** | โšก | install, dev, build, preview |
59
+ | **Spring Boot** | ๐ŸŒฑ | bootRun (Gradle) / spring-boot:run (Maven), build, test |
60
+ | **ASP.NET Core**| ๐ŸŒ | restore, run, watch, test |
61
+ | **Laravel** | ๐Ÿงก | composer install, artisan serve, test, migrate |
62
+ | **Rocket** | ๐Ÿš€ | cargo fetch, run, test |
63
+ | **Actix Web** | ๐Ÿฆ€ | cargo fetch, run, test |
64
+ | **Prisma** | โ—ฎ | install, generate, studio |
65
+ | **Tailwind** | ๐ŸŽจ | install |
66
+
67
+ ## Task Manager Shortcuts (Shift+T)
68
+
69
+ - **Shift+K**: Kill a running process or remove a finished task from history.
70
+ - **Shift+R**: Rename a task for better organization.
71
+ - **Arrows**: Move focus between tasks.
72
+ - **Enter**: Jump to the selected task's logs in Navigator.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "project-compass",
3
- "version": "2.9.2",
3
+ "version": "3.0.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
@@ -465,6 +465,10 @@ function Compass({rootPath, initialView = 'navigator'}) {
465
465
  });
466
466
 
467
467
  const projectCountLabel = `${projects.length} project${projects.length === 1 ? '' : 's'}`;
468
+ const toggleHint = config.showHelpCards ? 'Shift+H hide help' : 'Shift+H show help';
469
+ const statusHint = activeTask ? `[${activeTask.status.toUpperCase()}] ${activeTask.name}` : 'Idle Navigator';
470
+ const orbitHint = mainView === 'tasks' ? 'Tasks View' : `Orbit: ${tasks.length} tasks`;
471
+ const artHint = config.showArtBoard ? 'Shift+B hide art' : 'Shift+B show art';
468
472
 
469
473
  if (quitConfirm) {
470
474
  return create(Box, {flexDirection: 'column', borderStyle: 'round', borderColor: 'red', padding: 1}, create(Text, {bold: true, color: 'red'}, 'โš ๏ธ Confirm Exit'), create(Text, null, `There are ${tasks.filter(t=>t.status==='running').length} tasks still running in the background.`), create(Text, null, 'Are you sure you want to quit and stop all processes?'), create(Text, {marginTop: 1}, kleur.bold('Y') + ' to Quit, ' + kleur.bold('N') + ' to Cancel'));
@@ -578,11 +582,13 @@ function Compass({rootPath, initialView = 'navigator'}) {
578
582
  {label: 'Orbit & Studio', color: 'yellow', body: ['Shift+T task manager', 'Shift+A studio / Shift+B art board', 'Shift+S structure / Shift+Q quit']}
579
583
  ];
580
584
 
581
- const toggleHint = config.showHelpCards ? 'Shift+H hide help' : 'Shift+H show help';
582
585
  return create(Box, {flexDirection: 'column', padding: 1},
583
586
  create(Box, {justifyContent: 'space-between'},
584
587
  create(Box, {flexDirection: 'column'}, create(Text, {color: 'magenta', bold: true}, 'Project Compass'), create(Text, {dimColor: true}, `${projectCountLabel} detected in ${rootPath}`)),
585
- create(Box, {flexDirection: 'column', alignItems: 'flex-end'}, create(Text, {color: running ? 'yellow' : 'green'}, activeTask ? `[${activeTask.status.toUpperCase()}] ${activeTask.name}` : 'Idle Navigator'), create(Text, {dimColor: true}, `${toggleHint}, Shift+T: Tasks, Shift+Q: Quit`))
588
+ create(Box, {flexDirection: 'column', alignItems: 'flex-end'},
589
+ create(Text, {color: running ? 'yellow' : 'green'}, statusHint),
590
+ create(Text, {dimColor: true}, `${toggleHint} ยท ${orbitHint} ยท ${artHint} ยท Shift+Q: Quit`)
591
+ )
586
592
  ),
587
593
  artBoard,
588
594
  create(Box, {marginTop: 1, flexDirection: 'row', alignItems: 'stretch', width: '100%', flexWrap: 'wrap'},
@@ -597,7 +603,7 @@ function Compass({rootPath, initialView = 'navigator'}) {
597
603
  ),
598
604
  config.showHelpCards && create(Box, {marginTop: 1, flexDirection: 'row', justifyContent: 'space-between', flexWrap: 'wrap'}, ...helpCards.map((card, idx) => create(Box, {key: card.label, flexGrow: 1, flexBasis: 0, minWidth: HELP_CARD_MIN_WIDTH, marginRight: idx < 2 ? 1 : 0, marginBottom: 1, borderStyle: 'round', borderColor: card.color, padding: 1, flexDirection: 'column'}, create(Text, {color: card.color, bold: true, marginBottom: 1}, card.label), ...card.body.map((line, lidx) => create(Text, {key: lidx, dimColor: card.color === 'yellow'}, line))))),
599
605
  config.showStructureGuide && create(Box, {flexDirection: 'column', borderStyle: 'round', borderColor: 'blue', marginTop: 1, padding: 1}, create(Text, {color: 'cyan', bold: true}, 'Structure guide ยท press Shift+S to hide'), ...SCHEMA_GUIDE.map(e => create(Text, {key: e.type, dimColor: true}, `โ€ข ${e.icon} ${e.label}: ${e.files.join(', ')}`))),
600
- showHelp && create(Box, {flexDirection: 'column', borderStyle: 'double', borderColor: 'cyan', marginTop: 1, padding: 1}, create(Text, {color: 'cyan', bold: true}, 'Help overlay'), create(Text, null, 'Shift+โ†‘/โ†“ scrolls logs; Shift+X clears; Shift+E exports; Shift+A Studio; Shift+T Tasks; Shift+D Detach; Shift+B Toggle Art.'))
606
+ showHelp && create(Box, {flexDirection: 'column', borderStyle: 'double', borderColor: 'cyan', marginTop: 1, padding: 1}, create(Text, {color: 'cyan', bold: true}, 'Help overlay'), create(Text, null, 'Shift+โ†‘/โ†“ scrolls logs; Shift+X clears; Shift+E exports; Shift+A Studio; Shift+T Tasks; Shift+D Detach; Shift+B Toggle Art Board.'))
601
607
  );
602
608
  }
603
609
 
@@ -123,13 +123,11 @@ const builtInFrameworks = [
123
123
  commands[key] = {label, command: tokens, source: 'framework'};
124
124
  }
125
125
  };
126
- const buildFallback = () => ['npx', 'next', 'build'];
127
- const startFallback = () => ['npx', 'next', 'start'];
128
- const devFallback = () => ['npx', 'next', 'dev'];
129
- add('run', 'Next dev', devFallback);
130
- add('build', 'Next build', buildFallback);
126
+ add('install', 'Next install', () => ['npm', 'install']);
127
+ add('run', 'Next dev', () => ['npx', 'next', 'dev']);
128
+ add('build', 'Next build', () => ['npx', 'next', 'build']);
131
129
  add('test', 'Next test', () => ['npm', 'run', 'test']);
132
- add('start', 'Next start', startFallback);
130
+ add('start', 'Next start', () => ['npx', 'next', 'start']);
133
131
  return commands;
134
132
  }
135
133
  },
@@ -151,6 +149,7 @@ const builtInFrameworks = [
151
149
  commands[key] = {label, command: tokens, source: 'framework'};
152
150
  }
153
151
  };
152
+ add('install', 'React install', () => ['npm', 'install']);
154
153
  add('run', 'React dev', () => ['npm', 'run', 'dev']);
155
154
  add('build', 'React build', () => ['npm', 'run', 'build']);
156
155
  add('test', 'React test', () => ['npm', 'run', 'test']);
@@ -175,6 +174,7 @@ const builtInFrameworks = [
175
174
  commands[key] = {label, command: tokens, source: 'framework'};
176
175
  }
177
176
  };
177
+ add('install', 'Vue install', () => ['npm', 'install']);
178
178
  add('run', 'Vue dev', () => ['npm', 'run', 'dev']);
179
179
  add('build', 'Vue build', () => ['npm', 'run', 'build']);
180
180
  add('test', 'Vue test', () => ['npm', 'run', 'test']);
@@ -199,6 +199,7 @@ const builtInFrameworks = [
199
199
  commands[key] = {label, command: tokens, source: 'framework'};
200
200
  }
201
201
  };
202
+ add('install', 'Nest install', () => ['npm', 'install']);
202
203
  add('run', 'Nest dev', () => ['npm', 'run', 'start:dev']);
203
204
  add('build', 'Nest build', () => ['npm', 'run', 'build']);
204
205
  add('test', 'Nest test', () => ['npm', 'run', 'test']);
@@ -223,6 +224,7 @@ const builtInFrameworks = [
223
224
  commands[key] = {label, command: tokens, source: 'framework'};
224
225
  }
225
226
  };
227
+ add('install', 'Angular install', () => ['npm', 'install']);
226
228
  add('run', 'Angular serve', () => ['npm', 'run', 'start']);
227
229
  add('build', 'Angular build', () => ['npm', 'run', 'build']);
228
230
  add('test', 'Angular test', () => ['npm', 'run', 'test']);
@@ -247,6 +249,7 @@ const builtInFrameworks = [
247
249
  commands[key] = {label, command: tokens, source: 'framework'};
248
250
  }
249
251
  };
252
+ add('install', 'SvelteKit install', () => ['npm', 'install']);
250
253
  add('run', 'SvelteKit dev', () => ['npm', 'run', 'dev']);
251
254
  add('build', 'SvelteKit build', () => ['npm', 'run', 'build']);
252
255
  add('test', 'SvelteKit test', () => ['npm', 'run', 'test']);
@@ -272,6 +275,7 @@ const builtInFrameworks = [
272
275
  commands[key] = {label, command: tokens, source: 'framework'};
273
276
  }
274
277
  };
278
+ add('install', 'Nuxt install', () => ['npm', 'install']);
275
279
  add('run', 'Nuxt dev', () => ['npm', 'run', 'dev']);
276
280
  add('build', 'Nuxt build', () => ['npm', 'run', 'build']);
277
281
  add('start', 'Nuxt start', () => ['npm', 'run', 'start']);
@@ -297,6 +301,7 @@ const builtInFrameworks = [
297
301
  commands[key] = {label, command: tokens, source: 'framework'};
298
302
  }
299
303
  };
304
+ add('install', 'Astro install', () => ['npm', 'install']);
300
305
  add('run', 'Astro dev', () => ['npm', 'run', 'dev']);
301
306
  add('build', 'Astro build', () => ['npm', 'run', 'build']);
302
307
  add('preview', 'Astro preview', () => ['npm', 'run', 'preview']);
@@ -315,14 +320,16 @@ const builtInFrameworks = [
315
320
  },
316
321
  commands(project) {
317
322
  const managePath = path.join(project.path, 'manage.py');
318
- if (!fs.existsSync(managePath)) {
319
- return {};
323
+ const commands = {};
324
+ if (hasProjectFile(project.path, 'requirements.txt')) {
325
+ commands.install = {label: 'Pip install', command: ['pip', 'install', '-r', 'requirements.txt'], source: 'framework'};
320
326
  }
321
- return {
322
- run: {label: 'Django runserver', command: ['python', 'manage.py', 'runserver'], source: 'framework'},
323
- test: {label: 'Django test', command: ['python', 'manage.py', 'test'], source: 'framework'},
324
- migrate: {label: 'Django migrate', command: ['python', 'manage.py', 'migrate'], source: 'framework'}
325
- };
327
+ if (fs.existsSync(managePath)) {
328
+ commands.run = {label: 'Django runserver', command: ['python', 'manage.py', 'runserver'], source: 'framework'};
329
+ commands.test = {label: 'Django test', command: ['python', 'manage.py', 'test'], source: 'framework'};
330
+ commands.migrate = {label: 'Django migrate', command: ['python', 'manage.py', 'migrate'], source: 'framework'};
331
+ }
332
+ return commands;
326
333
  }
327
334
  },
328
335
  {
@@ -338,13 +345,15 @@ const builtInFrameworks = [
338
345
  },
339
346
  commands(project) {
340
347
  const entry = findPythonEntry(project.path);
341
- if (!entry) {
342
- return {};
348
+ const commands = {};
349
+ if (hasProjectFile(project.path, 'requirements.txt')) {
350
+ commands.install = {label: 'Pip install', command: ['pip', 'install', '-r', 'requirements.txt'], source: 'framework'};
343
351
  }
344
- return {
345
- run: {label: 'Flask app', command: ['python', entry], source: 'framework'},
346
- test: {label: 'Pytest', command: ['pytest'], source: 'framework'}
347
- };
352
+ if (entry) {
353
+ commands.run = {label: 'Flask app', command: ['python', entry], source: 'framework'};
354
+ commands.test = {label: 'Pytest', command: ['pytest'], source: 'framework'};
355
+ }
356
+ return commands;
348
357
  }
349
358
  },
350
359
  {
@@ -360,14 +369,16 @@ const builtInFrameworks = [
360
369
  },
361
370
  commands(project) {
362
371
  const entry = findPythonEntry(project.path);
363
- if (!entry) {
364
- return {};
372
+ const commands = {};
373
+ if (hasProjectFile(project.path, 'requirements.txt')) {
374
+ commands.install = {label: 'Pip install', command: ['pip', 'install', '-r', 'requirements.txt'], source: 'framework'};
365
375
  }
366
- const moduleName = entry.split('.').slice(0, -1).join('.') || entry;
367
- return {
368
- run: {label: 'Uvicorn reload', command: ['uvicorn', `${moduleName}:app`, '--reload'], source: 'framework'},
369
- test: {label: 'Pytest', command: ['pytest'], source: 'framework'}
370
- };
376
+ if (entry) {
377
+ const moduleName = entry.split('.').slice(0, -1).join('.') || entry;
378
+ commands.run = {label: 'Uvicorn reload', command: ['uvicorn', `${moduleName}:app`, '--reload'], source: 'framework'};
379
+ commands.test = {label: 'Pytest', command: ['pytest'], source: 'framework'};
380
+ }
381
+ return commands;
371
382
  }
372
383
  },
373
384
  {
@@ -388,6 +399,7 @@ const builtInFrameworks = [
388
399
  commands[key] = {label, command: tokens, source: 'framework'};
389
400
  }
390
401
  };
402
+ add('install', 'Vite install', () => ['npm', 'install']);
391
403
  add('run', 'Vite dev', () => ['npx', 'vite']);
392
404
  add('build', 'Vite build', () => ['npx', 'vite', 'build']);
393
405
  add('preview', 'Vite preview', () => ['npx', 'vite', 'preview']);
@@ -404,7 +416,7 @@ const builtInFrameworks = [
404
416
  match(project) {
405
417
  return hasProjectFile(project.path, 'tailwind.config.js') || hasProjectFile(project.path, 'tailwind.config.ts') || dependencyMatches(project, 'tailwindcss');
406
418
  },
407
- commands() { return {}; }
419
+ commands() { return { install: {label: 'Tailwind install', command: ['npm', 'install', '-D', 'tailwindcss'], source: 'framework'} }; }
408
420
  },
409
421
  {
410
422
  id: 'prisma',
@@ -418,6 +430,7 @@ const builtInFrameworks = [
418
430
  },
419
431
  commands() {
420
432
  return {
433
+ install: {label: 'Prisma install', command: ['npm', 'install', '@prisma/client'], source: 'framework'},
421
434
  generate: {label: 'Prisma generate', command: ['npx', 'prisma', 'generate'], source: 'framework'},
422
435
  studio: {label: 'Prisma studio', command: ['npx', 'prisma', 'studio'], source: 'framework'}
423
436
  };
@@ -441,6 +454,7 @@ const builtInFrameworks = [
441
454
  const hasGradlew = hasProjectFile(project.path, 'gradlew');
442
455
  if (hasGradlew) {
443
456
  return {
457
+ install: {label: 'Gradle Resolve', command: ['./gradlew', 'dependencies'], source: 'framework'},
444
458
  run: {label: 'Gradle BootRun', command: ['./gradlew', 'bootRun'], source: 'framework'},
445
459
  build: {label: 'Gradle Build', command: ['./gradlew', 'build'], source: 'framework'},
446
460
  test: {label: 'Gradle Test', command: ['./gradlew', 'test'], source: 'framework'}
@@ -448,6 +462,7 @@ const builtInFrameworks = [
448
462
  }
449
463
  const base = hasMvnw ? './mvnw' : 'mvn';
450
464
  return {
465
+ install: {label: 'Maven Install', command: [base, 'install'], source: 'framework'},
451
466
  run: {label: 'Spring Boot run', command: [base, 'spring-boot:run'], source: 'framework'},
452
467
  build: {label: 'Maven package', command: [base, 'package'], source: 'framework'},
453
468
  test: {label: 'Maven test', command: [base, 'test'], source: 'framework'}
@@ -466,6 +481,7 @@ const builtInFrameworks = [
466
481
  },
467
482
  commands() {
468
483
  return {
484
+ install: {label: 'Cargo Fetch', command: ['cargo', 'fetch'], source: 'framework'},
469
485
  run: {label: 'Rocket Run', command: ['cargo', 'run'], source: 'framework'},
470
486
  test: {label: 'Rocket Test', command: ['cargo', 'test'], source: 'framework'}
471
487
  };
@@ -483,6 +499,7 @@ const builtInFrameworks = [
483
499
  },
484
500
  commands() {
485
501
  return {
502
+ install: {label: 'Cargo Fetch', command: ['cargo', 'fetch'], source: 'framework'},
486
503
  run: {label: 'Actix Run', command: ['cargo', 'run'], source: 'framework'},
487
504
  test: {label: 'Actix Test', command: ['cargo', 'test'], source: 'framework'}
488
505
  };
@@ -501,6 +518,7 @@ const builtInFrameworks = [
501
518
  },
502
519
  commands() {
503
520
  return {
521
+ install: {label: 'dotnet restore', command: ['dotnet', 'restore'], source: 'framework'},
504
522
  run: {label: 'dotnet run', command: ['dotnet', 'run'], source: 'framework'},
505
523
  watch: {label: 'dotnet watch', command: ['dotnet', 'watch', 'run'], source: 'framework'},
506
524
  test: {label: 'dotnet test', command: ['dotnet', 'test'], source: 'framework'}
@@ -519,6 +537,7 @@ const builtInFrameworks = [
519
537
  },
520
538
  commands() {
521
539
  return {
540
+ install: {label: 'Composer install', command: ['composer', 'install'], source: 'framework'},
522
541
  run: {label: 'Artisan Serve', command: ['php', 'artisan', 'serve'], source: 'framework'},
523
542
  test: {label: 'Artisan Test', command: ['php', 'artisan', 'test'], source: 'framework'},
524
543
  migrate: {label: 'Artisan Migrate', command: ['php', 'artisan', 'migrate'], source: 'framework'}
@@ -568,6 +587,7 @@ class SchemaRegistry {
568
587
  }
569
588
  }
570
589
  };
590
+ commands.install = {label: 'Install', command: ['npm', 'install']};
571
591
  preferScript('build', ['build', 'compile', 'dist'], 'Build');
572
592
  preferScript('test', ['test', 'check', 'spec'], 'Test');
573
593
  preferScript('run', ['start', 'dev', 'serve', 'run'], 'Start');
@@ -618,6 +638,9 @@ class SchemaRegistry {
618
638
  async build(projectPath, manifest) {
619
639
  const missingBinaries = this.binaries.filter(b => !checkBinary(b));
620
640
  const commands = {};
641
+ if (hasProjectFile(projectPath, 'requirements.txt')) {
642
+ commands.install = {label: 'Pip Install', command: ['pip', 'install', '-r', 'requirements.txt']};
643
+ }
621
644
  if (hasProjectFile(projectPath, 'pyproject.toml')) {
622
645
  commands.test = {label: 'Pytest', command: ['pytest']};
623
646
  } else {
@@ -677,6 +700,7 @@ class SchemaRegistry {
677
700
  icon: '๐Ÿฆ€',
678
701
  priority: this.priority,
679
702
  commands: {
703
+ install: {label: 'Cargo fetch', command: ['cargo', 'fetch']},
680
704
  build: {label: 'Cargo build', command: ['cargo', 'build']},
681
705
  test: {label: 'Cargo test', command: ['cargo', 'test']},
682
706
  run: {label: 'Cargo run', command: ['cargo', 'run']}
@@ -708,6 +732,7 @@ class SchemaRegistry {
708
732
  icon: '๐Ÿน',
709
733
  priority: this.priority,
710
734
  commands: {
735
+ install: {label: 'Go tidy', command: ['go', 'mod', 'tidy']},
711
736
  build: {label: 'Go build', command: ['go', 'build', './...']},
712
737
  test: {label: 'Go test', command: ['go', 'test', './...']},
713
738
  run: {label: 'Go run', command: ['go', 'run', '.']}
@@ -735,9 +760,11 @@ class SchemaRegistry {
735
760
  const hasGradlew = hasProjectFile(projectPath, 'gradlew');
736
761
  const commands = {};
737
762
  if (hasGradlew) {
763
+ commands.install = {label: 'Gradle resolve', command: ['./gradlew', 'dependencies']};
738
764
  commands.build = {label: 'Gradle build', command: ['./gradlew', 'build']};
739
765
  commands.test = {label: 'Gradle test', command: ['./gradlew', 'test']};
740
766
  } else if (hasMvnw) {
767
+ commands.install = {label: 'Maven install', command: ['./mvnw', 'install']};
741
768
  commands.build = {label: 'Maven package', command: ['./mvnw', 'package']};
742
769
  commands.test = {label: 'Maven test', command: ['./mvnw', 'test']};
743
770
  } else {
@@ -780,6 +807,7 @@ class SchemaRegistry {
780
807
  icon: '๐Ÿ”ต',
781
808
  priority: this.priority,
782
809
  commands: {
810
+ install: {label: 'sbt update', command: ['sbt', 'update']},
783
811
  build: {label: 'sbt compile', command: ['sbt', 'compile']},
784
812
  test: {label: 'sbt test', command: ['sbt', 'test']},
785
813
  run: {label: 'sbt run', command: ['sbt', 'run']}
@@ -811,6 +839,7 @@ class SchemaRegistry {
811
839
  icon: '๐Ÿ˜',
812
840
  priority: this.priority,
813
841
  commands: {
842
+ install: {label: 'Composer install', command: ['composer', 'install']},
814
843
  test: {label: 'PHP -v', command: ['php', '-v']}
815
844
  },
816
845
  metadata: {},
@@ -840,6 +869,7 @@ class SchemaRegistry {
840
869
  icon: '๐Ÿ’Ž',
841
870
  priority: this.priority,
842
871
  commands: {
872
+ install: {label: 'Bundle install', command: ['bundle', 'install']},
843
873
  run: {label: 'Ruby console', command: ['ruby', 'app.rb']},
844
874
  test: {label: 'Ruby test', command: ['bundle', 'exec', 'rspec']}
845
875
  },
@@ -870,6 +900,7 @@ class SchemaRegistry {
870
900
  icon: '๐Ÿ”ท',
871
901
  priority: this.priority,
872
902
  commands: {
903
+ install: {label: 'dotnet restore', command: ['dotnet', 'restore']},
873
904
  build: {label: 'dotnet build', command: ['dotnet', 'build']},
874
905
  test: {label: 'dotnet test', command: ['dotnet', 'test']},
875
906
  run: {label: 'dotnet run', command: ['dotnet', 'run']}