cc-mirror 1.0.4 → 1.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.
Files changed (25) hide show
  1. package/README.md +168 -98
  2. package/dist/cc-mirror.mjs +788 -249
  3. package/dist/skills/multi-agent-orchestrator/SKILL.md +391 -0
  4. package/dist/skills/multi-agent-orchestrator/references/code-review.md +266 -0
  5. package/dist/skills/multi-agent-orchestrator/references/data-analysis.md +315 -0
  6. package/dist/skills/multi-agent-orchestrator/references/devops.md +309 -0
  7. package/dist/skills/multi-agent-orchestrator/references/documentation.md +310 -0
  8. package/dist/skills/multi-agent-orchestrator/references/domains/code-review.md +301 -0
  9. package/dist/skills/multi-agent-orchestrator/references/domains/data-analysis.md +347 -0
  10. package/dist/skills/multi-agent-orchestrator/references/domains/devops.md +340 -0
  11. package/dist/skills/multi-agent-orchestrator/references/domains/documentation.md +343 -0
  12. package/dist/skills/multi-agent-orchestrator/references/domains/project-management.md +370 -0
  13. package/dist/skills/multi-agent-orchestrator/references/domains/research.md +322 -0
  14. package/dist/skills/multi-agent-orchestrator/references/domains/software-development.md +269 -0
  15. package/dist/skills/multi-agent-orchestrator/references/domains/testing.md +313 -0
  16. package/dist/skills/multi-agent-orchestrator/references/examples.md +377 -0
  17. package/dist/skills/multi-agent-orchestrator/references/guide.md +327 -0
  18. package/dist/skills/multi-agent-orchestrator/references/patterns.md +441 -0
  19. package/dist/skills/multi-agent-orchestrator/references/project-management.md +345 -0
  20. package/dist/skills/multi-agent-orchestrator/references/research.md +285 -0
  21. package/dist/skills/multi-agent-orchestrator/references/software-development.md +242 -0
  22. package/dist/skills/multi-agent-orchestrator/references/testing.md +282 -0
  23. package/dist/skills/multi-agent-orchestrator/references/tools.md +454 -0
  24. package/dist/tui.mjs +1045 -360
  25. package/package.json +2 -2
package/dist/tui.mjs CHANGED
@@ -8,10 +8,10 @@ var __export = (target, all) => {
8
8
  import { render } from "ink";
9
9
 
10
10
  // src/tui/app.tsx
11
- import { useCallback, useEffect as useEffect7, useMemo as useMemo3, useState as useState13 } from "react";
11
+ import { useCallback, useEffect as useEffect8, useMemo as useMemo3, useState as useState13 } from "react";
12
12
  import { Box as Box25, Text as Text23, useApp, useInput as useInput13 } from "ink";
13
13
  import SelectInput from "ink-select-input";
14
- import path22 from "node:path";
14
+ import path24 from "node:path";
15
15
 
16
16
  // src/brands/index.ts
17
17
  var brands_exports = {};
@@ -1276,6 +1276,203 @@ var buildCCRouterTweakccConfig = () => ({
1276
1276
  }
1277
1277
  });
1278
1278
 
1279
+ // src/brands/mirror.ts
1280
+ var clamp5 = (value) => Math.max(0, Math.min(255, Math.round(value)));
1281
+ var hexToRgb5 = (hex) => {
1282
+ const normalized = hex.replace("#", "").trim();
1283
+ if (normalized.length === 3) {
1284
+ const [r, g, b] = normalized.split("");
1285
+ return {
1286
+ r: clamp5(parseInt(r + r, 16)),
1287
+ g: clamp5(parseInt(g + g, 16)),
1288
+ b: clamp5(parseInt(b + b, 16))
1289
+ };
1290
+ }
1291
+ if (normalized.length !== 6) {
1292
+ throw new Error(`Unsupported hex color: ${hex}`);
1293
+ }
1294
+ return {
1295
+ r: clamp5(parseInt(normalized.slice(0, 2), 16)),
1296
+ g: clamp5(parseInt(normalized.slice(2, 4), 16)),
1297
+ b: clamp5(parseInt(normalized.slice(4, 6), 16))
1298
+ };
1299
+ };
1300
+ var rgb5 = (hex) => {
1301
+ const { r, g, b } = hexToRgb5(hex);
1302
+ return `rgb(${r},${g},${b})`;
1303
+ };
1304
+ var mix5 = (hexA, hexB, weight) => {
1305
+ const a = hexToRgb5(hexA);
1306
+ const b = hexToRgb5(hexB);
1307
+ const w = Math.max(0, Math.min(1, weight));
1308
+ return `rgb(${clamp5(a.r + (b.r - a.r) * w)},${clamp5(a.g + (b.g - a.g) * w)},${clamp5(a.b + (b.b - a.b) * w)})`;
1309
+ };
1310
+ var lighten5 = (hex, weight) => mix5(hex, "#ffffff", weight);
1311
+ var palette5 = {
1312
+ // Base surfaces - near-black with metallic sheen
1313
+ base: "#0d0f12",
1314
+ surface: "#14161a",
1315
+ panel: "#1a1d22",
1316
+ elevated: "#22262d",
1317
+ // Borders - subtle silver
1318
+ border: "#3a3f48",
1319
+ borderStrong: "#4a5058",
1320
+ borderGlow: "#6a7078",
1321
+ // Text
1322
+ text: "#e8eaed",
1323
+ textMuted: "#b0b5bc",
1324
+ textDim: "#7a8088",
1325
+ // Primary: Silver/Chrome
1326
+ silver: "#c0c0c0",
1327
+ chrome: "#a0a0a0",
1328
+ platinum: "#e5e4e2",
1329
+ // Accent: Electric blue
1330
+ electric: "#00d4ff",
1331
+ electricSoft: "#4de1ff",
1332
+ electricDeep: "#00a3cc",
1333
+ // Secondary: Deep purple
1334
+ purple: "#6b5b95",
1335
+ purpleSoft: "#8a7ab4",
1336
+ // Semantic
1337
+ green: "#4ade80",
1338
+ red: "#f87171",
1339
+ orange: "#fb923c",
1340
+ cyan: "#22d3ee"
1341
+ };
1342
+ var theme4 = {
1343
+ name: "Mirror Claude",
1344
+ id: "mirror-claude",
1345
+ colors: {
1346
+ autoAccept: rgb5(palette5.green),
1347
+ bashBorder: rgb5(palette5.electric),
1348
+ claude: rgb5(palette5.silver),
1349
+ claudeShimmer: rgb5(palette5.platinum),
1350
+ claudeBlue_FOR_SYSTEM_SPINNER: rgb5(palette5.electric),
1351
+ claudeBlueShimmer_FOR_SYSTEM_SPINNER: lighten5(palette5.electric, 0.2),
1352
+ permission: rgb5(palette5.electricSoft),
1353
+ permissionShimmer: lighten5(palette5.electricSoft, 0.25),
1354
+ planMode: rgb5(palette5.purple),
1355
+ ide: rgb5(palette5.cyan),
1356
+ promptBorder: rgb5(palette5.border),
1357
+ promptBorderShimmer: rgb5(palette5.borderGlow),
1358
+ text: rgb5(palette5.text),
1359
+ inverseText: rgb5(palette5.base),
1360
+ inactive: rgb5(palette5.textDim),
1361
+ subtle: mix5(palette5.base, palette5.chrome, 0.08),
1362
+ suggestion: rgb5(palette5.electricSoft),
1363
+ remember: rgb5(palette5.purple),
1364
+ background: rgb5(palette5.base),
1365
+ success: rgb5(palette5.green),
1366
+ error: rgb5(palette5.red),
1367
+ warning: rgb5(palette5.orange),
1368
+ warningShimmer: lighten5(palette5.orange, 0.28),
1369
+ diffAdded: mix5(palette5.base, palette5.green, 0.15),
1370
+ diffRemoved: mix5(palette5.base, palette5.red, 0.15),
1371
+ diffAddedDimmed: mix5(palette5.base, palette5.green, 0.08),
1372
+ diffRemovedDimmed: mix5(palette5.base, palette5.red, 0.08),
1373
+ diffAddedWord: mix5(palette5.base, palette5.green, 0.32),
1374
+ diffRemovedWord: mix5(palette5.base, palette5.red, 0.32),
1375
+ diffAddedWordDimmed: mix5(palette5.base, palette5.green, 0.18),
1376
+ diffRemovedWordDimmed: mix5(palette5.base, palette5.red, 0.18),
1377
+ red_FOR_SUBAGENTS_ONLY: rgb5(palette5.red),
1378
+ blue_FOR_SUBAGENTS_ONLY: rgb5(palette5.electric),
1379
+ green_FOR_SUBAGENTS_ONLY: rgb5(palette5.green),
1380
+ yellow_FOR_SUBAGENTS_ONLY: rgb5(palette5.orange),
1381
+ purple_FOR_SUBAGENTS_ONLY: rgb5(palette5.purple),
1382
+ orange_FOR_SUBAGENTS_ONLY: rgb5(palette5.orange),
1383
+ pink_FOR_SUBAGENTS_ONLY: lighten5(palette5.purple, 0.32),
1384
+ cyan_FOR_SUBAGENTS_ONLY: rgb5(palette5.cyan),
1385
+ professionalBlue: rgb5(palette5.electric),
1386
+ rainbow_red: rgb5(palette5.red),
1387
+ rainbow_orange: rgb5(palette5.orange),
1388
+ rainbow_yellow: lighten5(palette5.orange, 0.18),
1389
+ rainbow_green: rgb5(palette5.green),
1390
+ rainbow_blue: rgb5(palette5.electricSoft),
1391
+ rainbow_indigo: rgb5(palette5.electricDeep),
1392
+ rainbow_violet: rgb5(palette5.purple),
1393
+ rainbow_red_shimmer: lighten5(palette5.red, 0.35),
1394
+ rainbow_orange_shimmer: lighten5(palette5.orange, 0.35),
1395
+ rainbow_yellow_shimmer: lighten5(palette5.orange, 0.3),
1396
+ rainbow_green_shimmer: lighten5(palette5.green, 0.35),
1397
+ rainbow_blue_shimmer: lighten5(palette5.electricSoft, 0.35),
1398
+ rainbow_indigo_shimmer: lighten5(palette5.electricDeep, 0.35),
1399
+ rainbow_violet_shimmer: lighten5(palette5.purple, 0.35),
1400
+ clawd_body: rgb5(palette5.silver),
1401
+ clawd_background: rgb5(palette5.base),
1402
+ userMessageBackground: rgb5(palette5.panel),
1403
+ bashMessageBackgroundColor: rgb5(palette5.surface),
1404
+ memoryBackgroundColor: mix5(palette5.panel, palette5.purple, 0.08),
1405
+ rate_limit_fill: rgb5(palette5.electric),
1406
+ rate_limit_empty: rgb5(palette5.borderStrong)
1407
+ }
1408
+ };
1409
+ var buildMirrorTweakccConfig = () => ({
1410
+ ccVersion: "",
1411
+ ccInstallationPath: null,
1412
+ lastModified: (/* @__PURE__ */ new Date()).toISOString(),
1413
+ changesApplied: false,
1414
+ hidePiebaldAnnouncement: true,
1415
+ settings: {
1416
+ themes: [theme4, ...DEFAULT_THEMES],
1417
+ thinkingVerbs: {
1418
+ format: "{}... ",
1419
+ verbs: [
1420
+ "Reflecting",
1421
+ "Refracting",
1422
+ "Projecting",
1423
+ "Mirroring",
1424
+ "Amplifying",
1425
+ "Focusing",
1426
+ "Polishing",
1427
+ "Crystallizing",
1428
+ "Calibrating",
1429
+ "Synthesizing",
1430
+ "Resolving",
1431
+ "Composing",
1432
+ "Rendering",
1433
+ "Finalizing"
1434
+ ]
1435
+ },
1436
+ thinkingStyle: {
1437
+ updateInterval: 100,
1438
+ phases: ["\u25C7", "\u25C6", "\u25C7", "\u25C8"],
1439
+ reverseMirror: true
1440
+ },
1441
+ userMessageDisplay: {
1442
+ format: formatUserMessage(getUserLabel()),
1443
+ styling: ["bold"],
1444
+ foregroundColor: rgb5(palette5.platinum),
1445
+ backgroundColor: rgb5(palette5.panel),
1446
+ borderStyle: "topBottomDouble",
1447
+ borderColor: rgb5(palette5.silver),
1448
+ paddingX: 1,
1449
+ paddingY: 0,
1450
+ fitBoxToContent: true
1451
+ },
1452
+ inputBox: {
1453
+ removeBorder: true
1454
+ },
1455
+ misc: {
1456
+ showTweakccVersion: false,
1457
+ showPatchesApplied: false,
1458
+ expandThinkingBlocks: true,
1459
+ enableConversationTitle: true,
1460
+ hideStartupBanner: true,
1461
+ hideCtrlGToEditPrompt: true,
1462
+ hideStartupClawd: true,
1463
+ increaseFileReadLimit: true
1464
+ },
1465
+ toolsets: [
1466
+ {
1467
+ name: "mirror",
1468
+ allowedTools: "*"
1469
+ }
1470
+ ],
1471
+ defaultToolset: "mirror",
1472
+ planModeToolset: "mirror"
1473
+ }
1474
+ });
1475
+
1279
1476
  // src/brands/index.ts
1280
1477
  var BRAND_PRESETS = {
1281
1478
  zai: {
@@ -1301,6 +1498,12 @@ var BRAND_PRESETS = {
1301
1498
  label: "CCRouter Sky",
1302
1499
  description: "Airy sky-blue accents for Claude Code Router.",
1303
1500
  buildTweakccConfig: buildCCRouterTweakccConfig
1501
+ },
1502
+ mirror: {
1503
+ key: "mirror",
1504
+ label: "Mirror Claude",
1505
+ description: "Reflective silver/chrome theme for pure Claude Code experience.",
1506
+ buildTweakccConfig: buildMirrorTweakccConfig
1304
1507
  }
1305
1508
  };
1306
1509
  var listBrandPresets = () => Object.values(BRAND_PRESETS);
@@ -1328,8 +1531,8 @@ var buildBrandConfig = (brandKey) => {
1328
1531
  var getBrandThemeId = (brandKey) => {
1329
1532
  if (!brandKey) return null;
1330
1533
  const config = buildBrandConfig(brandKey);
1331
- const theme4 = config.settings?.themes?.[0];
1332
- return theme4?.id ?? null;
1534
+ const theme5 = config.settings?.themes?.[0];
1535
+ return theme5?.id ?? null;
1333
1536
  };
1334
1537
 
1335
1538
  // src/core/index.ts
@@ -1349,8 +1552,8 @@ __export(core_exports, {
1349
1552
  updateVariant: () => updateVariant,
1350
1553
  updateVariantAsync: () => updateVariantAsync
1351
1554
  });
1352
- import fs10 from "node:fs";
1353
- import path19 from "node:path";
1555
+ import fs12 from "node:fs";
1556
+ import path21 from "node:path";
1354
1557
 
1355
1558
  // src/core/constants.ts
1356
1559
  import os2 from "node:os";
@@ -1418,7 +1621,7 @@ var ensureTweakccConfig = (tweakDir, brandKey) => {
1418
1621
  let didUpdate = false;
1419
1622
  if (brandKey === "minimax" && existingThemes.length > 0) {
1420
1623
  const filtered = existingThemes.filter(
1421
- (theme4) => theme4?.id !== "minimax-ember" && theme4?.id !== "minimax-glass" && theme4?.id !== "minimax-blade" && theme4?.name !== "MiniMax Ember" && theme4?.name !== "MiniMax Glass" && theme4?.name !== "MiniMax Blade"
1624
+ (theme5) => theme5?.id !== "minimax-ember" && theme5?.id !== "minimax-glass" && theme5?.id !== "minimax-blade" && theme5?.name !== "MiniMax Ember" && theme5?.name !== "MiniMax Glass" && theme5?.name !== "MiniMax Blade"
1422
1625
  );
1423
1626
  if (filtered.length !== existingThemes.length) {
1424
1627
  existingThemes = filtered;
@@ -1462,10 +1665,10 @@ var ensureTweakccConfig = (tweakDir, brandKey) => {
1462
1665
  if (brandThemes.length > 0) {
1463
1666
  const mergedThemes = [
1464
1667
  ...brandThemes,
1465
- ...existingThemes.filter((existingTheme) => !brandThemes.some((theme4) => themeMatches(existingTheme, theme4)))
1668
+ ...existingThemes.filter((existingTheme) => !brandThemes.some((theme5) => themeMatches(existingTheme, theme5)))
1466
1669
  ];
1467
1670
  const sameLength = mergedThemes.length === existingThemes.length;
1468
- const sameOrder = sameLength && mergedThemes.every((theme4, idx) => themeMatches(theme4, existingThemes[idx]));
1671
+ const sameOrder = sameLength && mergedThemes.every((theme5, idx) => themeMatches(theme5, existingThemes[idx]));
1469
1672
  if (!sameOrder) {
1470
1673
  existing.settings = { ...existing.settings, themes: mergedThemes };
1471
1674
  didUpdate = true;
@@ -1617,7 +1820,7 @@ var listVariants = (rootDir) => {
1617
1820
  };
1618
1821
 
1619
1822
  // src/core/variant-builder/VariantBuilder.ts
1620
- import path14 from "node:path";
1823
+ import path15 from "node:path";
1621
1824
 
1622
1825
  // src/providers/index.ts
1623
1826
  var providers_exports = {};
@@ -1699,6 +1902,29 @@ var PROVIDERS = {
1699
1902
  credentialOptional: true
1700
1903
  // No API key needed - CCRouter handles auth
1701
1904
  },
1905
+ mirror: {
1906
+ key: "mirror",
1907
+ label: "Mirror Claude",
1908
+ description: "Pure Claude Code with advanced features (team mode, custom theme)",
1909
+ baseUrl: "",
1910
+ // Empty = use Claude Code defaults (no ANTHROPIC_BASE_URL override)
1911
+ env: {
1912
+ // Only cosmetic settings - no auth or model overrides
1913
+ CC_MIRROR_SPLASH: 1,
1914
+ CC_MIRROR_PROVIDER_LABEL: "Mirror Claude",
1915
+ CC_MIRROR_SPLASH_STYLE: "mirror"
1916
+ },
1917
+ apiKeyLabel: "",
1918
+ // Empty = skip API key prompt
1919
+ authMode: "none",
1920
+ // No auth handling - user authenticates via normal Claude flow
1921
+ credentialOptional: true,
1922
+ // No credentials required at create time
1923
+ enablesTeamMode: true,
1924
+ // Auto-enable team mode patch
1925
+ noPromptPack: true
1926
+ // Skip prompt pack (pure Claude experience)
1927
+ },
1702
1928
  custom: {
1703
1929
  key: "custom",
1704
1930
  label: "Custom",
@@ -1744,6 +1970,19 @@ var buildEnv = ({ providerKey, baseUrl, apiKey, extraEnv, modelOverrides }) => {
1744
1970
  }
1745
1971
  const env = { ...provider.env };
1746
1972
  const authMode = provider.authMode ?? "apiKey";
1973
+ if (authMode === "none") {
1974
+ if (Array.isArray(extraEnv)) {
1975
+ for (const entry of extraEnv) {
1976
+ const idx = entry.indexOf("=");
1977
+ if (idx === -1) continue;
1978
+ const key = entry.slice(0, idx).trim();
1979
+ const value = entry.slice(idx + 1).trim();
1980
+ if (!key) continue;
1981
+ env[key] = value;
1982
+ }
1983
+ }
1984
+ return env;
1985
+ }
1747
1986
  if (!Object.hasOwn(env, "DISABLE_AUTOUPDATER")) {
1748
1987
  env.DISABLE_AUTOUPDATER = "1";
1749
1988
  }
@@ -1919,12 +2158,309 @@ var InstallNpmStep = class {
1919
2158
  }
1920
2159
  };
1921
2160
 
1922
- // src/core/variant-builder/steps/WriteConfigStep.ts
2161
+ // src/core/variant-builder/steps/TeamModeStep.ts
2162
+ import fs6 from "node:fs";
1923
2163
  import path7 from "node:path";
1924
2164
 
1925
- // src/core/claude-config.ts
2165
+ // src/core/skills.ts
1926
2166
  import fs5 from "node:fs";
2167
+ import os4 from "node:os";
1927
2168
  import path6 from "node:path";
2169
+ import { spawn as spawn3, spawnSync as spawnSync4 } from "node:child_process";
2170
+ import { fileURLToPath } from "node:url";
2171
+ var DEV_BROWSER_REPO = "https://github.com/SawyerHood/dev-browser.git";
2172
+ var DEV_BROWSER_ARCHIVE = "https://github.com/SawyerHood/dev-browser/archive/refs/heads/main.tar.gz";
2173
+ var SKILL_SUBDIR = path6.join("skills", "dev-browser");
2174
+ var MANAGED_MARKER = ".cc-mirror-managed";
2175
+ var ensureDir2 = (dir) => {
2176
+ fs5.mkdirSync(dir, { recursive: true });
2177
+ };
2178
+ var copyDir = (source, target) => {
2179
+ fs5.cpSync(source, target, { recursive: true });
2180
+ };
2181
+ var resolveSkillSourceDir = (repoDir) => {
2182
+ const direct = path6.join(repoDir, SKILL_SUBDIR);
2183
+ if (fs5.existsSync(direct)) return direct;
2184
+ const nested = fs5.readdirSync(repoDir).find((entry) => entry.startsWith("dev-browser-"));
2185
+ if (nested) {
2186
+ const candidate = path6.join(repoDir, nested, SKILL_SUBDIR);
2187
+ if (fs5.existsSync(candidate)) return candidate;
2188
+ }
2189
+ return null;
2190
+ };
2191
+ var cloneRepo = (targetDir) => {
2192
+ if (!commandExists("git")) return { ok: false, message: "git not found" };
2193
+ const result = spawnSync4("git", ["clone", "--depth", "1", DEV_BROWSER_REPO, targetDir], {
2194
+ encoding: "utf8"
2195
+ });
2196
+ if (result.status === 0) return { ok: true };
2197
+ return { ok: false, message: result.stderr?.trim() || result.stdout?.trim() || "git clone failed" };
2198
+ };
2199
+ var downloadArchive = (targetDir) => {
2200
+ if (!commandExists("curl") || !commandExists("tar")) {
2201
+ return { ok: false, message: "curl or tar not found" };
2202
+ }
2203
+ const archivePath = path6.join(targetDir, "dev-browser.tar.gz");
2204
+ const curlResult = spawnSync4("curl", ["-L", "-o", archivePath, DEV_BROWSER_ARCHIVE], { encoding: "utf8" });
2205
+ if (curlResult.status !== 0) {
2206
+ return { ok: false, message: curlResult.stderr?.trim() || "curl failed" };
2207
+ }
2208
+ const tarResult = spawnSync4("tar", ["-xzf", archivePath, "-C", targetDir], { encoding: "utf8" });
2209
+ if (tarResult.status !== 0) {
2210
+ return { ok: false, message: tarResult.stderr?.trim() || "tar extract failed" };
2211
+ }
2212
+ return { ok: true };
2213
+ };
2214
+ var ensureDevBrowserSkill = (opts) => {
2215
+ if (!opts.install) {
2216
+ return { status: "skipped", message: "skill install disabled" };
2217
+ }
2218
+ const skillRoot = opts.targetDir || path6.join(os4.homedir(), ".claude", "skills");
2219
+ const targetDir = path6.join(skillRoot, "dev-browser");
2220
+ const markerPath = path6.join(targetDir, MANAGED_MARKER);
2221
+ const exists = fs5.existsSync(targetDir);
2222
+ const managed = exists && fs5.existsSync(markerPath);
2223
+ if (exists && !managed && !opts.update) {
2224
+ return { status: "skipped", message: "existing skill is user-managed", path: targetDir };
2225
+ }
2226
+ ensureDir2(skillRoot);
2227
+ const tmpDir = fs5.mkdtempSync(path6.join(os4.tmpdir(), "cc-mirror-skill-"));
2228
+ try {
2229
+ let fetchResult = cloneRepo(tmpDir);
2230
+ if (!fetchResult.ok) {
2231
+ fetchResult = downloadArchive(tmpDir);
2232
+ }
2233
+ if (!fetchResult.ok) {
2234
+ return { status: "failed", message: fetchResult.message || "skill fetch failed" };
2235
+ }
2236
+ const sourceDir = resolveSkillSourceDir(tmpDir);
2237
+ if (!sourceDir) {
2238
+ return { status: "failed", message: "skill source not found after download" };
2239
+ }
2240
+ if (exists) {
2241
+ fs5.rmSync(targetDir, { recursive: true, force: true });
2242
+ }
2243
+ copyDir(sourceDir, targetDir);
2244
+ fs5.writeFileSync(
2245
+ markerPath,
2246
+ JSON.stringify({ managedBy: "cc-mirror", updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
2247
+ );
2248
+ return { status: exists ? "updated" : "installed", path: targetDir };
2249
+ } catch (error) {
2250
+ const message = error instanceof Error ? error.message : String(error);
2251
+ return { status: "failed", message };
2252
+ } finally {
2253
+ fs5.rmSync(tmpDir, { recursive: true, force: true });
2254
+ }
2255
+ };
2256
+ var ORCHESTRATOR_SKILL_NAME = "multi-agent-orchestrator";
2257
+ var findBundledSkillDir = () => {
2258
+ const thisFile = fileURLToPath(import.meta.url);
2259
+ const thisDir = path6.dirname(thisFile);
2260
+ const devPath = path6.join(thisDir, "..", "skills", ORCHESTRATOR_SKILL_NAME);
2261
+ if (fs5.existsSync(devPath)) return devPath;
2262
+ const distPath = path6.join(thisDir, "skills", ORCHESTRATOR_SKILL_NAME);
2263
+ if (fs5.existsSync(distPath)) return distPath;
2264
+ const distPath2 = path6.join(thisDir, "..", "skills", ORCHESTRATOR_SKILL_NAME);
2265
+ if (fs5.existsSync(distPath2)) return distPath2;
2266
+ return null;
2267
+ };
2268
+ var installOrchestratorSkill = (configDir) => {
2269
+ const sourceDir = findBundledSkillDir();
2270
+ if (!sourceDir) {
2271
+ return { status: "failed", message: "bundled orchestrator skill not found" };
2272
+ }
2273
+ const skillsDir = path6.join(configDir, "skills");
2274
+ const targetDir = path6.join(skillsDir, ORCHESTRATOR_SKILL_NAME);
2275
+ const markerPath = path6.join(targetDir, MANAGED_MARKER);
2276
+ try {
2277
+ ensureDir2(skillsDir);
2278
+ if (fs5.existsSync(targetDir) && !fs5.existsSync(markerPath)) {
2279
+ return { status: "skipped", message: "existing skill is user-managed", path: targetDir };
2280
+ }
2281
+ if (fs5.existsSync(targetDir)) {
2282
+ fs5.rmSync(targetDir, { recursive: true, force: true });
2283
+ }
2284
+ copyDir(sourceDir, targetDir);
2285
+ fs5.writeFileSync(
2286
+ markerPath,
2287
+ JSON.stringify({ managedBy: "cc-mirror", updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
2288
+ );
2289
+ return { status: "installed", path: targetDir };
2290
+ } catch (error) {
2291
+ const message = error instanceof Error ? error.message : String(error);
2292
+ return { status: "failed", message };
2293
+ }
2294
+ };
2295
+ var removeOrchestratorSkill = (configDir) => {
2296
+ const skillsDir = path6.join(configDir, "skills");
2297
+ const targetDir = path6.join(skillsDir, ORCHESTRATOR_SKILL_NAME);
2298
+ const markerPath = path6.join(targetDir, MANAGED_MARKER);
2299
+ if (!fs5.existsSync(targetDir)) {
2300
+ return { status: "skipped", message: "skill not installed" };
2301
+ }
2302
+ if (!fs5.existsSync(markerPath)) {
2303
+ return { status: "skipped", message: "skill is user-managed, not removing" };
2304
+ }
2305
+ try {
2306
+ fs5.rmSync(targetDir, { recursive: true, force: true });
2307
+ return { status: "removed", path: targetDir };
2308
+ } catch (error) {
2309
+ const message = error instanceof Error ? error.message : String(error);
2310
+ return { status: "failed", message };
2311
+ }
2312
+ };
2313
+ var spawnAsync = (cmd, args) => {
2314
+ return new Promise((resolve) => {
2315
+ const child = spawn3(cmd, args, { stdio: "pipe" });
2316
+ let stderr = "";
2317
+ let stdout = "";
2318
+ child.stdout?.on("data", (d) => {
2319
+ stdout += d.toString();
2320
+ });
2321
+ child.stderr?.on("data", (d) => {
2322
+ stderr += d.toString();
2323
+ });
2324
+ child.on("close", (code) => {
2325
+ if (code === 0) resolve({ ok: true });
2326
+ else resolve({ ok: false, message: stderr.trim() || stdout.trim() || `${cmd} failed` });
2327
+ });
2328
+ child.on("error", (err) => resolve({ ok: false, message: err.message }));
2329
+ });
2330
+ };
2331
+ var cloneRepoAsync = async (targetDir) => {
2332
+ if (!commandExists("git")) return { ok: false, message: "git not found" };
2333
+ return spawnAsync("git", ["clone", "--depth", "1", DEV_BROWSER_REPO, targetDir]);
2334
+ };
2335
+ var downloadArchiveAsync = async (targetDir) => {
2336
+ if (!commandExists("curl") || !commandExists("tar")) {
2337
+ return { ok: false, message: "curl or tar not found" };
2338
+ }
2339
+ const archivePath = path6.join(targetDir, "dev-browser.tar.gz");
2340
+ const curlResult = await spawnAsync("curl", ["-L", "-o", archivePath, DEV_BROWSER_ARCHIVE]);
2341
+ if (!curlResult.ok) return curlResult;
2342
+ return spawnAsync("tar", ["-xzf", archivePath, "-C", targetDir]);
2343
+ };
2344
+ var ensureDevBrowserSkillAsync = async (opts) => {
2345
+ if (!opts.install) {
2346
+ return { status: "skipped", message: "skill install disabled" };
2347
+ }
2348
+ const skillRoot = opts.targetDir || path6.join(os4.homedir(), ".claude", "skills");
2349
+ const targetDir = path6.join(skillRoot, "dev-browser");
2350
+ const markerPath = path6.join(targetDir, MANAGED_MARKER);
2351
+ const exists = fs5.existsSync(targetDir);
2352
+ const managed = exists && fs5.existsSync(markerPath);
2353
+ if (exists && !managed && !opts.update) {
2354
+ return { status: "skipped", message: "existing skill is user-managed", path: targetDir };
2355
+ }
2356
+ ensureDir2(skillRoot);
2357
+ const tmpDir = fs5.mkdtempSync(path6.join(os4.tmpdir(), "cc-mirror-skill-"));
2358
+ try {
2359
+ let fetchResult = await cloneRepoAsync(tmpDir);
2360
+ if (!fetchResult.ok) {
2361
+ fetchResult = await downloadArchiveAsync(tmpDir);
2362
+ }
2363
+ if (!fetchResult.ok) {
2364
+ return { status: "failed", message: fetchResult.message || "skill fetch failed" };
2365
+ }
2366
+ const sourceDir = resolveSkillSourceDir(tmpDir);
2367
+ if (!sourceDir) {
2368
+ return { status: "failed", message: "skill source not found after download" };
2369
+ }
2370
+ if (exists) {
2371
+ fs5.rmSync(targetDir, { recursive: true, force: true });
2372
+ }
2373
+ copyDir(sourceDir, targetDir);
2374
+ fs5.writeFileSync(
2375
+ markerPath,
2376
+ JSON.stringify({ managedBy: "cc-mirror", updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
2377
+ );
2378
+ return { status: exists ? "updated" : "installed", path: targetDir };
2379
+ } catch (error) {
2380
+ const message = error instanceof Error ? error.message : String(error);
2381
+ return { status: "failed", message };
2382
+ } finally {
2383
+ fs5.rmSync(tmpDir, { recursive: true, force: true });
2384
+ }
2385
+ };
2386
+
2387
+ // src/core/variant-builder/steps/TeamModeStep.ts
2388
+ var TEAM_MODE_DISABLED = "function sU(){return!1}";
2389
+ var TEAM_MODE_ENABLED = "function sU(){return!0}";
2390
+ var TeamModeStep = class {
2391
+ name = "TeamMode";
2392
+ shouldEnableTeamMode(ctx) {
2393
+ return Boolean(ctx.params.enableTeamMode) || Boolean(ctx.provider.enablesTeamMode);
2394
+ }
2395
+ execute(ctx) {
2396
+ if (!this.shouldEnableTeamMode(ctx)) return;
2397
+ ctx.report("Enabling team mode...");
2398
+ this.patchCli(ctx);
2399
+ }
2400
+ async executeAsync(ctx) {
2401
+ if (!this.shouldEnableTeamMode(ctx)) return;
2402
+ await ctx.report("Enabling team mode...");
2403
+ this.patchCli(ctx);
2404
+ }
2405
+ patchCli(ctx) {
2406
+ const { state, params, paths } = ctx;
2407
+ const cliPath = path7.join(paths.npmDir, "node_modules", "@anthropic-ai", "claude-code", "cli.js");
2408
+ const backupPath = `${cliPath}.backup`;
2409
+ if (!fs6.existsSync(cliPath)) {
2410
+ state.notes.push("Warning: cli.js not found, skipping team mode patch");
2411
+ return;
2412
+ }
2413
+ if (!fs6.existsSync(backupPath)) {
2414
+ fs6.copyFileSync(cliPath, backupPath);
2415
+ }
2416
+ let content = fs6.readFileSync(cliPath, "utf8");
2417
+ if (content.includes(TEAM_MODE_ENABLED)) {
2418
+ state.notes.push("Team mode already enabled");
2419
+ return;
2420
+ }
2421
+ if (!content.includes(TEAM_MODE_DISABLED)) {
2422
+ state.notes.push("Warning: Team mode function not found in cli.js, patch may not work");
2423
+ return;
2424
+ }
2425
+ content = content.replace(TEAM_MODE_DISABLED, TEAM_MODE_ENABLED);
2426
+ fs6.writeFileSync(cliPath, content);
2427
+ const verifyContent = fs6.readFileSync(cliPath, "utf8");
2428
+ if (!verifyContent.includes(TEAM_MODE_ENABLED)) {
2429
+ state.notes.push("Warning: Team mode patch verification failed");
2430
+ return;
2431
+ }
2432
+ const settingsPath = path7.join(paths.configDir, "settings.json");
2433
+ if (fs6.existsSync(settingsPath)) {
2434
+ try {
2435
+ const settings = JSON.parse(fs6.readFileSync(settingsPath, "utf8"));
2436
+ settings.env = settings.env || {};
2437
+ if (!settings.env.CLAUDE_CODE_TEAM_NAME) {
2438
+ settings.env.CLAUDE_CODE_TEAM_NAME = params.name;
2439
+ }
2440
+ if (!settings.env.CLAUDE_CODE_AGENT_TYPE) {
2441
+ settings.env.CLAUDE_CODE_AGENT_TYPE = "team-lead";
2442
+ }
2443
+ fs6.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
2444
+ } catch {
2445
+ state.notes.push("Warning: Could not update settings.json with team env vars");
2446
+ }
2447
+ }
2448
+ state.notes.push("Team mode enabled successfully");
2449
+ const skillResult = installOrchestratorSkill(paths.configDir);
2450
+ if (skillResult.status === "installed") {
2451
+ state.notes.push("Multi-agent orchestrator skill installed");
2452
+ } else if (skillResult.status === "failed") {
2453
+ state.notes.push(`Warning: orchestrator skill install failed: ${skillResult.message}`);
2454
+ }
2455
+ }
2456
+ };
2457
+
2458
+ // src/core/variant-builder/steps/WriteConfigStep.ts
2459
+ import path9 from "node:path";
2460
+
2461
+ // src/core/claude-config.ts
2462
+ import fs7 from "node:fs";
2463
+ import path8 from "node:path";
1928
2464
  var SETTINGS_FILE = "settings.json";
1929
2465
  var CLAUDE_CONFIG_FILE = ".claude.json";
1930
2466
  var PLACEHOLDER_KEY = "<API_KEY>";
@@ -1935,7 +2471,7 @@ var toStringOrNull = (value) => {
1935
2471
  return trimmed;
1936
2472
  };
1937
2473
  var readSettingsApiKey = (configDir) => {
1938
- const settingsPath = path6.join(configDir, SETTINGS_FILE);
2474
+ const settingsPath = path8.join(configDir, SETTINGS_FILE);
1939
2475
  const settings = readJson(settingsPath);
1940
2476
  if (!settings?.env) return null;
1941
2477
  const env = settings.env;
@@ -1947,7 +2483,7 @@ var ZAI_DENY_TOOLS = [
1947
2483
  "mcp__web_reader__webReader"
1948
2484
  ];
1949
2485
  var ensureZaiMcpDeny = (configDir) => {
1950
- const settingsPath = path6.join(configDir, SETTINGS_FILE);
2486
+ const settingsPath = path8.join(configDir, SETTINGS_FILE);
1951
2487
  const existing = readJson(settingsPath) || {};
1952
2488
  const permissions = existing.permissions || {};
1953
2489
  const deny = Array.isArray(permissions.deny) ? [...permissions.deny] : [];
@@ -1970,7 +2506,7 @@ var ensureZaiMcpDeny = (configDir) => {
1970
2506
  return true;
1971
2507
  };
1972
2508
  var ensureSettingsEnvDefaults = (configDir, defaults) => {
1973
- const settingsPath = path6.join(configDir, SETTINGS_FILE);
2509
+ const settingsPath = path8.join(configDir, SETTINGS_FILE);
1974
2510
  const existing = readJson(settingsPath) || {};
1975
2511
  const env = { ...existing.env ?? {} };
1976
2512
  let changed = false;
@@ -1985,7 +2521,7 @@ var ensureSettingsEnvDefaults = (configDir, defaults) => {
1985
2521
  return true;
1986
2522
  };
1987
2523
  var ensureSettingsEnvOverrides = (configDir, overrides) => {
1988
- const settingsPath = path6.join(configDir, SETTINGS_FILE);
2524
+ const settingsPath = path8.join(configDir, SETTINGS_FILE);
1989
2525
  const existing = readJson(settingsPath) || {};
1990
2526
  const env = { ...existing.env ?? {} };
1991
2527
  let changed = false;
@@ -2004,8 +2540,8 @@ var ensureApiKeyApproval = (configDir, apiKey) => {
2004
2540
  const resolvedKey = toStringOrNull(apiKey) || readSettingsApiKey(configDir);
2005
2541
  if (!resolvedKey) return false;
2006
2542
  const approvedToken = resolvedKey.slice(-20);
2007
- const configPath = path6.join(configDir, CLAUDE_CONFIG_FILE);
2008
- const exists = fs5.existsSync(configPath);
2543
+ const configPath = path8.join(configDir, CLAUDE_CONFIG_FILE);
2544
+ const exists = fs7.existsSync(configPath);
2009
2545
  let config = null;
2010
2546
  if (exists) {
2011
2547
  config = readJson(configPath);
@@ -2029,8 +2565,8 @@ var ensureApiKeyApproval = (configDir, apiKey) => {
2029
2565
  return true;
2030
2566
  };
2031
2567
  var ensureOnboardingState = (configDir, opts = {}) => {
2032
- const configPath = path6.join(configDir, CLAUDE_CONFIG_FILE);
2033
- const exists = fs5.existsSync(configPath);
2568
+ const configPath = path8.join(configDir, CLAUDE_CONFIG_FILE);
2569
+ const exists = fs7.existsSync(configPath);
2034
2570
  let config = null;
2035
2571
  if (exists) {
2036
2572
  config = readJson(configPath);
@@ -2051,7 +2587,7 @@ var ensureOnboardingState = (configDir, opts = {}) => {
2051
2587
  themeChanged = true;
2052
2588
  }
2053
2589
  }
2054
- if (config.hasCompletedOnboarding !== true) {
2590
+ if (!opts.skipOnboardingFlag && config.hasCompletedOnboarding !== true) {
2055
2591
  config.hasCompletedOnboarding = true;
2056
2592
  changed = true;
2057
2593
  onboardingChanged = true;
@@ -2064,8 +2600,8 @@ var ensureOnboardingState = (configDir, opts = {}) => {
2064
2600
  };
2065
2601
  var ensureMinimaxMcpServer = (configDir, apiKey) => {
2066
2602
  const resolvedKey = toStringOrNull(apiKey) || readSettingsApiKey(configDir);
2067
- const configPath = path6.join(configDir, CLAUDE_CONFIG_FILE);
2068
- const exists = fs5.existsSync(configPath);
2603
+ const configPath = path8.join(configDir, CLAUDE_CONFIG_FILE);
2604
+ const exists = fs7.existsSync(configPath);
2069
2605
  let config = null;
2070
2606
  if (exists) {
2071
2607
  config = readJson(configPath);
@@ -2122,7 +2658,7 @@ var WriteConfigStep = class {
2122
2658
  env.ANTHROPIC_API_KEY = "<API_KEY>";
2123
2659
  }
2124
2660
  const config = { env };
2125
- writeJson(path7.join(paths.configDir, "settings.json"), config);
2661
+ writeJson(path9.join(paths.configDir, "settings.json"), config);
2126
2662
  state.env = env;
2127
2663
  state.resolvedApiKey = typeof env.ANTHROPIC_API_KEY === "string" ? env.ANTHROPIC_API_KEY : void 0;
2128
2664
  ensureApiKeyApproval(paths.configDir, state.resolvedApiKey);
@@ -2162,9 +2698,11 @@ var BrandThemeStep = class {
2162
2698
  prefs.brandKey = brandKey;
2163
2699
  ensureTweakccConfig(paths.tweakDir, brandKey);
2164
2700
  const brandThemeId = !params.noTweak && brandKey ? getBrandThemeId(brandKey) : null;
2701
+ const skipOnboardingFlag = params.providerKey === "mirror";
2165
2702
  const onboarding = ensureOnboardingState(paths.configDir, {
2166
2703
  themeId: brandThemeId ?? "dark",
2167
- forceTheme: Boolean(brandThemeId)
2704
+ forceTheme: Boolean(brandThemeId),
2705
+ skipOnboardingFlag
2168
2706
  });
2169
2707
  if (onboarding.themeChanged) {
2170
2708
  state.notes.push(`Default theme set to ${brandThemeId ?? "dark"}.`);
@@ -2172,6 +2710,9 @@ var BrandThemeStep = class {
2172
2710
  if (onboarding.onboardingChanged) {
2173
2711
  state.notes.push("Onboarding marked complete.");
2174
2712
  }
2713
+ if (skipOnboardingFlag) {
2714
+ state.notes.push("Login screen enabled (authenticate when you run the variant).");
2715
+ }
2175
2716
  if (params.providerKey === "minimax") {
2176
2717
  ctx.report("Configuring MiniMax MCP server...");
2177
2718
  ensureMinimaxMcpServer(paths.configDir, state.resolvedApiKey);
@@ -2189,8 +2730,8 @@ var BrandThemeStep = class {
2189
2730
  };
2190
2731
 
2191
2732
  // src/core/prompt-pack.ts
2192
- import fs6 from "node:fs";
2193
- import path8 from "node:path";
2733
+ import fs8 from "node:fs";
2734
+ import path10 from "node:path";
2194
2735
 
2195
2736
  // src/core/prompt-pack/sanitize.ts
2196
2737
  var BACKTICK_REGEX = /`/g;
@@ -2605,17 +3146,17 @@ ${block}
2605
3146
  };
2606
3147
  var updatePromptFile = (filePath, overlay) => {
2607
3148
  if (!overlay) return false;
2608
- if (!fs6.existsSync(filePath)) return false;
2609
- const content = fs6.readFileSync(filePath, "utf8");
3149
+ if (!fs8.existsSync(filePath)) return false;
3150
+ const content = fs8.readFileSync(filePath, "utf8");
2610
3151
  const updated = insertOverlay(content, overlay);
2611
3152
  if (updated === content) return false;
2612
- fs6.writeFileSync(filePath, updated);
3153
+ fs8.writeFileSync(filePath, updated);
2613
3154
  return true;
2614
3155
  };
2615
3156
  var applyOverlays = (systemPromptsDir, overlays) => {
2616
3157
  const updated = [];
2617
3158
  for (const target of PROMPT_PACK_TARGETS) {
2618
- const filePath = path8.join(systemPromptsDir, target.filename);
3159
+ const filePath = path10.join(systemPromptsDir, target.filename);
2619
3160
  const overlay = overlays[target.key];
2620
3161
  if (updatePromptFile(filePath, overlay)) {
2621
3162
  updated.push(target.filename);
@@ -2628,7 +3169,7 @@ var applyPromptPack = (tweakDir, providerKey, mode = "minimal") => {
2628
3169
  return { changed: false, updated: [], mode };
2629
3170
  }
2630
3171
  const overlays = resolveOverlays(providerKey, mode);
2631
- const systemPromptsDir = path8.join(tweakDir, "system-prompts");
3172
+ const systemPromptsDir = path10.join(tweakDir, "system-prompts");
2632
3173
  const updated = applyOverlays(systemPromptsDir, overlays);
2633
3174
  return { changed: updated.length > 0, updated, mode };
2634
3175
  };
@@ -2695,10 +3236,10 @@ ${reapply.stdout ?? ""}`.trim();
2695
3236
  };
2696
3237
 
2697
3238
  // src/core/wrapper.ts
2698
- import fs7 from "node:fs";
2699
- import path9 from "node:path";
3239
+ import fs9 from "node:fs";
3240
+ import path11 from "node:path";
2700
3241
  var writeWrapper = (wrapperPath, configDir, binaryPath, runtime = "node") => {
2701
- const tweakDir = path9.join(path9.dirname(configDir), "tweakcc");
3242
+ const tweakDir = path11.join(path11.dirname(configDir), "tweakcc");
2702
3243
  const execLine = runtime === "node" ? `exec node "${binaryPath}" "$@"` : `exec "${binaryPath}" "$@"`;
2703
3244
  const envLoader = [
2704
3245
  "if command -v node >/dev/null 2>&1; then",
@@ -2770,6 +3311,15 @@ var writeWrapper = (wrapperPath, configDir, binaryPath, runtime = "node") => {
2770
3311
  // Deep blue
2771
3312
  ccrDim: "\x1B[38;5;31m",
2772
3313
  // Muted blue
3314
+ // Mirror: Silver/Chrome with electric blue
3315
+ mirPrimary: "\x1B[38;5;252m",
3316
+ // Silver/light gray
3317
+ mirSecondary: "\x1B[38;5;250m",
3318
+ // Platinum
3319
+ mirAccent: "\x1B[38;5;45m",
3320
+ // Electric cyan
3321
+ mirDim: "\x1B[38;5;243m",
3322
+ // Muted silver
2773
3323
  // Default: White/Gray
2774
3324
  defPrimary: "\x1B[38;5;255m",
2775
3325
  // White
@@ -2854,6 +3404,22 @@ var writeWrapper = (wrapperPath, configDir, binaryPath, runtime = "node") => {
2854
3404
  "CCMCCR",
2855
3405
  ' __cc_show_label="0"',
2856
3406
  " ;;",
3407
+ " mirror)",
3408
+ " cat <<'CCMMIR'",
3409
+ "",
3410
+ `${C.mirPrimary} \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557${C.reset}`,
3411
+ `${C.mirPrimary} \u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557${C.reset}`,
3412
+ `${C.mirSecondary} \u2588\u2588\u2554\u2588\u2588\u2588\u2588\u2554\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D${C.reset}`,
3413
+ `${C.mirSecondary} \u2588\u2588\u2551\u255A\u2588\u2588\u2554\u255D\u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557${C.reset}`,
3414
+ `${C.mirAccent} \u2588\u2588\u2551 \u255A\u2550\u255D \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551${C.reset}`,
3415
+ `${C.mirAccent} \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D${C.reset}`,
3416
+ "",
3417
+ `${C.mirDim} \u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${C.mirAccent}\u25C7${C.mirDim}\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501${C.reset}`,
3418
+ `${C.mirSecondary} Claude ${C.mirDim}\u2501${C.mirSecondary} Pure Reflection${C.reset}`,
3419
+ "",
3420
+ "CCMMIR",
3421
+ ' __cc_show_label="0"',
3422
+ " ;;",
2857
3423
  " *)",
2858
3424
  " cat <<'CCMGEN'",
2859
3425
  "",
@@ -2888,7 +3454,7 @@ var writeWrapper = (wrapperPath, configDir, binaryPath, runtime = "node") => {
2888
3454
  execLine,
2889
3455
  ""
2890
3456
  ].join("\n");
2891
- fs7.writeFileSync(wrapperPath, content, { mode: 493 });
3457
+ fs9.writeFileSync(wrapperPath, content, { mode: 493 });
2892
3458
  };
2893
3459
 
2894
3460
  // src/core/variant-builder/steps/WrapperStep.ts
@@ -2905,9 +3471,9 @@ var WrapperStep = class {
2905
3471
  };
2906
3472
 
2907
3473
  // src/core/shell-env.ts
2908
- import fs8 from "node:fs";
2909
- import os4 from "node:os";
2910
- import path10 from "node:path";
3474
+ import fs10 from "node:fs";
3475
+ import os5 from "node:os";
3476
+ import path12 from "node:path";
2911
3477
  var SETTINGS_FILE2 = "settings.json";
2912
3478
  var BLOCK_START = "# cc-mirror: Z.ai env start";
2913
3479
  var BLOCK_END = "# cc-mirror: Z.ai env end";
@@ -2919,22 +3485,22 @@ var normalizeApiKey = (value) => {
2919
3485
  return trimmed;
2920
3486
  };
2921
3487
  var resolveShellProfile = () => {
2922
- const home = os4.homedir();
3488
+ const home = os5.homedir();
2923
3489
  const shell = process.env.SHELL || "";
2924
- const name = path10.basename(shell);
3490
+ const name = path12.basename(shell);
2925
3491
  if (name === "zsh") {
2926
- return path10.join(home, ".zshrc");
3492
+ return path12.join(home, ".zshrc");
2927
3493
  }
2928
3494
  if (name === "bash") {
2929
- const bashrc = path10.join(home, ".bashrc");
2930
- if (fs8.existsSync(bashrc)) return bashrc;
2931
- return path10.join(home, ".bash_profile");
3495
+ const bashrc = path12.join(home, ".bashrc");
3496
+ if (fs10.existsSync(bashrc)) return bashrc;
3497
+ return path12.join(home, ".bash_profile");
2932
3498
  }
2933
3499
  return null;
2934
3500
  };
2935
3501
  var readSettingsApiKey2 = (configDir) => {
2936
- const settingsPath = path10.join(configDir, SETTINGS_FILE2);
2937
- if (!fs8.existsSync(settingsPath)) return null;
3502
+ const settingsPath = path12.join(configDir, SETTINGS_FILE2);
3503
+ if (!fs10.existsSync(settingsPath)) return null;
2938
3504
  const settings = readJson(settingsPath);
2939
3505
  const key = settings?.env?.ANTHROPIC_API_KEY;
2940
3506
  if (typeof key !== "string") return null;
@@ -2943,266 +3509,100 @@ var readSettingsApiKey2 = (configDir) => {
2943
3509
  var renderBlock = (apiKey) => `${BLOCK_START}
2944
3510
  export Z_AI_API_KEY="${apiKey}"
2945
3511
  ${BLOCK_END}
2946
- `;
2947
- var upsertBlock = (content, block) => {
2948
- if (content.includes(BLOCK_START) && content.includes(BLOCK_END)) {
2949
- const start = content.indexOf(BLOCK_START);
2950
- const end = content.indexOf(BLOCK_END, start);
2951
- const before = content.slice(0, start).trimEnd();
2952
- const after = content.slice(end + BLOCK_END.length).trimStart();
2953
- return `${before}
2954
-
2955
- ${block}
2956
- ${after}`.trimEnd() + "\n";
2957
- }
2958
- return `${content.trimEnd()}
2959
-
2960
- ${block}`.trimEnd() + "\n";
2961
- };
2962
- var hasZaiKeyInProfile = (content) => {
2963
- const lines = content.split("\n");
2964
- for (const line of lines) {
2965
- const trimmed = line.trim();
2966
- if (!trimmed || trimmed.startsWith("#")) continue;
2967
- const exportStripped = trimmed.startsWith("export ") ? trimmed.slice(7).trim() : trimmed;
2968
- if (!exportStripped.startsWith("Z_AI_API_KEY")) continue;
2969
- const equalsIndex = exportStripped.indexOf("=");
2970
- if (equalsIndex === -1) continue;
2971
- let value = exportStripped.slice(equalsIndex + 1).trim();
2972
- if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
2973
- value = value.slice(1, -1);
2974
- }
2975
- if (normalizeApiKey(value)) return true;
2976
- }
2977
- return false;
2978
- };
2979
- var ensureZaiShellEnv = (opts) => {
2980
- const apiKey = normalizeApiKey(opts.apiKey) || readSettingsApiKey2(opts.configDir);
2981
- if (!apiKey) {
2982
- return { status: "skipped", message: "Z_AI_API_KEY not set (missing API key)" };
2983
- }
2984
- const envKey = normalizeApiKey(process.env.Z_AI_API_KEY);
2985
- if (envKey) {
2986
- return { status: "skipped", message: "Z_AI_API_KEY already set in environment" };
2987
- }
2988
- const profile = opts.profilePath ?? resolveShellProfile();
2989
- if (!profile) {
2990
- return { status: "failed", message: "Unsupported shell; set Z_AI_API_KEY manually" };
2991
- }
2992
- const existing = fs8.existsSync(profile) ? fs8.readFileSync(profile, "utf8") : "";
2993
- if (hasZaiKeyInProfile(existing)) {
2994
- return { status: "skipped", message: "Z_AI_API_KEY already set in shell profile", path: profile };
2995
- }
2996
- const next = upsertBlock(existing, renderBlock(apiKey));
2997
- if (next === existing) {
2998
- return { status: "skipped", message: "Shell profile already up to date", path: profile };
2999
- }
3000
- fs8.writeFileSync(profile, next);
3001
- return { status: "updated", path: profile, message: `Run: source ${profile}` };
3002
- };
3003
-
3004
- // src/core/variant-builder/steps/ShellEnvStep.ts
3005
- var ShellEnvStep = class {
3006
- name = "ShellEnv";
3007
- execute(ctx) {
3008
- this.setupShellEnv(ctx);
3009
- }
3010
- async executeAsync(ctx) {
3011
- if (ctx.prefs.shellEnvEnabled && ctx.params.providerKey === "zai") {
3012
- await ctx.report("Configuring shell environment...");
3013
- }
3014
- this.setupShellEnv(ctx);
3015
- }
3016
- setupShellEnv(ctx) {
3017
- const { params, paths, prefs, state } = ctx;
3018
- if (prefs.shellEnvEnabled && params.providerKey === "zai") {
3019
- ctx.report("Configuring shell environment...");
3020
- const shellResult = ensureZaiShellEnv({
3021
- apiKey: state.resolvedApiKey ?? null,
3022
- configDir: paths.configDir
3023
- });
3024
- if (shellResult.status === "updated") {
3025
- const suffix = shellResult.message ? ` (${shellResult.message})` : "";
3026
- state.notes.push(`Z_AI_API_KEY written to ${shellResult.path}${suffix}`);
3027
- } else if (shellResult.status === "failed") {
3028
- state.notes.push(`Z_AI_API_KEY not written: ${shellResult.message || "unknown error"}`);
3029
- } else if (shellResult.message) {
3030
- state.notes.push(`Z_AI_API_KEY: ${shellResult.message}`);
3031
- }
3032
- } else if (params.providerKey === "zai") {
3033
- state.notes.push("Z_AI_API_KEY not written to shell profile. Set it manually in your shell rc file.");
3034
- }
3035
- }
3036
- };
3037
-
3038
- // src/core/variant-builder/steps/SkillInstallStep.ts
3039
- import path12 from "node:path";
3040
-
3041
- // src/core/skills.ts
3042
- import fs9 from "node:fs";
3043
- import os5 from "node:os";
3044
- import path11 from "node:path";
3045
- import { spawn as spawn3, spawnSync as spawnSync4 } from "node:child_process";
3046
- var DEV_BROWSER_REPO = "https://github.com/SawyerHood/dev-browser.git";
3047
- var DEV_BROWSER_ARCHIVE = "https://github.com/SawyerHood/dev-browser/archive/refs/heads/main.tar.gz";
3048
- var SKILL_SUBDIR = path11.join("skills", "dev-browser");
3049
- var MANAGED_MARKER = ".cc-mirror-managed";
3050
- var ensureDir2 = (dir) => {
3051
- fs9.mkdirSync(dir, { recursive: true });
3052
- };
3053
- var copyDir = (source, target) => {
3054
- fs9.cpSync(source, target, { recursive: true });
3055
- };
3056
- var resolveSkillSourceDir = (repoDir) => {
3057
- const direct = path11.join(repoDir, SKILL_SUBDIR);
3058
- if (fs9.existsSync(direct)) return direct;
3059
- const nested = fs9.readdirSync(repoDir).find((entry) => entry.startsWith("dev-browser-"));
3060
- if (nested) {
3061
- const candidate = path11.join(repoDir, nested, SKILL_SUBDIR);
3062
- if (fs9.existsSync(candidate)) return candidate;
3063
- }
3064
- return null;
3065
- };
3066
- var cloneRepo = (targetDir) => {
3067
- if (!commandExists("git")) return { ok: false, message: "git not found" };
3068
- const result = spawnSync4("git", ["clone", "--depth", "1", DEV_BROWSER_REPO, targetDir], {
3069
- encoding: "utf8"
3070
- });
3071
- if (result.status === 0) return { ok: true };
3072
- return { ok: false, message: result.stderr?.trim() || result.stdout?.trim() || "git clone failed" };
3073
- };
3074
- var downloadArchive = (targetDir) => {
3075
- if (!commandExists("curl") || !commandExists("tar")) {
3076
- return { ok: false, message: "curl or tar not found" };
3077
- }
3078
- const archivePath = path11.join(targetDir, "dev-browser.tar.gz");
3079
- const curlResult = spawnSync4("curl", ["-L", "-o", archivePath, DEV_BROWSER_ARCHIVE], { encoding: "utf8" });
3080
- if (curlResult.status !== 0) {
3081
- return { ok: false, message: curlResult.stderr?.trim() || "curl failed" };
3082
- }
3083
- const tarResult = spawnSync4("tar", ["-xzf", archivePath, "-C", targetDir], { encoding: "utf8" });
3084
- if (tarResult.status !== 0) {
3085
- return { ok: false, message: tarResult.stderr?.trim() || "tar extract failed" };
3086
- }
3087
- return { ok: true };
3088
- };
3089
- var ensureDevBrowserSkill = (opts) => {
3090
- if (!opts.install) {
3091
- return { status: "skipped", message: "skill install disabled" };
3092
- }
3093
- const skillRoot = opts.targetDir || path11.join(os5.homedir(), ".claude", "skills");
3094
- const targetDir = path11.join(skillRoot, "dev-browser");
3095
- const markerPath = path11.join(targetDir, MANAGED_MARKER);
3096
- const exists = fs9.existsSync(targetDir);
3097
- const managed = exists && fs9.existsSync(markerPath);
3098
- if (exists && !managed && !opts.update) {
3099
- return { status: "skipped", message: "existing skill is user-managed", path: targetDir };
3100
- }
3101
- ensureDir2(skillRoot);
3102
- const tmpDir = fs9.mkdtempSync(path11.join(os5.tmpdir(), "cc-mirror-skill-"));
3103
- try {
3104
- let fetchResult = cloneRepo(tmpDir);
3105
- if (!fetchResult.ok) {
3106
- fetchResult = downloadArchive(tmpDir);
3107
- }
3108
- if (!fetchResult.ok) {
3109
- return { status: "failed", message: fetchResult.message || "skill fetch failed" };
3110
- }
3111
- const sourceDir = resolveSkillSourceDir(tmpDir);
3112
- if (!sourceDir) {
3113
- return { status: "failed", message: "skill source not found after download" };
3114
- }
3115
- if (exists) {
3116
- fs9.rmSync(targetDir, { recursive: true, force: true });
3117
- }
3118
- copyDir(sourceDir, targetDir);
3119
- fs9.writeFileSync(
3120
- markerPath,
3121
- JSON.stringify({ managedBy: "cc-mirror", updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
3122
- );
3123
- return { status: exists ? "updated" : "installed", path: targetDir };
3124
- } catch (error) {
3125
- const message = error instanceof Error ? error.message : String(error);
3126
- return { status: "failed", message };
3127
- } finally {
3128
- fs9.rmSync(tmpDir, { recursive: true, force: true });
3129
- }
3130
- };
3131
- var spawnAsync = (cmd, args) => {
3132
- return new Promise((resolve) => {
3133
- const child = spawn3(cmd, args, { stdio: "pipe" });
3134
- let stderr = "";
3135
- let stdout = "";
3136
- child.stdout?.on("data", (d) => {
3137
- stdout += d.toString();
3138
- });
3139
- child.stderr?.on("data", (d) => {
3140
- stderr += d.toString();
3141
- });
3142
- child.on("close", (code) => {
3143
- if (code === 0) resolve({ ok: true });
3144
- else resolve({ ok: false, message: stderr.trim() || stdout.trim() || `${cmd} failed` });
3145
- });
3146
- child.on("error", (err) => resolve({ ok: false, message: err.message }));
3147
- });
3148
- };
3149
- var cloneRepoAsync = async (targetDir) => {
3150
- if (!commandExists("git")) return { ok: false, message: "git not found" };
3151
- return spawnAsync("git", ["clone", "--depth", "1", DEV_BROWSER_REPO, targetDir]);
3512
+ `;
3513
+ var upsertBlock = (content, block) => {
3514
+ if (content.includes(BLOCK_START) && content.includes(BLOCK_END)) {
3515
+ const start = content.indexOf(BLOCK_START);
3516
+ const end = content.indexOf(BLOCK_END, start);
3517
+ const before = content.slice(0, start).trimEnd();
3518
+ const after = content.slice(end + BLOCK_END.length).trimStart();
3519
+ return `${before}
3520
+
3521
+ ${block}
3522
+ ${after}`.trimEnd() + "\n";
3523
+ }
3524
+ return `${content.trimEnd()}
3525
+
3526
+ ${block}`.trimEnd() + "\n";
3152
3527
  };
3153
- var downloadArchiveAsync = async (targetDir) => {
3154
- if (!commandExists("curl") || !commandExists("tar")) {
3155
- return { ok: false, message: "curl or tar not found" };
3528
+ var hasZaiKeyInProfile = (content) => {
3529
+ const lines = content.split("\n");
3530
+ for (const line of lines) {
3531
+ const trimmed = line.trim();
3532
+ if (!trimmed || trimmed.startsWith("#")) continue;
3533
+ const exportStripped = trimmed.startsWith("export ") ? trimmed.slice(7).trim() : trimmed;
3534
+ if (!exportStripped.startsWith("Z_AI_API_KEY")) continue;
3535
+ const equalsIndex = exportStripped.indexOf("=");
3536
+ if (equalsIndex === -1) continue;
3537
+ let value = exportStripped.slice(equalsIndex + 1).trim();
3538
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
3539
+ value = value.slice(1, -1);
3540
+ }
3541
+ if (normalizeApiKey(value)) return true;
3156
3542
  }
3157
- const archivePath = path11.join(targetDir, "dev-browser.tar.gz");
3158
- const curlResult = await spawnAsync("curl", ["-L", "-o", archivePath, DEV_BROWSER_ARCHIVE]);
3159
- if (!curlResult.ok) return curlResult;
3160
- return spawnAsync("tar", ["-xzf", archivePath, "-C", targetDir]);
3543
+ return false;
3161
3544
  };
3162
- var ensureDevBrowserSkillAsync = async (opts) => {
3163
- if (!opts.install) {
3164
- return { status: "skipped", message: "skill install disabled" };
3545
+ var ensureZaiShellEnv = (opts) => {
3546
+ const apiKey = normalizeApiKey(opts.apiKey) || readSettingsApiKey2(opts.configDir);
3547
+ if (!apiKey) {
3548
+ return { status: "skipped", message: "Z_AI_API_KEY not set (missing API key)" };
3165
3549
  }
3166
- const skillRoot = opts.targetDir || path11.join(os5.homedir(), ".claude", "skills");
3167
- const targetDir = path11.join(skillRoot, "dev-browser");
3168
- const markerPath = path11.join(targetDir, MANAGED_MARKER);
3169
- const exists = fs9.existsSync(targetDir);
3170
- const managed = exists && fs9.existsSync(markerPath);
3171
- if (exists && !managed && !opts.update) {
3172
- return { status: "skipped", message: "existing skill is user-managed", path: targetDir };
3550
+ const envKey = normalizeApiKey(process.env.Z_AI_API_KEY);
3551
+ if (envKey) {
3552
+ return { status: "skipped", message: "Z_AI_API_KEY already set in environment" };
3173
3553
  }
3174
- ensureDir2(skillRoot);
3175
- const tmpDir = fs9.mkdtempSync(path11.join(os5.tmpdir(), "cc-mirror-skill-"));
3176
- try {
3177
- let fetchResult = await cloneRepoAsync(tmpDir);
3178
- if (!fetchResult.ok) {
3179
- fetchResult = await downloadArchiveAsync(tmpDir);
3180
- }
3181
- if (!fetchResult.ok) {
3182
- return { status: "failed", message: fetchResult.message || "skill fetch failed" };
3183
- }
3184
- const sourceDir = resolveSkillSourceDir(tmpDir);
3185
- if (!sourceDir) {
3186
- return { status: "failed", message: "skill source not found after download" };
3554
+ const profile = opts.profilePath ?? resolveShellProfile();
3555
+ if (!profile) {
3556
+ return { status: "failed", message: "Unsupported shell; set Z_AI_API_KEY manually" };
3557
+ }
3558
+ const existing = fs10.existsSync(profile) ? fs10.readFileSync(profile, "utf8") : "";
3559
+ if (hasZaiKeyInProfile(existing)) {
3560
+ return { status: "skipped", message: "Z_AI_API_KEY already set in shell profile", path: profile };
3561
+ }
3562
+ const next = upsertBlock(existing, renderBlock(apiKey));
3563
+ if (next === existing) {
3564
+ return { status: "skipped", message: "Shell profile already up to date", path: profile };
3565
+ }
3566
+ fs10.writeFileSync(profile, next);
3567
+ return { status: "updated", path: profile, message: `Run: source ${profile}` };
3568
+ };
3569
+
3570
+ // src/core/variant-builder/steps/ShellEnvStep.ts
3571
+ var ShellEnvStep = class {
3572
+ name = "ShellEnv";
3573
+ execute(ctx) {
3574
+ this.setupShellEnv(ctx);
3575
+ }
3576
+ async executeAsync(ctx) {
3577
+ if (ctx.prefs.shellEnvEnabled && ctx.params.providerKey === "zai") {
3578
+ await ctx.report("Configuring shell environment...");
3187
3579
  }
3188
- if (exists) {
3189
- fs9.rmSync(targetDir, { recursive: true, force: true });
3580
+ this.setupShellEnv(ctx);
3581
+ }
3582
+ setupShellEnv(ctx) {
3583
+ const { params, paths, prefs, state } = ctx;
3584
+ if (prefs.shellEnvEnabled && params.providerKey === "zai") {
3585
+ ctx.report("Configuring shell environment...");
3586
+ const shellResult = ensureZaiShellEnv({
3587
+ apiKey: state.resolvedApiKey ?? null,
3588
+ configDir: paths.configDir
3589
+ });
3590
+ if (shellResult.status === "updated") {
3591
+ const suffix = shellResult.message ? ` (${shellResult.message})` : "";
3592
+ state.notes.push(`Z_AI_API_KEY written to ${shellResult.path}${suffix}`);
3593
+ } else if (shellResult.status === "failed") {
3594
+ state.notes.push(`Z_AI_API_KEY not written: ${shellResult.message || "unknown error"}`);
3595
+ } else if (shellResult.message) {
3596
+ state.notes.push(`Z_AI_API_KEY: ${shellResult.message}`);
3597
+ }
3598
+ } else if (params.providerKey === "zai") {
3599
+ state.notes.push("Z_AI_API_KEY not written to shell profile. Set it manually in your shell rc file.");
3190
3600
  }
3191
- copyDir(sourceDir, targetDir);
3192
- fs9.writeFileSync(
3193
- markerPath,
3194
- JSON.stringify({ managedBy: "cc-mirror", updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2)
3195
- );
3196
- return { status: exists ? "updated" : "installed", path: targetDir };
3197
- } catch (error) {
3198
- const message = error instanceof Error ? error.message : String(error);
3199
- return { status: "failed", message };
3200
- } finally {
3201
- fs9.rmSync(tmpDir, { recursive: true, force: true });
3202
3601
  }
3203
3602
  };
3204
3603
 
3205
3604
  // src/core/variant-builder/steps/SkillInstallStep.ts
3605
+ import path13 from "node:path";
3206
3606
  var SkillInstallStep = class {
3207
3607
  name = "SkillInstall";
3208
3608
  execute(ctx) {
@@ -3214,7 +3614,7 @@ var SkillInstallStep = class {
3214
3614
  const skillResult = ensureDevBrowserSkill({
3215
3615
  install: true,
3216
3616
  update: prefs.skillUpdateEnabled,
3217
- targetDir: path12.join(paths.configDir, "skills")
3617
+ targetDir: path13.join(paths.configDir, "skills")
3218
3618
  });
3219
3619
  if (skillResult.status === "failed") {
3220
3620
  state.notes.push(`dev-browser skill install failed: ${skillResult.message || "unknown error"}`);
@@ -3231,7 +3631,7 @@ var SkillInstallStep = class {
3231
3631
  const skillResult = await ensureDevBrowserSkillAsync({
3232
3632
  install: true,
3233
3633
  update: prefs.skillUpdateEnabled,
3234
- targetDir: path12.join(paths.configDir, "skills")
3634
+ targetDir: path13.join(paths.configDir, "skills")
3235
3635
  });
3236
3636
  if (skillResult.status === "failed") {
3237
3637
  state.notes.push(`dev-browser skill install failed: ${skillResult.message || "unknown error"}`);
@@ -3242,7 +3642,7 @@ var SkillInstallStep = class {
3242
3642
  };
3243
3643
 
3244
3644
  // src/core/variant-builder/steps/FinalizeStep.ts
3245
- import path13 from "node:path";
3645
+ import path14 from "node:path";
3246
3646
  var FinalizeStep = class {
3247
3647
  name = "Finalize";
3248
3648
  execute(ctx) {
@@ -3254,7 +3654,8 @@ var FinalizeStep = class {
3254
3654
  this.finalize(ctx);
3255
3655
  }
3256
3656
  finalize(ctx) {
3257
- const { params, paths, prefs, state } = ctx;
3657
+ const { params, paths, prefs, state, provider } = ctx;
3658
+ const teamModeEnabled = Boolean(params.enableTeamMode) || Boolean(provider.enablesTeamMode);
3258
3659
  const meta = {
3259
3660
  name: params.name,
3260
3661
  provider: params.providerKey,
@@ -3273,9 +3674,10 @@ var FinalizeStep = class {
3273
3674
  installType: "npm",
3274
3675
  npmDir: paths.npmDir,
3275
3676
  npmPackage: prefs.resolvedNpmPackage,
3276
- npmVersion: prefs.resolvedNpmVersion
3677
+ npmVersion: prefs.resolvedNpmVersion,
3678
+ teamModeEnabled
3277
3679
  };
3278
- writeJson(path13.join(paths.variantDir, "variant.json"), meta);
3680
+ writeJson(path14.join(paths.variantDir, "variant.json"), meta);
3279
3681
  state.meta = meta;
3280
3682
  }
3281
3683
  };
@@ -3283,7 +3685,10 @@ var FinalizeStep = class {
3283
3685
  // src/core/variant-builder/VariantBuilder.ts
3284
3686
  var normalizeNpmPackage = (value) => value && value.trim().length > 0 ? value.trim() : DEFAULT_NPM_PACKAGE;
3285
3687
  var normalizeNpmVersion = () => DEFAULT_NPM_VERSION;
3286
- var shouldEnablePromptPack = (providerKey) => providerKey === "zai" || providerKey === "minimax";
3688
+ var shouldEnablePromptPack = (providerKey, provider) => {
3689
+ if (provider?.noPromptPack) return false;
3690
+ return providerKey === "zai" || providerKey === "minimax";
3691
+ };
3287
3692
  var defaultPromptPackMode = (providerKey) => providerKey === "zai" || providerKey === "minimax" ? "maximal" : "minimal";
3288
3693
  var shouldInstallSkills = (providerKey) => providerKey === "zai" || providerKey === "minimax";
3289
3694
  var shouldEnableShellEnv = (providerKey) => providerKey === "zai";
@@ -3294,6 +3699,8 @@ var VariantBuilder = class {
3294
3699
  this.steps = [
3295
3700
  new PrepareDirectoriesStep(),
3296
3701
  new InstallNpmStep(),
3702
+ new TeamModeStep(),
3703
+ // Patches cli.js for team mode (if enabled)
3297
3704
  new WriteConfigStep(),
3298
3705
  new BrandThemeStep(),
3299
3706
  new TweakccStep(),
@@ -3315,11 +3722,11 @@ var VariantBuilder = class {
3315
3722
  const binDir = params.binDir ?? DEFAULT_BIN_DIR;
3316
3723
  const resolvedRoot = expandTilde(rootDir) ?? rootDir;
3317
3724
  const resolvedBin = expandTilde(binDir) ?? binDir;
3318
- const variantDir = path14.join(resolvedRoot, params.name);
3319
- const configDir = path14.join(variantDir, "config");
3320
- const tweakDir = path14.join(variantDir, "tweakcc");
3321
- const wrapperPath = path14.join(resolvedBin, params.name);
3322
- const npmDir = path14.join(variantDir, "npm");
3725
+ const variantDir = path15.join(resolvedRoot, params.name);
3726
+ const configDir = path15.join(variantDir, "config");
3727
+ const tweakDir = path15.join(variantDir, "tweakcc");
3728
+ const wrapperPath = path15.join(resolvedBin, params.name);
3729
+ const npmDir = path15.join(variantDir, "npm");
3323
3730
  const paths = {
3324
3731
  resolvedRoot,
3325
3732
  resolvedBin,
@@ -3331,7 +3738,7 @@ var VariantBuilder = class {
3331
3738
  };
3332
3739
  const resolvedNpmPackage = normalizeNpmPackage(params.npmPackage);
3333
3740
  const resolvedNpmVersion = normalizeNpmVersion();
3334
- const promptPackPreference = params.promptPack ?? shouldEnablePromptPack(params.providerKey);
3741
+ const promptPackPreference = params.promptPack ?? shouldEnablePromptPack(params.providerKey, provider);
3335
3742
  const promptPackModePreference = params.promptPackMode ?? defaultPromptPackMode(params.providerKey);
3336
3743
  const promptPackEnabled = !params.noTweak && promptPackPreference;
3337
3744
  const skillInstallEnabled = params.skillInstall ?? shouldInstallSkills(params.providerKey);
@@ -3416,7 +3823,7 @@ var VariantBuilder = class {
3416
3823
  };
3417
3824
 
3418
3825
  // src/core/variant-builder/VariantUpdater.ts
3419
- import path18 from "node:path";
3826
+ import path20 from "node:path";
3420
3827
 
3421
3828
  // src/core/variant-builder/update-steps/InstallNpmUpdateStep.ts
3422
3829
  var InstallNpmUpdateStep = class {
@@ -3450,6 +3857,128 @@ var InstallNpmUpdateStep = class {
3450
3857
  }
3451
3858
  };
3452
3859
 
3860
+ // src/core/variant-builder/update-steps/TeamModeUpdateStep.ts
3861
+ import fs11 from "node:fs";
3862
+ import path16 from "node:path";
3863
+ var TEAM_MODE_DISABLED2 = "function sU(){return!1}";
3864
+ var TEAM_MODE_ENABLED2 = "function sU(){return!0}";
3865
+ var TeamModeUpdateStep = class {
3866
+ name = "TeamMode";
3867
+ shouldEnableTeamMode(ctx) {
3868
+ const provider = getProvider(ctx.meta.provider);
3869
+ return Boolean(ctx.opts.enableTeamMode) || Boolean(provider?.enablesTeamMode);
3870
+ }
3871
+ shouldDisableTeamMode(ctx) {
3872
+ return Boolean(ctx.opts.disableTeamMode);
3873
+ }
3874
+ execute(ctx) {
3875
+ if (this.shouldDisableTeamMode(ctx)) {
3876
+ ctx.report("Disabling team mode...");
3877
+ this.unpatchCli(ctx);
3878
+ return;
3879
+ }
3880
+ if (!this.shouldEnableTeamMode(ctx)) return;
3881
+ ctx.report("Enabling team mode...");
3882
+ this.patchCli(ctx);
3883
+ }
3884
+ async executeAsync(ctx) {
3885
+ if (this.shouldDisableTeamMode(ctx)) {
3886
+ await ctx.report("Disabling team mode...");
3887
+ this.unpatchCli(ctx);
3888
+ return;
3889
+ }
3890
+ if (!this.shouldEnableTeamMode(ctx)) return;
3891
+ await ctx.report("Enabling team mode...");
3892
+ this.patchCli(ctx);
3893
+ }
3894
+ unpatchCli(ctx) {
3895
+ const { state, meta } = ctx;
3896
+ const cliPath = path16.join(meta.npmDir || "", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
3897
+ if (!fs11.existsSync(cliPath)) {
3898
+ state.notes.push("Warning: cli.js not found, skipping team mode unpatch");
3899
+ return;
3900
+ }
3901
+ let content = fs11.readFileSync(cliPath, "utf8");
3902
+ if (content.includes(TEAM_MODE_DISABLED2)) {
3903
+ state.notes.push("Team mode already disabled");
3904
+ meta.teamModeEnabled = false;
3905
+ return;
3906
+ }
3907
+ if (!content.includes(TEAM_MODE_ENABLED2)) {
3908
+ state.notes.push("Warning: Team mode function not found in cli.js");
3909
+ return;
3910
+ }
3911
+ content = content.replace(TEAM_MODE_ENABLED2, TEAM_MODE_DISABLED2);
3912
+ fs11.writeFileSync(cliPath, content);
3913
+ const verifyContent = fs11.readFileSync(cliPath, "utf8");
3914
+ if (!verifyContent.includes(TEAM_MODE_DISABLED2)) {
3915
+ state.notes.push("Warning: Team mode unpatch verification failed");
3916
+ return;
3917
+ }
3918
+ meta.teamModeEnabled = false;
3919
+ state.notes.push("Team mode disabled successfully");
3920
+ const skillResult = removeOrchestratorSkill(meta.configDir);
3921
+ if (skillResult.status === "removed") {
3922
+ state.notes.push("Multi-agent orchestrator skill removed");
3923
+ } else if (skillResult.status === "failed") {
3924
+ state.notes.push(`Warning: orchestrator skill removal failed: ${skillResult.message}`);
3925
+ }
3926
+ }
3927
+ patchCli(ctx) {
3928
+ const { state, meta, name } = ctx;
3929
+ const cliPath = path16.join(meta.npmDir || "", "node_modules", "@anthropic-ai", "claude-code", "cli.js");
3930
+ const backupPath = `${cliPath}.backup`;
3931
+ if (!fs11.existsSync(cliPath)) {
3932
+ state.notes.push("Warning: cli.js not found, skipping team mode patch");
3933
+ return;
3934
+ }
3935
+ if (!fs11.existsSync(backupPath)) {
3936
+ fs11.copyFileSync(cliPath, backupPath);
3937
+ }
3938
+ let content = fs11.readFileSync(cliPath, "utf8");
3939
+ if (content.includes(TEAM_MODE_ENABLED2)) {
3940
+ state.notes.push("Team mode already enabled");
3941
+ meta.teamModeEnabled = true;
3942
+ return;
3943
+ }
3944
+ if (!content.includes(TEAM_MODE_DISABLED2)) {
3945
+ state.notes.push("Warning: Team mode function not found in cli.js, patch may not work");
3946
+ return;
3947
+ }
3948
+ content = content.replace(TEAM_MODE_DISABLED2, TEAM_MODE_ENABLED2);
3949
+ fs11.writeFileSync(cliPath, content);
3950
+ const verifyContent = fs11.readFileSync(cliPath, "utf8");
3951
+ if (!verifyContent.includes(TEAM_MODE_ENABLED2)) {
3952
+ state.notes.push("Warning: Team mode patch verification failed");
3953
+ return;
3954
+ }
3955
+ const settingsPath = path16.join(meta.configDir, "settings.json");
3956
+ if (fs11.existsSync(settingsPath)) {
3957
+ try {
3958
+ const settings = JSON.parse(fs11.readFileSync(settingsPath, "utf8"));
3959
+ settings.env = settings.env || {};
3960
+ if (!settings.env.CLAUDE_CODE_TEAM_NAME) {
3961
+ settings.env.CLAUDE_CODE_TEAM_NAME = name;
3962
+ }
3963
+ if (!settings.env.CLAUDE_CODE_AGENT_TYPE) {
3964
+ settings.env.CLAUDE_CODE_AGENT_TYPE = "team-lead";
3965
+ }
3966
+ fs11.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
3967
+ } catch {
3968
+ state.notes.push("Warning: Could not update settings.json with team env vars");
3969
+ }
3970
+ }
3971
+ meta.teamModeEnabled = true;
3972
+ state.notes.push("Team mode enabled successfully");
3973
+ const skillResult = installOrchestratorSkill(meta.configDir);
3974
+ if (skillResult.status === "installed") {
3975
+ state.notes.push("Multi-agent orchestrator skill installed");
3976
+ } else if (skillResult.status === "failed") {
3977
+ state.notes.push(`Warning: orchestrator skill install failed: ${skillResult.message}`);
3978
+ }
3979
+ }
3980
+ };
3981
+
3453
3982
  // src/core/variant-builder/update-steps/ModelOverridesStep.ts
3454
3983
  var ModelOverridesStep = class {
3455
3984
  name = "ModelOverrides";
@@ -3533,7 +4062,7 @@ ${reapply.stdout ?? ""}`.trim();
3533
4062
  };
3534
4063
 
3535
4064
  // src/core/variant-builder/update-steps/WrapperUpdateStep.ts
3536
- import path15 from "node:path";
4065
+ import path17 from "node:path";
3537
4066
  var WrapperUpdateStep = class {
3538
4067
  name = "Wrapper";
3539
4068
  execute(ctx) {
@@ -3551,7 +4080,7 @@ var WrapperUpdateStep = class {
3551
4080
  const resolvedBin = opts.binDir ? expandTilde(opts.binDir) ?? opts.binDir : meta.binDir;
3552
4081
  if (resolvedBin) {
3553
4082
  ensureDir(resolvedBin);
3554
- const wrapperPath = path15.join(resolvedBin, name);
4083
+ const wrapperPath = path17.join(resolvedBin, name);
3555
4084
  writeWrapper(wrapperPath, meta.configDir, meta.binaryPath, "node");
3556
4085
  meta.binDir = resolvedBin;
3557
4086
  }
@@ -3643,7 +4172,7 @@ var ShellEnvUpdateStep = class {
3643
4172
  };
3644
4173
 
3645
4174
  // src/core/variant-builder/update-steps/SkillInstallUpdateStep.ts
3646
- import path16 from "node:path";
4175
+ import path18 from "node:path";
3647
4176
  var SkillInstallUpdateStep = class {
3648
4177
  name = "SkillInstall";
3649
4178
  execute(ctx) {
@@ -3663,7 +4192,7 @@ var SkillInstallUpdateStep = class {
3663
4192
  const skillOpts = {
3664
4193
  install: true,
3665
4194
  update: prefs.skillUpdateEnabled,
3666
- targetDir: path16.join(meta.configDir, "skills")
4195
+ targetDir: path18.join(meta.configDir, "skills")
3667
4196
  };
3668
4197
  const skillResult = isAsync ? await ensureDevBrowserSkillAsync(skillOpts) : ensureDevBrowserSkill(skillOpts);
3669
4198
  if (skillResult.status === "failed") {
@@ -3675,7 +4204,7 @@ var SkillInstallUpdateStep = class {
3675
4204
  };
3676
4205
 
3677
4206
  // src/core/variant-builder/update-steps/FinalizeUpdateStep.ts
3678
- import path17 from "node:path";
4207
+ import path19 from "node:path";
3679
4208
  var FinalizeUpdateStep = class {
3680
4209
  name = "Finalize";
3681
4210
  execute(ctx) {
@@ -3693,14 +4222,18 @@ var FinalizeUpdateStep = class {
3693
4222
  meta.promptPackMode = prefs.promptPackModePreference;
3694
4223
  meta.skillInstall = prefs.skillInstallEnabled;
3695
4224
  meta.shellEnv = prefs.shellEnvEnabled;
3696
- writeJson(path17.join(paths.variantDir, "variant.json"), meta);
4225
+ writeJson(path19.join(paths.variantDir, "variant.json"), meta);
3697
4226
  }
3698
4227
  };
3699
4228
 
3700
4229
  // src/core/variant-builder/VariantUpdater.ts
3701
4230
  var normalizeNpmPackage2 = (value) => value && value.trim().length > 0 ? value.trim() : DEFAULT_NPM_PACKAGE;
3702
4231
  var normalizeNpmVersion2 = () => DEFAULT_NPM_VERSION;
3703
- var shouldEnablePromptPack2 = (providerKey) => providerKey === "zai" || providerKey === "minimax";
4232
+ var shouldEnablePromptPack2 = (providerKey) => {
4233
+ const provider = getProvider(providerKey);
4234
+ if (provider?.noPromptPack) return false;
4235
+ return providerKey === "zai" || providerKey === "minimax";
4236
+ };
3704
4237
  var defaultPromptPackMode2 = (providerKey) => providerKey === "zai" || providerKey === "minimax" ? "maximal" : "minimal";
3705
4238
  var shouldInstallSkills2 = (providerKey) => providerKey === "zai" || providerKey === "minimax";
3706
4239
  var shouldEnableShellEnv2 = (providerKey) => providerKey === "zai";
@@ -3710,6 +4243,8 @@ var VariantUpdater = class {
3710
4243
  this.isAsync = isAsync;
3711
4244
  this.steps = [
3712
4245
  new InstallNpmUpdateStep(),
4246
+ new TeamModeUpdateStep(),
4247
+ // Patches cli.js for team mode (if enabled)
3713
4248
  new ModelOverridesStep(),
3714
4249
  new TweakccUpdateStep(),
3715
4250
  new WrapperUpdateStep(),
@@ -3725,7 +4260,7 @@ var VariantUpdater = class {
3725
4260
  */
3726
4261
  initContext(rootDir, name, opts) {
3727
4262
  const resolvedRoot = expandTilde(rootDir || DEFAULT_ROOT) ?? rootDir;
3728
- const variantDir = path18.join(resolvedRoot, name);
4263
+ const variantDir = path20.join(resolvedRoot, name);
3729
4264
  const meta = loadVariantMeta(variantDir);
3730
4265
  if (!meta) throw new Error(`Variant not found: ${name}`);
3731
4266
  const resolvedNpmPackage = normalizeNpmPackage2(opts.npmPackage ?? meta.npmPackage);
@@ -3741,7 +4276,7 @@ var VariantUpdater = class {
3741
4276
  resolvedRoot,
3742
4277
  resolvedBin: opts.binDir ? expandTilde(opts.binDir) ?? opts.binDir : meta.binDir,
3743
4278
  variantDir,
3744
- npmDir: meta.npmDir || path18.join(variantDir, "npm")
4279
+ npmDir: meta.npmDir || path20.join(variantDir, "npm")
3745
4280
  };
3746
4281
  const prefs = {
3747
4282
  resolvedNpmPackage,
@@ -3829,17 +4364,17 @@ var updateVariant = (rootDir, name, opts = {}) => {
3829
4364
  };
3830
4365
  var removeVariant = (rootDir, name) => {
3831
4366
  const resolvedRoot = expandTilde(rootDir || DEFAULT_ROOT) ?? rootDir;
3832
- const variantDir = path19.join(resolvedRoot, name);
3833
- if (!fs10.existsSync(variantDir)) throw new Error(`Variant not found: ${name}`);
3834
- fs10.rmSync(variantDir, { recursive: true, force: true });
4367
+ const variantDir = path21.join(resolvedRoot, name);
4368
+ if (!fs12.existsSync(variantDir)) throw new Error(`Variant not found: ${name}`);
4369
+ fs12.rmSync(variantDir, { recursive: true, force: true });
3835
4370
  };
3836
4371
  var doctor = (rootDir, binDir) => {
3837
4372
  const resolvedRoot = expandTilde(rootDir || DEFAULT_ROOT) ?? rootDir;
3838
4373
  const resolvedBin = expandTilde(binDir || DEFAULT_BIN_DIR) ?? binDir;
3839
4374
  const variants = listVariants(resolvedRoot);
3840
4375
  return variants.map(({ name, meta }) => {
3841
- const wrapperPath = path19.join(resolvedBin, name);
3842
- const ok = Boolean(meta && fs10.existsSync(meta.binaryPath) && fs10.existsSync(wrapperPath));
4376
+ const wrapperPath = path21.join(resolvedBin, name);
4377
+ const ok = Boolean(meta && fs12.existsSync(meta.binaryPath) && fs12.existsSync(wrapperPath));
3843
4378
  return {
3844
4379
  name,
3845
4380
  ok,
@@ -3851,7 +4386,7 @@ var doctor = (rootDir, binDir) => {
3851
4386
  var listVariants2 = (rootDir) => listVariants(rootDir);
3852
4387
  var tweakVariant = (rootDir, name) => {
3853
4388
  const resolvedRoot = expandTilde(rootDir || DEFAULT_ROOT) ?? rootDir;
3854
- const variantDir = path19.join(resolvedRoot, name);
4389
+ const variantDir = path21.join(resolvedRoot, name);
3855
4390
  const meta = loadVariantMeta(variantDir);
3856
4391
  if (!meta) throw new Error(`Variant not found: ${name}`);
3857
4392
  ensureDir(meta.tweakDir);
@@ -3867,7 +4402,7 @@ ${result.stdout ?? ""}`.trim();
3867
4402
 
3868
4403
  // src/tui/hooks/useVariantCreate.ts
3869
4404
  import { useEffect } from "react";
3870
- import path20 from "node:path";
4405
+ import path22 from "node:path";
3871
4406
  function buildCreateSummary(params) {
3872
4407
  const {
3873
4408
  providerLabel,
@@ -3898,7 +4433,7 @@ function buildCreateNextSteps(name, rootDir) {
3898
4433
  `Run: ${name}`,
3899
4434
  `Update: cc-mirror update ${name}`,
3900
4435
  `Tweak: cc-mirror tweak ${name}`,
3901
- `Config: ${path20.join(rootDir, name, "config", "settings.json")}`
4436
+ `Config: ${path22.join(rootDir, name, "config", "settings.json")}`
3902
4437
  ];
3903
4438
  }
3904
4439
  function buildHelpLines() {
@@ -3952,7 +4487,7 @@ function useVariantCreate(options) {
3952
4487
  doneLines: [
3953
4488
  `Variant created: ${params.name}`,
3954
4489
  `Wrapper: ${result.wrapperPath}`,
3955
- `Config: ${path20.join(params.rootDir, params.name, "config")}`
4490
+ `Config: ${path22.join(params.rootDir, params.name, "config")}`
3956
4491
  ],
3957
4492
  summary,
3958
4493
  nextSteps: buildCreateNextSteps(params.name, params.rootDir),
@@ -3980,7 +4515,7 @@ function useVariantCreate(options) {
3980
4515
 
3981
4516
  // src/tui/hooks/useVariantUpdate.ts
3982
4517
  import { useEffect as useEffect2 } from "react";
3983
- import path21 from "node:path";
4518
+ import path23 from "node:path";
3984
4519
  function buildUpdateSummary(meta, notes) {
3985
4520
  return [
3986
4521
  `Provider: ${meta.provider}`,
@@ -3994,7 +4529,7 @@ function buildUpdateNextSteps(name, rootDir) {
3994
4529
  return [
3995
4530
  `Run: ${name}`,
3996
4531
  `Tweak: cc-mirror tweak ${name}`,
3997
- `Config: ${path21.join(rootDir, name, "config", "settings.json")}`
4532
+ `Config: ${path23.join(rootDir, name, "config", "settings.json")}`
3998
4533
  ];
3999
4534
  }
4000
4535
  function useVariantUpdate(options) {
@@ -4186,6 +4721,59 @@ function useModelConfig(options) {
4186
4721
  ]);
4187
4722
  }
4188
4723
 
4724
+ // src/tui/hooks/useTeamModeToggle.ts
4725
+ import { useEffect as useEffect5 } from "react";
4726
+ function useTeamModeToggle(options) {
4727
+ const { screen, selectedVariant, rootDir, binDir, core, setProgressLines, setScreen, onComplete, refreshVariants } = options;
4728
+ useEffect5(() => {
4729
+ if (screen !== "manage-team-mode") return;
4730
+ if (!selectedVariant) return;
4731
+ let cancelled = false;
4732
+ const runToggle = async () => {
4733
+ try {
4734
+ setProgressLines(() => []);
4735
+ const isCurrentlyEnabled = selectedVariant.teamModeEnabled;
4736
+ const action = isCurrentlyEnabled ? "Disabling" : "Enabling";
4737
+ setProgressLines((prev) => [...prev, `${action} team mode...`]);
4738
+ const opts = {
4739
+ tweakccStdio: "pipe",
4740
+ binDir,
4741
+ settingsOnly: true,
4742
+ // Don't reinstall npm package
4743
+ enableTeamMode: !isCurrentlyEnabled,
4744
+ disableTeamMode: isCurrentlyEnabled,
4745
+ onProgress: (step) => setProgressLines((prev) => [...prev, step])
4746
+ };
4747
+ const result = core.updateVariantAsync ? await core.updateVariantAsync(rootDir, selectedVariant.name, opts) : core.updateVariant(rootDir, selectedVariant.name, opts);
4748
+ if (cancelled) return;
4749
+ const newStatus = result.meta.teamModeEnabled ? "enabled" : "disabled";
4750
+ const completion = {
4751
+ doneLines: [`Team mode ${newStatus} for ${selectedVariant.name}`],
4752
+ summary: [...result.notes || []],
4753
+ nextSteps: [`Run: ${selectedVariant.name}`],
4754
+ help: ["Team mode adds TaskCreate, TaskGet, TaskUpdate, TaskList tools for multi-agent coordination"]
4755
+ };
4756
+ onComplete(completion);
4757
+ refreshVariants();
4758
+ } catch (error) {
4759
+ if (cancelled) return;
4760
+ const message = error instanceof Error ? error.message : String(error);
4761
+ onComplete({
4762
+ doneLines: [`Failed: ${message}`],
4763
+ summary: [],
4764
+ nextSteps: [],
4765
+ help: []
4766
+ });
4767
+ }
4768
+ if (!cancelled) setScreen("manage-team-mode-done");
4769
+ };
4770
+ runToggle();
4771
+ return () => {
4772
+ cancelled = true;
4773
+ };
4774
+ }, [screen, selectedVariant, rootDir, binDir, core, setProgressLines, setScreen, onComplete, refreshVariants]);
4775
+ }
4776
+
4189
4777
  // src/tui/screens/HomeScreen.tsx
4190
4778
  import { useState, useRef } from "react";
4191
4779
  import { Box as Box5, Text as Text5, useInput as useInput2 } from "ink";
@@ -4351,7 +4939,7 @@ var SelectMenu = ({ items, selectedIndex, onIndexChange, onSelect }) => {
4351
4939
  });
4352
4940
  return /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: items.map((item, idx) => /* @__PURE__ */ jsx2(MenuItemDisplay, { item, selected: idx === selectedIndex }, item.value)) });
4353
4941
  };
4354
- var ProviderCard = ({ provider, selected, disabled = false }) => /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
4942
+ var ProviderCard = ({ provider, selected, disabled = false, docsUrl }) => /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
4355
4943
  /* @__PURE__ */ jsxs2(Box2, { children: [
4356
4944
  /* @__PURE__ */ jsxs2(Text2, { color: selected ? colors.gold : colors.textMuted, children: [
4357
4945
  selected ? icons.pointer : icons.pointerEmpty,
@@ -4369,9 +4957,10 @@ var ProviderCard = ({ provider, selected, disabled = false }) => /* @__PURE__ */
4369
4957
  disabled && /* @__PURE__ */ jsx2(Text2, { color: colors.warning, children: " [Coming Soon]" })
4370
4958
  ] }),
4371
4959
  /* @__PURE__ */ jsx2(Box2, { marginLeft: 3, children: /* @__PURE__ */ jsx2(Text2, { color: disabled ? colors.textDim : colors.textMuted, dimColor: disabled, children: provider.description }) }),
4372
- provider.baseUrl && !disabled && /* @__PURE__ */ jsx2(Box2, { marginLeft: 3, children: /* @__PURE__ */ jsx2(Text2, { color: colors.primaryBright, dimColor: true, children: provider.baseUrl }) })
4960
+ provider.baseUrl && !disabled && /* @__PURE__ */ jsx2(Box2, { marginLeft: 3, children: /* @__PURE__ */ jsx2(Text2, { color: colors.primaryBright, dimColor: true, children: provider.baseUrl }) }),
4961
+ !provider.baseUrl && docsUrl && !disabled && /* @__PURE__ */ jsx2(Box2, { marginLeft: 3, children: /* @__PURE__ */ jsx2(Text2, { color: colors.primaryBright, dimColor: true, children: docsUrl }) })
4373
4962
  ] });
4374
- var VariantCard = ({ name, provider, path: path23, selected }) => /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
4963
+ var VariantCard = ({ name, provider, path: path25, selected }) => /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginBottom: 1, children: [
4375
4964
  /* @__PURE__ */ jsxs2(Box2, { children: [
4376
4965
  /* @__PURE__ */ jsxs2(Text2, { color: selected ? colors.gold : colors.textMuted, children: [
4377
4966
  selected ? icons.pointer : icons.pointerEmpty,
@@ -4384,7 +4973,7 @@ var VariantCard = ({ name, provider, path: path23, selected }) => /* @__PURE__ *
4384
4973
  ")"
4385
4974
  ] })
4386
4975
  ] }),
4387
- /* @__PURE__ */ jsx2(Box2, { marginLeft: 3, children: /* @__PURE__ */ jsx2(Text2, { color: colors.primaryBright, dimColor: true, children: path23 || `~/.local/bin/${name}` }) })
4976
+ /* @__PURE__ */ jsx2(Box2, { marginLeft: 3, children: /* @__PURE__ */ jsx2(Text2, { color: colors.primaryBright, dimColor: true, children: path25 || `~/.local/bin/${name}` }) })
4388
4977
  ] });
4389
4978
 
4390
4979
  // src/tui/components/ui/Logo.tsx
@@ -4657,6 +5246,26 @@ var PROVIDER_EDUCATION = {
4657
5246
  docs: "https://github.com/musistudio/claude-code-router#2-configuration"
4658
5247
  },
4659
5248
  setupNote: 'Install: npm i -g @musistudio/claude-code-router, run "ccr start". Configure models in ~/.claude-code-router/config.json'
5249
+ },
5250
+ mirror: {
5251
+ headline: "Mirror Claude \u2014 Pure Claude Code, Enhanced",
5252
+ tagline: "Reflections of perfection",
5253
+ features: [
5254
+ "Pure Claude Code experience (no proxy)",
5255
+ "Team mode enabled by default",
5256
+ "Isolated config for experimentation",
5257
+ "Premium silver/chrome theme",
5258
+ "No API key required at setup"
5259
+ ],
5260
+ bestFor: "Power users who want enhanced Claude Code without changing the AI",
5261
+ requiresMapping: false,
5262
+ hasPromptPack: false,
5263
+ setupLinks: {
5264
+ subscribe: "https://console.anthropic.com/settings/plans",
5265
+ apiKey: "https://console.anthropic.com/settings/keys",
5266
+ docs: "https://github.com/numman-ali/cc-mirror/blob/main/docs/features/mirror-claude.md"
5267
+ },
5268
+ setupNote: "Uses normal Claude authentication. Sign in via OAuth or set ANTHROPIC_API_KEY."
4660
5269
  }
4661
5270
  };
4662
5271
  var getProviderEducation = (providerKey) => {
@@ -4716,15 +5325,20 @@ var ProviderSelectScreen = ({ providers, onSelect }) => {
4716
5325
  " OpenRouter/Local LLMs require model mapping"
4717
5326
  ] })
4718
5327
  ] }),
4719
- /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", marginY: 1, children: providers.map((provider, idx) => /* @__PURE__ */ jsx7(
4720
- ProviderCard,
4721
- {
4722
- provider,
4723
- selected: idx === selectedIndex && !provider.experimental,
4724
- disabled: provider.experimental
4725
- },
4726
- provider.key
4727
- )) }),
5328
+ /* @__PURE__ */ jsx7(Box7, { flexDirection: "column", marginY: 1, children: providers.map((provider, idx) => {
5329
+ const providerEducation = getProviderEducation(provider.key);
5330
+ const docsUrl = providerEducation?.setupLinks?.docs;
5331
+ return /* @__PURE__ */ jsx7(
5332
+ ProviderCard,
5333
+ {
5334
+ provider,
5335
+ selected: idx === selectedIndex && !provider.experimental,
5336
+ disabled: provider.experimental,
5337
+ docsUrl
5338
+ },
5339
+ provider.key
5340
+ );
5341
+ }) }),
4728
5342
  showDetails && education && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginTop: 1, paddingX: 1, children: [
4729
5343
  /* @__PURE__ */ jsxs7(Box7, { marginBottom: 1, children: [
4730
5344
  /* @__PURE__ */ jsxs7(Text7, { color: colors.gold, children: [
@@ -4797,6 +5411,16 @@ var ProviderIntroScreen = ({
4797
5411
  steps2.push("Create!");
4798
5412
  return steps2;
4799
5413
  }
5414
+ if (providerKey === "mirror") {
5415
+ if (!isQuickSetup) {
5416
+ steps2.push("Choose a visual theme");
5417
+ steps2.push("Optional: dev-browser skill");
5418
+ }
5419
+ steps2.push("Name your variant");
5420
+ steps2.push("Create!");
5421
+ steps2.push("Authenticate via Claude Code (OAuth or API key)");
5422
+ return steps2;
5423
+ }
4800
5424
  steps2.push("Enter your API key");
4801
5425
  if (education?.requiresMapping) {
4802
5426
  steps2.push("Configure model aliases");
@@ -4841,7 +5465,14 @@ var ProviderIntroScreen = ({
4841
5465
  ] }, index)) })
4842
5466
  ] }),
4843
5467
  education?.setupNote && /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: colors.textDim, italic: true, children: education.setupNote }) }),
4844
- providerKey === "ccrouter" && /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsx8(Text8, { color: colors.primaryBright, children: "GitHub: https://github.com/musistudio/claude-code-router" }) }),
5468
+ education?.setupLinks?.github && /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsxs8(Text8, { color: colors.primaryBright, children: [
5469
+ "GitHub: ",
5470
+ education.setupLinks.github
5471
+ ] }) }),
5472
+ education?.setupLinks?.docs && !education?.setupLinks?.github && /* @__PURE__ */ jsx8(Box8, { marginTop: 1, children: /* @__PURE__ */ jsxs8(Text8, { color: colors.primaryBright, children: [
5473
+ "Docs: ",
5474
+ education.setupLinks.docs
5475
+ ] }) }),
4845
5476
  /* @__PURE__ */ jsx8(Box8, { marginTop: 2, children: /* @__PURE__ */ jsx8(Text8, { color: colors.primaryBright, children: "Press Enter to continue \u2192" }) })
4846
5477
  ]
4847
5478
  }
@@ -5115,16 +5746,16 @@ var SummaryScreen = ({ data, onConfirm, onBack, onCancel }) => {
5115
5746
  };
5116
5747
 
5117
5748
  // src/tui/screens/ProgressScreen.tsx
5118
- import { useEffect as useEffect6, useMemo, useState as useState5 } from "react";
5749
+ import { useEffect as useEffect7, useMemo, useState as useState5 } from "react";
5119
5750
  import { Box as Box15, Text as Text14 } from "ink";
5120
5751
 
5121
5752
  // src/tui/components/ui/Progress.tsx
5122
- import { useState as useState4, useEffect as useEffect5 } from "react";
5753
+ import { useState as useState4, useEffect as useEffect6 } from "react";
5123
5754
  import { Box as Box14, Text as Text13, useStdout } from "ink";
5124
5755
  import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
5125
5756
  var useSpinner = (interval = 80) => {
5126
5757
  const [frame, setFrame] = useState4(0);
5127
- useEffect5(() => {
5758
+ useEffect6(() => {
5128
5759
  const timer = setInterval(() => {
5129
5760
  setFrame((prev) => (prev + 1) % spinnerFrames.length);
5130
5761
  }, interval);
@@ -5217,7 +5848,7 @@ var HealthCheck = ({ name, ok, details }) => /* @__PURE__ */ jsxs14(Box14, { fle
5217
5848
  import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
5218
5849
  var ProgressScreen = ({ title, lines, variantName }) => {
5219
5850
  const [elapsedSeconds, setElapsedSeconds] = useState5(0);
5220
- useEffect6(() => {
5851
+ useEffect7(() => {
5221
5852
  const start = Date.now();
5222
5853
  const timer = setInterval(() => {
5223
5854
  setElapsedSeconds(Math.floor((Date.now() - start) / 1e3));
@@ -5433,13 +6064,21 @@ var VariantActionsScreen = ({
5433
6064
  onTweak,
5434
6065
  onRemove,
5435
6066
  onConfigureModels,
6067
+ onToggleTeamMode,
5436
6068
  onBack
5437
6069
  }) => {
5438
6070
  const [selectedIndex, setSelectedIndex] = useState8(0);
5439
6071
  const requiresModelMapping = meta.provider && MODEL_MAPPING_PROVIDERS.includes(meta.provider);
6072
+ const teamModeAction = onToggleTeamMode ? meta.teamModeEnabled ? { value: "team-mode", label: "Disable Team Mode", description: "Remove multi-agent task tools" } : {
6073
+ value: "team-mode",
6074
+ label: "Enable Team Mode",
6075
+ description: "Add multi-agent task tools",
6076
+ icon: "star"
6077
+ } : null;
5440
6078
  const actions = [
5441
6079
  { value: "update", label: "Update", description: "Re-sync binary + patches" },
5442
6080
  ...requiresModelMapping && onConfigureModels ? [{ value: "models", label: "Configure Models", description: "Edit Opus/Sonnet/Haiku mapping" }] : [],
6081
+ ...teamModeAction ? [teamModeAction] : [],
5443
6082
  { value: "tweak", label: "Customize", description: "Open tweakcc" },
5444
6083
  { value: "remove", label: "Remove", description: "Delete variant", icon: "exit" },
5445
6084
  { value: "back", label: "Back", icon: "back" }
@@ -5447,6 +6086,7 @@ var VariantActionsScreen = ({
5447
6086
  const handleSelect = (value) => {
5448
6087
  if (value === "update") onUpdate();
5449
6088
  if (value === "models" && onConfigureModels) onConfigureModels();
6089
+ if (value === "team-mode" && onToggleTeamMode) onToggleTeamMode();
5450
6090
  if (value === "tweak") onTweak();
5451
6091
  if (value === "remove") onRemove();
5452
6092
  if (value === "back") onBack();
@@ -5457,7 +6097,8 @@ var VariantActionsScreen = ({
5457
6097
  /* @__PURE__ */ jsx18(SummaryRow, { label: "Install", value: "NPM (cli.js)" }),
5458
6098
  /* @__PURE__ */ jsx18(SummaryRow, { label: "Binary", value: meta.binaryPath }),
5459
6099
  /* @__PURE__ */ jsx18(SummaryRow, { label: "Config", value: meta.configDir }),
5460
- /* @__PURE__ */ jsx18(SummaryRow, { label: "Wrapper", value: meta.wrapperPath })
6100
+ /* @__PURE__ */ jsx18(SummaryRow, { label: "Wrapper", value: meta.wrapperPath }),
6101
+ /* @__PURE__ */ jsx18(SummaryRow, { label: "Team Mode", value: meta.teamModeEnabled ? "Enabled" : "Disabled" })
5461
6102
  ] }),
5462
6103
  /* @__PURE__ */ jsx18(Box18, { marginY: 1, children: /* @__PURE__ */ jsx18(
5463
6104
  SelectMenu,
@@ -5937,8 +6578,14 @@ var FeedbackScreen = ({ onBack }) => {
5937
6578
  import { useState as useState12 } from "react";
5938
6579
  import { Box as Box24, Text as Text22, useInput as useInput12 } from "ink";
5939
6580
  import { jsx as jsx24, jsxs as jsxs24 } from "react/jsx-runtime";
5940
- var YesNoSelect = ({ title, onSelect, yesLabel = "Yes", noLabel = "No" }) => {
5941
- const [selectedIndex, setSelectedIndex] = useState12(0);
6581
+ var YesNoSelect = ({
6582
+ title,
6583
+ onSelect,
6584
+ yesLabel = "Yes",
6585
+ noLabel = "No",
6586
+ defaultNo = false
6587
+ }) => {
6588
+ const [selectedIndex, setSelectedIndex] = useState12(defaultNo ? 1 : 0);
5942
6589
  useInput12((input, key) => {
5943
6590
  if (key.upArrow || key.downArrow) {
5944
6591
  setSelectedIndex((prev) => prev === 0 ? 1 : 0);
@@ -6107,12 +6754,12 @@ var App = ({
6107
6754
  }
6108
6755
  }
6109
6756
  });
6110
- useEffect7(() => {
6757
+ useEffect8(() => {
6111
6758
  if (screen === "manage") {
6112
6759
  setVariants(core.listVariants(rootDir));
6113
6760
  }
6114
6761
  }, [screen, rootDir, core]);
6115
- useEffect7(() => {
6762
+ useEffect8(() => {
6116
6763
  if (screen !== "doctor") return;
6117
6764
  setDoctorReport(core.doctor(rootDir, binDir));
6118
6765
  }, [screen, rootDir, binDir, core]);
@@ -6180,7 +6827,7 @@ var App = ({
6180
6827
  setScreen,
6181
6828
  onComplete: handleOperationComplete
6182
6829
  });
6183
- useEffect7(() => {
6830
+ useEffect8(() => {
6184
6831
  if (screen !== "manage-tweak") return;
6185
6832
  if (!selectedVariant) return;
6186
6833
  setDoneLines([`To customize ${selectedVariant.name}, run:`]);
@@ -6202,6 +6849,17 @@ var App = ({
6202
6849
  setScreen,
6203
6850
  onComplete: handleOperationComplete
6204
6851
  });
6852
+ useTeamModeToggle({
6853
+ screen,
6854
+ selectedVariant,
6855
+ rootDir,
6856
+ binDir,
6857
+ core,
6858
+ setProgressLines,
6859
+ setScreen,
6860
+ onComplete: handleOperationComplete,
6861
+ refreshVariants: () => setVariants(core.listVariants(rootDir))
6862
+ });
6205
6863
  useUpdateAll({
6206
6864
  screen,
6207
6865
  rootDir,
@@ -6232,7 +6890,7 @@ var App = ({
6232
6890
  setCompletionNextSteps([]);
6233
6891
  setCompletionHelp([]);
6234
6892
  };
6235
- useEffect7(() => {
6893
+ useEffect8(() => {
6236
6894
  if (screen === "exit") {
6237
6895
  const timer = setTimeout(() => exit(), 100);
6238
6896
  return () => clearTimeout(timer);
@@ -6274,7 +6932,7 @@ var App = ({
6274
6932
  const defaults = providerDefaults(value);
6275
6933
  const keyDefaults = value === "zai" ? resolveZaiApiKey() : { value: "", detectedFrom: null, skipPrompt: false };
6276
6934
  setProviderKey(value);
6277
- setName(value);
6935
+ setName(value === "mirror" ? "mclaude" : value);
6278
6936
  setBaseUrl(selected?.baseUrl || "");
6279
6937
  setApiKey(keyDefaults.value);
6280
6938
  setApiKeyDetectedFrom(keyDefaults.detectedFrom);
@@ -6395,7 +7053,7 @@ var App = ({
6395
7053
  const defaults = providerDefaults(value);
6396
7054
  const keyDefaults = value === "zai" ? resolveZaiApiKey() : { value: "", detectedFrom: null, skipPrompt: false };
6397
7055
  setProviderKey(value);
6398
- setName(value);
7056
+ setName(value === "mirror" ? "mclaude" : value);
6399
7057
  setBaseUrl(selected?.baseUrl || "");
6400
7058
  setApiKey(keyDefaults.value);
6401
7059
  setApiKeyDetectedFrom(keyDefaults.detectedFrom);
@@ -6452,7 +7110,12 @@ var App = ({
6452
7110
  ] });
6453
7111
  }
6454
7112
  if (screen === "create-name") {
6455
- const nextScreen = providerKey === "ccrouter" ? "create-ccrouter-url" : "create-base-url";
7113
+ const getNextScreen = () => {
7114
+ if (providerKey === "ccrouter") return "create-ccrouter-url";
7115
+ if (providerKey === "mirror") return "create-skill-install";
7116
+ return "create-base-url";
7117
+ };
7118
+ const nextScreen = getNextScreen();
6456
7119
  return /* @__PURE__ */ jsxs25(Frame, { children: [
6457
7120
  /* @__PURE__ */ jsx25(Header, { title: "Variant Name", subtitle: "This becomes the CLI command name" }),
6458
7121
  /* @__PURE__ */ jsx25(Divider, {}),
@@ -6642,6 +7305,7 @@ var App = ({
6642
7305
  YesNoSelect,
6643
7306
  {
6644
7307
  title: "Add custom env entries?",
7308
+ defaultNo: true,
6645
7309
  onSelect: (value) => {
6646
7310
  if (value) {
6647
7311
  setScreen("create-env-add");
@@ -6730,12 +7394,12 @@ var App = ({
6730
7394
  variants: variants.map((v) => ({
6731
7395
  name: v.name,
6732
7396
  provider: v.meta?.provider,
6733
- wrapperPath: path22.join(binDir, v.name)
7397
+ wrapperPath: path24.join(binDir, v.name)
6734
7398
  })),
6735
7399
  onSelect: (variantName) => {
6736
7400
  const entry = variants.find((item) => item.name === variantName);
6737
7401
  if (!entry || !entry.meta) return;
6738
- setSelectedVariant({ ...entry.meta, wrapperPath: path22.join(binDir, entry.name) });
7402
+ setSelectedVariant({ ...entry.meta, wrapperPath: path24.join(binDir, entry.name) });
6739
7403
  setScreen("manage-actions");
6740
7404
  },
6741
7405
  onBack: () => setScreen("home")
@@ -6754,6 +7418,7 @@ var App = ({
6754
7418
  setModelHaiku("");
6755
7419
  setScreen("manage-models");
6756
7420
  },
7421
+ onToggleTeamMode: () => setScreen("manage-team-mode"),
6757
7422
  onTweak: () => setScreen("manage-tweak"),
6758
7423
  onRemove: () => setScreen("manage-remove"),
6759
7424
  onBack: () => setScreen("manage")
@@ -6779,6 +7444,26 @@ var App = ({
6779
7444
  }
6780
7445
  );
6781
7446
  }
7447
+ if (screen === "manage-team-mode" && selectedVariant) {
7448
+ const action = selectedVariant.teamModeEnabled ? "Disabling" : "Enabling";
7449
+ return /* @__PURE__ */ jsx25(ProgressScreen, { title: `${action} team mode`, lines: progressLines });
7450
+ }
7451
+ if (screen === "manage-team-mode-done") {
7452
+ return /* @__PURE__ */ jsx25(
7453
+ CompletionScreen,
7454
+ {
7455
+ title: "Team Mode",
7456
+ lines: doneLines,
7457
+ summary: completionSummary,
7458
+ nextSteps: completionNextSteps,
7459
+ help: completionHelp,
7460
+ onDone: (value) => {
7461
+ if (value === "home") setScreen("home");
7462
+ else setScreen("exit");
7463
+ }
7464
+ }
7465
+ );
7466
+ }
6782
7467
  if (screen === "manage-tweak" && selectedVariant) {
6783
7468
  return /* @__PURE__ */ jsx25(ProgressScreen, { title: "Launching tweakcc", lines: progressLines });
6784
7469
  }