@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,492 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Boss Claude Setup Wizard
5
+ * Interactive setup flow for first-time installation
6
+ */
7
+
8
+ import chalk from 'chalk';
9
+ import { existsSync, mkdirSync, writeFileSync } from 'fs';
10
+ import { join } from 'path';
11
+ import os from 'os';
12
+ import Redis from 'ioredis';
13
+ import pg from 'pg';
14
+ import { Octokit } from '@octokit/rest';
15
+ import {
16
+ header,
17
+ ask,
18
+ askSecret,
19
+ confirm,
20
+ spinner,
21
+ success,
22
+ error,
23
+ warning,
24
+ info,
25
+ box,
26
+ pause,
27
+ clear
28
+ } from './prompts.js';
29
+
30
+ const { Pool } = pg;
31
+
32
+ // Configuration
33
+ const BOSS_DIR = join(os.homedir(), '.boss-claude');
34
+ const ENV_FILE = join(BOSS_DIR, '.env');
35
+
36
+ /**
37
+ * Main setup wizard
38
+ */
39
+ async function runSetup() {
40
+ clear();
41
+
42
+ // Welcome screen
43
+ header(
44
+ '🎮 BOSS CLAUDE SETUP WIZARD',
45
+ 'Let\'s get you set up with your AI automation boss!'
46
+ );
47
+
48
+ box(
49
+ 'Boss Claude is a gamified AI assistant that tracks your\n' +
50
+ 'progress across all your projects. You earn XP, level up,\n' +
51
+ 'and build a token bank as you work with Claude.\n\n' +
52
+ 'This wizard will help you configure:\n' +
53
+ ' • GitHub integration (for session memory)\n' +
54
+ ' • Redis (for real-time stats)\n' +
55
+ ' • PostgreSQL (for advanced analytics)',
56
+ 'Welcome'
57
+ );
58
+
59
+ const shouldContinue = await confirm('\nReady to begin setup?', true);
60
+
61
+ if (!shouldContinue) {
62
+ console.log(chalk.yellow('\nSetup cancelled. Run "boss-claude setup" when ready!\n'));
63
+ process.exit(0);
64
+ }
65
+
66
+ // Create .boss-claude directory
67
+ if (!existsSync(BOSS_DIR)) {
68
+ mkdirSync(BOSS_DIR, { recursive: true });
69
+ success(`Created ${BOSS_DIR}`);
70
+ }
71
+
72
+ const config = {};
73
+
74
+ // Step 1: GitHub Token
75
+ await setupGitHub(config);
76
+
77
+ // Step 2: Redis
78
+ await setupRedis(config);
79
+
80
+ // Step 3: PostgreSQL
81
+ await setupPostgreSQL(config);
82
+
83
+ // Step 4: Save configuration
84
+ await saveConfig(config);
85
+
86
+ // Step 5: Test everything
87
+ await testConfiguration(config);
88
+
89
+ // Success!
90
+ showSuccessScreen();
91
+ }
92
+
93
+ /**
94
+ * Setup GitHub integration
95
+ */
96
+ async function setupGitHub(config) {
97
+ header('Step 1: GitHub Integration', 'Boss Claude uses GitHub Issues to store session memories');
98
+
99
+ info('Why GitHub?');
100
+ console.log(chalk.dim(' • Sessions are stored as searchable GitHub Issues'));
101
+ console.log(chalk.dim(' • Works across all your repositories'));
102
+ console.log(chalk.dim(' • Free and reliable long-term storage\n'));
103
+
104
+ const hasToken = await confirm('Do you already have a GitHub Personal Access Token?', false);
105
+
106
+ if (!hasToken) {
107
+ box(
108
+ 'Creating a GitHub Token:\n\n' +
109
+ '1. Go to: https://github.com/settings/tokens/new\n' +
110
+ '2. Note: "Boss Claude Session Memory"\n' +
111
+ '3. Scopes needed: repo (full control)\n' +
112
+ '4. Click "Generate token"\n' +
113
+ '5. Copy the token (it won\'t be shown again!)',
114
+ 'Instructions'
115
+ );
116
+
117
+ await pause();
118
+ }
119
+
120
+ // Get GitHub token
121
+ const githubToken = await askSecret('\nEnter your GitHub Personal Access Token');
122
+
123
+ if (!githubToken) {
124
+ error('GitHub token is required');
125
+ process.exit(1);
126
+ }
127
+
128
+ // Validate token
129
+ const githubResult = await spinner('Validating GitHub token', async () => {
130
+ const octokit = new Octokit({ auth: githubToken });
131
+ const { data: user } = await octokit.users.getAuthenticated();
132
+ return user;
133
+ });
134
+
135
+ if (!githubResult.success) {
136
+ error('Failed to validate GitHub token', githubResult.error.message);
137
+ process.exit(1);
138
+ }
139
+
140
+ success(`Authenticated as ${chalk.cyan(githubResult.result.login)}`);
141
+
142
+ config.GITHUB_TOKEN = githubToken;
143
+ config.GITHUB_USER = githubResult.result.login;
144
+ }
145
+
146
+ /**
147
+ * Setup Redis connection
148
+ */
149
+ async function setupRedis(config) {
150
+ header('Step 2: Redis Configuration', 'Redis stores real-time stats and session data');
151
+
152
+ info('Why Redis?');
153
+ console.log(chalk.dim(' • Fast real-time updates'));
154
+ console.log(chalk.dim(' • Efficient for frequently accessed data'));
155
+ console.log(chalk.dim(' • Great for leaderboards and stats\n'));
156
+
157
+ const hasRedis = await confirm('Do you have a Redis instance?', false);
158
+
159
+ if (!hasRedis) {
160
+ box(
161
+ 'Free Redis Options:\n\n' +
162
+ '1. Railway.app - redis.new (easiest!)\n' +
163
+ '2. Redis Cloud - redis.com/try-free\n' +
164
+ '3. Upstash - upstash.com (serverless)\n' +
165
+ '4. Local - brew install redis (macOS)\n\n' +
166
+ 'Connection string format:\n' +
167
+ 'redis://username:password@host:port',
168
+ 'Get Redis'
169
+ );
170
+
171
+ const setupLater = await confirm('\nWould you like to skip Redis for now?', false);
172
+
173
+ if (setupLater) {
174
+ warning('Skipping Redis. You can add it later by editing ~/.boss-claude/.env');
175
+ return;
176
+ }
177
+
178
+ await pause();
179
+ }
180
+
181
+ // Get Redis URL
182
+ const redisUrl = await ask('\nEnter Redis connection string', 'redis://localhost:6379');
183
+
184
+ // Validate Redis
185
+ const redisResult = await spinner('Testing Redis connection', async () => {
186
+ const client = new Redis(redisUrl);
187
+ await client.ping();
188
+ const info = await client.info('server');
189
+ await client.quit();
190
+ return info;
191
+ });
192
+
193
+ if (!redisResult.success) {
194
+ error('Failed to connect to Redis', redisResult.error.message);
195
+
196
+ const skipRedis = await confirm('\nContinue without Redis?', true);
197
+ if (!skipRedis) {
198
+ process.exit(1);
199
+ }
200
+ warning('Continuing without Redis. Some features will be limited.');
201
+ return;
202
+ }
203
+
204
+ success('Redis connection successful');
205
+ config.REDIS_URL = redisUrl;
206
+
207
+ // Initialize Redis data structures
208
+ const { setupRedisForWizard } = await import('../lib/setup/init-redis.js');
209
+ const initSuccess = await setupRedisForWizard(redisUrl, config.GITHUB_USER || 'default');
210
+
211
+ if (!initSuccess) {
212
+ const continueAnyway = await confirm('\nContinue with incomplete Redis setup?', true);
213
+ if (!continueAnyway) {
214
+ process.exit(1);
215
+ }
216
+ }
217
+ }
218
+
219
+ /**
220
+ * Setup PostgreSQL connection
221
+ */
222
+ async function setupPostgreSQL(config) {
223
+ header('Step 3: PostgreSQL Database', 'PostgreSQL provides advanced analytics and insights');
224
+
225
+ info('Why PostgreSQL?');
226
+ console.log(chalk.dim(' • Advanced session analytics'));
227
+ console.log(chalk.dim(' • Achievement tracking'));
228
+ console.log(chalk.dim(' • Historical data and trends\n'));
229
+
230
+ const hasPostgres = await confirm('Do you have a PostgreSQL database?', false);
231
+
232
+ if (!hasPostgres) {
233
+ box(
234
+ 'Free PostgreSQL Options:\n\n' +
235
+ '1. Railway.app - railway.app (recommended!)\n' +
236
+ '2. Supabase - supabase.com (includes UI)\n' +
237
+ '3. Neon - neon.tech (serverless)\n' +
238
+ '4. Local - brew install postgresql (macOS)\n\n' +
239
+ 'Connection string format:\n' +
240
+ 'postgresql://user:pass@host:port/database',
241
+ 'Get PostgreSQL'
242
+ );
243
+
244
+ const setupLater = await confirm('\nWould you like to skip PostgreSQL for now?', false);
245
+
246
+ if (setupLater) {
247
+ warning('Skipping PostgreSQL. Basic features will still work.');
248
+ return;
249
+ }
250
+
251
+ await pause();
252
+ }
253
+
254
+ // Get PostgreSQL URL
255
+ const postgresUrl = await ask('\nEnter PostgreSQL connection string');
256
+
257
+ if (!postgresUrl) {
258
+ warning('Skipping PostgreSQL. You can add it later.');
259
+ return;
260
+ }
261
+
262
+ // Validate PostgreSQL
263
+ const pgResult = await spinner('Testing PostgreSQL connection', async () => {
264
+ const pool = new Pool({
265
+ connectionString: postgresUrl,
266
+ ssl: { rejectUnauthorized: false }
267
+ });
268
+
269
+ const result = await pool.query('SELECT version()');
270
+ await pool.end();
271
+ return result.rows[0].version;
272
+ });
273
+
274
+ if (!pgResult.success) {
275
+ error('Failed to connect to PostgreSQL', pgResult.error.message);
276
+
277
+ const skipPg = await confirm('\nContinue without PostgreSQL?', true);
278
+ if (!skipPg) {
279
+ process.exit(1);
280
+ }
281
+ warning('Continuing without PostgreSQL. Some features will be limited.');
282
+ return;
283
+ }
284
+
285
+ success('PostgreSQL connection successful');
286
+ config.BOSS_CLAUDE_PG_URL = postgresUrl;
287
+
288
+ // Ask about schema setup
289
+ const shouldSetupSchema = await confirm('\nWould you like to set up the database schema now?', true);
290
+
291
+ if (shouldSetupSchema) {
292
+ await setupDatabaseSchema(postgresUrl);
293
+ } else {
294
+ info('You can set up the schema later by running: boss-claude db:setup');
295
+ }
296
+ }
297
+
298
+ /**
299
+ * Setup database schema
300
+ */
301
+ async function setupDatabaseSchema(postgresUrl) {
302
+ const schemaResult = await spinner('Creating database schema', async () => {
303
+ const pool = new Pool({
304
+ connectionString: postgresUrl,
305
+ ssl: { rejectUnauthorized: false }
306
+ });
307
+
308
+ // Create schema
309
+ await pool.query('CREATE SCHEMA IF NOT EXISTS boss_claude');
310
+
311
+ // Create sessions table
312
+ await pool.query(`
313
+ CREATE TABLE IF NOT EXISTS boss_claude.sessions (
314
+ id SERIAL PRIMARY KEY,
315
+ user_id TEXT NOT NULL,
316
+ project TEXT NOT NULL,
317
+ start_time TIMESTAMP DEFAULT NOW(),
318
+ end_time TIMESTAMP,
319
+ duration_seconds INTEGER GENERATED ALWAYS AS (
320
+ EXTRACT(EPOCH FROM (end_time - start_time))::INTEGER
321
+ ) STORED,
322
+ level_at_start INTEGER DEFAULT 1,
323
+ level_at_end INTEGER,
324
+ xp_earned INTEGER DEFAULT 0,
325
+ tokens_saved INTEGER DEFAULT 0,
326
+ tasks_completed INTEGER DEFAULT 0,
327
+ perfect_executions INTEGER DEFAULT 0,
328
+ efficiency_multiplier DECIMAL(3,2) DEFAULT 1.0,
329
+ summary TEXT,
330
+ context_data JSONB
331
+ )
332
+ `);
333
+
334
+ // Create achievements table
335
+ await pool.query(`
336
+ CREATE TABLE IF NOT EXISTS boss_claude.achievements (
337
+ id SERIAL PRIMARY KEY,
338
+ user_id TEXT NOT NULL,
339
+ achievement_type TEXT NOT NULL,
340
+ achievement_name TEXT NOT NULL,
341
+ description TEXT,
342
+ xp_reward INTEGER DEFAULT 0,
343
+ metadata JSONB,
344
+ earned_at TIMESTAMP DEFAULT NOW()
345
+ )
346
+ `);
347
+
348
+ // Create memory_snapshots table
349
+ await pool.query(`
350
+ CREATE TABLE IF NOT EXISTS boss_claude.memory_snapshots (
351
+ id SERIAL PRIMARY KEY,
352
+ user_id TEXT NOT NULL,
353
+ session_id INTEGER REFERENCES boss_claude.sessions(id),
354
+ snapshot_type TEXT NOT NULL,
355
+ snapshot_data JSONB NOT NULL,
356
+ level INTEGER,
357
+ token_bank INTEGER,
358
+ total_xp INTEGER,
359
+ efficiency DECIMAL(3,2),
360
+ created_at TIMESTAMP DEFAULT NOW()
361
+ )
362
+ `);
363
+
364
+ // Create indexes
365
+ await pool.query('CREATE INDEX IF NOT EXISTS idx_sessions_user_id ON boss_claude.sessions(user_id)');
366
+ await pool.query('CREATE INDEX IF NOT EXISTS idx_sessions_project ON boss_claude.sessions(project)');
367
+ await pool.query('CREATE INDEX IF NOT EXISTS idx_achievements_user_id ON boss_claude.achievements(user_id)');
368
+
369
+ await pool.end();
370
+ return true;
371
+ });
372
+
373
+ if (schemaResult.success) {
374
+ success('Database schema created successfully');
375
+ } else {
376
+ error('Failed to create database schema', schemaResult.error.message);
377
+ }
378
+ }
379
+
380
+ /**
381
+ * Save configuration to .env file
382
+ */
383
+ async function saveConfig(config) {
384
+ header('Saving Configuration', 'Writing settings to ~/.boss-claude/.env');
385
+
386
+ const envContent = Object.entries(config)
387
+ .map(([key, value]) => `${key}=${value}`)
388
+ .join('\n') + '\n';
389
+
390
+ await spinner('Saving configuration', async () => {
391
+ writeFileSync(ENV_FILE, envContent, 'utf-8');
392
+ return true;
393
+ });
394
+
395
+ success(`Configuration saved to ${ENV_FILE}`);
396
+ }
397
+
398
+ /**
399
+ * Test full configuration
400
+ */
401
+ async function testConfiguration(config) {
402
+ header('Testing Configuration', 'Verifying all connections');
403
+
404
+ const tests = [];
405
+
406
+ // Test GitHub
407
+ if (config.GITHUB_TOKEN) {
408
+ tests.push({
409
+ name: 'GitHub Authentication',
410
+ test: async () => {
411
+ const octokit = new Octokit({ auth: config.GITHUB_TOKEN });
412
+ await octokit.users.getAuthenticated();
413
+ }
414
+ });
415
+ }
416
+
417
+ // Test Redis
418
+ if (config.REDIS_URL) {
419
+ tests.push({
420
+ name: 'Redis Connection',
421
+ test: async () => {
422
+ const client = new Redis(config.REDIS_URL);
423
+ await client.ping();
424
+ await client.quit();
425
+ }
426
+ });
427
+ }
428
+
429
+ // Test PostgreSQL
430
+ if (config.BOSS_CLAUDE_PG_URL) {
431
+ tests.push({
432
+ name: 'PostgreSQL Connection',
433
+ test: async () => {
434
+ const pool = new Pool({
435
+ connectionString: config.BOSS_CLAUDE_PG_URL,
436
+ ssl: { rejectUnauthorized: false }
437
+ });
438
+ await pool.query('SELECT 1');
439
+ await pool.end();
440
+ }
441
+ });
442
+ }
443
+
444
+ // Run all tests
445
+ for (const test of tests) {
446
+ const result = await spinner(test.name, test.test);
447
+ if (!result.success) {
448
+ error(`${test.name} failed`, result.error.message);
449
+ }
450
+ }
451
+ }
452
+
453
+ /**
454
+ * Show success screen
455
+ */
456
+ function showSuccessScreen() {
457
+ clear();
458
+
459
+ header('🎉 Setup Complete!', 'Boss Claude is ready to go!');
460
+
461
+ box(
462
+ 'You\'re all set! Here\'s how to get started:\n\n' +
463
+ '1. Run "boss-claude init" in any git repository\n' +
464
+ '2. Use "boss-claude status" to check your stats\n' +
465
+ '3. Use "boss-claude save" to save sessions\n' +
466
+ '4. Use "boss-claude recall" to search memories\n\n' +
467
+ 'Boss Claude will auto-load in Claude Code and\n' +
468
+ 'track your progress across all projects.',
469
+ 'Next Steps'
470
+ );
471
+
472
+ success('Happy coding with Boss Claude!');
473
+
474
+ console.log(chalk.dim('\n💡 Tip: Add this to your project\'s CLAUDE.md:'));
475
+ box(
476
+ '# BOSS CLAUDE AUTO-LOAD\n' +
477
+ '```javascript\n' +
478
+ 'import { formatStatusForClaude } from \'@cpretzinger/boss-claude/lib/init.js\';\n' +
479
+ 'console.log(await formatStatusForClaude());\n' +
480
+ '```',
481
+ ''
482
+ );
483
+
484
+ console.log();
485
+ }
486
+
487
+ // Run setup
488
+ runSetup().catch((err) => {
489
+ console.error(chalk.red('\n❌ Setup failed:'), err.message);
490
+ console.error(chalk.dim(err.stack));
491
+ process.exit(1);
492
+ });
@@ -0,0 +1,17 @@
1
+ # Boss Claude Configuration
2
+ # Copy this file to ~/.boss-claude/.env and fill in your credentials
3
+
4
+ # Redis URL (required) - For Boss identity and session storage
5
+ REDIS_URL=redis://default:password@host:port
6
+
7
+ # GitHub Token (required) - For memory storage in GitHub Issues
8
+ # Create at: https://github.com/settings/tokens
9
+ # Needs: repo scope
10
+ GITHUB_TOKEN=ghp_your_token_here
11
+
12
+ # GitHub Owner (optional) - Defaults to 'cpretzinger'
13
+ GITHUB_OWNER=cpretzinger
14
+
15
+ # GitHub Memory Repository (optional) - Defaults to 'boss-claude-memory'
16
+ # This repo will store all your session memories as GitHub Issues
17
+ GITHUB_MEMORY_REPO=boss-claude-memory
package/lib/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # Boss Claude Libraries
2
+
3
+ Reusable modules for the Boss Claude CLI system.
4
+
5
+ ## Available Libraries
6
+
7
+ ### prompts.js - Interactive CLI Prompts
8
+
9
+ Beautiful, validated prompt system with colors and spinners.
10
+
11
+ **Quick Start:**
12
+
13
+ ```javascript
14
+ import prompts from './lib/prompts.js';
15
+
16
+ const name = await prompts.promptText({
17
+ message: 'Your name?',
18
+ validate: prompts.validators.required
19
+ });
20
+
21
+ prompts.success('Welcome, ' + name + '!');
22
+ ```
23
+
24
+ **Features:**
25
+ - Text, password, number input
26
+ - Select, multi-select
27
+ - Confirmations
28
+ - Built-in validators
29
+ - Beautiful colors and themes
30
+ - Loading spinners
31
+ - Progress indicators
32
+ - Preset prompt sequences
33
+
34
+ **Documentation:** See `/docs/PROMPTS.md`
35
+
36
+ **Examples:**
37
+ - `/examples/quick-test.js` - Simple test
38
+ - `/examples/prompts-demo.js` - Full demo
39
+ - `/examples/setup-wizard.js` - Real-world usage
40
+
41
+ **Run Examples:**
42
+
43
+ ```bash
44
+ npm run demo:quick # Quick test
45
+ npm run demo:prompts # Full demo
46
+ npm run demo:wizard # Setup wizard
47
+ ```
48
+
49
+ ## Creating New Libraries
50
+
51
+ 1. Create `/lib/your-library.js`
52
+ 2. Export functions/objects
53
+ 3. Add documentation to `/docs/YOUR-LIBRARY.md`
54
+ 4. Create examples in `/examples/`
55
+ 5. Update this README
56
+
57
+ ## Library Standards
58
+
59
+ - Use ES modules (`import`/`export`)
60
+ - Document all public functions
61
+ - Include JSDoc comments
62
+ - Provide usage examples
63
+ - Handle errors gracefully
64
+ - Use consistent naming
65
+ - Export default + named exports
66
+
67
+ ## Testing Libraries
68
+
69
+ Create test files in `/examples/` that demonstrate:
70
+ - Basic usage
71
+ - Error handling
72
+ - Edge cases
73
+ - Integration with other libraries
74
+
75
+ ## Dependencies
76
+
77
+ Libraries can use:
78
+ - inquirer (prompts)
79
+ - chalk (colors)
80
+ - ora (spinners)
81
+ - ioredis (Redis)
82
+ - pg (PostgreSQL)
83
+ - commander (CLI)
@@ -0,0 +1,61 @@
1
+ import { appendFileSync, mkdirSync } from 'fs';
2
+ import { join } from 'path';
3
+ import os from 'os';
4
+
5
+ const BOSS_DIR = join(os.homedir(), '.boss-claude');
6
+ const LOG_FILE = join(BOSS_DIR, 'agent-activity.log');
7
+
8
+ // Ensure directory exists
9
+ try {
10
+ mkdirSync(BOSS_DIR, { recursive: true });
11
+ } catch (err) {
12
+ // Directory already exists
13
+ }
14
+
15
+ /**
16
+ * Log agent activity to ~/.boss-claude/agent-activity.log
17
+ * @param {string} event - Event type (start, complete, error)
18
+ * @param {string} agent - Agent name
19
+ * @param {string} details - Additional details
20
+ */
21
+ export function logAgentActivity(event, agent, details = '') {
22
+ const timestamp = new Date().toISOString();
23
+ const logLine = `[${timestamp}] ${event.toUpperCase()}: ${agent}${details ? ' - ' + details : ''}\n`;
24
+
25
+ try {
26
+ appendFileSync(LOG_FILE, logLine, 'utf8');
27
+ } catch (err) {
28
+ // Silent fail - don't crash if logging fails
29
+ console.error(`Failed to write agent log: ${err.message}`);
30
+ }
31
+ }
32
+
33
+ /**
34
+ * Log Task agent start
35
+ * @param {string} taskDescription - Description of the task
36
+ */
37
+ export function logTaskStart(taskDescription) {
38
+ logAgentActivity('start', 'Task', taskDescription);
39
+ }
40
+
41
+ /**
42
+ * Log Task agent completion
43
+ * @param {string} taskDescription - Description of the task
44
+ * @param {boolean} success - Whether task succeeded
45
+ */
46
+ export function logTaskComplete(taskDescription, success = true) {
47
+ const status = success ? 'SUCCESS' : 'FAILED';
48
+ logAgentActivity('complete', 'Task', `${taskDescription} [${status}]`);
49
+ }
50
+
51
+ /**
52
+ * Log any agent activity
53
+ * @param {string} agentName - Name of the agent
54
+ * @param {string} action - Action being performed
55
+ * @param {string} details - Additional details
56
+ */
57
+ export function logAgent(agentName, action, details = '') {
58
+ logAgentActivity(action, agentName, details);
59
+ }
60
+
61
+ export { LOG_FILE };