ccsini 0.1.41 → 0.1.42
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.
- package/dist/index.js +159 -22
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -28018,14 +28018,14 @@ var {
|
|
|
28018
28018
|
} = import__.default;
|
|
28019
28019
|
|
|
28020
28020
|
// src/version.ts
|
|
28021
|
-
var VERSION = "0.1.
|
|
28021
|
+
var VERSION = "0.1.42";
|
|
28022
28022
|
|
|
28023
28023
|
// src/commands/init.ts
|
|
28024
28024
|
init_source();
|
|
28025
28025
|
init_ora();
|
|
28026
28026
|
init_dist16();
|
|
28027
28027
|
init_auth();
|
|
28028
|
-
import { platform } from "os";
|
|
28028
|
+
import { platform as platform2 } from "os";
|
|
28029
28029
|
|
|
28030
28030
|
// ../../node_modules/.bun/hash-wasm@4.12.0/node_modules/hash-wasm/dist/index.esm.js
|
|
28031
28031
|
/*!
|
|
@@ -29078,6 +29078,12 @@ class CcsiniClient {
|
|
|
29078
29078
|
throw new Error("Failed to reset account data");
|
|
29079
29079
|
return res.json();
|
|
29080
29080
|
}
|
|
29081
|
+
async heartbeat() {
|
|
29082
|
+
await fetch(`${this.apiUrl}/api/sync/heartbeat`, {
|
|
29083
|
+
method: "POST",
|
|
29084
|
+
headers: this.getHeaders()
|
|
29085
|
+
});
|
|
29086
|
+
}
|
|
29081
29087
|
async logSyncEvent(event) {
|
|
29082
29088
|
await fetch(`${this.apiUrl}/api/sync/log`, {
|
|
29083
29089
|
method: "POST",
|
|
@@ -29541,8 +29547,8 @@ function chunkArray(arr, size) {
|
|
|
29541
29547
|
}
|
|
29542
29548
|
|
|
29543
29549
|
// src/commands/init.ts
|
|
29544
|
-
import { writeFile as
|
|
29545
|
-
import { join as
|
|
29550
|
+
import { writeFile as writeFile7 } from "fs/promises";
|
|
29551
|
+
import { join as join8 } from "path";
|
|
29546
29552
|
|
|
29547
29553
|
// src/branding.ts
|
|
29548
29554
|
init_source();
|
|
@@ -29558,6 +29564,120 @@ var TAGLINE = ` ${source_default.bold(`ccsini v${VERSION}`)} \u2014 Claude Code
|
|
|
29558
29564
|
${source_default.dim("Encrypted sync for your Claude Code settings across devices")}
|
|
29559
29565
|
`;
|
|
29560
29566
|
|
|
29567
|
+
// src/heartbeat/scheduler.ts
|
|
29568
|
+
import { execSync } from "child_process";
|
|
29569
|
+
import { platform } from "os";
|
|
29570
|
+
import { writeFile as writeFile6, unlink } from "fs/promises";
|
|
29571
|
+
import { join as join7 } from "path";
|
|
29572
|
+
import { homedir as homedir3 } from "os";
|
|
29573
|
+
var TASK_NAME = "ccsini-heartbeat";
|
|
29574
|
+
var INTERVAL_MINUTES = 3;
|
|
29575
|
+
async function installHeartbeatScheduler() {
|
|
29576
|
+
const os3 = platform();
|
|
29577
|
+
if (os3 === "win32") {
|
|
29578
|
+
await installWindows();
|
|
29579
|
+
} else if (os3 === "darwin") {
|
|
29580
|
+
await installMacOS();
|
|
29581
|
+
} else {
|
|
29582
|
+
await installLinux();
|
|
29583
|
+
}
|
|
29584
|
+
}
|
|
29585
|
+
async function uninstallHeartbeatScheduler() {
|
|
29586
|
+
const os3 = platform();
|
|
29587
|
+
if (os3 === "win32") {
|
|
29588
|
+
await uninstallWindows();
|
|
29589
|
+
} else if (os3 === "darwin") {
|
|
29590
|
+
await uninstallMacOS();
|
|
29591
|
+
} else {
|
|
29592
|
+
await uninstallLinux();
|
|
29593
|
+
}
|
|
29594
|
+
}
|
|
29595
|
+
async function installWindows() {
|
|
29596
|
+
try {
|
|
29597
|
+
execSync(`schtasks /Delete /TN "${TASK_NAME}" /F`, { stdio: "ignore" });
|
|
29598
|
+
} catch {}
|
|
29599
|
+
execSync(`schtasks /Create /TN "${TASK_NAME}" /TR "ccsini heartbeat" /SC MINUTE /MO ${INTERVAL_MINUTES} /F`, { stdio: "ignore" });
|
|
29600
|
+
}
|
|
29601
|
+
async function uninstallWindows() {
|
|
29602
|
+
try {
|
|
29603
|
+
execSync(`schtasks /Delete /TN "${TASK_NAME}" /F`, { stdio: "ignore" });
|
|
29604
|
+
} catch {}
|
|
29605
|
+
}
|
|
29606
|
+
function getLaunchAgentPath() {
|
|
29607
|
+
return join7(homedir3(), "Library", "LaunchAgents", `com.ccsini.heartbeat.plist`);
|
|
29608
|
+
}
|
|
29609
|
+
async function installMacOS() {
|
|
29610
|
+
const plistPath = getLaunchAgentPath();
|
|
29611
|
+
let ccsiniPath = "ccsini";
|
|
29612
|
+
try {
|
|
29613
|
+
ccsiniPath = execSync("which ccsini", { encoding: "utf-8" }).trim();
|
|
29614
|
+
} catch {}
|
|
29615
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
29616
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
29617
|
+
<plist version="1.0">
|
|
29618
|
+
<dict>
|
|
29619
|
+
<key>Label</key>
|
|
29620
|
+
<string>com.ccsini.heartbeat</string>
|
|
29621
|
+
<key>ProgramArguments</key>
|
|
29622
|
+
<array>
|
|
29623
|
+
<string>${ccsiniPath}</string>
|
|
29624
|
+
<string>heartbeat</string>
|
|
29625
|
+
</array>
|
|
29626
|
+
<key>StartInterval</key>
|
|
29627
|
+
<integer>${INTERVAL_MINUTES * 60}</integer>
|
|
29628
|
+
<key>RunAtLoad</key>
|
|
29629
|
+
<true/>
|
|
29630
|
+
<key>StandardOutPath</key>
|
|
29631
|
+
<string>/dev/null</string>
|
|
29632
|
+
<key>StandardErrorPath</key>
|
|
29633
|
+
<string>/dev/null</string>
|
|
29634
|
+
</dict>
|
|
29635
|
+
</plist>`;
|
|
29636
|
+
await writeFile6(plistPath, plist);
|
|
29637
|
+
try {
|
|
29638
|
+
execSync(`launchctl unload "${plistPath}"`, { stdio: "ignore" });
|
|
29639
|
+
} catch {}
|
|
29640
|
+
execSync(`launchctl load "${plistPath}"`, { stdio: "ignore" });
|
|
29641
|
+
}
|
|
29642
|
+
async function uninstallMacOS() {
|
|
29643
|
+
const plistPath = getLaunchAgentPath();
|
|
29644
|
+
try {
|
|
29645
|
+
execSync(`launchctl unload "${plistPath}"`, { stdio: "ignore" });
|
|
29646
|
+
} catch {}
|
|
29647
|
+
try {
|
|
29648
|
+
await unlink(plistPath);
|
|
29649
|
+
} catch {}
|
|
29650
|
+
}
|
|
29651
|
+
async function installLinux() {
|
|
29652
|
+
let existing = "";
|
|
29653
|
+
try {
|
|
29654
|
+
existing = execSync("crontab -l 2>/dev/null", { encoding: "utf-8" });
|
|
29655
|
+
} catch {}
|
|
29656
|
+
const lines = existing.split(`
|
|
29657
|
+
`).filter((l) => !l.includes(TASK_NAME));
|
|
29658
|
+
lines.push(`*/${INTERVAL_MINUTES} * * * * ccsini heartbeat # ${TASK_NAME}`);
|
|
29659
|
+
const newCrontab = lines.filter((l) => l.trim() !== "").join(`
|
|
29660
|
+
`) + `
|
|
29661
|
+
`;
|
|
29662
|
+
execSync(`echo "${newCrontab.replace(/"/g, "\\\"")}" | crontab -`, { stdio: "ignore" });
|
|
29663
|
+
}
|
|
29664
|
+
async function uninstallLinux() {
|
|
29665
|
+
let existing = "";
|
|
29666
|
+
try {
|
|
29667
|
+
existing = execSync("crontab -l 2>/dev/null", { encoding: "utf-8" });
|
|
29668
|
+
} catch {
|
|
29669
|
+
return;
|
|
29670
|
+
}
|
|
29671
|
+
const lines = existing.split(`
|
|
29672
|
+
`).filter((l) => !l.includes(TASK_NAME));
|
|
29673
|
+
const newCrontab = lines.filter((l) => l.trim() !== "").join(`
|
|
29674
|
+
`) + `
|
|
29675
|
+
`;
|
|
29676
|
+
try {
|
|
29677
|
+
execSync(`echo "${newCrontab.replace(/"/g, "\\\"")}" | crontab -`, { stdio: "ignore" });
|
|
29678
|
+
} catch {}
|
|
29679
|
+
}
|
|
29680
|
+
|
|
29561
29681
|
// src/commands/init.ts
|
|
29562
29682
|
function registerInitCommand(program2) {
|
|
29563
29683
|
program2.command("init").description("Connect this device to your ccsini account").option("--token <token>", "Setup token from dashboard").action(async (opts) => {
|
|
@@ -29727,17 +29847,22 @@ function registerInitCommand(program2) {
|
|
|
29727
29847
|
deviceName,
|
|
29728
29848
|
apiUrl: "https://ccsini-api.anis-maisara190.workers.dev"
|
|
29729
29849
|
});
|
|
29730
|
-
await
|
|
29850
|
+
await writeFile7(join8(configDir, ".cached-key"), masterKey, {
|
|
29731
29851
|
mode: 384
|
|
29732
29852
|
});
|
|
29733
29853
|
await saveDefaultSchema(configDir);
|
|
29734
29854
|
saveSpinner.text = "Installing Claude Code hooks...";
|
|
29735
29855
|
await installHooks(getClaudeDir());
|
|
29856
|
+
saveSpinner.text = "Setting up heartbeat scheduler...";
|
|
29857
|
+
try {
|
|
29858
|
+
await installHeartbeatScheduler();
|
|
29859
|
+
} catch {}
|
|
29736
29860
|
saveSpinner.succeed("Setup complete!");
|
|
29737
29861
|
console.log(source_default.green(`
|
|
29738
29862
|
\u2713 Encryption keys generated`));
|
|
29739
29863
|
console.log(source_default.green(" \u2713 Device registered"));
|
|
29740
29864
|
console.log(source_default.green(" \u2713 Claude Code hooks installed"));
|
|
29865
|
+
console.log(source_default.green(" \u2713 Heartbeat scheduler installed"));
|
|
29741
29866
|
console.log(source_default.green(" \u2713 Auto-sync is active"));
|
|
29742
29867
|
console.log(source_default.dim(`
|
|
29743
29868
|
Just use 'claude' as normal. Sync happens automatically.
|
|
@@ -29749,7 +29874,7 @@ function registerInitCommand(program2) {
|
|
|
29749
29874
|
});
|
|
29750
29875
|
}
|
|
29751
29876
|
function detectPlatform() {
|
|
29752
|
-
const p =
|
|
29877
|
+
const p = platform2();
|
|
29753
29878
|
if (p === "win32")
|
|
29754
29879
|
return "windows";
|
|
29755
29880
|
if (p === "darwin")
|
|
@@ -29761,10 +29886,10 @@ function detectPlatform() {
|
|
|
29761
29886
|
init_auth();
|
|
29762
29887
|
init_auth();
|
|
29763
29888
|
init_src();
|
|
29764
|
-
import { readFile as readFile7, writeFile as
|
|
29765
|
-
import { join as
|
|
29889
|
+
import { readFile as readFile7, writeFile as writeFile8 } from "fs/promises";
|
|
29890
|
+
import { join as join9 } from "path";
|
|
29766
29891
|
async function getMasterKey(configDir) {
|
|
29767
|
-
const cachedKeyPath =
|
|
29892
|
+
const cachedKeyPath = join9(configDir, ".cached-key");
|
|
29768
29893
|
try {
|
|
29769
29894
|
const cached = await readFile7(cachedKeyPath);
|
|
29770
29895
|
return new Uint8Array(cached);
|
|
@@ -29836,16 +29961,25 @@ function registerAutoCommands(program2) {
|
|
|
29836
29961
|
]);
|
|
29837
29962
|
const config = await loadKeys(configDir);
|
|
29838
29963
|
const masterKey = await deriveKeyFromPassphrase(password, config.salt);
|
|
29839
|
-
await
|
|
29964
|
+
await writeFile8(join9(configDir, ".cached-key"), masterKey, {
|
|
29840
29965
|
mode: 384
|
|
29841
29966
|
});
|
|
29842
29967
|
console.log("Unlocked. Auto-sync is now active.");
|
|
29843
29968
|
});
|
|
29969
|
+
program2.command("heartbeat").description("Send heartbeat to keep device online (runs via scheduled task)").action(async () => {
|
|
29970
|
+
const configDir = getConfigDir();
|
|
29971
|
+
if (!await configExists(configDir))
|
|
29972
|
+
return;
|
|
29973
|
+
try {
|
|
29974
|
+
const client = await getAuthenticatedClient(configDir);
|
|
29975
|
+
await client.heartbeat();
|
|
29976
|
+
} catch {}
|
|
29977
|
+
});
|
|
29844
29978
|
program2.command("lock").description("Remove cached encryption key").action(async () => {
|
|
29845
29979
|
const configDir = getConfigDir();
|
|
29846
29980
|
const { rm } = await import("fs/promises");
|
|
29847
29981
|
try {
|
|
29848
|
-
await rm(
|
|
29982
|
+
await rm(join9(configDir, ".cached-key"));
|
|
29849
29983
|
console.log("Locked. Auto-sync paused until next unlock.");
|
|
29850
29984
|
} catch {
|
|
29851
29985
|
console.log("Already locked.");
|
|
@@ -29856,7 +29990,7 @@ function registerAutoCommands(program2) {
|
|
|
29856
29990
|
// src/commands/doctor.ts
|
|
29857
29991
|
init_source();
|
|
29858
29992
|
import { access as access2 } from "fs/promises";
|
|
29859
|
-
import { join as
|
|
29993
|
+
import { join as join10 } from "path";
|
|
29860
29994
|
function registerDoctorCommand(program2) {
|
|
29861
29995
|
program2.command("doctor").description("Diagnose ccsini setup and connectivity").action(async () => {
|
|
29862
29996
|
const configDir = getConfigDir();
|
|
@@ -29898,7 +30032,7 @@ function registerDoctorCommand(program2) {
|
|
|
29898
30032
|
allGood = false;
|
|
29899
30033
|
}
|
|
29900
30034
|
try {
|
|
29901
|
-
await access2(
|
|
30035
|
+
await access2(join10(configDir, ".cached-key"));
|
|
29902
30036
|
console.log(source_default.green(" \u2713 Auto-sync unlocked"));
|
|
29903
30037
|
} catch {
|
|
29904
30038
|
console.log(source_default.yellow(" \u26A0 Auto-sync locked (run 'ccsini unlock')"));
|
|
@@ -29926,10 +30060,10 @@ function registerDoctorCommand(program2) {
|
|
|
29926
30060
|
}
|
|
29927
30061
|
|
|
29928
30062
|
// src/commands/self.ts
|
|
29929
|
-
import { execSync } from "child_process";
|
|
30063
|
+
import { execSync as execSync2 } from "child_process";
|
|
29930
30064
|
function getLatestVersion() {
|
|
29931
30065
|
try {
|
|
29932
|
-
const result =
|
|
30066
|
+
const result = execSync2("npm view ccsini version", { encoding: "utf-8" }).trim();
|
|
29933
30067
|
return result;
|
|
29934
30068
|
} catch {
|
|
29935
30069
|
return null;
|
|
@@ -29952,7 +30086,7 @@ function registerSelfCommands(program2) {
|
|
|
29952
30086
|
`);
|
|
29953
30087
|
const cmd = `bun add -g ccsini@${latest}`;
|
|
29954
30088
|
try {
|
|
29955
|
-
|
|
30089
|
+
execSync2(cmd, { stdio: "inherit" });
|
|
29956
30090
|
console.log(`
|
|
29957
30091
|
Updated to v${latest}`);
|
|
29958
30092
|
try {
|
|
@@ -29972,13 +30106,16 @@ Update failed. Try manually:`);
|
|
|
29972
30106
|
program2.command("uninstall").description("Uninstall ccsini from this machine").action(async () => {
|
|
29973
30107
|
console.log(`Uninstalling ccsini...
|
|
29974
30108
|
`);
|
|
30109
|
+
try {
|
|
30110
|
+
await uninstallHeartbeatScheduler();
|
|
30111
|
+
} catch {}
|
|
29975
30112
|
let removed = false;
|
|
29976
30113
|
try {
|
|
29977
|
-
|
|
30114
|
+
execSync2("bun remove -g ccsini", { stdio: "inherit" });
|
|
29978
30115
|
removed = true;
|
|
29979
30116
|
} catch {}
|
|
29980
30117
|
try {
|
|
29981
|
-
|
|
30118
|
+
execSync2("npm uninstall -g ccsini", { stdio: "inherit" });
|
|
29982
30119
|
removed = true;
|
|
29983
30120
|
} catch {}
|
|
29984
30121
|
if (removed) {
|
|
@@ -29997,9 +30134,9 @@ Uninstall failed. Try manually:`);
|
|
|
29997
30134
|
init_auth();
|
|
29998
30135
|
init_src();
|
|
29999
30136
|
import { readFile as readFile8 } from "fs/promises";
|
|
30000
|
-
import { join as
|
|
30137
|
+
import { join as join11 } from "path";
|
|
30001
30138
|
async function getMasterKey2(configDir) {
|
|
30002
|
-
const cachedKeyPath =
|
|
30139
|
+
const cachedKeyPath = join11(configDir, ".cached-key");
|
|
30003
30140
|
try {
|
|
30004
30141
|
const cached = await readFile8(cachedKeyPath);
|
|
30005
30142
|
return new Uint8Array(cached);
|
|
@@ -30015,8 +30152,8 @@ async function getMasterKey2(configDir) {
|
|
|
30015
30152
|
]);
|
|
30016
30153
|
const config = await loadKeys(configDir);
|
|
30017
30154
|
const masterKey = await deriveKeyFromPassphrase(password, config.salt);
|
|
30018
|
-
const { writeFile:
|
|
30019
|
-
await
|
|
30155
|
+
const { writeFile: writeFile9 } = await import("fs/promises");
|
|
30156
|
+
await writeFile9(cachedKeyPath, masterKey, { mode: 384 });
|
|
30020
30157
|
return masterKey;
|
|
30021
30158
|
}
|
|
30022
30159
|
}
|