@claudeskill/cli 0.1.0
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/api.d.ts +148 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +218 -0
- package/dist/api.js.map +1 -0
- package/dist/commands/checkout.d.ts +8 -0
- package/dist/commands/checkout.d.ts.map +1 -0
- package/dist/commands/checkout.js +134 -0
- package/dist/commands/checkout.js.map +1 -0
- package/dist/commands/diff.d.ts +8 -0
- package/dist/commands/diff.d.ts.map +1 -0
- package/dist/commands/diff.js +156 -0
- package/dist/commands/diff.js.map +1 -0
- package/dist/commands/list.d.ts +14 -0
- package/dist/commands/list.d.ts.map +1 -0
- package/dist/commands/list.js +251 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/commands/log.d.ts +8 -0
- package/dist/commands/log.d.ts.map +1 -0
- package/dist/commands/log.js +74 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/commands/login.d.ts +8 -0
- package/dist/commands/login.d.ts.map +1 -0
- package/dist/commands/login.js +201 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.d.ts +8 -0
- package/dist/commands/logout.d.ts.map +1 -0
- package/dist/commands/logout.js +33 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/pull.d.ts +11 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +123 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.d.ts +12 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +128 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/status.d.ts +8 -0
- package/dist/commands/status.d.ts.map +1 -0
- package/dist/commands/status.js +104 -0
- package/dist/commands/status.js.map +1 -0
- package/dist/config.d.ts +25 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +54 -0
- package/dist/config.js.map +1 -0
- package/dist/credentials.d.ts +24 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +54 -0
- package/dist/credentials.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +166 -0
- package/dist/index.js.map +1 -0
- package/dist/menu.d.ts +8 -0
- package/dist/menu.d.ts.map +1 -0
- package/dist/menu.js +130 -0
- package/dist/menu.js.map +1 -0
- package/dist/onboarding.d.ts +8 -0
- package/dist/onboarding.d.ts.map +1 -0
- package/dist/onboarding.js +252 -0
- package/dist/onboarding.js.map +1 -0
- package/dist/sync.d.ts +83 -0
- package/dist/sync.d.ts.map +1 -0
- package/dist/sync.js +294 -0
- package/dist/sync.js.map +1 -0
- package/package.json +47 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Login command - authenticate with server
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import { generateSalt, generateMasterKey, generateRecoveryKey, deriveKeyFromPassphrase, encryptMasterKey, formatRecoveryKey, toBase64, } from "@claudeskill/core";
|
|
6
|
+
import { loadConfig } from "../config.js";
|
|
7
|
+
import { saveCredentials, loadCredentials } from "../credentials.js";
|
|
8
|
+
import * as api from "../api.js";
|
|
9
|
+
/**
|
|
10
|
+
* Run the login command
|
|
11
|
+
*/
|
|
12
|
+
export const runLogin = async () => {
|
|
13
|
+
const config = await loadConfig();
|
|
14
|
+
if (!config) {
|
|
15
|
+
p.log.error("Not configured. Run 'claude-skill-sync' first to set up.");
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (config.mode === "local") {
|
|
19
|
+
p.log.error("Cannot login in local-only mode.");
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
p.intro("Login to Claude Skill Sync");
|
|
23
|
+
// Check server health
|
|
24
|
+
const healthResult = await api.checkHealth();
|
|
25
|
+
if (!healthResult.ok) {
|
|
26
|
+
p.log.error(`Cannot connect to server: ${healthResult.error}`);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
// Get email
|
|
30
|
+
const email = await p.text({
|
|
31
|
+
message: "Email:",
|
|
32
|
+
placeholder: config.email ?? "you@example.com",
|
|
33
|
+
initialValue: config.email ?? undefined,
|
|
34
|
+
validate: (value) => {
|
|
35
|
+
if (!value)
|
|
36
|
+
return "Email is required";
|
|
37
|
+
if (!value.includes("@"))
|
|
38
|
+
return "Invalid email";
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
if (p.isCancel(email)) {
|
|
42
|
+
p.cancel("Login cancelled.");
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Request OTP
|
|
46
|
+
const spinner = p.spinner();
|
|
47
|
+
spinner.start("Sending verification code...");
|
|
48
|
+
const otpResult = await api.requestOtp(email);
|
|
49
|
+
if (!otpResult.ok) {
|
|
50
|
+
spinner.stop("Failed to send code");
|
|
51
|
+
p.log.error(otpResult.error);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
spinner.stop("Verification code sent!");
|
|
55
|
+
// Get OTP code
|
|
56
|
+
const code = await p.text({
|
|
57
|
+
message: "Enter the 6-digit code from your email:",
|
|
58
|
+
validate: (value) => {
|
|
59
|
+
if (!value)
|
|
60
|
+
return "Code is required";
|
|
61
|
+
if (!/^\d{6}$/.test(value))
|
|
62
|
+
return "Code must be 6 digits";
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
if (p.isCancel(code)) {
|
|
66
|
+
p.cancel("Login cancelled.");
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Verify OTP
|
|
70
|
+
spinner.start("Verifying...");
|
|
71
|
+
const verifyResult = await api.verifyOtp(email, code);
|
|
72
|
+
if (!verifyResult.ok) {
|
|
73
|
+
spinner.stop("Verification failed");
|
|
74
|
+
p.log.error(verifyResult.error);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
spinner.stop("Verified!");
|
|
78
|
+
const { accessToken, refreshToken, user } = verifyResult.data;
|
|
79
|
+
// Check if this is a new user or existing
|
|
80
|
+
if (user.isNewUser) {
|
|
81
|
+
// New user - need to set up encryption
|
|
82
|
+
p.log.info("Setting up encryption for your account...");
|
|
83
|
+
const passphrase = await p.password({
|
|
84
|
+
message: "Create a vault passphrase:",
|
|
85
|
+
mask: "*",
|
|
86
|
+
validate: (value) => {
|
|
87
|
+
if (!value)
|
|
88
|
+
return "Passphrase is required";
|
|
89
|
+
if (value.length < 8)
|
|
90
|
+
return "Passphrase must be at least 8 characters";
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
if (p.isCancel(passphrase)) {
|
|
94
|
+
p.cancel("Login cancelled.");
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const confirmPassphrase = await p.password({
|
|
98
|
+
message: "Confirm passphrase:",
|
|
99
|
+
mask: "*",
|
|
100
|
+
validate: (value) => {
|
|
101
|
+
if (value !== passphrase)
|
|
102
|
+
return "Passphrases do not match";
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
if (p.isCancel(confirmPassphrase)) {
|
|
106
|
+
p.cancel("Login cancelled.");
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// Generate keys
|
|
110
|
+
spinner.start("Generating encryption keys...");
|
|
111
|
+
const salt = generateSalt();
|
|
112
|
+
const masterKey = generateMasterKey();
|
|
113
|
+
const recoveryKey = generateRecoveryKey();
|
|
114
|
+
const derivedKey = deriveKeyFromPassphrase(passphrase, salt);
|
|
115
|
+
const encryptedMaster = encryptMasterKey(masterKey, derivedKey.key);
|
|
116
|
+
// Combine IV + tag + ciphertext for storage
|
|
117
|
+
const encryptedMasterKeyFull = new Uint8Array(encryptedMaster.iv.length +
|
|
118
|
+
encryptedMaster.tag.length +
|
|
119
|
+
encryptedMaster.encrypted.length);
|
|
120
|
+
encryptedMasterKeyFull.set(encryptedMaster.iv, 0);
|
|
121
|
+
encryptedMasterKeyFull.set(encryptedMaster.tag, encryptedMaster.iv.length);
|
|
122
|
+
encryptedMasterKeyFull.set(encryptedMaster.encrypted, encryptedMaster.iv.length + encryptedMaster.tag.length);
|
|
123
|
+
// Save credentials first so API calls work
|
|
124
|
+
await saveCredentials({
|
|
125
|
+
accessToken,
|
|
126
|
+
refreshToken,
|
|
127
|
+
encryptedMasterKey: toBase64(encryptedMasterKeyFull),
|
|
128
|
+
salt: toBase64(salt),
|
|
129
|
+
});
|
|
130
|
+
// Upload salt to server
|
|
131
|
+
const saltResult = await api.setSalt(toBase64(salt));
|
|
132
|
+
if (!saltResult.ok) {
|
|
133
|
+
spinner.stop("Failed to save encryption settings");
|
|
134
|
+
p.log.error(saltResult.error);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
// Upload encrypted master key to server (for web dashboard decryption)
|
|
138
|
+
const masterKeyResult = await api.setMasterKey(toBase64(encryptedMasterKeyFull));
|
|
139
|
+
if (!masterKeyResult.ok) {
|
|
140
|
+
// Non-fatal - dashboard decryption won't work but CLI will
|
|
141
|
+
p.log.warn("Could not sync master key for web dashboard");
|
|
142
|
+
}
|
|
143
|
+
spinner.stop("Encryption configured!");
|
|
144
|
+
// Show recovery key
|
|
145
|
+
const formattedRecoveryKey = formatRecoveryKey(recoveryKey);
|
|
146
|
+
p.note(`
|
|
147
|
+
${formattedRecoveryKey}
|
|
148
|
+
|
|
149
|
+
This is the ONLY way to recover your skills if you
|
|
150
|
+
forget your passphrase. Store it somewhere safe.
|
|
151
|
+
`.trim(), "SAVE YOUR RECOVERY KEY");
|
|
152
|
+
const saved = await p.confirm({
|
|
153
|
+
message: "I have saved my recovery key",
|
|
154
|
+
});
|
|
155
|
+
if (p.isCancel(saved) || !saved) {
|
|
156
|
+
p.note(formattedRecoveryKey, "RECOVERY KEY (showing again)");
|
|
157
|
+
await p.confirm({ message: "I have saved my recovery key" });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// Existing user - need to get salt and decrypt master key
|
|
162
|
+
p.log.info("Welcome back! Enter your passphrase to unlock.");
|
|
163
|
+
// Get salt from server
|
|
164
|
+
const saltResult = await api.getSalt();
|
|
165
|
+
if (!saltResult.ok) {
|
|
166
|
+
p.log.error(`Failed to get encryption settings: ${saltResult.error}`);
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
const passphrase = await p.password({
|
|
170
|
+
message: "Vault passphrase:",
|
|
171
|
+
mask: "*",
|
|
172
|
+
});
|
|
173
|
+
if (p.isCancel(passphrase)) {
|
|
174
|
+
p.cancel("Login cancelled.");
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
// For existing users, we need to verify the passphrase
|
|
178
|
+
// by trying to decrypt something or asking them to re-enter
|
|
179
|
+
// For now, just save the credentials
|
|
180
|
+
const existingCreds = await loadCredentials();
|
|
181
|
+
// Try to get master key from server, fall back to local
|
|
182
|
+
let encryptedMasterKey = existingCreds?.encryptedMasterKey ?? "";
|
|
183
|
+
const masterKeyResult = await api.getMasterKey();
|
|
184
|
+
if (masterKeyResult.ok && masterKeyResult.data.encryptedMasterKey) {
|
|
185
|
+
encryptedMasterKey = masterKeyResult.data.encryptedMasterKey;
|
|
186
|
+
}
|
|
187
|
+
else if (existingCreds?.encryptedMasterKey) {
|
|
188
|
+
// Sync local master key to server for web dashboard
|
|
189
|
+
await api.setMasterKey(existingCreds.encryptedMasterKey);
|
|
190
|
+
}
|
|
191
|
+
await saveCredentials({
|
|
192
|
+
accessToken,
|
|
193
|
+
refreshToken,
|
|
194
|
+
encryptedMasterKey,
|
|
195
|
+
salt: saltResult.data.salt,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
p.log.success("Logged in successfully!");
|
|
199
|
+
p.outro(`Logged in as ${email}`);
|
|
200
|
+
};
|
|
201
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH;;GAEG;AACH,eAAO,MAAM,SAAS,qBA8BrB,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Logout command - clear local credentials
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import { deleteCredentials, loadCredentials } from "../credentials.js";
|
|
6
|
+
import * as api from "../api.js";
|
|
7
|
+
/**
|
|
8
|
+
* Run the logout command
|
|
9
|
+
*/
|
|
10
|
+
export const runLogout = async () => {
|
|
11
|
+
const credentials = await loadCredentials();
|
|
12
|
+
if (!credentials?.accessToken) {
|
|
13
|
+
p.log.info("Not logged in.");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const confirm = await p.confirm({
|
|
17
|
+
message: "Are you sure you want to logout?",
|
|
18
|
+
});
|
|
19
|
+
if (p.isCancel(confirm) || !confirm) {
|
|
20
|
+
p.cancel("Logout cancelled.");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const spinner = p.spinner();
|
|
24
|
+
spinner.start("Logging out...");
|
|
25
|
+
// Invalidate server session
|
|
26
|
+
await api.logout();
|
|
27
|
+
// Delete local credentials
|
|
28
|
+
await deleteCredentials();
|
|
29
|
+
spinner.stop("Logged out");
|
|
30
|
+
p.log.success("Successfully logged out.");
|
|
31
|
+
p.log.info("Your encrypted skills remain on the server. Login again to access them.");
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,CAAC,MAAM,gBAAgB,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,KAAK,GAAG,MAAM,WAAW,CAAC;AAEjC;;GAEG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,IAAI,EAAE;IAClC,MAAM,WAAW,GAAG,MAAM,eAAe,EAAE,CAAC;IAE5C,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,CAAC;QAC9B,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC7B,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC;QAC9B,OAAO,EAAE,kCAAkC;KAC5C,CAAC,CAAC;IAEH,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACpC,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC;QAC9B,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAC5B,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IAEhC,4BAA4B;IAC5B,MAAM,GAAG,CAAC,MAAM,EAAE,CAAC;IAEnB,2BAA2B;IAC3B,MAAM,iBAAiB,EAAE,CAAC;IAE1B,OAAO,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAE3B,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC;IAC1C,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,yEAAyE,CAAC,CAAC;AACxF,CAAC,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pull command - download remote skills to local
|
|
3
|
+
*/
|
|
4
|
+
export type PullOptions = Partial<{
|
|
5
|
+
interactive: boolean;
|
|
6
|
+
}>;
|
|
7
|
+
/**
|
|
8
|
+
* Run the pull command
|
|
9
|
+
*/
|
|
10
|
+
export declare const runPull: (options?: PullOptions) => Promise<void>;
|
|
11
|
+
//# sourceMappingURL=pull.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC;IAChC,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,OAAO,GAAU,UAAS,WAAgB,kBAsItD,CAAC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pull command - download remote skills to local
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import { listAllSkills, getSkillKey, } from "@claudeskill/core";
|
|
6
|
+
import { loadConfig } from "../config.js";
|
|
7
|
+
import { loadCredentials } from "../credentials.js";
|
|
8
|
+
import { getMasterKey, pullSkills, loadSyncIndex } from "../sync.js";
|
|
9
|
+
import * as api from "../api.js";
|
|
10
|
+
/**
|
|
11
|
+
* Run the pull command
|
|
12
|
+
*/
|
|
13
|
+
export const runPull = async (options = {}) => {
|
|
14
|
+
const config = await loadConfig();
|
|
15
|
+
if (!config) {
|
|
16
|
+
p.log.error("Not configured. Run 'claude-skill-sync' first to set up.");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (config.mode === "local") {
|
|
20
|
+
p.log.error("Cannot pull in local-only mode. Change mode with 'claude-skill-sync config'.");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const credentials = await loadCredentials();
|
|
24
|
+
if (!credentials?.accessToken) {
|
|
25
|
+
p.log.error("Not logged in. Run 'claude-skill-sync login' first.");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// Check server connection
|
|
29
|
+
const healthResult = await api.checkHealth();
|
|
30
|
+
if (!healthResult.ok) {
|
|
31
|
+
p.log.error(`Cannot connect to server: ${healthResult.error}`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// In interactive mode, show preview of what will be pulled
|
|
35
|
+
if (options.interactive) {
|
|
36
|
+
const spinner = p.spinner();
|
|
37
|
+
spinner.start("Checking for updates...");
|
|
38
|
+
const skills = await listAllSkills();
|
|
39
|
+
const index = await loadSyncIndex();
|
|
40
|
+
const localSkillKeys = new Set(skills.map((s) => getSkillKey(s)));
|
|
41
|
+
// Get remote skills list
|
|
42
|
+
const listResult = await api.listSkills();
|
|
43
|
+
if (!listResult.ok) {
|
|
44
|
+
spinner.stop("Failed to check updates");
|
|
45
|
+
p.log.error(`Cannot list remote skills: ${listResult.error}`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const changes = listResult.data.skills
|
|
49
|
+
.filter((remoteSkill) => remoteSkill.currentHash)
|
|
50
|
+
.map((remoteSkill) => {
|
|
51
|
+
const existing = index.skills[remoteSkill.skillKey];
|
|
52
|
+
if (!localSkillKeys.has(remoteSkill.skillKey)) {
|
|
53
|
+
return { skillKey: remoteSkill.skillKey, status: "new" };
|
|
54
|
+
}
|
|
55
|
+
if (existing?.hash !== remoteSkill.currentHash) {
|
|
56
|
+
return { skillKey: remoteSkill.skillKey, status: "updated" };
|
|
57
|
+
}
|
|
58
|
+
return null;
|
|
59
|
+
})
|
|
60
|
+
.filter((change) => change !== null);
|
|
61
|
+
spinner.stop("Updates checked");
|
|
62
|
+
if (changes.length === 0) {
|
|
63
|
+
p.log.info("No updates to pull. Everything is up to date.");
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
// Show preview
|
|
67
|
+
console.log("");
|
|
68
|
+
console.log("Updates to pull:");
|
|
69
|
+
changes.forEach((change) => {
|
|
70
|
+
const icon = change.status === "new" ? "+" : "~";
|
|
71
|
+
const label = change.status === "new" ? "new" : "updated";
|
|
72
|
+
console.log(` ${icon} ${change.skillKey} (${label})`);
|
|
73
|
+
});
|
|
74
|
+
console.log("");
|
|
75
|
+
// Confirm
|
|
76
|
+
const confirm = await p.confirm({
|
|
77
|
+
message: `Pull ${changes.length} item${changes.length === 1 ? "" : "s"}?`,
|
|
78
|
+
});
|
|
79
|
+
if (p.isCancel(confirm) || !confirm) {
|
|
80
|
+
p.cancel("Pull cancelled.");
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Get passphrase to unlock vault
|
|
85
|
+
const passphrase = await p.password({
|
|
86
|
+
message: "Vault passphrase:",
|
|
87
|
+
mask: "*",
|
|
88
|
+
});
|
|
89
|
+
if (p.isCancel(passphrase)) {
|
|
90
|
+
p.cancel("Pull cancelled.");
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
// Get master key
|
|
94
|
+
const spinner = p.spinner();
|
|
95
|
+
spinner.start("Unlocking vault...");
|
|
96
|
+
const masterKey = await getMasterKey(passphrase);
|
|
97
|
+
if (!masterKey) {
|
|
98
|
+
spinner.stop("Failed to unlock vault");
|
|
99
|
+
p.log.error("Invalid passphrase or corrupted credentials.");
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
spinner.stop("Vault unlocked");
|
|
103
|
+
// Pull skills
|
|
104
|
+
spinner.start("Pulling skills...");
|
|
105
|
+
const { pulled, errors } = await pullSkills(masterKey, (msg) => {
|
|
106
|
+
spinner.message(msg);
|
|
107
|
+
});
|
|
108
|
+
spinner.stop("Pull complete");
|
|
109
|
+
// Report results
|
|
110
|
+
if (pulled > 0) {
|
|
111
|
+
p.log.success(`Pulled ${pulled} skill${pulled === 1 ? "" : "s"}`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
p.log.info("No new skills to pull");
|
|
115
|
+
}
|
|
116
|
+
if (errors.length > 0) {
|
|
117
|
+
p.log.warning("Some skills failed to pull:");
|
|
118
|
+
errors.forEach((error) => {
|
|
119
|
+
p.log.error(` ${error}`);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
//# sourceMappingURL=pull.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Push command - upload local skills to server
|
|
3
|
+
*/
|
|
4
|
+
export type PushOptions = Partial<{
|
|
5
|
+
message: string;
|
|
6
|
+
interactive: boolean;
|
|
7
|
+
}>;
|
|
8
|
+
/**
|
|
9
|
+
* Run the push command
|
|
10
|
+
*/
|
|
11
|
+
export declare const runPush: (options?: PushOptions) => Promise<void>;
|
|
12
|
+
//# sourceMappingURL=push.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AAAA;;GAEG;AAcH,MAAM,MAAM,WAAW,GAAG,OAAO,CAAC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,OAAO,CAAC;CACtB,CAAC,CAAC;AAEH;;GAEG;AACH,eAAO,MAAM,OAAO,GAAU,UAAS,WAAgB,kBA6ItD,CAAC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Push command - upload local skills to server
|
|
3
|
+
*/
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import { listAllSkills, computeSkillHash, getSkillKey, } from "@claudeskill/core";
|
|
6
|
+
import { loadConfig } from "../config.js";
|
|
7
|
+
import { loadCredentials } from "../credentials.js";
|
|
8
|
+
import { getMasterKey, pushSkills, loadSyncIndex } from "../sync.js";
|
|
9
|
+
import * as api from "../api.js";
|
|
10
|
+
/**
|
|
11
|
+
* Run the push command
|
|
12
|
+
*/
|
|
13
|
+
export const runPush = async (options = {}) => {
|
|
14
|
+
const config = await loadConfig();
|
|
15
|
+
if (!config) {
|
|
16
|
+
p.log.error("Not configured. Run 'claude-skill-sync' first to set up.");
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (config.mode === "local") {
|
|
20
|
+
p.log.error("Cannot push in local-only mode. Change mode with 'claude-skill-sync config'.");
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
const credentials = await loadCredentials();
|
|
24
|
+
if (!credentials?.accessToken) {
|
|
25
|
+
p.log.error("Not logged in. Run 'claude-skill-sync login' first.");
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
// Check server connection
|
|
29
|
+
const healthResult = await api.checkHealth();
|
|
30
|
+
if (!healthResult.ok) {
|
|
31
|
+
p.log.error(`Cannot connect to server: ${healthResult.error}`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
// In interactive mode, show preview of what will be pushed
|
|
35
|
+
if (options.interactive) {
|
|
36
|
+
const spinner = p.spinner();
|
|
37
|
+
spinner.start("Checking for changes...");
|
|
38
|
+
const skills = await listAllSkills();
|
|
39
|
+
const index = await loadSyncIndex();
|
|
40
|
+
const changes = skills
|
|
41
|
+
.map((skill) => {
|
|
42
|
+
const skillKey = getSkillKey(skill);
|
|
43
|
+
const contentHash = computeSkillHash(skill);
|
|
44
|
+
const existing = index.skills[skillKey];
|
|
45
|
+
if (!existing) {
|
|
46
|
+
return { name: skill.name, type: skill.type, status: "new" };
|
|
47
|
+
}
|
|
48
|
+
if (existing.hash !== contentHash) {
|
|
49
|
+
return { name: skill.name, type: skill.type, status: "modified" };
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
})
|
|
53
|
+
.filter((change) => change !== null);
|
|
54
|
+
spinner.stop("Changes detected");
|
|
55
|
+
if (changes.length === 0) {
|
|
56
|
+
p.log.info("No changes to push. Everything is up to date.");
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
// Show preview
|
|
60
|
+
console.log("");
|
|
61
|
+
console.log("Changes to push:");
|
|
62
|
+
changes.forEach((change) => {
|
|
63
|
+
const icon = change.status === "new" ? "+" : "~";
|
|
64
|
+
const label = change.status === "new" ? "new" : "modified";
|
|
65
|
+
console.log(` ${icon} ${change.type}/${change.name} (${label})`);
|
|
66
|
+
});
|
|
67
|
+
console.log("");
|
|
68
|
+
// Confirm
|
|
69
|
+
const confirm = await p.confirm({
|
|
70
|
+
message: `Push ${changes.length} item${changes.length === 1 ? "" : "s"}?`,
|
|
71
|
+
});
|
|
72
|
+
if (p.isCancel(confirm) || !confirm) {
|
|
73
|
+
p.cancel("Push cancelled.");
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// Ask for commit message
|
|
77
|
+
const commitMessage = await p.text({
|
|
78
|
+
message: "Commit message (optional):",
|
|
79
|
+
placeholder: "Describe your changes...",
|
|
80
|
+
});
|
|
81
|
+
if (p.isCancel(commitMessage)) {
|
|
82
|
+
p.cancel("Push cancelled.");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
if (commitMessage) {
|
|
86
|
+
options.message = commitMessage;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Get passphrase to unlock vault
|
|
90
|
+
const passphrase = await p.password({
|
|
91
|
+
message: "Vault passphrase:",
|
|
92
|
+
mask: "*",
|
|
93
|
+
});
|
|
94
|
+
if (p.isCancel(passphrase)) {
|
|
95
|
+
p.cancel("Push cancelled.");
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// Get master key
|
|
99
|
+
const spinner = p.spinner();
|
|
100
|
+
spinner.start("Unlocking vault...");
|
|
101
|
+
const masterKey = await getMasterKey(passphrase);
|
|
102
|
+
if (!masterKey) {
|
|
103
|
+
spinner.stop("Failed to unlock vault");
|
|
104
|
+
p.log.error("Invalid passphrase or corrupted credentials.");
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
spinner.stop("Vault unlocked");
|
|
108
|
+
// Push skills
|
|
109
|
+
spinner.start("Pushing skills...");
|
|
110
|
+
const { pushed, errors } = await pushSkills(masterKey, (msg) => {
|
|
111
|
+
spinner.message(msg);
|
|
112
|
+
}, options.message);
|
|
113
|
+
spinner.stop("Push complete");
|
|
114
|
+
// Report results
|
|
115
|
+
if (pushed > 0) {
|
|
116
|
+
p.log.success(`Pushed ${pushed} skill${pushed === 1 ? "" : "s"}`);
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
p.log.info("No changes to push");
|
|
120
|
+
}
|
|
121
|
+
if (errors.length > 0) {
|
|
122
|
+
p.log.warning("Some skills failed to push:");
|
|
123
|
+
errors.forEach((error) => {
|
|
124
|
+
p.log.error(` ${error}`);
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
//# sourceMappingURL=push.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0BH;;GAEG;AACH,eAAO,MAAM,SAAS,qBA8ErB,CAAC"}
|