@noobdemon/noob-cli 1.7.4 → 1.7.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -1
- package/skills/frontend-design/SKILL.md +42 -0
- package/src/i18n.js +6 -0
- package/src/repl.js +47 -0
- package/src/skills.js +68 -0
package/package.json
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-design
|
|
3
|
+
description: Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.
|
|
4
|
+
license: Complete terms in LICENSE.txt
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
This skill guides creation of distinctive, production-grade frontend interfaces that avoid generic "AI slop" aesthetics. Implement real working code with exceptional attention to aesthetic details and creative choices.
|
|
8
|
+
|
|
9
|
+
The user provides frontend requirements: a component, page, application, or interface to build. They may include context about the purpose, audience, or technical constraints.
|
|
10
|
+
|
|
11
|
+
## Design Thinking
|
|
12
|
+
|
|
13
|
+
Before coding, understand the context and commit to a BOLD aesthetic direction:
|
|
14
|
+
- **Purpose**: What problem does this interface solve? Who uses it?
|
|
15
|
+
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
|
16
|
+
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
|
17
|
+
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
|
18
|
+
|
|
19
|
+
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.
|
|
20
|
+
|
|
21
|
+
Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:
|
|
22
|
+
- Production-grade and functional
|
|
23
|
+
- Visually striking and memorable
|
|
24
|
+
- Cohesive with a clear aesthetic point-of-view
|
|
25
|
+
- Meticulously refined in every detail
|
|
26
|
+
|
|
27
|
+
## Frontend Aesthetics Guidelines
|
|
28
|
+
|
|
29
|
+
Focus on:
|
|
30
|
+
- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
|
|
31
|
+
- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
|
32
|
+
- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
|
|
33
|
+
- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
|
|
34
|
+
- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.
|
|
35
|
+
|
|
36
|
+
NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.
|
|
37
|
+
|
|
38
|
+
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.
|
|
39
|
+
|
|
40
|
+
**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.
|
|
41
|
+
|
|
42
|
+
Remember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
package/src/i18n.js
CHANGED
|
@@ -62,6 +62,8 @@ export const t = {
|
|
|
62
62
|
cmdAutoYolo: "/auto-yolo lưu/bỏ yolo làm mặc định mỗi lần chạy (cần xác nhận)",
|
|
63
63
|
cmdInit: "/init quét dự án & tạo noob.md (tổng quan + quy ước, như Claude Code)",
|
|
64
64
|
cmdKarpathy: "/karpathy [path] rà soát code theo 4 nguyên tắc Karpathy (/kc)",
|
|
65
|
+
cmdFrontendDesign: "/frontend-design <yêu cầu> thiết kế UI frontend chất lượng cao theo skill (/fd)",
|
|
66
|
+
cmdImprove: "/improve [hint] phân tích workspace & đề xuất tính năng cải thiện (/imp)",
|
|
65
67
|
cmdUltra: "/ultra <mục tiêu> tự hành: noob tự nghĩ & tự làm nhiệm vụ tới khi xong (/u)",
|
|
66
68
|
cmdLearn: "/learn [ghi chú] chưng cất bài học của phiên vào noob.md",
|
|
67
69
|
cmdCompact: "/compact tóm tắt phiên ngay để gọn ngữ cảnh (giữ trí nhớ dài hạn)",
|
|
@@ -123,6 +125,10 @@ export const t = {
|
|
|
123
125
|
autoCompactDone: (bK, aK, pct) => `✓ Auto-compact: ${bK}k → ${aK}k chars (giảm ${pct}%). Trí nhớ dài hạn đã giữ lại trong session_summary.`,
|
|
124
126
|
autoCompactFail: "Auto-compact thất bại — bạn nên /clear hoặc /compact thủ công.",
|
|
125
127
|
initRunning: "đang quét dự án & soạn noob.md…",
|
|
128
|
+
frontendDesignRunning: "đang vận dụng skill frontend-design…",
|
|
129
|
+
improveRunning: "đang khảo sát workspace & soạn đề xuất cải thiện…",
|
|
130
|
+
frontendDesignNoSkill: "không tìm thấy skills/frontend-design/SKILL.md — skill chưa được cài.",
|
|
131
|
+
frontendDesignNeedReq: "cần mô tả yêu cầu. Ví dụ: /frontend-design landing page cho app nghe nhạc lo-fi",
|
|
126
132
|
initOverwriteWarn: (p) => `⚠ Đã có noob.md tại ${p}. /init sẽ ghi đè nội dung hiện tại.`,
|
|
127
133
|
initOverwriteConfirm: "Ghi đè? gõ 'y' để xác nhận, phím khác để huỷ › ",
|
|
128
134
|
initCancel: "Huỷ /init — giữ nguyên noob.md.",
|
package/src/repl.js
CHANGED
|
@@ -15,6 +15,7 @@ import { loadMemory, memoryPath } from "./memory.js";
|
|
|
15
15
|
import { t } from "./i18n.js";
|
|
16
16
|
import { checkLatest, runUpdate, CURRENT } from "./update.js";
|
|
17
17
|
import * as sessions from "./sessions.js";
|
|
18
|
+
import { loadSkill, listSkills } from "./skills.js";
|
|
18
19
|
|
|
19
20
|
// Lệnh dùng cho autocomplete. Gõ "/l" → lọc các lệnh có "l" (login, logout,
|
|
20
21
|
// clear, models, yolo…); ↑/↓ chọn, Tab điền, Enter chạy mục đang sáng.
|
|
@@ -29,6 +30,8 @@ const SLASH = [
|
|
|
29
30
|
{ name: "/auto-yolo", desc: "lưu yolo làm mặc định (cần xác nhận)" },
|
|
30
31
|
{ name: "/init", desc: "quét dự án & tạo noob.md" },
|
|
31
32
|
{ name: "/karpathy", desc: "rà soát code (Karpathy)" },
|
|
33
|
+
{ name: "/frontend-design", desc: "thiết kế UI frontend chất lượng cao (skill)" },
|
|
34
|
+
{ name: "/improve", desc: "phân tích workspace & gợi ý tính năng cải thiện" },
|
|
32
35
|
{ name: "/ultra", desc: "tự hành: tự nghĩ & làm nhiệm vụ" },
|
|
33
36
|
{ name: "/agent", desc: "bật/tắt agent mode (spawn sub-agent)" },
|
|
34
37
|
{ name: "/tokens", desc: "xem số token đã dùng phiên này" },
|
|
@@ -332,6 +335,39 @@ export async function startRepl(opts = {}) {
|
|
|
332
335
|
}
|
|
333
336
|
const startFresh = () => (session = sessions.newSession({ cwd: process.cwd(), model: state.model.id }));
|
|
334
337
|
|
|
338
|
+
// /frontend-design <yêu cầu> — vận dụng skill frontend-design (skills/frontend-design/SKILL.md)
|
|
339
|
+
// để model tạo UI frontend chất lượng cao, tránh "AI slop" aesthetic.
|
|
340
|
+
async function runFrontendDesign(arg) {
|
|
341
|
+
if (!config.apiKey) return console.log(c.tool(" " + t.notLoggedIn));
|
|
342
|
+
if (!arg) return console.log(c.err(" " + t.frontendDesignNeedReq));
|
|
343
|
+
const skill = loadSkill("frontend-design");
|
|
344
|
+
if (!skill) return console.log(c.err(" " + t.frontendDesignNoSkill));
|
|
345
|
+
const prompt = `Bạn đang thực thi SKILL "frontend-design". Đọc kỹ hướng dẫn skill dưới đây và TUÂN THỦ khi xây dựng UI.
|
|
346
|
+
|
|
347
|
+
=== SKILL: frontend-design ===
|
|
348
|
+
${skill}
|
|
349
|
+
=== HẾT SKILL ===
|
|
350
|
+
|
|
351
|
+
YÊU CẦU NGƯỜI DÙNG:
|
|
352
|
+
${arg}
|
|
353
|
+
|
|
354
|
+
Thực thi: đọc/tạo file cần thiết bằng tool, viết code production-grade theo đúng tinh thần skill (typography đặc sắc, color/theme có cam kết, motion có chủ đích, layout bất ngờ, tránh AI slop). Báo cáo ngắn gọn các file đã tạo và lựa chọn thẩm mỹ chính.`;
|
|
355
|
+
console.log(c.tool(" 🎨 " + t.frontendDesignRunning));
|
|
356
|
+
await handle(prompt);
|
|
357
|
+
persist();
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// /improve [hint] — model rà soát workspace & đề xuất tính năng/cải tiến.
|
|
361
|
+
// KHÔNG sửa code, chỉ phân tích & đề xuất.
|
|
362
|
+
async function runImprove(arg) {
|
|
363
|
+
if (!config.apiKey) return console.log(c.tool(" " + t.notLoggedIn));
|
|
364
|
+
const focus = arg ? `\nNgười dùng nhấn mạnh: "${arg}". Ưu tiên theo hướng đó nhưng vẫn nêu gợi ý quan trọng khác.` : "";
|
|
365
|
+
const prompt = `Đóng vai senior engineer & product reviewer. KHẢO SÁT workspace hiện tại và đề xuất TÍNH NĂNG / CẢI TIẾN cho dự án.${focus}\n\nQUY TRÌNH (dùng tool, không nói suông):\n1. list_dir thư mục gốc để nắm cấu trúc.\n2. Đọc README.md, package.json, noob.md, CHANGELOG.md (nếu có) để hiểu mục đích & trạng thái.\n3. list_dir/glob các thư mục mã chính. KHÔNG đọc hết file — chỉ đủ để nắm kiến trúc.\n4. grep TODO/FIXME/HACK/XXX để biết chỗ tác giả đã ghi nhận.\n5. Ghi nhận thiếu test/lint/CI nếu có.\n\nSAU KHẢO SÁT, viết báo cáo Markdown TIẾNG VIỆT theo cấu trúc:\n\n## Tóm tắt dự án\n2–4 dòng: làm gì, tech gì, trạng thái.\n\n## Điểm mạnh hiện tại\n3–6 gạch đầu dòng.\n\n## Gợi ý cải thiện\n5–10 đề xuất, MỖI cái:\n### N. <Tên>\n- **Vấn đề/cơ hội:** quan sát cụ thể (kèm tên_file:dòng nếu được).\n- **Đề xuất:** mô tả tính năng/cải tiến.\n- **Lợi ích:** UX/hiệu năng/độ tin cậy/mở rộng.\n- **Công sức:** S (vài giờ) / M (1–2 ngày) / L (>2 ngày).\n- **Ưu tiên:** P0 / P1 / P2.\n\n## Đề xuất ưu tiên hàng đầu\n1–3 mục P0 nên làm trước, kèm lý do.\n\nQUY TẮC: bám observation từ code thật, KHÔNG gợi ý chung chung, thẳng thắn không nịnh, KHÔNG sửa code, KHÔNG ghi noob.md.`;
|
|
366
|
+
console.log(c.tool(" ✨ " + t.improveRunning));
|
|
367
|
+
await handle(prompt);
|
|
368
|
+
persist();
|
|
369
|
+
}
|
|
370
|
+
|
|
335
371
|
// /karpathy [path] — bắt noob tự rà soát code theo 4 nguyên tắc Karpathy.
|
|
336
372
|
// Không có path → soát các file đã đổi trong phiên (model thấy qua FILES CHANGED).
|
|
337
373
|
async function runKarpathy(arg) {
|
|
@@ -941,6 +977,15 @@ NGUYÊN TẮC:
|
|
|
941
977
|
case "kc":
|
|
942
978
|
await runKarpathy(arg);
|
|
943
979
|
break;
|
|
980
|
+
case "frontend-design":
|
|
981
|
+
case "frontend":
|
|
982
|
+
case "fd":
|
|
983
|
+
await runFrontendDesign(arg);
|
|
984
|
+
break;
|
|
985
|
+
case "improve":
|
|
986
|
+
case "imp":
|
|
987
|
+
await runImprove(arg);
|
|
988
|
+
break;
|
|
944
989
|
case "ultra":
|
|
945
990
|
case "u":
|
|
946
991
|
await runUltra(arg);
|
|
@@ -1216,6 +1261,8 @@ function printHelp() {
|
|
|
1216
1261
|
" " + t.cmdAutoYolo,
|
|
1217
1262
|
" " + t.cmdInit,
|
|
1218
1263
|
" " + t.cmdKarpathy,
|
|
1264
|
+
" " + t.cmdFrontendDesign,
|
|
1265
|
+
" " + t.cmdImprove,
|
|
1219
1266
|
" " + t.cmdUltra,
|
|
1220
1267
|
" " + t.cmdLearn,
|
|
1221
1268
|
" " + t.cmdCompact,
|
package/src/skills.js
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
// Quản lý skills: mỗi skill là một thư mục `skills/<name>/` chứa `SKILL.md`
|
|
2
|
+
// (theo quy ước Anthropic). Khi user gõ `/<skill-name>`, repl nạp nội dung
|
|
3
|
+
// SKILL.md đó như context bổ sung rồi giao việc cho agent.
|
|
4
|
+
//
|
|
5
|
+
// Resolve theo 2 tầng:
|
|
6
|
+
// 1) `<cwd>/skills/<name>/SKILL.md` — skill user tự viết trong project của họ
|
|
7
|
+
// (override được skill mặc định, để tinh chỉnh phong cách riêng).
|
|
8
|
+
// 2) `<noob-cli-package>/skills/<name>/SKILL.md` — skill đóng gói theo CLI,
|
|
9
|
+
// đảm bảo `npm i -g @noobdemon/noob-cli` xong là `/frontend-design` chạy
|
|
10
|
+
// được trên MỌI máy mà không cần clone repo.
|
|
11
|
+
//
|
|
12
|
+
// API tối giản — không over-engineer:
|
|
13
|
+
// loadSkill(name) -> string | null (nội dung SKILL.md, null nếu không có)
|
|
14
|
+
// listSkills() -> string[] (tên skill có sẵn, gộp 2 nguồn)
|
|
15
|
+
// skillPath(name) -> string | null (đường dẫn tuyệt đối SKILL.md đã resolve)
|
|
16
|
+
|
|
17
|
+
import fs from "node:fs";
|
|
18
|
+
import path from "node:path";
|
|
19
|
+
import { fileURLToPath } from "node:url";
|
|
20
|
+
|
|
21
|
+
// Thư mục `skills/` đi kèm package (cùng cấp với `src/`, `bin/`).
|
|
22
|
+
// `import.meta.url` -> .../noob-cli/src/skills.js => ../skills
|
|
23
|
+
const PACKAGE_SKILLS_DIR = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..", "skills");
|
|
24
|
+
|
|
25
|
+
function userSkillsDir() {
|
|
26
|
+
return path.join(process.cwd(), "skills");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function candidatePaths(name) {
|
|
30
|
+
return [
|
|
31
|
+
path.join(userSkillsDir(), name, "SKILL.md"), // user override trước
|
|
32
|
+
path.join(PACKAGE_SKILLS_DIR, name, "SKILL.md"), // built-in của CLI
|
|
33
|
+
];
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function skillPath(name) {
|
|
37
|
+
for (const p of candidatePaths(name)) {
|
|
38
|
+
if (fs.existsSync(p)) return p;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function loadSkill(name) {
|
|
44
|
+
try {
|
|
45
|
+
const p = skillPath(name);
|
|
46
|
+
if (!p) return null;
|
|
47
|
+
return fs.readFileSync(p, "utf8");
|
|
48
|
+
} catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function listIn(dir) {
|
|
54
|
+
try {
|
|
55
|
+
if (!fs.existsSync(dir)) return [];
|
|
56
|
+
return fs
|
|
57
|
+
.readdirSync(dir, { withFileTypes: true })
|
|
58
|
+
.filter((e) => e.isDirectory() && fs.existsSync(path.join(dir, e.name, "SKILL.md")))
|
|
59
|
+
.map((e) => e.name);
|
|
60
|
+
} catch {
|
|
61
|
+
return [];
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function listSkills() {
|
|
66
|
+
const merged = new Set([...listIn(userSkillsDir()), ...listIn(PACKAGE_SKILLS_DIR)]);
|
|
67
|
+
return [...merged].sort();
|
|
68
|
+
}
|