claudekit-cli 2.6.0 → 3.0.1
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 +327 -506
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5052,9 +5052,6 @@ var init_types2 = __esm(() => {
|
|
|
5052
5052
|
files: exports_external.array(TrackedFileSchema).optional()
|
|
5053
5053
|
});
|
|
5054
5054
|
ConfigSchema = exports_external.object({
|
|
5055
|
-
github: exports_external.object({
|
|
5056
|
-
token: exports_external.string().optional()
|
|
5057
|
-
}).optional(),
|
|
5058
5055
|
defaults: exports_external.object({
|
|
5059
5056
|
kit: KitType.optional(),
|
|
5060
5057
|
dir: exports_external.string().optional()
|
|
@@ -5425,7 +5422,7 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
5425
5422
|
var constants = __require("constants");
|
|
5426
5423
|
var origCwd = process.cwd;
|
|
5427
5424
|
var cwd = null;
|
|
5428
|
-
var
|
|
5425
|
+
var platform2 = process.env.GRACEFUL_FS_PLATFORM || process.platform;
|
|
5429
5426
|
process.cwd = function() {
|
|
5430
5427
|
if (!cwd)
|
|
5431
5428
|
cwd = origCwd.call(process);
|
|
@@ -5484,7 +5481,7 @@ var require_polyfills = __commonJS((exports, module) => {
|
|
|
5484
5481
|
};
|
|
5485
5482
|
fs.lchownSync = function() {};
|
|
5486
5483
|
}
|
|
5487
|
-
if (
|
|
5484
|
+
if (platform2 === "win32") {
|
|
5488
5485
|
fs.rename = typeof fs.rename !== "function" ? fs.rename : function(fs$rename) {
|
|
5489
5486
|
function rename(from, to, cb) {
|
|
5490
5487
|
var start = Date.now();
|
|
@@ -5924,8 +5921,8 @@ GFS4: `);
|
|
|
5924
5921
|
fs2.createReadStream = createReadStream;
|
|
5925
5922
|
fs2.createWriteStream = createWriteStream2;
|
|
5926
5923
|
var fs$readFile = fs2.readFile;
|
|
5927
|
-
fs2.readFile =
|
|
5928
|
-
function
|
|
5924
|
+
fs2.readFile = readFile2;
|
|
5925
|
+
function readFile2(path, options, cb) {
|
|
5929
5926
|
if (typeof options === "function")
|
|
5930
5927
|
cb = options, options = null;
|
|
5931
5928
|
return go$readFile(path, options, cb);
|
|
@@ -5941,8 +5938,8 @@ GFS4: `);
|
|
|
5941
5938
|
}
|
|
5942
5939
|
}
|
|
5943
5940
|
var fs$writeFile = fs2.writeFile;
|
|
5944
|
-
fs2.writeFile =
|
|
5945
|
-
function
|
|
5941
|
+
fs2.writeFile = writeFile2;
|
|
5942
|
+
function writeFile2(path, data, options, cb) {
|
|
5946
5943
|
if (typeof options === "function")
|
|
5947
5944
|
cb = options, options = null;
|
|
5948
5945
|
return go$writeFile(path, data, options, cb);
|
|
@@ -6862,14 +6859,14 @@ var require_empty = __commonJS((exports, module) => {
|
|
|
6862
6859
|
var u = require_universalify().fromPromise;
|
|
6863
6860
|
var fs = require_fs();
|
|
6864
6861
|
var path = __require("path");
|
|
6865
|
-
var
|
|
6862
|
+
var mkdir2 = require_mkdirs();
|
|
6866
6863
|
var remove = require_remove();
|
|
6867
6864
|
var emptyDir = u(async function emptyDir(dir) {
|
|
6868
6865
|
let items;
|
|
6869
6866
|
try {
|
|
6870
6867
|
items = await fs.readdir(dir);
|
|
6871
6868
|
} catch {
|
|
6872
|
-
return
|
|
6869
|
+
return mkdir2.mkdirs(dir);
|
|
6873
6870
|
}
|
|
6874
6871
|
return Promise.all(items.map((item) => remove.remove(path.join(dir, item))));
|
|
6875
6872
|
});
|
|
@@ -6878,7 +6875,7 @@ var require_empty = __commonJS((exports, module) => {
|
|
|
6878
6875
|
try {
|
|
6879
6876
|
items = fs.readdirSync(dir);
|
|
6880
6877
|
} catch {
|
|
6881
|
-
return
|
|
6878
|
+
return mkdir2.mkdirsSync(dir);
|
|
6882
6879
|
}
|
|
6883
6880
|
items.forEach((item) => {
|
|
6884
6881
|
item = path.join(dir, item);
|
|
@@ -6898,7 +6895,7 @@ var require_file = __commonJS((exports, module) => {
|
|
|
6898
6895
|
var u = require_universalify().fromPromise;
|
|
6899
6896
|
var path = __require("path");
|
|
6900
6897
|
var fs = require_fs();
|
|
6901
|
-
var
|
|
6898
|
+
var mkdir2 = require_mkdirs();
|
|
6902
6899
|
async function createFile(file) {
|
|
6903
6900
|
let stats;
|
|
6904
6901
|
try {
|
|
@@ -6912,7 +6909,7 @@ var require_file = __commonJS((exports, module) => {
|
|
|
6912
6909
|
dirStats = await fs.stat(dir);
|
|
6913
6910
|
} catch (err) {
|
|
6914
6911
|
if (err.code === "ENOENT") {
|
|
6915
|
-
await
|
|
6912
|
+
await mkdir2.mkdirs(dir);
|
|
6916
6913
|
await fs.writeFile(file, "");
|
|
6917
6914
|
return;
|
|
6918
6915
|
} else {
|
|
@@ -6939,7 +6936,7 @@ var require_file = __commonJS((exports, module) => {
|
|
|
6939
6936
|
}
|
|
6940
6937
|
} catch (err) {
|
|
6941
6938
|
if (err && err.code === "ENOENT")
|
|
6942
|
-
|
|
6939
|
+
mkdir2.mkdirsSync(dir);
|
|
6943
6940
|
else
|
|
6944
6941
|
throw err;
|
|
6945
6942
|
}
|
|
@@ -6956,7 +6953,7 @@ var require_link = __commonJS((exports, module) => {
|
|
|
6956
6953
|
var u = require_universalify().fromPromise;
|
|
6957
6954
|
var path = __require("path");
|
|
6958
6955
|
var fs = require_fs();
|
|
6959
|
-
var
|
|
6956
|
+
var mkdir2 = require_mkdirs();
|
|
6960
6957
|
var { pathExists } = require_path_exists();
|
|
6961
6958
|
var { areIdentical } = require_stat();
|
|
6962
6959
|
async function createLink(srcpath, dstpath) {
|
|
@@ -6976,7 +6973,7 @@ var require_link = __commonJS((exports, module) => {
|
|
|
6976
6973
|
const dir = path.dirname(dstpath);
|
|
6977
6974
|
const dirExists = await pathExists(dir);
|
|
6978
6975
|
if (!dirExists) {
|
|
6979
|
-
await
|
|
6976
|
+
await mkdir2.mkdirs(dir);
|
|
6980
6977
|
}
|
|
6981
6978
|
await fs.link(srcpath, dstpath);
|
|
6982
6979
|
}
|
|
@@ -6997,7 +6994,7 @@ var require_link = __commonJS((exports, module) => {
|
|
|
6997
6994
|
const dirExists = fs.existsSync(dir);
|
|
6998
6995
|
if (dirExists)
|
|
6999
6996
|
return fs.linkSync(srcpath, dstpath);
|
|
7000
|
-
|
|
6997
|
+
mkdir2.mkdirsSync(dir);
|
|
7001
6998
|
return fs.linkSync(srcpath, dstpath);
|
|
7002
6999
|
}
|
|
7003
7000
|
module.exports = {
|
|
@@ -7237,7 +7234,7 @@ var require_jsonfile = __commonJS((exports, module) => {
|
|
|
7237
7234
|
}
|
|
7238
7235
|
return obj;
|
|
7239
7236
|
}
|
|
7240
|
-
var
|
|
7237
|
+
var readFile2 = universalify.fromPromise(_readFile);
|
|
7241
7238
|
function readFileSync(file, options = {}) {
|
|
7242
7239
|
if (typeof options === "string") {
|
|
7243
7240
|
options = { encoding: options };
|
|
@@ -7262,16 +7259,16 @@ var require_jsonfile = __commonJS((exports, module) => {
|
|
|
7262
7259
|
const str = stringify(obj, options);
|
|
7263
7260
|
await universalify.fromCallback(fs.writeFile)(file, str, options);
|
|
7264
7261
|
}
|
|
7265
|
-
var
|
|
7262
|
+
var writeFile2 = universalify.fromPromise(_writeFile);
|
|
7266
7263
|
function writeFileSync(file, obj, options = {}) {
|
|
7267
7264
|
const fs = options.fs || _fs;
|
|
7268
7265
|
const str = stringify(obj, options);
|
|
7269
7266
|
return fs.writeFileSync(file, str, options);
|
|
7270
7267
|
}
|
|
7271
7268
|
module.exports = {
|
|
7272
|
-
readFile:
|
|
7269
|
+
readFile: readFile2,
|
|
7273
7270
|
readFileSync,
|
|
7274
|
-
writeFile:
|
|
7271
|
+
writeFile: writeFile2,
|
|
7275
7272
|
writeFileSync
|
|
7276
7273
|
};
|
|
7277
7274
|
});
|
|
@@ -7292,19 +7289,19 @@ var require_output_file = __commonJS((exports, module) => {
|
|
|
7292
7289
|
var u = require_universalify().fromPromise;
|
|
7293
7290
|
var fs = require_fs();
|
|
7294
7291
|
var path = __require("path");
|
|
7295
|
-
var
|
|
7292
|
+
var mkdir2 = require_mkdirs();
|
|
7296
7293
|
var pathExists = require_path_exists().pathExists;
|
|
7297
7294
|
async function outputFile(file, data, encoding = "utf-8") {
|
|
7298
7295
|
const dir = path.dirname(file);
|
|
7299
7296
|
if (!await pathExists(dir)) {
|
|
7300
|
-
await
|
|
7297
|
+
await mkdir2.mkdirs(dir);
|
|
7301
7298
|
}
|
|
7302
7299
|
return fs.writeFile(file, data, encoding);
|
|
7303
7300
|
}
|
|
7304
7301
|
function outputFileSync(file, ...args) {
|
|
7305
7302
|
const dir = path.dirname(file);
|
|
7306
7303
|
if (!fs.existsSync(dir)) {
|
|
7307
|
-
|
|
7304
|
+
mkdir2.mkdirsSync(dir);
|
|
7308
7305
|
}
|
|
7309
7306
|
fs.writeFileSync(file, ...args);
|
|
7310
7307
|
}
|
|
@@ -13045,7 +13042,7 @@ var cac = (name = "") => new CAC(name);
|
|
|
13045
13042
|
// package.json
|
|
13046
13043
|
var package_default = {
|
|
13047
13044
|
name: "claudekit-cli",
|
|
13048
|
-
version: "
|
|
13045
|
+
version: "3.0.1",
|
|
13049
13046
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
13050
13047
|
type: "module",
|
|
13051
13048
|
repository: {
|
|
@@ -13134,17 +13131,89 @@ init_dist2();
|
|
|
13134
13131
|
import { execSync as execSync2 } from "node:child_process";
|
|
13135
13132
|
|
|
13136
13133
|
// src/lib/auth.ts
|
|
13137
|
-
init_dist2();
|
|
13138
13134
|
init_types2();
|
|
13135
|
+
init_logger();
|
|
13139
13136
|
import { execSync } from "node:child_process";
|
|
13140
13137
|
|
|
13141
|
-
|
|
13138
|
+
class AuthManager {
|
|
13139
|
+
static token = null;
|
|
13140
|
+
static ghCliInstalled = null;
|
|
13141
|
+
static async getToken() {
|
|
13142
|
+
if (AuthManager.token) {
|
|
13143
|
+
return { token: AuthManager.token, method: "gh-cli" };
|
|
13144
|
+
}
|
|
13145
|
+
if (!AuthManager.isGhCliInstalled()) {
|
|
13146
|
+
throw new AuthenticationError(`GitHub CLI is not installed.
|
|
13147
|
+
|
|
13148
|
+
` + `ClaudeKit requires GitHub CLI for accessing private repositories.
|
|
13149
|
+
|
|
13150
|
+
` + `To install:
|
|
13151
|
+
` + ` macOS: brew install gh
|
|
13152
|
+
` + ` Windows: winget install GitHub.cli
|
|
13153
|
+
` + ` Linux: sudo apt install gh (or see: gh.io/install)
|
|
13154
|
+
|
|
13155
|
+
` + "After installing, run: gh auth login");
|
|
13156
|
+
}
|
|
13157
|
+
const token = AuthManager.getFromGhCli();
|
|
13158
|
+
if (token) {
|
|
13159
|
+
AuthManager.token = token;
|
|
13160
|
+
logger.debug("Using GitHub CLI authentication");
|
|
13161
|
+
return { token, method: "gh-cli" };
|
|
13162
|
+
}
|
|
13163
|
+
throw new AuthenticationError(`GitHub CLI is not authenticated.
|
|
13164
|
+
|
|
13165
|
+
` + `Run: gh auth login
|
|
13166
|
+
|
|
13167
|
+
` + "Then follow the prompts to authenticate with your GitHub account.");
|
|
13168
|
+
}
|
|
13169
|
+
static isGhCliInstalled() {
|
|
13170
|
+
if (AuthManager.ghCliInstalled !== null) {
|
|
13171
|
+
return AuthManager.ghCliInstalled;
|
|
13172
|
+
}
|
|
13173
|
+
try {
|
|
13174
|
+
execSync("gh --version", {
|
|
13175
|
+
stdio: "ignore",
|
|
13176
|
+
timeout: 5000
|
|
13177
|
+
});
|
|
13178
|
+
AuthManager.ghCliInstalled = true;
|
|
13179
|
+
return true;
|
|
13180
|
+
} catch {
|
|
13181
|
+
AuthManager.ghCliInstalled = false;
|
|
13182
|
+
return false;
|
|
13183
|
+
}
|
|
13184
|
+
}
|
|
13185
|
+
static getFromGhCli() {
|
|
13186
|
+
try {
|
|
13187
|
+
const token = execSync("gh auth token", {
|
|
13188
|
+
encoding: "utf-8",
|
|
13189
|
+
stdio: ["pipe", "pipe", "ignore"],
|
|
13190
|
+
timeout: 5000
|
|
13191
|
+
}).trim();
|
|
13192
|
+
if (token && token.length > 0) {
|
|
13193
|
+
return token;
|
|
13194
|
+
}
|
|
13195
|
+
return null;
|
|
13196
|
+
} catch {
|
|
13197
|
+
return null;
|
|
13198
|
+
}
|
|
13199
|
+
}
|
|
13200
|
+
static async clearToken() {
|
|
13201
|
+
AuthManager.token = null;
|
|
13202
|
+
logger.debug("Cleared cached token");
|
|
13203
|
+
}
|
|
13204
|
+
}
|
|
13205
|
+
|
|
13206
|
+
// src/lib/github.ts
|
|
13142
13207
|
init_types2();
|
|
13143
13208
|
init_logger();
|
|
13209
|
+
import { Octokit } from "@octokit/rest";
|
|
13210
|
+
|
|
13211
|
+
// src/lib/release-cache.ts
|
|
13212
|
+
init_zod();
|
|
13213
|
+
init_logger();
|
|
13144
13214
|
import { existsSync } from "node:fs";
|
|
13145
|
-
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
13146
|
-
import {
|
|
13147
|
-
import { platform as platform2 } from "node:os";
|
|
13215
|
+
import { mkdir, readFile, unlink, writeFile } from "node:fs/promises";
|
|
13216
|
+
import { join as join2 } from "node:path";
|
|
13148
13217
|
|
|
13149
13218
|
// src/utils/path-resolver.ts
|
|
13150
13219
|
import { homedir, platform } from "node:os";
|
|
@@ -13248,243 +13317,7 @@ class PathResolver {
|
|
|
13248
13317
|
}
|
|
13249
13318
|
}
|
|
13250
13319
|
|
|
13251
|
-
// src/utils/config.ts
|
|
13252
|
-
class ConfigManager {
|
|
13253
|
-
static config = null;
|
|
13254
|
-
static globalFlag = false;
|
|
13255
|
-
static setGlobalFlag(global2) {
|
|
13256
|
-
ConfigManager.globalFlag = global2;
|
|
13257
|
-
ConfigManager.config = null;
|
|
13258
|
-
}
|
|
13259
|
-
static getGlobalFlag() {
|
|
13260
|
-
return ConfigManager.globalFlag;
|
|
13261
|
-
}
|
|
13262
|
-
static async load() {
|
|
13263
|
-
if (ConfigManager.config) {
|
|
13264
|
-
return ConfigManager.config;
|
|
13265
|
-
}
|
|
13266
|
-
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
13267
|
-
try {
|
|
13268
|
-
if (existsSync(configFile)) {
|
|
13269
|
-
const content = await readFile(configFile, "utf-8");
|
|
13270
|
-
const data = JSON.parse(content);
|
|
13271
|
-
ConfigManager.config = ConfigSchema.parse(data);
|
|
13272
|
-
logger.debug(`Config loaded from ${configFile}`);
|
|
13273
|
-
return ConfigManager.config;
|
|
13274
|
-
}
|
|
13275
|
-
} catch (error) {
|
|
13276
|
-
logger.warning(`Failed to load config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
13277
|
-
}
|
|
13278
|
-
ConfigManager.config = { github: {}, defaults: {} };
|
|
13279
|
-
return ConfigManager.config;
|
|
13280
|
-
}
|
|
13281
|
-
static async save(config) {
|
|
13282
|
-
try {
|
|
13283
|
-
const validConfig = ConfigSchema.parse(config);
|
|
13284
|
-
const configDir = PathResolver.getConfigDir(ConfigManager.globalFlag);
|
|
13285
|
-
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
13286
|
-
if (!existsSync(configDir)) {
|
|
13287
|
-
await mkdir(configDir, { recursive: true });
|
|
13288
|
-
if (platform2() !== "win32") {
|
|
13289
|
-
await chmod(configDir, 448);
|
|
13290
|
-
}
|
|
13291
|
-
}
|
|
13292
|
-
await writeFile(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
|
|
13293
|
-
if (platform2() !== "win32") {
|
|
13294
|
-
await chmod(configFile, 384);
|
|
13295
|
-
}
|
|
13296
|
-
ConfigManager.config = validConfig;
|
|
13297
|
-
logger.debug(`Config saved to ${configFile}`);
|
|
13298
|
-
} catch (error) {
|
|
13299
|
-
throw new Error(`Failed to save config: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
13300
|
-
}
|
|
13301
|
-
}
|
|
13302
|
-
static async get() {
|
|
13303
|
-
return ConfigManager.load();
|
|
13304
|
-
}
|
|
13305
|
-
static async set(key, value) {
|
|
13306
|
-
const config = await ConfigManager.load();
|
|
13307
|
-
const keys = key.split(".");
|
|
13308
|
-
let current = config;
|
|
13309
|
-
for (let i = 0;i < keys.length - 1; i++) {
|
|
13310
|
-
if (!(keys[i] in current)) {
|
|
13311
|
-
current[keys[i]] = {};
|
|
13312
|
-
}
|
|
13313
|
-
current = current[keys[i]];
|
|
13314
|
-
}
|
|
13315
|
-
current[keys[keys.length - 1]] = value;
|
|
13316
|
-
await ConfigManager.save(config);
|
|
13317
|
-
}
|
|
13318
|
-
static async getToken() {
|
|
13319
|
-
const config = await ConfigManager.load();
|
|
13320
|
-
return config.github?.token;
|
|
13321
|
-
}
|
|
13322
|
-
static async setToken(token) {
|
|
13323
|
-
await ConfigManager.set("github.token", token);
|
|
13324
|
-
}
|
|
13325
|
-
}
|
|
13326
|
-
|
|
13327
|
-
// src/lib/auth.ts
|
|
13328
|
-
init_logger();
|
|
13329
|
-
var keytarModule = null;
|
|
13330
|
-
async function getKeytar() {
|
|
13331
|
-
if (keytarModule)
|
|
13332
|
-
return keytarModule;
|
|
13333
|
-
try {
|
|
13334
|
-
keytarModule = await import("keytar");
|
|
13335
|
-
return keytarModule;
|
|
13336
|
-
} catch (error) {
|
|
13337
|
-
logger.debug(`Keytar not available: ${String(error)}`);
|
|
13338
|
-
return null;
|
|
13339
|
-
}
|
|
13340
|
-
}
|
|
13341
|
-
var SERVICE_NAME = "claudekit-cli";
|
|
13342
|
-
var ACCOUNT_NAME = "github-token";
|
|
13343
|
-
|
|
13344
|
-
class AuthManager {
|
|
13345
|
-
static token = null;
|
|
13346
|
-
static authMethod = null;
|
|
13347
|
-
static async getToken() {
|
|
13348
|
-
if (AuthManager.token && AuthManager.authMethod) {
|
|
13349
|
-
return { token: AuthManager.token, method: AuthManager.authMethod };
|
|
13350
|
-
}
|
|
13351
|
-
try {
|
|
13352
|
-
const token = await AuthManager.getFromGhCli();
|
|
13353
|
-
if (token) {
|
|
13354
|
-
AuthManager.token = token;
|
|
13355
|
-
AuthManager.authMethod = "gh-cli";
|
|
13356
|
-
logger.debug("Using GitHub CLI authentication");
|
|
13357
|
-
return { token, method: "gh-cli" };
|
|
13358
|
-
}
|
|
13359
|
-
} catch (error) {
|
|
13360
|
-
logger.debug("GitHub CLI not available");
|
|
13361
|
-
}
|
|
13362
|
-
const envToken = process.env.GITHUB_TOKEN || process.env.GH_TOKEN;
|
|
13363
|
-
if (envToken) {
|
|
13364
|
-
AuthManager.token = envToken;
|
|
13365
|
-
AuthManager.authMethod = "env-var";
|
|
13366
|
-
logger.debug("Using environment variable authentication");
|
|
13367
|
-
return { token: envToken, method: "env-var" };
|
|
13368
|
-
}
|
|
13369
|
-
try {
|
|
13370
|
-
const configToken = await ConfigManager.getToken();
|
|
13371
|
-
if (configToken) {
|
|
13372
|
-
AuthManager.token = configToken;
|
|
13373
|
-
AuthManager.authMethod = "env-var";
|
|
13374
|
-
logger.debug("Using config file authentication");
|
|
13375
|
-
return { token: configToken, method: "env-var" };
|
|
13376
|
-
}
|
|
13377
|
-
} catch (error) {
|
|
13378
|
-
logger.debug("No token in config file");
|
|
13379
|
-
}
|
|
13380
|
-
try {
|
|
13381
|
-
const keytar = await getKeytar();
|
|
13382
|
-
if (keytar) {
|
|
13383
|
-
const keychainToken = await keytar.getPassword(SERVICE_NAME, ACCOUNT_NAME);
|
|
13384
|
-
if (keychainToken) {
|
|
13385
|
-
AuthManager.token = keychainToken;
|
|
13386
|
-
AuthManager.authMethod = "keychain";
|
|
13387
|
-
logger.debug("Using keychain authentication");
|
|
13388
|
-
return { token: keychainToken, method: "keychain" };
|
|
13389
|
-
}
|
|
13390
|
-
} else {
|
|
13391
|
-
logger.debug("Keychain not available on this system");
|
|
13392
|
-
}
|
|
13393
|
-
} catch (error) {
|
|
13394
|
-
logger.debug("No token in keychain");
|
|
13395
|
-
}
|
|
13396
|
-
const promptedToken = await AuthManager.promptForToken();
|
|
13397
|
-
AuthManager.token = promptedToken;
|
|
13398
|
-
AuthManager.authMethod = "prompt";
|
|
13399
|
-
return { token: promptedToken, method: "prompt" };
|
|
13400
|
-
}
|
|
13401
|
-
static async getFromGhCli() {
|
|
13402
|
-
try {
|
|
13403
|
-
const token = execSync("gh auth token", {
|
|
13404
|
-
encoding: "utf-8",
|
|
13405
|
-
stdio: ["pipe", "pipe", "ignore"],
|
|
13406
|
-
timeout: 5000
|
|
13407
|
-
}).trim();
|
|
13408
|
-
if (token && token.length > 0) {
|
|
13409
|
-
return token;
|
|
13410
|
-
}
|
|
13411
|
-
return null;
|
|
13412
|
-
} catch {
|
|
13413
|
-
return null;
|
|
13414
|
-
}
|
|
13415
|
-
}
|
|
13416
|
-
static async promptForToken() {
|
|
13417
|
-
logger.info("");
|
|
13418
|
-
logger.info("GitHub authentication required to access private repositories.");
|
|
13419
|
-
logger.info("");
|
|
13420
|
-
logger.info("\uD83D\uDCA1 Tip: For easier setup, use GitHub CLI instead:");
|
|
13421
|
-
logger.info(" gh auth login");
|
|
13422
|
-
logger.info("");
|
|
13423
|
-
logger.info("Or create a Personal Access Token:");
|
|
13424
|
-
logger.info(" https://github.com/settings/tokens/new?scopes=repo&description=ClaudeKit%20CLI");
|
|
13425
|
-
logger.info("");
|
|
13426
|
-
const token = await re({
|
|
13427
|
-
message: "Enter your GitHub Personal Access Token:",
|
|
13428
|
-
validate: (value) => {
|
|
13429
|
-
if (!value || value.length === 0) {
|
|
13430
|
-
return "Token is required";
|
|
13431
|
-
}
|
|
13432
|
-
if (!value.startsWith("ghp_") && !value.startsWith("github_pat_")) {
|
|
13433
|
-
return 'Invalid token format. Token should start with "ghp_" or "github_pat_"';
|
|
13434
|
-
}
|
|
13435
|
-
return;
|
|
13436
|
-
}
|
|
13437
|
-
});
|
|
13438
|
-
if (lD(token)) {
|
|
13439
|
-
logger.info("");
|
|
13440
|
-
logger.info("Alternative: Set GITHUB_TOKEN environment variable or use 'gh auth login'");
|
|
13441
|
-
throw new AuthenticationError("Authentication cancelled by user");
|
|
13442
|
-
}
|
|
13443
|
-
const keytar = await getKeytar();
|
|
13444
|
-
if (keytar) {
|
|
13445
|
-
const save = await se({
|
|
13446
|
-
message: "Save token securely in OS keychain?"
|
|
13447
|
-
});
|
|
13448
|
-
if (save && !lD(save)) {
|
|
13449
|
-
try {
|
|
13450
|
-
await keytar.setPassword(SERVICE_NAME, ACCOUNT_NAME, token);
|
|
13451
|
-
logger.success("Token saved securely in keychain");
|
|
13452
|
-
} catch (error) {
|
|
13453
|
-
logger.warning("Failed to save token to keychain");
|
|
13454
|
-
}
|
|
13455
|
-
}
|
|
13456
|
-
}
|
|
13457
|
-
return token;
|
|
13458
|
-
}
|
|
13459
|
-
static async clearToken() {
|
|
13460
|
-
AuthManager.token = null;
|
|
13461
|
-
AuthManager.authMethod = null;
|
|
13462
|
-
try {
|
|
13463
|
-
const keytar = await getKeytar();
|
|
13464
|
-
if (keytar) {
|
|
13465
|
-
await keytar.deletePassword(SERVICE_NAME, ACCOUNT_NAME);
|
|
13466
|
-
logger.success("Token cleared from keychain");
|
|
13467
|
-
}
|
|
13468
|
-
} catch (error) {
|
|
13469
|
-
logger.warning("Failed to clear token from keychain");
|
|
13470
|
-
}
|
|
13471
|
-
}
|
|
13472
|
-
static isValidTokenFormat(token) {
|
|
13473
|
-
return token.startsWith("ghp_") || token.startsWith("github_pat_");
|
|
13474
|
-
}
|
|
13475
|
-
}
|
|
13476
|
-
|
|
13477
|
-
// src/lib/github.ts
|
|
13478
|
-
init_types2();
|
|
13479
|
-
init_logger();
|
|
13480
|
-
import { Octokit } from "@octokit/rest";
|
|
13481
|
-
|
|
13482
13320
|
// src/lib/release-cache.ts
|
|
13483
|
-
init_zod();
|
|
13484
|
-
init_logger();
|
|
13485
|
-
import { existsSync as existsSync2 } from "node:fs";
|
|
13486
|
-
import { mkdir as mkdir2, readFile as readFile2, unlink, writeFile as writeFile2 } from "node:fs/promises";
|
|
13487
|
-
import { join as join2 } from "node:path";
|
|
13488
13321
|
var ReleaseCacheEntrySchema = exports_external.object({
|
|
13489
13322
|
timestamp: exports_external.number(),
|
|
13490
13323
|
releases: exports_external.array(exports_external.any())
|
|
@@ -13500,11 +13333,11 @@ class ReleaseCache {
|
|
|
13500
13333
|
async get(key) {
|
|
13501
13334
|
const cacheFile = this.getCachePath(key);
|
|
13502
13335
|
try {
|
|
13503
|
-
if (!
|
|
13336
|
+
if (!existsSync(cacheFile)) {
|
|
13504
13337
|
logger.debug(`Release cache not found for key: ${key}`);
|
|
13505
13338
|
return null;
|
|
13506
13339
|
}
|
|
13507
|
-
const content = await
|
|
13340
|
+
const content = await readFile(cacheFile, "utf-8");
|
|
13508
13341
|
const parsed = JSON.parse(content);
|
|
13509
13342
|
const cacheEntry = ReleaseCacheEntrySchema.parse(parsed);
|
|
13510
13343
|
if (this.isExpired(cacheEntry.timestamp)) {
|
|
@@ -13525,12 +13358,12 @@ class ReleaseCache {
|
|
|
13525
13358
|
async set(key, releases) {
|
|
13526
13359
|
const cacheFile = this.getCachePath(key);
|
|
13527
13360
|
try {
|
|
13528
|
-
await
|
|
13361
|
+
await mkdir(this.cacheDir, { recursive: true, mode: 448 });
|
|
13529
13362
|
const cacheEntry = {
|
|
13530
13363
|
timestamp: Date.now(),
|
|
13531
13364
|
releases
|
|
13532
13365
|
};
|
|
13533
|
-
await
|
|
13366
|
+
await writeFile(cacheFile, JSON.stringify(cacheEntry, null, 2), "utf-8");
|
|
13534
13367
|
logger.debug(`Release cache set for key: ${key}, cached ${releases.length} releases`);
|
|
13535
13368
|
} catch (error) {
|
|
13536
13369
|
logger.debug(`Failed to set release cache for key ${key}: ${error}`);
|
|
@@ -13540,7 +13373,7 @@ class ReleaseCache {
|
|
|
13540
13373
|
if (key) {
|
|
13541
13374
|
const cacheFile = this.getCachePath(key);
|
|
13542
13375
|
try {
|
|
13543
|
-
if (
|
|
13376
|
+
if (existsSync(cacheFile)) {
|
|
13544
13377
|
await unlink(cacheFile);
|
|
13545
13378
|
logger.debug(`Release cache cleared for key: ${key}`);
|
|
13546
13379
|
}
|
|
@@ -13850,50 +13683,57 @@ class GitHubClient {
|
|
|
13850
13683
|
});
|
|
13851
13684
|
return GitHubReleaseSchema.parse(data);
|
|
13852
13685
|
} catch (error) {
|
|
13853
|
-
|
|
13854
|
-
|
|
13686
|
+
return this.handleHttpError(error, {
|
|
13687
|
+
kit,
|
|
13688
|
+
operation: "fetch release",
|
|
13689
|
+
verboseFlag: "ck new --verbose"
|
|
13690
|
+
});
|
|
13691
|
+
}
|
|
13692
|
+
}
|
|
13693
|
+
async invalidateAuth() {
|
|
13694
|
+
await AuthManager.clearToken();
|
|
13695
|
+
this.octokit = null;
|
|
13696
|
+
logger.debug("Invalidated cached authentication due to 401 error");
|
|
13697
|
+
}
|
|
13698
|
+
async handleHttpError(error, context) {
|
|
13699
|
+
const { kit, operation, verboseFlag = "ck new --verbose" } = context;
|
|
13700
|
+
if (error?.status === 401) {
|
|
13701
|
+
await this.invalidateAuth();
|
|
13702
|
+
throw new GitHubError(`Authentication failed.
|
|
13855
13703
|
|
|
13856
|
-
|
|
13857
|
-
• You haven't accepted the GitHub repository invitation
|
|
13858
|
-
• Your token lacks the 'repo' scope (needs full private repo access)
|
|
13859
|
-
• You're not added as a collaborator yet
|
|
13860
|
-
• Repository doesn't exist
|
|
13704
|
+
Your GitHub CLI session may have expired.
|
|
13861
13705
|
|
|
13862
|
-
|
|
13863
|
-
|
|
13864
|
-
2. Use 'gh auth login' for automatic authentication (recommended)
|
|
13865
|
-
3. Recreate token with 'repo' scope: https://github.com/settings/tokens/new?scopes=repo
|
|
13866
|
-
4. Wait 2-5 minutes after accepting invitation for permissions to sync
|
|
13706
|
+
Solution: Re-authenticate with GitHub CLI
|
|
13707
|
+
gh auth login
|
|
13867
13708
|
|
|
13868
|
-
Need help? Run with:
|
|
13869
|
-
|
|
13870
|
-
|
|
13871
|
-
|
|
13709
|
+
Need help? Run with: ${verboseFlag}`, 401);
|
|
13710
|
+
}
|
|
13711
|
+
if (error?.status === 403) {
|
|
13712
|
+
throw new GitHubError(`Access forbidden.
|
|
13872
13713
|
|
|
13873
|
-
|
|
13874
|
-
` + ` 1. Use GitHub CLI (recommended): gh auth login
|
|
13875
|
-
` + ` 2. Create new token: https://github.com/settings/tokens/new?scopes=repo
|
|
13876
|
-
` + ` 3. Verify token format (should start with 'ghp_' or 'github_pat_')
|
|
13877
|
-
` + ` 4. Check token is set: echo $GITHUB_TOKEN
|
|
13714
|
+
Your GitHub CLI session may lack required permissions.
|
|
13878
13715
|
|
|
13879
|
-
|
|
13880
|
-
|
|
13881
|
-
if (error?.status === 403) {
|
|
13882
|
-
throw new GitHubError(`Access forbidden - token lacks required permissions.
|
|
13716
|
+
Solution: Re-authenticate with GitHub CLI
|
|
13717
|
+
gh auth login
|
|
13883
13718
|
|
|
13884
|
-
|
|
13719
|
+
Need help? Run with: ${verboseFlag}`, 403);
|
|
13720
|
+
}
|
|
13721
|
+
if (error?.status === 404) {
|
|
13722
|
+
throw new GitHubError(`Cannot access ${kit.name} repository.
|
|
13885
13723
|
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
|
|
13889
|
-
|
|
13724
|
+
Possible causes:
|
|
13725
|
+
• You haven't accepted the GitHub repository invitation
|
|
13726
|
+
• You're not added as a collaborator yet
|
|
13727
|
+
• Repository doesn't exist
|
|
13890
13728
|
|
|
13891
|
-
|
|
13729
|
+
Solutions:
|
|
13730
|
+
1. Check email for GitHub invitation and accept it
|
|
13731
|
+
2. Re-authenticate: gh auth login
|
|
13732
|
+
3. Wait 2-5 minutes after accepting invitation for permissions to sync
|
|
13892
13733
|
|
|
13893
|
-
|
|
13894
|
-
}
|
|
13895
|
-
throw new GitHubError(`Failed to fetch release: ${error?.message || "Unknown error"}`, error?.status);
|
|
13734
|
+
Need help? Run with: ${verboseFlag}`, 404);
|
|
13896
13735
|
}
|
|
13736
|
+
throw new GitHubError(`Failed to ${operation}: ${error?.message || "Unknown error"}`, error?.status);
|
|
13897
13737
|
}
|
|
13898
13738
|
async getReleaseByTag(kit, tag) {
|
|
13899
13739
|
try {
|
|
@@ -13912,40 +13752,19 @@ Need help? Run with: ck new --verbose`, 404);
|
|
|
13912
13752
|
Possible causes:
|
|
13913
13753
|
• Release version doesn't exist (check: ck versions --kit ${kit.name.toLowerCase()})
|
|
13914
13754
|
• You don't have repository access
|
|
13915
|
-
• Your token lacks the 'repo' scope
|
|
13916
13755
|
|
|
13917
13756
|
Solutions:
|
|
13918
13757
|
1. List available versions: ck versions --kit ${kit.name.toLowerCase()}
|
|
13919
13758
|
2. Check email for GitHub invitation and accept it
|
|
13920
|
-
3.
|
|
13921
|
-
4. Recreate token: https://github.com/settings/tokens/new?scopes=repo
|
|
13759
|
+
3. Re-authenticate: gh auth login
|
|
13922
13760
|
|
|
13923
13761
|
Need help? Run with: ck new --verbose`, 404);
|
|
13924
13762
|
}
|
|
13925
|
-
|
|
13926
|
-
|
|
13927
|
-
|
|
13928
|
-
|
|
13929
|
-
|
|
13930
|
-
` + ` 2. Create new token: https://github.com/settings/tokens/new?scopes=repo
|
|
13931
|
-
` + ` 3. Verify token format (should start with 'ghp_' or 'github_pat_')
|
|
13932
|
-
` + ` 4. Check token is set: echo $GITHUB_TOKEN
|
|
13933
|
-
|
|
13934
|
-
` + "Need help? Run with: ck new --verbose", 401);
|
|
13935
|
-
}
|
|
13936
|
-
if (error?.status === 403) {
|
|
13937
|
-
throw new GitHubError(`Access forbidden - token lacks required permissions.
|
|
13938
|
-
|
|
13939
|
-
` + `Your token needs the 'repo' scope for private repositories.
|
|
13940
|
-
|
|
13941
|
-
` + `Solutions:
|
|
13942
|
-
` + ` 1. Use GitHub CLI (handles scopes automatically): gh auth login
|
|
13943
|
-
` + ` 2. Recreate token with 'repo' scope: https://github.com/settings/tokens/new?scopes=repo
|
|
13944
|
-
` + ` 3. Check existing token scopes: https://github.com/settings/tokens
|
|
13945
|
-
|
|
13946
|
-
` + "Need help? Run with: ck new --verbose", 403);
|
|
13947
|
-
}
|
|
13948
|
-
throw new GitHubError(`Failed to fetch release: ${error?.message || "Unknown error"}`, error?.status);
|
|
13763
|
+
return this.handleHttpError(error, {
|
|
13764
|
+
kit,
|
|
13765
|
+
operation: "fetch release",
|
|
13766
|
+
verboseFlag: "ck new --verbose"
|
|
13767
|
+
});
|
|
13949
13768
|
}
|
|
13950
13769
|
}
|
|
13951
13770
|
async listReleases(kit, limit = 10) {
|
|
@@ -13959,40 +13778,11 @@ Need help? Run with: ck new --verbose`, 404);
|
|
|
13959
13778
|
});
|
|
13960
13779
|
return data.map((release) => GitHubReleaseSchema.parse(release));
|
|
13961
13780
|
} catch (error) {
|
|
13962
|
-
|
|
13963
|
-
|
|
13964
|
-
|
|
13965
|
-
|
|
13966
|
-
|
|
13967
|
-
` + ` 2. Create new token: https://github.com/settings/tokens/new?scopes=repo
|
|
13968
|
-
` + ` 3. Verify token format (should start with 'ghp_' or 'github_pat_')
|
|
13969
|
-
|
|
13970
|
-
` + "Need help? Run with: ck versions --verbose", 401);
|
|
13971
|
-
}
|
|
13972
|
-
if (error?.status === 403) {
|
|
13973
|
-
throw new GitHubError(`Access forbidden - token lacks required permissions.
|
|
13974
|
-
|
|
13975
|
-
` + `Your token needs the 'repo' scope for private repositories.
|
|
13976
|
-
|
|
13977
|
-
` + `Solutions:
|
|
13978
|
-
` + ` 1. Use GitHub CLI (handles scopes automatically): gh auth login
|
|
13979
|
-
` + ` 2. Recreate token with 'repo' scope: https://github.com/settings/tokens/new?scopes=repo
|
|
13980
|
-
|
|
13981
|
-
` + "Need help? Run with: ck versions --verbose", 403);
|
|
13982
|
-
}
|
|
13983
|
-
if (error?.status === 404) {
|
|
13984
|
-
throw new GitHubError(`Cannot access ${kit.name} repository.
|
|
13985
|
-
|
|
13986
|
-
You may not have been added as a collaborator yet.
|
|
13987
|
-
|
|
13988
|
-
Solutions:
|
|
13989
|
-
1. Check email for GitHub invitation and accept it
|
|
13990
|
-
2. Contact support to verify repository access
|
|
13991
|
-
3. Use 'gh auth login' for automatic authentication
|
|
13992
|
-
|
|
13993
|
-
Need help? Run with: ck versions --verbose`, 404);
|
|
13994
|
-
}
|
|
13995
|
-
throw new GitHubError(`Failed to list releases: ${error?.message || "Unknown error"}`, error?.status);
|
|
13781
|
+
return this.handleHttpError(error, {
|
|
13782
|
+
kit,
|
|
13783
|
+
operation: "list releases",
|
|
13784
|
+
verboseFlag: "ck versions --verbose"
|
|
13785
|
+
});
|
|
13996
13786
|
}
|
|
13997
13787
|
}
|
|
13998
13788
|
async checkAccess(kit) {
|
|
@@ -14009,45 +13799,22 @@ Need help? Run with: ck versions --verbose`, 404);
|
|
|
14009
13799
|
|
|
14010
13800
|
Possible causes:
|
|
14011
13801
|
• You haven't accepted the GitHub repository invitation
|
|
14012
|
-
• Your token lacks the 'repo' scope (needs full private repo access)
|
|
14013
13802
|
• You're not added as a collaborator yet
|
|
14014
|
-
•
|
|
13803
|
+
• You're logged into a different GitHub account
|
|
14015
13804
|
|
|
14016
13805
|
Solutions:
|
|
14017
13806
|
1. Check email for GitHub invitation and accept it
|
|
14018
|
-
2.
|
|
14019
|
-
3.
|
|
14020
|
-
4.
|
|
14021
|
-
5. Wait 2-5 minutes after accepting invitation for permissions to sync
|
|
13807
|
+
2. Re-authenticate: gh auth login
|
|
13808
|
+
3. Verify you're using the correct GitHub account
|
|
13809
|
+
4. Wait 2-5 minutes after accepting invitation for permissions to sync
|
|
14022
13810
|
|
|
14023
13811
|
Need help? Run with: ck new --verbose`, 404);
|
|
14024
13812
|
}
|
|
14025
|
-
|
|
14026
|
-
|
|
14027
|
-
|
|
14028
|
-
|
|
14029
|
-
|
|
14030
|
-
` + `Solutions:
|
|
14031
|
-
` + ` 1. Use GitHub CLI (handles scopes automatically): gh auth login
|
|
14032
|
-
` + ` 2. Recreate token with 'repo' scope: https://github.com/settings/tokens/new?scopes=repo
|
|
14033
|
-
` + ` 3. Check existing token scopes: https://github.com/settings/tokens
|
|
14034
|
-
|
|
14035
|
-
` + `Common mistake: Using 'public_repo' scope doesn't work for private repos.
|
|
14036
|
-
|
|
14037
|
-
` + "Need help? Run with: ck new --verbose", 403);
|
|
14038
|
-
}
|
|
14039
|
-
if (error?.status === 401) {
|
|
14040
|
-
throw new GitHubError(`Authentication failed - token is invalid or expired.
|
|
14041
|
-
|
|
14042
|
-
` + `Solutions:
|
|
14043
|
-
` + ` 1. Use GitHub CLI (recommended): gh auth login
|
|
14044
|
-
` + ` 2. Create new token: https://github.com/settings/tokens/new?scopes=repo
|
|
14045
|
-
` + ` 3. Verify token format (should start with 'ghp_' or 'github_pat_')
|
|
14046
|
-
` + ` 4. Check token is set: echo $GITHUB_TOKEN
|
|
14047
|
-
|
|
14048
|
-
` + "Need help? Run with: ck new --verbose", 401);
|
|
14049
|
-
}
|
|
14050
|
-
throw new GitHubError(`Failed to check repository access: ${error?.message || "Unknown error"}`, error?.status);
|
|
13813
|
+
return this.handleHttpError(error, {
|
|
13814
|
+
kit,
|
|
13815
|
+
operation: "check repository access",
|
|
13816
|
+
verboseFlag: "ck new --verbose"
|
|
13817
|
+
});
|
|
14051
13818
|
}
|
|
14052
13819
|
}
|
|
14053
13820
|
async listReleasesWithCache(kit, options = {}) {
|
|
@@ -14174,18 +13941,18 @@ import { promisify } from "node:util";
|
|
|
14174
13941
|
var execAsync = promisify(exec);
|
|
14175
13942
|
var isCIEnvironment = process.env.CI === "true" || process.env.CI_SAFE_MODE === "true";
|
|
14176
13943
|
function getOSInfo() {
|
|
14177
|
-
const
|
|
13944
|
+
const platform2 = process.platform;
|
|
14178
13945
|
const arch = process.arch;
|
|
14179
|
-
const isWindows =
|
|
14180
|
-
const isMacOS =
|
|
14181
|
-
const isLinux =
|
|
13946
|
+
const isWindows = platform2 === "win32";
|
|
13947
|
+
const isMacOS = platform2 === "darwin";
|
|
13948
|
+
const isLinux = platform2 === "linux";
|
|
14182
13949
|
const isWSL = isLinux && process.env.WSL_DISTRO_NAME !== undefined;
|
|
14183
|
-
let details = `${
|
|
13950
|
+
let details = `${platform2}-${arch}`;
|
|
14184
13951
|
if (isWSL) {
|
|
14185
13952
|
details += ` (WSL: ${process.env.WSL_DISTRO_NAME})`;
|
|
14186
13953
|
}
|
|
14187
13954
|
return {
|
|
14188
|
-
platform:
|
|
13955
|
+
platform: platform2,
|
|
14189
13956
|
arch,
|
|
14190
13957
|
isWindows,
|
|
14191
13958
|
isMacOS,
|
|
@@ -14462,68 +14229,40 @@ function checkEnvironmentVariables() {
|
|
|
14462
14229
|
const githubToken = process.env.GITHUB_TOKEN;
|
|
14463
14230
|
const ghToken = process.env.GH_TOKEN;
|
|
14464
14231
|
if (githubToken || ghToken) {
|
|
14465
|
-
const tokenToCheck = githubToken || ghToken;
|
|
14466
14232
|
const tokenVar = githubToken ? "GITHUB_TOKEN" : "GH_TOKEN";
|
|
14467
|
-
if (!tokenToCheck?.startsWith("ghp_") && !tokenToCheck?.startsWith("github_pat_")) {
|
|
14468
|
-
return {
|
|
14469
|
-
name: "Environment Variables",
|
|
14470
|
-
status: "fail",
|
|
14471
|
-
message: `${tokenVar} is set but has invalid format`,
|
|
14472
|
-
details: "Token should start with 'ghp_' or 'github_pat_'",
|
|
14473
|
-
suggestion: "Create new token: https://github.com/settings/tokens/new?scopes=repo"
|
|
14474
|
-
};
|
|
14475
|
-
}
|
|
14476
14233
|
return {
|
|
14477
14234
|
name: "Environment Variables",
|
|
14478
|
-
status: "
|
|
14479
|
-
message: `${tokenVar} is set
|
|
14480
|
-
details:
|
|
14235
|
+
status: "info",
|
|
14236
|
+
message: `${tokenVar} is set but PAT authentication is no longer supported`,
|
|
14237
|
+
details: "ClaudeKit now uses GitHub CLI exclusively for authentication",
|
|
14238
|
+
suggestion: "Run: gh auth login"
|
|
14481
14239
|
};
|
|
14482
14240
|
}
|
|
14483
14241
|
return {
|
|
14484
14242
|
name: "Environment Variables",
|
|
14485
14243
|
status: "info",
|
|
14486
|
-
message: "No GitHub token found in environment variables",
|
|
14487
|
-
details: "
|
|
14488
|
-
suggestion: `Set token:
|
|
14489
|
-
` + ` • Unix/Mac: export GITHUB_TOKEN=ghp_xxx
|
|
14490
|
-
` + " • Windows: [System.Environment]::SetEnvironmentVariable('GITHUB_TOKEN', 'ghp_xxx', 'User')"
|
|
14244
|
+
message: "No GitHub token found in environment variables (expected)",
|
|
14245
|
+
details: "ClaudeKit uses GitHub CLI for authentication"
|
|
14491
14246
|
};
|
|
14492
14247
|
}
|
|
14493
14248
|
async function checkAuthentication() {
|
|
14494
14249
|
try {
|
|
14495
|
-
const { token
|
|
14496
|
-
const methodLabels = {
|
|
14497
|
-
"gh-cli": "GitHub CLI",
|
|
14498
|
-
"env-var": "Environment Variable",
|
|
14499
|
-
keychain: "OS Keychain",
|
|
14500
|
-
prompt: "User Prompt"
|
|
14501
|
-
};
|
|
14502
|
-
if (!AuthManager.isValidTokenFormat(token)) {
|
|
14503
|
-
return {
|
|
14504
|
-
name: "Authentication",
|
|
14505
|
-
status: "fail",
|
|
14506
|
-
message: "Token has invalid format",
|
|
14507
|
-
details: "Token should start with 'ghp_' or 'github_pat_'",
|
|
14508
|
-
suggestion: "Create new token: https://github.com/settings/tokens/new?scopes=repo"
|
|
14509
|
-
};
|
|
14510
|
-
}
|
|
14250
|
+
const { token } = await AuthManager.getToken();
|
|
14511
14251
|
return {
|
|
14512
14252
|
name: "Authentication",
|
|
14513
14253
|
status: "pass",
|
|
14514
|
-
message:
|
|
14254
|
+
message: "Successfully authenticated via GitHub CLI",
|
|
14515
14255
|
details: `Token: ${token.substring(0, 8)}...`
|
|
14516
14256
|
};
|
|
14517
14257
|
} catch (error) {
|
|
14518
14258
|
return {
|
|
14519
14259
|
name: "Authentication",
|
|
14520
14260
|
status: "fail",
|
|
14521
|
-
message: "
|
|
14261
|
+
message: "GitHub CLI authentication required",
|
|
14522
14262
|
details: error?.message || "Unknown error",
|
|
14523
|
-
suggestion: `
|
|
14524
|
-
` + ` 1.
|
|
14525
|
-
` +
|
|
14526
|
-
` + " 3. Create token: https://github.com/settings/tokens/new?scopes=repo"
|
|
14263
|
+
suggestion: `To authenticate:
|
|
14264
|
+
` + ` 1. Install GitHub CLI: https://cli.github.com
|
|
14265
|
+
` + " 2. Run: gh auth login"
|
|
14527
14266
|
};
|
|
14528
14267
|
}
|
|
14529
14268
|
}
|
|
@@ -14552,7 +14291,7 @@ async function checkRepositoryAccess(kit) {
|
|
|
14552
14291
|
message: `Cannot access ${kitConfig.owner}/${kitConfig.repo}`,
|
|
14553
14292
|
suggestion: `Solutions:
|
|
14554
14293
|
` + ` 1. Check email for GitHub invitation and accept it
|
|
14555
|
-
` + ` 2.
|
|
14294
|
+
` + ` 2. Re-authenticate: gh auth login
|
|
14556
14295
|
` + ` 3. Wait 2-5 minutes after accepting invitation
|
|
14557
14296
|
` + " 4. Contact support if issue persists"
|
|
14558
14297
|
};
|
|
@@ -14563,9 +14302,9 @@ async function checkRepositoryAccess(kit) {
|
|
|
14563
14302
|
message: "Failed to check repository access",
|
|
14564
14303
|
details: error?.message || "Unknown error",
|
|
14565
14304
|
suggestion: `Possible causes:
|
|
14566
|
-
` + ` • Token lacks 'repo' scope
|
|
14567
14305
|
` + ` • You haven't been added as collaborator
|
|
14568
|
-
` +
|
|
14306
|
+
` + ` • Network connectivity issues
|
|
14307
|
+
` + " • Try: gh auth login"
|
|
14569
14308
|
};
|
|
14570
14309
|
}
|
|
14571
14310
|
}
|
|
@@ -14633,7 +14372,7 @@ function checkSystemInfo() {
|
|
|
14633
14372
|
|
|
14634
14373
|
// src/commands/doctor.ts
|
|
14635
14374
|
init_dist2();
|
|
14636
|
-
import { existsSync as
|
|
14375
|
+
import { existsSync as existsSync3 } from "node:fs";
|
|
14637
14376
|
import { join as join4 } from "node:path";
|
|
14638
14377
|
|
|
14639
14378
|
// src/utils/claudekit-scanner.ts
|
|
@@ -14732,16 +14471,16 @@ import { promisify as promisify2 } from "node:util";
|
|
|
14732
14471
|
init_logger();
|
|
14733
14472
|
var execAsync2 = promisify2(exec2);
|
|
14734
14473
|
async function detectOS() {
|
|
14735
|
-
const
|
|
14736
|
-
const info = { platform:
|
|
14737
|
-
if (
|
|
14474
|
+
const platform2 = process.platform;
|
|
14475
|
+
const info = { platform: platform2 };
|
|
14476
|
+
if (platform2 === "darwin") {
|
|
14738
14477
|
try {
|
|
14739
14478
|
await execAsync2("which brew");
|
|
14740
14479
|
info.hasHomebrew = true;
|
|
14741
14480
|
} catch {
|
|
14742
14481
|
info.hasHomebrew = false;
|
|
14743
14482
|
}
|
|
14744
|
-
} else if (
|
|
14483
|
+
} else if (platform2 === "linux") {
|
|
14745
14484
|
try {
|
|
14746
14485
|
if (fs.existsSync("/etc/os-release")) {
|
|
14747
14486
|
const content = fs.readFileSync("/etc/os-release", "utf-8");
|
|
@@ -15013,14 +14752,14 @@ function getManualInstructions(dependency, osInfo) {
|
|
|
15013
14752
|
init_environment();
|
|
15014
14753
|
init_logger();
|
|
15015
14754
|
function checkSkillsInstallation() {
|
|
15016
|
-
const
|
|
15017
|
-
const scriptName =
|
|
14755
|
+
const platform2 = process.platform;
|
|
14756
|
+
const scriptName = platform2 === "win32" ? "install.ps1" : "install.sh";
|
|
15018
14757
|
const globalSkillsDir = join4(PathResolver.getGlobalKitDir(), "skills");
|
|
15019
14758
|
const globalScriptPath = join4(globalSkillsDir, scriptName);
|
|
15020
|
-
const globalAvailable =
|
|
14759
|
+
const globalAvailable = existsSync3(globalScriptPath);
|
|
15021
14760
|
const projectSkillsDir = join4(process.cwd(), ".claude", "skills");
|
|
15022
14761
|
const projectScriptPath = join4(projectSkillsDir, scriptName);
|
|
15023
|
-
const projectAvailable =
|
|
14762
|
+
const projectAvailable = existsSync3(projectScriptPath);
|
|
15024
14763
|
return {
|
|
15025
14764
|
global: {
|
|
15026
14765
|
available: globalAvailable,
|
|
@@ -15292,7 +15031,7 @@ import { join as join22, resolve as resolve4 } from "node:path";
|
|
|
15292
15031
|
// src/lib/commands-prefix.ts
|
|
15293
15032
|
init_logger();
|
|
15294
15033
|
var import_fs_extra3 = __toESM(require_lib(), 1);
|
|
15295
|
-
import { lstat, mkdir as
|
|
15034
|
+
import { lstat, mkdir as mkdir2, readdir as readdir2, stat as stat2 } from "node:fs/promises";
|
|
15296
15035
|
import { join as join6 } from "node:path";
|
|
15297
15036
|
|
|
15298
15037
|
// src/utils/manifest-writer.ts
|
|
@@ -15451,8 +15190,11 @@ class OwnershipChecker {
|
|
|
15451
15190
|
const hash = createHash("sha256");
|
|
15452
15191
|
const stream = createReadStream(filePath);
|
|
15453
15192
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
15454
|
-
stream.on("end", () =>
|
|
15193
|
+
stream.on("end", () => {
|
|
15194
|
+
resolve(hash.digest("hex"));
|
|
15195
|
+
});
|
|
15455
15196
|
stream.on("error", (err) => {
|
|
15197
|
+
stream.destroy();
|
|
15456
15198
|
reject(new Error(`Failed to calculate checksum for "${filePath}": ${err.message}`));
|
|
15457
15199
|
});
|
|
15458
15200
|
});
|
|
@@ -15696,9 +15438,9 @@ class CommandsPrefix {
|
|
|
15696
15438
|
}
|
|
15697
15439
|
await import_fs_extra3.copy(commandsDir, backupDir);
|
|
15698
15440
|
logger.verbose("Created backup of commands directory");
|
|
15699
|
-
await
|
|
15441
|
+
await mkdir2(tempDir, { recursive: true });
|
|
15700
15442
|
const ckDir = join6(tempDir, "ck");
|
|
15701
|
-
await
|
|
15443
|
+
await mkdir2(ckDir, { recursive: true });
|
|
15702
15444
|
let processedCount = 0;
|
|
15703
15445
|
for (const entry of entries) {
|
|
15704
15446
|
const sourcePath = join6(commandsDir, entry);
|
|
@@ -15774,9 +15516,9 @@ class CommandsPrefix {
|
|
|
15774
15516
|
}
|
|
15775
15517
|
const metadata = await ManifestWriter.readManifest(claudeDir);
|
|
15776
15518
|
if (!metadata || !metadata.files || metadata.files.length === 0) {
|
|
15777
|
-
logger.
|
|
15778
|
-
logger.
|
|
15779
|
-
|
|
15519
|
+
logger.verbose("No ownership metadata found - skipping cleanup (legacy/fresh install)");
|
|
15520
|
+
logger.verbose("All existing files will be preserved as user-owned");
|
|
15521
|
+
return result;
|
|
15780
15522
|
}
|
|
15781
15523
|
const entries = await readdir2(commandsDir);
|
|
15782
15524
|
if (entries.length === 0) {
|
|
@@ -15972,7 +15714,7 @@ var import_ignore = __toESM(require_ignore(), 1);
|
|
|
15972
15714
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
15973
15715
|
import { execFile } from "node:child_process";
|
|
15974
15716
|
import { createWriteStream as createWriteStream2 } from "node:fs";
|
|
15975
|
-
import { mkdir as
|
|
15717
|
+
import { mkdir as mkdir4 } from "node:fs/promises";
|
|
15976
15718
|
import { tmpdir } from "node:os";
|
|
15977
15719
|
import { join as join8, relative as relative2, resolve } from "node:path";
|
|
15978
15720
|
import { TextDecoder } from "node:util";
|
|
@@ -19273,8 +19015,8 @@ class Minipass3 extends EventEmitter4 {
|
|
|
19273
19015
|
}
|
|
19274
19016
|
|
|
19275
19017
|
// node_modules/tar/dist/esm/normalize-windows-path.js
|
|
19276
|
-
var
|
|
19277
|
-
var normalizeWindowsPath =
|
|
19018
|
+
var platform2 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
19019
|
+
var normalizeWindowsPath = platform2 !== "win32" ? (p) => p : (p) => p && p.replace(/\\/g, "/");
|
|
19278
19020
|
|
|
19279
19021
|
// node_modules/tar/dist/esm/read-entry.js
|
|
19280
19022
|
class ReadEntry extends Minipass3 {
|
|
@@ -21472,8 +21214,8 @@ import path6 from "node:path";
|
|
|
21472
21214
|
|
|
21473
21215
|
// node_modules/tar/dist/esm/get-write-flag.js
|
|
21474
21216
|
import fs6 from "fs";
|
|
21475
|
-
var
|
|
21476
|
-
var isWindows2 =
|
|
21217
|
+
var platform3 = process.env.__FAKE_PLATFORM__ || process.platform;
|
|
21218
|
+
var isWindows2 = platform3 === "win32";
|
|
21477
21219
|
var { O_CREAT, O_TRUNC, O_WRONLY } = fs6.constants;
|
|
21478
21220
|
var UV_FS_O_FILEMAP = Number(process.env.__FAKE_FS_O_FILENAME__) || fs6.constants.UV_FS_O_FILEMAP || 0;
|
|
21479
21221
|
var fMapEnabled = isWindows2 && !!UV_FS_O_FILEMAP;
|
|
@@ -21604,7 +21346,7 @@ var checkCwd = (dir, cb) => {
|
|
|
21604
21346
|
cb(er);
|
|
21605
21347
|
});
|
|
21606
21348
|
};
|
|
21607
|
-
var
|
|
21349
|
+
var mkdir3 = (dir, opt, cb) => {
|
|
21608
21350
|
dir = normalizeWindowsPath(dir);
|
|
21609
21351
|
const umask = opt.umask ?? 18;
|
|
21610
21352
|
const mode = opt.mode | 448;
|
|
@@ -21764,8 +21506,8 @@ var normalizeUnicode = (s) => {
|
|
|
21764
21506
|
};
|
|
21765
21507
|
|
|
21766
21508
|
// node_modules/tar/dist/esm/path-reservations.js
|
|
21767
|
-
var
|
|
21768
|
-
var isWindows3 =
|
|
21509
|
+
var platform4 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
21510
|
+
var isWindows3 = platform4 === "win32";
|
|
21769
21511
|
var getDirs = (path6) => {
|
|
21770
21512
|
const dirs = path6.split("/").slice(0, -1).reduce((set, path7) => {
|
|
21771
21513
|
const s = set[set.length - 1];
|
|
@@ -21911,8 +21653,8 @@ var DOCHOWN = Symbol("doChown");
|
|
|
21911
21653
|
var UID = Symbol("uid");
|
|
21912
21654
|
var GID = Symbol("gid");
|
|
21913
21655
|
var CHECKED_CWD = Symbol("checkedCwd");
|
|
21914
|
-
var
|
|
21915
|
-
var isWindows4 =
|
|
21656
|
+
var platform5 = process.env.TESTING_TAR_FAKE_PLATFORM || process.platform;
|
|
21657
|
+
var isWindows4 = platform5 === "win32";
|
|
21916
21658
|
var DEFAULT_MAX_DEPTH = 1024;
|
|
21917
21659
|
var unlinkFile = (path7, cb) => {
|
|
21918
21660
|
if (!isWindows4) {
|
|
@@ -22127,7 +21869,7 @@ class Unpack extends Parser {
|
|
|
22127
21869
|
}
|
|
22128
21870
|
}
|
|
22129
21871
|
[MKDIR](dir, mode, cb) {
|
|
22130
|
-
|
|
21872
|
+
mkdir3(normalizeWindowsPath(dir), {
|
|
22131
21873
|
uid: this.uid,
|
|
22132
21874
|
gid: this.gid,
|
|
22133
21875
|
processUid: this.processUid,
|
|
@@ -25944,7 +25686,7 @@ class DownloadManager {
|
|
|
25944
25686
|
async downloadAsset(asset, destDir) {
|
|
25945
25687
|
try {
|
|
25946
25688
|
const destPath = join8(destDir, asset.name);
|
|
25947
|
-
await
|
|
25689
|
+
await mkdir4(destDir, { recursive: true });
|
|
25948
25690
|
logger.info(`Downloading ${asset.name} (${this.formatBytes(asset.size)})...`);
|
|
25949
25691
|
const progressBar = new import_cli_progress.default.SingleBar({
|
|
25950
25692
|
format: "Progress |{bar}| {percentage}% | {value}/{total} MB",
|
|
@@ -25994,7 +25736,7 @@ class DownloadManager {
|
|
|
25994
25736
|
async downloadFile(params) {
|
|
25995
25737
|
const { url, name: name2, size, destDir, token } = params;
|
|
25996
25738
|
const destPath = join8(destDir, name2);
|
|
25997
|
-
await
|
|
25739
|
+
await mkdir4(destDir, { recursive: true });
|
|
25998
25740
|
logger.info(`Downloading ${name2}${size ? ` (${this.formatBytes(size)})` : ""}...`);
|
|
25999
25741
|
const headers = {};
|
|
26000
25742
|
if (token && url.includes("api.github.com")) {
|
|
@@ -26058,7 +25800,7 @@ class DownloadManager {
|
|
|
26058
25800
|
try {
|
|
26059
25801
|
this.resetExtractionSize();
|
|
26060
25802
|
const detectedType = archiveType || this.detectArchiveType(archivePath);
|
|
26061
|
-
await
|
|
25803
|
+
await mkdir4(destDir, { recursive: true });
|
|
26062
25804
|
if (detectedType === "tar.gz") {
|
|
26063
25805
|
await this.extractTarGz(archivePath, destDir);
|
|
26064
25806
|
} else if (detectedType === "zip") {
|
|
@@ -26311,7 +26053,7 @@ class DownloadManager {
|
|
|
26311
26053
|
const timestamp = Date.now();
|
|
26312
26054
|
const primaryTempDir = join8(tmpdir(), `claudekit-${timestamp}`);
|
|
26313
26055
|
try {
|
|
26314
|
-
await
|
|
26056
|
+
await mkdir4(primaryTempDir, { recursive: true });
|
|
26315
26057
|
logger.debug(`Created temp directory: ${primaryTempDir}`);
|
|
26316
26058
|
return primaryTempDir;
|
|
26317
26059
|
} catch (primaryError) {
|
|
@@ -26327,7 +26069,7 @@ Solutions:
|
|
|
26327
26069
|
}
|
|
26328
26070
|
const fallbackTempDir = join8(homeDir, ".claudekit", "tmp", `claudekit-${timestamp}`);
|
|
26329
26071
|
try {
|
|
26330
|
-
await
|
|
26072
|
+
await mkdir4(fallbackTempDir, { recursive: true });
|
|
26331
26073
|
logger.debug(`Created temp directory (fallback): ${fallbackTempDir}`);
|
|
26332
26074
|
logger.warning(`Using fallback temp directory: ${fallbackTempDir}
|
|
26333
26075
|
(OS temp directory was not accessible)`);
|
|
@@ -26396,10 +26138,10 @@ async function handleFreshInstallation(claudeDir, prompts) {
|
|
|
26396
26138
|
|
|
26397
26139
|
// src/lib/global-path-transformer.ts
|
|
26398
26140
|
init_logger();
|
|
26399
|
-
import { readFile as
|
|
26400
|
-
import { platform as
|
|
26141
|
+
import { readFile as readFile4, readdir as readdir3, writeFile as writeFile3 } from "node:fs/promises";
|
|
26142
|
+
import { platform as platform6 } from "node:os";
|
|
26401
26143
|
import { extname, join as join10 } from "node:path";
|
|
26402
|
-
var IS_WINDOWS =
|
|
26144
|
+
var IS_WINDOWS = platform6() === "win32";
|
|
26403
26145
|
var HOME_PREFIX = IS_WINDOWS ? "%USERPROFILE%" : "$HOME";
|
|
26404
26146
|
function getHomeDirPrefix() {
|
|
26405
26147
|
return HOME_PREFIX;
|
|
@@ -26498,10 +26240,10 @@ async function transformPathsForGlobalInstall(directory, options = {}) {
|
|
|
26498
26240
|
await processDirectory(fullPath);
|
|
26499
26241
|
} else if (entry.isFile() && shouldTransformFile(entry.name)) {
|
|
26500
26242
|
try {
|
|
26501
|
-
const content = await
|
|
26243
|
+
const content = await readFile4(fullPath, "utf-8");
|
|
26502
26244
|
const { transformed, changes } = transformContent(content);
|
|
26503
26245
|
if (changes > 0) {
|
|
26504
|
-
await
|
|
26246
|
+
await writeFile3(fullPath, transformed, "utf-8");
|
|
26505
26247
|
filesTransformed++;
|
|
26506
26248
|
totalChanges += changes;
|
|
26507
26249
|
if (options.verbose) {
|
|
@@ -29076,7 +28818,7 @@ init_types2();
|
|
|
29076
28818
|
init_logger();
|
|
29077
28819
|
var import_fs_extra10 = __toESM(require_lib(), 1);
|
|
29078
28820
|
import { createHash as createHash2 } from "node:crypto";
|
|
29079
|
-
import { readFile as
|
|
28821
|
+
import { readFile as readFile8, readdir as readdir6, writeFile as writeFile7 } from "node:fs/promises";
|
|
29080
28822
|
import { join as join16, relative as relative5 } from "node:path";
|
|
29081
28823
|
|
|
29082
28824
|
class SkillsManifestManager {
|
|
@@ -29100,7 +28842,7 @@ class SkillsManifestManager {
|
|
|
29100
28842
|
}
|
|
29101
28843
|
static async writeManifest(skillsDir, manifest) {
|
|
29102
28844
|
const manifestPath = join16(skillsDir, SkillsManifestManager.MANIFEST_FILENAME);
|
|
29103
|
-
await
|
|
28845
|
+
await writeFile7(manifestPath, JSON.stringify(manifest, null, 2), "utf-8");
|
|
29104
28846
|
logger.debug(`Wrote manifest to: ${manifestPath}`);
|
|
29105
28847
|
}
|
|
29106
28848
|
static async readManifest(skillsDir) {
|
|
@@ -29110,7 +28852,7 @@ class SkillsManifestManager {
|
|
|
29110
28852
|
return null;
|
|
29111
28853
|
}
|
|
29112
28854
|
try {
|
|
29113
|
-
const content = await
|
|
28855
|
+
const content = await readFile8(manifestPath, "utf-8");
|
|
29114
28856
|
const data = JSON.parse(content);
|
|
29115
28857
|
const manifest = SkillsManifestSchema.parse(data);
|
|
29116
28858
|
logger.debug(`Read manifest from: ${manifestPath}`);
|
|
@@ -29182,7 +28924,7 @@ class SkillsManifestManager {
|
|
|
29182
28924
|
files.sort();
|
|
29183
28925
|
for (const file of files) {
|
|
29184
28926
|
const relativePath = relative5(dirPath, file);
|
|
29185
|
-
const content = await
|
|
28927
|
+
const content = await readFile8(file);
|
|
29186
28928
|
hash.update(relativePath);
|
|
29187
28929
|
hash.update(content);
|
|
29188
28930
|
}
|
|
@@ -29478,14 +29220,14 @@ class SkillsMigrationDetector {
|
|
|
29478
29220
|
init_types2();
|
|
29479
29221
|
init_logger();
|
|
29480
29222
|
var import_fs_extra14 = __toESM(require_lib(), 1);
|
|
29481
|
-
import { copyFile as copyFile2, mkdir as
|
|
29223
|
+
import { copyFile as copyFile2, mkdir as mkdir6, readdir as readdir10, rm as rm2 } from "node:fs/promises";
|
|
29482
29224
|
import { join as join20 } from "node:path";
|
|
29483
29225
|
|
|
29484
29226
|
// src/lib/skills-backup-manager.ts
|
|
29485
29227
|
init_types2();
|
|
29486
29228
|
init_logger();
|
|
29487
29229
|
var import_fs_extra12 = __toESM(require_lib(), 1);
|
|
29488
|
-
import { copyFile, mkdir as
|
|
29230
|
+
import { copyFile, mkdir as mkdir5, readdir as readdir8, rm, stat as stat4 } from "node:fs/promises";
|
|
29489
29231
|
import { basename as basename2, join as join18, normalize as normalize2 } from "node:path";
|
|
29490
29232
|
function validatePath2(path9, paramName) {
|
|
29491
29233
|
if (!path9 || typeof path9 !== "string") {
|
|
@@ -29515,7 +29257,7 @@ class SkillsBackupManager {
|
|
|
29515
29257
|
const backupDir = parentDir ? join18(parentDir, backupDirName) : join18(skillsDir, "..", backupDirName);
|
|
29516
29258
|
logger.info(`Creating backup at: ${backupDir}`);
|
|
29517
29259
|
try {
|
|
29518
|
-
await
|
|
29260
|
+
await mkdir5(backupDir, { recursive: true });
|
|
29519
29261
|
await SkillsBackupManager.copyDirectory(skillsDir, backupDir);
|
|
29520
29262
|
logger.success("Backup created successfully");
|
|
29521
29263
|
return backupDir;
|
|
@@ -29537,7 +29279,7 @@ class SkillsBackupManager {
|
|
|
29537
29279
|
if (await import_fs_extra12.pathExists(targetDir)) {
|
|
29538
29280
|
await rm(targetDir, { recursive: true, force: true });
|
|
29539
29281
|
}
|
|
29540
|
-
await
|
|
29282
|
+
await mkdir5(targetDir, { recursive: true });
|
|
29541
29283
|
await SkillsBackupManager.copyDirectory(backupDir, targetDir);
|
|
29542
29284
|
logger.success("Backup restored successfully");
|
|
29543
29285
|
} catch (error2) {
|
|
@@ -29597,7 +29339,7 @@ class SkillsBackupManager {
|
|
|
29597
29339
|
continue;
|
|
29598
29340
|
}
|
|
29599
29341
|
if (entry.isDirectory()) {
|
|
29600
|
-
await
|
|
29342
|
+
await mkdir5(destPath, { recursive: true });
|
|
29601
29343
|
await SkillsBackupManager.copyDirectory(sourcePath, destPath);
|
|
29602
29344
|
} else if (entry.isFile()) {
|
|
29603
29345
|
await copyFile(sourcePath, destPath);
|
|
@@ -29638,7 +29380,7 @@ init_logger();
|
|
|
29638
29380
|
var import_fs_extra13 = __toESM(require_lib(), 1);
|
|
29639
29381
|
import { createHash as createHash3 } from "node:crypto";
|
|
29640
29382
|
import { createReadStream as createReadStream2 } from "node:fs";
|
|
29641
|
-
import { readFile as
|
|
29383
|
+
import { readFile as readFile9, readdir as readdir9 } from "node:fs/promises";
|
|
29642
29384
|
import { join as join19, normalize as normalize3, relative as relative6 } from "node:path";
|
|
29643
29385
|
function validatePath3(path9, paramName) {
|
|
29644
29386
|
if (!path9 || typeof path9 !== "string") {
|
|
@@ -29851,8 +29593,13 @@ class SkillsCustomizationScanner {
|
|
|
29851
29593
|
const hash = createHash3("sha256");
|
|
29852
29594
|
const stream = createReadStream2(filePath);
|
|
29853
29595
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
29854
|
-
stream.on("end", () =>
|
|
29855
|
-
|
|
29596
|
+
stream.on("end", () => {
|
|
29597
|
+
resolve2(hash.digest("hex"));
|
|
29598
|
+
});
|
|
29599
|
+
stream.on("error", (error2) => {
|
|
29600
|
+
stream.destroy();
|
|
29601
|
+
reject(error2);
|
|
29602
|
+
});
|
|
29856
29603
|
});
|
|
29857
29604
|
}
|
|
29858
29605
|
static async hashDirectory(dirPath) {
|
|
@@ -29861,7 +29608,7 @@ class SkillsCustomizationScanner {
|
|
|
29861
29608
|
files.sort();
|
|
29862
29609
|
for (const file of files) {
|
|
29863
29610
|
const relativePath = relative6(dirPath, file);
|
|
29864
|
-
const content = await
|
|
29611
|
+
const content = await readFile9(file);
|
|
29865
29612
|
hash.update(relativePath);
|
|
29866
29613
|
hash.update(content);
|
|
29867
29614
|
}
|
|
@@ -30124,7 +29871,7 @@ class SkillsMigrator {
|
|
|
30124
29871
|
const preserved = [];
|
|
30125
29872
|
const errors2 = [];
|
|
30126
29873
|
const tempDir = join20(currentSkillsDir, "..", ".skills-migration-temp");
|
|
30127
|
-
await
|
|
29874
|
+
await mkdir6(tempDir, { recursive: true });
|
|
30128
29875
|
try {
|
|
30129
29876
|
for (const mapping of mappings) {
|
|
30130
29877
|
try {
|
|
@@ -30146,7 +29893,7 @@ class SkillsMigrator {
|
|
|
30146
29893
|
const category = mapping.category;
|
|
30147
29894
|
const targetPath = category ? join20(tempDir, category, skillName) : join20(tempDir, skillName);
|
|
30148
29895
|
if (category) {
|
|
30149
|
-
await
|
|
29896
|
+
await mkdir6(join20(tempDir, category), { recursive: true });
|
|
30150
29897
|
}
|
|
30151
29898
|
await SkillsMigrator.copySkillDirectory(currentSkillPath, targetPath);
|
|
30152
29899
|
migrated.push(skillName);
|
|
@@ -30165,7 +29912,7 @@ class SkillsMigrator {
|
|
|
30165
29912
|
}
|
|
30166
29913
|
}
|
|
30167
29914
|
await rm2(currentSkillsDir, { recursive: true, force: true });
|
|
30168
|
-
await
|
|
29915
|
+
await mkdir6(currentSkillsDir, { recursive: true });
|
|
30169
29916
|
await SkillsMigrator.copySkillDirectory(tempDir, currentSkillsDir);
|
|
30170
29917
|
await rm2(tempDir, { recursive: true, force: true });
|
|
30171
29918
|
return { migrated, preserved, errors: errors2 };
|
|
@@ -30177,7 +29924,7 @@ class SkillsMigrator {
|
|
|
30177
29924
|
}
|
|
30178
29925
|
}
|
|
30179
29926
|
static async copySkillDirectory(sourceDir, destDir) {
|
|
30180
|
-
await
|
|
29927
|
+
await mkdir6(destDir, { recursive: true });
|
|
30181
29928
|
const entries = await readdir10(sourceDir, { withFileTypes: true });
|
|
30182
29929
|
for (const entry of entries) {
|
|
30183
29930
|
const sourcePath = join20(sourceDir, entry.name);
|
|
@@ -30196,6 +29943,83 @@ class SkillsMigrator {
|
|
|
30196
29943
|
|
|
30197
29944
|
// src/commands/init.ts
|
|
30198
29945
|
init_types2();
|
|
29946
|
+
|
|
29947
|
+
// src/utils/config.ts
|
|
29948
|
+
init_types2();
|
|
29949
|
+
init_logger();
|
|
29950
|
+
import { existsSync as existsSync4 } from "node:fs";
|
|
29951
|
+
import { mkdir as mkdir7, readFile as readFile10, writeFile as writeFile8 } from "node:fs/promises";
|
|
29952
|
+
import { chmod } from "node:fs/promises";
|
|
29953
|
+
import { platform as platform7 } from "node:os";
|
|
29954
|
+
class ConfigManager {
|
|
29955
|
+
static config = null;
|
|
29956
|
+
static globalFlag = false;
|
|
29957
|
+
static setGlobalFlag(global3) {
|
|
29958
|
+
ConfigManager.globalFlag = global3;
|
|
29959
|
+
ConfigManager.config = null;
|
|
29960
|
+
}
|
|
29961
|
+
static getGlobalFlag() {
|
|
29962
|
+
return ConfigManager.globalFlag;
|
|
29963
|
+
}
|
|
29964
|
+
static async load() {
|
|
29965
|
+
if (ConfigManager.config) {
|
|
29966
|
+
return ConfigManager.config;
|
|
29967
|
+
}
|
|
29968
|
+
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
29969
|
+
try {
|
|
29970
|
+
if (existsSync4(configFile)) {
|
|
29971
|
+
const content = await readFile10(configFile, "utf-8");
|
|
29972
|
+
const data = JSON.parse(content);
|
|
29973
|
+
ConfigManager.config = ConfigSchema.parse(data);
|
|
29974
|
+
logger.debug(`Config loaded from ${configFile}`);
|
|
29975
|
+
return ConfigManager.config;
|
|
29976
|
+
}
|
|
29977
|
+
} catch (error2) {
|
|
29978
|
+
logger.warning(`Failed to load config: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
29979
|
+
}
|
|
29980
|
+
ConfigManager.config = { defaults: {} };
|
|
29981
|
+
return ConfigManager.config;
|
|
29982
|
+
}
|
|
29983
|
+
static async save(config) {
|
|
29984
|
+
try {
|
|
29985
|
+
const validConfig = ConfigSchema.parse(config);
|
|
29986
|
+
const configDir = PathResolver.getConfigDir(ConfigManager.globalFlag);
|
|
29987
|
+
const configFile = PathResolver.getConfigFile(ConfigManager.globalFlag);
|
|
29988
|
+
if (!existsSync4(configDir)) {
|
|
29989
|
+
await mkdir7(configDir, { recursive: true });
|
|
29990
|
+
if (platform7() !== "win32") {
|
|
29991
|
+
await chmod(configDir, 448);
|
|
29992
|
+
}
|
|
29993
|
+
}
|
|
29994
|
+
await writeFile8(configFile, JSON.stringify(validConfig, null, 2), "utf-8");
|
|
29995
|
+
if (platform7() !== "win32") {
|
|
29996
|
+
await chmod(configFile, 384);
|
|
29997
|
+
}
|
|
29998
|
+
ConfigManager.config = validConfig;
|
|
29999
|
+
logger.debug(`Config saved to ${configFile}`);
|
|
30000
|
+
} catch (error2) {
|
|
30001
|
+
throw new Error(`Failed to save config: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
30002
|
+
}
|
|
30003
|
+
}
|
|
30004
|
+
static async get() {
|
|
30005
|
+
return ConfigManager.load();
|
|
30006
|
+
}
|
|
30007
|
+
static async set(key, value) {
|
|
30008
|
+
const config = await ConfigManager.load();
|
|
30009
|
+
const keys = key.split(".");
|
|
30010
|
+
let current = config;
|
|
30011
|
+
for (let i = 0;i < keys.length - 1; i++) {
|
|
30012
|
+
if (!(keys[i] in current)) {
|
|
30013
|
+
current[keys[i]] = {};
|
|
30014
|
+
}
|
|
30015
|
+
current = current[keys[i]];
|
|
30016
|
+
}
|
|
30017
|
+
current[keys[keys.length - 1]] = value;
|
|
30018
|
+
await ConfigManager.save(config);
|
|
30019
|
+
}
|
|
30020
|
+
}
|
|
30021
|
+
|
|
30022
|
+
// src/commands/init.ts
|
|
30199
30023
|
init_environment();
|
|
30200
30024
|
|
|
30201
30025
|
// src/utils/file-scanner.ts
|
|
@@ -31076,7 +30900,7 @@ import { promisify as promisify5 } from "node:util";
|
|
|
31076
30900
|
// package.json
|
|
31077
30901
|
var package_default2 = {
|
|
31078
30902
|
name: "claudekit-cli",
|
|
31079
|
-
version: "
|
|
30903
|
+
version: "3.0.1",
|
|
31080
30904
|
description: "CLI tool for bootstrapping and updating ClaudeKit projects",
|
|
31081
30905
|
type: "module",
|
|
31082
30906
|
repository: {
|
|
@@ -32094,9 +31918,6 @@ var MetadataSchema2 = exports_external.object({
|
|
|
32094
31918
|
files: exports_external.array(TrackedFileSchema2).optional()
|
|
32095
31919
|
});
|
|
32096
31920
|
var ConfigSchema2 = exports_external.object({
|
|
32097
|
-
github: exports_external.object({
|
|
32098
|
-
token: exports_external.string().optional()
|
|
32099
|
-
}).optional(),
|
|
32100
31921
|
defaults: exports_external.object({
|
|
32101
31922
|
kit: KitType2.optional(),
|
|
32102
31923
|
dir: exports_external.string().optional()
|