rudel 0.1.8 → 0.1.9

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.js +385 -242
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1959,7 +1959,7 @@ async function run(app, inputs, context) {
1959
1959
  // package.json
1960
1960
  var package_default = {
1961
1961
  name: "rudel",
1962
- version: "0.1.8",
1962
+ version: "0.1.9",
1963
1963
  type: "module",
1964
1964
  description: "CLI for the Coding Agent Analytics Platform rudel.ai",
1965
1965
  license: "MIT",
@@ -6132,16 +6132,6 @@ function toDisplayPath(absolutePath) {
6132
6132
  const home = homedir();
6133
6133
  return absolutePath.startsWith(home) ? `~${absolutePath.slice(home.length)}` : absolutePath;
6134
6134
  }
6135
- function groupProjectsForCwd(projects, cwd) {
6136
- const current = projects.filter((p) => p.projectPath === cwd);
6137
- const currentSet = new Set(current);
6138
- const subfolders = projects.filter((p) => !currentSet.has(p) && p.projectPath.startsWith(`${cwd}/`));
6139
- const subfoldersSet = new Set(subfolders);
6140
- const others = projects.filter((p) => !currentSet.has(p) && !subfoldersSet.has(p));
6141
- subfolders.sort((a, b) => a.projectPath.localeCompare(b.projectPath));
6142
- others.sort((a, b) => a.displayPath.localeCompare(b.displayPath));
6143
- return { current, subfolders, others };
6144
- }
6145
6135
 
6146
6136
  // ../../packages/agent-adapters/src/adapters/claude-code/settings.ts
6147
6137
  import { execSync } from "child_process";
@@ -7778,33 +7768,314 @@ function getAvailableAdapters() {
7778
7768
  registerAdapter(claudeCodeAdapter);
7779
7769
  registerAdapter(codexAdapter);
7780
7770
 
7781
- // src/commands/dev/list-sessions.ts
7782
- async function runListSessions() {
7771
+ // src/lib/project-grouping.ts
7772
+ import { homedir as homedir6 } from "os";
7773
+
7774
+ // src/lib/git-info.ts
7775
+ import { join as join6 } from "path";
7776
+ var {$ } = globalThis.Bun;
7777
+ function normalizeRemoteUrl(url) {
7778
+ return url.replace(/^(https?:\/\/|git@|ssh:\/\/)/, "").replace(/:/, "/").replace(/\.git$/, "");
7779
+ }
7780
+ async function getGitInfo(cwd) {
7781
+ const [remoteUrl, branch, sha, packageInfo] = await Promise.all([
7782
+ getGitRemoteUrl(cwd),
7783
+ getGitBranch(cwd),
7784
+ getGitSha(cwd),
7785
+ getPackageInfo(cwd)
7786
+ ]);
7787
+ const gitRemote = remoteUrl ? normalizeRemoteUrl(remoteUrl) : undefined;
7788
+ return {
7789
+ gitRemote,
7790
+ packageName: packageInfo?.name,
7791
+ packageType: packageInfo?.type,
7792
+ branch: branch ?? undefined,
7793
+ sha: sha ?? undefined
7794
+ };
7795
+ }
7796
+ async function getPackageInfo(cwd) {
7797
+ try {
7798
+ const gitRootResult = await $`git -C ${cwd} rev-parse --show-toplevel`.quiet();
7799
+ const root = gitRootResult.exitCode === 0 ? gitRootResult.text().trim() : cwd;
7800
+ return await getNodePackage(root) ?? await getPythonPackage(root) ?? await getRustPackage(root) ?? await getGoModule(root);
7801
+ } catch {
7802
+ return null;
7803
+ }
7804
+ }
7805
+ async function getNodePackage(root) {
7806
+ try {
7807
+ const file = Bun.file(join6(root, "package.json"));
7808
+ if (!await file.exists())
7809
+ return null;
7810
+ const pkg = await file.json();
7811
+ return pkg.name ? { name: pkg.name, type: "package.json" } : null;
7812
+ } catch {
7813
+ return null;
7814
+ }
7815
+ }
7816
+ async function getPythonPackage(root) {
7817
+ try {
7818
+ const file = Bun.file(join6(root, "pyproject.toml"));
7819
+ if (!await file.exists())
7820
+ return null;
7821
+ const content = await file.text();
7822
+ const name = content.match(/^\s*name\s*=\s*"([^"]+)"/m)?.[1];
7823
+ return name ? { name, type: "pyproject.toml" } : null;
7824
+ } catch {
7825
+ return null;
7826
+ }
7827
+ }
7828
+ async function getRustPackage(root) {
7829
+ try {
7830
+ const file = Bun.file(join6(root, "Cargo.toml"));
7831
+ if (!await file.exists())
7832
+ return null;
7833
+ const content = await file.text();
7834
+ const name = content.match(/^\s*name\s*=\s*"([^"]+)"/m)?.[1];
7835
+ return name ? { name, type: "Cargo.toml" } : null;
7836
+ } catch {
7837
+ return null;
7838
+ }
7839
+ }
7840
+ async function getGoModule(root) {
7841
+ try {
7842
+ const file = Bun.file(join6(root, "go.mod"));
7843
+ if (!await file.exists())
7844
+ return null;
7845
+ const content = await file.text();
7846
+ const name = content.match(/^module\s+(\S+)/m)?.[1];
7847
+ return name ? { name, type: "go.mod" } : null;
7848
+ } catch {
7849
+ return null;
7850
+ }
7851
+ }
7852
+ async function getGitRemoteUrl(cwd) {
7853
+ try {
7854
+ const result = await $`git -C ${cwd} remote get-url origin`.quiet();
7855
+ if (result.exitCode !== 0)
7856
+ return null;
7857
+ return result.text().trim() || null;
7858
+ } catch {
7859
+ return null;
7860
+ }
7861
+ }
7862
+ async function getGitBranch(cwd) {
7863
+ try {
7864
+ const result = await $`git -C ${cwd} rev-parse --abbrev-ref HEAD`.quiet();
7865
+ if (result.exitCode !== 0)
7866
+ return null;
7867
+ return result.text().trim();
7868
+ } catch {
7869
+ return null;
7870
+ }
7871
+ }
7872
+ async function getGitSha(cwd) {
7873
+ try {
7874
+ const result = await $`git -C ${cwd} rev-parse HEAD`.quiet();
7875
+ if (result.exitCode !== 0)
7876
+ return null;
7877
+ return result.text().trim();
7878
+ } catch {
7879
+ return null;
7880
+ }
7881
+ }
7882
+
7883
+ // src/lib/remote-cache.ts
7884
+ import { homedir as homedir5 } from "os";
7885
+ import { join as join7 } from "path";
7886
+ var CACHE_PATH = join7(homedir5(), ".rudel", "remote-cache.json");
7887
+ async function getRemoteCache() {
7888
+ try {
7889
+ const file = Bun.file(CACHE_PATH);
7890
+ if (!await file.exists())
7891
+ return {};
7892
+ return await file.json();
7893
+ } catch {
7894
+ return {};
7895
+ }
7896
+ }
7897
+ function getCachedRemote(cache, encodedDir) {
7898
+ return cache[encodedDir] ?? null;
7899
+ }
7900
+ function cacheRemote(cache, encodedDir, normalizedRemote) {
7901
+ cache[encodedDir] = normalizedRemote;
7902
+ }
7903
+ async function cacheRemotes(cache) {
7904
+ try {
7905
+ const { mkdir } = await import("fs/promises");
7906
+ const { dirname: dirname3 } = await import("path");
7907
+ await mkdir(dirname3(CACHE_PATH), { recursive: true });
7908
+ await Bun.write(CACHE_PATH, JSON.stringify(cache));
7909
+ } catch {}
7910
+ }
7911
+
7912
+ // src/lib/project-grouping.ts
7913
+ async function scanAndGroupProjects(cwd = process.cwd()) {
7783
7914
  const adapters2 = getAvailableAdapters();
7784
- const allProjects = [];
7915
+ const projects = [];
7785
7916
  for (const adapter of adapters2) {
7786
- const projects = await adapter.scanAllSessions();
7787
- allProjects.push(...projects);
7917
+ const scanned = await adapter.scanAllSessions();
7918
+ projects.push(...scanned);
7919
+ }
7920
+ const groups = await groupProjectsByRemote(projects, cwd);
7921
+ return { projects, groups };
7922
+ }
7923
+ function extractDisplayName(normalized) {
7924
+ const parts = normalized.split("/");
7925
+ if (parts.length >= 3) {
7926
+ return parts.slice(1).join("/");
7927
+ }
7928
+ return normalized;
7929
+ }
7930
+ function encodeProjectPath2(projectPath) {
7931
+ return projectPath.replace(/\//g, "-");
7932
+ }
7933
+ async function groupProjectsByRemote(projects, cwd) {
7934
+ const cache = await getRemoteCache();
7935
+ let cacheUpdated = false;
7936
+ const remotes = await Promise.all(projects.map((p) => getGitRemoteUrl(p.projectPath)));
7937
+ const grouped = new Map;
7938
+ const ungrouped = [];
7939
+ for (let i = 0;i < projects.length; i++) {
7940
+ const project = projects[i];
7941
+ const remote = remotes[i];
7942
+ if (remote) {
7943
+ const normalized = normalizeRemoteUrl(remote);
7944
+ const encodedDir = encodeProjectPath2(project.projectPath);
7945
+ if (getCachedRemote(cache, encodedDir) !== normalized) {
7946
+ cacheRemote(cache, encodedDir, normalized);
7947
+ cacheUpdated = true;
7948
+ }
7949
+ const existing = grouped.get(normalized);
7950
+ if (existing) {
7951
+ existing.projects.push(project);
7952
+ } else {
7953
+ grouped.set(normalized, { remote: normalized, projects: [project] });
7954
+ }
7955
+ } else {
7956
+ const encodedDir = encodeProjectPath2(project.projectPath);
7957
+ const cached = getCachedRemote(cache, encodedDir);
7958
+ if (cached) {
7959
+ const existing = grouped.get(cached);
7960
+ if (existing) {
7961
+ existing.projects.push(project);
7962
+ } else {
7963
+ grouped.set(cached, { remote: cached, projects: [project] });
7964
+ }
7965
+ } else {
7966
+ ungrouped.push(project);
7967
+ }
7968
+ }
7788
7969
  }
7970
+ const groups = [];
7971
+ for (const [, entry] of grouped) {
7972
+ const containsCwd = entry.projects.some((p) => cwd === p.projectPath || cwd.startsWith(`${p.projectPath}/`));
7973
+ groups.push({
7974
+ displayName: extractDisplayName(entry.remote),
7975
+ gitRemote: entry.remote,
7976
+ projects: entry.projects,
7977
+ totalSessions: entry.projects.reduce((s, p) => s + p.sessionCount, 0),
7978
+ containsCwd
7979
+ });
7980
+ }
7981
+ const homeSegments = homedir6().split("/").length;
7982
+ const remainingUngrouped = [];
7983
+ for (const project of ungrouped) {
7984
+ const match = findBestGroupByPath(project, groups, homeSegments);
7985
+ if (match) {
7986
+ match.projects.push(project);
7987
+ match.totalSessions += project.sessionCount;
7988
+ if (cwd === project.projectPath || cwd.startsWith(`${project.projectPath}/`)) {
7989
+ match.containsCwd = true;
7990
+ }
7991
+ } else {
7992
+ remainingUngrouped.push(project);
7993
+ }
7994
+ }
7995
+ for (const project of remainingUngrouped) {
7996
+ const containsCwd = cwd === project.projectPath || cwd.startsWith(`${project.projectPath}/`);
7997
+ groups.push({
7998
+ displayName: project.displayPath,
7999
+ gitRemote: null,
8000
+ projects: [project],
8001
+ totalSessions: project.sessionCount,
8002
+ containsCwd
8003
+ });
8004
+ }
8005
+ groups.sort((a, b) => {
8006
+ if (a.containsCwd !== b.containsCwd)
8007
+ return a.containsCwd ? -1 : 1;
8008
+ const aHasRemote = a.gitRemote !== null;
8009
+ const bHasRemote = b.gitRemote !== null;
8010
+ if (aHasRemote !== bHasRemote)
8011
+ return aHasRemote ? -1 : 1;
8012
+ return a.displayName.localeCompare(b.displayName);
8013
+ });
8014
+ if (cacheUpdated) {
8015
+ cacheRemotes(cache);
8016
+ }
8017
+ return groups;
8018
+ }
8019
+ function commonPrefixLength(a, b) {
8020
+ const partsA = a.split("/");
8021
+ const partsB = b.split("/");
8022
+ let count = 0;
8023
+ for (let i = 0;i < Math.min(partsA.length, partsB.length); i++) {
8024
+ if (partsA[i] === partsB[i])
8025
+ count++;
8026
+ else
8027
+ break;
8028
+ }
8029
+ return count;
8030
+ }
8031
+ function findBestGroupByPath(project, groups, homeSegments) {
8032
+ let bestGroup = null;
8033
+ let bestLen = 0;
8034
+ let secondBestLen = 0;
8035
+ for (const group2 of groups) {
8036
+ if (!group2.gitRemote)
8037
+ continue;
8038
+ let groupBest = 0;
8039
+ for (const p of group2.projects) {
8040
+ groupBest = Math.max(groupBest, commonPrefixLength(project.projectPath, p.projectPath));
8041
+ }
8042
+ if (groupBest > bestLen) {
8043
+ secondBestLen = bestLen;
8044
+ bestLen = groupBest;
8045
+ bestGroup = group2;
8046
+ } else if (groupBest > secondBestLen) {
8047
+ secondBestLen = groupBest;
8048
+ }
8049
+ }
8050
+ if (bestGroup && bestLen > homeSegments && bestLen > secondBestLen) {
8051
+ return bestGroup;
8052
+ }
8053
+ return null;
8054
+ }
8055
+
8056
+ // src/commands/dev/list-sessions.ts
8057
+ async function runListSessions() {
8058
+ const { projects: allProjects, groups } = await scanAndGroupProjects();
7789
8059
  if (allProjects.length === 0) {
7790
8060
  console.log("No projects with sessions found.");
7791
8061
  return;
7792
8062
  }
7793
- const cwd = process.cwd();
7794
- const grouped = groupProjectsForCwd(allProjects, cwd);
7795
8063
  const lines = [];
7796
- for (const proj of grouped.current) {
7797
- const name = getAdapter(proj.source).name;
7798
- lines.push(`[${name}] ${proj.displayPath} (${proj.sessionCount} sessions) [current]`);
7799
- }
7800
- for (const sub of grouped.subfolders) {
7801
- const name = getAdapter(sub.source).name;
7802
- const relative = sub.projectPath.slice(cwd.length + 1);
7803
- lines.push(` [${name}] ${relative} (${sub.sessionCount} sessions)`);
7804
- }
7805
- for (const other of grouped.others) {
7806
- const name = getAdapter(other.source).name;
7807
- lines.push(`[${name}] ${other.displayPath} (${other.sessionCount} sessions)`);
8064
+ for (const group2 of groups) {
8065
+ const isCurrent = group2.containsCwd ? " [current]" : "";
8066
+ if (group2.projects.length === 1) {
8067
+ const proj = group2.projects[0];
8068
+ const name = getAdapter(proj.source).name;
8069
+ lines.push(`[${name}] ${proj.displayPath} (${proj.sessionCount} sessions)${isCurrent}`);
8070
+ continue;
8071
+ }
8072
+ const totalSessions2 = group2.projects.reduce((s, p) => s + p.sessionCount, 0);
8073
+ lines.push(`${group2.displayName} (${group2.projects.length} projects, ${totalSessions2} sessions)${isCurrent}`);
8074
+ for (const proj of group2.projects) {
8075
+ const name = getAdapter(proj.source).name;
8076
+ const cwdMarker = proj.projectPath === process.cwd() ? " [cwd]" : "";
8077
+ lines.push(` [${name}] ${proj.displayPath} (${proj.sessionCount} sessions)${cwdMarker}`);
8078
+ }
7808
8079
  }
7809
8080
  const totalSessions = allProjects.reduce((s, p) => s + p.sessionCount, 0);
7810
8081
  console.log(`${allProjects.length} projects, ${totalSessions} sessions
@@ -7863,8 +8134,8 @@ var X = (t, e = {}, s = {}) => {
7863
8134
  const ut = t.slice(C, w) || t.slice(h, o);
7864
8135
  v = 0;
7865
8136
  for (const Y of ut.replaceAll(ct, "")) {
7866
- const $ = Y.codePointAt(0) || 0;
7867
- if (lt($) ? f = m : ht($) ? f = V : E !== A && at($) ? f = E : f = A, c + f > b && (d = Math.min(d, Math.max(C, h) + v)), c + f > i) {
8137
+ const $2 = Y.codePointAt(0) || 0;
8138
+ if (lt($2) ? f = m : ht($2) ? f = V : E !== A && at($2) ? f = E : f = A, c + f > b && (d = Math.min(d, Math.max(C, h) + v)), c + f > i) {
7868
8139
  F = true;
7869
8140
  break t;
7870
8141
  }
@@ -8501,15 +8772,15 @@ var Fe = /\p{M}+/gu;
8501
8772
  var ye = { limit: 1 / 0, ellipsis: "" };
8502
8773
  var jt = (t, r = {}, s = {}) => {
8503
8774
  const i = r.limit ?? 1 / 0, a = r.ellipsis ?? "", o = r?.ellipsisWidth ?? (a ? jt(a, ye, s).width : 0), u = s.ansiWidth ?? 0, l = s.controlWidth ?? 0, n = s.tabWidth ?? 8, c = s.ambiguousWidth ?? 1, g = s.emojiWidth ?? 2, F = s.fullWidthWidth ?? 2, p = s.regularWidth ?? 1, E = s.wideWidth ?? 2;
8504
- let $ = 0, m = 0, h = t.length, y2 = 0, f = false, v = h, S2 = Math.max(0, i - o), I2 = 0, B2 = 0, A = 0, w = 0;
8775
+ let $2 = 0, m = 0, h = t.length, y2 = 0, f = false, v = h, S2 = Math.max(0, i - o), I2 = 0, B2 = 0, A = 0, w = 0;
8505
8776
  t:
8506
8777
  for (;; ) {
8507
- if (B2 > I2 || m >= h && m > $) {
8508
- const _2 = t.slice(I2, B2) || t.slice($, m);
8778
+ if (B2 > I2 || m >= h && m > $2) {
8779
+ const _2 = t.slice(I2, B2) || t.slice($2, m);
8509
8780
  y2 = 0;
8510
8781
  for (const D2 of _2.replaceAll(Fe, "")) {
8511
8782
  const T2 = D2.codePointAt(0) || 0;
8512
- if (ge(T2) ? w = F : fe(T2) ? w = E : c !== p && pe(T2) ? w = c : w = p, A + w > S2 && (v = Math.min(v, Math.max(I2, $) + y2)), A + w > i) {
8783
+ if (ge(T2) ? w = F : fe(T2) ? w = E : c !== p && pe(T2) ? w = c : w = p, A + w > S2 && (v = Math.min(v, Math.max(I2, $2) + y2)), A + w > i) {
8513
8784
  f = true;
8514
8785
  break t;
8515
8786
  }
@@ -8524,7 +8795,7 @@ var jt = (t, r = {}, s = {}) => {
8524
8795
  f = true;
8525
8796
  break;
8526
8797
  }
8527
- A += w, I2 = $, B2 = m, m = $ = at2.lastIndex;
8798
+ A += w, I2 = $2, B2 = m, m = $2 = at2.lastIndex;
8528
8799
  continue;
8529
8800
  }
8530
8801
  if (At2.lastIndex = m, At2.test(t)) {
@@ -8532,7 +8803,7 @@ var jt = (t, r = {}, s = {}) => {
8532
8803
  f = true;
8533
8804
  break;
8534
8805
  }
8535
- A += u, I2 = $, B2 = m, m = $ = At2.lastIndex;
8806
+ A += u, I2 = $2, B2 = m, m = $2 = At2.lastIndex;
8536
8807
  continue;
8537
8808
  }
8538
8809
  if (it2.lastIndex = m, it2.test(t)) {
@@ -8540,7 +8811,7 @@ var jt = (t, r = {}, s = {}) => {
8540
8811
  f = true;
8541
8812
  break;
8542
8813
  }
8543
- A += w, I2 = $, B2 = m, m = $ = it2.lastIndex;
8814
+ A += w, I2 = $2, B2 = m, m = $2 = it2.lastIndex;
8544
8815
  continue;
8545
8816
  }
8546
8817
  if (nt2.lastIndex = m, nt2.test(t)) {
@@ -8548,7 +8819,7 @@ var jt = (t, r = {}, s = {}) => {
8548
8819
  f = true;
8549
8820
  break;
8550
8821
  }
8551
- A += w, I2 = $, B2 = m, m = $ = nt2.lastIndex;
8822
+ A += w, I2 = $2, B2 = m, m = $2 = nt2.lastIndex;
8552
8823
  continue;
8553
8824
  }
8554
8825
  if (wt2.lastIndex = m, wt2.test(t)) {
@@ -8556,7 +8827,7 @@ var jt = (t, r = {}, s = {}) => {
8556
8827
  f = true;
8557
8828
  break;
8558
8829
  }
8559
- A += g, I2 = $, B2 = m, m = $ = wt2.lastIndex;
8830
+ A += g, I2 = $2, B2 = m, m = $2 = wt2.lastIndex;
8560
8831
  continue;
8561
8832
  }
8562
8833
  m += 1;
@@ -8619,34 +8890,34 @@ var Ie = (t, r, s = {}) => {
8619
8890
  let i = "", a, o;
8620
8891
  const u = t.split(" "), l = Ce(u);
8621
8892
  let n = [""];
8622
- for (const [$, m] of u.entries()) {
8893
+ for (const [$2, m] of u.entries()) {
8623
8894
  s.trim !== false && (n[n.length - 1] = (n.at(-1) ?? "").trimStart());
8624
8895
  let h = M2(n.at(-1) ?? "");
8625
- if ($ !== 0 && (h >= r && (s.wordWrap === false || s.trim === false) && (n.push(""), h = 0), (h > 0 || s.trim === false) && (n[n.length - 1] += " ", h++)), s.hard && l[$] > r) {
8626
- const y2 = r - h, f = 1 + Math.floor((l[$] - y2 - 1) / r);
8627
- Math.floor((l[$] - 1) / r) < f && n.push(""), It2(n, m, r);
8896
+ if ($2 !== 0 && (h >= r && (s.wordWrap === false || s.trim === false) && (n.push(""), h = 0), (h > 0 || s.trim === false) && (n[n.length - 1] += " ", h++)), s.hard && l[$2] > r) {
8897
+ const y2 = r - h, f = 1 + Math.floor((l[$2] - y2 - 1) / r);
8898
+ Math.floor((l[$2] - 1) / r) < f && n.push(""), It2(n, m, r);
8628
8899
  continue;
8629
8900
  }
8630
- if (h + l[$] > r && h > 0 && l[$] > 0) {
8901
+ if (h + l[$2] > r && h > 0 && l[$2] > 0) {
8631
8902
  if (s.wordWrap === false && h < r) {
8632
8903
  It2(n, m, r);
8633
8904
  continue;
8634
8905
  }
8635
8906
  n.push("");
8636
8907
  }
8637
- if (h + l[$] > r && s.wordWrap === false) {
8908
+ if (h + l[$2] > r && s.wordWrap === false) {
8638
8909
  It2(n, m, r);
8639
8910
  continue;
8640
8911
  }
8641
8912
  n[n.length - 1] += m;
8642
8913
  }
8643
- s.trim !== false && (n = n.map(($) => Se($)));
8914
+ s.trim !== false && (n = n.map(($2) => Se($2)));
8644
8915
  const c = n.join(`
8645
8916
  `), g = c[Symbol.iterator]();
8646
8917
  let F = g.next(), p = g.next(), E = 0;
8647
8918
  for (;!F.done; ) {
8648
- const $ = F.value, m = p.value;
8649
- if (i += $, $ === ot2 || $ === Gt) {
8919
+ const $2 = F.value, m = p.value;
8920
+ if (i += $2, $2 === ot2 || $2 === Gt) {
8650
8921
  Ht.lastIndex = E + 1;
8651
8922
  const f = Ht.exec(c)?.groups;
8652
8923
  if (f?.code !== undefined) {
@@ -8657,8 +8928,8 @@ var Ie = (t, r, s = {}) => {
8657
8928
  }
8658
8929
  const h = a ? we(a) : undefined;
8659
8930
  m === `
8660
- ` ? (o && (i += Kt("")), a && h && (i += Ut(h))) : $ === `
8661
- ` && (a && h && (i += Ut(a)), o && (i += Kt(o))), E += $.length, F = p, p = g.next();
8931
+ ` ? (o && (i += Kt("")), a && h && (i += Ut(h))) : $2 === `
8932
+ ` && (a && h && (i += Ut(a)), o && (i += Kt(o))), E += $2.length, F = p, p = g.next();
8662
8933
  }
8663
8934
  return i;
8664
8935
  };
@@ -8680,13 +8951,13 @@ var be = (t, r, s, i, a) => {
8680
8951
  };
8681
8952
  var X2 = (t) => {
8682
8953
  const { cursor: r, options: s, style: i } = t, a = t.output ?? process.stdout, o = rt(a), u = t.columnPadding ?? 0, l = t.rowPadding ?? 4, n = o - u, c = nt(a), g = import_picocolors2.default.dim("..."), F = t.maxItems ?? Number.POSITIVE_INFINITY, p = Math.max(c - l, 0), E = Math.max(Math.min(F, p), 5);
8683
- let $ = 0;
8684
- r >= E - 3 && ($ = Math.max(Math.min(r - E + 3, s.length - E), 0));
8685
- let m = E < s.length && $ > 0, h = E < s.length && $ + E < s.length;
8686
- const y2 = Math.min($ + E, s.length), f = [];
8954
+ let $2 = 0;
8955
+ r >= E - 3 && ($2 = Math.max(Math.min(r - E + 3, s.length - E), 0));
8956
+ let m = E < s.length && $2 > 0, h = E < s.length && $2 + E < s.length;
8957
+ const y2 = Math.min($2 + E, s.length), f = [];
8687
8958
  let v = 0;
8688
8959
  m && v++, h && v++;
8689
- const S2 = $ + (m ? 1 : 0), I2 = y2 - (h ? 1 : 0);
8960
+ const S2 = $2 + (m ? 1 : 0), I2 = y2 - (h ? 1 : 0);
8690
8961
  for (let A = S2;A < I2; A++) {
8691
8962
  const w = J2(i(s[A], A === r), n, { hard: true, trim: false }).split(`
8692
8963
  `);
@@ -8712,8 +8983,8 @@ function Yt(t, r, s, i) {
8712
8983
  }
8713
8984
  var Te = (t) => t;
8714
8985
  var Me = (t = "", r = "", s) => {
8715
- const i = s?.output ?? process.stdout, a = rt(i), o = 2, u = s?.titlePadding ?? 1, l = s?.contentPadding ?? 2, n = s?.width === undefined || s.width === "auto" ? 1 : Math.min(1, s.width), c = s?.withGuide ?? _.withGuide ? `${d} ` : "", g = s?.formatBorder ?? Te, F = ((s?.rounded) ? _e : De).map(g), p = g(rt2), E = g(d), $ = M2(c), m = M2(r), h = a - $;
8716
- let y2 = Math.floor(a * n) - $;
8986
+ const i = s?.output ?? process.stdout, a = rt(i), o = 2, u = s?.titlePadding ?? 1, l = s?.contentPadding ?? 2, n = s?.width === undefined || s.width === "auto" ? 1 : Math.min(1, s.width), c = s?.withGuide ?? _.withGuide ? `${d} ` : "", g = s?.formatBorder ?? Te, F = ((s?.rounded) ? _e : De).map(g), p = g(rt2), E = g(d), $2 = M2(c), m = M2(r), h = a - $2;
8987
+ let y2 = Math.floor(a * n) - $2;
8717
8988
  if (s?.width === "auto") {
8718
8989
  const _2 = t.split(`
8719
8990
  `);
@@ -8775,8 +9046,8 @@ var R2 = { message: (t = [], { symbol: r = import_picocolors2.default.gray(d), s
8775
9046
  if (F.length > 0) {
8776
9047
  const [p, ...E] = F;
8777
9048
  p.length > 0 ? u.push(`${c}${p}`) : u.push(l ? r : "");
8778
- for (const $ of E)
8779
- $.length > 0 ? u.push(`${g}${$}`) : u.push(l ? s : "");
9049
+ for (const $2 of E)
9050
+ $2.length > 0 ? u.push(`${g}${$2}`) : u.push(l ? s : "");
8780
9051
  }
8781
9052
  i.write(`${u.join(`
8782
9053
  `)}
@@ -8868,7 +9139,7 @@ ${import_picocolors2.default.cyan(x2)}
8868
9139
  var Ke = import_picocolors2.default.magenta;
8869
9140
  var bt2 = ({ indicator: t = "dots", onCancel: r, output: s = process.stdout, cancelMessage: i, errorMessage: a, frames: o = et2 ? ["\u25D2", "\u25D0", "\u25D3", "\u25D1"] : ["\u2022", "o", "O", "0"], delay: u = et2 ? 80 : 120, signal: l, ...n } = {}) => {
8870
9141
  const c = ct2();
8871
- let g, F, p = false, E = false, $ = "", m, h = performance.now();
9142
+ let g, F, p = false, E = false, $2 = "", m, h = performance.now();
8872
9143
  const y2 = rt(s), f = n?.styleFrame ?? Ke, v = (b) => {
8873
9144
  const O2 = b > 1 ? a ?? _.messages.error : i ?? _.messages.cancel;
8874
9145
  E = b === 1, p && (L2(O2, b), E && typeof r == "function" && r());
@@ -8888,22 +9159,22 @@ var bt2 = ({ indicator: t = "dots", onCancel: r, output: s = process.stdout, can
8888
9159
  const O2 = (performance.now() - b) / 1000, j2 = Math.floor(O2 / 60), G2 = Math.floor(O2 % 60);
8889
9160
  return j2 > 0 ? `[${j2}m ${G2}s]` : `[${G2}s]`;
8890
9161
  }, T2 = n.withGuide ?? _.withGuide, Y = (b = "") => {
8891
- p = true, g = Bt({ output: s }), $ = _2(b), h = performance.now(), T2 && s.write(`${import_picocolors2.default.gray(d)}
9162
+ p = true, g = Bt({ output: s }), $2 = _2(b), h = performance.now(), T2 && s.write(`${import_picocolors2.default.gray(d)}
8892
9163
  `);
8893
9164
  let O2 = 0, j2 = 0;
8894
9165
  B2(), F = setInterval(() => {
8895
- if (c && $ === m)
9166
+ if (c && $2 === m)
8896
9167
  return;
8897
- w(), m = $;
9168
+ w(), m = $2;
8898
9169
  const G2 = f(o[O2]);
8899
9170
  let tt2;
8900
9171
  if (c)
8901
- tt2 = `${G2} ${$}...`;
9172
+ tt2 = `${G2} ${$2}...`;
8902
9173
  else if (t === "timer")
8903
- tt2 = `${G2} ${$} ${D2(h)}`;
9174
+ tt2 = `${G2} ${$2} ${D2(h)}`;
8904
9175
  else {
8905
9176
  const te = ".".repeat(Math.floor(j2)).slice(0, 3);
8906
- tt2 = `${G2} ${$}${te}`;
9177
+ tt2 = `${G2} ${$2}${te}`;
8907
9178
  }
8908
9179
  const Zt = J2(tt2, y2, { hard: true, trim: false });
8909
9180
  s.write(Zt), O2 = O2 + 1 < o.length ? O2 + 1 : 0, j2 = j2 < 4 ? j2 + 0.125 : 0;
@@ -8913,12 +9184,12 @@ var bt2 = ({ indicator: t = "dots", onCancel: r, output: s = process.stdout, can
8913
9184
  return;
8914
9185
  p = false, clearInterval(F), w();
8915
9186
  const G2 = O2 === 0 ? import_picocolors2.default.green(V) : O2 === 1 ? import_picocolors2.default.red(dt2) : import_picocolors2.default.red($t2);
8916
- $ = b ?? $, j2 || (t === "timer" ? s.write(`${G2} ${$} ${D2(h)}
8917
- `) : s.write(`${G2} ${$}
9187
+ $2 = b ?? $2, j2 || (t === "timer" ? s.write(`${G2} ${$2} ${D2(h)}
9188
+ `) : s.write(`${G2} ${$2}
8918
9189
  `)), A(), g();
8919
9190
  };
8920
9191
  return { start: Y, stop: (b = "") => L2(b, 0), message: (b = "") => {
8921
- $ = _2(b ?? $);
9192
+ $2 = _2(b ?? $2);
8922
9193
  }, cancel: (b = "") => L2(b, 1), error: (b = "") => L2(b, 2), clear: () => L2("", 0, true), get isCancelled() {
8923
9194
  return E;
8924
9195
  } };
@@ -8940,13 +9211,13 @@ function qe({ style: t = "heavy", max: r = 100, size: s = 40, ...i } = {}) {
8940
9211
  default:
8941
9212
  return import_picocolors2.default.magenta;
8942
9213
  }
8943
- }, g = (E, $) => {
9214
+ }, g = (E, $2) => {
8944
9215
  const m = Math.floor(o / l * n);
8945
- return `${c(E)(zt[t].repeat(m))}${import_picocolors2.default.dim(zt[t].repeat(n - m))} ${$}`;
9216
+ return `${c(E)(zt[t].repeat(m))}${import_picocolors2.default.dim(zt[t].repeat(n - m))} ${$2}`;
8946
9217
  }, F = (E = "") => {
8947
9218
  u = E, a.start(g("initial", E));
8948
- }, p = (E = 1, $) => {
8949
- o = Math.min(l, E + o), a.message(g("active", $ ?? u)), u = $ ?? u;
9219
+ }, p = (E = 1, $2) => {
9220
+ o = Math.min(l, E + o), a.message(g("active", $2 ?? u)), u = $2 ?? u;
8950
9221
  };
8951
9222
  return { start: F, stop: a.stop, cancel: a.cancel, error: a.error, clear: a.clear, advance: p, isCancelled: a.isCancelled, message: (E) => p(0, E) };
8952
9223
  }
@@ -10505,13 +10776,13 @@ import {
10505
10776
  rmSync,
10506
10777
  writeFileSync as writeFileSync3
10507
10778
  } from "fs";
10508
- import { homedir as homedir5 } from "os";
10509
- import { join as join6 } from "path";
10779
+ import { homedir as homedir7 } from "os";
10780
+ import { join as join8 } from "path";
10510
10781
  function getConfigDir() {
10511
- return process.env.RUDEL_CONFIG_DIR ?? join6(homedir5(), ".rudel");
10782
+ return process.env.RUDEL_CONFIG_DIR ?? join8(homedir7(), ".rudel");
10512
10783
  }
10513
10784
  function getCredentialsPath() {
10514
- return join6(getConfigDir(), "credentials.json");
10785
+ return join8(getConfigDir(), "credentials.json");
10515
10786
  }
10516
10787
  function saveCredentials(token, apiBaseUrl) {
10517
10788
  const dir = getConfigDir();
@@ -10694,8 +10965,8 @@ async function pMap(iterable, mapper, {
10694
10965
  var pMapSkip = Symbol("skip");
10695
10966
 
10696
10967
  // src/lib/failed-uploads.ts
10697
- import { homedir as homedir6 } from "os";
10698
- import { join as join7 } from "path";
10968
+ import { homedir as homedir8 } from "os";
10969
+ import { join as join9 } from "path";
10699
10970
 
10700
10971
  // ../../node_modules/.bun/@orpc+contract@1.13.6/node_modules/@orpc/contract/dist/shared/contract.D_dZrO__.mjs
10701
10972
  function mergeErrorMap(errorMap1, errorMap2) {
@@ -11393,7 +11664,7 @@ var contract = {
11393
11664
  };
11394
11665
 
11395
11666
  // src/lib/failed-uploads.ts
11396
- var FAILED_UPLOADS_PATH = join7(homedir6(), ".rudel", "failed-uploads.json");
11667
+ var FAILED_UPLOADS_PATH = join9(homedir8(), ".rudel", "failed-uploads.json");
11397
11668
  function normalizeSource(raw) {
11398
11669
  if (typeof raw !== "string")
11399
11670
  return;
@@ -11541,125 +11812,16 @@ function renderBatchSummary(summary, options) {
11541
11812
  }
11542
11813
  }
11543
11814
 
11544
- // src/lib/git-info.ts
11545
- import { join as join8 } from "path";
11546
- var {$ } = globalThis.Bun;
11547
- function normalizeRemoteUrl(url) {
11548
- return url.replace(/^(https?:\/\/|git@|ssh:\/\/)/, "").replace(/:/, "/").replace(/\.git$/, "");
11549
- }
11550
- async function getGitInfo(cwd) {
11551
- const [remoteUrl, branch, sha, packageInfo] = await Promise.all([
11552
- getGitRemoteUrl(cwd),
11553
- getGitBranch(cwd),
11554
- getGitSha(cwd),
11555
- getPackageInfo(cwd)
11556
- ]);
11557
- const gitRemote = remoteUrl ? normalizeRemoteUrl(remoteUrl) : undefined;
11558
- return {
11559
- gitRemote,
11560
- packageName: packageInfo?.name,
11561
- packageType: packageInfo?.type,
11562
- branch: branch ?? undefined,
11563
- sha: sha ?? undefined
11564
- };
11565
- }
11566
- async function getPackageInfo(cwd) {
11567
- try {
11568
- const gitRootResult = await $`git -C ${cwd} rev-parse --show-toplevel`.quiet();
11569
- const root = gitRootResult.exitCode === 0 ? gitRootResult.text().trim() : cwd;
11570
- return await getNodePackage(root) ?? await getPythonPackage(root) ?? await getRustPackage(root) ?? await getGoModule(root);
11571
- } catch {
11572
- return null;
11573
- }
11574
- }
11575
- async function getNodePackage(root) {
11576
- try {
11577
- const file = Bun.file(join8(root, "package.json"));
11578
- if (!await file.exists())
11579
- return null;
11580
- const pkg = await file.json();
11581
- return pkg.name ? { name: pkg.name, type: "package.json" } : null;
11582
- } catch {
11583
- return null;
11584
- }
11585
- }
11586
- async function getPythonPackage(root) {
11587
- try {
11588
- const file = Bun.file(join8(root, "pyproject.toml"));
11589
- if (!await file.exists())
11590
- return null;
11591
- const content = await file.text();
11592
- const name = content.match(/^\s*name\s*=\s*"([^"]+)"/m)?.[1];
11593
- return name ? { name, type: "pyproject.toml" } : null;
11594
- } catch {
11595
- return null;
11596
- }
11597
- }
11598
- async function getRustPackage(root) {
11599
- try {
11600
- const file = Bun.file(join8(root, "Cargo.toml"));
11601
- if (!await file.exists())
11602
- return null;
11603
- const content = await file.text();
11604
- const name = content.match(/^\s*name\s*=\s*"([^"]+)"/m)?.[1];
11605
- return name ? { name, type: "Cargo.toml" } : null;
11606
- } catch {
11607
- return null;
11608
- }
11609
- }
11610
- async function getGoModule(root) {
11611
- try {
11612
- const file = Bun.file(join8(root, "go.mod"));
11613
- if (!await file.exists())
11614
- return null;
11615
- const content = await file.text();
11616
- const name = content.match(/^module\s+(\S+)/m)?.[1];
11617
- return name ? { name, type: "go.mod" } : null;
11618
- } catch {
11619
- return null;
11620
- }
11621
- }
11622
- async function getGitRemoteUrl(cwd) {
11623
- try {
11624
- const result = await $`git -C ${cwd} remote get-url origin`.quiet();
11625
- if (result.exitCode !== 0)
11626
- return null;
11627
- return result.text().trim() || null;
11628
- } catch {
11629
- return null;
11630
- }
11631
- }
11632
- async function getGitBranch(cwd) {
11633
- try {
11634
- const result = await $`git -C ${cwd} rev-parse --abbrev-ref HEAD`.quiet();
11635
- if (result.exitCode !== 0)
11636
- return null;
11637
- return result.text().trim();
11638
- } catch {
11639
- return null;
11640
- }
11641
- }
11642
- async function getGitSha(cwd) {
11643
- try {
11644
- const result = await $`git -C ${cwd} rev-parse HEAD`.quiet();
11645
- if (result.exitCode !== 0)
11646
- return null;
11647
- return result.text().trim();
11648
- } catch {
11649
- return null;
11650
- }
11651
- }
11652
-
11653
11815
  // src/lib/project-config.ts
11654
11816
  import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
11655
- import { homedir as homedir7 } from "os";
11656
- import { join as join9 } from "path";
11817
+ import { homedir as homedir9 } from "os";
11818
+ import { join as join10 } from "path";
11657
11819
  var {$: $2 } = globalThis.Bun;
11658
11820
  function getConfigDir2() {
11659
- return process.env.RUDEL_CONFIG_DIR ?? join9(homedir7(), ".rudel");
11821
+ return process.env.RUDEL_CONFIG_DIR ?? join10(homedir9(), ".rudel");
11660
11822
  }
11661
11823
  function getProjectsConfigPath() {
11662
- return join9(getConfigDir2(), "projects.json");
11824
+ return join10(getConfigDir2(), "projects.json");
11663
11825
  }
11664
11826
  function loadProjectsConfig() {
11665
11827
  const path = getProjectsConfigPath();
@@ -13503,8 +13665,8 @@ var ConfigError = class extends Error {
13503
13665
  };
13504
13666
 
13505
13667
  // src/logging.ts
13506
- import { homedir as homedir8 } from "os";
13507
- import { join as join11 } from "path";
13668
+ import { homedir as homedir10 } from "os";
13669
+ import { join as join12 } from "path";
13508
13670
 
13509
13671
  // ../../node_modules/.bun/@logtape+file@2.0.4+2d5de51540e256d2/node_modules/@logtape/file/dist/filesink.base.js
13510
13672
  var AdaptiveFlushStrategy = class {
@@ -13770,7 +13932,7 @@ function getBaseFileSink(path, options) {
13770
13932
 
13771
13933
  // ../../node_modules/.bun/@logtape+file@2.0.4+2d5de51540e256d2/node_modules/@logtape/file/dist/filesink.node.js
13772
13934
  import fs from "fs";
13773
- import { join as join10 } from "path";
13935
+ import { join as join11 } from "path";
13774
13936
  import { promisify } from "util";
13775
13937
  var nodeDriver = {
13776
13938
  openSync(path) {
@@ -13810,14 +13972,14 @@ var nodeTimeDriver = {
13810
13972
  readdirSync: fs.readdirSync,
13811
13973
  unlinkSync: fs.unlinkSync,
13812
13974
  mkdirSync: fs.mkdirSync,
13813
- joinPath: join10
13975
+ joinPath: join11
13814
13976
  };
13815
13977
  var nodeAsyncTimeDriver = {
13816
13978
  ...nodeAsyncDriver,
13817
13979
  readdirSync: fs.readdirSync,
13818
13980
  unlinkSync: fs.unlinkSync,
13819
13981
  mkdirSync: fs.mkdirSync,
13820
- joinPath: join10
13982
+ joinPath: join11
13821
13983
  };
13822
13984
  function getFileSink(path, options = {}) {
13823
13985
  if (options.nonBlocking)
@@ -13832,8 +13994,8 @@ function getFileSink(path, options = {}) {
13832
13994
  }
13833
13995
 
13834
13996
  // src/logging.ts
13835
- var LOG_DIR = join11(homedir8(), ".rudel", "logs");
13836
- var LOG_FILE = join11(LOG_DIR, "hook-upload.log");
13997
+ var LOG_DIR = join12(homedir10(), ".rudel", "logs");
13998
+ var LOG_FILE = join12(LOG_DIR, "hook-upload.log");
13837
13999
  async function setupHookLogging() {
13838
14000
  const { mkdir } = await import("fs/promises");
13839
14001
  await mkdir(LOG_DIR, { recursive: true }).catch(() => {});
@@ -14215,8 +14377,8 @@ var setOrgCommand = buildCommand({
14215
14377
 
14216
14378
  // src/lib/classifier.ts
14217
14379
  import { mkdir, unlink } from "fs/promises";
14218
- import { homedir as homedir9 } from "os";
14219
- import { join as join12 } from "path";
14380
+ import { homedir as homedir11 } from "os";
14381
+ import { join as join13 } from "path";
14220
14382
 
14221
14383
  // src/lib/types.ts
14222
14384
  var SESSION_TAGS = [
@@ -14243,8 +14405,8 @@ var SYSTEM_PROMPT = `You are a session classifier. Analyze the Claude Code sessi
14243
14405
  CRITICAL: Respond with ONLY the tag name. Nothing else. No explanation, no punctuation, no formatting. Just ONE of: research, new_feature, bug_fix, refactoring, documentation, tests`;
14244
14406
  async function classifySession(content) {
14245
14407
  const truncatedContent = content.slice(0, 50000);
14246
- const tempDir = join12(homedir9(), ".claude", "temp");
14247
- const tempFile = join12(tempDir, `classify-${Date.now()}.txt`);
14408
+ const tempDir = join13(homedir11(), ".claude", "temp");
14409
+ const tempFile = join13(tempDir, `classify-${Date.now()}.txt`);
14248
14410
  try {
14249
14411
  await mkdir(tempDir, { recursive: true });
14250
14412
  await Bun.write(tempFile, `Classify this session transcript:
@@ -14284,9 +14446,9 @@ ${truncatedContent}`);
14284
14446
 
14285
14447
  // src/lib/session-resolver.ts
14286
14448
  import { access, readdir as readdir3 } from "fs/promises";
14287
- import { homedir as homedir10 } from "os";
14288
- import { basename, dirname as dirname3, join as join13 } from "path";
14289
- var SESSIONS_BASE_DIR3 = join13(homedir10(), ".claude", "projects");
14449
+ import { homedir as homedir12 } from "os";
14450
+ import { basename, dirname as dirname3, join as join14 } from "path";
14451
+ var SESSIONS_BASE_DIR3 = join14(homedir12(), ".claude", "projects");
14290
14452
  async function resolveSession(input) {
14291
14453
  const isPath = input.includes("/") || input.endsWith(".jsonl");
14292
14454
  if (isPath) {
@@ -14318,11 +14480,11 @@ async function resolveFromId(sessionId) {
14318
14480
  throw new Error(`Session not found: ${sessionId}`);
14319
14481
  }
14320
14482
  for (const projectDir of projectDirs) {
14321
- const sessionDir = join13(SESSIONS_BASE_DIR3, projectDir);
14483
+ const sessionDir = join14(SESSIONS_BASE_DIR3, projectDir);
14322
14484
  try {
14323
14485
  const files = await readdir3(sessionDir);
14324
14486
  if (files.includes(sessionFileName)) {
14325
- const transcriptPath = join13(sessionDir, sessionFileName);
14487
+ const transcriptPath = join14(sessionDir, sessionFileName);
14326
14488
  const projectPath = await decodeProjectPath(projectDir);
14327
14489
  return {
14328
14490
  transcriptPath,
@@ -14352,45 +14514,26 @@ async function runInteractiveUpload(flags) {
14352
14514
  We("rudel upload");
14353
14515
  const spin = bt2();
14354
14516
  spin.start("Scanning projects...");
14355
- const adapters2 = getAvailableAdapters();
14356
- const allProjects = [];
14357
- for (const adapter of adapters2) {
14358
- const projects = await adapter.scanAllSessions();
14359
- allProjects.push(...projects);
14360
- }
14517
+ const { projects: allProjects, groups } = await scanAndGroupProjects();
14361
14518
  spin.stop(`Found ${allProjects.length} project(s)`);
14362
14519
  if (allProjects.length === 0) {
14363
14520
  R2.warn("No projects with sessions found.");
14364
14521
  Le("Nothing to upload.");
14365
14522
  return;
14366
14523
  }
14367
- const cwd = process.cwd();
14368
- const grouped = groupProjectsForCwd(allProjects, cwd);
14369
14524
  const options = [];
14370
14525
  const preSelected = [];
14371
- for (const proj of grouped.current) {
14372
- options.push({
14373
- value: proj,
14374
- label: `[${getAdapterName(proj.source)}] ${proj.displayPath}`,
14375
- hint: sessionCountHint(proj.sessionCount)
14376
- });
14377
- preSelected.push(proj);
14378
- }
14379
- for (const sub of grouped.subfolders) {
14380
- const relative = sub.projectPath.slice(cwd.length + 1);
14381
- options.push({
14382
- value: sub,
14383
- label: ` [${getAdapterName(sub.source)}] ${relative}`,
14384
- hint: sessionCountHint(sub.sessionCount)
14385
- });
14386
- preSelected.push(sub);
14387
- }
14388
- for (const other of grouped.others) {
14389
- options.push({
14390
- value: other,
14391
- label: `[${getAdapterName(other.source)}] ${other.displayPath}`,
14392
- hint: sessionCountHint(other.sessionCount)
14393
- });
14526
+ for (const group2 of groups) {
14527
+ for (const proj of group2.projects) {
14528
+ options.push({
14529
+ value: proj,
14530
+ label: `[${getAdapterName(proj.source)}] ${proj.displayPath}`,
14531
+ hint: sessionCountHint(proj.sessionCount)
14532
+ });
14533
+ if (group2.containsCwd) {
14534
+ preSelected.push(proj);
14535
+ }
14536
+ }
14394
14537
  }
14395
14538
  const selected = await je({
14396
14539
  message: "Select projects to upload",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rudel",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "type": "module",
5
5
  "description": "CLI for the Coding Agent Analytics Platform rudel.ai",
6
6
  "license": "MIT",