@likyly/wizard 0.0.0-stage → 0.7.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/package.json CHANGED
@@ -1,6 +1,32 @@
1
1
  {
2
2
  "name": "@likyly/wizard",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.7.0",
4
+ "description": "Install LIKYLY in one command: detects your framework, installs the SDK, writes your public key and connects your AI coding assistant (Claude Code, Cursor, VS Code) to the LIKYLY MCP server.",
5
+ "type": "module",
6
+ "bin": {
7
+ "likyly-wizard": "./bin/likyly-wizard.mjs",
8
+ "wizard": "./bin/likyly-wizard.mjs"
9
+ },
10
+ "files": [
11
+ "bin",
12
+ "dist",
13
+ "skill"
14
+ ],
15
+ "scripts": {
16
+ "build": "node build.mjs",
17
+ "pretest": "npm run build",
18
+ "test": "node --test test/*.test.mjs",
19
+ "prepack": "npm run build && mkdir -p skill && cp ../../docs/SKILL.md skill/SKILL.md"
20
+ },
21
+ "engines": {
22
+ "node": ">=22"
23
+ },
24
+ "license": "MIT",
25
+ "devDependencies": {
26
+ "esbuild": "^0.28.2",
27
+ "ink": "^8.0.0",
28
+ "ink-spinner": "^5.0.0",
29
+ "ink-text-input": "^6.0.0",
30
+ "react": "^19.3.1"
31
+ }
32
+ }
package/skill/SKILL.md ADDED
@@ -0,0 +1,312 @@
1
+ ---
2
+ name: likyly
3
+ description: Connect a catalog to LIKYLY, configure a recommendation placement, integrate it into a web app, and verify the integration - using the LIKYLY MCP server's tools. Use when a developer asks to add/configure/integrate/verify LIKYLY recommendations in their project.
4
+ ---
5
+
6
+ # LIKYLY setup guide
7
+
8
+ LIKYLY has no chat of its own - **you are the interface**. Everything below is done through
9
+ the LIKYLY MCP server's tools, which make real, live changes to the developer's LIKYLY
10
+ account (they are not documentation lookups). If the LIKYLY tools aren't available, answer
11
+ with the "Not connected" message below and stop - don't guess at endpoints or hand-write HTTP
12
+ calls instead.
13
+
14
+ ### Not connected
15
+
16
+ Check first that the `likyly` tools really are missing right now (they may have connected since
17
+ the developer's last message): never say both "not connected" and "connected". Then answer with
18
+ exactly this, nothing more:
19
+
20
+ ```
21
+ **✕ LIKYLY · Not connected** - Claude Code can't reach the LIKYLY MCP server.
22
+
23
+ **Your account**
24
+ - Account: <email>
25
+ - Workspace: <name>
26
+
27
+ **What to do**
28
+ 1. Type `/mcp`, choose `likyly`, then **Reconnect**.
29
+ 2. When it shows ✔ connected, send your request again.
30
+ ```
31
+
32
+ - Account and workspace come from the comment lines of `.likyly/credentials.env`; leave the
33
+ block out if the file is missing - then step 1 is "Run `npx @likyly/wizard mcp add` in a
34
+ terminal, then restart Claude Code in this folder".
35
+ - Don't diagnose: the server reads its key from `.likyly/credentials.env` by itself, so never ask
36
+ to export or `source` anything. If Reconnect fails, the developer pastes the error shown by
37
+ `/mcp` and only then you explain.
38
+
39
+ ## Critical rules
40
+
41
+ - **Never** put a secret key or a developer key in code that ships to a browser: an env var
42
+ read client-side, a `NEXT_PUBLIC_*`/`VITE_PUBLIC_*`-prefixed variable, a committed file, or
43
+ anywhere `@likyly/react`'s `<LikylyProvider apiKey>` / `@likyly/sdk`'s browser-facing usage
44
+ can see it. Only the **restricted public key** belongs there. If you only have a developer/
45
+ secret key and need a public one for the browser, ask the developer to grab their public key
46
+ from their LIKYLY account page - never mint or repurpose a developer key for this.
47
+ - **Never** guess at what framework, rendering mode, or auth system the project uses -
48
+ inspect it (package.json, the router/framework in use, existing auth calls) and pass what
49
+ you found into `get_integration_recipe`, don't assume.
50
+ - **Never** claim an integration works without calling `validate_integration` - report exactly
51
+ what it says, not what you expect it to say.
52
+ - **Never** try to auto-track `product_view`, `add_to_cart` or `purchase` - there is no
53
+ universal way to detect these across an arbitrary stack. Find the actual place in the
54
+ project's own code where each happens and add the call there (see Phase 3).
55
+ - **Never** work around a plan limit. A `403` saying `plan limit reached` (a second catalog,
56
+ a second data source, more products) or a `429` on a sync means the workspace's plan does
57
+ not include that - the free plan is 1 catalog, 1 data source, 50 products and 1 sync per day.
58
+ Do not retry, rename the catalog, split the catalog or push through another route: stop, tell
59
+ the developer which limit was hit, and give them the upgrade link from the error message
60
+ (there is no online payment yet - Pro is requested with a form in their LIKYLY console).
61
+ - Every strategy underneath a placement (`content`, `session`, `collaborative`, `hybrid`,
62
+ `popular`, or `auto`) is an existing LIKYLY engine - don't reimplement any of this logic
63
+ yourself, only configure it.
64
+
65
+ ## Phase 1: Connect a catalog
66
+
67
+ Skip this phase if the developer already has a catalog/`product_type` connected - ask, or
68
+ check with `list_data_sources`.
69
+
70
+ **An existing source that is out of date** (old URL, old catalog, ids that no longer match the
71
+ code) is not a reason to stop: fix it with `update_data_source` (new `config.base_url`, new
72
+ `product_type`...). This is not working around the one-source limit - it is the same source.
73
+ Only `delete_data_source` after the developer agrees, since it is irreversible.
74
+
75
+ **A catalog LIKYLY cannot reach** - the site runs on `localhost`, `127.0.0.1`, a `.local` or
76
+ private address, behind a VPN, or the products live only in the codebase - cannot use a pull
77
+ type (`rest_api`, `json_url`, `csv_url`): LIKYLY's servers would try to call their own
78
+ localhost. Use a push source instead, no tunnel needed:
79
+ 1. `create_data_source` with `type: "webhook"` (or `update_data_source` on the existing one)
80
+ and keep the one-time `push_secret` from the response (`rotate_push_secret` if it is lost).
81
+ 2. Read the products from the project itself (its API route handler, JSON files, seed, database
82
+ module), map them to items with the same ids the code uses on product pages.
83
+ 3. `push_items` in batches of up to 1000, then `get_catalog_stats` to confirm the count.
84
+ Tell the developer that a production deployment should switch to a pull source on the public
85
+ URL, or call the push endpoint from their own code when products change.
86
+
87
+ 1. `list_source_types` - see what LIKYLY can connect to and what each type's `config`/
88
+ `credentials` shape looks like.
89
+ 2. `create_data_source` with the type that matches what the developer described (a REST API,
90
+ a CSV, Shopify, ...). This only saves configuration - nothing is fetched yet.
91
+ 3. `test_data_source` - confirms LIKYLY can actually reach it. Fix the config/credentials and
92
+ retry if it fails; don't move on with a broken connection.
93
+ 4. `preview_data_source` - a small real sample plus a suggested field mapping.
94
+ 5. `configure_field_mapping` with `dry_run: true` first to check the mapping's effect on the
95
+ sample, then again with `dry_run: false` (or without the flag) to save it.
96
+ 6. `sync_data_source` (`mode: "full"` for the first sync).
97
+ 7. `get_sync_status` - poll until it's no longer `running`. Report the outcome plainly: items
98
+ synced, items rejected (if any, say why), and the current status - this is what "verify the
99
+ import" means, and the developer will ask for it explicitly if they don't get it
100
+ unprompted.
101
+ 8. `get_catalog_stats` if you want the resulting catalog's item count for the report above.
102
+
103
+ ## Phase 2: Configure recommendations
104
+
105
+ 1. Translate the developer's request into a `create_placement` call. `strategy: "auto"`
106
+ covers most requests on its own (it already blends: identified user + current item ->
107
+ hybrid; current item alone -> content; a session with history -> session; nothing usable ->
108
+ popular) - reach for an explicit strategy only if the developer asked for one specific
109
+ engine. Map their wording to fields:
110
+ - "for anonymous visitors, use the current product and the session" -> `signals: {required:
111
+ ["current_item_id"], optional: ["session_id", "anonymous_id"]}`, `strategy: "auto"`.
112
+ - "personalize once they're logged in" -> add `"user_id"` to `signals.optional` (already
113
+ covered by `auto`, nothing else to configure).
114
+ - "never show the current product" -> `business_rules.exclude_current_item: true` (this is
115
+ already the default - only set it explicitly if the developer wants to confirm it, or set
116
+ it `false` if they explicitly want the opposite).
117
+ - "exclude out-of-stock" -> `filters.in_stock_only: true`.
118
+ - "exclude what's in the cart" -> `signals.optional` includes `"cart_item_ids"`,
119
+ `business_rules.exclude_cart_items: true`.
120
+ - "N items" -> `limit: N`.
121
+ - Where on the site (product page, homepage, cart, ...) -> `context_type`.
122
+ 2. `preview_placement` with a couple of real item ids (and a fake session/user id) from the
123
+ project's own catalog - check `strategy_used` and `items` look right before moving on.
124
+ 3. `get_placement_requirements` - exactly which context keys (`current_item_id`, `user_id`,
125
+ `session_id`, ...) Phase 3's integration needs to supply.
126
+
127
+ ## Phase 3: Integrate
128
+
129
+ **Always ask on which branch, before editing any file.** Run `git branch --show-current` and
130
+ `git status --short`, then ask in one question with numbered choices, and wait for the answer -
131
+ every time, even when the developer seems to be on the right branch already:
132
+
133
+ - On `likyly/setup` (the wizard's branch): "1. Keep working on likyly/setup - recommended ·
134
+ 2. Cancel".
135
+ - On any other branch `<b>`: "1. On a new branch likyly/setup (from `<b>`, which stays as is) -
136
+ recommended · 2. Directly on `<b>` · 3. Cancel". Choice 1: `git switch likyly/setup`, or
137
+ `git switch -c likyly/setup` when it does not exist.
138
+ - Not a git repository: "I'll change files directly (no git to review them). 1. Go · 2. Cancel".
139
+
140
+ Then say in one line where you work. Their uncommitted work comes along untouched: never stash, reset, checkout or restore a file you did not write
141
+ yourself. Never commit or push unless the developer asks; when they ask for a pull request,
142
+ commit only the files you changed (not their pending work), push the branch and open it with
143
+ `gh pr create`.
144
+
145
+ 1. Inspect the project: package manager, framework (React/Next.js/Vue/Svelte/vanilla/other),
146
+ whether it's a Client or Server Component context at the integration point, and whether the
147
+ current user's id is already available there (an existing auth hook/session).
148
+ 2. `get_integration_recipe` with what you found (`placement`, `framework`, `rendering_mode`,
149
+ `has_auth_context`). Use its `packages`/`env`/`publicApi`/`requiredContext`/`requiredEvents`/
150
+ `warnings` - `minimalExample` is a short illustrative snippet, not a file to paste verbatim;
151
+ adapt it to the component you're actually editing, reusing the project's existing markup/
152
+ styling for each recommended item's card.
153
+ 3. Install the packages the recipe named. For React/Next.js: `@likyly/sdk` + `@likyly/react`;
154
+ otherwise `@likyly/sdk` alone.
155
+ 4. Wire the public key in via whatever env var convention the project already uses for public/
156
+ client-side config (see Critical rules) - `<LikylyProvider apiKey={...}>` once near the
157
+ app's root for React/Next.js, or `new Likyly({ apiKey })` once for anything else.
158
+ 5. Render the placement at the integration point:
159
+ - React/Next.js: `<LikylyRecommendations placement="..." itemId={...} userId={...}
160
+ sessionId={...} />` for a fast, auto-tracked (impression + click) integration, or
161
+ `useRecommendations({...})` (headless) if the project needs full control of the markup -
162
+ either way, pass `context.itemId`/`userId`/`sessionId` for whatever `get_placement_
163
+ requirements` named. Use `LikylySession` (from `@likyly/sdk`, exposed as
164
+ `useLikyly().session` under `@likyly/react`) for an anonymous session id if the project
165
+ has none of its own yet.
166
+ - Anything else: `likyly.recommend({ placement, context })`, render the items yourself,
167
+ call `likyly.events.recommendationImpression`/`recommendationClick` for the events
168
+ `<LikylyRecommendations>` would have handled automatically.
169
+ 6. `get_tracking_requirements` for the rest of the funnel. For each event that isn't already
170
+ automatic, find the real place it happens in the project's own code and add the call there:
171
+ `likyly.events.productView` on the product page's own render/mount, `.addToCart` at the
172
+ project's actual add-to-cart handler, `.purchase` (with an `eventId`) at its actual
173
+ checkout-complete point. For a native Shopify/WooCommerce store, prefer the platform's own
174
+ order-completed webhook/event over guessing at custom checkout code.
175
+ 7. If the project has real login, call `likyly.events.identify` (or `LikylySession.identify`)
176
+ right after it succeeds, so the visitor's pre-login session history gets attached to them.
177
+
178
+ ## Phase 4: Verify
179
+
180
+ 1. **Check the code you wrote**, with the project's own tools - never install new ones. Look at
181
+ `package.json` scripts (or the stack's equivalents: `composer`, `pyproject`, `Makefile`...) and
182
+ run, in this order, those that exist: types (`tsc --noEmit` or a `typecheck` script), lint
183
+ (`lint` script), tests (`test` script), build (`build` script). Fix every failure your changes
184
+ caused, then run the check again. A failure in a file you did not touch was already there:
185
+ leave it, and say so in the report. No test suite in the project: say so - don't add one
186
+ unless the developer asks.
187
+ 2. `validate_integration` for the placement you just wired up. Report every check in the
188
+ **Integration** table of the final report, with its count - don't paraphrase it into "looks good."
189
+ 3. For anything not `ok`: `get_recent_integration_events` if you need to see the actual rows
190
+ behind a count, then fix the real cause (a missing call, a wrong `data_product_type`, a
191
+ context key never sent) and validate again. A freshly-added event may need one real
192
+ interaction (view the page, click a card, ...) before it shows up - say so rather than
193
+ treating it as broken on the first check.
194
+
195
+ **Cached answers.** LIKYLY keeps an anonymous visitor's answer for a product for an hour (and
196
+ the site's SDK keeps it in the browser): a page can show the previous recommendations right after
197
+ a change. A catalog or placement change empties LIKYLY's cache on its own; for anything else
198
+ (stock handled outside LIKYLY, a deploy) or when the developer wants to see fresh results now,
199
+ call `purge_recommendation_cache` (the developer can also run `npx @likyly/wizard cache clear
200
+ [placement]` or `/likyly-clear-cache` in Claude Code), and tell them the browser keeps its own
201
+ copy per tab: open the page in a new tab to see the fresh recommendations. Never purge on every check: it is not needed to validate an integration.
202
+
203
+ ## Final report
204
+
205
+ End every LIKYLY task - finished or stopped - with this report and nothing after it: a table
206
+ the developer reads in five seconds, links to check for themselves, and the single next
207
+ action. Write it in the developer's language. **20 lines at most** outside the tables. No
208
+ narration of what you did, no tool names, no scopes, no explanations of how LIKYLY works,
209
+ no list of optional clean-ups.
210
+
211
+ ```
212
+ **◆ LIKYLY · Live** - <one line: what now works, e.g. "recommendations on the shoe product pages">
213
+
214
+ | | | |
215
+ |---|---|---|
216
+ | ◆ | Catalog | <catalog> · <N> products in LIKYLY |
217
+ | ◆ | Recommendations | "<placement title>" · `<route>` · <N> items |
218
+ | ◆ | Tracking | <events, e.g. views, clicks, add to bag> |
219
+
220
+ **Code checks** · on the files I changed
221
+ | | Check | Result |
222
+ |---|---|---|
223
+ | ◆ | Types · `<command>` | no error |
224
+ | ◆ | Lint · `<command>` | no error |
225
+ | ◇ | Tests | no test suite in this project |
226
+ | ◆ | Build · `<command>` | passes |
227
+
228
+ **Integration** · what LIKYLY received from your site, last 24 h
229
+ | | Check | Seen |
230
+ |---|---|---|
231
+ | ◆ | Recommendations requested | <N> |
232
+ | ◆ | Current product sent | <N> |
233
+ | ◆ | Visitor session sent | <N> |
234
+ | ◆ | Shown (impressions) | <N> |
235
+ | ◆ | Clicked | <N> |
236
+ | ◆ | Product views | <N> |
237
+ | ◆ | Add to cart | <N> |
238
+ | ◇ | Purchases | 0 · <why, e.g. no checkout on this site> |
239
+
240
+ **Review** · nothing committed · branch `<branch>`
241
+ - <N> files: `<path>` (new), `<path>` (modified), ...
242
+ - VS Code: Source Control (Ctrl/Cmd+Shift+G) shows each change side by side · or `git diff`
243
+ - Keep it: ask me to commit and open a pull request · Drop it: `git switch <base> && git branch -D likyly/setup`
244
+
245
+ **Check it yourself**
246
+ - Your page: <exact local URL>
247
+ - Your catalog: <console>/account/catalogues/<catalog>/parcourir
248
+ - Your recommendations: <console>/account/recommendations
249
+
250
+ **Your account**
251
+ - Account: <email>
252
+ - Workspace: <name>
253
+ - Console: <console>
254
+
255
+ **Commands**
256
+ | Command | What it does |
257
+ |---|---|
258
+ | `/likyly-help` | Lists these commands and what you can ask in plain words |
259
+ | `/likyly-inventory` | What LIKYLY added to this site: each recommendation block and its page, tracking, setup |
260
+ | `/likyly-model [catalog] [days]` | The recommendation model: versions, which one is live, training date, performance |
261
+ | `/likyly-clear-cache [placement]` | Shows fresh recommendations right away (otherwise they refresh within the hour) |
262
+ | `/likyly-uninstall` | Removes LIKYLY from this project: shows what it will remove, asks on which branch |
263
+
264
+ **Next:** <one action, in one short sentence>
265
+ ```
266
+
267
+ - **Marks** - LIKYLY's own, the same as the wizard's, never emoji: `◆` done · `◇` not yet or not
268
+ needed (say why in the detail) · `✕` blocked or failing. The title uses the same mark:
269
+ `◆ LIKYLY · Live`, `◇ LIKYLY · Not showing yet`, `✕ LIKYLY · Blocked` (then the reason in a few
270
+ words instead of what works).
271
+ - **Summary table**: one row per area, the detail under ten words. Add a row only for something
272
+ that matters to the result.
273
+ - **Catalog**: the product count comes from LIKYLY (the MCP tools), never from the site's own
274
+ files - it is what the developer will find in the console. If the two differ, say so in the
275
+ detail ("20 on the site, 18 in LIKYLY").
276
+ - **Code checks**: one row per check you ran, with the exact command; `◇` with the reason for a
277
+ check the project does not have; `✕` with the first error when one still fails. A failure that
278
+ was already there before your changes: `◇` "fails already, not in my files". Never `◆` a check
279
+ you did not run.
280
+ - **Integration**: every check `validate_integration` returned, in plain words, with its count.
281
+ `◇` for an event the site cannot send (a purchase without a checkout), with why.
282
+ - `◆ Live` only when the code checks have no `✕` and `validate_integration` shows recommendations
283
+ requested and returned. A server error from LIKYLY (5xx) is `✕ Blocked`.
284
+ - **Next** says what the developer does, in plain words, never an id or a code. For a LIKYLY
285
+ server error: "Nothing to change in your code: LIKYLY's API fails on this placement. Reload the
286
+ page once it is fixed, then ask me to check again." Give the request id only if the developer
287
+ asks how to report it.
288
+ - **Review**: list every file you created or changed (from `git status --short`, minus what was
289
+ already modified before you started), new ones marked "new". Leave out the "Drop it" hint when
290
+ you worked on the developer's own branch. Not a git repository: list the files and skip the rest.
291
+ - **Your account**: read the account, workspace and console from the comment lines of
292
+ `.likyly/credentials.env` (`# Account:`, `# Workspace:`, `# Console:`); leave a line out if it is
293
+ not there. `<console>` is the `# Console:` value (e.g. `http://localhost:6001` when testing
294
+ against a local LIKYLY - the catalog only exists there), `https://www.likyly.com` when there is
295
+ none. The developer signs in to that console with this account to see the catalog.
296
+ - **Commands**: one row per command that exists in the project (`.claude/commands/likyly-*.md`),
297
+ each with what it does in plain words. Outside Claude Code, use the terminal forms instead:
298
+ `npx @likyly/wizard cache clear [placement]` and `npx @likyly/wizard uninstall`.
299
+ - **Next** is the single most useful action, in one sentence, with no explanation of causes. If
300
+ you made a mistake along the way (a file changed by accident), it goes there instead.
301
+ - The developer can ask for details: then, and only then, explain.
302
+
303
+ ## Example: one prompt, the whole thing
304
+
305
+ > "Configure LIKYLY on my product pages. I want 4 alternatives. Personalize for logged-in
306
+ > users. For anonymous visitors, use the current product and the session. Never show the
307
+ > current product. Integrate the result into my existing ProductPage component, using my
308
+ > current styling. Add the required tracking. Then verify the integration."
309
+
310
+ Run Phases 2-4 in order for this (Phase 1 only if no catalog is connected yet) - nothing here
311
+ needs the developer to go read LIKYLY's docs by hand if you can get the same information
312
+ through the tools above.