canicode 0.3.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/LICENSE +21 -0
- package/README.md +298 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +4399 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/index.d.ts +1104 -0
- package/dist/index.js +3513 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/server.js +3009 -0
- package/dist/mcp/server.js.map +1 -0
- package/package.json +63 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 minseon
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# CanICode
|
|
2
|
+
|
|
3
|
+
Analyze Figma designs. Score how dev-friendly and AI-friendly they are. Get actionable issues before writing code.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install -g canicode
|
|
7
|
+
canicode init --token YOUR_FIGMA_TOKEN
|
|
8
|
+
canicode analyze "https://www.figma.com/design/ABC123/MyDesign?node-id=1-234"
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
> Run `canicode docs setup` for the full setup guide — CLI, MCP Server, Claude Skills, and all options.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## How It Works
|
|
16
|
+
|
|
17
|
+
39 rules across 6 categories check every node in the Figma tree:
|
|
18
|
+
|
|
19
|
+
| Category | Rules | What it checks |
|
|
20
|
+
|----------|-------|----------------|
|
|
21
|
+
| Layout | 11 | Auto-layout usage, responsive behavior, nesting depth |
|
|
22
|
+
| Design Token | 7 | Color/font/shadow tokenization, spacing consistency |
|
|
23
|
+
| Component | 6 | Component reuse, detached instances, variant coverage |
|
|
24
|
+
| Naming | 5 | Semantic names, default names, naming conventions |
|
|
25
|
+
| AI Readability | 5 | Structure clarity, z-index reliance, empty frames |
|
|
26
|
+
| Handoff Risk | 5 | Hardcoded values, truncation handling, placeholder images |
|
|
27
|
+
|
|
28
|
+
Each issue is classified: **Blocking** > **Risk** > **Missing Info** > **Suggestion**.
|
|
29
|
+
|
|
30
|
+
Scores use density + diversity weighting per category, combined into an overall grade (A/B/C/D/F).
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Getting Started
|
|
35
|
+
|
|
36
|
+
Three ways to use CanICode. Pick one.
|
|
37
|
+
|
|
38
|
+
### CLI (standalone)
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npx canicode analyze "https://www.figma.com/design/ABC123/MyDesign?node-id=1-234"
|
|
42
|
+
|
|
43
|
+
# Or install globally
|
|
44
|
+
npm install -g canicode
|
|
45
|
+
canicode analyze "https://www.figma.com/design/ABC123/MyDesign?node-id=1-234"
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
To enable "Comment on Figma" buttons in reports, set your Figma token:
|
|
49
|
+
```bash
|
|
50
|
+
canicode init --token figd_xxxxxxxxxxxxx
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### MCP Server (Claude Code / Cursor / Claude Desktop)
|
|
54
|
+
|
|
55
|
+
**Claude Code:**
|
|
56
|
+
```bash
|
|
57
|
+
claude mcp add canicode -e FIGMA_TOKEN=figd_xxxxxxxxxxxxx -- npx -y canicode canicode-mcp
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**Cursor** (`~/.cursor/mcp.json`):
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"canicode": {
|
|
65
|
+
"command": "npx",
|
|
66
|
+
"args": ["-y", "canicode", "canicode-mcp"],
|
|
67
|
+
"env": {
|
|
68
|
+
"FIGMA_TOKEN": "figd_xxxxxxxxxxxxx"
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
**Claude Desktop** (`~/Library/Application Support/Claude/claude_desktop_config.json`):
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"mcpServers": {
|
|
79
|
+
"canicode": {
|
|
80
|
+
"command": "npx",
|
|
81
|
+
"args": ["-y", "canicode", "canicode-mcp"],
|
|
82
|
+
"env": {
|
|
83
|
+
"FIGMA_TOKEN": "figd_xxxxxxxxxxxxx"
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Then ask: *"Analyze this Figma design: https://www.figma.com/design/..."*
|
|
91
|
+
|
|
92
|
+
> With `FIGMA_TOKEN` set, the HTML report includes "Comment on Figma" buttons that post analysis findings directly to Figma nodes.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
<details>
|
|
97
|
+
<summary><strong>Data Sources</strong></summary>
|
|
98
|
+
|
|
99
|
+
| Flag | Source | Token required |
|
|
100
|
+
|------|--------|----------------|
|
|
101
|
+
| (none) | Auto-detect: MCP first, then REST API | For API fallback |
|
|
102
|
+
| `--mcp` | Figma MCP via Claude Code | None |
|
|
103
|
+
| `--api` | Figma REST API | Yes |
|
|
104
|
+
|
|
105
|
+
Token priority:
|
|
106
|
+
1. `--token` flag (one-time override)
|
|
107
|
+
2. `FIGMA_TOKEN` env var (CI/CD)
|
|
108
|
+
3. `~/.canicode/config.json` (`canicode init`)
|
|
109
|
+
|
|
110
|
+
</details>
|
|
111
|
+
|
|
112
|
+
<details>
|
|
113
|
+
<summary><strong>Presets</strong></summary>
|
|
114
|
+
|
|
115
|
+
| Preset | Behavior |
|
|
116
|
+
|--------|----------|
|
|
117
|
+
| `relaxed` | Downgrades blocking to risk, reduces scores by 50% |
|
|
118
|
+
| `dev-friendly` | Focuses on layout and handoff rules only |
|
|
119
|
+
| `ai-ready` | Boosts structure and naming rule weights by 150% |
|
|
120
|
+
| `strict` | Enables all rules, increases all scores by 150% |
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
canicode analyze <url> --preset strict
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
</details>
|
|
127
|
+
|
|
128
|
+
<details>
|
|
129
|
+
<summary><strong>Custom Rules</strong></summary>
|
|
130
|
+
|
|
131
|
+
Add project-specific checks via a JSON file:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
canicode analyze <url> --custom-rules ./my-rules.json
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
```json
|
|
138
|
+
[
|
|
139
|
+
{
|
|
140
|
+
"id": "icon-missing-component",
|
|
141
|
+
"category": "component",
|
|
142
|
+
"severity": "blocking",
|
|
143
|
+
"score": -10,
|
|
144
|
+
"prompt": "Check if this node is an icon and is not a component.",
|
|
145
|
+
"why": "Icons that are not components cannot be reused.",
|
|
146
|
+
"impact": "Developers will hardcode icons.",
|
|
147
|
+
"fix": "Convert to a component and publish to the library."
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
See [`examples/custom-rules.json`](examples/custom-rules.json) | Run `canicode docs rules`
|
|
153
|
+
|
|
154
|
+
</details>
|
|
155
|
+
|
|
156
|
+
<details>
|
|
157
|
+
<summary><strong>Config Overrides</strong></summary>
|
|
158
|
+
|
|
159
|
+
Override built-in rule scores, severity, and global settings:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
canicode analyze <url> --config ./my-config.json
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"gridBase": 4,
|
|
168
|
+
"colorTolerance": 5,
|
|
169
|
+
"rules": {
|
|
170
|
+
"no-auto-layout": { "score": -15, "severity": "blocking" },
|
|
171
|
+
"default-name": { "enabled": false }
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
| Option | Description |
|
|
177
|
+
|--------|-------------|
|
|
178
|
+
| `gridBase` | Spacing grid unit (default: 8) |
|
|
179
|
+
| `colorTolerance` | Color difference tolerance (default: 10) |
|
|
180
|
+
| `excludeNodeTypes` | Node types to skip |
|
|
181
|
+
| `excludeNodeNames` | Node name patterns to skip |
|
|
182
|
+
| `rules.<id>.score` | Override rule score |
|
|
183
|
+
| `rules.<id>.severity` | Override rule severity |
|
|
184
|
+
| `rules.<id>.enabled` | Enable/disable a rule |
|
|
185
|
+
|
|
186
|
+
See [`examples/config.json`](examples/config.json) | Run `canicode docs config`
|
|
187
|
+
|
|
188
|
+
</details>
|
|
189
|
+
|
|
190
|
+
<details>
|
|
191
|
+
<summary><strong>Scoring Algorithm</strong></summary>
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
Final Score = (Density Score × 0.7) + (Diversity Score × 0.3)
|
|
195
|
+
|
|
196
|
+
Density Score = 100 - (weighted issue count / node count) × 100
|
|
197
|
+
Diversity Score = (1 - unique violated rules / total rules in category) × 100
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Severity weights issues — a single blocking issue counts 3x more than a suggestion. Scores are calculated per category and combined into an overall grade (A/B/C/D/F).
|
|
201
|
+
|
|
202
|
+
</details>
|
|
203
|
+
|
|
204
|
+
<details>
|
|
205
|
+
<summary><strong>MCP Server Details</strong></summary>
|
|
206
|
+
|
|
207
|
+
The `canicode-mcp` server exposes two tools: `analyze` and `list-rules`.
|
|
208
|
+
|
|
209
|
+
**Route A — Figma MCP relay (no token):**
|
|
210
|
+
|
|
211
|
+
```
|
|
212
|
+
Claude Code → Figma MCP get_metadata → XML node tree
|
|
213
|
+
Claude Code → canicode MCP analyze(designData: XML) → result
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Route B — REST API direct (token):**
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
Claude Code → canicode MCP analyze(input: URL) → internal fetch → result
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
Route A requires two MCP servers (figma + canicode). Route B requires one + a saved token.
|
|
223
|
+
|
|
224
|
+
The `analyze` tool accepts `designData` (XML/JSON from Figma MCP) or `input` (Figma URL / fixture path). When both are provided, `designData` takes priority.
|
|
225
|
+
|
|
226
|
+
</details>
|
|
227
|
+
|
|
228
|
+
<details>
|
|
229
|
+
<summary><strong>Save Fixture</strong></summary>
|
|
230
|
+
|
|
231
|
+
Save Figma file data as JSON for offline analysis:
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
canicode save-fixture https://www.figma.com/design/ABC123/MyDesign
|
|
235
|
+
canicode save-fixture https://www.figma.com/design/ABC123/MyDesign --mcp
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
</details>
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
<details>
|
|
243
|
+
<summary><strong>Tech Stack</strong></summary>
|
|
244
|
+
|
|
245
|
+
| Layer | Tool |
|
|
246
|
+
|-------|------|
|
|
247
|
+
| Runtime | Node.js (>= 18) |
|
|
248
|
+
| Language | TypeScript (strict mode) |
|
|
249
|
+
| Package Manager | pnpm |
|
|
250
|
+
| Validation | Zod |
|
|
251
|
+
| Testing | Vitest |
|
|
252
|
+
| CLI | cac |
|
|
253
|
+
| Build | tsup |
|
|
254
|
+
|
|
255
|
+
</details>
|
|
256
|
+
|
|
257
|
+
<details>
|
|
258
|
+
<summary><strong>Calibration (Internal)</strong></summary>
|
|
259
|
+
|
|
260
|
+
Rule scores are validated against actual code conversion difficulty via a calibration pipeline. This runs inside Claude Code using `/calibrate-loop` — not exposed as a CLI command.
|
|
261
|
+
|
|
262
|
+
The pipeline uses 4 subagents:
|
|
263
|
+
1. **Runner** — Analyzes a fixture and extracts issue data
|
|
264
|
+
2. **Converter** — Converts flagged Figma nodes to code via Figma MCP
|
|
265
|
+
3. **Critic** — Reviews proposed score adjustments
|
|
266
|
+
4. **Arbitrator** — Makes final decisions and commits changes
|
|
267
|
+
|
|
268
|
+
</details>
|
|
269
|
+
|
|
270
|
+
<details>
|
|
271
|
+
<summary><strong>Development</strong></summary>
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
git clone https://github.com/let-sunny/canicode.git
|
|
275
|
+
cd canicode
|
|
276
|
+
pnpm install
|
|
277
|
+
pnpm build
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
pnpm dev # watch mode
|
|
282
|
+
pnpm test # run tests
|
|
283
|
+
pnpm lint # type check
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
</details>
|
|
287
|
+
|
|
288
|
+
## Roadmap
|
|
289
|
+
|
|
290
|
+
- [x] **Phase 1** — 39 rules, density-based scoring, HTML reports, presets, scoped analysis
|
|
291
|
+
- [x] **Phase 2** — 4-agent calibration pipeline, `/calibrate-loop` debate loop
|
|
292
|
+
- [x] **Phase 3** — Custom rules, config overrides, MCP server, Claude Skills
|
|
293
|
+
- [x] **Phase 4** — Figma comment from report (per-issue "Comment" button in HTML report, posts to Figma node via API)
|
|
294
|
+
- [ ] **Phase 5** — Screenshot comparison (Figma vs AI-generated code, visual diff)
|
|
295
|
+
|
|
296
|
+
## License
|
|
297
|
+
|
|
298
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
#!/usr/bin/env node
|