@sma1lboy/kobe 0.7.11 → 0.7.12

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 +266 -163
  2. package/package.json +2 -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.11",
73
+ version: "0.7.12",
74
74
  description: "TUI orchestrator for Claude Code (codename)",
75
75
  type: "module",
76
76
  packageManager: "bun@1.3.13",
@@ -118,6 +118,7 @@ var init_package = __esm(() => {
118
118
  "@biomejs/biome": "1.9.4",
119
119
  "@tsconfig/bun": "1.0.9",
120
120
  "@types/bun": "1.3.12",
121
+ "@types/node": "25.6.2",
121
122
  knip: "^6.14.2",
122
123
  "node-pty": "^1.1.0",
123
124
  typescript: "5.8.2",
@@ -663,6 +664,33 @@ class TaskIndexStore {
663
664
  this.notifyListeners();
664
665
  return next;
665
666
  }
667
+ async move(id, delta, withinIds) {
668
+ this.assertLoaded();
669
+ const task = this.cache.tasks.find((t) => t.id === id);
670
+ if (!task)
671
+ throw new Error(`task not found: ${id}`);
672
+ const ids = withinIds?.length ? withinIds : this.cache.tasks.map((t) => t.id);
673
+ const pos = ids.indexOf(String(id));
674
+ if (pos < 0)
675
+ throw new Error(`task not movable in current group: ${id}`);
676
+ const targetId = ids[pos + delta];
677
+ if (!targetId)
678
+ return task;
679
+ const fromIdx = this.cache.tasks.findIndex((t) => t.id === id);
680
+ const toIdx = this.cache.tasks.findIndex((t) => t.id === targetId);
681
+ if (fromIdx < 0 || toIdx < 0 || fromIdx === toIdx)
682
+ return task;
683
+ const [moved] = this.cache.tasks.splice(fromIdx, 1);
684
+ if (!moved)
685
+ return task;
686
+ const adjustedToIdx = fromIdx < toIdx ? toIdx - 1 : toIdx;
687
+ const insertAt = delta > 0 ? adjustedToIdx + 1 : adjustedToIdx;
688
+ const next = { ...moved, updatedAt: new Date().toISOString() };
689
+ this.cache.tasks.splice(insertAt, 0, next);
690
+ await this.save();
691
+ this.notifyListeners();
692
+ return next;
693
+ }
666
694
  async archive(id, status = "done") {
667
695
  return this.update(id, { status });
668
696
  }
@@ -3096,6 +3124,13 @@ class Orchestrator {
3096
3124
  return;
3097
3125
  await this.store.update(task.id, { pinned: next });
3098
3126
  }
3127
+ async moveTask(id, delta) {
3128
+ const task = this.requireTask(id);
3129
+ if (task.kind === "main")
3130
+ return;
3131
+ const groupIds = this.store.list().filter((t) => (t.kind ?? "task") !== "main" && t.archived === task.archived && (t.pinned ?? false) === (task.pinned ?? false)).map((t) => String(t.id));
3132
+ await this.store.move(task.id, delta, groupIds);
3133
+ }
3099
3134
  async setArchived(id, archived) {
3100
3135
  const task = this.requireTask(id);
3101
3136
  const next = archived ?? !task.archived;
@@ -5344,6 +5379,14 @@ async function startDaemonServer(orch, options = {}) {
5344
5379
  await orch.setPinned(taskId, optionalBoolean(payload, "pinned"));
5345
5380
  return {};
5346
5381
  }
5382
+ case "task.move": {
5383
+ const taskId = requireString(payload, "taskId");
5384
+ const direction = requireString(payload, "direction");
5385
+ if (direction !== "up" && direction !== "down")
5386
+ throw new Error("direction must be up or down");
5387
+ await orch.moveTask(taskId, direction === "up" ? -1 : 1);
5388
+ return {};
5389
+ }
5347
5390
  case "task.status": {
5348
5391
  const taskId = requireString(payload, "taskId");
5349
5392
  const status = requireString(payload, "status");
@@ -10187,6 +10230,9 @@ class RemoteOrchestrator {
10187
10230
  async setPinned(id, pinned) {
10188
10231
  await this.client.request("task.pin", { taskId: String(id), pinned });
10189
10232
  }
10233
+ async moveTask(id, delta) {
10234
+ await this.client.request("task.move", { taskId: String(id), direction: delta < 0 ? "up" : "down" });
10235
+ }
10190
10236
  async setArchived(id, archived) {
10191
10237
  await this.client.request("task.archive", { taskId: String(id), archived });
10192
10238
  }
@@ -17106,28 +17152,51 @@ function useSidebarBindings(opts) {
17106
17152
  return ids[idx];
17107
17153
  };
17108
17154
  const searchModeAccessor = () => opts.searchMode?.() ?? false;
17155
+ const moveModeAccessor = () => opts.moveMode?.() ?? false;
17109
17156
  useBindings(() => ({
17110
17157
  enabled: opts.focused() && !searchModeAccessor(),
17111
17158
  bindings: bindByIds({
17112
17159
  "sidebar.nav": (evt) => {
17160
+ if (moveModeAccessor()) {
17161
+ const id = cursorTaskId();
17162
+ if (id === undefined)
17163
+ return;
17164
+ if (evt.name === "j" || evt.name === "down")
17165
+ opts.onMoveRequest?.(id, 1);
17166
+ else if (evt.name === "k" || evt.name === "up")
17167
+ opts.onMoveRequest?.(id, -1);
17168
+ return;
17169
+ }
17113
17170
  if (evt.name === "j" || evt.name === "down")
17114
17171
  ctrl.moveDown();
17115
17172
  else if (evt.name === "k" || evt.name === "up")
17116
17173
  ctrl.moveUp();
17117
17174
  },
17118
- "sidebar.select": () => ctrl.selectCurrent(),
17175
+ "sidebar.select": () => {
17176
+ if (moveModeAccessor()) {
17177
+ opts.onMoveModeExit?.();
17178
+ return;
17179
+ }
17180
+ ctrl.selectCurrent();
17181
+ },
17119
17182
  "sidebar.goto": (evt) => {
17183
+ if (moveModeAccessor())
17184
+ return;
17120
17185
  if (evt.shift)
17121
17186
  ctrl.pressShiftG();
17122
17187
  else
17123
17188
  ctrl.pressG();
17124
17189
  },
17125
17190
  "sidebar.delete": () => {
17191
+ if (moveModeAccessor())
17192
+ return;
17126
17193
  const id = cursorTaskId();
17127
17194
  if (id !== undefined)
17128
17195
  opts.onDeleteRequest?.(id);
17129
17196
  },
17130
17197
  "sidebar.archive": () => {
17198
+ if (moveModeAccessor())
17199
+ return;
17131
17200
  const id = cursorTaskId();
17132
17201
  if (id !== undefined)
17133
17202
  opts.onArchiveRequest?.(id);
@@ -17140,20 +17209,32 @@ function useSidebarBindings(opts) {
17140
17209
  opts.onLocalMergeRequest?.(id);
17141
17210
  },
17142
17211
  "sidebar.rename": () => {
17212
+ if (moveModeAccessor())
17213
+ return;
17143
17214
  const id = cursorTaskId();
17144
17215
  if (id !== undefined)
17145
17216
  opts.onRenameRequest?.(id);
17146
17217
  },
17147
17218
  "sidebar.pin": (evt) => {
17219
+ if (moveModeAccessor())
17220
+ return;
17148
17221
  if (!evt.shift)
17149
17222
  return;
17150
17223
  const id = cursorTaskId();
17151
17224
  if (id !== undefined)
17152
17225
  opts.onPinRequest?.(id);
17153
17226
  },
17154
- "sidebar.search.enter": () => opts.onSearchEnter?.()
17227
+ "sidebar.search.enter": () => {
17228
+ if (moveModeAccessor())
17229
+ return;
17230
+ opts.onSearchEnter?.();
17231
+ }
17155
17232
  })
17156
17233
  }));
17234
+ useBindings(() => ({
17235
+ enabled: opts.focused() && moveModeAccessor(),
17236
+ bindings: [{ key: "escape", cmd: () => opts.onMoveModeExit?.() }]
17237
+ }));
17157
17238
  useBindings(() => ({
17158
17239
  enabled: opts.focused(),
17159
17240
  bindings: bindByIds({
@@ -17338,6 +17419,9 @@ function Sidebar(props) {
17338
17419
  onDeleteRequest: (id) => props.onDeleteRequest?.(id),
17339
17420
  onArchiveRequest: (id) => props.onArchiveRequest?.(id),
17340
17421
  onLocalMergeRequest: (id) => props.onLocalMergeRequest?.(id),
17422
+ moveMode: props.moveMode,
17423
+ onMoveRequest: (id, delta) => props.onMoveRequest?.(id, delta),
17424
+ onMoveModeExit: () => props.onMoveModeExit?.(),
17341
17425
  onRenameRequest: (id) => props.onRenameRequest?.(id),
17342
17426
  onPinRequest: (id) => props.onPinRequest?.(id),
17343
17427
  onViewSwitch: (delta) => cycleView(delta),
@@ -17558,33 +17642,55 @@ function Sidebar(props) {
17558
17642
  });
17559
17643
  const titleText = isMain ? repoBasename(task.repo) : task.title;
17560
17644
  const activity = () => props.engineState?.().get(task.id)?.state;
17561
- const loading = () => activity() === "running" || isLive() || !isMain && task.status === "in_progress";
17562
- const activityChip = () => {
17645
+ const hasActivity = () => activity() !== undefined;
17646
+ const loading = () => activity() === "running" || isLive() || !hasActivity() && !isMain && task.status === "in_progress";
17647
+ const activityBadge = () => {
17563
17648
  switch (activity()) {
17564
17649
  case "rate_limited":
17565
17650
  return {
17566
- text: "limited",
17651
+ glyph: "\u25F7",
17567
17652
  tone: "warning"
17568
17653
  };
17569
17654
  case "permission_needed":
17570
17655
  return {
17571
- text: "approve?",
17656
+ glyph: "?",
17572
17657
  tone: "warning"
17573
17658
  };
17574
17659
  case "error":
17575
17660
  return {
17576
- text: "error",
17661
+ glyph: "\u2715",
17577
17662
  tone: "error"
17578
17663
  };
17579
17664
  case "turn_complete":
17580
17665
  return {
17581
- text: "done",
17666
+ glyph: "\u2713",
17582
17667
  tone: "primary"
17583
17668
  };
17584
17669
  default:
17585
17670
  return null;
17586
17671
  }
17587
17672
  };
17673
+ const stateGlyph = () => {
17674
+ if (loading())
17675
+ return IN_PROGRESS_SPINNER[spinnerFrame()] ?? IN_PROGRESS_SPINNER[0];
17676
+ return activityBadge()?.glyph ?? badge.glyph;
17677
+ };
17678
+ const projectGlyph = () => {
17679
+ if (loading())
17680
+ return IN_PROGRESS_SPINNER[spinnerFrame()] ?? IN_PROGRESS_SPINNER[0];
17681
+ return activityBadge()?.glyph ?? "\u2605";
17682
+ };
17683
+ const stateColor = () => {
17684
+ const active = activityBadge();
17685
+ if (!loading() && active) {
17686
+ if (active.tone === "error")
17687
+ return theme.error;
17688
+ if (active.tone === "warning")
17689
+ return theme.warning;
17690
+ return theme.primary;
17691
+ }
17692
+ return badgeColor();
17693
+ };
17588
17694
  const subtitleText = createMemo(() => {
17589
17695
  if (task.branch.length > 0)
17590
17696
  return truncateBranchLabel(task.branch, subtitleBudget());
@@ -17639,7 +17745,7 @@ function Sidebar(props) {
17639
17745
  insert(_el$29, createComponent2(Show, {
17640
17746
  when: isMain,
17641
17747
  get children() {
17642
- var _el$30 = createElement("box"), _el$31 = createElement("text"), _el$32 = createElement("box"), _el$33 = createElement("text"), _el$34 = createElement("text");
17748
+ var _el$30 = createElement("box"), _el$31 = createElement("text"), _el$32 = createElement("box"), _el$33 = createElement("text"), _el$34 = createElement("text"), _el$35 = createElement("text");
17643
17749
  insertNode(_el$30, _el$31);
17644
17750
  insertNode(_el$30, _el$32);
17645
17751
  setProp(_el$30, "flexDirection", "row");
@@ -17648,64 +17754,36 @@ function Sidebar(props) {
17648
17754
  insert(_el$31, barGlyph);
17649
17755
  insertNode(_el$32, _el$33);
17650
17756
  insertNode(_el$32, _el$34);
17757
+ insertNode(_el$32, _el$35);
17651
17758
  setProp(_el$32, "flexDirection", "row");
17652
17759
  setProp(_el$32, "flexGrow", 1);
17653
17760
  setProp(_el$32, "paddingRight", 1);
17654
17761
  setProp(_el$32, "gap", 0);
17655
17762
  setProp(_el$33, "wrapMode", "none");
17656
- insert(_el$33, (() => {
17657
- var _c$2 = memo2(() => !!loading());
17658
- return () => _c$2() ? IN_PROGRESS_SPINNER[spinnerFrame()] ?? IN_PROGRESS_SPINNER[0] : "\u2605";
17659
- })());
17763
+ insert(_el$33, projectGlyph);
17660
17764
  setProp(_el$34, "wrapMode", "none");
17661
17765
  setProp(_el$34, "flexGrow", 1);
17662
17766
  insert(_el$34, () => spacedTitle(titleText, titleBudget()));
17663
- insert(_el$32, createComponent2(Show, {
17664
- get when() {
17665
- return loading();
17666
- },
17667
- get children() {
17668
- var _el$35 = createElement("text");
17669
- insertNode(_el$35, createTextNode(` working`));
17670
- setProp(_el$35, "wrapMode", "none");
17671
- effect((_$p) => setProp(_el$35, "fg", theme.primary, _$p));
17672
- return _el$35;
17673
- }
17674
- }), null);
17675
- insert(_el$32, createComponent2(Show, {
17676
- get when() {
17677
- return !loading();
17678
- },
17679
- get children() {
17680
- var _el$37 = createElement("text");
17681
- setProp(_el$37, "wrapMode", "none");
17682
- insert(_el$37, () => ` ${truncatePathTail(abbrevHome(task.repo), subtitleBudget())}`);
17683
- effect((_p$) => {
17684
- var _v$15 = theme.textMuted, _v$16 = TextAttributes9.DIM;
17685
- _v$15 !== _p$.e && (_p$.e = setProp(_el$37, "fg", _v$15, _p$.e));
17686
- _v$16 !== _p$.t && (_p$.t = setProp(_el$37, "attributes", _v$16, _p$.t));
17687
- return _p$;
17688
- }, {
17689
- e: undefined,
17690
- t: undefined
17691
- });
17692
- return _el$37;
17693
- }
17694
- }), null);
17767
+ setProp(_el$35, "wrapMode", "none");
17768
+ insert(_el$35, () => ` ${truncatePathTail(abbrevHome(task.repo), subtitleBudget())}`);
17695
17769
  effect((_p$) => {
17696
- var _v$17 = barColor(), _v$18 = theme.primary, _v$19 = TextAttributes9.BOLD, _v$20 = theme.text, _v$21 = TextAttributes9.BOLD;
17697
- _v$17 !== _p$.e && (_p$.e = setProp(_el$31, "fg", _v$17, _p$.e));
17698
- _v$18 !== _p$.t && (_p$.t = setProp(_el$33, "fg", _v$18, _p$.t));
17699
- _v$19 !== _p$.a && (_p$.a = setProp(_el$33, "attributes", _v$19, _p$.a));
17700
- _v$20 !== _p$.o && (_p$.o = setProp(_el$34, "fg", _v$20, _p$.o));
17701
- _v$21 !== _p$.i && (_p$.i = setProp(_el$34, "attributes", _v$21, _p$.i));
17770
+ var _v$15 = barColor(), _v$16 = stateColor(), _v$17 = TextAttributes9.BOLD, _v$18 = theme.text, _v$19 = TextAttributes9.BOLD, _v$20 = theme.textMuted, _v$21 = TextAttributes9.DIM;
17771
+ _v$15 !== _p$.e && (_p$.e = setProp(_el$31, "fg", _v$15, _p$.e));
17772
+ _v$16 !== _p$.t && (_p$.t = setProp(_el$33, "fg", _v$16, _p$.t));
17773
+ _v$17 !== _p$.a && (_p$.a = setProp(_el$33, "attributes", _v$17, _p$.a));
17774
+ _v$18 !== _p$.o && (_p$.o = setProp(_el$34, "fg", _v$18, _p$.o));
17775
+ _v$19 !== _p$.i && (_p$.i = setProp(_el$34, "attributes", _v$19, _p$.i));
17776
+ _v$20 !== _p$.n && (_p$.n = setProp(_el$35, "fg", _v$20, _p$.n));
17777
+ _v$21 !== _p$.s && (_p$.s = setProp(_el$35, "attributes", _v$21, _p$.s));
17702
17778
  return _p$;
17703
17779
  }, {
17704
17780
  e: undefined,
17705
17781
  t: undefined,
17706
17782
  a: undefined,
17707
17783
  o: undefined,
17708
- i: undefined
17784
+ i: undefined,
17785
+ n: undefined,
17786
+ s: undefined
17709
17787
  });
17710
17788
  return _el$30;
17711
17789
  }
@@ -17714,58 +17792,43 @@ function Sidebar(props) {
17714
17792
  when: !isMain,
17715
17793
  get children() {
17716
17794
  return [(() => {
17717
- var _el$38 = createElement("box"), _el$39 = createElement("text"), _el$40 = createElement("box"), _el$41 = createElement("text"), _el$42 = createElement("text");
17795
+ var _el$36 = createElement("box"), _el$37 = createElement("text"), _el$38 = createElement("box"), _el$39 = createElement("text"), _el$40 = createElement("text");
17796
+ insertNode(_el$36, _el$37);
17797
+ insertNode(_el$36, _el$38);
17798
+ setProp(_el$36, "flexDirection", "row");
17799
+ setProp(_el$36, "gap", 0);
17800
+ setProp(_el$37, "wrapMode", "none");
17801
+ insert(_el$37, barGlyph);
17718
17802
  insertNode(_el$38, _el$39);
17719
17803
  insertNode(_el$38, _el$40);
17720
17804
  setProp(_el$38, "flexDirection", "row");
17805
+ setProp(_el$38, "flexGrow", 1);
17806
+ setProp(_el$38, "paddingRight", 1);
17721
17807
  setProp(_el$38, "gap", 0);
17722
17808
  setProp(_el$39, "wrapMode", "none");
17723
- insert(_el$39, barGlyph);
17724
- insertNode(_el$40, _el$41);
17725
- insertNode(_el$40, _el$42);
17726
- setProp(_el$40, "flexDirection", "row");
17809
+ insert(_el$39, stateGlyph);
17810
+ setProp(_el$40, "wrapMode", "none");
17727
17811
  setProp(_el$40, "flexGrow", 1);
17728
- setProp(_el$40, "paddingRight", 1);
17729
- setProp(_el$40, "gap", 0);
17730
- setProp(_el$41, "wrapMode", "none");
17731
- insert(_el$41, (() => {
17732
- var _c$3 = memo2(() => !!loading());
17733
- return () => _c$3() ? IN_PROGRESS_SPINNER[spinnerFrame()] ?? IN_PROGRESS_SPINNER[0] : badge.glyph;
17734
- })());
17735
- setProp(_el$42, "wrapMode", "none");
17736
- setProp(_el$42, "flexGrow", 1);
17737
- insert(_el$42, () => spacedTitle(titleText, titleBudget()));
17738
- insert(_el$40, createComponent2(Show, {
17812
+ insert(_el$40, () => spacedTitle(titleText, titleBudget()));
17813
+ insert(_el$38, createComponent2(Show, {
17739
17814
  get when() {
17740
- return loading();
17815
+ return memo2(() => !!props.moveMode?.())() && isCursor();
17741
17816
  },
17742
17817
  get children() {
17743
- var _el$43 = createElement("text");
17744
- insertNode(_el$43, createTextNode(` working`));
17745
- setProp(_el$43, "wrapMode", "none");
17746
- effect((_$p) => setProp(_el$43, "fg", theme.primary, _$p));
17747
- return _el$43;
17818
+ var _el$41 = createElement("text");
17819
+ insertNode(_el$41, createTextNode(` move`));
17820
+ setProp(_el$41, "wrapMode", "none");
17821
+ effect((_$p) => setProp(_el$41, "fg", theme.warning, _$p));
17822
+ return _el$41;
17748
17823
  }
17749
17824
  }), null);
17750
- insert(_el$40, createComponent2(Show, {
17751
- get when() {
17752
- return memo2(() => !!!loading())() && activityChip();
17753
- },
17754
- children: (chip) => (() => {
17755
- var _el$55 = createElement("text");
17756
- setProp(_el$55, "wrapMode", "none");
17757
- insert(_el$55, () => ` ${chip().text}`);
17758
- effect((_$p) => setProp(_el$55, "fg", chip().tone === "error" ? theme.error : chip().tone === "warning" ? theme.warning : theme.primary, _$p));
17759
- return _el$55;
17760
- })()
17761
- }), null);
17762
17825
  effect((_p$) => {
17763
- var _v$22 = barColor(), _v$23 = badgeColor(), _v$24 = TextAttributes9.BOLD, _v$25 = theme.text, _v$26 = isSelected() || isCursor() ? TextAttributes9.BOLD : undefined;
17764
- _v$22 !== _p$.e && (_p$.e = setProp(_el$39, "fg", _v$22, _p$.e));
17765
- _v$23 !== _p$.t && (_p$.t = setProp(_el$41, "fg", _v$23, _p$.t));
17766
- _v$24 !== _p$.a && (_p$.a = setProp(_el$41, "attributes", _v$24, _p$.a));
17767
- _v$25 !== _p$.o && (_p$.o = setProp(_el$42, "fg", _v$25, _p$.o));
17768
- _v$26 !== _p$.i && (_p$.i = setProp(_el$42, "attributes", _v$26, _p$.i));
17826
+ var _v$22 = barColor(), _v$23 = stateColor(), _v$24 = TextAttributes9.BOLD, _v$25 = theme.text, _v$26 = isSelected() || isCursor() ? TextAttributes9.BOLD : undefined;
17827
+ _v$22 !== _p$.e && (_p$.e = setProp(_el$37, "fg", _v$22, _p$.e));
17828
+ _v$23 !== _p$.t && (_p$.t = setProp(_el$39, "fg", _v$23, _p$.t));
17829
+ _v$24 !== _p$.a && (_p$.a = setProp(_el$39, "attributes", _v$24, _p$.a));
17830
+ _v$25 !== _p$.o && (_p$.o = setProp(_el$40, "fg", _v$25, _p$.o));
17831
+ _v$26 !== _p$.i && (_p$.i = setProp(_el$40, "attributes", _v$26, _p$.i));
17769
17832
  return _p$;
17770
17833
  }, {
17771
17834
  e: undefined,
@@ -17774,74 +17837,74 @@ function Sidebar(props) {
17774
17837
  o: undefined,
17775
17838
  i: undefined
17776
17839
  });
17777
- return _el$38;
17840
+ return _el$36;
17778
17841
  })(), (() => {
17779
- var _el$45 = createElement("box"), _el$46 = createElement("text"), _el$47 = createElement("box"), _el$48 = createElement("text");
17842
+ var _el$43 = createElement("box"), _el$44 = createElement("text"), _el$45 = createElement("box"), _el$46 = createElement("text");
17843
+ insertNode(_el$43, _el$44);
17844
+ insertNode(_el$43, _el$45);
17845
+ setProp(_el$43, "flexDirection", "row");
17846
+ setProp(_el$43, "gap", 0);
17847
+ setProp(_el$44, "wrapMode", "none");
17848
+ insert(_el$44, barGlyph);
17780
17849
  insertNode(_el$45, _el$46);
17781
- insertNode(_el$45, _el$47);
17782
17850
  setProp(_el$45, "flexDirection", "row");
17783
- setProp(_el$45, "gap", 0);
17851
+ setProp(_el$45, "flexGrow", 1);
17852
+ setProp(_el$45, "paddingLeft", 2);
17853
+ setProp(_el$45, "paddingRight", 1);
17854
+ setProp(_el$45, "gap", 1);
17784
17855
  setProp(_el$46, "wrapMode", "none");
17785
- insert(_el$46, barGlyph);
17786
- insertNode(_el$47, _el$48);
17787
- setProp(_el$47, "flexDirection", "row");
17788
- setProp(_el$47, "flexGrow", 1);
17789
- setProp(_el$47, "paddingLeft", 2);
17790
- setProp(_el$47, "paddingRight", 1);
17791
- setProp(_el$47, "gap", 1);
17792
- setProp(_el$48, "wrapMode", "none");
17793
- setProp(_el$48, "flexGrow", 1);
17794
- insert(_el$48, subtitleText);
17795
- insert(_el$47, createComponent2(Show, {
17856
+ setProp(_el$46, "flexGrow", 1);
17857
+ insert(_el$46, subtitleText);
17858
+ insert(_el$45, createComponent2(Show, {
17796
17859
  get when() {
17797
17860
  return task.pinned === true;
17798
17861
  },
17799
17862
  get children() {
17800
- var _el$49 = createElement("text");
17801
- insertNode(_el$49, createTextNode(`\u25B4`));
17802
- setProp(_el$49, "wrapMode", "none");
17803
- effect((_$p) => setProp(_el$49, "fg", theme.warning, _$p));
17804
- return _el$49;
17863
+ var _el$47 = createElement("text");
17864
+ insertNode(_el$47, createTextNode(`\u25B4`));
17865
+ setProp(_el$47, "wrapMode", "none");
17866
+ effect((_$p) => setProp(_el$47, "fg", theme.warning, _$p));
17867
+ return _el$47;
17805
17868
  }
17806
17869
  }), null);
17807
- insert(_el$47, createComponent2(Show, {
17870
+ insert(_el$45, createComponent2(Show, {
17808
17871
  get when() {
17809
17872
  return changes().added > 0;
17810
17873
  },
17811
17874
  get children() {
17812
- var _el$51 = createElement("text"), _el$52 = createTextNode(`+`);
17813
- insertNode(_el$51, _el$52);
17814
- setProp(_el$51, "wrapMode", "none");
17815
- insert(_el$51, () => changes().added, null);
17816
- effect((_$p) => setProp(_el$51, "fg", theme.success, _$p));
17817
- return _el$51;
17875
+ var _el$49 = createElement("text"), _el$50 = createTextNode(`+`);
17876
+ insertNode(_el$49, _el$50);
17877
+ setProp(_el$49, "wrapMode", "none");
17878
+ insert(_el$49, () => changes().added, null);
17879
+ effect((_$p) => setProp(_el$49, "fg", theme.success, _$p));
17880
+ return _el$49;
17818
17881
  }
17819
17882
  }), null);
17820
- insert(_el$47, createComponent2(Show, {
17883
+ insert(_el$45, createComponent2(Show, {
17821
17884
  get when() {
17822
17885
  return changes().deleted > 0;
17823
17886
  },
17824
17887
  get children() {
17825
- var _el$53 = createElement("text"), _el$54 = createTextNode(`\u2212`);
17826
- insertNode(_el$53, _el$54);
17827
- setProp(_el$53, "wrapMode", "none");
17828
- insert(_el$53, () => changes().deleted, null);
17829
- effect((_$p) => setProp(_el$53, "fg", theme.error, _$p));
17830
- return _el$53;
17888
+ var _el$51 = createElement("text"), _el$52 = createTextNode(`\u2212`);
17889
+ insertNode(_el$51, _el$52);
17890
+ setProp(_el$51, "wrapMode", "none");
17891
+ insert(_el$51, () => changes().deleted, null);
17892
+ effect((_$p) => setProp(_el$51, "fg", theme.error, _$p));
17893
+ return _el$51;
17831
17894
  }
17832
17895
  }), null);
17833
17896
  effect((_p$) => {
17834
17897
  var _v$27 = barColor(), _v$28 = theme.textMuted, _v$29 = TextAttributes9.DIM;
17835
- _v$27 !== _p$.e && (_p$.e = setProp(_el$46, "fg", _v$27, _p$.e));
17836
- _v$28 !== _p$.t && (_p$.t = setProp(_el$48, "fg", _v$28, _p$.t));
17837
- _v$29 !== _p$.a && (_p$.a = setProp(_el$48, "attributes", _v$29, _p$.a));
17898
+ _v$27 !== _p$.e && (_p$.e = setProp(_el$44, "fg", _v$27, _p$.e));
17899
+ _v$28 !== _p$.t && (_p$.t = setProp(_el$46, "fg", _v$28, _p$.t));
17900
+ _v$29 !== _p$.a && (_p$.a = setProp(_el$46, "attributes", _v$29, _p$.a));
17838
17901
  return _p$;
17839
17902
  }, {
17840
17903
  e: undefined,
17841
17904
  t: undefined,
17842
17905
  a: undefined
17843
17906
  });
17844
- return _el$45;
17907
+ return _el$43;
17845
17908
  })()];
17846
17909
  }
17847
17910
  }), null);
@@ -17904,43 +17967,43 @@ function Sidebar(props) {
17904
17967
  const left = createMemo(() => Math.max(0, Math.min(h().x + 2, dims().width - boxW() - 1)));
17905
17968
  const top = createMemo(() => Math.max(0, Math.min(h().y + 1, dims().height - boxH() - 1)));
17906
17969
  return (() => {
17907
- var _el$56 = createElement("box");
17908
- setProp(_el$56, "position", "absolute");
17909
- setProp(_el$56, "zIndex", 2600);
17910
- setProp(_el$56, "flexDirection", "column");
17911
- setProp(_el$56, "border", true);
17912
- setProp(_el$56, "paddingLeft", 1);
17913
- setProp(_el$56, "paddingRight", 1);
17914
- insert(_el$56, createComponent2(For, {
17970
+ var _el$53 = createElement("box");
17971
+ setProp(_el$53, "position", "absolute");
17972
+ setProp(_el$53, "zIndex", 2600);
17973
+ setProp(_el$53, "flexDirection", "column");
17974
+ setProp(_el$53, "border", true);
17975
+ setProp(_el$53, "paddingLeft", 1);
17976
+ setProp(_el$53, "paddingRight", 1);
17977
+ insert(_el$53, createComponent2(For, {
17915
17978
  get each() {
17916
17979
  return lines();
17917
17980
  },
17918
17981
  children: (l) => (() => {
17919
- var _el$57 = createElement("text");
17920
- setProp(_el$57, "wrapMode", "none");
17921
- insert(_el$57, (() => {
17922
- var _c$4 = memo2(() => !!l.dim);
17923
- return () => _c$4() ? truncatePathTail(l.text, innerW()) : truncateTitle(l.text, innerW());
17982
+ var _el$54 = createElement("text");
17983
+ setProp(_el$54, "wrapMode", "none");
17984
+ insert(_el$54, (() => {
17985
+ var _c$2 = memo2(() => !!l.dim);
17986
+ return () => _c$2() ? truncatePathTail(l.text, innerW()) : truncateTitle(l.text, innerW());
17924
17987
  })());
17925
17988
  effect((_p$) => {
17926
17989
  var _v$35 = l.dim ? theme.textMuted : theme.text, _v$36 = l.bold ? TextAttributes9.BOLD : l.dim ? TextAttributes9.DIM : undefined;
17927
- _v$35 !== _p$.e && (_p$.e = setProp(_el$57, "fg", _v$35, _p$.e));
17928
- _v$36 !== _p$.t && (_p$.t = setProp(_el$57, "attributes", _v$36, _p$.t));
17990
+ _v$35 !== _p$.e && (_p$.e = setProp(_el$54, "fg", _v$35, _p$.e));
17991
+ _v$36 !== _p$.t && (_p$.t = setProp(_el$54, "attributes", _v$36, _p$.t));
17929
17992
  return _p$;
17930
17993
  }, {
17931
17994
  e: undefined,
17932
17995
  t: undefined
17933
17996
  });
17934
- return _el$57;
17997
+ return _el$54;
17935
17998
  })()
17936
17999
  }));
17937
18000
  effect((_p$) => {
17938
18001
  var _v$30 = left(), _v$31 = top(), _v$32 = boxW(), _v$33 = theme.focusAccent, _v$34 = theme.backgroundElement;
17939
- _v$30 !== _p$.e && (_p$.e = setProp(_el$56, "left", _v$30, _p$.e));
17940
- _v$31 !== _p$.t && (_p$.t = setProp(_el$56, "top", _v$31, _p$.t));
17941
- _v$32 !== _p$.a && (_p$.a = setProp(_el$56, "width", _v$32, _p$.a));
17942
- _v$33 !== _p$.o && (_p$.o = setProp(_el$56, "borderColor", _v$33, _p$.o));
17943
- _v$34 !== _p$.i && (_p$.i = setProp(_el$56, "backgroundColor", _v$34, _p$.i));
18002
+ _v$30 !== _p$.e && (_p$.e = setProp(_el$53, "left", _v$30, _p$.e));
18003
+ _v$31 !== _p$.t && (_p$.t = setProp(_el$53, "top", _v$31, _p$.t));
18004
+ _v$32 !== _p$.a && (_p$.a = setProp(_el$53, "width", _v$32, _p$.a));
18005
+ _v$33 !== _p$.o && (_p$.o = setProp(_el$53, "borderColor", _v$33, _p$.o));
18006
+ _v$34 !== _p$.i && (_p$.i = setProp(_el$53, "backgroundColor", _v$34, _p$.i));
17944
18007
  return _p$;
17945
18008
  }, {
17946
18009
  e: undefined,
@@ -17949,7 +18012,7 @@ function Sidebar(props) {
17949
18012
  o: undefined,
17950
18013
  i: undefined
17951
18014
  });
17952
- return _el$56;
18015
+ return _el$53;
17953
18016
  })();
17954
18017
  }
17955
18018
  }), null);
@@ -18045,6 +18108,7 @@ function TasksShell(props) {
18045
18108
  const dialog = useDialog();
18046
18109
  const kv = useKV();
18047
18110
  const [selectedId, setSelectedId] = createSignal(props.tasks().some((t) => t.id === props.initialTaskId) ? props.initialTaskId : props.tasks()[0]?.id ?? null);
18111
+ const [moveMode, setMoveMode] = createSignal(false);
18048
18112
  const [updateInfo, setUpdateInfo] = createSignal(null);
18049
18113
  const dimensions = useTerminalDimensions();
18050
18114
  let activeConfirmed = !props.initialTaskId;
@@ -18294,6 +18358,19 @@ function TasksShell(props) {
18294
18358
  console.error(`[kobe tasks] failed to open worktree with ${opener.label}`);
18295
18359
  }
18296
18360
  }
18361
+ async function moveTask(id, delta) {
18362
+ const task = props.tasks().find((t) => t.id === id);
18363
+ if (!task || task.kind === "main" || !props.orch)
18364
+ return;
18365
+ try {
18366
+ await props.orch.moveTask(id, delta);
18367
+ } catch (err) {
18368
+ console.error("[kobe tasks] task.move failed:", err);
18369
+ return;
18370
+ }
18371
+ setSelectedId(id);
18372
+ await props.reload();
18373
+ }
18297
18374
  useBindings(() => ({
18298
18375
  enabled: dialog.stack.length === 0,
18299
18376
  bindings: [{
@@ -18425,18 +18502,30 @@ function TasksShell(props) {
18425
18502
  onRenameRequest: (id) => void renameTask(id),
18426
18503
  onDeleteRequest: (id) => void deleteTask(id),
18427
18504
  onArchiveRequest: (id) => void archiveTask(id),
18505
+ onLocalMergeRequest: (id) => {
18506
+ const task = props.tasks().find((t) => t.id === id);
18507
+ if (!task || task.kind === "main")
18508
+ return;
18509
+ setSelectedId(id);
18510
+ setMoveMode((cur) => !cur);
18511
+ },
18512
+ moveMode,
18513
+ onMoveRequest: (id, delta) => void moveTask(id, delta),
18514
+ onMoveModeExit: () => setMoveMode(false),
18428
18515
  focused: () => dialog.stack.length === 0
18429
18516
  }));
18430
- insert(_el$, createComponent2(ShortcutHints, {}), null);
18517
+ insert(_el$, createComponent2(ShortcutHints, {
18518
+ moveMode
18519
+ }), null);
18431
18520
  effect((_$p) => setProp(_el$, "backgroundColor", theme.background, _$p));
18432
18521
  return _el$;
18433
18522
  })();
18434
18523
  }
18435
- function ShortcutHints() {
18524
+ function ShortcutHints(props) {
18436
18525
  const {
18437
18526
  theme
18438
18527
  } = useTheme();
18439
- const HINTS = [{
18528
+ const DEFAULT_HINTS = [{
18440
18529
  k: "\u23CE",
18441
18530
  label: "open"
18442
18531
  }, {
@@ -18451,6 +18540,9 @@ function ShortcutHints() {
18451
18540
  }, {
18452
18541
  k: "[/]",
18453
18542
  label: "views"
18543
+ }, {
18544
+ k: "M",
18545
+ label: "move task"
18454
18546
  }, {
18455
18547
  k: "A/D",
18456
18548
  label: "archive/delete"
@@ -18485,9 +18577,17 @@ function ShortcutHints() {
18485
18577
  k: "\u2303Q",
18486
18578
  label: "detach"
18487
18579
  }];
18580
+ const MOVE_HINTS = [{
18581
+ k: "J/K",
18582
+ label: "reorder"
18583
+ }, {
18584
+ k: "\u23CE/Esc",
18585
+ label: "done"
18586
+ }];
18587
+ const hints = () => props.moveMode?.() ? MOVE_HINTS : DEFAULT_HINTS;
18488
18588
  const LABEL_COL_MAX = 18;
18489
- const labelColWidth = Math.min(LABEL_COL_MAX, Math.max(...HINTS.map((h) => h.label.length)));
18490
- const clipLabel = (s) => s.length <= labelColWidth ? s : `${s.slice(0, Math.max(0, labelColWidth - 1))}\u2026`;
18589
+ const labelColWidth = () => Math.min(LABEL_COL_MAX, Math.max(...hints().map((h) => h.label.length)));
18590
+ const clipLabel = (s) => s.length <= labelColWidth() ? s : `${s.slice(0, Math.max(0, labelColWidth() - 1))}\u2026`;
18491
18591
  return (() => {
18492
18592
  var _el$3 = createElement("box"), _el$4 = createElement("text");
18493
18593
  insertNode(_el$3, _el$4);
@@ -18500,7 +18600,9 @@ function ShortcutHints() {
18500
18600
  insertNode(_el$4, createTextNode(`\u2500\u2500 keys \u2500\u2500`));
18501
18601
  setProp(_el$4, "wrapMode", "none");
18502
18602
  insert(_el$3, createComponent2(For, {
18503
- each: HINTS,
18603
+ get each() {
18604
+ return hints();
18605
+ },
18504
18606
  children: (h) => (() => {
18505
18607
  var _el$6 = createElement("box"), _el$7 = createElement("box"), _el$8 = createElement("text"), _el$9 = createTextNode(`[`), _el$0 = createTextNode(`]`), _el$1 = createElement("box"), _el$10 = createElement("text");
18506
18608
  insertNode(_el$6, _el$7);
@@ -18516,20 +18618,21 @@ function ShortcutHints() {
18516
18618
  setProp(_el$8, "wrapMode", "none");
18517
18619
  insert(_el$8, () => h.k, _el$0);
18518
18620
  insertNode(_el$1, _el$10);
18519
- setProp(_el$1, "width", labelColWidth);
18520
18621
  setProp(_el$1, "flexShrink", 0);
18521
18622
  setProp(_el$10, "wrapMode", "none");
18522
18623
  insert(_el$10, () => clipLabel(h.label));
18523
18624
  effect((_p$) => {
18524
- var _v$3 = theme.accent, _v$4 = TextAttributes10.BOLD, _v$5 = theme.textMuted;
18625
+ var _v$3 = theme.accent, _v$4 = TextAttributes10.BOLD, _v$5 = labelColWidth(), _v$6 = theme.textMuted;
18525
18626
  _v$3 !== _p$.e && (_p$.e = setProp(_el$8, "fg", _v$3, _p$.e));
18526
18627
  _v$4 !== _p$.t && (_p$.t = setProp(_el$8, "attributes", _v$4, _p$.t));
18527
- _v$5 !== _p$.a && (_p$.a = setProp(_el$10, "fg", _v$5, _p$.a));
18628
+ _v$5 !== _p$.a && (_p$.a = setProp(_el$1, "width", _v$5, _p$.a));
18629
+ _v$6 !== _p$.o && (_p$.o = setProp(_el$10, "fg", _v$6, _p$.o));
18528
18630
  return _p$;
18529
18631
  }, {
18530
18632
  e: undefined,
18531
18633
  t: undefined,
18532
- a: undefined
18634
+ a: undefined,
18635
+ o: undefined
18533
18636
  });
18534
18637
  return _el$6;
18535
18638
  })()
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.11",
4
+ "version": "0.7.12",
5
5
  "description": "TUI orchestrator for Claude Code (codename)",
6
6
  "type": "module",
7
7
  "packageManager": "bun@1.3.13",
@@ -49,6 +49,7 @@
49
49
  "@biomejs/biome": "1.9.4",
50
50
  "@tsconfig/bun": "1.0.9",
51
51
  "@types/bun": "1.3.12",
52
+ "@types/node": "25.6.2",
52
53
  "knip": "^6.14.2",
53
54
  "node-pty": "^1.1.0",
54
55
  "typescript": "5.8.2",