skills-ws 1.4.1 → 1.5.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/LICENSE +21 -0
- package/README.md +179 -17
- package/bin/cli.mjs +93 -115
- package/package.json +18 -29
- package/skills/ai-agent-building/SKILL.md +17 -19
- package/skills/aleph-cloud-self-deployment/SKILL.md +3711 -504
- package/skills/auth-implementation/SKILL.md +5 -4
- package/skills/ci-cd-pipeline/SKILL.md +1 -1
- package/skills/defi-integration/SKILL.md +8 -5
- package/skills/docker-production/SKILL.md +3 -2
- package/skills/mcp-client/SKILL.md +814 -0
- package/skills/mcp-server-builder/SKILL.md +1768 -0
- package/skills/monitoring-observability/SKILL.md +1 -1
- package/skills/nextjs-performance/SKILL.md +3 -2
- package/skills/onchain-analytics/SKILL.md +14 -9
- package/skills/postgres-mastery/SKILL.md +2 -3
- package/skills/product-led-growth/SKILL.md +7 -6
- package/skills/saas-billing/SKILL.md +2032 -0
- package/skills/solidity-dev/SKILL.md +3 -0
- package/skills/stripe-billing/SKILL.md +16 -16
- package/skills/telegram-mini-apps/SKILL.md +1860 -0
- package/CHANGELOG.md +0 -39
- package/REVIEW.md +0 -516
- package/app/cli/page.tsx +0 -100
- package/app/docs/page.tsx +0 -117
- package/app/faq/page.tsx +0 -92
- package/app/globals.css +0 -25
- package/app/layout.tsx +0 -248
- package/app/not-found.tsx +0 -22
- package/app/page.tsx +0 -141
- package/app/sitemap.ts +0 -25
- package/app/skills/[name]/page.tsx +0 -192
- package/components/AsciiBackground.tsx +0 -207
- package/components/FaqAccordion.tsx +0 -45
- package/components/InstallBox.tsx +0 -43
- package/components/NpmDownloads.tsx +0 -43
- package/components/SkillContent.tsx +0 -103
- package/components/SkillsGrid.tsx +0 -132
- package/lib/skills.ts +0 -47
- package/next-env.d.ts +0 -5
- package/next.config.mjs +0 -7
- package/npm-package.json +0 -56
- package/postcss.config.mjs +0 -8
- package/public/favicon.ico +0 -0
- package/public/favicon.svg +0 -4
- package/public/install.sh +0 -111
- package/public/llms-full.txt +0 -1000
- package/public/llms.txt +0 -83
- package/public/og.png +0 -0
- package/public/robots.txt +0 -51
- package/public/skills.json +0 -2335
- package/skills-data/ab-testing/SKILL.md +0 -171
- package/skills-data/accounting-finance/SKILL.md +0 -139
- package/skills-data/affiliate-marketing/SKILL.md +0 -152
- package/skills-data/ai-agent-design/SKILL.md +0 -207
- package/skills-data/api-design/SKILL.md +0 -226
- package/skills-data/ascii-banner/SKILL.md +0 -317
- package/skills-data/bing-webmaster/SKILL.md +0 -130
- package/skills-data/blog-engine/SKILL.md +0 -91
- package/skills-data/brand-strategy/SKILL.md +0 -205
- package/skills-data/business-development/SKILL.md +0 -140
- package/skills-data/cicd-pipelines/SKILL.md +0 -232
- package/skills-data/cold-outreach/SKILL.md +0 -169
- package/skills-data/community-building/SKILL.md +0 -144
- package/skills-data/competitor-intelligence/SKILL.md +0 -145
- package/skills-data/content-strategy/SKILL.md +0 -85
- package/skills-data/copywriting/SKILL.md +0 -88
- package/skills-data/crm-builder/SKILL.md +0 -86
- package/skills-data/crm-operations/SKILL.md +0 -148
- package/skills-data/customer-acquisition/SKILL.md +0 -133
- package/skills-data/customer-feedback/SKILL.md +0 -140
- package/skills-data/data-analytics/SKILL.md +0 -203
- package/skills-data/data-management/SKILL.md +0 -199
- package/skills-data/database-design/SKILL.md +0 -158
- package/skills-data/email-sequence/SKILL.md +0 -81
- package/skills-data/eu-legal-compliance/SKILL.md +0 -156
- package/skills-data/git-workflow/SKILL.md +0 -200
- package/skills-data/google-analytics/SKILL.md +0 -188
- package/skills-data/growth-hacking/SKILL.md +0 -75
- package/skills-data/hiring-team-building/SKILL.md +0 -172
- package/skills-data/influencer-marketing/SKILL.md +0 -181
- package/skills-data/landing-page-builder/SKILL.md +0 -93
- package/skills-data/lead-scoring/SKILL.md +0 -64
- package/skills-data/local-seo/SKILL.md +0 -70
- package/skills-data/marketing-analytics/SKILL.md +0 -106
- package/skills-data/mvp-launcher/SKILL.md +0 -145
- package/skills-data/nextjs-stack/SKILL.md +0 -231
- package/skills-data/page-cro/SKILL.md +0 -80
- package/skills-data/paid-ads/SKILL.md +0 -110
- package/skills-data/popup-cro/SKILL.md +0 -52
- package/skills-data/pr-media-outreach/SKILL.md +0 -140
- package/skills-data/pricing-optimization/SKILL.md +0 -316
- package/skills-data/programmatic-seo/SKILL.md +0 -65
- package/skills-data/project-management/SKILL.md +0 -161
- package/skills-data/prompt-engineering/SKILL.md +0 -189
- package/skills-data/retention-analytics/SKILL.md +0 -161
- package/skills-data/revenue-operations/SKILL.md +0 -162
- package/skills-data/sales-funnel/SKILL.md +0 -56
- package/skills-data/search-console/SKILL.md +0 -159
- package/skills-data/security-hardening/SKILL.md +0 -176
- package/skills-data/seo-geo/SKILL.md +0 -138
- package/skills-data/signup-flow-cro/SKILL.md +0 -64
- package/skills-data/smart-contract-auditor/SKILL.md +0 -64
- package/skills-data/social-media-growth/SKILL.md +0 -146
- package/skills-data/social-media-kit/SKILL.md +0 -56
- package/skills-data/testing-strategy/SKILL.md +0 -344
- package/skills-data/ui-ux-pro-max/SKILL.md +0 -72
- package/skills-data/virustotal/SKILL.md +0 -108
- package/skills-data/web-performance/SKILL.md +0 -219
- package/skills-data/webinar-events/SKILL.md +0 -148
- package/skills-data/yandex-webmaster/SKILL.md +0 -159
- package/skills.json +0 -2335
- package/tailwind.config.ts +0 -45
- package/tsconfig.json +0 -26
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Commit Media SARL
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
#
|
|
1
|
+
# skills.ws
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Agent skills for AI coding assistants. 81 skills across 8 categories — built for OpenClaw, Claude Code, Cursor, Codex, and any agent that supports the SKILL.md format.
|
|
4
4
|
|
|
5
|
-
**Website:** [
|
|
6
|
-
**npm:** [npmjs.com/package/skills-ws](https://www.npmjs.com/package/skills-ws)
|
|
5
|
+
**Website:** [skills.ws](https://skills.ws) | **npm:** [skills-ws](https://www.npmjs.com/package/skills-ws) | **Docs:** [llms-full.txt](https://skills.ws/llms-full.txt)
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
9
10
|
|
|
10
11
|
```bash
|
|
11
12
|
npx skills-ws install # interactive picker
|
|
@@ -14,32 +15,193 @@ npx skills-ws install all # install everything
|
|
|
14
15
|
npx skills-ws list # list available skills
|
|
15
16
|
```
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
Skills are `SKILL.md` files that give AI coding assistants specialized knowledge — workflows, checklists, code patterns, and domain expertise. Install a skill and your agent gains expert-level capability in that domain.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Skills (81 across 8 categories)
|
|
23
|
+
|
|
24
|
+
### Marketing (15)
|
|
25
|
+
SEO/GEO, content strategy, copywriting, paid ads, email sequences, PR/media, influencer marketing, brand strategy, webinars, blog engine, and more.
|
|
26
|
+
|
|
27
|
+
### Dev (16)
|
|
28
|
+
Git workflow, CI/CD, API design, database design, testing, web performance, security hardening, prompt engineering, AI agent design, MVP launcher, Next.js stack.
|
|
29
|
+
|
|
30
|
+
### Growth (10)
|
|
31
|
+
Social media, community building, customer feedback, business development, cold outreach, competitor intelligence, affiliate marketing.
|
|
32
|
+
|
|
33
|
+
### Operations (11)
|
|
34
|
+
EU legal compliance (GDPR, AI Act, DSA), hiring/team building, project management, CRM, accounting, revenue ops.
|
|
18
35
|
|
|
19
|
-
|
|
36
|
+
### Conversion (8)
|
|
37
|
+
Landing pages, signup flows, popups, A/B testing, pricing optimization, lead scoring, CRO, sales funnels.
|
|
20
38
|
|
|
21
|
-
|
|
39
|
+
### Analytics (7)
|
|
40
|
+
Google Analytics, Search Console, Bing/Yandex Webmaster, data analytics, retention analytics.
|
|
22
41
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
### Web3 (6)
|
|
43
|
+
Blockchain deployment, Aleph Cloud, decentralized infrastructure.
|
|
44
|
+
|
|
45
|
+
### Design (4)
|
|
46
|
+
UI/UX Pro Max, landing page builder, ASCII banner.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## How Skills Work
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
┌─────────────────────────────────────────┐
|
|
54
|
+
│ AI Coding Assistant │
|
|
55
|
+
│ (OpenClaw, Claude Code, Cursor, Codex) │
|
|
56
|
+
│ │
|
|
57
|
+
│ ┌───────────────────────────────────┐ │
|
|
58
|
+
│ │ SKILL.md files │ │
|
|
59
|
+
│ │ Loaded into agent context on │ │
|
|
60
|
+
│ │ startup — gives the agent │ │
|
|
61
|
+
│ │ domain expertise, workflows, │ │
|
|
62
|
+
│ │ checklists, and code patterns │ │
|
|
63
|
+
│ └───────────────────────────────────┘ │
|
|
64
|
+
└─────────────────────────────────────────┘
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
1. You install a skill via `npx skills-ws install <name>`
|
|
68
|
+
2. A `SKILL.md` file is placed in your agent's skills directory
|
|
69
|
+
3. Your AI assistant reads it on startup and gains that expertise
|
|
70
|
+
4. Ask your assistant to do anything related to that domain — it now knows the best practices, patterns, and workflows
|
|
71
|
+
|
|
72
|
+
Skills are **markdown only** — no executable code, no runtime dependencies, no supply chain risk.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## CLI Reference
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
# Interactive mode — browse and select skills
|
|
80
|
+
npx skills-ws install
|
|
81
|
+
|
|
82
|
+
# Install a specific skill
|
|
83
|
+
npx skills-ws install seo-geo
|
|
84
|
+
|
|
85
|
+
# Install multiple skills
|
|
86
|
+
npx skills-ws install seo-geo copywriting ab-testing
|
|
87
|
+
|
|
88
|
+
# Install all skills
|
|
89
|
+
npx skills-ws install all
|
|
90
|
+
|
|
91
|
+
# List available skills with categories
|
|
92
|
+
npx skills-ws list
|
|
93
|
+
|
|
94
|
+
# Install to a custom directory
|
|
95
|
+
npx skills-ws install seo-geo --dir ./my-agent/skills
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The CLI auto-detects your agent type (OpenClaw, Claude Code, Cursor, Codex) and installs to the correct directory.
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Website Features
|
|
103
|
+
|
|
104
|
+
The [skills.ws](https://skills.ws) website provides:
|
|
105
|
+
|
|
106
|
+
- **Searchable skill grid** — filter by category, search by name
|
|
107
|
+
- **Individual skill pages** — full SKILL.md content rendered as Markdown
|
|
108
|
+
- **One-click install commands** — copy `npx` command to clipboard
|
|
109
|
+
- **Live npm download counter** — monthly download stats
|
|
110
|
+
- **VirusTotal scan status** — every skill file is scanned
|
|
111
|
+
|
|
112
|
+
### Keyboard Shortcuts
|
|
113
|
+
|
|
114
|
+
| Key | Action |
|
|
115
|
+
|-----|--------|
|
|
116
|
+
| `/` | Focus search |
|
|
117
|
+
| `Esc` | Clear search |
|
|
118
|
+
|
|
119
|
+
---
|
|
31
120
|
|
|
32
121
|
## Development
|
|
33
122
|
|
|
34
123
|
```bash
|
|
124
|
+
git clone https://github.com/san-npm/skills-ws.git
|
|
125
|
+
cd skills-ws
|
|
35
126
|
npm install
|
|
36
127
|
npm run dev # http://localhost:3000
|
|
37
128
|
npm run build # static export to out/
|
|
129
|
+
npm run lint # ESLint + Next.js linter
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Stack
|
|
133
|
+
|
|
134
|
+
- **Next.js 14** — static export (SSG), App Router
|
|
135
|
+
- **React 18** + TypeScript 5
|
|
136
|
+
- **Tailwind CSS 3.4** — dark theme
|
|
137
|
+
- **Three.js** — WebGL ASCII art background (homepage)
|
|
138
|
+
- **react-markdown** + remark-gfm — SKILL.md rendering
|
|
139
|
+
|
|
140
|
+
### Project Structure
|
|
141
|
+
|
|
142
|
+
```
|
|
143
|
+
skills-ws/
|
|
144
|
+
├── app/ # Next.js App Router
|
|
145
|
+
│ ├── page.tsx # Homepage — ASCII hero, skill grid, stats
|
|
146
|
+
│ ├── skills/[name]/ # Dynamic skill detail pages (SSG)
|
|
147
|
+
│ ├── docs/ # How agent skills work
|
|
148
|
+
│ ├── cli/ # CLI reference
|
|
149
|
+
│ ├── faq/ # FAQ with accordion
|
|
150
|
+
│ └── sitemap.ts # Dynamic XML sitemap
|
|
151
|
+
├── components/ # React components
|
|
152
|
+
│ ├── AsciiBackground.tsx # Three.js WebGL → ASCII canvas
|
|
153
|
+
│ ├── SkillsGrid.tsx # Searchable/filterable skill grid
|
|
154
|
+
│ ├── SkillContent.tsx # Markdown renderer
|
|
155
|
+
│ ├── InstallBox.tsx # Copy-to-clipboard install command
|
|
156
|
+
│ └── NpmDownloads.tsx # Live npm download counter
|
|
157
|
+
├── lib/
|
|
158
|
+
│ └── skills.ts # Skill data access + TypeScript interfaces
|
|
159
|
+
├── skills/ # Raw SKILL.md files (81 directories)
|
|
160
|
+
├── public/
|
|
161
|
+
│ ├── skills.json # Skills database (81 skills, all metadata + content)
|
|
162
|
+
│ ├── llms.txt # LLM-readable skill index
|
|
163
|
+
│ ├── llms-full.txt # Full content dump for LLMs
|
|
164
|
+
│ ├── robots.txt # Crawl directives
|
|
165
|
+
│ └── install.sh # Bash installer script
|
|
166
|
+
└── skills.json # Master skills database
|
|
38
167
|
```
|
|
39
168
|
|
|
169
|
+
### Build Output
|
|
170
|
+
|
|
171
|
+
Static export generates ~85 pages:
|
|
172
|
+
- Homepage + docs + CLI + FAQ + 404
|
|
173
|
+
- 81 individual skill detail pages
|
|
174
|
+
- XML sitemap
|
|
175
|
+
|
|
176
|
+
No server needed — deploy to any static host (Vercel, Netlify, GitHub Pages, S3).
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## SEO & Structured Data
|
|
181
|
+
|
|
182
|
+
- Dynamic XML sitemap with all skill pages
|
|
183
|
+
- OpenGraph + Twitter Card meta tags
|
|
184
|
+
- JSON-LD schemas: Organization, WebSite, SoftwareApplication, BreadcrumbList, FAQPage
|
|
185
|
+
- Google Analytics 4 integration
|
|
186
|
+
- `llms.txt` + `llms-full.txt` for AI crawlers
|
|
187
|
+
- `robots.txt` with sitemap reference
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
40
191
|
## Security
|
|
41
192
|
|
|
42
|
-
|
|
193
|
+
Skills are **markdown files only** — no executable code.
|
|
194
|
+
|
|
195
|
+
- Zero runtime dependencies (no supply chain risk)
|
|
196
|
+
- No `eval()`, `exec()`, or `child_process` patterns
|
|
197
|
+
- All skills built in-house, no third-party content
|
|
198
|
+
- VirusTotal scanning on all skill files
|
|
199
|
+
- Environment-only credentials (nothing hardcoded)
|
|
200
|
+
- npm package published with Sigstore provenance attestation
|
|
201
|
+
|
|
202
|
+
See [SECURITY.md](SECURITY.md) for vulnerability reporting.
|
|
203
|
+
|
|
204
|
+
---
|
|
43
205
|
|
|
44
206
|
## License
|
|
45
207
|
|
package/bin/cli.mjs
CHANGED
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { readdir, readFile, copyFile, mkdir, stat } from "node:fs/promises";
|
|
4
4
|
import { join, dirname } from "node:path";
|
|
5
|
-
import { createInterface } from "node:readline";
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
7
5
|
import readline from "node:readline";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
8
7
|
|
|
9
8
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
10
9
|
const SKILLS_DIR = join(__dirname, "..", "skills");
|
|
@@ -266,142 +265,121 @@ async function detectTarget() {
|
|
|
266
265
|
return defaultTarget;
|
|
267
266
|
}
|
|
268
267
|
|
|
269
|
-
// ──
|
|
270
|
-
|
|
271
|
-
async function main() {
|
|
272
|
-
const args = process.argv.slice(2);
|
|
273
|
-
const skills = await getSkills();
|
|
274
|
-
|
|
275
|
-
await playBanner();
|
|
268
|
+
// ── Interactive Picker ───────────────────────────────────────
|
|
276
269
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
return;
|
|
270
|
+
async function interactivePick(skills) {
|
|
271
|
+
for (let i = 0; i < skills.length; i++) {
|
|
272
|
+
process.stdout.write(
|
|
273
|
+
` ${GRAY}${String(i + 1).padStart(2)}${R} ${GREEN}${skills[i].name.padEnd(24)}${R}${DIM}${skills[i].desc.slice(0, 50)}${R}\n`
|
|
274
|
+
);
|
|
283
275
|
}
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
rl.close();
|
|
299
|
-
|
|
300
|
-
if (answer.trim().toLowerCase() === "all") {
|
|
301
|
-
names.push(...skills.map((s) => s.name));
|
|
302
|
-
} else {
|
|
303
|
-
for (const part of answer.split(",").map((s) => s.trim()).filter(Boolean)) {
|
|
304
|
-
const num = parseInt(part);
|
|
305
|
-
if (!isNaN(num) && num >= 1 && num <= skills.length) names.push(skills[num - 1].name);
|
|
306
|
-
else names.push(part);
|
|
307
|
-
}
|
|
308
|
-
}
|
|
276
|
+
process.stdout.write(`\n ${YELLOW}Enter numbers or names (comma-separated), or 'all':${R}\n`);
|
|
277
|
+
|
|
278
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
279
|
+
const answer = await new Promise((resolve) => rl.question(` ${CYAN}> ${R}`, resolve));
|
|
280
|
+
rl.close();
|
|
281
|
+
|
|
282
|
+
const names = [];
|
|
283
|
+
if (answer.trim().toLowerCase() === "all") {
|
|
284
|
+
names.push(...skills.map((s) => s.name));
|
|
285
|
+
} else {
|
|
286
|
+
for (const part of answer.split(",").map((s) => s.trim()).filter(Boolean)) {
|
|
287
|
+
const num = parseInt(part);
|
|
288
|
+
if (!isNaN(num) && num >= 1 && num <= skills.length) names.push(skills[num - 1].name);
|
|
289
|
+
else names.push(part);
|
|
309
290
|
}
|
|
291
|
+
}
|
|
292
|
+
return names;
|
|
293
|
+
}
|
|
310
294
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
295
|
+
async function installSkills(names, skills, customDir) {
|
|
296
|
+
if (names.length === 0) {
|
|
297
|
+
process.stdout.write(` ${DIM}Nothing selected.${R}\n`);
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
315
300
|
|
|
316
|
-
|
|
317
|
-
|
|
301
|
+
const target = customDir || await detectTarget();
|
|
302
|
+
process.stdout.write(`\n ${DIM}${target}${R}\n\n`);
|
|
318
303
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
await copyDir(skill.dir, join(target, name));
|
|
327
|
-
installed++;
|
|
304
|
+
let installed = 0;
|
|
305
|
+
for (const name of names) {
|
|
306
|
+
const skill = skills.find((s) => s.name === name);
|
|
307
|
+
if (!skill) {
|
|
308
|
+
process.stdout.write(` ${YELLOW}skip${R} ${name} ${DIM}(not found)${R}\n`);
|
|
309
|
+
continue;
|
|
328
310
|
}
|
|
311
|
+
await copyDir(skill.dir, join(target, name));
|
|
312
|
+
installed++;
|
|
313
|
+
}
|
|
329
314
|
|
|
330
|
-
|
|
331
|
-
|
|
315
|
+
await playInstallProgress(installed);
|
|
316
|
+
process.stdout.write("\n");
|
|
332
317
|
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
318
|
+
for (const name of names) {
|
|
319
|
+
if (skills.find((s) => s.name === name)) {
|
|
320
|
+
process.stdout.write(` ${GREEN}+${R} ${name}\n`);
|
|
337
321
|
}
|
|
338
|
-
process.stdout.write(`\n ${DIM}skills.ws${R}\n\n`);
|
|
339
|
-
return;
|
|
340
322
|
}
|
|
323
|
+
process.stdout.write(`\n ${DIM}skills.ws${R}\n\n`);
|
|
324
|
+
}
|
|
341
325
|
|
|
342
|
-
|
|
343
|
-
if (!args[0] || args[0] === "help" || args[0] === "-h" || args[0] === "--help") {
|
|
344
|
-
if (args[0] === "help" || args[0] === "-h" || args[0] === "--help") {
|
|
345
|
-
process.stdout.write(` ${B}Usage:${R}\n\n`);
|
|
346
|
-
process.stdout.write(` ${CYAN}npx skills-ws${R} Interactive picker\n`);
|
|
347
|
-
process.stdout.write(` ${CYAN}npx skills-ws list${R} List all skills\n`);
|
|
348
|
-
process.stdout.write(` ${CYAN}npx skills-ws install <name>${R} Install specific skill(s)\n`);
|
|
349
|
-
process.stdout.write(` ${CYAN}npx skills-ws install all${R} Install everything\n`);
|
|
350
|
-
process.stdout.write(`\n ${DIM}${skills.length} skills | skills.ws${R}\n\n`);
|
|
351
|
-
return;
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Interactive picker
|
|
355
|
-
for (let i = 0; i < skills.length; i++) {
|
|
356
|
-
process.stdout.write(
|
|
357
|
-
` ${GRAY}${String(i + 1).padStart(2)}${R} ${GREEN}${skills[i].name.padEnd(24)}${R}${DIM}${skills[i].desc.slice(0, 50)}${R}\n`
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
process.stdout.write(`\n ${YELLOW}Enter numbers or names (comma-separated), or 'all':${R}\n`);
|
|
326
|
+
// ── Main ─────────────────────────────────────────────────────
|
|
361
327
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
328
|
+
async function main() {
|
|
329
|
+
const rawArgs = process.argv.slice(2);
|
|
330
|
+
const skills = await getSkills();
|
|
365
331
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
332
|
+
// Parse --dir flag from anywhere in args
|
|
333
|
+
let customDir = null;
|
|
334
|
+
const args = [];
|
|
335
|
+
for (let i = 0; i < rawArgs.length; i++) {
|
|
336
|
+
if (rawArgs[i] === "--dir" && i + 1 < rawArgs.length) {
|
|
337
|
+
customDir = rawArgs[i + 1];
|
|
338
|
+
i++; // skip next
|
|
369
339
|
} else {
|
|
370
|
-
|
|
371
|
-
const num = parseInt(part);
|
|
372
|
-
if (!isNaN(num) && num >= 1 && num <= skills.length) names.push(skills[num - 1].name);
|
|
373
|
-
else names.push(part);
|
|
374
|
-
}
|
|
340
|
+
args.push(rawArgs[i]);
|
|
375
341
|
}
|
|
342
|
+
}
|
|
376
343
|
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
344
|
+
await playBanner();
|
|
345
|
+
|
|
346
|
+
if (args[0] === "list" || args[0] === "ls") {
|
|
347
|
+
for (const s of skills) {
|
|
348
|
+
process.stdout.write(` ${GREEN}${s.name.padEnd(24)}${R}${DIM}${s.desc.slice(0, 55)}${R}\n`);
|
|
380
349
|
}
|
|
350
|
+
process.stdout.write(`\n ${DIM}${skills.length} skills | npx skills-ws install <name>${R}\n\n`);
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
381
353
|
|
|
382
|
-
|
|
383
|
-
|
|
354
|
+
if (args[0] === "install" || args[0] === "add") {
|
|
355
|
+
let names = args.slice(1);
|
|
384
356
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
continue;
|
|
391
|
-
}
|
|
392
|
-
await copyDir(skill.dir, join(target, name));
|
|
393
|
-
installed++;
|
|
357
|
+
// Handle "all" keyword
|
|
358
|
+
if (names.includes("all")) {
|
|
359
|
+
names = skills.map((s) => s.name);
|
|
360
|
+
} else if (names.length === 0) {
|
|
361
|
+
names = await interactivePick(skills);
|
|
394
362
|
}
|
|
395
363
|
|
|
396
|
-
await
|
|
397
|
-
|
|
364
|
+
await installSkills(names, skills, customDir);
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
398
367
|
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}
|
|
404
|
-
process.stdout.write(
|
|
368
|
+
if (args[0] === "help" || args[0] === "-h" || args[0] === "--help") {
|
|
369
|
+
process.stdout.write(` ${B}Usage:${R}\n\n`);
|
|
370
|
+
process.stdout.write(` ${CYAN}npx skills-ws${R} Interactive picker\n`);
|
|
371
|
+
process.stdout.write(` ${CYAN}npx skills-ws list${R} List all skills\n`);
|
|
372
|
+
process.stdout.write(` ${CYAN}npx skills-ws install <name>${R} Install specific skill(s)\n`);
|
|
373
|
+
process.stdout.write(` ${CYAN}npx skills-ws install all${R} Install everything\n`);
|
|
374
|
+
process.stdout.write(` ${CYAN}npx skills-ws install --dir .${R} Install to custom directory\n`);
|
|
375
|
+
process.stdout.write(`\n ${DIM}${skills.length} skills | skills.ws${R}\n\n`);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// No args = interactive install
|
|
380
|
+
if (!args[0]) {
|
|
381
|
+
const names = await interactivePick(skills);
|
|
382
|
+
await installSkills(names, skills, customDir);
|
|
405
383
|
return;
|
|
406
384
|
}
|
|
407
385
|
}
|
package/package.json
CHANGED
|
@@ -1,33 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "skills-ws",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"
|
|
5
|
-
"dev": "next dev",
|
|
6
|
-
"build": "next build",
|
|
7
|
-
"start": "next start",
|
|
8
|
-
"lint": "next lint"
|
|
9
|
-
},
|
|
10
|
-
"dependencies": {
|
|
11
|
-
"@vercel/analytics": "^1.6.1",
|
|
12
|
-
"next": "14.2.35",
|
|
13
|
-
"react": "^18",
|
|
14
|
-
"react-dom": "^18",
|
|
15
|
-
"react-markdown": "^10.1.0",
|
|
16
|
-
"remark-gfm": "^4.0.1",
|
|
17
|
-
"three": "^0.183.1"
|
|
18
|
-
},
|
|
19
|
-
"devDependencies": {
|
|
20
|
-
"@types/node": "^20",
|
|
21
|
-
"@types/react": "^18",
|
|
22
|
-
"@types/react-dom": "^18",
|
|
23
|
-
"@types/three": "^0.183.1",
|
|
24
|
-
"postcss": "^8",
|
|
25
|
-
"tailwindcss": "^3.4.1",
|
|
26
|
-
"typescript": "^5"
|
|
27
|
-
},
|
|
28
|
-
"description": "77 expert agent skills for AI coding assistants — marketing, growth, web3, dev, design & operations. Built for OpenClaw, Claude Code, Cursor, and Codex.",
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "81 agent skills for AI coding assistants \u2014 marketing, growth, web3, dev, design & operations. Built for OpenClaw, Claude Code, Cursor, and Codex.",
|
|
29
5
|
"bin": {
|
|
30
|
-
"skills-ws": "bin/cli.mjs"
|
|
6
|
+
"skills-ws": "./bin/cli.mjs"
|
|
31
7
|
},
|
|
32
8
|
"keywords": [
|
|
33
9
|
"ai",
|
|
@@ -57,11 +33,24 @@
|
|
|
57
33
|
"design-system",
|
|
58
34
|
"auth"
|
|
59
35
|
],
|
|
36
|
+
"author": "Commit Media <bob@openletz.com> (https://openletz.com)",
|
|
60
37
|
"license": "MIT",
|
|
61
38
|
"repository": {
|
|
62
39
|
"type": "git",
|
|
63
40
|
"url": "https://github.com/san-npm/skills-ws"
|
|
64
41
|
},
|
|
65
42
|
"homepage": "https://skills.ws",
|
|
66
|
-
"
|
|
67
|
-
|
|
43
|
+
"bugs": {
|
|
44
|
+
"url": "https://github.com/san-npm/skills-ws/issues"
|
|
45
|
+
},
|
|
46
|
+
"files": [
|
|
47
|
+
"bin/",
|
|
48
|
+
"skills/",
|
|
49
|
+
"README.md",
|
|
50
|
+
"LICENSE",
|
|
51
|
+
"SECURITY.md"
|
|
52
|
+
],
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=18"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -24,7 +24,7 @@ LangGraph is the production-grade choice for complex agents. It gives you explic
|
|
|
24
24
|
### Basic Agent with Tool Calling
|
|
25
25
|
|
|
26
26
|
```python
|
|
27
|
-
# pip install langgraph langchain-openai
|
|
27
|
+
# pip install langgraph langchain-openai langgraph-checkpoint-sqlite
|
|
28
28
|
from typing import Annotated, TypedDict
|
|
29
29
|
from langgraph.graph import StateGraph, START, END
|
|
30
30
|
from langgraph.graph.message import add_messages
|
|
@@ -306,8 +306,8 @@ def with_retry(max_retries: int = 3):
|
|
|
306
306
|
return decorator
|
|
307
307
|
|
|
308
308
|
@tool
|
|
309
|
-
@with_timeout(30)
|
|
310
309
|
@with_retry(3)
|
|
310
|
+
@with_timeout(30)
|
|
311
311
|
async def query_database(sql: str) -> str:
|
|
312
312
|
"""Execute a read-only SQL query against the analytics database.
|
|
313
313
|
|
|
@@ -659,23 +659,25 @@ def sanitize_user_input(text: str) -> str:
|
|
|
659
659
|
### Output Validation
|
|
660
660
|
|
|
661
661
|
```python
|
|
662
|
-
from pydantic import BaseModel,
|
|
662
|
+
from pydantic import BaseModel, field_validator
|
|
663
663
|
|
|
664
664
|
class AgentResponse(BaseModel):
|
|
665
665
|
answer: str
|
|
666
666
|
sources: list[str]
|
|
667
667
|
confidence: float
|
|
668
668
|
|
|
669
|
-
@
|
|
670
|
-
|
|
669
|
+
@field_validator("answer")
|
|
670
|
+
@classmethod
|
|
671
|
+
def no_system_leaks(cls, v: str) -> str:
|
|
671
672
|
forbidden = ["system prompt", "you are an AI", "as an AI language model"]
|
|
672
673
|
for phrase in forbidden:
|
|
673
674
|
if phrase.lower() in v.lower():
|
|
674
675
|
raise ValueError("Response contained forbidden content")
|
|
675
676
|
return v
|
|
676
677
|
|
|
677
|
-
@
|
|
678
|
-
|
|
678
|
+
@field_validator("confidence")
|
|
679
|
+
@classmethod
|
|
680
|
+
def valid_range(cls, v: float) -> float:
|
|
679
681
|
if not 0 <= v <= 1:
|
|
680
682
|
raise ValueError("Confidence must be between 0 and 1")
|
|
681
683
|
return v
|
|
@@ -783,7 +785,7 @@ MCP is the standard for connecting agents to external tools. Instead of hardcodi
|
|
|
783
785
|
```typescript
|
|
784
786
|
// mcp-server.ts — expose tools for any MCP-compatible agent
|
|
785
787
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
786
|
-
import {
|
|
788
|
+
import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
|
|
787
789
|
import express from 'express';
|
|
788
790
|
|
|
789
791
|
const server = new McpServer({ name: 'my-tools', version: '1.0.0' });
|
|
@@ -814,20 +816,16 @@ server.tool('create_ticket', 'Create a support ticket in Jira', {
|
|
|
814
816
|
};
|
|
815
817
|
});
|
|
816
818
|
|
|
817
|
-
//
|
|
819
|
+
// Streamable HTTP transport (replaces deprecated SSE transport)
|
|
818
820
|
const app = express();
|
|
819
|
-
|
|
821
|
+
app.use(express.json());
|
|
820
822
|
|
|
821
|
-
app.
|
|
822
|
-
const transport = new
|
|
823
|
-
|
|
824
|
-
|
|
823
|
+
app.post('/mcp', async (req, res) => {
|
|
824
|
+
const transport = new StreamableHTTPServerTransport({
|
|
825
|
+
sessionIdGenerator: undefined, // stateless
|
|
826
|
+
});
|
|
825
827
|
await server.connect(transport);
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
app.post('/mcp/messages', async (req, res) => {
|
|
829
|
-
const sessionId = req.query.sessionId as string;
|
|
830
|
-
await transports[sessionId]?.handlePostMessage(req, res);
|
|
828
|
+
await transport.handleRequest(req, res);
|
|
831
829
|
});
|
|
832
830
|
|
|
833
831
|
app.listen(3100, () => console.log('MCP server on :3100'));
|