@cpretzinger/boss-claude 1.0.0 → 1.0.2

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 (87) hide show
  1. package/README.md +304 -1
  2. package/bin/boss-claude.js +1138 -0
  3. package/bin/commands/mode.js +250 -0
  4. package/bin/onyx-guard.js +259 -0
  5. package/bin/onyx-guard.sh +251 -0
  6. package/bin/prompts.js +284 -0
  7. package/bin/rollback.js +85 -0
  8. package/bin/setup-wizard.js +492 -0
  9. package/config/.env.example +17 -0
  10. package/lib/README.md +83 -0
  11. package/lib/agent-logger.js +61 -0
  12. package/lib/agents/memory-engineers/github-memory-engineer.js +251 -0
  13. package/lib/agents/memory-engineers/postgres-memory-engineer.js +633 -0
  14. package/lib/agents/memory-engineers/qdrant-memory-engineer.js +358 -0
  15. package/lib/agents/memory-engineers/redis-memory-engineer.js +383 -0
  16. package/lib/agents/memory-supervisor.js +526 -0
  17. package/lib/agents/registry.js +135 -0
  18. package/lib/auto-monitor.js +131 -0
  19. package/lib/checkpoint-hook.js +112 -0
  20. package/lib/checkpoint.js +319 -0
  21. package/lib/commentator.js +213 -0
  22. package/lib/context-scribe.js +120 -0
  23. package/lib/delegation-strategies.js +326 -0
  24. package/lib/hierarchy-validator.js +643 -0
  25. package/lib/index.js +15 -0
  26. package/lib/init-with-mode.js +261 -0
  27. package/lib/init.js +44 -6
  28. package/lib/memory-result-aggregator.js +252 -0
  29. package/lib/memory.js +35 -7
  30. package/lib/mode-enforcer.js +473 -0
  31. package/lib/onyx-banner.js +169 -0
  32. package/lib/onyx-identity.js +214 -0
  33. package/lib/onyx-monitor.js +381 -0
  34. package/lib/onyx-reminder.js +188 -0
  35. package/lib/onyx-tool-interceptor.js +341 -0
  36. package/lib/onyx-wrapper.js +315 -0
  37. package/lib/orchestrator-gate.js +334 -0
  38. package/lib/output-formatter.js +296 -0
  39. package/lib/postgres.js +1 -1
  40. package/lib/prompt-injector.js +220 -0
  41. package/lib/prompts.js +532 -0
  42. package/lib/session.js +153 -6
  43. package/lib/setup/README.md +187 -0
  44. package/lib/setup/env-manager.js +785 -0
  45. package/lib/setup/error-recovery.js +630 -0
  46. package/lib/setup/explain-scopes.js +385 -0
  47. package/lib/setup/github-instructions.js +333 -0
  48. package/lib/setup/github-repo.js +254 -0
  49. package/lib/setup/import-credentials.js +498 -0
  50. package/lib/setup/index.js +62 -0
  51. package/lib/setup/init-postgres.js +785 -0
  52. package/lib/setup/init-redis.js +456 -0
  53. package/lib/setup/integration-test.js +652 -0
  54. package/lib/setup/progress.js +357 -0
  55. package/lib/setup/rollback.js +670 -0
  56. package/lib/setup/rollback.test.js +452 -0
  57. package/lib/setup/setup-with-rollback.example.js +351 -0
  58. package/lib/setup/summary.js +400 -0
  59. package/lib/setup/test-github-setup.js +10 -0
  60. package/lib/setup/test-postgres-init.js +98 -0
  61. package/lib/setup/verify-setup.js +102 -0
  62. package/lib/task-agent-worker.js +235 -0
  63. package/lib/token-monitor.js +466 -0
  64. package/lib/tool-wrapper-integration.js +369 -0
  65. package/lib/tool-wrapper.js +387 -0
  66. package/lib/validators/README.md +497 -0
  67. package/lib/validators/config.js +583 -0
  68. package/lib/validators/config.test.js +175 -0
  69. package/lib/validators/github.js +310 -0
  70. package/lib/validators/github.test.js +61 -0
  71. package/lib/validators/index.js +15 -0
  72. package/lib/validators/postgres.js +525 -0
  73. package/package.json +98 -13
  74. package/scripts/benchmark-memory.js +433 -0
  75. package/scripts/check-secrets.sh +12 -0
  76. package/scripts/fetch-todos.mjs +148 -0
  77. package/scripts/graceful-shutdown.sh +156 -0
  78. package/scripts/install-onyx-hooks.js +373 -0
  79. package/scripts/install.js +119 -18
  80. package/scripts/redis-monitor.js +284 -0
  81. package/scripts/redis-setup.js +412 -0
  82. package/scripts/test-memory-retrieval.js +201 -0
  83. package/scripts/validate-exports.js +68 -0
  84. package/scripts/validate-package.js +120 -0
  85. package/scripts/verify-onyx-deployment.js +309 -0
  86. package/scripts/verify-redis-deployment.js +354 -0
  87. package/scripts/verify-redis-init.js +219 -0
@@ -0,0 +1,400 @@
1
+ /**
2
+ * Boss Claude Setup Summary
3
+ *
4
+ * Beautiful success summary that makes users feel accomplished after setup.
5
+ * Displays what was configured, next steps, and helpful commands to try.
6
+ */
7
+
8
+ import chalk from 'chalk';
9
+ import prompts from '../prompts.js';
10
+
11
+ const {
12
+ success,
13
+ info,
14
+ muted,
15
+ blank,
16
+ divider,
17
+ keyValue,
18
+ theme
19
+ } = prompts;
20
+
21
+ /**
22
+ * Display a beautiful setup success summary
23
+ *
24
+ * @param {Object} config - Setup configuration results
25
+ * @param {Object} config.user - User information (name, email, username)
26
+ * @param {Object} config.github - GitHub setup results (enabled, repo, token)
27
+ * @param {Object} config.redis - Redis setup results (enabled, url, stats)
28
+ * @param {Object} config.postgres - PostgreSQL setup results (enabled, url, stats)
29
+ * @param {Object} config.env - Environment file information (path, created)
30
+ * @param {number} config.duration - Setup duration in milliseconds
31
+ */
32
+ export function displaySetupSummary(config) {
33
+ blank();
34
+ divider();
35
+ blank();
36
+
37
+ // Success header with celebration
38
+ console.log(chalk.bold.green(' ✨ SETUP COMPLETE! ✨'));
39
+ blank();
40
+
41
+ const emoji = getRandomSuccessEmoji();
42
+ console.log(chalk.dim(` ${emoji} Boss Claude is ready to revolutionize your workflow ${emoji}`));
43
+ blank();
44
+ divider();
45
+ blank();
46
+
47
+ // Configuration summary
48
+ console.log(chalk.bold(' 📋 WHAT WAS CONFIGURED'));
49
+ blank();
50
+
51
+ // User info
52
+ if (config.user) {
53
+ keyValue('Your Name', config.user.name || 'Not provided');
54
+ if (config.user.email) {
55
+ keyValue('Email', config.user.email);
56
+ }
57
+ if (config.user.username) {
58
+ keyValue('GitHub Username', `@${config.user.username}`);
59
+ }
60
+ blank();
61
+ }
62
+
63
+ // GitHub integration
64
+ if (config.github?.enabled) {
65
+ keyValue('GitHub Integration', chalk.green('✓ Enabled'));
66
+ if (config.github.repo) {
67
+ keyValue(' Repository', config.github.repo);
68
+ }
69
+ keyValue(' Authentication', chalk.green('✓ Configured'));
70
+ blank();
71
+ } else {
72
+ keyValue('GitHub Integration', chalk.yellow('○ Skipped (manual mode)'));
73
+ blank();
74
+ }
75
+
76
+ // Redis
77
+ if (config.redis?.enabled) {
78
+ keyValue('Redis (Session Storage)', chalk.green('✓ Connected'));
79
+ if (config.redis.stats) {
80
+ keyValue(' Identity Created', chalk.green('✓ Level 1 Boss'));
81
+ keyValue(' Data Structures', chalk.green(`✓ ${config.redis.stats.dataStructures || 'Initialized'}`));
82
+ }
83
+ blank();
84
+ } else {
85
+ keyValue('Redis', chalk.yellow('○ Skipped (sessions not persisted)'));
86
+ blank();
87
+ }
88
+
89
+ // PostgreSQL
90
+ if (config.postgres?.enabled) {
91
+ keyValue('PostgreSQL (Analytics)', chalk.green('✓ Connected'));
92
+ if (config.postgres.stats) {
93
+ keyValue(' Schema Version', config.postgres.stats.schemaVersion || 'v1');
94
+ keyValue(' Tables Created', chalk.green(`✓ ${config.postgres.stats.tablesCreated || 'All ready'}`));
95
+ }
96
+ blank();
97
+ } else {
98
+ keyValue('PostgreSQL', chalk.yellow('○ Skipped (analytics disabled)'));
99
+ blank();
100
+ }
101
+
102
+ // Environment file
103
+ if (config.env?.created) {
104
+ keyValue('Environment File', chalk.green('✓ Created'));
105
+ keyValue(' Location', config.env.path || '~/.boss-claude/.env');
106
+ blank();
107
+ }
108
+
109
+ // Setup duration
110
+ if (config.duration) {
111
+ const seconds = (config.duration / 1000).toFixed(1);
112
+ keyValue('Setup Time', `${seconds}s ${getSpeedComment(seconds)}`);
113
+ blank();
114
+ }
115
+
116
+ divider();
117
+ blank();
118
+
119
+ // Next steps
120
+ console.log(chalk.bold(' 🚀 NEXT STEPS'));
121
+ blank();
122
+
123
+ const steps = [
124
+ 'Check your status anytime with:',
125
+ chalk.cyan(' $ boss-claude status'),
126
+ '',
127
+ 'Start a new session:',
128
+ chalk.cyan(' $ boss-claude start "Working on awesome feature"'),
129
+ '',
130
+ 'Save your progress:',
131
+ chalk.cyan(' $ boss-claude save "Completed authentication system"'),
132
+ '',
133
+ 'View your achievements:',
134
+ chalk.cyan(' $ boss-claude achievements')
135
+ ];
136
+
137
+ steps.forEach(step => console.log(chalk.dim(` ${step}`)));
138
+ blank();
139
+
140
+ divider();
141
+ blank();
142
+
143
+ // Helpful tips
144
+ console.log(chalk.bold(' 💡 PRO TIPS'));
145
+ blank();
146
+
147
+ const tips = [
148
+ chalk.dim('• Boss Claude tracks XP, tokens, and achievements automatically'),
149
+ chalk.dim('• Your identity persists across ALL your repositories'),
150
+ chalk.dim('• Use ') + chalk.cyan('boss-claude --help') + chalk.dim(' to see all commands'),
151
+ chalk.dim('• Check ') + chalk.cyan('~/.boss-claude/') + chalk.dim(' for configs and logs')
152
+ ];
153
+
154
+ tips.forEach(tip => console.log(` ${tip}`));
155
+ blank();
156
+
157
+ divider();
158
+ blank();
159
+
160
+ // Final motivation
161
+ const motivation = getRandomMotivation();
162
+ console.log(chalk.bold.green(` ${motivation}`));
163
+ blank();
164
+
165
+ // Documentation link
166
+ console.log(chalk.dim(' 📚 Docs: https://github.com/cpretzinger/boss-claude#readme'));
167
+ blank();
168
+ divider();
169
+ blank();
170
+ }
171
+
172
+ /**
173
+ * Display a compact summary (for quick setups)
174
+ *
175
+ * @param {Object} config - Simplified config object
176
+ */
177
+ export function displayQuickSummary(config) {
178
+ blank();
179
+ success('Setup complete!');
180
+ blank();
181
+
182
+ if (config.redis?.enabled) {
183
+ info(`Redis connected: ${config.redis.url?.split('@')[1]?.split('/')[0] || 'localhost'}`);
184
+ }
185
+
186
+ if (config.postgres?.enabled) {
187
+ info(`PostgreSQL connected: ${config.postgres.url?.split('@')[1]?.split('/')[0] || 'localhost'}`);
188
+ }
189
+
190
+ if (config.github?.enabled) {
191
+ info(`GitHub repo: ${config.github.repo}`);
192
+ }
193
+
194
+ blank();
195
+ console.log(chalk.dim(' Try: ') + chalk.cyan('boss-claude status'));
196
+ blank();
197
+ }
198
+
199
+ /**
200
+ * Display a summary for partial/failed setup
201
+ *
202
+ * @param {Object} config - Config with success/failure info
203
+ * @param {Array<string>} errors - List of errors encountered
204
+ */
205
+ export function displayPartialSummary(config, errors = []) {
206
+ blank();
207
+ divider();
208
+ blank();
209
+
210
+ console.log(chalk.bold.yellow(' ⚠️ SETUP PARTIALLY COMPLETE'));
211
+ blank();
212
+
213
+ // Show what worked
214
+ const successes = [];
215
+ if (config.redis?.enabled) successes.push('Redis');
216
+ if (config.postgres?.enabled) successes.push('PostgreSQL');
217
+ if (config.github?.enabled) successes.push('GitHub');
218
+
219
+ if (successes.length > 0) {
220
+ keyValue('Configured', chalk.green(successes.join(', ')));
221
+ blank();
222
+ }
223
+
224
+ // Show what failed
225
+ if (errors.length > 0) {
226
+ console.log(chalk.bold.red(' ❌ ISSUES ENCOUNTERED'));
227
+ blank();
228
+ errors.forEach(err => {
229
+ console.log(chalk.dim(` • ${err}`));
230
+ });
231
+ blank();
232
+ }
233
+
234
+ divider();
235
+ blank();
236
+
237
+ console.log(chalk.dim(' You can re-run setup anytime with: ') + chalk.cyan('boss-claude setup'));
238
+ blank();
239
+ }
240
+
241
+ /**
242
+ * Display rollback summary
243
+ *
244
+ * @param {Object} rollback - Rollback information
245
+ */
246
+ export function displayRollbackSummary(rollback) {
247
+ blank();
248
+ divider();
249
+ blank();
250
+
251
+ console.log(chalk.bold.yellow(' ↩️ SETUP ROLLED BACK'));
252
+ blank();
253
+
254
+ if (rollback.reason) {
255
+ keyValue('Reason', rollback.reason);
256
+ blank();
257
+ }
258
+
259
+ if (rollback.actionsReverted?.length > 0) {
260
+ console.log(chalk.dim(' Actions reverted:'));
261
+ rollback.actionsReverted.forEach(action => {
262
+ console.log(chalk.dim(` • ${action}`));
263
+ });
264
+ blank();
265
+ }
266
+
267
+ divider();
268
+ blank();
269
+
270
+ console.log(chalk.dim(' Your system is back to its original state.'));
271
+ console.log(chalk.dim(' Run ') + chalk.cyan('boss-claude setup') + chalk.dim(' to try again.'));
272
+ blank();
273
+ }
274
+
275
+ /**
276
+ * Display validation results
277
+ *
278
+ * @param {Object} validation - Validation test results
279
+ */
280
+ export function displayValidationSummary(validation) {
281
+ blank();
282
+ divider();
283
+ blank();
284
+
285
+ console.log(chalk.bold(' 🔍 VALIDATION RESULTS'));
286
+ blank();
287
+
288
+ const tests = validation.tests || {};
289
+ let passed = 0;
290
+ let failed = 0;
291
+
292
+ Object.entries(tests).forEach(([name, result]) => {
293
+ if (result.success) {
294
+ console.log(chalk.green(` ✓ ${name}`));
295
+ passed++;
296
+ } else {
297
+ console.log(chalk.red(` ✗ ${name}`));
298
+ if (result.error) {
299
+ console.log(chalk.dim(` ${result.error}`));
300
+ }
301
+ failed++;
302
+ }
303
+ });
304
+
305
+ blank();
306
+ divider();
307
+ blank();
308
+
309
+ if (failed === 0) {
310
+ success(`All ${passed} tests passed!`);
311
+ } else {
312
+ console.log(chalk.yellow(` ${passed} passed, ${failed} failed`));
313
+ }
314
+
315
+ blank();
316
+ }
317
+
318
+ /**
319
+ * Get a random success emoji
320
+ * @returns {string}
321
+ */
322
+ function getRandomSuccessEmoji() {
323
+ const emojis = ['🎉', '🎊', '🌟', '⭐', '🚀', '💪', '🔥', '✨'];
324
+ return emojis[Math.floor(Math.random() * emojis.length)];
325
+ }
326
+
327
+ /**
328
+ * Get a comment about setup speed
329
+ * @param {number} seconds - Duration in seconds
330
+ * @returns {string}
331
+ */
332
+ function getSpeedComment(seconds) {
333
+ if (seconds < 5) return '⚡ Lightning fast!';
334
+ if (seconds < 15) return '🚀 Quick setup!';
335
+ if (seconds < 30) return '✓ Not bad!';
336
+ return '✓ Done!';
337
+ }
338
+
339
+ /**
340
+ * Get a random motivational message
341
+ * @returns {string}
342
+ */
343
+ function getRandomMotivation() {
344
+ const messages = [
345
+ 'You\'re all set! Time to build something amazing.',
346
+ 'Configuration complete. Let\'s get to work!',
347
+ 'Ready to level up your productivity!',
348
+ 'Everything is configured. Go make magic happen!',
349
+ 'Setup successful. Your AI assistant awaits!',
350
+ 'You\'re ready to rock! Let\'s do this.',
351
+ 'Configuration locked in. Time to shine!',
352
+ 'All systems go! Let\'s build the future.'
353
+ ];
354
+ return messages[Math.floor(Math.random() * messages.length)];
355
+ }
356
+
357
+ /**
358
+ * Create a configuration summary object from setup results
359
+ *
360
+ * @param {Object} results - Raw setup results from wizard
361
+ * @returns {Object} Formatted config for summary
362
+ */
363
+ export function createSummaryConfig(results) {
364
+ return {
365
+ user: {
366
+ name: results.userName || results.user?.name,
367
+ email: results.userEmail || results.user?.email,
368
+ username: results.githubUsername || results.github?.username
369
+ },
370
+ github: {
371
+ enabled: results.githubEnabled || results.github?.enabled || false,
372
+ repo: results.githubRepo || results.github?.repo,
373
+ token: results.githubToken ? '✓ Set' : null
374
+ },
375
+ redis: {
376
+ enabled: results.redisEnabled || results.redis?.enabled || false,
377
+ url: results.redisUrl || results.redis?.url,
378
+ stats: results.redisStats || results.redis?.stats
379
+ },
380
+ postgres: {
381
+ enabled: results.postgresEnabled || results.postgres?.enabled || false,
382
+ url: results.postgresUrl || results.postgres?.url,
383
+ stats: results.postgresStats || results.postgres?.stats
384
+ },
385
+ env: {
386
+ created: results.envCreated || results.env?.created || false,
387
+ path: results.envPath || results.env?.path
388
+ },
389
+ duration: results.duration || results.setupDuration
390
+ };
391
+ }
392
+
393
+ export default {
394
+ displaySetupSummary,
395
+ displayQuickSummary,
396
+ displayPartialSummary,
397
+ displayRollbackSummary,
398
+ displayValidationSummary,
399
+ createSummaryConfig
400
+ };
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Test script for GitHub repository setup
5
+ * Usage: node lib/setup/test-github-setup.js
6
+ */
7
+
8
+ import { setupGitHubRepoCommand } from './github-repo.js';
9
+
10
+ await setupGitHubRepoCommand();
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Test PostgreSQL Initialization
4
+ *
5
+ * Simple test script to verify init-postgres.js works correctly
6
+ * Tests: connection, schema creation, health checks, and stats
7
+ */
8
+
9
+ import {
10
+ initializePostgres,
11
+ verifyPostgres,
12
+ getPostgresStats,
13
+ printInitResults
14
+ } from './init-postgres.js';
15
+ import chalk from 'chalk';
16
+
17
+ // Get connection string from environment or use default
18
+ const connectionString = process.env.DATABASE_URL || process.env.POSTGRES_URL;
19
+
20
+ if (!connectionString) {
21
+ console.log(chalk.red('\n✗ Error: No PostgreSQL connection string found'));
22
+ console.log(chalk.dim('Set DATABASE_URL or POSTGRES_URL environment variable\n'));
23
+ process.exit(1);
24
+ }
25
+
26
+ async function runTests() {
27
+ console.log(chalk.cyan('\n🧪 Testing PostgreSQL Initialization\n'));
28
+ console.log(chalk.dim(`Connection: ${connectionString.replace(/:[^:@]+@/, ':****@')}\n`));
29
+
30
+ try {
31
+ // Test 1: Verify connection
32
+ console.log(chalk.cyan('1️⃣ Verifying connection...'));
33
+ const verification = await verifyPostgres(connectionString);
34
+
35
+ if (!verification.connected) {
36
+ console.log(chalk.red(`✗ Connection failed: ${verification.error}\n`));
37
+ process.exit(1);
38
+ }
39
+
40
+ console.log(chalk.green('✓ Connected successfully'));
41
+ console.log(chalk.dim(` Database: ${verification.version.split(',')[0]}`));
42
+
43
+ if (verification.schemaExists) {
44
+ console.log(chalk.yellow('○ Schema already exists'));
45
+ console.log(chalk.dim(` Tables: ${verification.tables.join(', ')}`));
46
+ } else {
47
+ console.log(chalk.dim(' Schema does not exist yet'));
48
+ }
49
+
50
+ // Test 2: Initialize schema
51
+ console.log(chalk.cyan('\n2️⃣ Initializing schema...'));
52
+ const results = await initializePostgres(connectionString, false);
53
+ printInitResults(results);
54
+
55
+ if (!results.healthCheck.passed) {
56
+ console.log(chalk.red('✗ Initialization failed health check\n'));
57
+ process.exit(1);
58
+ }
59
+
60
+ // Test 3: Get statistics
61
+ console.log(chalk.cyan('3️⃣ Retrieving statistics...'));
62
+ const stats = await getPostgresStats(connectionString);
63
+
64
+ console.log(chalk.dim('\nDatabase Statistics:'));
65
+ console.log(chalk.dim(` Total Sessions: ${stats.totalSessions}`));
66
+ console.log(chalk.dim(` Active Sessions: ${stats.activeSessions}`));
67
+ console.log(chalk.dim(` Unique Users: ${stats.totalUsers}`));
68
+ console.log(chalk.dim(` Total Achievements: ${stats.totalAchievements}`));
69
+ console.log(chalk.dim(` Memory Snapshots: ${stats.totalSnapshots}`));
70
+ console.log(chalk.dim(` Schema Size: ${stats.schemaSize}`));
71
+
72
+ if (stats.oldestSession) {
73
+ console.log(chalk.dim(` First Session: ${new Date(stats.oldestSession).toLocaleDateString()}`));
74
+ }
75
+ if (stats.newestSession) {
76
+ console.log(chalk.dim(` Last Session: ${new Date(stats.newestSession).toLocaleDateString()}`));
77
+ }
78
+
79
+ // Test 4: Verify again
80
+ console.log(chalk.cyan('\n4️⃣ Final verification...'));
81
+ const finalCheck = await verifyPostgres(connectionString);
82
+
83
+ if (finalCheck.connected && finalCheck.healthCheck.passed) {
84
+ console.log(chalk.green('\n✓ All tests passed! PostgreSQL is ready.\n'));
85
+ process.exit(0);
86
+ } else {
87
+ console.log(chalk.red('\n✗ Final verification failed\n'));
88
+ process.exit(1);
89
+ }
90
+
91
+ } catch (error) {
92
+ console.log(chalk.red(`\n✗ Test failed: ${error.message}`));
93
+ console.log(chalk.dim(error.stack));
94
+ process.exit(1);
95
+ }
96
+ }
97
+
98
+ runTests();
@@ -0,0 +1,102 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Verification script for GitHub repository setup
5
+ * Tests all major functionality without creating a repository
6
+ */
7
+
8
+ import chalk from 'chalk';
9
+ import { getGitHubToken } from './github-repo.js';
10
+ import { Octokit } from '@octokit/rest';
11
+
12
+ console.log(chalk.bold('\n🔍 Boss Claude GitHub Setup Verification\n'));
13
+
14
+ // Step 1: Check for token
15
+ console.log(chalk.blue('1. Checking for GitHub token...'));
16
+ const token = getGitHubToken();
17
+
18
+ if (token) {
19
+ console.log(chalk.green(' ✓ Token found'));
20
+ console.log(chalk.gray(` → Source: ${process.env.GITHUB_TOKEN ? 'GITHUB_TOKEN env var' : 'git config'}`));
21
+ console.log(chalk.gray(` → Length: ${token.length} characters`));
22
+ console.log(chalk.gray(` → Prefix: ${token.substring(0, 7)}...`));
23
+ } else {
24
+ console.log(chalk.red(' ✗ No token found'));
25
+ console.log(chalk.yellow('\n To fix, run one of these:'));
26
+ console.log(chalk.gray(' export GITHUB_TOKEN=ghp_your_token'));
27
+ console.log(chalk.gray(' git config --global github.token ghp_your_token'));
28
+ process.exit(1);
29
+ }
30
+
31
+ // Step 2: Test authentication
32
+ console.log(chalk.blue('\n2. Testing GitHub authentication...'));
33
+ const octokit = new Octokit({ auth: token });
34
+
35
+ try {
36
+ const { data: user } = await octokit.users.getAuthenticated();
37
+ console.log(chalk.green(' ✓ Authentication successful'));
38
+ console.log(chalk.gray(` → Username: ${user.login}`));
39
+ console.log(chalk.gray(` → Name: ${user.name || 'Not set'}`));
40
+ console.log(chalk.gray(` → Account type: ${user.type}`));
41
+ console.log(chalk.gray(` → Public repos: ${user.public_repos}`));
42
+ console.log(chalk.gray(` → Private repos: ${user.total_private_repos || 'Unknown'}`));
43
+ } catch (error) {
44
+ console.log(chalk.red(' ✗ Authentication failed'));
45
+ console.log(chalk.red(` → Error: ${error.message}`));
46
+ console.log(chalk.yellow('\n Your token may be invalid or expired.'));
47
+ console.log(chalk.gray(' Create a new token at: https://github.com/settings/tokens'));
48
+ process.exit(1);
49
+ }
50
+
51
+ // Step 3: Check token scopes
52
+ console.log(chalk.blue('\n3. Checking token permissions...'));
53
+ try {
54
+ const { headers } = await octokit.request('HEAD /user');
55
+ const scopes = headers['x-oauth-scopes']?.split(', ') || [];
56
+
57
+ if (scopes.length === 0) {
58
+ console.log(chalk.yellow(' ⚠ Warning: Could not determine token scopes'));
59
+ } else {
60
+ console.log(chalk.green(' ✓ Token scopes found'));
61
+ scopes.forEach(scope => {
62
+ const hasRepo = scope === 'repo' || scope.startsWith('repo:');
63
+ const icon = hasRepo ? chalk.green('✓') : chalk.gray('•');
64
+ console.log(chalk.gray(` ${icon} ${scope}`));
65
+ });
66
+
67
+ const hasRepoScope = scopes.some(s => s === 'repo' || s.startsWith('repo:'));
68
+ if (hasRepoScope) {
69
+ console.log(chalk.green('\n ✓ Token has required repo permissions'));
70
+ } else {
71
+ console.log(chalk.yellow('\n ⚠ Warning: Token may not have repo creation permissions'));
72
+ console.log(chalk.gray(' → Required scope: repo'));
73
+ }
74
+ }
75
+ } catch (error) {
76
+ console.log(chalk.yellow(' ⚠ Could not check token permissions'));
77
+ console.log(chalk.gray(` → ${error.message}`));
78
+ }
79
+
80
+ // Step 4: Check rate limits
81
+ console.log(chalk.blue('\n4. Checking API rate limits...'));
82
+ try {
83
+ const { data: rateLimit } = await octokit.rateLimit.get();
84
+ const { core } = rateLimit.resources;
85
+
86
+ console.log(chalk.green(' ✓ Rate limit status'));
87
+ console.log(chalk.gray(` → Remaining: ${core.remaining}/${core.limit}`));
88
+ console.log(chalk.gray(` → Resets at: ${new Date(core.reset * 1000).toLocaleTimeString()}`));
89
+
90
+ if (core.remaining < 10) {
91
+ console.log(chalk.yellow('\n ⚠ Warning: Low rate limit remaining'));
92
+ }
93
+ } catch (error) {
94
+ console.log(chalk.yellow(' ⚠ Could not check rate limits'));
95
+ console.log(chalk.gray(` → ${error.message}`));
96
+ }
97
+
98
+ // Step 5: Summary
99
+ console.log(chalk.bold.green('\n✓ Verification Complete\n'));
100
+ console.log(chalk.gray('Your GitHub setup is ready for Boss Claude repository creation.'));
101
+ console.log(chalk.gray('\nTo create the repository, run:'));
102
+ console.log(chalk.cyan(' node lib/setup/test-github-setup.js\n'));