launchframe 0.4.0 → 0.4.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/.amazonq/cli-agents/clone-website.json +9 -0
- package/.amazonq/cli-agents/launchframe.json +9 -0
- package/.amazonq/rules/project.md +158 -0
- package/.augment/commands/clone-website.md +488 -0
- package/.augment/commands/launchframe.md +46 -0
- package/.claude/skills/clone-website/SKILL.md +14 -0
- package/.claude/skills/launchframe/SKILL.md +45 -0
- package/.clinerules +78 -67
- package/.codex/skills/clone-website/SKILL.md +487 -473
- package/.codex/skills/launchframe/SKILL.md +45 -0
- package/.continue/commands/clone-website.md +489 -475
- package/.continue/commands/launchframe.md +47 -0
- package/.continue/rules/project.md +82 -71
- package/.cursor/commands/clone-website.md +484 -470
- package/.cursor/commands/launchframe.md +42 -0
- package/.gemini/commands/clone-website.toml +490 -476
- package/.gemini/commands/launchframe.toml +48 -0
- package/.github/copilot-instructions.md +78 -67
- package/.github/skills/clone-website/SKILL.md +487 -473
- package/.github/skills/launchframe/SKILL.md +45 -0
- package/.opencode/commands/clone-website.md +487 -473
- package/.opencode/commands/launchframe.md +45 -0
- package/.windsurf/workflows/clone-website.md +484 -470
- package/.windsurf/workflows/launchframe.md +42 -0
- package/AGENTS.md +3 -2
- package/README.md +15 -3
- package/bin/launchframe.mjs +21 -16
- package/docs/research/INSPECTION_GUIDE.md +10 -0
- package/package.json +4 -2
- package/scripts/sync-skills.mjs +108 -95
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
<!-- AUTO-GENERATED from .claude/skills/launchframe/SKILL.md — do not edit directly.
|
|
2
|
+
Run `node scripts/sync-skills.mjs` to regenerate. -->
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# Launchframe
|
|
6
|
+
|
|
7
|
+
You are helping the user scaffold a **new** project from **the reference URL and SaaS idea from the user (see slash command arguments)**:
|
|
8
|
+
|
|
9
|
+
- A **reference URL** (the website to copy later with `/clone-website`)
|
|
10
|
+
- A **SaaS idea** string (headline / positioning for the generated landing page)
|
|
11
|
+
|
|
12
|
+
## Parse inputs
|
|
13
|
+
|
|
14
|
+
1. Split **the reference URL and SaaS idea from the user (see slash command arguments)** into:
|
|
15
|
+
- **URL** — First `http://` or `https://` URL. Normalize (trim, validate). If invalid or missing, ask once for a correct URL.
|
|
16
|
+
- **SaaS idea** — Everything after the URL, typically in quotes. Strip surrounding quotes. If empty, ask for a short product pitch.
|
|
17
|
+
|
|
18
|
+
2. Optional flags the user might pass (same as the CLI): `--dir` / `-o` for output folder, `--skip-install` to skip `npm install`.
|
|
19
|
+
|
|
20
|
+
## Run the published CLI
|
|
21
|
+
|
|
22
|
+
Execute the scaffold using the **latest** package from npm (exact intent: **`launchframe@latest`**):
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npx launchframe@latest "<url>" "<saas-idea>" [--dir <folder>] [--skip-install]
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- Use shell-appropriate quoting (PowerShell vs bash). Escape embedded quotes in the SaaS idea.
|
|
29
|
+
- **Output path:** The Launchframe CLI must not write **inside** the npm package / template directory itself (that would recurse). If the open workspace is this repository, run `npx` with `--dir` pointing to a **sibling** path (e.g. `..\\my-app` on Windows, `../my-app` on macOS/Linux) or ask the user for a folder **outside** the repo.
|
|
30
|
+
- Prefer letting the CLI run `npm install` unless the user passed `--skip-install`.
|
|
31
|
+
|
|
32
|
+
## After scaffold
|
|
33
|
+
|
|
34
|
+
Tell the user:
|
|
35
|
+
|
|
36
|
+
1. `cd` into the new project directory.
|
|
37
|
+
2. `npm run dev` to preview the SaaS landing shell.
|
|
38
|
+
3. Run **`/clone-website <same-reference-url>`** in that project so the agent can reverse-engineer the reference site into components, while keeping the SaaS idea from `launchframe.context.json` / `src/lib/launchframe-config.ts`.
|
|
39
|
+
|
|
40
|
+
## Fallback (local dev only)
|
|
41
|
+
|
|
42
|
+
If `npx launchframe@latest` is unavailable (offline), from a **checkout of this repo** you may run `node bin/launchframe.mjs "<url>" "<saas-idea>" ...` with the same rules for `--dir` outside the package root.
|
package/AGENTS.md
CHANGED
|
@@ -7,7 +7,7 @@ This version has breaking changes — APIs, conventions, and file structure may
|
|
|
7
7
|
# Website Reverse-Engineer Template
|
|
8
8
|
|
|
9
9
|
## What This Is
|
|
10
|
-
A reusable template for reverse-engineering any website into a clean, modern Next.js codebase using AI coding agents. The Next.js + shadcn/ui + Tailwind v4 base is pre-scaffolded —
|
|
10
|
+
A reusable template for reverse-engineering any website into a clean, modern Next.js codebase using AI coding agents. The Next.js + shadcn/ui + Tailwind v4 base is pre-scaffolded — start a **new** project with **`/launchframe <url> "your saas idea"`** (runs **`npx launchframe@latest`**), or work in the current repo and run **`/clone-website <url1> [<url2> ...]`** to clone into this tree.
|
|
11
11
|
|
|
12
12
|
## Tech Stack
|
|
13
13
|
- **Framework:** Next.js 16 (App Router, React 19, TypeScript strict)
|
|
@@ -35,6 +35,7 @@ A reusable template for reverse-engineering any website into a clean, modern Nex
|
|
|
35
35
|
- **No personal aesthetic changes during emulation phase** — match 1:1 first, customize later
|
|
36
36
|
- **Real content** — use actual text and assets from the target site, not placeholders
|
|
37
37
|
- **Beauty-first** — every pixel matters
|
|
38
|
+
- **DOM crawl priority** — when walking the target page, emphasize **images** (raster, responsive sources, CSS backgrounds), **SVGs** (inline icons, sprites, masks), then **motion** (keyframes, transitions, scroll/time-driven animation, libraries). Scrape and save real assets from the DOM/network first; **create** a stand-in image or vector only when fetch/blocking prevents extraction, and label substitutes clearly in research notes so the clone stays auditable
|
|
38
39
|
|
|
39
40
|
## Project Structure
|
|
40
41
|
```
|
|
@@ -60,6 +61,6 @@ scripts/ # Asset download scripts
|
|
|
60
61
|
## MOST IMPORTANT NOTES
|
|
61
62
|
- When launching Claude Code agent teams, ALWAYS have each teammate work in their own worktree branch and merge everyone's work at the end, resolving any merge conflicts smartly since you are basically serving the orchestrator role and have full context to our goals, work given, work achieved, and desired outcomes.
|
|
62
63
|
- After editing `AGENTS.md`, run `bash scripts/sync-agent-rules.sh` to regenerate platform-specific instruction files.
|
|
63
|
-
- After editing `.claude/skills
|
|
64
|
+
- After editing `.claude/skills/*/SKILL.md` (for example `clone-website` or `launchframe`), run `node scripts/sync-skills.mjs` to regenerate skill and command files for all platforms.
|
|
64
65
|
|
|
65
66
|
@docs/research/INSPECTION_GUIDE.md
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
<a href="https://github.com/JCodesMore/ai-website-cloner-template/blob/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue" alt="MIT License" /></a> <a href="https://github.com/JCodesMore/ai-website-cloner-template/stargazers"><img src="https://img.shields.io/github/stars/JCodesMore/ai-website-cloner-template?style=flat" alt="Stars" /></a> <a href="https://discord.gg/hrTSX5yTpB"><img src="https://img.shields.io/discord/1400896964597383279?label=discord" alt="Discord" /></a>
|
|
4
4
|
|
|
5
|
-
Scaffold a Next.js + shadcn/ui project from **a reference URL you want to copy** plus **your SaaS idea** that drives landing-page positioning.
|
|
5
|
+
Scaffold a Next.js + shadcn/ui project from **a reference URL you want to copy** plus **your SaaS idea** that drives landing-page positioning. Use **`npx launchframe@latest`** or the slash command **`/launchframe <url> "your idea"`** to scaffold, then run **`/clone-website`** so your AI agent reverse-engineers the reference layout while preserving your messaging inputs (`launchframe.context.json`, `docs/research/LAUNCHFRAME.md`, `src/lib/launchframe-config.ts`).
|
|
6
6
|
|
|
7
7
|
**Recommended: [Claude Code](https://docs.anthropic.com/en/docs/claude-code) with Opus 4.7 for best results** — but works with a variety of AI coding agents.
|
|
8
8
|
|
|
@@ -14,7 +14,17 @@ Scaffold a Next.js + shadcn/ui project from **a reference URL you want to copy**
|
|
|
14
14
|
|
|
15
15
|
## Quick Start
|
|
16
16
|
|
|
17
|
-
###
|
|
17
|
+
### AI agents (slash command)
|
|
18
|
+
|
|
19
|
+
In Cursor, Claude Code, Continue, and other synced tools:
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
/launchframe https://example.com "Your SaaS idea in plain language"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The agent runs **`npx launchframe@latest`** with those arguments (see `.cursor/commands/launchframe.md`). Output must be **outside** the template package directory when developing from a clone of this repo — use `--dir ../my-app` or an absolute path.
|
|
26
|
+
|
|
27
|
+
### CLI (same as slash command)
|
|
18
28
|
|
|
19
29
|
From an empty folder (or anywhere you want the project folder created):
|
|
20
30
|
|
|
@@ -22,6 +32,8 @@ From an empty folder (or anywhere you want the project folder created):
|
|
|
22
32
|
npx launchframe@latest https://example.com "Your SaaS idea in plain language"
|
|
23
33
|
```
|
|
24
34
|
|
|
35
|
+
Scaffolding copies the full template at the repository root — including **hidden agent config** (for example `.cursor/`, `.claude/`, `.github/`, `.amazonq/`, `.augment/`, and other dotfiles) so tools see the same rules and commands as this template.
|
|
36
|
+
|
|
25
37
|
Optional flags:
|
|
26
38
|
|
|
27
39
|
- `--dir my-app` / `-o my-app` — output folder name (default: `<hostname>-launchframe`)
|
|
@@ -39,7 +51,7 @@ Open your AI agent and run `/clone-website <same-reference-url>` so it rebuilds
|
|
|
39
51
|
### Git template (advanced)
|
|
40
52
|
|
|
41
53
|
1. Clone this repository and `npm install`
|
|
42
|
-
2. Replace `src/lib/launchframe-config.ts` or run `npx launchframe ...` into a fresh folder
|
|
54
|
+
2. Replace `src/lib/launchframe-config.ts` or run `npx launchframe@latest ...` into a fresh folder
|
|
43
55
|
3. Run `/clone-website <target-url>` from your agent
|
|
44
56
|
|
|
45
57
|
> Using a different agent? Open `AGENTS.md` for project instructions — most agents pick it up automatically.
|
package/bin/launchframe.mjs
CHANGED
|
@@ -12,21 +12,27 @@ import { fileURLToPath } from "node:url";
|
|
|
12
12
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
13
13
|
const PKG_ROOT = resolve(__dirname, "..");
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
".
|
|
24
|
-
".
|
|
25
|
-
"
|
|
26
|
-
"
|
|
15
|
+
/**
|
|
16
|
+
* Never copy these root entries into a scaffolded app (build artifacts, VCS, the CLI itself).
|
|
17
|
+
* All other root files and folders are copied as-is — including every dotfile and dot-directory
|
|
18
|
+
* so AI agents see the same agent rules, skills, and IDE metadata as this template.
|
|
19
|
+
*/
|
|
20
|
+
const SKIP_DIR_NAMES = new Set([
|
|
21
|
+
"bin",
|
|
22
|
+
"node_modules",
|
|
23
|
+
".git",
|
|
24
|
+
".next",
|
|
25
|
+
"dist",
|
|
26
|
+
"out",
|
|
27
|
+
"coverage",
|
|
28
|
+
".turbo",
|
|
27
29
|
]);
|
|
28
30
|
|
|
29
|
-
const SKIP_ROOT_FILES = new Set([
|
|
31
|
+
const SKIP_ROOT_FILES = new Set([
|
|
32
|
+
"package-lock.json",
|
|
33
|
+
".DS_Store",
|
|
34
|
+
"Thumbs.db",
|
|
35
|
+
]);
|
|
30
36
|
|
|
31
37
|
function printHelp() {
|
|
32
38
|
console.log(`
|
|
@@ -46,6 +52,8 @@ Options:
|
|
|
46
52
|
|
|
47
53
|
Note:
|
|
48
54
|
The output folder must not live inside the Launchframe package directory (the folder that contains this CLI).
|
|
55
|
+
Scaffolding copies every root file and folder from the template (including dotfiles such as .cursor, .claude,
|
|
56
|
+
.github, etc.) except build/cache directories, so your AI tools see the same rules and commands as upstream.
|
|
49
57
|
|
|
50
58
|
Example:
|
|
51
59
|
npx launchframe@latest https://stripe.com "AI invoicing for freelancers"
|
|
@@ -133,9 +141,6 @@ function tsStringLiteral(value) {
|
|
|
133
141
|
|
|
134
142
|
function shouldCopyRootEntry(baseName, isDirectory) {
|
|
135
143
|
if (SKIP_DIR_NAMES.has(baseName)) return false;
|
|
136
|
-
if (isDirectory && baseName.startsWith(".")) {
|
|
137
|
-
if (!ALLOW_DOT_DIRS.has(baseName)) return false;
|
|
138
|
-
}
|
|
139
144
|
if (!isDirectory && SKIP_ROOT_FILES.has(baseName)) return false;
|
|
140
145
|
return true;
|
|
141
146
|
}
|
|
@@ -4,6 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
This guide outlines what to capture when inspecting a target website via Chrome MCP or browser DevTools.
|
|
6
6
|
|
|
7
|
+
## Priority: media, SVGs, and motion (do this early)
|
|
8
|
+
|
|
9
|
+
When crawling the DOM and network, **tackle these before fine-tuning copy or spacing**:
|
|
10
|
+
|
|
11
|
+
1. **Raster imagery** — Every `<img>`, `<picture>` / `source`, `srcset` / `sizes`, CDN URLs, lazy-loaded `data-src`, `loading="lazy"` nodes, **CSS `background-image`** on the element and ancestors (including `::before` / `::after`), masks that use `url()`, `<video>` still / poster frames. Prefer **downloading** originals via scripts or MCP; if a URL is blocked or session-gated, **export a screenshot** of the element’s bounding box at a crisp DPR and store it under `public/images/`, and note the substitute in the spec.
|
|
12
|
+
2. **SVGs** — Inline `<svg>`, `<use>` / sprite sheets, **SVG in CSS** (`mask-image`, `background-image`), favicons as SVG, logo marks. Prefer extracting path/viewBox into React components or static files under `public/` — **recreate** from a screenshot/trace only when the markup is obfuscated or blocked.
|
|
13
|
+
3. **Motion & animation** — Inspect Styles for `animation`, `animation-name`, `animation-timeline`, `transition`, `transform`, `@keyframes`; check for libraries (Framer Motion, GSAP, Lottie, Lenis). Capture **durations, easings, delays, fill-modes**, scroll/view triggers, and `prefers-reduced-motion` handling. Motion often defines perceived quality — do not leave it as an afterthought.
|
|
14
|
+
|
|
15
|
+
Then continue with typography, spacing, and component structure as usual.
|
|
16
|
+
|
|
7
17
|
## Phase 1: Visual Audit
|
|
8
18
|
|
|
9
19
|
### Screenshots to Capture
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "launchframe",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Scaffold a Next.js app from a reference URL plus your SaaS idea — AI-ready website cloning",
|
|
6
6
|
"author": "JCodesMore",
|
|
@@ -62,7 +62,9 @@
|
|
|
62
62
|
".gemini",
|
|
63
63
|
".opencode",
|
|
64
64
|
".windsurf",
|
|
65
|
-
".github"
|
|
65
|
+
".github",
|
|
66
|
+
".amazonq",
|
|
67
|
+
".augment"
|
|
66
68
|
],
|
|
67
69
|
"scripts": {
|
|
68
70
|
"dev": "next dev",
|
package/scripts/sync-skills.mjs
CHANGED
|
@@ -1,111 +1,124 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Generates
|
|
5
|
-
* Source of truth:
|
|
4
|
+
* Generates invokable skill/command files for all supported AI coding platforms.
|
|
5
|
+
* Source of truth: `.claude/skills/<skill-id>/SKILL.md` (YAML frontmatter + markdown body).
|
|
6
6
|
*
|
|
7
7
|
* Usage: node scripts/sync-skills.mjs
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
import { readFileSync, writeFileSync, mkdirSync } from
|
|
11
|
-
import { dirname, join } from
|
|
12
|
-
import { fileURLToPath } from
|
|
10
|
+
import { readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
|
|
14
|
+
const ROOT = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
15
|
+
|
|
16
|
+
const SKILLS = [
|
|
17
|
+
{
|
|
18
|
+
id: "clone-website",
|
|
19
|
+
sourceRel: ".claude/skills/clone-website/SKILL.md",
|
|
20
|
+
shortDesc: "Reverse-engineer and clone any website as a pixel-perfect replica",
|
|
21
|
+
plainSubstitution: "the target URL provided by the user",
|
|
22
|
+
augmentArgumentHint: "<url>",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "launchframe",
|
|
26
|
+
sourceRel: ".claude/skills/launchframe/SKILL.md",
|
|
27
|
+
shortDesc:
|
|
28
|
+
"Scaffold a Next.js app with npx launchframe@latest from a reference URL and SaaS idea",
|
|
29
|
+
plainSubstitution:
|
|
30
|
+
"the reference URL and SaaS idea from the user (see slash command arguments)",
|
|
31
|
+
augmentArgumentHint: "<url> \"<saas-idea>\"",
|
|
32
|
+
},
|
|
33
|
+
];
|
|
13
34
|
|
|
14
|
-
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
let raw;
|
|
20
|
-
try {
|
|
21
|
-
raw = readFileSync(SOURCE, 'utf8').replace(/\r\n/g, '\n');
|
|
22
|
-
} catch {
|
|
23
|
-
console.error(`Error: Source skill not found at .claude/skills/clone-website/SKILL.md`);
|
|
24
|
-
process.exit(1);
|
|
35
|
+
function write(relPath, content) {
|
|
36
|
+
const full = join(ROOT, relPath);
|
|
37
|
+
mkdirSync(dirname(full), { recursive: true });
|
|
38
|
+
writeFileSync(full, content, "utf8");
|
|
39
|
+
console.log(` \u2713 ${relPath}`);
|
|
25
40
|
}
|
|
26
41
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
function parseSkill(sourceRel) {
|
|
43
|
+
const full = join(ROOT, sourceRel);
|
|
44
|
+
const raw = readFileSync(full, "utf8").replace(/\r\n/g, "\n");
|
|
45
|
+
const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
46
|
+
if (!match) {
|
|
47
|
+
throw new Error(`Could not parse frontmatter: ${sourceRel}`);
|
|
48
|
+
}
|
|
49
|
+
return { raw, body: match[2] };
|
|
31
50
|
}
|
|
32
51
|
|
|
33
|
-
|
|
34
|
-
const
|
|
52
|
+
function syncSkill(skill) {
|
|
53
|
+
const { id, sourceRel, shortDesc, plainSubstitution, augmentArgumentHint } = skill;
|
|
54
|
+
|
|
55
|
+
let parsed;
|
|
56
|
+
try {
|
|
57
|
+
parsed = parseSkill(sourceRel);
|
|
58
|
+
} catch (e) {
|
|
59
|
+
console.error(e.message || e);
|
|
60
|
+
process.exit(1);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const { raw, body } = parsed;
|
|
64
|
+
const noArgs = (text) => text.replace(/\$ARGUMENTS/g, plainSubstitution);
|
|
65
|
+
const header =
|
|
66
|
+
`<!-- AUTO-GENERATED from ${sourceRel} \u2014 do not edit directly.\n` +
|
|
67
|
+
` Run \`node scripts/sync-skills.mjs\` to regenerate. -->\n\n`;
|
|
68
|
+
|
|
69
|
+
console.log(`\nSyncing ${id}...\n Source: ${sourceRel}\n`);
|
|
70
|
+
|
|
71
|
+
write(`.codex/skills/${id}/SKILL.md`, raw);
|
|
72
|
+
write(`.github/skills/${id}/SKILL.md`, raw);
|
|
73
|
+
|
|
74
|
+
write(`.cursor/commands/${id}.md`, header + noArgs(body));
|
|
75
|
+
|
|
76
|
+
write(`.windsurf/workflows/${id}.md`, header + noArgs(body));
|
|
77
|
+
|
|
78
|
+
const geminiBody = body.replace(/\$ARGUMENTS/g, "{{args}}");
|
|
79
|
+
write(
|
|
80
|
+
`.gemini/commands/${id}.toml`,
|
|
81
|
+
`# AUTO-GENERATED from ${sourceRel}\n` +
|
|
82
|
+
`# Run \`node scripts/sync-skills.mjs\` to regenerate.\n\n` +
|
|
83
|
+
`description = ${JSON.stringify(shortDesc)}\n\n` +
|
|
84
|
+
`[prompt]\ntext = '''\n${geminiBody}\n'''\n`,
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
write(
|
|
88
|
+
`.opencode/commands/${id}.md`,
|
|
89
|
+
`---\ndescription: ${JSON.stringify(shortDesc)}\n---\n${header}${body}`,
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
write(
|
|
93
|
+
`.augment/commands/${id}.md`,
|
|
94
|
+
`---\ndescription: ${JSON.stringify(shortDesc)}\nargument-hint: ${JSON.stringify(augmentArgumentHint)}\n---\n${header}${body}`,
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
write(
|
|
98
|
+
`.continue/commands/${id}.md`,
|
|
99
|
+
`---\nname: ${id}\ndescription: ${JSON.stringify(shortDesc)}\ninvokable: true\n---\n${header}${body}`,
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
write(
|
|
103
|
+
`.amazonq/cli-agents/${id}.json`,
|
|
104
|
+
JSON.stringify(
|
|
105
|
+
{
|
|
106
|
+
name: id,
|
|
107
|
+
description: shortDesc,
|
|
108
|
+
prompt: noArgs(body),
|
|
109
|
+
fileContext: ["AGENTS.md", "docs/research/**"],
|
|
110
|
+
},
|
|
111
|
+
null,
|
|
112
|
+
2,
|
|
113
|
+
) + "\n",
|
|
114
|
+
);
|
|
115
|
+
}
|
|
35
116
|
|
|
36
|
-
|
|
117
|
+
console.log("Syncing skills to all platforms...");
|
|
37
118
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
mkdirSync(dirname(full), { recursive: true });
|
|
41
|
-
writeFileSync(full, content, 'utf8');
|
|
42
|
-
console.log(` \u2713 ${relPath}`);
|
|
119
|
+
for (const skill of SKILLS) {
|
|
120
|
+
syncSkill(skill);
|
|
43
121
|
}
|
|
44
122
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
' Run `node scripts/sync-skills.mjs` to regenerate. -->\n\n';
|
|
48
|
-
|
|
49
|
-
const noArgs = (text) => text.replace(/\$ARGUMENTS/g, 'the target URL provided by the user');
|
|
50
|
-
|
|
51
|
-
// --- Generate ---
|
|
52
|
-
|
|
53
|
-
console.log('Syncing clone-website skill to all platforms...');
|
|
54
|
-
console.log(` Source: .claude/skills/clone-website/SKILL.md\n`);
|
|
55
|
-
|
|
56
|
-
// 1. Codex CLI — same SKILL.md format, same $ARGUMENTS syntax
|
|
57
|
-
write('.codex/skills/clone-website/SKILL.md', raw);
|
|
58
|
-
|
|
59
|
-
// 2. GitHub Copilot — same SKILL.md format
|
|
60
|
-
write('.github/skills/clone-website/SKILL.md', raw);
|
|
61
|
-
|
|
62
|
-
// 3. Cursor — plain markdown, no argument substitution support
|
|
63
|
-
write('.cursor/commands/clone-website.md', HEADER + noArgs(body));
|
|
64
|
-
|
|
65
|
-
// 4. Windsurf — markdown workflow
|
|
66
|
-
write('.windsurf/workflows/clone-website.md', HEADER + noArgs(body));
|
|
67
|
-
|
|
68
|
-
// 5. Gemini CLI — TOML format, {{args}} for arguments
|
|
69
|
-
const geminiBody = body.replace(/\$ARGUMENTS/g, '{{args}}');
|
|
70
|
-
write(
|
|
71
|
-
'.gemini/commands/clone-website.toml',
|
|
72
|
-
`# AUTO-GENERATED from .claude/skills/clone-website/SKILL.md\n` +
|
|
73
|
-
`# Run \`node scripts/sync-skills.mjs\` to regenerate.\n\n` +
|
|
74
|
-
`description = "${shortDesc}"\n\n` +
|
|
75
|
-
`[prompt]\ntext = '''\n${geminiBody}\n'''\n`
|
|
76
|
-
);
|
|
77
|
-
|
|
78
|
-
// 6. OpenCode — markdown + YAML frontmatter, $ARGUMENTS works natively
|
|
79
|
-
write(
|
|
80
|
-
'.opencode/commands/clone-website.md',
|
|
81
|
-
`---\ndescription: "${shortDesc}"\n---\n${HEADER}${body}`
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
// 7. Augment Code — markdown + YAML frontmatter
|
|
85
|
-
write(
|
|
86
|
-
'.augment/commands/clone-website.md',
|
|
87
|
-
`---\ndescription: "${shortDesc}"\nargument-hint: "<url>"\n---\n${HEADER}${body}`
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
// 8. Continue — prompt file with invokable: true
|
|
91
|
-
write(
|
|
92
|
-
'.continue/commands/clone-website.md',
|
|
93
|
-
`---\nname: clone-website\ndescription: "${shortDesc}"\ninvokable: true\n---\n${HEADER}${body}`
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
// 9. Amazon Q — JSON agent definition
|
|
97
|
-
write(
|
|
98
|
-
'.amazonq/cli-agents/clone-website.json',
|
|
99
|
-
JSON.stringify(
|
|
100
|
-
{
|
|
101
|
-
name: 'clone-website',
|
|
102
|
-
description: shortDesc,
|
|
103
|
-
prompt: noArgs(body),
|
|
104
|
-
fileContext: ['AGENTS.md', 'docs/research/**'],
|
|
105
|
-
},
|
|
106
|
-
null,
|
|
107
|
-
2
|
|
108
|
-
) + '\n'
|
|
109
|
-
);
|
|
110
|
-
|
|
111
|
-
console.log('\nDone! 9 platform command files generated from source skill.');
|
|
123
|
+
const totalFiles = SKILLS.length * 9;
|
|
124
|
+
console.log(`\nDone! ${totalFiles} platform files generated (${SKILLS.length} skills \u00d7 9 targets).`);
|