vibecodingmachine-cli 1.0.4 → 1.0.5

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/.eslintrc.js +16 -16
  3. package/README.md +85 -85
  4. package/bin/vibecodingmachine.js +274 -274
  5. package/jest.config.js +8 -8
  6. package/logs/audit/2025-11-07.jsonl +2 -2
  7. package/package.json +62 -66
  8. package/scripts/README.md +128 -128
  9. package/scripts/auto-start-wrapper.sh +92 -92
  10. package/scripts/postinstall.js +81 -81
  11. package/src/commands/auth.js +96 -96
  12. package/src/commands/auto-direct.js +1748 -1748
  13. package/src/commands/auto.js +4692 -4692
  14. package/src/commands/auto.js.bak +710 -710
  15. package/src/commands/ide.js +70 -70
  16. package/src/commands/repo.js +159 -159
  17. package/src/commands/requirements.js +161 -161
  18. package/src/commands/setup.js +91 -91
  19. package/src/commands/status.js +88 -88
  20. package/src/index.js +5 -5
  21. package/src/utils/auth.js +577 -577
  22. package/src/utils/auto-mode-ansi-ui.js +238 -238
  23. package/src/utils/auto-mode-simple-ui.js +161 -161
  24. package/src/utils/auto-mode-ui.js.bak.blessed +207 -207
  25. package/src/utils/auto-mode.js +65 -65
  26. package/src/utils/config.js +64 -64
  27. package/src/utils/interactive.js +3616 -3616
  28. package/src/utils/keyboard-handler.js +152 -152
  29. package/src/utils/logger.js +4 -4
  30. package/src/utils/persistent-header.js +116 -116
  31. package/src/utils/provider-registry.js +128 -128
  32. package/src/utils/status-card.js +120 -120
  33. package/src/utils/stdout-interceptor.js +127 -127
  34. package/tests/auto-mode.test.js +37 -37
  35. package/tests/config.test.js +34 -34
  36. package/.allnightai/temp/auto-status.json +0 -6
  37. package/.env +0 -7
@@ -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 };