oh-my-customcode 1.1.97 → 1.1.99

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -46,10 +46,79 @@ var __esm = (fn, res, err) => () => {
46
46
  };
47
47
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
48
48
 
49
+ // src/utils/home.ts
50
+ import { homedir, userInfo } from "node:os";
51
+ import { parse, sep } from "node:path";
52
+ function readEnvHome() {
53
+ return process.env.HOME;
54
+ }
55
+ function readOsHome() {
56
+ return homedir();
57
+ }
58
+ function readPasswdHome() {
59
+ return userInfo().homedir;
60
+ }
61
+ function stripTrailingSeparators(path) {
62
+ const rootLength = parse(path).root.length;
63
+ let end = path.length;
64
+ while (end > rootLength && (path[end - 1] === "/" || path[end - 1] === sep)) {
65
+ end--;
66
+ }
67
+ return path.slice(0, end);
68
+ }
69
+ function resolveHomeDir(sources = {}) {
70
+ const candidates = [
71
+ sources.envHome ?? readEnvHome,
72
+ sources.osHome ?? readOsHome,
73
+ sources.passwdHome ?? readPasswdHome
74
+ ];
75
+ for (const read of candidates) {
76
+ try {
77
+ const value = read();
78
+ if (value) {
79
+ return stripTrailingSeparators(value);
80
+ }
81
+ } catch {}
82
+ }
83
+ return "";
84
+ }
85
+ function isPathWithin(path, base) {
86
+ const strippedBase = stripTrailingSeparators(base);
87
+ if (strippedBase === "") {
88
+ return false;
89
+ }
90
+ const strippedPath = stripTrailingSeparators(path);
91
+ if (strippedPath === strippedBase) {
92
+ return true;
93
+ }
94
+ const prefix = strippedBase.endsWith(sep) || strippedBase.endsWith("/") ? strippedBase : strippedBase + sep;
95
+ return path.startsWith(prefix);
96
+ }
97
+ function isUnderHome(path, home) {
98
+ return isPathWithin(path, home ?? resolveHomeDir());
99
+ }
100
+ function shortenHome(path, home) {
101
+ const base = stripTrailingSeparators(home ?? resolveHomeDir());
102
+ if (!isPathWithin(path, base)) {
103
+ return path;
104
+ }
105
+ const strippedPath = stripTrailingSeparators(path);
106
+ if (strippedPath === base) {
107
+ return "~";
108
+ }
109
+ let rest = path.slice(base.length);
110
+ while (rest.startsWith("/") || rest.startsWith(sep)) {
111
+ rest = rest.slice(1);
112
+ }
113
+ return `~${sep}${rest}`;
114
+ }
115
+ var init_home = () => {};
116
+
49
117
  // src/core/registry.ts
118
+ import { realpathSync } from "node:fs";
50
119
  import { mkdir, readFile, writeFile } from "node:fs/promises";
51
- import { homedir, tmpdir } from "node:os";
52
- import { basename, join, resolve, sep } from "node:path";
120
+ import { tmpdir } from "node:os";
121
+ import { basename, join, resolve, sep as sep2 } from "node:path";
53
122
  function isTempPath(projectPath) {
54
123
  const normalized = resolve(projectPath);
55
124
  const candidates = new Set;
@@ -62,21 +131,29 @@ function isTempPath(projectPath) {
62
131
  candidates.add("/tmp");
63
132
  candidates.add("/var/tmp");
64
133
  candidates.add("/var/folders");
134
+ for (const candidate of [...candidates]) {
135
+ try {
136
+ candidates.add(realpathSync(candidate));
137
+ } catch {}
138
+ }
65
139
  for (const candidate of candidates) {
66
- if (normalized === candidate || normalized.startsWith(candidate + sep)) {
140
+ if (normalized === candidate || normalized.startsWith(candidate + sep2)) {
67
141
  return true;
68
142
  }
69
143
  }
70
144
  return false;
71
145
  }
72
- function registryDir() {
146
+ function registryDir(home) {
73
147
  if (_registryDirOverride !== undefined)
74
148
  return _registryDirOverride;
75
149
  const envOverride = process.env.OMCUSTOM_REGISTRY_DIR;
76
150
  if (envOverride)
77
151
  return envOverride;
78
- const home = process.env.HOME ?? homedir();
79
- return join(home, ".oh-my-customcode");
152
+ const resolved = home ?? resolveHomeDir();
153
+ if (resolved === "") {
154
+ throw new Error("Could not determine the home directory for the project registry");
155
+ }
156
+ return join(resolved, ".oh-my-customcode");
80
157
  }
81
158
  function registryPath() {
82
159
  return join(registryDir(), "projects.json");
@@ -208,6 +285,7 @@ async function migrateFromLockfiles(searchDirs) {
208
285
  }
209
286
  var _registryDirOverride, SCAN_SKIP_DIRS;
210
287
  var init_registry = __esm(() => {
288
+ init_home();
211
289
  SCAN_SKIP_DIRS = new Set(["node_modules", "dist", "build", ".git"]);
212
290
  });
213
291
 
@@ -219,7 +297,7 @@ var init_package = __esm(() => {
219
297
  workspaces: [
220
298
  "packages/*"
221
299
  ],
222
- version: "1.1.97",
300
+ version: "1.1.99",
223
301
  description: "Batteries-included agent harness for Claude Code",
224
302
  type: "module",
225
303
  bin: {
@@ -7215,7 +7293,7 @@ var require_public_api = __commonJS(function(exports) {
7215
7293
  });
7216
7294
 
7217
7295
  // src/utils/fs.ts
7218
- import { dirname as dirname2, isAbsolute, join as join3, relative, resolve as resolve2, sep as sep2 } from "node:path";
7296
+ import { dirname as dirname2, isAbsolute, join as join3, relative, resolve as resolve2, sep as sep3 } from "node:path";
7219
7297
  import { fileURLToPath } from "node:url";
7220
7298
  function validatePreserveFilePath(filePath, projectRoot) {
7221
7299
  if (!filePath || filePath.trim() === "") {
@@ -7311,7 +7389,7 @@ function shouldSkipPath(destPath, destRoot, skipPaths) {
7311
7389
  for (const skipPath of skipPaths) {
7312
7390
  if (skipPath.endsWith("/")) {
7313
7391
  const dirPath = skipPath.slice(0, -1);
7314
- if (relativePath === dirPath || relativePath.startsWith(dirPath + sep2)) {
7392
+ if (relativePath === dirPath || relativePath.startsWith(dirPath + sep3)) {
7315
7393
  return true;
7316
7394
  }
7317
7395
  } else {
@@ -7427,8 +7505,7 @@ var UTF8_BOM = "\uFEFF";
7427
7505
  var init_fs = () => {};
7428
7506
 
7429
7507
  // src/cli/projects.ts
7430
- import { homedir as homedir3 } from "node:os";
7431
- import { basename as basename4, join as join11, sep as sep3 } from "node:path";
7508
+ import { basename as basename4, join as join11, resolve as resolve3 } from "node:path";
7432
7509
  async function readLockFile(projectDir) {
7433
7510
  const lockFilePath = join11(projectDir, ".omcustom.lock.json");
7434
7511
  try {
@@ -7462,13 +7539,15 @@ async function getTemplateVersion() {
7462
7539
  }
7463
7540
  return package_default.version;
7464
7541
  }
7542
+ function normalizeSearchPaths(paths) {
7543
+ if (!paths || paths.length === 0)
7544
+ return;
7545
+ return paths.map((p) => resolve3(p));
7546
+ }
7465
7547
  function matchesSearchPaths(projectPath, searchPaths) {
7466
7548
  if (!searchPaths || searchPaths.length === 0)
7467
7549
  return true;
7468
- return searchPaths.some((searchPath) => projectPath === searchPath || projectPath.startsWith(searchPath + sep3));
7469
- }
7470
- function isUnderHome(projectPath, home) {
7471
- return projectPath.startsWith(home + sep3) || projectPath === home;
7550
+ return searchPaths.some((searchPath) => isPathWithin(projectPath, searchPath));
7472
7551
  }
7473
7552
  function sortProjects(projects) {
7474
7553
  return projects.sort((a, b) => {
@@ -7484,15 +7563,16 @@ async function findProjects(options = {}) {
7484
7563
  const registry = await readRegistry();
7485
7564
  if (Object.keys(registry.projects).length === 0) {
7486
7565
  const fallbackResults = await _findProjectsFromLockfiles(options, currentVersion);
7487
- if (fallbackResults.length === 0 && !options.paths) {
7566
+ if (fallbackResults.length === 0 && !normalizeSearchPaths(options.paths)) {
7488
7567
  process.stderr.write(" No projects in registry. Run `omcustom projects --migrate` to import existing projects.\n");
7489
7568
  }
7490
7569
  return fallbackResults;
7491
7570
  }
7492
7571
  const results = [];
7493
- const home = process.env.HOME ?? homedir3();
7572
+ const home = resolveHomeDir();
7573
+ const searchPaths = normalizeSearchPaths(options.paths);
7494
7574
  for (const [projectPath, entry] of Object.entries(registry.projects)) {
7495
- if (!matchesSearchPaths(projectPath, options.paths))
7575
+ if (!matchesSearchPaths(projectPath, searchPaths))
7496
7576
  continue;
7497
7577
  if (!isUnderHome(projectPath, home))
7498
7578
  continue;
@@ -7544,9 +7624,10 @@ async function _findProjectsFromLockfiles(options, currentVersion) {
7544
7624
  const fs = await import("node:fs/promises");
7545
7625
  const seen = new Set;
7546
7626
  const results = [];
7547
- const home = process.env.HOME ?? homedir3();
7548
- const searchPaths = options.paths ? [...options.paths] : [];
7549
- if (!options.paths) {
7627
+ const home = resolveHomeDir();
7628
+ const providedPaths = normalizeSearchPaths(options.paths);
7629
+ const searchPaths = providedPaths ? [...providedPaths] : [];
7630
+ if (!providedPaths) {
7550
7631
  const cwd = process.cwd();
7551
7632
  if (!searchPaths.includes(cwd))
7552
7633
  searchPaths.push(cwd);
@@ -7576,8 +7657,9 @@ function formatProjectsTable(projects, currentVersion) {
7576
7657
  console.log(" 레지스트리가 비어 있습니다. `omcustom projects --migrate`를 실행하여 기존 프로젝트를 가져오세요.\n");
7577
7658
  return;
7578
7659
  }
7660
+ const home = resolveHomeDir();
7579
7661
  const nameWidth = Math.max(20, ...projects.map((p) => p.name.length));
7580
- const pathWidth = Math.max(35, ...projects.map((p) => shortenPath(p.path).length));
7662
+ const pathWidth = Math.max(35, ...projects.map((p) => shortenHome(p.path, home).length));
7581
7663
  const versionWidth = 10;
7582
7664
  console.log(`
7583
7665
  oh-my-customcode 적용 프로젝트 목록:
@@ -7590,7 +7672,7 @@ function formatProjectsTable(projects, currentVersion) {
7590
7672
  console.log(` ${"─".repeat(nameWidth)} ${"─".repeat(pathWidth)} ${"─".repeat(versionWidth)} ${"─".repeat(12)}`);
7591
7673
  for (const project of projects) {
7592
7674
  const name = project.name.padEnd(nameWidth);
7593
- const path = shortenPath(project.path).padEnd(pathWidth);
7675
+ const path = shortenHome(project.path, home).padEnd(pathWidth);
7594
7676
  const version = (project.version || "unknown").padEnd(versionWidth);
7595
7677
  const statusIcon = project.status === "latest" ? "✓ latest" : project.status === "outdated" ? "⚠ outdated" : "? unknown";
7596
7678
  console.log(` ${name} ${path} ${version} ${statusIcon}`);
@@ -7604,29 +7686,24 @@ function formatProjectsTable(projects, currentVersion) {
7604
7686
  console.log(` Latest version: v${currentVersion}
7605
7687
  `);
7606
7688
  }
7607
- function shortenPath(path) {
7608
- const home = process.env.HOME ?? homedir3();
7609
- if (path.startsWith(home)) {
7610
- return `~${path.slice(home.length)}`;
7611
- }
7612
- return path;
7613
- }
7614
7689
  function formatProjectsSimple(projects, currentVersion) {
7615
7690
  console.log(`
7616
7691
  oh-my-customcode 적용 프로젝트 (${projects.length}개):`);
7692
+ const home = resolveHomeDir();
7617
7693
  for (const project of projects) {
7618
7694
  const version = project.version ? `v${project.version}` : "unknown";
7619
7695
  const status = project.status === "latest" ? "✓" : project.status === "outdated" ? "⚠" : "?";
7620
- console.log(` ${status} ${project.name} [${version}] — ${shortenPath(project.path)}`);
7696
+ console.log(` ${status} ${project.name} [${version}] — ${shortenHome(project.path, home)}`);
7621
7697
  }
7622
7698
  console.log(`
7623
7699
  현재 설치 버전: v${currentVersion}`);
7624
7700
  }
7701
+ function buildMigrationSearchDirs(home, extraPaths = []) {
7702
+ return [...home ? DEFAULT_SEARCH_DIRS.map((d) => join11(home, d)) : [], ...extraPaths];
7703
+ }
7625
7704
  async function runMigration(options) {
7626
7705
  await Promise.resolve().then(() => init_registry());
7627
- const DEFAULT_SEARCH_DIRS = ["workspace", "projects", "dev", "src", "code", "repos", "work"];
7628
- const home = process.env.HOME ?? homedir3();
7629
- const searchDirs = [...DEFAULT_SEARCH_DIRS.map((d) => join11(home, d)), ...options.paths ?? []];
7706
+ const searchDirs = buildMigrationSearchDirs(resolveHomeDir(), options.paths ?? []);
7630
7707
  const cwd = process.cwd();
7631
7708
  if (!searchDirs.includes(cwd))
7632
7709
  searchDirs.push(cwd);
@@ -7675,12 +7752,14 @@ async function projectsCommand(options = {}) {
7675
7752
  return { success: false, projects: [], currentVersion, errors: [errorMessage] };
7676
7753
  }
7677
7754
  }
7678
- var SCAN_SKIP_DIRS2;
7755
+ var SCAN_SKIP_DIRS2, DEFAULT_SEARCH_DIRS;
7679
7756
  var init_projects = __esm(() => {
7680
7757
  init_package();
7681
7758
  init_registry();
7682
7759
  init_fs();
7760
+ init_home();
7683
7761
  SCAN_SKIP_DIRS2 = new Set(["node_modules", "dist", "build", ".git"]);
7762
+ DEFAULT_SEARCH_DIRS = ["workspace", "projects", "dev", "src", "code", "repos", "work"];
7684
7763
  });
7685
7764
 
7686
7765
  // node_modules/.bun/sisteransi@1.0.5/node_modules/sisteransi/src/index.js
@@ -20882,7 +20961,7 @@ function runForeground(projectRoot, port, buildDirOpts) {
20882
20961
  }
20883
20962
 
20884
20963
  // src/cli/sync.ts
20885
- import { resolve as resolve3 } from "node:path";
20964
+ import { resolve as resolve4 } from "node:path";
20886
20965
 
20887
20966
  // src/core/sync.ts
20888
20967
  init_fs();
@@ -21002,7 +21081,7 @@ async function exportSnapshot(targetDir, outputPath) {
21002
21081
 
21003
21082
  // src/cli/sync.ts
21004
21083
  async function runExport(targetDir, outputPath) {
21005
- const result = await exportSnapshot(targetDir, resolve3(outputPath));
21084
+ const result = await exportSnapshot(targetDir, resolve4(outputPath));
21006
21085
  if (!result.success) {
21007
21086
  console.error(`
21008
21087
  Export failed — no .claude/ directory found in current project.`);
@@ -21059,7 +21138,7 @@ Summary: ${result.unchanged} unchanged, ${result.modified.length} modified, ${re
21059
21138
  }
21060
21139
  function syncCommand(program) {
21061
21140
  program.command("sync").description(i18n.t("cli.sync.description")).option("--check", "Compare current state against lockfile (default behavior)").option("--reference <path>", "Compare against an external snapshot instead of the lockfile").option("--export <path>", "Export current .claude/ state as a reusable snapshot").action(async (options) => {
21062
- const targetDir = resolve3(".");
21141
+ const targetDir = resolve4(".");
21063
21142
  if (options.export) {
21064
21143
  await runExport(targetDir, options.export);
21065
21144
  return;
package/dist/index.js CHANGED
@@ -204,10 +204,49 @@ function matchesPattern(filename, pattern) {
204
204
  var UTF8_BOM = "\uFEFF";
205
205
  var init_fs = () => {};
206
206
 
207
+ // src/utils/home.ts
208
+ import { homedir, userInfo } from "node:os";
209
+ import { parse, sep as sep2 } from "node:path";
210
+ function readEnvHome() {
211
+ return process.env.HOME;
212
+ }
213
+ function readOsHome() {
214
+ return homedir();
215
+ }
216
+ function readPasswdHome() {
217
+ return userInfo().homedir;
218
+ }
219
+ function stripTrailingSeparators(path) {
220
+ const rootLength = parse(path).root.length;
221
+ let end = path.length;
222
+ while (end > rootLength && (path[end - 1] === "/" || path[end - 1] === sep2)) {
223
+ end--;
224
+ }
225
+ return path.slice(0, end);
226
+ }
227
+ function resolveHomeDir(sources = {}) {
228
+ const candidates = [
229
+ sources.envHome ?? readEnvHome,
230
+ sources.osHome ?? readOsHome,
231
+ sources.passwdHome ?? readPasswdHome
232
+ ];
233
+ for (const read of candidates) {
234
+ try {
235
+ const value = read();
236
+ if (value) {
237
+ return stripTrailingSeparators(value);
238
+ }
239
+ } catch {}
240
+ }
241
+ return "";
242
+ }
243
+ var init_home = () => {};
244
+
207
245
  // src/core/registry.ts
246
+ import { realpathSync } from "node:fs";
208
247
  import { mkdir, readFile, writeFile } from "node:fs/promises";
209
- import { homedir, tmpdir } from "node:os";
210
- import { basename as basename3, join as join6, resolve as resolve2, sep as sep2 } from "node:path";
248
+ import { tmpdir } from "node:os";
249
+ import { basename as basename3, join as join6, resolve as resolve2, sep as sep3 } from "node:path";
211
250
  function isTempPath(projectPath) {
212
251
  const normalized = resolve2(projectPath);
213
252
  const candidates = new Set;
@@ -220,21 +259,29 @@ function isTempPath(projectPath) {
220
259
  candidates.add("/tmp");
221
260
  candidates.add("/var/tmp");
222
261
  candidates.add("/var/folders");
262
+ for (const candidate of [...candidates]) {
263
+ try {
264
+ candidates.add(realpathSync(candidate));
265
+ } catch {}
266
+ }
223
267
  for (const candidate of candidates) {
224
- if (normalized === candidate || normalized.startsWith(candidate + sep2)) {
268
+ if (normalized === candidate || normalized.startsWith(candidate + sep3)) {
225
269
  return true;
226
270
  }
227
271
  }
228
272
  return false;
229
273
  }
230
- function registryDir() {
274
+ function registryDir(home) {
231
275
  if (_registryDirOverride !== undefined)
232
276
  return _registryDirOverride;
233
277
  const envOverride = process.env.OMCUSTOM_REGISTRY_DIR;
234
278
  if (envOverride)
235
279
  return envOverride;
236
- const home = process.env.HOME ?? homedir();
237
- return join6(home, ".oh-my-customcode");
280
+ const resolved = home ?? resolveHomeDir();
281
+ if (resolved === "") {
282
+ throw new Error("Could not determine the home directory for the project registry");
283
+ }
284
+ return join6(resolved, ".oh-my-customcode");
238
285
  }
239
286
  function registryPath() {
240
287
  return join6(registryDir(), "projects.json");
@@ -277,6 +324,7 @@ async function registerProject(projectPath, version) {
277
324
  }
278
325
  var _registryDirOverride, SCAN_SKIP_DIRS;
279
326
  var init_registry = __esm(() => {
327
+ init_home();
280
328
  SCAN_SKIP_DIRS = new Set(["node_modules", "dist", "build", ".git"]);
281
329
  });
282
330
 
@@ -2766,7 +2814,7 @@ var package_default = {
2766
2814
  workspaces: [
2767
2815
  "packages/*"
2768
2816
  ],
2769
- version: "1.1.97",
2817
+ version: "1.1.99",
2770
2818
  description: "Batteries-included agent harness for Claude Code",
2771
2819
  type: "module",
2772
2820
  bin: {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "workspaces": [
4
4
  "packages/*"
5
5
  ],
6
- "version": "1.1.97",
6
+ "version": "1.1.99",
7
7
  "description": "Batteries-included agent harness for Claude Code",
8
8
  "type": "module",
9
9
  "bin": {
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "1.1.97",
2
+ "version": "1.1.99",
3
3
  "lastUpdated": "2026-09-03",
4
4
  "omcustomMinClaudeCode": "2.1.121",
5
5
  "omcustomMinClaudeCodeReason": "Sensitive-path direct Write/Edit on .claude/** under bypassPermissions (R010 deprecation, #1101)",