@zan_team/cli 0.0.2 → 0.0.3

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/README.md CHANGED
@@ -360,15 +360,31 @@ zan project rpc-key pull
360
360
  ```
361
361
 
362
362
  命令写入当前工作目录中固定的 `ZAN_API_KEY`:已存在时替换,缺少时追加,文件
363
- 不存在时创建。实际生效的测试覆盖 Key 优先,否则从加密 Endpoint 缓存中提取
364
- 服务端下发的 Project Key;不要求选择 Network。命令不接受 Key、stdin、变量名
363
+ 不存在时创建。API Key 按环境和 Project ID 独立保存在系统凭据库(macOS Keychain
364
+ 等),与 Endpoint 缓存的加密密钥、手动覆盖值分别存储。`pull` 优先使用手动覆盖值,
365
+ 否则直接读取所选 Project 已保存的 API Key,不需要读取网络缓存或请求后端。
366
+
367
+ 首次缺失时,CLI 请求该 Project 的网络列表,从首个可识别的 RPC 地址提取 API Key
368
+ 并保存到系统凭据库;现有后端接口通过地址携带 Key。刷新网络列表时同步更新保存的
369
+ API Key,服务端不再返回可识别 Key 时移除旧记录。`zan project cache clear` 会同时
370
+ 清理当前项目保存的 API Key;退出登录会清理当前环境各项目的 Key 和覆盖值。
371
+
372
+ API Key 属于所选 Project,不要求选择 Network。未选择 Project 时,交互终端会
373
+ 列出项目供选择,非交互模式需使用 `--project <id>` 或先执行 `zan project use <id>`。
374
+ 命令不接受 Key、stdin、变量名
365
375
  或输出路径,也不会在人工输出、JSON 输出、错误或日志中包含 Key。新文件及更新
366
376
  后的文件在 POSIX 系统上使用 `0600` 权限,并通过文件锁和原子替换写入;符号链接
367
377
  或非普通 `.env` 会被拒绝。
368
378
 
369
- `pull` 只写 `.env`,不会修改其他环境配置文件。
370
- 它不会检查 Git 跟踪状态或自动更新 `.gitignore`,请自行确保 `.env`
371
- 不会被提交。写入后,任何拥有当前目录读取权限的进程或 Agent 都可能读取这个明文
379
+ `pull` 会确保 `.env` 被 Git 忽略:已有生效规则(包括父目录、通配符和全局规则)时
380
+ 不修改 `.gitignore`,否则在当前目录的 `.gitignore` 末尾追加 `/.env`。尚未初始化 Git
381
+ 仓库的目录也支持此行为,不会自动创建项目仓库。此检查使用本机 Git;Git 不可用时会提示风险。
382
+
383
+ 若 `.env` 已被 Git 跟踪,或无法检查、更新忽略规则,命令仍写入 Key,并在终端提示
384
+ 误提交 Key 的风险;JSON 结果通过 `warnings` 返回同样的提示。已跟踪时可执行
385
+ `git rm --cached -- .env` 取消跟踪,并在提交前检查暂存内容;CLI 不会自动修改 Git
386
+ 索引,忽略规则也不能清除历史提交中的内容。其他环境配置文件不会被修改。
387
+ 写入后,任何拥有当前目录读取权限的进程或 Agent 都可能读取这个明文
372
388
  文件;“不泄露”保证只覆盖该命令自身的参数、输出、错误和日志边界。
373
389
 
374
390
  管理默认 Project 和 Network:
package/dist/cli.js CHANGED
@@ -1809,6 +1809,10 @@ function registerProject(program, outputWriter, getRuntimeContext, input, rpcKey
1809
1809
  rpcKey.command("pull").description("Write the active Project RPC API Key to .env").action(async () => {
1810
1810
  const { rpcKeyPullService } = await getRuntimeContext();
1811
1811
  const result = await rpcKeyPullService.pull();
1812
+ for (const warning of result.warnings ?? []) {
1813
+ outputWriter.writeStderr(`Warning: ${warning}
1814
+ `);
1815
+ }
1812
1816
  outputWriter.success(
1813
1817
  result,
1814
1818
  "ZAN_API_KEY was written to .env"
@@ -1891,7 +1895,7 @@ function registerSign(program, outputWriter, getRuntimeContext) {
1891
1895
  }
1892
1896
 
1893
1897
  // src/version.ts
1894
- var CLI_VERSION = true ? "0.0.2" : pkg.version;
1898
+ var CLI_VERSION = true ? "0.0.3" : pkg.version;
1895
1899
 
1896
1900
  // src/commands/version.ts
1897
1901
  function registerVersion(program, outputWriter) {
@@ -2166,7 +2170,7 @@ var ReadlineProjectPrompt = class {
2166
2170
 
2167
2171
  // src/runtime/context.ts
2168
2172
  import { homedir as readHomedir2 } from "os";
2169
- import { join as join6 } from "path";
2173
+ import { join as join7 } from "path";
2170
2174
 
2171
2175
  // src/auth/session-metadata-store.ts
2172
2176
  import { z as z8 } from "zod";
@@ -2630,9 +2634,9 @@ var BrowserFlow = class {
2630
2634
  // src/auth/browser-opener.ts
2631
2635
  import { execFile as nodeExecFile } from "child_process";
2632
2636
  var BrowserOpener = class {
2633
- constructor(platform = process.platform, execFile = nodeExecFile) {
2637
+ constructor(platform = process.platform, execFile2 = nodeExecFile) {
2634
2638
  this.platform = platform;
2635
- this.execFile = execFile;
2639
+ this.execFile = execFile2;
2636
2640
  }
2637
2641
  platform;
2638
2642
  execFile;
@@ -5133,7 +5137,7 @@ var NetworkSelector = class {
5133
5137
  };
5134
5138
 
5135
5139
  // src/projects/dotenv-api-key-writer.ts
5136
- import { randomUUID as randomUUID3 } from "crypto";
5140
+ import { randomUUID as randomUUID4 } from "crypto";
5137
5141
  import {
5138
5142
  chmod as nodeChmod2,
5139
5143
  lstat as nodeLstat2,
@@ -5142,7 +5146,111 @@ import {
5142
5146
  rename as nodeRename,
5143
5147
  unlink as nodeUnlink
5144
5148
  } from "fs/promises";
5145
- import { isAbsolute as isAbsolute3, join as join4 } from "path";
5149
+ import { isAbsolute as isAbsolute3, join as join5 } from "path";
5150
+
5151
+ // src/projects/dotenv-gitignore.ts
5152
+ import { execFile } from "child_process";
5153
+ import { randomUUID as randomUUID3 } from "crypto";
5154
+ import { lstat as lstat4, mkdtemp as mkdtemp2, open as open2, readFile as readFile3, rename as rename2, rm as rm2 } from "fs/promises";
5155
+ import { tmpdir } from "os";
5156
+ import { join as join4 } from "path";
5157
+ import { promisify } from "util";
5158
+ var execute = promisify(execFile);
5159
+ var UNCONFIRMED_WARNING = "Unable to confirm .env is ignored by Git; there is a risk of committing the API Key. Check Git and .gitignore before committing.";
5160
+ function protectionFailure() {
5161
+ return new Error("Unable to verify Git ignore rules.");
5162
+ }
5163
+ async function appendRule(directory) {
5164
+ const filename = join4(directory, ".gitignore");
5165
+ let current = "";
5166
+ let mode = 420;
5167
+ try {
5168
+ const info = await lstat4(filename);
5169
+ if (!info.isFile() || info.isSymbolicLink()) throw protectionFailure();
5170
+ mode = info.mode & 511;
5171
+ current = await readFile3(filename, "utf8");
5172
+ } catch (error) {
5173
+ if (error.code !== "ENOENT") throw error;
5174
+ }
5175
+ const newline = current.includes("\r\n") ? "\r\n" : "\n";
5176
+ const separator = current.length === 0 || current.endsWith("\n") ? "" : newline;
5177
+ const temporary = join4(directory, `.gitignore.${randomUUID3()}.tmp`);
5178
+ try {
5179
+ const handle = await open2(temporary, "wx", mode);
5180
+ try {
5181
+ await handle.writeFile(`${current}${separator}/.env${newline}`, "utf8");
5182
+ await handle.sync();
5183
+ } finally {
5184
+ await handle.close();
5185
+ }
5186
+ await rename2(temporary, filename);
5187
+ } finally {
5188
+ await rm2(temporary, { force: true });
5189
+ }
5190
+ }
5191
+ async function ensureDotenvIgnored(directory) {
5192
+ const warnings = [];
5193
+ const env = { ...process.env, LC_ALL: "C" };
5194
+ for (const name of ["GIT_DIR", "GIT_WORK_TREE", "GIT_INDEX_FILE", "GIT_COMMON_DIR", "GIT_PREFIX"]) {
5195
+ delete env[name];
5196
+ }
5197
+ const git = async (args) => {
5198
+ try {
5199
+ return { code: 0, ...await execute("git", args, {
5200
+ cwd: directory,
5201
+ env,
5202
+ encoding: "utf8",
5203
+ timeout: 1e4,
5204
+ maxBuffer: 64 * 1024
5205
+ }) };
5206
+ } catch (error) {
5207
+ const failure = error;
5208
+ if (typeof failure.code !== "number") throw protectionFailure();
5209
+ return { code: failure.code, stdout: failure.stdout ?? "", stderr: failure.stderr ?? "" };
5210
+ }
5211
+ };
5212
+ let temporaryRepository;
5213
+ try {
5214
+ const repository = await git(["rev-parse", "--is-inside-work-tree"]);
5215
+ let prefix = [];
5216
+ if (repository.code === 0 && repository.stdout.trim() === "true") {
5217
+ const tracked = await git(["ls-files", "--error-unmatch", "--", ".env"]);
5218
+ if (tracked.code === 0) {
5219
+ warnings.push(
5220
+ ".env is already tracked by Git; there is a risk of committing the API Key even with .gitignore. Run: git rm --cached -- .env, and review staged changes before committing."
5221
+ );
5222
+ } else if (tracked.code !== 1) {
5223
+ throw protectionFailure();
5224
+ }
5225
+ } else if (repository.code === 128 && repository.stderr.includes("not a git repository")) {
5226
+ temporaryRepository = await mkdtemp2(join4(tmpdir(), "zan-ignore-"));
5227
+ const initialized = await git(["init", "--bare", "--quiet", "--template=", temporaryRepository]);
5228
+ if (initialized.code !== 0) throw protectionFailure();
5229
+ prefix = [`--git-dir=${temporaryRepository}`, `--work-tree=${directory}`, "-c", "core.bare=false"];
5230
+ } else {
5231
+ throw protectionFailure();
5232
+ }
5233
+ const ignored = await git([...prefix, "check-ignore", "--quiet", "--no-index", "--", ".env"]);
5234
+ if (ignored.code === 0) return warnings;
5235
+ if (ignored.code !== 1) throw protectionFailure();
5236
+ await appendRule(directory);
5237
+ const verified = await git([...prefix, "check-ignore", "--quiet", "--no-index", "--", ".env"]);
5238
+ if (verified.code !== 0) throw protectionFailure();
5239
+ } catch {
5240
+ warnings.push(UNCONFIRMED_WARNING);
5241
+ } finally {
5242
+ if (temporaryRepository !== void 0) {
5243
+ try {
5244
+ await rm2(temporaryRepository, { recursive: true, force: true });
5245
+ } catch {
5246
+ warnings.push("Temporary Git metadata could not be removed; review the system temporary directory.");
5247
+ }
5248
+ }
5249
+ }
5250
+ return warnings;
5251
+ }
5252
+
5253
+ // src/projects/dotenv-api-key-writer.ts
5146
5254
  var API_KEY_ASSIGNMENT = /^[ \t]*(?:export[ \t]+)?ZAN_API_KEY[ \t]*=/u;
5147
5255
  function unsafeKeyFailure() {
5148
5256
  return new CliFailure(
@@ -5220,7 +5328,7 @@ var DotenvApiKeyWriter = class {
5220
5328
  this.options = options;
5221
5329
  this.platform = options.platform ?? process.platform;
5222
5330
  this.fileSystem = options.fileSystem ?? nodeDotenvApiKeyFileSystem;
5223
- this.createTemporaryId = options.createTemporaryId ?? randomUUID3;
5331
+ this.createTemporaryId = options.createTemporaryId ?? randomUUID4;
5224
5332
  }
5225
5333
  options;
5226
5334
  platform;
@@ -5234,8 +5342,9 @@ var DotenvApiKeyWriter = class {
5234
5342
  if (!isAbsolute3(this.options.directory)) {
5235
5343
  throw unsafeDotenvPathFailure();
5236
5344
  }
5237
- const lockPath = join4(this.options.directory, ".env.zan.lock");
5345
+ const lockPath = join5(this.options.directory, ".env.zan.lock");
5238
5346
  let renamed = false;
5347
+ let warnings = [];
5239
5348
  try {
5240
5349
  await this.assertSafeOptionalPath(lockPath);
5241
5350
  const lock = new FileLock(lockPath, {
@@ -5244,11 +5353,15 @@ var DotenvApiKeyWriter = class {
5244
5353
  await lock.withLock(async () => {
5245
5354
  const current = await this.readExistingFile();
5246
5355
  const next = updateApiKeyAssignment(current, parsed.data);
5356
+ warnings = await ensureDotenvIgnored(this.options.directory);
5247
5357
  await this.replaceAtomically(next, () => {
5248
5358
  renamed = true;
5249
5359
  });
5250
5360
  });
5251
5361
  } catch (error) {
5362
+ if (error instanceof CliFailure) {
5363
+ throw error;
5364
+ }
5252
5365
  if (error instanceof UnsafeDotenvPathError) {
5253
5366
  throw unsafeDotenvPathFailure();
5254
5367
  }
@@ -5257,6 +5370,9 @@ var DotenvApiKeyWriter = class {
5257
5370
  }
5258
5371
  throw dotenvWriteFailure();
5259
5372
  }
5373
+ if (warnings.length > 0) {
5374
+ return { warnings };
5375
+ }
5260
5376
  }
5261
5377
  async assertSafeOptionalPath(path) {
5262
5378
  try {
@@ -5272,7 +5388,7 @@ var DotenvApiKeyWriter = class {
5272
5388
  }
5273
5389
  }
5274
5390
  async readExistingFile() {
5275
- const filename = join4(this.options.directory, ".env");
5391
+ const filename = join5(this.options.directory, ".env");
5276
5392
  await this.assertSafeOptionalPath(filename);
5277
5393
  try {
5278
5394
  return await this.fileSystem.readFile(filename, "utf8");
@@ -5284,8 +5400,8 @@ var DotenvApiKeyWriter = class {
5284
5400
  }
5285
5401
  }
5286
5402
  async replaceAtomically(content, onRenamed) {
5287
- const filename = join4(this.options.directory, ".env");
5288
- const temporaryFile = join4(
5403
+ const filename = join5(this.options.directory, ".env");
5404
+ const temporaryFile = join5(
5289
5405
  this.options.directory,
5290
5406
  `.env.${process.pid}.${this.createTemporaryId()}.tmp`
5291
5407
  );
@@ -5479,22 +5595,22 @@ import { posix, win32 } from "path";
5479
5595
  // src/storage/atomic-json.ts
5480
5596
  import {
5481
5597
  chmod as chmod3,
5482
- lstat as lstat4,
5598
+ lstat as lstat5,
5483
5599
  mkdir as mkdir3,
5484
- open as open2,
5485
- readFile as readFile3,
5486
- rename as rename2,
5600
+ open as open3,
5601
+ readFile as readFile4,
5602
+ rename as rename3,
5487
5603
  unlink as unlink2
5488
5604
  } from "fs/promises";
5489
5605
  import { dirname as dirname2 } from "path";
5490
- import { randomUUID as randomUUID4 } from "crypto";
5606
+ import { randomUUID as randomUUID5 } from "crypto";
5491
5607
  var nodeAtomicJsonFileSystem = Object.freeze({
5492
5608
  chmod: chmod3,
5493
- lstat: lstat4,
5609
+ lstat: lstat5,
5494
5610
  mkdir: mkdir3,
5495
- open: open2,
5496
- readFile: readFile3,
5497
- rename: rename2,
5611
+ open: open3,
5612
+ readFile: readFile4,
5613
+ rename: rename3,
5498
5614
  unlink: unlink2
5499
5615
  });
5500
5616
  function hasErrorCode5(error, code) {
@@ -5538,7 +5654,7 @@ var AtomicJsonStore = class {
5538
5654
  this.filename = filename;
5539
5655
  this.fileSystem = options.fileSystem ?? nodeAtomicJsonFileSystem;
5540
5656
  this.platform = options.platform ?? process.platform;
5541
- this.createTemporaryId = options.createTemporaryId ?? randomUUID4;
5657
+ this.createTemporaryId = options.createTemporaryId ?? randomUUID5;
5542
5658
  }
5543
5659
  schema;
5544
5660
  filename;
@@ -5840,6 +5956,13 @@ var ProjectEndpointCache = class {
5840
5956
  ).toString("base64url");
5841
5957
  return `endpoint-cache-key-${scope}`;
5842
5958
  }
5959
+ apiKeyAccount(projectId) {
5960
+ const scope = Buffer6.from(
5961
+ `${this.options.environment}:${projectId}`,
5962
+ "utf8"
5963
+ ).toString("base64url");
5964
+ return `project-rpc-key-${scope}`;
5965
+ }
5843
5966
  overrideAccount(projectId) {
5844
5967
  const scope = Buffer6.from(
5845
5968
  `${this.options.environment}:${projectId}`,
@@ -5895,6 +6018,18 @@ var ProjectEndpointCache = class {
5895
6018
  }
5896
6019
  throw error;
5897
6020
  }
6021
+ let apiKey;
6022
+ for (const network of networks) {
6023
+ apiKey = this.extractCredential(network.endpoints.https);
6024
+ if (apiKey !== void 0) {
6025
+ break;
6026
+ }
6027
+ }
6028
+ if (apiKey === void 0) {
6029
+ await this.options.secretStore.delete(this.apiKeyAccount(projectId));
6030
+ } else {
6031
+ await this.options.secretStore.write(this.apiKeyAccount(projectId), apiKey);
6032
+ }
5898
6033
  return networks;
5899
6034
  }
5900
6035
  status(projectId) {
@@ -5903,7 +6038,8 @@ var ProjectEndpointCache = class {
5903
6038
  async clear(projectId) {
5904
6039
  const results = await Promise.allSettled([
5905
6040
  this.options.store.delete(projectId),
5906
- this.options.secretStore.delete(this.cacheKeyAccount(projectId))
6041
+ this.options.secretStore.delete(this.cacheKeyAccount(projectId)),
6042
+ this.options.secretStore.delete(this.apiKeyAccount(projectId))
5907
6043
  ]);
5908
6044
  const failure = results.find(
5909
6045
  (result) => result.status === "rejected"
@@ -5962,20 +6098,23 @@ var ProjectEndpointCache = class {
5962
6098
  this.overrideAccount(projectId)
5963
6099
  );
5964
6100
  if (override !== null) {
5965
- const parsed = rpcApiKeySchema.safeParse(override);
5966
- if (!parsed.success) {
6101
+ const parsed2 = rpcApiKeySchema.safeParse(override);
6102
+ if (!parsed2.success) {
5967
6103
  throw unavailableApiKey();
5968
6104
  }
5969
- return parsed.data;
6105
+ return parsed2.data;
5970
6106
  }
5971
- const candidates = (await this.list(projectId)).map(
5972
- (network) => this.extractCredential(network)
5973
- );
5974
- const unique = new Set(candidates);
5975
- if (candidates.length === 0 || unique.size !== 1) {
6107
+ const account = this.apiKeyAccount(projectId);
6108
+ let key = await this.options.secretStore.read(account);
6109
+ if (key === null) {
6110
+ await this.refresh(projectId);
6111
+ key = await this.options.secretStore.read(account);
6112
+ }
6113
+ const parsed = rpcApiKeySchema.safeParse(key);
6114
+ if (!parsed.success) {
5976
6115
  throw unavailableApiKey();
5977
6116
  }
5978
- return candidates[0];
6117
+ return parsed.data;
5979
6118
  }
5980
6119
  async applyOverride(projectId, network) {
5981
6120
  const key = await this.options.secretStore.read(
@@ -6032,33 +6171,39 @@ var ProjectEndpointCache = class {
6032
6171
  );
6033
6172
  }
6034
6173
  }
6035
- extractCredential(network) {
6174
+ extractCredential(endpoint) {
6036
6175
  try {
6037
- const url = new URL(network.endpoints.https);
6176
+ const url = new URL(endpoint);
6038
6177
  const trustedHost = url.hostname === "zan.top" || url.hostname.endsWith(".zan.top");
6039
6178
  const segments = url.pathname.slice(1).split("/");
6040
6179
  if (url.protocol !== "https:" || !trustedHost || url.port.length > 0 || url.username.length > 0 || url.password.length > 0 || url.search.length > 0 || url.hash.length > 0 || !url.pathname.startsWith("/") || segments.some((segment) => segment.length === 0) || url.pathname !== `/${segments.join("/")}`) {
6041
6180
  throw new Error("unsafe");
6042
6181
  }
6043
- let candidate;
6044
- if (network.ecosystem === "hyperliquid") {
6045
- if (segments.length !== 6 || segments[0] !== "node" || segments[1] !== "v1" || segments[2] !== "hyperliquid" || segments[3] !== network.network || segments[5] !== "evm") {
6046
- throw new Error("unsafe");
6047
- }
6048
- candidate = segments[4];
6049
- } else {
6050
- if (segments.length !== 5 || segments[0] !== "node" || segments[1] !== "v1" || !networkIdSchema.safeParse(segments[2]).success || segments[3] !== network.network) {
6051
- throw new Error("unsafe");
6052
- }
6053
- candidate = segments[4];
6182
+ if (segments[0] !== "node" || segments[1] !== "v1" || !networkIdSchema.safeParse(segments[2]).success || !networkIdSchema.safeParse(segments[3]).success) {
6183
+ return void 0;
6184
+ }
6185
+ let suffix = "";
6186
+ switch (segments[2]) {
6187
+ case "hyperliquid":
6188
+ suffix = "evm";
6189
+ break;
6190
+ case "avax":
6191
+ suffix = "ext/bc/C/rpc";
6192
+ break;
6193
+ case "tron":
6194
+ suffix = "jsonrpc";
6195
+ break;
6054
6196
  }
6055
- const parsed = rpcApiKeySchema.safeParse(candidate);
6197
+ if (segments.slice(5).join("/") !== suffix) {
6198
+ return void 0;
6199
+ }
6200
+ const parsed = rpcApiKeySchema.safeParse(segments[4]);
6056
6201
  if (!parsed.success) {
6057
6202
  throw new Error("unsafe");
6058
6203
  }
6059
6204
  return parsed.data;
6060
6205
  } catch {
6061
- throw unavailableApiKey();
6206
+ return void 0;
6062
6207
  }
6063
6208
  }
6064
6209
  };
@@ -6072,21 +6217,22 @@ var RpcKeyPullService = class {
6072
6217
  async pull() {
6073
6218
  const projectId = await this.dependencies.projects.activeId();
6074
6219
  const key = await this.dependencies.keys.effectiveApiKey(projectId);
6075
- await this.dependencies.writer.write(key);
6220
+ const result = await this.dependencies.writer.write(key);
6076
6221
  return {
6077
6222
  file: ".env",
6078
6223
  variable: "ZAN_API_KEY",
6079
- updated: true
6224
+ updated: true,
6225
+ ...result?.warnings.length ? { warnings: result.warnings } : {}
6080
6226
  };
6081
6227
  }
6082
6228
  };
6083
6229
 
6084
6230
  // src/projects/project-service.ts
6085
- import { randomUUID as randomUUID5 } from "crypto";
6231
+ import { randomUUID as randomUUID6 } from "crypto";
6086
6232
  var ProjectService = class {
6087
6233
  constructor(options) {
6088
6234
  this.options = options;
6089
- this.createIdempotencyKey = options.createIdempotencyKey ?? randomUUID5;
6235
+ this.createIdempotencyKey = options.createIdempotencyKey ?? randomUUID6;
6090
6236
  }
6091
6237
  options;
6092
6238
  createIdempotencyKey;
@@ -6480,7 +6626,7 @@ var SettingsStore = class {
6480
6626
  };
6481
6627
 
6482
6628
  // src/settings/paths.ts
6483
- import { join as join5, posix as posix2, win32 as win322 } from "path";
6629
+ import { join as join6, posix as posix2, win32 as win322 } from "path";
6484
6630
  function nonEmpty(value) {
6485
6631
  return value === void 0 || value.length === 0 ? void 0 : value;
6486
6632
  }
@@ -6513,7 +6659,7 @@ function resolveZanHome(env, platform, homedir2) {
6513
6659
  }
6514
6660
  if (platform === "darwin") {
6515
6661
  return validateHomePath(
6516
- join5(readHomedir(homedir2), "Library", "Application Support", "zan"),
6662
+ join6(readHomedir(homedir2), "Library", "Application Support", "zan"),
6517
6663
  platform
6518
6664
  );
6519
6665
  }
@@ -7336,7 +7482,7 @@ function createRuntimeContext(input) {
7336
7482
  walletService ??= new WalletService({
7337
7483
  index: new AtomicJsonStore(
7338
7484
  walletIndexSchema,
7339
- join6(home, "wallets.json"),
7485
+ join7(home, "wallets.json"),
7340
7486
  { platform }
7341
7487
  ),
7342
7488
  secrets: secretStore,
@@ -7652,4 +7798,3 @@ export {
7652
7798
  isMainModule,
7653
7799
  runCli
7654
7800
  };
7655
- //# sourceMappingURL=cli.js.map
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@zan_team/cli",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "Unified ZAN command-line interface for developers, automation, and AI agents",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "zan": "./dist/cli.js"
8
8
  },
9
9
  "files": [
10
- "dist",
10
+ "dist/cli.js",
11
11
  "skills",
12
12
  "README.md"
13
13
  ],