aiblueprint-cli 1.3.1 → 1.3.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.
- package/README.md +18 -1
- package/dist/cli.js +250 -249
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -547,10 +547,27 @@ aiblueprint claude-code pro setup
|
|
|
547
547
|
# Check premium status
|
|
548
548
|
aiblueprint claude-code pro status
|
|
549
549
|
|
|
550
|
-
# Update premium configs
|
|
550
|
+
# Update premium configs (overwrites all)
|
|
551
551
|
aiblueprint claude-code pro update
|
|
552
|
+
|
|
553
|
+
# Sync premium configs (selective update)
|
|
554
|
+
aiblueprint claude-code pro sync
|
|
552
555
|
```
|
|
553
556
|
|
|
557
|
+
### Sync Command
|
|
558
|
+
|
|
559
|
+
The `sync` command provides intelligent selective updates:
|
|
560
|
+
|
|
561
|
+
```bash
|
|
562
|
+
aiblueprint claude-code pro sync
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
**Features:**
|
|
566
|
+
- 🔍 **Diff Analysis** - Compares your local config with the latest premium version
|
|
567
|
+
- 📝 **Categorized Changes** - Shows NEW and MODIFIED items separately
|
|
568
|
+
- ✅ **Selective Update** - Choose exactly which files/folders to update
|
|
569
|
+
- 📁 **Smart Grouping** - Commands and agents shown individually, skills and scripts grouped as folders
|
|
570
|
+
|
|
554
571
|
**Learn more:** https://mlv.sh/claude-cli
|
|
555
572
|
|
|
556
573
|
---
|
package/dist/cli.js
CHANGED
|
@@ -33191,20 +33191,23 @@ async function checkAndInstallDependencies() {
|
|
|
33191
33191
|
}
|
|
33192
33192
|
}
|
|
33193
33193
|
}
|
|
33194
|
-
async function
|
|
33195
|
-
const
|
|
33194
|
+
async function installScriptsDependencies(claudeDir) {
|
|
33195
|
+
const scriptsDir = path4.join(claudeDir, "scripts");
|
|
33196
33196
|
console.log(source_default.yellow(`
|
|
33197
|
-
Installing
|
|
33197
|
+
Installing scripts dependencies...`));
|
|
33198
33198
|
try {
|
|
33199
33199
|
execSync("bun install", {
|
|
33200
|
-
cwd:
|
|
33200
|
+
cwd: scriptsDir,
|
|
33201
33201
|
stdio: "inherit"
|
|
33202
33202
|
});
|
|
33203
|
-
console.log(source_default.green(" ✓
|
|
33203
|
+
console.log(source_default.green(" ✓ Scripts dependencies installed"));
|
|
33204
33204
|
} catch (error) {
|
|
33205
|
-
console.log(source_default.red(" Failed to install
|
|
33205
|
+
console.log(source_default.red(" Failed to install scripts dependencies. Please run 'bun install' manually in ~/.claude/scripts"));
|
|
33206
33206
|
}
|
|
33207
33207
|
}
|
|
33208
|
+
async function installStatuslineDependencies(claudeDir) {
|
|
33209
|
+
await installScriptsDependencies(claudeDir);
|
|
33210
|
+
}
|
|
33208
33211
|
|
|
33209
33212
|
// src/commands/setup/settings.ts
|
|
33210
33213
|
var import_fs_extra3 = __toESM(require_lib4(), 1);
|
|
@@ -34917,6 +34920,10 @@ var de = () => {
|
|
|
34917
34920
|
return process.on("uncaughtExceptionMonitor", () => $2(2)), process.on("unhandledRejection", () => $2(2)), process.on("SIGINT", () => $2(1)), process.on("SIGTERM", () => $2(1)), process.on("exit", $2), { start: l2, stop: u, message: m2 };
|
|
34918
34921
|
};
|
|
34919
34922
|
|
|
34923
|
+
// src/commands/pro.ts
|
|
34924
|
+
import os10 from "os";
|
|
34925
|
+
import path16 from "path";
|
|
34926
|
+
|
|
34920
34927
|
// src/lib/pro-installer.ts
|
|
34921
34928
|
var import_fs_extra12 = __toESM(require_lib4(), 1);
|
|
34922
34929
|
import os8 from "os";
|
|
@@ -34945,7 +34952,7 @@ async function downloadFromPrivateGitHub(repo, branch, relativePath, targetPath,
|
|
|
34945
34952
|
return false;
|
|
34946
34953
|
}
|
|
34947
34954
|
}
|
|
34948
|
-
async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetDir, githubToken) {
|
|
34955
|
+
async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetDir, githubToken, onProgress) {
|
|
34949
34956
|
try {
|
|
34950
34957
|
const apiUrl = `https://api.github.com/repos/${repo}/contents/${dirPath}?ref=${branch}`;
|
|
34951
34958
|
const response = await fetch(apiUrl, {
|
|
@@ -34967,10 +34974,12 @@ async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetD
|
|
|
34967
34974
|
for (const file of files) {
|
|
34968
34975
|
const relativePath = dirPath ? `${dirPath}/${file.name}` : file.name;
|
|
34969
34976
|
const targetPath = path14.join(targetDir, file.name);
|
|
34977
|
+
const displayPath = relativePath.replace("claude-code-config/", "");
|
|
34970
34978
|
if (file.type === "file") {
|
|
34979
|
+
onProgress?.(displayPath, "file");
|
|
34971
34980
|
await downloadFromPrivateGitHub(repo, branch, relativePath, targetPath, githubToken);
|
|
34972
34981
|
} else if (file.type === "dir") {
|
|
34973
|
-
await downloadDirectoryFromPrivateGitHub(repo, branch, relativePath, targetPath, githubToken);
|
|
34982
|
+
await downloadDirectoryFromPrivateGitHub(repo, branch, relativePath, targetPath, githubToken, onProgress);
|
|
34974
34983
|
}
|
|
34975
34984
|
}
|
|
34976
34985
|
return true;
|
|
@@ -34980,11 +34989,11 @@ async function downloadDirectoryFromPrivateGitHub(repo, branch, dirPath, targetD
|
|
|
34980
34989
|
}
|
|
34981
34990
|
}
|
|
34982
34991
|
async function installProConfigs(options) {
|
|
34983
|
-
const { githubToken, claudeCodeFolder } = options;
|
|
34992
|
+
const { githubToken, claudeCodeFolder, onProgress } = options;
|
|
34984
34993
|
const claudeFolder = claudeCodeFolder || path14.join(os8.homedir(), ".claude");
|
|
34985
34994
|
const tempDir = path14.join(os8.tmpdir(), `aiblueprint-premium-${Date.now()}`);
|
|
34986
34995
|
try {
|
|
34987
|
-
const success = await downloadDirectoryFromPrivateGitHub(PREMIUM_REPO, PREMIUM_BRANCH, "claude-code-config", tempDir, githubToken);
|
|
34996
|
+
const success = await downloadDirectoryFromPrivateGitHub(PREMIUM_REPO, PREMIUM_BRANCH, "claude-code-config", tempDir, githubToken, onProgress);
|
|
34988
34997
|
if (!success) {
|
|
34989
34998
|
throw new Error("Failed to download premium configurations");
|
|
34990
34999
|
}
|
|
@@ -34992,66 +35001,45 @@ async function installProConfigs(options) {
|
|
|
34992
35001
|
overwrite: true,
|
|
34993
35002
|
recursive: true
|
|
34994
35003
|
});
|
|
34995
|
-
console.log(`✓ Premium configurations installed to ${claudeFolder}`);
|
|
34996
35004
|
} catch (error) {
|
|
34997
35005
|
throw new Error(`Failed to install premium configs: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
34998
35006
|
} finally {
|
|
34999
35007
|
try {
|
|
35000
35008
|
await import_fs_extra12.default.remove(tempDir);
|
|
35001
|
-
} catch
|
|
35009
|
+
} catch {
|
|
35002
35010
|
}
|
|
35003
35011
|
}
|
|
35004
35012
|
}
|
|
35005
35013
|
|
|
35006
|
-
// src/lib/
|
|
35014
|
+
// src/lib/token-storage.ts
|
|
35007
35015
|
var import_fs_extra13 = __toESM(require_lib4(), 1);
|
|
35008
|
-
import path15 from "path";
|
|
35009
35016
|
import os9 from "os";
|
|
35010
|
-
|
|
35011
|
-
const claudeDir = options.claudeCodeFolder || path15.join(os9.homedir(), ".claude");
|
|
35012
|
-
await import_fs_extra13.default.ensureDir(claudeDir);
|
|
35013
|
-
console.log(source_default.gray("\uD83D\uDCE6 Installing free configurations..."));
|
|
35014
|
-
console.log(source_default.gray(" • Commands..."));
|
|
35015
|
-
await downloadDirectoryFromGitHub("commands", path15.join(claudeDir, "commands"));
|
|
35016
|
-
console.log(source_default.gray(" • Agents..."));
|
|
35017
|
-
await downloadDirectoryFromGitHub("agents", path15.join(claudeDir, "agents"));
|
|
35018
|
-
if (!skipStatusline) {
|
|
35019
|
-
console.log(source_default.gray(" • Statusline (basic)..."));
|
|
35020
|
-
await downloadDirectoryFromGitHub("scripts/statusline", path15.join(claudeDir, "scripts", "statusline"));
|
|
35021
|
-
}
|
|
35022
|
-
console.log(source_default.green("✓ Free configurations installed"));
|
|
35023
|
-
return claudeDir;
|
|
35024
|
-
}
|
|
35025
|
-
|
|
35026
|
-
// src/lib/token-storage.ts
|
|
35027
|
-
var import_fs_extra14 = __toESM(require_lib4(), 1);
|
|
35028
|
-
import os10 from "os";
|
|
35029
|
-
import path16 from "path";
|
|
35017
|
+
import path15 from "path";
|
|
35030
35018
|
function getConfigDir() {
|
|
35031
|
-
const platform =
|
|
35019
|
+
const platform = os9.platform();
|
|
35032
35020
|
if (platform === "win32") {
|
|
35033
|
-
const appData = process.env.APPDATA ||
|
|
35034
|
-
return
|
|
35021
|
+
const appData = process.env.APPDATA || path15.join(os9.homedir(), "AppData", "Roaming");
|
|
35022
|
+
return path15.join(appData, "aiblueprint");
|
|
35035
35023
|
} else {
|
|
35036
|
-
const configHome = process.env.XDG_CONFIG_HOME ||
|
|
35037
|
-
return
|
|
35024
|
+
const configHome = process.env.XDG_CONFIG_HOME || path15.join(os9.homedir(), ".config");
|
|
35025
|
+
return path15.join(configHome, "aiblueprint");
|
|
35038
35026
|
}
|
|
35039
35027
|
}
|
|
35040
35028
|
function getTokenFilePath() {
|
|
35041
|
-
return
|
|
35029
|
+
return path15.join(getConfigDir(), "token.txt");
|
|
35042
35030
|
}
|
|
35043
35031
|
async function saveToken(githubToken) {
|
|
35044
35032
|
const tokenFile = getTokenFilePath();
|
|
35045
|
-
await
|
|
35046
|
-
await
|
|
35033
|
+
await import_fs_extra13.default.ensureDir(path15.dirname(tokenFile));
|
|
35034
|
+
await import_fs_extra13.default.writeFile(tokenFile, githubToken, { mode: 384 });
|
|
35047
35035
|
}
|
|
35048
35036
|
async function getToken() {
|
|
35049
35037
|
const tokenFile = getTokenFilePath();
|
|
35050
|
-
if (!await
|
|
35038
|
+
if (!await import_fs_extra13.default.pathExists(tokenFile)) {
|
|
35051
35039
|
return null;
|
|
35052
35040
|
}
|
|
35053
35041
|
try {
|
|
35054
|
-
const token = await
|
|
35042
|
+
const token = await import_fs_extra13.default.readFile(tokenFile, "utf-8");
|
|
35055
35043
|
return token.trim();
|
|
35056
35044
|
} catch (error) {
|
|
35057
35045
|
return null;
|
|
@@ -35060,13 +35048,12 @@ async function getToken() {
|
|
|
35060
35048
|
function getTokenInfo() {
|
|
35061
35049
|
return {
|
|
35062
35050
|
path: getTokenFilePath(),
|
|
35063
|
-
platform:
|
|
35051
|
+
platform: os9.platform()
|
|
35064
35052
|
};
|
|
35065
35053
|
}
|
|
35066
35054
|
|
|
35067
35055
|
// src/commands/pro.ts
|
|
35068
|
-
var
|
|
35069
|
-
import path17 from "path";
|
|
35056
|
+
var import_fs_extra14 = __toESM(require_lib4(), 1);
|
|
35070
35057
|
var API_URL = "https://codeline.app/api/products";
|
|
35071
35058
|
var PRODUCT_ID = "prd_XJVgxVPbGG";
|
|
35072
35059
|
async function countInstalledItems(claudeDir) {
|
|
@@ -35076,27 +35063,27 @@ async function countInstalledItems(claudeDir) {
|
|
|
35076
35063
|
skills: 0
|
|
35077
35064
|
};
|
|
35078
35065
|
try {
|
|
35079
|
-
const commandsDir =
|
|
35080
|
-
if (await
|
|
35081
|
-
const files = await
|
|
35066
|
+
const commandsDir = path16.join(claudeDir, "commands");
|
|
35067
|
+
if (await import_fs_extra14.default.pathExists(commandsDir)) {
|
|
35068
|
+
const files = await import_fs_extra14.default.readdir(commandsDir);
|
|
35082
35069
|
counts.commands = files.filter((f3) => f3.endsWith(".md")).length;
|
|
35083
35070
|
}
|
|
35084
35071
|
} catch {
|
|
35085
35072
|
}
|
|
35086
35073
|
try {
|
|
35087
|
-
const agentsDir =
|
|
35088
|
-
if (await
|
|
35089
|
-
const files = await
|
|
35074
|
+
const agentsDir = path16.join(claudeDir, "agents");
|
|
35075
|
+
if (await import_fs_extra14.default.pathExists(agentsDir)) {
|
|
35076
|
+
const files = await import_fs_extra14.default.readdir(agentsDir);
|
|
35090
35077
|
counts.agents = files.filter((f3) => f3.endsWith(".md")).length;
|
|
35091
35078
|
}
|
|
35092
35079
|
} catch {
|
|
35093
35080
|
}
|
|
35094
35081
|
try {
|
|
35095
|
-
const skillsDir =
|
|
35096
|
-
if (await
|
|
35097
|
-
const items = await
|
|
35082
|
+
const skillsDir = path16.join(claudeDir, "skills");
|
|
35083
|
+
if (await import_fs_extra14.default.pathExists(skillsDir)) {
|
|
35084
|
+
const items = await import_fs_extra14.default.readdir(skillsDir);
|
|
35098
35085
|
const dirs = await Promise.all(items.map(async (item) => {
|
|
35099
|
-
const stat = await
|
|
35086
|
+
const stat = await import_fs_extra14.default.stat(path16.join(skillsDir, item));
|
|
35100
35087
|
return stat.isDirectory();
|
|
35101
35088
|
}));
|
|
35102
35089
|
counts.skills = dirs.filter(Boolean).length;
|
|
@@ -35203,16 +35190,24 @@ async function proSetupCommand(options = {}) {
|
|
|
35203
35190
|
$e(source_default.red("❌ Not activated"));
|
|
35204
35191
|
process.exit(1);
|
|
35205
35192
|
}
|
|
35193
|
+
const claudeDir = options.folder ? path16.resolve(options.folder) : path16.join(os10.homedir(), ".claude");
|
|
35206
35194
|
const spinner = de();
|
|
35207
|
-
|
|
35208
|
-
|
|
35209
|
-
|
|
35195
|
+
const onProgress = (file, type) => {
|
|
35196
|
+
spinner.message(`Installing: ${source_default.cyan(file)} ${source_default.gray(`(${type})`)}`);
|
|
35197
|
+
};
|
|
35210
35198
|
spinner.start("Installing premium configurations...");
|
|
35211
35199
|
await installProConfigs({
|
|
35212
35200
|
githubToken,
|
|
35213
|
-
claudeCodeFolder: claudeDir
|
|
35201
|
+
claudeCodeFolder: claudeDir,
|
|
35202
|
+
onProgress
|
|
35214
35203
|
});
|
|
35215
35204
|
spinner.stop("Premium configurations installed");
|
|
35205
|
+
spinner.start("Checking global dependencies...");
|
|
35206
|
+
await checkAndInstallDependencies();
|
|
35207
|
+
spinner.stop("Global dependencies ready");
|
|
35208
|
+
spinner.start("Installing scripts dependencies...");
|
|
35209
|
+
await installScriptsDependencies(claudeDir);
|
|
35210
|
+
spinner.stop("Scripts dependencies installed");
|
|
35216
35211
|
spinner.start("Setting up shell shortcuts...");
|
|
35217
35212
|
await setupShellShortcuts();
|
|
35218
35213
|
spinner.stop("Shell shortcuts configured");
|
|
@@ -35273,11 +35268,11 @@ async function proUpdateCommand(options = {}) {
|
|
|
35273
35268
|
|
|
35274
35269
|
// src/commands/sync.ts
|
|
35275
35270
|
import os11 from "os";
|
|
35276
|
-
import
|
|
35271
|
+
import path18 from "path";
|
|
35277
35272
|
|
|
35278
35273
|
// src/lib/sync-utils.ts
|
|
35279
|
-
var
|
|
35280
|
-
import
|
|
35274
|
+
var import_fs_extra15 = __toESM(require_lib4(), 1);
|
|
35275
|
+
import path17 from "path";
|
|
35281
35276
|
import crypto from "crypto";
|
|
35282
35277
|
var PREMIUM_REPO2 = "Melvynx/aiblueprint-cli-premium";
|
|
35283
35278
|
var PREMIUM_BRANCH2 = "main";
|
|
@@ -35307,147 +35302,140 @@ async function listRemoteDirectory(dirPath, githubToken) {
|
|
|
35307
35302
|
}
|
|
35308
35303
|
return files;
|
|
35309
35304
|
}
|
|
35310
|
-
async function
|
|
35311
|
-
|
|
35312
|
-
|
|
35313
|
-
|
|
35314
|
-
|
|
35315
|
-
|
|
35305
|
+
async function listRemoteFilesRecursive(dirPath, githubToken, basePath = "") {
|
|
35306
|
+
const results = [];
|
|
35307
|
+
const files = await listRemoteDirectory(dirPath, githubToken);
|
|
35308
|
+
for (const file of files) {
|
|
35309
|
+
const relativePath = basePath ? `${basePath}/${file.name}` : file.name;
|
|
35310
|
+
if (file.type === "file") {
|
|
35311
|
+
results.push({ path: relativePath, sha: file.sha, isFolder: false });
|
|
35312
|
+
} else if (file.type === "dir") {
|
|
35313
|
+
results.push({ path: relativePath, sha: "", isFolder: true });
|
|
35314
|
+
const subFiles = await listRemoteFilesRecursive(`${dirPath}/${file.name}`, githubToken, relativePath);
|
|
35315
|
+
results.push(...subFiles);
|
|
35316
|
+
}
|
|
35316
35317
|
}
|
|
35318
|
+
return results;
|
|
35317
35319
|
}
|
|
35318
|
-
async function
|
|
35320
|
+
async function computeLocalFileSha(filePath) {
|
|
35319
35321
|
try {
|
|
35320
|
-
|
|
35321
|
-
|
|
35322
|
-
}
|
|
35323
|
-
const files = await getAllFilesRecursive(folderPath);
|
|
35324
|
-
if (files.length === 0) {
|
|
35325
|
-
return null;
|
|
35326
|
-
}
|
|
35327
|
-
const hashes = [];
|
|
35328
|
-
for (const file of files.sort()) {
|
|
35329
|
-
const content = await import_fs_extra16.default.readFile(file);
|
|
35330
|
-
hashes.push(computeFileSha(content));
|
|
35331
|
-
}
|
|
35332
|
-
return crypto.createHash("sha1").update(hashes.join("")).digest("hex");
|
|
35322
|
+
const content = await import_fs_extra15.default.readFile(filePath);
|
|
35323
|
+
return computeFileSha(content);
|
|
35333
35324
|
} catch {
|
|
35334
35325
|
return null;
|
|
35335
35326
|
}
|
|
35336
35327
|
}
|
|
35337
|
-
async function
|
|
35328
|
+
async function listLocalFiles(dir) {
|
|
35338
35329
|
const files = [];
|
|
35339
|
-
|
|
35330
|
+
if (!await import_fs_extra15.default.pathExists(dir)) {
|
|
35331
|
+
return files;
|
|
35332
|
+
}
|
|
35333
|
+
const items = await import_fs_extra15.default.readdir(dir);
|
|
35340
35334
|
for (const item of items) {
|
|
35341
|
-
const fullPath =
|
|
35342
|
-
const stat = await
|
|
35335
|
+
const fullPath = path17.join(dir, item);
|
|
35336
|
+
const stat = await import_fs_extra15.default.stat(fullPath);
|
|
35343
35337
|
if (stat.isDirectory()) {
|
|
35344
|
-
|
|
35338
|
+
files.push(item);
|
|
35339
|
+
const subFiles = await listLocalFilesRecursive(fullPath, item);
|
|
35345
35340
|
files.push(...subFiles);
|
|
35346
35341
|
} else {
|
|
35347
|
-
files.push(
|
|
35342
|
+
files.push(item);
|
|
35348
35343
|
}
|
|
35349
35344
|
}
|
|
35350
35345
|
return files;
|
|
35351
35346
|
}
|
|
35352
|
-
async function
|
|
35353
|
-
const
|
|
35354
|
-
await
|
|
35355
|
-
|
|
35356
|
-
|
|
35357
|
-
}
|
|
35358
|
-
|
|
35359
|
-
|
|
35360
|
-
|
|
35361
|
-
|
|
35362
|
-
|
|
35363
|
-
} else
|
|
35364
|
-
|
|
35347
|
+
async function listLocalFilesRecursive(dir, basePath) {
|
|
35348
|
+
const files = [];
|
|
35349
|
+
const items = await import_fs_extra15.default.readdir(dir);
|
|
35350
|
+
for (const item of items) {
|
|
35351
|
+
const fullPath = path17.join(dir, item);
|
|
35352
|
+
const relativePath = `${basePath}/${item}`;
|
|
35353
|
+
const stat = await import_fs_extra15.default.stat(fullPath);
|
|
35354
|
+
if (stat.isDirectory()) {
|
|
35355
|
+
files.push(relativePath);
|
|
35356
|
+
const subFiles = await listLocalFilesRecursive(fullPath, relativePath);
|
|
35357
|
+
files.push(...subFiles);
|
|
35358
|
+
} else {
|
|
35359
|
+
files.push(relativePath);
|
|
35365
35360
|
}
|
|
35366
35361
|
}
|
|
35362
|
+
return files;
|
|
35367
35363
|
}
|
|
35368
|
-
async function
|
|
35364
|
+
async function analyzeCategory(category, claudeDir, githubToken) {
|
|
35369
35365
|
const items = [];
|
|
35370
|
-
const
|
|
35371
|
-
|
|
35372
|
-
|
|
35373
|
-
|
|
35374
|
-
|
|
35375
|
-
|
|
35376
|
-
|
|
35377
|
-
|
|
35378
|
-
|
|
35366
|
+
const localDir = path17.join(claudeDir, category);
|
|
35367
|
+
const remoteFiles = await listRemoteFilesRecursive(category, githubToken);
|
|
35368
|
+
const localFiles = await listLocalFiles(localDir);
|
|
35369
|
+
const remoteSet = new Map;
|
|
35370
|
+
for (const rf of remoteFiles) {
|
|
35371
|
+
remoteSet.set(rf.path, { sha: rf.sha, isFolder: rf.isFolder });
|
|
35372
|
+
}
|
|
35373
|
+
const localSet = new Set(localFiles);
|
|
35374
|
+
for (const [remotePath, { sha, isFolder }] of remoteSet) {
|
|
35375
|
+
const localPath = path17.join(localDir, remotePath);
|
|
35376
|
+
if (isFolder) {
|
|
35377
|
+
continue;
|
|
35378
|
+
}
|
|
35379
|
+
if (!localSet.has(remotePath)) {
|
|
35379
35380
|
items.push({
|
|
35380
|
-
name:
|
|
35381
|
-
relativePath:
|
|
35382
|
-
|
|
35383
|
-
|
|
35384
|
-
remoteSha: file.sha,
|
|
35385
|
-
localSha: localSha || undefined,
|
|
35386
|
-
category: "commands"
|
|
35381
|
+
name: remotePath,
|
|
35382
|
+
relativePath: `${category}/${remotePath}`,
|
|
35383
|
+
status: "new",
|
|
35384
|
+
category
|
|
35387
35385
|
});
|
|
35388
|
-
}
|
|
35389
|
-
}
|
|
35390
|
-
const agentsRemote = await listRemoteDirectory("agents", githubToken);
|
|
35391
|
-
for (const file of agentsRemote) {
|
|
35392
|
-
if (file.type === "file" && file.name.endsWith(".md")) {
|
|
35393
|
-
const localPath = path18.join(claudeDir, "agents", file.name);
|
|
35386
|
+
} else {
|
|
35394
35387
|
const localSha = await computeLocalFileSha(localPath);
|
|
35395
|
-
|
|
35396
|
-
|
|
35397
|
-
|
|
35388
|
+
if (localSha !== sha) {
|
|
35389
|
+
items.push({
|
|
35390
|
+
name: remotePath,
|
|
35391
|
+
relativePath: `${category}/${remotePath}`,
|
|
35392
|
+
status: "modified",
|
|
35393
|
+
category
|
|
35394
|
+
});
|
|
35395
|
+
} else {
|
|
35396
|
+
items.push({
|
|
35397
|
+
name: remotePath,
|
|
35398
|
+
relativePath: `${category}/${remotePath}`,
|
|
35399
|
+
status: "unchanged",
|
|
35400
|
+
category
|
|
35401
|
+
});
|
|
35398
35402
|
}
|
|
35399
|
-
items.push({
|
|
35400
|
-
name: file.name.replace(".md", ""),
|
|
35401
|
-
relativePath: `agents/${file.name}`,
|
|
35402
|
-
type: "file",
|
|
35403
|
-
status,
|
|
35404
|
-
remoteSha: file.sha,
|
|
35405
|
-
localSha: localSha || undefined,
|
|
35406
|
-
category: "agents"
|
|
35407
|
-
});
|
|
35408
35403
|
}
|
|
35409
35404
|
}
|
|
35410
|
-
const
|
|
35411
|
-
|
|
35412
|
-
|
|
35413
|
-
|
|
35414
|
-
|
|
35415
|
-
|
|
35416
|
-
|
|
35417
|
-
|
|
35418
|
-
|
|
35419
|
-
|
|
35420
|
-
|
|
35421
|
-
|
|
35422
|
-
|
|
35423
|
-
remoteSha,
|
|
35424
|
-
localSha: localSha || undefined,
|
|
35425
|
-
category: "skills"
|
|
35426
|
-
});
|
|
35405
|
+
for (const localPath of localSet) {
|
|
35406
|
+
if (!remoteSet.has(localPath)) {
|
|
35407
|
+
const fullPath = path17.join(localDir, localPath);
|
|
35408
|
+
const stat = await import_fs_extra15.default.stat(fullPath).catch(() => null);
|
|
35409
|
+
if (stat && !stat.isDirectory()) {
|
|
35410
|
+
items.push({
|
|
35411
|
+
name: localPath,
|
|
35412
|
+
relativePath: `${category}/${localPath}`,
|
|
35413
|
+
status: "deleted",
|
|
35414
|
+
category
|
|
35415
|
+
});
|
|
35416
|
+
}
|
|
35417
|
+
}
|
|
35427
35418
|
}
|
|
35428
|
-
|
|
35429
|
-
|
|
35430
|
-
|
|
35431
|
-
|
|
35432
|
-
|
|
35433
|
-
|
|
35434
|
-
|
|
35435
|
-
|
|
35436
|
-
|
|
35437
|
-
|
|
35438
|
-
|
|
35439
|
-
|
|
35440
|
-
|
|
35441
|
-
remoteSha,
|
|
35442
|
-
localSha: localSha || undefined,
|
|
35443
|
-
category: "scripts"
|
|
35444
|
-
});
|
|
35419
|
+
return items;
|
|
35420
|
+
}
|
|
35421
|
+
async function analyzeSyncChanges(claudeDir, githubToken) {
|
|
35422
|
+
const allItems = [];
|
|
35423
|
+
const categories = [
|
|
35424
|
+
"commands",
|
|
35425
|
+
"agents",
|
|
35426
|
+
"skills",
|
|
35427
|
+
"scripts"
|
|
35428
|
+
];
|
|
35429
|
+
for (const category of categories) {
|
|
35430
|
+
const items = await analyzeCategory(category, claudeDir, githubToken);
|
|
35431
|
+
allItems.push(...items);
|
|
35445
35432
|
}
|
|
35446
35433
|
return {
|
|
35447
|
-
items,
|
|
35448
|
-
newCount:
|
|
35449
|
-
modifiedCount:
|
|
35450
|
-
|
|
35434
|
+
items: allItems,
|
|
35435
|
+
newCount: allItems.filter((i) => i.status === "new").length,
|
|
35436
|
+
modifiedCount: allItems.filter((i) => i.status === "modified").length,
|
|
35437
|
+
deletedCount: allItems.filter((i) => i.status === "deleted").length,
|
|
35438
|
+
unchangedCount: allItems.filter((i) => i.status === "unchanged").length
|
|
35451
35439
|
};
|
|
35452
35440
|
}
|
|
35453
35441
|
async function downloadFromPrivateGitHub2(relativePath, targetPath, githubToken) {
|
|
@@ -35463,45 +35451,30 @@ async function downloadFromPrivateGitHub2(relativePath, targetPath, githubToken)
|
|
|
35463
35451
|
return false;
|
|
35464
35452
|
}
|
|
35465
35453
|
const content = await response.arrayBuffer();
|
|
35466
|
-
await
|
|
35467
|
-
await
|
|
35468
|
-
return true;
|
|
35469
|
-
} catch {
|
|
35470
|
-
return false;
|
|
35471
|
-
}
|
|
35472
|
-
}
|
|
35473
|
-
async function downloadDirectoryFromPrivateGitHub2(dirPath, targetDir, githubToken) {
|
|
35474
|
-
try {
|
|
35475
|
-
const files = await listRemoteDirectory(dirPath, githubToken);
|
|
35476
|
-
await import_fs_extra16.default.ensureDir(targetDir);
|
|
35477
|
-
for (const file of files) {
|
|
35478
|
-
const relativePath = `${dirPath}/${file.name}`;
|
|
35479
|
-
const targetPath = path18.join(targetDir, file.name);
|
|
35480
|
-
if (file.type === "file") {
|
|
35481
|
-
await downloadFromPrivateGitHub2(relativePath, targetPath, githubToken);
|
|
35482
|
-
} else if (file.type === "dir") {
|
|
35483
|
-
await downloadDirectoryFromPrivateGitHub2(relativePath, targetPath, githubToken);
|
|
35484
|
-
}
|
|
35485
|
-
}
|
|
35454
|
+
await import_fs_extra15.default.ensureDir(path17.dirname(targetPath));
|
|
35455
|
+
await import_fs_extra15.default.writeFile(targetPath, Buffer.from(content));
|
|
35486
35456
|
return true;
|
|
35487
35457
|
} catch {
|
|
35488
35458
|
return false;
|
|
35489
35459
|
}
|
|
35490
35460
|
}
|
|
35491
|
-
async function syncSelectedItems(claudeDir, items, githubToken) {
|
|
35461
|
+
async function syncSelectedItems(claudeDir, items, githubToken, onProgress) {
|
|
35492
35462
|
let success = 0;
|
|
35493
35463
|
let failed = 0;
|
|
35464
|
+
let deleted = 0;
|
|
35494
35465
|
for (const item of items) {
|
|
35495
|
-
const targetPath =
|
|
35496
|
-
if (item.
|
|
35497
|
-
|
|
35498
|
-
|
|
35499
|
-
|
|
35500
|
-
|
|
35466
|
+
const targetPath = path17.join(claudeDir, item.relativePath);
|
|
35467
|
+
if (item.status === "deleted") {
|
|
35468
|
+
onProgress?.(item.relativePath, "deleting");
|
|
35469
|
+
try {
|
|
35470
|
+
await import_fs_extra15.default.remove(targetPath);
|
|
35471
|
+
deleted++;
|
|
35472
|
+
} catch {
|
|
35501
35473
|
failed++;
|
|
35502
35474
|
}
|
|
35503
35475
|
} else {
|
|
35504
|
-
|
|
35476
|
+
onProgress?.(item.relativePath, item.status === "new" ? "adding" : "updating");
|
|
35477
|
+
const ok = await downloadFromPrivateGitHub2(item.relativePath, targetPath, githubToken);
|
|
35505
35478
|
if (ok) {
|
|
35506
35479
|
success++;
|
|
35507
35480
|
} else {
|
|
@@ -35509,10 +35482,34 @@ async function syncSelectedItems(claudeDir, items, githubToken) {
|
|
|
35509
35482
|
}
|
|
35510
35483
|
}
|
|
35511
35484
|
}
|
|
35512
|
-
return { success, failed };
|
|
35485
|
+
return { success, failed, deleted };
|
|
35513
35486
|
}
|
|
35514
35487
|
|
|
35515
35488
|
// src/commands/sync.ts
|
|
35489
|
+
function formatItem(item) {
|
|
35490
|
+
const icons = {
|
|
35491
|
+
new: "\uD83C\uDD95",
|
|
35492
|
+
modified: "\uD83D\uDCDD",
|
|
35493
|
+
deleted: "\uD83D\uDDD1️",
|
|
35494
|
+
unchanged: "✅"
|
|
35495
|
+
};
|
|
35496
|
+
const colors12 = {
|
|
35497
|
+
new: source_default.green,
|
|
35498
|
+
modified: source_default.yellow,
|
|
35499
|
+
deleted: source_default.red,
|
|
35500
|
+
unchanged: source_default.gray
|
|
35501
|
+
};
|
|
35502
|
+
return `${icons[item.status]} ${colors12[item.status](item.relativePath)}`;
|
|
35503
|
+
}
|
|
35504
|
+
function groupByCategory(items) {
|
|
35505
|
+
const grouped = new Map;
|
|
35506
|
+
for (const item of items) {
|
|
35507
|
+
const existing = grouped.get(item.category) || [];
|
|
35508
|
+
existing.push(item);
|
|
35509
|
+
grouped.set(item.category, existing);
|
|
35510
|
+
}
|
|
35511
|
+
return grouped;
|
|
35512
|
+
}
|
|
35516
35513
|
async function proSyncCommand(options = {}) {
|
|
35517
35514
|
oe(source_default.blue("\uD83D\uDD04 Sync Premium Configurations"));
|
|
35518
35515
|
try {
|
|
@@ -35523,37 +35520,38 @@ async function proSyncCommand(options = {}) {
|
|
|
35523
35520
|
$e(source_default.red("❌ Not activated"));
|
|
35524
35521
|
process.exit(1);
|
|
35525
35522
|
}
|
|
35526
|
-
const claudeDir = options.folder ?
|
|
35523
|
+
const claudeDir = options.folder ? path18.resolve(options.folder) : path18.join(os11.homedir(), ".claude");
|
|
35527
35524
|
const spinner = de();
|
|
35528
35525
|
spinner.start("Analyzing changes...");
|
|
35529
35526
|
const result = await analyzeSyncChanges(claudeDir, githubToken);
|
|
35530
35527
|
spinner.stop("Analysis complete");
|
|
35531
|
-
|
|
35528
|
+
const changedItems = result.items.filter((i) => i.status !== "unchanged");
|
|
35529
|
+
if (changedItems.length === 0) {
|
|
35532
35530
|
f2.success("Everything is up to date!");
|
|
35533
35531
|
$e(source_default.green("✅ No changes needed"));
|
|
35534
35532
|
return;
|
|
35535
35533
|
}
|
|
35536
|
-
f2.info(`Found ${result.newCount} new, ${result.modifiedCount} modified, ${result.unchangedCount} unchanged`);
|
|
35537
|
-
|
|
35538
|
-
|
|
35539
|
-
const
|
|
35540
|
-
|
|
35541
|
-
|
|
35542
|
-
|
|
35543
|
-
|
|
35544
|
-
|
|
35545
|
-
hint: `${item.category} (new ${item.type})`
|
|
35546
|
-
});
|
|
35534
|
+
f2.info(`Found: ${source_default.green(`${result.newCount} new`)}, ${source_default.yellow(`${result.modifiedCount} modified`)}, ${source_default.red(`${result.deletedCount} to remove`)}, ${source_default.gray(`${result.unchangedCount} unchanged`)}`);
|
|
35535
|
+
f2.message("");
|
|
35536
|
+
f2.message(source_default.bold("Changes by category:"));
|
|
35537
|
+
const grouped = groupByCategory(changedItems);
|
|
35538
|
+
for (const [category, items] of grouped) {
|
|
35539
|
+
f2.message("");
|
|
35540
|
+
f2.message(source_default.cyan.bold(` ${category.toUpperCase()}`));
|
|
35541
|
+
for (const item of items) {
|
|
35542
|
+
f2.message(` ${formatItem(item)}`);
|
|
35547
35543
|
}
|
|
35548
35544
|
}
|
|
35549
|
-
|
|
35550
|
-
|
|
35551
|
-
|
|
35552
|
-
|
|
35553
|
-
|
|
35554
|
-
|
|
35555
|
-
|
|
35556
|
-
|
|
35545
|
+
f2.message("");
|
|
35546
|
+
const choices = [];
|
|
35547
|
+
for (const item of changedItems) {
|
|
35548
|
+
const icons = { new: "\uD83C\uDD95", modified: "\uD83D\uDCDD", deleted: "\uD83D\uDDD1️", unchanged: "" };
|
|
35549
|
+
const actions = { new: "add", modified: "update", deleted: "remove", unchanged: "" };
|
|
35550
|
+
choices.push({
|
|
35551
|
+
value: item,
|
|
35552
|
+
label: `${icons[item.status]} ${item.relativePath}`,
|
|
35553
|
+
hint: actions[item.status]
|
|
35554
|
+
});
|
|
35557
35555
|
}
|
|
35558
35556
|
const selected = await ae({
|
|
35559
35557
|
message: "Select items to sync:",
|
|
@@ -35571,38 +35569,41 @@ async function proSyncCommand(options = {}) {
|
|
|
35571
35569
|
$e(source_default.yellow("⚠️ Nothing to sync"));
|
|
35572
35570
|
return;
|
|
35573
35571
|
}
|
|
35572
|
+
const toAdd = selectedItems.filter((i) => i.status === "new").length;
|
|
35573
|
+
const toUpdate = selectedItems.filter((i) => i.status === "modified").length;
|
|
35574
|
+
const toRemove = selectedItems.filter((i) => i.status === "deleted").length;
|
|
35575
|
+
const summary = [
|
|
35576
|
+
toAdd > 0 ? `add ${toAdd}` : "",
|
|
35577
|
+
toUpdate > 0 ? `update ${toUpdate}` : "",
|
|
35578
|
+
toRemove > 0 ? `remove ${toRemove}` : ""
|
|
35579
|
+
].filter(Boolean).join(", ");
|
|
35574
35580
|
const confirmResult = await se({
|
|
35575
|
-
message: `
|
|
35581
|
+
message: `Proceed? (${summary})`,
|
|
35576
35582
|
initialValue: true
|
|
35577
35583
|
});
|
|
35578
35584
|
if (lD(confirmResult) || !confirmResult) {
|
|
35579
35585
|
ue("Sync cancelled");
|
|
35580
35586
|
process.exit(0);
|
|
35581
35587
|
}
|
|
35582
|
-
spinner.start(
|
|
35583
|
-
const syncResult = await syncSelectedItems(claudeDir, selectedItems, githubToken)
|
|
35588
|
+
spinner.start("Syncing...");
|
|
35589
|
+
const syncResult = await syncSelectedItems(claudeDir, selectedItems, githubToken, (file, action) => {
|
|
35590
|
+
spinner.message(`${action}: ${source_default.cyan(file)}`);
|
|
35591
|
+
});
|
|
35584
35592
|
spinner.stop("Sync complete");
|
|
35585
|
-
|
|
35586
|
-
|
|
35587
|
-
|
|
35588
|
-
|
|
35593
|
+
const results = [];
|
|
35594
|
+
if (syncResult.success > 0)
|
|
35595
|
+
results.push(source_default.green(`${syncResult.success} added/updated`));
|
|
35596
|
+
if (syncResult.deleted > 0)
|
|
35597
|
+
results.push(source_default.red(`${syncResult.deleted} removed`));
|
|
35598
|
+
if (syncResult.failed > 0)
|
|
35599
|
+
results.push(source_default.yellow(`${syncResult.failed} failed`));
|
|
35600
|
+
f2.success(results.join(", "));
|
|
35601
|
+
const scriptsWereSynced = selectedItems.some((i) => i.category === "scripts");
|
|
35602
|
+
if (scriptsWereSynced) {
|
|
35603
|
+
spinner.start("Installing scripts dependencies...");
|
|
35604
|
+
await installScriptsDependencies(claudeDir);
|
|
35605
|
+
spinner.stop("Scripts dependencies installed");
|
|
35589
35606
|
}
|
|
35590
|
-
const syncedByCategory = {
|
|
35591
|
-
commands: selectedItems.filter((i) => i.category === "commands").length,
|
|
35592
|
-
agents: selectedItems.filter((i) => i.category === "agents").length,
|
|
35593
|
-
skills: selectedItems.filter((i) => i.category === "skills").length,
|
|
35594
|
-
scripts: selectedItems.filter((i) => i.category === "scripts").length
|
|
35595
|
-
};
|
|
35596
|
-
const summary = [];
|
|
35597
|
-
if (syncedByCategory.commands > 0)
|
|
35598
|
-
summary.push(`${syncedByCategory.commands} command(s)`);
|
|
35599
|
-
if (syncedByCategory.agents > 0)
|
|
35600
|
-
summary.push(`${syncedByCategory.agents} agent(s)`);
|
|
35601
|
-
if (syncedByCategory.skills > 0)
|
|
35602
|
-
summary.push("skills folder");
|
|
35603
|
-
if (syncedByCategory.scripts > 0)
|
|
35604
|
-
summary.push("scripts folder");
|
|
35605
|
-
f2.info(`Synced: ${summary.join(", ")}`);
|
|
35606
35607
|
$e(source_default.green("✅ Sync completed"));
|
|
35607
35608
|
} catch (error) {
|
|
35608
35609
|
if (error instanceof Error) {
|