@lgcyaxi/oh-my-claude 1.0.0 → 1.1.1

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 (49) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +43 -0
  2. package/CHANGELOG.md +53 -0
  3. package/CLAUDE.md +60 -0
  4. package/README.md +97 -12
  5. package/README.zh-CN.md +58 -11
  6. package/bin/oh-my-claude.js +4 -2
  7. package/changelog/v1.0.0.md +28 -0
  8. package/changelog/v1.0.1.md +28 -0
  9. package/changelog/v1.1.0.md +20 -0
  10. package/changelog/v1.1.1.md +71 -0
  11. package/dist/cli.js +213 -4
  12. package/dist/hooks/comment-checker.js +1 -1
  13. package/dist/hooks/task-notification.js +124 -0
  14. package/dist/hooks/task-tracker.js +144 -0
  15. package/dist/index-1dv6t98k.js +7654 -0
  16. package/dist/index-5ars1tn4.js +7348 -0
  17. package/dist/index-d79fk9ah.js +7350 -0
  18. package/dist/index-hzm01rkh.js +7654 -0
  19. package/dist/index-qrbfj4cd.js +7664 -0
  20. package/dist/index-ypyx3ye0.js +7349 -0
  21. package/dist/index.js +24 -1
  22. package/dist/mcp/server.js +202 -45
  23. package/dist/statusline/statusline.js +146 -0
  24. package/package.json +6 -5
  25. package/src/agents/document-writer.ts +5 -0
  26. package/src/agents/explore.ts +5 -0
  27. package/src/agents/frontend-ui-ux.ts +5 -0
  28. package/src/agents/librarian.ts +5 -0
  29. package/src/agents/oracle.ts +5 -0
  30. package/src/agents/types.ts +11 -0
  31. package/src/cli.ts +261 -2
  32. package/src/commands/index.ts +8 -1
  33. package/src/commands/omc-status.md +71 -0
  34. package/src/commands/omcx-issue.md +175 -0
  35. package/src/commands/ulw.md +144 -0
  36. package/src/config/loader.ts +73 -0
  37. package/src/config/schema.ts +25 -2
  38. package/src/generators/agent-generator.ts +17 -1
  39. package/src/hooks/comment-checker.ts +2 -2
  40. package/src/hooks/task-notification.ts +206 -0
  41. package/src/hooks/task-tracker.ts +252 -0
  42. package/src/installer/index.ts +55 -4
  43. package/src/installer/settings-merger.ts +86 -0
  44. package/src/installer/statusline-merger.ts +169 -0
  45. package/src/mcp/background-agent-server/server.ts +11 -2
  46. package/src/mcp/background-agent-server/task-manager.ts +83 -4
  47. package/src/providers/router.ts +28 -0
  48. package/src/statusline/formatter.ts +164 -0
  49. package/src/statusline/statusline.ts +103 -0
@@ -108,6 +108,11 @@ export const exploreAgent: AgentDefinition = {
108
108
  executionMode: "mcp",
109
109
  category: "explorer",
110
110
  restrictedTools: ["Edit", "Write", "Task"],
111
+ fallback: {
112
+ provider: "claude",
113
+ model: "claude-haiku-4-5",
114
+ executionMode: "task",
115
+ },
111
116
  };
112
117
 
113
118
  export default exploreAgent;
@@ -101,6 +101,11 @@ export const frontendUiUxAgent: AgentDefinition = {
101
101
  defaultTemperature: 0.7,
102
102
  executionMode: "mcp",
103
103
  category: "specialist",
104
+ fallback: {
105
+ provider: "claude",
106
+ model: "claude-sonnet-4-5",
107
+ executionMode: "task",
108
+ },
104
109
  };
105
110
 
106
111
  export default frontendUiUxAgent;
@@ -211,6 +211,11 @@ export const librarianAgent: AgentDefinition = {
211
211
  executionMode: "mcp",
212
212
  category: "explorer",
213
213
  restrictedTools: ["Edit", "Write"],
214
+ fallback: {
215
+ provider: "claude",
216
+ model: "claude-sonnet-4-5",
217
+ executionMode: "task",
218
+ },
214
219
  };
215
220
 
216
221
  export default librarianAgent;
@@ -99,6 +99,11 @@ export const oracleAgent: AgentDefinition = {
99
99
  executionMode: "mcp",
100
100
  category: "advisor",
101
101
  restrictedTools: ["Edit", "Write", "Task"],
102
+ fallback: {
103
+ provider: "claude",
104
+ model: "claude-opus-4-5",
105
+ executionMode: "task",
106
+ },
102
107
  };
103
108
 
104
109
  export default oracleAgent;
@@ -2,6 +2,15 @@
2
2
  * Agent definition types for oh-my-claude
3
3
  */
4
4
 
5
+ export interface AgentFallback {
6
+ /** Fallback provider (usually "claude") */
7
+ provider: string;
8
+ /** Fallback model */
9
+ model: string;
10
+ /** Fallback execution mode (usually "task" for Claude) */
11
+ executionMode: "task" | "mcp";
12
+ }
13
+
5
14
  export interface AgentDefinition {
6
15
  /** Agent identifier (used in config) */
7
16
  name: string;
@@ -21,6 +30,8 @@ export interface AgentDefinition {
21
30
  category: "orchestrator" | "reviewer" | "scout" | "advisor" | "explorer" | "specialist" | "planner";
22
31
  /** Tools this agent should NOT use (restrictions) */
23
32
  restrictedTools?: string[];
33
+ /** Fallback configuration when primary provider API key is not available */
34
+ fallback?: AgentFallback;
24
35
  }
25
36
 
26
37
  export interface AgentMarkdownOptions {
package/src/cli.ts CHANGED
@@ -7,6 +7,7 @@
7
7
  * npx oh-my-claude uninstall # Uninstall oh-my-claude
8
8
  * npx oh-my-claude status # Check installation status
9
9
  * npx oh-my-claude doctor # Diagnose configuration issues
10
+ * npx oh-my-claude update # Update oh-my-claude to latest version
10
11
  * npx oh-my-claude setup-mcp # Install official MCP servers (MiniMax, GLM)
11
12
  */
12
13
 
@@ -18,7 +19,7 @@ import { loadConfig } from "./config";
18
19
  program
19
20
  .name("oh-my-claude")
20
21
  .description("Multi-agent orchestration plugin for Claude Code")
21
- .version("1.0.0");
22
+ .version("1.1.1");
22
23
 
23
24
  // Install command
24
25
  program
@@ -205,6 +206,7 @@ program
205
206
  console.log(` ${status.components.agents ? ok("Agent files generated") : fail("Agent files generated")}`);
206
207
  console.log(` ${status.components.hooks ? ok("Hooks configured") : fail("Hooks configured")}`);
207
208
  console.log(` ${status.components.mcp ? ok("MCP server configured") : fail("MCP server configured")}`);
209
+ console.log(` ${status.components.statusLine ? ok("StatusLine configured") : warn("StatusLine not configured")}`);
208
210
  console.log(` ${status.components.config ? ok("Configuration file exists") : fail("Configuration file exists")}`);
209
211
 
210
212
 
@@ -242,11 +244,13 @@ program
242
244
  "omc-explore",
243
245
  "omc-plan",
244
246
  "omc-start-work",
247
+ "omc-status",
245
248
  // Quick action commands
246
249
  "omcx-commit",
247
250
  "omcx-implement",
248
251
  "omcx-refactor",
249
252
  "omcx-docs",
253
+ "omcx-issue",
250
254
  ];
251
255
  console.log(` ${subheader("Agent commands (omc-):")}`);
252
256
  for (const cmd of expectedCommands.filter(c => c.startsWith("omc-"))) {
@@ -290,12 +294,43 @@ program
290
294
  // Hooks detail
291
295
  console.log(`\n${header("Hooks (detailed):")}`);
292
296
  const hooksDir = join(homedir(), ".claude", "oh-my-claude", "hooks");
293
- const expectedHooks = ["comment-checker.js", "todo-continuation.js"];
297
+ const expectedHooks = ["comment-checker.js", "todo-continuation.js", "task-notification.js"];
294
298
  for (const hook of expectedHooks) {
295
299
  const hookPath = join(hooksDir, hook);
296
300
  const exists = existsSync(hookPath);
297
301
  console.log(` ${exists ? ok(hook) : fail(hook)}`);
298
302
  }
303
+
304
+ // StatusLine detail
305
+ console.log(`\n${header("StatusLine (detailed):")}`);
306
+ const statusLineDir = join(homedir(), ".claude", "oh-my-claude", "dist", "statusline");
307
+ const statusLineScript = join(statusLineDir, "statusline.js");
308
+ const statusFileExists = existsSync(statusLineScript);
309
+ console.log(` ${statusFileExists ? ok("statusline.js installed") : fail("statusline.js not installed")}`);
310
+
311
+ try {
312
+ const settingsPath = join(homedir(), ".claude", "settings.json");
313
+ if (existsSync(settingsPath)) {
314
+ const settings = JSON.parse(require("node:fs").readFileSync(settingsPath, "utf-8"));
315
+ if (settings.statusLine) {
316
+ const cmd = settings.statusLine.command || "";
317
+ const isOurs = cmd.includes("oh-my-claude");
318
+ const isWrapper = cmd.includes("statusline-wrapper");
319
+ console.log(` ${ok("StatusLine configured in settings.json")}`);
320
+ if (isWrapper) {
321
+ console.log(` Mode: ${c.yellow}Merged (wrapper)${c.reset}`);
322
+ } else if (isOurs) {
323
+ console.log(` Mode: ${c.green}Direct${c.reset}`);
324
+ } else {
325
+ console.log(` Mode: ${c.cyan}External${c.reset}`);
326
+ }
327
+ } else {
328
+ console.log(` ${warn("StatusLine not configured in settings.json")}`);
329
+ }
330
+ }
331
+ } catch {
332
+ console.log(` ${fail("Failed to read settings.json")}`);
333
+ }
299
334
  }
300
335
 
301
336
  // Check providers
@@ -362,6 +397,230 @@ program
362
397
  }
363
398
  });
364
399
 
400
+ // Update command
401
+ program
402
+ .command("update")
403
+ .description("Update oh-my-claude to the latest version")
404
+ .option("--check", "Only check for updates without installing")
405
+ .option("--force", "Force update even if already on latest version")
406
+ .action(async (options) => {
407
+ const { execSync } = require("node:child_process");
408
+ const { readFileSync, existsSync } = require("node:fs");
409
+ const { join } = require("node:path");
410
+ const { homedir } = require("node:os");
411
+
412
+ // Color helpers
413
+ const useColor = process.stdout.isTTY;
414
+ const c = {
415
+ reset: useColor ? "\x1b[0m" : "",
416
+ bold: useColor ? "\x1b[1m" : "",
417
+ dim: useColor ? "\x1b[2m" : "",
418
+ green: useColor ? "\x1b[32m" : "",
419
+ red: useColor ? "\x1b[31m" : "",
420
+ yellow: useColor ? "\x1b[33m" : "",
421
+ cyan: useColor ? "\x1b[36m" : "",
422
+ magenta: useColor ? "\x1b[35m" : "",
423
+ };
424
+
425
+ const ok = (text: string) => `${c.green}✓${c.reset} ${text}`;
426
+ const fail = (text: string) => `${c.red}✗${c.reset} ${text}`;
427
+ const warn = (text: string) => `${c.yellow}⚠${c.reset} ${text}`;
428
+ const header = (text: string) => `${c.cyan}${c.bold}${text}${c.reset}`;
429
+ const dimText = (text: string) => `${c.dim}${text}${c.reset}`;
430
+
431
+ const PACKAGE_NAME = "@lgcyaxi/oh-my-claude";
432
+
433
+ console.log(`${c.bold}${c.magenta}oh-my-claude Update${c.reset}\n`);
434
+
435
+ // Get current version
436
+ let currentVersion = "unknown";
437
+ try {
438
+ // Try to read from package.json in the installed location
439
+ const installDir = join(homedir(), ".claude", "oh-my-claude");
440
+ const localPkgPath = join(installDir, "package.json");
441
+
442
+ if (existsSync(localPkgPath)) {
443
+ const pkg = JSON.parse(readFileSync(localPkgPath, "utf-8"));
444
+ currentVersion = pkg.version;
445
+ } else {
446
+ // Fall back to the version from the running CLI
447
+ currentVersion = program.version() || "unknown";
448
+ }
449
+ } catch (error) {
450
+ // Use the CLI version as fallback
451
+ currentVersion = program.version() || "unknown";
452
+ }
453
+
454
+ console.log(`Current version: ${c.cyan}${currentVersion}${c.reset}`);
455
+
456
+ // Fetch latest version from npm
457
+ let latestVersion = "unknown";
458
+ try {
459
+ console.log(`${dimText("Checking npm registry for latest version...")}`);
460
+ const npmInfo = execSync(`npm view ${PACKAGE_NAME} version 2>/dev/null`, {
461
+ encoding: "utf-8",
462
+ }).trim();
463
+ latestVersion = npmInfo;
464
+ console.log(`Latest version: ${c.cyan}${latestVersion}${c.reset}\n`);
465
+ } catch (error) {
466
+ console.log(`${fail("Failed to fetch latest version from npm")}`);
467
+ console.log(`${dimText("Check your internet connection or try again later")}\n`);
468
+ process.exit(1);
469
+ }
470
+
471
+ // Compare versions
472
+ const isUpToDate = currentVersion === latestVersion;
473
+ const needsUpdate = !isUpToDate || options.force;
474
+
475
+ if (isUpToDate && !options.force) {
476
+ console.log(ok("You are already on the latest version!"));
477
+ process.exit(0);
478
+ }
479
+
480
+ if (options.check) {
481
+ if (needsUpdate) {
482
+ console.log(warn(`Update available: ${currentVersion} → ${latestVersion}`));
483
+ console.log(`\nRun ${c.cyan}npx ${PACKAGE_NAME} update${c.reset} to update.`);
484
+ }
485
+ process.exit(0);
486
+ }
487
+
488
+ // Perform update
489
+ console.log(header("Updating oh-my-claude...\n"));
490
+
491
+ try {
492
+ // Step 1: Clear npx cache for the package
493
+ console.log(`${dimText("Clearing npx cache...")}`);
494
+ try {
495
+ execSync(`npx --yes clear-npx-cache 2>/dev/null || true`, { stdio: "pipe" });
496
+ } catch {
497
+ // Ignore errors - cache clear is optional
498
+ }
499
+
500
+ // Step 2: Install latest version via npx
501
+ console.log(`${dimText("Downloading latest version...")}`);
502
+
503
+ // Use npx with --yes to ensure latest version is fetched
504
+ // The @latest tag forces npm to check for the newest version
505
+ const updateCmd = `npx --yes ${PACKAGE_NAME}@latest install --force`;
506
+ console.log(`${dimText(`Running: ${updateCmd}`)}\n`);
507
+
508
+ execSync(updateCmd, { stdio: "inherit" });
509
+
510
+ console.log(`\n${ok("Update complete!")}`);
511
+ console.log(`Updated from ${c.yellow}${currentVersion}${c.reset} to ${c.green}${latestVersion}${c.reset}`);
512
+
513
+ // Show changelog hint
514
+ console.log(`\n${dimText("View changelog at: https://github.com/lgcyaxi/oh-my-claude/blob/main/CHANGELOG.md")}`);
515
+
516
+ } catch (error) {
517
+ console.log(`\n${fail("Update failed")}`);
518
+ console.log(`${dimText("Try running manually:")}`);
519
+ console.log(` ${c.cyan}npx ${PACKAGE_NAME}@latest install --force${c.reset}`);
520
+ process.exit(1);
521
+ }
522
+ });
523
+
524
+ // StatusLine command
525
+ program
526
+ .command("statusline")
527
+ .description("Manage statusline integration")
528
+ .option("--enable", "Enable statusline")
529
+ .option("--disable", "Disable statusline")
530
+ .option("--status", "Show current statusline configuration")
531
+ .action((options) => {
532
+ const { readFileSync, existsSync } = require("node:fs");
533
+ const { join } = require("node:path");
534
+ const { homedir } = require("node:os");
535
+
536
+ // Color helpers
537
+ const useColor = process.stdout.isTTY;
538
+ const c = {
539
+ reset: useColor ? "\x1b[0m" : "",
540
+ bold: useColor ? "\x1b[1m" : "",
541
+ dim: useColor ? "\x1b[2m" : "",
542
+ green: useColor ? "\x1b[32m" : "",
543
+ red: useColor ? "\x1b[31m" : "",
544
+ yellow: useColor ? "\x1b[33m" : "",
545
+ cyan: useColor ? "\x1b[36m" : "",
546
+ };
547
+
548
+ const ok = (text: string) => `${c.green}+${c.reset} ${text}`;
549
+ const fail = (text: string) => `${c.red}x${c.reset} ${text}`;
550
+ const warn = (text: string) => `${c.yellow}!${c.reset} ${text}`;
551
+
552
+ const settingsPath = join(homedir(), ".claude", "settings.json");
553
+
554
+ if (options.status || (!options.enable && !options.disable)) {
555
+ // Show status
556
+ console.log(`${c.bold}StatusLine Status${c.reset}\n`);
557
+
558
+ if (!existsSync(settingsPath)) {
559
+ console.log(fail("settings.json not found"));
560
+ process.exit(1);
561
+ }
562
+
563
+ try {
564
+ const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
565
+
566
+ if (!settings.statusLine) {
567
+ console.log(fail("StatusLine not configured"));
568
+ console.log(`\nRun ${c.cyan}oh-my-claude statusline --enable${c.reset} to enable.`);
569
+ } else {
570
+ const cmd = settings.statusLine.command || "";
571
+ const isOurs = cmd.includes("oh-my-claude");
572
+ const isWrapper = cmd.includes("statusline-wrapper");
573
+
574
+ console.log(ok("StatusLine configured"));
575
+ console.log(` Command: ${c.dim}${cmd}${c.reset}`);
576
+
577
+ if (isWrapper) {
578
+ console.log(` Mode: ${c.yellow}Merged (wrapper)${c.reset}`);
579
+ } else if (isOurs) {
580
+ console.log(` Mode: ${c.green}Direct${c.reset}`);
581
+ } else {
582
+ console.log(` Mode: ${c.cyan}External${c.reset}`);
583
+ }
584
+ }
585
+ } catch (error) {
586
+ console.log(fail(`Failed to read settings: ${error}`));
587
+ process.exit(1);
588
+ }
589
+ } else if (options.enable) {
590
+ // Enable statusline
591
+ const { installStatusLine } = require("./installer/settings-merger");
592
+ const { getStatusLineScriptPath } = require("./installer");
593
+
594
+ try {
595
+ const result = installStatusLine(getStatusLineScriptPath());
596
+ if (result.installed) {
597
+ console.log(ok("StatusLine enabled"));
598
+ if (result.wrapperCreated) {
599
+ console.log(warn("Wrapper created to merge with existing statusLine"));
600
+ }
601
+ }
602
+ } catch (error) {
603
+ console.log(fail(`Failed to enable statusline: ${error}`));
604
+ process.exit(1);
605
+ }
606
+ } else if (options.disable) {
607
+ // Disable statusline
608
+ const { uninstallStatusLine } = require("./installer/settings-merger");
609
+
610
+ try {
611
+ const result = uninstallStatusLine();
612
+ if (result) {
613
+ console.log(ok("StatusLine disabled"));
614
+ } else {
615
+ console.log(warn("StatusLine was not configured"));
616
+ }
617
+ } catch (error) {
618
+ console.log(fail(`Failed to disable statusline: ${error}`));
619
+ process.exit(1);
620
+ }
621
+ }
622
+ });
623
+
365
624
  // Setup MCP command
366
625
  program
367
626
  .command("setup-mcp")
@@ -18,6 +18,7 @@ export const agentCommands = [
18
18
  "omc-explore",
19
19
  "omc-plan",
20
20
  "omc-start-work",
21
+ "omc-status",
21
22
  ] as const;
22
23
 
23
24
  // Quick action commands (omcx- prefix)
@@ -26,10 +27,16 @@ export const actionCommands = [
26
27
  "omcx-implement",
27
28
  "omcx-refactor",
28
29
  "omcx-docs",
30
+ "omcx-issue",
31
+ ] as const;
32
+
33
+ // Special mode commands
34
+ export const modeCommands = [
35
+ "ulw", // Ultrawork mode - work until done
29
36
  ] as const;
30
37
 
31
38
  // All commands
32
- export const commands = [...agentCommands, ...actionCommands] as const;
39
+ export const commands = [...agentCommands, ...actionCommands, ...modeCommands] as const;
33
40
 
34
41
  export type CommandName = typeof commands[number];
35
42
 
@@ -0,0 +1,71 @@
1
+ # /omc-status
2
+
3
+ Display status dashboard for oh-my-claude MCP background agents.
4
+
5
+ ## Instructions
6
+
7
+ The user wants to see the current status of MCP background agents. Display a formatted ASCII dashboard showing:
8
+
9
+ 1. **Active Tasks** - Currently running background tasks
10
+ 2. **Provider Concurrency** - Usage bars for each provider
11
+ 3. **Recent Tasks** - Last 5 completed/failed tasks
12
+
13
+ **Step 1: Get system status**
14
+
15
+ ```
16
+ Use mcp__oh-my-claude-background__get_status to get:
17
+ - Provider configuration (which have API keys)
18
+ - Concurrency limits per provider
19
+ - Current active task counts
20
+ ```
21
+
22
+ **Step 2: Get task list**
23
+
24
+ ```
25
+ Use mcp__oh-my-claude-background__list_tasks with:
26
+ - limit: 20
27
+ (Gets recent tasks including running, completed, failed, fallback_required)
28
+ ```
29
+
30
+ **Step 3: Display dashboard**
31
+
32
+ Format the output as an ASCII dashboard:
33
+
34
+ ```
35
+ oh-my-claude Status Dashboard
36
+ ==============================
37
+
38
+ ACTIVE TASKS (count)
39
+ [agent] task_id... Provider [progress] status duration
40
+
41
+ PROVIDER CONCURRENCY
42
+ Provider: [bar] active/limit active, queued queued
43
+
44
+ RECENT TASKS (last 5)
45
+ [status] task_id agent time_ago
46
+ ```
47
+
48
+ **ASCII Progress Bar Helper:**
49
+
50
+ For concurrency bars, use:
51
+ - Full blocks: active tasks
52
+ - Empty blocks: remaining capacity
53
+ - 10 character width total
54
+
55
+ ```
56
+ Example: 4/10 active -> "4/10 active"
57
+ ```
58
+
59
+ **Status indicators:**
60
+ - `running` - Task is executing
61
+ - `completed` - Task finished successfully
62
+ - `failed` - Task encountered an error
63
+ - `fallback_required` - Provider API key not configured
64
+
65
+ **If no tasks:**
66
+ Display a message that no background tasks have been run yet, and suggest using `/omc-oracle` or other agent commands.
67
+
68
+ **If MCP server not available:**
69
+ Display an error message suggesting to run `oh-my-claude doctor` to check configuration.
70
+
71
+ Now gather the status and display the dashboard.
@@ -0,0 +1,175 @@
1
+ # /omcx-issue
2
+
3
+ Report a bug to oh-my-claude GitHub Issues.
4
+
5
+ ## Instructions
6
+
7
+ Create a bug report for the oh-my-claude project with auto-collected environment diagnostics.
8
+
9
+ ### Prerequisites Check
10
+
11
+ **FIRST**: Verify GitHub MCP is available by calling:
12
+ ```
13
+ mcp__plugin_github_github__get_me()
14
+ ```
15
+
16
+ If this fails or the tool is not available, display:
17
+ ```
18
+ GitHub MCP is not available. To report issues, you need the GitHub MCP plugin.
19
+
20
+ Install it with:
21
+ claude mcp add github -- npx -y @modelcontextprotocol/server-github
22
+
23
+ Or report manually at: https://github.com/lgcyaxi/oh-my-claude/issues/new
24
+ ```
25
+ Then stop execution.
26
+
27
+ ### Workflow
28
+
29
+ 1. **Collect Environment Diagnostics**
30
+
31
+ Run these commands to gather system info:
32
+ ```bash
33
+ # oh-my-claude version
34
+ oh-my-claude --version 2>/dev/null || npx @lgcyaxi/oh-my-claude --version 2>/dev/null || echo "unknown"
35
+
36
+ # OS info
37
+ uname -s -r
38
+
39
+ # Node.js version
40
+ node --version
41
+
42
+ # Bun version (optional)
43
+ bun --version 2>/dev/null || echo "not installed"
44
+
45
+ # Installation type detection
46
+ which oh-my-claude >/dev/null 2>&1 && echo "global" || echo "npx"
47
+
48
+ # Doctor output (sanitized)
49
+ oh-my-claude doctor --no-color 2>/dev/null || npx @lgcyaxi/oh-my-claude doctor --no-color 2>/dev/null || echo "doctor command failed"
50
+ ```
51
+
52
+ 2. **Gather Issue Details from User**
53
+
54
+ Ask the user for:
55
+ - Brief summary of the issue (1 line - used as title)
56
+ - What happened (actual behavior)
57
+ - What was expected
58
+ - Steps to reproduce (optional)
59
+ - Any additional context
60
+
61
+ 3. **Generate Issue Draft**
62
+
63
+ Format the issue body:
64
+ ```markdown
65
+ ## Description
66
+ [User's brief summary]
67
+
68
+ ## What happened
69
+ [User's actual behavior description]
70
+
71
+ ## Expected behavior
72
+ [User's expected behavior]
73
+
74
+ ## Steps to reproduce
75
+ [User's steps, or "N/A" if not provided]
76
+
77
+ ## Environment
78
+
79
+ | Component | Value |
80
+ |-----------|-------|
81
+ | oh-my-claude | [version] |
82
+ | OS | [os info] |
83
+ | Node.js | [version] |
84
+ | Bun | [version or "not installed"] |
85
+ | Installation | [global/npx] |
86
+
87
+ <details>
88
+ <summary>Doctor output</summary>
89
+
90
+ ```
91
+ [doctor command output - sanitized, no API keys]
92
+ ```
93
+
94
+ </details>
95
+
96
+ ## Additional context
97
+ [User's additional context, or "None"]
98
+
99
+ ---
100
+ *Reported via `/omcx-issue` command*
101
+ ```
102
+
103
+ 4. **Show Draft and Request Confirmation**
104
+
105
+ Display the complete issue to the user:
106
+ ```
107
+ Issue Draft
108
+ -----------
109
+
110
+ Title: [Bug] [summary]
111
+
112
+ [issue body]
113
+
114
+ -----------
115
+
116
+ Does this look correct?
117
+ - "yes" or "submit" to create the issue
118
+ - "edit" to modify before submitting
119
+ - "cancel" to abort
120
+ ```
121
+
122
+ 5. **Submit Issue**
123
+
124
+ On confirmation, create the issue:
125
+ ```
126
+ mcp__plugin_github_github__issue_write(
127
+ method: "create",
128
+ owner: "lgcyaxi",
129
+ repo: "oh-my-claude",
130
+ title: "[Bug] <user's summary>",
131
+ body: "<generated body>",
132
+ labels: ["bug", "user-reported"]
133
+ )
134
+ ```
135
+
136
+ 6. **Report Result**
137
+
138
+ On success:
139
+ ```
140
+ Issue created successfully!
141
+
142
+ View at: https://github.com/lgcyaxi/oh-my-claude/issues/<number>
143
+
144
+ Thank you for helping improve oh-my-claude!
145
+ ```
146
+
147
+ On failure:
148
+ ```
149
+ Failed to create issue: <error message>
150
+
151
+ You can report manually at: https://github.com/lgcyaxi/oh-my-claude/issues/new
152
+ ```
153
+
154
+ ### Important Notes
155
+
156
+ - Always sanitize doctor output - never include API keys
157
+ - Use `npx @lgcyaxi/oh-my-claude` as fallback when global command unavailable
158
+ - Labels "bug" and "user-reported" are applied automatically
159
+ - Issue title format: `[Bug] <user's summary>`
160
+
161
+ ### Arguments
162
+
163
+ `/omcx-issue [quick description]`
164
+
165
+ - If description provided: Use as the issue summary
166
+ - If no description: Prompt user for issue summary
167
+
168
+ ### Examples
169
+
170
+ ```
171
+ /omcx-issue commands not installing properly
172
+ /omcx-issue MCP server fails to connect
173
+ /omcx-issue oracle agent returns empty response
174
+ /omcx-issue
175
+ ```