@simplysm/sd-claude 13.0.82 → 13.0.84
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/rules/sd-claude-rules.md +10 -6
- package/claude/rules/sd-simplysm-usage.md +5 -5
- package/claude/skills/sd-api-review/SKILL.md +51 -51
- package/claude/skills/sd-check/SKILL.md +40 -40
- package/claude/skills/sd-commit/SKILL.md +31 -31
- package/claude/skills/sd-debug/SKILL.md +77 -68
- package/claude/skills/sd-document/SKILL.md +56 -56
- package/claude/skills/sd-email-analyze/SKILL.md +22 -22
- package/claude/skills/sd-init/SKILL.md +63 -63
- package/claude/skills/sd-plan/SKILL.md +62 -61
- package/claude/skills/sd-readme/SKILL.md +59 -59
- package/claude/skills/sd-review/SKILL.md +35 -35
- package/claude/skills/sd-simplify/SKILL.md +30 -30
- 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,22 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import { validateName, profileExists, getProfileDir, getCurrentUserID } from "./auth-utils.js";
|
|
4
|
-
function runAuthRemove(name, homeDir) {
|
|
5
|
-
validateName(name);
|
|
6
|
-
if (!profileExists(name, homeDir)) {
|
|
7
|
-
throw new Error(`Profile '${name}' not found.`);
|
|
8
|
-
}
|
|
9
|
-
const profileDir = getProfileDir(name, homeDir);
|
|
10
|
-
const authJsonPath = path.join(profileDir, "auth.json");
|
|
11
|
-
const authData = JSON.parse(fs.readFileSync(authJsonPath, "utf-8"));
|
|
12
|
-
const currentUserID = getCurrentUserID(homeDir);
|
|
13
|
-
if (currentUserID != null && currentUserID === authData.userID) {
|
|
14
|
-
console.warn(`Warning: '${name}' is currently active.`);
|
|
15
|
-
}
|
|
16
|
-
fs.rmSync(profileDir, { recursive: true });
|
|
17
|
-
console.log(`Removed profile '${name}'`);
|
|
18
|
-
}
|
|
19
|
-
export {
|
|
20
|
-
runAuthRemove
|
|
21
|
-
};
|
|
22
|
-
//# sourceMappingURL=auth-remove.js.map
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/commands/auth-remove.ts"],
|
|
4
|
-
"mappings": "AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,cAAc,eAAe,eAAe,wBAAwB;AAEtE,SAAS,cAAc,MAAc,SAAwB;AAClE,eAAa,IAAI;AAEjB,MAAI,CAAC,cAAc,MAAM,OAAO,GAAG;AACjC,UAAM,IAAI,MAAM,YAAY,IAAI,cAAc;AAAA,EAChD;AAEA,QAAM,aAAa,cAAc,MAAM,OAAO;AAC9C,QAAM,eAAe,KAAK,KAAK,YAAY,WAAW;AACtD,QAAM,WAAW,KAAK,MAAM,GAAG,aAAa,cAAc,OAAO,CAAC;AAElE,QAAM,gBAAgB,iBAAiB,OAAO;AAC9C,MAAI,iBAAiB,QAAQ,kBAAkB,SAAS,QAAQ;AAE9D,YAAQ,KAAK,aAAa,IAAI,wBAAwB;AAAA,EACxD;AAEA,KAAG,OAAO,YAAY,EAAE,WAAW,KAAK,CAAC;AAGzC,UAAQ,IAAI,oBAAoB,IAAI,GAAG;AACzC;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-use.d.ts","sourceRoot":"","sources":["../../src/commands/auth-use.ts"],"names":[],"mappings":"AAKA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CA+C/D"}
|
|
@@ -1,33 +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
|
-
function runAuthUse(name, homeDir) {
|
|
6
|
-
validateName(name);
|
|
7
|
-
if (!profileExists(name, homeDir)) {
|
|
8
|
-
throw new Error(`Profile '${name}' not found.`);
|
|
9
|
-
}
|
|
10
|
-
const profileDir = getProfileDir(name, homeDir);
|
|
11
|
-
const home = homeDir ?? os.homedir();
|
|
12
|
-
const authJson = JSON.parse(fs.readFileSync(path.join(profileDir, "auth.json"), "utf-8"));
|
|
13
|
-
const savedCredentials = JSON.parse(
|
|
14
|
-
fs.readFileSync(path.join(profileDir, "credentials.json"), "utf-8")
|
|
15
|
-
);
|
|
16
|
-
const claudeAiOauth = savedCredentials["claudeAiOauth"];
|
|
17
|
-
if (claudeAiOauth?.expiresAt != null && claudeAiOauth.expiresAt < Date.now()) {
|
|
18
|
-
console.warn("Warning: Token expired. Run /login after switching.");
|
|
19
|
-
}
|
|
20
|
-
const claudeJsonPath = path.join(home, ".claude.json");
|
|
21
|
-
const claudeData = JSON.parse(fs.readFileSync(claudeJsonPath, "utf-8"));
|
|
22
|
-
claudeData["oauthAccount"] = authJson.oauthAccount;
|
|
23
|
-
claudeData["userID"] = authJson.userID;
|
|
24
|
-
fs.writeFileSync(claudeJsonPath, JSON.stringify(claudeData, null, 2));
|
|
25
|
-
const credentialsPath = path.join(home, ".claude", ".credentials.json");
|
|
26
|
-
fs.writeFileSync(credentialsPath, JSON.stringify(savedCredentials, null, 2));
|
|
27
|
-
const email = authJson.oauthAccount["emailAddress"] ?? "unknown";
|
|
28
|
-
console.log(`Switched to ${name} (${email})`);
|
|
29
|
-
}
|
|
30
|
-
export {
|
|
31
|
-
runAuthUse
|
|
32
|
-
};
|
|
33
|
-
//# sourceMappingURL=auth-use.js.map
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/commands/auth-use.ts"],
|
|
4
|
-
"mappings": "AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,QAAQ;AACf,SAAS,cAAc,eAAe,qBAAqB;AAEpD,SAAS,WAAW,MAAc,SAAwB;AAC/D,eAAa,IAAI;AAEjB,MAAI,CAAC,cAAc,MAAM,OAAO,GAAG;AACjC,UAAM,IAAI,MAAM,YAAY,IAAI,cAAc;AAAA,EAChD;AAEA,QAAM,aAAa,cAAc,MAAM,OAAO;AAC9C,QAAM,OAAO,WAAW,GAAG,QAAQ;AAGnC,QAAM,WAAW,KAAK,MAAM,GAAG,aAAa,KAAK,KAAK,YAAY,WAAW,GAAG,OAAO,CAAC;AAKxF,QAAM,mBAAmB,KAAK;AAAA,IAC5B,GAAG,aAAa,KAAK,KAAK,YAAY,kBAAkB,GAAG,OAAO;AAAA,EACpE;AAGA,QAAM,gBAAgB,iBAAiB,eAAe;AACtD,MAAI,eAAe,aAAa,QAAQ,cAAc,YAAY,KAAK,IAAI,GAAG;AAE5E,YAAQ,KAAK,qDAAqD;AAAA,EACpE;AAGA,QAAM,iBAAiB,KAAK,KAAK,MAAM,cAAc;AACrD,QAAM,aAAa,KAAK,MAAM,GAAG,aAAa,gBAAgB,OAAO,CAAC;AAKtE,aAAW,cAAc,IAAI,SAAS;AACtC,aAAW,QAAQ,IAAI,SAAS;AAEhC,KAAG,cAAc,gBAAgB,KAAK,UAAU,YAAY,MAAM,CAAC,CAAC;AAGpE,QAAM,kBAAkB,KAAK,KAAK,MAAM,WAAW,mBAAmB;AACtE,KAAG,cAAc,iBAAiB,KAAK,UAAU,kBAAkB,MAAM,CAAC,CAAC;AAG3E,QAAM,QAAS,SAAS,aAAa,cAAc,KAA4B;AAE/E,UAAQ,IAAI,eAAe,IAAI,KAAK,KAAK,GAAG;AAC9C;",
|
|
5
|
-
"names": []
|
|
6
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
export declare function validateName(name: string): void;
|
|
2
|
-
export declare function getProfileDir(name: string, homeDir?: string): string;
|
|
3
|
-
export declare function profileExists(name: string, homeDir?: string): boolean;
|
|
4
|
-
export declare function listProfiles(homeDir?: string): string[];
|
|
5
|
-
export declare function readCurrentAuth(homeDir?: string): {
|
|
6
|
-
oauthAccount: Record<string, unknown>;
|
|
7
|
-
userID: string;
|
|
8
|
-
};
|
|
9
|
-
export declare function readCurrentCredentials(homeDir?: string): Record<string, unknown>;
|
|
10
|
-
export declare function getCurrentUserID(homeDir?: string): string | undefined;
|
|
11
|
-
//# sourceMappingURL=auth-utils.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth-utils.d.ts","sourceRoot":"","sources":["../../src/commands/auth-utils.ts"],"names":[],"mappings":"AAMA,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAM/C;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAEpE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAErE;AAED,wBAAgB,YAAY,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAUvD;AAED,wBAAgB,eAAe,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG;IACjD,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;CAChB,CAYA;AAED,wBAAgB,sBAAsB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAGhF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAQrE"}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import os from "os";
|
|
4
|
-
const NAME_PATTERN = /^[a-z0-9_-]+$/;
|
|
5
|
-
function validateName(name) {
|
|
6
|
-
if (!NAME_PATTERN.test(name)) {
|
|
7
|
-
throw new Error(
|
|
8
|
-
`Invalid name '${name}'. Use only lowercase letters, numbers, hyphens, underscores.`
|
|
9
|
-
);
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
function getProfileDir(name, homeDir) {
|
|
13
|
-
return path.join(homeDir ?? os.homedir(), ".sd-claude", "auth", name);
|
|
14
|
-
}
|
|
15
|
-
function profileExists(name, homeDir) {
|
|
16
|
-
return fs.existsSync(getProfileDir(name, homeDir));
|
|
17
|
-
}
|
|
18
|
-
function listProfiles(homeDir) {
|
|
19
|
-
const authDir = path.join(homeDir ?? os.homedir(), ".sd-claude", "auth");
|
|
20
|
-
if (!fs.existsSync(authDir)) {
|
|
21
|
-
return [];
|
|
22
|
-
}
|
|
23
|
-
return fs.readdirSync(authDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
|
|
24
|
-
}
|
|
25
|
-
function readCurrentAuth(homeDir) {
|
|
26
|
-
const claudeJsonPath = path.join(homeDir ?? os.homedir(), ".claude.json");
|
|
27
|
-
const data = JSON.parse(fs.readFileSync(claudeJsonPath, "utf-8"));
|
|
28
|
-
const oauthAccount = data["oauthAccount"];
|
|
29
|
-
const userID = data["userID"];
|
|
30
|
-
if (oauthAccount == null || userID == null) {
|
|
31
|
-
throw new Error("Not logged in. Run /login first.");
|
|
32
|
-
}
|
|
33
|
-
return { oauthAccount, userID };
|
|
34
|
-
}
|
|
35
|
-
function readCurrentCredentials(homeDir) {
|
|
36
|
-
const credentialsPath = path.join(homeDir ?? os.homedir(), ".claude", ".credentials.json");
|
|
37
|
-
return JSON.parse(fs.readFileSync(credentialsPath, "utf-8"));
|
|
38
|
-
}
|
|
39
|
-
function getCurrentUserID(homeDir) {
|
|
40
|
-
const claudeJsonPath = path.join(homeDir ?? os.homedir(), ".claude.json");
|
|
41
|
-
try {
|
|
42
|
-
const data = JSON.parse(fs.readFileSync(claudeJsonPath, "utf-8"));
|
|
43
|
-
return data["userID"];
|
|
44
|
-
} catch {
|
|
45
|
-
return void 0;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
export {
|
|
49
|
-
getCurrentUserID,
|
|
50
|
-
getProfileDir,
|
|
51
|
-
listProfiles,
|
|
52
|
-
profileExists,
|
|
53
|
-
readCurrentAuth,
|
|
54
|
-
readCurrentCredentials,
|
|
55
|
-
validateName
|
|
56
|
-
};
|
|
57
|
-
//# sourceMappingURL=auth-utils.js.map
|
|
@@ -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
|
-
}
|