@lgcyaxi/oh-my-claude 1.0.1 → 1.1.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.
package/dist/index.js CHANGED
@@ -39,6 +39,10 @@ import {
39
39
  getMcpServerPath,
40
40
  getProviderDetails,
41
41
  getProvidersStatus,
42
+ getStatusLineScriptPath,
43
+ init_agent_generator,
44
+ init_agents,
45
+ init_installer,
42
46
  install,
43
47
  isMcpAgent,
44
48
  isProviderConfigured,
@@ -58,7 +62,10 @@ import {
58
62
  sisyphusAgent,
59
63
  taskAgents,
60
64
  uninstall
61
- } from "./index-5ars1tn4.js";
65
+ } from "./index-814gp2s3.js";
66
+
67
+ // src/index.ts
68
+ init_agents();
62
69
  // src/providers/deepseek.ts
63
70
  var DEEPSEEK_BASE_URL = "https://api.deepseek.com/anthropic";
64
71
  var DEEPSEEK_API_KEY_ENV = "DEEPSEEK_API_KEY";
@@ -80,6 +87,11 @@ function createMiniMaxClient() {
80
87
  return createAnthropicClientFromEnv("MiniMax", MINIMAX_BASE_URL, MINIMAX_API_KEY_ENV, "MiniMax-M2.1");
81
88
  }
82
89
  var minimaxClient = createMiniMaxClient();
90
+ // src/generators/index.ts
91
+ init_agent_generator();
92
+
93
+ // src/index.ts
94
+ init_installer();
83
95
  export {
84
96
  zhipuClient,
85
97
  uninstall,
@@ -103,6 +115,7 @@ export {
103
115
  isProviderConfigured,
104
116
  isMcpAgent,
105
117
  install,
118
+ getStatusLineScriptPath,
106
119
  getProvidersStatus,
107
120
  getProviderDetails,
108
121
  getMcpServerPath,
@@ -18573,10 +18573,65 @@ function getAgent(name) {
18573
18573
  }
18574
18574
 
18575
18575
  // src/mcp/background-agent-server/task-manager.ts
18576
+ import { writeFileSync, mkdirSync, existsSync as existsSync2 } from "node:fs";
18577
+ import { join as join2, dirname } from "node:path";
18578
+ import { homedir as homedir2 } from "node:os";
18579
+
18580
+ // src/mcp/background-agent-server/concurrency.ts
18581
+ var activeCounts = new Map;
18582
+ var queues = new Map;
18583
+ function getConcurrencyLimit(provider) {
18584
+ const config2 = loadConfig();
18585
+ const perProvider = config2.concurrency.per_provider?.[provider];
18586
+ if (perProvider !== undefined) {
18587
+ return perProvider;
18588
+ }
18589
+ return config2.concurrency.default;
18590
+ }
18591
+ function getActiveCount(provider) {
18592
+ return activeCounts.get(provider) ?? 0;
18593
+ }
18594
+ function getConcurrencyStatus() {
18595
+ const config2 = loadConfig();
18596
+ const status = {};
18597
+ const providers = Object.keys(config2.providers);
18598
+ for (const provider of providers) {
18599
+ status[provider] = {
18600
+ active: getActiveCount(provider),
18601
+ limit: getConcurrencyLimit(provider),
18602
+ queued: queues.get(provider)?.length ?? 0
18603
+ };
18604
+ }
18605
+ return status;
18606
+ }
18607
+
18608
+ // src/mcp/background-agent-server/task-manager.ts
18609
+ var STATUS_FILE_PATH = join2(homedir2(), ".claude", "oh-my-claude", "status.json");
18576
18610
  var tasks = new Map;
18577
18611
  function generateTaskId() {
18578
18612
  return `task_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
18579
18613
  }
18614
+ function updateStatusFile() {
18615
+ try {
18616
+ const dir = dirname(STATUS_FILE_PATH);
18617
+ if (!existsSync2(dir)) {
18618
+ mkdirSync(dir, { recursive: true });
18619
+ }
18620
+ const activeTasks = Array.from(tasks.values()).filter((t) => t.status === "running" || t.status === "pending").map((t) => ({
18621
+ agent: t.agentName || t.categoryName || "unknown",
18622
+ startedAt: t.startedAt || t.createdAt
18623
+ }));
18624
+ const providers = getConcurrencyStatus();
18625
+ const status = {
18626
+ activeTasks,
18627
+ providers,
18628
+ updatedAt: new Date().toISOString()
18629
+ };
18630
+ writeFileSync(STATUS_FILE_PATH, JSON.stringify(status, null, 2));
18631
+ } catch (error2) {
18632
+ console.error("Failed to update status file:", error2);
18633
+ }
18634
+ }
18580
18635
  async function launchTask(options) {
18581
18636
  const { agentName, categoryName, prompt, systemPrompt } = options;
18582
18637
  if (!agentName && !categoryName) {
@@ -18599,6 +18654,7 @@ async function launchTask(options) {
18599
18654
  createdAt: Date.now()
18600
18655
  };
18601
18656
  tasks.set(taskId, task);
18657
+ updateStatusFile();
18602
18658
  runTask(task, finalSystemPrompt).catch((error2) => {
18603
18659
  console.error(`Task ${taskId} failed:`, error2);
18604
18660
  });
@@ -18608,6 +18664,7 @@ async function runTask(task, systemPrompt) {
18608
18664
  task.status = "running";
18609
18665
  task.startedAt = Date.now();
18610
18666
  tasks.set(task.id, task);
18667
+ updateStatusFile();
18611
18668
  try {
18612
18669
  const messages = [];
18613
18670
  if (systemPrompt) {
@@ -18633,6 +18690,7 @@ async function runTask(task, systemPrompt) {
18633
18690
  task.result = result;
18634
18691
  task.completedAt = Date.now();
18635
18692
  tasks.set(task.id, task);
18693
+ updateStatusFile();
18636
18694
  } catch (error2) {
18637
18695
  if (error2 instanceof FallbackRequiredError) {
18638
18696
  task.status = "fallback_required";
@@ -18649,6 +18707,7 @@ async function runTask(task, systemPrompt) {
18649
18707
  }
18650
18708
  task.completedAt = Date.now();
18651
18709
  tasks.set(task.id, task);
18710
+ updateStatusFile();
18652
18711
  }
18653
18712
  }
18654
18713
  function pollTask(taskId) {
@@ -18672,6 +18731,7 @@ function cancelTask(taskId) {
18672
18731
  task.status = "cancelled";
18673
18732
  task.completedAt = Date.now();
18674
18733
  tasks.set(taskId, task);
18734
+ updateStatusFile();
18675
18735
  return true;
18676
18736
  }
18677
18737
  return false;
@@ -18686,6 +18746,9 @@ function cancelAllTasks() {
18686
18746
  cancelled++;
18687
18747
  }
18688
18748
  }
18749
+ if (cancelled > 0) {
18750
+ updateStatusFile();
18751
+ }
18689
18752
  return cancelled;
18690
18753
  }
18691
18754
  function listTasks(options) {
@@ -18711,34 +18774,6 @@ function cleanupTasks(maxAgeMs = 30 * 60 * 1000) {
18711
18774
  return cleaned;
18712
18775
  }
18713
18776
 
18714
- // src/mcp/background-agent-server/concurrency.ts
18715
- var activeCounts = new Map;
18716
- var queues = new Map;
18717
- function getConcurrencyLimit(provider) {
18718
- const config2 = loadConfig();
18719
- const perProvider = config2.concurrency.per_provider?.[provider];
18720
- if (perProvider !== undefined) {
18721
- return perProvider;
18722
- }
18723
- return config2.concurrency.default;
18724
- }
18725
- function getActiveCount(provider) {
18726
- return activeCounts.get(provider) ?? 0;
18727
- }
18728
- function getConcurrencyStatus() {
18729
- const config2 = loadConfig();
18730
- const status = {};
18731
- const providers = Object.keys(config2.providers);
18732
- for (const provider of providers) {
18733
- status[provider] = {
18734
- active: getActiveCount(provider),
18735
- limit: getConcurrencyLimit(provider),
18736
- queued: queues.get(provider)?.length ?? 0
18737
- };
18738
- }
18739
- return status;
18740
- }
18741
-
18742
18777
  // src/mcp/background-agent-server/server.ts
18743
18778
  var tools = [
18744
18779
  {
@@ -19032,6 +19067,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
19032
19067
  async function main() {
19033
19068
  const transport = new StdioServerTransport;
19034
19069
  await server.connect(transport);
19070
+ updateStatusFile();
19035
19071
  console.error("oh-my-claude Background Agent MCP Server running");
19036
19072
  }
19037
19073
  main().catch((error2) => {
@@ -0,0 +1,146 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/statusline/statusline.ts
4
+ import { readFileSync, existsSync } from "node:fs";
5
+ import { join } from "node:path";
6
+ import { homedir } from "node:os";
7
+
8
+ // src/statusline/formatter.ts
9
+ var AGENT_ABBREV = {
10
+ oracle: "Oracle",
11
+ librarian: "Lib",
12
+ explore: "Exp",
13
+ "frontend-ui-ux": "UI",
14
+ "document-writer": "Doc"
15
+ };
16
+ var TASK_AGENT_ABBREV = {
17
+ Scout: "Scout",
18
+ Planner: "Plan",
19
+ General: "Gen",
20
+ Guide: "Guide",
21
+ Bash: "Bash"
22
+ };
23
+ var PROVIDER_ABBREV = {
24
+ deepseek: "DS",
25
+ zhipu: "ZP",
26
+ minimax: "MM",
27
+ openrouter: "OR"
28
+ };
29
+ function formatDuration(seconds) {
30
+ if (seconds < 60) {
31
+ return `${Math.floor(seconds)}s`;
32
+ }
33
+ const minutes = Math.floor(seconds / 60);
34
+ return `${minutes}m`;
35
+ }
36
+ function getAgentAbbrev(agent) {
37
+ if (agent.startsWith("@")) {
38
+ const taskAgent = agent.slice(1);
39
+ return `@${TASK_AGENT_ABBREV[taskAgent] || taskAgent.slice(0, 4)}`;
40
+ }
41
+ return AGENT_ABBREV[agent.toLowerCase()] || agent.slice(0, 4);
42
+ }
43
+ function getProviderAbbrev(provider) {
44
+ return PROVIDER_ABBREV[provider.toLowerCase()] || provider.slice(0, 2).toUpperCase();
45
+ }
46
+ function formatStatusLine(data) {
47
+ const parts = ["omc"];
48
+ const now = Date.now();
49
+ if (data.activeTasks.length > 0) {
50
+ const tasksToShow = data.activeTasks.slice(0, 3);
51
+ for (const task of tasksToShow) {
52
+ const durationSec = Math.floor((now - task.startedAt) / 1000);
53
+ const agentName = getAgentAbbrev(task.agent);
54
+ const duration = formatDuration(durationSec);
55
+ parts.push(`[${agentName}: ${duration}]`);
56
+ }
57
+ if (data.activeTasks.length > 3) {
58
+ parts.push(`+${data.activeTasks.length - 3}`);
59
+ }
60
+ }
61
+ const providerParts = [];
62
+ const providersToShow = ["deepseek", "zhipu", "minimax"];
63
+ for (const provider of providersToShow) {
64
+ const status = data.providers[provider];
65
+ if (status && (status.active > 0 || data.activeTasks.length > 0)) {
66
+ const abbrev = getProviderAbbrev(provider);
67
+ providerParts.push(`${abbrev}: ${status.active}/${status.limit}`);
68
+ }
69
+ }
70
+ if (providerParts.length > 0) {
71
+ parts.push("|");
72
+ parts.push(...providerParts);
73
+ }
74
+ return parts.join(" ");
75
+ }
76
+ function formatEmptyStatusLine() {
77
+ return "omc ready";
78
+ }
79
+ function formatIdleStatusLine(providers) {
80
+ const parts = ["omc ready"];
81
+ const providerParts = [];
82
+ const providersToShow = ["deepseek", "zhipu", "minimax"];
83
+ for (const provider of providersToShow) {
84
+ const status = providers[provider];
85
+ if (status && status.limit > 0) {
86
+ const abbrev = getProviderAbbrev(provider);
87
+ providerParts.push(`${abbrev}: ${status.limit}`);
88
+ }
89
+ }
90
+ if (providerParts.length > 0) {
91
+ parts.push("|");
92
+ parts.push(...providerParts);
93
+ }
94
+ return parts.join(" ");
95
+ }
96
+
97
+ // src/statusline/statusline.ts
98
+ var STATUS_FILE_PATH = join(homedir(), ".claude", "oh-my-claude", "status.json");
99
+ var TIMEOUT_MS = 100;
100
+ function readStatusFile() {
101
+ try {
102
+ if (!existsSync(STATUS_FILE_PATH)) {
103
+ return null;
104
+ }
105
+ const content = readFileSync(STATUS_FILE_PATH, "utf-8");
106
+ const data = JSON.parse(content);
107
+ if (!data || typeof data !== "object") {
108
+ return null;
109
+ }
110
+ if (data.updatedAt) {
111
+ const updatedAt = new Date(data.updatedAt).getTime();
112
+ const age = Date.now() - updatedAt;
113
+ if (age > 5 * 60 * 1000) {
114
+ return null;
115
+ }
116
+ }
117
+ return data;
118
+ } catch {
119
+ return null;
120
+ }
121
+ }
122
+ async function main() {
123
+ const timeoutId = setTimeout(() => {
124
+ console.log(formatEmptyStatusLine());
125
+ process.exit(0);
126
+ }, TIMEOUT_MS);
127
+ try {
128
+ let _input = "";
129
+ try {
130
+ _input = readFileSync(0, "utf-8");
131
+ } catch {}
132
+ const statusData = readStatusFile();
133
+ if (!statusData) {
134
+ console.log(formatEmptyStatusLine());
135
+ } else if (statusData.activeTasks.length === 0) {
136
+ console.log(formatIdleStatusLine(statusData.providers));
137
+ } else {
138
+ console.log(formatStatusLine(statusData));
139
+ }
140
+ } catch {
141
+ console.log(formatEmptyStatusLine());
142
+ } finally {
143
+ clearTimeout(timeoutId);
144
+ }
145
+ }
146
+ main();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lgcyaxi/oh-my-claude",
3
- "version": "1.0.1",
3
+ "version": "1.1.2",
4
4
  "description": "Multi-agent orchestration plugin for Claude Code with multi-provider support",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -11,8 +11,9 @@
11
11
  "scripts": {
12
12
  "build": "bun build src/index.ts src/cli.ts --outdir dist --target node --splitting",
13
13
  "build:mcp": "bun build src/mcp/background-agent-server/server.ts --outdir dist/mcp --target node",
14
- "build:hooks": "bun build src/hooks/comment-checker.ts src/hooks/todo-continuation.ts --outdir dist/hooks --target node",
15
- "build:all": "bun run build && bun run build:mcp && bun run build:hooks",
14
+ "build:hooks": "bun build src/hooks/comment-checker.ts src/hooks/todo-continuation.ts src/hooks/task-notification.ts src/hooks/task-tracker.ts --outdir dist/hooks --target node",
15
+ "build:statusline": "bun build src/statusline/statusline.ts --outdir dist/statusline --target node",
16
+ "build:all": "bun run build && bun run build:mcp && bun run build:hooks && bun run build:statusline",
16
17
  "typecheck": "tsc --noEmit",
17
18
  "test": "bun test",
18
19
  "dev": "bun run --watch src/index.ts",
package/src/cli.ts CHANGED
@@ -19,7 +19,7 @@ import { loadConfig } from "./config";
19
19
  program
20
20
  .name("oh-my-claude")
21
21
  .description("Multi-agent orchestration plugin for Claude Code")
22
- .version("1.0.1");
22
+ .version("1.1.2");
23
23
 
24
24
  // Install command
25
25
  program
@@ -206,6 +206,7 @@ program
206
206
  console.log(` ${status.components.agents ? ok("Agent files generated") : fail("Agent files generated")}`);
207
207
  console.log(` ${status.components.hooks ? ok("Hooks configured") : fail("Hooks configured")}`);
208
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")}`);
209
210
  console.log(` ${status.components.config ? ok("Configuration file exists") : fail("Configuration file exists")}`);
210
211
 
211
212
 
@@ -243,11 +244,13 @@ program
243
244
  "omc-explore",
244
245
  "omc-plan",
245
246
  "omc-start-work",
247
+ "omc-status",
246
248
  // Quick action commands
247
249
  "omcx-commit",
248
250
  "omcx-implement",
249
251
  "omcx-refactor",
250
252
  "omcx-docs",
253
+ "omcx-issue",
251
254
  ];
252
255
  console.log(` ${subheader("Agent commands (omc-):")}`);
253
256
  for (const cmd of expectedCommands.filter(c => c.startsWith("omc-"))) {
@@ -265,7 +268,7 @@ program
265
268
  // Detailed MCP status
266
269
  console.log(`\n${header("MCP Server (detailed):")}`);
267
270
  try {
268
- const mcpList = execSync("claude mcp list 2>/dev/null", { encoding: "utf-8" });
271
+ const mcpList = execSync("claude mcp list", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
269
272
  const omcLine = mcpList.split("\n").find((line: string) => line.includes("oh-my-claude-background"));
270
273
  if (omcLine) {
271
274
  const isConnected = omcLine.includes("✓ Connected");
@@ -291,12 +294,43 @@ program
291
294
  // Hooks detail
292
295
  console.log(`\n${header("Hooks (detailed):")}`);
293
296
  const hooksDir = join(homedir(), ".claude", "oh-my-claude", "hooks");
294
- const expectedHooks = ["comment-checker.js", "todo-continuation.js"];
297
+ const expectedHooks = ["comment-checker.js", "todo-continuation.js", "task-notification.js"];
295
298
  for (const hook of expectedHooks) {
296
299
  const hookPath = join(hooksDir, hook);
297
300
  const exists = existsSync(hookPath);
298
301
  console.log(` ${exists ? ok(hook) : fail(hook)}`);
299
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
+ }
300
334
  }
301
335
 
302
336
  // Check providers
@@ -423,8 +457,10 @@ program
423
457
  let latestVersion = "unknown";
424
458
  try {
425
459
  console.log(`${dimText("Checking npm registry for latest version...")}`);
426
- const npmInfo = execSync(`npm view ${PACKAGE_NAME} version 2>/dev/null`, {
460
+ // Use stdio: 'pipe' to suppress stderr instead of shell redirection (Windows compatible)
461
+ const npmInfo = execSync(`npm view ${PACKAGE_NAME} version`, {
427
462
  encoding: "utf-8",
463
+ stdio: ["pipe", "pipe", "pipe"],
428
464
  }).trim();
429
465
  latestVersion = npmInfo;
430
466
  console.log(`Latest version: ${c.cyan}${latestVersion}${c.reset}\n`);
@@ -455,12 +491,16 @@ program
455
491
  console.log(header("Updating oh-my-claude...\n"));
456
492
 
457
493
  try {
458
- // Step 1: Clear npx cache for the package
494
+ // Step 1: Clear npx cache for the package (optional, may fail on some systems)
459
495
  console.log(`${dimText("Clearing npx cache...")}`);
460
496
  try {
461
- execSync(`npx --yes clear-npx-cache 2>/dev/null || true`, { stdio: "pipe" });
497
+ // Use stdio: 'pipe' for Windows compatibility instead of shell redirection
498
+ execSync(`npx --yes clear-npx-cache`, {
499
+ stdio: ["pipe", "pipe", "pipe"],
500
+ timeout: 10000
501
+ });
462
502
  } catch {
463
- // Ignore errors - cache clear is optional
503
+ // Ignore errors - cache clear is optional and may not be available
464
504
  }
465
505
 
466
506
  // Step 2: Install latest version via npx
@@ -487,6 +527,106 @@ program
487
527
  }
488
528
  });
489
529
 
530
+ // StatusLine command
531
+ program
532
+ .command("statusline")
533
+ .description("Manage statusline integration")
534
+ .option("--enable", "Enable statusline")
535
+ .option("--disable", "Disable statusline")
536
+ .option("--status", "Show current statusline configuration")
537
+ .action((options) => {
538
+ const { readFileSync, existsSync } = require("node:fs");
539
+ const { join } = require("node:path");
540
+ const { homedir } = require("node:os");
541
+
542
+ // Color helpers
543
+ const useColor = process.stdout.isTTY;
544
+ const c = {
545
+ reset: useColor ? "\x1b[0m" : "",
546
+ bold: useColor ? "\x1b[1m" : "",
547
+ dim: useColor ? "\x1b[2m" : "",
548
+ green: useColor ? "\x1b[32m" : "",
549
+ red: useColor ? "\x1b[31m" : "",
550
+ yellow: useColor ? "\x1b[33m" : "",
551
+ cyan: useColor ? "\x1b[36m" : "",
552
+ };
553
+
554
+ const ok = (text: string) => `${c.green}+${c.reset} ${text}`;
555
+ const fail = (text: string) => `${c.red}x${c.reset} ${text}`;
556
+ const warn = (text: string) => `${c.yellow}!${c.reset} ${text}`;
557
+
558
+ const settingsPath = join(homedir(), ".claude", "settings.json");
559
+
560
+ if (options.status || (!options.enable && !options.disable)) {
561
+ // Show status
562
+ console.log(`${c.bold}StatusLine Status${c.reset}\n`);
563
+
564
+ if (!existsSync(settingsPath)) {
565
+ console.log(fail("settings.json not found"));
566
+ process.exit(1);
567
+ }
568
+
569
+ try {
570
+ const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
571
+
572
+ if (!settings.statusLine) {
573
+ console.log(fail("StatusLine not configured"));
574
+ console.log(`\nRun ${c.cyan}oh-my-claude statusline --enable${c.reset} to enable.`);
575
+ } else {
576
+ const cmd = settings.statusLine.command || "";
577
+ const isOurs = cmd.includes("oh-my-claude");
578
+ const isWrapper = cmd.includes("statusline-wrapper");
579
+
580
+ console.log(ok("StatusLine configured"));
581
+ console.log(` Command: ${c.dim}${cmd}${c.reset}`);
582
+
583
+ if (isWrapper) {
584
+ console.log(` Mode: ${c.yellow}Merged (wrapper)${c.reset}`);
585
+ } else if (isOurs) {
586
+ console.log(` Mode: ${c.green}Direct${c.reset}`);
587
+ } else {
588
+ console.log(` Mode: ${c.cyan}External${c.reset}`);
589
+ }
590
+ }
591
+ } catch (error) {
592
+ console.log(fail(`Failed to read settings: ${error}`));
593
+ process.exit(1);
594
+ }
595
+ } else if (options.enable) {
596
+ // Enable statusline
597
+ const { installStatusLine } = require("./installer/settings-merger");
598
+ const { getStatusLineScriptPath } = require("./installer");
599
+
600
+ try {
601
+ const result = installStatusLine(getStatusLineScriptPath());
602
+ if (result.installed) {
603
+ console.log(ok("StatusLine enabled"));
604
+ if (result.wrapperCreated) {
605
+ console.log(warn("Wrapper created to merge with existing statusLine"));
606
+ }
607
+ }
608
+ } catch (error) {
609
+ console.log(fail(`Failed to enable statusline: ${error}`));
610
+ process.exit(1);
611
+ }
612
+ } else if (options.disable) {
613
+ // Disable statusline
614
+ const { uninstallStatusLine } = require("./installer/settings-merger");
615
+
616
+ try {
617
+ const result = uninstallStatusLine();
618
+ if (result) {
619
+ console.log(ok("StatusLine disabled"));
620
+ } else {
621
+ console.log(warn("StatusLine was not configured"));
622
+ }
623
+ } catch (error) {
624
+ console.log(fail(`Failed to disable statusline: ${error}`));
625
+ process.exit(1);
626
+ }
627
+ }
628
+ });
629
+
490
630
  // Setup MCP command
491
631
  program
492
632
  .command("setup-mcp")
@@ -598,7 +738,7 @@ program
598
738
  if (installThinking) {
599
739
  console.log(`${c.bold}Anthropic Official:${c.reset}`);
600
740
  try {
601
- const mcpList = execSync("claude mcp list 2>/dev/null", { encoding: "utf-8" });
741
+ const mcpList = execSync("claude mcp list", { encoding: "utf-8" });
602
742
  if (mcpList.includes("sequential-thinking")) {
603
743
  console.log(` ${ok("sequential-thinking already installed")}`);
604
744
  } else {
@@ -621,7 +761,7 @@ program
621
761
  } else {
622
762
  try {
623
763
  // Check if already installed
624
- const mcpList = execSync("claude mcp list 2>/dev/null", { encoding: "utf-8" });
764
+ const mcpList = execSync("claude mcp list", { encoding: "utf-8" });
625
765
  if (mcpList.includes("MiniMax")) {
626
766
  console.log(` ${ok("MiniMax already installed")}`);
627
767
  } else {
@@ -648,7 +788,7 @@ program
648
788
  for (const [key, server] of glmServers) {
649
789
  try {
650
790
  // Check if already installed
651
- const mcpList = execSync("claude mcp list 2>/dev/null", { encoding: "utf-8" });
791
+ const mcpList = execSync("claude mcp list", { encoding: "utf-8" });
652
792
  if (mcpList.includes(server.name)) {
653
793
  console.log(` ${ok(`${server.name} already installed`)}`);
654
794
  } else {
@@ -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