@simplysm/sd-claude 13.0.69 → 13.0.70

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 (78) hide show
  1. package/README.md +12 -601
  2. package/claude/agents/sd-api-reviewer.md +0 -1
  3. package/claude/agents/sd-code-reviewer.md +0 -1
  4. package/claude/agents/sd-code-simplifier.md +1 -1
  5. package/claude/agents/sd-security-reviewer.md +0 -1
  6. package/claude/refs/sd-angular.md +26 -26
  7. package/claude/refs/sd-orm-v12.md +17 -17
  8. package/claude/rules/sd-refs-linker.md +14 -14
  9. package/claude/sd-statusline.js +21 -21
  10. package/claude/skills/sd-api-name-review/SKILL.md +1 -2
  11. package/claude/skills/sd-brainstorm/SKILL.md +3 -4
  12. package/claude/skills/sd-check/SKILL.md +2 -2
  13. package/claude/skills/sd-commit/SKILL.md +1 -2
  14. package/claude/skills/sd-debug/SKILL.md +1 -2
  15. package/claude/skills/sd-discuss/SKILL.md +1 -3
  16. package/claude/skills/sd-document/SKILL.md +99 -0
  17. package/claude/skills/sd-document/extract_docx.py +92 -0
  18. package/claude/skills/sd-document/extract_pdf.py +102 -0
  19. package/claude/skills/sd-document/extract_pptx.py +77 -0
  20. package/claude/skills/sd-document/extract_xlsx.py +83 -0
  21. package/claude/skills/sd-email-analyze/SKILL.md +6 -6
  22. package/claude/skills/sd-plan/SKILL.md +1 -3
  23. package/claude/skills/sd-plan-dev/SKILL.md +94 -111
  24. package/claude/skills/sd-plan-dev/code-quality-reviewer-prompt.md +1 -1
  25. package/claude/skills/sd-plan-dev/final-review-prompt.md +1 -1
  26. package/claude/skills/sd-plan-dev/spec-reviewer-prompt.md +1 -1
  27. package/claude/skills/sd-readme/SKILL.md +107 -88
  28. package/claude/skills/sd-review/SKILL.md +14 -16
  29. package/claude/skills/sd-skill/SKILL.md +6 -317
  30. package/claude/skills/sd-skill/cso-guide.md +161 -0
  31. package/claude/skills/sd-skill/writing-guide.md +163 -0
  32. package/claude/skills/sd-tdd/SKILL.md +1 -3
  33. package/claude/skills/sd-use/SKILL.md +1 -3
  34. package/claude/skills/sd-worktree/SKILL.md +1 -2
  35. package/dist/commands/auth-add.d.ts +2 -0
  36. package/dist/commands/auth-add.d.ts.map +1 -0
  37. package/dist/commands/auth-add.js +32 -0
  38. package/dist/commands/auth-add.js.map +6 -0
  39. package/dist/commands/auth-list.d.ts +2 -0
  40. package/dist/commands/auth-list.d.ts.map +1 -0
  41. package/dist/commands/auth-list.js +37 -0
  42. package/dist/commands/auth-list.js.map +6 -0
  43. package/dist/commands/auth-remove.d.ts +2 -0
  44. package/dist/commands/auth-remove.d.ts.map +1 -0
  45. package/dist/commands/auth-remove.js +22 -0
  46. package/dist/commands/auth-remove.js.map +6 -0
  47. package/dist/commands/auth-use.d.ts +2 -0
  48. package/dist/commands/auth-use.d.ts.map +1 -0
  49. package/dist/commands/auth-use.js +33 -0
  50. package/dist/commands/auth-use.js.map +6 -0
  51. package/dist/commands/auth-utils.d.ts +11 -0
  52. package/dist/commands/auth-utils.d.ts.map +1 -0
  53. package/dist/commands/auth-utils.js +57 -0
  54. package/dist/commands/auth-utils.js.map +6 -0
  55. package/dist/commands/install.js +3 -3
  56. package/dist/commands/install.js.map +1 -1
  57. package/dist/index.d.ts +5 -0
  58. package/dist/index.d.ts.map +1 -1
  59. package/dist/index.js +5 -0
  60. package/dist/index.js.map +1 -1
  61. package/dist/sd-claude.js +68 -3
  62. package/dist/sd-claude.js.map +1 -1
  63. package/package.json +3 -2
  64. package/scripts/sync-claude-assets.mjs +1 -1
  65. package/src/commands/auth-add.ts +36 -0
  66. package/src/commands/auth-list.ts +44 -0
  67. package/src/commands/auth-remove.ts +26 -0
  68. package/src/commands/auth-use.ts +53 -0
  69. package/src/commands/auth-utils.ts +65 -0
  70. package/src/commands/install.ts +19 -19
  71. package/src/index.ts +5 -0
  72. package/src/sd-claude.ts +81 -3
  73. package/tests/auth-add.spec.ts +74 -0
  74. package/tests/auth-list.spec.ts +175 -0
  75. package/tests/auth-remove.spec.ts +74 -0
  76. package/tests/auth-use.spec.ts +153 -0
  77. package/tests/auth-utils.spec.ts +173 -0
  78. package/claude/skills/sd-explore/SKILL.md +0 -78
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: sd-worktree
3
- description: Git worktree management for branch isolation
4
- disable-model-invocation: true
3
+ description: "Git worktree branch isolation (explicit invocation only)"
5
4
  model: haiku
6
5
  ---
7
6
 
@@ -0,0 +1,2 @@
1
+ export declare function runAuthAdd(name: string, homeDir?: string): void;
2
+ //# sourceMappingURL=auth-add.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-add.d.ts","sourceRoot":"","sources":["../../src/commands/auth-add.ts"],"names":[],"mappings":"AAUA,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAyB/D"}
@@ -0,0 +1,32 @@
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
+ function runAuthAdd(name, homeDir) {
11
+ validateName(name);
12
+ if (profileExists(name, homeDir)) {
13
+ throw new Error(
14
+ `Profile '${name}' already exists. Remove it first with: sd-claude auth remove ${name}`
15
+ );
16
+ }
17
+ const { oauthAccount, userID } = readCurrentAuth(homeDir);
18
+ const credentials = readCurrentCredentials(homeDir);
19
+ const profileDir = getProfileDir(name, homeDir);
20
+ fs.mkdirSync(profileDir, { recursive: true });
21
+ fs.writeFileSync(
22
+ path.join(profileDir, "auth.json"),
23
+ JSON.stringify({ oauthAccount, userID }, null, 2)
24
+ );
25
+ fs.writeFileSync(path.join(profileDir, "credentials.json"), JSON.stringify(credentials, null, 2));
26
+ const email = oauthAccount["emailAddress"];
27
+ console.log(`Saved profile '${name}' (${email ?? userID})`);
28
+ }
29
+ export {
30
+ runAuthAdd
31
+ };
32
+ //# sourceMappingURL=auth-add.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/auth-add.ts"],
4
+ "mappings": "AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEA,SAAS,WAAW,MAAc,SAAwB;AAC/D,eAAa,IAAI;AAEjB,MAAI,cAAc,MAAM,OAAO,GAAG;AAChC,UAAM,IAAI;AAAA,MACR,YAAY,IAAI,iEAAiE,IAAI;AAAA,IACvF;AAAA,EACF;AAEA,QAAM,EAAE,cAAc,OAAO,IAAI,gBAAgB,OAAO;AACxD,QAAM,cAAc,uBAAuB,OAAO;AAElD,QAAM,aAAa,cAAc,MAAM,OAAO;AAC9C,KAAG,UAAU,YAAY,EAAE,WAAW,KAAK,CAAC;AAE5C,KAAG;AAAA,IACD,KAAK,KAAK,YAAY,WAAW;AAAA,IACjC,KAAK,UAAU,EAAE,cAAc,OAAO,GAAG,MAAM,CAAC;AAAA,EAClD;AAEA,KAAG,cAAc,KAAK,KAAK,YAAY,kBAAkB,GAAG,KAAK,UAAU,aAAa,MAAM,CAAC,CAAC;AAEhG,QAAM,QAAQ,aAAa,cAAc;AAEzC,UAAQ,IAAI,kBAAkB,IAAI,MAAM,SAAS,MAAM,GAAG;AAC5D;",
5
+ "names": []
6
+ }
@@ -0,0 +1,2 @@
1
+ export declare function runAuthList(homeDir?: string): void;
2
+ //# sourceMappingURL=auth-list.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-list.d.ts","sourceRoot":"","sources":["../../src/commands/auth-list.ts"],"names":[],"mappings":"AAIA,wBAAgB,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAuClD"}
@@ -0,0 +1,37 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { listProfiles, getCurrentUserID, getProfileDir } from "./auth-utils.js";
4
+ function runAuthList(homeDir) {
5
+ const profiles = listProfiles(homeDir);
6
+ if (profiles.length === 0) {
7
+ console.log("No saved profiles.");
8
+ return;
9
+ }
10
+ const currentUserID = getCurrentUserID(homeDir);
11
+ const sorted = [...profiles].sort((a, b) => a.localeCompare(b));
12
+ for (const name of sorted) {
13
+ const profileDir = getProfileDir(name, homeDir);
14
+ const authData = JSON.parse(
15
+ fs.readFileSync(path.join(profileDir, "auth.json"), "utf-8")
16
+ );
17
+ const credData = JSON.parse(
18
+ fs.readFileSync(path.join(profileDir, "credentials.json"), "utf-8")
19
+ );
20
+ const oauthAccount = authData["oauthAccount"];
21
+ const email = oauthAccount?.["emailAddress"] ?? "";
22
+ const userID = authData["userID"];
23
+ const oauth = credData["claudeAiOauth"];
24
+ let expiresStr = "unknown";
25
+ if (oauth != null && typeof oauth["expiresAt"] === "number") {
26
+ const d = new Date(oauth["expiresAt"]);
27
+ expiresStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
28
+ }
29
+ const isActive = currentUserID != null && userID === currentUserID;
30
+ const prefix = isActive ? "*" : " ";
31
+ console.log(`${prefix} ${name} (${email}) expires: ${expiresStr}`);
32
+ }
33
+ }
34
+ export {
35
+ runAuthList
36
+ };
37
+ //# sourceMappingURL=auth-list.js.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/commands/auth-list.ts"],
4
+ "mappings": "AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,cAAc,kBAAkB,qBAAqB;AAEvD,SAAS,YAAY,SAAwB;AAClD,QAAM,WAAW,aAAa,OAAO;AAErC,MAAI,SAAS,WAAW,GAAG;AAEzB,YAAQ,IAAI,oBAAoB;AAChC;AAAA,EACF;AAEA,QAAM,gBAAgB,iBAAiB,OAAO;AAC9C,QAAM,SAAS,CAAC,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,cAAc,CAAC,CAAC;AAE9D,aAAW,QAAQ,QAAQ;AACzB,UAAM,aAAa,cAAc,MAAM,OAAO;AAE9C,UAAM,WAAW,KAAK;AAAA,MACpB,GAAG,aAAa,KAAK,KAAK,YAAY,WAAW,GAAG,OAAO;AAAA,IAC7D;AAEA,UAAM,WAAW,KAAK;AAAA,MACpB,GAAG,aAAa,KAAK,KAAK,YAAY,kBAAkB,GAAG,OAAO;AAAA,IACpE;AAEA,UAAM,eAAe,SAAS,cAAc;AAC5C,UAAM,QAAS,eAAe,cAAc,KAA4B;AACxE,UAAM,SAAS,SAAS,QAAQ;AAChC,UAAM,QAAQ,SAAS,eAAe;AACtC,QAAI,aAAa;AACjB,QAAI,SAAS,QAAQ,OAAO,MAAM,WAAW,MAAM,UAAU;AAC3D,YAAM,IAAI,IAAI,KAAK,MAAM,WAAW,CAAC;AACrC,mBAAa,GAAG,EAAE,YAAY,CAAC,IAAI,OAAO,EAAE,SAAS,IAAI,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC,IAAI,OAAO,EAAE,QAAQ,CAAC,EAAE,SAAS,GAAG,GAAG,CAAC;AAAA,IACtH;AAEA,UAAM,WAAW,iBAAiB,QAAQ,WAAW;AACrD,UAAM,SAAS,WAAW,MAAM;AAGhC,YAAQ,IAAI,GAAG,MAAM,IAAI,IAAI,KAAK,KAAK,cAAc,UAAU,EAAE;AAAA,EACnE;AACF;",
5
+ "names": []
6
+ }
@@ -0,0 +1,2 @@
1
+ export declare function runAuthRemove(name: string, homeDir?: string): void;
2
+ //# sourceMappingURL=auth-remove.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-remove.d.ts","sourceRoot":"","sources":["../../src/commands/auth-remove.ts"],"names":[],"mappings":"AAIA,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAqBlE"}
@@ -0,0 +1,22 @@
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
@@ -0,0 +1,6 @@
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
+ }
@@ -0,0 +1,2 @@
1
+ export declare function runAuthUse(name: string, homeDir?: string): void;
2
+ //# sourceMappingURL=auth-use.d.ts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,33 @@
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
@@ -0,0 +1,6 @@
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
+ }
@@ -0,0 +1,11 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,57 @@
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
@@ -0,0 +1,6 @@
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
+ }
@@ -8,7 +8,7 @@ function runInstall() {
8
8
  const sourceDir = path.join(pkgRoot, "claude");
9
9
  const projectRoot = findProjectRoot(__dirname);
10
10
  if (projectRoot == null) {
11
- console.log("[@simplysm/sd-claude] \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4 \uAC74\uB108\uB701\uB2C8\uB2E4.");
11
+ console.log("[@simplysm/sd-claude] Could not find project root, skipping installation.");
12
12
  return;
13
13
  }
14
14
  if (isSimplysmMonorepoSameMajor(projectRoot, pkgRoot)) {
@@ -25,9 +25,9 @@ function runInstall() {
25
25
  cleanSdEntries(targetDir);
26
26
  copySdEntries(sourceDir, targetDir, sourceEntries);
27
27
  setupStatusLine(targetDir);
28
- console.log(`[@simplysm/sd-claude] ${sourceEntries.length}\uAC1C\uC758 sd-* \uD56D\uBAA9\uC744 \uC124\uCE58\uD588\uC2B5\uB2C8\uB2E4.`);
28
+ console.log(`[@simplysm/sd-claude] Installed ${sourceEntries.length} sd-* entries.`);
29
29
  } catch (err) {
30
- console.warn("[@simplysm/sd-claude] postinstall \uACBD\uACE0:", err.message);
30
+ console.warn("[@simplysm/sd-claude] postinstall warning:", err.message);
31
31
  }
32
32
  }
33
33
  function findProjectRoot(dirname) {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/commands/install.ts"],
4
- "mappings": "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",
4
+ "mappings": "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",
5
5
  "names": []
6
6
  }
package/dist/index.d.ts CHANGED
@@ -1,2 +1,7 @@
1
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";
2
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,uBAAuB,CAAC"}
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 CHANGED
@@ -1,2 +1,7 @@
1
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";
2
7
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts"],
4
- "mappings": "AACA,cAAc;",
4
+ "mappings": "AACA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
5
5
  "names": []
6
6
  }
package/dist/sd-claude.js CHANGED
@@ -2,12 +2,77 @@
2
2
  import yargs from "yargs";
3
3
  import { hideBin } from "yargs/helpers";
4
4
  import { runInstall } from "./commands/install.js";
5
- await yargs(hideBin(process.argv)).help("help", "\uB3C4\uC6C0\uB9D0").alias("help", "h").command(
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(
6
10
  "install",
7
- "Claude Code \uC5D0\uC14B\uC744 \uD504\uB85C\uC81D\uD2B8\uC5D0 \uC124\uCE58\uD55C\uB2E4.",
11
+ "Installs Claude Code assets to the project.",
8
12
  (cmd) => cmd.version(false).hide("help"),
9
13
  () => {
10
14
  runInstall();
11
15
  }
12
- ).demandCommand(1, "\uBA85\uB839\uC5B4\uB97C \uC9C0\uC815\uD574\uC8FC\uC138\uC694.").strict().parse();
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
+ () => {
54
+ try {
55
+ 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();
13
78
  //# sourceMappingURL=sd-claude.js.map
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/sd-claude.ts"],
4
- "mappings": ";AAEA,OAAO,WAAW;AAClB,SAAS,eAAe;AACxB,SAAS,kBAAkB;AAE3B,MAAM,MAAM,QAAQ,QAAQ,IAAI,CAAC,EAC9B,KAAK,QAAQ,oBAAK,EAClB,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,cAAc,GAAG,gEAAc,EAC/B,OAAO,EACP,MAAM;",
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,MAAM;AACJ,UAAI;AACF,oBAAY;AAAA,MACd,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
5
  "names": []
6
6
  }
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@simplysm/sd-claude",
3
- "version": "13.0.69",
3
+ "version": "13.0.70",
4
4
  "description": "Simplysm Claude Code CLI — asset installer",
5
- "author": "김석래",
5
+ "author": "simplysm",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
8
8
  "type": "git",
@@ -15,6 +15,7 @@
15
15
  "files": [
16
16
  "dist",
17
17
  "src",
18
+ "tests",
18
19
  "scripts",
19
20
  "claude"
20
21
  ],
@@ -43,4 +43,4 @@ for (const entry of allEntries) {
43
43
  fs.cpSync(src, dest, { recursive: true });
44
44
  }
45
45
 
46
- console.log(`${allEntries.length}개의 sd-* 에셋을 동기화했습니다.`);
46
+ console.log(`Synchronized ${allEntries.length} sd-* assets.`);
@@ -0,0 +1,36 @@
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
+ }
@@ -0,0 +1,44 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { listProfiles, getCurrentUserID, getProfileDir } from "./auth-utils.js";
4
+
5
+ export function runAuthList(homeDir?: string): void {
6
+ const profiles = listProfiles(homeDir);
7
+
8
+ if (profiles.length === 0) {
9
+ // eslint-disable-next-line no-console
10
+ console.log("No saved profiles.");
11
+ return;
12
+ }
13
+
14
+ const currentUserID = getCurrentUserID(homeDir);
15
+ const sorted = [...profiles].sort((a, b) => a.localeCompare(b));
16
+
17
+ for (const name of sorted) {
18
+ const profileDir = getProfileDir(name, homeDir);
19
+
20
+ const authData = JSON.parse(
21
+ fs.readFileSync(path.join(profileDir, "auth.json"), "utf-8"),
22
+ ) as Record<string, unknown>;
23
+
24
+ const credData = JSON.parse(
25
+ fs.readFileSync(path.join(profileDir, "credentials.json"), "utf-8"),
26
+ ) as Record<string, unknown>;
27
+
28
+ const oauthAccount = authData["oauthAccount"] as Record<string, unknown> | undefined;
29
+ const email = (oauthAccount?.["emailAddress"] as string | undefined) ?? "";
30
+ const userID = authData["userID"] as string | undefined;
31
+ const oauth = credData["claudeAiOauth"] as Record<string, unknown> | undefined;
32
+ let expiresStr = "unknown";
33
+ if (oauth != null && typeof oauth["expiresAt"] === "number") {
34
+ const d = new Date(oauth["expiresAt"]);
35
+ expiresStr = `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
36
+ }
37
+
38
+ const isActive = currentUserID != null && userID === currentUserID;
39
+ const prefix = isActive ? "*" : " ";
40
+
41
+ // eslint-disable-next-line no-console
42
+ console.log(`${prefix} ${name} (${email}) expires: ${expiresStr}`);
43
+ }
44
+ }
@@ -0,0 +1,26 @@
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
+ }