@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,333 @@
1
+ #!/usr/bin/env node
2
+
3
+ import chalk from 'chalk';
4
+ import boxen from 'boxen';
5
+
6
+ /**
7
+ * Display step-by-step instructions for creating a GitHub Personal Access Token
8
+ * with the correct scopes for BOSS Claude automation
9
+ */
10
+ export function displayGitHubPATInstructions() {
11
+ console.log('\n');
12
+ console.log(boxen(
13
+ chalk.bold.cyan('GitHub Personal Access Token Setup Guide'),
14
+ {
15
+ padding: 1,
16
+ margin: 1,
17
+ borderStyle: 'double',
18
+ borderColor: 'cyan'
19
+ }
20
+ ));
21
+
22
+ console.log(chalk.yellow('\n📋 WHY YOU NEED THIS:'));
23
+ console.log('BOSS Claude needs GitHub API access to automate:');
24
+ console.log(' • Creating commits with co-author attribution');
25
+ console.log(' • Managing pull requests and reviews');
26
+ console.log(' • Reading repository information');
27
+ console.log(' • Creating and managing issues');
28
+ console.log(' • Analyzing code and commit history\n');
29
+
30
+ // Step 1
31
+ console.log(chalk.bold.green('STEP 1: Navigate to GitHub Token Settings'));
32
+ console.log(chalk.gray('─'.repeat(70)));
33
+ console.log('\n📍 Go to: ' + chalk.blue.underline('https://github.com/settings/tokens'));
34
+ console.log('\nAlternatively:');
35
+ console.log(' 1. Click your profile picture (top-right corner)');
36
+ console.log(' 2. Click ' + chalk.bold('"Settings"'));
37
+ console.log(' 3. Scroll down to ' + chalk.bold('"Developer settings"') + ' (bottom of left sidebar)');
38
+ console.log(' 4. Click ' + chalk.bold('"Personal access tokens"'));
39
+ console.log(' 5. Click ' + chalk.bold('"Tokens (classic)"'));
40
+ console.log('\n' + chalk.dim('Screenshot: You\'ll see a page with "Generate new token" button\n'));
41
+
42
+ // Step 2
43
+ console.log(chalk.bold.green('STEP 2: Generate New Token'));
44
+ console.log(chalk.gray('─'.repeat(70)));
45
+ console.log('\n1. Click the ' + chalk.bold('"Generate new token"') + ' dropdown');
46
+ console.log('2. Select ' + chalk.bold('"Generate new token (classic)"'));
47
+ console.log('\n' + chalk.yellow('⚠️ IMPORTANT:') + ' Use "classic" tokens, not fine-grained tokens\n');
48
+
49
+ // Step 3
50
+ console.log(chalk.bold.green('STEP 3: Configure Token Details'));
51
+ console.log(chalk.gray('─'.repeat(70)));
52
+ console.log('\n' + chalk.bold('Note:') + ' Give your token a descriptive name');
53
+ console.log(' Example: ' + chalk.cyan('"BOSS Claude Automation"'));
54
+ console.log('\n' + chalk.bold('Expiration:') + ' Choose based on your preference');
55
+ console.log(' • ' + chalk.cyan('30 days') + ' - More secure (recommended for testing)');
56
+ console.log(' • ' + chalk.cyan('90 days') + ' - Balanced');
57
+ console.log(' • ' + chalk.cyan('No expiration') + ' - Convenient but less secure\n');
58
+
59
+ // Step 4
60
+ console.log(chalk.bold.green('STEP 4: Select Scopes (CHECK THESE BOXES)'));
61
+ console.log(chalk.gray('─'.repeat(70)));
62
+ console.log('\n' + chalk.bold.yellow('⚡ REQUIRED SCOPES - Check these checkboxes:\n'));
63
+
64
+ const requiredScopes = [
65
+ {
66
+ name: 'repo',
67
+ description: 'Full control of private repositories',
68
+ details: [
69
+ 'repo:status - Access commit status',
70
+ 'repo_deployment - Access deployment status',
71
+ 'public_repo - Access public repositories',
72
+ 'repo:invite - Access repository invitations',
73
+ 'security_events - Read/write security events'
74
+ ],
75
+ note: 'This automatically checks all sub-scopes'
76
+ },
77
+ {
78
+ name: 'workflow',
79
+ description: 'Update GitHub Action workflows',
80
+ details: [
81
+ 'Allows BOSS Claude to create/modify GitHub Actions',
82
+ 'Required for CI/CD automation'
83
+ ],
84
+ note: 'Separate checkbox, not under repo'
85
+ },
86
+ {
87
+ name: 'write:packages',
88
+ description: 'Upload packages to GitHub Package Registry',
89
+ details: [
90
+ 'Needed if publishing NPM packages via GitHub',
91
+ 'Includes read:packages scope'
92
+ ],
93
+ note: 'Optional - only if using GitHub Packages'
94
+ },
95
+ {
96
+ name: 'read:org',
97
+ description: 'Read org and team membership, read org projects',
98
+ details: [
99
+ 'Required for accessing organization repositories',
100
+ 'Needed if BOSS Claude works with org repos'
101
+ ],
102
+ note: 'Optional - only if using organization repos'
103
+ }
104
+ ];
105
+
106
+ requiredScopes.forEach((scope, index) => {
107
+ console.log(chalk.bold.cyan(`☑ ${scope.name}`) + chalk.gray(` - ${scope.description}`));
108
+ scope.details.forEach(detail => {
109
+ console.log(' ' + chalk.dim(detail));
110
+ });
111
+ if (scope.note) {
112
+ console.log(' ' + chalk.yellow(`💡 ${scope.note}`));
113
+ }
114
+ console.log('');
115
+ });
116
+
117
+ console.log(chalk.bold.yellow('📝 MINIMUM REQUIRED FOR BASIC OPERATION:'));
118
+ console.log(' ☑ ' + chalk.bold('repo') + ' (with all sub-scopes)');
119
+ console.log(' ☑ ' + chalk.bold('workflow') + ' (if using GitHub Actions)\n');
120
+
121
+ // Step 5
122
+ console.log(chalk.bold.green('STEP 5: Visual Checklist'));
123
+ console.log(chalk.gray('─'.repeat(70)));
124
+ console.log('\nYour GitHub page should look like this:\n');
125
+ console.log(chalk.dim('┌─────────────────────────────────────────┐'));
126
+ console.log(chalk.dim('│') + ' Select scopes ' + chalk.dim('│'));
127
+ console.log(chalk.dim('│ │'));
128
+ console.log(chalk.dim('│') + ' ' + chalk.green('☑') + ' repo ' + chalk.dim('│'));
129
+ console.log(chalk.dim('│') + ' ' + chalk.green('☑') + ' repo:status ' + chalk.dim('│'));
130
+ console.log(chalk.dim('│') + ' ' + chalk.green('☑') + ' repo_deployment ' + chalk.dim('│'));
131
+ console.log(chalk.dim('│') + ' ' + chalk.green('☑') + ' public_repo ' + chalk.dim('│'));
132
+ console.log(chalk.dim('│') + ' ' + chalk.green('☑') + ' repo:invite ' + chalk.dim('│'));
133
+ console.log(chalk.dim('│') + ' ' + chalk.green('☑') + ' security_events ' + chalk.dim('│'));
134
+ console.log(chalk.dim('│ │'));
135
+ console.log(chalk.dim('│') + ' ' + chalk.green('☑') + ' workflow ' + chalk.dim('│'));
136
+ console.log(chalk.dim('│ │'));
137
+ console.log(chalk.dim('│') + ' ☐ write:packages ' + chalk.dim('│'));
138
+ console.log(chalk.dim('│') + ' ☐ read:org ' + chalk.dim('│'));
139
+ console.log(chalk.dim('└─────────────────────────────────────────┘'));
140
+ console.log('');
141
+
142
+ // Step 6
143
+ console.log(chalk.bold.green('STEP 6: Generate and Copy Token'));
144
+ console.log(chalk.gray('─'.repeat(70)));
145
+ console.log('\n1. Scroll to the bottom of the page');
146
+ console.log('2. Click the ' + chalk.bold.green('"Generate token"') + ' button');
147
+ console.log('3. GitHub will display your new token ' + chalk.bold('ONLY ONCE'));
148
+ console.log('4. Click the ' + chalk.cyan('📋 copy icon') + ' to copy the token');
149
+ console.log('\n' + chalk.bold.red('⚠️ CRITICAL:') + ' Save this token immediately!');
150
+ console.log(' You will ' + chalk.bold('NEVER') + ' be able to see it again.\n');
151
+
152
+ // Step 7
153
+ console.log(chalk.bold.green('STEP 7: Add Token to BOSS Claude'));
154
+ console.log(chalk.gray('─'.repeat(70)));
155
+ console.log('\nRun this command and paste your token when prompted:\n');
156
+ console.log(' ' + chalk.cyan('boss-claude github auth'));
157
+ console.log('\nOr manually add to your environment:\n');
158
+ console.log(' ' + chalk.gray('# Add to ~/.bashrc or ~/.zshrc'));
159
+ console.log(' ' + chalk.cyan('export GITHUB_TOKEN=') + chalk.yellow('ghp_your_token_here'));
160
+ console.log('\n');
161
+
162
+ // Security Tips
163
+ console.log(boxen(
164
+ chalk.bold.red('🔒 SECURITY TIPS\n\n') +
165
+ '• Treat this token like a password - never commit it to git\n' +
166
+ '• Store it in environment variables or secure credential managers\n' +
167
+ '• Rotate tokens every 90 days for better security\n' +
168
+ '• If token is compromised, revoke immediately at:\n' +
169
+ ' ' + chalk.blue.underline('https://github.com/settings/tokens') + '\n' +
170
+ '• Use different tokens for different projects/purposes',
171
+ {
172
+ padding: 1,
173
+ margin: 1,
174
+ borderStyle: 'round',
175
+ borderColor: 'red'
176
+ }
177
+ ));
178
+
179
+ // Troubleshooting
180
+ console.log('\n' + chalk.bold.yellow('🔧 TROUBLESHOOTING\n'));
181
+ console.log(chalk.bold('Token not working?'));
182
+ console.log(' 1. Verify scopes are correct (run: ' + chalk.cyan('boss-claude github check-scopes') + ')');
183
+ console.log(' 2. Check token hasn\'t expired');
184
+ console.log(' 3. Ensure token is properly set in environment');
185
+ console.log(' 4. Try regenerating with same scopes\n');
186
+
187
+ console.log(chalk.bold('Need different scopes?'));
188
+ console.log(' • You can edit token scopes at: ' + chalk.blue.underline('https://github.com/settings/tokens'));
189
+ console.log(' • Click on token name → Update scopes → Save\n');
190
+
191
+ // Quick Links
192
+ console.log(chalk.bold.cyan('📚 QUICK LINKS\n'));
193
+ console.log(' Create Token: ' + chalk.blue.underline('https://github.com/settings/tokens/new'));
194
+ console.log(' Manage Tokens: ' + chalk.blue.underline('https://github.com/settings/tokens'));
195
+ console.log(' GitHub Docs: ' + chalk.blue.underline('https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens'));
196
+ console.log(' BOSS Claude: ' + chalk.blue.underline('https://github.com/cpretzinger/boss-claude'));
197
+ console.log('\n');
198
+
199
+ console.log(chalk.green('✅ Once you have your token, run: ') + chalk.bold.cyan('boss-claude github auth'));
200
+ console.log('\n');
201
+ }
202
+
203
+ /**
204
+ * Display scope verification instructions
205
+ */
206
+ export function displayScopeVerification() {
207
+ console.log('\n');
208
+ console.log(boxen(
209
+ chalk.bold.yellow('GitHub Token Scope Verification'),
210
+ {
211
+ padding: 1,
212
+ borderStyle: 'round',
213
+ borderColor: 'yellow'
214
+ }
215
+ ));
216
+
217
+ console.log('\n' + chalk.bold('How to verify your token has the correct scopes:\n'));
218
+ console.log('1. Go to: ' + chalk.blue.underline('https://github.com/settings/tokens'));
219
+ console.log('2. Find your "BOSS Claude Automation" token');
220
+ console.log('3. Check the scopes listed under the token name\n');
221
+
222
+ console.log(chalk.bold('Expected scopes:'));
223
+ console.log(' • ' + chalk.cyan('repo'));
224
+ console.log(' • ' + chalk.cyan('workflow'));
225
+ console.log(' • ' + chalk.gray('write:packages (optional)'));
226
+ console.log(' • ' + chalk.gray('read:org (optional)'));
227
+ console.log('\n');
228
+ }
229
+
230
+ /**
231
+ * Display common errors and solutions
232
+ */
233
+ export function displayCommonErrors() {
234
+ console.log('\n');
235
+ console.log(boxen(
236
+ chalk.bold.red('Common GitHub Token Errors & Solutions'),
237
+ {
238
+ padding: 1,
239
+ borderStyle: 'round',
240
+ borderColor: 'red'
241
+ }
242
+ ));
243
+
244
+ const errors = [
245
+ {
246
+ error: '401 Unauthorized',
247
+ causes: [
248
+ 'Token is invalid or expired',
249
+ 'Token not properly set in environment'
250
+ ],
251
+ solutions: [
252
+ 'Regenerate token',
253
+ 'Check GITHUB_TOKEN environment variable',
254
+ 'Verify no extra spaces when copying token'
255
+ ]
256
+ },
257
+ {
258
+ error: '403 Forbidden',
259
+ causes: [
260
+ 'Missing required scopes',
261
+ 'Repository access denied',
262
+ 'Rate limit exceeded'
263
+ ],
264
+ solutions: [
265
+ 'Add required scopes to token',
266
+ 'Check repository permissions',
267
+ 'Wait for rate limit reset (check headers)'
268
+ ]
269
+ },
270
+ {
271
+ error: '404 Not Found',
272
+ causes: [
273
+ 'Repository doesn\'t exist',
274
+ 'No read access to private repo'
275
+ ],
276
+ solutions: [
277
+ 'Verify repository name',
278
+ 'Add repo scope to token',
279
+ 'Check organization permissions'
280
+ ]
281
+ },
282
+ {
283
+ error: 'Resource not accessible by personal access token',
284
+ causes: [
285
+ 'Missing workflow scope',
286
+ 'Trying to access organization resource without org scope'
287
+ ],
288
+ solutions: [
289
+ 'Add workflow scope for Actions',
290
+ 'Add read:org scope for organization repos'
291
+ ]
292
+ }
293
+ ];
294
+
295
+ errors.forEach((item, index) => {
296
+ console.log('\n' + chalk.bold.red(`ERROR ${index + 1}: ${item.error}`));
297
+ console.log(chalk.yellow(' Possible causes:'));
298
+ item.causes.forEach(cause => console.log(' • ' + cause));
299
+ console.log(chalk.green(' Solutions:'));
300
+ item.solutions.forEach(solution => console.log(' ✓ ' + solution));
301
+ });
302
+
303
+ console.log('\n');
304
+ }
305
+
306
+ // CLI interface
307
+ if (import.meta.url === `file://${process.argv[1]}`) {
308
+ const command = process.argv[2];
309
+
310
+ switch (command) {
311
+ case 'verify':
312
+ displayScopeVerification();
313
+ break;
314
+ case 'errors':
315
+ displayCommonErrors();
316
+ break;
317
+ case 'help':
318
+ console.log('\nUsage:');
319
+ console.log(' node github-instructions.js Show full setup guide');
320
+ console.log(' node github-instructions.js verify Show scope verification');
321
+ console.log(' node github-instructions.js errors Show common errors');
322
+ console.log(' node github-instructions.js help Show this help\n');
323
+ break;
324
+ default:
325
+ displayGitHubPATInstructions();
326
+ }
327
+ }
328
+
329
+ export default {
330
+ displayGitHubPATInstructions,
331
+ displayScopeVerification,
332
+ displayCommonErrors
333
+ };
@@ -0,0 +1,254 @@
1
+ import { Octokit } from '@octokit/rest';
2
+ import { execSync } from 'child_process';
3
+ import chalk from 'chalk';
4
+
5
+ const REPO_NAME = 'boss-claude-memory';
6
+ const REPO_DESCRIPTION = 'Boss Claude persistent memory store - session data, achievements, and XP progression';
7
+
8
+ /**
9
+ * Get GitHub token from environment or git config
10
+ */
11
+ function getGitHubToken() {
12
+ // Try environment variable first
13
+ if (process.env.GITHUB_TOKEN) {
14
+ return process.env.GITHUB_TOKEN;
15
+ }
16
+
17
+ // Try git config
18
+ try {
19
+ const token = execSync('git config --global github.token', {
20
+ encoding: 'utf8',
21
+ stdio: ['pipe', 'pipe', 'ignore']
22
+ }).trim();
23
+ if (token) return token;
24
+ } catch (error) {
25
+ // Ignore errors, will handle missing token below
26
+ }
27
+
28
+ return null;
29
+ }
30
+
31
+ /**
32
+ * Get current GitHub username
33
+ */
34
+ async function getGitHubUsername(octokit) {
35
+ try {
36
+ const { data } = await octokit.users.getAuthenticated();
37
+ return data.login;
38
+ } catch (error) {
39
+ throw new Error('Failed to get GitHub username. Please check your token.');
40
+ }
41
+ }
42
+
43
+ /**
44
+ * Check if repository exists
45
+ */
46
+ async function repositoryExists(octokit, owner, repo) {
47
+ try {
48
+ await octokit.repos.get({ owner, repo });
49
+ return true;
50
+ } catch (error) {
51
+ if (error.status === 404) {
52
+ return false;
53
+ }
54
+ throw error;
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Create private repository
60
+ */
61
+ async function createRepository(octokit, repo) {
62
+ try {
63
+ const { data } = await octokit.repos.createForAuthenticatedUser({
64
+ name: repo,
65
+ description: REPO_DESCRIPTION,
66
+ private: true,
67
+ auto_init: true,
68
+ has_issues: false,
69
+ has_projects: false,
70
+ has_wiki: false
71
+ });
72
+ return data;
73
+ } catch (error) {
74
+ if (error.status === 422) {
75
+ throw new Error(`Repository "${repo}" already exists or name is invalid`);
76
+ }
77
+ throw error;
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Update repository description and settings
83
+ */
84
+ async function updateRepository(octokit, owner, repo) {
85
+ try {
86
+ await octokit.repos.update({
87
+ owner,
88
+ repo,
89
+ description: REPO_DESCRIPTION,
90
+ private: true,
91
+ has_issues: false,
92
+ has_projects: false,
93
+ has_wiki: false
94
+ });
95
+ } catch (error) {
96
+ throw new Error(`Failed to update repository settings: ${error.message}`);
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Verify repository access and permissions
102
+ */
103
+ async function verifyAccess(octokit, owner, repo) {
104
+ try {
105
+ const { data } = await octokit.repos.get({ owner, repo });
106
+
107
+ const checks = {
108
+ exists: true,
109
+ isPrivate: data.private,
110
+ hasWriteAccess: data.permissions?.push || data.permissions?.admin,
111
+ url: data.html_url,
112
+ cloneUrl: data.clone_url
113
+ };
114
+
115
+ return checks;
116
+ } catch (error) {
117
+ if (error.status === 404) {
118
+ return {
119
+ exists: false,
120
+ isPrivate: false,
121
+ hasWriteAccess: false,
122
+ url: null,
123
+ cloneUrl: null
124
+ };
125
+ }
126
+ throw error;
127
+ }
128
+ }
129
+
130
+ /**
131
+ * Main setup function
132
+ */
133
+ export async function setupGitHubRepo(options = {}) {
134
+ const { verbose = false } = options;
135
+
136
+ const log = (msg, type = 'info') => {
137
+ if (!verbose && type === 'debug') return;
138
+
139
+ const prefix = {
140
+ info: chalk.blue('ℹ'),
141
+ success: chalk.green('✓'),
142
+ error: chalk.red('✗'),
143
+ debug: chalk.gray('→')
144
+ }[type] || '';
145
+
146
+ console.log(`${prefix} ${msg}`);
147
+ };
148
+
149
+ try {
150
+ // Step 1: Get GitHub token
151
+ const token = getGitHubToken();
152
+ if (!token) {
153
+ throw new Error(
154
+ 'GitHub token not found. Set GITHUB_TOKEN environment variable or run:\n' +
155
+ 'git config --global github.token YOUR_TOKEN'
156
+ );
157
+ }
158
+ log('GitHub token found', 'debug');
159
+
160
+ // Step 2: Initialize Octokit
161
+ const octokit = new Octokit({ auth: token });
162
+ log('Authenticated with GitHub', 'debug');
163
+
164
+ // Step 3: Get username
165
+ const username = await getGitHubUsername(octokit);
166
+ log(`GitHub user: ${username}`, 'debug');
167
+
168
+ // Step 4: Check if repo exists
169
+ log('Checking for existing repository...', 'debug');
170
+ const exists = await repositoryExists(octokit, username, REPO_NAME);
171
+
172
+ if (!exists) {
173
+ // Step 5: Create repository
174
+ log(`Creating private repository "${REPO_NAME}"...`, 'info');
175
+ const repo = await createRepository(octokit, REPO_NAME);
176
+ log(`Repository created: ${repo.html_url}`, 'success');
177
+ } else {
178
+ log(`Repository "${REPO_NAME}" already exists`, 'debug');
179
+
180
+ // Update description and ensure privacy
181
+ log('Updating repository settings...', 'debug');
182
+ await updateRepository(octokit, username, REPO_NAME);
183
+ log('Repository settings updated', 'debug');
184
+ }
185
+
186
+ // Step 6: Verify access
187
+ log('Verifying repository access...', 'debug');
188
+ const access = await verifyAccess(octokit, username, REPO_NAME);
189
+
190
+ if (!access.exists) {
191
+ throw new Error(`Repository verification failed: ${REPO_NAME} not found`);
192
+ }
193
+
194
+ if (!access.isPrivate) {
195
+ console.warn(chalk.yellow('⚠ Warning: Repository is public. Consider making it private.'));
196
+ }
197
+
198
+ if (!access.hasWriteAccess) {
199
+ throw new Error('No write access to repository. Check your permissions.');
200
+ }
201
+
202
+ log('Repository access verified', 'success');
203
+
204
+ return {
205
+ success: true,
206
+ owner: username,
207
+ repo: REPO_NAME,
208
+ url: access.url,
209
+ cloneUrl: access.cloneUrl,
210
+ isPrivate: access.isPrivate,
211
+ created: !exists
212
+ };
213
+
214
+ } catch (error) {
215
+ log(error.message, 'error');
216
+
217
+ return {
218
+ success: false,
219
+ error: error.message,
220
+ owner: null,
221
+ repo: REPO_NAME,
222
+ url: null,
223
+ cloneUrl: null,
224
+ isPrivate: false,
225
+ created: false
226
+ };
227
+ }
228
+ }
229
+
230
+ /**
231
+ * CLI-friendly wrapper
232
+ */
233
+ export async function setupGitHubRepoCommand() {
234
+ console.log(chalk.bold('\n🔧 Boss Claude GitHub Repository Setup\n'));
235
+
236
+ const result = await setupGitHubRepo({ verbose: true });
237
+
238
+ if (result.success) {
239
+ console.log(chalk.green.bold('\n✓ Setup Complete!\n'));
240
+ console.log(chalk.gray('Repository Details:'));
241
+ console.log(chalk.gray(' Owner:'), result.owner);
242
+ console.log(chalk.gray(' Name:'), result.repo);
243
+ console.log(chalk.gray(' URL:'), result.url);
244
+ console.log(chalk.gray(' Private:'), result.isPrivate ? chalk.green('Yes') : chalk.red('No'));
245
+ console.log(chalk.gray(' Status:'), result.created ? chalk.yellow('Created') : chalk.blue('Updated'));
246
+ } else {
247
+ console.log(chalk.red.bold('\n✗ Setup Failed\n'));
248
+ console.log(chalk.red(result.error));
249
+ process.exit(1);
250
+ }
251
+ }
252
+
253
+ // Export for testing
254
+ export { getGitHubToken, getGitHubUsername, repositoryExists, createRepository };