rudel 0.2.0 → 0.2.2

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 +134 -68
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,5 +1,4 @@
1
1
  #!/usr/bin/env node
2
- import { createRequire } from "node:module";
3
2
  var __create = Object.create;
4
3
  var __getProtoOf = Object.getPrototypeOf;
5
4
  var __defProp = Object.defineProperty;
@@ -26,7 +25,6 @@ var __export = (target, all) => {
26
25
  set: (newValue) => all[name] = () => newValue
27
26
  });
28
27
  };
29
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
30
28
 
31
29
  // ../../node_modules/sisteransi/src/index.js
32
30
  var require_src = __commonJS((exports, module) => {
@@ -1889,7 +1887,7 @@ async function run(app, inputs, context) {
1889
1887
  // package.json
1890
1888
  var package_default = {
1891
1889
  name: "rudel",
1892
- version: "0.2.0",
1890
+ version: "0.2.2",
1893
1891
  type: "module",
1894
1892
  description: "CLI for the Coding Agent Analytics Platform rudel.ai",
1895
1893
  license: "MIT",
@@ -7795,7 +7793,8 @@ function exec(cmd, args) {
7795
7793
 
7796
7794
  // src/lib/git-info.ts
7797
7795
  function normalizeRemoteUrl(url) {
7798
- return url.replace(/^(https?:\/\/|git@|ssh:\/\/)/, "").replace(/:/, "/").replace(/\.git$/, "");
7796
+ const sanitizedUrl = url.replace(/^([a-z][a-z\d+.-]*:\/\/)[^/]+@/i, "$1");
7797
+ return sanitizedUrl.replace(/^(https?:\/\/|git@|ssh:\/\/)/, "").replace(/:/, "/").replace(/\.git$/, "");
7799
7798
  }
7800
7799
  async function getGitInfo(cwd) {
7801
7800
  const [remoteUrl, branch, sha, packageInfo] = await Promise.all([
@@ -7919,15 +7918,43 @@ async function getGitSha(cwd) {
7919
7918
 
7920
7919
  // src/lib/remote-cache.ts
7921
7920
  import { existsSync as existsSync5, readFileSync as readFileSync4 } from "node:fs";
7922
- import { mkdir, writeFile } from "node:fs/promises";
7921
+ import { join as join8 } from "node:path";
7922
+
7923
+ // src/lib/local-state.ts
7924
+ import { chmod, mkdir, writeFile } from "node:fs/promises";
7923
7925
  import { homedir as homedir5 } from "node:os";
7924
7926
  import { dirname as dirname3, join as join7 } from "node:path";
7925
- var CACHE_PATH = join7(homedir5(), ".rudel", "remote-cache.json");
7927
+ var PRIVATE_DIRECTORY_MODE = 448;
7928
+ var PRIVATE_FILE_MODE = 384;
7929
+ function getRudelConfigDir() {
7930
+ return process.env.RUDEL_CONFIG_DIR ?? join7(homedir5(), ".rudel");
7931
+ }
7932
+ async function ensurePrivateFile(filePath, configDir) {
7933
+ await secureDirectory(configDir);
7934
+ const fileDirectory = dirname3(filePath);
7935
+ if (fileDirectory !== configDir) {
7936
+ await secureDirectory(fileDirectory);
7937
+ }
7938
+ await writeFile(filePath, "", { flag: "a", mode: PRIVATE_FILE_MODE });
7939
+ await chmod(filePath, PRIVATE_FILE_MODE);
7940
+ }
7941
+ async function writePrivateFile(filePath, content, configDir) {
7942
+ await ensurePrivateFile(filePath, configDir);
7943
+ await writeFile(filePath, content, "utf8");
7944
+ }
7945
+ async function secureDirectory(path) {
7946
+ await mkdir(path, { recursive: true, mode: PRIVATE_DIRECTORY_MODE });
7947
+ await chmod(path, PRIVATE_DIRECTORY_MODE);
7948
+ }
7949
+
7950
+ // src/lib/remote-cache.ts
7926
7951
  async function getRemoteCache() {
7927
7952
  try {
7928
- if (!existsSync5(CACHE_PATH))
7953
+ const path = getRemoteCachePath();
7954
+ if (!existsSync5(path))
7929
7955
  return {};
7930
- return JSON.parse(readFileSync4(CACHE_PATH, "utf-8"));
7956
+ await ensurePrivateFile(path, getRudelConfigDir());
7957
+ return JSON.parse(readFileSync4(path, "utf-8"));
7931
7958
  } catch {
7932
7959
  return {};
7933
7960
  }
@@ -7940,10 +7967,12 @@ function cacheRemote(cache, encodedDir, normalizedRemote) {
7940
7967
  }
7941
7968
  async function cacheRemotes(cache) {
7942
7969
  try {
7943
- await mkdir(dirname3(CACHE_PATH), { recursive: true });
7944
- await writeFile(CACHE_PATH, JSON.stringify(cache));
7970
+ await writePrivateFile(getRemoteCachePath(), JSON.stringify(cache), getRudelConfigDir());
7945
7971
  } catch {}
7946
7972
  }
7973
+ function getRemoteCachePath() {
7974
+ return join8(getRudelConfigDir(), "remote-cache.json");
7975
+ }
7947
7976
 
7948
7977
  // src/lib/project-grouping.ts
7949
7978
  async function scanAndGroupProjects(cwd = process.cwd()) {
@@ -10992,7 +11021,6 @@ var SessionAnalyticsSchema = exports_external.object({
10992
11021
  skills: exports_external.array(exports_external.string()),
10993
11022
  slash_commands: exports_external.array(exports_external.string()),
10994
11023
  has_commit: exports_external.boolean(),
10995
- session_archetype: exports_external.string(),
10996
11024
  model_used: exports_external.string(),
10997
11025
  used_plan_mode: exports_external.boolean(),
10998
11026
  source: SourceSchema.optional()
@@ -11015,6 +11043,8 @@ var SessionAnalyticsSummaryComparisonSchema = exports_external.object({
11015
11043
  })
11016
11044
  });
11017
11045
  var SessionListInputSchema = DaysInputSchema.extend({
11046
+ startDate: exports_external.string().date().optional(),
11047
+ endDate: exports_external.string().date().optional(),
11018
11048
  userId: exports_external.string().max(MAX_ID_FILTER_LENGTH).optional(),
11019
11049
  projectPath: exports_external.string().max(MAX_PATH_FILTER_LENGTH).optional(),
11020
11050
  repository: exports_external.string().max(MAX_PATH_FILTER_LENGTH).optional(),
@@ -11028,7 +11058,6 @@ var VALID_DIMENSIONS = [
11028
11058
  "user_id",
11029
11059
  "project_path",
11030
11060
  "repository",
11031
- "session_archetype",
11032
11061
  "model_used",
11033
11062
  "has_commit",
11034
11063
  "used_plan_mode",
@@ -11082,7 +11111,6 @@ var SessionDetailSchema = exports_external.object({
11082
11111
  success_score: exports_external.number().optional(),
11083
11112
  duration_min: exports_external.number().optional(),
11084
11113
  total_interactions: exports_external.number().optional(),
11085
- session_archetype: exports_external.string().optional(),
11086
11114
  model_used: exports_external.string().optional(),
11087
11115
  source: SourceSchema.optional()
11088
11116
  });
@@ -11819,43 +11847,77 @@ var contract = {
11819
11847
  };
11820
11848
 
11821
11849
  // src/lib/credentials.ts
11850
+ import { randomUUID } from "node:crypto";
11822
11851
  import {
11852
+ chmodSync,
11823
11853
  existsSync as existsSync6,
11824
11854
  mkdirSync as mkdirSync2,
11825
11855
  readFileSync as readFileSync5,
11856
+ renameSync,
11826
11857
  rmSync,
11858
+ statSync,
11827
11859
  writeFileSync as writeFileSync3
11828
11860
  } from "node:fs";
11829
11861
  import { homedir as homedir7 } from "node:os";
11830
- import { join as join8 } from "node:path";
11862
+ import { join as join9 } from "node:path";
11863
+ var PRIVATE_DIRECTORY_MODE2 = 448;
11864
+ var PRIVATE_FILE_MODE2 = 384;
11831
11865
  function getConfigDir() {
11832
- return process.env.RUDEL_CONFIG_DIR ?? join8(homedir7(), ".rudel");
11833
- }
11834
- function getCredentialsPath() {
11835
- return join8(getConfigDir(), "credentials.json");
11866
+ return process.env.RUDEL_CONFIG_DIR ?? join9(homedir7(), ".rudel");
11836
11867
  }
11837
11868
  function saveCredentials(credentials) {
11838
11869
  const dir = getConfigDir();
11839
- if (!existsSync6(dir)) {
11840
- mkdirSync2(dir, { recursive: true, mode: 448 });
11870
+ const path = getCredentialsPath(dir);
11871
+ const content = JSON.stringify(credentials, null, 2);
11872
+ mkdirSync2(dir, { recursive: true, mode: PRIVATE_DIRECTORY_MODE2 });
11873
+ enforcePrivateMode(dir, PRIVATE_DIRECTORY_MODE2);
11874
+ if (existsSync6(path)) {
11875
+ enforcePrivateMode(path, PRIVATE_FILE_MODE2);
11841
11876
  }
11842
- writeFileSync3(getCredentialsPath(), JSON.stringify(credentials, null, 2), {
11843
- mode: 384
11844
- });
11877
+ replaceCredentialsFile(path, content);
11845
11878
  }
11846
11879
  function loadCredentials() {
11847
- const path = getCredentialsPath();
11880
+ const dir = getConfigDir();
11881
+ const path = getCredentialsPath(dir);
11848
11882
  if (!existsSync6(path))
11849
11883
  return null;
11884
+ enforcePrivateMode(dir, PRIVATE_DIRECTORY_MODE2);
11885
+ enforcePrivateMode(path, PRIVATE_FILE_MODE2);
11850
11886
  const content = readFileSync5(path, "utf-8");
11851
11887
  return JSON.parse(content);
11852
11888
  }
11853
11889
  function clearCredentials() {
11854
- const path = getCredentialsPath();
11890
+ const path = getCredentialsPath(getConfigDir());
11855
11891
  if (existsSync6(path)) {
11856
11892
  rmSync(path);
11857
11893
  }
11858
11894
  }
11895
+ function getCredentialsPath(configDir) {
11896
+ return join9(configDir, "credentials.json");
11897
+ }
11898
+ function replaceCredentialsFile(path, content) {
11899
+ const temporaryPath = `${path}.${process.pid}.${randomUUID()}.tmp`;
11900
+ try {
11901
+ writeFileSync3(temporaryPath, content, {
11902
+ encoding: "utf8",
11903
+ flag: "wx",
11904
+ mode: PRIVATE_FILE_MODE2
11905
+ });
11906
+ enforcePrivateMode(temporaryPath, PRIVATE_FILE_MODE2);
11907
+ renameSync(temporaryPath, path);
11908
+ enforcePrivateMode(path, PRIVATE_FILE_MODE2);
11909
+ } finally {
11910
+ rmSync(temporaryPath, { force: true });
11911
+ }
11912
+ }
11913
+ function enforcePrivateMode(path, mode) {
11914
+ if (process.platform === "win32")
11915
+ return;
11916
+ chmodSync(path, mode);
11917
+ if ((statSync(path).mode & 511) !== mode) {
11918
+ throw new Error("Unable to establish private credential permissions");
11919
+ }
11920
+ }
11859
11921
 
11860
11922
  // src/lib/insecure-url-opt-in.ts
11861
11923
  var TRUTHY_ENV_VALUES = ["1", "true", "yes", "on"];
@@ -13875,12 +13937,9 @@ var pMapSkip = Symbol("skip");
13875
13937
 
13876
13938
  // src/lib/failed-uploads.ts
13877
13939
  import { existsSync as existsSync7, readFileSync as readFileSync6 } from "node:fs";
13878
- import { mkdir as mkdir2, writeFile as writeFile2 } from "node:fs/promises";
13879
- import { homedir as homedir8 } from "node:os";
13880
- import { dirname as dirname4, join as join9 } from "node:path";
13940
+ import { join as join10 } from "node:path";
13881
13941
  function getFailedUploadsPath() {
13882
- const configDir = process.env.RUDEL_CONFIG_DIR ?? join9(homedir8(), ".rudel");
13883
- return join9(configDir, "failed-uploads.json");
13942
+ return join10(getRudelConfigDir(), "failed-uploads.json");
13884
13943
  }
13885
13944
  function normalizeSource(raw) {
13886
13945
  if (typeof raw !== "string")
@@ -13894,6 +13953,7 @@ async function loadFailedUploads() {
13894
13953
  const path = getFailedUploadsPath();
13895
13954
  if (!existsSync7(path))
13896
13955
  return [];
13956
+ await ensurePrivateFile(path, getRudelConfigDir());
13897
13957
  const data = JSON.parse(readFileSync6(path, "utf-8"));
13898
13958
  return data.failures.map((f) => ({
13899
13959
  ...f,
@@ -13906,9 +13966,8 @@ async function loadFailedUploads() {
13906
13966
  async function saveFailedUploads(failures) {
13907
13967
  try {
13908
13968
  const path = getFailedUploadsPath();
13909
- await mkdir2(dirname4(path), { recursive: true });
13910
13969
  const data = { failures };
13911
- await writeFile2(path, JSON.stringify(data, null, 2));
13970
+ await writePrivateFile(path, JSON.stringify(data, null, 2), getRudelConfigDir());
13912
13971
  } catch {}
13913
13972
  }
13914
13973
  async function recordFailedUpload(failure) {
@@ -14390,13 +14449,13 @@ function renderBatchSummary(summary, options) {
14390
14449
  }
14391
14450
 
14392
14451
  // src/lib/product-analytics.ts
14393
- import { randomUUID } from "node:crypto";
14452
+ import { randomUUID as randomUUID2 } from "node:crypto";
14394
14453
  import { existsSync as existsSync8, mkdirSync as mkdirSync3, readFileSync as readFileSync7, writeFileSync as writeFileSync4 } from "node:fs";
14395
- import { homedir as homedir9 } from "node:os";
14396
- import { join as join10 } from "node:path";
14454
+ import { homedir as homedir8 } from "node:os";
14455
+ import { join as join11 } from "node:path";
14397
14456
 
14398
14457
  // ../../node_modules/posthog-node/dist/extensions/error-tracking/modifiers/module.node.mjs
14399
- import { dirname as dirname5, posix, sep } from "path";
14458
+ import { dirname as dirname4, posix, sep } from "path";
14400
14459
  function createModulerModifier() {
14401
14460
  const getModuleFromFileName = createGetModuleFromFilename();
14402
14461
  return async (frames) => {
@@ -14405,7 +14464,7 @@ function createModulerModifier() {
14405
14464
  return frames;
14406
14465
  };
14407
14466
  }
14408
- function createGetModuleFromFilename(basePath = process.argv[1] ? dirname5(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
14467
+ function createGetModuleFromFilename(basePath = process.argv[1] ? dirname4(process.argv[1]) : process.cwd(), isWindows = sep === "\\") {
14409
14468
  const normalizedBase = isWindows ? normalizeWindowsPath(basePath) : basePath;
14410
14469
  return (filename) => {
14411
14470
  if (!filename)
@@ -18865,10 +18924,10 @@ function getClient() {
18865
18924
  return client;
18866
18925
  }
18867
18926
  function getConfigDir2() {
18868
- return process.env.RUDEL_CONFIG_DIR ?? join10(homedir9(), ".rudel");
18927
+ return process.env.RUDEL_CONFIG_DIR ?? join11(homedir8(), ".rudel");
18869
18928
  }
18870
18929
  function getAnalyticsStatePath() {
18871
- return join10(getConfigDir2(), ANALYTICS_STATE_FILE);
18930
+ return join11(getConfigDir2(), ANALYTICS_STATE_FILE);
18872
18931
  }
18873
18932
  function readAnalyticsState() {
18874
18933
  const statePath = getAnalyticsStatePath();
@@ -18912,7 +18971,7 @@ function getOrCreateCliInstallationId() {
18912
18971
  if (typeof state.cli_installation_id === "string") {
18913
18972
  return state.cli_installation_id;
18914
18973
  }
18915
- const cliInstallationId = randomUUID();
18974
+ const cliInstallationId = randomUUID2();
18916
18975
  writeAnalyticsState({
18917
18976
  ...state,
18918
18977
  cli_installation_id: cliInstallationId
@@ -19021,30 +19080,37 @@ function getBaseCliEventPayload() {
19021
19080
  var CliProductAnalyticsEvents = PRODUCT_ANALYTICS_EVENTS;
19022
19081
 
19023
19082
  // src/lib/project-config.ts
19024
- import { existsSync as existsSync9, mkdirSync as mkdirSync4, readFileSync as readFileSync8, writeFileSync as writeFileSync5 } from "node:fs";
19025
- import { homedir as homedir10 } from "node:os";
19026
- import { join as join11 } from "node:path";
19083
+ import {
19084
+ chmodSync as chmodSync2,
19085
+ existsSync as existsSync9,
19086
+ mkdirSync as mkdirSync4,
19087
+ readFileSync as readFileSync8,
19088
+ writeFileSync as writeFileSync5
19089
+ } from "node:fs";
19090
+ import { homedir as homedir9 } from "node:os";
19091
+ import { join as join12 } from "node:path";
19027
19092
  function getConfigDir3() {
19028
- return process.env.RUDEL_CONFIG_DIR ?? join11(homedir10(), ".rudel");
19093
+ return process.env.RUDEL_CONFIG_DIR ?? join12(homedir9(), ".rudel");
19029
19094
  }
19030
19095
  function getProjectsConfigPath() {
19031
- return join11(getConfigDir3(), "projects.json");
19096
+ return join12(getConfigDir3(), "projects.json");
19032
19097
  }
19033
19098
  function loadProjectsConfig() {
19034
19099
  const path = getProjectsConfigPath();
19035
19100
  if (!existsSync9(path))
19036
19101
  return { projects: {} };
19102
+ chmodSync2(getConfigDir3(), 448);
19103
+ chmodSync2(path, 384);
19037
19104
  const content = readFileSync8(path, "utf-8");
19038
19105
  return JSON.parse(content);
19039
19106
  }
19040
19107
  function saveProjectsConfig(config) {
19041
19108
  const dir = getConfigDir3();
19042
- if (!existsSync9(dir)) {
19043
- mkdirSync4(dir, { recursive: true, mode: 448 });
19044
- }
19045
- writeFileSync5(getProjectsConfigPath(), JSON.stringify(config, null, 2), {
19046
- mode: 384
19047
- });
19109
+ mkdirSync4(dir, { recursive: true, mode: 448 });
19110
+ chmodSync2(dir, 448);
19111
+ const path = getProjectsConfigPath();
19112
+ writeFileSync5(path, JSON.stringify(config, null, 2), { mode: 384 });
19113
+ chmodSync2(path, 384);
19048
19114
  }
19049
19115
  async function getProjectKey(cwd) {
19050
19116
  try {
@@ -19057,7 +19123,9 @@ async function getProjectKey(cwd) {
19057
19123
  ]);
19058
19124
  if (result.exitCode === 0) {
19059
19125
  const url = result.stdout.trim();
19060
- return url.replace(/^(https?:\/\/|git@|ssh:\/\/)/, "").replace(/:/, "/").replace(/\.git$/, "");
19126
+ if (url.length > 0) {
19127
+ return normalizeRemoteUrl(url);
19128
+ }
19061
19129
  }
19062
19130
  } catch {}
19063
19131
  try {
@@ -20919,8 +20987,7 @@ async function reportHookUploadFailure(logger2, result, failure) {
20919
20987
  }
20920
20988
 
20921
20989
  // src/logging.ts
20922
- import { homedir as homedir11 } from "node:os";
20923
- import { join as join13 } from "node:path";
20990
+ import { join as join14 } from "node:path";
20924
20991
 
20925
20992
  // ../../node_modules/@logtape/file/dist/filesink.base.js
20926
20993
  var AdaptiveFlushStrategy = class {
@@ -21186,7 +21253,7 @@ function getBaseFileSink(path, options) {
21186
21253
 
21187
21254
  // ../../node_modules/@logtape/file/dist/filesink.node.js
21188
21255
  import fs from "node:fs";
21189
- import { join as join12 } from "node:path";
21256
+ import { join as join13 } from "node:path";
21190
21257
  import { promisify } from "node:util";
21191
21258
  var nodeDriver = {
21192
21259
  openSync(path) {
@@ -21226,14 +21293,14 @@ var nodeTimeDriver = {
21226
21293
  readdirSync: fs.readdirSync,
21227
21294
  unlinkSync: fs.unlinkSync,
21228
21295
  mkdirSync: fs.mkdirSync,
21229
- joinPath: join12
21296
+ joinPath: join13
21230
21297
  };
21231
21298
  var nodeAsyncTimeDriver = {
21232
21299
  ...nodeAsyncDriver,
21233
21300
  readdirSync: fs.readdirSync,
21234
21301
  unlinkSync: fs.unlinkSync,
21235
21302
  mkdirSync: fs.mkdirSync,
21236
- joinPath: join12
21303
+ joinPath: join13
21237
21304
  };
21238
21305
  function getFileSink(path, options = {}) {
21239
21306
  if (options.nonBlocking)
@@ -21248,14 +21315,13 @@ function getFileSink(path, options = {}) {
21248
21315
  }
21249
21316
 
21250
21317
  // src/logging.ts
21251
- var LOG_DIR = join13(homedir11(), ".rudel", "logs");
21252
- var LOG_FILE = join13(LOG_DIR, "hook-upload.log");
21253
21318
  async function setupHookLogging() {
21254
- const { mkdir: mkdir3 } = await import("node:fs/promises");
21255
- await mkdir3(LOG_DIR, { recursive: true }).catch(() => {});
21319
+ const configDir = getRudelConfigDir();
21320
+ const logFile = join14(configDir, "logs", "hook-upload.log");
21321
+ await ensurePrivateFile(logFile, configDir);
21256
21322
  await configure({
21257
21323
  sinks: {
21258
- file: getFileSink(LOG_FILE)
21324
+ file: getFileSink(logFile)
21259
21325
  },
21260
21326
  loggers: [
21261
21327
  {
@@ -21924,9 +21990,9 @@ function execWithStdin(cmd, args, stdin) {
21924
21990
 
21925
21991
  // src/lib/session-resolver.ts
21926
21992
  import { access, readdir as readdir3 } from "node:fs/promises";
21927
- import { homedir as homedir12 } from "node:os";
21928
- import { basename, dirname as dirname6, join as join14 } from "node:path";
21929
- var SESSIONS_BASE_DIR3 = join14(homedir12(), ".claude", "projects");
21993
+ import { homedir as homedir10 } from "node:os";
21994
+ import { basename, dirname as dirname5, join as join15 } from "node:path";
21995
+ var SESSIONS_BASE_DIR3 = join15(homedir10(), ".claude", "projects");
21930
21996
  async function resolveSession(input) {
21931
21997
  const isPath = input.includes("/") || input.endsWith(".jsonl");
21932
21998
  if (isPath) {
@@ -21943,7 +22009,7 @@ async function resolveFromPath(filePath) {
21943
22009
  throw new Error(`Session file not found: ${filePath}`);
21944
22010
  }
21945
22011
  const sessionId = filename.replace(/\.jsonl$/, "");
21946
- const sessionDir = dirname6(filePath);
22012
+ const sessionDir = dirname5(filePath);
21947
22013
  const parentDir = basename(sessionDir);
21948
22014
  const projectPath = await decodeProjectPath(parentDir);
21949
22015
  return { transcriptPath: filePath, projectPath, sessionDir, sessionId };
@@ -21958,11 +22024,11 @@ async function resolveFromId(sessionId) {
21958
22024
  throw new Error(`Session not found: ${sessionId}`);
21959
22025
  }
21960
22026
  for (const projectDir of projectDirs) {
21961
- const sessionDir = join14(SESSIONS_BASE_DIR3, projectDir);
22027
+ const sessionDir = join15(SESSIONS_BASE_DIR3, projectDir);
21962
22028
  try {
21963
22029
  const files = await readdir3(sessionDir);
21964
22030
  if (files.includes(sessionFileName)) {
21965
- const transcriptPath = join14(sessionDir, sessionFileName);
22031
+ const transcriptPath = join15(sessionDir, sessionFileName);
21966
22032
  const projectPath = await decodeProjectPath(projectDir);
21967
22033
  return {
21968
22034
  transcriptPath,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rudel",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "type": "module",
5
5
  "description": "CLI for the Coding Agent Analytics Platform rudel.ai",
6
6
  "license": "MIT",