vibecodingmachine-cli 2025.12.25-1541 → 2026.1.3-2209

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.
@@ -0,0 +1,64 @@
1
+ const inquirer = require('inquirer');
2
+ const chalk = require('chalk');
3
+
4
+ /**
5
+ * Enhanced inquirer.prompt that shows a helpful hint for questions with defaults
6
+ * @param {Array} questions - Array of inquirer question objects
7
+ * @param {Object} options - Options object
8
+ * @param {boolean} options.showDefaultHint - Whether to show the default hint (default: true)
9
+ * @returns {Promise} - Promise resolving to answers
10
+ */
11
+ async function promptWithDefaults(questions, options = {}) {
12
+ const { showDefaultHint = true } = options;
13
+
14
+ // Check if any questions have defaults and if we should show the hint
15
+ const hasDefaults = questions.some(q => q.default !== undefined);
16
+
17
+ if (showDefaultHint && hasDefaults) {
18
+ // Show the hint in gray before the first question with a default
19
+ console.log(chalk.gray('(Capital letters are defaults--press return to select the defaults)'));
20
+ }
21
+
22
+ return await inquirer.prompt(questions);
23
+ }
24
+
25
+ /**
26
+ * Track whether we've shown the default hint in this session
27
+ * This ensures we only show it once per CLI session
28
+ */
29
+ let hasShownDefaultHint = false;
30
+
31
+ /**
32
+ * Enhanced inquirer.prompt that shows the default hint only once per session
33
+ * @param {Array} questions - Array of inquirer question objects
34
+ * @param {Object} options - Options object
35
+ * @param {boolean} options.forceShowHint - Force showing the hint even if already shown
36
+ * @returns {Promise} - Promise resolving to answers
37
+ */
38
+ async function promptWithDefaultsOnce(questions, options = {}) {
39
+ const { forceShowHint = false } = options;
40
+
41
+ // Check if any questions have defaults
42
+ const hasDefaults = questions.some(q => q.default !== undefined);
43
+
44
+ if (hasDefaults && (!hasShownDefaultHint || forceShowHint)) {
45
+ // Show the hint in gray before the first question with a default
46
+ console.log(chalk.gray('(Capital letters are defaults--press return to select the defaults)'));
47
+ hasShownDefaultHint = true;
48
+ }
49
+
50
+ return await inquirer.prompt(questions);
51
+ }
52
+
53
+ /**
54
+ * Reset the hint tracking (useful for testing or new sessions)
55
+ */
56
+ function resetDefaultHint() {
57
+ hasShownDefaultHint = false;
58
+ }
59
+
60
+ module.exports = {
61
+ promptWithDefaults,
62
+ promptWithDefaultsOnce,
63
+ resetDefaultHint
64
+ };
@@ -0,0 +1,76 @@
1
+ const os = require('os');
2
+ const path = require('path');
3
+ const fs = require('fs-extra');
4
+
5
+ describe('interactive home directory bootstrap', () => {
6
+ const tmpHome = path.join(os.tmpdir(), `vibecodingmachine_test_home_${Date.now()}`);
7
+ const tmpConfig = path.join(os.tmpdir(), `vibecodingmachine_test_config_${Date.now()}.json`);
8
+
9
+ beforeAll(async () => {
10
+ process.env.VIBECODINGMACHINE_CONFIG_PATH = tmpConfig;
11
+ await fs.ensureDir(tmpHome);
12
+
13
+ jest.resetModules();
14
+
15
+ jest.spyOn(os, 'homedir').mockReturnValue(tmpHome);
16
+
17
+ process.chdir(tmpHome);
18
+
19
+ const prompts = [];
20
+ jest.doMock('inquirer', () => ({
21
+ prompt: async (questions) => {
22
+ prompts.push(questions);
23
+ const q0 = Array.isArray(questions) ? questions[0] : questions;
24
+
25
+ if (q0 && q0.name === 'shouldCreateCodeDir') {
26
+ return { shouldCreateCodeDir: true };
27
+ }
28
+
29
+ if (q0 && q0.name === 'projectName') {
30
+ return { projectName: 'My Project Name' };
31
+ }
32
+
33
+ return {};
34
+ }
35
+ }));
36
+
37
+ jest.doMock('vibecodingmachine-core', () => ({
38
+ checkVibeCodingMachineExists: async () => ({ insideExists: false, siblingExists: false }),
39
+ getHostname: () => 'test-host',
40
+ getRequirementsFilename: async () => 'REQUIREMENTS.md',
41
+ requirementsExists: async () => false,
42
+ isComputerNameEnabled: async () => false,
43
+ t: (k) => k,
44
+ detectLocale: () => 'en',
45
+ setLocale: () => {}
46
+ }));
47
+
48
+
49
+ });
50
+
51
+ afterAll(async () => {
52
+ jest.restoreAllMocks();
53
+ delete process.env.VIBECODINGMACHINE_CONFIG_PATH;
54
+ await fs.remove(tmpConfig).catch(() => {});
55
+ await fs.remove(tmpHome).catch(() => {});
56
+ });
57
+
58
+ test('bootstraps ~/code/<project> from home and can init .vibecodingmachine inside it', async () => {
59
+ const { bootstrapProjectIfInHomeDir } = require('../src/utils/interactive');
60
+ await bootstrapProjectIfInHomeDir();
61
+
62
+ const projectDir = path.join(tmpHome, 'code', 'my-project-name');
63
+ const projectDirReal = await fs.realpath(projectDir);
64
+ expect(await fs.realpath(process.cwd())).toBe(projectDirReal);
65
+ expect(await fs.pathExists(projectDirReal)).toBe(true);
66
+
67
+ const { initRepo } = require('../src/commands/repo');
68
+ await initRepo({ location: 'inside' });
69
+
70
+ const vcmDir = path.join(projectDirReal, '.vibecodingmachine');
71
+ expect(await fs.pathExists(vcmDir)).toBe(true);
72
+
73
+ const requirementsPath = path.join(vcmDir, 'REQUIREMENTS.md');
74
+ expect(await fs.pathExists(requirementsPath)).toBe(true);
75
+ });
76
+ });