@simplysm/sd-claude 13.0.69 → 13.0.71
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 +12 -601
- package/claude/agents/sd-api-reviewer.md +0 -1
- package/claude/agents/sd-code-reviewer.md +0 -1
- package/claude/agents/sd-code-simplifier.md +1 -1
- package/claude/agents/sd-security-reviewer.md +0 -1
- package/claude/refs/sd-angular.md +26 -26
- package/claude/refs/sd-orm-v12.md +17 -17
- package/claude/rules/sd-refs-linker.md +14 -14
- package/claude/sd-statusline.js +21 -21
- package/claude/skills/sd-api-name-review/SKILL.md +1 -2
- package/claude/skills/sd-brainstorm/SKILL.md +3 -4
- package/claude/skills/sd-check/SKILL.md +1 -2
- package/claude/skills/sd-commit/SKILL.md +2 -3
- package/claude/skills/sd-debug/SKILL.md +1 -2
- package/claude/skills/sd-discuss/SKILL.md +1 -3
- package/claude/skills/sd-document/SKILL.md +99 -0
- package/claude/skills/sd-document/extract_docx.py +92 -0
- package/claude/skills/sd-document/extract_pdf.py +102 -0
- package/claude/skills/sd-document/extract_pptx.py +77 -0
- package/claude/skills/sd-document/extract_xlsx.py +83 -0
- package/claude/skills/sd-email-analyze/SKILL.md +6 -6
- package/claude/skills/sd-plan/SKILL.md +1 -3
- package/claude/skills/sd-plan-dev/SKILL.md +94 -111
- package/claude/skills/sd-plan-dev/code-quality-reviewer-prompt.md +1 -1
- package/claude/skills/sd-plan-dev/final-review-prompt.md +1 -1
- package/claude/skills/sd-plan-dev/spec-reviewer-prompt.md +1 -1
- package/claude/skills/sd-readme/SKILL.md +107 -88
- package/claude/skills/sd-review/SKILL.md +14 -16
- package/claude/skills/sd-skill/SKILL.md +6 -317
- package/claude/skills/sd-skill/cso-guide.md +161 -0
- package/claude/skills/sd-skill/writing-guide.md +163 -0
- package/claude/skills/sd-tdd/SKILL.md +1 -3
- package/claude/skills/sd-use/SKILL.md +1 -3
- package/claude/skills/sd-worktree/SKILL.md +52 -2
- package/dist/commands/auth-add.d.ts +2 -0
- package/dist/commands/auth-add.d.ts.map +1 -0
- package/dist/commands/auth-add.js +32 -0
- package/dist/commands/auth-add.js.map +6 -0
- package/dist/commands/auth-list.d.ts +2 -0
- package/dist/commands/auth-list.d.ts.map +1 -0
- package/dist/commands/auth-list.js +37 -0
- package/dist/commands/auth-list.js.map +6 -0
- package/dist/commands/auth-remove.d.ts +2 -0
- package/dist/commands/auth-remove.d.ts.map +1 -0
- package/dist/commands/auth-remove.js +22 -0
- package/dist/commands/auth-remove.js.map +6 -0
- package/dist/commands/auth-use.d.ts +2 -0
- package/dist/commands/auth-use.d.ts.map +1 -0
- package/dist/commands/auth-use.js +33 -0
- package/dist/commands/auth-use.js.map +6 -0
- package/dist/commands/auth-utils.d.ts +11 -0
- package/dist/commands/auth-utils.d.ts.map +1 -0
- package/dist/commands/auth-utils.js +57 -0
- package/dist/commands/auth-utils.js.map +6 -0
- package/dist/commands/install.js +3 -3
- package/dist/commands/install.js.map +1 -1
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/sd-claude.js +68 -3
- package/dist/sd-claude.js.map +1 -1
- package/package.json +3 -2
- package/scripts/sync-claude-assets.mjs +1 -1
- package/src/commands/auth-add.ts +36 -0
- package/src/commands/auth-list.ts +44 -0
- package/src/commands/auth-remove.ts +26 -0
- package/src/commands/auth-use.ts +53 -0
- package/src/commands/auth-utils.ts +65 -0
- package/src/commands/install.ts +19 -19
- package/src/index.ts +5 -0
- package/src/sd-claude.ts +81 -3
- package/tests/auth-add.spec.ts +74 -0
- package/tests/auth-list.spec.ts +175 -0
- package/tests/auth-remove.spec.ts +74 -0
- package/tests/auth-use.spec.ts +153 -0
- package/tests/auth-utils.spec.ts +173 -0
- package/claude/skills/sd-explore/SKILL.md +0 -78
|
@@ -1,12 +1,54 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: sd-worktree
|
|
3
|
-
description: Git worktree
|
|
4
|
-
disable-model-invocation: true
|
|
3
|
+
description: "Git worktree branch isolation (explicit invocation only)"
|
|
5
4
|
model: haiku
|
|
6
5
|
---
|
|
7
6
|
|
|
8
7
|
# sd-worktree
|
|
9
8
|
|
|
9
|
+
## CRITICAL SAFETY RULES — MERGE & STASH
|
|
10
|
+
|
|
11
|
+
**These rules are ABSOLUTE. No exceptions. Applies to ALL modes (yolo, normal, plan, etc.).**
|
|
12
|
+
|
|
13
|
+
1. **NEVER run `git stash drop`, `git stash pop`, or `git stash clear`.**
|
|
14
|
+
- If you stashed something, ONLY use `git stash apply` (which keeps the stash intact).
|
|
15
|
+
- If stash is no longer needed, ASK the user before dropping it.
|
|
16
|
+
|
|
17
|
+
2. **If `merge` fails or produces conflicts → STOP IMMEDIATELY and show this message:**
|
|
18
|
+
```
|
|
19
|
+
⚠️ merge 중 문제가 발생했습니다.
|
|
20
|
+
직접 수동으로 merge를 진행해 주세요.
|
|
21
|
+
(에러 내용: <에러/충돌 정보 그대로 출력>)
|
|
22
|
+
```
|
|
23
|
+
- Do NOT attempt to resolve conflicts yourself.
|
|
24
|
+
- Do NOT run `git merge --abort` without asking.
|
|
25
|
+
- Do NOT proceed to `clean` after a failed merge.
|
|
26
|
+
- Do NOT retry or work around the error.
|
|
27
|
+
- Just show the message above and STOP. Do nothing else.
|
|
28
|
+
|
|
29
|
+
3. **If `rebase` fails or produces conflicts → STOP IMMEDIATELY and show this message:**
|
|
30
|
+
```
|
|
31
|
+
⚠️ rebase 중 문제가 발생했습니다.
|
|
32
|
+
직접 수동으로 rebase를 진행해 주세요.
|
|
33
|
+
(에러 내용: <에러/충돌 정보 그대로 출력>)
|
|
34
|
+
```
|
|
35
|
+
- Same rules as merge. Do NOT auto-resolve. Just show the message and STOP.
|
|
36
|
+
|
|
37
|
+
4. **NEVER run destructive git commands during worktree workflows:**
|
|
38
|
+
- `git reset --hard`, `git checkout -- .`, `git restore .`, `git clean -f`
|
|
39
|
+
- `git branch -D` (force delete) — only `-d` (safe delete) is allowed
|
|
40
|
+
- `git stash drop`, `git stash pop`, `git stash clear`
|
|
41
|
+
|
|
42
|
+
5. **Before ANY merge/rebase, verify:**
|
|
43
|
+
- Both main and worktree have NO uncommitted changes (`git status --porcelain`)
|
|
44
|
+
- If uncommitted changes exist → ask the user (do NOT auto-stash)
|
|
45
|
+
|
|
46
|
+
6. **After merge completes, verify success before proceeding:**
|
|
47
|
+
- Check `git status` — if merge conflicts exist, STOP and report
|
|
48
|
+
- Do NOT proceed to `clean` until merge is confirmed successful
|
|
49
|
+
|
|
50
|
+
**Violation of these rules causes IRREVERSIBLE DATA LOSS.**
|
|
51
|
+
|
|
10
52
|
## Overview
|
|
11
53
|
|
|
12
54
|
Create, merge, and clean up git worktrees under `.worktrees/`. Uses the current branch of the main working tree as the source branch.
|
|
@@ -45,6 +87,7 @@ node .claude/skills/sd-worktree/sd-worktree.mjs rebase [name]
|
|
|
45
87
|
- Rebases the worktree branch onto the latest commit of the main branch
|
|
46
88
|
- Errors if uncommitted changes exist → commit or stash first
|
|
47
89
|
- Use when you want a clean history before merging
|
|
90
|
+
- **If rebase fails or conflicts → STOP. Report to user. Do NOT auto-resolve.**
|
|
48
91
|
|
|
49
92
|
### merge — Merge into main branch
|
|
50
93
|
|
|
@@ -57,6 +100,13 @@ node .claude/skills/sd-worktree/sd-worktree.mjs merge [name]
|
|
|
57
100
|
- Errors if uncommitted changes exist → commit or stash first
|
|
58
101
|
- After merge, always `cd <project-root>` (required for subsequent clean)
|
|
59
102
|
|
|
103
|
+
**MERGE SAFETY PROTOCOL:**
|
|
104
|
+
1. Before merge: check BOTH main and worktree for uncommitted changes
|
|
105
|
+
2. If the script exits with non-zero → show "직접 수동으로 merge해 주세요" message and STOP.
|
|
106
|
+
3. After merge: run `git status` in main to confirm no conflicts
|
|
107
|
+
4. If conflicts or errors → show "직접 수동으로 merge해 주세요" message and STOP.
|
|
108
|
+
5. Only proceed to `clean` after confirming merge was fully successful
|
|
109
|
+
|
|
60
110
|
### clean — Remove worktree and delete branch
|
|
61
111
|
|
|
62
112
|
```bash
|
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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
|
+
}
|
package/dist/commands/install.js
CHANGED
|
@@ -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]
|
|
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}
|
|
28
|
+
console.log(`[@simplysm/sd-claude] Installed ${sourceEntries.length} sd-* entries.`);
|
|
29
29
|
} catch (err) {
|
|
30
|
-
console.warn("[@simplysm/sd-claude] postinstall
|
|
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": "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,
|
|
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
|
package/dist/index.d.ts.map
CHANGED
|
@@ -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
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
|
-
|
|
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
|
|
11
|
+
"Installs Claude Code assets to the project.",
|
|
8
12
|
(cmd) => cmd.version(false).hide("help"),
|
|
9
13
|
() => {
|
|
10
14
|
runInstall();
|
|
11
15
|
}
|
|
12
|
-
).
|
|
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
|
package/dist/sd-claude.js.map
CHANGED
|
@@ -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;
|
|
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.
|
|
3
|
+
"version": "13.0.71",
|
|
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
|
],
|
|
@@ -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
|
+
}
|