@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.
- package/dist/cli/index.js +71 -110
- 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.
|
|
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 {
|
|
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
|
|
8564
|
+
return globalSettingsPath();
|
|
8571
8565
|
if (stored.startsWith("repo:"))
|
|
8572
|
-
return
|
|
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
|
-
|
|
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
|
|
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
|
|
8621
|
-
|
|
8622
|
-
|
|
8623
|
-
|
|
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
|
-
|
|
8639
|
-
|
|
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
|
-
|
|
8642
|
-
"
|
|
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
|
|
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(
|
|
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(
|
|
16035
|
+
mkdirSync4(dirname7(statePath2), {
|
|
16075
16036
|
recursive: true
|
|
16076
16037
|
});
|
|
16077
16038
|
const tmp = `${statePath2}.tmp`;
|
package/package.json
CHANGED