canicode 0.9.1 → 0.10.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "canicode",
3
- "version": "0.9.1",
3
+ "version": "0.10.1",
4
4
  "mcpName": "io.github.let-sunny/canicode",
5
5
  "description": "Score your Figma designs with AI-calibrated rules. CLI + MCP server.",
6
6
  "type": "module",
@@ -17,21 +17,23 @@
17
17
  }
18
18
  },
19
19
  "scripts": {
20
- "build": "tsup --config tsup.config.ts",
20
+ "build": "tsup --config tsup.config.ts && pnpm build:roundtrip && pnpm bundle:skills",
21
21
  "build:web": "bash scripts/build-web.sh",
22
+ "build:roundtrip": "tsup --config tsup.roundtrip.config.ts",
23
+ "bundle:skills": "bash scripts/bundle-skills.sh",
22
24
  "dev": "tsup --watch",
23
25
  "test": "vitest",
24
26
  "test:run": "vitest run",
25
27
  "lint": "tsc --noEmit",
26
28
  "build:plugin": "bash scripts/build-plugin.sh",
27
29
  "sync-docs": "tsx scripts/sync-rule-docs.ts",
28
- "clean": "rm -rf dist"
30
+ "clean": "rm -rf dist skills"
29
31
  },
30
32
  "files": [
31
33
  "dist",
34
+ "skills",
32
35
  "README.md",
33
- "docs/CUSTOMIZATION.md",
34
- ".claude/skills/design-to-code/PROMPT.md"
36
+ "docs/CUSTOMIZATION.md"
35
37
  ],
36
38
  "keywords": [
37
39
  "figma",
@@ -0,0 +1,76 @@
1
+ ---
2
+ name: canicode
3
+ description: Analyze Figma designs for development-friendliness and AI-friendliness scores
4
+ ---
5
+
6
+ # CanICode -- Figma Design Analysis
7
+
8
+ Analyze Figma design files to score how development-friendly and AI-friendly they are. Produces actionable reports with specific issues and fix suggestions.
9
+
10
+ ## Prerequisites
11
+
12
+ This skill works with either channel — the CLI or the canicode MCP server. Both return the same analysis; pick whichever is already set up. Requires either:
13
+ - A **saved fixture** (from `canicode calibrate-save-fixture`)
14
+ - A **FIGMA_TOKEN** for live Figma URLs
15
+
16
+ ## How to Analyze
17
+
18
+ ### From a Figma URL
19
+
20
+ ```bash
21
+ npx canicode analyze "https://www.figma.com/design/ABC123/MyDesign?node-id=1-234" --token YOUR_TOKEN
22
+ ```
23
+
24
+ Or if FIGMA_TOKEN is set in environment:
25
+ ```bash
26
+ npx canicode analyze "https://www.figma.com/design/ABC123/MyDesign?node-id=1-234"
27
+ ```
28
+
29
+ ### From a saved fixture
30
+
31
+ ```bash
32
+ npx canicode analyze fixtures/my-design
33
+ ```
34
+
35
+ ### Save a fixture for offline analysis
36
+
37
+ ```bash
38
+ npx canicode calibrate-save-fixture "https://www.figma.com/design/ABC123/MyDesign?node-id=1-234" --output fixtures/my-design
39
+ ```
40
+
41
+ ## Analysis Options
42
+
43
+ ### Presets
44
+ - `--preset relaxed` — Downgrades blocking to risk, reduces scores by 50%
45
+ - `--preset dev-friendly` — Enables only pixel-critical and responsive-critical rules, disables the rest
46
+ - `--preset ai-ready` — Sets pixel-critical and token-management rule scores to 150% of defaults
47
+ - `--preset strict` — Increases all scores by 150%
48
+
49
+ ### Config overrides
50
+ ```bash
51
+ npx canicode analyze <input> --config ./my-config.json
52
+ ```
53
+
54
+ ### JSON output
55
+ ```bash
56
+ npx canicode analyze <input> --json
57
+ ```
58
+
59
+ ### Via MCP (when `canicode-mcp` is installed)
60
+
61
+ If the user has the canicode MCP server installed, prefer the MCP tool — it avoids the `npx` spawn overhead and reuses a warm Figma client:
62
+
63
+ ```
64
+ analyze({ input: "<figma-url-or-fixture-path>" })
65
+ ```
66
+
67
+ Options mirror the CLI: `preset`, `token`, `config`, `targetNodeId`, `json`. The `json` response field matches `npx canicode analyze --json` byte-for-byte, so downstream code can parse either source.
68
+
69
+ ## What It Reports
70
+
71
+ 16 rules across 6 categories: Pixel Critical, Responsive Critical, Code Quality, Token Management, Interaction, Semantic.
72
+
73
+ Each issue includes:
74
+ - Rule ID and severity (blocking / risk / missing-info / suggestion)
75
+ - Affected node with Figma deep link
76
+ - Why it matters, impact, and how to fix
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: canicode-gotchas
3
+ description: Gotcha survey workflow plus accumulating per-design answers — one Workflow region on top, numbered sections appended per Figma design
4
+ ---
5
+
6
+ # CanICode Gotchas -- Design Gotcha Survey & Skill Writer
7
+
8
+ Run a gotcha survey on a Figma design to identify implementation pitfalls, collect developer answers, and upsert them into this skill file so code generation agents can reference them automatically. The file has two regions: the **Workflow** below (installed by `canicode init`, never overwritten) and the **Collected Gotchas** region at the bottom (one numbered section per design, replaced in place on re-runs).
9
+
10
+ ## Prerequisites
11
+
12
+ - **canicode MCP server** (preferred): `claude mcp add canicode -e FIGMA_TOKEN=figd_xxx -- npx -y -p canicode canicode-mcp`
13
+ - **Without canicode MCP** (fallback): the `canicode gotcha-survey --json` CLI produces the same response shape — no MCP installation required.
14
+ - **FIGMA_TOKEN** configured for live Figma URLs
15
+
16
+ ## Workflow
17
+
18
+ ### Step 1: Run the gotcha survey
19
+
20
+ If the `gotcha-survey` MCP tool is available, call it with the user's Figma URL:
21
+
22
+ ```
23
+ gotcha-survey({ input: "<figma-url-or-fixture-path>" })
24
+ ```
25
+
26
+ **Without canicode MCP** — shell out to the CLI. The `--json` output parses identically:
27
+
28
+ ```bash
29
+ npx canicode gotcha-survey "<figma-url-or-fixture-path>" --json
30
+ ```
31
+
32
+ Either channel returns:
33
+ - `designGrade`: overall grade (S, A+, A, B+, B, C+, C, D, F)
34
+ - `isReadyForCodeGen`: whether the design can be implemented without gotchas
35
+ - `questions`: array of gotcha questions (may be empty)
36
+
37
+ ### Step 2: Check if survey is needed
38
+
39
+ If `isReadyForCodeGen` is `true` or `questions` is empty:
40
+ - Tell the user: "This design scored **{designGrade}** and is ready for code generation — no gotchas to resolve."
41
+ - Do NOT write to the skill file.
42
+ - Stop here.
43
+
44
+ ### Step 3: Present questions to the user
45
+
46
+ For each question in the `questions` array, present it to the user one at a time:
47
+
48
+ ```
49
+ **[{severity}] {ruleId}** — node: {nodeName}
50
+
51
+ {question}
52
+
53
+ > Hint: {hint}
54
+ > Example: {example}
55
+ ```
56
+
57
+ Wait for the user's answer before moving to the next question. The user may:
58
+ - Answer the question directly
59
+ - Say "skip" to skip a question
60
+ - Say "n/a" if the question is not applicable
61
+
62
+ ### Step 4: Upsert the gotcha section
63
+
64
+ After collecting all answers, **upsert** this design's section into the `# Collected Gotchas` region at the bottom of this file:
65
+
66
+ ```
67
+ .claude/skills/canicode-gotchas/SKILL.md
68
+ ```
69
+
70
+ This file goes in the **user's project** (current working directory), NOT in the canicode repo. The Workflow region above **must never be modified** — only the `# Collected Gotchas` region below is touched.
71
+
72
+ #### Step 4a: Compute `designKey`
73
+
74
+ `designKey` uniquely identifies the design so re-running on the same URL replaces the existing section in place. Parse it from the survey input:
75
+
76
+ - **Figma URL** — extract `fileKey` and `nodeId` from the URL and join them as `<fileKey>#<nodeId>`. Example: `https://figma.com/design/abc123XYZ/My-File?node-id=42-100` → `designKey = "abc123XYZ#42:100"` (convert `-` to `:` in nodeId, the same normalization the Figma MCP uses). Drop any other query-string parameters — only `node-id` matters for the key.
77
+ - **Fixture path** — use the absolute path, e.g. `/Users/me/project/fixtures/simple.json`.
78
+
79
+ Do **not** use the raw survey input URL as the key: trailing query parameters (`?t=...`, `?mode=...`) break string matching on re-runs.
80
+
81
+ #### Step 4b: Read the existing file and locate the target section
82
+
83
+ 1. Read `.claude/skills/canicode-gotchas/SKILL.md` if it exists.
84
+ 2. Detect the file's state using the two structural markers that uniquely identify each case — the YAML frontmatter (present on every `canicode init` install) and the `# Collected Gotchas` heading (present on every post-#340 install):
85
+ - **File missing** → tell the user to run `canicode init` first, then re-invoke this skill. Stop here.
86
+ - **File has YAML frontmatter AND a `# Collected Gotchas` heading** (the default shipped shape since #340) → proceed to step 3 below.
87
+ - **File has YAML frontmatter but no `# Collected Gotchas` heading** (an older workflow install, or a user-edited workflow that dropped the trailing heading) → preserve everything above unchanged and append a new `# Collected Gotchas` heading at the bottom, then proceed to step 3.
88
+ - **File missing the YAML frontmatter** (a pre-#340 single-design clobber — the old overwrite rewrote the frontmatter's `description` to the per-design variant, so a well-formed canicode frontmatter is the cleanest discriminator) → **do not attempt to reconstruct the workflow inline**. Tell the user: "Your gotchas SKILL.md looks like the pre-#340 single-design format. Run `canicode init --force` to restore the workflow, then re-run this survey — your answers will land in a clean numbered section." Stop here.
89
+ 3. Walk the existing `## #NNN — ...` sections under `# Collected Gotchas` and look for one whose `- **Design key**:` bullet matches the `designKey` from Step 4a. Substring match against the bullet value is sufficient.
90
+ - **Found** → replace that section in place. **Preserve its `#NNN` number** so external references (downstream skills, user notes) remain stable.
91
+ - **Not found** → append a new section at the bottom of the region. `#NNN = (highest existing number) + 1`, zero-padded to three digits. Never reuse a number that appeared earlier and was deleted; numbering is monotonic.
92
+
93
+ The Workflow region above must never be touched. Do NOT copy Workflow prose into the per-design section; the section only carries metadata + gotcha answers.
94
+
95
+ ## Output Template
96
+
97
+ Each per-design section in the `# Collected Gotchas` region has this exact shape:
98
+
99
+ ````markdown
100
+ ## #NNN — {designName} — {YYYY-MM-DD}
101
+
102
+ - **Figma URL**: {figmaUrl}
103
+ - **Design key**: {designKey}
104
+ - **Grade**: {designGrade}
105
+ - **Analyzed at**: {analyzedAt}
106
+
107
+ ### Gotchas
108
+
109
+ #### {ruleId} — {nodeName}
110
+
111
+ - **Severity**: {severity}
112
+ - **Node ID**: {nodeId}
113
+ - **Instance context** (omit this bullet if `instanceContext` was not in the survey question): parent instance `parentInstanceNodeId`, source node `sourceNodeId`, component `sourceComponentName` / `sourceComponentId` when present — roundtrip apply uses this to write on the source definition when instance overrides fail.
114
+ - **Question**: {question}
115
+ - **Answer**: {userAnswer}
116
+
117
+ (repeat for each question)
118
+ ````
119
+
120
+ ### Field mapping
121
+
122
+ | Field | Source |
123
+ |-------|--------|
124
+ | `NNN` | `sectionNumber` — zero-padded three-digit index. Preserved on re-run, incremented on append. |
125
+ | `designName` | Figma file name or fixture name from the input |
126
+ | `YYYY-MM-DD` | Today's date (the day you are running the survey) |
127
+ | `figmaUrl` | The input URL or fixture path provided by the user |
128
+ | `designKey` | `<fileKey>#<nodeId>` for Figma URLs, absolute path for fixtures (see Step 4a) |
129
+ | `designGrade` | `designGrade` from gotcha-survey response |
130
+ | `analyzedAt` | Current timestamp (ISO 8601) |
131
+ | `ruleId` | `ruleId` from each question |
132
+ | `nodeName` | `nodeName` from each question |
133
+ | `severity` | `severity` from each question (blocking / risk) |
134
+ | `nodeId` | `nodeId` from each question |
135
+ | `instanceContext` | When present on the question, copy `parentInstanceNodeId`, `sourceNodeId`, `sourceComponentId`, `sourceComponentName` into the bullet above (roundtrip / Plugin apply) |
136
+ | `question` | `question` from each question |
137
+ | `userAnswer` | The answer collected from the user in Step 3 |
138
+
139
+ ### Skipped questions
140
+
141
+ If the user skipped a question or said "n/a", still include it in the section with:
142
+
143
+ ```markdown
144
+ - **Answer**: _(skipped)_
145
+ ```
146
+
147
+ This ensures the code generation agent knows the gotcha exists even if no answer was provided.
148
+
149
+ ## Edge Cases
150
+
151
+ - **No questions returned**: The design is ready for code generation. Inform the user and stop (Step 2). Do not touch the file.
152
+ - **Re-run on the same design**: Replace that design's section in place (matched by `Design key`) — preserve the original `#NNN` number. Do NOT append a duplicate.
153
+ - **Re-run on a different design**: Append a new section with the next `#NNN`. Prior designs' sections are untouched.
154
+ - **Workflow region**: Never modified. If you notice the Workflow region has been edited by the user, leave their edits alone — only the `# Collected Gotchas` region is under skill control.
155
+ - **Pre-#340 clobbered file** (the YAML frontmatter was rewritten to a per-design variant, so the canonical `canicode-gotchas` frontmatter is missing): tell the user to run `canicode init --force` to restore the workflow, then re-run the survey. The prior single-design content cannot be automatically migrated into a `## #001` section — the user re-runs and gets a clean section.
156
+ - **MCP tool not available**: Fall back to `npx canicode gotcha-survey <input> --json` — the CLI returns the same `GotchaSurvey` shape. If the CLI is also unavailable (e.g. no node runtime), tell the user to install the canicode MCP server or the `canicode` npm package (see Prerequisites).
157
+ - **Partial answers**: If the user stops mid-survey, upsert the section with answers collected so far. Mark remaining questions as _(skipped)_.
158
+ - **Manual section deletion**: If the user deletes a middle section by hand, do not renumber existing sections. The next new section still gets `(highest existing number) + 1`; numeric gaps are acceptable (same pattern as `.claude/docs/ADR.md`).
159
+
160
+ # Collected Gotchas