terminalhire 0.7.0 → 0.8.0

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.
@@ -3047,6 +3047,15 @@ var init_intro = __esm({
3047
3047
  }
3048
3048
  });
3049
3049
 
3050
+ // ../../packages/core/src/directoryThreshold.ts
3051
+ var STRONG_MATCH_THRESHOLD;
3052
+ var init_directoryThreshold = __esm({
3053
+ "../../packages/core/src/directoryThreshold.ts"() {
3054
+ "use strict";
3055
+ STRONG_MATCH_THRESHOLD = 0.58;
3056
+ }
3057
+ });
3058
+
3050
3059
  // ../../packages/core/src/index.ts
3051
3060
  var src_exports = {};
3052
3061
  __export(src_exports, {
@@ -3066,6 +3075,7 @@ __export(src_exports, {
3066
3075
  INTRO_ALLOWED_FIELDS: () => INTRO_ALLOWED_FIELDS,
3067
3076
  INTRO_PENDING_TTL_MS: () => INTRO_PENDING_TTL_MS,
3068
3077
  LEVER_SLUGS_BY_TIER: () => LEVER_SLUGS_BY_TIER,
3078
+ STRONG_MATCH_THRESHOLD: () => STRONG_MATCH_THRESHOLD,
3069
3079
  SYNONYMS: () => SYNONYMS,
3070
3080
  VOCABULARY: () => VOCABULARY,
3071
3081
  VOCAB_NODES: () => VOCAB_NODES,
@@ -3134,6 +3144,7 @@ var init_src = __esm({
3134
3144
  init_partners();
3135
3145
  init_github();
3136
3146
  init_intro();
3147
+ init_directoryThreshold();
3137
3148
  }
3138
3149
  });
3139
3150
 
@@ -3377,6 +3388,95 @@ var init_profile = __esm({
3377
3388
  }
3378
3389
  });
3379
3390
 
3391
+ // src/config.ts
3392
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync3 } from "fs";
3393
+ import { join as join4 } from "path";
3394
+ import { homedir as homedir3 } from "os";
3395
+ function readConfig() {
3396
+ try {
3397
+ if (!existsSync3(CONFIG_FILE)) return { ...DEFAULT_CONFIG };
3398
+ const raw = readFileSync4(CONFIG_FILE, "utf8");
3399
+ const parsed = JSON.parse(raw);
3400
+ return { ...DEFAULT_CONFIG, ...parsed };
3401
+ } catch {
3402
+ return { ...DEFAULT_CONFIG };
3403
+ }
3404
+ }
3405
+ function writeConfig(config) {
3406
+ mkdirSync3(TERMINALHIRE_DIR3, { recursive: true });
3407
+ const current = readConfig();
3408
+ const merged = { ...current, ...config };
3409
+ writeFileSync3(CONFIG_FILE, JSON.stringify(merged, null, 2) + "\n", "utf8");
3410
+ }
3411
+ function isPeerConnectEnabled() {
3412
+ return readConfig().peerConnect === true;
3413
+ }
3414
+ var TERMINALHIRE_DIR3, CONFIG_FILE, DEFAULT_CONFIG;
3415
+ var init_config = __esm({
3416
+ "src/config.ts"() {
3417
+ "use strict";
3418
+ TERMINALHIRE_DIR3 = join4(homedir3(), ".terminalhire");
3419
+ CONFIG_FILE = join4(TERMINALHIRE_DIR3, "config.json");
3420
+ DEFAULT_CONFIG = {
3421
+ nudge: "session",
3422
+ peerConnect: false,
3423
+ peerConnectPrompted: false
3424
+ };
3425
+ }
3426
+ });
3427
+
3428
+ // bin/peer-connect-prompt.js
3429
+ var peer_connect_prompt_exports = {};
3430
+ __export(peer_connect_prompt_exports, {
3431
+ maybePromptPeerConnect: () => maybePromptPeerConnect
3432
+ });
3433
+ import { createInterface } from "readline";
3434
+ async function maybePromptPeerConnect({
3435
+ input = process.stdin,
3436
+ output = process.stdout,
3437
+ isInteractive = Boolean(process.stdin.isTTY && process.stdout.isTTY)
3438
+ } = {}) {
3439
+ const cfg = readConfig();
3440
+ if (cfg.peerConnectPrompted) {
3441
+ return { prompted: false, peerConnect: cfg.peerConnect === true };
3442
+ }
3443
+ if (!isInteractive) {
3444
+ return { prompted: false, peerConnect: cfg.peerConnect === true };
3445
+ }
3446
+ const rl = createInterface({ input, output });
3447
+ const answer = await new Promise((resolve2) => {
3448
+ rl.question(PROMPT, (a) => {
3449
+ rl.close();
3450
+ resolve2(String(a).trim().toLowerCase());
3451
+ });
3452
+ });
3453
+ const optedIn = answer === "y" || answer === "yes";
3454
+ writeConfig({ peerConnect: optedIn, peerConnectPrompted: true });
3455
+ output.write(
3456
+ optedIn ? "\n Peer-connect ON \u2014 peers & founders may surface in your spinner.\n Turn it off anytime: terminalhire config --connect off\n\n" : "\n Peer-connect stays OFF. Enable anytime: terminalhire config --connect on\n\n"
3457
+ );
3458
+ return { prompted: true, peerConnect: optedIn };
3459
+ }
3460
+ var PROMPT;
3461
+ var init_peer_connect_prompt = __esm({
3462
+ "bin/peer-connect-prompt.js"() {
3463
+ "use strict";
3464
+ init_config();
3465
+ PROMPT = [
3466
+ "",
3467
+ " Connect with other builders?",
3468
+ "",
3469
+ " See peers and founders building what you're building \u2014 matched on your machine,",
3470
+ " so nothing about you leaves it. The only thing ever sent is anonymous: the",
3471
+ " matched person's public username, never yours, never your profile or fingerprint.",
3472
+ "",
3473
+ " Change it anytime: terminalhire config --connect on|off",
3474
+ "",
3475
+ " Opt in? [y/N]: "
3476
+ ].join("\n");
3477
+ }
3478
+ });
3479
+
3380
3480
  // bin/jpi-login.js
3381
3481
  var jpi_login_exports = {};
3382
3482
  __export(jpi_login_exports, {
@@ -3411,9 +3511,9 @@ async function runLogin() {
3411
3511
  if (process.env["TERMINALHIRE_GITHUB_MOCK"] === "1" || process.env["JPI_GITHUB_MOCK"] === "1") {
3412
3512
  const { createRequire: createRequire2 } = await import("module");
3413
3513
  const { fileURLToPath: fileURLToPath7 } = await import("url");
3414
- const { join: join20, dirname: dirname3 } = await import("path");
3514
+ const { join: join21, dirname: dirname3 } = await import("path");
3415
3515
  const __dirname6 = fileURLToPath7(new URL(".", import.meta.url));
3416
- const fixturePath = join20(__dirname6, "../../fixtures/github-sample.json");
3516
+ const fixturePath = join21(__dirname6, "../../fixtures/github-sample.json");
3417
3517
  const { readFileSync: readFileSync19 } = await import("fs");
3418
3518
  ghProfile = JSON.parse(readFileSync19(fixturePath, "utf8"));
3419
3519
  } else {
@@ -3486,6 +3586,11 @@ async function runLogin() {
3486
3586
  } catch {
3487
3587
  }
3488
3588
  }
3589
+ try {
3590
+ const { maybePromptPeerConnect: maybePromptPeerConnect2 } = await Promise.resolve().then(() => (init_peer_connect_prompt(), peer_connect_prompt_exports));
3591
+ await maybePromptPeerConnect2();
3592
+ } catch {
3593
+ }
3489
3594
  console.log(" Run `terminalhire jobs` to see matching roles using your enriched profile.");
3490
3595
  console.log("");
3491
3596
  } catch (err) {
@@ -3532,14 +3637,14 @@ var jpi_jobs_exports = {};
3532
3637
  __export(jpi_jobs_exports, {
3533
3638
  run: () => run2
3534
3639
  });
3535
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, existsSync as existsSync3 } from "fs";
3536
- import { join as join4 } from "path";
3537
- import { homedir as homedir3 } from "os";
3538
- import { createInterface } from "readline";
3640
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, existsSync as existsSync4 } from "fs";
3641
+ import { join as join5 } from "path";
3642
+ import { homedir as homedir4 } from "os";
3643
+ import { createInterface as createInterface2 } from "readline";
3539
3644
  import { fileURLToPath as fileURLToPath2 } from "url";
3540
3645
  function readIndexCache() {
3541
3646
  try {
3542
- const raw = readFileSync4(INDEX_CACHE_FILE, "utf8");
3647
+ const raw = readFileSync5(INDEX_CACHE_FILE, "utf8");
3543
3648
  const entry = JSON.parse(raw);
3544
3649
  if (Date.now() - entry.ts < INDEX_TTL_MS) return entry.index;
3545
3650
  return null;
@@ -3548,8 +3653,8 @@ function readIndexCache() {
3548
3653
  }
3549
3654
  }
3550
3655
  function writeIndexCache(index) {
3551
- mkdirSync3(TERMINALHIRE_DIR3, { recursive: true });
3552
- writeFileSync3(INDEX_CACHE_FILE, JSON.stringify({ ts: Date.now(), index }), "utf8");
3656
+ mkdirSync4(TERMINALHIRE_DIR4, { recursive: true });
3657
+ writeFileSync4(INDEX_CACHE_FILE, JSON.stringify({ ts: Date.now(), index }), "utf8");
3553
3658
  }
3554
3659
  async function fetchIndex() {
3555
3660
  const cached = readIndexCache();
@@ -3563,7 +3668,7 @@ async function fetchIndex() {
3563
3668
  return index;
3564
3669
  }
3565
3670
  function prompt(question) {
3566
- const rl = createInterface({ input: process.stdin, output: process.stdout });
3671
+ const rl = createInterface2({ input: process.stdin, output: process.stdout });
3567
3672
  return new Promise((resolve2) => {
3568
3673
  rl.question(question, (answer) => {
3569
3674
  rl.close();
@@ -3714,10 +3819,10 @@ async function run2() {
3714
3819
  acceptance: profile.acceptance
3715
3820
  });
3716
3821
  try {
3717
- const cacheRaw = readFileSync4(INDEX_CACHE_FILE, "utf8");
3822
+ const cacheRaw = readFileSync5(INDEX_CACHE_FILE, "utf8");
3718
3823
  const cacheEntry = JSON.parse(cacheRaw);
3719
3824
  cacheEntry.matchCount = results.length;
3720
- writeFileSync3(INDEX_CACHE_FILE, JSON.stringify(cacheEntry), "utf8");
3825
+ writeFileSync4(INDEX_CACHE_FILE, JSON.stringify(cacheEntry), "utf8");
3721
3826
  } catch {
3722
3827
  }
3723
3828
  if (results.length === 0) {
@@ -3762,13 +3867,13 @@ Open this URL to apply directly (no data shared):
3762
3867
  process.exit(1);
3763
3868
  }
3764
3869
  }
3765
- var __dirname, TERMINALHIRE_DIR3, INDEX_CACHE_FILE, INDEX_TTL_MS, API_URL, DEFAULT_LIMIT, args, limitArg, LIMIT, REMOTE_ONLY, SHOW_ALL;
3870
+ var __dirname, TERMINALHIRE_DIR4, INDEX_CACHE_FILE, INDEX_TTL_MS, API_URL, DEFAULT_LIMIT, args, limitArg, LIMIT, REMOTE_ONLY, SHOW_ALL;
3766
3871
  var init_jpi_jobs = __esm({
3767
3872
  "bin/jpi-jobs.js"() {
3768
3873
  "use strict";
3769
3874
  __dirname = fileURLToPath2(new URL(".", import.meta.url));
3770
- TERMINALHIRE_DIR3 = join4(homedir3(), ".terminalhire");
3771
- INDEX_CACHE_FILE = join4(TERMINALHIRE_DIR3, "index-cache.json");
3875
+ TERMINALHIRE_DIR4 = join5(homedir4(), ".terminalhire");
3876
+ INDEX_CACHE_FILE = join5(TERMINALHIRE_DIR4, "index-cache.json");
3772
3877
  INDEX_TTL_MS = 15 * 60 * 1e3;
3773
3878
  API_URL = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
3774
3879
  DEFAULT_LIMIT = 10;
@@ -3780,19 +3885,13 @@ var init_jpi_jobs = __esm({
3780
3885
  }
3781
3886
  });
3782
3887
 
3783
- // bin/jpi-devs.js
3784
- var jpi_devs_exports = {};
3785
- __export(jpi_devs_exports, {
3786
- reportMatched: () => reportMatched,
3787
- run: () => run3
3788
- });
3789
- import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4 } from "fs";
3790
- import { join as join5 } from "path";
3791
- import { homedir as homedir4 } from "os";
3792
- import { createInterface as createInterface2 } from "readline";
3888
+ // bin/directory.js
3889
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
3890
+ import { join as join6 } from "path";
3891
+ import { homedir as homedir5 } from "os";
3793
3892
  function readDirectoryCache() {
3794
3893
  try {
3795
- const entry = JSON.parse(readFileSync5(DIRECTORY_CACHE_FILE, "utf8"));
3894
+ const entry = JSON.parse(readFileSync6(DIRECTORY_CACHE_FILE, "utf8"));
3796
3895
  if (typeof entry.ts === "number" && Number.isFinite(entry.ts) && Date.now() - entry.ts < INDEX_TTL_MS2) {
3797
3896
  return { index: entry.index, ts: entry.ts };
3798
3897
  }
@@ -3802,12 +3901,12 @@ function readDirectoryCache() {
3802
3901
  }
3803
3902
  }
3804
3903
  function writeDirectoryCache(index) {
3805
- mkdirSync4(TERMINALHIRE_DIR4, { recursive: true });
3806
- writeFileSync4(DIRECTORY_CACHE_FILE, JSON.stringify({ ts: Date.now(), index }), "utf8");
3904
+ mkdirSync5(TERMINALHIRE_DIR5, { recursive: true });
3905
+ writeFileSync5(DIRECTORY_CACHE_FILE, JSON.stringify({ ts: Date.now(), index }), "utf8");
3807
3906
  }
3808
3907
  function readProject() {
3809
3908
  try {
3810
- return JSON.parse(readFileSync5(PROJECT_FILE, "utf8"));
3909
+ return JSON.parse(readFileSync6(PROJECT_FILE, "utf8"));
3811
3910
  } catch {
3812
3911
  return null;
3813
3912
  }
@@ -3818,13 +3917,13 @@ function relativeTime(ts) {
3818
3917
  const mins = Math.round(secs / 60);
3819
3918
  return mins < 60 ? `${mins}m ago` : `${Math.round(mins / 60)}h ago`;
3820
3919
  }
3821
- async function fetchDirectory() {
3920
+ async function fetchDirectory({ quiet = false } = {}) {
3822
3921
  const cached = readDirectoryCache();
3823
3922
  if (cached) {
3824
- console.log(`\u2713 Using cached directory (updated ${relativeTime(cached.ts)})`);
3923
+ if (!quiet) console.log(`\u2713 Using cached directory (updated ${relativeTime(cached.ts)})`);
3825
3924
  return cached.index;
3826
3925
  }
3827
- console.log(`\u21BB Refreshing builder directory from ${API_URL2}/api/directory...`);
3926
+ if (!quiet) console.log(`\u21BB Refreshing builder directory from ${API_URL2}/api/directory...`);
3828
3927
  const res = await fetch(`${API_URL2}/api/directory`, { signal: AbortSignal.timeout(1e4) });
3829
3928
  if (!res.ok) throw new Error(`/api/directory returned ${res.status}`);
3830
3929
  const index = await res.json();
@@ -3839,7 +3938,7 @@ function reportMatched(results, fetchImpl = fetch) {
3839
3938
  )
3840
3939
  ];
3841
3940
  if (logins.length === 0) return;
3842
- Promise.resolve(
3941
+ return Promise.resolve(
3843
3942
  fetchImpl(`${API_URL2}/api/directory/matched`, {
3844
3943
  method: "POST",
3845
3944
  headers: { "Content-Type": "application/json" },
@@ -3851,8 +3950,27 @@ function reportMatched(results, fetchImpl = fetch) {
3851
3950
  } catch {
3852
3951
  }
3853
3952
  }
3953
+ var TERMINALHIRE_DIR5, DIRECTORY_CACHE_FILE, PROJECT_FILE, INDEX_TTL_MS2, API_URL2;
3954
+ var init_directory2 = __esm({
3955
+ "bin/directory.js"() {
3956
+ "use strict";
3957
+ TERMINALHIRE_DIR5 = join6(homedir5(), ".terminalhire");
3958
+ DIRECTORY_CACHE_FILE = join6(TERMINALHIRE_DIR5, "directory-cache.json");
3959
+ PROJECT_FILE = join6(TERMINALHIRE_DIR5, "project.json");
3960
+ INDEX_TTL_MS2 = 15 * 60 * 1e3;
3961
+ API_URL2 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
3962
+ }
3963
+ });
3964
+
3965
+ // bin/jpi-devs.js
3966
+ var jpi_devs_exports = {};
3967
+ __export(jpi_devs_exports, {
3968
+ reportMatched: () => reportMatched,
3969
+ run: () => run3
3970
+ });
3971
+ import { createInterface as createInterface3 } from "readline";
3854
3972
  function prompt2(question) {
3855
- const rl = createInterface2({ input: process.stdin, output: process.stdout });
3973
+ const rl = createInterface3({ input: process.stdin, output: process.stdout });
3856
3974
  return new Promise((resolve2) => {
3857
3975
  rl.question(question, (answer) => {
3858
3976
  rl.close();
@@ -3862,7 +3980,7 @@ function prompt2(question) {
3862
3980
  }
3863
3981
  function credentialUrl(job) {
3864
3982
  const u = job.url ?? "";
3865
- return u.startsWith("http") ? u : `${API_URL2}${u}`;
3983
+ return u.startsWith("http") ? u : `${API_URL3}${u}`;
3866
3984
  }
3867
3985
  function linkTitle2(title, url) {
3868
3986
  const isTTY = process.stdout.isTTY;
@@ -3947,15 +4065,12 @@ Open this public credential (no data shared):
3947
4065
  process.exit(1);
3948
4066
  }
3949
4067
  }
3950
- var TERMINALHIRE_DIR4, DIRECTORY_CACHE_FILE, PROJECT_FILE, INDEX_TTL_MS2, API_URL2, DEFAULT_LIMIT2, args2, limitArg2, LIMIT2, SHOW_ALL2, AS_PROJECT;
4068
+ var API_URL3, DEFAULT_LIMIT2, args2, limitArg2, LIMIT2, SHOW_ALL2, AS_PROJECT;
3951
4069
  var init_jpi_devs = __esm({
3952
4070
  "bin/jpi-devs.js"() {
3953
4071
  "use strict";
3954
- TERMINALHIRE_DIR4 = join5(homedir4(), ".terminalhire");
3955
- DIRECTORY_CACHE_FILE = join5(TERMINALHIRE_DIR4, "directory-cache.json");
3956
- PROJECT_FILE = join5(TERMINALHIRE_DIR4, "project.json");
3957
- INDEX_TTL_MS2 = 15 * 60 * 1e3;
3958
- API_URL2 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
4072
+ init_directory2();
4073
+ API_URL3 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
3959
4074
  DEFAULT_LIMIT2 = 10;
3960
4075
  args2 = process.argv.slice(2);
3961
4076
  limitArg2 = args2.indexOf("--limit");
@@ -3970,19 +4085,19 @@ var jpi_project_exports = {};
3970
4085
  __export(jpi_project_exports, {
3971
4086
  run: () => run4
3972
4087
  });
3973
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, mkdirSync as mkdirSync5 } from "fs";
3974
- import { join as join6 } from "path";
3975
- import { homedir as homedir5 } from "os";
3976
- import { createInterface as createInterface3 } from "readline";
4088
+ import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6 } from "fs";
4089
+ import { join as join7 } from "path";
4090
+ import { homedir as homedir6 } from "os";
4091
+ import { createInterface as createInterface4 } from "readline";
3977
4092
  function readProject2() {
3978
4093
  try {
3979
- return JSON.parse(readFileSync6(PROJECT_FILE2, "utf8"));
4094
+ return JSON.parse(readFileSync7(PROJECT_FILE2, "utf8"));
3980
4095
  } catch {
3981
4096
  return null;
3982
4097
  }
3983
4098
  }
3984
4099
  function promptRaw(question) {
3985
- const rl = createInterface3({ input: process.stdin, output: process.stdout });
4100
+ const rl = createInterface4({ input: process.stdin, output: process.stdout });
3986
4101
  return new Promise((resolve2) => {
3987
4102
  rl.question(question, (answer) => {
3988
4103
  rl.close();
@@ -4052,8 +4167,8 @@ async function run4() {
4052
4167
  prefs: {},
4053
4168
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
4054
4169
  };
4055
- mkdirSync5(TERMINALHIRE_DIR5, { recursive: true });
4056
- writeFileSync5(PROJECT_FILE2, JSON.stringify(project, null, 2), "utf8");
4170
+ mkdirSync6(TERMINALHIRE_DIR6, { recursive: true });
4171
+ writeFileSync6(PROJECT_FILE2, JSON.stringify(project, null, 2), "utf8");
4057
4172
  console.log(`
4058
4173
  \u2726 Project saved locally (never sent): ${title}`);
4059
4174
  console.log(` Skills: ${skillTags.join(", ")}`);
@@ -4064,12 +4179,12 @@ async function run4() {
4064
4179
  process.exit(1);
4065
4180
  }
4066
4181
  }
4067
- var TERMINALHIRE_DIR5, PROJECT_FILE2, args3, SHOW, declarationArg;
4182
+ var TERMINALHIRE_DIR6, PROJECT_FILE2, args3, SHOW, declarationArg;
4068
4183
  var init_jpi_project = __esm({
4069
4184
  "bin/jpi-project.js"() {
4070
4185
  "use strict";
4071
- TERMINALHIRE_DIR5 = join6(homedir5(), ".terminalhire");
4072
- PROJECT_FILE2 = join6(TERMINALHIRE_DIR5, "project.json");
4186
+ TERMINALHIRE_DIR6 = join7(homedir6(), ".terminalhire");
4187
+ PROJECT_FILE2 = join7(TERMINALHIRE_DIR6, "project.json");
4073
4188
  args3 = process.argv.slice(2);
4074
4189
  SHOW = args3.includes("--show");
4075
4190
  declarationArg = args3.filter((a) => !a.startsWith("--")).join(" ").trim();
@@ -4081,13 +4196,13 @@ var jpi_bounties_exports = {};
4081
4196
  __export(jpi_bounties_exports, {
4082
4197
  run: () => run5
4083
4198
  });
4084
- import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, mkdirSync as mkdirSync6 } from "fs";
4085
- import { join as join7 } from "path";
4086
- import { homedir as homedir6 } from "os";
4087
- import { createInterface as createInterface4 } from "readline";
4199
+ import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7 } from "fs";
4200
+ import { join as join8 } from "path";
4201
+ import { homedir as homedir7 } from "os";
4202
+ import { createInterface as createInterface5 } from "readline";
4088
4203
  function readIndexCache2() {
4089
4204
  try {
4090
- const entry = JSON.parse(readFileSync7(INDEX_CACHE_FILE2, "utf8"));
4205
+ const entry = JSON.parse(readFileSync8(INDEX_CACHE_FILE2, "utf8"));
4091
4206
  if (Date.now() - entry.ts < INDEX_TTL_MS3) return entry.index;
4092
4207
  return null;
4093
4208
  } catch {
@@ -4095,20 +4210,20 @@ function readIndexCache2() {
4095
4210
  }
4096
4211
  }
4097
4212
  function writeIndexCache2(index) {
4098
- mkdirSync6(TERMINALHIRE_DIR6, { recursive: true });
4099
- writeFileSync6(INDEX_CACHE_FILE2, JSON.stringify({ ts: Date.now(), index }), "utf8");
4213
+ mkdirSync7(TERMINALHIRE_DIR7, { recursive: true });
4214
+ writeFileSync7(INDEX_CACHE_FILE2, JSON.stringify({ ts: Date.now(), index }), "utf8");
4100
4215
  }
4101
4216
  async function fetchIndex2() {
4102
4217
  const cached = readIndexCache2();
4103
4218
  if (cached) return cached;
4104
- const res = await fetch(`${API_URL3}/api/index`, { signal: AbortSignal.timeout(1e4) });
4219
+ const res = await fetch(`${API_URL4}/api/index`, { signal: AbortSignal.timeout(1e4) });
4105
4220
  if (!res.ok) throw new Error(`/api/index returned ${res.status}`);
4106
4221
  const index = await res.json();
4107
4222
  writeIndexCache2(index);
4108
4223
  return index;
4109
4224
  }
4110
4225
  function prompt3(question) {
4111
- const rl = createInterface4({ input: process.stdin, output: process.stdout });
4226
+ const rl = createInterface5({ input: process.stdin, output: process.stdout });
4112
4227
  return new Promise((resolve2) => {
4113
4228
  rl.question(question, (answer) => {
4114
4229
  rl.close();
@@ -4142,7 +4257,7 @@ ${i + 1}. ${linkTitle3(job.title, job.url)}`);
4142
4257
  }
4143
4258
  async function run5() {
4144
4259
  try {
4145
- console.log(`Fetching bounty index from ${API_URL3}/api/index...`);
4260
+ console.log(`Fetching bounty index from ${API_URL4}/api/index...`);
4146
4261
  const index = await fetchIndex2();
4147
4262
  let bounties = (index.jobs ?? []).filter((j) => j.source === "bounty");
4148
4263
  if (PRICED_ONLY) bounties = bounties.filter((j) => j.bounty?.amountUSD != null);
@@ -4200,14 +4315,14 @@ Open this to claim/work the bounty (you go straight to the source \u2014 we neve
4200
4315
  process.exit(1);
4201
4316
  }
4202
4317
  }
4203
- var TERMINALHIRE_DIR6, INDEX_CACHE_FILE2, INDEX_TTL_MS3, API_URL3, DEFAULT_LIMIT3, args4, limitArg3, LIMIT3, PRICED_ONLY, SHOW_ALL3, WINNABLE_ONLY, EFFORT_LABEL;
4318
+ var TERMINALHIRE_DIR7, INDEX_CACHE_FILE2, INDEX_TTL_MS3, API_URL4, DEFAULT_LIMIT3, args4, limitArg3, LIMIT3, PRICED_ONLY, SHOW_ALL3, WINNABLE_ONLY, EFFORT_LABEL;
4204
4319
  var init_jpi_bounties = __esm({
4205
4320
  "bin/jpi-bounties.js"() {
4206
4321
  "use strict";
4207
- TERMINALHIRE_DIR6 = join7(homedir6(), ".terminalhire");
4208
- INDEX_CACHE_FILE2 = join7(TERMINALHIRE_DIR6, "index-cache.json");
4322
+ TERMINALHIRE_DIR7 = join8(homedir7(), ".terminalhire");
4323
+ INDEX_CACHE_FILE2 = join8(TERMINALHIRE_DIR7, "index-cache.json");
4209
4324
  INDEX_TTL_MS3 = 15 * 60 * 1e3;
4210
- API_URL3 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
4325
+ API_URL4 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
4211
4326
  DEFAULT_LIMIT3 = 15;
4212
4327
  args4 = process.argv.slice(2);
4213
4328
  limitArg3 = args4.indexOf("--limit");
@@ -4230,26 +4345,26 @@ __export(claims_exports, {
4230
4345
  removeClaim: () => removeClaim,
4231
4346
  updateClaim: () => updateClaim
4232
4347
  });
4233
- import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, mkdirSync as mkdirSync7, renameSync, existsSync as existsSync4 } from "fs";
4234
- import { join as join8 } from "path";
4235
- import { homedir as homedir7 } from "os";
4348
+ import { readFileSync as readFileSync9, writeFileSync as writeFileSync8, mkdirSync as mkdirSync8, renameSync, existsSync as existsSync5 } from "fs";
4349
+ import { join as join9 } from "path";
4350
+ import { homedir as homedir8 } from "os";
4236
4351
  function nowISO() {
4237
4352
  return (/* @__PURE__ */ new Date()).toISOString();
4238
4353
  }
4239
4354
  function readClaims() {
4240
4355
  try {
4241
- if (!existsSync4(CLAIMS_FILE)) return [];
4242
- const data = JSON.parse(readFileSync8(CLAIMS_FILE, "utf8"));
4356
+ if (!existsSync5(CLAIMS_FILE)) return [];
4357
+ const data = JSON.parse(readFileSync9(CLAIMS_FILE, "utf8"));
4243
4358
  return Array.isArray(data?.claims) ? data.claims : [];
4244
4359
  } catch {
4245
4360
  return [];
4246
4361
  }
4247
4362
  }
4248
4363
  function writeClaims(claims) {
4249
- mkdirSync7(TERMINALHIRE_DIR7, { recursive: true });
4364
+ mkdirSync8(TERMINALHIRE_DIR8, { recursive: true });
4250
4365
  const tmp = `${CLAIMS_FILE}.tmp`;
4251
4366
  const payload = { claims };
4252
- writeFileSync7(tmp, JSON.stringify(payload, null, 2), "utf8");
4367
+ writeFileSync8(tmp, JSON.stringify(payload, null, 2), "utf8");
4253
4368
  renameSync(tmp, CLAIMS_FILE);
4254
4369
  }
4255
4370
  function findClaim(id) {
@@ -4302,12 +4417,12 @@ function acceptedPRRate(claims = readClaims()) {
4302
4417
  const merged = claims.filter((c) => c.state === "merged").length;
4303
4418
  return { merged, total, rate: total === 0 ? 0 : merged / total };
4304
4419
  }
4305
- var TERMINALHIRE_DIR7, CLAIMS_FILE, TERMINAL_STATES;
4420
+ var TERMINALHIRE_DIR8, CLAIMS_FILE, TERMINAL_STATES;
4306
4421
  var init_claims = __esm({
4307
4422
  "src/claims.ts"() {
4308
4423
  "use strict";
4309
- TERMINALHIRE_DIR7 = join8(homedir7(), ".terminalhire");
4310
- CLAIMS_FILE = join8(TERMINALHIRE_DIR7, "claims.json");
4424
+ TERMINALHIRE_DIR8 = join9(homedir8(), ".terminalhire");
4425
+ CLAIMS_FILE = join9(TERMINALHIRE_DIR8, "claims.json");
4311
4426
  TERMINAL_STATES = /* @__PURE__ */ new Set(["merged", "abandoned"]);
4312
4427
  }
4313
4428
  });
@@ -4317,18 +4432,18 @@ var jpi_claim_exports = {};
4317
4432
  __export(jpi_claim_exports, {
4318
4433
  run: () => run6
4319
4434
  });
4320
- import { readFileSync as readFileSync9, existsSync as existsSync5 } from "fs";
4321
- import { join as join9 } from "path";
4322
- import { homedir as homedir8 } from "os";
4435
+ import { readFileSync as readFileSync10, existsSync as existsSync6 } from "fs";
4436
+ import { join as join10 } from "path";
4437
+ import { homedir as homedir9 } from "os";
4323
4438
  import { execFile } from "child_process";
4324
4439
  import { promisify } from "util";
4325
- import { createInterface as createInterface5 } from "readline";
4440
+ import { createInterface as createInterface6 } from "readline";
4326
4441
  async function sh(cmd, args5, opts = {}) {
4327
4442
  const { stdout } = await pExecFile(cmd, args5, { ...opts, shell: false, maxBuffer: 16 * 1024 * 1024 });
4328
4443
  return String(stdout).trim();
4329
4444
  }
4330
4445
  async function confirm(question) {
4331
- const rl = createInterface5({ input: process.stdin, output: process.stdout });
4446
+ const rl = createInterface6({ input: process.stdin, output: process.stdout });
4332
4447
  try {
4333
4448
  const ans = await new Promise((resolve2) => rl.question(question, resolve2));
4334
4449
  return /^y(es)?$/i.test(String(ans).trim());
@@ -4366,8 +4481,8 @@ function parseRepoFromRemote(url) {
4366
4481
  }
4367
4482
  function findBountyInCache(bountyId) {
4368
4483
  try {
4369
- if (!existsSync5(INDEX_CACHE_FILE3)) return null;
4370
- const entry = JSON.parse(readFileSync9(INDEX_CACHE_FILE3, "utf8"));
4484
+ if (!existsSync6(INDEX_CACHE_FILE3)) return null;
4485
+ const entry = JSON.parse(readFileSync10(INDEX_CACHE_FILE3, "utf8"));
4371
4486
  const jobs = entry?.index?.jobs ?? [];
4372
4487
  const job = jobs.find((j) => j.id === bountyId && j.source === "bounty");
4373
4488
  return job ?? null;
@@ -4871,12 +4986,12 @@ async function run6() {
4871
4986
  process.exit(1);
4872
4987
  }
4873
4988
  }
4874
- var TERMINALHIRE_DIR8, INDEX_CACHE_FILE3, GH_API, GH_HEADERS, pExecFile, VALUE_FLAGS;
4989
+ var TERMINALHIRE_DIR9, INDEX_CACHE_FILE3, GH_API, GH_HEADERS, pExecFile, VALUE_FLAGS;
4875
4990
  var init_jpi_claim = __esm({
4876
4991
  "bin/jpi-claim.js"() {
4877
4992
  "use strict";
4878
- TERMINALHIRE_DIR8 = join9(homedir8(), ".terminalhire");
4879
- INDEX_CACHE_FILE3 = join9(TERMINALHIRE_DIR8, "index-cache.json");
4993
+ TERMINALHIRE_DIR9 = join10(homedir9(), ".terminalhire");
4994
+ INDEX_CACHE_FILE3 = join10(TERMINALHIRE_DIR9, "index-cache.json");
4880
4995
  GH_API = "https://api.github.com";
4881
4996
  GH_HEADERS = { "User-Agent": "terminalhire-claim", Accept: "application/vnd.github+json" };
4882
4997
  pExecFile = promisify(execFile);
@@ -5160,7 +5275,7 @@ function finalize(build) {
5160
5275
  };
5161
5276
  }
5162
5277
  function reconstruct(files, opts = {}) {
5163
- const join20 = opts.joinSidechains !== false;
5278
+ const join21 = opts.joinSidechains !== false;
5164
5279
  const mains = [];
5165
5280
  const sidechains = [];
5166
5281
  for (const file of files) {
@@ -5185,7 +5300,7 @@ function reconstruct(files, opts = {}) {
5185
5300
  }
5186
5301
  const orphanedSidechainPaths = [];
5187
5302
  const joinedPaths = /* @__PURE__ */ new Set();
5188
- if (join20) {
5303
+ if (join21) {
5189
5304
  const sidechainsBySession = /* @__PURE__ */ new Map();
5190
5305
  for (const sc of sidechains) {
5191
5306
  const acc = sidechainsBySession.get(sc.sessionId) ?? [];
@@ -5739,14 +5854,14 @@ __export(trajectory_exports, {
5739
5854
  runTrajectoryPush: () => runTrajectoryPush
5740
5855
  });
5741
5856
  import {
5742
- existsSync as existsSync6,
5743
- mkdirSync as mkdirSync8,
5744
- readFileSync as readFileSync10,
5857
+ existsSync as existsSync7,
5858
+ mkdirSync as mkdirSync9,
5859
+ readFileSync as readFileSync11,
5745
5860
  readdirSync,
5746
- writeFileSync as writeFileSync8
5861
+ writeFileSync as writeFileSync9
5747
5862
  } from "fs";
5748
- import { homedir as homedir9 } from "os";
5749
- import { join as join10 } from "path";
5863
+ import { homedir as homedir10 } from "os";
5864
+ import { join as join11 } from "path";
5750
5865
  function isRecord4(value) {
5751
5866
  return typeof value === "object" && value !== null && !Array.isArray(value);
5752
5867
  }
@@ -5778,7 +5893,7 @@ function findJsonlFiles(dir) {
5778
5893
  return out;
5779
5894
  }
5780
5895
  for (const entry of entries) {
5781
- const full = join10(dir, entry.name);
5896
+ const full = join11(dir, entry.name);
5782
5897
  if (entry.isDirectory()) {
5783
5898
  out.push(...findJsonlFiles(full));
5784
5899
  } else if (entry.isFile() && entry.name.endsWith(".jsonl")) {
@@ -5792,7 +5907,7 @@ function loadCorpus(paths) {
5792
5907
  for (const path of paths) {
5793
5908
  let text;
5794
5909
  try {
5795
- text = readFileSync10(path, "utf8");
5910
+ text = readFileSync11(path, "utf8");
5796
5911
  } catch {
5797
5912
  continue;
5798
5913
  }
@@ -5891,12 +6006,12 @@ function renderMarkdown(view) {
5891
6006
  return lines.join("\n");
5892
6007
  }
5893
6008
  function writeExportArtifacts(score, markdown) {
5894
- const dir = join10(homedir9(), ".terminalhire");
5895
- mkdirSync8(dir, { recursive: true });
5896
- const jsonPath = join10(dir, "trajectory-export.json");
5897
- const mdPath = join10(dir, "trajectory-export.md");
5898
- writeFileSync8(jsonPath, JSON.stringify(score, null, 2) + "\n", "utf8");
5899
- writeFileSync8(mdPath, markdown, "utf8");
6009
+ const dir = join11(homedir10(), ".terminalhire");
6010
+ mkdirSync9(dir, { recursive: true });
6011
+ const jsonPath = join11(dir, "trajectory-export.json");
6012
+ const mdPath = join11(dir, "trajectory-export.md");
6013
+ writeFileSync9(jsonPath, JSON.stringify(score, null, 2) + "\n", "utf8");
6014
+ writeFileSync9(mdPath, markdown, "utf8");
5900
6015
  return { jsonPath, mdPath };
5901
6016
  }
5902
6017
  function renderInward(allNodes, view, files) {
@@ -5915,8 +6030,8 @@ function renderInward(allNodes, view, files) {
5915
6030
  console.log("");
5916
6031
  }
5917
6032
  function buildTrajectory() {
5918
- const projectsDir = join10(homedir9(), ".claude", "projects");
5919
- if (!existsSync6(projectsDir)) return null;
6033
+ const projectsDir = join11(homedir10(), ".claude", "projects");
6034
+ if (!existsSync7(projectsDir)) return null;
5920
6035
  const paths = findJsonlFiles(projectsDir);
5921
6036
  if (paths.length === 0) return null;
5922
6037
  const files = loadCorpus(paths);
@@ -5989,8 +6104,8 @@ function defaultPushDeps() {
5989
6104
  }
5990
6105
  },
5991
6106
  prompt: async (question) => {
5992
- const { createInterface: createInterface10 } = await import("readline");
5993
- const rl = createInterface10({ input: process.stdin, output: process.stdout });
6107
+ const { createInterface: createInterface11 } = await import("readline");
6108
+ const rl = createInterface11({ input: process.stdin, output: process.stdout });
5994
6109
  return new Promise((res) => {
5995
6110
  rl.question(question, (answer) => {
5996
6111
  rl.close();
@@ -6240,8 +6355,8 @@ function defaultIntroDeps() {
6240
6355
  }
6241
6356
  },
6242
6357
  prompt: async (question) => {
6243
- const { createInterface: createInterface10 } = await import("readline");
6244
- const rl = createInterface10({ input: process.stdin, output: process.stdout });
6358
+ const { createInterface: createInterface11 } = await import("readline");
6359
+ const rl = createInterface11({ input: process.stdin, output: process.stdout });
6245
6360
  return new Promise((res) => {
6246
6361
  rl.question(question, (answer) => {
6247
6362
  rl.close();
@@ -6594,9 +6709,9 @@ var jpi_profile_exports = {};
6594
6709
  __export(jpi_profile_exports, {
6595
6710
  run: () => run9
6596
6711
  });
6597
- import { createInterface as createInterface6 } from "readline";
6712
+ import { createInterface as createInterface7 } from "readline";
6598
6713
  function prompt4(question) {
6599
- const rl = createInterface6({ input: process.stdin, output: process.stdout });
6714
+ const rl = createInterface7({ input: process.stdin, output: process.stdout });
6600
6715
  return new Promise((resolve2) => {
6601
6716
  rl.question(question, (answer) => {
6602
6717
  rl.close();
@@ -6677,9 +6792,9 @@ var signal_exports = {};
6677
6792
  __export(signal_exports, {
6678
6793
  extractFingerprint: () => extractFingerprint
6679
6794
  });
6680
- import { readFileSync as readFileSync11, readdirSync as readdirSync2 } from "fs";
6795
+ import { readFileSync as readFileSync12, readdirSync as readdirSync2 } from "fs";
6681
6796
  import { execFileSync } from "child_process";
6682
- import { join as join11 } from "path";
6797
+ import { join as join12 } from "path";
6683
6798
  function safeGit(args5, cwd) {
6684
6799
  try {
6685
6800
  return execFileSync("git", ["-C", cwd, ...args5], {
@@ -6707,20 +6822,20 @@ function isEmployerContext(cwd) {
6707
6822
  }
6708
6823
  function readJsonSafe(path) {
6709
6824
  try {
6710
- return JSON.parse(readFileSync11(path, "utf8"));
6825
+ return JSON.parse(readFileSync12(path, "utf8"));
6711
6826
  } catch {
6712
6827
  return null;
6713
6828
  }
6714
6829
  }
6715
6830
  function readFileSafe(path) {
6716
6831
  try {
6717
- return readFileSync11(path, "utf8");
6832
+ return readFileSync12(path, "utf8");
6718
6833
  } catch {
6719
6834
  return "";
6720
6835
  }
6721
6836
  }
6722
6837
  function tokensFromPackageJson(cwd) {
6723
- const pkg = readJsonSafe(join11(cwd, "package.json"));
6838
+ const pkg = readJsonSafe(join12(cwd, "package.json"));
6724
6839
  if (!pkg || typeof pkg !== "object") return [];
6725
6840
  const p = pkg;
6726
6841
  const deps = {
@@ -6734,9 +6849,9 @@ function workspaceMemberDirs(cwd) {
6734
6849
  const dirs = [cwd];
6735
6850
  for (const group of ["apps", "packages"]) {
6736
6851
  try {
6737
- const groupDir = join11(cwd, group);
6852
+ const groupDir = join12(cwd, group);
6738
6853
  for (const e of readdirSync2(groupDir, { withFileTypes: true })) {
6739
- if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(join11(groupDir, e.name));
6854
+ if (e.isDirectory() && !e.isSymbolicLink()) dirs.push(join12(groupDir, e.name));
6740
6855
  }
6741
6856
  } catch {
6742
6857
  }
@@ -6744,18 +6859,18 @@ function workspaceMemberDirs(cwd) {
6744
6859
  return dirs;
6745
6860
  }
6746
6861
  function tokensFromRequirementsTxt(cwd) {
6747
- const content = readFileSafe(join11(cwd, "requirements.txt"));
6862
+ const content = readFileSafe(join12(cwd, "requirements.txt"));
6748
6863
  if (!content) return [];
6749
6864
  return content.split("\n").map((l) => l.trim().split(/[>=<!\[;]/)[0].trim().toLowerCase()).filter(Boolean);
6750
6865
  }
6751
6866
  function tokensFromGoMod(cwd) {
6752
- const content = readFileSafe(join11(cwd, "go.mod"));
6867
+ const content = readFileSafe(join12(cwd, "go.mod"));
6753
6868
  if (!content) return [];
6754
6869
  const requires = Array.from(content.matchAll(/^\s+([^\s]+)\s+v/gm)).map((m) => m[1].split("/").pop() ?? "").filter(Boolean);
6755
6870
  return ["go", ...requires];
6756
6871
  }
6757
6872
  function tokensFromCargoToml(cwd) {
6758
- const content = readFileSafe(join11(cwd, "Cargo.toml"));
6873
+ const content = readFileSafe(join12(cwd, "Cargo.toml"));
6759
6874
  if (!content) return [];
6760
6875
  const deps = [];
6761
6876
  let inDeps = false;
@@ -6776,7 +6891,7 @@ function tokensFromFileExtensions(cwd) {
6776
6891
  const tokens = [];
6777
6892
  const scanDirs = [cwd];
6778
6893
  try {
6779
- const srcDir = join11(cwd, "src");
6894
+ const srcDir = join12(cwd, "src");
6780
6895
  readdirSync2(srcDir);
6781
6896
  scanDirs.push(srcDir);
6782
6897
  } catch {
@@ -6976,22 +7091,8 @@ var jpi_config_exports = {};
6976
7091
  __export(jpi_config_exports, {
6977
7092
  run: () => run11
6978
7093
  });
6979
- import { readFileSync as readFileSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync9, existsSync as existsSync7 } from "fs";
6980
- import { join as join12 } from "path";
6981
- import { homedir as homedir10 } from "os";
6982
- function readConfig() {
6983
- try {
6984
- if (!existsSync7(CONFIG_FILE)) return { ...DEFAULT_CONFIG };
6985
- return { ...DEFAULT_CONFIG, ...JSON.parse(readFileSync12(CONFIG_FILE, "utf8")) };
6986
- } catch {
6987
- return { ...DEFAULT_CONFIG };
6988
- }
6989
- }
6990
- function writeConfig(patch) {
6991
- mkdirSync9(TERMINALHIRE_DIR9, { recursive: true });
6992
- const merged = { ...readConfig(), ...patch };
6993
- writeFileSync9(CONFIG_FILE, JSON.stringify(merged, null, 2) + "\n", "utf8");
6994
- }
7094
+ import { join as join13 } from "path";
7095
+ import { homedir as homedir11 } from "os";
6995
7096
  function parseNudgeMode(raw) {
6996
7097
  if (raw === "session" || raw === "always") return raw;
6997
7098
  const m = /^every:(\d+)$/.exec(raw);
@@ -7011,13 +7112,18 @@ async function run11() {
7011
7112
  if (envOverride) {
7012
7113
  console.log(` (overridden by TERMINALHIRE_NUDGE=${envOverride} at runtime)`);
7013
7114
  }
7014
- console.log(` config file: ${CONFIG_FILE}`);
7115
+ console.log(` peer-connect: ${cfg.peerConnect ? "on" : "off"} (ambient peer & founder surfacing; default off)`);
7116
+ console.log(` config file: ${CONFIG_FILE2}`);
7015
7117
  console.log("");
7016
7118
  console.log(" Valid nudge values:");
7017
7119
  console.log(" session \u2014 print at most once per Claude Code session (default)");
7018
7120
  console.log(" always \u2014 print every statusLine render when matches exist");
7019
7121
  console.log(" every:N \u2014 print every Nth render (e.g. every:3)");
7020
7122
  console.log("");
7123
+ console.log(" Peer-connect (--connect on|off):");
7124
+ console.log(" on \u2014 surface peers & founders in the spinner + send an anonymous matched signal");
7125
+ console.log(" off \u2014 no peer matching, no directory fetch, no signal (default)");
7126
+ console.log("");
7021
7127
  return;
7022
7128
  }
7023
7129
  const nudgeIdx = filtered.indexOf("--nudge");
@@ -7034,20 +7140,33 @@ async function run11() {
7034
7140
  }
7035
7141
  writeConfig({ nudge: parsed });
7036
7142
  console.log(` nudge set to: ${parsed}`);
7037
- console.log(` (saved to ${CONFIG_FILE})`);
7143
+ console.log(` (saved to ${CONFIG_FILE2})`);
7144
+ return;
7145
+ }
7146
+ const connectIdx = filtered.indexOf("--connect");
7147
+ if (connectIdx !== -1) {
7148
+ const value = filtered[connectIdx + 1];
7149
+ if (value !== "on" && value !== "off") {
7150
+ console.error("Error: --connect requires a value: on | off");
7151
+ process.exit(1);
7152
+ }
7153
+ writeConfig({ peerConnect: value === "on", peerConnectPrompted: true });
7154
+ console.log(` peer-connect set to: ${value}`);
7155
+ console.log(` (saved to ${CONFIG_FILE2})`);
7038
7156
  return;
7039
7157
  }
7040
7158
  console.error("Usage: terminalhire config --nudge <session|always|every:N>");
7159
+ console.error(" terminalhire config --connect <on|off>");
7041
7160
  console.error(" terminalhire config --show");
7042
7161
  process.exit(1);
7043
7162
  }
7044
- var TERMINALHIRE_DIR9, CONFIG_FILE, DEFAULT_CONFIG;
7163
+ var TERMINALHIRE_DIR10, CONFIG_FILE2;
7045
7164
  var init_jpi_config = __esm({
7046
7165
  "bin/jpi-config.js"() {
7047
7166
  "use strict";
7048
- TERMINALHIRE_DIR9 = join12(homedir10(), ".terminalhire");
7049
- CONFIG_FILE = join12(TERMINALHIRE_DIR9, "config.json");
7050
- DEFAULT_CONFIG = { nudge: "session" };
7167
+ init_config();
7168
+ TERMINALHIRE_DIR10 = join13(homedir11(), ".terminalhire");
7169
+ CONFIG_FILE2 = join13(TERMINALHIRE_DIR10, "config.json");
7051
7170
  }
7052
7171
  });
7053
7172
 
@@ -7058,6 +7177,7 @@ __export(spinner_exports, {
7058
7177
  applySpinnerTips: () => applySpinnerTips,
7059
7178
  applySpinnerVerbs: () => applySpinnerVerbs,
7060
7179
  buildContextVerbs: () => buildContextVerbs,
7180
+ buildPeerLine: () => buildPeerLine,
7061
7181
  buildSpinnerPool: () => buildSpinnerPool,
7062
7182
  buildTips: () => buildTips,
7063
7183
  clearSpinnerTips: () => clearSpinnerTips,
@@ -7075,8 +7195,8 @@ import {
7075
7195
  mkdirSync as mkdirSync10,
7076
7196
  renameSync as renameSync2
7077
7197
  } from "fs";
7078
- import { join as join13, dirname } from "path";
7079
- import { homedir as homedir11 } from "os";
7198
+ import { join as join14, dirname } from "path";
7199
+ import { homedir as homedir12 } from "os";
7080
7200
  function readJson(path, fallback) {
7081
7201
  try {
7082
7202
  return existsSync8(path) ? JSON.parse(readFileSync13(path, "utf8")) : fallback;
@@ -7094,7 +7214,7 @@ function titleCase(s) {
7094
7214
  return String(s || "").replace(/\b\w/g, (c) => c.toUpperCase());
7095
7215
  }
7096
7216
  function readSpinnerConfig() {
7097
- const cfg = readJson(CONFIG_FILE2, {});
7217
+ const cfg = readJson(CONFIG_FILE3, {});
7098
7218
  const spinner = cfg && typeof cfg.spinner === "object" ? cfg.spinner : {};
7099
7219
  const merged = { ...SPINNER_DEFAULTS, ...spinner };
7100
7220
  if (merged.mode !== "append" && merged.mode !== "replace") merged.mode = SPINNER_DEFAULTS.mode;
@@ -7174,10 +7294,18 @@ function buildContextVerbs(topMatches, sessionTags) {
7174
7294
  if (hasBounty) headers.push(`\u2726 Roles + \u{1F48E} paid bounties in your stack \u2014 link below`);
7175
7295
  return headers;
7176
7296
  }
7297
+ function buildPeerLine(topPeers) {
7298
+ const n = (Array.isArray(topPeers) ? topPeers : []).filter(Boolean).length;
7299
+ if (n < 1) return null;
7300
+ return n === 1 ? `\u25C6 1 builder matches what you're building \xB7 terminalhire devs` : `\u25C6 ${n} builders match what you're building \xB7 terminalhire devs`;
7301
+ }
7177
7302
  function buildSpinnerPool(topMatches, max = 6, opts = {}) {
7178
- const { sessionTags, frequency = "always" } = opts;
7303
+ const { sessionTags, frequency = "always", topPeers } = opts;
7179
7304
  const ranked = rankBySessionTags(topMatches, sessionTags);
7180
- if (!Array.isArray(ranked) || ranked.length === 0) return [];
7305
+ if (!Array.isArray(ranked) || ranked.length === 0) {
7306
+ const peerLine = buildPeerLine(topPeers);
7307
+ return peerLine ? [peerLine] : [];
7308
+ }
7181
7309
  const headers = buildContextVerbs(ranked, sessionTags);
7182
7310
  const cap = Math.max(1, verbCountForFrequency(frequency, headers.length));
7183
7311
  return [...headers.slice(0, cap), ctaVerb()];
@@ -7335,14 +7463,14 @@ function clearSpinnerTips() {
7335
7463
  }
7336
7464
  return { cleared: true };
7337
7465
  }
7338
- var TH_DIR, CLAUDE_SETTINGS, CONFIG_FILE2, SPINNER_STATE_FILE, SPINNER_DEFAULTS, VERB_INTROS;
7466
+ var TH_DIR, CLAUDE_SETTINGS, CONFIG_FILE3, SPINNER_STATE_FILE, SPINNER_DEFAULTS, VERB_INTROS;
7339
7467
  var init_spinner = __esm({
7340
7468
  "bin/spinner.js"() {
7341
7469
  "use strict";
7342
- TH_DIR = process.env["TERMINALHIRE_DIR"] || join13(homedir11(), ".terminalhire");
7343
- CLAUDE_SETTINGS = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join13(homedir11(), ".claude", "settings.json");
7344
- CONFIG_FILE2 = join13(TH_DIR, "config.json");
7345
- SPINNER_STATE_FILE = join13(TH_DIR, "spinner-state.json");
7470
+ TH_DIR = process.env["TERMINALHIRE_DIR"] || join14(homedir12(), ".terminalhire");
7471
+ CLAUDE_SETTINGS = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join14(homedir12(), ".claude", "settings.json");
7472
+ CONFIG_FILE3 = join14(TH_DIR, "config.json");
7473
+ SPINNER_STATE_FILE = join14(TH_DIR, "spinner-state.json");
7346
7474
  SPINNER_DEFAULTS = { enabled: false, mode: "append", max: 6, frequency: "sometimes" };
7347
7475
  VERB_INTROS = ["Matched:", "You\u2019d fit:", "Worth a look:", "On your radar:", "Fits your stack:"];
7348
7476
  }
@@ -7360,12 +7488,12 @@ import {
7360
7488
  existsSync as existsSync9,
7361
7489
  mkdirSync as mkdirSync11
7362
7490
  } from "fs";
7363
- import { join as join14 } from "path";
7364
- import { homedir as homedir12 } from "os";
7365
- import { createInterface as createInterface7 } from "readline";
7491
+ import { join as join15 } from "path";
7492
+ import { homedir as homedir13 } from "os";
7493
+ import { createInterface as createInterface8 } from "readline";
7366
7494
  function readConfig2() {
7367
7495
  try {
7368
- return existsSync9(CONFIG_FILE3) ? JSON.parse(readFileSync14(CONFIG_FILE3, "utf8")) : {};
7496
+ return existsSync9(CONFIG_FILE4) ? JSON.parse(readFileSync14(CONFIG_FILE4, "utf8")) : {};
7369
7497
  } catch {
7370
7498
  return {};
7371
7499
  }
@@ -7373,7 +7501,7 @@ function readConfig2() {
7373
7501
  function writeConfig2(patch) {
7374
7502
  mkdirSync11(TH_DIR2, { recursive: true });
7375
7503
  const merged = { ...readConfig2(), ...patch };
7376
- writeFileSync11(CONFIG_FILE3, JSON.stringify(merged, null, 2) + "\n", "utf8");
7504
+ writeFileSync11(CONFIG_FILE4, JSON.stringify(merged, null, 2) + "\n", "utf8");
7377
7505
  }
7378
7506
  function backupSettings() {
7379
7507
  if (!existsSync9(SETTINGS_PATH)) return null;
@@ -7383,7 +7511,7 @@ function backupSettings() {
7383
7511
  return backupPath;
7384
7512
  }
7385
7513
  function ask(question) {
7386
- const rl = createInterface7({ input: process.stdin, output: process.stdout });
7514
+ const rl = createInterface8({ input: process.stdin, output: process.stdout });
7387
7515
  return new Promise((res) => {
7388
7516
  rl.question(question, (answer) => {
7389
7517
  rl.close();
@@ -7531,15 +7659,15 @@ async function run12() {
7531
7659
  console.error("Usage: terminalhire spinner --on | --off | --show | --mode <append|replace> | --max N | --frequency <always|sometimes|rare>");
7532
7660
  process.exit(1);
7533
7661
  }
7534
- var TH_DIR2, CONFIG_FILE3, SETTINGS_PATH, CACHE_FILE;
7662
+ var TH_DIR2, CONFIG_FILE4, SETTINGS_PATH, CACHE_FILE;
7535
7663
  var init_jpi_spinner = __esm({
7536
7664
  "bin/jpi-spinner.js"() {
7537
7665
  "use strict";
7538
7666
  init_spinner();
7539
- TH_DIR2 = process.env["TERMINALHIRE_DIR"] || join14(homedir12(), ".terminalhire");
7540
- CONFIG_FILE3 = join14(TH_DIR2, "config.json");
7541
- SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join14(homedir12(), ".claude", "settings.json");
7542
- CACHE_FILE = join14(TH_DIR2, "index-cache.json");
7667
+ TH_DIR2 = process.env["TERMINALHIRE_DIR"] || join15(homedir13(), ".terminalhire");
7668
+ CONFIG_FILE4 = join15(TH_DIR2, "config.json");
7669
+ SETTINGS_PATH = process.env["TERMINALHIRE_CLAUDE_SETTINGS"] || join15(homedir13(), ".claude", "settings.json");
7670
+ CACHE_FILE = join15(TH_DIR2, "index-cache.json");
7543
7671
  }
7544
7672
  });
7545
7673
 
@@ -7549,11 +7677,11 @@ __export(jpi_sync_exports, {
7549
7677
  run: () => run13
7550
7678
  });
7551
7679
  import { readFileSync as readFileSync15, writeFileSync as writeFileSync12, mkdirSync as mkdirSync12, existsSync as existsSync10, rmSync as rmSync2 } from "fs";
7552
- import { join as join15 } from "path";
7553
- import { homedir as homedir13, hostname as osHostname } from "os";
7554
- import { createInterface as createInterface8 } from "readline";
7680
+ import { join as join16 } from "path";
7681
+ import { homedir as homedir14, hostname as osHostname } from "os";
7682
+ import { createInterface as createInterface9 } from "readline";
7555
7683
  function ask2(question) {
7556
- const rl = createInterface8({ input: process.stdin, output: process.stdout });
7684
+ const rl = createInterface9({ input: process.stdin, output: process.stdout });
7557
7685
  return new Promise((res) => {
7558
7686
  rl.question(question, (answer) => {
7559
7687
  rl.close();
@@ -7636,7 +7764,7 @@ async function runPush() {
7636
7764
  const fields = buildConsentFields(profile);
7637
7765
  renderPreview(fields);
7638
7766
  await new Promise((resolve2) => {
7639
- const rl = createInterface8({ input: process.stdin, output: process.stdout });
7767
+ const rl = createInterface9({ input: process.stdin, output: process.stdout });
7640
7768
  rl.question(
7641
7769
  " Press Enter to open your browser to authorize + consent (or Ctrl-C to cancel)... ",
7642
7770
  () => {
@@ -7834,7 +7962,7 @@ async function runDelete() {
7834
7962
  console.log("\n Requesting deletion...");
7835
7963
  let res;
7836
7964
  try {
7837
- res = await fetch(`${API_URL4}/api/profile-sync`, {
7965
+ res = await fetch(`${API_URL5}/api/profile-sync`, {
7838
7966
  method: "DELETE",
7839
7967
  headers: { "Content-Type": "application/json" },
7840
7968
  body: JSON.stringify({ consentToken, login, deleteToken }),
@@ -7884,14 +8012,14 @@ async function run13() {
7884
8012
  console.log(" This is NOT required to use terminalhire.");
7885
8013
  console.log("");
7886
8014
  }
7887
- var TH_DIR3, TIER1_MARKER, API_URL4, SYNC_BASE, POLL_INTERVAL_MS, POLL_TIMEOUT_MS, CONSENT_VERSION;
8015
+ var TH_DIR3, TIER1_MARKER, API_URL5, SYNC_BASE, POLL_INTERVAL_MS, POLL_TIMEOUT_MS, CONSENT_VERSION;
7888
8016
  var init_jpi_sync = __esm({
7889
8017
  "bin/jpi-sync.js"() {
7890
8018
  "use strict";
7891
8019
  init_open_url();
7892
- TH_DIR3 = process.env["TERMINALHIRE_DIR"] || join15(homedir13(), ".terminalhire");
7893
- TIER1_MARKER = join15(TH_DIR3, "tier1.json");
7894
- API_URL4 = process.env["TERMINALHIRE_API_URL"] || process.env["JPI_API_URL"] || "https://terminalhire.com";
8020
+ TH_DIR3 = process.env["TERMINALHIRE_DIR"] || join16(homedir14(), ".terminalhire");
8021
+ TIER1_MARKER = join16(TH_DIR3, "tier1.json");
8022
+ API_URL5 = process.env["TERMINALHIRE_API_URL"] || process.env["JPI_API_URL"] || "https://terminalhire.com";
7895
8023
  SYNC_BASE = "https://www.terminalhire.com";
7896
8024
  POLL_INTERVAL_MS = 2e3;
7897
8025
  POLL_TIMEOUT_MS = 10 * 60 * 1e3;
@@ -7905,13 +8033,13 @@ __export(jpi_init_exports, {
7905
8033
  run: () => run14
7906
8034
  });
7907
8035
  import { existsSync as existsSync11 } from "fs";
7908
- import { join as join16, resolve } from "path";
8036
+ import { join as join17, resolve } from "path";
7909
8037
  import { fileURLToPath as fileURLToPath3 } from "url";
7910
- import { createInterface as createInterface9 } from "readline";
8038
+ import { createInterface as createInterface10 } from "readline";
7911
8039
  import { spawnSync, spawn as spawn2 } from "child_process";
7912
- import { homedir as homedir14 } from "os";
8040
+ import { homedir as homedir15 } from "os";
7913
8041
  function ask3(question) {
7914
- const rl = createInterface9({ input: process.stdin, output: process.stdout });
8042
+ const rl = createInterface10({ input: process.stdin, output: process.stdout });
7915
8043
  return new Promise((resolve2) => {
7916
8044
  rl.question(question, (answer) => {
7917
8045
  rl.close();
@@ -7920,13 +8048,13 @@ function ask3(question) {
7920
8048
  });
7921
8049
  }
7922
8050
  function resolveScript(name) {
7923
- const distPath = resolve(join16(__dirname2, "..", "..", "dist", "bin", `${name}.js`));
7924
- const legacyPath = resolve(join16(__dirname2, `${name}.js`));
8051
+ const distPath = resolve(join17(__dirname2, "..", "..", "dist", "bin", `${name}.js`));
8052
+ const legacyPath = resolve(join17(__dirname2, `${name}.js`));
7925
8053
  return existsSync11(distPath) ? distPath : legacyPath;
7926
8054
  }
7927
8055
  function resolveInstallJs() {
7928
- const fromDist = resolve(join16(__dirname2, "..", "..", "install.js"));
7929
- const fromBin = resolve(join16(__dirname2, "..", "install.js"));
8056
+ const fromDist = resolve(join17(__dirname2, "..", "..", "install.js"));
8057
+ const fromBin = resolve(join17(__dirname2, "..", "install.js"));
7930
8058
  if (existsSync11(fromDist)) return fromDist;
7931
8059
  if (existsSync11(fromBin)) return fromBin;
7932
8060
  return fromBin;
@@ -8037,14 +8165,14 @@ __export(jpi_refresh_exports, {
8037
8165
  run: () => run15
8038
8166
  });
8039
8167
  import { readFileSync as readFileSync16, writeFileSync as writeFileSync13, existsSync as existsSync12, mkdirSync as mkdirSync13 } from "fs";
8040
- import { join as join17 } from "path";
8041
- import { homedir as homedir15 } from "os";
8168
+ import { join as join18 } from "path";
8169
+ import { homedir as homedir16 } from "os";
8042
8170
  import { fileURLToPath as fileURLToPath4 } from "url";
8043
8171
  async function run15() {
8044
8172
  try {
8045
8173
  let index;
8046
8174
  try {
8047
- const res = await fetch(`${API_URL5}/api/index`, {
8175
+ const res = await fetch(`${API_URL6}/api/index`, {
8048
8176
  signal: AbortSignal.timeout(15e3),
8049
8177
  headers: { "Accept": "application/json" }
8050
8178
  });
@@ -8092,12 +8220,51 @@ async function run15() {
8092
8220
  }
8093
8221
  } catch {
8094
8222
  }
8095
- mkdirSync13(TERMINALHIRE_DIR10, { recursive: true });
8223
+ let topPeers = [];
8224
+ if (isPeerConnectEnabled()) try {
8225
+ const { match: match2, STRONG_MATCH_THRESHOLD: STRONG_MATCH_THRESHOLD2 } = await Promise.resolve().then(() => (init_src(), src_exports));
8226
+ const { extractFingerprint: extractFingerprint2 } = await Promise.resolve().then(() => (init_signal(), signal_exports));
8227
+ const sig = extractFingerprint2(process.cwd());
8228
+ const project = readProject();
8229
+ const skillTags = [
8230
+ .../* @__PURE__ */ new Set([
8231
+ ...Array.isArray(sig?.skillTags) ? sig.skillTags : [],
8232
+ ...project && Array.isArray(project.skillTags) ? project.skillTags : []
8233
+ ])
8234
+ ];
8235
+ if (skillTags.length > 0) {
8236
+ const fp = { skillTags, prefs: project?.prefs ?? {} };
8237
+ const directory = await fetchDirectory({ quiet: true });
8238
+ const cards = directory?.cards ?? [];
8239
+ if (cards.length > 0) {
8240
+ const peerResults = match2(fp, cards, cards.length).filter(
8241
+ (r) => r.score >= STRONG_MATCH_THRESHOLD2
8242
+ );
8243
+ topPeers = peerResults.map((r) => ({
8244
+ login: r.job.company,
8245
+ // public handle (person login / project owner)
8246
+ title: r.job.title,
8247
+ // public card title (name or project title)
8248
+ score: r.score,
8249
+ matchedTags: r.matchedTags,
8250
+ source: r.job.source,
8251
+ // 'person' | 'project'
8252
+ url: r.job.url,
8253
+ // public /r/<login> credential link
8254
+ id: r.job.id
8255
+ }));
8256
+ await reportMatched(peerResults);
8257
+ }
8258
+ }
8259
+ } catch {
8260
+ }
8261
+ mkdirSync13(TERMINALHIRE_DIR11, { recursive: true });
8096
8262
  const cacheEntry = {
8097
8263
  ts: Date.now(),
8098
8264
  index,
8099
8265
  matchCount,
8100
- topMatches
8266
+ topMatches,
8267
+ topPeers
8101
8268
  };
8102
8269
  writeFileSync13(INDEX_CACHE_FILE4, JSON.stringify(cacheEntry), "utf8");
8103
8270
  try {
@@ -8123,10 +8290,10 @@ async function run15() {
8123
8290
  } catch {
8124
8291
  }
8125
8292
  const ranked = rankBySessionTags2(topMatches, sessionTags);
8126
- const verbs = buildSpinnerPool2(ranked, sc.max, { sessionTags, frequency: sc.frequency });
8293
+ const verbs = buildSpinnerPool2(ranked, sc.max, { sessionTags, frequency: sc.frequency, topPeers });
8127
8294
  if (verbs.length > 0) applySpinnerVerbs2(verbs, sc.mode);
8128
8295
  else clearSpinnerVerbs2();
8129
- const tips = buildTips2(ranked, API_URL5, 8);
8296
+ const tips = buildTips2(ranked, API_URL6, 8);
8130
8297
  if (tips.length > 0) applySpinnerTips2(tips);
8131
8298
  else clearSpinnerTips2();
8132
8299
  } else {
@@ -8143,14 +8310,16 @@ async function run15() {
8143
8310
  process.exit(1);
8144
8311
  }
8145
8312
  }
8146
- var __dirname3, TERMINALHIRE_DIR10, INDEX_CACHE_FILE4, API_URL5;
8313
+ var __dirname3, TERMINALHIRE_DIR11, INDEX_CACHE_FILE4, API_URL6;
8147
8314
  var init_jpi_refresh = __esm({
8148
8315
  "bin/jpi-refresh.js"() {
8149
8316
  "use strict";
8317
+ init_directory2();
8318
+ init_config();
8150
8319
  __dirname3 = fileURLToPath4(new URL(".", import.meta.url));
8151
- TERMINALHIRE_DIR10 = join17(homedir15(), ".terminalhire");
8152
- INDEX_CACHE_FILE4 = join17(TERMINALHIRE_DIR10, "index-cache.json");
8153
- API_URL5 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
8320
+ TERMINALHIRE_DIR11 = join18(homedir16(), ".terminalhire");
8321
+ INDEX_CACHE_FILE4 = join18(TERMINALHIRE_DIR11, "index-cache.json");
8322
+ API_URL6 = process.env["TERMINALHIRE_API_URL"] ?? process.env["JPI_API_URL"] ?? "https://terminalhire.com";
8154
8323
  }
8155
8324
  });
8156
8325
 
@@ -8160,8 +8329,8 @@ __export(jpi_save_exports, {
8160
8329
  run: () => run16
8161
8330
  });
8162
8331
  import { readFileSync as readFileSync17, existsSync as existsSync13 } from "fs";
8163
- import { join as join18 } from "path";
8164
- import { homedir as homedir16 } from "os";
8332
+ import { join as join19 } from "path";
8333
+ import { homedir as homedir17 } from "os";
8165
8334
  import { fileURLToPath as fileURLToPath5 } from "url";
8166
8335
  function findJobInCache(jobId) {
8167
8336
  try {
@@ -8254,27 +8423,27 @@ async function run16() {
8254
8423
  process.exit(1);
8255
8424
  }
8256
8425
  }
8257
- var __dirname4, TERMINALHIRE_DIR11, INDEX_CACHE_FILE5;
8426
+ var __dirname4, TERMINALHIRE_DIR12, INDEX_CACHE_FILE5;
8258
8427
  var init_jpi_save = __esm({
8259
8428
  "bin/jpi-save.js"() {
8260
8429
  "use strict";
8261
8430
  __dirname4 = fileURLToPath5(new URL(".", import.meta.url));
8262
- TERMINALHIRE_DIR11 = join18(homedir16(), ".terminalhire");
8263
- INDEX_CACHE_FILE5 = join18(TERMINALHIRE_DIR11, "index-cache.json");
8431
+ TERMINALHIRE_DIR12 = join19(homedir17(), ".terminalhire");
8432
+ INDEX_CACHE_FILE5 = join19(TERMINALHIRE_DIR12, "index-cache.json");
8264
8433
  }
8265
8434
  });
8266
8435
 
8267
8436
  // bin/jpi-dispatch.js
8268
8437
  import { fileURLToPath as fileURLToPath6 } from "url";
8269
- import { join as join19, dirname as dirname2 } from "path";
8438
+ import { join as join20, dirname as dirname2 } from "path";
8270
8439
  import { existsSync as existsSync14, readFileSync as readFileSync18 } from "fs";
8271
8440
  import { createRequire } from "module";
8272
8441
  var __dirname5 = fileURLToPath6(new URL(".", import.meta.url));
8273
8442
  function readPackageVersion() {
8274
8443
  try {
8275
8444
  const candidates = [
8276
- join19(__dirname5, "..", "..", "package.json"),
8277
- join19(__dirname5, "..", "package.json")
8445
+ join20(__dirname5, "..", "..", "package.json"),
8446
+ join20(__dirname5, "..", "package.json")
8278
8447
  ];
8279
8448
  for (const p of candidates) {
8280
8449
  if (existsSync14(p)) {
@@ -8289,7 +8458,7 @@ function readPackageVersion() {
8289
8458
  var firstArg = process.argv[2];
8290
8459
  if (!firstArg && !process.stdin.isTTY) {
8291
8460
  const { default: childProcess } = await import("child_process");
8292
- const nudgeScript = join19(__dirname5, "jpi.js");
8461
+ const nudgeScript = join20(__dirname5, "jpi.js");
8293
8462
  const child = childProcess.spawnSync(process.execPath, [nudgeScript], {
8294
8463
  stdio: ["inherit", "inherit", "inherit"]
8295
8464
  });
@@ -8327,6 +8496,7 @@ if (!firstArg || firstArg === "help" || firstArg === "--help" || firstArg === "-
8327
8496
  console.log(" terminalhire config --nudge session Nudge at most once per session (default)");
8328
8497
  console.log(" terminalhire config --nudge always Nudge every statusLine render");
8329
8498
  console.log(" terminalhire config --nudge every:N Nudge every Nth render");
8499
+ console.log(" terminalhire config --connect on|off Opt in/out of ambient peer & founder surfacing (default off)");
8330
8500
  console.log(" terminalhire config --show Print current config");
8331
8501
  console.log(" terminalhire spinner --show Job matches in the spinner line while Claude works");
8332
8502
  console.log(" terminalhire spinner --off Turn the spinner job surface off (restores your spinner)");