@simplysm/sd-claude 13.0.78 → 13.0.80
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/claude/rules/sd-claude-rules.md +4 -63
- package/claude/rules/sd-simplysm-usage.md +7 -0
- package/claude/sd-session-start.sh +10 -0
- package/claude/skills/sd-api-review/SKILL.md +89 -0
- package/claude/skills/sd-check/SKILL.md +55 -57
- package/claude/skills/sd-commit/SKILL.md +37 -42
- package/claude/skills/sd-debug/SKILL.md +75 -265
- package/claude/skills/sd-document/SKILL.md +63 -53
- package/claude/skills/sd-document/_common.py +94 -0
- package/claude/skills/sd-document/extract_docx.py +19 -48
- package/claude/skills/sd-document/extract_pdf.py +22 -50
- package/claude/skills/sd-document/extract_pptx.py +17 -40
- package/claude/skills/sd-document/extract_xlsx.py +19 -40
- package/claude/skills/sd-email-analyze/SKILL.md +23 -31
- package/claude/skills/sd-email-analyze/email-analyzer.py +79 -65
- package/claude/skills/sd-init/SKILL.md +133 -0
- package/claude/skills/sd-plan/SKILL.md +69 -120
- package/claude/skills/sd-readme/SKILL.md +106 -131
- package/claude/skills/sd-review/SKILL.md +38 -155
- package/claude/skills/sd-simplify/SKILL.md +59 -0
- package/package.json +3 -2
- package/README.md +0 -297
- package/claude/refs/sd-angular.md +0 -127
- package/claude/refs/sd-code-conventions.md +0 -155
- package/claude/refs/sd-directories.md +0 -7
- package/claude/refs/sd-library-issue.md +0 -7
- package/claude/refs/sd-migration.md +0 -7
- package/claude/refs/sd-orm-v12.md +0 -81
- package/claude/refs/sd-orm.md +0 -23
- package/claude/refs/sd-service.md +0 -5
- package/claude/refs/sd-simplysm-docs.md +0 -52
- package/claude/refs/sd-solid.md +0 -68
- package/claude/refs/sd-workflow.md +0 -25
- package/claude/rules/sd-refs-linker.md +0 -52
- package/claude/sd-statusline.js +0 -296
- package/claude/skills/sd-api-name-review/SKILL.md +0 -154
- package/claude/skills/sd-brainstorm/SKILL.md +0 -215
- package/claude/skills/sd-debug/condition-based-waiting-example.ts +0 -158
- package/claude/skills/sd-debug/condition-based-waiting.md +0 -114
- package/claude/skills/sd-debug/defense-in-depth.md +0 -128
- package/claude/skills/sd-debug/find-polluter.sh +0 -64
- package/claude/skills/sd-debug/root-cause-tracing.md +0 -168
- package/claude/skills/sd-discuss/SKILL.md +0 -91
- package/claude/skills/sd-explore/SKILL.md +0 -118
- package/claude/skills/sd-plan-dev/SKILL.md +0 -294
- package/claude/skills/sd-plan-dev/code-quality-reviewer-prompt.md +0 -49
- package/claude/skills/sd-plan-dev/final-review-prompt.md +0 -50
- package/claude/skills/sd-plan-dev/implementer-prompt.md +0 -60
- package/claude/skills/sd-plan-dev/spec-reviewer-prompt.md +0 -45
- package/claude/skills/sd-review/api-reviewer-prompt.md +0 -75
- package/claude/skills/sd-review/code-reviewer-prompt.md +0 -82
- package/claude/skills/sd-review/convention-checker-prompt.md +0 -61
- package/claude/skills/sd-review/refactoring-analyzer-prompt.md +0 -92
- package/claude/skills/sd-skill/SKILL.md +0 -417
- package/claude/skills/sd-skill/anthropic-best-practices.md +0 -156
- package/claude/skills/sd-skill/cso-guide.md +0 -161
- package/claude/skills/sd-skill/examples/CLAUDE_MD_TESTING.md +0 -200
- package/claude/skills/sd-skill/persuasion-principles.md +0 -220
- package/claude/skills/sd-skill/testing-skills-with-subagents.md +0 -408
- package/claude/skills/sd-skill/writing-guide.md +0 -159
- package/claude/skills/sd-tdd/SKILL.md +0 -385
- package/claude/skills/sd-tdd/testing-anti-patterns.md +0 -317
- package/claude/skills/sd-use/SKILL.md +0 -67
- package/claude/skills/sd-worktree/SKILL.md +0 -78
package/claude/refs/sd-orm.md
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# ORM Guidelines
|
|
2
|
-
|
|
3
|
-
## Table Definition
|
|
4
|
-
|
|
5
|
-
```typescript
|
|
6
|
-
const User = Table("User")
|
|
7
|
-
.database("mydb")
|
|
8
|
-
.columns((c) => ({ id: c.bigint().autoIncrement(), name: c.varchar(100) }))
|
|
9
|
-
.primaryKey("id");
|
|
10
|
-
```
|
|
11
|
-
|
|
12
|
-
## SQL Injection Prevention
|
|
13
|
-
|
|
14
|
-
ORM uses string escaping (not parameter binding). **Always validate user input before ORM queries.**
|
|
15
|
-
|
|
16
|
-
```typescript
|
|
17
|
-
const userId = Number(req.query.id);
|
|
18
|
-
if (Number.isNaN(userId)) throw new Error("Invalid ID");
|
|
19
|
-
await db
|
|
20
|
-
.user()
|
|
21
|
-
.where((u) => [expr.eq(u.id, userId)])
|
|
22
|
-
.result();
|
|
23
|
-
```
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
# @simplysm Package Documentation
|
|
2
|
-
|
|
3
|
-
When you need API details, usage examples, or component props for `@simplysm/*` packages,
|
|
4
|
-
read the package's README.md from node_modules.
|
|
5
|
-
|
|
6
|
-
## How to use
|
|
7
|
-
|
|
8
|
-
Read the package README directly:
|
|
9
|
-
|
|
10
|
-
```
|
|
11
|
-
node_modules/@simplysm/{package-name}/README.md
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
If not found (pnpm hoisting), try:
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
packages/*/node_modules/@simplysm/{package-name}/README.md
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
## When to use
|
|
21
|
-
|
|
22
|
-
**MANDATORY**: Read the relevant README BEFORE any of the following:
|
|
23
|
-
|
|
24
|
-
- Writing new code that uses `@simplysm/*` APIs
|
|
25
|
-
- Fixing type errors or bugs in code that uses `@simplysm/*` APIs
|
|
26
|
-
- Making assumptions about type mappings (e.g., DB column types → TypeScript types)
|
|
27
|
-
- Refactoring or migrating code that depends on `@simplysm/*` packages
|
|
28
|
-
|
|
29
|
-
Do NOT guess API behavior or type mappings — always verify from the README first.
|
|
30
|
-
|
|
31
|
-
## Available Packages
|
|
32
|
-
|
|
33
|
-
| Package | Description |
|
|
34
|
-
| ------------------------------ | --------------------------------------------------------------- |
|
|
35
|
-
| `core-common` | Common utilities, custom types (DateTime, DateOnly, Time, Uuid) |
|
|
36
|
-
| `core-browser` | Browser-specific extensions |
|
|
37
|
-
| `core-node` | Node.js utilities (filesystem, workers) |
|
|
38
|
-
| `orm-common` | ORM query builder, table schema definitions |
|
|
39
|
-
| `orm-node` | DB connectors (MySQL, MSSQL, PostgreSQL) |
|
|
40
|
-
| `service-common` | Service protocol, type definitions |
|
|
41
|
-
| `service-client` | WebSocket client |
|
|
42
|
-
| `service-server` | Fastify-based HTTP/WebSocket server |
|
|
43
|
-
| `solid` | SolidJS UI components + Tailwind CSS |
|
|
44
|
-
| `excel` | Excel (.xlsx) read/write |
|
|
45
|
-
| `storage` | FTP/SFTP client |
|
|
46
|
-
| `sd-cli` | Build, lint, typecheck CLI tool |
|
|
47
|
-
| `claude` | Claude Code skills/agents (auto-installs via postinstall) |
|
|
48
|
-
| `eslint-plugin` | Custom ESLint rules |
|
|
49
|
-
| `capacitor-plugin-auto-update` | Auto update |
|
|
50
|
-
| `capacitor-plugin-broadcast` | Broadcast |
|
|
51
|
-
| `capacitor-plugin-file-system` | File system |
|
|
52
|
-
| `capacitor-plugin-usb-storage` | USB storage |
|
package/claude/refs/sd-solid.md
DELETED
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
# SolidJS Guidelines
|
|
2
|
-
|
|
3
|
-
**SolidJS is NOT React!**
|
|
4
|
-
|
|
5
|
-
## Core Concepts
|
|
6
|
-
|
|
7
|
-
- Component functions run **once** at mount (not on every state change)
|
|
8
|
-
- Fine-grained reactivity: unchanged signals don't re-evaluate expressions
|
|
9
|
-
- `createMemo`: only for expensive computations used in multiple places
|
|
10
|
-
- **Props destructuring prohibited** → use `props.xxx`
|
|
11
|
-
- Conditionals: `<Show>`, Lists: `<For>`
|
|
12
|
-
- No SSR → browser APIs usable directly
|
|
13
|
-
- Responsive: Mobile UI below 520px
|
|
14
|
-
- Chrome 84+ target
|
|
15
|
-
- CSS NOT transpiled → no `aspect-ratio`, `inset`, `:is()`, `:where()`
|
|
16
|
-
|
|
17
|
-
## Props Design
|
|
18
|
-
|
|
19
|
-
- Props that don't need parameters must accept plain values (`editable={perms().edit}`), not wrapped in functions (`editable={() => perms().edit}`) — use function props only when parameters are needed (callbacks)
|
|
20
|
-
|
|
21
|
-
## Implementation Rules
|
|
22
|
-
|
|
23
|
-
- Prefer signals/stores over Provider/Context
|
|
24
|
-
- Check existing patterns before introducing abstractions
|
|
25
|
-
- Before modifying components: always Read the file to check existing props/patterns
|
|
26
|
-
|
|
27
|
-
## Hook Naming
|
|
28
|
-
|
|
29
|
-
- `create*`: Reactive hooks wrapping SolidJS primitives
|
|
30
|
-
- `use*`: Hooks depending on Provider Context
|
|
31
|
-
- Others: no hook prefix
|
|
32
|
-
|
|
33
|
-
## Compound Components
|
|
34
|
-
|
|
35
|
-
All sub-components via dot notation only (`Parent.Child`).
|
|
36
|
-
|
|
37
|
-
- Export using `Object.assign` pattern:
|
|
38
|
-
```ts
|
|
39
|
-
export const Select = Object.assign(SelectInnerComponent, {
|
|
40
|
-
Item: SelectItem,
|
|
41
|
-
Header: SelectHeader,
|
|
42
|
-
Action: SelectAction,
|
|
43
|
-
ItemTemplate: SelectItemTemplate,
|
|
44
|
-
});
|
|
45
|
-
```
|
|
46
|
-
- Do NOT declare a separate type or interface for the compound component (e.g., `SelectComponent`, `TabsComponent`)
|
|
47
|
-
- Do NOT use type assertions on the export (e.g., `as SelectComponent`)
|
|
48
|
-
- Don't export sub-components separately (export parent only)
|
|
49
|
-
- UI elements → compound sub-components, non-rendering config (state, behavior, callbacks) → props
|
|
50
|
-
|
|
51
|
-
## Tailwind CSS
|
|
52
|
-
|
|
53
|
-
- `darkMode: "class"`, `aspectRatio` plugin disabled (Chrome 84)
|
|
54
|
-
- Semantic colors: `primary`(blue), `info`(sky), `success`(green), `warning`(amber), `danger`(red), `base`(zinc) → never use `zinc-*` directly
|
|
55
|
-
- Heights: `field`, `field-sm`, `field-lg`
|
|
56
|
-
- z-index: `sidebar`(100), `sidebar-backdrop`(99), `dropdown`(1000)
|
|
57
|
-
- Default `rem`, use `em` for text-relative sizing (e.g., Icon)
|
|
58
|
-
- Use `clsx()` with semantic grouping + `twMerge()` for conflict resolution
|
|
59
|
-
- Before modifying styles: Read existing class patterns of the same component
|
|
60
|
-
- **Class strings inline**: Do not extract class strings into separate variables — write them directly in the JSX return
|
|
61
|
-
- **`*.styles.ts` files**: Tailwind class strings must be wrapped with `clsx()` for IntelliSense support
|
|
62
|
-
|
|
63
|
-
## Application View Naming (`client-*`)
|
|
64
|
-
|
|
65
|
-
- `~Sheet` — List view based on DataSheet (e.g., `UserSheet`)
|
|
66
|
-
- `~Detail` — Single record detail/edit view (e.g., `MyInfoDetail`)
|
|
67
|
-
- `~View` — Everything else (e.g., `LoginView`, `MainView`)
|
|
68
|
-
- Directory: `src/views/` (usable as standalone page, embedded component, or modal)
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# Workflow Rules
|
|
2
|
-
|
|
3
|
-
- **No auto-proceeding after skill completion**: When the user explicitly invokes a skill, report the result and **stop** once the skill finishes. Do not guess the next step and proceed arbitrarily. Wait for explicit user instructions if further work is needed.
|
|
4
|
-
- **Exception — yolo mode**: When a skill explicitly defines a "yolo mode" that chains multiple skills sequentially (e.g., sd-plan's "Path A: yolo"), auto-proceeding is permitted for the duration of that chain. Each step MUST still be invoked via the Skill tool.
|
|
5
|
-
|
|
6
|
-
## Problem-Solving Principles
|
|
7
|
-
|
|
8
|
-
- **Root cause first**: When encountering errors or unexpected behavior, always investigate the root cause before attempting a fix. Do not apply workarounds, hacks, or surface-level patches.
|
|
9
|
-
- **No band-aid fixes**: Avoid techniques like suppressing errors, adding defensive checks to hide symptoms, bypassing validation, or inflating timeout values. These mask the real problem and create technical debt.
|
|
10
|
-
- **Consider refactoring**: If the root cause reveals a design flaw or structural issue, propose a refactoring approach rather than working around it. A proper fix — even if larger in scope — is better than a fragile workaround.
|
|
11
|
-
- **Trace the full chain**: Follow the error or issue through the entire call chain (caller -> callee -> dependencies) to understand why it happens, not just where it happens.
|
|
12
|
-
- **When uncertain, ask**: If the root cause is unclear or the fix requires significant changes, discuss with the user before proceeding. Present findings and options rather than silently applying a quick fix.
|
|
13
|
-
|
|
14
|
-
## Pre-coding Checklist
|
|
15
|
-
|
|
16
|
-
- Before creating new files: Glob/Read similar existing files to check structure and patterns
|
|
17
|
-
- Before modifying functions/classes: Read the file to understand existing code style
|
|
18
|
-
- When unsure about API/method usage: Check signatures in source code
|
|
19
|
-
- **Always search the local codebase first.** Do not search the web or external docs until you have confirmed the answer is not in local code.
|
|
20
|
-
- **If confidence is low, ask the user instead of writing code**
|
|
21
|
-
|
|
22
|
-
## Memory Policy
|
|
23
|
-
|
|
24
|
-
- **Do NOT use auto memory** (`~/.claude/projects/.../memory/`). It is environment-specific and does not persist across machines.
|
|
25
|
-
- All persistent knowledge belongs in `.claude/rules/` or project docs (committed to git).
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
# Reference Guide
|
|
2
|
-
|
|
3
|
-
Before starting work, **Read** the relevant reference files from `.claude/refs/`.
|
|
4
|
-
|
|
5
|
-
## Version Detection
|
|
6
|
-
|
|
7
|
-
Determine the major version by the `version` field in `package.json`.
|
|
8
|
-
|
|
9
|
-
- `12.x.x` → **v12** (< 13)
|
|
10
|
-
- `13.x.x` → **v13** (>= 13)
|
|
11
|
-
|
|
12
|
-
## Common (all versions)
|
|
13
|
-
|
|
14
|
-
| When | Read this file |
|
|
15
|
-
| ------------------------------------------------ | ------------------------------------- |
|
|
16
|
-
| Writing, modifying, or reviewing code | `.claude/refs/sd-code-conventions.md` |
|
|
17
|
-
| Working with `.cache/` or Playwright screenshots | `.claude/refs/sd-directories.md` |
|
|
18
|
-
| Using `@simplysm/*` package APIs | `.claude/refs/sd-simplysm-docs.md` |
|
|
19
|
-
| Debugging, problem-solving, or planning approach | `.claude/refs/sd-workflow.md` |
|
|
20
|
-
| Using `@simplysm/service-*` packages | `.claude/refs/sd-service.md` |
|
|
21
|
-
| Migrating/porting code from another codebase | `.claude/refs/sd-migration.md` |
|
|
22
|
-
| Debugging in a project that uses `@simplysm/*` as an external dependency (not the simplysm monorepo itself) | `.claude/refs/sd-library-issue.md` |
|
|
23
|
-
|
|
24
|
-
## v12 only (< 13)
|
|
25
|
-
|
|
26
|
-
| When | Read this file |
|
|
27
|
-
| -------------------------------------- | ---------------------------- |
|
|
28
|
-
| Working on Angular / @simplysm/sd-angular | `.claude/refs/sd-angular.md` |
|
|
29
|
-
| Using `@simplysm/sd-orm-*` packages | `.claude/refs/sd-orm-v12.md` |
|
|
30
|
-
|
|
31
|
-
- v12 is **Angular** based (no SolidJS)
|
|
32
|
-
- ORM uses **decorator** pattern (`@Table`, `@Column`)
|
|
33
|
-
- Package names: use `sd-` prefix (`sd-core-common`, `sd-orm-common`, etc.)
|
|
34
|
-
- Package manager: **yarn**
|
|
35
|
-
|
|
36
|
-
## v13 only (>= 13)
|
|
37
|
-
|
|
38
|
-
| When | Read this file |
|
|
39
|
-
| -------------------------------------------- | -------------------------- |
|
|
40
|
-
| Working on SolidJS / @simplysm/solid / Tailwind | `.claude/refs/sd-solid.md` |
|
|
41
|
-
| Using `@simplysm/orm-*` packages | `.claude/refs/sd-orm.md` |
|
|
42
|
-
|
|
43
|
-
- v13 is **SolidJS** based (no Angular)
|
|
44
|
-
- ORM uses **functional builder** pattern (`Table().columns().primaryKey()`)
|
|
45
|
-
- Package names: no prefix (`core-common`, `orm-common`, etc.)
|
|
46
|
-
- Package manager: **pnpm**
|
|
47
|
-
|
|
48
|
-
## Rules
|
|
49
|
-
|
|
50
|
-
- Read the reference BEFORE starting the related work (not after)
|
|
51
|
-
- You may read multiple references if the task spans multiple areas
|
|
52
|
-
- If unsure whether a reference applies, read it — the cost of reading is low
|
package/claude/sd-statusline.js
DELETED
|
@@ -1,296 +0,0 @@
|
|
|
1
|
-
// @ts-check
|
|
2
|
-
import fs from "fs";
|
|
3
|
-
import os from "os";
|
|
4
|
-
import path from "path";
|
|
5
|
-
import { stdin } from "process";
|
|
6
|
-
|
|
7
|
-
//#region Constants
|
|
8
|
-
|
|
9
|
-
const STDIN_TIMEOUT_MS = 5000;
|
|
10
|
-
const FETCH_TIMEOUT_MS = 3000;
|
|
11
|
-
const CACHE_TTL_MS = 60_000; // 1 minutes
|
|
12
|
-
const CACHE_PATH = path.join(os.homedir(), ".claude", "usage-api-cache.json");
|
|
13
|
-
|
|
14
|
-
//#endregion
|
|
15
|
-
|
|
16
|
-
//#region Stdin
|
|
17
|
-
|
|
18
|
-
/** @returns {Promise<string>} */
|
|
19
|
-
function readStdin() {
|
|
20
|
-
return new Promise((resolve) => {
|
|
21
|
-
let data = "";
|
|
22
|
-
|
|
23
|
-
const cleanup = () => {
|
|
24
|
-
stdin.removeAllListeners("data");
|
|
25
|
-
stdin.removeAllListeners("end");
|
|
26
|
-
stdin.removeAllListeners("error");
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const timeout = setTimeout(() => {
|
|
30
|
-
cleanup();
|
|
31
|
-
resolve("");
|
|
32
|
-
}, STDIN_TIMEOUT_MS);
|
|
33
|
-
|
|
34
|
-
stdin.setEncoding("utf8");
|
|
35
|
-
stdin.on("data", (chunk) => {
|
|
36
|
-
data += chunk;
|
|
37
|
-
});
|
|
38
|
-
stdin.on("end", () => {
|
|
39
|
-
clearTimeout(timeout);
|
|
40
|
-
cleanup();
|
|
41
|
-
resolve(data);
|
|
42
|
-
});
|
|
43
|
-
stdin.on("error", () => {
|
|
44
|
-
clearTimeout(timeout);
|
|
45
|
-
cleanup();
|
|
46
|
-
resolve("");
|
|
47
|
-
});
|
|
48
|
-
});
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
//#endregion
|
|
52
|
-
|
|
53
|
-
//#region OAuth
|
|
54
|
-
|
|
55
|
-
/** @returns {string | undefined} */
|
|
56
|
-
function getOAuthToken() {
|
|
57
|
-
try {
|
|
58
|
-
const configDir = process.env.CLAUDE_CONFIG_DIR ?? path.join(os.homedir(), ".claude");
|
|
59
|
-
const credentialsPath = path.join(configDir, ".credentials.json");
|
|
60
|
-
if (!fs.existsSync(credentialsPath)) {
|
|
61
|
-
return undefined;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const content = fs.readFileSync(credentialsPath, "utf-8");
|
|
65
|
-
const credentials = JSON.parse(content);
|
|
66
|
-
const oauth = credentials.claudeAiOauth;
|
|
67
|
-
|
|
68
|
-
// Check token expiration
|
|
69
|
-
if (oauth?.expiresAt != null && Date.now() > oauth.expiresAt) {
|
|
70
|
-
return undefined;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
return oauth?.accessToken;
|
|
74
|
-
} catch {
|
|
75
|
-
return undefined;
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Read cached usage data from local file.
|
|
81
|
-
* @returns {{ data: object, timestamp: number } | undefined}
|
|
82
|
-
*/
|
|
83
|
-
function readCache() {
|
|
84
|
-
try {
|
|
85
|
-
if (!fs.existsSync(CACHE_PATH)) return undefined;
|
|
86
|
-
const content = fs.readFileSync(CACHE_PATH, "utf-8");
|
|
87
|
-
return JSON.parse(content);
|
|
88
|
-
} catch {
|
|
89
|
-
return undefined;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Write usage data to local cache file.
|
|
95
|
-
* @param {object} data
|
|
96
|
-
*/
|
|
97
|
-
function writeCache(data) {
|
|
98
|
-
try {
|
|
99
|
-
fs.writeFileSync(CACHE_PATH, JSON.stringify({ data, timestamp: Date.now() }), "utf-8");
|
|
100
|
-
} catch {
|
|
101
|
-
// ignore write errors
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Fetch Anthropic API usage information using OAuth token, with 1-minute cache.
|
|
107
|
-
* @param {string} token - OAuth access token
|
|
108
|
-
* @param {string} version - Claude Code version
|
|
109
|
-
* @returns {Promise<{
|
|
110
|
-
* seven_day?: {utilization?: number, resets_at?: string},
|
|
111
|
-
* daily?: {utilization?: number, resets_at?: string},
|
|
112
|
-
* five_hour?: {utilization?: number, resets_at?: string},
|
|
113
|
-
* extra_usage?: {is_enabled?: boolean, monthly_limit?: number | null, used_credits?: number}
|
|
114
|
-
* } | undefined>}
|
|
115
|
-
*/
|
|
116
|
-
async function fetchUsage(token, version) {
|
|
117
|
-
// Return cached data if still valid
|
|
118
|
-
const cache = readCache();
|
|
119
|
-
if (cache != null && Date.now() - cache.timestamp < CACHE_TTL_MS) {
|
|
120
|
-
return cache.data;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
try {
|
|
124
|
-
const controller = new AbortController();
|
|
125
|
-
const timeout = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
126
|
-
|
|
127
|
-
const response = await fetch("https://api.anthropic.com/api/oauth/usage", {
|
|
128
|
-
headers: {
|
|
129
|
-
"Authorization": `Bearer ${token}`,
|
|
130
|
-
"Accept": "application/json",
|
|
131
|
-
'anthropic-beta': 'oauth-2025-04-20'
|
|
132
|
-
},
|
|
133
|
-
signal: controller.signal,
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
clearTimeout(timeout);
|
|
137
|
-
|
|
138
|
-
if (!response.ok) {
|
|
139
|
-
// API failed — update timestamp to prevent retry for TTL duration
|
|
140
|
-
writeCache(cache?.data ?? {});
|
|
141
|
-
return undefined;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
const data = await response.json();
|
|
145
|
-
|
|
146
|
-
if (data == null || typeof data !== "object") {
|
|
147
|
-
writeCache(cache?.data ?? {});
|
|
148
|
-
return undefined;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
writeCache(data);
|
|
152
|
-
return data;
|
|
153
|
-
} catch {
|
|
154
|
-
// Network error — update timestamp to prevent retry for TTL duration
|
|
155
|
-
writeCache(cache?.data ?? {});
|
|
156
|
-
return undefined;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
//#endregion
|
|
161
|
-
|
|
162
|
-
//#region Formatting
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* @param {number | undefined} value
|
|
166
|
-
* @returns {string}
|
|
167
|
-
*/
|
|
168
|
-
function formatPercent(value) {
|
|
169
|
-
if (value == null) return "?";
|
|
170
|
-
return Math.round(value).toString();
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* @param {string | undefined} isoDate
|
|
175
|
-
* @returns {string}
|
|
176
|
-
*/
|
|
177
|
-
function formatTimeRemaining(isoDate) {
|
|
178
|
-
if (isoDate == null) return "";
|
|
179
|
-
try {
|
|
180
|
-
const resetTime = new Date(isoDate).getTime();
|
|
181
|
-
if (Number.isNaN(resetTime)) return "";
|
|
182
|
-
|
|
183
|
-
const now = Date.now();
|
|
184
|
-
const diffMs = resetTime - now;
|
|
185
|
-
|
|
186
|
-
if (diffMs <= 0) return "";
|
|
187
|
-
|
|
188
|
-
const diffMinutes = Math.floor(diffMs / (1000 * 60));
|
|
189
|
-
const diffHours = Math.floor(diffMinutes / 60);
|
|
190
|
-
const days = Math.floor(diffHours / 24);
|
|
191
|
-
const hours = diffHours % 24;
|
|
192
|
-
const minutes = diffMinutes % 60;
|
|
193
|
-
|
|
194
|
-
if (days > 0) {
|
|
195
|
-
return `${days}d${hours}h`;
|
|
196
|
-
}
|
|
197
|
-
if (hours > 0) {
|
|
198
|
-
return `${hours}h${minutes}m`;
|
|
199
|
-
}
|
|
200
|
-
return `${minutes}m`;
|
|
201
|
-
} catch {
|
|
202
|
-
return "";
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
//#endregion
|
|
207
|
-
|
|
208
|
-
//#region Main
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* JSON information received from stdin
|
|
212
|
-
* @typedef {object} StdinInput
|
|
213
|
-
* @property {{display_name?: string}} [model] - Model information
|
|
214
|
-
* @property {{context_window_size?: number, remaining_context_tokens?: number, current_usage?: {input_tokens?: number, output_tokens?: number, cache_creation_input_tokens?: number, cache_read_input_tokens?: number}}} [context_window] - Context window information
|
|
215
|
-
* @property {{tokens_used?: number, tokens_limit?: number}} [weekly_token_usage] - Weekly token usage (fallback)
|
|
216
|
-
* @property {string} [version] - Claude Code version
|
|
217
|
-
*/
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Output Claude Code status bar information.
|
|
221
|
-
* Combine JSON received from stdin with OAuth API response to output
|
|
222
|
-
* model name, context usage, and daily/weekly usage.
|
|
223
|
-
*/
|
|
224
|
-
async function main() {
|
|
225
|
-
const inputStr = await readStdin();
|
|
226
|
-
/** @type {StdinInput} */
|
|
227
|
-
let input = {};
|
|
228
|
-
|
|
229
|
-
if (inputStr !== "") {
|
|
230
|
-
try {
|
|
231
|
-
input = JSON.parse(inputStr);
|
|
232
|
-
} catch {
|
|
233
|
-
// Use empty object if JSON parsing fails
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// Basic information
|
|
238
|
-
const modelName = input.model?.display_name ?? "Unknown";
|
|
239
|
-
const contextSize = input.context_window?.context_window_size ?? 0;
|
|
240
|
-
const usage = input.context_window?.current_usage;
|
|
241
|
-
const contextUsed =
|
|
242
|
-
(usage?.input_tokens ?? 0) +
|
|
243
|
-
(usage?.output_tokens ?? 0) +
|
|
244
|
-
(usage?.cache_creation_input_tokens ?? 0) +
|
|
245
|
-
(usage?.cache_read_input_tokens ?? 0);
|
|
246
|
-
const contextPercent = contextSize > 0 ? Math.round((contextUsed / contextSize) * 100) : 0;
|
|
247
|
-
|
|
248
|
-
// Try fetching usage with OAuth token
|
|
249
|
-
const token = getOAuthToken();
|
|
250
|
-
let dailyPercent = "?";
|
|
251
|
-
let dailyResetTime = "";
|
|
252
|
-
let weekPercent = "?";
|
|
253
|
-
let weekResetDay = "";
|
|
254
|
-
let extraUsage = "";
|
|
255
|
-
|
|
256
|
-
if (token != null) {
|
|
257
|
-
const usageResponse = await fetchUsage(token, input.version ?? "unknown");
|
|
258
|
-
if (usageResponse != null) {
|
|
259
|
-
// Use daily or five_hour
|
|
260
|
-
const dailyData = usageResponse.daily ?? usageResponse.five_hour;
|
|
261
|
-
dailyPercent = formatPercent(dailyData?.utilization);
|
|
262
|
-
dailyResetTime = formatTimeRemaining(dailyData?.resets_at);
|
|
263
|
-
weekPercent = formatPercent(usageResponse.seven_day?.utilization);
|
|
264
|
-
weekResetDay = formatTimeRemaining(usageResponse.seven_day?.resets_at);
|
|
265
|
-
|
|
266
|
-
// Extra usage
|
|
267
|
-
if (usageResponse.extra_usage?.is_enabled && usageResponse.extra_usage.used_credits != null) {
|
|
268
|
-
extraUsage = `$${(usageResponse.extra_usage.used_credits / 100).toFixed(2)}`;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Fallback: weekly_token_usage
|
|
274
|
-
if (weekPercent === "?" && input.weekly_token_usage != null) {
|
|
275
|
-
const used = input.weekly_token_usage.tokens_used ?? 0;
|
|
276
|
-
const limit = input.weekly_token_usage.tokens_limit ?? 0;
|
|
277
|
-
if (limit > 0) {
|
|
278
|
-
weekPercent = Math.round((used / limit) * 100).toString();
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// Folder name + git branch
|
|
283
|
-
const cwd = input.cwd ?? process.cwd();
|
|
284
|
-
const folderName = path.basename(cwd);
|
|
285
|
-
|
|
286
|
-
// Output
|
|
287
|
-
const dailyStr = dailyResetTime ? `${dailyPercent}%(${dailyResetTime})` : `${dailyPercent}%`;
|
|
288
|
-
const weekStr = weekResetDay ? `${weekPercent}%(${weekResetDay})` : `${weekPercent}%`;
|
|
289
|
-
const parts = [folderName, modelName, `${contextPercent}%`, dailyStr, weekStr];
|
|
290
|
-
if (extraUsage) parts.push(extraUsage);
|
|
291
|
-
console.log(parts.join(" │ "));
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
void main();
|
|
295
|
-
|
|
296
|
-
//#endregion
|
|
@@ -1,154 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: sd-api-name-review
|
|
3
|
-
description: "Public API naming review (explicit invocation only)"
|
|
4
|
-
model: sonnet
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# sd-api-name-review
|
|
8
|
-
|
|
9
|
-
## Overview
|
|
10
|
-
|
|
11
|
-
Compare a library/module's public API names against industry standards and review internal consistency, producing a standardization report. Uses **sd-explore** to extract the API surface, then dispatches research agents for industry comparison.
|
|
12
|
-
|
|
13
|
-
**Analysis only — no code modifications.**
|
|
14
|
-
|
|
15
|
-
## Principles
|
|
16
|
-
|
|
17
|
-
- **Breaking changes are irrelevant**: Do NOT dismiss findings because renaming would cause a breaking change.
|
|
18
|
-
- **Internal consistency first**: Internal naming consistency takes priority over external standards.
|
|
19
|
-
|
|
20
|
-
## Usage
|
|
21
|
-
|
|
22
|
-
- `/sd-api-name-review packages/solid` — full naming review
|
|
23
|
-
- `/sd-api-name-review packages/orm-common` — review specific package
|
|
24
|
-
- `/sd-api-name-review` — if no argument, ask the user for the target path
|
|
25
|
-
|
|
26
|
-
## Target Selection
|
|
27
|
-
|
|
28
|
-
- With argument: review source code at the given path
|
|
29
|
-
- Without argument: ask the user for the target path
|
|
30
|
-
|
|
31
|
-
**Important:** Review ALL source files under the target path. Do not use git status or git diff to limit scope.
|
|
32
|
-
|
|
33
|
-
## Workflow
|
|
34
|
-
|
|
35
|
-
### Step 1: Prepare Context
|
|
36
|
-
|
|
37
|
-
Read these files:
|
|
38
|
-
- `CLAUDE.md` — project overview
|
|
39
|
-
- `.claude/rules/sd-refs-linker.md` — reference guide
|
|
40
|
-
- Target's `package.json` — version (v12/v13)
|
|
41
|
-
|
|
42
|
-
Based on version and target, read all applicable reference files (e.g., `sd-code-conventions.md`, `sd-solid.md`).
|
|
43
|
-
|
|
44
|
-
Keep the collected conventions in memory — they will inform the analysis in later steps.
|
|
45
|
-
|
|
46
|
-
### Step 2: API Extraction (via sd-explore)
|
|
47
|
-
|
|
48
|
-
Follow the **sd-explore** workflow to extract the target's public API surface.
|
|
49
|
-
|
|
50
|
-
**sd-explore input:**
|
|
51
|
-
|
|
52
|
-
- **Target path**: the review target directory
|
|
53
|
-
- **Name**: `api-name-review`
|
|
54
|
-
- **File patterns**: `**/*.ts`, `**/*.tsx` (exclude `node_modules`, `dist`)
|
|
55
|
-
- **Analysis instructions**:
|
|
56
|
-
|
|
57
|
-
"For each file, extract its public API surface:
|
|
58
|
-
- All exported identifiers (functions, classes, types, constants, etc.)
|
|
59
|
-
- Names and types of user-facing parameters/options/config
|
|
60
|
-
- Naming pattern classification (prefixes, suffixes, verb/adjective/noun usage, abbreviations, etc.)
|
|
61
|
-
|
|
62
|
-
Output format:
|
|
63
|
-
```
|
|
64
|
-
# API Surface: [directory names]
|
|
65
|
-
|
|
66
|
-
## Exports
|
|
67
|
-
- `path/to/file.ts` — `exportName`: type (function/class/type/const), signature summary
|
|
68
|
-
|
|
69
|
-
## Naming Patterns
|
|
70
|
-
- Pattern: description (e.g., 'create-' prefix for factory functions)
|
|
71
|
-
- Examples: list of identifiers using this pattern
|
|
72
|
-
```
|
|
73
|
-
"
|
|
74
|
-
|
|
75
|
-
### Step 3: Industry Standard Research
|
|
76
|
-
|
|
77
|
-
Based on Step 2 results:
|
|
78
|
-
|
|
79
|
-
1. Identify **recurring naming patterns** from the extracted API
|
|
80
|
-
2. Determine the target's domain and tech stack to **select comparable libraries**
|
|
81
|
-
3. Dispatch **parallel agents** to web-search/fetch official docs for each comparable library, investigating naming conventions for the same pattern categories
|
|
82
|
-
|
|
83
|
-
Each research agent receives:
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
Research naming conventions in [library name] for these pattern categories:
|
|
87
|
-
[list of patterns from Step 2]
|
|
88
|
-
|
|
89
|
-
For each pattern, document:
|
|
90
|
-
- What naming convention the library uses
|
|
91
|
-
- Specific examples from the API
|
|
92
|
-
- Any documented rationale for the convention
|
|
93
|
-
|
|
94
|
-
Write results to: .tmp/api-name-review/research-{library_name}.md
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### Step 4: Comparative Analysis & Verification
|
|
98
|
-
|
|
99
|
-
Cross-compare Step 2 (API surface) and Step 3 (industry research) results.
|
|
100
|
-
|
|
101
|
-
Classify each naming pattern:
|
|
102
|
-
|
|
103
|
-
| Priority | Criteria |
|
|
104
|
-
| -------- | ------------------------------------------------------ |
|
|
105
|
-
| **P0** | Misaligned with majority of surveyed libraries |
|
|
106
|
-
| **P1** | Internal inconsistency (same concept, different names) |
|
|
107
|
-
| **P2** | Better industry term exists (optional) |
|
|
108
|
-
| **Keep** | Already aligned with standards |
|
|
109
|
-
|
|
110
|
-
**MANDATORY: Read actual code for EVERY finding.** For each finding, `Read` the file at the referenced location before finalizing. Do NOT rely on explore descriptions alone — verify against the actual code.
|
|
111
|
-
|
|
112
|
-
Each finding includes: current name, recommended change, rationale (usage patterns per library).
|
|
113
|
-
|
|
114
|
-
### Step 5: Report & User Confirmation
|
|
115
|
-
|
|
116
|
-
Present **Keep** items to the user as a summary.
|
|
117
|
-
|
|
118
|
-
Then present each **P0/P1/P2** finding to the user **one at a time**, ordered by priority (P0 → P1 → P2).
|
|
119
|
-
|
|
120
|
-
For each finding, explain:
|
|
121
|
-
1. **What the problem is** — the current name and why it's misaligned or inconsistent
|
|
122
|
-
2. **How it could be fixed** — recommended name(s) with rationale from surveyed libraries
|
|
123
|
-
3. **Ask**: address this or skip?
|
|
124
|
-
|
|
125
|
-
Collect only findings the user confirms. If the user skips all findings, report that and end.
|
|
126
|
-
|
|
127
|
-
### Step 6: Brainstorm Handoff
|
|
128
|
-
|
|
129
|
-
Invoke **sd-brainstorm** with all user-confirmed findings as context:
|
|
130
|
-
|
|
131
|
-
_
|
|
132
|
-
"Design naming changes for the following review findings.
|
|
133
|
-
|
|
134
|
-
**For each finding, you MUST:**
|
|
135
|
-
1. Review it thoroughly — examine the code, understand the context, assess the real impact
|
|
136
|
-
2. If any aspect is unclear or ambiguous, ask the user (one question at a time, per brainstorm rules)
|
|
137
|
-
3. If a finding has low cost-benefit (adds complexity for marginal gain, pure style preference, scope too small), drop it. After triage, briefly list all dropped findings with one-line reasons (no user confirmation needed).
|
|
138
|
-
4. For findings worth fixing, explore approaches and design solutions
|
|
139
|
-
|
|
140
|
-
Findings that survive your triage become the design scope. Apply your normal brainstorm process (gap review → approaches → design presentation) to the surviving findings as a group.
|
|
141
|
-
|
|
142
|
-
<include all confirmed findings with their priority, file:line, current name, recommended name, and rationale>"
|
|
143
|
-
|
|
144
|
-
sd-brainstorm then owns the full cycle: triage (with user input as needed) → design.
|
|
145
|
-
|
|
146
|
-
## Common Mistakes
|
|
147
|
-
|
|
148
|
-
| Mistake | Fix |
|
|
149
|
-
|---------|-----|
|
|
150
|
-
| Using git diff to limit scope | Review ALL source files under target |
|
|
151
|
-
| Skipping context preparation | Always read conventions and refs before analysis |
|
|
152
|
-
| Skipping verification | Always verify findings against actual code |
|
|
153
|
-
| Dismissing findings due to breaking changes | Breaking changes are irrelevant — report the naming issue |
|
|
154
|
-
| Not writing research results to files | Research agents MUST write to disk — prevents context bloat |
|