ccsini 0.1.5 → 0.1.7

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/index.js +52 -11
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -26950,7 +26950,7 @@ var {
26950
26950
  } = import__.default;
26951
26951
 
26952
26952
  // src/version.ts
26953
- var VERSION = "0.1.5";
26953
+ var VERSION = "0.1.7";
26954
26954
 
26955
26955
  // src/commands/init.ts
26956
26956
  init_source();
@@ -28369,13 +28369,19 @@ async function walkDir(dir) {
28369
28369
  }
28370
28370
  return files;
28371
28371
  }
28372
- async function scanClaudeDir(claudeDir) {
28372
+ async function scanClaudeDir(claudeDir, onProgress) {
28373
+ const progress = onProgress ?? (() => {});
28374
+ progress("Walking directory tree...");
28373
28375
  const allFiles = await walkDir(claudeDir);
28376
+ progress(`Found ${allFiles.length} files, hashing...`);
28374
28377
  const results = [];
28378
+ let processed = 0;
28375
28379
  for (const absolutePath of allFiles) {
28376
28380
  const relativePath = relative(claudeDir, absolutePath).split("\\").join("/");
28377
- if (isExcluded(relativePath))
28381
+ if (isExcluded(relativePath)) {
28382
+ processed++;
28378
28383
  continue;
28384
+ }
28379
28385
  const fileStat = await stat(absolutePath);
28380
28386
  const hash = await hashFile(absolutePath);
28381
28387
  results.push({
@@ -28386,13 +28392,17 @@ async function scanClaudeDir(claudeDir) {
28386
28392
  modified: fileStat.mtimeMs,
28387
28393
  category: categorizeFile(relativePath)
28388
28394
  });
28395
+ processed++;
28396
+ if (processed % 10 === 0 || processed === allFiles.length) {
28397
+ progress(`Scanning ${processed}/${allFiles.length}: ${relativePath}`);
28398
+ }
28389
28399
  }
28390
28400
  return results;
28391
28401
  }
28392
28402
 
28393
28403
  // src/core/manifest.ts
28394
- async function generateManifest(claudeDir, deviceName) {
28395
- const files = await scanClaudeDir(claudeDir);
28404
+ async function generateManifest(claudeDir, deviceName, onProgress) {
28405
+ const files = await scanClaudeDir(claudeDir, onProgress);
28396
28406
  const entries = {};
28397
28407
  for (const file of files) {
28398
28408
  entries[file.relativePath] = {
@@ -28498,12 +28508,16 @@ function mergeLastWriteWins(localContent, remoteContent, localModified, remoteMo
28498
28508
  function getClaudeDir() {
28499
28509
  return join6(homedir2(), ".claude");
28500
28510
  }
28501
- async function pushSync(client, masterKey, deviceName, configDir) {
28511
+ async function pushSync(client, masterKey, deviceName, configDir, onProgress) {
28502
28512
  const start = Date.now();
28503
28513
  const claudeDir = getClaudeDir();
28504
28514
  const errors2 = [];
28505
28515
  let bytesTransferred = 0;
28506
- const localManifest = await generateManifest(claudeDir, deviceName);
28516
+ const progress = onProgress ?? (() => {});
28517
+ const localManifest = await generateManifest(claudeDir, deviceName, progress);
28518
+ const fileCount = Object.keys(localManifest.files).length;
28519
+ progress(`Scanned ${fileCount} files`);
28520
+ progress("Fetching remote manifest...");
28507
28521
  const remoteManifestEnc = await client.getManifest();
28508
28522
  let remoteManifest = null;
28509
28523
  if (remoteManifestEnc) {
@@ -28514,8 +28528,11 @@ async function pushSync(client, masterKey, deviceName, configDir) {
28514
28528
  remoteManifest = null;
28515
28529
  }
28516
28530
  }
28531
+ progress("Comparing manifests...");
28517
28532
  const diffs = diffManifests(localManifest, remoteManifest);
28518
28533
  const toPush = diffs.filter((d) => d.action === "push" || d.action === "merge");
28534
+ progress(`${toPush.length} files to push`);
28535
+ let uploaded = 0;
28519
28536
  const chunks = chunkArray(toPush, MAX_CONCURRENT_TRANSFERS);
28520
28537
  for (const chunk of chunks) {
28521
28538
  await Promise.all(chunk.map(async (diff) => {
@@ -28525,16 +28542,20 @@ async function pushSync(client, masterKey, deviceName, configDir) {
28525
28542
  const encrypted = encryptFile(masterKey, diff.path, content);
28526
28543
  await client.uploadBlob(diff.localHash, encrypted);
28527
28544
  bytesTransferred += encrypted.length;
28545
+ uploaded++;
28546
+ progress(`Uploading ${uploaded}/${toPush.length}: ${diff.path}`);
28528
28547
  } catch (e) {
28529
28548
  errors2.push(`Push ${diff.path}: ${e.message}`);
28530
28549
  }
28531
28550
  }));
28532
28551
  }
28552
+ progress("Saving manifest...");
28533
28553
  const manifestJson = JSON.stringify(localManifest);
28534
28554
  const manifestEnc = encryptFile(masterKey, "__manifest__", new TextEncoder().encode(manifestJson));
28535
28555
  await client.putManifest(manifestEnc);
28536
28556
  await saveManifest(configDir, localManifest);
28537
28557
  const durationMs = Date.now() - start;
28558
+ progress("Logging sync event...");
28538
28559
  await client.logSyncEvent({
28539
28560
  action: "push",
28540
28561
  filesChanged: toPush.length,
@@ -28549,11 +28570,13 @@ async function pushSync(client, masterKey, deviceName, configDir) {
28549
28570
  errors: errors2
28550
28571
  };
28551
28572
  }
28552
- async function pullSync(client, masterKey, deviceName, configDir) {
28573
+ async function pullSync(client, masterKey, deviceName, configDir, onProgress) {
28553
28574
  const start = Date.now();
28554
28575
  const claudeDir = getClaudeDir();
28555
28576
  const errors2 = [];
28556
28577
  let bytesTransferred = 0;
28578
+ const progress = onProgress ?? (() => {});
28579
+ progress("Fetching remote manifest...");
28557
28580
  const remoteManifestEnc = await client.getManifest();
28558
28581
  if (!remoteManifestEnc) {
28559
28582
  return {
@@ -28579,9 +28602,13 @@ async function pullSync(client, masterKey, deviceName, configDir) {
28579
28602
  ]
28580
28603
  };
28581
28604
  }
28605
+ progress("Loading local manifest...");
28582
28606
  const localManifest = await loadManifest(configDir);
28607
+ progress("Comparing manifests...");
28583
28608
  const diffs = diffManifests(localManifest, remoteManifest);
28584
28609
  const toPull = diffs.filter((d) => d.action === "pull" || d.action === "merge");
28610
+ progress(`${toPull.length} files to pull`);
28611
+ let downloaded = 0;
28585
28612
  const chunks = chunkArray(toPull, MAX_CONCURRENT_TRANSFERS);
28586
28613
  for (const chunk of chunks) {
28587
28614
  await Promise.all(chunk.map(async (diff) => {
@@ -28596,6 +28623,8 @@ async function pullSync(client, masterKey, deviceName, configDir) {
28596
28623
  if (diff.category === "session") {
28597
28624
  const merged = mergeSessionFiles(localContent, remoteContent);
28598
28625
  await writeFile5(localPath2, merged);
28626
+ downloaded++;
28627
+ progress(`Downloading ${downloaded}/${toPull.length}: ${diff.path}`);
28599
28628
  return;
28600
28629
  }
28601
28630
  const entry = remoteManifest.files[diff.path];
@@ -28604,19 +28633,25 @@ async function pullSync(client, masterKey, deviceName, configDir) {
28604
28633
  const result = mergeLastWriteWins(localContent, remoteContent, localEntry.modified, entry.modified);
28605
28634
  await writeFile5(localPath2, result.content);
28606
28635
  await writeFile5(`${localPath2}.bak`, result.backupContent);
28636
+ downloaded++;
28637
+ progress(`Downloading ${downloaded}/${toPull.length}: ${diff.path}`);
28607
28638
  return;
28608
28639
  }
28609
28640
  }
28610
28641
  const localPath = join6(claudeDir, diff.path);
28611
28642
  await mkdir2(dirname(localPath), { recursive: true });
28612
28643
  await writeFile5(localPath, decrypted);
28644
+ downloaded++;
28645
+ progress(`Downloading ${downloaded}/${toPull.length}: ${diff.path}`);
28613
28646
  } catch (e) {
28614
28647
  errors2.push(`Pull ${diff.path}: ${e.message}`);
28615
28648
  }
28616
28649
  }));
28617
28650
  }
28651
+ progress("Saving manifest...");
28618
28652
  await saveManifest(configDir, remoteManifest);
28619
28653
  const durationMs = Date.now() - start;
28654
+ progress("Logging sync event...");
28620
28655
  await client.logSyncEvent({
28621
28656
  action: "pull",
28622
28657
  filesChanged: toPull.length,
@@ -29004,7 +29039,9 @@ function registerSyncCommands(program2) {
29004
29039
  const client = await getAuthenticatedClient2(configDir);
29005
29040
  const config = await loadKeys(configDir);
29006
29041
  const spinner = ora2("Scanning files...").start();
29007
- const result = await pushSync(client, masterKey, config.deviceName, configDir);
29042
+ const result = await pushSync(client, masterKey, config.deviceName, configDir, (msg) => {
29043
+ spinner.text = msg;
29044
+ });
29008
29045
  if (result.errors.length > 0) {
29009
29046
  spinner.warn("Push completed with errors");
29010
29047
  for (const err of result.errors) {
@@ -29032,7 +29069,9 @@ function registerSyncCommands(program2) {
29032
29069
  const client = await getAuthenticatedClient2(configDir);
29033
29070
  const config = await loadKeys(configDir);
29034
29071
  const spinner = ora2("Pulling from cloud...").start();
29035
- const result = await pullSync(client, masterKey, config.deviceName, configDir);
29072
+ const result = await pullSync(client, masterKey, config.deviceName, configDir, (msg) => {
29073
+ spinner.text = msg;
29074
+ });
29036
29075
  if (result.errors.length > 0) {
29037
29076
  spinner.warn("Pull completed with errors");
29038
29077
  for (const err of result.errors) {
@@ -29062,7 +29101,9 @@ function registerSyncCommands(program2) {
29062
29101
  const spinner = ora2("Checking status...").start();
29063
29102
  const localManifest = await loadManifest(configDir);
29064
29103
  const claudeDir = getClaudeDir();
29065
- const currentManifest = await generateManifest(claudeDir, config.deviceName);
29104
+ const currentManifest = await generateManifest(claudeDir, config.deviceName, (msg) => {
29105
+ spinner.text = msg;
29106
+ });
29066
29107
  let remoteManifest = null;
29067
29108
  const remoteManifestEnc = await client.getManifest();
29068
29109
  if (remoteManifestEnc) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ccsini",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Claude Code seamless sync across devices",
5
5
  "type": "module",
6
6
  "bin": {