vibecodingmachine-cli 1.0.5 → 1.0.6

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.
Files changed (37) hide show
  1. package/.allnightai/REQUIREMENTS.md +11 -11
  2. package/.allnightai/temp/auto-status.json +6 -0
  3. package/.env +7 -0
  4. package/.eslintrc.js +16 -16
  5. package/README.md +85 -85
  6. package/bin/vibecodingmachine.js +274 -274
  7. package/jest.config.js +8 -8
  8. package/logs/audit/2025-11-07.jsonl +2 -2
  9. package/package.json +62 -62
  10. package/scripts/README.md +128 -128
  11. package/scripts/auto-start-wrapper.sh +92 -92
  12. package/scripts/postinstall.js +81 -81
  13. package/src/commands/auth.js +96 -96
  14. package/src/commands/auto-direct.js +1748 -1748
  15. package/src/commands/auto.js +4692 -4692
  16. package/src/commands/auto.js.bak +710 -710
  17. package/src/commands/ide.js +70 -70
  18. package/src/commands/repo.js +159 -159
  19. package/src/commands/requirements.js +161 -161
  20. package/src/commands/setup.js +91 -91
  21. package/src/commands/status.js +88 -88
  22. package/src/index.js +5 -5
  23. package/src/utils/auth.js +571 -577
  24. package/src/utils/auto-mode-ansi-ui.js +238 -238
  25. package/src/utils/auto-mode-simple-ui.js +161 -161
  26. package/src/utils/auto-mode-ui.js.bak.blessed +207 -207
  27. package/src/utils/auto-mode.js +65 -65
  28. package/src/utils/config.js +64 -64
  29. package/src/utils/interactive.js +3616 -3616
  30. package/src/utils/keyboard-handler.js +153 -152
  31. package/src/utils/logger.js +4 -4
  32. package/src/utils/persistent-header.js +116 -116
  33. package/src/utils/provider-registry.js +128 -128
  34. package/src/utils/status-card.js +120 -120
  35. package/src/utils/stdout-interceptor.js +127 -127
  36. package/tests/auto-mode.test.js +37 -37
  37. package/tests/config.test.js +34 -34
@@ -1,161 +1,161 @@
1
- const path = require('path');
2
- const fs = require('fs-extra');
3
- const chalk = require('chalk');
4
- const chokidar = require('chokidar');
5
- const { getRepoPath } = require('../utils/config');
6
- const { getRequirementsPath } = require('vibecodingmachine-core');
7
-
8
- async function getReqPathOrExit() {
9
- const repoPath = await getRepoPath();
10
- if (!repoPath) {
11
- console.log(chalk.yellow('No repository path configured'));
12
- console.log(chalk.gray('Use'), chalk.cyan('vcm repo:init'), chalk.gray('or'), chalk.cyan('vcm repo:set <path>'));
13
- process.exit(1);
14
- }
15
- // Use getRequirementsPath which handles hostname-specific files
16
- const reqPath = await getRequirementsPath(repoPath);
17
- return { repoPath, reqPath };
18
- }
19
-
20
- async function list(options) {
21
- try {
22
- const { reqPath } = await getReqPathOrExit();
23
- if (!await fs.pathExists(reqPath)) {
24
- console.log(chalk.yellow('No REQUIREMENTS.md found.'));
25
- return;
26
- }
27
- const content = await fs.readFile(reqPath, 'utf8');
28
- const lines = content.split('\n');
29
- const filter = options && options.status ? String(options.status).toLowerCase() : null;
30
- for (const line of lines) {
31
- if (line.startsWith('### ') || line.startsWith('## ')) {
32
- if (!filter || line.toLowerCase().includes(filter)) {
33
- console.log(line);
34
- }
35
- }
36
- }
37
- } catch (error) {
38
- console.error(chalk.red('Error listing requirements:'), error.message);
39
- process.exit(1);
40
- }
41
- }
42
-
43
- async function add(name) {
44
- try {
45
- const { reqPath } = await getReqPathOrExit();
46
- await fs.ensureFile(reqPath);
47
- let content = await fs.readFile(reqPath, 'utf8').catch(() => '');
48
-
49
- // Find the TODO section
50
- const todoSectionHeader = '## ⏳ Requirements not yet completed';
51
- if (!content.includes(todoSectionHeader)) {
52
- content += '\n\n' + todoSectionHeader + '\n';
53
- }
54
-
55
- // Insert at the top of the TODO section (right after the header)
56
- const lines = content.split('\n');
57
- const newLines = [];
58
- let inserted = false;
59
-
60
- for (let i = 0; i < lines.length; i++) {
61
- newLines.push(lines[i]);
62
-
63
- // Insert right after the TODO section header (new header format)
64
- if (!inserted && lines[i].includes(todoSectionHeader)) {
65
- // Add requirement header
66
- newLines.push(`### ${name}`);
67
- // Add blank line after requirement
68
- newLines.push('');
69
- inserted = true;
70
- }
71
- }
72
-
73
- content = newLines.join('\n');
74
- await fs.writeFile(reqPath, content);
75
- console.log(chalk.green('✓ Requirement added'));
76
- } catch (error) {
77
- console.error(chalk.red('Error adding requirement:'), error.message);
78
- process.exit(1);
79
- }
80
- }
81
-
82
- async function current() {
83
- try {
84
- const { reqPath } = await getReqPathOrExit();
85
- if (!await fs.pathExists(reqPath)) {
86
- console.log(chalk.yellow('No REQUIREMENTS.md found.'));
87
- return;
88
- }
89
- const content = await fs.readFile(reqPath, 'utf8');
90
- const match = content.match(/## \uD83D\uDEA6 Current Status\n([A-Z_]+)/);
91
- console.log(chalk.cyan(match ? match[1] : 'UNKNOWN'));
92
- } catch (error) {
93
- console.error(chalk.red('Error reading current status:'), error.message);
94
- process.exit(1);
95
- }
96
- }
97
-
98
- async function next() {
99
- try {
100
- const { reqPath } = await getReqPathOrExit();
101
- if (!await fs.pathExists(reqPath)) {
102
- console.log(chalk.yellow('No REQUIREMENTS.md found.'));
103
- return;
104
- }
105
- const content = await fs.readFile(reqPath, 'utf8');
106
- const order = ['PREPARE', 'ACT', 'CLEAN UP', 'VERIFY', 'DONE'];
107
- const currentMatch = content.match(/## \uD83D\uDEA6 Current Status\n([A-Z_ ]+)/);
108
- const current = currentMatch ? currentMatch[1] : 'PREPARE';
109
- const idx = Math.min(order.indexOf(current) + 1, order.length - 1);
110
- const nextStatus = order[idx];
111
- const updated = content.replace(/(## \uD83D\uDEA6 Current Status\n)([A-Z_ ]+)/, `$1${nextStatus}`);
112
- await fs.writeFile(reqPath, updated);
113
- console.log(chalk.green('✓ Moved to next status:'), chalk.cyan(nextStatus));
114
- } catch (error) {
115
- console.error(chalk.red('Error updating status:'), error.message);
116
- process.exit(1);
117
- }
118
- }
119
-
120
- async function edit() {
121
- try {
122
- const { reqPath } = await getReqPathOrExit();
123
- const opener = process.env.EDITOR ? null : 'open';
124
- if (process.env.EDITOR) {
125
- const { spawn } = require('child_process');
126
- const child = spawn(process.env.EDITOR, [reqPath], { stdio: 'inherit' });
127
- child.on('exit', (code) => process.exit(code || 0));
128
- } else {
129
- const { execSync } = require('child_process');
130
- execSync(`${opener} ${JSON.stringify(reqPath)}`);
131
- }
132
- } catch (error) {
133
- console.error(chalk.red('Error opening file:'), error.message);
134
- process.exit(1);
135
- }
136
- }
137
-
138
- async function watch() {
139
- try {
140
- const { reqPath } = await getReqPathOrExit();
141
- console.log(chalk.gray('Watching:'), chalk.cyan(reqPath));
142
- chokidar.watch(reqPath, { ignoreInitial: true })
143
- .on('change', () => console.log(chalk.green('✓ REQUIREMENTS.md changed')))
144
- .on('error', (err) => console.error(chalk.red('Watcher error:'), err.message));
145
- } catch (error) {
146
- console.error(chalk.red('Error watching requirements:'), error.message);
147
- process.exit(1);
148
- }
149
- }
150
-
151
- module.exports = {
152
- list,
153
- add,
154
- current,
155
- next,
156
- edit,
157
- watch
158
- };
159
-
160
-
161
-
1
+ const path = require('path');
2
+ const fs = require('fs-extra');
3
+ const chalk = require('chalk');
4
+ const chokidar = require('chokidar');
5
+ const { getRepoPath } = require('../utils/config');
6
+ const { getRequirementsPath } = require('vibecodingmachine-core');
7
+
8
+ async function getReqPathOrExit() {
9
+ const repoPath = await getRepoPath();
10
+ if (!repoPath) {
11
+ console.log(chalk.yellow('No repository path configured'));
12
+ console.log(chalk.gray('Use'), chalk.cyan('vcm repo:init'), chalk.gray('or'), chalk.cyan('vcm repo:set <path>'));
13
+ process.exit(1);
14
+ }
15
+ // Use getRequirementsPath which handles hostname-specific files
16
+ const reqPath = await getRequirementsPath(repoPath);
17
+ return { repoPath, reqPath };
18
+ }
19
+
20
+ async function list(options) {
21
+ try {
22
+ const { reqPath } = await getReqPathOrExit();
23
+ if (!await fs.pathExists(reqPath)) {
24
+ console.log(chalk.yellow('No REQUIREMENTS.md found.'));
25
+ return;
26
+ }
27
+ const content = await fs.readFile(reqPath, 'utf8');
28
+ const lines = content.split('\n');
29
+ const filter = options && options.status ? String(options.status).toLowerCase() : null;
30
+ for (const line of lines) {
31
+ if (line.startsWith('### ') || line.startsWith('## ')) {
32
+ if (!filter || line.toLowerCase().includes(filter)) {
33
+ console.log(line);
34
+ }
35
+ }
36
+ }
37
+ } catch (error) {
38
+ console.error(chalk.red('Error listing requirements:'), error.message);
39
+ process.exit(1);
40
+ }
41
+ }
42
+
43
+ async function add(name) {
44
+ try {
45
+ const { reqPath } = await getReqPathOrExit();
46
+ await fs.ensureFile(reqPath);
47
+ let content = await fs.readFile(reqPath, 'utf8').catch(() => '');
48
+
49
+ // Find the TODO section
50
+ const todoSectionHeader = '## ⏳ Requirements not yet completed';
51
+ if (!content.includes(todoSectionHeader)) {
52
+ content += '\n\n' + todoSectionHeader + '\n';
53
+ }
54
+
55
+ // Insert at the top of the TODO section (right after the header)
56
+ const lines = content.split('\n');
57
+ const newLines = [];
58
+ let inserted = false;
59
+
60
+ for (let i = 0; i < lines.length; i++) {
61
+ newLines.push(lines[i]);
62
+
63
+ // Insert right after the TODO section header (new header format)
64
+ if (!inserted && lines[i].includes(todoSectionHeader)) {
65
+ // Add requirement header
66
+ newLines.push(`### ${name}`);
67
+ // Add blank line after requirement
68
+ newLines.push('');
69
+ inserted = true;
70
+ }
71
+ }
72
+
73
+ content = newLines.join('\n');
74
+ await fs.writeFile(reqPath, content);
75
+ console.log(chalk.green('✓ Requirement added'));
76
+ } catch (error) {
77
+ console.error(chalk.red('Error adding requirement:'), error.message);
78
+ process.exit(1);
79
+ }
80
+ }
81
+
82
+ async function current() {
83
+ try {
84
+ const { reqPath } = await getReqPathOrExit();
85
+ if (!await fs.pathExists(reqPath)) {
86
+ console.log(chalk.yellow('No REQUIREMENTS.md found.'));
87
+ return;
88
+ }
89
+ const content = await fs.readFile(reqPath, 'utf8');
90
+ const match = content.match(/## \uD83D\uDEA6 Current Status\n([A-Z_]+)/);
91
+ console.log(chalk.cyan(match ? match[1] : 'UNKNOWN'));
92
+ } catch (error) {
93
+ console.error(chalk.red('Error reading current status:'), error.message);
94
+ process.exit(1);
95
+ }
96
+ }
97
+
98
+ async function next() {
99
+ try {
100
+ const { reqPath } = await getReqPathOrExit();
101
+ if (!await fs.pathExists(reqPath)) {
102
+ console.log(chalk.yellow('No REQUIREMENTS.md found.'));
103
+ return;
104
+ }
105
+ const content = await fs.readFile(reqPath, 'utf8');
106
+ const order = ['PREPARE', 'ACT', 'CLEAN UP', 'VERIFY', 'DONE'];
107
+ const currentMatch = content.match(/## \uD83D\uDEA6 Current Status\n([A-Z_ ]+)/);
108
+ const current = currentMatch ? currentMatch[1] : 'PREPARE';
109
+ const idx = Math.min(order.indexOf(current) + 1, order.length - 1);
110
+ const nextStatus = order[idx];
111
+ const updated = content.replace(/(## \uD83D\uDEA6 Current Status\n)([A-Z_ ]+)/, `$1${nextStatus}`);
112
+ await fs.writeFile(reqPath, updated);
113
+ console.log(chalk.green('✓ Moved to next status:'), chalk.cyan(nextStatus));
114
+ } catch (error) {
115
+ console.error(chalk.red('Error updating status:'), error.message);
116
+ process.exit(1);
117
+ }
118
+ }
119
+
120
+ async function edit() {
121
+ try {
122
+ const { reqPath } = await getReqPathOrExit();
123
+ const opener = process.env.EDITOR ? null : 'open';
124
+ if (process.env.EDITOR) {
125
+ const { spawn } = require('child_process');
126
+ const child = spawn(process.env.EDITOR, [reqPath], { stdio: 'inherit' });
127
+ child.on('exit', (code) => process.exit(code || 0));
128
+ } else {
129
+ const { execSync } = require('child_process');
130
+ execSync(`${opener} ${JSON.stringify(reqPath)}`);
131
+ }
132
+ } catch (error) {
133
+ console.error(chalk.red('Error opening file:'), error.message);
134
+ process.exit(1);
135
+ }
136
+ }
137
+
138
+ async function watch() {
139
+ try {
140
+ const { reqPath } = await getReqPathOrExit();
141
+ console.log(chalk.gray('Watching:'), chalk.cyan(reqPath));
142
+ chokidar.watch(reqPath, { ignoreInitial: true })
143
+ .on('change', () => console.log(chalk.green('✓ REQUIREMENTS.md changed')))
144
+ .on('error', (err) => console.error(chalk.red('Watcher error:'), err.message));
145
+ } catch (error) {
146
+ console.error(chalk.red('Error watching requirements:'), error.message);
147
+ process.exit(1);
148
+ }
149
+ }
150
+
151
+ module.exports = {
152
+ list,
153
+ add,
154
+ current,
155
+ next,
156
+ edit,
157
+ watch
158
+ };
159
+
160
+
161
+
@@ -1,91 +1,91 @@
1
- const fs = require('fs');
2
- const path = require('path');
3
- const os = require('os');
4
- const chalk = require('chalk');
5
- const inquirer = require('inquirer');
6
-
7
- async function setupAlias() {
8
- console.log(chalk.bold.cyan('\n🛠️ Setup Vibe Coding Machine Alias\n'));
9
-
10
- // Detect shell
11
- const shell = process.env.SHELL;
12
- let configFile = '';
13
- let shellName = '';
14
-
15
- if (shell.includes('zsh')) {
16
- shellName = 'zsh';
17
- configFile = path.join(os.homedir(), '.zshrc');
18
- } else if (shell.includes('bash')) {
19
- shellName = 'bash';
20
- configFile = path.join(os.homedir(), '.bashrc');
21
- // On Mac, .bash_profile is often used instead of .bashrc for login shells
22
- if (process.platform === 'darwin' && !fs.existsSync(configFile)) {
23
- const profile = path.join(os.homedir(), '.bash_profile');
24
- if (fs.existsSync(profile)) {
25
- configFile = profile;
26
- }
27
- }
28
- } else if (shell.includes('fish')) {
29
- shellName = 'fish';
30
- configFile = path.join(os.homedir(), '.config', 'fish', 'config.fish');
31
- } else {
32
- console.log(chalk.yellow(`⚠️ Could not detect supported shell (zsh, bash, fish). Current shell: ${shell}`));
33
- console.log(chalk.gray('You can manually add the alias:\n'));
34
- console.log(chalk.cyan(' alias vcm="vibecodingmachine"'));
35
- return;
36
- }
37
-
38
- console.log(chalk.gray(`Detected shell: ${chalk.cyan(shellName)}`));
39
- console.log(chalk.gray(`Config file: ${chalk.cyan(configFile)}`));
40
-
41
- // Check if config file exists
42
- if (!fs.existsSync(configFile)) {
43
- // For fish, ensure directory exists
44
- if (shellName === 'fish') {
45
- const configDir = path.dirname(configFile);
46
- if (!fs.existsSync(configDir)) {
47
- fs.mkdirSync(configDir, { recursive: true });
48
- }
49
- }
50
- // Create empty file if it doesn't exist
51
- fs.writeFileSync(configFile, '', 'utf8');
52
- }
53
-
54
- // Read config file
55
- let content = fs.readFileSync(configFile, 'utf8');
56
-
57
- // Check if alias already exists
58
- if (content.includes('alias vcm="vibecodingmachine"') || content.includes("alias vcm='vibecodingmachine'")) {
59
- console.log(chalk.green('\n✓ "vcm" alias is already configured!'));
60
- return;
61
- }
62
-
63
- // Confirm with user
64
- const { confirm } = await inquirer.prompt([
65
- {
66
- type: 'confirm',
67
- name: 'confirm',
68
- message: `Add 'vcm' alias to ${path.basename(configFile)}?`,
69
- default: true
70
- }
71
- ]);
72
-
73
- if (!confirm) {
74
- console.log(chalk.yellow('\nCancelled.'));
75
- return;
76
- }
77
-
78
- // Add alias
79
- const aliasCommand = '\n# Vibe Coding Machine Alias\nalias vcm="vibecodingmachine"\n';
80
-
81
- try {
82
- fs.appendFileSync(configFile, aliasCommand, 'utf8');
83
- console.log(chalk.green(`\n✓ Added alias to ${path.basename(configFile)}`));
84
- console.log(chalk.gray('\nYou may need to restart your terminal or run:'));
85
- console.log(chalk.cyan(` source ${configFile}`));
86
- } catch (error) {
87
- console.log(chalk.red(`\n✗ Error writing to config file: ${error.message}`));
88
- }
89
- }
90
-
91
- module.exports = { setupAlias };
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const os = require('os');
4
+ const chalk = require('chalk');
5
+ const inquirer = require('inquirer');
6
+
7
+ async function setupAlias() {
8
+ console.log(chalk.bold.cyan('\n🛠️ Setup Vibe Coding Machine Alias\n'));
9
+
10
+ // Detect shell
11
+ const shell = process.env.SHELL;
12
+ let configFile = '';
13
+ let shellName = '';
14
+
15
+ if (shell.includes('zsh')) {
16
+ shellName = 'zsh';
17
+ configFile = path.join(os.homedir(), '.zshrc');
18
+ } else if (shell.includes('bash')) {
19
+ shellName = 'bash';
20
+ configFile = path.join(os.homedir(), '.bashrc');
21
+ // On Mac, .bash_profile is often used instead of .bashrc for login shells
22
+ if (process.platform === 'darwin' && !fs.existsSync(configFile)) {
23
+ const profile = path.join(os.homedir(), '.bash_profile');
24
+ if (fs.existsSync(profile)) {
25
+ configFile = profile;
26
+ }
27
+ }
28
+ } else if (shell.includes('fish')) {
29
+ shellName = 'fish';
30
+ configFile = path.join(os.homedir(), '.config', 'fish', 'config.fish');
31
+ } else {
32
+ console.log(chalk.yellow(`⚠️ Could not detect supported shell (zsh, bash, fish). Current shell: ${shell}`));
33
+ console.log(chalk.gray('You can manually add the alias:\n'));
34
+ console.log(chalk.cyan(' alias vcm="vibecodingmachine"'));
35
+ return;
36
+ }
37
+
38
+ console.log(chalk.gray(`Detected shell: ${chalk.cyan(shellName)}`));
39
+ console.log(chalk.gray(`Config file: ${chalk.cyan(configFile)}`));
40
+
41
+ // Check if config file exists
42
+ if (!fs.existsSync(configFile)) {
43
+ // For fish, ensure directory exists
44
+ if (shellName === 'fish') {
45
+ const configDir = path.dirname(configFile);
46
+ if (!fs.existsSync(configDir)) {
47
+ fs.mkdirSync(configDir, { recursive: true });
48
+ }
49
+ }
50
+ // Create empty file if it doesn't exist
51
+ fs.writeFileSync(configFile, '', 'utf8');
52
+ }
53
+
54
+ // Read config file
55
+ let content = fs.readFileSync(configFile, 'utf8');
56
+
57
+ // Check if alias already exists
58
+ if (content.includes('alias vcm="vibecodingmachine"') || content.includes("alias vcm='vibecodingmachine'")) {
59
+ console.log(chalk.green('\n✓ "vcm" alias is already configured!'));
60
+ return;
61
+ }
62
+
63
+ // Confirm with user
64
+ const { confirm } = await inquirer.prompt([
65
+ {
66
+ type: 'confirm',
67
+ name: 'confirm',
68
+ message: `Add 'vcm' alias to ${path.basename(configFile)}?`,
69
+ default: true
70
+ }
71
+ ]);
72
+
73
+ if (!confirm) {
74
+ console.log(chalk.yellow('\nCancelled.'));
75
+ return;
76
+ }
77
+
78
+ // Add alias
79
+ const aliasCommand = '\n# Vibe Coding Machine Alias\nalias vcm="vibecodingmachine"\n';
80
+
81
+ try {
82
+ fs.appendFileSync(configFile, aliasCommand, 'utf8');
83
+ console.log(chalk.green(`\n✓ Added alias to ${path.basename(configFile)}`));
84
+ console.log(chalk.gray('\nYou may need to restart your terminal or run:'));
85
+ console.log(chalk.cyan(` source ${configFile}`));
86
+ } catch (error) {
87
+ console.log(chalk.red(`\n✗ Error writing to config file: ${error.message}`));
88
+ }
89
+ }
90
+
91
+ module.exports = { setupAlias };