@sma1lboy/kobe 0.7.9 → 0.7.10

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.
Files changed (2) hide show
  1. package/dist/cli/index.js +71 -110
  2. package/package.json +1 -1
package/dist/cli/index.js CHANGED
@@ -70,7 +70,7 @@ var init_package = __esm(() => {
70
70
  package_default = {
71
71
  $schema: "https://json.schemastore.org/package.json",
72
72
  name: "@sma1lboy/kobe",
73
- version: "0.7.9",
73
+ version: "0.7.10",
74
74
  description: "TUI orchestrator for Claude Code (codename)",
75
75
  type: "module",
76
76
  packageManager: "bun@1.3.13",
@@ -5019,6 +5019,35 @@ function matchTaskByCwd(tasks, cwd) {
5019
5019
  }
5020
5020
  return bestId;
5021
5021
  }
5022
+ function findAdoptableWorktree(tasks, cwd) {
5023
+ const target = normalize(cwd);
5024
+ const repos = new Set;
5025
+ const known = new Set;
5026
+ for (const t of tasks) {
5027
+ if (t.repo)
5028
+ repos.add(normalize(t.repo));
5029
+ if (t.worktreePath)
5030
+ known.add(normalize(t.worktreePath));
5031
+ }
5032
+ const seg = `/${KOBE_WORKTREE_ROOT_SUBPATH}/`;
5033
+ for (const repo of repos) {
5034
+ const prefix = `${repo}${seg}`;
5035
+ if (!target.startsWith(prefix))
5036
+ continue;
5037
+ const rest = target.slice(prefix.length);
5038
+ const name = rest.split("/")[0];
5039
+ if (!name)
5040
+ continue;
5041
+ const worktreePath = `${prefix}${name}`;
5042
+ if (known.has(worktreePath))
5043
+ return;
5044
+ return { repo, worktreePath };
5045
+ }
5046
+ return;
5047
+ }
5048
+ var init_cwd_task = __esm(() => {
5049
+ init_paths();
5050
+ });
5022
5051
 
5023
5052
  // src/daemon/event-bus.ts
5024
5053
  class DaemonEventBus {
@@ -5345,6 +5374,16 @@ async function startDaemonServer(orch, options = {}) {
5345
5374
  throw new Error(`unknown engine event kind: ${kind}`);
5346
5375
  const explicitId = optionalString(payload, "taskId");
5347
5376
  const cwd = optionalString(payload, "cwd");
5377
+ if (!explicitId && cwd && kind === "session-start") {
5378
+ const cand = findAdoptableWorktree(orch.listTasks(), cwd);
5379
+ if (cand) {
5380
+ try {
5381
+ await orch.adoptWorktree({ repo: cand.repo, worktreePath: cand.worktreePath, ifExists: "return" });
5382
+ } catch (err) {
5383
+ logDaemonError("worktree-autosync", err);
5384
+ }
5385
+ }
5386
+ }
5348
5387
  const taskId = explicitId ?? (cwd ? matchTaskByCwd(orch.listTasks(), cwd) : undefined);
5349
5388
  if (!taskId)
5350
5389
  return {};
@@ -5491,6 +5530,7 @@ var init_server = __esm(() => {
5491
5530
  init_hook_events();
5492
5531
  init_version();
5493
5532
  init_auto_title_poller();
5533
+ init_cwd_task();
5494
5534
  init_paths2();
5495
5535
  init_protocol();
5496
5536
  DEFAULT_UPDATE_POLL_MS = 6 * 60 * 60 * 1000;
@@ -8380,10 +8420,6 @@ class ClaudeHookAdapter {
8380
8420
  async removeActivityHooks(settingsFilePath) {
8381
8421
  await this.editSettings(settingsFilePath, (cur) => mergeActivityHooks(cur, false));
8382
8422
  }
8383
- async installWorktreeSyncHook(settingsFilePath) {
8384
- const command = shellQuoteArgv([...kobeCliInvocation(), "hook", "worktree-created"]);
8385
- await this.editSettings(settingsFilePath, (cur) => mergeWorktreeSyncHook(cur, command));
8386
- }
8387
8423
  async removeWorktreeSyncHook(settingsFilePath) {
8388
8424
  await this.editSettings(settingsFilePath, (cur) => mergeWorktreeSyncHook(cur, null));
8389
8425
  }
@@ -8434,7 +8470,6 @@ class NoopHookAdapter {
8434
8470
  supportsWorktreeSync() {
8435
8471
  return false;
8436
8472
  }
8437
- async installWorktreeSyncHook() {}
8438
8473
  async removeWorktreeSyncHook() {}
8439
8474
  }
8440
8475
  var init_hook_adapter2 = __esm(() => {
@@ -8448,7 +8483,7 @@ __export(exports_hook_cmd, {
8448
8483
  ensureGlobalKobeHooks: () => ensureGlobalKobeHooks
8449
8484
  });
8450
8485
  import { homedir as homedir10 } from "os";
8451
- import { dirname as dirname7, join as join9, resolve as resolve6 } from "path";
8486
+ import { join as join9, resolve as resolve6 } from "path";
8452
8487
  async function readStdinPayload() {
8453
8488
  try {
8454
8489
  const text = await Promise.race([
@@ -8488,10 +8523,6 @@ async function runHookSubcommand(argv) {
8488
8523
  return;
8489
8524
  }
8490
8525
  try {
8491
- if (verb === "worktree-created") {
8492
- await reportWorktreeCreated();
8493
- return;
8494
- }
8495
8526
  if (!verb || !isEngineActivityKind(verb))
8496
8527
  return;
8497
8528
  const payload = await readStdinPayload();
@@ -8517,43 +8548,6 @@ async function runHookSubcommand(argv) {
8517
8548
  }
8518
8549
  } catch {}
8519
8550
  }
8520
- async function reportWorktreeCreated() {
8521
- const payload = await readStdinPayload();
8522
- const worktreePath = typeof payload.worktree_path === "string" ? payload.worktree_path : undefined;
8523
- if (!worktreePath)
8524
- return;
8525
- const repo = await deriveRepoRoot(worktreePath);
8526
- if (!repo)
8527
- return;
8528
- const client = await connectIfRunning();
8529
- if (!client)
8530
- return;
8531
- try {
8532
- await client.request("worktree.adopt", { repo, worktreePath, ifExists: "return" });
8533
- } finally {
8534
- client.close();
8535
- }
8536
- }
8537
- async function deriveRepoRoot(worktreePath) {
8538
- try {
8539
- const proc = Bun.spawn(["git", "-C", worktreePath, "rev-parse", "--path-format=absolute", "--git-common-dir"], {
8540
- stdout: "pipe",
8541
- stderr: "ignore"
8542
- });
8543
- const [out, code] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
8544
- if (code !== 0)
8545
- return;
8546
- const commonDir = out.trim();
8547
- return commonDir ? dirname7(commonDir) : undefined;
8548
- } catch {
8549
- return;
8550
- }
8551
- }
8552
- function syncSettingsPath(scope) {
8553
- if (scope.kind === "repo")
8554
- return join9(resolve6(scope.path), ".claude", "settings.json");
8555
- return globalSettingsPath();
8556
- }
8557
8551
  function worktreeSyncAdapters() {
8558
8552
  return ALL_VENDORS.map((v) => createEngineHookAdapter(v)).filter((a) => a.supportsWorktreeSync());
8559
8553
  }
@@ -8567,9 +8561,9 @@ function persistedSyncPath(stored) {
8567
8561
  if (!stored || stored === "off")
8568
8562
  return;
8569
8563
  if (stored === "global")
8570
- return syncSettingsPath({ kind: "global" });
8564
+ return globalSettingsPath();
8571
8565
  if (stored.startsWith("repo:"))
8572
- return syncSettingsPath({ kind: "repo", path: stored.slice(5) });
8566
+ return join9(resolve6(stored.slice(5)), ".claude", "settings.json");
8573
8567
  return stored;
8574
8568
  }
8575
8569
  async function ensureGlobalKobeHooks() {
@@ -8577,69 +8571,36 @@ async function ensureGlobalKobeHooks() {
8577
8571
  const globalPath = globalSettingsPath();
8578
8572
  for (const a of activityHookAdapters())
8579
8573
  await a.installActivityHooks(globalPath);
8580
- const stored = getPersistedString(SYNC_SETTING_KEY);
8581
- if (stored === "off")
8582
- return;
8583
- const syncAdapters = worktreeSyncAdapters();
8584
- if (syncAdapters.length === 0)
8585
- return;
8586
- const path6 = persistedSyncPath(stored) ?? syncSettingsPath({ kind: "global" });
8587
- for (const a of syncAdapters)
8588
- await a.installWorktreeSyncHook(path6);
8589
- if (!stored)
8590
- setPersistedString(SYNC_SETTING_KEY, path6);
8574
+ await cleanupWorktreeSyncHook();
8591
8575
  } catch {}
8592
8576
  }
8593
- async function runHookSetup(argv) {
8594
- if (argv.includes("--help") || argv.includes("-h")) {
8595
- process.stdout.write([
8596
- "Usage: kobe hook setup [--global | --repo <path> | --off]",
8597
- "",
8598
- "Syncs an external `claude --worktree` into kobe as a task. This is ON",
8599
- "by default (installed globally into ~/.claude on launch). Use this to",
8600
- "move it to one repo (--repo <path>) or to turn it OFF (--off).",
8601
- ""
8602
- ].join(`
8603
- `));
8604
- return;
8605
- }
8606
- const off = argv.includes("--off");
8607
- const repoIdx = argv.indexOf("--repo");
8608
- const repoPath = repoIdx !== -1 ? argv[repoIdx + 1] : undefined;
8609
- if (repoIdx !== -1 && !repoPath) {
8610
- process.stderr.write(`kobe hook setup: --repo requires a path
8611
- `);
8612
- process.exit(2);
8613
- }
8577
+ async function cleanupWorktreeSyncHook() {
8614
8578
  const adapters = worktreeSyncAdapters();
8615
- if (adapters.length === 0) {
8616
- process.stdout.write(`kobe hook setup: no engine supports external worktree sync \u2014 nothing to do
8617
- `);
8579
+ if (adapters.length === 0)
8618
8580
  return;
8619
- }
8620
- const prevPath = persistedSyncPath(getPersistedString(SYNC_SETTING_KEY));
8621
- if (off) {
8622
- if (prevPath) {
8623
- for (const a of adapters)
8624
- await a.removeWorktreeSyncHook(prevPath);
8625
- }
8626
- setPersistedString(SYNC_SETTING_KEY, "off");
8627
- process.stdout.write(`kobe hook setup: external worktree sync disabled${prevPath ? ` (removed from ${prevPath})` : ""}
8628
- `);
8629
- return;
8630
- }
8631
- const scope = repoPath ? { kind: "repo", path: repoPath } : { kind: "global" };
8632
- const path6 = syncSettingsPath(scope);
8633
- if (prevPath && prevPath !== path6) {
8634
- for (const a of adapters)
8635
- await a.removeWorktreeSyncHook(prevPath);
8636
- }
8581
+ const stored = getPersistedString(SYNC_SETTING_KEY);
8582
+ const paths = new Set([globalSettingsPath()]);
8583
+ const prev = persistedSyncPath(stored);
8584
+ if (prev)
8585
+ paths.add(prev);
8637
8586
  for (const a of adapters)
8638
- await a.installWorktreeSyncHook(path6);
8639
- setPersistedString(SYNC_SETTING_KEY, path6);
8587
+ for (const p of paths)
8588
+ await a.removeWorktreeSyncHook(p);
8589
+ if (stored !== "off")
8590
+ setPersistedString(SYNC_SETTING_KEY, "off");
8591
+ }
8592
+ async function runHookSetup(_argv) {
8593
+ await cleanupWorktreeSyncHook();
8640
8594
  process.stdout.write([
8641
- `kobe hook setup: external worktree sync enabled (${scope.kind}) \u2014 wrote ${path6}`,
8642
- "New `claude --worktree` worktrees will appear as kobe tasks.",
8595
+ "kobe hook setup is deprecated and now a no-op (cleanup only).",
8596
+ "",
8597
+ "The old external-worktree sync used a global WorktreeCreate hook, which is",
8598
+ "a VCS provider hook \u2014 its presence broke `claude --worktree` / EnterWorktree",
8599
+ "in every repo. Any hook kobe previously installed has been removed.",
8600
+ "",
8601
+ "Sync is now automatic: a `claude --worktree` (or any session) started in a",
8602
+ "worktree under a repo kobe already tracks is adopted as a task on launch.",
8603
+ "To adopt existing worktrees on demand, use the New Task dialog or `kobe adopt`.",
8643
8604
  ""
8644
8605
  ].join(`
8645
8606
  `));
@@ -15988,7 +15949,7 @@ var init_focus = __esm(() => {
15988
15949
 
15989
15950
  // src/tui/context/kv.tsx
15990
15951
  import { mkdirSync as mkdirSync4, readFileSync as readFileSync9, renameSync as renameSync2, writeFileSync as writeFileSync3 } from "fs";
15991
- import { dirname as dirname8 } from "path";
15952
+ import { dirname as dirname7 } from "path";
15992
15953
  function loadInitial() {
15993
15954
  const statePath2 = kvStatePath();
15994
15955
  try {
@@ -16016,7 +15977,7 @@ var init_kv = __esm(() => {
16016
15977
  function writeNow(label) {
16017
15978
  const statePath2 = kvStatePath();
16018
15979
  try {
16019
- mkdirSync4(dirname8(statePath2), {
15980
+ mkdirSync4(dirname7(statePath2), {
16020
15981
  recursive: true
16021
15982
  });
16022
15983
  const tmp = `${statePath2}.tmp`;
@@ -16071,7 +16032,7 @@ var init_kv = __esm(() => {
16071
16032
  }
16072
16033
  const statePath2 = kvStatePath();
16073
16034
  try {
16074
- mkdirSync4(dirname8(statePath2), {
16035
+ mkdirSync4(dirname7(statePath2), {
16075
16036
  recursive: true
16076
16037
  });
16077
16038
  const tmp = `${statePath2}.tmp`;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
3
  "name": "@sma1lboy/kobe",
4
- "version": "0.7.9",
4
+ "version": "0.7.10",
5
5
  "description": "TUI orchestrator for Claude Code (codename)",
6
6
  "type": "module",
7
7
  "packageManager": "bun@1.3.13",