teamix-evo 0.19.2 → 0.20.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,5 +1,5 @@
1
1
  // src/core/tokens-init.ts
2
- import * as path8 from "path";
2
+ import * as path9 from "path";
3
3
  import * as fs7 from "fs/promises";
4
4
  import {
5
5
  loadTokensPackageManifest,
@@ -306,7 +306,7 @@ async function loadSkillsData(packageName) {
306
306
  }
307
307
 
308
308
  // src/core/skills-installer.ts
309
- import * as path7 from "path";
309
+ import * as path8 from "path";
310
310
  import * as fs6 from "fs/promises";
311
311
  import {
312
312
  replaceManagedRegion,
@@ -351,13 +351,40 @@ var ClaudeAdapter = class {
351
351
  }
352
352
  };
353
353
 
354
+ // src/ide/CodexAdapter.ts
355
+ import * as os3 from "os";
356
+ import * as path6 from "path";
357
+ var CodexAdapter = class {
358
+ kind = "codex";
359
+ name = "codex";
360
+ getProjectRoot() {
361
+ return process.cwd();
362
+ }
363
+ detectIde() {
364
+ return Boolean(
365
+ process.env.CODEX_HOME || process.env.CODEX_SANDBOX || process.env.CODEX_THREAD_ID || process.env.CODEX_CI
366
+ );
367
+ }
368
+ getSkillTargetDir(skillName, scope, projectRoot) {
369
+ const base = scope === "global" ? path6.join(os3.homedir(), ".agents") : path6.join(projectRoot ?? this.getProjectRoot(), ".agents");
370
+ return path6.join(base, "skills", skillName);
371
+ }
372
+ };
373
+
354
374
  // src/ide/index.ts
375
+ var ALL_IDE_KINDS = [
376
+ "qoder",
377
+ "claude",
378
+ "codex"
379
+ ];
355
380
  function getAdapter(kind) {
356
381
  switch (kind) {
357
382
  case "qoder":
358
383
  return new QoderAdapter();
359
384
  case "claude":
360
385
  return new ClaudeAdapter();
386
+ case "codex":
387
+ return new CodexAdapter();
361
388
  default: {
362
389
  const _exhaustive = kind;
363
390
  throw new Error(`Unsupported IDE kind: ${_exhaustive}`);
@@ -394,21 +421,21 @@ async function loadTemplateFile(filePath) {
394
421
  }
395
422
 
396
423
  // src/utils/path.ts
397
- import * as path6 from "path";
424
+ import * as path7 from "path";
398
425
  import * as fs5 from "fs/promises";
399
426
  import { createRequire as createRequire2 } from "module";
400
427
  var require3 = createRequire2(import.meta.url);
401
428
  function resolveSourcePath(source, variantDir, packageRoot) {
402
429
  if (source.startsWith("_template/")) {
403
- return path6.join(packageRoot, source);
430
+ return path7.join(packageRoot, source);
404
431
  }
405
- return path6.join(variantDir, source);
432
+ return path7.join(variantDir, source);
406
433
  }
407
434
  async function walkDir(dir, skipDirs) {
408
435
  const files = [];
409
436
  const entries = await fs5.readdir(dir, { withFileTypes: true });
410
437
  for (const entry of entries) {
411
- const fullPath = path6.join(dir, entry.name);
438
+ const fullPath = path7.join(dir, entry.name);
412
439
  if (entry.isDirectory()) {
413
440
  if (skipDirs && skipDirs.has(entry.name)) continue;
414
441
  files.push(...await walkDir(fullPath, skipDirs));
@@ -420,10 +447,10 @@ async function walkDir(dir, skipDirs) {
420
447
  }
421
448
  function resolveTokensPackageRoot(packageName) {
422
449
  const pkgJson = require3.resolve(`${packageName}/package.json`);
423
- return path6.dirname(pkgJson);
450
+ return path7.dirname(pkgJson);
424
451
  }
425
452
  function resolveResourceTarget(projectRoot, target) {
426
- return path6.isAbsolute(target) ? target : path6.resolve(projectRoot, target);
453
+ return path7.isAbsolute(target) ? target : path7.resolve(projectRoot, target);
427
454
  }
428
455
 
429
456
  // src/core/skills-installer.ts
@@ -460,7 +487,7 @@ async function installSkills(options) {
460
487
  }
461
488
  async function renderSkillFiles(skill, options) {
462
489
  const { data, packageRoot } = options;
463
- const sourceAbs = path7.resolve(packageRoot, skill.source);
490
+ const sourceAbs = path8.resolve(packageRoot, skill.source);
464
491
  const stat4 = await fs6.stat(sourceAbs);
465
492
  const rendered = /* @__PURE__ */ new Map();
466
493
  if (stat4.isFile()) {
@@ -470,7 +497,7 @@ async function renderSkillFiles(skill, options) {
470
497
  }
471
498
  const entries = await walkDir(sourceAbs);
472
499
  for (const entry of entries) {
473
- let rel2 = path7.relative(sourceAbs, entry);
500
+ let rel2 = path8.relative(sourceAbs, entry);
474
501
  if (skill.template && rel2.endsWith(".hbs")) {
475
502
  rel2 = rel2.slice(0, -4);
476
503
  }
@@ -485,7 +512,7 @@ async function writeRenderedToIde(skill, rendered, ide, scope, projectRoot) {
485
512
  const records = [];
486
513
  await ensureDir(targetDir);
487
514
  for (const [rel2, sourceContent] of rendered) {
488
- const targetFile = path7.join(targetDir, rel2);
515
+ const targetFile = path8.join(targetDir, rel2);
489
516
  const writtenContent = await writeMirrorContent(
490
517
  targetFile,
491
518
  sourceContent,
@@ -557,7 +584,7 @@ function makeMirrorRecord(skill, projectRoot, targetAbs, content, ide, scope, re
557
584
  const id = rel2 && rel2 !== "SKILL.md" ? `${skill.id}:${rel2}` : skill.id;
558
585
  return {
559
586
  id,
560
- target: path7.relative(projectRoot, targetAbs),
587
+ target: path8.relative(projectRoot, targetAbs),
561
588
  hash: computeHash(content),
562
589
  strategy: skill.updateStrategy,
563
590
  ide,
@@ -594,7 +621,7 @@ async function updateRenderedInIde(skill, rendered, ide, scope, projectRoot, sum
594
621
  const records = [];
595
622
  await ensureDir(targetDir);
596
623
  for (const [rel2, newContent] of rendered) {
597
- const targetFile = path7.join(targetDir, rel2);
624
+ const targetFile = path8.join(targetDir, rel2);
598
625
  const exists = await fileExists(targetFile);
599
626
  const written = await rewriteSingleFile({
600
627
  targetFile,
@@ -684,12 +711,13 @@ async function reinstallSkillsToIdes(options) {
684
711
  continue;
685
712
  }
686
713
  const rendered = await renderSkillFiles(entry, { data, packageRoot });
687
- for (const ide of ides) {
714
+ const supportedIdes = entry.ides.filter((ide) => ides.includes(ide));
715
+ for (const ide of supportedIdes) {
688
716
  const adapter = getAdapter(ide);
689
717
  const targetDir = adapter.getSkillTargetDir(skill.name, scope, projectRoot);
690
718
  await ensureDir(targetDir);
691
719
  for (const [rel2, sourceContent] of rendered) {
692
- const targetFile = path7.join(targetDir, rel2);
720
+ const targetFile = path8.join(targetDir, rel2);
693
721
  const writtenContent = await writeMirrorContent(
694
722
  targetFile,
695
723
  sourceContent,
@@ -697,7 +725,7 @@ async function reinstallSkillsToIdes(options) {
697
725
  );
698
726
  out.push({
699
727
  id: rel2 === "SKILL.md" ? skill.id : `${skill.id}:${rel2}`,
700
- target: path7.relative(projectRoot, targetFile),
728
+ target: path8.relative(projectRoot, targetFile),
701
729
  hash: computeHash(writtenContent),
702
730
  strategy: skill.updateStrategy,
703
731
  ide,
@@ -717,7 +745,7 @@ async function pruneEmptyIdeSkillDirs(args) {
717
745
  args.scope,
718
746
  args.projectRoot
719
747
  );
720
- const skillsRoot = path7.dirname(placeholderDir);
748
+ const skillsRoot = path8.dirname(placeholderDir);
721
749
  let entries;
722
750
  try {
723
751
  entries = await fs6.readdir(skillsRoot);
@@ -725,7 +753,7 @@ async function pruneEmptyIdeSkillDirs(args) {
725
753
  continue;
726
754
  }
727
755
  for (const name of entries) {
728
- const dir = path7.join(skillsRoot, name);
756
+ const dir = path8.join(skillsRoot, name);
729
757
  let stat4;
730
758
  try {
731
759
  stat4 = await fs6.stat(dir);
@@ -765,7 +793,7 @@ async function removeSkillFiles(records, projectRoot) {
765
793
  }
766
794
  }
767
795
  const startDirs = new Set(
768
- records.map((r) => path7.dirname(resolveResourceTarget(projectRoot, r.target)))
796
+ records.map((r) => path8.dirname(resolveResourceTarget(projectRoot, r.target)))
769
797
  );
770
798
  for (const startDir of startDirs) {
771
799
  let dir = startDir;
@@ -777,7 +805,7 @@ async function removeSkillFiles(records, projectRoot) {
777
805
  } catch {
778
806
  break;
779
807
  }
780
- dir = path7.dirname(dir);
808
+ dir = path8.dirname(dir);
781
809
  }
782
810
  }
783
811
  return removed;
@@ -1206,7 +1234,7 @@ async function autoUpgradeOutdatedSkills(args) {
1206
1234
 
1207
1235
  // src/core/tokens-init.ts
1208
1236
  var DEFAULT_SKILLS_PACKAGE2 = "@teamix-evo/skills";
1209
- var DEFAULT_AUTO_SKILL_IDES = ["qoder", "claude"];
1237
+ var DEFAULT_AUTO_SKILL_IDES = [...ALL_IDE_KINDS];
1210
1238
  var DEFAULT_AUTO_SKILL_SCOPE = "project";
1211
1239
  var DEFAULT_TOKENS_PACKAGE = "@teamix-evo/tokens";
1212
1240
  var CONSUMER_TOKENS_DIR = "tokens";
@@ -1246,7 +1274,7 @@ Run \`npx teamix-evo@latest tokens list-variants\` to see all options.`
1246
1274
  const result = await installVariantFile(fileRel, packageRoot, projectRoot);
1247
1275
  if (result) installed.push(result);
1248
1276
  }
1249
- const overridesAbs = path8.join(
1277
+ const overridesAbs = path9.join(
1250
1278
  projectRoot,
1251
1279
  CONSUMER_TOKENS_DIR,
1252
1280
  CONSUMER_OVERRIDES_FILE
@@ -1259,7 +1287,7 @@ Run \`npx teamix-evo@latest tokens list-variants\` to see all options.`
1259
1287
  const overridesContent = await fs7.readFile(overridesAbs, "utf-8");
1260
1288
  installed.push({
1261
1289
  id: overridesId,
1262
- target: path8.posix.join(CONSUMER_TOKENS_DIR, CONSUMER_OVERRIDES_FILE),
1290
+ target: path9.posix.join(CONSUMER_TOKENS_DIR, CONSUMER_OVERRIDES_FILE),
1263
1291
  hash: computeHash(overridesContent),
1264
1292
  strategy: "frozen"
1265
1293
  });
@@ -1277,7 +1305,7 @@ Run \`npx teamix-evo@latest tokens list-variants\` to see all options.`
1277
1305
  installedAt: (/* @__PURE__ */ new Date()).toISOString()
1278
1306
  };
1279
1307
  await writeFileSafe(
1280
- path8.join(projectRoot, ".teamix-evo", "tokens-lock.json"),
1308
+ path9.join(projectRoot, ".teamix-evo", "tokens-lock.json"),
1281
1309
  JSON.stringify(lock, null, 2) + "\n"
1282
1310
  );
1283
1311
  const config = {
@@ -1397,11 +1425,11 @@ async function tryAutoInstallVariantSkills(args) {
1397
1425
  }
1398
1426
  }
1399
1427
  async function installVariantFile(fileRelToPackage, packageRoot, projectRoot) {
1400
- const sourceAbs = path8.join(packageRoot, fileRelToPackage);
1401
- const base = path8.basename(fileRelToPackage);
1428
+ const sourceAbs = path9.join(packageRoot, fileRelToPackage);
1429
+ const base = path9.basename(fileRelToPackage);
1402
1430
  if (base === "theme.css") {
1403
- const targetRel = path8.posix.join(CONSUMER_TOKENS_DIR, CONSUMER_THEME_FILE);
1404
- const targetAbs = path8.join(projectRoot, targetRel);
1431
+ const targetRel = path9.posix.join(CONSUMER_TOKENS_DIR, CONSUMER_THEME_FILE);
1432
+ const targetAbs = path9.join(projectRoot, targetRel);
1405
1433
  const content = await fs7.readFile(sourceAbs, "utf-8");
1406
1434
  if (await fileExists(targetAbs)) {
1407
1435
  await backupFile(targetAbs, projectRoot);
@@ -1415,11 +1443,11 @@ async function installVariantFile(fileRelToPackage, packageRoot, projectRoot) {
1415
1443
  };
1416
1444
  }
1417
1445
  if (base === "overrides.css" || base === "tokens.overrides.css") {
1418
- const targetRel = path8.posix.join(
1446
+ const targetRel = path9.posix.join(
1419
1447
  CONSUMER_TOKENS_DIR,
1420
1448
  CONSUMER_OVERRIDES_FILE
1421
1449
  );
1422
- const targetAbs = path8.join(projectRoot, targetRel);
1450
+ const targetAbs = path9.join(projectRoot, targetRel);
1423
1451
  if (await fileExists(targetAbs)) {
1424
1452
  const existing = await fs7.readFile(targetAbs, "utf-8");
1425
1453
  return {
@@ -1458,7 +1486,7 @@ async function listTokenVariants(packageName = DEFAULT_TOKENS_PACKAGE, packageRo
1458
1486
 
1459
1487
  // src/core/agents-md.ts
1460
1488
  import * as fs8 from "fs/promises";
1461
- import * as path9 from "path";
1489
+ import * as path10 from "path";
1462
1490
  import { hasManagedRegion as hasManagedRegion2, replaceManagedRegion as replaceManagedRegion2 } from "@teamix-evo/registry";
1463
1491
  var AGENTS_MD_MANAGED_ID = "teamix-evo-skills";
1464
1492
  async function runGenerateAgentsMd(options) {
@@ -1467,7 +1495,7 @@ async function runGenerateAgentsMd(options) {
1467
1495
  const mode = options.mode ?? "overwrite";
1468
1496
  const config = await readProjectConfig(projectRoot);
1469
1497
  const lock = await readSkillsLock(projectRoot);
1470
- const ides = config?.packages?.skills?.ides ?? ["qoder", "claude"];
1498
+ const ides = config?.packages?.skills?.ides ?? [...ALL_IDE_KINDS];
1471
1499
  const scope = config?.packages?.skills?.scope ?? lock?.skills[skillIds[0] ?? ""]?.scope ?? "project";
1472
1500
  const skillScopeMap = /* @__PURE__ */ new Map();
1473
1501
  for (const id of skillIds) skillScopeMap.set(id, scope);
@@ -1484,7 +1512,7 @@ async function runGenerateAgentsMd(options) {
1484
1512
  sections.push(section);
1485
1513
  if (missing) missingSkillIds.push(id);
1486
1514
  }
1487
- const target = path9.join(projectRoot, "AGENTS.md");
1515
+ const target = path10.join(projectRoot, "AGENTS.md");
1488
1516
  const targetExists = await fileExists(target);
1489
1517
  const fullTemplate = renderAgentsMd({ variant, sections });
1490
1518
  const managedBody = renderManagedBlockBody({ variant, sections });
@@ -1539,7 +1567,7 @@ async function renderSkillSection(projectRoot, skillId, ides, scope) {
1539
1567
  let missing = false;
1540
1568
  for (const ide of ides) {
1541
1569
  const adapter = getAdapter(ide);
1542
- const skillPath = path9.join(
1570
+ const skillPath = path10.join(
1543
1571
  adapter.getSkillTargetDir(skillId, scope, projectRoot),
1544
1572
  "SKILL.md"
1545
1573
  );
@@ -1713,7 +1741,7 @@ async function runSkillsUpdate(options) {
1713
1741
  if (!skillsCfg) {
1714
1742
  return { status: "no-skills" };
1715
1743
  }
1716
- const ides = skillsCfg.ides ?? ["qoder", "claude"];
1744
+ const ides = skillsCfg.ides ?? [...ALL_IDE_KINDS];
1717
1745
  const scope = skillsCfg.scope ?? "project";
1718
1746
  let existingLock = await readSkillsLock(projectRoot);
1719
1747
  if (!existingLock || Object.keys(existingLock.skills).length === 0) {
@@ -1965,25 +1993,25 @@ async function runUiInit(options) {
1965
1993
  }
1966
1994
 
1967
1995
  // src/core/ui-client.ts
1968
- import * as path10 from "path";
1996
+ import * as path11 from "path";
1969
1997
  import * as fs9 from "fs/promises";
1970
1998
  import { createRequire as createRequire3 } from "module";
1971
1999
  import { loadUiPackageManifest } from "@teamix-evo/registry";
1972
2000
  var require4 = createRequire3(import.meta.url);
1973
2001
  function resolvePackageRoot2(packageName) {
1974
2002
  const pkgJsonPath = require4.resolve(`${packageName}/package.json`);
1975
- return path10.dirname(pkgJsonPath);
2003
+ return path11.dirname(pkgJsonPath);
1976
2004
  }
1977
2005
  async function loadUiData(packageName) {
1978
2006
  const packageRoot = resolvePackageRoot2(packageName);
1979
2007
  logger.debug(`Resolved ui package root: ${packageRoot}`);
1980
2008
  const manifest = await loadUiPackageManifest(packageRoot);
1981
2009
  const pkgJson = JSON.parse(
1982
- await fs9.readFile(path10.join(packageRoot, "package.json"), "utf-8")
2010
+ await fs9.readFile(path11.join(packageRoot, "package.json"), "utf-8")
1983
2011
  );
1984
2012
  manifest.version = pkgJson.version;
1985
2013
  let data = {};
1986
- const dataPath = path10.join(packageRoot, "_data.json");
2014
+ const dataPath = path11.join(packageRoot, "_data.json");
1987
2015
  try {
1988
2016
  const raw = await fs9.readFile(dataPath, "utf-8");
1989
2017
  data = JSON.parse(raw);
@@ -1997,7 +2025,7 @@ async function loadUiData(packageName) {
1997
2025
  }
1998
2026
 
1999
2027
  // src/core/ui-installer.ts
2000
- import * as path11 from "path";
2028
+ import * as path12 from "path";
2001
2029
  import * as fs10 from "fs/promises";
2002
2030
  import { resolveUiEntryOrder } from "@teamix-evo/registry";
2003
2031
 
@@ -2079,7 +2107,7 @@ async function installUiEntries(options) {
2079
2107
  continue;
2080
2108
  }
2081
2109
  const rootForEntry = entryPackageRoot?.get(entry.id) ?? packageRoot;
2082
- const sourceAbs = path11.resolve(rootForEntry, file.source);
2110
+ const sourceAbs = path12.resolve(rootForEntry, file.source);
2083
2111
  const raw = await fs10.readFile(sourceAbs, "utf-8");
2084
2112
  const transformed = rewriteImports(raw, aliases, { flatten });
2085
2113
  if (exists) {
@@ -2089,13 +2117,13 @@ async function installUiEntries(options) {
2089
2117
  skipped++;
2090
2118
  resources.push({
2091
2119
  id: `${entry.id}:${file.targetName}`,
2092
- target: path11.relative(projectRoot, targetAbs),
2120
+ target: path12.relative(projectRoot, targetAbs),
2093
2121
  hash: computeHash(transformed),
2094
2122
  strategy: entry.updateStrategy ?? "frozen"
2095
2123
  });
2096
2124
  continue;
2097
2125
  }
2098
- const relPath = path11.relative(projectRoot, targetAbs);
2126
+ const relPath = path12.relative(projectRoot, targetAbs);
2099
2127
  const prior = priorByTarget.get(relPath);
2100
2128
  if (prior && prior.hash !== "sha256:legacy-unknown") {
2101
2129
  const onDiskHash = computeHash(current);
@@ -2116,7 +2144,7 @@ async function installUiEntries(options) {
2116
2144
  await writeFileSafe(targetAbs, transformed);
2117
2145
  resources.push({
2118
2146
  id: `${entry.id}:${file.targetName}`,
2119
- target: path11.relative(projectRoot, targetAbs),
2147
+ target: path12.relative(projectRoot, targetAbs),
2120
2148
  hash: computeHash(transformed),
2121
2149
  strategy: entry.updateStrategy ?? "frozen"
2122
2150
  });
@@ -2140,10 +2168,10 @@ function resolveTargetPath(projectRoot, aliases, entry, file) {
2140
2168
  `Entry "${entry.id}" requires alias "${file.targetAlias}" but it is not configured.`
2141
2169
  );
2142
2170
  }
2143
- return path11.join(projectRoot, aliasDir, file.targetName);
2171
+ return path12.join(projectRoot, aliasDir, file.targetName);
2144
2172
  }
2145
2173
  function rel(projectRoot, abs) {
2146
- return path11.relative(projectRoot, abs);
2174
+ return path12.relative(projectRoot, abs);
2147
2175
  }
2148
2176
  async function removeUiFiles(records, projectRoot) {
2149
2177
  const removed = [];
@@ -2159,7 +2187,7 @@ async function removeUiFiles(records, projectRoot) {
2159
2187
  }
2160
2188
  }
2161
2189
  const parents = new Set(
2162
- records.map((r) => path11.dirname(resolveResourceTarget(projectRoot, r.target)))
2190
+ records.map((r) => path12.dirname(resolveResourceTarget(projectRoot, r.target)))
2163
2191
  );
2164
2192
  for (const dir of parents) {
2165
2193
  try {
@@ -2299,7 +2327,7 @@ async function runUiList(options) {
2299
2327
  }
2300
2328
 
2301
2329
  // src/core/variant-ui-add.ts
2302
- import * as path12 from "path";
2330
+ import * as path13 from "path";
2303
2331
  import * as fs11 from "fs/promises";
2304
2332
  import { createRequire as createRequire4 } from "module";
2305
2333
  import {
@@ -2310,7 +2338,7 @@ import {
2310
2338
  var require5 = createRequire4(import.meta.url);
2311
2339
  function resolvePackageRoot3(packageName) {
2312
2340
  const pkgJsonPath = require5.resolve(`${packageName}/package.json`);
2313
- return path12.dirname(pkgJsonPath);
2341
+ return path13.dirname(pkgJsonPath);
2314
2342
  }
2315
2343
  async function runVariantUiAdd(packageName, options) {
2316
2344
  const { projectRoot, variant, ids, overwrite } = options;
@@ -2333,10 +2361,10 @@ async function runVariantUiAdd(packageName, options) {
2333
2361
  `Variant "${variant}" not found in ${fullPackageName}. Known variants: ${known}. Hint: \`teamix-evo ${packageName} list-variants\` shows all.`
2334
2362
  );
2335
2363
  }
2336
- const variantDir = path12.join(packageRoot, "variants", variant);
2364
+ const variantDir = path13.join(packageRoot, "variants", variant);
2337
2365
  const variantManifest = await loadVariantUiPackageManifest(variantDir);
2338
2366
  const pkgJson = JSON.parse(
2339
- await fs11.readFile(path12.join(packageRoot, "package.json"), "utf-8")
2367
+ await fs11.readFile(path13.join(packageRoot, "package.json"), "utf-8")
2340
2368
  );
2341
2369
  const packageVersion = pkgJson.version;
2342
2370
  const knownIds = new Set(variantManifest.entries.map((e) => e.id));
@@ -2452,7 +2480,7 @@ async function listVariantUiEntries(packageName, variant, packageRoot) {
2452
2480
  `Variant "${variant}" not found in ${fullPackageName}. Known: ${known}.`
2453
2481
  );
2454
2482
  }
2455
- const variantDir = path12.join(root, "variants", variant);
2483
+ const variantDir = path13.join(root, "variants", variant);
2456
2484
  const variantManifest = await loadVariantUiPackageManifest(variantDir);
2457
2485
  return {
2458
2486
  packageName: fullPackageName,
@@ -2471,10 +2499,19 @@ async function listBizUiEntries(variant, packageRoot) {
2471
2499
  }
2472
2500
 
2473
2501
  // src/core/lint-init.ts
2474
- import * as path13 from "path";
2502
+ import * as path14 from "path";
2475
2503
  import * as fs12 from "fs";
2476
2504
  import { execa } from "execa";
2477
- var ESLINT_CONFIG_CONTENT = `/**
2505
+ function renderEslintConfig(tailwindCssConfigPath) {
2506
+ const tailwindSettings = tailwindCssConfigPath ? `
2507
+ {
2508
+ settings: {
2509
+ tailwindcss: {
2510
+ cssConfigPath: '${tailwindCssConfigPath}',
2511
+ },
2512
+ },
2513
+ },` : "";
2514
+ return `/**
2478
2515
  * teamix-evo consumer ESLint preset \u2014 9 token-discipline rules.
2479
2516
  * - Repo-wide: no-color-literal / no-arbitrary-tw-value / no-raw-color-scale /
2480
2517
  * no-large-radius / prefer-gap-over-space / no-manual-dark-classnames /
@@ -2485,8 +2522,30 @@ var ESLINT_CONFIG_CONTENT = `/**
2485
2522
  */
2486
2523
  import consumerPreset from '@teamix-evo/eslint-config/presets/consumer';
2487
2524
 
2488
- export default [...consumerPreset];
2525
+ export default [
2526
+ ...consumerPreset,${tailwindSettings}
2527
+ ];
2489
2528
  `;
2529
+ }
2530
+ var TAILWIND_CSS_CANDIDATES = [
2531
+ "src/index.css",
2532
+ "src/globals.css",
2533
+ "src/app/globals.css",
2534
+ "app/globals.css",
2535
+ "styles/globals.css",
2536
+ "src/styles/tailwind.css"
2537
+ ];
2538
+ async function detectTailwindCssConfigPath(projectRoot) {
2539
+ for (const candidate of TAILWIND_CSS_CANDIDATES) {
2540
+ const content = await readFileOrNull(path14.join(projectRoot, candidate));
2541
+ if (content && /@(?:import\s+['"]tailwindcss(?:\/[^'"]*)?['"]|theme\b|tailwind\b)/.test(
2542
+ content
2543
+ )) {
2544
+ return `./${candidate}`;
2545
+ }
2546
+ }
2547
+ return null;
2548
+ }
2490
2549
  var STYLELINT_CONFIG_CONTENT = `/** @type {import('stylelint').Config} */
2491
2550
  module.exports = {
2492
2551
  extends: ['@teamix-evo/stylelint-config/presets/consumer'],
@@ -2515,8 +2574,8 @@ async function runLintInit(options) {
2515
2574
  eslintExistingPaths = [],
2516
2575
  stylelintExistingPaths = []
2517
2576
  } = options;
2518
- const eslintConfigPath = path13.join(projectRoot, "eslint.config.js");
2519
- const stylelintConfigPath = path13.join(projectRoot, "stylelint.config.cjs");
2577
+ const eslintConfigPath = path14.join(projectRoot, "eslint.config.js");
2578
+ const stylelintConfigPath = path14.join(projectRoot, "stylelint.config.cjs");
2520
2579
  const eslintTemplateExists = await fileExists(eslintConfigPath);
2521
2580
  const stylelintTemplateExists = await fileExists(stylelintConfigPath);
2522
2581
  const eslintSkipRequested = eslintStrategy === "skip" && eslintExistingPaths.length > 0;
@@ -2540,18 +2599,24 @@ async function runLintInit(options) {
2540
2599
  }
2541
2600
  if (eslintNeedsWrite && eslintExistingPaths.length > 0) {
2542
2601
  for (const rel2 of eslintExistingPaths) {
2543
- await backupFile(path13.join(projectRoot, rel2), projectRoot);
2602
+ await backupFile(path14.join(projectRoot, rel2), projectRoot);
2544
2603
  }
2545
2604
  }
2546
2605
  if (stylelintNeedsWrite && stylelintExistingPaths.length > 0) {
2547
2606
  for (const rel2 of stylelintExistingPaths) {
2548
- await backupFile(path13.join(projectRoot, rel2), projectRoot);
2607
+ await backupFile(path14.join(projectRoot, rel2), projectRoot);
2549
2608
  }
2550
2609
  }
2551
2610
  let wroteEslint = false;
2552
2611
  let wroteStylelint = false;
2553
2612
  if (eslintNeedsWrite) {
2554
- await writeFileSafe(eslintConfigPath, ESLINT_CONFIG_CONTENT);
2613
+ const tailwindCssConfigPath = await detectTailwindCssConfigPath(
2614
+ projectRoot
2615
+ );
2616
+ await writeFileSafe(
2617
+ eslintConfigPath,
2618
+ renderEslintConfig(tailwindCssConfigPath)
2619
+ );
2555
2620
  logger.debug(`Wrote eslint.config.js \u2192 ${eslintConfigPath}`);
2556
2621
  wroteEslint = true;
2557
2622
  }
@@ -2601,12 +2666,12 @@ async function runLintInit(options) {
2601
2666
  };
2602
2667
  }
2603
2668
  function detectPm(projectRoot) {
2604
- if (fs12.existsSync(path13.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
2605
- if (fs12.existsSync(path13.join(projectRoot, "yarn.lock"))) return "yarn";
2669
+ if (fs12.existsSync(path14.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
2670
+ if (fs12.existsSync(path14.join(projectRoot, "yarn.lock"))) return "yarn";
2606
2671
  return "npm";
2607
2672
  }
2608
2673
  async function patchPackageJsonScripts(projectRoot) {
2609
- const pkgPath = path13.join(projectRoot, "package.json");
2674
+ const pkgPath = path14.join(projectRoot, "package.json");
2610
2675
  const raw = await readFileOrNull(pkgPath);
2611
2676
  if (!raw) return false;
2612
2677
  let pkg;
@@ -2636,7 +2701,7 @@ async function patchPackageJsonScripts(projectRoot) {
2636
2701
 
2637
2702
  // src/core/init-detect.ts
2638
2703
  import * as fs13 from "fs/promises";
2639
- import * as path14 from "path";
2704
+ import * as path15 from "path";
2640
2705
  var IGNORED_TOP_LEVEL = /* @__PURE__ */ new Set([
2641
2706
  ".git",
2642
2707
  ".gitignore",
@@ -2648,6 +2713,7 @@ var IGNORED_TOP_LEVEL = /* @__PURE__ */ new Set([
2648
2713
  ".vscode",
2649
2714
  ".qoder",
2650
2715
  ".claude",
2716
+ ".agents",
2651
2717
  "README.md",
2652
2718
  "README",
2653
2719
  "README.txt",
@@ -2656,7 +2722,7 @@ var IGNORED_TOP_LEVEL = /* @__PURE__ */ new Set([
2656
2722
  "LICENSE.txt"
2657
2723
  ]);
2658
2724
  async function detectProjectState(cwd) {
2659
- const absCwd = path14.resolve(cwd);
2725
+ const absCwd = path15.resolve(cwd);
2660
2726
  const teamixDir = getTeamixDir(absCwd);
2661
2727
  const hasTeamixDir = await fileExists(teamixDir);
2662
2728
  if (hasTeamixDir) {
@@ -2664,7 +2730,7 @@ async function detectProjectState(cwd) {
2664
2730
  state: "teamix-evo-installed",
2665
2731
  cwd: absCwd,
2666
2732
  hasTeamixDir: true,
2667
- hasPackageJson: await fileExists(path14.join(absCwd, "package.json")),
2733
+ hasPackageJson: await fileExists(path15.join(absCwd, "package.json")),
2668
2734
  significantEntries: []
2669
2735
  };
2670
2736
  }
@@ -2705,7 +2771,7 @@ async function detectProjectState(cwd) {
2705
2771
 
2706
2772
  // src/core/project-state.ts
2707
2773
  import * as fs14 from "fs/promises";
2708
- import * as path15 from "path";
2774
+ import * as path16 from "path";
2709
2775
  var IGNORED_TOP_LEVEL2 = /* @__PURE__ */ new Set([
2710
2776
  ".git",
2711
2777
  ".gitignore",
@@ -2717,6 +2783,7 @@ var IGNORED_TOP_LEVEL2 = /* @__PURE__ */ new Set([
2717
2783
  ".vscode",
2718
2784
  ".qoder",
2719
2785
  ".claude",
2786
+ ".agents",
2720
2787
  "README.md",
2721
2788
  "README",
2722
2789
  "README.txt",
@@ -2736,22 +2803,22 @@ async function isShadcnComponentsJson(filePath) {
2736
2803
  }
2737
2804
  }
2738
2805
  async function detectProjectState2(cwd) {
2739
- const absCwd = path15.resolve(cwd);
2806
+ const absCwd = path16.resolve(cwd);
2740
2807
  const teamixDir = getTeamixDir(absCwd);
2741
2808
  const hasTeamixDir = await fileExists(teamixDir);
2742
- const hasTeamixConfig = hasTeamixDir && await fileExists(path15.join(teamixDir, "config.json"));
2809
+ const hasTeamixConfig = hasTeamixDir && await fileExists(path16.join(teamixDir, "config.json"));
2743
2810
  if (hasTeamixDir && hasTeamixConfig) {
2744
2811
  return {
2745
2812
  state: "teamix-evo",
2746
2813
  cwd: absCwd,
2747
2814
  hasTeamixDir: true,
2748
- hasPackageJson: await fileExists(path15.join(absCwd, "package.json")),
2815
+ hasPackageJson: await fileExists(path16.join(absCwd, "package.json")),
2749
2816
  hasComponentsJson: false,
2750
2817
  significantEntries: []
2751
2818
  };
2752
2819
  }
2753
- const componentsJsonPath = path15.join(absCwd, "components.json");
2754
- const hasPackageJson = await fileExists(path15.join(absCwd, "package.json"));
2820
+ const componentsJsonPath = path16.join(absCwd, "components.json");
2821
+ const hasPackageJson = await fileExists(path16.join(absCwd, "package.json"));
2755
2822
  const hasComponentsJson = await isShadcnComponentsJson(componentsJsonPath);
2756
2823
  if (hasPackageJson && hasComponentsJson) {
2757
2824
  return {
@@ -2794,7 +2861,7 @@ async function detectProjectState2(cwd) {
2794
2861
  let buildTool = "unknown";
2795
2862
  let allDeps = {};
2796
2863
  if (hasPackageJson) {
2797
- const pkgRaw = await readFileOrNull(path15.join(absCwd, "package.json"));
2864
+ const pkgRaw = await readFileOrNull(path16.join(absCwd, "package.json"));
2798
2865
  if (pkgRaw) {
2799
2866
  try {
2800
2867
  const pkg = JSON.parse(pkgRaw);
@@ -2810,11 +2877,11 @@ async function detectProjectState2(cwd) {
2810
2877
  } else if ("element-ui" in allDeps || "element-plus" in allDeps) {
2811
2878
  legacyLib = "element";
2812
2879
  }
2813
- if (await fileExists(path15.join(absCwd, "build.json"))) {
2880
+ if (await fileExists(path16.join(absCwd, "build.json"))) {
2814
2881
  buildTool = "ice";
2815
- } else if (await fileExists(path15.join(absCwd, "vite.config.ts")) || await fileExists(path15.join(absCwd, "vite.config.js")) || await fileExists(path15.join(absCwd, "vite.config.mts"))) {
2882
+ } else if (await fileExists(path16.join(absCwd, "vite.config.ts")) || await fileExists(path16.join(absCwd, "vite.config.js")) || await fileExists(path16.join(absCwd, "vite.config.mts"))) {
2816
2883
  buildTool = "vite";
2817
- } else if (await fileExists(path15.join(absCwd, "webpack.config.js")) || await fileExists(path15.join(absCwd, "webpack.config.ts"))) {
2884
+ } else if (await fileExists(path16.join(absCwd, "webpack.config.js")) || await fileExists(path16.join(absCwd, "webpack.config.ts"))) {
2818
2885
  buildTool = "webpack";
2819
2886
  } else if ("umi" in allDeps || "@umijs/max" in allDeps) {
2820
2887
  buildTool = "umi";
@@ -2886,7 +2953,7 @@ function assertCommandPrecondition(command, state, options) {
2886
2953
  // src/core/init-conflicts.ts
2887
2954
  import * as crypto from "crypto";
2888
2955
  import * as fs15 from "fs/promises";
2889
- import * as path16 from "path";
2956
+ import * as path17 from "path";
2890
2957
  var TAILWIND_CONFIG_CANDIDATES = [
2891
2958
  "tailwind.config.ts",
2892
2959
  "tailwind.config.js",
@@ -2950,7 +3017,7 @@ function fingerprint(parts) {
2950
3017
  return `sha256:${hash.digest("hex").slice(0, 16)}`;
2951
3018
  }
2952
3019
  async function readPackageJson(cwd) {
2953
- const raw = await readFileOrNull(path16.join(cwd, "package.json"));
3020
+ const raw = await readFileOrNull(path17.join(cwd, "package.json"));
2954
3021
  if (raw === null) return null;
2955
3022
  try {
2956
3023
  return JSON.parse(raw);
@@ -2970,7 +3037,7 @@ function detectTailwindMajor(pkg) {
2970
3037
  return null;
2971
3038
  }
2972
3039
  async function detectAgentsMd(cwd) {
2973
- const target = path16.join(cwd, "AGENTS.md");
3040
+ const target = path17.join(cwd, "AGENTS.md");
2974
3041
  const content = await readFileOrNull(target);
2975
3042
  const exists = content !== null;
2976
3043
  return {
@@ -2983,7 +3050,7 @@ async function detectAgentsMd(cwd) {
2983
3050
  };
2984
3051
  }
2985
3052
  async function detectComponentsJson(cwd) {
2986
- const target = path16.join(cwd, "components.json");
3053
+ const target = path17.join(cwd, "components.json");
2987
3054
  const content = await readFileOrNull(target);
2988
3055
  const exists = content !== null;
2989
3056
  return {
@@ -2999,7 +3066,7 @@ async function detectTailwindConfig(cwd) {
2999
3066
  const matched = [];
3000
3067
  const contents = [];
3001
3068
  for (const rel2 of TAILWIND_CONFIG_CANDIDATES) {
3002
- const c = await readFileOrNull(path16.join(cwd, rel2));
3069
+ const c = await readFileOrNull(path17.join(cwd, rel2));
3003
3070
  if (c !== null) {
3004
3071
  matched.push(rel2);
3005
3072
  contents.push(c);
@@ -3022,14 +3089,14 @@ async function detectTokens(cwd) {
3022
3089
  const matched = [];
3023
3090
  const contents = [];
3024
3091
  for (const rel2 of TOKENS_FILE_CANDIDATES) {
3025
- const c = await readFileOrNull(path16.join(cwd, rel2));
3092
+ const c = await readFileOrNull(path17.join(cwd, rel2));
3026
3093
  if (c !== null) {
3027
3094
  matched.push(rel2);
3028
3095
  contents.push(c);
3029
3096
  }
3030
3097
  }
3031
3098
  for (const rel2 of TOKENS_DIR_CANDIDATES) {
3032
- const abs = path16.join(cwd, rel2);
3099
+ const abs = path17.join(cwd, rel2);
3033
3100
  if (await isDir(abs) && await dirHasContent(abs)) {
3034
3101
  matched.push(`${rel2}/`);
3035
3102
  }
@@ -3048,7 +3115,7 @@ async function detectIndexCss(cwd) {
3048
3115
  const matched = [];
3049
3116
  const contents = [];
3050
3117
  for (const rel2 of INDEX_CSS_CANDIDATES) {
3051
- const c = await readFileOrNull(path16.join(cwd, rel2));
3118
+ const c = await readFileOrNull(path17.join(cwd, rel2));
3052
3119
  if (c !== null) {
3053
3120
  matched.push(rel2);
3054
3121
  contents.push(c);
@@ -3067,17 +3134,17 @@ async function detectIndexCss(cwd) {
3067
3134
  async function detectShadcnSource(cwd) {
3068
3135
  const matched = [];
3069
3136
  for (const rel2 of SHADCN_FILE_CANDIDATES) {
3070
- if (await fileExists(path16.join(cwd, rel2))) matched.push(rel2);
3137
+ if (await fileExists(path17.join(cwd, rel2))) matched.push(rel2);
3071
3138
  }
3072
3139
  for (const rel2 of SHADCN_DIR_CANDIDATES) {
3073
- const abs = path16.join(cwd, rel2);
3140
+ const abs = path17.join(cwd, rel2);
3074
3141
  if (await isDir(abs) && await dirHasContent(abs)) {
3075
3142
  matched.push(`${rel2}/`);
3076
3143
  }
3077
3144
  }
3078
3145
  let componentCount = 0;
3079
3146
  try {
3080
- const uiDir = path16.join(cwd, "src/components/ui");
3147
+ const uiDir = path17.join(cwd, "src/components/ui");
3081
3148
  if (await isDir(uiDir)) {
3082
3149
  const entries = await fs15.readdir(uiDir);
3083
3150
  componentCount = entries.filter(
@@ -3097,7 +3164,7 @@ async function detectShadcnSource(cwd) {
3097
3164
  };
3098
3165
  }
3099
3166
  async function detectConflicts(cwd) {
3100
- const absCwd = path16.resolve(cwd);
3167
+ const absCwd = path17.resolve(cwd);
3101
3168
  const items = await Promise.all([
3102
3169
  detectAgentsMd(absCwd),
3103
3170
  detectComponentsJson(absCwd),
@@ -3118,7 +3185,7 @@ async function detectEslintConfig(cwd) {
3118
3185
  const matched = [];
3119
3186
  const contents = [];
3120
3187
  for (const rel2 of ESLINT_CONFIG_CANDIDATES) {
3121
- const c = await readFileOrNull(path16.join(cwd, rel2));
3188
+ const c = await readFileOrNull(path17.join(cwd, rel2));
3122
3189
  if (c !== null) {
3123
3190
  matched.push(rel2);
3124
3191
  contents.push(c);
@@ -3138,7 +3205,7 @@ async function detectStylelintConfig(cwd) {
3138
3205
  const matched = [];
3139
3206
  const contents = [];
3140
3207
  for (const rel2 of STYLELINT_CONFIG_CANDIDATES) {
3141
- const c = await readFileOrNull(path16.join(cwd, rel2));
3208
+ const c = await readFileOrNull(path17.join(cwd, rel2));
3142
3209
  if (c !== null) {
3143
3210
  matched.push(rel2);
3144
3211
  contents.push(c);
@@ -3156,9 +3223,9 @@ async function detectStylelintConfig(cwd) {
3156
3223
  }
3157
3224
 
3158
3225
  // src/core/html-theme-patch.ts
3159
- import * as path17 from "path";
3226
+ import * as path18 from "path";
3160
3227
  async function patchHtmlDataTheme(projectRoot, variant) {
3161
- const htmlPath = path17.join(projectRoot, "index.html");
3228
+ const htmlPath = path18.join(projectRoot, "index.html");
3162
3229
  const content = await readFileOrNull(htmlPath);
3163
3230
  if (content === null) {
3164
3231
  return { status: "not-found", htmlPath };
@@ -3178,7 +3245,7 @@ async function patchHtmlDataTheme(projectRoot, variant) {
3178
3245
  }
3179
3246
 
3180
3247
  // src/core/meta-installer.ts
3181
- import * as path18 from "path";
3248
+ import * as path19 from "path";
3182
3249
  import * as fs16 from "fs/promises";
3183
3250
  import { createRequire as createRequire5 } from "module";
3184
3251
  import {
@@ -3189,11 +3256,11 @@ var require6 = createRequire5(import.meta.url);
3189
3256
  var META_DIR = "meta";
3190
3257
  function resolvePackageRoot4(packageName) {
3191
3258
  const pkgJsonPath = require6.resolve(`${packageName}/package.json`);
3192
- return path18.dirname(pkgJsonPath);
3259
+ return path19.dirname(pkgJsonPath);
3193
3260
  }
3194
3261
  function getMetaDir(projectRoot, category) {
3195
- const base = path18.join(getTeamixDir(projectRoot), META_DIR);
3196
- return category ? path18.join(base, category) : base;
3262
+ const base = path19.join(getTeamixDir(projectRoot), META_DIR);
3263
+ return category ? path19.join(base, category) : base;
3197
3264
  }
3198
3265
  async function landUiMeta(projectRoot) {
3199
3266
  const packageRoot = resolvePackageRoot4("@teamix-evo/ui");
@@ -3207,7 +3274,7 @@ async function landUiMeta(projectRoot) {
3207
3274
  }
3208
3275
  async function landBizUiMeta(projectRoot, variant) {
3209
3276
  const packageRoot = resolvePackageRoot4("@teamix-evo/biz-ui");
3210
- const variantRoot = path18.join(packageRoot, "variants", variant);
3277
+ const variantRoot = path19.join(packageRoot, "variants", variant);
3211
3278
  const manifest = await loadVariantUiPackageManifest2(variantRoot);
3212
3279
  return landManifestMeta({
3213
3280
  projectRoot,
@@ -3221,8 +3288,8 @@ async function landManifestMeta(opts) {
3221
3288
  await ensureTeamixDir(projectRoot);
3222
3289
  const metaDir = getMetaDir(projectRoot, category);
3223
3290
  await ensureDir(metaDir);
3224
- const manifestDest = path18.join(metaDir, "manifest.json");
3225
- const manifestSrc = path18.join(packageRoot, "manifest.json");
3291
+ const manifestDest = path19.join(metaDir, "manifest.json");
3292
+ const manifestSrc = path19.join(packageRoot, "manifest.json");
3226
3293
  await fs16.copyFile(manifestSrc, manifestDest);
3227
3294
  logger.debug(`meta: copied manifest.json \u2192 ${manifestDest}`);
3228
3295
  let written = 0;
@@ -3230,8 +3297,8 @@ async function landManifestMeta(opts) {
3230
3297
  for (const entry of manifest.entries) {
3231
3298
  if (!entry.meta) continue;
3232
3299
  total++;
3233
- const srcPath = path18.join(packageRoot, entry.meta);
3234
- const destPath = path18.join(metaDir, `${entry.id}.md`);
3300
+ const srcPath = path19.join(packageRoot, entry.meta);
3301
+ const destPath = path19.join(metaDir, `${entry.id}.md`);
3235
3302
  try {
3236
3303
  await fs16.copyFile(srcPath, destPath);
3237
3304
  written++;
@@ -3257,17 +3324,17 @@ async function landManifestMeta(opts) {
3257
3324
 
3258
3325
  // src/core/deps-install.ts
3259
3326
  import * as fs17 from "fs/promises";
3260
- import * as path19 from "path";
3327
+ import * as path20 from "path";
3261
3328
  import { exec } from "child_process";
3262
3329
  import { promisify } from "util";
3263
3330
  var execAsync = promisify(exec);
3264
3331
  async function detectPackageManager(projectRoot) {
3265
- if (await fileExists(path19.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
3266
- if (await fileExists(path19.join(projectRoot, "pnpm-workspace.yaml")))
3332
+ if (await fileExists(path20.join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
3333
+ if (await fileExists(path20.join(projectRoot, "pnpm-workspace.yaml")))
3267
3334
  return "pnpm";
3268
- if (await fileExists(path19.join(projectRoot, "bun.lockb"))) return "bun";
3269
- if (await fileExists(path19.join(projectRoot, "bun.lock"))) return "bun";
3270
- if (await fileExists(path19.join(projectRoot, "yarn.lock"))) return "yarn";
3335
+ if (await fileExists(path20.join(projectRoot, "bun.lockb"))) return "bun";
3336
+ if (await fileExists(path20.join(projectRoot, "bun.lock"))) return "bun";
3337
+ if (await fileExists(path20.join(projectRoot, "yarn.lock"))) return "yarn";
3271
3338
  return "npm";
3272
3339
  }
3273
3340
  function getInstallCommand(pm) {
@@ -3284,7 +3351,7 @@ function getInstallCommand(pm) {
3284
3351
  }
3285
3352
  async function installProjectDeps(options) {
3286
3353
  const { projectRoot, npmDependencies, skipInstall = false } = options;
3287
- const pkgPath = path19.join(projectRoot, "package.json");
3354
+ const pkgPath = path20.join(projectRoot, "package.json");
3288
3355
  const raw = await readFileOrNull(pkgPath);
3289
3356
  if (!raw) {
3290
3357
  throw new Error(
@@ -3376,18 +3443,18 @@ ${stepLines}
3376
3443
 
3377
3444
  // src/core/file-changes.ts
3378
3445
  import * as fs18 from "fs/promises";
3379
- import * as path20 from "path";
3446
+ import * as path21 from "path";
3380
3447
  function toRelativePosix(p, projectRoot) {
3381
3448
  let rel2 = p;
3382
- if (path20.isAbsolute(p)) {
3383
- rel2 = path20.relative(projectRoot, p);
3449
+ if (path21.isAbsolute(p)) {
3450
+ rel2 = path21.relative(projectRoot, p);
3384
3451
  }
3385
- return rel2.split(path20.sep).join("/");
3452
+ return rel2.split(path21.sep).join("/");
3386
3453
  }
3387
3454
 
3388
3455
  // src/core/project-init.ts
3389
3456
  import * as fsNode from "fs/promises";
3390
- import * as path21 from "path";
3457
+ import * as path22 from "path";
3391
3458
  var CRITICAL_STEPS = /* @__PURE__ */ new Set([
3392
3459
  "tokens",
3393
3460
  "skills",
@@ -3509,9 +3576,9 @@ async function runProjectInit(options) {
3509
3576
  name: "skills",
3510
3577
  status: "ok",
3511
3578
  detail: `${result.skillCount} skills, ${result.fileCount} files (added: ${result.addedSkillIds.join(", ") || "none"})`,
3512
- changes: result.addedSkillIds.map((id) => ({
3579
+ changes: result.resources.map((resource) => ({
3513
3580
  kind: "created",
3514
- path: `.${ides[0] ?? "qoder"}/skills/${id}/SKILL.md`,
3581
+ path: resource.target,
3515
3582
  step: "skills",
3516
3583
  detail: "skill installed"
3517
3584
  }))
@@ -3761,7 +3828,7 @@ async function runProjectInit(options) {
3761
3828
  detail: "projectRoot does not exist"
3762
3829
  });
3763
3830
  } else {
3764
- const giPath = path21.join(projectRoot, ".gitignore");
3831
+ const giPath = path22.join(projectRoot, ".gitignore");
3765
3832
  let giContent = "";
3766
3833
  try {
3767
3834
  giContent = await fsNode.readFile(giPath, "utf-8");
@@ -3821,12 +3888,12 @@ async function runProjectInit(options) {
3821
3888
  if (!dryRun && hasFailures) {
3822
3889
  try {
3823
3890
  const checklistContent = renderInitChecklist({ variant, status, steps });
3824
- const checklistPath = path21.join(
3891
+ const checklistPath = path22.join(
3825
3892
  projectRoot,
3826
3893
  ".teamix-evo",
3827
3894
  "init-checklist.md"
3828
3895
  );
3829
- await fsNode.mkdir(path21.dirname(checklistPath), { recursive: true });
3896
+ await fsNode.mkdir(path22.dirname(checklistPath), { recursive: true });
3830
3897
  await fsNode.writeFile(checklistPath, checklistContent, "utf-8");
3831
3898
  logger.info(" wrote .teamix-evo/init-checklist.md");
3832
3899
  } catch {
@@ -3870,7 +3937,7 @@ import { hasManagedRegion as hasManagedRegion3, replaceManagedRegion as replaceM
3870
3937
 
3871
3938
  // src/core/snapshot.ts
3872
3939
  import * as fs19 from "fs/promises";
3873
- import * as path22 from "path";
3940
+ import * as path23 from "path";
3874
3941
  var TEAMIX_DIR2 = ".teamix-evo";
3875
3942
  var SNAPSHOTS_DIR = ".snapshots";
3876
3943
  var META_FILE = "_meta.json";
@@ -3886,7 +3953,7 @@ function fsSafeToIso(safe) {
3886
3953
  );
3887
3954
  }
3888
3955
  async function createSnapshot(projectRoot, opts = {}) {
3889
- const teamixDir = path22.join(projectRoot, TEAMIX_DIR2);
3956
+ const teamixDir = path23.join(projectRoot, TEAMIX_DIR2);
3890
3957
  try {
3891
3958
  const stat4 = await fs19.stat(teamixDir);
3892
3959
  if (!stat4.isDirectory()) return null;
@@ -3896,14 +3963,14 @@ async function createSnapshot(projectRoot, opts = {}) {
3896
3963
  }
3897
3964
  const isoTs = (/* @__PURE__ */ new Date()).toISOString();
3898
3965
  const ts = isoToFsSafe(isoTs);
3899
- const snapshotRoot = path22.join(teamixDir, SNAPSHOTS_DIR);
3900
- const target = path22.join(snapshotRoot, ts);
3966
+ const snapshotRoot = path23.join(teamixDir, SNAPSHOTS_DIR);
3967
+ const target = path23.join(snapshotRoot, ts);
3901
3968
  await fs19.mkdir(target, { recursive: true });
3902
3969
  const entries = await fs19.readdir(teamixDir, { withFileTypes: true });
3903
3970
  for (const entry of entries) {
3904
3971
  if (entry.name === SNAPSHOTS_DIR) continue;
3905
- const src = path22.join(teamixDir, entry.name);
3906
- const dst = path22.join(target, entry.name);
3972
+ const src = path23.join(teamixDir, entry.name);
3973
+ const dst = path23.join(target, entry.name);
3907
3974
  await fs19.cp(src, dst, { recursive: true });
3908
3975
  }
3909
3976
  const meta = {
@@ -3911,19 +3978,19 @@ async function createSnapshot(projectRoot, opts = {}) {
3911
3978
  reason: opts.reason ?? "manual"
3912
3979
  };
3913
3980
  await fs19.writeFile(
3914
- path22.join(target, META_FILE),
3981
+ path23.join(target, META_FILE),
3915
3982
  JSON.stringify(meta, null, 2) + "\n",
3916
3983
  "utf-8"
3917
3984
  );
3918
3985
  logger.debug(
3919
- `Snapshot created \u2192 ${path22.relative(projectRoot, target)} (${meta.reason})`
3986
+ `Snapshot created \u2192 ${path23.relative(projectRoot, target)} (${meta.reason})`
3920
3987
  );
3921
3988
  const keep = opts.keep ?? DEFAULT_KEEP;
3922
3989
  await pruneSnapshots(projectRoot, keep, { protectedTs: opts.protectedTs });
3923
3990
  return { ts, path: target };
3924
3991
  }
3925
3992
  async function listSnapshots(projectRoot) {
3926
- const snapshotRoot = path22.join(projectRoot, TEAMIX_DIR2, SNAPSHOTS_DIR);
3993
+ const snapshotRoot = path23.join(projectRoot, TEAMIX_DIR2, SNAPSHOTS_DIR);
3927
3994
  let entries;
3928
3995
  try {
3929
3996
  entries = await fs19.readdir(snapshotRoot, { withFileTypes: true });
@@ -3934,11 +4001,11 @@ async function listSnapshots(projectRoot) {
3934
4001
  const result = [];
3935
4002
  for (const entry of entries) {
3936
4003
  if (!entry.isDirectory()) continue;
3937
- const dir = path22.join(snapshotRoot, entry.name);
4004
+ const dir = path23.join(snapshotRoot, entry.name);
3938
4005
  let isoTs = null;
3939
4006
  let reason = null;
3940
4007
  try {
3941
- const raw = await fs19.readFile(path22.join(dir, META_FILE), "utf-8");
4008
+ const raw = await fs19.readFile(path23.join(dir, META_FILE), "utf-8");
3942
4009
  const parsed = JSON.parse(raw);
3943
4010
  if (typeof parsed.ts === "string") isoTs = parsed.ts;
3944
4011
  if (typeof parsed.reason === "string" && SNAPSHOT_REASONS.includes(
@@ -3972,7 +4039,7 @@ async function pruneSnapshots(projectRoot, keep = DEFAULT_KEEP, opts = {}) {
3972
4039
 
3973
4040
  // src/core/graft-init.ts
3974
4041
  import * as fsNode2 from "fs/promises";
3975
- import * as path23 from "path";
4042
+ import * as path24 from "path";
3976
4043
  var CRITICAL_STEPS2 = /* @__PURE__ */ new Set([
3977
4044
  "ensure-teamix-dir",
3978
4045
  "tokens",
@@ -4011,7 +4078,7 @@ async function runGraftInit(options) {
4011
4078
  onStep
4012
4079
  } = options;
4013
4080
  const ide = options.ide ?? "qoder";
4014
- const ides = options.ides ?? ["qoder", "claude"];
4081
+ const ides = options.ides ?? [...ALL_IDE_KINDS];
4015
4082
  const scope = options.scope ?? "project";
4016
4083
  const steps = [];
4017
4084
  let aborted = false;
@@ -4179,7 +4246,7 @@ async function runGraftInit(options) {
4179
4246
  }
4180
4247
  if (!aborted) {
4181
4248
  try {
4182
- const agentsMdPath = path23.join(projectRoot, "AGENTS.md");
4249
+ const agentsMdPath = path24.join(projectRoot, "AGENTS.md");
4183
4250
  const existing = await readFileOrNull(agentsMdPath) ?? "";
4184
4251
  const meta = LEGACY_LIB_META[legacyLib] ?? {
4185
4252
  displayName: legacyLib,
@@ -4240,7 +4307,7 @@ async function runGraftInit(options) {
4240
4307
  }
4241
4308
  if (!aborted) {
4242
4309
  try {
4243
- const giPath = path23.join(projectRoot, ".gitignore");
4310
+ const giPath = path24.join(projectRoot, ".gitignore");
4244
4311
  let giContent = "";
4245
4312
  try {
4246
4313
  giContent = await fsNode2.readFile(giPath, "utf-8");
@@ -4295,7 +4362,7 @@ ${body}
4295
4362
  }
4296
4363
 
4297
4364
  // src/core/installer.ts
4298
- import * as path24 from "path";
4365
+ import * as path25 from "path";
4299
4366
  import * as fs20 from "fs/promises";
4300
4367
  async function installResources(options) {
4301
4368
  const { projectRoot, manifest, data, variantDir, packageRoot } = options;
@@ -4333,7 +4400,7 @@ async function installSingleResource(resource, projectRoot, data, variantDir, pa
4333
4400
  variantDir,
4334
4401
  packageRoot
4335
4402
  );
4336
- const targetPath = path24.join(projectRoot, resource.target);
4403
+ const targetPath = path25.join(projectRoot, resource.target);
4337
4404
  let content;
4338
4405
  if (resource.template) {
4339
4406
  const templateContent = await loadTemplateFile(sourcePath);
@@ -4357,13 +4424,13 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
4357
4424
  variantDir,
4358
4425
  packageRoot
4359
4426
  );
4360
- const targetDir = path24.join(projectRoot, resource.target);
4427
+ const targetDir = path25.join(projectRoot, resource.target);
4361
4428
  const results = [];
4362
4429
  await ensureDir(targetDir);
4363
4430
  const entries = await walkDir(sourcePath);
4364
4431
  for (const entry of entries) {
4365
- const relPath = path24.relative(sourcePath, entry);
4366
- let targetFile = path24.join(targetDir, relPath);
4432
+ const relPath = path25.relative(sourcePath, entry);
4433
+ let targetFile = path25.join(targetDir, relPath);
4367
4434
  if (resource.template && targetFile.endsWith(".hbs")) {
4368
4435
  targetFile = targetFile.slice(0, -4);
4369
4436
  }
@@ -4376,7 +4443,7 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
4376
4443
  }
4377
4444
  await writeFileSafe(targetFile, content);
4378
4445
  const hash = computeHash(content);
4379
- const targetRel = path24.relative(projectRoot, targetFile);
4446
+ const targetRel = path25.relative(projectRoot, targetFile);
4380
4447
  results.push({
4381
4448
  id: `${resource.id}:${relPath}`,
4382
4449
  target: targetRel,
@@ -4389,23 +4456,23 @@ async function installRecursiveResource(resource, projectRoot, data, variantDir,
4389
4456
  }
4390
4457
 
4391
4458
  // src/core/registry-client.ts
4392
- import * as path25 from "path";
4459
+ import * as path26 from "path";
4393
4460
  import * as fs21 from "fs/promises";
4394
4461
  import { createRequire as createRequire6 } from "module";
4395
4462
  import { loadVariantManifest } from "@teamix-evo/registry";
4396
4463
  var require7 = createRequire6(import.meta.url);
4397
4464
  function resolvePackageRoot5(packageName) {
4398
4465
  const pkgJsonPath = require7.resolve(`${packageName}/package.json`);
4399
- return path25.dirname(pkgJsonPath);
4466
+ return path26.dirname(pkgJsonPath);
4400
4467
  }
4401
4468
  async function loadVariantData(packageName, variant) {
4402
4469
  const packageRoot = resolvePackageRoot5(packageName);
4403
- const variantDir = path25.join(packageRoot, "library", variant);
4470
+ const variantDir = path26.join(packageRoot, "library", variant);
4404
4471
  logger.debug(`Resolved variant dir: ${variantDir}`);
4405
4472
  logger.debug(`Package root: ${packageRoot}`);
4406
4473
  const manifest = await loadVariantManifest(variantDir);
4407
4474
  let data = {};
4408
- const dataPath = path25.join(variantDir, "_data.json");
4475
+ const dataPath = path26.join(variantDir, "_data.json");
4409
4476
  try {
4410
4477
  const raw = await fs21.readFile(dataPath, "utf-8");
4411
4478
  data = JSON.parse(raw);