hybard-agent 0.1.0

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/bin/agent.js ADDED
@@ -0,0 +1,673 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Hybard CLI — Professional autonomous coding assistant.
5
+ *
6
+ * Usage:
7
+ * hybard Interactive chat
8
+ * hybard "prompt" Single message
9
+ * hybard code "prompt" Generate and optionally save code
10
+ * hybard fix <file> Fix a file
11
+ * hybard explain <file> Explain code
12
+ * hybard search <query> Search codebase
13
+ * hybard project Show project info
14
+ * hybard network Show network status
15
+ * hybard help Show help
16
+ */
17
+
18
+ const path = require('path');
19
+ const fs = require('fs');
20
+ const os = require('os');
21
+ const readline = require('readline');
22
+ const { Engine, Git, Security, Production, Evaluator } = require('../lib/engine');
23
+ const { detectLocalIP, discoverHybardServer } = require('../lib/online');
24
+
25
+ const engine = new Engine();
26
+
27
+ // ─── Status Printer ──────────────────────────────────────
28
+
29
+ function status(msg) {
30
+ process.stdout.write(`\x1b[90m ${msg}\x1b[0m`);
31
+ }
32
+
33
+ function success(msg) {
34
+ console.log(`\x1b[32m ${msg}\x1b[0m`);
35
+ }
36
+
37
+ function info(msg) {
38
+ console.log(`\x1b[36m ${msg}\x1b[0m`);
39
+ }
40
+
41
+ function header(title) {
42
+ console.log();
43
+ console.log(`\x1b[1m${title}\x1b[0m`);
44
+ }
45
+
46
+ // ─── Interactive Chat ────────────────────────────────────
47
+
48
+ async function interactiveChat() {
49
+ const rl = readline.createInterface({
50
+ input: process.stdin,
51
+ output: process.stdout,
52
+ prompt: '\x1b[1mhybard\x1b[0m › ',
53
+ });
54
+
55
+ console.log();
56
+ console.log('\x1b[1m Hybard\x1b[0m \x1b[90mAutonomous Coding Assistant\x1b[0m');
57
+ console.log('\x1b[90m Type your request, or /help for commands.\x1b[0m');
58
+ console.log();
59
+
60
+ rl.prompt();
61
+
62
+ rl.on('line', async (line) => {
63
+ const input = line.trim();
64
+ if (!input) { rl.prompt(); return; }
65
+
66
+ // Slash commands
67
+ if (input === '/quit' || input === '/exit') {
68
+ console.log('\n\x1b[90m Goodbye.\x1b[0m\n');
69
+ rl.close();
70
+ return;
71
+ }
72
+
73
+ if (input === '/help') {
74
+ printChatHelp();
75
+ rl.prompt();
76
+ return;
77
+ }
78
+
79
+ if (input === '/clear') {
80
+ console.clear();
81
+ rl.prompt();
82
+ return;
83
+ }
84
+
85
+ if (input === '/project') {
86
+ printProjectInfo();
87
+ rl.prompt();
88
+ return;
89
+ }
90
+
91
+ if (input === '/network') {
92
+ await printNetworkInfo();
93
+ rl.prompt();
94
+ return;
95
+ }
96
+
97
+ if (input.startsWith('/search ')) {
98
+ const query = input.slice(8);
99
+ printSearchResults(query);
100
+ rl.prompt();
101
+ return;
102
+ }
103
+
104
+ // Normal message — autonomous processing
105
+ status('Thinking...');
106
+ try {
107
+ const response = await engine.process(input);
108
+ console.log();
109
+ console.log(response);
110
+ console.log();
111
+ } catch (err) {
112
+ console.log(`\n\x1b[31m Error: ${err.message}\x1b[0m\n`);
113
+ }
114
+ rl.prompt();
115
+ });
116
+
117
+ rl.on('close', () => process.exit(0));
118
+ }
119
+
120
+ // ─── Single-Shot Commands ────────────────────────────────
121
+
122
+ async function singleShot(prompt) {
123
+ status('Processing...');
124
+ try {
125
+ const response = await engine.process(prompt);
126
+ console.log();
127
+ console.log(response);
128
+ console.log();
129
+ } catch (err) {
130
+ console.error(`\n\x1b[31m Error: ${err.message}\x1b[0m\n`);
131
+ process.exit(1);
132
+ }
133
+ }
134
+
135
+ async function generateCode(prompt) {
136
+ status('Generating code...');
137
+
138
+ const system = `You are an expert programmer. Generate clean, working code.
139
+ Return ONLY the code in markdown code blocks with language tags.
140
+ Include filename as a comment at the top of each file.`;
141
+
142
+ try {
143
+ const response = await engine.ai.chat(prompt, { system });
144
+ console.log();
145
+ console.log(response);
146
+ console.log();
147
+
148
+ // Extract code blocks and offer to save
149
+ const blocks = extractCodeBlocks(response);
150
+ if (blocks.length > 0) {
151
+ console.log(`\x1b[90m Found ${blocks.length} code block(s)\x1b[0m`);
152
+ for (const b of blocks) {
153
+ console.log(` → ${b.filename} (${b.language})`);
154
+ }
155
+
156
+ const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
157
+ rl.question('\n Save to files? (y/n) ', async (answer) => {
158
+ if (answer.toLowerCase() === 'y') {
159
+ for (const block of blocks) {
160
+ const abs = path.resolve(block.filename);
161
+ const dir = path.dirname(abs);
162
+ if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
163
+ fs.writeFileSync(abs, block.code, 'utf8');
164
+ success(`Created ${block.filename}`);
165
+ }
166
+ console.log();
167
+ }
168
+ rl.close();
169
+ });
170
+ }
171
+ } catch (err) {
172
+ console.error(`\n\x1b[31m Error: ${err.message}\x1b[0m\n`);
173
+ process.exit(1);
174
+ }
175
+ }
176
+
177
+ async function fixFile(filePath) {
178
+ const abs = path.resolve(filePath);
179
+ if (!fs.existsSync(abs)) {
180
+ console.error(`\n\x1b[31m File not found: ${filePath}\x1b[0m\n`);
181
+ process.exit(1);
182
+ }
183
+
184
+ const content = fs.readFileSync(abs, 'utf8');
185
+ status(`Fixing ${filePath}...`);
186
+
187
+ try {
188
+ const system = `You are a debugging expert. Fix the given code.
189
+ Return ONLY the corrected code in a markdown code block.
190
+ Do not include explanations.`;
191
+
192
+ const response = await engine.ai.chat(
193
+ `Fix any issues in this code:\n\n\`\`\`\n${content}\n\`\`\``,
194
+ { system }
195
+ );
196
+
197
+ const blocks = extractCodeBlocks(response);
198
+ if (blocks.length > 0) {
199
+ // Backup original
200
+ fs.writeFileSync(abs + '.bak', content, 'utf8');
201
+ fs.writeFileSync(abs, blocks[0].code, 'utf8');
202
+ success(`Fixed ${filePath} (backup: ${filePath}.bak)`);
203
+ } else {
204
+ console.log('\n\x1b[33m No changes needed — file looks good.\x1b[0m\n');
205
+ }
206
+ } catch (err) {
207
+ console.error(`\n\x1b[31m Error: ${err.message}\x1b[0m\n`);
208
+ process.exit(1);
209
+ }
210
+ }
211
+
212
+ async function explainFile(filePath) {
213
+ const abs = path.resolve(filePath);
214
+ if (!fs.existsSync(abs)) {
215
+ console.error(`\n\x1b[31m File not found: ${filePath}\x1b[0m\n`);
216
+ process.exit(1);
217
+ }
218
+
219
+ const content = fs.readFileSync(abs, 'utf8');
220
+ status(`Analyzing ${filePath}...`);
221
+
222
+ try {
223
+ const system = `You are a code analyst. Explain the given code clearly.
224
+ Cover: what it does, how it works, key patterns, and potential issues.
225
+ Be concise but thorough.`;
226
+
227
+ const response = await engine.ai.chat(
228
+ `Explain this code:\n\n\`\`\`\n${content}\n\`\`\``,
229
+ { system }
230
+ );
231
+
232
+ console.log();
233
+ console.log(response);
234
+ console.log();
235
+ } catch (err) {
236
+ console.error(`\n\x1b[31m Error: ${err.message}\x1b[0m\n`);
237
+ process.exit(1);
238
+ }
239
+ }
240
+
241
+ function searchCodebase(query) {
242
+ status(`Searching for "${query}"...`);
243
+ const result = engine.executeTool('search_code', { query });
244
+
245
+ if (!result.ok || result.count === 0) {
246
+ console.log('\n\x1b[90m No results found.\x1b[0m\n');
247
+ return;
248
+ }
249
+
250
+ console.log();
251
+ console.log(` Found ${result.count} match(es) in ${result.results.length} file(s):\n`);
252
+ for (const r of result.results.slice(0, 10)) {
253
+ console.log(` \x1b[36m${r.file}\x1b[0m`);
254
+ for (const m of r.matches.slice(0, 3)) {
255
+ console.log(` L${m.line}: ${m.content.slice(0, 100)}`);
256
+ }
257
+ }
258
+ console.log();
259
+ }
260
+
261
+ function printProjectInfo() {
262
+ const result = engine.executeTool('detect_project', {});
263
+ if (!result.ok) {
264
+ console.log('\n\x1b[90m No project detected.\x1b[0m\n');
265
+ return;
266
+ }
267
+ console.log();
268
+ console.log(' \x1b[1mProject Info\x1b[0m');
269
+ console.log(` Type: ${result.type}`);
270
+ console.log(` Languages: ${result.languages.join(', ') || 'Unknown'}`);
271
+ console.log(` Frameworks: ${result.frameworks.join(', ') || 'None'}`);
272
+ console.log(` Entry: ${result.entryPoints.join(', ') || 'None'}`);
273
+ console.log(` Config: ${result.configFiles.join(', ') || 'None'}`);
274
+ console.log();
275
+ }
276
+
277
+ async function printNetworkInfo() {
278
+ const localIP = detectLocalIP();
279
+ console.log();
280
+ console.log(' \x1b[1mNetwork Status\x1b[0m');
281
+ console.log(` Local IP: ${localIP}`);
282
+ console.log(` Server: http://${localIP}:8000`);
283
+ console.log(` Endpoint: http://${localIP}:8000/v1/chat/completions`);
284
+ console.log(` Health: http://${localIP}:8000/health`);
285
+ console.log(` Platform: ${os.platform()} ${os.arch()}`);
286
+ console.log(` CPU: ${os.cpus().length} cores`);
287
+ console.log(` RAM: ${(os.totalmem() / (1024 ** 3)).toFixed(1)} GB`);
288
+ try {
289
+ const server = await discoverHybardServer();
290
+ console.log(` Status: ${server ? '\x1b[32mONLINE\x1b[0m' : '\x1b[31mOFFLINE\x1b[0m'}`);
291
+ } catch (e) {
292
+ console.log(' Status: \x1b[33mUNKNOWN\x1b[0m');
293
+ }
294
+ console.log();
295
+ }
296
+
297
+ function printSearchResults(query) {
298
+ searchCodebase(query);
299
+ }
300
+
301
+ // ─── Helpers ─────────────────────────────────────────────
302
+
303
+ function extractCodeBlocks(text) {
304
+ const blocks = [];
305
+ const regex = /```(\w*)\n([\s\S]*?)```/g;
306
+ let match;
307
+ while ((match = regex.exec(text)) !== null) {
308
+ const lang = match[1] || 'txt';
309
+ const code = match[2].trim();
310
+ // Try to extract filename from code comment
311
+ const fileMatch = code.match(/(?:#|\/\/|\/\*+|<!--)\s*(?:filename|file|path)[:\s]+(.+\.\w+)/i);
312
+ const filename = fileMatch ? fileMatch[1].trim() : `generated.${extMap[lang] || 'txt'}`;
313
+ blocks.push({ language: lang, code, filename });
314
+ }
315
+ return blocks;
316
+ }
317
+
318
+ const extMap = {
319
+ python: 'py', javascript: 'js', typescript: 'ts', dart: 'dart',
320
+ html: 'html', css: 'css', sql: 'sql', bash: 'sh', json: 'json',
321
+ };
322
+
323
+ function printChatHelp() {
324
+ console.log(`
325
+ \x1b[1mCommands:\x1b[0m
326
+ /help Show this help
327
+ /project Show project info
328
+ /network Show network status
329
+ /search <q> Search codebase
330
+ /clear Clear screen
331
+ /quit Exit
332
+
333
+ \x1b[1mTips:\x1b[0m
334
+ Just type naturally — the agent understands context.
335
+ Example: "Add a login page to my React app"
336
+ Example: "একটা Python calculator বানাও"
337
+ Example: "Fix the bug in src/utils.js"
338
+ `);
339
+ }
340
+
341
+ // ─── Git Commands ─────────────────────────────────────────
342
+
343
+ function printGitStatus() {
344
+ const s = Git.statusSummary();
345
+ if (!s.isRepo) {
346
+ console.log('\n\x1b[90m Not a git repository.\x1b[0m\n');
347
+ return;
348
+ }
349
+ console.log();
350
+ console.log(' \x1b[1mGit Status\x1b[0m');
351
+ console.log(` Branch: ${s.branch}`);
352
+ console.log(` Modified: ${s.modified.length ? s.modified.join(', ') : 'none'}`);
353
+ console.log(` Added: ${s.added.length ? s.added.join(', ') : 'none'}`);
354
+ console.log(` Deleted: ${s.deleted.length ? s.deleted.join(', ') : 'none'}`);
355
+ console.log();
356
+ }
357
+
358
+ function printGitDiff(file) {
359
+ const result = file ? Git.diffFile(file) : Git.diff();
360
+ if (!result.ok || !result.stdout) {
361
+ console.log('\n\x1b[90m No changes.\x1b[0m\n');
362
+ return;
363
+ }
364
+ console.log();
365
+ console.log(result.stdout);
366
+ console.log();
367
+ }
368
+
369
+ function printGitLog(n) {
370
+ const result = Git.log(n);
371
+ if (!result.ok) {
372
+ console.log('\n\x1b[90m No git history.\x1b[0m\n');
373
+ return;
374
+ }
375
+ console.log();
376
+ console.log(' \x1b[1mRecent Commits\x1b[0m');
377
+ result.stdout.split('\n').forEach(line => console.log(` ${line}`));
378
+ console.log();
379
+ }
380
+
381
+ function gitCommit(message) {
382
+ status('Committing...');
383
+ const result = Git.commit(message);
384
+ if (result.ok) {
385
+ success(`Committed: ${message}`);
386
+ } else {
387
+ console.log(`\n\x1b[31m Commit failed: ${result.stderr}\x1b[0m\n`);
388
+ }
389
+ }
390
+
391
+ function printGitBranches() {
392
+ const result = Git.branches();
393
+ if (!result.ok) {
394
+ console.log('\n\x1b[90m No branches.\x1b[0m\n');
395
+ return;
396
+ }
397
+ console.log();
398
+ result.stdout.split('\n').forEach(line => {
399
+ const trimmed = line.trim();
400
+ if (trimmed.startsWith('*')) {
401
+ console.log(` \x1b[32m${trimmed}\x1b[0m`);
402
+ } else if (trimmed) {
403
+ console.log(` ${trimmed}`);
404
+ }
405
+ });
406
+ console.log();
407
+ }
408
+
409
+ function gitRollback(n) {
410
+ status(`Rolling back ${n} commit(s)...`);
411
+ const result = Git.rollback(n);
412
+ if (result.ok) {
413
+ success(`Rolled back ${n} commit(s)`);
414
+ } else {
415
+ console.log(`\n\x1b[31m Rollback failed: ${result.stderr}\x1b[0m\n`);
416
+ }
417
+ }
418
+
419
+ // ─── Security Commands ───────────────────────────────────
420
+
421
+ function securityScan(filePath) {
422
+ status(`Scanning ${filePath}...`);
423
+ const abs = path.resolve(filePath);
424
+ if (fs.existsSync(abs) && fs.statSync(abs).isFile()) {
425
+ const result = engine.executeTool('security_scan', { path: filePath });
426
+ console.log();
427
+ if (result.hasIssues) {
428
+ console.log(' \x1b[31mSecurity Issues Found:\x1b[0m');
429
+ result.secrets.forEach(s => console.log(` ⚠ ${s}`));
430
+ } else {
431
+ console.log(' \x1b[32mNo security issues found.\x1b[0m');
432
+ }
433
+ console.log();
434
+ } else {
435
+ // Scan all files in directory
436
+ const searcher = new (require('../lib/hybard-agent').CodebaseSearch)(process.cwd());
437
+ const files = searcher.findFiles('.').slice(0, 20);
438
+ let totalIssues = 0;
439
+ console.log();
440
+ for (const f of files) {
441
+ const result = engine.executeTool('security_scan', { path: f });
442
+ if (result.hasIssues) {
443
+ console.log(` \x1b[31m${f}:\x1b[0m`);
444
+ result.secrets.forEach(s => console.log(` ⚠ ${s}`));
445
+ totalIssues += result.secrets.length;
446
+ }
447
+ }
448
+ if (totalIssues === 0) {
449
+ console.log(' \x1b[32mNo security issues found in project.\x1b[0m');
450
+ } else {
451
+ console.log(`\n \x1b[31m${totalIssues} issue(s) found.\x1b[0m`);
452
+ }
453
+ console.log();
454
+ }
455
+ }
456
+
457
+ function securityValidate(input) {
458
+ const result = Security.validateInput(input);
459
+ console.log();
460
+ if (result.ok) {
461
+ console.log(' \x1b[32mInput is safe.\x1b[0m');
462
+ } else {
463
+ console.log(` \x1b[31m${result.reason}\x1b[0m`);
464
+ }
465
+ console.log();
466
+ }
467
+
468
+ // ─── Production Commands ─────────────────────────────────
469
+
470
+ function printSystemHealth() {
471
+ const health = Production.healthCheck();
472
+ const info = Production.getSystemInfo();
473
+ console.log();
474
+ console.log(' \x1b[1mSystem Health\x1b[0m');
475
+ const statusColor = health.status === 'healthy' ? '\x1b[32m' : health.status === 'warning' ? '\x1b[33m' : '\x1b[31m';
476
+ console.log(` Status: ${statusColor}${health.status.toUpperCase()}\x1b[0m`);
477
+ console.log(` Memory: ${health.memory}`);
478
+ console.log(` CPU: ${health.cpu}`);
479
+ console.log(` Uptime: ${health.uptime}`);
480
+ console.log(` Platform: ${info.platform} ${info.arch}`);
481
+ console.log(` Node: ${info.nodeVersion}`);
482
+ console.log(` Hostname: ${info.hostname}`);
483
+ console.log();
484
+ }
485
+
486
+ // ─── Evaluation Commands ─────────────────────────────────
487
+
488
+ function evalCode(filePath) {
489
+ const abs = path.resolve(filePath);
490
+ if (!fs.existsSync(abs)) {
491
+ console.error(`\n\x1b[31m File not found: ${filePath}\x1b[0m\n`);
492
+ process.exit(1);
493
+ }
494
+ const content = fs.readFileSync(abs, 'utf8');
495
+ const ext = path.extname(filePath).slice(1);
496
+ const langMap = { py: 'python', js: 'javascript', ts: 'typescript', dart: 'dart', sql: 'sql' };
497
+ const lang = langMap[ext] || 'python';
498
+
499
+ const result = Evaluator.evaluateCode(content, lang);
500
+ console.log();
501
+ console.log(' \x1b[1mCode Evaluation\x1b[0m');
502
+ const scoreColor = result.score >= 80 ? '\x1b[32m' : result.score >= 50 ? '\x1b[33m' : '\x1b[31m';
503
+ console.log(` Score: ${scoreColor}${result.score}/100\x1b[0m`);
504
+ console.log(` Lines: ${result.metrics.lines}`);
505
+ console.log(` Comments: ${result.metrics.commentRatio}`);
506
+ console.log(` Docstring: ${result.metrics.hasDocstring ? 'Yes' : 'No'}`);
507
+ console.log(` Type Hints: ${result.metrics.hasTypeHints ? 'Yes' : 'No'}`);
508
+ if (result.issues.length > 0) {
509
+ console.log(' Issues:');
510
+ result.issues.forEach(i => console.log(` ⚠ ${i}`));
511
+ } else {
512
+ console.log(' \x1b[32mNo issues found.\x1b[0m');
513
+ }
514
+ console.log();
515
+ }
516
+
517
+ // ─── Main ────────────────────────────────────────────────
518
+
519
+ async function main() {
520
+ const args = process.argv.slice(2);
521
+
522
+ if (args.length === 0) {
523
+ await interactiveChat();
524
+ return;
525
+ }
526
+
527
+ const cmd = args[0].toLowerCase();
528
+ const rest = args.slice(1).join(' ');
529
+
530
+ switch (cmd) {
531
+ case 'help': case '--help': case '-h':
532
+ printFullHelp();
533
+ break;
534
+ case 'code': case 'generate':
535
+ if (!rest) { console.error('\n Usage: hybard code "description"\n'); process.exit(1); }
536
+ await generateCode(rest);
537
+ break;
538
+ case 'fix':
539
+ if (!rest) { console.error('\n Usage: hybard fix <file>\n'); process.exit(1); }
540
+ await fixFile(rest);
541
+ break;
542
+ case 'explain':
543
+ if (!rest) { console.error('\n Usage: hybard explain <file>\n'); process.exit(1); }
544
+ await explainFile(rest);
545
+ break;
546
+ case 'search': case 'find':
547
+ if (!rest) { console.error('\n Usage: hybard search <query>\n'); process.exit(1); }
548
+ searchCodebase(rest);
549
+ break;
550
+ case 'project': case 'info':
551
+ printProjectInfo();
552
+ break;
553
+ case 'network': case 'server': case 'status':
554
+ await printNetworkInfo();
555
+ break;
556
+ case 'run':
557
+ if (!rest) { console.error('\n Usage: hybard run <command>\n'); process.exit(1); }
558
+ const result = engine.executeTool('run_command', { command: rest });
559
+ if (result.ok) console.log(result.stdout);
560
+ else console.error(result.stderr || result.error);
561
+ break;
562
+
563
+ case 'git':
564
+ case 'g':
565
+ {
566
+ const sub = (args[1] || 'status').toLowerCase();
567
+ switch (sub) {
568
+ case 'status': case 'st':
569
+ printGitStatus();
570
+ break;
571
+ case 'diff': case 'd':
572
+ printGitDiff(args[2]);
573
+ break;
574
+ case 'log':
575
+ printGitLog(parseInt(args[2]) || 10);
576
+ break;
577
+ case 'commit': case 'ci':
578
+ if (!args[2]) { console.error('\n Usage: hybard git commit "message"\n'); process.exit(1); }
579
+ gitCommit(args.slice(2).join(' '));
580
+ break;
581
+ case 'branch': case 'b':
582
+ printGitBranches();
583
+ break;
584
+ case 'rollback': case 'rb':
585
+ gitRollback(parseInt(args[2]) || 1);
586
+ break;
587
+ default:
588
+ printGitStatus();
589
+ }
590
+ }
591
+ break;
592
+
593
+ case 'security': case 'sec':
594
+ {
595
+ const sub = (args[1] || 'scan').toLowerCase();
596
+ switch (sub) {
597
+ case 'scan':
598
+ if (!args[2]) { console.error('\n Usage: hybard security scan <file>\n'); process.exit(1); }
599
+ securityScan(args[2]);
600
+ break;
601
+ case 'validate':
602
+ if (!args[2]) { console.error('\n Usage: hybard security validate "input"\n'); process.exit(1); }
603
+ securityValidate(args.slice(2).join(' '));
604
+ break;
605
+ default:
606
+ securityScan(args[2] || '.');
607
+ }
608
+ }
609
+ break;
610
+
611
+ case 'health': case 'sys':
612
+ printSystemHealth();
613
+ break;
614
+
615
+ case 'eval':
616
+ if (!rest) { console.error('\n Usage: hybard eval <file>\n'); process.exit(1); }
617
+ evalCode(rest);
618
+ break;
619
+
620
+ default:
621
+ await singleShot(args.join(' '));
622
+ break;
623
+ }
624
+ }
625
+
626
+ function printFullHelp() {
627
+ console.log(`
628
+ \x1b[1mHybard\x1b[0m \x1b[90mAutonomous Coding Assistant\x1b[0m
629
+
630
+ \x1b[1mUsage:\x1b[0m
631
+ hybard Interactive chat
632
+ hybard "prompt" Single message
633
+ hybard code "prompt" Generate code
634
+ hybard fix <file> Fix a file
635
+ hybard explain <file> Explain code
636
+ hybard search <query> Search codebase
637
+ hybard project Project info
638
+ hybard network Network status
639
+ hybard run <command> Run shell command
640
+
641
+ \x1b[1mGit:\x1b[0m
642
+ hybard git status Show git status
643
+ hybard git diff [file] Show changes
644
+ hybard git log [n] Show recent commits
645
+ hybard git commit "msg" Stage all & commit
646
+ hybard git branch List branches
647
+ hybard git rollback [n] Rollback N commits
648
+
649
+ \x1b[1mSecurity:\x1b[0m
650
+ hybard security scan <f> Scan for secrets/vulnerabilities
651
+ hybard security validate "input" Check for prompt injection
652
+
653
+ \x1b[1mProduction:\x1b[0m
654
+ hybard health System health check
655
+
656
+ \x1b[1mEvaluation:\x1b[0m
657
+ hybard eval <file> Evaluate code quality
658
+
659
+ \x1b[1mExamples:\x1b[0m
660
+ hybard code "create a Python login page"
661
+ hybard code "একটা Flutter app বানাও"
662
+ hybard git status
663
+ hybard git commit "add login feature"
664
+ hybard security scan src/auth.py
665
+ hybard health
666
+ hybard eval lib/engine.js
667
+ `);
668
+ }
669
+
670
+ main().catch(err => {
671
+ console.error(`\n\x1b[31m Fatal: ${err.message}\x1b[0m\n`);
672
+ process.exit(1);
673
+ });