@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.
Files changed (51) hide show
  1. package/README.md +43 -0
  2. package/claude/skills/sd-plan/SKILL.md +4 -3
  3. package/package.json +3 -19
  4. package/scripts/postinstall.mjs +126 -9
  5. package/scripts/sd-entries.mjs +33 -0
  6. package/scripts/sync-claude-assets.mjs +4 -21
  7. package/dist/commands/auth-add.d.ts +0 -2
  8. package/dist/commands/auth-add.d.ts.map +0 -1
  9. package/dist/commands/auth-add.js +0 -32
  10. package/dist/commands/auth-add.js.map +0 -6
  11. package/dist/commands/auth-list.d.ts +0 -2
  12. package/dist/commands/auth-list.d.ts.map +0 -1
  13. package/dist/commands/auth-list.js +0 -95
  14. package/dist/commands/auth-list.js.map +0 -6
  15. package/dist/commands/auth-remove.d.ts +0 -2
  16. package/dist/commands/auth-remove.d.ts.map +0 -1
  17. package/dist/commands/auth-remove.js +0 -22
  18. package/dist/commands/auth-remove.js.map +0 -6
  19. package/dist/commands/auth-use.d.ts +0 -2
  20. package/dist/commands/auth-use.d.ts.map +0 -1
  21. package/dist/commands/auth-use.js +0 -33
  22. package/dist/commands/auth-use.js.map +0 -6
  23. package/dist/commands/auth-utils.d.ts +0 -11
  24. package/dist/commands/auth-utils.d.ts.map +0 -1
  25. package/dist/commands/auth-utils.js +0 -57
  26. package/dist/commands/auth-utils.js.map +0 -6
  27. package/dist/commands/install.d.ts +0 -2
  28. package/dist/commands/install.d.ts.map +0 -1
  29. package/dist/commands/install.js +0 -127
  30. package/dist/commands/install.js.map +0 -6
  31. package/dist/index.d.ts +0 -7
  32. package/dist/index.d.ts.map +0 -1
  33. package/dist/index.js +0 -7
  34. package/dist/index.js.map +0 -6
  35. package/dist/sd-claude.d.ts +0 -3
  36. package/dist/sd-claude.d.ts.map +0 -1
  37. package/dist/sd-claude.js +0 -78
  38. package/dist/sd-claude.js.map +0 -6
  39. package/src/commands/auth-add.ts +0 -36
  40. package/src/commands/auth-list.ts +0 -130
  41. package/src/commands/auth-remove.ts +0 -26
  42. package/src/commands/auth-use.ts +0 -53
  43. package/src/commands/auth-utils.ts +0 -65
  44. package/src/commands/install.ts +0 -183
  45. package/src/index.ts +0 -7
  46. package/src/sd-claude.ts +0 -98
  47. package/tests/auth-add.spec.ts +0 -74
  48. package/tests/auth-list.spec.ts +0 -198
  49. package/tests/auth-remove.spec.ts +0 -74
  50. package/tests/auth-use.spec.ts +0 -153
  51. 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,2 +0,0 @@
1
- export declare function runInstall(): void;
2
- //# sourceMappingURL=install.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/commands/install.ts"],"names":[],"mappings":"AAQA,wBAAgB,UAAU,IAAI,IAAI,CA0CjC"}
@@ -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": "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",
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
@@ -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
@@ -1,6 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../src/index.ts"],
4
- "mappings": "AACA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
5
- "names": []
6
- }
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
3
- //# sourceMappingURL=sd-claude.d.ts.map
@@ -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
@@ -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
- }
@@ -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
- }
@@ -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
- }