@usebitl/cli 0.1.2 → 0.1.4

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.
@@ -314,7 +314,7 @@ var sessionKey = (source, sessionId) => `${source}:${sessionId}`;
314
314
 
315
315
  // ../../shared/src/prepare.ts
316
316
  var WIRE_VERSION = 2;
317
- var TEXT_LIMIT = 500;
317
+ var TEXT_LIMIT = 1e4;
318
318
  var TITLE_LIMIT = 80;
319
319
  var clip = (s, max = TEXT_LIMIT) => {
320
320
  const t = s.trim();
@@ -466,13 +466,17 @@ function readCloudConfig(home = bitlHome()) {
466
466
  return null;
467
467
  }
468
468
  }
469
+ function clientVersionHeader() {
470
+ const v = "0.1.4";
471
+ return v ? { "x-bitl-client": v } : {};
472
+ }
469
473
  function resolveTarget(home = bitlHome()) {
470
474
  const cloud = readCloudConfig(home);
471
475
  if (cloud) {
472
476
  return {
473
477
  kind: "cloud",
474
478
  url: cloud.url.replace(/\/+$/, ""),
475
- headers: { authorization: `Bearer ${cloud.apiKey}` },
479
+ headers: { authorization: `Bearer ${cloud.apiKey}`, ...clientVersionHeader() },
476
480
  keys: () => keysFromBase64Url(readFileSync2(cloudKeyPath(home), "utf8"))
477
481
  };
478
482
  }
package/dist/cli.mjs CHANGED
@@ -7,7 +7,7 @@ var __export = (target, all) => {
7
7
 
8
8
  // ../src/index.ts
9
9
  import { homedir as homedir3 } from "node:os";
10
- import { join as join4, resolve as resolve2 } from "node:path";
10
+ import { join as join5, resolve as resolve2 } from "node:path";
11
11
 
12
12
  // ../../shared/src/crypto.ts
13
13
  var MASTER_KEY_BYTES = 32;
@@ -61,14 +61,14 @@ async function open(keys, sealed, aad) {
61
61
  return fromUtf8.decode(unpad(new Uint8Array(pt)));
62
62
  }
63
63
  var INBOX_CURVE = { name: "ECDH", namedCurve: "P-256" };
64
- async function inboxKey(shared, ephemeralPublic, usage) {
64
+ async function inboxKey(shared, ephemeralPublic, usage2) {
65
65
  const base = await subtle().importKey("raw", shared, "HKDF", false, ["deriveKey"]);
66
66
  return subtle().deriveKey(
67
67
  { name: "HKDF", hash: "SHA-256", salt: new Uint8Array(ephemeralPublic), info: utf8.encode("bitl/v1/inbox") },
68
68
  base,
69
69
  { name: "AES-GCM", length: 256 },
70
70
  false,
71
- [usage]
71
+ [usage2]
72
72
  );
73
73
  }
74
74
  var importInboxPrivateKey = (pkcs8) => subtle().importKey("pkcs8", fromBase64Url(pkcs8), INBOX_CURVE, false, ["deriveBits"]);
@@ -154,7 +154,7 @@ async function verifyPublicKey(secret, role, publicKey, mac3) {
154
154
  return false;
155
155
  }
156
156
  }
157
- async function wrappingKey(ownPrivate, peerPublic, pairingId, usage) {
157
+ async function wrappingKey(ownPrivate, peerPublic, pairingId, usage2) {
158
158
  const shared = await subtle2().deriveBits({ name: "ECDH", public: await importPublicKey(peerPublic) }, ownPrivate, 256);
159
159
  const base = await subtle2().importKey("raw", shared, "HKDF", false, ["deriveKey"]);
160
160
  return subtle2().deriveKey(
@@ -162,7 +162,7 @@ async function wrappingKey(ownPrivate, peerPublic, pairingId, usage) {
162
162
  base,
163
163
  { name: "AES-GCM", length: 256 },
164
164
  false,
165
- [usage]
165
+ [usage2]
166
166
  );
167
167
  }
168
168
  async function wrapMasterKey(master, ownPrivate, peerPublic, pairingId) {
@@ -204,6 +204,18 @@ var EVENT_CONTENT_FIELDS = [
204
204
  "model"
205
205
  ];
206
206
 
207
+ // ../../shared/src/release.ts
208
+ function compareVersions(a, b) {
209
+ const pa = a.split(".").map((n) => Number.parseInt(n, 10) || 0);
210
+ const pb = b.split(".").map((n) => Number.parseInt(n, 10) || 0);
211
+ for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
212
+ const d = (pa[i] ?? 0) - (pb[i] ?? 0);
213
+ if (d !== 0) return Math.sign(d);
214
+ }
215
+ return 0;
216
+ }
217
+ var VERSION_PATTERN = /^\d{1,4}\.\d{1,4}\.\d{1,4}$/;
218
+
207
219
  // ../../shared/src/view.ts
208
220
  async function tryOpen(keys, sealed, aad) {
209
221
  if (sealed === void 0) return { failed: false };
@@ -1135,8 +1147,8 @@ function numKeys(data) {
1135
1147
  return keyCount;
1136
1148
  }
1137
1149
  var getParsedType = (data) => {
1138
- const t = typeof data;
1139
- switch (t) {
1150
+ const t2 = typeof data;
1151
+ switch (t2) {
1140
1152
  case "undefined":
1141
1153
  return "undefined";
1142
1154
  case "string":
@@ -1175,7 +1187,7 @@ var getParsedType = (data) => {
1175
1187
  }
1176
1188
  return "object";
1177
1189
  default:
1178
- throw new Error(`Unknown data type: ${t}`);
1190
+ throw new Error(`Unknown data type: ${t2}`);
1179
1191
  }
1180
1192
  };
1181
1193
  var propertyKeyTypes = /* @__PURE__ */ new Set(["string", "number", "symbol"]);
@@ -1463,8 +1475,8 @@ function getLengthableOrigin(input2) {
1463
1475
  return "unknown";
1464
1476
  }
1465
1477
  function parsedType(data) {
1466
- const t = typeof data;
1467
- switch (t) {
1478
+ const t2 = typeof data;
1479
+ switch (t2) {
1468
1480
  case "number": {
1469
1481
  return Number.isNaN(data) ? "nan" : "number";
1470
1482
  }
@@ -1481,7 +1493,7 @@ function parsedType(data) {
1481
1493
  }
1482
1494
  }
1483
1495
  }
1484
- return t;
1496
+ return t2;
1485
1497
  }
1486
1498
  function issue(...args) {
1487
1499
  const [iss, input2, inst] = args;
@@ -3679,7 +3691,7 @@ function handleCatchall(proms, input2, payload, ctx, def, inst, abortEarly) {
3679
3691
  const unrecognized = [];
3680
3692
  const keySet = def.keySet;
3681
3693
  const _catchall = def.catchall._zod;
3682
- const t = _catchall.def.type;
3694
+ const t2 = _catchall.def.type;
3683
3695
  const optin = _catchall.optin;
3684
3696
  const optout = _catchall.optout;
3685
3697
  let seen = 0;
@@ -3692,11 +3704,11 @@ function handleCatchall(proms, input2, payload, ctx, def, inst, abortEarly) {
3692
3704
  if (keySet.has(key))
3693
3705
  continue;
3694
3706
  if (key === "__proto__") {
3695
- if (t === "never")
3707
+ if (t2 === "never")
3696
3708
  unrecognized.push(key);
3697
3709
  continue;
3698
3710
  }
3699
- if (t === "never") {
3711
+ if (t2 === "never") {
3700
3712
  unrecognized.push(key);
3701
3713
  continue;
3702
3714
  }
@@ -7930,16 +7942,16 @@ var error20 = () => {
7930
7942
  number: { unit: "", shortLabel: "\u05E7\u05D8\u05DF", longLabel: "\u05D2\u05D3\u05D5\u05DC" }
7931
7943
  // no unit
7932
7944
  };
7933
- const typeEntry = (t) => t ? TypeNames[t] : void 0;
7934
- const typeLabel = (t) => {
7935
- const e = typeEntry(t);
7945
+ const typeEntry = (t2) => t2 ? TypeNames[t2] : void 0;
7946
+ const typeLabel = (t2) => {
7947
+ const e = typeEntry(t2);
7936
7948
  if (e)
7937
7949
  return e.label;
7938
- return t ?? TypeNames.unknown.label;
7950
+ return t2 ?? TypeNames.unknown.label;
7939
7951
  };
7940
- const withDefinite = (t) => `\u05D4${typeLabel(t)}`;
7941
- const verbFor = (t) => {
7942
- const e = typeEntry(t);
7952
+ const withDefinite = (t2) => `\u05D4${typeLabel(t2)}`;
7953
+ const verbFor = (t2) => {
7954
+ const e = typeEntry(t2);
7943
7955
  const gender = e?.gender ?? "m";
7944
7956
  return gender === "f" ? "\u05E6\u05E8\u05D9\u05DB\u05D4 \u05DC\u05D4\u05D9\u05D5\u05EA" : "\u05E6\u05E8\u05D9\u05DA \u05DC\u05D4\u05D9\u05D5\u05EA";
7945
7957
  };
@@ -16812,7 +16824,7 @@ function stringifyKeyNames(bySchema, json2, visited) {
16812
16824
  json2 = { ...json2, [keyword]: mapped };
16813
16825
  }
16814
16826
  const types = Array.isArray(json2.type) ? json2.type : [json2.type];
16815
- const numericType = !types.includes("string") && types.some((t) => t === "number" || t === "integer");
16827
+ const numericType = !types.includes("string") && types.some((t2) => t2 === "number" || t2 === "integer");
16816
16828
  const values = json2.enum ?? (json2.const !== void 0 ? [json2.const] : void 0);
16817
16829
  if (!numericType && !values?.some((v) => typeof v === "number"))
16818
16830
  return json2;
@@ -19315,8 +19327,8 @@ function convertBaseSchema(schema, ctx) {
19315
19327
  }
19316
19328
  const type = schema.type;
19317
19329
  if (Array.isArray(type)) {
19318
- const typeSchemas = type.map((t) => {
19319
- const typeSchema = { ...schema, type: t };
19330
+ const typeSchemas = type.map((t2) => {
19331
+ const typeSchema = { ...schema, type: t2 };
19320
19332
  return convertBaseSchema(typeSchema, ctx);
19321
19333
  });
19322
19334
  if (typeSchemas.length === 0) {
@@ -19935,7 +19947,7 @@ var AgentEvent = external_exports.object({
19935
19947
  });
19936
19948
 
19937
19949
  // ../../shared/src/wire.ts
19938
- var SealedValue = external_exports.string().max(8e3).regex(SEALED_PATTERN);
19950
+ var SealedValue = external_exports.string().max(64e3).regex(SEALED_PATTERN);
19939
19951
  var id = external_exports.string().min(1).max(200);
19940
19952
  var SignalSchema = external_exports.object({
19941
19953
  source: AgentSource,
@@ -20012,13 +20024,17 @@ function removeCloudLogin(home = bitlHome()) {
20012
20024
  rmSync(cloudConfigPath(home), { force: true });
20013
20025
  rmSync(cloudKeyPath(home), { force: true });
20014
20026
  }
20027
+ function clientVersionHeader() {
20028
+ const v = "0.1.4";
20029
+ return v ? { "x-bitl-client": v } : {};
20030
+ }
20015
20031
  function resolveTarget(home = bitlHome()) {
20016
20032
  const cloud = readCloudConfig(home);
20017
20033
  if (cloud) {
20018
20034
  return {
20019
20035
  kind: "cloud",
20020
20036
  url: cloud.url.replace(/\/+$/, ""),
20021
- headers: { authorization: `Bearer ${cloud.apiKey}` },
20037
+ headers: { authorization: `Bearer ${cloud.apiKey}`, ...clientVersionHeader() },
20022
20038
  keys: () => keysFromBase64Url(readFileSync2(cloudKeyPath(home), "utf8"))
20023
20039
  };
20024
20040
  }
@@ -20037,13 +20053,181 @@ var MAX_TRANSCRIPT_BYTES2 = 20 * 1024 * 1024;
20037
20053
  var DEFAULT_APPROVAL_WAIT_MS = 10 * 6e4;
20038
20054
 
20039
20055
  // ../src/index.ts
20040
- import { readFileSync as readFileSync4 } from "node:fs";
20056
+ import { readFileSync as readFileSync5 } from "node:fs";
20041
20057
 
20042
20058
  // ../src/install.ts
20043
20059
  import { copyFileSync, existsSync, mkdirSync as mkdirSync3, readdirSync, readFileSync as readFileSync3, writeFileSync as writeFileSync3 } from "node:fs";
20044
20060
  import { homedir as homedir2 } from "node:os";
20045
20061
  import { dirname as dirname3, join as join3, resolve } from "node:path";
20046
20062
  import { fileURLToPath } from "node:url";
20063
+
20064
+ // ../src/i18n.ts
20065
+ var ko = {
20066
+ "usage.title": "bitl \u2014 AI \uC5D0\uC774\uC804\uD2B8 \uC791\uC5C5 \uD604\uD669\uD310 (https://usebitl.com)",
20067
+ "update.available": "\u2191 bitl {latest} \uAC00 \uB098\uC654\uC2B5\uB2C8\uB2E4 (\uC9C0\uAE08 {current}) \u2014 npm i -g @usebitl/cli",
20068
+ "update.changelog": " \uBC14\uB010 \uC810: https://usebitl.com/changelog",
20069
+ "usage.start": "\uC11C\uBC84 \uC2DC\uC791 (http://127.0.0.1:7777)",
20070
+ "usage.status": "\uD604\uC7AC \uC138\uC158 \uC694\uC57D (\uC774 PC \uC758 \uD0A4\uB85C \uBCF5\uD638\uD654)",
20071
+ "usage.pair": "\uBE0C\uB77C\uC6B0\uC800\uC5D0 \uC554\uD638\uD654 \uD0A4\uB97C \uB118\uAE30\uB294 \uB9C1\uD06C (\uBE0C\uB77C\uC6B0\uC800\xB7\uC8FC\uC18C\uB9C8\uB2E4 \uD55C \uBC88)",
20072
+ "usage.pairArgs": "[--url \uC8FC\uC18C]",
20073
+ "usage.loginArgsDefault": "[--url <\uC8FC\uC18C>] [--name \uC774\uB984] [--no-browser]",
20074
+ "usage.loginArgs": "--url <\uC8FC\uC18C> [--name \uC774\uB984] [--no-browser]",
20075
+ "usage.loginDefault": "\uC774 PC \uB97C \uACC4\uC815\uC5D0 \uC5F0\uACB0 (\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC2B9\uC778, \uAE30\uBCF8 {url})",
20076
+ "usage.login": "\uC774 PC \uB97C \uD074\uB77C\uC6B0\uB4DC \uACC4\uC815\uC5D0 \uC5F0\uACB0 (\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC2B9\uC778)",
20077
+ "usage.logoutCloud": "\uC5F0\uACB0 \uD574\uC81C",
20078
+ "usage.logout": "\uC5F0\uACB0 \uD574\uC81C \u2192 \uB2E4\uC2DC \uB85C\uCEEC \uC11C\uBC84\uB85C",
20079
+ "usage.installClaude": "Claude Code hook \uB4F1\uB85D (\uAE30\uBCF8: ~/.claude/settings.json)",
20080
+ "usage.installCodex": "Codex hook \uB4F1\uB85D (~/.codex/config.toml)",
20081
+ "usage.installAgy": "Antigravity hook \uB4F1\uB85D (~/.gemini/config/hooks.json, CLI\xB7IDE \uACF5\uC6A9)",
20082
+ "usage.installDesktop": "Claude Desktop \uC5D0 MCP \uC11C\uBC84 \uB4F1\uB85D",
20083
+ "usage.remote": "\uC6D0\uACA9 \uC2B9\uC778: \uCF1C\uBA74 Claude Code \uC758 \uAD8C\uD55C \uC694\uCCAD\uC744 \uD734\uB300\uD3F0\xB7\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uD5C8\uC6A9\xB7\uAC70\uBD80",
20084
+ "usage.remote2": "\u2014 \uD130\uBBF8\uB110\xB7\uBE0C\uB77C\uC6B0\uC800\xB7\uD734\uB300\uD3F0 \uC911 \uBA3C\uC800 \uB2F5\uD55C \uCABD\uC774 \uC801\uC6A9\uB41C\uB2E4 (\uD3F0\uC758 \uB2F5\uC740 \uCD5C\uB300 10\uBD84 \uAE30\uB2E4\uB9BC)",
20085
+ "err.optionValue": "{name} \uB4A4\uC5D0 \uAC12\uC744 \uC9C0\uC815\uD558\uC138\uC694",
20086
+ "err.cloudUnreachable": "\uD074\uB77C\uC6B0\uB4DC \uC11C\uBC84\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 ({url})",
20087
+ "err.localUnreachable": "\uC11C\uBC84\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 ({url}). bitl start \uB85C \uC2DC\uC791\uD558\uC138\uC694.",
20088
+ "err.revoked": "\uC774 PC \uC758 \uC5F0\uACB0\uC774 \uB04A\uACBC\uC2B5\uB2C8\uB2E4 (\uAE30\uAE30\uAC00 \uC81C\uAC70\uB428). bitl logout \uD6C4 bitl login \uC73C\uB85C \uB2E4\uC2DC \uC5F0\uACB0\uD558\uC138\uC694.",
20089
+ "err.remoteUsage": "\uC0AC\uC6A9\uBC95: bitl remote [on|off]",
20090
+ "err.remoteUnsupported": "\uC774 \uC11C\uBC84\uB294 \uC6D0\uACA9 \uC2B9\uC778\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 (\uC11C\uBC84\uB97C \uC0C8 \uBC84\uC804\uC73C\uB85C \uC5C5\uB370\uC774\uD2B8\uD558\uC138\uC694)",
20091
+ "err.noDesktop": "claude-desktop(\uB85C\uCEEC MCP)\uC740 \uC774 \uD328\uD0A4\uC9C0\uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4. claude.ai \uCEE4\uB125\uD130\uB97C \uC4F0\uC138\uC694: https://usebitl.com/app",
20092
+ "err.unknownTarget": "\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uB300\uC0C1: {target} \u2014 {list}",
20093
+ "err.none": "(\uC5C6\uC74C)",
20094
+ "err.noStart": "bitl start(\uB85C\uCEEC \uC11C\uBC84)\uB294 \uC774 \uD328\uD0A4\uC9C0\uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4. https://usebitl.com \uC5D0\uC11C \uC4F0\uC138\uC694.",
20095
+ "err.loginUrl": "\uC5F0\uACB0\uD560 \uC11C\uBE44\uC2A4 \uC8FC\uC18C\uB97C \uC9C0\uC815\uD558\uC138\uC694: bitl login --url https://\u2026",
20096
+ "err.agySpace": "Antigravity \uB294 \uACF5\uBC31\uC774 \uC788\uB294 \uACBD\uB85C\uB97C \uC2E4\uD589\uD558\uC9C0 \uBABB\uD569\uB2C8\uB2E4: {path}",
20097
+ "pair.intro": "\uC774 \uB9C1\uD06C\uB97C \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uD55C \uBC88 \uC5F4\uBA74 \uADF8 \uBE0C\uB77C\uC6B0\uC800\uAC00 \uD0A4\uB97C \uAE30\uC5B5\uD569\uB2C8\uB2E4 (\uB2E4\uB978 \uC0AC\uB78C\uC5D0\uAC8C \uBCF4\uB0B4\uC9C0 \uB9C8\uC138\uC694):",
20098
+ "pair.otherUrl": " BITL \uC744 \uB2E4\uB978 \uC8FC\uC18C\uB85C \uC5F0\uB2E4\uBA74 \uADF8 \uC8FC\uC18C\uB85C: bitl pair --url http://localhost:7788",
20099
+ "pair.cloud": ' \uD074\uB77C\uC6B0\uB4DC \uACC4\uC815\uC740 \uBCF4\uD1B5 \uC6F9\uC758 "\uAE30\uAE30" \u2192 "\uAE30\uAE30 \uCD94\uAC00"(QR) \uB85C \uD0A4\uB97C \uB118\uAE41\uB2C8\uB2E4. \uC774 \uB9C1\uD06C\uB294 \uC608\uBE44 \uBC29\uBC95\uC785\uB2C8\uB2E4.',
20100
+ "pair.keyFile": " \uD0A4 \uD30C\uC77C: {path} \u2014 \uC9C0\uC6B0\uBA74 \uC774\uC804 \uAE30\uB85D\uC744 \uBCFC \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.",
20101
+ "status.cloud": "(\uD074\uB77C\uC6B0\uB4DC \uACC4\uC815: {url})",
20102
+ "status.none": "\uC9C4\uD589 \uC911\uC778 \uC138\uC158 \uC5C6\uC74C",
20103
+ "remote.on": "\uC6D0\uACA9 \uC2B9\uC778: \uCF1C\uC9D0 \u2014 Claude Code \uC758 \uAD8C\uD55C \uC694\uCCAD\uC774 \uD734\uB300\uD3F0\xB7\uBE0C\uB77C\uC6B0\uC800\uB85C \uAC11\uB2C8\uB2E4 (\uD654\uBA74\xB7\uC54C\uB9BC\uC5D0\uC11C \uD5C8\uC6A9\xB7\uAC70\uBD80)",
20104
+ "remote.off": "\uC6D0\uACA9 \uC2B9\uC778: \uAEBC\uC9D0 \u2014 \uAD8C\uD55C \uC694\uCCAD\uC740 \uD130\uBBF8\uB110\uC5D0\uC11C \uC2B9\uC778\uD569\uB2C8\uB2E4",
20105
+ "remote.needHook": " hook \uC774 \uC5C6\uC73C\uBA74 \uB3D9\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: bitl install claude \uB97C \uD55C \uBC88 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694 (\uC6D0\uACA9 \uC2B9\uC778 hook \uCD94\uAC00)",
20106
+ "install.adapter": "\uC5B4\uB311\uD130: {path}",
20107
+ "install.codexTrust": "\uC544\uC9C1 \uB3D9\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: Codex \uB97C \uC5F4\uACE0 /hooks \uC5D0\uC11C bitl hook \uC744 \uC2E0\uB8B0(trust)\uD558\uC138\uC694.",
20108
+ "install.agyRestart": "\uC2E4\uD589 \uC911\uC778 agy \uB294 \uB2E4\uC2DC \uC2DC\uC791\uD574\uC57C \uC801\uC6A9\uB429\uB2C8\uB2E4.",
20109
+ "install.mcp": "MCP \uC11C\uBC84: {path}",
20110
+ "install.desktopRestart": "Claude Desktop \uC744 \uC7AC\uC2DC\uC791\uD574\uC57C \uC801\uC6A9\uB429\uB2C8\uB2E4.",
20111
+ "install.unchanged": "\uBCC0\uACBD \uC5C6\uC74C: {file}",
20112
+ "install.added": "\uB4F1\uB85D \uC644\uB8CC: {file}",
20113
+ "install.removed": "\uC81C\uAC70 \uC644\uB8CC: {file}",
20114
+ "install.backup": " \uBC31\uC5C5: {path}",
20115
+ "start.pair": " \uBE0C\uB77C\uC6B0\uC800 \uC5F0\uACB0(\uCC98\uC74C \uD55C \uBC88): {url}",
20116
+ "login.unreachable": "\uC11C\uBC84\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 ({where}).",
20117
+ "login.unreachableHint": ' \uC11C\uBC84\uAC00 \uCF1C\uC838 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694 \u2014 \uBE0C\uB77C\uC6B0\uC800\uB85C {origin}/api/health \uB97C \uC5F4\uBA74 {"ok":true} \uAC00 \uBCF4\uC5EC\uC57C \uD569\uB2C8\uB2E4.',
20118
+ "login.already": "\uC774\uBBF8 \uC5F0\uACB0\uB3FC \uC788\uC2B5\uB2C8\uB2E4: {url} ({name}). \uB2E4\uC2DC \uC5F0\uACB0\uD558\uB824\uBA74 \uBA3C\uC800 bitl logout",
20119
+ "login.notBitl": "{url} \uB294 \uD074\uB77C\uC6B0\uB4DC \uBAA8\uB4DC BITL \uC11C\uBC84\uAC00 \uC544\uB2D9\uB2C8\uB2E4 (\uAE30\uAE30 \uC5F0\uACB0 API \uAC00 \uC5C6\uC74C)",
20120
+ "login.tooMany": "\uC5F0\uACB0 \uC694\uCCAD\uC774 \uB108\uBB34 \uB9CE\uC2B5\uB2C8\uB2E4. \uC7A0\uC2DC \uB4A4 \uB2E4\uC2DC \uD558\uC138\uC694",
20121
+ "login.cannotStart": "\uC5F0\uACB0\uC744 \uC2DC\uC791\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 ({status})",
20122
+ "login.approve": "\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC774 PC \uC758 \uC5F0\uACB0\uC744 \uC2B9\uC778\uD558\uC138\uC694:",
20123
+ "login.manual": " (\uBE0C\uB77C\uC6B0\uC800\uAC00 \uC5F4\uB9AC\uC9C0 \uC54A\uC73C\uBA74 \uC704 \uC8FC\uC18C\uB97C \uC9C1\uC811 \uC5EC\uC138\uC694. {min}\uBD84 \uC548\uC5D0)",
20124
+ "login.expired": "\uC5F0\uACB0 \uC694\uCCAD\uC774 \uB9CC\uB8CC\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC bitl login \uD558\uC138\uC694",
20125
+ "login.timeout": "\uC2DC\uAC04 \uC548\uC5D0 \uC2B9\uC778\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC bitl login \uD558\uC138\uC694",
20126
+ "login.denied": "\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F0\uACB0\uC744 \uAC70\uC808\uD588\uC2B5\uB2C8\uB2E4",
20127
+ "login.noResult": "\uC2B9\uC778 \uACB0\uACFC\uB97C \uBC1B\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC bitl login \uD558\uC138\uC694",
20128
+ "login.badSignature": "\uACBD\uACE0: \uC2B9\uC778\uD55C \uBE0C\uB77C\uC6B0\uC800\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC5B4 \uC5F0\uACB0\uC744 \uC911\uB2E8\uD588\uC2B5\uB2C8\uB2E4 (\uACF5\uAC1C\uD0A4 \uC11C\uBA85\uC774 \uB9DE\uC9C0 \uC54A\uC74C)",
20129
+ "login.noKeyBrowser": "\uC774 \uACC4\uC815\uC758 \uD0A4\uAC00 \uC5C6\uB294 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC2B9\uC778\uD588\uC2B5\uB2C8\uB2E4. \uCE74\uB4DC \uB0B4\uC6A9\uC774 \uBCF4\uC774\uB294 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC2B9\uC778\uD558\uB3C4\uB85D \uB2E4\uC2DC bitl login \uD558\uC138\uC694",
20130
+ "login.keyMismatch": "\uACC4\uC815\uC5D0 \uC774\uBBF8 \uB2E4\uB978 \uD0A4\uAC00 \uC788\uC2B5\uB2C8\uB2E4. \uCE74\uB4DC \uB0B4\uC6A9\uC774 \uBCF4\uC774\uB294 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC2B9\uC778\uD558\uC138\uC694",
20131
+ "login.deliverFailed": "\uD0A4\uB97C \uB118\uAE30\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4 ({status})",
20132
+ "login.connected": "\uC5F0\uACB0\uB428: \uC774 PC({name})\uC758 \uC5D0\uC774\uC804\uD2B8 \uC791\uC5C5\uC774 {web} \uACC4\uC815\uC73C\uB85C \uAC11\uB2C8\uB2E4{via}.",
20133
+ "login.via": " (\uBCF4\uB0B4\uB294 \uC8FC\uC18C: {api})",
20134
+ "login.next": " hook \uC774 \uC544\uC9C1 \uC5C6\uB2E4\uBA74: bitl install claude",
20135
+ "logout.notConnected": "\uD074\uB77C\uC6B0\uB4DC \uACC4\uC815\uC5D0 \uC5F0\uACB0\uB3FC \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 (\uB85C\uCEEC \uBAA8\uB4DC).",
20136
+ "logout.done": "\uC5F0\uACB0 \uD574\uC81C: {url} ({name}). \uC774\uC81C \uC774 PC \uC758 \uB85C\uCEEC \uC11C\uBC84\uB85C \uBCF4\uB0C5\uB2C8\uB2E4.",
20137
+ "logout.doneCloud": "\uC5F0\uACB0 \uD574\uC81C: {url} ({name}). \uC774 PC \uC758 \uC5D0\uC774\uC804\uD2B8 \uC791\uC5C5\uC740 \uB354 \uC774\uC0C1 \uBCF4\uB0B4\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."
20138
+ };
20139
+ var en = {
20140
+ "usage.title": "bitl \u2014 all your AI coding agents in one place (https://usebitl.com)",
20141
+ "update.available": "\u2191 bitl {latest} is available (you have {current}) \u2014 npm i -g @usebitl/cli",
20142
+ "update.changelog": " What changed: https://usebitl.com/changelog",
20143
+ "usage.start": "Start the server (http://127.0.0.1:7777)",
20144
+ "usage.status": "Summary of current sessions (decrypted with this PC\u2019s key)",
20145
+ "usage.pair": "Link that hands the encryption key to a browser (once per browser and address)",
20146
+ "usage.pairArgs": "[--url URL]",
20147
+ "usage.loginArgsDefault": "[--url <URL>] [--name NAME] [--no-browser]",
20148
+ "usage.loginArgs": "--url <URL> [--name NAME] [--no-browser]",
20149
+ "usage.loginDefault": "Connect this PC to your account (approve in the browser; default {url})",
20150
+ "usage.login": "Connect this PC to your cloud account (approve in the browser)",
20151
+ "usage.logoutCloud": "Disconnect",
20152
+ "usage.logout": "Disconnect \u2192 back to the local server",
20153
+ "usage.installClaude": "Add Claude Code hooks (default: ~/.claude/settings.json)",
20154
+ "usage.installCodex": "Add Codex hooks (~/.codex/config.toml)",
20155
+ "usage.installAgy": "Add Antigravity hooks (~/.gemini/config/hooks.json, shared by CLI and IDE)",
20156
+ "usage.installDesktop": "Add the MCP server to Claude Desktop",
20157
+ "usage.remote": "Remote approval: when on, allow or deny Claude Code permission requests from your phone or browser",
20158
+ "usage.remote2": "\u2014 whichever of terminal, browser or phone answers first wins (waits up to 10 minutes for the phone)",
20159
+ "err.optionValue": "Give a value after {name}",
20160
+ "err.cloudUnreachable": "Can't reach the cloud server ({url})",
20161
+ "err.localUnreachable": "Can't reach the server ({url}). Start it with bitl start.",
20162
+ "err.revoked": "This PC was disconnected (the device was removed). Run bitl logout, then bitl login to connect again.",
20163
+ "err.remoteUsage": "Usage: bitl remote [on|off]",
20164
+ "err.remoteUnsupported": "This server doesn't support remote approval (update the server to a newer version)",
20165
+ "err.noDesktop": "claude-desktop (local MCP) is not in this package. Use the claude.ai connector: https://usebitl.com/app",
20166
+ "err.unknownTarget": "Unsupported target: {target} \u2014 {list}",
20167
+ "err.none": "(none)",
20168
+ "err.noStart": "bitl start (local server) is not in this package. Use https://usebitl.com.",
20169
+ "err.loginUrl": "Give the service URL to connect to: bitl login --url https://\u2026",
20170
+ "err.agySpace": "Antigravity can't run a path that contains spaces: {path}",
20171
+ "pair.intro": "Open this link once in a browser and that browser remembers the key (do not share it):",
20172
+ "pair.otherUrl": " If you open BITL at another address, use it: bitl pair --url http://localhost:7788",
20173
+ "pair.cloud": ' Cloud accounts usually hand over the key on the web with "Devices" \u2192 "Add device" (QR). This link is a fallback.',
20174
+ "pair.keyFile": " Key file: {path} \u2014 deleting it makes your earlier history unreadable.",
20175
+ "status.cloud": "(cloud account: {url})",
20176
+ "status.none": "No active sessions",
20177
+ "remote.on": "Remote approval: on \u2014 Claude Code permission requests go to your phone and browser (allow or deny on screen or from notifications)",
20178
+ "remote.off": "Remote approval: off \u2014 approve permission requests in the terminal",
20179
+ "remote.needHook": " It won't work without the hook: run bitl install claude once more (adds the remote approval hook)",
20180
+ "install.adapter": "Adapter: {path}",
20181
+ "install.codexTrust": "Not active yet: open Codex and trust the bitl hooks in /hooks.",
20182
+ "install.agyRestart": "Restart any running agy for this to take effect.",
20183
+ "install.mcp": "MCP server: {path}",
20184
+ "install.desktopRestart": "Restart Claude Desktop for this to take effect.",
20185
+ "install.unchanged": "No change: {file}",
20186
+ "install.added": "Added: {file}",
20187
+ "install.removed": "Removed: {file}",
20188
+ "install.backup": " Backup: {path}",
20189
+ "start.pair": " Connect a browser (first time only): {url}",
20190
+ "login.unreachable": "Can't reach the server ({where}).",
20191
+ "login.unreachableHint": ' Check that the server is running \u2014 opening {origin}/api/health in a browser should show {"ok":true}.',
20192
+ "login.already": "Already connected: {url} ({name}). To connect again, run bitl logout first",
20193
+ "login.notBitl": "{url} isn't a cloud-mode BITL server (no device connection API)",
20194
+ "login.tooMany": "Too many connection requests. Try again in a moment",
20195
+ "login.cannotStart": "Couldn't start connecting ({status})",
20196
+ "login.approve": "Approve connecting this PC in your browser:",
20197
+ "login.manual": " (If the browser doesn't open, open the URL above yourself within {min} min)",
20198
+ "login.expired": "The connection request expired. Run bitl login again",
20199
+ "login.timeout": "It wasn't approved in time. Run bitl login again",
20200
+ "login.denied": "The connection was denied in the browser",
20201
+ "login.noResult": "Didn't receive the approval result. Run bitl login again",
20202
+ "login.badSignature": "Warning: couldn't verify the approving browser, so the connection was stopped (public key signature mismatch)",
20203
+ "login.noKeyBrowser": "You approved from a browser that doesn't have this account's key. Run bitl login again and approve in a browser that shows card contents",
20204
+ "login.keyMismatch": "This account already has a different key. Approve in a browser that shows card contents",
20205
+ "login.deliverFailed": "Couldn't hand over the key ({status})",
20206
+ "login.connected": "Connected: agent work on this PC ({name}) now goes to your account at {web}{via}.",
20207
+ "login.via": " (sending to {api})",
20208
+ "login.next": " If you have no hooks yet: bitl install claude",
20209
+ "logout.notConnected": "Not connected to a cloud account (local mode).",
20210
+ "logout.done": "Disconnected: {url} ({name}). This PC now sends to its local server.",
20211
+ "logout.doneCloud": "Disconnected: {url} ({name}). Agent work on this PC is no longer sent."
20212
+ };
20213
+ var DICT = { ko, en };
20214
+ function detectLang(env = process.env, systemLocale = Intl.DateTimeFormat().resolvedOptions().locale) {
20215
+ const forced = env.BITL_LANG?.trim().toLowerCase();
20216
+ if (forced === "ko" || forced === "en") return forced;
20217
+ for (const v of [env.LC_ALL, env.LC_MESSAGES, env.LANG]) {
20218
+ const s = v?.trim();
20219
+ if (!s || s === "C" || s === "POSIX" || s.startsWith("C.")) continue;
20220
+ return s.toLowerCase().startsWith("ko") ? "ko" : "en";
20221
+ }
20222
+ return systemLocale.toLowerCase().startsWith("ko") ? "ko" : "en";
20223
+ }
20224
+ var lang = () => detectLang();
20225
+ function t(key, vars) {
20226
+ const text = DICT[lang()][key] ?? ko[key];
20227
+ return vars ? text.replace(/\{(\w+)\}/g, (m, k) => k in vars ? String(vars[k]) : m) : text;
20228
+ }
20229
+
20230
+ // ../src/install.ts
20047
20231
  var CLAUDE_EVENTS = [
20048
20232
  "SessionStart",
20049
20233
  "SessionEnd",
@@ -20131,9 +20315,9 @@ var codexConfigPath = () => join3(process.env.CODEX_HOME ?? join3(homedir2(), ".
20131
20315
  function removeCodexBlock(toml) {
20132
20316
  const sections = [[]];
20133
20317
  for (const line of toml.split("\n")) {
20134
- const t = line.trim();
20135
- if (t === CODEX_BEGIN || t === CODEX_END) continue;
20136
- if (t.startsWith("[")) sections.push([]);
20318
+ const t2 = line.trim();
20319
+ if (t2 === CODEX_BEGIN || t2 === CODEX_END) continue;
20320
+ if (t2.startsWith("[")) sections.push([]);
20137
20321
  sections[sections.length - 1].push(line);
20138
20322
  }
20139
20323
  const header = (sec) => sec[0]?.trim() ?? "";
@@ -20163,7 +20347,7 @@ var ANTIGRAVITY_TOOL_EVENTS = /* @__PURE__ */ new Set(["PreToolUse", "PostToolUs
20163
20347
  var ANTIGRAVITY_HOOK_NAME = "bitl";
20164
20348
  var antigravityHooksPath = () => join3(homedir2(), ".gemini", "config", "hooks.json");
20165
20349
  function addAntigravityHooks(config2, adapter = ADAPTER_PATH) {
20166
- if (/\s/.test(adapter)) throw new Error(`Antigravity \uB294 \uACF5\uBC31\uC774 \uC788\uB294 \uACBD\uB85C\uB97C \uC2E4\uD589\uD558\uC9C0 \uBABB\uD569\uB2C8\uB2E4: ${adapter}`);
20350
+ if (/\s/.test(adapter)) throw new Error(t("err.agySpace", { path: adapter }));
20167
20351
  const group = { enabled: true };
20168
20352
  for (const event of ANTIGRAVITY_EVENTS) {
20169
20353
  const handler = { type: "command", command: `node ${adapter} --source antigravity --event ${event}`, timeout: 10 };
@@ -20213,8 +20397,8 @@ async function postJson(url2, body, headers = {}) {
20213
20397
  const origin = new URL(url2).origin;
20214
20398
  const code = err.cause?.code;
20215
20399
  throw new Error(
20216
- `\uC11C\uBC84\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (${origin}${code ? `, ${code}` : ""}).
20217
- \uC11C\uBC84\uAC00 \uCF1C\uC838 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694 \u2014 \uBE0C\uB77C\uC6B0\uC800\uB85C ${origin}/api/health \uB97C \uC5F4\uBA74 {"ok":true} \uAC00 \uBCF4\uC5EC\uC57C \uD569\uB2C8\uB2E4.`
20400
+ `${t("login.unreachable", { where: `${origin}${code ? `, ${code}` : ""}` })}
20401
+ ${t("login.unreachableHint", { origin })}`
20218
20402
  );
20219
20403
  });
20220
20404
  return { status: res.status, json: await res.json().catch(() => ({})) };
@@ -20234,45 +20418,45 @@ function openBrowser(url2) {
20234
20418
  async function login(url2, name = hostname3(), opts = {}) {
20235
20419
  const base = url2.trim().replace(/\/+$/, "");
20236
20420
  const existing = readCloudConfig();
20237
- if (existing) throw new Error(`\uC774\uBBF8 \uC5F0\uACB0\uB3FC \uC788\uC2B5\uB2C8\uB2E4: ${existing.url} (${existing.name}). \uB2E4\uC2DC \uC5F0\uACB0\uD558\uB824\uBA74 \uBA3C\uC800 bitl logout`);
20421
+ if (existing) throw new Error(t("login.already", { url: existing.url, name: existing.name }));
20238
20422
  const secret = generatePairingSecret();
20239
20423
  const kp = await generateDeviceKeyPair(false);
20240
20424
  const mac3 = await signPublicKey(secret, "initiator", kp.publicKey);
20241
20425
  const start = await postJson(`${base}/api/pairing/start`, { kind: "cli", name, publicKey: kp.publicKey, mac: mac3 });
20242
- if (start.status === 404) throw new Error(`${base} \uB294 \uD074\uB77C\uC6B0\uB4DC \uBAA8\uB4DC BITL \uC11C\uBC84\uAC00 \uC544\uB2D9\uB2C8\uB2E4 (\uAE30\uAE30 \uC5F0\uACB0 API \uAC00 \uC5C6\uC74C)`);
20243
- if (start.status === 429) throw new Error("\uC5F0\uACB0 \uC694\uCCAD\uC774 \uB108\uBB34 \uB9CE\uC2B5\uB2C8\uB2E4. \uC7A0\uC2DC \uB4A4 \uB2E4\uC2DC \uD558\uC138\uC694");
20244
- if (start.status !== 200) throw new Error(`\uC5F0\uACB0\uC744 \uC2DC\uC791\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (${start.status})`);
20426
+ if (start.status === 404) throw new Error(t("login.notBitl", { url: base }));
20427
+ if (start.status === 429) throw new Error(t("login.tooMany"));
20428
+ if (start.status !== 200) throw new Error(t("login.cannotStart", { status: start.status }));
20245
20429
  const { id: id2, pollToken, expiresAt, intervalMs, webUrl, apiUrl } = start.json;
20246
20430
  const web = (webUrl ?? base).replace(/\/+$/, "");
20247
20431
  const api = (apiUrl ?? base).replace(/\/+$/, "");
20248
20432
  const link = `${web}/link?p=${encodeURIComponent(id2)}#s=${secret}`;
20249
- console.log("\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC774 PC \uC758 \uC5F0\uACB0\uC744 \uC2B9\uC778\uD558\uC138\uC694:");
20433
+ console.log(t("login.approve"));
20250
20434
  console.log(` ${link}`);
20251
- console.log(` (\uBE0C\uB77C\uC6B0\uC800\uAC00 \uC5F4\uB9AC\uC9C0 \uC54A\uC73C\uBA74 \uC704 \uC8FC\uC18C\uB97C \uC9C1\uC811 \uC5EC\uC138\uC694. ${Math.round((Date.parse(expiresAt) - Date.now()) / 6e4)}\uBD84 \uC548\uC5D0)`);
20435
+ console.log(t("login.manual", { min: Math.round((Date.parse(expiresAt) - Date.now()) / 6e4) }));
20252
20436
  if (opts.openBrowser !== false) openBrowser(link);
20253
20437
  let view;
20254
20438
  while (Date.now() < Date.parse(expiresAt)) {
20255
20439
  await sleep(intervalMs || 2e3);
20256
20440
  const r = await postJson(`${base}/api/pairing/${encodeURIComponent(id2)}/poll`, { pollToken }).catch(() => void 0);
20257
20441
  if (!r) continue;
20258
- if (r.status === 404) throw new Error("\uC5F0\uACB0 \uC694\uCCAD\uC774 \uB9CC\uB8CC\uB410\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC bitl login \uD558\uC138\uC694");
20442
+ if (r.status === 404) throw new Error(t("login.expired"));
20259
20443
  view = r.json;
20260
20444
  if (view.status !== "pending") break;
20261
20445
  }
20262
- if (!view || view.status === "pending") throw new Error("\uC2DC\uAC04 \uC548\uC5D0 \uC2B9\uC778\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC bitl login \uD558\uC138\uC694");
20263
- if (view.status === "denied") throw new Error("\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC5F0\uACB0\uC744 \uAC70\uC808\uD588\uC2B5\uB2C8\uB2E4");
20446
+ if (!view || view.status === "pending") throw new Error(t("login.timeout"));
20447
+ if (view.status === "denied") throw new Error(t("login.denied"));
20264
20448
  const apiKey = view.device?.apiKey;
20265
- if (!view.device || !view.peer) throw new Error("\uC2B9\uC778 \uACB0\uACFC\uB97C \uBC1B\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC bitl login \uD558\uC138\uC694");
20449
+ if (!view.device || !view.peer) throw new Error(t("login.noResult"));
20266
20450
  if (!await verifyPublicKey(secret, "responder", view.peer.publicKey, view.peer.mac)) {
20267
20451
  await revokeSelf(base, apiKey);
20268
- throw new Error("\uACBD\uACE0: \uC2B9\uC778\uD55C \uBE0C\uB77C\uC6B0\uC800\uB97C \uD655\uC778\uD560 \uC218 \uC5C6\uC5B4 \uC5F0\uACB0\uC744 \uC911\uB2E8\uD588\uC2B5\uB2C8\uB2E4 (\uACF5\uAC1C\uD0A4 \uC11C\uBA85\uC774 \uB9DE\uC9C0 \uC54A\uC74C)");
20452
+ throw new Error(t("login.badSignature"));
20269
20453
  }
20270
20454
  let masterB64;
20271
20455
  if (view.wrapped) {
20272
20456
  masterB64 = toBase64Url(await unwrapMasterKey(view.wrapped, kp.privateKey, view.peer.publicKey, id2));
20273
20457
  } else if (view.accountKeyId) {
20274
20458
  await revokeSelf(base, apiKey);
20275
- throw new Error("\uC774 \uACC4\uC815\uC758 \uD0A4\uAC00 \uC5C6\uB294 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC2B9\uC778\uD588\uC2B5\uB2C8\uB2E4. \uCE74\uB4DC \uB0B4\uC6A9\uC774 \uBCF4\uC774\uB294 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC2B9\uC778\uD558\uB3C4\uB85D \uB2E4\uC2DC bitl login \uD558\uC138\uC694");
20459
+ throw new Error(t("login.noKeyBrowser"));
20276
20460
  } else {
20277
20461
  masterB64 = loadOrCreateMasterKey();
20278
20462
  const master = fromBase64Url(masterB64);
@@ -20281,50 +20465,97 @@ async function login(url2, name = hostname3(), opts = {}) {
20281
20465
  const d = await postJson(`${base}/api/pairing/${encodeURIComponent(id2)}/initiator-deliver`, { pollToken, wrapped, keyId: keys.kid });
20282
20466
  if (d.status !== 200) {
20283
20467
  await revokeSelf(base, apiKey);
20284
- throw new Error(d.json.error === "key-mismatch" ? "\uACC4\uC815\uC5D0 \uC774\uBBF8 \uB2E4\uB978 \uD0A4\uAC00 \uC788\uC2B5\uB2C8\uB2E4. \uCE74\uB4DC \uB0B4\uC6A9\uC774 \uBCF4\uC774\uB294 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC2B9\uC778\uD558\uC138\uC694" : `\uD0A4\uB97C \uB118\uAE30\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4 (${d.status})`);
20468
+ throw new Error(d.json.error === "key-mismatch" ? t("login.keyMismatch") : t("login.deliverFailed", { status: d.status }));
20285
20469
  }
20286
20470
  }
20287
20471
  saveCloudLogin({ url: api, deviceId: view.device.id, apiKey: view.device.apiKey, name }, masterB64);
20288
20472
  console.log(`
20289
- \uC5F0\uACB0\uB428: \uC774 PC(${name})\uC758 \uC5D0\uC774\uC804\uD2B8 \uC791\uC5C5\uC774 ${web} \uACC4\uC815\uC73C\uB85C \uAC11\uB2C8\uB2E4${api !== web ? ` (\uBCF4\uB0B4\uB294 \uC8FC\uC18C: ${api})` : ""}.`);
20290
- console.log(" hook \uC774 \uC544\uC9C1 \uC5C6\uB2E4\uBA74: bitl install claude");
20473
+ ${t("login.connected", { name, web, via: api !== web ? t("login.via", { api }) : "" })}`);
20474
+ console.log(t("login.next"));
20291
20475
  }
20292
20476
  async function logout() {
20293
20477
  const cfg = readCloudConfig();
20294
- if (!cfg) return console.log("\uD074\uB77C\uC6B0\uB4DC \uACC4\uC815\uC5D0 \uC5F0\uACB0\uB3FC \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 (\uB85C\uCEEC \uBAA8\uB4DC).");
20478
+ if (!cfg) return console.log(t("logout.notConnected"));
20295
20479
  await revokeSelf(cfg.url, cfg.apiKey);
20296
20480
  removeCloudLogin();
20297
- console.log(`\uC5F0\uACB0 \uD574\uC81C: ${cfg.url} (${cfg.name}). \uC774\uC81C \uC774 PC \uC758 \uB85C\uCEEC \uC11C\uBC84\uB85C \uBCF4\uB0C5\uB2C8\uB2E4.`);
20481
+ console.log(t(true ? "logout.doneCloud" : "logout.done", { url: cfg.url, name: cfg.name }));
20482
+ }
20483
+
20484
+ // ../src/update.ts
20485
+ import { mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "node:fs";
20486
+ import { join as join4 } from "node:path";
20487
+ var REGISTRY = "https://registry.npmjs.org/@usebitl/cli/latest";
20488
+ var DAY = 864e5;
20489
+ var TIMEOUT_MS = 1e3;
20490
+ var cachePath = () => join4(bitlHome(), "update-check.json");
20491
+ function readCache() {
20492
+ try {
20493
+ return JSON.parse(readFileSync4(cachePath(), "utf8"));
20494
+ } catch {
20495
+ return null;
20496
+ }
20497
+ }
20498
+ async function fetchLatest() {
20499
+ try {
20500
+ const res = await fetch(REGISTRY, { signal: AbortSignal.timeout(TIMEOUT_MS), headers: { accept: "application/json" } });
20501
+ if (!res.ok) return void 0;
20502
+ const v = (await res.json()).version;
20503
+ return typeof v === "string" && VERSION_PATTERN.test(v) ? v : void 0;
20504
+ } catch {
20505
+ return void 0;
20506
+ }
20507
+ }
20508
+ async function latestVersion(now = Date.now()) {
20509
+ const cache = readCache();
20510
+ if (cache && now - Date.parse(cache.checkedAt) < DAY) return cache.latest;
20511
+ const latest = await fetchLatest() ?? cache?.latest;
20512
+ try {
20513
+ mkdirSync4(bitlHome(), { recursive: true });
20514
+ writeFileSync4(cachePath(), JSON.stringify({ checkedAt: new Date(now).toISOString(), latest }) + "\n");
20515
+ } catch {
20516
+ }
20517
+ return latest;
20518
+ }
20519
+ async function updateNotice(current = "0.1.4") {
20520
+ if (!current || process.env.BITL_NO_UPDATE_CHECK === "1") return void 0;
20521
+ const latest = await latestVersion();
20522
+ if (!latest || compareVersions(latest, current) <= 0) return void 0;
20523
+ return `${t("update.available", { latest, current })}
20524
+ ${t("update.changelog")}`;
20298
20525
  }
20299
20526
 
20300
20527
  // ../src/index.ts
20301
20528
  var CLOUD_ONLY = true;
20302
20529
  var DEFAULT_URL = "https://api.usebitl.com";
20303
- var USAGE = [
20304
- "bitl \u2014 AI \uC5D0\uC774\uC804\uD2B8 \uC791\uC5C5 \uD604\uD669\uD310 (https://usebitl.com)",
20530
+ var row = (cmd, desc) => {
20531
+ const width = cmd.length + (cmd.match(/[가-힣]/g)?.length ?? 0);
20532
+ return ` ${width < 40 ? cmd + " ".repeat(40 - width) : `${cmd} `}${desc}`;
20533
+ };
20534
+ var usage = () => [
20535
+ t("usage.title"),
20305
20536
  "",
20306
- ...CLOUD_ONLY ? [] : [" bitl start \uC11C\uBC84 \uC2DC\uC791 (http://127.0.0.1:7777)"],
20307
- " bitl status \uD604\uC7AC \uC138\uC158 \uC694\uC57D (\uC774 PC \uC758 \uD0A4\uB85C \uBCF5\uD638\uD654)",
20308
- " bitl pair [--url \uC8FC\uC18C] \uBE0C\uB77C\uC6B0\uC800\uC5D0 \uC554\uD638\uD654 \uD0A4\uB97C \uB118\uAE30\uB294 \uB9C1\uD06C (\uBE0C\uB77C\uC6B0\uC800\xB7\uC8FC\uC18C\uB9C8\uB2E4 \uD55C \uBC88)",
20537
+ ...CLOUD_ONLY ? [] : [row("bitl start", t("usage.start"))],
20538
+ row("bitl status", t("usage.status")),
20539
+ row(`bitl pair ${t("usage.pairArgs")}`, t("usage.pair")),
20309
20540
  "",
20310
- DEFAULT_URL ? ` bitl login [--url <\uC8FC\uC18C>] [--name \uC774\uB984] [--no-browser] \uC774 PC \uB97C \uACC4\uC815\uC5D0 \uC5F0\uACB0 (\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC2B9\uC778, \uAE30\uBCF8 ${DEFAULT_URL})` : " bitl login --url <\uC8FC\uC18C> [--name \uC774\uB984] [--no-browser] \uC774 PC \uB97C \uD074\uB77C\uC6B0\uB4DC \uACC4\uC815\uC5D0 \uC5F0\uACB0 (\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC2B9\uC778)",
20311
- CLOUD_ONLY ? " bitl logout \uC5F0\uACB0 \uD574\uC81C" : " bitl logout \uC5F0\uACB0 \uD574\uC81C \u2192 \uB2E4\uC2DC \uB85C\uCEEC \uC11C\uBC84\uB85C",
20541
+ DEFAULT_URL ? row(`bitl login ${t("usage.loginArgsDefault")}`, t("usage.loginDefault", { url: DEFAULT_URL })) : row(`bitl login ${t("usage.loginArgs")}`, t("usage.login")),
20542
+ row("bitl logout", CLOUD_ONLY ? t("usage.logoutCloud") : t("usage.logout")),
20312
20543
  "",
20313
- " bitl install claude [--project D] Claude Code hook \uB4F1\uB85D (\uAE30\uBCF8: ~/.claude/settings.json)",
20314
- " bitl install codex Codex hook \uB4F1\uB85D (~/.codex/config.toml)",
20315
- " bitl install antigravity Antigravity hook \uB4F1\uB85D (~/.gemini/config/hooks.json, CLI\xB7IDE \uACF5\uC6A9)",
20316
- ...CLOUD_ONLY ? [] : [" bitl install claude-desktop Claude Desktop \uC5D0 MCP \uC11C\uBC84 \uB4F1\uB85D"],
20544
+ row("bitl install claude [--project D]", t("usage.installClaude")),
20545
+ row("bitl install codex", t("usage.installCodex")),
20546
+ row("bitl install antigravity", t("usage.installAgy")),
20547
+ ...CLOUD_ONLY ? [] : [row("bitl install claude-desktop", t("usage.installDesktop"))],
20317
20548
  ` bitl uninstall <claude|codex|antigravity${CLOUD_ONLY ? "" : "|claude-desktop"}> [--project D]`,
20318
20549
  "",
20319
- " bitl remote [on|off] \uC6D0\uACA9 \uC2B9\uC778: \uCF1C\uBA74 Claude Code \uC758 \uAD8C\uD55C \uC694\uCCAD\uC744 \uD734\uB300\uD3F0\xB7\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uD5C8\uC6A9\xB7\uAC70\uBD80",
20320
- " \u2014 \uD130\uBBF8\uB110\xB7\uBE0C\uB77C\uC6B0\uC800\xB7\uD734\uB300\uD3F0 \uC911 \uBA3C\uC800 \uB2F5\uD55C \uCABD\uC774 \uC801\uC6A9\uB41C\uB2E4 (\uD3F0\uC758 \uB2F5\uC740 \uCD5C\uB300 10\uBD84 \uAE30\uB2E4\uB9BC)"
20550
+ row("bitl remote [on|off]", t("usage.remote")),
20551
+ row("", t("usage.remote2"))
20321
20552
  ].join("\n");
20322
20553
  var serverUrl = () => process.env.BITL_URL ?? `http://127.0.0.1:${process.env.BITL_PORT ?? 7777}`;
20323
20554
  function option(args, name) {
20324
20555
  const i = args.indexOf(name);
20325
20556
  if (i < 0) return void 0;
20326
20557
  const v = args[i + 1];
20327
- if (!v) throw new Error(`${name} \uB4A4\uC5D0 \uAC12\uC744 \uC9C0\uC815\uD558\uC138\uC694`);
20558
+ if (!v) throw new Error(t("err.optionValue", { name }));
20328
20559
  args.splice(i, 2);
20329
20560
  return v;
20330
20561
  }
@@ -20336,22 +20567,22 @@ async function request(path, init = {}) {
20336
20567
  body: init.body === void 0 ? void 0 : JSON.stringify(init.body)
20337
20568
  }).catch(() => {
20338
20569
  throw new Error(
20339
- target.kind === "cloud" ? `\uD074\uB77C\uC6B0\uB4DC \uC11C\uBC84\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (${target.url})` : `\uC11C\uBC84\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4 (${target.url}). bitl start \uB85C \uC2DC\uC791\uD558\uC138\uC694.`
20570
+ target.kind === "cloud" ? t("err.cloudUnreachable", { url: target.url }) : t("err.localUnreachable", { url: target.url })
20340
20571
  );
20341
20572
  });
20342
- if (res.status === 401) throw new Error("\uC774 PC \uC758 \uC5F0\uACB0\uC774 \uB04A\uACBC\uC2B5\uB2C8\uB2E4 (\uAE30\uAE30\uAC00 \uC81C\uAC70\uB428). bitl logout \uD6C4 bitl login \uC73C\uB85C \uB2E4\uC2DC \uC5F0\uACB0\uD558\uC138\uC694.");
20573
+ if (res.status === 401) throw new Error(t("err.revoked"));
20343
20574
  return res;
20344
20575
  }
20345
20576
  var boardUrl = (override) => (override?.trim() || process.env.BITL_PUBLIC_URL?.trim() || readCloudConfig()?.url || serverUrl()).replace(/\/+$/, "");
20346
- var masterForPair = () => readCloudConfig() ? readFileSync4(cloudKeyPath(), "utf8").trim() : loadOrCreateMasterKey();
20577
+ var masterForPair = () => readCloudConfig() ? readFileSync5(cloudKeyPath(), "utf8").trim() : loadOrCreateMasterKey();
20347
20578
  var pairUrl = (base) => `${boardUrl(base)}/#key=${masterForPair()}`;
20348
20579
  function pair(args) {
20349
20580
  const base = option(args, "--url");
20350
- console.log("\uC774 \uB9C1\uD06C\uB97C \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uD55C \uBC88 \uC5F4\uBA74 \uADF8 \uBE0C\uB77C\uC6B0\uC800\uAC00 \uD0A4\uB97C \uAE30\uC5B5\uD569\uB2C8\uB2E4 (\uB2E4\uB978 \uC0AC\uB78C\uC5D0\uAC8C \uBCF4\uB0B4\uC9C0 \uB9C8\uC138\uC694):");
20581
+ console.log(t("pair.intro"));
20351
20582
  console.log(` ${pairUrl(base)}`);
20352
- if (!base) console.log(" \uBCF4\uB4DC\uB97C \uB2E4\uB978 \uC8FC\uC18C\uB85C \uC5F0\uB2E4\uBA74 \uADF8 \uC8FC\uC18C\uB85C: bitl pair --url http://localhost:7788");
20353
- if (readCloudConfig()) console.log(' \uD074\uB77C\uC6B0\uB4DC \uACC4\uC815\uC740 \uBCF4\uD1B5 \uC6F9\uC758 "\uAE30\uAE30" \u2192 "\uAE30\uAE30 \uCD94\uAC00"(QR) \uB85C \uD0A4\uB97C \uB118\uAE41\uB2C8\uB2E4. \uC774 \uB9C1\uD06C\uB294 \uC608\uBE44 \uBC29\uBC95\uC785\uB2C8\uB2E4.');
20354
- console.log(` \uD0A4 \uD30C\uC77C: ${readCloudConfig() ? cloudKeyPath() : keyPath(bitlHome())} \u2014 \uC9C0\uC6B0\uBA74 \uC774\uC804 \uAE30\uB85D\uC744 \uBCFC \uC218 \uC5C6\uC2B5\uB2C8\uB2E4.`);
20583
+ if (!base) console.log(t("pair.otherUrl"));
20584
+ if (readCloudConfig()) console.log(t("pair.cloud"));
20585
+ console.log(t("pair.keyFile", { path: readCloudConfig() ? cloudKeyPath() : keyPath(bitlHome()) }));
20355
20586
  }
20356
20587
  async function status() {
20357
20588
  const target = resolveTarget();
@@ -20363,8 +20594,8 @@ async function status() {
20363
20594
  process.exitCode = 1;
20364
20595
  return;
20365
20596
  }
20366
- if (target.kind === "cloud") console.log(`(\uD074\uB77C\uC6B0\uB4DC \uACC4\uC815: ${target.url})`);
20367
- if (stored.length === 0) return console.log("\uC9C4\uD589 \uC911\uC778 \uC138\uC158 \uC5C6\uC74C");
20597
+ if (target.kind === "cloud") console.log(t("status.cloud", { url: target.url }));
20598
+ if (stored.length === 0) return console.log(t("status.none"));
20368
20599
  let keys = await target.keys();
20369
20600
  if (target.kind === "cloud") {
20370
20601
  const res = await request("/api/inbox-key").catch(() => null);
@@ -20380,12 +20611,12 @@ async function status() {
20380
20611
  }
20381
20612
  }
20382
20613
  async function away(arg) {
20383
- if (arg !== void 0 && arg !== "on" && arg !== "off") throw new Error("\uC0AC\uC6A9\uBC95: bitl remote [on|off]");
20614
+ if (arg !== void 0 && arg !== "on" && arg !== "off") throw new Error(t("err.remoteUsage"));
20384
20615
  const res = arg === void 0 ? await request("/api/approvals/mode") : await request("/api/approvals/mode", { method: "PUT", body: { away: arg === "on" } });
20385
- if (res.status === 404) throw new Error("\uC774 \uC11C\uBC84\uB294 \uC6D0\uACA9 \uC2B9\uC778\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 (\uC11C\uBC84\uB97C \uC0C8 \uBC84\uC804\uC73C\uB85C \uC5C5\uB370\uC774\uD2B8\uD558\uC138\uC694)");
20616
+ if (res.status === 404) throw new Error(t("err.remoteUnsupported"));
20386
20617
  const { away: on } = await res.json();
20387
- console.log(on ? "\uC6D0\uACA9 \uC2B9\uC778: \uCF1C\uC9D0 \u2014 Claude Code \uC758 \uAD8C\uD55C \uC694\uCCAD\uC774 \uD734\uB300\uD3F0\xB7\uBE0C\uB77C\uC6B0\uC800\uB85C \uAC11\uB2C8\uB2E4 (\uBCF4\uB4DC\xB7\uC54C\uB9BC\uC5D0\uC11C \uD5C8\uC6A9\xB7\uAC70\uBD80)" : "\uC6D0\uACA9 \uC2B9\uC778: \uAEBC\uC9D0 \u2014 \uAD8C\uD55C \uC694\uCCAD\uC740 \uD130\uBBF8\uB110\uC5D0\uC11C \uC2B9\uC778\uD569\uB2C8\uB2E4");
20388
- if (on) console.log(" hook \uC774 \uC5C6\uC73C\uBA74 \uB3D9\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: bitl install claude \uB97C \uD55C \uBC88 \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694 (\uC6D0\uACA9 \uC2B9\uC778 hook \uCD94\uAC00)");
20618
+ console.log(on ? t("remote.on") : t("remote.off"));
20619
+ if (on) console.log(t("remote.needHook"));
20389
20620
  }
20390
20621
  function install(cmd, target, args) {
20391
20622
  const add = cmd === "install";
@@ -20395,47 +20626,49 @@ function install(cmd, target, args) {
20395
20626
  switch (target) {
20396
20627
  case "claude": {
20397
20628
  const project = option(args, "--project");
20398
- file2 = project ? join4(resolve2(project), ".claude", "settings.json") : join4(homedir3(), ".claude", "settings.json");
20629
+ file2 = project ? join5(resolve2(project), ".claude", "settings.json") : join5(homedir3(), ".claude", "settings.json");
20399
20630
  result = updateSettingsFile(file2, add ? (s) => addHooks(s) : removeHooks);
20400
- extra = `\uC5B4\uB311\uD130: ${ADAPTER_PATH}`;
20631
+ extra = t("install.adapter", { path: ADAPTER_PATH });
20401
20632
  break;
20402
20633
  }
20403
20634
  case "codex":
20404
20635
  file2 = codexConfigPath();
20405
- result = updateTextFile(file2, add ? (t) => addCodexBlock(t) : removeCodexBlock);
20406
- extra = `\uC5B4\uB311\uD130: ${ADAPTER_PATH}
20407
- \uC544\uC9C1 \uB3D9\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: Codex \uB97C \uC5F4\uACE0 /hooks \uC5D0\uC11C bitl hook \uC744 \uC2E0\uB8B0(trust)\uD558\uC138\uC694.`;
20636
+ result = updateTextFile(file2, add ? (t2) => addCodexBlock(t2) : removeCodexBlock);
20637
+ extra = `${t("install.adapter", { path: ADAPTER_PATH })}
20638
+ ${t("install.codexTrust")}`;
20408
20639
  break;
20409
20640
  case "antigravity":
20410
20641
  file2 = antigravityHooksPath();
20411
20642
  result = updateSettingsFile(file2, add ? (c) => addAntigravityHooks(c) : removeAntigravityHooks);
20412
- extra = `\uC5B4\uB311\uD130: ${ADAPTER_PATH}
20413
- \uC2E4\uD589 \uC911\uC778 agy \uB294 \uB2E4\uC2DC \uC2DC\uC791\uD574\uC57C \uC801\uC6A9\uB429\uB2C8\uB2E4.`;
20643
+ extra = `${t("install.adapter", { path: ADAPTER_PATH })}
20644
+ ${t("install.agyRestart")}`;
20414
20645
  break;
20415
20646
  case "claude-desktop":
20416
- if (CLOUD_ONLY) throw new Error("claude-desktop(\uB85C\uCEEC MCP)\uC740 \uC774 \uD328\uD0A4\uC9C0\uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4. claude.ai \uCEE4\uB125\uD130\uB97C \uC4F0\uC138\uC694: https://usebitl.com/app");
20647
+ if (CLOUD_ONLY) throw new Error(t("err.noDesktop"));
20417
20648
  file2 = claudeDesktopConfigPath();
20418
20649
  result = updateSettingsFile(file2, add ? (c) => addMcpServer(c) : removeMcpServer);
20419
- extra = `MCP \uC11C\uBC84: ${MCP_PATH}
20420
- Claude Desktop \uC744 \uC7AC\uC2DC\uC791\uD574\uC57C \uC801\uC6A9\uB429\uB2C8\uB2E4.`;
20650
+ extra = `${t("install.mcp", { path: MCP_PATH })}
20651
+ ${t("install.desktopRestart")}`;
20421
20652
  break;
20422
20653
  default:
20423
- throw new Error(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uB300\uC0C1: ${target ?? "(\uC5C6\uC74C)"} \u2014 claude, codex, antigravity, claude-desktop`);
20654
+ throw new Error(
20655
+ t("err.unknownTarget", { target: target ?? t("err.none"), list: `claude, codex, antigravity${CLOUD_ONLY ? "" : ", claude-desktop"}` })
20656
+ );
20424
20657
  }
20425
- if (!result.changed) return console.log(`\uBCC0\uACBD \uC5C6\uC74C: ${file2}`);
20426
- console.log(`${add ? "\uB4F1\uB85D" : "\uC81C\uAC70"} \uC644\uB8CC: ${file2}`);
20427
- if (result.backup) console.log(` \uBC31\uC5C5: ${result.backup}`);
20658
+ if (!result.changed) return console.log(t("install.unchanged", { file: file2 }));
20659
+ console.log(t(add ? "install.added" : "install.removed", { file: file2 }));
20660
+ if (result.backup) console.log(t("install.backup", { path: result.backup }));
20428
20661
  if (add && extra) console.log(` ${extra}`);
20429
20662
  }
20430
20663
  async function main(argv) {
20431
20664
  const [cmd, ...rest] = argv;
20432
20665
  switch (cmd) {
20433
20666
  case "start": {
20434
- if (CLOUD_ONLY) throw new Error("bitl start(\uB85C\uCEEC \uC11C\uBC84)\uB294 \uC774 \uD328\uD0A4\uC9C0\uC5D0 \uC5C6\uC2B5\uB2C8\uB2E4. https://usebitl.com \uC5D0\uC11C \uC4F0\uC138\uC694.");
20667
+ if (CLOUD_ONLY) throw new Error(t("err.noStart"));
20435
20668
  const { startServer } = await import("@bitl/server");
20436
20669
  await startServer();
20437
20670
  loadOrCreateMasterKey();
20438
- console.log(` \uBE0C\uB77C\uC6B0\uC800 \uC5F0\uACB0(\uCC98\uC74C \uD55C \uBC88): ${pairUrl()}`);
20671
+ console.log(t("start.pair", { url: pairUrl() }));
20439
20672
  return;
20440
20673
  }
20441
20674
  case "install":
@@ -20447,7 +20680,7 @@ async function main(argv) {
20447
20680
  return pair(rest);
20448
20681
  case "login": {
20449
20682
  const url2 = option(rest, "--url") ?? process.env.BITL_PUBLIC_URL?.trim() ?? DEFAULT_URL;
20450
- if (!url2) throw new Error("\uC5F0\uACB0\uD560 \uC11C\uBE44\uC2A4 \uC8FC\uC18C\uB97C \uC9C0\uC815\uD558\uC138\uC694: bitl login --url https://\u2026");
20683
+ if (!url2) throw new Error(t("err.loginUrl"));
20451
20684
  return login(url2, option(rest, "--name"), { openBrowser: !rest.includes("--no-browser") });
20452
20685
  }
20453
20686
  case "logout":
@@ -20456,10 +20689,15 @@ async function main(argv) {
20456
20689
  case "away":
20457
20690
  return away(rest[0]);
20458
20691
  default:
20459
- console.log(USAGE);
20692
+ console.log(usage());
20460
20693
  }
20461
20694
  }
20462
20695
  main(process.argv.slice(2)).catch((err) => {
20463
20696
  console.error(err instanceof Error ? err.message : err);
20464
20697
  process.exitCode = 1;
20698
+ }).then(async () => {
20699
+ if (process.argv[2] === "start") return;
20700
+ const notice = await updateNotice();
20701
+ if (notice) console.error(`
20702
+ ${notice}`);
20465
20703
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usebitl/cli",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "BITL CLI — connect Claude Code, Codex and Antigravity to usebitl.com and stay in the loop of every agent you run",
5
5
  "type": "module",
6
6
  "bin": {