@simplysm/sd-claude 13.0.71 → 13.0.74
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 +286 -13
- package/claude/refs/sd-code-conventions.md +11 -0
- package/claude/refs/sd-library-issue.md +7 -0
- package/claude/rules/sd-claude-rules.md +15 -4
- package/claude/rules/sd-refs-linker.md +1 -0
- package/claude/sd-statusline.js +1 -1
- package/claude/skills/sd-brainstorm/SKILL.md +1 -1
- package/claude/skills/sd-check/SKILL.md +15 -6
- package/claude/skills/sd-commit/SKILL.md +2 -0
- package/claude/skills/sd-debug/find-polluter.sh +8 -2
- package/claude/skills/sd-debug/root-cause-tracing.md +2 -2
- package/claude/skills/sd-document/extract_docx.py +5 -5
- package/claude/skills/sd-document/extract_pdf.py +11 -11
- package/claude/skills/sd-document/extract_pptx.py +5 -5
- package/claude/skills/sd-document/extract_xlsx.py +7 -7
- package/claude/skills/sd-email-analyze/email-analyzer.py +28 -28
- package/claude/skills/sd-plan/SKILL.md +11 -2
- package/claude/skills/sd-plan-dev/SKILL.md +5 -3
- package/claude/skills/sd-plan-dev/final-review-prompt.md +3 -3
- package/claude/skills/sd-readme/SKILL.md +86 -106
- package/claude/skills/sd-review/SKILL.md +58 -62
- package/claude/skills/sd-review/api-reviewer-prompt.md +90 -0
- package/claude/skills/sd-review/code-reviewer-prompt.md +85 -0
- package/claude/skills/sd-review/code-simplifier-prompt.md +88 -0
- package/claude/skills/sd-worktree/SKILL.md +10 -8
- package/claude/skills/sd-worktree/sd-worktree.mjs +5 -5
- package/dist/commands/auth-list.d.ts +1 -1
- package/dist/commands/auth-list.d.ts.map +1 -1
- package/dist/commands/auth-list.js +79 -21
- package/dist/commands/auth-list.js.map +1 -1
- package/dist/sd-claude.js +2 -2
- package/dist/sd-claude.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/auth-list.ts +110 -24
- package/src/sd-claude.ts +2 -2
- package/tests/auth-list.spec.ts +42 -19
- package/claude/agents/sd-api-reviewer.md +0 -81
- package/claude/agents/sd-code-reviewer.md +0 -48
- package/claude/agents/sd-code-simplifier.md +0 -47
- package/claude/agents/sd-security-reviewer.md +0 -92
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/commands/auth-list.ts"],
|
|
4
|
-
"mappings": "AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,SAAS,cAAc,kBAAkB,qBAAqB;
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": []
|
|
6
6
|
}
|
package/dist/sd-claude.js
CHANGED
|
@@ -50,9 +50,9 @@ await yargs(hideBin(process.argv)).help("help", "Help").alias("help", "h").comma
|
|
|
50
50
|
"list",
|
|
51
51
|
"Displays the list of saved accounts",
|
|
52
52
|
(sub) => sub,
|
|
53
|
-
() => {
|
|
53
|
+
async () => {
|
|
54
54
|
try {
|
|
55
|
-
runAuthList();
|
|
55
|
+
await runAuthList();
|
|
56
56
|
} catch (err) {
|
|
57
57
|
console.error(err.message);
|
|
58
58
|
process.exit(1);
|
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;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,
|
|
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
5
|
"names": []
|
|
6
6
|
}
|
package/package.json
CHANGED
|
@@ -2,7 +2,75 @@ import fs from "fs";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
import { listProfiles, getCurrentUserID, getProfileDir } from "./auth-utils.js";
|
|
4
4
|
|
|
5
|
-
|
|
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> {
|
|
6
74
|
const profiles = listProfiles(homeDir);
|
|
7
75
|
|
|
8
76
|
if (profiles.length === 0) {
|
|
@@ -14,31 +82,49 @@ export function runAuthList(homeDir?: string): void {
|
|
|
14
82
|
const currentUserID = getCurrentUserID(homeDir);
|
|
15
83
|
const sorted = [...profiles].sort((a, b) => a.localeCompare(b));
|
|
16
84
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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);
|
|
37
121
|
|
|
38
|
-
|
|
39
|
-
|
|
122
|
+
return `${prefix} ${name} (${email}) expires: ${expiresStr} │ ${fiveHourStr} │ ${weekStr}`;
|
|
123
|
+
}),
|
|
124
|
+
);
|
|
40
125
|
|
|
126
|
+
for (const line of results) {
|
|
41
127
|
// eslint-disable-next-line no-console
|
|
42
|
-
console.log(
|
|
128
|
+
console.log(line);
|
|
43
129
|
}
|
|
44
130
|
}
|
package/src/sd-claude.ts
CHANGED
|
@@ -63,9 +63,9 @@ await yargs(hideBin(process.argv))
|
|
|
63
63
|
"list",
|
|
64
64
|
"Displays the list of saved accounts",
|
|
65
65
|
(sub) => sub,
|
|
66
|
-
() => {
|
|
66
|
+
async () => {
|
|
67
67
|
try {
|
|
68
|
-
runAuthList();
|
|
68
|
+
await runAuthList();
|
|
69
69
|
} catch (err) {
|
|
70
70
|
// eslint-disable-next-line no-console
|
|
71
71
|
console.error((err as Error).message);
|
package/tests/auth-list.spec.ts
CHANGED
|
@@ -4,6 +4,15 @@ import fs from "fs";
|
|
|
4
4
|
import os from "os";
|
|
5
5
|
import { runAuthList } from "../src/commands/auth-list";
|
|
6
6
|
|
|
7
|
+
// Mock global fetch to prevent real API calls
|
|
8
|
+
vi.stubGlobal(
|
|
9
|
+
"fetch",
|
|
10
|
+
vi.fn().mockResolvedValue({
|
|
11
|
+
ok: false,
|
|
12
|
+
json: () => Promise.resolve({}),
|
|
13
|
+
}),
|
|
14
|
+
);
|
|
15
|
+
|
|
7
16
|
describe("runAuthList", () => {
|
|
8
17
|
let tmpDir: string;
|
|
9
18
|
|
|
@@ -16,15 +25,15 @@ describe("runAuthList", () => {
|
|
|
16
25
|
vi.restoreAllMocks();
|
|
17
26
|
});
|
|
18
27
|
|
|
19
|
-
test("outputs 'No saved profiles.' when no profiles exist", () => {
|
|
28
|
+
test("outputs 'No saved profiles.' when no profiles exist", async () => {
|
|
20
29
|
const spy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
21
30
|
|
|
22
|
-
runAuthList(tmpDir);
|
|
31
|
+
await runAuthList(tmpDir);
|
|
23
32
|
|
|
24
33
|
expect(spy).toHaveBeenCalledWith("No saved profiles.");
|
|
25
34
|
});
|
|
26
35
|
|
|
27
|
-
test("outputs profiles sorted alphabetically with active marker", () => {
|
|
36
|
+
test("outputs profiles sorted alphabetically with active marker", async () => {
|
|
28
37
|
const authDir = path.join(tmpDir, ".sd-claude", "auth");
|
|
29
38
|
|
|
30
39
|
// Create profile "beta"
|
|
@@ -62,16 +71,22 @@ describe("runAuthList", () => {
|
|
|
62
71
|
|
|
63
72
|
const spy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
64
73
|
|
|
65
|
-
runAuthList(tmpDir);
|
|
74
|
+
await runAuthList(tmpDir);
|
|
66
75
|
|
|
67
76
|
expect(spy).toHaveBeenCalledTimes(2);
|
|
68
|
-
// alpha comes first (alphabetical), and is active
|
|
69
|
-
expect(spy).toHaveBeenNthCalledWith(
|
|
77
|
+
// alpha comes first (alphabetical), and is active; usage shows ? when fetch fails
|
|
78
|
+
expect(spy).toHaveBeenNthCalledWith(
|
|
79
|
+
1,
|
|
80
|
+
"* alpha (alpha@example.com) expires: 2025-06-25 │ 5h: ? │ 7d: ?",
|
|
81
|
+
);
|
|
70
82
|
// beta is not active
|
|
71
|
-
expect(spy).toHaveBeenNthCalledWith(
|
|
83
|
+
expect(spy).toHaveBeenNthCalledWith(
|
|
84
|
+
2,
|
|
85
|
+
" beta (beta@example.com) expires: 2025-06-20 │ 5h: ? │ 7d: ?",
|
|
86
|
+
);
|
|
72
87
|
});
|
|
73
88
|
|
|
74
|
-
test("shows email even when organizationName is missing", () => {
|
|
89
|
+
test("shows email even when organizationName is missing", async () => {
|
|
75
90
|
const authDir = path.join(tmpDir, ".sd-claude", "auth");
|
|
76
91
|
|
|
77
92
|
const profileDir = path.join(authDir, "personal");
|
|
@@ -90,12 +105,14 @@ describe("runAuthList", () => {
|
|
|
90
105
|
|
|
91
106
|
const spy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
92
107
|
|
|
93
|
-
runAuthList(tmpDir);
|
|
108
|
+
await runAuthList(tmpDir);
|
|
94
109
|
|
|
95
|
-
expect(spy).toHaveBeenCalledWith(
|
|
110
|
+
expect(spy).toHaveBeenCalledWith(
|
|
111
|
+
" personal (user@gmail.com) expires: 2025-07-01 │ 5h: ? │ 7d: ?",
|
|
112
|
+
);
|
|
96
113
|
});
|
|
97
114
|
|
|
98
|
-
test("shows 'unknown' when expiresAt is missing", () => {
|
|
115
|
+
test("shows 'unknown' when expiresAt is missing", async () => {
|
|
99
116
|
const authDir = path.join(tmpDir, ".sd-claude", "auth");
|
|
100
117
|
|
|
101
118
|
const profileDir = path.join(authDir, "noexpiry");
|
|
@@ -111,12 +128,14 @@ describe("runAuthList", () => {
|
|
|
111
128
|
|
|
112
129
|
const spy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
113
130
|
|
|
114
|
-
runAuthList(tmpDir);
|
|
131
|
+
await runAuthList(tmpDir);
|
|
115
132
|
|
|
116
|
-
expect(spy).toHaveBeenCalledWith(
|
|
133
|
+
expect(spy).toHaveBeenCalledWith(
|
|
134
|
+
" noexpiry (noexp@example.com) expires: unknown │ 5h: ? │ 7d: ?",
|
|
135
|
+
);
|
|
117
136
|
});
|
|
118
137
|
|
|
119
|
-
test("marks active profile with * when userID matches", () => {
|
|
138
|
+
test("marks active profile with * when userID matches", async () => {
|
|
120
139
|
const authDir = path.join(tmpDir, ".sd-claude", "auth");
|
|
121
140
|
|
|
122
141
|
const profileDir = path.join(authDir, "work");
|
|
@@ -138,12 +157,14 @@ describe("runAuthList", () => {
|
|
|
138
157
|
|
|
139
158
|
const spy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
140
159
|
|
|
141
|
-
runAuthList(tmpDir);
|
|
160
|
+
await runAuthList(tmpDir);
|
|
142
161
|
|
|
143
|
-
expect(spy).toHaveBeenCalledWith(
|
|
162
|
+
expect(spy).toHaveBeenCalledWith(
|
|
163
|
+
"* work (work@company.com) expires: 2025-12-31 │ 5h: ? │ 7d: ?",
|
|
164
|
+
);
|
|
144
165
|
});
|
|
145
166
|
|
|
146
|
-
test("non-active profile has space prefix instead of *", () => {
|
|
167
|
+
test("non-active profile has space prefix instead of *", async () => {
|
|
147
168
|
const authDir = path.join(tmpDir, ".sd-claude", "auth");
|
|
148
169
|
|
|
149
170
|
const profileDir = path.join(authDir, "other");
|
|
@@ -168,8 +189,10 @@ describe("runAuthList", () => {
|
|
|
168
189
|
|
|
169
190
|
const spy = vi.spyOn(console, "log").mockImplementation(() => {});
|
|
170
191
|
|
|
171
|
-
runAuthList(tmpDir);
|
|
192
|
+
await runAuthList(tmpDir);
|
|
172
193
|
|
|
173
|
-
expect(spy).toHaveBeenCalledWith(
|
|
194
|
+
expect(spy).toHaveBeenCalledWith(
|
|
195
|
+
" other (other@example.com) expires: 2025-08-15 │ 5h: ? │ 7d: ?",
|
|
196
|
+
);
|
|
174
197
|
});
|
|
175
198
|
});
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: sd-api-reviewer
|
|
3
|
-
description: Reviews a library's public API for developer experience (DX) quality - naming consistency, industry standard alignment, intuitiveness, error messages, type hints, configuration complexity, and usage pattern coherence
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
You are an expert API/DX reviewer who evaluates libraries from the **consumer's perspective**. Your goal is to identify friction points that developers encounter when using a package.
|
|
7
|
-
|
|
8
|
-
## Review Scope
|
|
9
|
-
|
|
10
|
-
Analyze the specified package's public API surface (exports, types, configuration). The user will provide the target path.
|
|
11
|
-
|
|
12
|
-
## Core Review Responsibilities
|
|
13
|
-
|
|
14
|
-
### 1. Naming Review
|
|
15
|
-
|
|
16
|
-
- **Industry standard comparison**: Compare naming patterns against major libraries in the same domain (use WebSearch)
|
|
17
|
-
- **Internal consistency**: Same concept with different names, same pattern with different prefixes/suffixes
|
|
18
|
-
- **Intuitiveness**: Whether the behavior can be predicted from the name alone
|
|
19
|
-
- **Internal consistency over external standards**: Before suggesting a naming change, verify the existing pattern across ALL similar components in the library. If the library consistently uses one convention (e.g., `value`/`onValueChange` for all form controls), do NOT suggest an industry-standard alternative (e.g., `checked`/`onCheckedChange`) that would break internal consistency.
|
|
20
|
-
|
|
21
|
-
### 2. API Intuitiveness
|
|
22
|
-
|
|
23
|
-
- **Learning curve**: Whether a first-time developer can use it without documentation
|
|
24
|
-
- **Principle of least surprise**: APIs that behave differently than expected
|
|
25
|
-
- **Default value quality**: Whether most use cases work without additional configuration
|
|
26
|
-
|
|
27
|
-
### 3. Type Hints & Error Messages
|
|
28
|
-
|
|
29
|
-
- **Type sufficiency**: Whether enough type information is provided for autocompletion and compile-time validation
|
|
30
|
-
- **Error message quality**: Whether error messages guide the user to the cause and solution
|
|
31
|
-
- **Generic usage**: Whether type inference works naturally
|
|
32
|
-
|
|
33
|
-
### 4. Configuration & Boilerplate
|
|
34
|
-
|
|
35
|
-
- **Configuration complexity**: Whether basic usage requires excessive setup
|
|
36
|
-
- **Boilerplate**: Whether too much repetitive code is needed
|
|
37
|
-
- **Progressive complexity**: Whether it scales naturally from simple to advanced usage
|
|
38
|
-
|
|
39
|
-
### 5. Usage Pattern Coherence
|
|
40
|
-
|
|
41
|
-
- **Pattern consistency**: Whether similar tasks use similar patterns
|
|
42
|
-
- **Composition**: Whether features combine naturally
|
|
43
|
-
- **Escape hatch**: Whether there are ways to break out of framework constraints when needed
|
|
44
|
-
|
|
45
|
-
## Confidence Scoring
|
|
46
|
-
|
|
47
|
-
Rate each issue 0-100:
|
|
48
|
-
|
|
49
|
-
- **0**: False positive or subjective preference
|
|
50
|
-
- **25**: Minor friction, workaround is obvious
|
|
51
|
-
- **50**: Real friction but not blocking
|
|
52
|
-
- **75**: Significant DX issue, developers will struggle
|
|
53
|
-
- **100**: Critical — developers will misuse or give up
|
|
54
|
-
|
|
55
|
-
**Only report issues with confidence >= 70.**
|
|
56
|
-
|
|
57
|
-
## Output Format
|
|
58
|
-
|
|
59
|
-
Start with a brief summary of the package's public API surface.
|
|
60
|
-
|
|
61
|
-
### Findings by Category
|
|
62
|
-
|
|
63
|
-
For each high-confidence issue:
|
|
64
|
-
|
|
65
|
-
- Clear description with confidence score
|
|
66
|
-
- File path and relevant export/type
|
|
67
|
-
- Comparison with industry standard libraries (if applicable)
|
|
68
|
-
- Concrete improvement suggestion
|
|
69
|
-
|
|
70
|
-
### Priority
|
|
71
|
-
|
|
72
|
-
| Priority | Criteria |
|
|
73
|
-
| -------- | -------------------------------------------------------------- |
|
|
74
|
-
| **P0** | API misuse likely — naming misleads or types insufficient |
|
|
75
|
-
| **P1** | Significant friction — unnecessary complexity or inconsistency |
|
|
76
|
-
| **P2** | Minor improvement — better naming or defaults exist |
|
|
77
|
-
| **Keep** | Already aligned with standards |
|
|
78
|
-
|
|
79
|
-
### Summary Table
|
|
80
|
-
|
|
81
|
-
End with a table: current API, suggested change, priority, rationale.
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: sd-code-reviewer
|
|
3
|
-
description: Reviews code for bugs, logic errors, security vulnerabilities, code quality issues, and adherence to project conventions, using confidence-based filtering to report only high-priority issues that truly matter
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
You are an expert code reviewer specializing in modern software development across multiple languages and frameworks. Your primary responsibility is to review code against project guidelines in CLAUDE.md with high precision to minimize false positives.
|
|
7
|
-
|
|
8
|
-
## Review Scope
|
|
9
|
-
|
|
10
|
-
By default, review unstaged changes from `git diff`. The user may specify different files or scope to review.
|
|
11
|
-
|
|
12
|
-
## Core Review Responsibilities
|
|
13
|
-
|
|
14
|
-
**Project Guidelines Compliance**: Verify adherence to explicit project rules (typically in CLAUDE.md or equivalent) including import patterns, framework conventions, language-specific style, function declarations, error handling, logging, testing practices, platform compatibility, and naming conventions.
|
|
15
|
-
|
|
16
|
-
**Bug Detection**: Identify actual bugs that will impact functionality - logic errors, null/undefined handling, race conditions, memory leaks, security vulnerabilities, and performance problems.
|
|
17
|
-
|
|
18
|
-
**Code Quality**: Evaluate significant issues like code duplication, missing critical error handling, accessibility problems, and inadequate test coverage.
|
|
19
|
-
|
|
20
|
-
## Confidence Scoring
|
|
21
|
-
|
|
22
|
-
Rate each potential issue on a scale from 0-100:
|
|
23
|
-
|
|
24
|
-
- **0**: Not confident at all. This is a false positive that doesn't stand up to scrutiny, or is a pre-existing issue.
|
|
25
|
-
- **25**: Somewhat confident. This might be a real issue, but may also be a false positive. If stylistic, it wasn't explicitly called out in project guidelines.
|
|
26
|
-
- **50**: Moderately confident. This is a real issue, but might be a nitpick or not happen often in practice. Not very important relative to the rest of the changes.
|
|
27
|
-
- **75**: Highly confident. Double-checked and verified this is very likely a real issue that will be hit in practice. The existing approach is insufficient. Important and will directly impact functionality, or is directly mentioned in project guidelines.
|
|
28
|
-
- **100**: Absolutely certain. Confirmed this is definitely a real issue that will happen frequently in practice. The evidence directly confirms this.
|
|
29
|
-
|
|
30
|
-
**Only report issues with confidence ≥ 80.** Focus on issues that truly matter - quality over quantity.
|
|
31
|
-
|
|
32
|
-
## False Positive Prevention
|
|
33
|
-
|
|
34
|
-
- **Visual/UI behavior**: Do NOT flag CSS transforms (rotate, translate, scale) or visual states without verifying the actual rendering context (e.g., icon position, layout direction). CSS rotate values depend on icon placement — rotate-90 on a right-aligned chevron is correct for a "collapsed" state.
|
|
35
|
-
- **Pre-existing patterns**: If an issue exists in unchanged code and is part of an established pattern, do NOT report it unless it causes actual bugs.
|
|
36
|
-
|
|
37
|
-
## Output Guidance
|
|
38
|
-
|
|
39
|
-
Start by clearly stating what you're reviewing. For each high-confidence issue, provide:
|
|
40
|
-
|
|
41
|
-
- Clear description with confidence score
|
|
42
|
-
- File path and line number
|
|
43
|
-
- Specific project guideline reference or bug explanation
|
|
44
|
-
- Concrete fix suggestion
|
|
45
|
-
|
|
46
|
-
Group issues by severity (Critical vs Important). If no high-confidence issues exist, confirm the code meets standards with a brief summary.
|
|
47
|
-
|
|
48
|
-
Structure your response for maximum actionability - developers should know exactly what to fix and why.
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: sd-code-simplifier
|
|
3
|
-
description: Simplifies and refines code for clarity, consistency, and maintainability while preserving all functionality. Focuses on recently modified code unless instructed otherwise.
|
|
4
|
-
model: sonnet
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
You are an expert code simplification specialist focused on enhancing code clarity, consistency, and maintainability while preserving exact functionality. Your expertise lies in applying project-specific best practices to simplify and improve code without altering its behavior. You prioritize readable, explicit code over overly compact solutions. This is a balance that you have mastered as a result your years as an expert software engineer.
|
|
8
|
-
|
|
9
|
-
You will analyze recently modified code and apply refinements that:
|
|
10
|
-
|
|
11
|
-
1. **Preserve Functionality**: Never change what the code does - only how it does it. All original features, outputs, and behaviors must remain intact.
|
|
12
|
-
|
|
13
|
-
2. **Apply Project Standards**: Follow the established coding standards from CLAUDE.md including:
|
|
14
|
-
- Import patterns, module structure, and naming conventions
|
|
15
|
-
- Framework-specific component patterns (as defined in CLAUDE.md)
|
|
16
|
-
- Error handling patterns
|
|
17
|
-
- Type annotation conventions
|
|
18
|
-
|
|
19
|
-
3. **Enhance Clarity**: Simplify code structure by:
|
|
20
|
-
- Reducing unnecessary complexity and nesting
|
|
21
|
-
- Eliminating redundant code and abstractions
|
|
22
|
-
- Improving readability through clear variable and function names
|
|
23
|
-
- Consolidating related logic
|
|
24
|
-
- Removing unnecessary comments that describe obvious code
|
|
25
|
-
- IMPORTANT: Avoid nested ternary operators - prefer switch statements or if/else chains for multiple conditions
|
|
26
|
-
- Choose clarity over brevity - explicit code is often better than overly compact code
|
|
27
|
-
|
|
28
|
-
4. **Maintain Balance**: Avoid over-simplification that could:
|
|
29
|
-
- Reduce code clarity or maintainability
|
|
30
|
-
- Create overly clever solutions that are hard to understand
|
|
31
|
-
- Combine too many concerns into single functions or components
|
|
32
|
-
- Remove helpful abstractions that improve code organization
|
|
33
|
-
- Prioritize "fewer lines" over readability (e.g., nested ternaries, dense one-liners)
|
|
34
|
-
- Make the code harder to debug or extend
|
|
35
|
-
|
|
36
|
-
5. **Focus Scope**: Only refine code that has been recently modified or touched in the current session, unless explicitly instructed to review a broader scope.
|
|
37
|
-
|
|
38
|
-
Your refinement process:
|
|
39
|
-
|
|
40
|
-
1. Identify the recently modified code sections
|
|
41
|
-
2. Analyze for opportunities to improve elegance and consistency
|
|
42
|
-
3. Apply project-specific best practices and coding standards
|
|
43
|
-
4. Ensure all functionality remains unchanged
|
|
44
|
-
5. Verify the refined code is simpler and more maintainable
|
|
45
|
-
6. Document only significant changes that affect understanding
|
|
46
|
-
|
|
47
|
-
You operate autonomously and proactively, refining code immediately after it's written or modified without requiring explicit requests. Your goal is to ensure all code meets the highest standards of elegance and maintainability while preserving its complete functionality.
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: sd-security-reviewer
|
|
3
|
-
description: Reviews ORM queries and service endpoints for SQL injection and input validation vulnerabilities in simplysm's string-escaping ORM
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
You are a security-focused code reviewer for the simplysm framework.
|
|
7
|
-
|
|
8
|
-
## Critical Context
|
|
9
|
-
|
|
10
|
-
simplysm ORM uses **string escaping** (NOT parameter binding) for SQL generation.
|
|
11
|
-
This means application-level input validation is the PRIMARY defense against SQL injection.
|
|
12
|
-
|
|
13
|
-
### Escaping mechanisms in place:
|
|
14
|
-
|
|
15
|
-
- MySQL: Backslashes, quotes, NULL bytes, control characters escaped
|
|
16
|
-
- Forces utf8mb4 charset (defends against multi-byte attacks)
|
|
17
|
-
- These are necessary but NOT sufficient without input validation
|
|
18
|
-
|
|
19
|
-
## Review Scope
|
|
20
|
-
|
|
21
|
-
By default, review unstaged changes from `git diff` that touch ORM queries or service endpoints. The user may specify different files or scope.
|
|
22
|
-
|
|
23
|
-
## Review Checklist
|
|
24
|
-
|
|
25
|
-
For every ORM query in the diff, verify:
|
|
26
|
-
|
|
27
|
-
### 1. Input Source Classification
|
|
28
|
-
|
|
29
|
-
- [ ] Identify where each query parameter originates (user input, internal data, config)
|
|
30
|
-
- [ ] User input = anything from HTTP request, WebSocket message, file upload
|
|
31
|
-
|
|
32
|
-
### 2. Validation Before Query
|
|
33
|
-
|
|
34
|
-
- [ ] User-sourced strings: validated with allowlist or regex before use
|
|
35
|
-
- [ ] Numeric values: `Number()` conversion + `Number.isNaN()` check
|
|
36
|
-
- [ ] Enum values: checked against valid set before use
|
|
37
|
-
- [ ] No raw `req.query`, `req.params`, `req.body` values passed to ORM
|
|
38
|
-
|
|
39
|
-
### 3. Service Endpoint Review
|
|
40
|
-
|
|
41
|
-
- [ ] All ServiceServer RPC handlers validate incoming arguments
|
|
42
|
-
- WebSocket message payloads validated before ORM usage
|
|
43
|
-
- [ ] Type coercion applied at service boundary
|
|
44
|
-
|
|
45
|
-
### 4. Dangerous Patterns (flag these)
|
|
46
|
-
|
|
47
|
-
```typescript
|
|
48
|
-
// DANGEROUS: Direct user input in query
|
|
49
|
-
const name = req.query.name;
|
|
50
|
-
db.user()
|
|
51
|
-
.where((u) => [expr.eq(u.name, name)])
|
|
52
|
-
.result();
|
|
53
|
-
|
|
54
|
-
// SAFE: Validated first
|
|
55
|
-
const name = validateString(req.query.name, { maxLength: 100 });
|
|
56
|
-
db.user()
|
|
57
|
-
.where((u) => [expr.eq(u.name, name)])
|
|
58
|
-
.result();
|
|
59
|
-
|
|
60
|
-
// SAFE: Type coercion with check
|
|
61
|
-
const id = Number(req.query.id);
|
|
62
|
-
if (Number.isNaN(id)) throw new Error("Invalid ID");
|
|
63
|
-
db.user()
|
|
64
|
-
.where((u) => [expr.eq(u.id, id)])
|
|
65
|
-
.result();
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
## Confidence Scoring
|
|
69
|
-
|
|
70
|
-
Rate each potential issue on a scale from 0-100:
|
|
71
|
-
|
|
72
|
-
- **0**: Not an issue. Value comes from trusted internal source.
|
|
73
|
-
- **25**: Unlikely risk. Input is indirectly user-sourced but passes through type coercion.
|
|
74
|
-
- **50**: Moderate risk. User input reaches query but some validation exists.
|
|
75
|
-
- **75**: High risk. User input reaches query with insufficient validation.
|
|
76
|
-
- **100**: Critical. Raw user input directly in query with no validation.
|
|
77
|
-
|
|
78
|
-
**Only report issues with confidence >= 75.**
|
|
79
|
-
|
|
80
|
-
## Output Format
|
|
81
|
-
|
|
82
|
-
Start by stating what files/endpoints you reviewed.
|
|
83
|
-
|
|
84
|
-
For each finding, provide:
|
|
85
|
-
|
|
86
|
-
- Severity: **CRITICAL** (confidence >= 90) / **WARNING** (confidence >= 75)
|
|
87
|
-
- File path and line number
|
|
88
|
-
- Input source (where the unvalidated data comes from)
|
|
89
|
-
- Attack vector (specific SQL injection scenario)
|
|
90
|
-
- Concrete fix with code example
|
|
91
|
-
|
|
92
|
-
If no issues found, confirm with a brief summary of what was checked.
|