@simplysm/sd-claude 13.0.82 → 13.0.83
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 +43 -0
- package/claude/skills/sd-plan/SKILL.md +4 -3
- package/package.json +3 -19
- package/scripts/postinstall.mjs +126 -9
- package/scripts/sd-entries.mjs +33 -0
- package/scripts/sync-claude-assets.mjs +4 -21
- package/dist/commands/auth-add.d.ts +0 -2
- package/dist/commands/auth-add.d.ts.map +0 -1
- package/dist/commands/auth-add.js +0 -32
- package/dist/commands/auth-add.js.map +0 -6
- package/dist/commands/auth-list.d.ts +0 -2
- package/dist/commands/auth-list.d.ts.map +0 -1
- package/dist/commands/auth-list.js +0 -95
- package/dist/commands/auth-list.js.map +0 -6
- package/dist/commands/auth-remove.d.ts +0 -2
- package/dist/commands/auth-remove.d.ts.map +0 -1
- package/dist/commands/auth-remove.js +0 -22
- package/dist/commands/auth-remove.js.map +0 -6
- package/dist/commands/auth-use.d.ts +0 -2
- package/dist/commands/auth-use.d.ts.map +0 -1
- package/dist/commands/auth-use.js +0 -33
- package/dist/commands/auth-use.js.map +0 -6
- package/dist/commands/auth-utils.d.ts +0 -11
- package/dist/commands/auth-utils.d.ts.map +0 -1
- package/dist/commands/auth-utils.js +0 -57
- package/dist/commands/auth-utils.js.map +0 -6
- package/dist/commands/install.d.ts +0 -2
- package/dist/commands/install.d.ts.map +0 -1
- package/dist/commands/install.js +0 -127
- package/dist/commands/install.js.map +0 -6
- package/dist/index.d.ts +0 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -7
- package/dist/index.js.map +0 -6
- package/dist/sd-claude.d.ts +0 -3
- package/dist/sd-claude.d.ts.map +0 -1
- package/dist/sd-claude.js +0 -78
- package/dist/sd-claude.js.map +0 -6
- package/src/commands/auth-add.ts +0 -36
- package/src/commands/auth-list.ts +0 -130
- package/src/commands/auth-remove.ts +0 -26
- package/src/commands/auth-use.ts +0 -53
- package/src/commands/auth-utils.ts +0 -65
- package/src/commands/install.ts +0 -183
- package/src/index.ts +0 -7
- package/src/sd-claude.ts +0 -98
- package/tests/auth-add.spec.ts +0 -74
- package/tests/auth-list.spec.ts +0 -198
- package/tests/auth-remove.spec.ts +0 -74
- package/tests/auth-use.spec.ts +0 -153
- package/tests/auth-utils.spec.ts +0 -173
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/commands/auth-utils.ts"],
|
|
4
|
-
"mappings": "AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AAEf,MAAM,eAAe;AAEd,SAAS,aAAa,MAAoB;AAC/C,MAAI,CAAC,aAAa,KAAK,IAAI,GAAG;AAC5B,UAAM,IAAI;AAAA,MACR,iBAAiB,IAAI;AAAA,IACvB;AAAA,EACF;AACF;AAEO,SAAS,cAAc,MAAc,SAA0B;AACpE,SAAO,KAAK,KAAK,WAAW,GAAG,QAAQ,GAAG,cAAc,QAAQ,IAAI;AACtE;AAEO,SAAS,cAAc,MAAc,SAA2B;AACrE,SAAO,GAAG,WAAW,cAAc,MAAM,OAAO,CAAC;AACnD;AAEO,SAAS,aAAa,SAA4B;AACvD,QAAM,UAAU,KAAK,KAAK,WAAW,GAAG,QAAQ,GAAG,cAAc,MAAM;AACvE,MAAI,CAAC,GAAG,WAAW,OAAO,GAAG;AAC3B,WAAO,CAAC;AAAA,EACV;AAEA,SAAO,GACJ,YAAY,SAAS,EAAE,eAAe,KAAK,CAAC,EAC5C,OAAO,CAAC,UAAU,MAAM,YAAY,CAAC,EACrC,IAAI,CAAC,UAAU,MAAM,IAAI;AAC9B;AAEO,SAAS,gBAAgB,SAG9B;AACA,QAAM,iBAAiB,KAAK,KAAK,WAAW,GAAG,QAAQ,GAAG,cAAc;AACxE,QAAM,OAAO,KAAK,MAAM,GAAG,aAAa,gBAAgB,OAAO,CAAC;AAEhE,QAAM,eAAe,KAAK,cAAc;AACxC,QAAM,SAAS,KAAK,QAAQ;AAE5B,MAAI,gBAAgB,QAAQ,UAAU,MAAM;AAC1C,UAAM,IAAI,MAAM,kCAAkC;AAAA,EACpD;AAEA,SAAO,EAAE,cAAc,OAAO;AAChC;AAEO,SAAS,uBAAuB,SAA2C;AAChF,QAAM,kBAAkB,KAAK,KAAK,WAAW,GAAG,QAAQ,GAAG,WAAW,mBAAmB;AACzF,SAAO,KAAK,MAAM,GAAG,aAAa,iBAAiB,OAAO,CAAC;AAC7D;AAEO,SAAS,iBAAiB,SAAsC;AACrE,QAAM,iBAAiB,KAAK,KAAK,WAAW,GAAG,QAAQ,GAAG,cAAc;AACxE,MAAI;AACF,UAAM,OAAO,KAAK,MAAM,GAAG,aAAa,gBAAgB,OAAO,CAAC;AAChE,WAAO,KAAK,QAAQ;AAAA,EACtB,QAAQ;AACN,WAAO;AAAA,EACT;AACF;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAQA,wBAAgB,UAAU,IAAI,IAAI,CA0CjC"}
|
package/dist/commands/install.js
DELETED
|
@@ -1,127 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { fileURLToPath } from "url";
|
|
4
|
-
function runInstall() {
|
|
5
|
-
try {
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
7
|
-
const pkgRoot = path.resolve(__dirname, "../..");
|
|
8
|
-
const sourceDir = path.join(pkgRoot, "claude");
|
|
9
|
-
const projectRoot = findProjectRoot(__dirname);
|
|
10
|
-
if (projectRoot == null) {
|
|
11
|
-
console.log("[@simplysm/sd-claude] Could not find project root, skipping installation.");
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
if (isSimplysmMonorepoSameMajor(projectRoot, pkgRoot)) {
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
if (!fs.existsSync(sourceDir)) {
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
const sourceEntries = collectSdEntries(sourceDir);
|
|
21
|
-
if (sourceEntries.length === 0) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
const targetDir = path.join(projectRoot, ".claude");
|
|
25
|
-
cleanSdEntries(targetDir);
|
|
26
|
-
copySdEntries(sourceDir, targetDir, sourceEntries);
|
|
27
|
-
setupSettings(targetDir);
|
|
28
|
-
console.log(`[@simplysm/sd-claude] Installed ${sourceEntries.length} sd-* entries.`);
|
|
29
|
-
} catch (err) {
|
|
30
|
-
console.warn("[@simplysm/sd-claude] postinstall warning:", err.message);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
function findProjectRoot(dirname) {
|
|
34
|
-
if (process.env["INIT_CWD"] != null) {
|
|
35
|
-
return process.env["INIT_CWD"];
|
|
36
|
-
}
|
|
37
|
-
const sep = path.sep;
|
|
38
|
-
const marker = sep + "node_modules" + sep;
|
|
39
|
-
const idx = dirname.indexOf(marker);
|
|
40
|
-
return idx !== -1 ? dirname.substring(0, idx) : void 0;
|
|
41
|
-
}
|
|
42
|
-
function isSimplysmMonorepoSameMajor(projectRoot, pkgRoot) {
|
|
43
|
-
const projectPkgPath = path.join(projectRoot, "package.json");
|
|
44
|
-
if (!fs.existsSync(projectPkgPath)) return false;
|
|
45
|
-
const projectPkg = JSON.parse(fs.readFileSync(projectPkgPath, "utf-8"));
|
|
46
|
-
if (projectPkg.name !== "simplysm") return false;
|
|
47
|
-
const sdClaudePkgPath = path.join(pkgRoot, "package.json");
|
|
48
|
-
if (!fs.existsSync(sdClaudePkgPath)) return false;
|
|
49
|
-
const sdClaudePkg = JSON.parse(fs.readFileSync(sdClaudePkgPath, "utf-8"));
|
|
50
|
-
const projectMajor = projectPkg.version?.split(".")[0];
|
|
51
|
-
const sdClaudeMajor = sdClaudePkg.version?.split(".")[0];
|
|
52
|
-
return projectMajor != null && projectMajor === sdClaudeMajor;
|
|
53
|
-
}
|
|
54
|
-
function collectSdEntries(sourceDir) {
|
|
55
|
-
const entries = [];
|
|
56
|
-
for (const name of fs.readdirSync(sourceDir)) {
|
|
57
|
-
if (name.startsWith("sd-")) {
|
|
58
|
-
entries.push(name);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
for (const dirent of fs.readdirSync(sourceDir, { withFileTypes: true })) {
|
|
62
|
-
if (!dirent.isDirectory() || dirent.name.startsWith("sd-")) continue;
|
|
63
|
-
const subPath = path.join(sourceDir, dirent.name);
|
|
64
|
-
for (const name of fs.readdirSync(subPath)) {
|
|
65
|
-
if (name.startsWith("sd-")) {
|
|
66
|
-
entries.push(path.join(dirent.name, name));
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
return entries;
|
|
71
|
-
}
|
|
72
|
-
function cleanSdEntries(targetDir) {
|
|
73
|
-
if (!fs.existsSync(targetDir)) return;
|
|
74
|
-
for (const name of fs.readdirSync(targetDir)) {
|
|
75
|
-
if (name.startsWith("sd-")) {
|
|
76
|
-
fs.rmSync(path.join(targetDir, name), { recursive: true });
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
for (const dirent of fs.readdirSync(targetDir, { withFileTypes: true })) {
|
|
80
|
-
if (!dirent.isDirectory() || dirent.name.startsWith("sd-")) continue;
|
|
81
|
-
const subPath = path.join(targetDir, dirent.name);
|
|
82
|
-
for (const name of fs.readdirSync(subPath)) {
|
|
83
|
-
if (name.startsWith("sd-")) {
|
|
84
|
-
fs.rmSync(path.join(subPath, name), { recursive: true });
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
function copySdEntries(sourceDir, targetDir, entries) {
|
|
90
|
-
fs.mkdirSync(targetDir, { recursive: true });
|
|
91
|
-
for (const entry of entries) {
|
|
92
|
-
const src = path.join(sourceDir, entry);
|
|
93
|
-
const dest = path.join(targetDir, entry);
|
|
94
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
95
|
-
fs.cpSync(src, dest, { recursive: true });
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
function setupSettings(targetDir) {
|
|
99
|
-
const settingsPath = path.join(targetDir, "settings.json");
|
|
100
|
-
let settings = {};
|
|
101
|
-
if (fs.existsSync(settingsPath)) {
|
|
102
|
-
settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
103
|
-
}
|
|
104
|
-
settings["statusLine"] = { type: "command", command: "python .claude/sd-statusline.py" };
|
|
105
|
-
const sdSessionEntry = {
|
|
106
|
-
matcher: "startup|resume|clear|compact",
|
|
107
|
-
hooks: [{ type: "command", command: "bash .claude/sd-session-start.sh" }]
|
|
108
|
-
};
|
|
109
|
-
const sessionStart = settings["SessionStart"];
|
|
110
|
-
if (sessionStart == null) {
|
|
111
|
-
settings["SessionStart"] = [sdSessionEntry];
|
|
112
|
-
} else {
|
|
113
|
-
const idx = sessionStart.findIndex(
|
|
114
|
-
(entry) => entry.hooks?.some((hook) => hook.command.includes("sd-session-start"))
|
|
115
|
-
);
|
|
116
|
-
if (idx >= 0) {
|
|
117
|
-
sessionStart[idx] = sdSessionEntry;
|
|
118
|
-
} else {
|
|
119
|
-
sessionStart.push(sdSessionEntry);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
123
|
-
}
|
|
124
|
-
export {
|
|
125
|
-
runInstall
|
|
126
|
-
};
|
|
127
|
-
//# sourceMappingURL=install.js.map
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/commands/install.ts"],
|
|
4
|
-
"mappings": "AAIA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAEvB,SAAS,aAAmB;AACjC,MAAI;AACF,UAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAE7D,UAAM,UAAU,KAAK,QAAQ,WAAW,OAAO;AAC/C,UAAM,YAAY,KAAK,KAAK,SAAS,QAAQ;AAE7C,UAAM,cAAc,gBAAgB,SAAS;AAC7C,QAAI,eAAe,MAAM;AAEvB,cAAQ,IAAI,2EAA2E;AACvF;AAAA,IACF;AAGA,QAAI,4BAA4B,aAAa,OAAO,GAAG;AACrD;AAAA,IACF;AAGA,QAAI,CAAC,GAAG,WAAW,SAAS,GAAG;AAC7B;AAAA,IACF;AAEA,UAAM,gBAAgB,iBAAiB,SAAS;AAChD,QAAI,cAAc,WAAW,GAAG;AAC9B;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,KAAK,aAAa,SAAS;AAElD,mBAAe,SAAS;AACxB,kBAAc,WAAW,WAAW,aAAa;AACjD,kBAAc,SAAS;AAGvB,YAAQ,IAAI,mCAAmC,cAAc,MAAM,gBAAgB;AAAA,EACrF,SAAS,KAAK;AAGZ,YAAQ,KAAK,8CAA+C,IAAc,OAAO;AAAA,EACnF;AACF;AAGA,SAAS,gBAAgB,SAAqC;AAC5D,MAAI,QAAQ,IAAI,UAAU,KAAK,MAAM;AACnC,WAAO,QAAQ,IAAI,UAAU;AAAA,EAC/B;AAEA,QAAM,MAAM,KAAK;AACjB,QAAM,SAAS,MAAM,iBAAiB;AACtC,QAAM,MAAM,QAAQ,QAAQ,MAAM;AAClC,SAAO,QAAQ,KAAK,QAAQ,UAAU,GAAG,GAAG,IAAI;AAClD;AAGA,SAAS,4BAA4B,aAAqB,SAA0B;AAClF,QAAM,iBAAiB,KAAK,KAAK,aAAa,cAAc;AAC5D,MAAI,CAAC,GAAG,WAAW,cAAc,EAAG,QAAO;AAE3C,QAAM,aAAa,KAAK,MAAM,GAAG,aAAa,gBAAgB,OAAO,CAAC;AAItE,MAAI,WAAW,SAAS,WAAY,QAAO;AAE3C,QAAM,kBAAkB,KAAK,KAAK,SAAS,cAAc;AACzD,MAAI,CAAC,GAAG,WAAW,eAAe,EAAG,QAAO;AAE5C,QAAM,cAAc,KAAK,MAAM,GAAG,aAAa,iBAAiB,OAAO,CAAC;AAIxE,QAAM,eAAe,WAAW,SAAS,MAAM,GAAG,EAAE,CAAC;AACrD,QAAM,gBAAgB,YAAY,SAAS,MAAM,GAAG,EAAE,CAAC;AACvD,SAAO,gBAAgB,QAAQ,iBAAiB;AAClD;AAGA,SAAS,iBAAiB,WAA6B;AACrD,QAAM,UAAoB,CAAC;AAG3B,aAAW,QAAQ,GAAG,YAAY,SAAS,GAAG;AAC5C,QAAI,KAAK,WAAW,KAAK,GAAG;AAC1B,cAAQ,KAAK,IAAI;AAAA,IACnB;AAAA,EACF;AAGA,aAAW,UAAU,GAAG,YAAY,WAAW,EAAE,eAAe,KAAK,CAAC,GAAG;AACvE,QAAI,CAAC,OAAO,YAAY,KAAK,OAAO,KAAK,WAAW,KAAK,EAAG;AAC5D,UAAM,UAAU,KAAK,KAAK,WAAW,OAAO,IAAI;AAChD,eAAW,QAAQ,GAAG,YAAY,OAAO,GAAG;AAC1C,UAAI,KAAK,WAAW,KAAK,GAAG;AAC1B,gBAAQ,KAAK,KAAK,KAAK,OAAO,MAAM,IAAI,CAAC;AAAA,MAC3C;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAGA,SAAS,eAAe,WAAyB;AAC/C,MAAI,CAAC,GAAG,WAAW,SAAS,EAAG;AAG/B,aAAW,QAAQ,GAAG,YAAY,SAAS,GAAG;AAC5C,QAAI,KAAK,WAAW,KAAK,GAAG;AAC1B,SAAG,OAAO,KAAK,KAAK,WAAW,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,IAC3D;AAAA,EACF;AAGA,aAAW,UAAU,GAAG,YAAY,WAAW,EAAE,eAAe,KAAK,CAAC,GAAG;AACvE,QAAI,CAAC,OAAO,YAAY,KAAK,OAAO,KAAK,WAAW,KAAK,EAAG;AAC5D,UAAM,UAAU,KAAK,KAAK,WAAW,OAAO,IAAI;AAChD,eAAW,QAAQ,GAAG,YAAY,OAAO,GAAG;AAC1C,UAAI,KAAK,WAAW,KAAK,GAAG;AAC1B,WAAG,OAAO,KAAK,KAAK,SAAS,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AAAA,MACzD;AAAA,IACF;AAAA,EACF;AACF;AAGA,SAAS,cAAc,WAAmB,WAAmB,SAAyB;AACpF,KAAG,UAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AAC3C,aAAW,SAAS,SAAS;AAC3B,UAAM,MAAM,KAAK,KAAK,WAAW,KAAK;AACtC,UAAM,OAAO,KAAK,KAAK,WAAW,KAAK;AACvC,OAAG,UAAU,KAAK,QAAQ,IAAI,GAAG,EAAE,WAAW,KAAK,CAAC;AACpD,OAAG,OAAO,KAAK,MAAM,EAAE,WAAW,KAAK,CAAC;AAAA,EAC1C;AACF;AAGA,SAAS,cAAc,WAAyB;AAC9C,QAAM,eAAe,KAAK,KAAK,WAAW,eAAe;AAEzD,MAAI,WAAoC,CAAC;AACzC,MAAI,GAAG,WAAW,YAAY,GAAG;AAC/B,eAAW,KAAK,MAAM,GAAG,aAAa,cAAc,OAAO,CAAC;AAAA,EAC9D;AAGA,WAAS,YAAY,IAAI,EAAE,MAAM,WAAW,SAAS,kCAAkC;AAGvF,QAAM,iBAAiB;AAAA,IACrB,SAAS;AAAA,IACT,OAAO,CAAC,EAAE,MAAM,WAAW,SAAS,mCAAmC,CAAC;AAAA,EAC1E;AAEA,QAAM,eAAe,SAAS,cAAc;AAI5C,MAAI,gBAAgB,MAAM;AACxB,aAAS,cAAc,IAAI,CAAC,cAAc;AAAA,EAC5C,OAAO;AACL,UAAM,MAAM,aAAa;AAAA,MAAU,CAAC,UAClC,MAAM,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,SAAS,kBAAkB,CAAC;AAAA,IACvE;AACA,QAAI,OAAO,GAAG;AACZ,mBAAa,GAAG,IAAI;AAAA,IACtB,OAAO;AACL,mBAAa,KAAK,cAAc;AAAA,IAClC;AAAA,EACF;AAEA,KAAG,cAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AACzE;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
package/dist/index.d.ts
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export * from "./commands/install.js";
|
|
2
|
-
export * from "./commands/auth-utils.js";
|
|
3
|
-
export * from "./commands/auth-add.js";
|
|
4
|
-
export * from "./commands/auth-use.js";
|
|
5
|
-
export * from "./commands/auth-list.js";
|
|
6
|
-
export * from "./commands/auth-remove.js";
|
|
7
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC"}
|
package/dist/index.js
DELETED
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export * from "./commands/install.js";
|
|
2
|
-
export * from "./commands/auth-utils.js";
|
|
3
|
-
export * from "./commands/auth-add.js";
|
|
4
|
-
export * from "./commands/auth-use.js";
|
|
5
|
-
export * from "./commands/auth-list.js";
|
|
6
|
-
export * from "./commands/auth-remove.js";
|
|
7
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
package/dist/sd-claude.d.ts
DELETED
package/dist/sd-claude.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"sd-claude.d.ts","sourceRoot":"","sources":["../src/sd-claude.ts"],"names":[],"mappings":""}
|
package/dist/sd-claude.js
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import yargs from "yargs";
|
|
3
|
-
import { hideBin } from "yargs/helpers";
|
|
4
|
-
import { runInstall } from "./commands/install.js";
|
|
5
|
-
import { runAuthAdd } from "./commands/auth-add.js";
|
|
6
|
-
import { runAuthUse } from "./commands/auth-use.js";
|
|
7
|
-
import { runAuthList } from "./commands/auth-list.js";
|
|
8
|
-
import { runAuthRemove } from "./commands/auth-remove.js";
|
|
9
|
-
await yargs(hideBin(process.argv)).help("help", "Help").alias("help", "h").command(
|
|
10
|
-
"install",
|
|
11
|
-
"Installs Claude Code assets to the project.",
|
|
12
|
-
(cmd) => cmd.version(false).hide("help"),
|
|
13
|
-
() => {
|
|
14
|
-
runInstall();
|
|
15
|
-
}
|
|
16
|
-
).command(
|
|
17
|
-
"auth",
|
|
18
|
-
"Manages Claude account profiles.",
|
|
19
|
-
(cmd) => cmd.version(false).hide("help").command(
|
|
20
|
-
"add <name>",
|
|
21
|
-
"Saves the currently logged-in account",
|
|
22
|
-
(sub) => sub.positional("name", {
|
|
23
|
-
type: "string",
|
|
24
|
-
demandOption: true
|
|
25
|
-
}),
|
|
26
|
-
(argv) => {
|
|
27
|
-
try {
|
|
28
|
-
runAuthAdd(argv.name);
|
|
29
|
-
} catch (err) {
|
|
30
|
-
console.error(err.message);
|
|
31
|
-
process.exit(1);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
).command(
|
|
35
|
-
"use <name>",
|
|
36
|
-
"Switches to a saved account",
|
|
37
|
-
(sub) => sub.positional("name", {
|
|
38
|
-
type: "string",
|
|
39
|
-
demandOption: true
|
|
40
|
-
}),
|
|
41
|
-
(argv) => {
|
|
42
|
-
try {
|
|
43
|
-
runAuthUse(argv.name);
|
|
44
|
-
} catch (err) {
|
|
45
|
-
console.error(err.message);
|
|
46
|
-
process.exit(1);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
).command(
|
|
50
|
-
"list",
|
|
51
|
-
"Displays the list of saved accounts",
|
|
52
|
-
(sub) => sub,
|
|
53
|
-
async () => {
|
|
54
|
-
try {
|
|
55
|
-
await runAuthList();
|
|
56
|
-
} catch (err) {
|
|
57
|
-
console.error(err.message);
|
|
58
|
-
process.exit(1);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
).command(
|
|
62
|
-
"remove <name>",
|
|
63
|
-
"Removes a saved account",
|
|
64
|
-
(sub) => sub.positional("name", {
|
|
65
|
-
type: "string",
|
|
66
|
-
demandOption: true
|
|
67
|
-
}),
|
|
68
|
-
(argv) => {
|
|
69
|
-
try {
|
|
70
|
-
runAuthRemove(argv.name);
|
|
71
|
-
} catch (err) {
|
|
72
|
-
console.error(err.message);
|
|
73
|
-
process.exit(1);
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
).demandCommand(1, "Please specify an auth subcommand.")
|
|
77
|
-
).demandCommand(1, "Please specify a command.").strict().parse();
|
|
78
|
-
//# sourceMappingURL=sd-claude.js.map
|
package/dist/sd-claude.js.map
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/sd-claude.ts"],
|
|
4
|
-
"mappings": ";AAEA,OAAO,WAAW;AAClB,SAAS,eAAe;AACxB,SAAS,kBAAkB;AAC3B,SAAS,kBAAkB;AAC3B,SAAS,kBAAkB;AAC3B,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAE9B,MAAM,MAAM,QAAQ,QAAQ,IAAI,CAAC,EAC9B,KAAK,QAAQ,MAAM,EACnB,MAAM,QAAQ,GAAG,EACjB;AAAA,EACC;AAAA,EACA;AAAA,EACA,CAAC,QAAQ,IAAI,QAAQ,KAAK,EAAE,KAAK,MAAM;AAAA,EACvC,MAAM;AACJ,eAAW;AAAA,EACb;AACF,EACC;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAoC,CAAC,QACpD,IACG,QAAQ,KAAK,EACb,KAAK,MAAM,EACX;AAAA,IACC;AAAA,IACA;AAAA,IACA,CAAC,QACC,IAAI,WAAW,QAAQ;AAAA,MACrB,MAAM;AAAA,MACN,cAAc;AAAA,IAChB,CAAC;AAAA,IACH,CAAC,SAAS;AACR,UAAI;AACF,mBAAW,KAAK,IAAI;AAAA,MACtB,SAAS,KAAK;AAEZ,gBAAQ,MAAO,IAAc,OAAO;AACpC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF,EACC;AAAA,IACC;AAAA,IACA;AAAA,IACA,CAAC,QACC,IAAI,WAAW,QAAQ;AAAA,MACrB,MAAM;AAAA,MACN,cAAc;AAAA,IAChB,CAAC;AAAA,IACH,CAAC,SAAS;AACR,UAAI;AACF,mBAAW,KAAK,IAAI;AAAA,MACtB,SAAS,KAAK;AAEZ,gBAAQ,MAAO,IAAc,OAAO;AACpC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF,EACC;AAAA,IACC;AAAA,IACA;AAAA,IACA,CAAC,QAAQ;AAAA,IACT,YAAY;AACV,UAAI;AACF,cAAM,YAAY;AAAA,MACpB,SAAS,KAAK;AAEZ,gBAAQ,MAAO,IAAc,OAAO;AACpC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF,EACC;AAAA,IACC;AAAA,IACA;AAAA,IACA,CAAC,QACC,IAAI,WAAW,QAAQ;AAAA,MACrB,MAAM;AAAA,MACN,cAAc;AAAA,IAChB,CAAC;AAAA,IACH,CAAC,SAAS;AACR,UAAI;AACF,sBAAc,KAAK,IAAI;AAAA,MACzB,SAAS,KAAK;AAEZ,gBAAQ,MAAO,IAAc,OAAO;AACpC,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF;AAAA,EACF,EACC,cAAc,GAAG,oCAAoC;AAC1D,EACC,cAAc,GAAG,2BAA2B,EAC5C,OAAO,EACP,MAAM;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
package/src/commands/auth-add.ts
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import {
|
|
4
|
-
validateName,
|
|
5
|
-
profileExists,
|
|
6
|
-
getProfileDir,
|
|
7
|
-
readCurrentAuth,
|
|
8
|
-
readCurrentCredentials,
|
|
9
|
-
} from "./auth-utils.js";
|
|
10
|
-
|
|
11
|
-
export function runAuthAdd(name: string, homeDir?: string): void {
|
|
12
|
-
validateName(name);
|
|
13
|
-
|
|
14
|
-
if (profileExists(name, homeDir)) {
|
|
15
|
-
throw new Error(
|
|
16
|
-
`Profile '${name}' already exists. Remove it first with: sd-claude auth remove ${name}`,
|
|
17
|
-
);
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const { oauthAccount, userID } = readCurrentAuth(homeDir);
|
|
21
|
-
const credentials = readCurrentCredentials(homeDir);
|
|
22
|
-
|
|
23
|
-
const profileDir = getProfileDir(name, homeDir);
|
|
24
|
-
fs.mkdirSync(profileDir, { recursive: true });
|
|
25
|
-
|
|
26
|
-
fs.writeFileSync(
|
|
27
|
-
path.join(profileDir, "auth.json"),
|
|
28
|
-
JSON.stringify({ oauthAccount, userID }, null, 2),
|
|
29
|
-
);
|
|
30
|
-
|
|
31
|
-
fs.writeFileSync(path.join(profileDir, "credentials.json"), JSON.stringify(credentials, null, 2));
|
|
32
|
-
|
|
33
|
-
const email = oauthAccount["emailAddress"] as string | undefined;
|
|
34
|
-
// eslint-disable-next-line no-console
|
|
35
|
-
console.log(`Saved profile '${name}' (${email ?? userID})`);
|
|
36
|
-
}
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { listProfiles, getCurrentUserID, getProfileDir } from "./auth-utils.js";
|
|
4
|
-
|
|
5
|
-
const FETCH_TIMEOUT_MS = 5000;
|
|
6
|
-
|
|
7
|
-
interface UsageData {
|
|
8
|
-
utilization?: number;
|
|
9
|
-
resets_at?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
interface UsageResponse {
|
|
13
|
-
five_hour?: UsageData;
|
|
14
|
-
daily?: UsageData;
|
|
15
|
-
seven_day?: UsageData;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
async function fetchUsage(accessToken: string): Promise<UsageResponse | undefined> {
|
|
19
|
-
try {
|
|
20
|
-
const controller = new AbortController();
|
|
21
|
-
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
22
|
-
|
|
23
|
-
const response = await fetch("https://api.anthropic.com/api/oauth/usage", {
|
|
24
|
-
headers: {
|
|
25
|
-
Authorization: `Bearer ${accessToken}`,
|
|
26
|
-
"anthropic-beta": "oauth-2025-04-20",
|
|
27
|
-
},
|
|
28
|
-
signal: controller.signal,
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
clearTimeout(timeout);
|
|
32
|
-
|
|
33
|
-
if (!response.ok) {
|
|
34
|
-
return undefined;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return (await response.json()) as UsageResponse;
|
|
38
|
-
} catch {
|
|
39
|
-
return undefined;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
function formatTimeRemaining(isoDate: string | undefined): string {
|
|
44
|
-
if (isoDate == null) return "";
|
|
45
|
-
try {
|
|
46
|
-
const resetTime = new Date(isoDate).getTime();
|
|
47
|
-
if (Number.isNaN(resetTime)) return "";
|
|
48
|
-
|
|
49
|
-
const diffMs = resetTime - Date.now();
|
|
50
|
-
if (diffMs <= 0) return "";
|
|
51
|
-
|
|
52
|
-
const diffMinutes = Math.floor(diffMs / (1000 * 60));
|
|
53
|
-
const diffHours = Math.floor(diffMinutes / 60);
|
|
54
|
-
const days = Math.floor(diffHours / 24);
|
|
55
|
-
const hours = diffHours % 24;
|
|
56
|
-
const minutes = diffMinutes % 60;
|
|
57
|
-
|
|
58
|
-
if (days > 0) return `${String(days)}d${String(hours)}h`;
|
|
59
|
-
if (hours > 0) return `${String(hours)}h${String(minutes)}m`;
|
|
60
|
-
return `${String(minutes)}m`;
|
|
61
|
-
} catch {
|
|
62
|
-
return "";
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function formatUsage(label: string, data: UsageData | undefined): string {
|
|
67
|
-
if (data == null) return `${label}: ?`;
|
|
68
|
-
const pct = data.utilization != null ? `${String(Math.round(data.utilization))}%` : "?";
|
|
69
|
-
const remaining = formatTimeRemaining(data.resets_at);
|
|
70
|
-
return remaining ? `${label}: ${pct}(${remaining})` : `${label}: ${pct}`;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export async function runAuthList(homeDir?: string): Promise<void> {
|
|
74
|
-
const profiles = listProfiles(homeDir);
|
|
75
|
-
|
|
76
|
-
if (profiles.length === 0) {
|
|
77
|
-
// eslint-disable-next-line no-console
|
|
78
|
-
console.log("No saved profiles.");
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
const currentUserID = getCurrentUserID(homeDir);
|
|
83
|
-
const sorted = [...profiles].sort((a, b) => a.localeCompare(b));
|
|
84
|
-
|
|
85
|
-
const results = await Promise.all(
|
|
86
|
-
sorted.map(async (name) => {
|
|
87
|
-
const profileDir = getProfileDir(name, homeDir);
|
|
88
|
-
|
|
89
|
-
const authData = JSON.parse(
|
|
90
|
-
fs.readFileSync(path.join(profileDir, "auth.json"), "utf-8"),
|
|
91
|
-
) as Record<string, unknown>;
|
|
92
|
-
|
|
93
|
-
const credData = JSON.parse(
|
|
94
|
-
fs.readFileSync(path.join(profileDir, "credentials.json"), "utf-8"),
|
|
95
|
-
) as Record<string, unknown>;
|
|
96
|
-
|
|
97
|
-
const oauthAccount = authData["oauthAccount"] as Record<string, unknown> | undefined;
|
|
98
|
-
const email = (oauthAccount?.["emailAddress"] as string | undefined) ?? "";
|
|
99
|
-
const userID = authData["userID"] as string | undefined;
|
|
100
|
-
const oauth = credData["claudeAiOauth"] as Record<string, unknown> | undefined;
|
|
101
|
-
|
|
102
|
-
let expiresStr = "unknown";
|
|
103
|
-
if (oauth != null && typeof oauth["expiresAt"] === "number") {
|
|
104
|
-
const d = new Date(oauth["expiresAt"]);
|
|
105
|
-
expiresStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const isActive = currentUserID != null && userID === currentUserID;
|
|
109
|
-
const prefix = isActive ? "*" : " ";
|
|
110
|
-
|
|
111
|
-
// Fetch usage via OAuth token
|
|
112
|
-
const accessToken = oauth?.["accessToken"] as string | undefined;
|
|
113
|
-
const expiresAt = oauth?.["expiresAt"];
|
|
114
|
-
const tokenExpired = typeof expiresAt === "number" && Date.now() > expiresAt;
|
|
115
|
-
const usage =
|
|
116
|
-
accessToken != null && !tokenExpired ? await fetchUsage(accessToken) : undefined;
|
|
117
|
-
|
|
118
|
-
const dailyData = usage?.daily ?? usage?.five_hour;
|
|
119
|
-
const fiveHourStr = formatUsage("5h", dailyData);
|
|
120
|
-
const weekStr = formatUsage("7d", usage?.seven_day);
|
|
121
|
-
|
|
122
|
-
return `${prefix} ${name} (${email}) expires: ${expiresStr} │ ${fiveHourStr} │ ${weekStr}`;
|
|
123
|
-
}),
|
|
124
|
-
);
|
|
125
|
-
|
|
126
|
-
for (const line of results) {
|
|
127
|
-
// eslint-disable-next-line no-console
|
|
128
|
-
console.log(line);
|
|
129
|
-
}
|
|
130
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { validateName, profileExists, getProfileDir, getCurrentUserID } from "./auth-utils.js";
|
|
4
|
-
|
|
5
|
-
export function runAuthRemove(name: string, homeDir?: string): void {
|
|
6
|
-
validateName(name);
|
|
7
|
-
|
|
8
|
-
if (!profileExists(name, homeDir)) {
|
|
9
|
-
throw new Error(`Profile '${name}' not found.`);
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
const profileDir = getProfileDir(name, homeDir);
|
|
13
|
-
const authJsonPath = path.join(profileDir, "auth.json");
|
|
14
|
-
const authData = JSON.parse(fs.readFileSync(authJsonPath, "utf-8")) as { userID: string };
|
|
15
|
-
|
|
16
|
-
const currentUserID = getCurrentUserID(homeDir);
|
|
17
|
-
if (currentUserID != null && currentUserID === authData.userID) {
|
|
18
|
-
// eslint-disable-next-line no-console
|
|
19
|
-
console.warn(`Warning: '${name}' is currently active.`);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
fs.rmSync(profileDir, { recursive: true });
|
|
23
|
-
|
|
24
|
-
// eslint-disable-next-line no-console
|
|
25
|
-
console.log(`Removed profile '${name}'`);
|
|
26
|
-
}
|
package/src/commands/auth-use.ts
DELETED
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import os from "os";
|
|
4
|
-
import { validateName, profileExists, getProfileDir } from "./auth-utils.js";
|
|
5
|
-
|
|
6
|
-
export function runAuthUse(name: string, homeDir?: string): void {
|
|
7
|
-
validateName(name);
|
|
8
|
-
|
|
9
|
-
if (!profileExists(name, homeDir)) {
|
|
10
|
-
throw new Error(`Profile '${name}' not found.`);
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
const profileDir = getProfileDir(name, homeDir);
|
|
14
|
-
const home = homeDir ?? os.homedir();
|
|
15
|
-
|
|
16
|
-
// Read saved auth.json and credentials.json from profile directory
|
|
17
|
-
const authJson = JSON.parse(fs.readFileSync(path.join(profileDir, "auth.json"), "utf-8")) as {
|
|
18
|
-
oauthAccount: Record<string, unknown>;
|
|
19
|
-
userID: string;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const savedCredentials = JSON.parse(
|
|
23
|
-
fs.readFileSync(path.join(profileDir, "credentials.json"), "utf-8"),
|
|
24
|
-
) as Record<string, unknown>;
|
|
25
|
-
|
|
26
|
-
// Check token expiry
|
|
27
|
-
const claudeAiOauth = savedCredentials["claudeAiOauth"] as { expiresAt?: number } | undefined;
|
|
28
|
-
if (claudeAiOauth?.expiresAt != null && claudeAiOauth.expiresAt < Date.now()) {
|
|
29
|
-
// eslint-disable-next-line no-console
|
|
30
|
-
console.warn("Warning: Token expired. Run /login after switching.");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Read ~/.claude.json, replace ONLY oauthAccount and userID, write back
|
|
34
|
-
const claudeJsonPath = path.join(home, ".claude.json");
|
|
35
|
-
const claudeData = JSON.parse(fs.readFileSync(claudeJsonPath, "utf-8")) as Record<
|
|
36
|
-
string,
|
|
37
|
-
unknown
|
|
38
|
-
>;
|
|
39
|
-
|
|
40
|
-
claudeData["oauthAccount"] = authJson.oauthAccount;
|
|
41
|
-
claudeData["userID"] = authJson.userID;
|
|
42
|
-
|
|
43
|
-
fs.writeFileSync(claudeJsonPath, JSON.stringify(claudeData, null, 2));
|
|
44
|
-
|
|
45
|
-
// Replace ~/.claude/.credentials.json entirely with saved credentials
|
|
46
|
-
const credentialsPath = path.join(home, ".claude", ".credentials.json");
|
|
47
|
-
fs.writeFileSync(credentialsPath, JSON.stringify(savedCredentials, null, 2));
|
|
48
|
-
|
|
49
|
-
// Log the switch
|
|
50
|
-
const email = (authJson.oauthAccount["emailAddress"] as string | undefined) ?? "unknown";
|
|
51
|
-
// eslint-disable-next-line no-console
|
|
52
|
-
console.log(`Switched to ${name} (${email})`);
|
|
53
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import os from "os";
|
|
4
|
-
|
|
5
|
-
const NAME_PATTERN = /^[a-z0-9_-]+$/;
|
|
6
|
-
|
|
7
|
-
export function validateName(name: string): void {
|
|
8
|
-
if (!NAME_PATTERN.test(name)) {
|
|
9
|
-
throw new Error(
|
|
10
|
-
`Invalid name '${name}'. Use only lowercase letters, numbers, hyphens, underscores.`,
|
|
11
|
-
);
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function getProfileDir(name: string, homeDir?: string): string {
|
|
16
|
-
return path.join(homeDir ?? os.homedir(), ".sd-claude", "auth", name);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export function profileExists(name: string, homeDir?: string): boolean {
|
|
20
|
-
return fs.existsSync(getProfileDir(name, homeDir));
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export function listProfiles(homeDir?: string): string[] {
|
|
24
|
-
const authDir = path.join(homeDir ?? os.homedir(), ".sd-claude", "auth");
|
|
25
|
-
if (!fs.existsSync(authDir)) {
|
|
26
|
-
return [];
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return fs
|
|
30
|
-
.readdirSync(authDir, { withFileTypes: true })
|
|
31
|
-
.filter((entry) => entry.isDirectory())
|
|
32
|
-
.map((entry) => entry.name);
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export function readCurrentAuth(homeDir?: string): {
|
|
36
|
-
oauthAccount: Record<string, unknown>;
|
|
37
|
-
userID: string;
|
|
38
|
-
} {
|
|
39
|
-
const claudeJsonPath = path.join(homeDir ?? os.homedir(), ".claude.json");
|
|
40
|
-
const data = JSON.parse(fs.readFileSync(claudeJsonPath, "utf-8")) as Record<string, unknown>;
|
|
41
|
-
|
|
42
|
-
const oauthAccount = data["oauthAccount"] as Record<string, unknown> | undefined;
|
|
43
|
-
const userID = data["userID"] as string | undefined;
|
|
44
|
-
|
|
45
|
-
if (oauthAccount == null || userID == null) {
|
|
46
|
-
throw new Error("Not logged in. Run /login first.");
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
return { oauthAccount, userID };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export function readCurrentCredentials(homeDir?: string): Record<string, unknown> {
|
|
53
|
-
const credentialsPath = path.join(homeDir ?? os.homedir(), ".claude", ".credentials.json");
|
|
54
|
-
return JSON.parse(fs.readFileSync(credentialsPath, "utf-8")) as Record<string, unknown>;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function getCurrentUserID(homeDir?: string): string | undefined {
|
|
58
|
-
const claudeJsonPath = path.join(homeDir ?? os.homedir(), ".claude.json");
|
|
59
|
-
try {
|
|
60
|
-
const data = JSON.parse(fs.readFileSync(claudeJsonPath, "utf-8")) as Record<string, unknown>;
|
|
61
|
-
return data["userID"] as string | undefined;
|
|
62
|
-
} catch {
|
|
63
|
-
return undefined;
|
|
64
|
-
}
|
|
65
|
-
}
|