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