agentic-web-developer 0.0.0-stage → 1.0.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/README.md +127 -2
- package/bin/install.js +546 -0
- package/docs/EXAMPLES.md +67 -0
- package/docs/INSTALL.md +147 -0
- package/package.json +41 -4
package/README.md
CHANGED
|
@@ -1,3 +1,128 @@
|
|
|
1
|
-
#
|
|
1
|
+
# agentic-web-developer
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
An **agentic skill** that turns an AI coding agent into a complete web-development and website-selling system — distilled from Jack Roberts' two videos:
|
|
4
|
+
|
|
5
|
+
1. **"How I build $10,000 AI Websites in 17 mins (Google AI Studio 2.0)"** — design DNA extraction (builder brief, scaffold, tokens), outlier competitor research (top-5 vs bottom-5), the conversion blueprint.
|
|
6
|
+
2. **"How I Build & Sell $8,000 AI Websites (AntiGravity + Stitch)"** — the M.O.N.E.Y framework, lead generation, the config-driven cloning system, outreach emails, deployment and monetization.
|
|
7
|
+
|
|
8
|
+
Plus a **novel-idea / product-launch mode** for websites not covered by the videos (SaaS, products, marketplaces).
|
|
9
|
+
|
|
10
|
+
## What you get
|
|
11
|
+
|
|
12
|
+
- **Stage-gated pipeline** (Intake → Niche → Research → Design → Build → QA → Animation handoff → Deploy → Sell) where the agent **asks for your input at every step** — it never runs ahead on assumptions.
|
|
13
|
+
- **Design-tool agnostic** — Figma, Paper, Google Stitch, Google AI Studio, Framer or code-first. You supply the credentials/MCP for your tool of choice.
|
|
14
|
+
- **Framework agnostic** — Next.js, React, Vue, Svelte, Astro, plain HTML, WordPress, GoHighLevel — you pick.
|
|
15
|
+
- **All animation is delegated** to the [AnimotionJS agentic skill](https://skills.animotion.click/checkout) — this skill never writes animation code itself.
|
|
16
|
+
- 10 reference playbooks + 4 ready-to-fill templates (builder brief, scaffold HTML, `siteconfig.ts`, outlier anatomy).
|
|
17
|
+
|
|
18
|
+
## Install
|
|
19
|
+
|
|
20
|
+
Full guide (per-agent paths, manual install, uninstall): **[docs/INSTALL.md](docs/INSTALL.md)** — worked examples of both modes: **[docs/EXAMPLES.md](docs/EXAMPLES.md)**.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
# auto-detect your agent (opencode → claude → any detected agent)
|
|
24
|
+
npx agentic-web-developer install
|
|
25
|
+
|
|
26
|
+
# or target one of the 15 supported agents
|
|
27
|
+
npx agentic-web-developer install --agent=opencode
|
|
28
|
+
npx agentic-web-developer install --agent=claude
|
|
29
|
+
|
|
30
|
+
# or install for every detected agent at once
|
|
31
|
+
npx agentic-web-developer install --all
|
|
32
|
+
|
|
33
|
+
# see what's installed where
|
|
34
|
+
npx agentic-web-developer detect
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Other flags: `--force` (overwrite), `--dry-run` (print targets only), `--dir=<path>` (custom destination), `--source=<url|path>` / `--token=<key>` (skill source).
|
|
38
|
+
|
|
39
|
+
Then **restart your AI agent** so it loads the skill.
|
|
40
|
+
|
|
41
|
+
> **Where does the skill come from?** Not from npm — the package ships only the installer and docs. The installer fetches the skill from a source you configure (`--source`, `AWD_SOURCE`, or the author's `awd.source` in `package.json`). See [docs/INSTALL.md § Skill source](docs/INSTALL.md#skill-source).
|
|
42
|
+
|
|
43
|
+
### Supported agents
|
|
44
|
+
|
|
45
|
+
`opencode` · `claude` · `copilot` · `cursor` · `windsurf` · `codex` · `cline` · `roo` · `cody` · `codium` · `aider` · `continue` · `augment` · `amazonq` · `jetbrains`
|
|
46
|
+
|
|
47
|
+
The installer writes **each agent's own file format** with the right frontmatter — `SKILL.md` for skill agents, `skill.md` for Windsurf/Codium, `rules/*.mdc` for Cursor, `rules/*.md` for Continue/Augment/Amazon Q, `CONVENTIONS.md` for Aider — and puts the `references/` + `templates/` payload where that agent can read it. Same 15 agents as the AnimotionJS skill.
|
|
48
|
+
|
|
49
|
+
### Manual install (no CLI)
|
|
50
|
+
|
|
51
|
+
See **[docs/INSTALL.md](docs/INSTALL.md#manual-install-no-cli)** — per-agent copy instructions for all 15 agents.
|
|
52
|
+
|
|
53
|
+
## Animations are a separate skill (required to finish a site)
|
|
54
|
+
|
|
55
|
+
Every website built with this skill gets its **animations and interactions from the AnimotionJS agentic skill** — hero reveals, scroll effects, hover states, counters, parallax, text FX. Install it too:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npx animotion-skills install --tier=agentic --agent=<your-agent> --license-key=YOUR_KEY
|
|
59
|
+
# or for all detected agents:
|
|
60
|
+
npx animotion-skills install --tier=agentic --all --license-key=YOUR_KEY
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- License key (Studio plan, $15/month): https://skills.animotion.click/checkout
|
|
64
|
+
- Local source on the author's machine: `C:\Users\creat\Projects\Animotionjs\animotion-skills`
|
|
65
|
+
|
|
66
|
+
Without it, the skill will still design and build — but it will stop at Stage 8 and ask you to install Animotion before any motion work.
|
|
67
|
+
|
|
68
|
+
## Using the skill
|
|
69
|
+
|
|
70
|
+
Just talk to your agent:
|
|
71
|
+
|
|
72
|
+
> "Build me a website that converts for my pool cleaning business"
|
|
73
|
+
> "Launch a product website for my new SaaS idea"
|
|
74
|
+
> "Use the agentic-web-developer skill"
|
|
75
|
+
|
|
76
|
+
The agent classifies the project (Mode A: build-and-sell, Mode B: novel idea), then walks you through every gate.
|
|
77
|
+
|
|
78
|
+
## Project layout
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
agentic-web-developer/
|
|
82
|
+
├── package.json # npm manifest (bin: agentic-web-developer, awd.source)
|
|
83
|
+
├── bin/install.js # zero-dependency installer CLI (all 15 agents, per-agent formats)
|
|
84
|
+
├── skill/ # ← the skill itself (source of truth; never published)
|
|
85
|
+
│ ├── SKILL.md
|
|
86
|
+
│ ├── references/ # 10 playbooks
|
|
87
|
+
│ └── templates/ # 4 fill-in templates
|
|
88
|
+
├── docs/ # ← the only content tracked in Git
|
|
89
|
+
│ ├── INSTALL.md # install guide for all 15 agents
|
|
90
|
+
│ └── EXAMPLES.md # worked walkthroughs: Mode A + Mode B
|
|
91
|
+
└── README.md # ← tracked in Git
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
> **Git vs npm vs skill source — nothing public carries your source:**
|
|
95
|
+
> - **Git:** only `README.md` and `docs/` are visible (`.gitignore` hides the rest).
|
|
96
|
+
> - **npm:** only the installer + docs are published (npm tarballs are public forever, so `skill/` is excluded) — set `awd.source` in `package.json` before publishing.
|
|
97
|
+
> - **Skill source:** `skill/` is fetched by the installer from the URL/path you configure (`--source`, `AWD_SOURCE`, or `awd.source`), with `--token`/`AWD_TOKEN` for private hosts.
|
|
98
|
+
|
|
99
|
+
## Development
|
|
100
|
+
|
|
101
|
+
Edit files under `skill/`, then refresh your local opencode install:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
node bin/install.js install --agent=opencode --force
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Check the package contents before publishing:
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
npm run pack:check
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Publishing to npm
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
# 1. point the installer at your private skill source first (never published to npm)
|
|
117
|
+
# edit package.json -> "awd": { "source": "https://api.github.com/repos/YOU/REPO/tarball/main" }
|
|
118
|
+
# (end users pass the token: AWD_TOKEN=... npx agentic-web-developer install)
|
|
119
|
+
|
|
120
|
+
npm login # once, with your npm account
|
|
121
|
+
npm publish # publishes bin + docs only (publishConfig.access = "public")
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Bump `version` in `package.json` for every update, then `npm publish` again.
|
|
125
|
+
|
|
126
|
+
## License
|
|
127
|
+
|
|
128
|
+
UNLICENSED — all rights reserved by the author. Replace the `license` field in `package.json` and add a LICENSE file if you intend to distribute it under a specific license.
|
package/bin/install.js
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* agentic-web-developer installer
|
|
4
|
+
*
|
|
5
|
+
* npx agentic-web-developer install [--agent=<key>|all] [--source=<url|path>] [--token=<key>]
|
|
6
|
+
* [--force] [--dry-run] [--dir=<path>]
|
|
7
|
+
* npx agentic-web-developer detect
|
|
8
|
+
*
|
|
9
|
+
* The npm package ships only this installer (+ docs). The skill payload is
|
|
10
|
+
* resolved from the first available source:
|
|
11
|
+
*
|
|
12
|
+
* 1. --source=<url|path> explicit flag (URL of a .tar.gz/.zip, or a local folder/archive)
|
|
13
|
+
* 2. AWD_SOURCE=<url|path> environment variable
|
|
14
|
+
* 3. skill/ next to this file local development checkout
|
|
15
|
+
* 4. awd.source in package.json configured by the package author
|
|
16
|
+
*
|
|
17
|
+
* Private sources: --token=<key> or AWD_TOKEN=<key> (GITHUB_TOKEN is used
|
|
18
|
+
* for github.com URLs). Installs each agent with its own file format.
|
|
19
|
+
* No dependencies. Node 18+.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
const fs = require("fs");
|
|
23
|
+
const path = require("path");
|
|
24
|
+
const os = require("os");
|
|
25
|
+
const { execFileSync } = require("child_process");
|
|
26
|
+
|
|
27
|
+
const argv = process.argv.slice(2);
|
|
28
|
+
const flags = {};
|
|
29
|
+
for (const arg of argv) {
|
|
30
|
+
const m = arg.match(/^--([^=]+)(?:=(.*))?$/);
|
|
31
|
+
if (m) flags[m[1]] = m[2] !== undefined ? m[2] : true;
|
|
32
|
+
}
|
|
33
|
+
const command = argv.find((a) => !a.startsWith("--")) || (flags.detect ? "detect" : "install");
|
|
34
|
+
|
|
35
|
+
const HOME = flags.home ? path.resolve(flags.home) : os.homedir();
|
|
36
|
+
const APPDATA = flags.home
|
|
37
|
+
? path.join(HOME, "AppData", "Roaming")
|
|
38
|
+
: process.env.APPDATA || path.join(os.homedir(), "AppData", "Roaming");
|
|
39
|
+
const LOCALAPPDATA = flags.home
|
|
40
|
+
? path.join(HOME, "AppData", "Local")
|
|
41
|
+
: process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local");
|
|
42
|
+
const PKG_ROOT = path.join(__dirname, "..");
|
|
43
|
+
const BUNDLED_SKILL = path.join(PKG_ROOT, "skill");
|
|
44
|
+
const SKILL_NAME = "agentic-web-developer";
|
|
45
|
+
const MARKER = "<!-- agentic-web-developer | installed by npx agentic-web-developer -->";
|
|
46
|
+
|
|
47
|
+
// format:
|
|
48
|
+
// skill -> <dirs>/<name>/SKILL.md
|
|
49
|
+
// skill-lower -> <dirs>/<name>/skill.md
|
|
50
|
+
// rules-mdc -> <agentRoot>/rules/<name>.mdc (Cursor rules)
|
|
51
|
+
// rules-md -> <agentRoot>/rules/<name>.md (Continue / Augment / Amazon Q)
|
|
52
|
+
// conventions -> <dirs>/CONVENTIONS.md (Aider)
|
|
53
|
+
// dirs = candidate skills directories (first existing one wins, else the first is created)
|
|
54
|
+
// roots = used by `detect` to decide whether the agent is installed on this machine
|
|
55
|
+
const AGENTS = {
|
|
56
|
+
opencode: {
|
|
57
|
+
name: "OpenCode",
|
|
58
|
+
format: "skill",
|
|
59
|
+
roots: [path.join(HOME, ".config", "opencode"), path.join(HOME, ".opencode")],
|
|
60
|
+
dirs: [path.join(HOME, ".config", "opencode", "skills"), path.join(HOME, ".opencode", "skills")]
|
|
61
|
+
},
|
|
62
|
+
claude: {
|
|
63
|
+
name: "Claude Code",
|
|
64
|
+
format: "skill",
|
|
65
|
+
roots: [path.join(HOME, ".claude"), path.join(APPDATA, "claude")],
|
|
66
|
+
dirs: [path.join(HOME, ".claude", "skills"), path.join(APPDATA, "claude", "skills")]
|
|
67
|
+
},
|
|
68
|
+
copilot: {
|
|
69
|
+
name: "GitHub Copilot",
|
|
70
|
+
format: "skill",
|
|
71
|
+
roots: [path.join(APPDATA, "github-copilot"), path.join(HOME, ".config", "github-copilot")],
|
|
72
|
+
dirs: [path.join(APPDATA, "github-copilot", "skills"), path.join(HOME, ".config", "github-copilot", "skills")]
|
|
73
|
+
},
|
|
74
|
+
cursor: {
|
|
75
|
+
name: "Cursor",
|
|
76
|
+
format: "rules-mdc",
|
|
77
|
+
roots: [path.join(HOME, ".cursor"), path.join(LOCALAPPDATA, "cursor")],
|
|
78
|
+
dirs: [path.join(HOME, ".cursor", "skills"), path.join(LOCALAPPDATA, "cursor", "skills")]
|
|
79
|
+
},
|
|
80
|
+
windsurf: {
|
|
81
|
+
name: "Windsurf (Codeium)",
|
|
82
|
+
format: "skill-lower",
|
|
83
|
+
roots: [path.join(HOME, ".codeium", "windsurf"), path.join(LOCALAPPDATA, "windsurf")],
|
|
84
|
+
dirs: [path.join(HOME, ".codeium", "windsurf", "skills"), path.join(LOCALAPPDATA, "windsurf", "skills")]
|
|
85
|
+
},
|
|
86
|
+
cody: {
|
|
87
|
+
name: "Cody (Sourcegraph)",
|
|
88
|
+
format: "skill",
|
|
89
|
+
roots: [path.join(HOME, ".cody"), path.join(APPDATA, "cody")],
|
|
90
|
+
dirs: [path.join(HOME, ".cody", "skills"), path.join(APPDATA, "cody", "skills")]
|
|
91
|
+
},
|
|
92
|
+
codium: {
|
|
93
|
+
name: "Codium",
|
|
94
|
+
format: "skill-lower",
|
|
95
|
+
roots: [path.join(HOME, ".codium"), path.join(LOCALAPPDATA, "codium")],
|
|
96
|
+
dirs: [path.join(HOME, ".codium", "skills"), path.join(LOCALAPPDATA, "codium", "skills")]
|
|
97
|
+
},
|
|
98
|
+
aider: {
|
|
99
|
+
name: "Aider",
|
|
100
|
+
format: "conventions",
|
|
101
|
+
roots: [path.join(HOME, ".aider")],
|
|
102
|
+
dirs: [path.join(HOME, ".aider", "skills")]
|
|
103
|
+
},
|
|
104
|
+
continue: {
|
|
105
|
+
name: "Continue",
|
|
106
|
+
format: "rules-md",
|
|
107
|
+
roots: [path.join(HOME, ".continue")],
|
|
108
|
+
dirs: [path.join(HOME, ".continue", "skills")]
|
|
109
|
+
},
|
|
110
|
+
codex: {
|
|
111
|
+
name: "Codex (OpenAI)",
|
|
112
|
+
format: "skill",
|
|
113
|
+
roots: [path.join(HOME, ".codex"), path.join(HOME, ".agents")],
|
|
114
|
+
dirs: [path.join(HOME, ".codex", "skills"), path.join(HOME, ".agents", "skills")]
|
|
115
|
+
},
|
|
116
|
+
roo: {
|
|
117
|
+
name: "Roo Code",
|
|
118
|
+
format: "skill",
|
|
119
|
+
roots: [path.join(HOME, ".roo"), path.join(HOME, ".agents")],
|
|
120
|
+
dirs: [path.join(HOME, ".roo", "skills"), path.join(HOME, ".agents", "skills")]
|
|
121
|
+
},
|
|
122
|
+
cline: {
|
|
123
|
+
name: "Cline",
|
|
124
|
+
format: "skill",
|
|
125
|
+
roots: [path.join(HOME, ".cline"), path.join(HOME, ".agents")],
|
|
126
|
+
dirs: [path.join(HOME, ".cline", "skills"), path.join(HOME, ".agents", "skills")]
|
|
127
|
+
},
|
|
128
|
+
augment: {
|
|
129
|
+
name: "Augment",
|
|
130
|
+
format: "rules-md",
|
|
131
|
+
roots: [path.join(HOME, ".augment")],
|
|
132
|
+
dirs: [path.join(HOME, ".augment", "skills")]
|
|
133
|
+
},
|
|
134
|
+
amazonq: {
|
|
135
|
+
name: "Amazon Q",
|
|
136
|
+
format: "rules-md",
|
|
137
|
+
roots: [path.join(HOME, ".amazonq"), path.join(HOME, ".aws", "amazonq")],
|
|
138
|
+
dirs: [path.join(HOME, ".amazonq", "skills"), path.join(HOME, ".aws", "amazonq", "skills")]
|
|
139
|
+
},
|
|
140
|
+
jetbrains: {
|
|
141
|
+
name: "JetBrains AI",
|
|
142
|
+
format: "skill",
|
|
143
|
+
roots: [path.join(HOME, ".junie")],
|
|
144
|
+
dirs: [path.join(HOME, ".junie", "skills")]
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
function readSource(skillDir) {
|
|
149
|
+
const skillMd = path.join(skillDir, "SKILL.md");
|
|
150
|
+
if (!fs.existsSync(skillMd)) {
|
|
151
|
+
throw new Error(`no SKILL.md at ${skillMd}`);
|
|
152
|
+
}
|
|
153
|
+
const raw = fs.readFileSync(skillMd, "utf8");
|
|
154
|
+
const fm = raw.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
|
|
155
|
+
const body = fm ? raw.slice(fm[0].length) : raw;
|
|
156
|
+
const descMatch = fm && fm[1].match(/^description:\s*(.+)$/m);
|
|
157
|
+
const description = descMatch ? descMatch[1].trim().replace(/^['"]|['"]$/g, "") : SKILL_NAME;
|
|
158
|
+
return { body, description };
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function getFrontmatter(key, description) {
|
|
162
|
+
const d = description.replace(/'/g, "''");
|
|
163
|
+
const base = `name: ${SKILL_NAME}\ndescription: '${d}'\nlicense: Proprietary`;
|
|
164
|
+
switch (key) {
|
|
165
|
+
case "aider":
|
|
166
|
+
return ""; // Aider uses plain markdown, no frontmatter
|
|
167
|
+
case "opencode":
|
|
168
|
+
return `---\n${base}\ncompatibility: opencode\n---\n\n`;
|
|
169
|
+
case "cursor":
|
|
170
|
+
return `---\n${base}\nglobs: ["**/*.{html,css,js,ts,jsx,tsx,vue,svelte,astro,md}"]\nalwaysApply: true\n---\n\n`;
|
|
171
|
+
case "claude":
|
|
172
|
+
return `---\n${base}\nversion: 1.0.0\n---\n\n`;
|
|
173
|
+
case "copilot":
|
|
174
|
+
return `---\n${base}\napplyTo: "**/*"\n---\n\n`;
|
|
175
|
+
case "windsurf":
|
|
176
|
+
case "codium":
|
|
177
|
+
return `---\n${base}\ntrigger: always_on\n---\n\n`;
|
|
178
|
+
case "cody":
|
|
179
|
+
return `---\n${base}\n---\n\n`;
|
|
180
|
+
case "continue":
|
|
181
|
+
return `---\n${base}\nglobs: "**/*"\n---\n\n`;
|
|
182
|
+
case "codex":
|
|
183
|
+
return `---\n${base}\nmetadata:\n short-description: Build and sell high-converting websites\n---\n\n`;
|
|
184
|
+
case "roo":
|
|
185
|
+
case "cline":
|
|
186
|
+
case "jetbrains":
|
|
187
|
+
return `---\n${base}\nversion: 1.0.0\n---\n\n`;
|
|
188
|
+
case "augment":
|
|
189
|
+
case "amazonq":
|
|
190
|
+
return `---\n${base}\n---\n\n`;
|
|
191
|
+
default:
|
|
192
|
+
return `---\n${base}\n---\n\n`;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
function pickDir(agent) {
|
|
197
|
+
for (const d of agent.dirs) {
|
|
198
|
+
if (fs.existsSync(d)) return d;
|
|
199
|
+
}
|
|
200
|
+
return agent.dirs[0];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// agentRoot: the agent's home (dir containing skills/ or rules/), derived from a skills dir
|
|
204
|
+
function agentRootOf(skillsDir) {
|
|
205
|
+
return path.basename(skillsDir) === "skills" ? path.dirname(skillsDir) : skillsDir;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function destFor(key, agent) {
|
|
209
|
+
if (flags.dir) {
|
|
210
|
+
const payloadDir = path.join(path.resolve(flags.dir), SKILL_NAME);
|
|
211
|
+
return { payloadDir, mainFile: path.join(payloadDir, "SKILL.md") };
|
|
212
|
+
}
|
|
213
|
+
const base = pickDir(agent);
|
|
214
|
+
const payloadDir = path.join(base, SKILL_NAME);
|
|
215
|
+
const root = agentRootOf(base);
|
|
216
|
+
switch (agent.format) {
|
|
217
|
+
case "skill":
|
|
218
|
+
return { payloadDir, mainFile: path.join(payloadDir, "SKILL.md") };
|
|
219
|
+
case "skill-lower":
|
|
220
|
+
return { payloadDir, mainFile: path.join(payloadDir, "skill.md") };
|
|
221
|
+
case "rules-mdc":
|
|
222
|
+
return { payloadDir, mainFile: path.join(root, "rules", `${SKILL_NAME}.mdc`) };
|
|
223
|
+
case "rules-md":
|
|
224
|
+
return { payloadDir, mainFile: path.join(root, "rules", `${SKILL_NAME}.md`) };
|
|
225
|
+
case "conventions":
|
|
226
|
+
return { payloadDir, mainFile: path.join(base, "CONVENTIONS.md") };
|
|
227
|
+
default:
|
|
228
|
+
return { payloadDir, mainFile: path.join(payloadDir, "SKILL.md") };
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function copyRecursive(src, dest) {
|
|
233
|
+
const stat = fs.statSync(src);
|
|
234
|
+
if (stat.isDirectory()) {
|
|
235
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
236
|
+
for (const entry of fs.readdirSync(src)) {
|
|
237
|
+
copyRecursive(path.join(src, entry), path.join(dest, entry));
|
|
238
|
+
}
|
|
239
|
+
} else {
|
|
240
|
+
fs.copyFileSync(src, dest);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function installPayload(payloadDir, skillDir) {
|
|
245
|
+
copyRecursive(path.join(skillDir, "references"), path.join(payloadDir, "references"));
|
|
246
|
+
copyRecursive(path.join(skillDir, "templates"), path.join(payloadDir, "templates"));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* ---------------- skill source resolution (private fetch) ---------------- */
|
|
250
|
+
|
|
251
|
+
function expandHome(p) {
|
|
252
|
+
if (p === "~") return HOME;
|
|
253
|
+
if (p.startsWith("~/") || p.startsWith("~\\")) return path.join(HOME, p.slice(2));
|
|
254
|
+
return p;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Find the folder holding SKILL.md inside an extracted/downloaded tree.
|
|
258
|
+
// Accepts: the skill folder itself, a folder containing skill/, or an
|
|
259
|
+
// archive whose repo root is the skill (depth <= 3).
|
|
260
|
+
function findSkillRoot(root, depth) {
|
|
261
|
+
if (fs.existsSync(path.join(root, "SKILL.md"))) return root;
|
|
262
|
+
const nested = path.join(root, "skill");
|
|
263
|
+
if (fs.existsSync(path.join(nested, "SKILL.md"))) return nested;
|
|
264
|
+
if (depth >= 3) return null;
|
|
265
|
+
let entries;
|
|
266
|
+
try {
|
|
267
|
+
entries = fs.readdirSync(root, { withFileTypes: true });
|
|
268
|
+
} catch {
|
|
269
|
+
return null;
|
|
270
|
+
}
|
|
271
|
+
for (const e of entries) {
|
|
272
|
+
if (!e.isDirectory()) continue;
|
|
273
|
+
const found = findSkillRoot(path.join(root, e.name), depth + 1);
|
|
274
|
+
if (found) return found;
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
function extractArchive(file) {
|
|
280
|
+
const work = fs.mkdtempSync(path.join(os.tmpdir(), "awd-src-"));
|
|
281
|
+
const args = /\.zip$/i.test(file) ? ["-xf", file, "-C", work] : ["-xzf", file, "-C", work];
|
|
282
|
+
try {
|
|
283
|
+
execFileSync("tar", args, { stdio: "pipe" });
|
|
284
|
+
} catch (e) {
|
|
285
|
+
throw new Error(
|
|
286
|
+
`could not extract ${path.basename(file)} with tar (tar must be on PATH; use a .tar.gz archive — raw: ${e.message})`
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
return work;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
async function downloadTo(url, label) {
|
|
293
|
+
const headers = {
|
|
294
|
+
"User-Agent": "agentic-web-developer-installer",
|
|
295
|
+
Accept: "application/octet-stream, */*"
|
|
296
|
+
};
|
|
297
|
+
const isGithub = /github\.com|githubusercontent\.com/i.test(url);
|
|
298
|
+
const token = flags.token || process.env.AWD_TOKEN || (isGithub ? process.env.GITHUB_TOKEN : undefined);
|
|
299
|
+
if (token) headers.Authorization = `Bearer ${token}`;
|
|
300
|
+
|
|
301
|
+
let res;
|
|
302
|
+
try {
|
|
303
|
+
res = await fetch(url, { headers, redirect: "follow" });
|
|
304
|
+
} catch (e) {
|
|
305
|
+
throw new Error(`${label}: network error fetching skill source — ${e.message}`);
|
|
306
|
+
}
|
|
307
|
+
if (!res.ok) {
|
|
308
|
+
const hint =
|
|
309
|
+
res.status === 404 || res.status === 403 || res.status === 401
|
|
310
|
+
? " (private source? add --token=<key> or AWD_TOKEN=<key>)"
|
|
311
|
+
: "";
|
|
312
|
+
throw new Error(`${label}: download failed — HTTP ${res.status} ${res.statusText}${hint}`);
|
|
313
|
+
}
|
|
314
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "awd-dl-"));
|
|
315
|
+
const name = (url.split("?")[0].split("/").pop() || "source").replace(/[^A-Za-z0-9._-]/g, "_");
|
|
316
|
+
const file = path.join(dir, name.includes(".") ? name : `${name}.tar.gz`);
|
|
317
|
+
fs.writeFileSync(file, Buffer.from(await res.arrayBuffer()));
|
|
318
|
+
return file;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
async function resolveLocation(loc, label) {
|
|
322
|
+
if (/^https?:\/\//i.test(loc)) {
|
|
323
|
+
console.log(`skill source (${label}): ${loc}`);
|
|
324
|
+
const file = await downloadTo(loc, label);
|
|
325
|
+
const root = findSkillRoot(extractArchive(file), 0);
|
|
326
|
+
if (!root) throw new Error(`${label}: the downloaded archive contains no SKILL.md — does the source contain the skill/ folder?`);
|
|
327
|
+
return root;
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
const p = path.resolve(expandHome(loc));
|
|
331
|
+
if (!fs.existsSync(p)) return null;
|
|
332
|
+
if (fs.statSync(p).isDirectory()) {
|
|
333
|
+
const root = findSkillRoot(p, 0);
|
|
334
|
+
if (!root) throw new Error(`${label}: no SKILL.md found under ${p}`);
|
|
335
|
+
return root;
|
|
336
|
+
}
|
|
337
|
+
const root = findSkillRoot(extractArchive(p), 0);
|
|
338
|
+
if (!root) throw new Error(`${label}: the archive contains no SKILL.md`);
|
|
339
|
+
return root;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function readPkg() {
|
|
343
|
+
try {
|
|
344
|
+
return JSON.parse(fs.readFileSync(path.join(PKG_ROOT, "package.json"), "utf8"));
|
|
345
|
+
} catch {
|
|
346
|
+
return null;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
async function resolveSource() {
|
|
351
|
+
// 1. explicit flag
|
|
352
|
+
if (flags.source) {
|
|
353
|
+
const r = await resolveLocation(String(flags.source), "--source");
|
|
354
|
+
if (!r) throw new Error(`--source: no such file or directory: ${flags.source}`);
|
|
355
|
+
return r;
|
|
356
|
+
}
|
|
357
|
+
// 2. environment
|
|
358
|
+
if (process.env.AWD_SOURCE) {
|
|
359
|
+
const r = await resolveLocation(process.env.AWD_SOURCE, "AWD_SOURCE");
|
|
360
|
+
if (!r) throw new Error(`AWD_SOURCE: no such file or directory: ${process.env.AWD_SOURCE}`);
|
|
361
|
+
return r;
|
|
362
|
+
}
|
|
363
|
+
// 3. local development checkout (skill/ next to bin/)
|
|
364
|
+
if (fs.existsSync(path.join(BUNDLED_SKILL, "SKILL.md"))) return BUNDLED_SKILL;
|
|
365
|
+
// 4. source configured by the package author
|
|
366
|
+
const pkg = readPkg();
|
|
367
|
+
const pkgSource = pkg && pkg.awd && pkg.awd.source;
|
|
368
|
+
if (pkgSource) {
|
|
369
|
+
const r = await resolveLocation(String(pkgSource), "package.json awd.source");
|
|
370
|
+
if (r) return r;
|
|
371
|
+
throw new Error(`package.json awd.source could not be resolved: ${pkgSource}`);
|
|
372
|
+
}
|
|
373
|
+
throw new Error(
|
|
374
|
+
[
|
|
375
|
+
"no skill source found — this npm package ships only the installer (+ docs).",
|
|
376
|
+
"Provide the skill payload with one of:",
|
|
377
|
+
" --source=<url|path> a .tar.gz/.zip URL, or a local skill folder/archive",
|
|
378
|
+
" AWD_SOURCE=<url|path> same, via environment variable",
|
|
379
|
+
" awd.source in package.json set by the package author before publishing",
|
|
380
|
+
"Private sources also need a token: --token=<key> or AWD_TOKEN=<key>",
|
|
381
|
+
"Local development: keep the skill/ folder next to bin/ — it is used automatically."
|
|
382
|
+
].join("\n")
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/* -------------------------------- commands -------------------------------- */
|
|
387
|
+
|
|
388
|
+
function detect() {
|
|
389
|
+
console.log(`\nAgents on this machine (and ${SKILL_NAME} install status):\n`);
|
|
390
|
+
let found = 0;
|
|
391
|
+
for (const [key, agent] of Object.entries(AGENTS)) {
|
|
392
|
+
const present = agent.roots.some((r) => fs.existsSync(r));
|
|
393
|
+
const { mainFile, payloadDir } = destFor(key, agent);
|
|
394
|
+
let installed = fs.existsSync(mainFile);
|
|
395
|
+
// Aider's CONVENTIONS.md may belong to another skill — require our marker
|
|
396
|
+
if (installed && agent.format === "conventions") {
|
|
397
|
+
installed = fs.readFileSync(mainFile, "utf8").includes(MARKER);
|
|
398
|
+
}
|
|
399
|
+
if (installed && !fs.existsSync(payloadDir)) installed = false;
|
|
400
|
+
if (present) found++;
|
|
401
|
+
const status = installed ? "INSTALLED" : present ? "not installed" : "agent not found";
|
|
402
|
+
console.log(
|
|
403
|
+
` ${present || installed ? "*" : " "} ${key.padEnd(10)} ${agent.name.padEnd(20)} ${status}` +
|
|
404
|
+
(installed ? ` -> ${mainFile}` : "")
|
|
405
|
+
);
|
|
406
|
+
}
|
|
407
|
+
console.log(`\n Install: npx ${SKILL_NAME} install --agent=<key> (or --all, or omit --agent for auto)\n`);
|
|
408
|
+
return found;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
async function install() {
|
|
412
|
+
const skillDir = await resolveSource();
|
|
413
|
+
const { body, description } = readSource(skillDir);
|
|
414
|
+
|
|
415
|
+
let keys;
|
|
416
|
+
if (flags.agent === "all") {
|
|
417
|
+
keys = Object.keys(AGENTS);
|
|
418
|
+
} else if (flags.agent) {
|
|
419
|
+
if (!AGENTS[flags.agent]) {
|
|
420
|
+
throw new Error(`unknown agent "${flags.agent}". Valid keys: ${Object.keys(AGENTS).join(", ")}, all`);
|
|
421
|
+
}
|
|
422
|
+
keys = [flags.agent];
|
|
423
|
+
} else if (flags.all) {
|
|
424
|
+
keys = Object.keys(AGENTS);
|
|
425
|
+
} else {
|
|
426
|
+
// auto: opencode first, then claude, then any detected agent
|
|
427
|
+
const detected = Object.entries(AGENTS).filter(([, a]) => a.roots.some((r) => fs.existsSync(r)));
|
|
428
|
+
const preferred = ["opencode", "claude"].filter((k) => detected.some(([dk]) => dk === k));
|
|
429
|
+
keys = [preferred[0] || (detected[0] && detected[0][0]) || "opencode"];
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
let done = 0;
|
|
433
|
+
for (const key of keys) {
|
|
434
|
+
const agent = AGENTS[key];
|
|
435
|
+
const { payloadDir, mainFile } = destFor(key, agent);
|
|
436
|
+
const isRuleFile = ["rules-mdc", "rules-md", "conventions"].includes(agent.format);
|
|
437
|
+
|
|
438
|
+
if (flags["dry-run"]) {
|
|
439
|
+
console.log(`[dry-run] ${agent.name} (${key})`);
|
|
440
|
+
console.log(` main: ${mainFile}`);
|
|
441
|
+
console.log(` refs: ${payloadDir}{/references, /templates}`);
|
|
442
|
+
done++;
|
|
443
|
+
continue;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
if (fs.existsSync(mainFile) && !flags.force) {
|
|
447
|
+
if (agent.format === "conventions") {
|
|
448
|
+
const existing = fs.readFileSync(mainFile, "utf8");
|
|
449
|
+
if (!existing.includes(MARKER)) {
|
|
450
|
+
console.log(`skip ${agent.name}: ${mainFile} already exists and was not written by this installer (use --force to overwrite)`);
|
|
451
|
+
continue;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
console.log(`skip ${agent.name}: already installed at ${mainFile} (use --force to overwrite)`);
|
|
455
|
+
continue;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
fs.mkdirSync(payloadDir, { recursive: true });
|
|
459
|
+
installPayload(payloadDir, skillDir);
|
|
460
|
+
|
|
461
|
+
// Frontmatter per agent; rule files get a pointer to the reference payload
|
|
462
|
+
let content = getFrontmatter(key, description) + body;
|
|
463
|
+
if (isRuleFile) {
|
|
464
|
+
const pointer = `> Reference playbooks: ${path.join(payloadDir, "references")} — templates: ${path.join(payloadDir, "templates")}\n\n`;
|
|
465
|
+
const fm = content.match(/^---\r?\n[\s\S]*?\r?\n---\r?\n\n/);
|
|
466
|
+
if (fm) {
|
|
467
|
+
content = fm[0] + pointer + content.slice(fm[0].length);
|
|
468
|
+
} else {
|
|
469
|
+
content = `${MARKER}\n${pointer}${content}`;
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
fs.mkdirSync(path.dirname(mainFile), { recursive: true });
|
|
473
|
+
fs.writeFileSync(mainFile, content);
|
|
474
|
+
console.log(`installed ${agent.name} (${key})`);
|
|
475
|
+
console.log(` main: ${mainFile}`);
|
|
476
|
+
console.log(` refs: ${payloadDir}`);
|
|
477
|
+
done++;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (!done) {
|
|
481
|
+
console.log("nothing installed — everything already present (use --force to overwrite)");
|
|
482
|
+
} else if (!flags["dry-run"]) {
|
|
483
|
+
console.log(`\nDone. Restart your AI agent so it loads ${SKILL_NAME}.`);
|
|
484
|
+
console.log("Animations for any site built with this skill are handled by the AnimotionJS agentic skill:");
|
|
485
|
+
console.log(" npx animotion-skills install --tier=agentic --agent=<agent> --license-key=YOUR_KEY");
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
switch (command) {
|
|
490
|
+
case "detect":
|
|
491
|
+
detect();
|
|
492
|
+
break;
|
|
493
|
+
case "install":
|
|
494
|
+
install().catch((err) => {
|
|
495
|
+
console.error(`error: ${err.message}`);
|
|
496
|
+
process.exit(1);
|
|
497
|
+
});
|
|
498
|
+
break;
|
|
499
|
+
case "help":
|
|
500
|
+
case "--help":
|
|
501
|
+
usage();
|
|
502
|
+
break;
|
|
503
|
+
default:
|
|
504
|
+
usage();
|
|
505
|
+
process.exit(1);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
function usage() {
|
|
509
|
+
console.log(`
|
|
510
|
+
${SKILL_NAME} — install the agentic-web-developer skill into your AI agent
|
|
511
|
+
|
|
512
|
+
Usage:
|
|
513
|
+
npx ${SKILL_NAME} install [options]
|
|
514
|
+
npx ${SKILL_NAME} detect
|
|
515
|
+
|
|
516
|
+
Options:
|
|
517
|
+
--agent=<key> Target one agent: ${Object.keys(AGENTS).join(", ")}
|
|
518
|
+
--agent=all Target every supported agent
|
|
519
|
+
--all Same as --agent=all
|
|
520
|
+
--source=<s> Skill source: a .tar.gz/.zip URL or a local folder/archive
|
|
521
|
+
(falls back to AWD_SOURCE, then skill/, then awd.source)
|
|
522
|
+
--token=<key> Auth token for a private source (or AWD_TOKEN=<key>)
|
|
523
|
+
--force Overwrite an existing install
|
|
524
|
+
--dry-run Print target paths without copying
|
|
525
|
+
--dir=<path> Install into <path>/${SKILL_NAME} (flat, SKILL.md layout)
|
|
526
|
+
--home=<path> Use <path> as the home directory (testing)
|
|
527
|
+
|
|
528
|
+
Skill source order: --source > AWD_SOURCE > ./skill > package.json awd.source
|
|
529
|
+
The npm package ships only this installer (+ docs) — never the skill source.
|
|
530
|
+
|
|
531
|
+
Each agent gets its own file format:
|
|
532
|
+
skill agents (opencode, claude, copilot, cody, codex, roo, cline, jetbrains)
|
|
533
|
+
-> <skills>/${SKILL_NAME}/SKILL.md
|
|
534
|
+
windsurf, codium -> <skills>/${SKILL_NAME}/skill.md
|
|
535
|
+
cursor -> ~/.cursor/rules/${SKILL_NAME}.mdc
|
|
536
|
+
continue -> ~/.continue/rules/${SKILL_NAME}.md
|
|
537
|
+
augment -> ~/.augment/rules/${SKILL_NAME}.md
|
|
538
|
+
amazonq -> ~/.amazonq/rules/${SKILL_NAME}.md
|
|
539
|
+
aider -> ~/.aider/skills/CONVENTIONS.md
|
|
540
|
+
|
|
541
|
+
Examples:
|
|
542
|
+
npx ${SKILL_NAME} install # auto-detect agent
|
|
543
|
+
npx ${SKILL_NAME} install --agent=all --source=https://you/server/skill.tar.gz --token=KEY
|
|
544
|
+
npx ${SKILL_NAME} detect
|
|
545
|
+
`);
|
|
546
|
+
}
|
package/docs/EXAMPLES.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Examples — the two scenarios
|
|
2
|
+
|
|
3
|
+
The skill runs the same 11-stage gated pipeline in both modes. Every stage ends with a question to you; answers are recorded in `build-state.md`. These are two complete walkthroughs.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Scenario A — Mode A: build-and-sell a website for a local business
|
|
8
|
+
|
|
9
|
+
**You say:**
|
|
10
|
+
|
|
11
|
+
> "Build me a website that converts for my pool cleaning business in Phoenix."
|
|
12
|
+
|
|
13
|
+
**Mode:** A (build-and-sell — the video default). Goal: a site you can sell as a product, plus the outreach system to find buyers.
|
|
14
|
+
|
|
15
|
+
| Stage | What happens | The gate (you answer) |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| 0 — Intake | Agent records: offer ("pool cleaning, weekly plans"), audience (Phoenix homeowners), mode A, no client list yet, $0/mo tool budget | "Confirm the offer and audience — and do you have any clients/leads yet, or start from zero?" → *"start from zero"* |
|
|
18
|
+
| 1 — Money framework | Runs **M** of M.O.N.E.Y: validates "pool cleaning in Phoenix" — unsexy niche, 20+ businesses, most sites outdated, you know the trade | "Pick the niche: pool cleaning, HVAC, or landscaping in Phoenix?" → *"pool cleaning"* |
|
|
19
|
+
| 2 — Research | **Design Blueprint Extractor** on an inspiration site you name (e.g. a clean SaaS-style home-services site) → `builderbrief.md`, `scaffold.html`, `tokens.json`. **Outlier Research** scrapes 12 pool companies → top 5 / bottom 5 → `outlier-anatomy.md` (winners: price-on-site, booking form, reviews above fold; losers: flash intros, no phone number) | "Approve the inspiration site and the outlier findings?" → *"yes, but keep the blue from the inspiration"* |
|
|
20
|
+
| 3 — Design tool | — | "Which tool: Stitch, AI Studio, Figma, Paper, or code-first?" → *"Stitch"* |
|
|
21
|
+
| 4 — Design | Section plan from the anatomy: hero + phone CTA, stat strip (years, pools serviced), plans grid, how-it-works, reviews, FAQ, quote form | "Review the design — approve before code?" → *"approve"* |
|
|
22
|
+
| 5 — Framework | — | "Framework?" → *"plain HTML/CSS + a bit of JS"* (client wants cheap hosting) |
|
|
23
|
+
| 6 — Build | Page(s) built 1:1 from the design, all content from `siteconfig.ts`; AI-generated hero image iterated until the pool photo leaves room for the headline | "Look at localhost — review before QA?" → *"looks good"* |
|
|
24
|
+
| 7 — QA | Conversion blueprint + UI/UX checklist: H1 "Pool Cleaning That Never Misses a Week" (6 words), AA contrast, form tested, mobile widths checked | "QA passed — approve?" → *"approve"* |
|
|
25
|
+
| 8 — Animation | You're told: **all motion goes to AnimotionJS** (Stage plan): hero reveal, scroll reveals, plan-card hover, counter on the stat strip → motion brief written and handed to the Animotion skill | "Animotion installed? Approve the motion brief?" → *"installed, approved"* |
|
|
26
|
+
| 9 — Deploy | — | "Deploy where: GitHub→Vercel, GoHighLevel, or WordPress?" → *"GitHub → Vercel"* |
|
|
27
|
+
| 10 — Sell | Runs the outreach system: scrapes Phoenix pool companies (Apify, budget-capped), enriches emails, then sends: *free site as the foot in the door* → hosting retainer ($50–150/mo) → SEO/reviews upsells; Day 1/3/7 follow-ups | "Draft the outreach emails for niche 'pool cleaning'?" → *"send to 20 leads"* |
|
|
28
|
+
|
|
29
|
+
**Result:** a deployed, converting site + a repeatable client-acquisition loop. The same `siteconfig.ts` makes the next local-business site a clone, not a rebuild.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Scenario B — **Mode B — launch your own product (SaaS)**
|
|
34
|
+
|
|
35
|
+
**You say:**
|
|
36
|
+
|
|
37
|
+
> "I have a SaaS idea — FocusFlow, a focus timer with team accountability. I want to launch it."
|
|
38
|
+
|
|
39
|
+
**Mode:** B (novel idea / product launch — no customer list). Re-scopes Stages 1, 2's outliers, 4–7's goal, 3/5's surface, and 10's motion.
|
|
40
|
+
|
|
41
|
+
| Stage | What happens | The gate (you answer) |
|
|
42
|
+
|---|---|---|
|
|
43
|
+
| 0 — Intake | Agent records: idea ("FocusFlow — team focus timer"), audience (remote teams / ADHD founders), mode B, **brand assets collected**: existing teal logo + palette from your deck; **inspiration sites collected**: linear.app and stripe.com | "Confirm the idea and audience — and what brand assets exist?" → *"teal logo + palette; new type"* |
|
|
44
|
+
| 1 — Idea/audience validation | Re-scoped: who has this problem (r/ADHD, remote-work Discords), alternatives (Float, Motion, plain Pomodoro), demand signals (competitor reviews complaining about pricing) | "Audience confirmed: remote teams of 2–10?" → *"yes"* |
|
|
45
|
+
| 2 — Research | **Design Blueprint Extractor runs exactly like Mode A**: linear.app as inspiration (type scale, density, border language) + **second pass on your brand** (teal palette from the logo/deck) → merged: brand colors win, linear sets the feel → `builderbrief.md`, `scaffold.html`, `tokens.json`. **Outlier Research** re-scoped to rival launch pages (Motion, Forest, Pomodoro apps by traffic/reviews) → `outlier-anatomy.md` | "Approve the inspiration + extracted brand style?" → *"yes, keep #0D9488 as primary"* |
|
|
46
|
+
| 3 — Design tool | — | "Tool?" → *"code-first (Next.js)"* (multi-page app-like site) |
|
|
47
|
+
| 4 — Design | Section plan re-scoped to the product's anatomy: demo/video hero, feature grid, integrations logos, pricing tiers, testimonials, FAQ — single CTA: **Join the waitlist** | "Approve the design?" → *"approve"* |
|
|
48
|
+
| 5 — Framework | — | "Framework?" → *"Next.js"* — multi-page scaffold: `/`, `/pricing`, `/docs` |
|
|
49
|
+
| 6 — Build | Pages built from the outlier anatomy; AI-generated abstract hero matched to the teal palette; conversion goal wired: waitlist form (email only, no password) | "Review on localhost?" → *"approve"* |
|
|
50
|
+
| 7 — QA | Same checklists, goal adjusted: H1 "Focus Together, Finish Faster" (5 words), one CTA everywhere, form → provider tested, responsive pass | "QA passed?" → *"approve"* |
|
|
51
|
+
| 8 — Animation | Motion brief to AnimotionJS: hero mask reveal, feature-card scroll stagger, pricing hover lift, waitlist-button magnetic hover | "Animotion installed? Approve brief?" → *"approved"* |
|
|
52
|
+
| 9 — Deploy | — | "Deploy where?" → *"GitHub → Vercel + custom domain"* |
|
|
53
|
+
| 10 — Launch motion | Re-scoped from cold outreach: waitlist/launch email sequence, founder outreach (remote-work communities, r/SaaS), Product Hunt draft — same email rules (human subject, no hard ask, proof + link); monetization = trial/paid tiers instead of retainers | "Draft the launch emails and PH post?" → *"yes"* |
|
|
54
|
+
|
|
55
|
+
**Result:** a live multi-page product site with your brand DNA extracted alongside the inspiration, waitlist converting, and a launch sequence ready to send.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## What's identical in both modes
|
|
60
|
+
|
|
61
|
+
- Inspiration-site **design DNA extraction** and **brand-style extraction** (Stage 2)
|
|
62
|
+
- The conversion blueprint and QA checklists (Stage 7)
|
|
63
|
+
- Deployment (Stage 9)
|
|
64
|
+
- **The animation rule:** no motion code is ever written by this skill — Stage 8 hands a motion brief to the **AnimotionJS agentic skill** for all 15 supported agents
|
|
65
|
+
- A question gate at the end of every stage
|
|
66
|
+
|
|
67
|
+
Install for your agent: [INSTALL.md](./INSTALL.md).
|
package/docs/INSTALL.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# Installing agentic-web-developer
|
|
2
|
+
|
|
3
|
+
The skill installs into **15 AI coding agents** — the same 15 the AnimotionJS skill supports. The installer writes each agent's own file format (`SKILL.md`, `skill.md`, a rules file, or `CONVENTIONS.md`) with the right frontmatter, plus the reference playbooks and templates alongside it.
|
|
4
|
+
|
|
5
|
+
> **The npm package contains only the installer and these docs** — never the skill source. The installer fetches the skill payload from a *skill source* you configure (see [Skill source](#skill-source)).
|
|
6
|
+
|
|
7
|
+
## Quick start
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
# auto-detect your agent (opencode -> claude -> any detected agent)
|
|
11
|
+
npx agentic-web-developer install
|
|
12
|
+
|
|
13
|
+
# target one agent by key
|
|
14
|
+
npx agentic-web-developer install --agent=claude
|
|
15
|
+
|
|
16
|
+
# install for every supported agent at once
|
|
17
|
+
npx agentic-web-developer install --all
|
|
18
|
+
|
|
19
|
+
# see what's installed, and where
|
|
20
|
+
npx agentic-web-developer detect
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Then **restart your AI agent** so it loads the skill.
|
|
24
|
+
|
|
25
|
+
### All flags
|
|
26
|
+
|
|
27
|
+
| Flag | Effect |
|
|
28
|
+
|---|---|
|
|
29
|
+
| `--agent=<key>` | Install for one agent (keys in the table below) |
|
|
30
|
+
| `--agent=all` / `--all` | Install for all 15 agents |
|
|
31
|
+
| `--source=<url\|path>` | Skill source: a `.tar.gz`/`.zip` URL, or a local skill folder/archive |
|
|
32
|
+
| `--token=<key>` | Auth token for a private source (else `AWD_TOKEN`) |
|
|
33
|
+
| `--force` | Overwrite an existing install |
|
|
34
|
+
| `--dry-run` | Print the target paths without writing anything |
|
|
35
|
+
| `--dir=<path>` | Install flat into `<path>/agentic-web-developer/` (SKILL.md layout) |
|
|
36
|
+
| `--home=<path>` | Use `<path>` as the home directory (for testing) |
|
|
37
|
+
|
|
38
|
+
## Skill source
|
|
39
|
+
|
|
40
|
+
Because the npm tarball ships no `skill/` folder, the installer resolves the payload from the first available source, in this order:
|
|
41
|
+
|
|
42
|
+
1. `--source=<url|path>` — explicit flag
|
|
43
|
+
2. `AWD_SOURCE=<url|path>` — environment variable
|
|
44
|
+
3. `skill/` next to `bin/` — local development checkout (used automatically)
|
|
45
|
+
4. `awd.source` in `package.json` — set by the package author before publishing
|
|
46
|
+
|
|
47
|
+
**URL sources** are downloaded and extracted (system `tar`; `.tar.gz` preferred, `.zip` works on Windows/macOS). The archive may be the repo root, a `skill/` folder inside it, or anything containing `SKILL.md` within three levels.
|
|
48
|
+
|
|
49
|
+
**Private sources** need a token: `--token=<key>` or `AWD_TOKEN=<key>` (`GITHUB_TOKEN` is used automatically for github.com URLs):
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
# private GitHub repo (tarball API)
|
|
53
|
+
npx agentic-web-developer install --source=https://api.github.com/repos/YOU/private-skill/tarball/main --token=ghp_XXXX
|
|
54
|
+
|
|
55
|
+
# same, via environment (handy for CI or shell profiles)
|
|
56
|
+
export AWD_SOURCE=https://api.github.com/repos/YOU/private-skill/tarball/main
|
|
57
|
+
export AWD_TOKEN=ghp_XXXX
|
|
58
|
+
npx agentic-web-developer install
|
|
59
|
+
|
|
60
|
+
# your own server / object storage
|
|
61
|
+
npx agentic-web-developer install --source=https://your-server/skill.tar.gz
|
|
62
|
+
|
|
63
|
+
# local folder or archive (no network)
|
|
64
|
+
npx agentic-web-developer install --source=~/backups/skill
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The package author normally sets `awd.source` in `package.json` once, so end users just run `npx agentic-web-developer install` with no configuration.
|
|
68
|
+
|
|
69
|
+
## Where each agent gets the skill
|
|
70
|
+
|
|
71
|
+
| Key | Agent | File written | Plus |
|
|
72
|
+
|---|---|---|---|
|
|
73
|
+
| `opencode` | OpenCode | `~/.config/opencode/skills/agentic-web-developer/SKILL.md` | `references/`, `templates/` |
|
|
74
|
+
| `claude` | Claude Code | `~/.claude/skills/agentic-web-developer/SKILL.md` | `references/`, `templates/` |
|
|
75
|
+
| `copilot` | GitHub Copilot | `%APPDATA%\github-copilot\skills\agentic-web-developer\SKILL.md` | `references/`, `templates/` |
|
|
76
|
+
| `cursor` | Cursor | `~/.cursor/rules/agentic-web-developer.mdc` | payload in `~/.cursor/skills/agentic-web-developer/` |
|
|
77
|
+
| `windsurf` | Windsurf (Codeium) | `~/.codeium/windsurf/skills/agentic-web-developer/skill.md` | `references/`, `templates/` |
|
|
78
|
+
| `cody` | Cody (Sourcegraph) | `~/.cody/skills/agentic-web-developer/SKILL.md` | `references/`, `templates/` |
|
|
79
|
+
| `codium` | Codium | `~/.codium/skills/agentic-web-developer/skill.md` | `references/`, `templates/` |
|
|
80
|
+
| `aider` | Aider | `~/.aider/skills/CONVENTIONS.md` | payload in `~/.aider/skills/agentic-web-developer/` |
|
|
81
|
+
| `continue` | Continue | `~/.continue/rules/agentic-web-developer.md` | payload in `~/.continue/skills/agentic-web-developer/` |
|
|
82
|
+
| `codex` | Codex (OpenAI) | `~/.codex/skills/agentic-web-developer/SKILL.md` | `references/`, `templates/` |
|
|
83
|
+
| `roo` | Roo Code | `~/.roo/skills/agentic-web-developer/SKILL.md` | `references/`, `templates/` |
|
|
84
|
+
| `cline` | Cline | `~/.cline/skills/agentic-web-developer/SKILL.md` | `references/`, `templates/` |
|
|
85
|
+
| `augment` | Augment | `~/.augment/rules/agentic-web-developer.md` | payload in `~/.augment/skills/agentic-web-developer/` |
|
|
86
|
+
| `amazonq` | Amazon Q | `~/.amazonq/rules/agentic-web-developer.md` | payload in `~/.amazonq/skills/agentic-web-developer/` |
|
|
87
|
+
| `jetbrains` | JetBrains AI | `~/.junie/skills/agentic-web-developer/SKILL.md` | `references/`, `templates/` |
|
|
88
|
+
|
|
89
|
+
Notes:
|
|
90
|
+
|
|
91
|
+
- **Rules agents** (cursor, continue, augment, amazonq) receive the full skill body as a rules file with agent-specific frontmatter (`globs`, `alwaysApply`, `trigger`, …). The file starts with a pointer to the installed `references/` and `templates/` payload so the agent can read the playbooks on demand.
|
|
92
|
+
- **Aider** has no skill loader — it reads conventions files. The skill lands at `~/.aider/skills/CONVENTIONS.md`. Point Aider at it with `aider --read ~/.aider/skills/CONVENTIONS.md`, or copy that file into a project as `CONVENTIONS.md`. The installer never overwrites a `CONVENTIONS.md` it didn't write (unless you pass `--force`), so an existing Animotion or other conventions file is safe.
|
|
93
|
+
- Windows paths are shown with `~` for your user home; `%APPDATA%` is your Roaming app-data folder.
|
|
94
|
+
|
|
95
|
+
## Manual install (no CLI)
|
|
96
|
+
|
|
97
|
+
Get the skill folder itself (the package doesn't contain it — take it from your configured source, or a copy someone sent you), then place the files as the table above says:
|
|
98
|
+
|
|
99
|
+
- **SKILL.md agents** — copy the `skill/` folder to `<skills-dir>/agentic-web-developer/` (it must contain `SKILL.md`, `references/`, `templates/`).
|
|
100
|
+
- **Windsurf / Codium** — same, but rename `SKILL.md` to `skill.md`.
|
|
101
|
+
- **Cursor** — copy `skill/SKILL.md` to `~/.cursor/rules/agentic-web-developer.mdc`, keep `references/` + `templates/` in `~/.cursor/skills/agentic-web-developer/`.
|
|
102
|
+
- **Continue / Augment / Amazon Q** — copy `skill/SKILL.md` to the agent's `rules/agentic-web-developer.md` (paths in the table), payload alongside in `skills/agentic-web-developer/`.
|
|
103
|
+
- **Aider** — copy `skill/SKILL.md` (without its `---` frontmatter block) to `~/.aider/skills/CONVENTIONS.md`.
|
|
104
|
+
|
|
105
|
+
## Verify
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
npx agentic-web-developer detect
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
`INSTALLED` next to an agent means the skill file and its payload are both in place.
|
|
112
|
+
|
|
113
|
+
## Uninstall
|
|
114
|
+
|
|
115
|
+
Delete what the table lists for your agent — the skill file **and** the `agentic-web-developer/` payload folder. For example:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
# opencode
|
|
119
|
+
rm -rf ~/.config/opencode/skills/agentic-web-developer
|
|
120
|
+
|
|
121
|
+
# cursor (rule file + payload)
|
|
122
|
+
rm -f ~/.cursor/rules/agentic-web-developer.mdc
|
|
123
|
+
rm -rf ~/.cursor/skills/agentic-web-developer
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## Companion: AnimotionJS (required for animation)
|
|
127
|
+
|
|
128
|
+
Every site built with this skill gets its **animations from the AnimotionJS agentic skill** — this skill never writes motion code. Install Animotion for the same agent:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
npx animotion-skills install --tier=agentic --agent=<agent> --license-key=YOUR_KEY
|
|
132
|
+
npx animotion-skills install --tier=agentic --all --license-key=YOUR_KEY # every detected agent
|
|
133
|
+
npx animotion-skills install --detect
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
- License key (Studio plan, $15/month): https://skills.animotion.click/checkout
|
|
137
|
+
- Without a key the build still works up to Stage 8 (animation handoff), where it stops and asks you to install Animotion.
|
|
138
|
+
|
|
139
|
+
## Repository vs npm package vs skill source
|
|
140
|
+
|
|
141
|
+
- **This Git repository** contains **documentation only** (`README.md`, `docs/`) — the `.gitignore` hides everything else.
|
|
142
|
+
- **The npm package** contains **only the installer** (`bin/install.js`) + docs — never `skill/`. Anything in a published tarball is publicly downloadable forever, so the source stays out of it.
|
|
143
|
+
- **The skill source** lives wherever you say: [Skill source](#skill-source) (`--source`, `AWD_SOURCE`, or the author's `awd.source`).
|
|
144
|
+
|
|
145
|
+
## Examples
|
|
146
|
+
|
|
147
|
+
Two full scenario walkthroughs — one per mode — are in [EXAMPLES.md](./EXAMPLES.md).
|
package/package.json
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentic-web-developer",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "Agentic skill for building high-converting websites that sell — design DNA extraction, outlier competitor research, conversion blueprints, the M.O.N.E.Y sales framework, lead generation, cloning, outreach and deployment, with a novel-idea/product-launch mode. All animation work is delegated to the AnimotionJS agentic skill.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"opencode",
|
|
7
|
+
"skill",
|
|
8
|
+
"agentic",
|
|
9
|
+
"ai-agents",
|
|
10
|
+
"claude-code",
|
|
11
|
+
"cursor",
|
|
12
|
+
"web-development",
|
|
13
|
+
"website-builder",
|
|
14
|
+
"conversion",
|
|
15
|
+
"landing-page",
|
|
16
|
+
"money-framework",
|
|
17
|
+
"animotion",
|
|
18
|
+
"animotionjs"
|
|
19
|
+
],
|
|
20
|
+
"bin": {
|
|
21
|
+
"agentic-web-developer": "bin/install.js"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"bin",
|
|
25
|
+
"docs",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"scripts": {
|
|
29
|
+
"detect": "node bin/install.js detect",
|
|
30
|
+
"install:skill": "node bin/install.js install",
|
|
31
|
+
"pack:check": "npm pack --dry-run"
|
|
32
|
+
},
|
|
33
|
+
"engines": {
|
|
34
|
+
"node": ">=18"
|
|
35
|
+
},
|
|
36
|
+
"license": "UNLICENSED",
|
|
37
|
+
"awd": {
|
|
38
|
+
"source": "https://4e2zaktqel.ucarecd.net/c3f306d4-38fd-4545-b6ef-e3bef7f9888a/skilltar.gz"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
}
|
|
43
|
+
}
|