@codebakers/cli 3.8.2 → 3.8.3
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/dist/commands/init.d.ts +0 -3
- package/dist/commands/init.js +578 -550
- package/dist/commands/install.js +14 -15
- package/dist/commands/upgrade.d.ts +1 -1
- package/dist/commands/upgrade.js +57 -313
- package/dist/index.js +7 -151
- package/package.json +1 -1
- package/src/commands/init.ts +606 -559
- package/src/commands/install.ts +14 -15
- package/src/commands/upgrade.ts +60 -369
- package/src/index.ts +7 -185
package/dist/commands/install.js
CHANGED
|
@@ -10,8 +10,8 @@ const fs_1 = require("fs");
|
|
|
10
10
|
const path_1 = require("path");
|
|
11
11
|
const config_js_1 = require("../config.js");
|
|
12
12
|
const api_js_1 = require("../lib/api.js");
|
|
13
|
-
//
|
|
14
|
-
const
|
|
13
|
+
// Bootstrap files - patterns come from server via MCP
|
|
14
|
+
const CLAUDE_MD_BOOTSTRAP = `# CodeBakers
|
|
15
15
|
|
|
16
16
|
**MANDATORY: Before writing ANY code, call the \`discover_patterns\` MCP tool.**
|
|
17
17
|
|
|
@@ -25,7 +25,7 @@ The server will return:
|
|
|
25
25
|
|
|
26
26
|
**You cannot write code without calling this tool first. The server tracks compliance.**
|
|
27
27
|
`;
|
|
28
|
-
const
|
|
28
|
+
const CURSORRULES_BOOTSTRAP = `# CodeBakers
|
|
29
29
|
|
|
30
30
|
**MANDATORY: Before writing ANY code, call the \`discover_patterns\` MCP tool.**
|
|
31
31
|
|
|
@@ -40,26 +40,26 @@ The server will return:
|
|
|
40
40
|
**You cannot write code without calling this tool first. The server tracks compliance.**
|
|
41
41
|
`;
|
|
42
42
|
async function install() {
|
|
43
|
-
console.log(chalk_1.default.blue('\n CodeBakers Install
|
|
43
|
+
console.log(chalk_1.default.blue('\n CodeBakers Install\n'));
|
|
44
44
|
const apiKey = (0, config_js_1.getApiKey)();
|
|
45
45
|
if (!apiKey) {
|
|
46
46
|
console.log(chalk_1.default.red(' Not logged in. Run `codebakers login` first.\n'));
|
|
47
47
|
process.exit(1);
|
|
48
48
|
}
|
|
49
|
-
const spinner = (0, ora_1.default)('Installing CodeBakers
|
|
49
|
+
const spinner = (0, ora_1.default)('Installing CodeBakers...').start();
|
|
50
50
|
try {
|
|
51
51
|
const cwd = process.cwd();
|
|
52
52
|
const claudeMdPath = (0, path_1.join)(cwd, 'CLAUDE.md');
|
|
53
53
|
const cursorRulesPath = (0, path_1.join)(cwd, '.cursorrules');
|
|
54
54
|
const claudeDir = (0, path_1.join)(cwd, '.claude');
|
|
55
|
-
//
|
|
55
|
+
// Remove old .claude folder if it exists (patterns now server-side)
|
|
56
56
|
if ((0, fs_1.existsSync)(claudeDir)) {
|
|
57
|
-
spinner.text = '
|
|
57
|
+
spinner.text = 'Removing old pattern files...';
|
|
58
58
|
(0, fs_1.rmSync)(claudeDir, { recursive: true, force: true });
|
|
59
59
|
}
|
|
60
|
-
// Write
|
|
61
|
-
(0, fs_1.writeFileSync)(claudeMdPath,
|
|
62
|
-
(0, fs_1.writeFileSync)(cursorRulesPath,
|
|
60
|
+
// Write bootstrap files
|
|
61
|
+
(0, fs_1.writeFileSync)(claudeMdPath, CLAUDE_MD_BOOTSTRAP);
|
|
62
|
+
(0, fs_1.writeFileSync)(cursorRulesPath, CURSORRULES_BOOTSTRAP);
|
|
63
63
|
// Add .cursorrules to .gitignore if not present
|
|
64
64
|
const gitignorePath = (0, path_1.join)(cwd, '.gitignore');
|
|
65
65
|
if ((0, fs_1.existsSync)(gitignorePath)) {
|
|
@@ -69,15 +69,14 @@ async function install() {
|
|
|
69
69
|
(0, fs_1.writeFileSync)(gitignorePath, gitignore + additions);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
|
-
spinner.succeed('CodeBakers
|
|
72
|
+
spinner.succeed('CodeBakers installed!');
|
|
73
73
|
console.log(chalk_1.default.gray('\n Files created:'));
|
|
74
74
|
console.log(chalk_1.default.gray(' - CLAUDE.md (Claude Code gateway)'));
|
|
75
75
|
console.log(chalk_1.default.gray(' - .cursorrules (Cursor IDE gateway)'));
|
|
76
|
-
console.log(chalk_1.default.cyan('\n
|
|
77
|
-
console.log(chalk_1.default.gray(' - Patterns are
|
|
76
|
+
console.log(chalk_1.default.cyan('\n How it works:'));
|
|
77
|
+
console.log(chalk_1.default.gray(' - Patterns are fetched from server in real-time'));
|
|
78
78
|
console.log(chalk_1.default.gray(' - AI calls discover_patterns before coding'));
|
|
79
|
-
console.log(chalk_1.default.gray(' -
|
|
80
|
-
console.log(chalk_1.default.gray(' - Usage tracking & compliance'));
|
|
79
|
+
console.log(chalk_1.default.gray(' - Always up-to-date, no manual updates needed'));
|
|
81
80
|
console.log(chalk_1.default.gray(`\n CLI version: ${(0, api_js_1.getCliVersion)()}`));
|
|
82
81
|
console.log(chalk_1.default.blue('\n Start building! AI will fetch patterns via MCP.\n'));
|
|
83
82
|
}
|
package/dist/commands/upgrade.js
CHANGED
|
@@ -10,75 +10,8 @@ const fs_1 = require("fs");
|
|
|
10
10
|
const path_1 = require("path");
|
|
11
11
|
const config_js_1 = require("../config.js");
|
|
12
12
|
const api_js_1 = require("../lib/api.js");
|
|
13
|
-
//
|
|
14
|
-
const
|
|
15
|
-
# CodeBakers Pre-Commit Hook - Session Enforcement
|
|
16
|
-
# Blocks commits unless AI called discover_patterns and validate_complete
|
|
17
|
-
node "$(dirname "$0")/validate-session.js"
|
|
18
|
-
exit $?
|
|
19
|
-
`;
|
|
20
|
-
const VALIDATE_SESSION_SCRIPT = `#!/usr/bin/env node
|
|
21
|
-
const fs = require('fs');
|
|
22
|
-
const path = require('path');
|
|
23
|
-
const RED = '\\x1b[31m', GREEN = '\\x1b[32m', YELLOW = '\\x1b[33m', CYAN = '\\x1b[36m', RESET = '\\x1b[0m';
|
|
24
|
-
function log(c, m) { console.log(c + m + RESET); }
|
|
25
|
-
|
|
26
|
-
async function validate() {
|
|
27
|
-
const stateFile = path.join(process.cwd(), '.codebakers.json');
|
|
28
|
-
if (!fs.existsSync(stateFile)) return { valid: true, reason: 'not-codebakers' };
|
|
29
|
-
|
|
30
|
-
let state;
|
|
31
|
-
try { state = JSON.parse(fs.readFileSync(stateFile, 'utf-8')); }
|
|
32
|
-
catch { return { valid: false, reason: 'invalid-state' }; }
|
|
33
|
-
|
|
34
|
-
if (!state.serverEnforced) return { valid: true, reason: 'legacy' };
|
|
35
|
-
|
|
36
|
-
const v = state.lastValidation;
|
|
37
|
-
if (!v) return { valid: false, reason: 'no-validation', msg: 'AI must call validate_complete before commit' };
|
|
38
|
-
if (!v.passed) return { valid: false, reason: 'failed', msg: 'Validation failed - fix issues first' };
|
|
39
|
-
|
|
40
|
-
const age = Date.now() - new Date(v.timestamp).getTime();
|
|
41
|
-
if (age > 30 * 60 * 1000) return { valid: false, reason: 'stale', msg: 'Validation expired - call validate_complete again' };
|
|
42
|
-
|
|
43
|
-
return { valid: true, reason: 'ok' };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async function main() {
|
|
47
|
-
console.log(''); log(CYAN, ' 🍪 CodeBakers Pre-Commit');
|
|
48
|
-
const r = await validate();
|
|
49
|
-
if (r.valid) { log(GREEN, ' ✓ Commit allowed'); console.log(''); process.exit(0); }
|
|
50
|
-
else { log(RED, ' ✗ Blocked: ' + r.reason); if (r.msg) log(YELLOW, ' ' + r.msg);
|
|
51
|
-
console.log(''); log(YELLOW, ' Bypass: git commit --no-verify'); console.log(''); process.exit(1); }
|
|
52
|
-
}
|
|
53
|
-
main().catch(e => { log(RED, ' Error: ' + e.message); process.exit(1); });
|
|
54
|
-
`;
|
|
55
|
-
/**
|
|
56
|
-
* Install pre-commit hook for session enforcement
|
|
57
|
-
*/
|
|
58
|
-
function installPrecommitHook(cwd) {
|
|
59
|
-
const gitDir = (0, path_1.join)(cwd, '.git');
|
|
60
|
-
if (!(0, fs_1.existsSync)(gitDir)) {
|
|
61
|
-
console.log(chalk_1.default.gray(' ⏭️ Skipping pre-commit hook (not a git repo)'));
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
const hooksDir = (0, path_1.join)(gitDir, 'hooks');
|
|
65
|
-
if (!(0, fs_1.existsSync)(hooksDir)) {
|
|
66
|
-
(0, fs_1.mkdirSync)(hooksDir, { recursive: true });
|
|
67
|
-
}
|
|
68
|
-
// Write pre-commit hook
|
|
69
|
-
const preCommitPath = (0, path_1.join)(hooksDir, 'pre-commit');
|
|
70
|
-
(0, fs_1.writeFileSync)(preCommitPath, PRE_COMMIT_SCRIPT);
|
|
71
|
-
try {
|
|
72
|
-
(0, fs_1.chmodSync)(preCommitPath, '755');
|
|
73
|
-
}
|
|
74
|
-
catch { /* Windows */ }
|
|
75
|
-
// Write validation script
|
|
76
|
-
const validatePath = (0, path_1.join)(hooksDir, 'validate-session.js');
|
|
77
|
-
(0, fs_1.writeFileSync)(validatePath, VALIDATE_SESSION_SCRIPT);
|
|
78
|
-
console.log(chalk_1.default.green(' ✓ Installed pre-commit hook (blocks commits without validation)'));
|
|
79
|
-
}
|
|
80
|
-
// Ultra-minimal CLAUDE.md for v6.0 - ALL instructions come from server
|
|
81
|
-
const MINIMAL_CLAUDE_MD = `# CodeBakers v6.0
|
|
13
|
+
// Bootstrap files - patterns come from server via MCP
|
|
14
|
+
const CLAUDE_MD_BOOTSTRAP = `# CodeBakers
|
|
82
15
|
|
|
83
16
|
**MANDATORY: Before writing ANY code, call the \`discover_patterns\` MCP tool.**
|
|
84
17
|
|
|
@@ -93,12 +26,8 @@ The server will return:
|
|
|
93
26
|
- Validation instructions
|
|
94
27
|
|
|
95
28
|
**You cannot write code without calling this tool first. The server tracks compliance.**
|
|
96
|
-
|
|
97
|
-
---
|
|
98
|
-
*CodeBakers v6.0 - Server-Enforced*
|
|
99
29
|
`;
|
|
100
|
-
|
|
101
|
-
const MINIMAL_CURSORRULES = `# CodeBakers v6.0
|
|
30
|
+
const CURSORRULES_BOOTSTRAP = `# CodeBakers
|
|
102
31
|
|
|
103
32
|
MANDATORY: Before writing ANY code, call the discover_patterns MCP tool.
|
|
104
33
|
|
|
@@ -109,128 +38,46 @@ The server returns all patterns, rules, and test requirements.
|
|
|
109
38
|
You cannot write code without calling this tool first.
|
|
110
39
|
`;
|
|
111
40
|
/**
|
|
112
|
-
*
|
|
113
|
-
*/
|
|
114
|
-
function isVersionLessThan(v1, v2) {
|
|
115
|
-
const parts1 = v1.split('.').map(Number);
|
|
116
|
-
const parts2 = v2.split('.').map(Number);
|
|
117
|
-
for (let i = 0; i < 3; i++) {
|
|
118
|
-
const p1 = parts1[i] || 0;
|
|
119
|
-
const p2 = parts2[i] || 0;
|
|
120
|
-
if (p1 < p2)
|
|
121
|
-
return true;
|
|
122
|
-
if (p1 > p2)
|
|
123
|
-
return false;
|
|
124
|
-
}
|
|
125
|
-
return false;
|
|
126
|
-
}
|
|
127
|
-
/**
|
|
128
|
-
* Confirm download to server (non-blocking, fire-and-forget)
|
|
129
|
-
*/
|
|
130
|
-
async function confirmDownload(apiUrl, apiKey, data) {
|
|
131
|
-
try {
|
|
132
|
-
await fetch(`${apiUrl}/api/content/confirm`, {
|
|
133
|
-
method: 'POST',
|
|
134
|
-
headers: {
|
|
135
|
-
'Content-Type': 'application/json',
|
|
136
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
137
|
-
},
|
|
138
|
-
body: JSON.stringify(data),
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
catch {
|
|
142
|
-
// Silently ignore - this is just for analytics
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Get current installed version from .claude/.version.json
|
|
41
|
+
* Check if project is using server-enforced mode
|
|
147
42
|
*/
|
|
148
|
-
function
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
return data.version || null;
|
|
155
|
-
}
|
|
156
|
-
if ((0, fs_1.existsSync)(codebakersFile)) {
|
|
157
|
-
const data = JSON.parse((0, fs_1.readFileSync)(codebakersFile, 'utf-8'));
|
|
158
|
-
return data.version || null;
|
|
43
|
+
function isServerEnforced(cwd) {
|
|
44
|
+
const stateFile = (0, path_1.join)(cwd, '.codebakers.json');
|
|
45
|
+
if ((0, fs_1.existsSync)(stateFile)) {
|
|
46
|
+
try {
|
|
47
|
+
const state = JSON.parse((0, fs_1.readFileSync)(stateFile, 'utf-8'));
|
|
48
|
+
return state.serverEnforced === true;
|
|
159
49
|
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
// Ignore errors
|
|
163
|
-
}
|
|
164
|
-
return null;
|
|
165
|
-
}
|
|
166
|
-
/**
|
|
167
|
-
* Backup old files before migration
|
|
168
|
-
*/
|
|
169
|
-
function backupOldFiles(cwd) {
|
|
170
|
-
const backupDir = (0, path_1.join)(cwd, '.codebakers', 'backup', new Date().toISOString().replace(/[:.]/g, '-'));
|
|
171
|
-
(0, fs_1.mkdirSync)(backupDir, { recursive: true });
|
|
172
|
-
// Backup CLAUDE.md
|
|
173
|
-
const claudeMd = (0, path_1.join)(cwd, 'CLAUDE.md');
|
|
174
|
-
if ((0, fs_1.existsSync)(claudeMd)) {
|
|
175
|
-
(0, fs_1.copyFileSync)(claudeMd, (0, path_1.join)(backupDir, 'CLAUDE.md'));
|
|
176
|
-
}
|
|
177
|
-
// Backup .cursorrules
|
|
178
|
-
const cursorrules = (0, path_1.join)(cwd, '.cursorrules');
|
|
179
|
-
if ((0, fs_1.existsSync)(cursorrules)) {
|
|
180
|
-
(0, fs_1.copyFileSync)(cursorrules, (0, path_1.join)(backupDir, '.cursorrules'));
|
|
181
|
-
}
|
|
182
|
-
// Backup .claude folder
|
|
183
|
-
const claudeDir = (0, path_1.join)(cwd, '.claude');
|
|
184
|
-
if ((0, fs_1.existsSync)(claudeDir)) {
|
|
185
|
-
const claudeBackup = (0, path_1.join)(backupDir, '.claude');
|
|
186
|
-
(0, fs_1.mkdirSync)(claudeBackup, { recursive: true });
|
|
187
|
-
const files = (0, fs_1.readdirSync)(claudeDir);
|
|
188
|
-
for (const file of files) {
|
|
189
|
-
const src = (0, path_1.join)(claudeDir, file);
|
|
190
|
-
const dest = (0, path_1.join)(claudeBackup, file);
|
|
191
|
-
try {
|
|
192
|
-
(0, fs_1.copyFileSync)(src, dest);
|
|
193
|
-
}
|
|
194
|
-
catch {
|
|
195
|
-
// Ignore copy errors
|
|
196
|
-
}
|
|
50
|
+
catch {
|
|
51
|
+
// Ignore parse errors
|
|
197
52
|
}
|
|
198
53
|
}
|
|
199
|
-
|
|
54
|
+
return false;
|
|
200
55
|
}
|
|
201
56
|
/**
|
|
202
|
-
* Migrate to
|
|
57
|
+
* Migrate project to server-enforced mode
|
|
203
58
|
*/
|
|
204
|
-
function
|
|
205
|
-
console.log(chalk_1.default.yellow('\n 📦
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
(0, fs_1.writeFileSync)(claudeMd, MINIMAL_CLAUDE_MD);
|
|
212
|
-
console.log(chalk_1.default.green(' ✓ Updated CLAUDE.md (minimal server-enforced version)'));
|
|
213
|
-
// Replace .cursorrules with minimal version
|
|
59
|
+
function migrateToServerEnforced(cwd) {
|
|
60
|
+
console.log(chalk_1.default.yellow('\n 📦 Upgrading to server-enforced patterns...\n'));
|
|
61
|
+
// Update CLAUDE.md
|
|
62
|
+
const claudeMdPath = (0, path_1.join)(cwd, 'CLAUDE.md');
|
|
63
|
+
(0, fs_1.writeFileSync)(claudeMdPath, CLAUDE_MD_BOOTSTRAP);
|
|
64
|
+
console.log(chalk_1.default.green(' ✓ Updated CLAUDE.md'));
|
|
65
|
+
// Update .cursorrules
|
|
214
66
|
const cursorrules = (0, path_1.join)(cwd, '.cursorrules');
|
|
215
|
-
(0, fs_1.writeFileSync)(cursorrules,
|
|
216
|
-
console.log(chalk_1.default.green(' ✓ Updated .cursorrules
|
|
217
|
-
//
|
|
67
|
+
(0, fs_1.writeFileSync)(cursorrules, CURSORRULES_BOOTSTRAP);
|
|
68
|
+
console.log(chalk_1.default.green(' ✓ Updated .cursorrules'));
|
|
69
|
+
// Remove old .claude folder if it exists (patterns now come from server)
|
|
218
70
|
const claudeDir = (0, path_1.join)(cwd, '.claude');
|
|
219
71
|
if ((0, fs_1.existsSync)(claudeDir)) {
|
|
220
72
|
try {
|
|
221
73
|
(0, fs_1.rmSync)(claudeDir, { recursive: true, force: true });
|
|
222
74
|
console.log(chalk_1.default.green(' ✓ Removed .claude/ folder (patterns now server-side)'));
|
|
223
75
|
}
|
|
224
|
-
catch
|
|
76
|
+
catch {
|
|
225
77
|
console.log(chalk_1.default.yellow(' ⚠️ Could not remove .claude/ folder - please delete manually'));
|
|
226
78
|
}
|
|
227
79
|
}
|
|
228
|
-
//
|
|
229
|
-
const codebakersDir = (0, path_1.join)(cwd, '.codebakers');
|
|
230
|
-
if (!(0, fs_1.existsSync)(codebakersDir)) {
|
|
231
|
-
(0, fs_1.mkdirSync)(codebakersDir, { recursive: true });
|
|
232
|
-
}
|
|
233
|
-
// Update version in .codebakers.json
|
|
80
|
+
// Update .codebakers.json
|
|
234
81
|
const stateFile = (0, path_1.join)(cwd, '.codebakers.json');
|
|
235
82
|
let state = {};
|
|
236
83
|
if ((0, fs_1.existsSync)(stateFile)) {
|
|
@@ -241,164 +88,61 @@ function migrateToV6(cwd) {
|
|
|
241
88
|
// Ignore errors
|
|
242
89
|
}
|
|
243
90
|
}
|
|
244
|
-
state.version = '6.0';
|
|
245
91
|
state.migratedAt = new Date().toISOString();
|
|
246
92
|
state.serverEnforced = true;
|
|
247
93
|
(0, fs_1.writeFileSync)(stateFile, JSON.stringify(state, null, 2));
|
|
248
|
-
|
|
249
|
-
installPrecommitHook(cwd);
|
|
250
|
-
console.log(chalk_1.default.green('\n ✅ Migration to v6.0 complete!\n'));
|
|
94
|
+
console.log(chalk_1.default.green('\n ✅ Upgrade complete!\n'));
|
|
251
95
|
console.log(chalk_1.default.cyan(' What changed:'));
|
|
252
96
|
console.log(chalk_1.default.gray(' - Patterns are now fetched from server in real-time'));
|
|
253
|
-
console.log(chalk_1.default.gray(' -
|
|
254
|
-
console.log(chalk_1.default.gray(' -
|
|
255
|
-
console.log(chalk_1.default.gray(' -
|
|
256
|
-
console.log(chalk_1.default.gray(' - No local pattern files needed\n'));
|
|
97
|
+
console.log(chalk_1.default.gray(' - AI calls discover_patterns before coding'));
|
|
98
|
+
console.log(chalk_1.default.gray(' - No local pattern files needed'));
|
|
99
|
+
console.log(chalk_1.default.gray(' - Always up-to-date patterns\n'));
|
|
257
100
|
}
|
|
258
101
|
/**
|
|
259
|
-
* Upgrade CodeBakers
|
|
102
|
+
* Upgrade CodeBakers - checks for CLI updates and ensures server-enforced setup
|
|
260
103
|
*/
|
|
261
104
|
async function upgrade() {
|
|
262
105
|
console.log(chalk_1.default.blue('\n CodeBakers Upgrade\n'));
|
|
263
106
|
const cwd = process.cwd();
|
|
264
107
|
const claudeMdPath = (0, path_1.join)(cwd, 'CLAUDE.md');
|
|
265
|
-
const claudeDir = (0, path_1.join)(cwd, '.claude');
|
|
266
108
|
const codebakersJson = (0, path_1.join)(cwd, '.codebakers.json');
|
|
267
109
|
// Check if this is a CodeBakers project
|
|
268
|
-
if (!(0, fs_1.existsSync)(claudeMdPath) && !(0, fs_1.existsSync)(
|
|
110
|
+
if (!(0, fs_1.existsSync)(claudeMdPath) && !(0, fs_1.existsSync)(codebakersJson)) {
|
|
269
111
|
console.log(chalk_1.default.yellow(' No CodeBakers installation found in this directory.\n'));
|
|
270
|
-
console.log(chalk_1.default.gray(' Run `codebakers
|
|
112
|
+
console.log(chalk_1.default.gray(' Run `codebakers init` to set up CodeBakers first.\n'));
|
|
271
113
|
return;
|
|
272
114
|
}
|
|
273
115
|
// Check for CLI updates
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
116
|
+
const spinner = (0, ora_1.default)('Checking for CLI updates...').start();
|
|
117
|
+
try {
|
|
118
|
+
const updateInfo = await (0, api_js_1.checkForUpdates)();
|
|
119
|
+
if (updateInfo?.updateAvailable) {
|
|
120
|
+
spinner.succeed('CLI update available!');
|
|
121
|
+
console.log(chalk_1.default.yellow(`\n ⚠️ New CLI version: ${updateInfo.currentVersion} → ${updateInfo.latestVersion}`));
|
|
122
|
+
console.log(chalk_1.default.cyan(' Run: npm install -g @codebakers/cli@latest\n'));
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
spinner.succeed(`CLI is up to date (v${(0, api_js_1.getCliVersion)()})`);
|
|
126
|
+
}
|
|
279
127
|
}
|
|
280
|
-
|
|
281
|
-
|
|
128
|
+
catch {
|
|
129
|
+
spinner.warn('Could not check for CLI updates');
|
|
282
130
|
}
|
|
283
131
|
// Check API key
|
|
284
132
|
const apiKey = (0, config_js_1.getApiKey)();
|
|
285
133
|
if (!apiKey) {
|
|
286
|
-
console.log(chalk_1.default.yellow(' Not logged in. Run `codebakers
|
|
287
|
-
return;
|
|
134
|
+
console.log(chalk_1.default.yellow('\n Not logged in. Run `codebakers login` to authenticate.\n'));
|
|
288
135
|
}
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
const spinner = (0, ora_1.default)('Checking server for latest version...').start();
|
|
292
|
-
try {
|
|
293
|
-
const apiUrl = (0, config_js_1.getApiUrl)();
|
|
294
|
-
// Check latest version from server
|
|
295
|
-
const versionResponse = await fetch(`${apiUrl}/api/content/version`, {
|
|
296
|
-
method: 'GET',
|
|
297
|
-
headers: {
|
|
298
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
299
|
-
},
|
|
300
|
-
});
|
|
301
|
-
if (!versionResponse.ok) {
|
|
302
|
-
throw new Error('Failed to check version');
|
|
303
|
-
}
|
|
304
|
-
const versionData = await versionResponse.json();
|
|
305
|
-
const latestVersion = versionData.version;
|
|
306
|
-
spinner.succeed(`Latest version: v${latestVersion}`);
|
|
307
|
-
// Check if we need to migrate to v6.0
|
|
308
|
-
const needsV6Migration = currentVersion && isVersionLessThan(currentVersion, '6.0') &&
|
|
309
|
-
!isVersionLessThan(latestVersion, '6.0');
|
|
310
|
-
if (needsV6Migration || (!currentVersion && !isVersionLessThan(latestVersion, '6.0'))) {
|
|
311
|
-
// Need to migrate to v6.0 server-enforced patterns
|
|
312
|
-
migrateToV6(cwd);
|
|
313
|
-
// Confirm migration to server
|
|
314
|
-
confirmDownload(apiUrl, apiKey, {
|
|
315
|
-
version: '6.0',
|
|
316
|
-
moduleCount: 0, // No local modules in v6
|
|
317
|
-
cliVersion: (0, api_js_1.getCliVersion)(),
|
|
318
|
-
command: 'upgrade-v6-migration',
|
|
319
|
-
}).catch(() => { });
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
// For v6.0+, just confirm the installation is up to date
|
|
323
|
-
const stateFile = (0, path_1.join)(cwd, '.codebakers.json');
|
|
324
|
-
let state = {};
|
|
325
|
-
if ((0, fs_1.existsSync)(stateFile)) {
|
|
326
|
-
try {
|
|
327
|
-
state = JSON.parse((0, fs_1.readFileSync)(stateFile, 'utf-8'));
|
|
328
|
-
}
|
|
329
|
-
catch {
|
|
330
|
-
// Ignore
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
if (state.serverEnforced) {
|
|
334
|
-
// Already on v6.0+ server-enforced mode
|
|
335
|
-
console.log(chalk_1.default.green('\n ✅ Already using v6.0 server-enforced patterns!\n'));
|
|
336
|
-
console.log(chalk_1.default.gray(' Patterns are fetched from server in real-time.'));
|
|
337
|
-
console.log(chalk_1.default.gray(' No local updates needed.\n'));
|
|
338
|
-
return;
|
|
339
|
-
}
|
|
340
|
-
// Legacy upgrade for pre-6.0 versions (fetch full content)
|
|
341
|
-
const contentSpinner = (0, ora_1.default)('Fetching latest patterns...').start();
|
|
342
|
-
const response = await fetch(`${apiUrl}/api/content`, {
|
|
343
|
-
method: 'GET',
|
|
344
|
-
headers: {
|
|
345
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
346
|
-
},
|
|
347
|
-
});
|
|
348
|
-
if (!response.ok) {
|
|
349
|
-
const error = await response.json().catch(() => ({}));
|
|
350
|
-
throw new Error(error.error || 'Failed to fetch patterns');
|
|
351
|
-
}
|
|
352
|
-
const content = await response.json();
|
|
353
|
-
contentSpinner.succeed(`Patterns v${content.version} downloaded`);
|
|
354
|
-
// Count what we're updating
|
|
355
|
-
const moduleCount = Object.keys(content.modules).length;
|
|
356
|
-
console.log(chalk_1.default.gray(` Updating ${moduleCount} modules...\n`));
|
|
357
|
-
// Update CLAUDE.md
|
|
358
|
-
if (content.router) {
|
|
359
|
-
(0, fs_1.writeFileSync)(claudeMdPath, content.router);
|
|
360
|
-
console.log(chalk_1.default.green(' ✓ Updated CLAUDE.md'));
|
|
361
|
-
}
|
|
362
|
-
// Update pattern modules
|
|
363
|
-
if (content.modules && Object.keys(content.modules).length > 0) {
|
|
364
|
-
if (!(0, fs_1.existsSync)(claudeDir)) {
|
|
365
|
-
(0, fs_1.mkdirSync)(claudeDir, { recursive: true });
|
|
366
|
-
}
|
|
367
|
-
for (const [name, data] of Object.entries(content.modules)) {
|
|
368
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(claudeDir, name), data);
|
|
369
|
-
}
|
|
370
|
-
console.log(chalk_1.default.green(` ✓ Updated ${moduleCount} modules in .claude/`));
|
|
371
|
-
}
|
|
372
|
-
// Write version file for tracking
|
|
373
|
-
const versionInfo = {
|
|
374
|
-
version: content.version,
|
|
375
|
-
moduleCount,
|
|
376
|
-
updatedAt: new Date().toISOString(),
|
|
377
|
-
cliVersion: (0, api_js_1.getCliVersion)(),
|
|
378
|
-
};
|
|
379
|
-
if (!(0, fs_1.existsSync)(claudeDir)) {
|
|
380
|
-
(0, fs_1.mkdirSync)(claudeDir, { recursive: true });
|
|
381
|
-
}
|
|
382
|
-
(0, fs_1.writeFileSync)((0, path_1.join)(claudeDir, '.version.json'), JSON.stringify(versionInfo, null, 2));
|
|
383
|
-
console.log(chalk_1.default.green(' ✓ Version info saved'));
|
|
384
|
-
// Confirm download to server (non-blocking)
|
|
385
|
-
confirmDownload(apiUrl, apiKey, {
|
|
386
|
-
version: content.version,
|
|
387
|
-
moduleCount,
|
|
388
|
-
cliVersion: (0, api_js_1.getCliVersion)(),
|
|
389
|
-
command: 'upgrade',
|
|
390
|
-
}).catch(() => { }); // Silently ignore confirmation failures
|
|
391
|
-
console.log(chalk_1.default.green(`\n ✅ Upgraded to patterns v${content.version}!\n`));
|
|
392
|
-
// Show what's new if available
|
|
393
|
-
console.log(chalk_1.default.gray(' Changes take effect in your next AI session.\n'));
|
|
136
|
+
else {
|
|
137
|
+
console.log(chalk_1.default.green(' ✓ Logged in\n'));
|
|
394
138
|
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
console.log(chalk_1.default.
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
}
|
|
402
|
-
process.exit(1);
|
|
139
|
+
// Check if already using server-enforced patterns
|
|
140
|
+
if (isServerEnforced(cwd)) {
|
|
141
|
+
console.log(chalk_1.default.green(' ✅ Already using server-enforced patterns!\n'));
|
|
142
|
+
console.log(chalk_1.default.gray(' Patterns are fetched from server in real-time.'));
|
|
143
|
+
console.log(chalk_1.default.gray(' AI calls discover_patterns before coding - always up to date.\n'));
|
|
144
|
+
return;
|
|
403
145
|
}
|
|
146
|
+
// Migrate to server-enforced mode
|
|
147
|
+
migrateToServerEnforced(cwd);
|
|
404
148
|
}
|