terminalhire 0.40.4 → 0.40.6

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.
@@ -10618,6 +10618,14 @@ function warnStderr(message) {
10618
10618
  process.stderr.write(`${message}
10619
10619
  `);
10620
10620
  }
10621
+ function makeWarnOnce() {
10622
+ const seen = /* @__PURE__ */ new Set();
10623
+ return (message) => {
10624
+ if (seen.has(message)) return;
10625
+ seen.add(message);
10626
+ warnStderr(message);
10627
+ };
10628
+ }
10621
10629
  function atomicWriteFileSync(filePath, content) {
10622
10630
  const dir = dirname(filePath);
10623
10631
  ensureStateDirForSecret(dir);
@@ -10663,11 +10671,11 @@ async function deleteKey() {
10663
10671
  if (e.code !== "ENOENT") throw e;
10664
10672
  }
10665
10673
  }
10666
- async function resolveKey(filePath, opts) {
10674
+ async function resolveKey(filePath, opts, warnOnce) {
10667
10675
  if (opts.keyPolicy === "keychain-required") {
10668
10676
  const key = await tryLoadFromKeytar();
10669
10677
  if (!key) {
10670
- warnStderr(
10678
+ warnOnce(
10671
10679
  `crypto-store: OS keychain unavailable \u2014 store at ${filePath} is disabled (no plaintext key file will be written)`
10672
10680
  );
10673
10681
  return null;
@@ -10677,8 +10685,9 @@ async function resolveKey(filePath, opts) {
10677
10685
  return loadOrCreateSharedKey();
10678
10686
  }
10679
10687
  function createEncryptedStore(filePath, opts) {
10688
+ const warnOnce = makeWarnOnce();
10680
10689
  async function read() {
10681
- const key = await resolveKey(filePath, opts);
10690
+ const key = await resolveKey(filePath, opts, warnOnce);
10682
10691
  if (!key) return opts.blank();
10683
10692
  if (!existsSync3(filePath)) return opts.blank();
10684
10693
  try {
@@ -10687,12 +10696,12 @@ function createEncryptedStore(filePath, opts) {
10687
10696
  const plaintext = decrypt(blob, key);
10688
10697
  return JSON.parse(plaintext);
10689
10698
  } catch {
10690
- warnStderr(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
10699
+ warnOnce(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
10691
10700
  return opts.blank();
10692
10701
  }
10693
10702
  }
10694
10703
  async function write(value) {
10695
- const key = await resolveKey(filePath, opts);
10704
+ const key = await resolveKey(filePath, opts, warnOnce);
10696
10705
  if (!key) return;
10697
10706
  const blob = encrypt(JSON.stringify(value), key);
10698
10707
  atomicWriteFileSync(filePath, JSON.stringify(blob, null, 2));
@@ -5478,6 +5478,14 @@ function warnStderr(message) {
5478
5478
  process.stderr.write(`${message}
5479
5479
  `);
5480
5480
  }
5481
+ function makeWarnOnce() {
5482
+ const seen = /* @__PURE__ */ new Set();
5483
+ return (message) => {
5484
+ if (seen.has(message)) return;
5485
+ seen.add(message);
5486
+ warnStderr(message);
5487
+ };
5488
+ }
5481
5489
  function atomicWriteFileSync(filePath, content) {
5482
5490
  const dir = dirname(filePath);
5483
5491
  ensureStateDirForSecret(dir);
@@ -5523,11 +5531,11 @@ async function deleteKey() {
5523
5531
  if (e.code !== "ENOENT") throw e;
5524
5532
  }
5525
5533
  }
5526
- async function resolveKey(filePath, opts) {
5534
+ async function resolveKey(filePath, opts, warnOnce) {
5527
5535
  if (opts.keyPolicy === "keychain-required") {
5528
5536
  const key = await tryLoadFromKeytar();
5529
5537
  if (!key) {
5530
- warnStderr(
5538
+ warnOnce(
5531
5539
  `crypto-store: OS keychain unavailable \u2014 store at ${filePath} is disabled (no plaintext key file will be written)`
5532
5540
  );
5533
5541
  return null;
@@ -5537,8 +5545,9 @@ async function resolveKey(filePath, opts) {
5537
5545
  return loadOrCreateSharedKey();
5538
5546
  }
5539
5547
  function createEncryptedStore(filePath, opts) {
5548
+ const warnOnce = makeWarnOnce();
5540
5549
  async function read() {
5541
- const key = await resolveKey(filePath, opts);
5550
+ const key = await resolveKey(filePath, opts, warnOnce);
5542
5551
  if (!key) return opts.blank();
5543
5552
  if (!existsSync9(filePath)) return opts.blank();
5544
5553
  try {
@@ -5547,12 +5556,12 @@ function createEncryptedStore(filePath, opts) {
5547
5556
  const plaintext = decrypt2(blob, key);
5548
5557
  return JSON.parse(plaintext);
5549
5558
  } catch {
5550
- warnStderr(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
5559
+ warnOnce(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
5551
5560
  return opts.blank();
5552
5561
  }
5553
5562
  }
5554
5563
  async function write(value) {
5555
- const key = await resolveKey(filePath, opts);
5564
+ const key = await resolveKey(filePath, opts, warnOnce);
5556
5565
  if (!key) return;
5557
5566
  const blob = encrypt2(JSON.stringify(value), key);
5558
5567
  atomicWriteFileSync(filePath, JSON.stringify(blob, null, 2));
@@ -24831,6 +24831,14 @@ function warnStderr(message) {
24831
24831
  process.stderr.write(`${message}
24832
24832
  `);
24833
24833
  }
24834
+ function makeWarnOnce() {
24835
+ const seen = /* @__PURE__ */ new Set();
24836
+ return (message) => {
24837
+ if (seen.has(message)) return;
24838
+ seen.add(message);
24839
+ warnStderr(message);
24840
+ };
24841
+ }
24834
24842
  function atomicWriteFileSync(filePath, content) {
24835
24843
  const dir = dirname4(filePath);
24836
24844
  ensureStateDirForSecret(dir);
@@ -24876,11 +24884,11 @@ async function deleteKey() {
24876
24884
  if (e.code !== "ENOENT") throw e;
24877
24885
  }
24878
24886
  }
24879
- async function resolveKey(filePath, opts) {
24887
+ async function resolveKey(filePath, opts, warnOnce) {
24880
24888
  if (opts.keyPolicy === "keychain-required") {
24881
24889
  const key = await tryLoadFromKeytar();
24882
24890
  if (!key) {
24883
- warnStderr(
24891
+ warnOnce(
24884
24892
  `crypto-store: OS keychain unavailable \u2014 store at ${filePath} is disabled (no plaintext key file will be written)`
24885
24893
  );
24886
24894
  return null;
@@ -24890,8 +24898,9 @@ async function resolveKey(filePath, opts) {
24890
24898
  return loadOrCreateSharedKey();
24891
24899
  }
24892
24900
  function createEncryptedStore(filePath, opts) {
24901
+ const warnOnce = makeWarnOnce();
24893
24902
  async function read() {
24894
- const key = await resolveKey(filePath, opts);
24903
+ const key = await resolveKey(filePath, opts, warnOnce);
24895
24904
  if (!key) return opts.blank();
24896
24905
  if (!existsSync6(filePath)) return opts.blank();
24897
24906
  try {
@@ -24900,12 +24909,12 @@ function createEncryptedStore(filePath, opts) {
24900
24909
  const plaintext = decrypt2(blob, key);
24901
24910
  return JSON.parse(plaintext);
24902
24911
  } catch {
24903
- warnStderr(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
24912
+ warnOnce(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
24904
24913
  return opts.blank();
24905
24914
  }
24906
24915
  }
24907
24916
  async function write(value) {
24908
- const key = await resolveKey(filePath, opts);
24917
+ const key = await resolveKey(filePath, opts, warnOnce);
24909
24918
  if (!key) return;
24910
24919
  const blob = encrypt2(JSON.stringify(value), key);
24911
24920
  atomicWriteFileSync(filePath, JSON.stringify(blob, null, 2));
@@ -2742,6 +2742,14 @@ function warnStderr(message) {
2742
2742
  process.stderr.write(`${message}
2743
2743
  `);
2744
2744
  }
2745
+ function makeWarnOnce() {
2746
+ const seen = /* @__PURE__ */ new Set();
2747
+ return (message) => {
2748
+ if (seen.has(message)) return;
2749
+ seen.add(message);
2750
+ warnStderr(message);
2751
+ };
2752
+ }
2745
2753
  function atomicWriteFileSync(filePath, content) {
2746
2754
  const dir = dirname(filePath);
2747
2755
  ensureStateDirForSecret(dir);
@@ -2787,11 +2795,11 @@ async function deleteKey() {
2787
2795
  if (e.code !== "ENOENT") throw e;
2788
2796
  }
2789
2797
  }
2790
- async function resolveKey(filePath, opts) {
2798
+ async function resolveKey(filePath, opts, warnOnce) {
2791
2799
  if (opts.keyPolicy === "keychain-required") {
2792
2800
  const key = await tryLoadFromKeytar();
2793
2801
  if (!key) {
2794
- warnStderr(
2802
+ warnOnce(
2795
2803
  `crypto-store: OS keychain unavailable \u2014 store at ${filePath} is disabled (no plaintext key file will be written)`
2796
2804
  );
2797
2805
  return null;
@@ -2801,8 +2809,9 @@ async function resolveKey(filePath, opts) {
2801
2809
  return loadOrCreateSharedKey();
2802
2810
  }
2803
2811
  function createEncryptedStore(filePath, opts) {
2812
+ const warnOnce = makeWarnOnce();
2804
2813
  async function read() {
2805
- const key = await resolveKey(filePath, opts);
2814
+ const key = await resolveKey(filePath, opts, warnOnce);
2806
2815
  if (!key) return opts.blank();
2807
2816
  if (!existsSync4(filePath)) return opts.blank();
2808
2817
  try {
@@ -2811,12 +2820,12 @@ function createEncryptedStore(filePath, opts) {
2811
2820
  const plaintext = decrypt(blob, key);
2812
2821
  return JSON.parse(plaintext);
2813
2822
  } catch {
2814
- warnStderr(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
2823
+ warnOnce(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
2815
2824
  return opts.blank();
2816
2825
  }
2817
2826
  }
2818
2827
  async function write(value) {
2819
- const key = await resolveKey(filePath, opts);
2828
+ const key = await resolveKey(filePath, opts, warnOnce);
2820
2829
  if (!key) return;
2821
2830
  const blob = encrypt(JSON.stringify(value), key);
2822
2831
  atomicWriteFileSync(filePath, JSON.stringify(blob, null, 2));
@@ -10566,6 +10566,14 @@ function warnStderr(message) {
10566
10566
  process.stderr.write(`${message}
10567
10567
  `);
10568
10568
  }
10569
+ function makeWarnOnce() {
10570
+ const seen = /* @__PURE__ */ new Set();
10571
+ return (message) => {
10572
+ if (seen.has(message)) return;
10573
+ seen.add(message);
10574
+ warnStderr(message);
10575
+ };
10576
+ }
10569
10577
  function atomicWriteFileSync(filePath, content) {
10570
10578
  const dir = dirname(filePath);
10571
10579
  ensureStateDirForSecret(dir);
@@ -10611,11 +10619,11 @@ async function deleteKey() {
10611
10619
  if (e.code !== "ENOENT") throw e;
10612
10620
  }
10613
10621
  }
10614
- async function resolveKey(filePath, opts) {
10622
+ async function resolveKey(filePath, opts, warnOnce) {
10615
10623
  if (opts.keyPolicy === "keychain-required") {
10616
10624
  const key = await tryLoadFromKeytar();
10617
10625
  if (!key) {
10618
- warnStderr(
10626
+ warnOnce(
10619
10627
  `crypto-store: OS keychain unavailable \u2014 store at ${filePath} is disabled (no plaintext key file will be written)`
10620
10628
  );
10621
10629
  return null;
@@ -10625,8 +10633,9 @@ async function resolveKey(filePath, opts) {
10625
10633
  return loadOrCreateSharedKey();
10626
10634
  }
10627
10635
  function createEncryptedStore(filePath, opts) {
10636
+ const warnOnce = makeWarnOnce();
10628
10637
  async function read() {
10629
- const key = await resolveKey(filePath, opts);
10638
+ const key = await resolveKey(filePath, opts, warnOnce);
10630
10639
  if (!key) return opts.blank();
10631
10640
  if (!existsSync3(filePath)) return opts.blank();
10632
10641
  try {
@@ -10635,12 +10644,12 @@ function createEncryptedStore(filePath, opts) {
10635
10644
  const plaintext = decrypt(blob, key);
10636
10645
  return JSON.parse(plaintext);
10637
10646
  } catch {
10638
- warnStderr(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
10647
+ warnOnce(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
10639
10648
  return opts.blank();
10640
10649
  }
10641
10650
  }
10642
10651
  async function write(value) {
10643
- const key = await resolveKey(filePath, opts);
10652
+ const key = await resolveKey(filePath, opts, warnOnce);
10644
10653
  if (!key) return;
10645
10654
  const blob = encrypt(JSON.stringify(value), key);
10646
10655
  atomicWriteFileSync(filePath, JSON.stringify(blob, null, 2));
@@ -11928,6 +11928,14 @@ function warnStderr(message) {
11928
11928
  process.stderr.write(`${message}
11929
11929
  `);
11930
11930
  }
11931
+ function makeWarnOnce() {
11932
+ const seen = /* @__PURE__ */ new Set();
11933
+ return (message) => {
11934
+ if (seen.has(message)) return;
11935
+ seen.add(message);
11936
+ warnStderr(message);
11937
+ };
11938
+ }
11931
11939
  function atomicWriteFileSync(filePath, content) {
11932
11940
  const dir = dirname(filePath);
11933
11941
  ensureStateDirForSecret(dir);
@@ -11973,11 +11981,11 @@ async function deleteKey() {
11973
11981
  if (e.code !== "ENOENT") throw e;
11974
11982
  }
11975
11983
  }
11976
- async function resolveKey(filePath, opts) {
11984
+ async function resolveKey(filePath, opts, warnOnce) {
11977
11985
  if (opts.keyPolicy === "keychain-required") {
11978
11986
  const key = await tryLoadFromKeytar();
11979
11987
  if (!key) {
11980
- warnStderr(
11988
+ warnOnce(
11981
11989
  `crypto-store: OS keychain unavailable \u2014 store at ${filePath} is disabled (no plaintext key file will be written)`
11982
11990
  );
11983
11991
  return null;
@@ -11987,8 +11995,9 @@ async function resolveKey(filePath, opts) {
11987
11995
  return loadOrCreateSharedKey();
11988
11996
  }
11989
11997
  function createEncryptedStore(filePath, opts) {
11998
+ const warnOnce = makeWarnOnce();
11990
11999
  async function read() {
11991
- const key = await resolveKey(filePath, opts);
12000
+ const key = await resolveKey(filePath, opts, warnOnce);
11992
12001
  if (!key) return opts.blank();
11993
12002
  if (!existsSync8(filePath)) return opts.blank();
11994
12003
  try {
@@ -11997,12 +12006,12 @@ function createEncryptedStore(filePath, opts) {
11997
12006
  const plaintext = decrypt2(blob, key);
11998
12007
  return JSON.parse(plaintext);
11999
12008
  } catch {
12000
- warnStderr(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
12009
+ warnOnce(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
12001
12010
  return opts.blank();
12002
12011
  }
12003
12012
  }
12004
12013
  async function write(value) {
12005
- const key = await resolveKey(filePath, opts);
12014
+ const key = await resolveKey(filePath, opts, warnOnce);
12006
12015
  if (!key) return;
12007
12016
  const blob = encrypt2(JSON.stringify(value), key);
12008
12017
  atomicWriteFileSync(filePath, JSON.stringify(blob, null, 2));
@@ -63618,15 +63627,11 @@ async function run25() {
63618
63627
  console.log("");
63619
63628
  console.log(" Fetching anonymous job index (no dev data sent)...");
63620
63629
  const jobsScript = resolveScript("jpi-jobs");
63621
- const seedChild = spawnSync3(
63622
- process.execPath,
63623
- [jobsScript, "--limit", "0"],
63624
- {
63625
- stdio: ["ignore", "pipe", "pipe"],
63626
- env: { ...process.env, TERMINALHIRE_SEED_ONLY: "1" },
63627
- timeout: 15e3
63628
- }
63629
- );
63630
+ const seedChild = spawnSync3(process.execPath, [jobsScript, "--limit", "0"], {
63631
+ stdio: ["ignore", "pipe", "pipe"],
63632
+ env: { ...process.env, TERMINALHIRE_SEED_ONLY: "1" },
63633
+ timeout: 15e3
63634
+ });
63630
63635
  if (seedChild.status === 0) {
63631
63636
  console.log(" Job cache seeded successfully.");
63632
63637
  } else {
@@ -63658,7 +63663,9 @@ async function run25() {
63658
63663
  console.log("");
63659
63664
  console.log(" This is the only step that modifies a system file.");
63660
63665
  console.log(" A timestamped backup is created before any change.");
63661
- console.log(" Disable at any time: node install.js --uninstall (or terminalhire spinner --off)");
63666
+ console.log(
63667
+ " Disable at any time: node install.js --uninstall (or terminalhire spinner --off)"
63668
+ );
63662
63669
  console.log("");
63663
63670
  try {
63664
63671
  const installMod = await import(pathToFileURL(resolveInstallJs()).href);
@@ -63677,9 +63684,10 @@ async function run25() {
63677
63684
  console.log("");
63678
63685
  console.log(" A statusLine that shows ONLY personal connection signals \u2014 \u{1F4AC} unread");
63679
63686
  console.log(" messages and inbound intro requests. Never job ads (those stay in the");
63680
- console.log(" spinner). Local cache read, zero network. Separate consent + backup;");
63681
- console.log(" it stays current across plugin updates and preserves any existing");
63682
- console.log(" statusLine you have. Remove any time: node statusline-install.js --uninstall");
63687
+ console.log(" spinner). Local cache read, zero network. On by default; backs up and");
63688
+ console.log(" preserves any existing statusLine, and stays current across plugin");
63689
+ console.log(" updates. Answer n to skip, or remove later with:");
63690
+ console.log(" terminalhire statusline --off");
63683
63691
  console.log("");
63684
63692
  try {
63685
63693
  const statuslineMod = await import(pathToFileURL(resolveStatuslineInstallJs()).href);
@@ -63687,7 +63695,9 @@ async function run25() {
63687
63695
  await statuslineMod.installStatusline({ ask: ask4 });
63688
63696
  } else {
63689
63697
  console.log("");
63690
- console.log(" statusLine setup unavailable in this build. Run manually: node statusline-install.js");
63698
+ console.log(
63699
+ " statusLine setup unavailable in this build. Run manually: node statusline-install.js"
63700
+ );
63691
63701
  }
63692
63702
  } catch {
63693
63703
  console.log("");
@@ -63716,7 +63726,9 @@ async function run25() {
63716
63726
  console.log(" this terminal (one-time OS registration; macOS may show an Automation");
63717
63727
  console.log(" prompt the first time a link is opened). Nothing is sent anywhere \u2014 it");
63718
63728
  console.log(" only wires th://claim/<token> links on this machine to a local, read-only");
63719
- console.log(" `terminalhire claim preview <token>`. Undo any time: terminalhire protocol unregister");
63729
+ console.log(
63730
+ " `terminalhire claim preview <token>`. Undo any time: terminalhire protocol unregister"
63731
+ );
63720
63732
  console.log("");
63721
63733
  const protocolAnswer = await ask4("Register th:// claim links now? [Y/n] (Enter = yes): ");
63722
63734
  const doProtocol = protocolAnswer === "" || protocolAnswer === "y" || protocolAnswer === "yes";
@@ -11198,6 +11198,14 @@ function warnStderr(message) {
11198
11198
  process.stderr.write(`${message}
11199
11199
  `);
11200
11200
  }
11201
+ function makeWarnOnce() {
11202
+ const seen = /* @__PURE__ */ new Set();
11203
+ return (message) => {
11204
+ if (seen.has(message)) return;
11205
+ seen.add(message);
11206
+ warnStderr(message);
11207
+ };
11208
+ }
11201
11209
  function atomicWriteFileSync(filePath, content) {
11202
11210
  const dir = dirname(filePath);
11203
11211
  ensureStateDirForSecret(dir);
@@ -11243,11 +11251,11 @@ async function deleteKey() {
11243
11251
  if (e.code !== "ENOENT") throw e;
11244
11252
  }
11245
11253
  }
11246
- async function resolveKey(filePath, opts) {
11254
+ async function resolveKey(filePath, opts, warnOnce) {
11247
11255
  if (opts.keyPolicy === "keychain-required") {
11248
11256
  const key = await tryLoadFromKeytar();
11249
11257
  if (!key) {
11250
- warnStderr(
11258
+ warnOnce(
11251
11259
  `crypto-store: OS keychain unavailable \u2014 store at ${filePath} is disabled (no plaintext key file will be written)`
11252
11260
  );
11253
11261
  return null;
@@ -11257,8 +11265,9 @@ async function resolveKey(filePath, opts) {
11257
11265
  return loadOrCreateSharedKey();
11258
11266
  }
11259
11267
  function createEncryptedStore(filePath, opts) {
11268
+ const warnOnce = makeWarnOnce();
11260
11269
  async function read() {
11261
- const key = await resolveKey(filePath, opts);
11270
+ const key = await resolveKey(filePath, opts, warnOnce);
11262
11271
  if (!key) return opts.blank();
11263
11272
  if (!existsSync4(filePath)) return opts.blank();
11264
11273
  try {
@@ -11267,12 +11276,12 @@ function createEncryptedStore(filePath, opts) {
11267
11276
  const plaintext = decrypt(blob, key);
11268
11277
  return JSON.parse(plaintext);
11269
11278
  } catch {
11270
- warnStderr(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
11279
+ warnOnce(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
11271
11280
  return opts.blank();
11272
11281
  }
11273
11282
  }
11274
11283
  async function write(value) {
11275
- const key = await resolveKey(filePath, opts);
11284
+ const key = await resolveKey(filePath, opts, warnOnce);
11276
11285
  if (!key) return;
11277
11286
  const blob = encrypt(JSON.stringify(value), key);
11278
11287
  atomicWriteFileSync(filePath, JSON.stringify(blob, null, 2));
@@ -5478,6 +5478,14 @@ function warnStderr(message) {
5478
5478
  process.stderr.write(`${message}
5479
5479
  `);
5480
5480
  }
5481
+ function makeWarnOnce() {
5482
+ const seen = /* @__PURE__ */ new Set();
5483
+ return (message) => {
5484
+ if (seen.has(message)) return;
5485
+ seen.add(message);
5486
+ warnStderr(message);
5487
+ };
5488
+ }
5481
5489
  function atomicWriteFileSync(filePath, content) {
5482
5490
  const dir = dirname(filePath);
5483
5491
  ensureStateDirForSecret(dir);
@@ -5523,11 +5531,11 @@ async function deleteKey() {
5523
5531
  if (e.code !== "ENOENT") throw e;
5524
5532
  }
5525
5533
  }
5526
- async function resolveKey(filePath, opts) {
5534
+ async function resolveKey(filePath, opts, warnOnce) {
5527
5535
  if (opts.keyPolicy === "keychain-required") {
5528
5536
  const key = await tryLoadFromKeytar();
5529
5537
  if (!key) {
5530
- warnStderr(
5538
+ warnOnce(
5531
5539
  `crypto-store: OS keychain unavailable \u2014 store at ${filePath} is disabled (no plaintext key file will be written)`
5532
5540
  );
5533
5541
  return null;
@@ -5537,8 +5545,9 @@ async function resolveKey(filePath, opts) {
5537
5545
  return loadOrCreateSharedKey();
5538
5546
  }
5539
5547
  function createEncryptedStore(filePath, opts) {
5548
+ const warnOnce = makeWarnOnce();
5540
5549
  async function read() {
5541
- const key = await resolveKey(filePath, opts);
5550
+ const key = await resolveKey(filePath, opts, warnOnce);
5542
5551
  if (!key) return opts.blank();
5543
5552
  if (!existsSync9(filePath)) return opts.blank();
5544
5553
  try {
@@ -5547,12 +5556,12 @@ function createEncryptedStore(filePath, opts) {
5547
5556
  const plaintext = decrypt2(blob, key);
5548
5557
  return JSON.parse(plaintext);
5549
5558
  } catch {
5550
- warnStderr(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
5559
+ warnOnce(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
5551
5560
  return opts.blank();
5552
5561
  }
5553
5562
  }
5554
5563
  async function write(value) {
5555
- const key = await resolveKey(filePath, opts);
5564
+ const key = await resolveKey(filePath, opts, warnOnce);
5556
5565
  if (!key) return;
5557
5566
  const blob = encrypt2(JSON.stringify(value), key);
5558
5567
  atomicWriteFileSync(filePath, JSON.stringify(blob, null, 2));
@@ -10772,15 +10772,11 @@ async function run() {
10772
10772
  console.log("");
10773
10773
  console.log(" Fetching anonymous job index (no dev data sent)...");
10774
10774
  const jobsScript = resolveScript("jpi-jobs");
10775
- const seedChild = spawnSync(
10776
- process.execPath,
10777
- [jobsScript, "--limit", "0"],
10778
- {
10779
- stdio: ["ignore", "pipe", "pipe"],
10780
- env: { ...process.env, TERMINALHIRE_SEED_ONLY: "1" },
10781
- timeout: 15e3
10782
- }
10783
- );
10775
+ const seedChild = spawnSync(process.execPath, [jobsScript, "--limit", "0"], {
10776
+ stdio: ["ignore", "pipe", "pipe"],
10777
+ env: { ...process.env, TERMINALHIRE_SEED_ONLY: "1" },
10778
+ timeout: 15e3
10779
+ });
10784
10780
  if (seedChild.status === 0) {
10785
10781
  console.log(" Job cache seeded successfully.");
10786
10782
  } else {
@@ -10812,7 +10808,9 @@ async function run() {
10812
10808
  console.log("");
10813
10809
  console.log(" This is the only step that modifies a system file.");
10814
10810
  console.log(" A timestamped backup is created before any change.");
10815
- console.log(" Disable at any time: node install.js --uninstall (or terminalhire spinner --off)");
10811
+ console.log(
10812
+ " Disable at any time: node install.js --uninstall (or terminalhire spinner --off)"
10813
+ );
10816
10814
  console.log("");
10817
10815
  try {
10818
10816
  const installMod = await import(pathToFileURL(resolveInstallJs()).href);
@@ -10831,9 +10829,10 @@ async function run() {
10831
10829
  console.log("");
10832
10830
  console.log(" A statusLine that shows ONLY personal connection signals \u2014 \u{1F4AC} unread");
10833
10831
  console.log(" messages and inbound intro requests. Never job ads (those stay in the");
10834
- console.log(" spinner). Local cache read, zero network. Separate consent + backup;");
10835
- console.log(" it stays current across plugin updates and preserves any existing");
10836
- console.log(" statusLine you have. Remove any time: node statusline-install.js --uninstall");
10832
+ console.log(" spinner). Local cache read, zero network. On by default; backs up and");
10833
+ console.log(" preserves any existing statusLine, and stays current across plugin");
10834
+ console.log(" updates. Answer n to skip, or remove later with:");
10835
+ console.log(" terminalhire statusline --off");
10837
10836
  console.log("");
10838
10837
  try {
10839
10838
  const statuslineMod = await import(pathToFileURL(resolveStatuslineInstallJs()).href);
@@ -10841,7 +10840,9 @@ async function run() {
10841
10840
  await statuslineMod.installStatusline({ ask });
10842
10841
  } else {
10843
10842
  console.log("");
10844
- console.log(" statusLine setup unavailable in this build. Run manually: node statusline-install.js");
10843
+ console.log(
10844
+ " statusLine setup unavailable in this build. Run manually: node statusline-install.js"
10845
+ );
10845
10846
  }
10846
10847
  } catch {
10847
10848
  console.log("");
@@ -10870,7 +10871,9 @@ async function run() {
10870
10871
  console.log(" this terminal (one-time OS registration; macOS may show an Automation");
10871
10872
  console.log(" prompt the first time a link is opened). Nothing is sent anywhere \u2014 it");
10872
10873
  console.log(" only wires th://claim/<token> links on this machine to a local, read-only");
10873
- console.log(" `terminalhire claim preview <token>`. Undo any time: terminalhire protocol unregister");
10874
+ console.log(
10875
+ " `terminalhire claim preview <token>`. Undo any time: terminalhire protocol unregister"
10876
+ );
10874
10877
  console.log("");
10875
10878
  const protocolAnswer = await ask("Register th:// claim links now? [Y/n] (Enter = yes): ");
10876
10879
  const doProtocol = protocolAnswer === "" || protocolAnswer === "y" || protocolAnswer === "yes";
@@ -1547,6 +1547,14 @@ function warnStderr(message) {
1547
1547
  process.stderr.write(`${message}
1548
1548
  `);
1549
1549
  }
1550
+ function makeWarnOnce() {
1551
+ const seen = /* @__PURE__ */ new Set();
1552
+ return (message) => {
1553
+ if (seen.has(message)) return;
1554
+ seen.add(message);
1555
+ warnStderr(message);
1556
+ };
1557
+ }
1550
1558
  function atomicWriteFileSync(filePath, content) {
1551
1559
  const dir = dirname(filePath);
1552
1560
  ensureStateDirForSecret(dir);
@@ -1592,11 +1600,11 @@ async function deleteKey() {
1592
1600
  if (e.code !== "ENOENT") throw e;
1593
1601
  }
1594
1602
  }
1595
- async function resolveKey(filePath, opts) {
1603
+ async function resolveKey(filePath, opts, warnOnce) {
1596
1604
  if (opts.keyPolicy === "keychain-required") {
1597
1605
  const key = await tryLoadFromKeytar();
1598
1606
  if (!key) {
1599
- warnStderr(
1607
+ warnOnce(
1600
1608
  `crypto-store: OS keychain unavailable \u2014 store at ${filePath} is disabled (no plaintext key file will be written)`
1601
1609
  );
1602
1610
  return null;
@@ -1606,8 +1614,9 @@ async function resolveKey(filePath, opts) {
1606
1614
  return loadOrCreateSharedKey();
1607
1615
  }
1608
1616
  function createEncryptedStore(filePath, opts) {
1617
+ const warnOnce = makeWarnOnce();
1609
1618
  async function read() {
1610
- const key = await resolveKey(filePath, opts);
1619
+ const key = await resolveKey(filePath, opts, warnOnce);
1611
1620
  if (!key) return opts.blank();
1612
1621
  if (!existsSync4(filePath)) return opts.blank();
1613
1622
  try {
@@ -1616,12 +1625,12 @@ function createEncryptedStore(filePath, opts) {
1616
1625
  const plaintext = decrypt(blob, key);
1617
1626
  return JSON.parse(plaintext);
1618
1627
  } catch {
1619
- warnStderr(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
1628
+ warnOnce(`crypto-store: failed to decrypt ${filePath} \u2014 returning blank`);
1620
1629
  return opts.blank();
1621
1630
  }
1622
1631
  }
1623
1632
  async function write(value) {
1624
- const key = await resolveKey(filePath, opts);
1633
+ const key = await resolveKey(filePath, opts, warnOnce);
1625
1634
  if (!key) return;
1626
1635
  const blob = encrypt(JSON.stringify(value), key);
1627
1636
  atomicWriteFileSync(filePath, JSON.stringify(blob, null, 2));