From 8b94442023e3e30ff5ab5ba22c0a588a0153ce9b Mon Sep 17 00:00:00 2001 From: Rohan Suresh Date: Tue, 19 May 2026 12:37:30 -0400 Subject: [PATCH 1/3] Add retool-import-lovable sibling skill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sibling skill that specializes the import flow for legacy-Vite Lovable projects (lovable-tagger or .lovable/ at repo root). Skips the generic vendor-agnostic discovery scan because Lovable's structure is known up front — Vite + react-router-dom + Supabase edge functions calling the connector-gateway proxy — and pre-fills IMPORT_PLAN.md from structural facts. Targeted HITL: one prompt per Supabase edge function (mapping the connector-gateway service to a Retool resource) and one combined prompt per migrations directory. Generic retool-import skill gains a Phase 0 source-tool detection step that delegates to this sibling via the Skill tool when Lovable signals are present. Phase 0 is structural (signal files only) — Phases 1-4 of the generic skill remain strictly vendor-agnostic. TanStack Start Lovable projects (post-April 2026 format) are explicitly out of scope and the skill refuses them with a clear message. --- .../skills/retool-import-lovable/SKILL.md | 364 ++++++++++++++++++ .../skills/retool-import/SKILL.md | 51 ++- 2 files changed, 406 insertions(+), 9 deletions(-) create mode 100644 plugins/retool-import/skills/retool-import-lovable/SKILL.md diff --git a/plugins/retool-import/skills/retool-import-lovable/SKILL.md b/plugins/retool-import/skills/retool-import-lovable/SKILL.md new file mode 100644 index 0000000..3afd8b3 --- /dev/null +++ b/plugins/retool-import/skills/retool-import-lovable/SKILL.md @@ -0,0 +1,364 @@ +--- +name: retool-import-lovable +description: Use this skill when the user wants to import a Lovable-generated React app (legacy Vite + Supabase) into Retool as an R^2 app. Detected by `lovable-tagger` in package.json or a `.lovable/` directory at the repo root. The skill skips vendor-agnostic discovery because Lovable's structure (Vite + react-router-dom + Supabase edge functions calling Lovable's connector gateway) is known up front; it pre-fills the import plan from structural facts, asks targeted HITL only for the choices that genuinely need a human (which Retool resource backs each Supabase edge function and migration), and hands a prepared import plan to Retool's R^2 sandbox agent via the `retool_submit_prepared_import` MCP tool. +--- + +# retool-import-lovable + +Lovable-specialized variant of the [`retool-import`](../retool-import/SKILL.md) skill. Use this skill instead of the generic one when the project shows Lovable signals — the generic skill detects those signals in its Phase 0 and delegates here automatically. The skill remains directly invocable for users who already know they have a Lovable export. + +## Why this exists + +The generic `retool-import` skill is vendor-agnostic by design: it runs a closed-taxonomy discovery scan against an arbitrary React repo. That works for any source tool, but it's wasted work for projects with predictable structure. A legacy-Vite Lovable project ALWAYS has: + +- Vite + React + `react-router-dom` for the frontend (entry at `src/main.tsx` → `src/App.tsx`) +- Tailwind + shadcn primitives under `src/components/ui/` +- Supabase as the backend: edge functions under `supabase/functions//index.ts` (Deno runtime) and migrations under `supabase/migrations/*.sql` +- Lovable's connector gateway (`connector-gateway.lovable.dev/`) proxying third-party APIs (Linear, Slack, S3, Gmail, etc.) from inside the edge functions +- `VITE_SUPABASE_URL` / `VITE_SUPABASE_PUBLISHABLE_KEY` / `VITE_SUPABASE_PROJECT_ID` env vars + +Because the shape is known, this skill pre-fills the IMPORT_PLAN.md from structural facts and only asks HITL questions that genuinely cannot be answered from the source tree (which Retool resource owns the schema, which Retool resource backs each connector-gateway service). + +## Scope + +This skill handles **legacy Vite Lovable projects** only. Lovable began emitting TanStack Start projects (with `@tanstack/react-start`, `src/app/__root.tsx`, file-based routing, SSR) around April 2026. Those projects have a different entry shape and routing model and are NOT supported here. See [TanStack guard](#tanstack-guard) below for the refuse behavior. + +## State machine overview + +The skill runs these steps sequentially. Each has a fixed input, a fixed output, and a fixed exit condition. + +1. Prerequisites check — confirm React repo + MCP tools. +2. Lovable signal validation — confirm Lovable signals are present; refuse TanStack projects. +3. Pre-fill — populate the structural facts table from the known Lovable layout (no discovery scan). +4. Targeted HITL — one prompt per Supabase edge function, one combined prompt per migration directory, one prompt for Supabase Auth if used. +5. Produce artifacts — cleaned source tree (shared filter + Lovable-specific drops) plus pre-populated IMPORT_PLAN.md. +6. Handoff — call `retool_submit_prepared_import` with the cleaned tree and plan. + +Do NOT skip steps. Do NOT pause for user input outside step 4. + +## 1. Prerequisites check + +Same as the generic skill. Verify and stop with a clear error if either fails: + +1. **React repo.** Read `package.json` at the repo root. The `dependencies` (or `devDependencies`) must include `react`. If not, stop and tell the user this skill targets React apps. +2. **Required MCP tools.** `retool_list_resources` and `retool_submit_prepared_import` must both be visible. If `retool_submit_prepared_import` is missing, stop with: "The retool-import-lovable skill requires `retool_submit_prepared_import`, which is gated by the `mcpServerRetoolImportEnabled` flag. Ask your Retool admin to enable that flag for your org." + +## 2. Lovable signal validation + +### Lovable signal present + +Confirm at least one of: + +- `lovable-tagger` in `devDependencies` of the repo root `package.json` +- `.lovable/` directory exists at the repo root +- `src/integrations/supabase/client.ts` AND `src/integrations/supabase/types.ts` both exist (a weaker signal — only treat as positive if combined with one of the above) + +If none of these are present, stop and tell the user: "No Lovable signals detected. Use the generic `retool-import` skill instead — it works on any React app via vendor-agnostic discovery." + +### TanStack guard + +If the repo root `package.json` contains `@tanstack/react-start` (in either `dependencies` or `devDependencies`), OR `src/app/__root.tsx` exists, stop with this message: + +``` +This project appears to be a Lovable TanStack Start app (post-April 2026 +format). This skill currently supports legacy Vite Lovable projects only — +TanStack Start has a different entry shape, file-based routing, and SSR +that need their own transformation recipes. + +For now, please run the generic `retool-import` skill, which uses +vendor-agnostic discovery and will still produce a useful import plan +(it just won't pre-fill from Lovable structural knowledge). +``` + +Do NOT attempt a best-effort import on TanStack projects. + +### React entry exists + +Confirm `src/main.tsx` and `src/App.tsx` both exist. If either is missing, this isn't a standard Lovable scaffold — stop and point the user at the generic skill. + +## 3. Pre-fill from structural facts + +The following file-role mapping is true for every legacy-Vite Lovable project. Treat it as ground truth; do not re-derive it via discovery. + +| Source path | Role | Disposition | +| ----------- | ---- | ----------- | +| `src/main.tsx` | `createRoot` bootstrap | DROP — R2's baked `/frontend/index.tsx` owns this | +| `src/App.tsx` | `` table | PORT to `/frontend/App.tsx` | +| `src/pages/*.tsx` | route page components | PORT to `/frontend/pages/` | +| `src/components/.tsx` | feature components | PORT to `/frontend/components/` | +| `src/components/ui/*.tsx` | shadcn primitives | DROP — R2 has these baked at `/frontend/lib/shadcn/` | +| `src/hooks/use-toast.ts`, `src/hooks/use-mobile.tsx` | shadcn hook duplicates | DROP — R2 baked | +| `src/hooks/.{ts,tsx}` | user hooks | PORT to `/frontend/hooks/` | +| `src/lib/utils.ts` | `cn()` helper | DROP — R2 baked has it | +| `src/lib/edge.ts` | `callEdgeFunction` wrapper | DROP — call sites rewrite to generated backend-fn hooks | +| `src/integrations/supabase/client.ts` | Supabase client | DROP — call sites rewrite to generated backend-fn hooks | +| `src/integrations/supabase/types.ts` | auto-generated DB types | DROP from the import; surface schema in HITL instead | +| `src/index.css` | Tailwind directives + global CSS | MERGE custom rules into R2's baked Tailwind; surface non-default `@layer` blocks in Styling adapters | +| `src/App.css` | additional CSS | PORT to `/frontend/App.css` only if non-empty and not just Vite defaults | +| `src/vite-env.d.ts` | Vite TS shim | DROP — R2 baked | +| `supabase/functions//index.ts` | Deno edge function | REWRITE as R2 backend function — one HITL prompt per function (see step 4.1) | +| `supabase/migrations/*.sql` | Postgres schema migrations | Surface tables in HITL; user picks Retool Postgres resource (see step 4.2). Do NOT auto-apply. | +| `supabase/config.toml` | Supabase project ID | DROP | +| `public/*` | static assets (favicon, robots.txt, etc.) | PORT to `/frontend/public/` | +| `vite.config.ts` | Vite config (loads `lovable-tagger`) | DROP — R2 owns its baked Vite config | +| `tsconfig.json`, `tsconfig.app.json`, `tsconfig.node.json` | TS configs | DROP — R2 baked | +| `tailwind.config.ts` / `tailwind.config.js` | Tailwind theme | DROP the file; surface non-default theme extensions in Styling adapters | +| `postcss.config.{js,cjs,mjs}` | PostCSS config | DROP — R2 baked | +| `eslint.config.{js,cjs}` | ESLint config | DROP — R2 baked | +| `components.json` | shadcn registry config | DROP — R2 owns its shadcn registry | +| `index.html` | Vite HTML entry | DROP — R2 baked | +| `playwright.config.ts`, `playwright-fixture.ts`, `vitest.config.ts` | testing scaffold | DROP — R2 doesn't execute these | +| `.lovable/sync.config.json` | Lovable GitHub sync metadata | DROP | +| `.env`, `.env.local` | secrets | DROP (already filtered by shared zip filter) | +| `.env.example` | env template | KEEP (shared zip filter already preserves this) | +| lockfiles (`bun.lockb`, `bun.lock`, `package-lock.json`, etc.) | DROP (shared filter) | +| `README.md` | project readme | DROP — usually just the Lovable scaffold placeholder | + +If the project contains files at paths NOT listed above (e.g. `src/contexts/`, `src/stores/`, `src/utils/`), default to PORT under `/frontend//`. Only deviate from the table when the source path matches a row. + +## 4. Targeted HITL + +Run all three prompts in this order. The user answers each in the terminal. After all answers are in, present the resolutions back in a single summary and ask `Proceed? (y/n)`. + +### 4.1. Supabase edge functions → Retool resources + +For each `supabase/functions//index.ts` (skip the `_shared/` subdirectory if present — it holds shared helpers, not a function): + +1. Read the file. +2. Look for `connector-gateway.lovable.dev/` URLs. The path segment after `.dev/` identifies the upstream service. Common mappings: + + | Gateway path | Inferred category | Compatible Retool resource types | + | ------------ | ----------------- | -------------------------------- | + | `linear`, `github`, `notion`, `asana`, `monday`, `jira` | `http_api` | `rest_api`, `graphql` | + | `slack` | `http_api` | `rest_api` (Retool's Slack integration is wrapped REST) | + | `aws_s3`, `gcs_storage` | `object_storage` | `s3`, `gcs` | + | `gmail`, `sendgrid_email` | `email` | `sendgrid`, `smtp`, `rest_api` | + | `postgres`, `mysql`, `bigquery`, `snowflake` | `database` | the matching native type | + | `stripe` | `payments` | `stripe`, `rest_api` | + | `openai`, `anthropic` | `ai` | `openai`, `rest_api` | + | anything else | `unknown` | (no filter — surface all candidates) | + +3. If NO gateway URL is present, the function talks directly to some service via SDK imports or env-var-driven `fetch` calls. Apply the three generic detection heuristics from the [discovery subagent brief](../../agents/discovery-subagent.md#detection-heuristics--apply-generically) — third-party imports, env var references, non-relative HTTP calls — to that single file. Pick the strongest signal and infer the category as above. +4. Call `retool_list_resources` with the compatible-types filter (or no filter for `unknown`). Take the top 3 candidates scored by case-insensitive token overlap between resource name/displayName and the gateway-path tokens. +5. Present the prompt: + + ``` + Edge function: supabase/functions// + Calls: via Lovable connector gateway + (or: "direct SDK usage" if no gateway URL) + Will become R2 backend function: + + Compatible Retool resources of type []: + 1) (, environments: ...) + 2) (, environments: ...) + 3) (, environments: ...) + + Note: resource matching is currently by name + type only; + host metadata isn't surfaced yet. + + Pick a resource by number, type USE_MOCK_DATA to mock, + or type a resource name not in the list above. + ``` + +6. Record the answer keyed by `(function name, inferred category)`. + +### 4.2. Supabase migrations → Retool Postgres resource + +If `supabase/migrations/` contains any `*.sql` files: + +1. Read every `.sql` file in that directory. +2. Extract table names from `CREATE TABLE [IF NOT EXISTS] .` statements. Also note any `CREATE POLICY` (RLS) statements, but do NOT try to translate them — surface as open questions. +3. Treat all migrations as one combined Data needs row: `vendor: supabase`, `category: database`. +4. Call `retool_list_resources` with `resource_type=postgres`. Take the top 3 candidates (name + type only). +5. Present: + + ``` + Detected Supabase schema: + Migrations: .sql files in supabase/migrations/ + Tables: + RLS policies: (will be surfaced as open questions, not auto-translated) + + Compatible Retool Postgres resources: + 1) (postgres, environments: ...) + 2) (postgres, environments: ...) + 3) (postgres, environments: ...) + + Pick a resource by number, USE_MOCK_DATA, or type a custom resource name. + + IMPORTANT: this skill does NOT auto-apply your migrations. After import, + you'll need to apply the SQL in supabase/migrations/ against your chosen + Postgres resource manually (or via R2's follow-up flow). + ``` + +6. Record the answer. + +### 4.3. Supabase Auth (if detected) + +Scan the ported source files for any reference to `supabase.auth.` or imports of `signIn` / `signUp` / `signOut` / `onAuthStateChange` from `@supabase/supabase-js`. + +If any are found, present: + +``` +Supabase Auth detected. Used in: . + +R2 does not currently auto-translate Supabase Auth to Retool sessions. +Pick a strategy: + 1) USE_MOCK_DATA — mock the current user during import; wire later + 2) MAP_TO_RETOOL_SESSION — replace useAuth() / supabase.auth calls + with R2's useCurrentUser() hook (best-effort substitution; some + code paths may need manual review) + 3) Type a custom resolution strategy describing what you want +``` + +Record the answer. + +If no Supabase Auth calls are detected, skip this prompt. + +### 4.4. Summary + +Present every recorded resolution in one block: + +``` +Resolutions: + - + - + - Supabase schema → + - Supabase Auth → +``` + +Then ask `Proceed? (y/n)`. On `n`, return to whichever prompt the user wants to revise. On `y`, proceed to step 5. + +## 5. Produce artifacts + +### 5a. Cleaned source tree + +Walk the repo and apply the shared zip filter at `../../references/filter-constants.ts` (`shouldSkipZipEntry`, `isTextFile`, per-file 1 MiB cap, aggregate 50 MiB cap, 5,000 file count cap). + +In addition to the shared filter, drop these Lovable-specific paths (always): + +- `vite.config.ts` +- `tsconfig.json`, `tsconfig.app.json`, `tsconfig.node.json` +- `postcss.config.js`, `postcss.config.cjs`, `postcss.config.mjs` +- `eslint.config.js`, `eslint.config.cjs` +- `components.json` +- `tailwind.config.ts`, `tailwind.config.js` +- `index.html` +- `playwright.config.ts`, `playwright-fixture.ts`, `vitest.config.ts` +- `supabase/config.toml` +- All files under `.lovable/` +- All files under `src/components/ui/` +- `src/main.tsx` +- `src/integrations/supabase/client.ts` +- `src/integrations/supabase/types.ts` +- `src/lib/edge.ts` +- `src/vite-env.d.ts` +- `README.md` (drop only if its content is the default Lovable scaffold; otherwise keep) + +Stop and warn the user if the file count exceeds 5,000 or the aggregate size exceeds 50 MiB. Surface the offending paths and ask how to proceed. + +Build a `Record` keyed by repo-relative path. This is the `files` payload for `retool_submit_prepared_import`. + +### 5b. IMPORT_PLAN.md + +Start from `../../references/IMPORT_PLAN.template.md`. Fill in: + +**`status=prepared_by_mcp`** — already in the template; keep it. + +**Overview** — 2-3 sentences identifying this as a Lovable (legacy Vite) + Supabase project. Mention the React entry, the count of Supabase edge functions, and the count of migrations. Example: "Legacy-Vite Lovable project with React entry at `src/main.tsx` → `src/App.tsx`. Backend is 3 Supabase edge functions and 1 migration creating 1 table. The edge functions proxy Linear, Slack, and AWS S3 via Lovable's connector gateway." + +**Routes & pages** — parse the `` table from `src/App.tsx`. For each `} />`: + +| route | page file | purpose | auth required | +| ----- | --------- | ------- | ------------- | +| `/` | `src/pages/Index.tsx` | | Y/N | + +`auth required` is `Y` if the page imports anything from `@supabase/supabase-js` auth helpers, else `N`. If `src/App.tsx`'s route table can't be parsed cleanly (unusual route shape, dynamic imports), leave the `` marker and an empty table. + +**Component tree** — walk `src/App.tsx` → page imports → component imports to depth 3. Indented bullet list. Annotate nodes: +- `(data-fetching)` if they use `useQuery`, `supabase.from()`, or `callEdgeFunction` +- `(stateful)` if they call `useState` with more than trivial flags + +**Data needs (resolved)** — one row per Supabase edge function whose inferred category is `database`/`auth`/`object_storage`/`realtime`, plus the combined migrations row. + +| category | vendor | evidence_paths | resolved_target | notes | +| -------- | ------ | -------------- | --------------- | ----- | +| database | supabase | `supabase/migrations/*.sql` | | tables: | +| object_storage | aws-s3-via-lovable-gateway | `supabase/functions/s3-files/index.ts` | | via Lovable connector gateway | + +**External services (resolved)** — one row per Supabase edge function whose inferred category is `http_api`/`email`/`sms`/`payments`/`queue`/`analytics`/`search`/`ai`/`unknown`. + +| category | vendor | evidence_paths | resolved_target | notes | +| -------- | ------ | -------------- | --------------- | ----- | +| http_api | linear-via-lovable-gateway | `supabase/functions/linear-tickets/index.ts` | | via Lovable connector gateway | + +**Backend functions to author** — pre-populate one row per edge function. R2 fills the target path and any implementation hints. + +| backend fn | source | description | +| ---------- | ------ | ----------- | +| `` | `supabase/functions//index.ts` | | + +**Source → target mapping** — pre-populate every row from the structural-facts table in step 3 (every file the skill actually saw, with its disposition). Leave the `class` column BLANK — R2 fills it in Phase M classification. + +| source path | target path | class | transform notes | +| ----------- | ----------- | ----- | --------------- | +| `src/App.tsx` | `/frontend/App.tsx` | | port verbatim; substitute react-router import to R2's react-router | +| `src/pages/Index.tsx` | `/frontend/pages/Index.tsx` | | port; rewrite supabase.from/callEdgeFunction to generated hooks | +| `src/integrations/supabase/client.ts` | DROP | | call sites rewrite to generated backend-fn hooks | +| `supabase/functions/linear-tickets/index.ts` | `/backend/functions/getLinearTickets.ts` (or similar) | | call Retool Linear resource (); preserve action routing | + +Above the table, place `` so R2 knows the rows are real, not placeholders. + +**Styling & theming adapters** — if `tailwind.config.ts` extends the default theme, list the extension keys here (e.g. "custom colors: brand-primary, brand-secondary; custom fontFamily: 'Sora'"). If `src/index.css` contains `@layer` blocks beyond Tailwind's defaults, list those. If neither, write "No non-default theme extensions detected. Use R2's baked Tailwind config as-is." + +**Dependency delta** — list the packages in `package.json` that need migration treatment: + +- ADD: +- SUBSTITUTE: `@supabase/supabase-js` → generated backend-fn hooks (no direct dep) +- DELETE: `lovable-tagger`, `@vitejs/plugin-react-swc` (R2 baked uses its own Vite plugin) +- KEEP: `react`, `react-dom`, `react-router-dom`, all `@radix-ui/*`, `@tanstack/react-query`, `lucide-react`, `tailwind-merge`, `clsx`, `class-variance-authority`, `recharts`, `date-fns`, `react-hook-form`, `zod`, etc. + +**Cut list** — populate from step 5a's drop list. Include both canonical drops (lockfiles, `.env`, `__MACOSX/`) and Lovable-specific drops (`lovable-tagger`-loading `vite.config.ts`, `components.json`, `src/components/ui/`, etc.). One bullet per dropped path with a one-line reason. + +**Open questions / known gaps** — always include: + +- "Migrations are NOT auto-applied. Run `supabase/migrations/*.sql` against the chosen Postgres resource manually after import." +- "Resource matching is currently name + type only; host metadata isn't yet surfaced by `retool_list_resources`." +- For every `USE_MOCK_DATA` resolution: " is mocked during import; wire to a real resource later." +- If Supabase Auth was detected and resolved to MAP_TO_RETOOL_SESSION: "R2 will attempt a best-effort substitution of `useAuth()` / `supabase.auth.*` calls with `useCurrentUser()`. Some code paths may require manual review." +- If any RLS policies were detected in the migrations: "RLS policies in the original schema are NOT translated. R2 will apply at the application layer if you specify per-row permissions; otherwise the Retool resource's access controls apply." +- If any edge function's category was `unknown`: " couldn't be classified from the gateway URL or imports. R2 will need to determine the right backend-function shape." + +**Phased build order** — leave the `` marker. R2 derives this in Phase M. + +## 6. Handoff + +Call `retool_submit_prepared_import` with: + +``` +{ + files: , + importPlan: , + targetAppId: +} +``` + +Stream progress notifications as they arrive. When the tool returns, surface the editor URL: + +``` +Done. Your Retool app is at: +``` + +If the tool call fails, surface the error verbatim and stop. Do NOT retry silently. + +## Hard rules / safety + +- Never read `.env` or `.env.local`. Only `.env.example` is safe. +- Never auto-apply `supabase/migrations/*.sql` against any database — always surface the SQL and tell the user to apply manually. +- Never auto-resolve a Retool resource pick without HITL, even when there's exactly one candidate of the matching type. +- TanStack Start Lovable projects are out of scope. Refuse with the message in [TanStack guard](#tanstack-guard). Do NOT attempt a best-effort import. +- If a Supabase edge function's gateway URL doesn't match the known mapping table, classify the inferred category as `unknown` and surface in open questions — do NOT force-fit it into a category it doesn't belong to. +- Never write outside the user's repo. The skill's only outputs are the in-terminal HITL prompts and the `retool_submit_prepared_import` MCP tool call. + +## Summary for the user + +This skill imports a legacy-Vite Lovable + Supabase project into Retool as an R^2 app. It skips the generic vendor-agnostic discovery scan because Lovable's structure is well-known: it pre-fills the import plan from structural facts, asks one HITL prompt per Supabase edge function (mapping each to a Retool resource) plus one combined prompt per migration directory, packages your source tree with secrets and vendor-specific configs stripped, and hands the prepared plan to Retool's R^2 sandbox agent. You'll get an editor URL when R^2 finishes generating the app. diff --git a/plugins/retool-import/skills/retool-import/SKILL.md b/plugins/retool-import/skills/retool-import/SKILL.md index 7ac9f04..dd7a8b5 100644 --- a/plugins/retool-import/skills/retool-import/SKILL.md +++ b/plugins/retool-import/skills/retool-import/SKILL.md @@ -9,15 +9,16 @@ This skill prepares a user's app for being imported into Retool via MCP. The ski ## State machine overview -The skill runs six phases sequentially. Each phase has a fixed input, a fixed output, and a fixed exit condition. Do NOT skip phases. Do NOT pause for user input outside of Phase 4 (HITL). +The skill runs these phases sequentially. Each phase has a fixed input, a fixed output, and a fixed exit condition. Do NOT skip phases — except that Phase 0 may delegate to a sibling skill, in which case this skill stops entirely and the sibling owns the rest of the flow. Do NOT pause for user input outside of Phase 4 (HITL). 1. Prerequisites check — confirm we are in a React repo and that the required MCP tools are available. -2. Phase 1 — Recon. Read a tight set of files and emit a structured summary of the workspace shape. -3. Phase 2 — Discovery scan. Fan out vendor-agnostic discovery subagents against the directory tree. -4. Phase 3 — Resource matching. For each discovered service, call `retool_list_resources` for compatible types and rank candidates. -5. Phase 4 — HITL. One prompt per distinct service. User picks a resource by number or `USE_MOCK_DATA`. Summarize the resolutions back for final confirm. -6. Phase 5 — Produce artifacts. Walk the repo with the zip filter to build a cleaned source tree, and fill in `IMPORT_PLAN.template.md`. -7. Phase 6 — Handoff. Call `retool_submit_prepared_import` with the cleaned tree and partial plan. Stream progress. Surface the editor URL. +2. Phase 0 — Source-tool detection. Look for known source-tool signals (e.g. `lovable-tagger`, `.lovable/`). On a positive match, delegate to the matching sibling skill via the Skill tool and STOP. On no match, proceed to Phase 1. +3. Phase 1 — Recon. Read a tight set of files and emit a structured summary of the workspace shape. +4. Phase 2 — Discovery scan. Fan out vendor-agnostic discovery subagents against the directory tree. +5. Phase 3 — Resource matching. For each discovered service, call `retool_list_resources` for compatible types and rank candidates. +6. Phase 4 — HITL. One prompt per distinct service. User picks a resource by number or `USE_MOCK_DATA`. Summarize the resolutions back for final confirm. +7. Phase 5 — Produce artifacts. Walk the repo with the zip filter to build a cleaned source tree, and fill in `IMPORT_PLAN.template.md`. +8. Phase 6 — Handoff. Call `retool_submit_prepared_import` with the cleaned tree and partial plan. Stream progress. Surface the editor URL. ## Prerequisites check @@ -26,7 +27,39 @@ Before Phase 1, verify two things and stop with a clear error if either fails: 1. **React repo.** Read `package.json` at the repo root. If absent, look for a single clearly-identifiable client subdirectory (`packages//package.json` or `apps//package.json`) and use that as the client root. In either case, the `dependencies` (or `devDependencies`) must include one of: `react`, `react-dom`, `next`, `vite`, `gatsby`, `expo`. If none is present, stop and tell the user this skill targets React apps. 2. **Required MCP tools.** The skill needs `retool_list_resources` (existing) and `retool_submit_prepared_import` (new, gated by the `mcpServerRetoolImportEnabled` flag). If `retool_submit_prepared_import` is not visible as an MCP tool, stop and tell the user: "The retool-import skill requires `retool_submit_prepared_import`, which is gated by the `mcpServerRetoolImportEnabled` flag. Ask your Retool admin to enable that flag for your org." -If both checks pass, proceed to Phase 1. +If both checks pass, proceed to Phase 0. + +## Phase 0 — Source-tool detection + +Before the vendor-agnostic discovery scan runs, do a quick structural check for known source-tool conventions. If the project matches one of the supported per-tool specializations, delegate to the matching sibling skill via the Skill tool and STOP — the sibling owns the rest of the flow. + +This is the ONLY place in this skill where vendor-specific knowledge is encoded. Detection looks at *signal files* (a known package name in `package.json`, a known directory) — it does NOT classify code behavior. Phases 1–4 below remain strictly vendor-agnostic. + +### Detection signals + +Read the repo root `package.json` and the top-level directory listing exactly once. Check signals in this order — first match wins: + +| Signal (any of) | Source tool | Sibling skill | +| --------------- | ----------- | ------------- | +| `lovable-tagger` in `devDependencies` OR `.lovable/` directory exists at repo root | Lovable (legacy Vite) | `retool-import:retool-import-lovable` | + +(Future entries — v0, Replit, Bolt — land here as their specializations ship.) + +### Delegation + +On a positive match: + +1. Tell the user briefly: "Detected this is a `` project. Switching to the `` specialization for a more accurate import." +2. Invoke the matching sibling skill via the Skill tool. The sibling will run its own validation and proceed. +3. STOP. Do NOT continue with Phase 1+ in this skill. + +On no match, proceed to Phase 1 with the generic vendor-agnostic flow. + +### Why detection is structural + +The generic discovery in Phases 1–4 intentionally avoids vendor-specific code paths so it works on any React app — Supabase, Firebase, Prisma, hand-rolled REST, etc. Phase 0 is the one exception, and it stays narrow on purpose: it only looks at signal files whose presence is a near-deterministic fingerprint of the source tool (e.g. `lovable-tagger` is only emitted by Lovable's Vite scaffold). This means Phase 0 cannot mistakenly route a vendor-agnostic React app to a per-tool skill. + +If you find yourself wanting to add a Phase 0 signal that requires reading code behavior to disambiguate, push the rule into the matching sibling skill's own validation instead — keep Phase 0 here as a fast signal-file scan only. ## Phase 1 — Recon @@ -256,7 +289,7 @@ If the tool call fails, surface the error verbatim and stop. Do NOT retry silent - Never read `.env` or `.env.local`. Only `.env.example` is safe. - If discovery finds a service the user did not acknowledge in Phase 4, do NOT silently skip — surface it as an open question in the plan. - If `retool_submit_prepared_import` is not available as an MCP tool, stop at Phase 5 and tell the user to enable `mcpServerRetoolImportEnabled` for their org. -- Discovery is LLM-driven against the closed category taxonomy. Vendor is a free-text string. Do NOT add vendor-specific code paths — the same skill must work on Supabase, Firebase, Prisma, hand-rolled REST, etc. +- Phase 2 (discovery) is LLM-driven against the closed category taxonomy. Vendor is a free-text string. Do NOT add vendor-specific code paths in Phase 2 — the same discovery pass must work on Supabase, Firebase, Prisma, hand-rolled REST, etc. Phase 0 is the only place vendor-specific knowledge is encoded, and it operates on signal files alone (never on code behavior). ## Summary for the user From 6b5b5dc412193f30c9a3e42b5d4b724eb4d4fd21 Mon Sep 17 00:00:00 2001 From: Rohan Suresh Date: Wed, 27 May 2026 18:29:48 -0400 Subject: [PATCH 2/3] Address review feedback Scrub R^2 / R2 references throughout the lovable SKILL.md in favor of 'Retool React app' (in the public-facing description and summary), 'Retool's React app sandbox agent' (for the downstream agent), and bare 'Retool' (everywhere R2 referred to the downstream system that fills in / owns / executes plan steps). --- .../retool-import/.claude-plugin/plugin.json | 2 +- .../skills/retool-import-lovable/SKILL.md | 64 +++++++++---------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/plugins/retool-import/.claude-plugin/plugin.json b/plugins/retool-import/.claude-plugin/plugin.json index a58188b..b577ec3 100644 --- a/plugins/retool-import/.claude-plugin/plugin.json +++ b/plugins/retool-import/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "retool-import", - "version": "0.1.0", + "version": "0.2.0", "description": "Import an existing React app into Retool as a Retool React app. Discovers external services in your repo, matches them against your Retool resources, and hands a prepared import plan to Retool's React app sandbox agent.", "author": { "name": "Retool", "email": "support@retool.com" }, "homepage": "https://retool.com", diff --git a/plugins/retool-import/skills/retool-import-lovable/SKILL.md b/plugins/retool-import/skills/retool-import-lovable/SKILL.md index 3afd8b3..02ef59c 100644 --- a/plugins/retool-import/skills/retool-import-lovable/SKILL.md +++ b/plugins/retool-import/skills/retool-import-lovable/SKILL.md @@ -1,6 +1,6 @@ --- name: retool-import-lovable -description: Use this skill when the user wants to import a Lovable-generated React app (legacy Vite + Supabase) into Retool as an R^2 app. Detected by `lovable-tagger` in package.json or a `.lovable/` directory at the repo root. The skill skips vendor-agnostic discovery because Lovable's structure (Vite + react-router-dom + Supabase edge functions calling Lovable's connector gateway) is known up front; it pre-fills the import plan from structural facts, asks targeted HITL only for the choices that genuinely need a human (which Retool resource backs each Supabase edge function and migration), and hands a prepared import plan to Retool's R^2 sandbox agent via the `retool_submit_prepared_import` MCP tool. +description: Use this skill when the user wants to import a Lovable-generated React app (legacy Vite + Supabase) into Retool as a Retool React app. Detected by `lovable-tagger` in package.json or a `.lovable/` directory at the repo root. The skill skips vendor-agnostic discovery because Lovable's structure (Vite + react-router-dom + Supabase edge functions calling Lovable's connector gateway) is known up front; it pre-fills the import plan from structural facts, asks targeted HITL only for the choices that genuinely need a human (which Retool resource backs each Supabase edge function and migration), and hands a prepared import plan to Retool's React app sandbox agent via the `retool_submit_prepared_import` MCP tool. --- # retool-import-lovable @@ -82,32 +82,32 @@ The following file-role mapping is true for every legacy-Vite Lovable project. T | Source path | Role | Disposition | | ----------- | ---- | ----------- | -| `src/main.tsx` | `createRoot` bootstrap | DROP — R2's baked `/frontend/index.tsx` owns this | +| `src/main.tsx` | `createRoot` bootstrap | DROP — Retool's baked `/frontend/index.tsx` owns this | | `src/App.tsx` | `` table | PORT to `/frontend/App.tsx` | | `src/pages/*.tsx` | route page components | PORT to `/frontend/pages/` | | `src/components/.tsx` | feature components | PORT to `/frontend/components/` | -| `src/components/ui/*.tsx` | shadcn primitives | DROP — R2 has these baked at `/frontend/lib/shadcn/` | -| `src/hooks/use-toast.ts`, `src/hooks/use-mobile.tsx` | shadcn hook duplicates | DROP — R2 baked | +| `src/components/ui/*.tsx` | shadcn primitives | DROP — Retool has these baked at `/frontend/lib/shadcn/` | +| `src/hooks/use-toast.ts`, `src/hooks/use-mobile.tsx` | shadcn hook duplicates | DROP — Retool baked | | `src/hooks/.{ts,tsx}` | user hooks | PORT to `/frontend/hooks/` | -| `src/lib/utils.ts` | `cn()` helper | DROP — R2 baked has it | +| `src/lib/utils.ts` | `cn()` helper | DROP — Retool baked has it | | `src/lib/edge.ts` | `callEdgeFunction` wrapper | DROP — call sites rewrite to generated backend-fn hooks | | `src/integrations/supabase/client.ts` | Supabase client | DROP — call sites rewrite to generated backend-fn hooks | | `src/integrations/supabase/types.ts` | auto-generated DB types | DROP from the import; surface schema in HITL instead | -| `src/index.css` | Tailwind directives + global CSS | MERGE custom rules into R2's baked Tailwind; surface non-default `@layer` blocks in Styling adapters | +| `src/index.css` | Tailwind directives + global CSS | MERGE custom rules into Retool's baked Tailwind; surface non-default `@layer` blocks in Styling adapters | | `src/App.css` | additional CSS | PORT to `/frontend/App.css` only if non-empty and not just Vite defaults | -| `src/vite-env.d.ts` | Vite TS shim | DROP — R2 baked | -| `supabase/functions//index.ts` | Deno edge function | REWRITE as R2 backend function — one HITL prompt per function (see step 4.1) | +| `src/vite-env.d.ts` | Vite TS shim | DROP — Retool baked | +| `supabase/functions//index.ts` | Deno edge function | REWRITE as Retool backend function — one HITL prompt per function (see step 4.1) | | `supabase/migrations/*.sql` | Postgres schema migrations | Surface tables in HITL; user picks Retool Postgres resource (see step 4.2). Do NOT auto-apply. | | `supabase/config.toml` | Supabase project ID | DROP | | `public/*` | static assets (favicon, robots.txt, etc.) | PORT to `/frontend/public/` | -| `vite.config.ts` | Vite config (loads `lovable-tagger`) | DROP — R2 owns its baked Vite config | -| `tsconfig.json`, `tsconfig.app.json`, `tsconfig.node.json` | TS configs | DROP — R2 baked | +| `vite.config.ts` | Vite config (loads `lovable-tagger`) | DROP — Retool owns its baked Vite config | +| `tsconfig.json`, `tsconfig.app.json`, `tsconfig.node.json` | TS configs | DROP — Retool baked | | `tailwind.config.ts` / `tailwind.config.js` | Tailwind theme | DROP the file; surface non-default theme extensions in Styling adapters | -| `postcss.config.{js,cjs,mjs}` | PostCSS config | DROP — R2 baked | -| `eslint.config.{js,cjs}` | ESLint config | DROP — R2 baked | -| `components.json` | shadcn registry config | DROP — R2 owns its shadcn registry | -| `index.html` | Vite HTML entry | DROP — R2 baked | -| `playwright.config.ts`, `playwright-fixture.ts`, `vitest.config.ts` | testing scaffold | DROP — R2 doesn't execute these | +| `postcss.config.{js,cjs,mjs}` | PostCSS config | DROP — Retool baked | +| `eslint.config.{js,cjs}` | ESLint config | DROP — Retool baked | +| `components.json` | shadcn registry config | DROP — Retool owns its shadcn registry | +| `index.html` | Vite HTML entry | DROP — Retool baked | +| `playwright.config.ts`, `playwright-fixture.ts`, `vitest.config.ts` | testing scaffold | DROP — Retool doesn't execute these | | `.lovable/sync.config.json` | Lovable GitHub sync metadata | DROP | | `.env`, `.env.local` | secrets | DROP (already filtered by shared zip filter) | | `.env.example` | env template | KEEP (shared zip filter already preserves this) | @@ -146,7 +146,7 @@ For each `supabase/functions//index.ts` (skip the `_shared/` subdirectory Edge function: supabase/functions// Calls: via Lovable connector gateway (or: "direct SDK usage" if no gateway URL) - Will become R2 backend function: + Will become Retool backend function: Compatible Retool resources of type []: 1) (, environments: ...) @@ -187,7 +187,7 @@ If `supabase/migrations/` contains any `*.sql` files: IMPORTANT: this skill does NOT auto-apply your migrations. After import, you'll need to apply the SQL in supabase/migrations/ against your chosen - Postgres resource manually (or via R2's follow-up flow). + Postgres resource manually (or via Retool's follow-up flow). ``` 6. Record the answer. @@ -201,11 +201,11 @@ If any are found, present: ``` Supabase Auth detected. Used in: . -R2 does not currently auto-translate Supabase Auth to Retool sessions. +Retool does not currently auto-translate Supabase Auth to Retool sessions. Pick a strategy: 1) USE_MOCK_DATA — mock the current user during import; wire later 2) MAP_TO_RETOOL_SESSION — replace useAuth() / supabase.auth calls - with R2's useCurrentUser() hook (best-effort substitution; some + with Retool's useCurrentUser() hook (best-effort substitution; some code paths may need manual review) 3) Type a custom resolution strategy describing what you want ``` @@ -272,7 +272,7 @@ Start from `../../references/IMPORT_PLAN.template.md`. Fill in: | ----- | --------- | ------- | ------------- | | `/` | `src/pages/Index.tsx` | | Y/N | -`auth required` is `Y` if the page imports anything from `@supabase/supabase-js` auth helpers, else `N`. If `src/App.tsx`'s route table can't be parsed cleanly (unusual route shape, dynamic imports), leave the `` marker and an empty table. +`auth required` is `Y` if the page imports anything from `@supabase/supabase-js` auth helpers, else `N`. If `src/App.tsx`'s route table can't be parsed cleanly (unusual route shape, dynamic imports), leave the `` marker and an empty table. **Component tree** — walk `src/App.tsx` → page imports → component imports to depth 3. Indented bullet list. Annotate nodes: - `(data-fetching)` if they use `useQuery`, `supabase.from()`, or `callEdgeFunction` @@ -291,30 +291,30 @@ Start from `../../references/IMPORT_PLAN.template.md`. Fill in: | -------- | ------ | -------------- | --------------- | ----- | | http_api | linear-via-lovable-gateway | `supabase/functions/linear-tickets/index.ts` | | via Lovable connector gateway | -**Backend functions to author** — pre-populate one row per edge function. R2 fills the target path and any implementation hints. +**Backend functions to author** — pre-populate one row per edge function. Retool fills the target path and any implementation hints. | backend fn | source | description | | ---------- | ------ | ----------- | | `` | `supabase/functions//index.ts` | | -**Source → target mapping** — pre-populate every row from the structural-facts table in step 3 (every file the skill actually saw, with its disposition). Leave the `class` column BLANK — R2 fills it in Phase M classification. +**Source → target mapping** — pre-populate every row from the structural-facts table in step 3 (every file the skill actually saw, with its disposition). Leave the `class` column BLANK — Retool fills it in Phase M classification. | source path | target path | class | transform notes | | ----------- | ----------- | ----- | --------------- | -| `src/App.tsx` | `/frontend/App.tsx` | | port verbatim; substitute react-router import to R2's react-router | +| `src/App.tsx` | `/frontend/App.tsx` | | port verbatim; substitute react-router import to Retool's react-router | | `src/pages/Index.tsx` | `/frontend/pages/Index.tsx` | | port; rewrite supabase.from/callEdgeFunction to generated hooks | | `src/integrations/supabase/client.ts` | DROP | | call sites rewrite to generated backend-fn hooks | | `supabase/functions/linear-tickets/index.ts` | `/backend/functions/getLinearTickets.ts` (or similar) | | call Retool Linear resource (); preserve action routing | -Above the table, place `` so R2 knows the rows are real, not placeholders. +Above the table, place `` so Retool knows the rows are real, not placeholders. -**Styling & theming adapters** — if `tailwind.config.ts` extends the default theme, list the extension keys here (e.g. "custom colors: brand-primary, brand-secondary; custom fontFamily: 'Sora'"). If `src/index.css` contains `@layer` blocks beyond Tailwind's defaults, list those. If neither, write "No non-default theme extensions detected. Use R2's baked Tailwind config as-is." +**Styling & theming adapters** — if `tailwind.config.ts` extends the default theme, list the extension keys here (e.g. "custom colors: brand-primary, brand-secondary; custom fontFamily: 'Sora'"). If `src/index.css` contains `@layer` blocks beyond Tailwind's defaults, list those. If neither, write "No non-default theme extensions detected. Use Retool's baked Tailwind config as-is." **Dependency delta** — list the packages in `package.json` that need migration treatment: -- ADD: +- ADD: - SUBSTITUTE: `@supabase/supabase-js` → generated backend-fn hooks (no direct dep) -- DELETE: `lovable-tagger`, `@vitejs/plugin-react-swc` (R2 baked uses its own Vite plugin) +- DELETE: `lovable-tagger`, `@vitejs/plugin-react-swc` (Retool baked uses its own Vite plugin) - KEEP: `react`, `react-dom`, `react-router-dom`, all `@radix-ui/*`, `@tanstack/react-query`, `lucide-react`, `tailwind-merge`, `clsx`, `class-variance-authority`, `recharts`, `date-fns`, `react-hook-form`, `zod`, etc. **Cut list** — populate from step 5a's drop list. Include both canonical drops (lockfiles, `.env`, `__MACOSX/`) and Lovable-specific drops (`lovable-tagger`-loading `vite.config.ts`, `components.json`, `src/components/ui/`, etc.). One bullet per dropped path with a one-line reason. @@ -324,11 +324,11 @@ Above the table, place `` marker. R2 derives this in Phase M. +**Phased build order** — leave the `` marker. Retool derives this in Phase M. ## 6. Handoff @@ -361,4 +361,4 @@ If the tool call fails, surface the error verbatim and stop. Do NOT retry silent ## Summary for the user -This skill imports a legacy-Vite Lovable + Supabase project into Retool as an R^2 app. It skips the generic vendor-agnostic discovery scan because Lovable's structure is well-known: it pre-fills the import plan from structural facts, asks one HITL prompt per Supabase edge function (mapping each to a Retool resource) plus one combined prompt per migration directory, packages your source tree with secrets and vendor-specific configs stripped, and hands the prepared plan to Retool's R^2 sandbox agent. You'll get an editor URL when R^2 finishes generating the app. +This skill imports a legacy-Vite Lovable + Supabase project into Retool as a Retool React app. It skips the generic vendor-agnostic discovery scan because Lovable's structure is well-known: it pre-fills the import plan from structural facts, asks one HITL prompt per Supabase edge function (mapping each to a Retool resource) plus one combined prompt per migration directory, packages your source tree with secrets and vendor-specific configs stripped, and hands the prepared plan to Retool's React app sandbox agent. You'll get an editor URL when Retool finishes generating the app. From 873ca80d7cf0f2e2fef19a54a111be34692aae95 Mon Sep 17 00:00:00 2001 From: Rohan Suresh Date: Mon, 1 Jun 2026 11:05:25 -0700 Subject: [PATCH 3/3] Address review feedback: clarify legacy-Vite scope, add unsupported-shape fallback - Define legacy-Vite vs TanStack Start shapes at first use - Reframe Scope as the Lovable skill (recipe covers Vite; TanStack falls back) - Replace TanStack hard-refuse with an Unsupported-shape fallback that offers a no-prep import via retool_submit_prepared_import - Make the generic skill's future-specializations note vendor-neutral --- .../skills/retool-import-lovable/SKILL.md | 41 +++++++++++-------- .../skills/retool-import/SKILL.md | 2 +- 2 files changed, 24 insertions(+), 19 deletions(-) diff --git a/plugins/retool-import/skills/retool-import-lovable/SKILL.md b/plugins/retool-import/skills/retool-import-lovable/SKILL.md index 02ef59c..d6a9d57 100644 --- a/plugins/retool-import/skills/retool-import-lovable/SKILL.md +++ b/plugins/retool-import/skills/retool-import-lovable/SKILL.md @@ -9,7 +9,9 @@ Lovable-specialized variant of the [`retool-import`](../retool-import/SKILL.md) ## Why this exists -The generic `retool-import` skill is vendor-agnostic by design: it runs a closed-taxonomy discovery scan against an arbitrary React repo. That works for any source tool, but it's wasted work for projects with predictable structure. A legacy-Vite Lovable project ALWAYS has: +The generic `retool-import` skill is vendor-agnostic by design: it runs a closed-taxonomy discovery scan against an arbitrary React repo. That works for any source tool, but it's wasted work for projects with predictable structure — and Lovable's exports are highly predictable. + +Lovable has shipped two project shapes over time. **Legacy Vite** — the original shape, and the one this skill supports — is a client-side React SPA: Vite bundler, `react-router-dom` routing, Supabase backend. The newer shape (TanStack Start, from ~April 2026) is an SSR framework with file-based routing, different enough that it needs its own recipe (see [Scope](#scope)). A legacy-Vite Lovable project ALWAYS has: - Vite + React + `react-router-dom` for the frontend (entry at `src/main.tsx` → `src/App.tsx`) - Tailwind + shadcn primitives under `src/components/ui/` @@ -21,14 +23,16 @@ Because the shape is known, this skill pre-fills the IMPORT_PLAN.md from structu ## Scope -This skill handles **legacy Vite Lovable projects** only. Lovable began emitting TanStack Start projects (with `@tanstack/react-start`, `src/app/__root.tsx`, file-based routing, SSR) around April 2026. Those projects have a different entry shape and routing model and are NOT supported here. See [TanStack guard](#tanstack-guard) below for the refuse behavior. +This is the skill for **Lovable** projects. The Lovable signals (`lovable-tagger` / `.lovable/`) fire for any Lovable export, but the import recipe currently covers the **legacy Vite** shape only — the client-side SPA described above. + +Lovable began emitting **TanStack Start** projects (with `@tanstack/react-start`, `src/app/__root.tsx`, file-based routing, SSR) around April 2026. Those have a different entry shape and routing model, so this skill's structural pre-fill doesn't apply. When the skill detects one it doesn't dead-end the user — it explains the gap and offers a no-prep fallback import (see [TanStack guard](#tanstack-guard) and [Unsupported-shape fallback](#unsupported-shape-fallback)). ## State machine overview The skill runs these steps sequentially. Each has a fixed input, a fixed output, and a fixed exit condition. 1. Prerequisites check — confirm React repo + MCP tools. -2. Lovable signal validation — confirm Lovable signals are present; refuse TanStack projects. +2. Lovable signal validation — confirm Lovable signals are present; offer the no-prep fallback for TanStack / non-standard shapes. 3. Pre-fill — populate the structural facts table from the known Lovable layout (no discovery scan). 4. Targeted HITL — one prompt per Supabase edge function, one combined prompt per migration directory, one prompt for Supabase Auth if used. 5. Produce artifacts — cleaned source tree (shared filter + Lovable-specific drops) plus pre-populated IMPORT_PLAN.md. @@ -57,24 +61,25 @@ If none of these are present, stop and tell the user: "No Lovable signals detect ### TanStack guard -If the repo root `package.json` contains `@tanstack/react-start` (in either `dependencies` or `devDependencies`), OR `src/app/__root.tsx` exists, stop with this message: +If the repo root `package.json` contains `@tanstack/react-start` (in either `dependencies` or `devDependencies`), OR `src/app/__root.tsx` exists, this is a Lovable TanStack Start app (post-April 2026 format). The skill's structural pre-fill assumes the legacy-Vite layout and would mis-map this project's files, so do NOT run steps 3–4 on it. Instead, follow the [Unsupported-shape fallback](#unsupported-shape-fallback). -``` -This project appears to be a Lovable TanStack Start app (post-April 2026 -format). This skill currently supports legacy Vite Lovable projects only — -TanStack Start has a different entry shape, file-based routing, and SSR -that need their own transformation recipes. - -For now, please run the generic `retool-import` skill, which uses -vendor-agnostic discovery and will still produce a useful import plan -(it just won't pre-fill from Lovable structural knowledge). -``` +### React entry exists -Do NOT attempt a best-effort import on TanStack projects. +Confirm `src/main.tsx` and `src/App.tsx` both exist. If either is missing, this isn't a standard legacy-Vite Lovable scaffold — follow the [Unsupported-shape fallback](#unsupported-shape-fallback). -### React entry exists +### Unsupported-shape fallback + +When a project carries Lovable signals but isn't a shape this skill can pre-transform (TanStack Start, or a non-standard scaffold), don't dead-end the user. Tell them this skill doesn't support the app type, then offer: + +``` +This skill doesn't support this Lovable app type, so I can't pre-fill the +import plan. Want me to import it anyway, without skill preparation? I'll +hand the source tree straight to Retool's React app import and let the +Retool agent attempt the transformation itself — no structural pre-fill, +no guided resource mapping. Reply "import anyway" to try, or stop here. +``` -Confirm `src/main.tsx` and `src/App.tsx` both exist. If either is missing, this isn't a standard Lovable scaffold — stop and point the user at the generic skill. +If the user replies "import anyway": skip steps 3–4. Produce the cleaned source tree using the SHARED zip filter only (step 5a, *without* the Lovable-specific drops — those assume the legacy-Vite layout), then call `retool_submit_prepared_import` (step 6) with that tree and a minimal IMPORT_PLAN.md whose Overview states the import is unprepared and the Retool agent owns all transformation. Otherwise, stop. ## 3. Pre-fill from structural facts @@ -355,7 +360,7 @@ If the tool call fails, surface the error verbatim and stop. Do NOT retry silent - Never read `.env` or `.env.local`. Only `.env.example` is safe. - Never auto-apply `supabase/migrations/*.sql` against any database — always surface the SQL and tell the user to apply manually. - Never auto-resolve a Retool resource pick without HITL, even when there's exactly one candidate of the matching type. -- TanStack Start Lovable projects are out of scope. Refuse with the message in [TanStack guard](#tanstack-guard). Do NOT attempt a best-effort import. +- TanStack Start Lovable projects are out of scope for the pre-filled recipe. Do NOT run the structural pre-fill (steps 3–4) on them. Offer the [Unsupported-shape fallback](#unsupported-shape-fallback) instead of dead-ending the user. - If a Supabase edge function's gateway URL doesn't match the known mapping table, classify the inferred category as `unknown` and surface in open questions — do NOT force-fit it into a category it doesn't belong to. - Never write outside the user's repo. The skill's only outputs are the in-terminal HITL prompts and the `retool_submit_prepared_import` MCP tool call. diff --git a/plugins/retool-import/skills/retool-import/SKILL.md b/plugins/retool-import/skills/retool-import/SKILL.md index dd7a8b5..e5f4e31 100644 --- a/plugins/retool-import/skills/retool-import/SKILL.md +++ b/plugins/retool-import/skills/retool-import/SKILL.md @@ -43,7 +43,7 @@ Read the repo root `package.json` and the top-level directory listing exactly on | --------------- | ----------- | ------------- | | `lovable-tagger` in `devDependencies` OR `.lovable/` directory exists at repo root | Lovable (legacy Vite) | `retool-import:retool-import-lovable` | -(Future entries — v0, Replit, Bolt — land here as their specializations ship.) +(Future per-tool specializations land here as they ship.) ### Delegation