@skilly-hand/skilly-hand 0.12.0 → 0.14.0

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/CHANGELOG.md CHANGED
@@ -16,7 +16,38 @@ All notable changes to this project are documented in this file.
16
16
  ### Removed
17
17
  - _None._
18
18
 
19
- ## [0.12.0] - 2026-04-05
19
+ ## [0.14.0] - 2026-04-06
20
+ [View on npm](https://www.npmjs.com/package/@skilly-hand/skilly-hand/v/0.14.0)
21
+
22
+ ### Added
23
+ - _None._
24
+
25
+ ### Changed
26
+ - _None._
27
+
28
+ ### Fixed
29
+ - _None._
30
+
31
+ ### Removed
32
+ - _None._
33
+
34
+ ## [0.13.0] - 2026-04-05
35
+ [View on npm](https://www.npmjs.com/package/@skilly-hand/skilly-hand/v/0.13.0)
36
+
37
+ ### Added
38
+ - Figma plugin detection support
39
+ - New test fixtures for figma-plugin projects
40
+
41
+ ### Changed
42
+ - Improved project detection logic with configExists helper function
43
+ - Updated skill recommendations for React, Next.js, Angular, Vite, and other technologies
44
+ - Changed figma-mcp-0to1 skill detectors from "always" to "figma"
45
+
46
+ ### Fixed
47
+ - _None._
48
+
49
+ ### Removed
50
+ - _None._
20
51
  [View on npm](https://www.npmjs.com/package/@skilly-hand/skilly-hand/v/0.12.0)
21
52
 
22
53
  ### Added
@@ -4,7 +4,7 @@
4
4
  "description": "Guide users from Figma MCP installation and authentication through first canvas creation, with function-level tool coverage and operational recovery patterns.",
5
5
  "portable": true,
6
6
  "tags": ["figma", "mcp", "workflow", "design"],
7
- "detectors": ["always"],
7
+ "detectors": ["figma"],
8
8
  "detectionTriggers": ["manual"],
9
9
  "installsFor": ["all"],
10
10
  "agentSupport": ["codex", "claude", "cursor", "gemini", "copilot", "antigravity", "windsurf", "trae"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skilly-hand/skilly-hand",
3
- "version": "0.12.0",
3
+ "version": "0.14.0",
4
4
  "license": "CC-BY-NC-4.0",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -31,10 +31,12 @@
31
31
  "test": "node --test tests/*.test.js",
32
32
  "security:check": "node ./scripts/security-check.mjs",
33
33
  "verify:packlist": "node ./scripts/verify-packlist.mjs",
34
- "verify:publish": "npm run security:check && npm run catalog:check && npm test && npm run verify:packlist",
34
+ "verify:versions": "node ./scripts/verify-versions.mjs",
35
+ "verify:publish": "npm run verify:versions && npm run security:check && npm run catalog:check && npm test && npm run verify:packlist",
35
36
  "publish:prepare": "npm run verify:publish && npm pack --dry-run --json",
36
37
  "publish:otp": "node ./scripts/publish-with-otp.mjs",
37
38
  "publish:next": "node ./scripts/publish-with-otp.mjs --tag next",
39
+ "setup:hooks": "node ./scripts/setup-hooks.mjs",
38
40
  "prepublishOnly": "npm run verify:publish",
39
41
  "version": "node ./scripts/release-changelog.mjs",
40
42
  "changelog:release": "node ./scripts/release-changelog.mjs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skilly-hand/catalog",
3
- "version": "0.1.0",
3
+ "version": "0.14.0",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skilly-hand/cli",
3
- "version": "0.1.0",
3
+ "version": "0.14.0",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skilly-hand/core",
3
- "version": "0.1.0",
3
+ "version": "0.14.0",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skilly-hand/detectors",
3
- "version": "0.1.0",
3
+ "version": "0.14.0",
4
4
  "private": true,
5
5
  "type": "module"
6
6
  }
@@ -10,6 +10,13 @@ async function pathExists(filePath) {
10
10
  }
11
11
  }
12
12
 
13
+ async function configExists(cwd, base, extensions = ["js", "ts"]) {
14
+ for (const ext of extensions) {
15
+ if (await pathExists(path.join(cwd, `${base}.${ext}`))) return true;
16
+ }
17
+ return false;
18
+ }
19
+
13
20
  async function readJson(filePath) {
14
21
  if (!(await pathExists(filePath))) {
15
22
  return null;
@@ -41,14 +48,10 @@ export async function detectProject(cwd) {
41
48
  const packageJson = await readJson(path.join(cwd, "package.json"));
42
49
  const tsconfigExists = await pathExists(path.join(cwd, "tsconfig.json"));
43
50
  const angularJsonExists = await pathExists(path.join(cwd, "angular.json"));
44
- const viteConfigExists =
45
- (await pathExists(path.join(cwd, "vite.config.js"))) ||
46
- (await pathExists(path.join(cwd, "vite.config.ts")));
47
- const nextConfigExists =
48
- (await pathExists(path.join(cwd, "next.config.js"))) ||
49
- (await pathExists(path.join(cwd, "next.config.mjs"))) ||
50
- (await pathExists(path.join(cwd, "next.config.ts")));
51
+ const viteConfigExists = await configExists(cwd, "vite.config");
52
+ const nextConfigExists = await configExists(cwd, "next.config", ["js", "mjs", "ts"]);
51
53
  const storybookDirExists = await pathExists(path.join(cwd, ".storybook"));
54
+ const figmaConfigExists = await configExists(cwd, "figma.config");
52
55
  const results = [];
53
56
 
54
57
  if (packageJson) {
@@ -56,27 +59,34 @@ export async function detectProject(cwd) {
56
59
  technology: "nodejs",
57
60
  confidence: 1,
58
61
  reasons: ["Found package.json"],
59
- recommendedSkillIds: ["token-optimizer", "commit-writer", "pr-writer", "spec-driven-development"]
62
+ recommendedSkillIds: [
63
+ "token-optimizer",
64
+ "spec-driven-development",
65
+ "review-rangers",
66
+ "project-teacher"
67
+ ]
60
68
  });
61
69
  }
62
70
 
63
- if (packageJson || tsconfigExists) {
71
+ const deps = packageJson ? { ...packageJson.dependencies, ...packageJson.devDependencies } : {};
72
+
73
+ if (tsconfigExists || "typescript" in deps) {
64
74
  addDetection(results, {
65
75
  technology: "typescript",
66
- confidence: tsconfigExists ? 0.95 : 0.7,
67
- reasons: tsconfigExists ? ["Found tsconfig.json"] : ["TypeScript inferred from project layout"],
76
+ confidence: tsconfigExists ? 0.95 : 0.9,
77
+ reasons: tsconfigExists
78
+ ? ["Found tsconfig.json"]
79
+ : ['Dependency "typescript" found in package.json'],
68
80
  recommendedSkillIds: ["token-optimizer"]
69
81
  });
70
82
  }
71
83
 
72
- const deps = packageJson ? { ...packageJson.dependencies, ...packageJson.devDependencies } : {};
73
-
74
84
  if ("react" in deps) {
75
85
  addDetection(results, {
76
86
  technology: "react",
77
87
  confidence: 0.95,
78
88
  reasons: ['Dependency "react" found in package.json'],
79
- recommendedSkillIds: ["accessibility-audit", "storybook-component-stories", "playwright-ui-testing"]
89
+ recommendedSkillIds: ["accessibility-audit", "react-guidelines", "frontend-design"]
80
90
  });
81
91
  }
82
92
 
@@ -84,8 +94,15 @@ export async function detectProject(cwd) {
84
94
  addDetection(results, {
85
95
  technology: "nextjs",
86
96
  confidence: nextConfigExists ? 1 : 0.9,
87
- reasons: nextConfigExists ? ["Found next.config.*"] : ['Dependency "next" found in package.json'],
88
- recommendedSkillIds: ["accessibility-audit", "playwright-ui-testing", "spec-driven-development"]
97
+ reasons: nextConfigExists
98
+ ? ["Found next.config.*"]
99
+ : ['Dependency "next" found in package.json'],
100
+ recommendedSkillIds: [
101
+ "accessibility-audit",
102
+ "spec-driven-development",
103
+ "react-guidelines",
104
+ "frontend-design"
105
+ ]
89
106
  });
90
107
  }
91
108
 
@@ -93,12 +110,14 @@ export async function detectProject(cwd) {
93
110
  addDetection(results, {
94
111
  technology: "angular",
95
112
  confidence: angularJsonExists ? 1 : 0.95,
96
- reasons: angularJsonExists ? ["Found angular.json"] : ['Dependency "@angular/core" found in package.json'],
113
+ reasons: angularJsonExists
114
+ ? ["Found angular.json"]
115
+ : ['Dependency "@angular/core" found in package.json'],
97
116
  recommendedSkillIds: [
98
117
  "angular-guidelines",
99
- "vitest-component-testing",
100
- "storybook-component-stories",
101
- "accessibility-audit"
118
+ "accessibility-audit",
119
+ "frontend-design",
120
+ "test-driven-development"
102
121
  ]
103
122
  });
104
123
  }
@@ -107,8 +126,10 @@ export async function detectProject(cwd) {
107
126
  addDetection(results, {
108
127
  technology: "vite",
109
128
  confidence: viteConfigExists ? 1 : 0.9,
110
- reasons: viteConfigExists ? ["Found vite.config.*"] : ['Dependency "vite" found in package.json'],
111
- recommendedSkillIds: ["storybook-component-stories", "playwright-ui-testing"]
129
+ reasons: viteConfigExists
130
+ ? ["Found vite.config.*"]
131
+ : ['Dependency "vite" found in package.json'],
132
+ recommendedSkillIds: ["frontend-design"]
112
133
  });
113
134
  }
114
135
 
@@ -117,7 +138,7 @@ export async function detectProject(cwd) {
117
138
  technology: "playwright",
118
139
  confidence: 0.95,
119
140
  reasons: ['Dependency "@playwright/test" found in package.json'],
120
- recommendedSkillIds: ["playwright-ui-testing"]
141
+ recommendedSkillIds: ["test-driven-development"]
121
142
  });
122
143
  }
123
144
 
@@ -126,16 +147,19 @@ export async function detectProject(cwd) {
126
147
  technology: "vitest",
127
148
  confidence: 0.95,
128
149
  reasons: ['Dependency "vitest" found in package.json'],
129
- recommendedSkillIds: ["vitest-component-testing"]
150
+ recommendedSkillIds: ["test-driven-development"]
130
151
  });
131
152
  }
132
153
 
133
- if ("tailwindcss" in deps || (await pathExists(path.join(cwd, "tailwind.config.js"))) || (await pathExists(path.join(cwd, "tailwind.config.ts")))) {
154
+ const tailwindConfigExists = await configExists(cwd, "tailwind.config");
155
+ if ("tailwindcss" in deps || tailwindConfigExists) {
134
156
  addDetection(results, {
135
157
  technology: "tailwindcss",
136
- confidence: 0.9,
137
- reasons: ['Dependency "tailwindcss" or config file found'],
138
- recommendedSkillIds: ["accessibility-audit", "css-modules"]
158
+ confidence: tailwindConfigExists ? 1 : 0.9,
159
+ reasons: tailwindConfigExists
160
+ ? ["Found tailwind.config.*"]
161
+ : ['Dependency "tailwindcss" found in package.json'],
162
+ recommendedSkillIds: ["accessibility-audit", "frontend-design"]
139
163
  });
140
164
  }
141
165
 
@@ -143,8 +167,23 @@ export async function detectProject(cwd) {
143
167
  addDetection(results, {
144
168
  technology: "storybook",
145
169
  confidence: storybookDirExists ? 1 : 0.9,
146
- reasons: storybookDirExists ? ["Found .storybook directory"] : ["Storybook dependency found"],
147
- recommendedSkillIds: ["storybook-component-stories", "playwright-ui-testing"]
170
+ reasons: storybookDirExists
171
+ ? ["Found .storybook directory"]
172
+ : ["Storybook dependency found in package.json"],
173
+ recommendedSkillIds: ["frontend-design"]
174
+ });
175
+ }
176
+
177
+ const figmaDeps = ["@figma/plugin-typings", "@figma/widget-typings", "figma-api"];
178
+ const figmaDepFound = figmaDeps.find((dep) => dep in deps);
179
+ if (figmaConfigExists || figmaDepFound) {
180
+ addDetection(results, {
181
+ technology: "figma",
182
+ confidence: figmaConfigExists ? 1 : 0.95,
183
+ reasons: figmaConfigExists
184
+ ? ["Found figma.config.*"]
185
+ : [`Dependency "${figmaDepFound}" found in package.json`],
186
+ recommendedSkillIds: ["figma-mcp-0to1"]
148
187
  });
149
188
  }
150
189
 
@@ -152,7 +191,20 @@ export async function detectProject(cwd) {
152
191
  }
153
192
 
154
193
  export async function inspectProjectFiles(cwd) {
155
- const probes = ["package.json", "tsconfig.json", "angular.json", ".storybook"];
194
+ const probes = [
195
+ "package.json",
196
+ "tsconfig.json",
197
+ "angular.json",
198
+ ".storybook",
199
+ "vite.config.js",
200
+ "vite.config.ts",
201
+ "next.config.js",
202
+ "next.config.mjs",
203
+ "tailwind.config.js",
204
+ "tailwind.config.ts",
205
+ "figma.config.js",
206
+ "figma.config.ts"
207
+ ];
156
208
  const statuses = [];
157
209
 
158
210
  for (const probe of probes) {