chron-mcp 0.1.19 → 0.1.20

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "chron",
3
3
  "description": "Audit-grade timestamped logs for every AI conversation — stored locally, owned by you.",
4
- "version": "0.1.19",
4
+ "version": "0.1.20",
5
5
  "author": {
6
6
  "name": "Nivaya"
7
7
  },
package/dist/cli/index.js CHANGED
@@ -1184,7 +1184,7 @@ var init_sql = __esm({
1184
1184
  return new SQL([new StringChunk(str)]);
1185
1185
  }
1186
1186
  sql2.raw = raw;
1187
- function join4(chunks, separator) {
1187
+ function join6(chunks, separator) {
1188
1188
  const result = [];
1189
1189
  for (const [i, chunk] of chunks.entries()) {
1190
1190
  if (i > 0 && separator !== void 0) {
@@ -1194,7 +1194,7 @@ var init_sql = __esm({
1194
1194
  }
1195
1195
  return new SQL(result);
1196
1196
  }
1197
- sql2.join = join4;
1197
+ sql2.join = join6;
1198
1198
  function identifier(value) {
1199
1199
  return new Name(value);
1200
1200
  }
@@ -2806,7 +2806,7 @@ var require_filesystem = __commonJS({
2806
2806
  "use strict";
2807
2807
  var fs = require("fs");
2808
2808
  var LDD_PATH = "/usr/bin/ldd";
2809
- var readFileSync2 = (path) => fs.readFileSync(path, "utf-8");
2809
+ var readFileSync3 = (path) => fs.readFileSync(path, "utf-8");
2810
2810
  var readFile = (path) => new Promise((resolve, reject) => {
2811
2811
  fs.readFile(path, "utf-8", (err, data) => {
2812
2812
  if (err) {
@@ -2818,7 +2818,7 @@ var require_filesystem = __commonJS({
2818
2818
  });
2819
2819
  module2.exports = {
2820
2820
  LDD_PATH,
2821
- readFileSync: readFileSync2,
2821
+ readFileSync: readFileSync3,
2822
2822
  readFile
2823
2823
  };
2824
2824
  }
@@ -2830,7 +2830,7 @@ var require_detect_libc = __commonJS({
2830
2830
  "use strict";
2831
2831
  var childProcess = require("child_process");
2832
2832
  var { isLinux, getReport } = require_process();
2833
- var { LDD_PATH, readFile, readFileSync: readFileSync2 } = require_filesystem();
2833
+ var { LDD_PATH, readFile, readFileSync: readFileSync3 } = require_filesystem();
2834
2834
  var cachedFamilyFilesystem;
2835
2835
  var cachedVersionFilesystem;
2836
2836
  var command2 = "getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true";
@@ -2911,7 +2911,7 @@ var require_detect_libc = __commonJS({
2911
2911
  }
2912
2912
  cachedFamilyFilesystem = null;
2913
2913
  try {
2914
- const lddContent = readFileSync2(LDD_PATH);
2914
+ const lddContent = readFileSync3(LDD_PATH);
2915
2915
  cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
2916
2916
  } catch (e) {
2917
2917
  }
@@ -2968,7 +2968,7 @@ var require_detect_libc = __commonJS({
2968
2968
  }
2969
2969
  cachedVersionFilesystem = null;
2970
2970
  try {
2971
- const lddContent = readFileSync2(LDD_PATH);
2971
+ const lddContent = readFileSync3(LDD_PATH);
2972
2972
  const versionMatch = lddContent.match(RE_GLIBC_VERSION);
2973
2973
  if (versionMatch) {
2974
2974
  cachedVersionFilesystem = versionMatch[1];
@@ -6162,7 +6162,7 @@ var require_websocket = __commonJS({
6162
6162
  var http = require("http");
6163
6163
  var net = require("net");
6164
6164
  var tls = require("tls");
6165
- var { randomBytes, createHash: createHash2 } = require("crypto");
6165
+ var { randomBytes, createHash: createHash4 } = require("crypto");
6166
6166
  var { Duplex, Readable } = require("stream");
6167
6167
  var { URL: URL2 } = require("url");
6168
6168
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -6842,7 +6842,7 @@ var require_websocket = __commonJS({
6842
6842
  abortHandshake(websocket, socket, "Invalid Upgrade header");
6843
6843
  return;
6844
6844
  }
6845
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
6845
+ const digest = createHash4("sha1").update(key + GUID).digest("base64");
6846
6846
  if (res.headers["sec-websocket-accept"] !== digest) {
6847
6847
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
6848
6848
  return;
@@ -7229,7 +7229,7 @@ var require_websocket_server = __commonJS({
7229
7229
  var EventEmitter = require("events");
7230
7230
  var http = require("http");
7231
7231
  var { Duplex } = require("stream");
7232
- var { createHash: createHash2 } = require("crypto");
7232
+ var { createHash: createHash4 } = require("crypto");
7233
7233
  var extension2 = require_extension();
7234
7234
  var PerMessageDeflate2 = require_permessage_deflate();
7235
7235
  var subprotocol2 = require_subprotocol();
@@ -7538,7 +7538,7 @@ var require_websocket_server = __commonJS({
7538
7538
  }
7539
7539
  if (this._state > RUNNING)
7540
7540
  return abortHandshake(socket, 503);
7541
- const digest = createHash2("sha1").update(key + GUID).digest("base64");
7541
+ const digest = createHash4("sha1").update(key + GUID).digest("base64");
7542
7542
  const headers = [
7543
7543
  "HTTP/1.1 101 Switching Protocols",
7544
7544
  "Upgrade: websocket",
@@ -14252,7 +14252,7 @@ var init_select2 = __esm({
14252
14252
  const tableName = getTableLikeName(table);
14253
14253
  for (const item of extractUsedTable(table))
14254
14254
  this.usedTables.add(item);
14255
- if (typeof tableName === "string" && this.config.joins?.some((join4) => join4.alias === tableName)) {
14255
+ if (typeof tableName === "string" && this.config.joins?.some((join6) => join6.alias === tableName)) {
14256
14256
  throw new Error(`Alias "${tableName}" is already used in this query`);
14257
14257
  }
14258
14258
  if (!this.isPartialSelect) {
@@ -15141,7 +15141,7 @@ var init_update = __esm({
15141
15141
  createJoin(joinType) {
15142
15142
  return (table, on) => {
15143
15143
  const tableName = getTableLikeName(table);
15144
- if (typeof tableName === "string" && this.config.joins.some((join4) => join4.alias === tableName)) {
15144
+ if (typeof tableName === "string" && this.config.joins.some((join6) => join6.alias === tableName)) {
15145
15145
  throw new Error(`Alias "${tableName}" is already used in this query`);
15146
15146
  }
15147
15147
  if (typeof on === "function") {
@@ -16541,7 +16541,9 @@ var init_schema = __esm({
16541
16541
  created_at: text("created_at").notNull(),
16542
16542
  updated_at: text("updated_at").notNull(),
16543
16543
  parent_session_id: text("parent_session_id"),
16544
- external_ref: text("external_ref")
16544
+ external_ref: text("external_ref"),
16545
+ public_key: text("public_key"),
16546
+ signature: text("signature")
16545
16547
  });
16546
16548
  messages = sqliteTable("messages", {
16547
16549
  id: text("id").primaryKey(),
@@ -16602,6 +16604,12 @@ async function initDb(dbPath2) {
16602
16604
  if (!sessCols.includes("external_ref")) {
16603
16605
  await client.execute("ALTER TABLE sessions ADD COLUMN external_ref TEXT");
16604
16606
  }
16607
+ if (!sessCols.includes("public_key")) {
16608
+ await client.execute("ALTER TABLE sessions ADD COLUMN public_key TEXT");
16609
+ }
16610
+ if (!sessCols.includes("signature")) {
16611
+ await client.execute("ALTER TABLE sessions ADD COLUMN signature TEXT");
16612
+ }
16605
16613
  return drizzle(client, { schema: schema_exports });
16606
16614
  }
16607
16615
  var import_os, import_fs, import_path, CREATE_SQL;
@@ -16622,7 +16630,9 @@ var init_db2 = __esm({
16622
16630
  created_at TEXT NOT NULL,
16623
16631
  updated_at TEXT NOT NULL,
16624
16632
  parent_session_id TEXT,
16625
- external_ref TEXT
16633
+ external_ref TEXT,
16634
+ public_key TEXT,
16635
+ signature TEXT
16626
16636
  )`,
16627
16637
  `CREATE TABLE IF NOT EXISTS messages (
16628
16638
  id TEXT PRIMARY KEY,
@@ -16824,14 +16834,14 @@ async function queryIntegrity(db) {
16824
16834
  unchained++;
16825
16835
  continue;
16826
16836
  }
16827
- let ok = true;
16837
+ let ok2 = true;
16828
16838
  for (let i = 1; i < chained.length; i++) {
16829
16839
  if (chained[i].prev_hash !== chained[i - 1].content_hash) {
16830
- ok = false;
16840
+ ok2 = false;
16831
16841
  break;
16832
16842
  }
16833
16843
  }
16834
- if (ok)
16844
+ if (ok2)
16835
16845
  intact++;
16836
16846
  else {
16837
16847
  broken++;
@@ -17419,7 +17429,7 @@ var require_package = __commonJS({
17419
17429
  "package.json"(exports2, module2) {
17420
17430
  module2.exports = {
17421
17431
  name: "chron-mcp",
17422
- version: "0.1.19",
17432
+ version: "0.1.20",
17423
17433
  mcpName: "io.github.sirinivask/chron",
17424
17434
  description: "Audit-grade timestamped logs for every AI conversation",
17425
17435
  repository: {
@@ -17578,7 +17588,7 @@ ${DIM4}Sending test event...${RESET5} `);
17578
17588
  }
17579
17589
  }]
17580
17590
  }]);
17581
- let ok = false;
17591
+ let ok2 = false;
17582
17592
  let statusCode = 0;
17583
17593
  try {
17584
17594
  const res = await fetch(url, {
@@ -17590,7 +17600,7 @@ ${DIM4}Sending test event...${RESET5} `);
17590
17600
  body: testPayload
17591
17601
  });
17592
17602
  statusCode = res.status;
17593
- ok = res.ok;
17603
+ ok2 = res.ok;
17594
17604
  } catch (e) {
17595
17605
  process.stdout.write(`${RED}failed${RESET5}
17596
17606
  `);
@@ -17599,7 +17609,7 @@ ${DIM4}Sending test event...${RESET5} `);
17599
17609
  `);
17600
17610
  process.exit(1);
17601
17611
  }
17602
- if (!ok) {
17612
+ if (!ok2) {
17603
17613
  process.stdout.write(`${RED}failed (HTTP ${statusCode})${RESET5}
17604
17614
  `);
17605
17615
  process.stderr.write(` ${RED}Check your URL and token, then try again.${RESET5}
@@ -18118,6 +18128,254 @@ var init_summary = __esm({
18118
18128
  }
18119
18129
  });
18120
18130
 
18131
+ // src/utils/signing.ts
18132
+ function keysDir() {
18133
+ return (0, import_path4.join)((0, import_os5.homedir)(), ".chron", "keys");
18134
+ }
18135
+ function privKeyPath(sessionId) {
18136
+ return (0, import_path4.join)(keysDir(), `${sessionId}.key`);
18137
+ }
18138
+ function sessionDigest(sessionId, finalContentHash, messageCount, firstCreatedAt) {
18139
+ const input = `${sessionId}|${finalContentHash}|${messageCount}|${firstCreatedAt}`;
18140
+ return (0, import_crypto2.createHash)("sha256").update(input).digest();
18141
+ }
18142
+ function signSession(sessionId, finalContentHash, messageCount, firstCreatedAt) {
18143
+ const privPath = privKeyPath(sessionId);
18144
+ if (!(0, import_fs4.existsSync)(privPath)) {
18145
+ throw new Error(`Private key not found: ${privPath}`);
18146
+ }
18147
+ const privateKey = (0, import_fs4.readFileSync)(privPath, "utf8");
18148
+ const digest = sessionDigest(sessionId, finalContentHash, messageCount, firstCreatedAt);
18149
+ const sig = (0, import_crypto2.sign)(null, digest, privateKey);
18150
+ return sig.toString("base64");
18151
+ }
18152
+ function verifySignature(publicKeyPem, signatureB64, sessionId, finalContentHash, messageCount, firstCreatedAt) {
18153
+ try {
18154
+ const digest = sessionDigest(sessionId, finalContentHash, messageCount, firstCreatedAt);
18155
+ const sigBuf = Buffer.from(signatureB64, "base64");
18156
+ return (0, import_crypto2.verify)(null, digest, publicKeyPem, sigBuf);
18157
+ } catch {
18158
+ return false;
18159
+ }
18160
+ }
18161
+ var import_crypto2, import_fs4, import_path4, import_os5;
18162
+ var init_signing = __esm({
18163
+ "src/utils/signing.ts"() {
18164
+ "use strict";
18165
+ import_crypto2 = require("crypto");
18166
+ import_fs4 = require("fs");
18167
+ import_path4 = require("path");
18168
+ import_os5 = require("os");
18169
+ }
18170
+ });
18171
+
18172
+ // src/cli/sign.ts
18173
+ var sign_exports = {};
18174
+ __export(sign_exports, {
18175
+ runSign: () => runSign
18176
+ });
18177
+ async function runSign(args2) {
18178
+ const prefix = args2[0];
18179
+ if (!prefix) {
18180
+ process.stderr.write("Usage: chron sign <session-id-prefix>\n");
18181
+ process.exit(1);
18182
+ }
18183
+ const db = await initDb();
18184
+ const allSessions = await db.select().from(sessions);
18185
+ const session = allSessions.find((s) => s.id.startsWith(prefix));
18186
+ if (!session) {
18187
+ process.stderr.write(`Session not found: ${prefix}
18188
+ `);
18189
+ process.exit(1);
18190
+ }
18191
+ if (!session.public_key) {
18192
+ process.stderr.write(`Session ${session.id.slice(0, 8)} has no public key \u2014 was it created before v0.1.19?
18193
+ `);
18194
+ process.exit(1);
18195
+ }
18196
+ if (!(0, import_fs6.existsSync)(privKeyPath(session.id))) {
18197
+ process.stderr.write(`Private key not found: ${privKeyPath(session.id)}
18198
+ `);
18199
+ process.stderr.write("The key is stored on the machine where the session was created.\n");
18200
+ process.exit(1);
18201
+ }
18202
+ const [countRow] = await db.select({
18203
+ count: sql`count(*)`,
18204
+ first_created_at: sql`min(${messages.created_at})`
18205
+ }).from(messages).where(eq(messages.session_id, session.id));
18206
+ const messageCount = countRow?.count ?? 0;
18207
+ const firstCreatedAt = countRow?.first_created_at ?? "";
18208
+ if (messageCount === 0) {
18209
+ process.stderr.write("Session has no messages \u2014 nothing to sign.\n");
18210
+ process.exit(1);
18211
+ }
18212
+ const lastMsg = await db.select({ content_hash: messages.content_hash }).from(messages).where(eq(messages.session_id, session.id)).orderBy(asc(sql`rowid`)).limit(1e3);
18213
+ const finalContentHash = lastMsg[lastMsg.length - 1]?.content_hash ?? "";
18214
+ if (!finalContentHash) {
18215
+ process.stderr.write("Session has no hash chain \u2014 cannot sign.\n");
18216
+ process.exit(1);
18217
+ }
18218
+ const signature = signSession(session.id, finalContentHash, messageCount, firstCreatedAt);
18219
+ await db.update(sessions).set({ signature }).where(eq(sessions.id, session.id));
18220
+ const sigData = {
18221
+ chron_signature: "v1",
18222
+ session_id: session.id,
18223
+ session_title: session.title,
18224
+ public_key_pem: session.public_key,
18225
+ message_count: messageCount,
18226
+ first_message_at: firstCreatedAt,
18227
+ final_content_hash: finalContentHash,
18228
+ signature,
18229
+ signed_at: (/* @__PURE__ */ new Date()).toISOString()
18230
+ };
18231
+ const sigFile = (0, import_path5.join)(process.cwd(), `${session.id.slice(0, 8)}.chron.sig`);
18232
+ (0, import_fs5.writeFileSync)(sigFile, JSON.stringify(sigData, null, 2));
18233
+ process.stdout.write(`Signed session ${session.id.slice(0, 8)}
18234
+ `);
18235
+ process.stdout.write(` messages : ${messageCount}
18236
+ `);
18237
+ process.stdout.write(` final hash: ${finalContentHash.slice(0, 16)}\u2026
18238
+ `);
18239
+ process.stdout.write(` sig file : ${sigFile}
18240
+ `);
18241
+ }
18242
+ var import_fs5, import_path5, import_fs6;
18243
+ var init_sign = __esm({
18244
+ "src/cli/sign.ts"() {
18245
+ "use strict";
18246
+ init_drizzle_orm();
18247
+ import_fs5 = require("fs");
18248
+ import_path5 = require("path");
18249
+ init_db2();
18250
+ init_schema();
18251
+ init_signing();
18252
+ import_fs6 = require("fs");
18253
+ }
18254
+ });
18255
+
18256
+ // src/utils/hash.ts
18257
+ function computeContentHash(sessionId, role, content, createdAt, prevHash, eventType) {
18258
+ const base = `${sessionId}|${role}|${content}|${createdAt}|${prevHash ?? ""}`;
18259
+ const input = eventType != null ? `${base}|${eventType}` : base;
18260
+ return (0, import_crypto3.createHash)("sha256").update(input).digest("hex");
18261
+ }
18262
+ var import_crypto3;
18263
+ var init_hash = __esm({
18264
+ "src/utils/hash.ts"() {
18265
+ "use strict";
18266
+ import_crypto3 = require("crypto");
18267
+ }
18268
+ });
18269
+
18270
+ // src/cli/verify.ts
18271
+ var verify_exports = {};
18272
+ __export(verify_exports, {
18273
+ runVerify: () => runVerify
18274
+ });
18275
+ function ok(msg) {
18276
+ process.stdout.write(` ${GREEN3}\u2713${RESET7} ${msg}
18277
+ `);
18278
+ }
18279
+ function fail(msg) {
18280
+ process.stdout.write(` ${RED3}\u2717${RESET7} ${msg}
18281
+ `);
18282
+ }
18283
+ function warn(msg) {
18284
+ process.stdout.write(` ${YELLOW5}!${RESET7} ${msg}
18285
+ `);
18286
+ }
18287
+ async function runVerify(args2) {
18288
+ const prefix = args2[0];
18289
+ if (!prefix) {
18290
+ process.stderr.write("Usage: chron verify <session-id-prefix>\n");
18291
+ process.exit(1);
18292
+ }
18293
+ const db = await initDb();
18294
+ const allSessions = await db.select().from(sessions);
18295
+ const session = allSessions.find((s) => s.id.startsWith(prefix));
18296
+ if (!session) {
18297
+ process.stderr.write(`Session not found: ${prefix}
18298
+ `);
18299
+ process.exit(1);
18300
+ }
18301
+ process.stdout.write(`
18302
+ ${BOLD7}Verifying session ${session.id.slice(0, 8)}${RESET7} \u2014 ${session.title}
18303
+
18304
+ `);
18305
+ const rows = await db.select().from(messages).where(eq(messages.session_id, session.id)).orderBy(asc(messages.created_at), asc(sql`rowid`));
18306
+ process.stdout.write(`${BOLD7}Hash chain${RESET7} (${rows.length} messages)
18307
+ `);
18308
+ const chained = rows.filter((r) => r.content_hash !== null);
18309
+ let chainOk = true;
18310
+ if (chained.length === 0) {
18311
+ warn("No chained messages \u2014 session pre-dates hash chaining");
18312
+ } else {
18313
+ for (let i = 0; i < chained.length; i++) {
18314
+ const row = chained[i];
18315
+ const expectedPrev = i === 0 ? null : chained[i - 1].content_hash;
18316
+ if (row.prev_hash !== expectedPrev) {
18317
+ fail(`Row ${i + 1} (${row.id.slice(0, 8)}): prev_hash mismatch \u2014 chain broken`);
18318
+ chainOk = false;
18319
+ break;
18320
+ }
18321
+ const expected = computeContentHash(row.session_id, row.role, row.content, row.created_at, row.prev_hash, row.event_type ?? void 0);
18322
+ if (row.content_hash !== expected) {
18323
+ fail(`Row ${i + 1} (${row.id.slice(0, 8)}): content_hash mismatch \u2014 row tampered`);
18324
+ chainOk = false;
18325
+ break;
18326
+ }
18327
+ }
18328
+ if (chainOk)
18329
+ ok(`All ${chained.length} hashes valid`);
18330
+ }
18331
+ process.stdout.write(`
18332
+ ${BOLD7}Signature${RESET7}
18333
+ `);
18334
+ if (!session.public_key) {
18335
+ warn("No public key \u2014 session was created before signing support (v0.1.19)");
18336
+ } else if (!session.signature) {
18337
+ warn("Not yet signed \u2014 run: chron sign " + session.id.slice(0, 8));
18338
+ } else {
18339
+ const finalHash = chained[chained.length - 1]?.content_hash ?? "";
18340
+ const firstCreatedAt = rows[0]?.created_at ?? "";
18341
+ const sigValid = verifySignature(
18342
+ session.public_key,
18343
+ session.signature,
18344
+ session.id,
18345
+ finalHash,
18346
+ rows.length,
18347
+ firstCreatedAt
18348
+ );
18349
+ if (sigValid) {
18350
+ ok("Ed25519 signature valid");
18351
+ process.stdout.write(` ${DIM6}public key: ${session.public_key.split("\n")[1]?.slice(0, 40)}\u2026${RESET7}
18352
+ `);
18353
+ } else {
18354
+ fail("Ed25519 signature INVALID \u2014 session data may have been altered after signing");
18355
+ }
18356
+ }
18357
+ process.stdout.write("\n");
18358
+ const allOk = chainOk && (session.signature ? true : true);
18359
+ process.exit(allOk ? 0 : 1);
18360
+ }
18361
+ var RESET7, BOLD7, GREEN3, RED3, DIM6, YELLOW5;
18362
+ var init_verify = __esm({
18363
+ "src/cli/verify.ts"() {
18364
+ "use strict";
18365
+ init_drizzle_orm();
18366
+ init_db2();
18367
+ init_schema();
18368
+ init_hash();
18369
+ init_signing();
18370
+ RESET7 = "\x1B[0m";
18371
+ BOLD7 = "\x1B[1m";
18372
+ GREEN3 = "\x1B[32m";
18373
+ RED3 = "\x1B[31m";
18374
+ DIM6 = "\x1B[2m";
18375
+ YELLOW5 = "\x1B[33m";
18376
+ }
18377
+ });
18378
+
18121
18379
  // src/cli/index.ts
18122
18380
  var [, , command, ...args] = process.argv;
18123
18381
  async function main() {
@@ -18157,6 +18415,16 @@ async function main() {
18157
18415
  await runSummary2(args);
18158
18416
  break;
18159
18417
  }
18418
+ case "sign": {
18419
+ const { runSign: runSign2 } = await Promise.resolve().then(() => (init_sign(), sign_exports));
18420
+ await runSign2(args);
18421
+ break;
18422
+ }
18423
+ case "verify": {
18424
+ const { runVerify: runVerify2 } = await Promise.resolve().then(() => (init_verify(), verify_exports));
18425
+ await runVerify2(args);
18426
+ break;
18427
+ }
18160
18428
  default: {
18161
18429
  const name = command ? `Unknown command: ${command}
18162
18430
 
@@ -18172,6 +18440,8 @@ Commands:
18172
18440
  settings View current configuration
18173
18441
  connect Connect to a SIEM integration (crowdstrike, sentinel, splunk)
18174
18442
  summary Structured summary of a session (timeline, mutations, secrets)
18443
+ sign Sign a session with its Ed25519 key \u2014 produces a .chron.sig file
18444
+ verify Verify a session's hash chain and Ed25519 signature
18175
18445
 
18176
18446
  Options (history):
18177
18447
  --limit=<n> Max sessions to show (default: 20)
@@ -18182,7 +18452,7 @@ Options (report):
18182
18452
  --format=soc2 Generate SOC 2 HTML evidence package
18183
18453
  --output=<file> Output file for --format=soc2 (default: soc2-report.html)
18184
18454
 
18185
- Options (export / secrets):
18455
+ Options (export / secrets / sign / verify):
18186
18456
  <id-prefix> Scope to a single session
18187
18457
  `
18188
18458
  );
package/dist/index.js CHANGED
@@ -6890,7 +6890,7 @@ var require_filesystem = __commonJS({
6890
6890
  "use strict";
6891
6891
  var fs = require("fs");
6892
6892
  var LDD_PATH = "/usr/bin/ldd";
6893
- var readFileSync3 = (path) => fs.readFileSync(path, "utf-8");
6893
+ var readFileSync4 = (path) => fs.readFileSync(path, "utf-8");
6894
6894
  var readFile = (path) => new Promise((resolve, reject) => {
6895
6895
  fs.readFile(path, "utf-8", (err, data) => {
6896
6896
  if (err) {
@@ -6902,7 +6902,7 @@ var require_filesystem = __commonJS({
6902
6902
  });
6903
6903
  module2.exports = {
6904
6904
  LDD_PATH,
6905
- readFileSync: readFileSync3,
6905
+ readFileSync: readFileSync4,
6906
6906
  readFile
6907
6907
  };
6908
6908
  }
@@ -6914,7 +6914,7 @@ var require_detect_libc = __commonJS({
6914
6914
  "use strict";
6915
6915
  var childProcess = require("child_process");
6916
6916
  var { isLinux, getReport } = require_process();
6917
- var { LDD_PATH, readFile, readFileSync: readFileSync3 } = require_filesystem();
6917
+ var { LDD_PATH, readFile, readFileSync: readFileSync4 } = require_filesystem();
6918
6918
  var cachedFamilyFilesystem;
6919
6919
  var cachedVersionFilesystem;
6920
6920
  var command = "getconf GNU_LIBC_VERSION 2>&1 || true; ldd --version 2>&1 || true";
@@ -6995,7 +6995,7 @@ var require_detect_libc = __commonJS({
6995
6995
  }
6996
6996
  cachedFamilyFilesystem = null;
6997
6997
  try {
6998
- const lddContent = readFileSync3(LDD_PATH);
6998
+ const lddContent = readFileSync4(LDD_PATH);
6999
6999
  cachedFamilyFilesystem = getFamilyFromLddContent(lddContent);
7000
7000
  } catch (e) {
7001
7001
  }
@@ -7052,7 +7052,7 @@ var require_detect_libc = __commonJS({
7052
7052
  }
7053
7053
  cachedVersionFilesystem = null;
7054
7054
  try {
7055
- const lddContent = readFileSync3(LDD_PATH);
7055
+ const lddContent = readFileSync4(LDD_PATH);
7056
7056
  const versionMatch = lddContent.match(RE_GLIBC_VERSION);
7057
7057
  if (versionMatch) {
7058
7058
  cachedVersionFilesystem = versionMatch[1];
@@ -10246,7 +10246,7 @@ var require_websocket = __commonJS({
10246
10246
  var http = require("http");
10247
10247
  var net = require("net");
10248
10248
  var tls = require("tls");
10249
- var { randomBytes, createHash: createHash3 } = require("crypto");
10249
+ var { randomBytes, createHash: createHash4 } = require("crypto");
10250
10250
  var { Duplex, Readable } = require("stream");
10251
10251
  var { URL: URL3 } = require("url");
10252
10252
  var PerMessageDeflate2 = require_permessage_deflate();
@@ -10926,7 +10926,7 @@ var require_websocket = __commonJS({
10926
10926
  abortHandshake(websocket, socket, "Invalid Upgrade header");
10927
10927
  return;
10928
10928
  }
10929
- const digest = createHash3("sha1").update(key + GUID).digest("base64");
10929
+ const digest = createHash4("sha1").update(key + GUID).digest("base64");
10930
10930
  if (res.headers["sec-websocket-accept"] !== digest) {
10931
10931
  abortHandshake(websocket, socket, "Invalid Sec-WebSocket-Accept header");
10932
10932
  return;
@@ -11313,7 +11313,7 @@ var require_websocket_server = __commonJS({
11313
11313
  var EventEmitter = require("events");
11314
11314
  var http = require("http");
11315
11315
  var { Duplex } = require("stream");
11316
- var { createHash: createHash3 } = require("crypto");
11316
+ var { createHash: createHash4 } = require("crypto");
11317
11317
  var extension2 = require_extension();
11318
11318
  var PerMessageDeflate2 = require_permessage_deflate();
11319
11319
  var subprotocol2 = require_subprotocol();
@@ -11622,7 +11622,7 @@ var require_websocket_server = __commonJS({
11622
11622
  }
11623
11623
  if (this._state > RUNNING)
11624
11624
  return abortHandshake(socket, 503);
11625
- const digest = createHash3("sha1").update(key + GUID).digest("base64");
11625
+ const digest = createHash4("sha1").update(key + GUID).digest("base64");
11626
11626
  const headers = [
11627
11627
  "HTTP/1.1 101 Switching Protocols",
11628
11628
  "Upgrade: websocket",
@@ -17521,7 +17521,7 @@ var init_sql2 = __esm({
17521
17521
  return new SQL([new StringChunk(str)]);
17522
17522
  }
17523
17523
  sql2.raw = raw;
17524
- function join5(chunks, separator) {
17524
+ function join6(chunks, separator) {
17525
17525
  const result = [];
17526
17526
  for (const [i, chunk] of chunks.entries()) {
17527
17527
  if (i > 0 && separator !== void 0) {
@@ -17531,7 +17531,7 @@ var init_sql2 = __esm({
17531
17531
  }
17532
17532
  return new SQL(result);
17533
17533
  }
17534
- sql2.join = join5;
17534
+ sql2.join = join6;
17535
17535
  function identifier(value) {
17536
17536
  return new Name(value);
17537
17537
  }
@@ -20462,7 +20462,7 @@ var init_select2 = __esm({
20462
20462
  const tableName = getTableLikeName(table);
20463
20463
  for (const item of extractUsedTable(table))
20464
20464
  this.usedTables.add(item);
20465
- if (typeof tableName === "string" && this.config.joins?.some((join5) => join5.alias === tableName)) {
20465
+ if (typeof tableName === "string" && this.config.joins?.some((join6) => join6.alias === tableName)) {
20466
20466
  throw new Error(`Alias "${tableName}" is already used in this query`);
20467
20467
  }
20468
20468
  if (!this.isPartialSelect) {
@@ -21351,7 +21351,7 @@ var init_update = __esm({
21351
21351
  createJoin(joinType) {
21352
21352
  return (table, on) => {
21353
21353
  const tableName = getTableLikeName(table);
21354
- if (typeof tableName === "string" && this.config.joins.some((join5) => join5.alias === tableName)) {
21354
+ if (typeof tableName === "string" && this.config.joins.some((join6) => join6.alias === tableName)) {
21355
21355
  throw new Error(`Alias "${tableName}" is already used in this query`);
21356
21356
  }
21357
21357
  if (typeof on === "function") {
@@ -22751,7 +22751,9 @@ var init_schema = __esm({
22751
22751
  created_at: text("created_at").notNull(),
22752
22752
  updated_at: text("updated_at").notNull(),
22753
22753
  parent_session_id: text("parent_session_id"),
22754
- external_ref: text("external_ref")
22754
+ external_ref: text("external_ref"),
22755
+ public_key: text("public_key"),
22756
+ signature: text("signature")
22755
22757
  });
22756
22758
  messages = sqliteTable("messages", {
22757
22759
  id: text("id").primaryKey(),
@@ -22812,6 +22814,12 @@ async function initDb(dbPath) {
22812
22814
  if (!sessCols.includes("external_ref")) {
22813
22815
  await client.execute("ALTER TABLE sessions ADD COLUMN external_ref TEXT");
22814
22816
  }
22817
+ if (!sessCols.includes("public_key")) {
22818
+ await client.execute("ALTER TABLE sessions ADD COLUMN public_key TEXT");
22819
+ }
22820
+ if (!sessCols.includes("signature")) {
22821
+ await client.execute("ALTER TABLE sessions ADD COLUMN signature TEXT");
22822
+ }
22815
22823
  return drizzle(client, { schema: schema_exports });
22816
22824
  }
22817
22825
  var import_os, import_fs, import_path, CREATE_SQL;
@@ -22832,7 +22840,9 @@ var init_db2 = __esm({
22832
22840
  created_at TEXT NOT NULL,
22833
22841
  updated_at TEXT NOT NULL,
22834
22842
  parent_session_id TEXT,
22835
- external_ref TEXT
22843
+ external_ref TEXT,
22844
+ public_key TEXT,
22845
+ signature TEXT
22836
22846
  )`,
22837
22847
  `CREATE TABLE IF NOT EXISTS messages (
22838
22848
  id TEXT PRIMARY KEY,
@@ -38464,7 +38474,7 @@ var init_time = __esm({
38464
38474
  var version4;
38465
38475
  var init_package = __esm({
38466
38476
  "package.json"() {
38467
- version4 = "0.1.19";
38477
+ version4 = "0.1.20";
38468
38478
  }
38469
38479
  });
38470
38480
 
@@ -38708,12 +38718,62 @@ var init_relay = __esm({
38708
38718
  }
38709
38719
  });
38710
38720
 
38721
+ // src/utils/signing.ts
38722
+ function keysDir() {
38723
+ return (0, import_path3.join)((0, import_os3.homedir)(), ".chron", "keys");
38724
+ }
38725
+ function privKeyPath(sessionId) {
38726
+ return (0, import_path3.join)(keysDir(), `${sessionId}.key`);
38727
+ }
38728
+ function pubKeyPath(sessionId) {
38729
+ return (0, import_path3.join)(keysDir(), `${sessionId}.pub`);
38730
+ }
38731
+ function generateSessionKeypair(sessionId) {
38732
+ const { privateKey, publicKey } = (0, import_crypto4.generateKeyPairSync)("ed25519", {
38733
+ privateKeyEncoding: { type: "pkcs8", format: "pem" },
38734
+ publicKeyEncoding: { type: "spki", format: "pem" }
38735
+ });
38736
+ const dir = keysDir();
38737
+ (0, import_fs3.mkdirSync)(dir, { recursive: true });
38738
+ (0, import_fs3.writeFileSync)(privKeyPath(sessionId), privateKey, { mode: 384 });
38739
+ (0, import_fs3.writeFileSync)(pubKeyPath(sessionId), publicKey);
38740
+ return publicKey;
38741
+ }
38742
+ function sessionDigest(sessionId, finalContentHash, messageCount, firstCreatedAt) {
38743
+ const input = `${sessionId}|${finalContentHash}|${messageCount}|${firstCreatedAt}`;
38744
+ return (0, import_crypto4.createHash)("sha256").update(input).digest();
38745
+ }
38746
+ function verifySignature(publicKeyPem, signatureB64, sessionId, finalContentHash, messageCount, firstCreatedAt) {
38747
+ try {
38748
+ const digest = sessionDigest(sessionId, finalContentHash, messageCount, firstCreatedAt);
38749
+ const sigBuf = Buffer.from(signatureB64, "base64");
38750
+ return (0, import_crypto4.verify)(null, digest, publicKeyPem, sigBuf);
38751
+ } catch {
38752
+ return false;
38753
+ }
38754
+ }
38755
+ var import_crypto4, import_fs3, import_path3, import_os3;
38756
+ var init_signing = __esm({
38757
+ "src/utils/signing.ts"() {
38758
+ "use strict";
38759
+ import_crypto4 = require("crypto");
38760
+ import_fs3 = require("fs");
38761
+ import_path3 = require("path");
38762
+ import_os3 = require("os");
38763
+ }
38764
+ });
38765
+
38711
38766
  // src/tools/sessions.ts
38712
38767
  function startSession(db) {
38713
38768
  return async (args) => {
38714
38769
  const id = v4_default();
38715
38770
  const now = localISOString();
38716
38771
  try {
38772
+ let publicKey = null;
38773
+ try {
38774
+ publicKey = generateSessionKeypair(id);
38775
+ } catch {
38776
+ }
38717
38777
  await db.insert(sessions).values({
38718
38778
  id,
38719
38779
  title: args.title,
@@ -38721,7 +38781,8 @@ function startSession(db) {
38721
38781
  created_at: now,
38722
38782
  updated_at: now,
38723
38783
  parent_session_id: args.parent_session_id ?? null,
38724
- external_ref: args.external_ref ?? null
38784
+ external_ref: args.external_ref ?? null,
38785
+ public_key: publicKey
38725
38786
  });
38726
38787
  emitEvent({ event_type: "session_started", timestamp: now, session: { id_prefix: id.slice(0, 8), ai_tool: args.ai_tool ?? null } });
38727
38788
  return {
@@ -38756,6 +38817,11 @@ function initSession(db) {
38756
38817
  let created;
38757
38818
  let ai_tool;
38758
38819
  try {
38820
+ let publicKey = null;
38821
+ try {
38822
+ publicKey = generateSessionKeypair(id);
38823
+ } catch {
38824
+ }
38759
38825
  await db.insert(sessions).values({
38760
38826
  id,
38761
38827
  title: args.title,
@@ -38763,7 +38829,8 @@ function initSession(db) {
38763
38829
  created_at: now,
38764
38830
  updated_at: now,
38765
38831
  parent_session_id: args.parent_session_id ?? null,
38766
- external_ref: args.external_ref ?? null
38832
+ external_ref: args.external_ref ?? null,
38833
+ public_key: publicKey
38767
38834
  });
38768
38835
  session_id = id;
38769
38836
  created = true;
@@ -38864,6 +38931,7 @@ var init_sessions = __esm({
38864
38931
  init_schema();
38865
38932
  init_time();
38866
38933
  init_relay();
38934
+ init_signing();
38867
38935
  }
38868
38936
  });
38869
38937
 
@@ -38871,13 +38939,13 @@ var init_sessions = __esm({
38871
38939
  function computeContentHash(sessionId, role, content, createdAt, prevHash, eventType) {
38872
38940
  const base = `${sessionId}|${role}|${content}|${createdAt}|${prevHash ?? ""}`;
38873
38941
  const input = eventType != null ? `${base}|${eventType}` : base;
38874
- return (0, import_crypto4.createHash)("sha256").update(input).digest("hex");
38942
+ return (0, import_crypto5.createHash)("sha256").update(input).digest("hex");
38875
38943
  }
38876
- var import_crypto4;
38944
+ var import_crypto5;
38877
38945
  var init_hash = __esm({
38878
38946
  "src/utils/hash.ts"() {
38879
38947
  "use strict";
38880
- import_crypto4 = require("crypto");
38948
+ import_crypto5 = require("crypto");
38881
38949
  }
38882
38950
  });
38883
38951
 
@@ -39345,6 +39413,7 @@ var init_messages = __esm({
39345
39413
  // src/tools/verify.ts
39346
39414
  function verifySession(db) {
39347
39415
  return async (args) => {
39416
+ const [sessionRow] = await db.select().from(sessions).where(eq(sessions.id, args.session_id)).limit(1);
39348
39417
  const rows = await db.select().from(messages).where(eq(messages.session_id, args.session_id)).orderBy(asc(messages.created_at), asc(sql`rowid`));
39349
39418
  const chained = rows.filter((r) => r.content_hash !== null);
39350
39419
  if (chained.length === 0) {
@@ -39376,10 +39445,23 @@ function verifySession(db) {
39376
39445
  };
39377
39446
  }
39378
39447
  }
39448
+ let signature_valid = "unsigned";
39449
+ if (sessionRow?.public_key && sessionRow?.signature) {
39450
+ const finalHash = chained[chained.length - 1]?.content_hash ?? "";
39451
+ const firstCreatedAt = rows[0]?.created_at ?? "";
39452
+ signature_valid = verifySignature(
39453
+ sessionRow.public_key,
39454
+ sessionRow.signature,
39455
+ args.session_id,
39456
+ finalHash,
39457
+ rows.length,
39458
+ firstCreatedAt
39459
+ );
39460
+ }
39379
39461
  return {
39380
39462
  content: [{
39381
39463
  type: "text",
39382
- text: JSON.stringify({ valid: true, messages: rows.length, chained: chained.length })
39464
+ text: JSON.stringify({ valid: true, messages: rows.length, chained: chained.length, signature_valid })
39383
39465
  }]
39384
39466
  };
39385
39467
  };
@@ -39390,6 +39472,7 @@ var init_verify = __esm({
39390
39472
  init_drizzle_orm();
39391
39473
  init_schema();
39392
39474
  init_hash();
39475
+ init_signing();
39393
39476
  }
39394
39477
  });
39395
39478
 
@@ -39793,24 +39876,24 @@ __export(setup_exports, {
39793
39876
  runSetup: () => runSetup
39794
39877
  });
39795
39878
  function configPath(...parts) {
39796
- return (0, import_path3.join)((0, import_os3.homedir)(), ...parts);
39879
+ return (0, import_path4.join)((0, import_os4.homedir)(), ...parts);
39797
39880
  }
39798
39881
  function readJson(filePath) {
39799
- if (!(0, import_fs3.existsSync)(filePath))
39882
+ if (!(0, import_fs4.existsSync)(filePath))
39800
39883
  return {};
39801
39884
  try {
39802
- return JSON.parse((0, import_fs3.readFileSync)(filePath, "utf8"));
39885
+ return JSON.parse((0, import_fs4.readFileSync)(filePath, "utf8"));
39803
39886
  } catch {
39804
39887
  return {};
39805
39888
  }
39806
39889
  }
39807
39890
  function writeJson(filePath, data) {
39808
- (0, import_fs3.mkdirSync)((0, import_path3.dirname)(filePath), { recursive: true });
39809
- (0, import_fs3.writeFileSync)(filePath, JSON.stringify(data, null, 2) + "\n", "utf8");
39891
+ (0, import_fs4.mkdirSync)((0, import_path4.dirname)(filePath), { recursive: true });
39892
+ (0, import_fs4.writeFileSync)(filePath, JSON.stringify(data, null, 2) + "\n", "utf8");
39810
39893
  }
39811
39894
  function configureTool(name, filePath) {
39812
- const dir = (0, import_path3.dirname)(filePath);
39813
- if (!(0, import_fs3.existsSync)(dir) && name !== "Claude Code") {
39895
+ const dir = (0, import_path4.dirname)(filePath);
39896
+ if (!(0, import_fs4.existsSync)(dir) && name !== "Claude Code") {
39814
39897
  return { tool: name, status: "skipped" };
39815
39898
  }
39816
39899
  try {
@@ -39831,7 +39914,7 @@ function configureClaudeCode() {
39831
39914
  try {
39832
39915
  (0, import_child_process.execSync)("claude mcp add chron -- npx -y chron-mcp", { stdio: "pipe" });
39833
39916
  } catch {
39834
- const result = configureTool("Claude Code", (0, import_path3.join)((0, import_os3.homedir)(), ".claude", "settings.json"));
39917
+ const result = configureTool("Claude Code", (0, import_path4.join)((0, import_os4.homedir)(), ".claude", "settings.json"));
39835
39918
  if (result.status === "error")
39836
39919
  return result;
39837
39920
  }
@@ -39839,13 +39922,13 @@ function configureClaudeCode() {
39839
39922
  return { tool: "Claude Code", status: "added" };
39840
39923
  }
39841
39924
  function installClaudeCodeHook() {
39842
- const skillSrc = (0, import_path3.join)(__dirname, "..", "skills", "chron.skill.md");
39843
- const skillDst = (0, import_path3.join)((0, import_os3.homedir)(), ".chron", "chron.skill.md");
39844
- if ((0, import_fs3.existsSync)(skillSrc)) {
39845
- (0, import_fs3.mkdirSync)((0, import_path3.dirname)(skillDst), { recursive: true });
39846
- (0, import_fs3.copyFileSync)(skillSrc, skillDst);
39925
+ const skillSrc = (0, import_path4.join)(__dirname, "..", "skills", "chron.skill.md");
39926
+ const skillDst = (0, import_path4.join)((0, import_os4.homedir)(), ".chron", "chron.skill.md");
39927
+ if ((0, import_fs4.existsSync)(skillSrc)) {
39928
+ (0, import_fs4.mkdirSync)((0, import_path4.dirname)(skillDst), { recursive: true });
39929
+ (0, import_fs4.copyFileSync)(skillSrc, skillDst);
39847
39930
  }
39848
- const settingsPath = (0, import_path3.join)((0, import_os3.homedir)(), ".claude", "settings.json");
39931
+ const settingsPath = (0, import_path4.join)((0, import_os4.homedir)(), ".claude", "settings.json");
39849
39932
  const settings = readJson(settingsPath);
39850
39933
  if (!settings.hooks)
39851
39934
  settings.hooks = {};
@@ -39869,13 +39952,13 @@ async function runSetup() {
39869
39952
  }
39870
39953
  return results.filter((r) => r.status !== "skipped");
39871
39954
  }
39872
- var import_fs3, import_os3, import_path3, import_child_process, CHRON_ENTRY, TOOLS;
39955
+ var import_fs4, import_os4, import_path4, import_child_process, CHRON_ENTRY, TOOLS;
39873
39956
  var init_setup = __esm({
39874
39957
  "src/setup.ts"() {
39875
39958
  "use strict";
39876
- import_fs3 = require("fs");
39877
- import_os3 = require("os");
39878
- import_path3 = require("path");
39959
+ import_fs4 = require("fs");
39960
+ import_os4 = require("os");
39961
+ import_path4 = require("path");
39879
39962
  import_child_process = require("child_process");
39880
39963
  CHRON_ENTRY = {
39881
39964
  command: "npx",
@@ -39884,11 +39967,11 @@ var init_setup = __esm({
39884
39967
  TOOLS = [
39885
39968
  {
39886
39969
  name: "Claude Desktop",
39887
- path: process.platform === "win32" ? (0, import_path3.join)(process.env.APPDATA ?? "", "Claude", "claude_desktop_config.json") : configPath("Library", "Application Support", "Claude", "claude_desktop_config.json")
39970
+ path: process.platform === "win32" ? (0, import_path4.join)(process.env.APPDATA ?? "", "Claude", "claude_desktop_config.json") : configPath("Library", "Application Support", "Claude", "claude_desktop_config.json")
39888
39971
  },
39889
39972
  {
39890
39973
  name: "Cursor",
39891
- path: process.platform === "win32" ? (0, import_path3.join)(process.env.APPDATA ?? "", "Cursor", "User", "globalStorage", "cursor.mcp", "mcp.json") : configPath(".cursor", "mcp.json")
39974
+ path: process.platform === "win32" ? (0, import_path4.join)(process.env.APPDATA ?? "", "Cursor", "User", "globalStorage", "cursor.mcp", "mcp.json") : configPath(".cursor", "mcp.json")
39892
39975
  },
39893
39976
  {
39894
39977
  name: "Windsurf",
@@ -60076,7 +60159,7 @@ var require_view = __commonJS({
60076
60159
  var dirname3 = path.dirname;
60077
60160
  var basename = path.basename;
60078
60161
  var extname = path.extname;
60079
- var join5 = path.join;
60162
+ var join6 = path.join;
60080
60163
  var resolve = path.resolve;
60081
60164
  module2.exports = View2;
60082
60165
  function View2(name, options) {
@@ -60124,12 +60207,12 @@ var require_view = __commonJS({
60124
60207
  };
60125
60208
  View2.prototype.resolve = function resolve2(dir, file) {
60126
60209
  var ext = this.ext;
60127
- var path2 = join5(dir, file);
60210
+ var path2 = join6(dir, file);
60128
60211
  var stat = tryStat(path2);
60129
60212
  if (stat && stat.isFile()) {
60130
60213
  return path2;
60131
60214
  }
60132
- path2 = join5(dir, basename(file, ext), "index" + ext);
60215
+ path2 = join6(dir, basename(file, ext), "index" + ext);
60133
60216
  stat = tryStat(path2);
60134
60217
  if (stat && stat.isFile()) {
60135
60218
  return path2;
@@ -61196,7 +61279,7 @@ var require_send = __commonJS({
61196
61279
  var Stream2 = require("stream");
61197
61280
  var util2 = require("util");
61198
61281
  var extname = path.extname;
61199
- var join5 = path.join;
61282
+ var join6 = path.join;
61200
61283
  var normalize = path.normalize;
61201
61284
  var resolve = path.resolve;
61202
61285
  var sep = path.sep;
@@ -61415,7 +61498,7 @@ var require_send = __commonJS({
61415
61498
  return res;
61416
61499
  }
61417
61500
  parts = path2.split(sep);
61418
- path2 = normalize(join5(root, path2));
61501
+ path2 = normalize(join6(root, path2));
61419
61502
  } else {
61420
61503
  if (UP_PATH_REGEXP.test(path2)) {
61421
61504
  debug('malicious path "%s"', path2);
@@ -61556,7 +61639,7 @@ var require_send = __commonJS({
61556
61639
  return self.onStatError(err);
61557
61640
  return self.error(404);
61558
61641
  }
61559
- var p = join5(path2, self._index[i]);
61642
+ var p = join6(path2, self._index[i]);
61560
61643
  debug('stat "%s"', p);
61561
61644
  fs.stat(p, function(err2, stat) {
61562
61645
  if (err2)
@@ -69004,8 +69087,8 @@ var StdioServerTransport = class {
69004
69087
  };
69005
69088
 
69006
69089
  // src/index.ts
69007
- var import_os4 = require("os");
69008
- var import_path4 = require("path");
69090
+ var import_os5 = require("os");
69091
+ var import_path5 = require("path");
69009
69092
  init_db2();
69010
69093
  init_server3();
69011
69094
  init_package();
@@ -69015,7 +69098,7 @@ if (process.argv[2] === "--version" || process.argv[2] === "-v") {
69015
69098
  process.exit(0);
69016
69099
  }
69017
69100
  async function main() {
69018
- const dbPath = process.env.CHRON_DB_PATH ?? (0, import_path4.join)((0, import_os4.homedir)(), ".chron", "chron.db");
69101
+ const dbPath = process.env.CHRON_DB_PATH ?? (0, import_path5.join)((0, import_os5.homedir)(), ".chron", "chron.db");
69019
69102
  if (process.stdin.isTTY) {
69020
69103
  process.stdout.write(`chron-mcp ${version4}
69021
69104
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chron-mcp",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "mcpName": "io.github.sirinivask/chron",
5
5
  "description": "Audit-grade timestamped logs for every AI conversation",
6
6
  "repository": {