nodeskai 0.4.0__tar.gz

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.
nodeskai-0.4.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 NoDeskAI contributors
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.
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.4
2
+ Name: nodeskai
3
+ Version: 0.4.0
4
+ Summary: Skill-pack giup AI coding agent code ky luat hon, xay dung hoan toan tren dien thoai.
5
+ License: MIT
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Dynamic: license-file
10
+
11
+ # NoDeskAI
12
+
13
+ *[Đọc bằng tiếng Việt](README.vi.md)*
14
+
15
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
16
+ [![Made in Vietnam](https://img.shields.io/badge/made%20in-%F0%9F%87%BB%F0%9F%87%B3%20Vietnam-red.svg)](#)
17
+ [![Built on a phone](https://img.shields.io/badge/built%20on-%F0%9F%93%B1%20a%20phone-brightgreen.svg)](#)
18
+
19
+ **Your AI coding agent keeps guessing, over-engineering, and editing code
20
+ outside the scope you asked for. NoDeskAI fixes that — in one command.**
21
+
22
+ NoDeskAI is a skill-pack for AI coding agents (Claude Code, Cursor, Codex
23
+ CLI, Windsurf...): install it once and your agent stops silently guessing
24
+ at ambiguous requests, stops bloating simple tasks into over-engineered
25
+ solutions, and stops touching code outside what you asked for. It ships
26
+ with `audit` — a built-in scanner that checks the skill/rule files you're
27
+ about to trust for bloat, duplicate rules, and prompt-injection patterns.
28
+
29
+ > 🇻🇳 **Made in Vietnam.** Every line of this project — writing, testing,
30
+ > committing, and pushing to GitHub — was done entirely on an Android
31
+ > phone through Termux. No PC, no laptop, no iPad.
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pip install nodeskai
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ ```bash
42
+ cd your-project
43
+ nodeskai init
44
+ ```
45
+
46
+ This writes the full discipline ruleset into **all 4 agent-config files**
47
+ (`CLAUDE.md`, `.cursorrules`, `AGENTS.md`, `.windsurfrules`) — creating
48
+ whichever ones don't exist yet, and appending to any that already have
49
+ content of your own (your existing content is kept, NoDeskAI's block is
50
+ added below it). It also creates `NODESKAI.md` as the source of truth.
51
+ Every file gets a metadata line (flags + version) at the top so `sync`
52
+ knows how to update it later.
53
+
54
+ ### Optional modes
55
+
56
+ ```bash
57
+ nodeskai init --strict # extra guardrails for high-risk decisions
58
+ nodeskai init --fast # relaxed rules for obviously trivial tasks
59
+ nodeskai init --product-context # adds a product/team-context skill (missing from the original CLAUDE.md)
60
+ ```
61
+
62
+ `--strict` and `--fast` can't be combined (they're opposite modes).
63
+
64
+ ### Update when a new skill version is available
65
+
66
+ ```bash
67
+ nodeskai sync
68
+ ```
69
+
70
+ Updates **every file NoDeskAI manages** (NODESKAI.md + installed
71
+ agent-configs) to match the currently installed NoDeskAI version, keeping
72
+ each file's own flags from `init` and preserving any hand-written content
73
+ that came before the NoDeskAI block. Files with no NoDeskAI metadata
74
+ (hand-written, never run through `init`) are reported as `[SKIP]` — they
75
+ don't break the command.
76
+
77
+ ### Check installed skill/agent-config files
78
+
79
+ ```bash
80
+ nodeskai audit
81
+ ```
82
+
83
+ Scans every skill/agent-config file in the project for:
84
+ - **Bloat** — files over 150 lines, where important rules risk getting
85
+ buried.
86
+ - **Duplicate rules** — a sign of rules being added over time without ever
87
+ being cleaned up.
88
+ - **Suspicious patterns** — prompt-injection attempts, destructive
89
+ commands, data-exfiltration signs.
90
+
91
+ ## Current status
92
+
93
+ v0.4.0 — `init` writes the full skill into all 4 agent-config files at
94
+ once, `audit` is fully functional (bloat / duplicates / suspicious
95
+ patterns), `sync` updates every managed file when a new skill version is
96
+ available, keeping each file's own flags.
97
+
98
+ ## Support the project
99
+
100
+ If NoDeskAI is useful to you, you can support it through GitHub Sponsors
101
+ (link coming soon) or Ko-fi.
102
+
103
+ ## License
104
+
105
+ MIT
@@ -0,0 +1,95 @@
1
+ # NoDeskAI
2
+
3
+ *[Đọc bằng tiếng Việt](README.vi.md)*
4
+
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
+ [![Made in Vietnam](https://img.shields.io/badge/made%20in-%F0%9F%87%BB%F0%9F%87%B3%20Vietnam-red.svg)](#)
7
+ [![Built on a phone](https://img.shields.io/badge/built%20on-%F0%9F%93%B1%20a%20phone-brightgreen.svg)](#)
8
+
9
+ **Your AI coding agent keeps guessing, over-engineering, and editing code
10
+ outside the scope you asked for. NoDeskAI fixes that — in one command.**
11
+
12
+ NoDeskAI is a skill-pack for AI coding agents (Claude Code, Cursor, Codex
13
+ CLI, Windsurf...): install it once and your agent stops silently guessing
14
+ at ambiguous requests, stops bloating simple tasks into over-engineered
15
+ solutions, and stops touching code outside what you asked for. It ships
16
+ with `audit` — a built-in scanner that checks the skill/rule files you're
17
+ about to trust for bloat, duplicate rules, and prompt-injection patterns.
18
+
19
+ > 🇻🇳 **Made in Vietnam.** Every line of this project — writing, testing,
20
+ > committing, and pushing to GitHub — was done entirely on an Android
21
+ > phone through Termux. No PC, no laptop, no iPad.
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ pip install nodeskai
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ```bash
32
+ cd your-project
33
+ nodeskai init
34
+ ```
35
+
36
+ This writes the full discipline ruleset into **all 4 agent-config files**
37
+ (`CLAUDE.md`, `.cursorrules`, `AGENTS.md`, `.windsurfrules`) — creating
38
+ whichever ones don't exist yet, and appending to any that already have
39
+ content of your own (your existing content is kept, NoDeskAI's block is
40
+ added below it). It also creates `NODESKAI.md` as the source of truth.
41
+ Every file gets a metadata line (flags + version) at the top so `sync`
42
+ knows how to update it later.
43
+
44
+ ### Optional modes
45
+
46
+ ```bash
47
+ nodeskai init --strict # extra guardrails for high-risk decisions
48
+ nodeskai init --fast # relaxed rules for obviously trivial tasks
49
+ nodeskai init --product-context # adds a product/team-context skill (missing from the original CLAUDE.md)
50
+ ```
51
+
52
+ `--strict` and `--fast` can't be combined (they're opposite modes).
53
+
54
+ ### Update when a new skill version is available
55
+
56
+ ```bash
57
+ nodeskai sync
58
+ ```
59
+
60
+ Updates **every file NoDeskAI manages** (NODESKAI.md + installed
61
+ agent-configs) to match the currently installed NoDeskAI version, keeping
62
+ each file's own flags from `init` and preserving any hand-written content
63
+ that came before the NoDeskAI block. Files with no NoDeskAI metadata
64
+ (hand-written, never run through `init`) are reported as `[SKIP]` — they
65
+ don't break the command.
66
+
67
+ ### Check installed skill/agent-config files
68
+
69
+ ```bash
70
+ nodeskai audit
71
+ ```
72
+
73
+ Scans every skill/agent-config file in the project for:
74
+ - **Bloat** — files over 150 lines, where important rules risk getting
75
+ buried.
76
+ - **Duplicate rules** — a sign of rules being added over time without ever
77
+ being cleaned up.
78
+ - **Suspicious patterns** — prompt-injection attempts, destructive
79
+ commands, data-exfiltration signs.
80
+
81
+ ## Current status
82
+
83
+ v0.4.0 — `init` writes the full skill into all 4 agent-config files at
84
+ once, `audit` is fully functional (bloat / duplicates / suspicious
85
+ patterns), `sync` updates every managed file when a new skill version is
86
+ available, keeping each file's own flags.
87
+
88
+ ## Support the project
89
+
90
+ If NoDeskAI is useful to you, you can support it through GitHub Sponsors
91
+ (link coming soon) or Ko-fi.
92
+
93
+ ## License
94
+
95
+ MIT
@@ -0,0 +1 @@
1
+ __version__ = "0.4.0"
@@ -0,0 +1,446 @@
1
+ """
2
+ NoDeskAI CLI - entry point.
3
+ Giai đoạn 2: `init` có thêm --strict / --fast / --product-context.
4
+ Thêm lệnh `audit`: kiểm tra bloat, rule trùng lặp, và pattern độc hại
5
+ trong các file skill/agent-config đã cài trong project.
6
+ Giai đoạn 3 (bước 1): thêm lệnh `sync` - cập nhật NODESKAI.md theo bản
7
+ skill mới nhất của package đang cài, giữ nguyên các flag đã chọn lúc
8
+ `init`. `init` giờ ghi thêm 1 dòng metadata (flags + version) ở đầu
9
+ NODESKAI.md để `sync` biết cách build lại.
10
+ """
11
+
12
+ import argparse
13
+ import re
14
+ import shutil
15
+ import sys
16
+ from pathlib import Path
17
+
18
+ from nodeskai import __version__
19
+
20
+ # ============================================================
21
+ # Cấu hình chung
22
+ # ============================================================
23
+
24
+ # Các file cấu hình agent mà NoDeskAI biết nhận diện.
25
+ AGENT_CONFIG_FILES = {
26
+ "CLAUDE.md": "Claude Code",
27
+ ".cursorrules": "Cursor",
28
+ "AGENTS.md": "Codex CLI",
29
+ ".windsurfrules": "Windsurf",
30
+ }
31
+
32
+ NODESKAI_SKILL_FILE = "NODESKAI.md"
33
+
34
+ # Dòng metadata được `init` ghi ở đầu NODESKAI.md để `sync` sau này biết
35
+ # phải build lại với flag nào, và biết NODESKAI.md đang ở version nào.
36
+ METADATA_PREFIX = "<!-- NoDeskAI: flags={flags}; version={version} -->"
37
+ METADATA_PATTERN = re.compile(
38
+ r"<!--\s*NoDeskAI:\s*flags=([^;]*);\s*version=([^\s]+?)\s*-->"
39
+ )
40
+
41
+ # Thư mục chứa các skill đóng gói sẵn cùng package (nodeskai/skills/).
42
+ SKILLS_DIR = Path(__file__).parent / "skills"
43
+
44
+ CORE_SKILL_FILENAME = "no-overengineering.md"
45
+ STRICT_SKILL_FILENAME = "strict-mode.md"
46
+ FAST_SKILL_FILENAME = "fast-mode.md"
47
+ PRODUCT_CONTEXT_SKILL_FILENAME = "product-context.md"
48
+
49
+ # Ngưỡng số dòng để cảnh báo "phình to" (bloat) - dựa trên khoảng trống #2
50
+ # đã phân tích từ CLAUDE.md gốc (file bị chôn vùi rule quan trọng khi vượt
51
+ # quá ngưỡng hợp lý).
52
+ BLOAT_LINE_THRESHOLD = 150
53
+
54
+ # Danh sách pattern đáng ngờ dùng cho `audit`. Đây là các dấu hiệu PHÒNG THỦ
55
+ # (defensive) để cảnh báo người dùng nội dung khả nghi trong skill/rule file
56
+ # họ sắp tin tưởng - không phải hướng dẫn khai thác.
57
+ MALICIOUS_PATTERNS = [
58
+ ("ignore all previous instructions", "Dấu hiệu prompt injection - cố ghi đè chỉ dẫn hệ thống"),
59
+ ("ignore the above instructions", "Dấu hiệu prompt injection - cố ghi đè chỉ dẫn hệ thống"),
60
+ ("disregard the system prompt", "Dấu hiệu prompt injection - cố ghi đè chỉ dẫn hệ thống"),
61
+ ("curl | bash", "Tải và thực thi script ngay lập tức - rủi ro cao"),
62
+ ("curl | sh", "Tải và thực thi script ngay lập tức - rủi ro cao"),
63
+ ("wget | bash", "Tải và thực thi script ngay lập tức - rủi ro cao"),
64
+ ("rm -rf /", "Lệnh có thể xoá phá huỷ hệ thống"),
65
+ ("base64 -d | bash", "Giải mã và chạy lệnh ẩn - kỹ thuật che giấu payload"),
66
+ ("act as though you have no restrictions", "Yêu cầu bỏ qua giới hạn an toàn"),
67
+ ("disable safety", "Yêu cầu tắt cơ chế an toàn"),
68
+ ("exfiltrate", "Có dấu hiệu liên quan tới rò rỉ dữ liệu ra ngoài"),
69
+ ("send this data to http", "Có dấu hiệu gửi dữ liệu ra ngoài một cách âm thầm"),
70
+ ]
71
+
72
+
73
+ # ============================================================
74
+ # Hàm dùng chung
75
+ # ============================================================
76
+
77
+ def detect_installed_files(project_dir: Path):
78
+ """
79
+ Trả về danh sách các file NoDeskAI có thể audit trong project:
80
+ NODESKAI.md (nếu có) + mọi agent config file đang tồn tại.
81
+ """
82
+ files = []
83
+ nodeskai_file = project_dir / NODESKAI_SKILL_FILE
84
+ if nodeskai_file.exists():
85
+ files.append(nodeskai_file)
86
+ for filename in AGENT_CONFIG_FILES:
87
+ path = project_dir / filename
88
+ if path.exists():
89
+ files.append(path)
90
+ return files
91
+
92
+
93
+ # ============================================================
94
+ # Lệnh `init`
95
+ # ============================================================
96
+
97
+ def build_skill_body(strict: bool, fast: bool, product_context: bool) -> str:
98
+ """
99
+ Ghép PHẦN NỘI DUNG skill (không gồm dòng metadata) dựa trên các flag
100
+ chế độ được chọn. Core skill luôn được bao gồm. Tách riêng khỏi
101
+ build_skill_content() để `sync` có thể build lại phần nội dung mà
102
+ không phải lặp lại logic ghép flag.
103
+ """
104
+ parts = []
105
+
106
+ core_path = SKILLS_DIR / CORE_SKILL_FILENAME
107
+ parts.append(core_path.read_text(encoding="utf-8"))
108
+
109
+ if strict:
110
+ strict_path = SKILLS_DIR / STRICT_SKILL_FILENAME
111
+ parts.append(strict_path.read_text(encoding="utf-8"))
112
+
113
+ if fast:
114
+ fast_path = SKILLS_DIR / FAST_SKILL_FILENAME
115
+ parts.append(fast_path.read_text(encoding="utf-8"))
116
+
117
+ if product_context:
118
+ pc_path = SKILLS_DIR / PRODUCT_CONTEXT_SKILL_FILENAME
119
+ parts.append(pc_path.read_text(encoding="utf-8"))
120
+
121
+ return "\n\n---\n\n".join(parts)
122
+
123
+
124
+ def flags_to_string(strict: bool, fast: bool, product_context: bool) -> str:
125
+ """Chuyển các flag bool thành chuỗi 'strict,product-context' để lưu metadata."""
126
+ names = []
127
+ if strict:
128
+ names.append("strict")
129
+ if fast:
130
+ names.append("fast")
131
+ if product_context:
132
+ names.append("product-context")
133
+ return ",".join(names)
134
+
135
+
136
+ def string_to_flags(flags_str: str):
137
+ """Ngược lại flags_to_string(): chuỗi metadata -> (strict, fast, product_context)."""
138
+ names = {n.strip() for n in flags_str.split(",") if n.strip()}
139
+ return ("strict" in names, "fast" in names, "product-context" in names)
140
+
141
+
142
+ def build_skill_content(strict: bool, fast: bool, product_context: bool) -> str:
143
+ """
144
+ Ghép nội dung skill ĐẦY ĐỦ (kèm dòng metadata ở đầu) sẽ ghi vào
145
+ NODESKAI.md. Đây là hàm `init` dùng để tạo file lần đầu.
146
+ """
147
+ metadata_line = METADATA_PREFIX.format(
148
+ flags=flags_to_string(strict, fast, product_context),
149
+ version=__version__,
150
+ )
151
+ body = build_skill_body(strict, fast, product_context)
152
+ return metadata_line + "\n\n" + body
153
+
154
+
155
+ def parse_metadata(content: str):
156
+ """
157
+ Đọc dòng metadata ở đầu 1 NODESKAI.md đã tồn tại.
158
+ Trả về (strict, fast, product_context, version) nếu tìm thấy, hoặc
159
+ None nếu file này không có metadata (vd. được tạo bởi bản NoDeskAI
160
+ cũ hơn trước khi có tính năng sync).
161
+ """
162
+ match = METADATA_PATTERN.search(content)
163
+ if not match:
164
+ return None
165
+ flags_str, version = match.group(1), match.group(2)
166
+ strict, fast, product_context = string_to_flags(flags_str)
167
+ return strict, fast, product_context, version
168
+
169
+
170
+ def install_skill_into_agent_configs(project_dir: Path, skill_full_content: str):
171
+ """
172
+ Ghi đầy đủ nội dung skill vào TẤT CẢ agent-config đã biết
173
+ (CLAUDE.md, .cursorrules, AGENTS.md, .windsurfrules) - đây là phần
174
+ giải quyết khoảng trống #6 (đa agent): mỗi tool đọc đúng file riêng
175
+ của nó, không cần chèn 1 dòng tham chiếu rồi bắt agent tự đi tìm
176
+ NODESKAI.md nữa. Nếu file đã có nội dung khác (do dev viết tay), giữ
177
+ nguyên phần đó và nối thêm khối NoDeskAI xuống cuối. Nếu file đã
178
+ từng được NoDeskAI cài trước đó (có marker "NoDeskAI:"), bỏ qua để
179
+ không chèn trùng - dùng `sync` để cập nhật thay vì `init` lại.
180
+ Trả về danh sách dòng log để in ra cho người dùng.
181
+ """
182
+ logs = []
183
+ for filename, label in AGENT_CONFIG_FILES.items():
184
+ path = project_dir / filename
185
+ if path.exists():
186
+ existing_content = path.read_text(encoding="utf-8")
187
+ if "NoDeskAI:" in existing_content:
188
+ logs.append(f"[SKIP] {filename} ({label}) đã cài NoDeskAI từ trước, không chèn lại (dùng 'nodeskai sync' để cập nhật)")
189
+ continue
190
+ if existing_content.strip():
191
+ new_content = existing_content.rstrip("\n") + "\n\n" + skill_full_content
192
+ else:
193
+ new_content = skill_full_content
194
+ path.write_text(new_content, encoding="utf-8")
195
+ logs.append(f"[OK] Đã thêm skill vào {filename} ({label}) — giữ nguyên nội dung cũ của file")
196
+ else:
197
+ path.write_text(skill_full_content, encoding="utf-8")
198
+ logs.append(f"[OK] Đã tạo mới {filename} ({label})")
199
+ return logs
200
+
201
+
202
+ def cmd_init(args):
203
+ if args.strict and args.fast:
204
+ print("Lỗi: không thể dùng đồng thời --strict và --fast (2 chế độ đối lập nhau).")
205
+ sys.exit(1)
206
+
207
+ project_dir = Path(args.path).resolve()
208
+
209
+ if not project_dir.exists():
210
+ print(f"Lỗi: đường dẫn không tồn tại: {project_dir}")
211
+ sys.exit(1)
212
+
213
+ skill_content = build_skill_content(
214
+ strict=args.strict,
215
+ fast=args.fast,
216
+ product_context=args.product_context,
217
+ )
218
+
219
+ skill_dest = project_dir / NODESKAI_SKILL_FILE
220
+ skill_dest.write_text(skill_content, encoding="utf-8")
221
+ print(f"[OK] Đã cài skill vào: {skill_dest}")
222
+
223
+ mode_labels = []
224
+ if args.strict:
225
+ mode_labels.append("strict")
226
+ if args.fast:
227
+ mode_labels.append("fast")
228
+ if args.product_context:
229
+ mode_labels.append("product-context")
230
+ if mode_labels:
231
+ print(f"[OK] Chế độ bật thêm: {', '.join(mode_labels)}")
232
+
233
+ for log_line in install_skill_into_agent_configs(project_dir, skill_content):
234
+ print(log_line)
235
+
236
+ print("\nHoàn tất. Claude Code, Cursor, Codex CLI, Windsurf đều đã có sẵn quy tắc trong đúng file cấu hình riêng của từng tool.")
237
+
238
+
239
+ # ============================================================
240
+ # Lệnh `sync`
241
+ # ============================================================
242
+
243
+ def cmd_sync(args):
244
+ """
245
+ Cập nhật MỌI file NoDeskAI quản lý trong project (NODESKAI.md + tất cả
246
+ agent-config đã cài) theo bản skill mới nhất của package đang cài, mỗi
247
+ file giữ đúng flag riêng của nó (đọc từ dòng metadata). Giữ nguyên phần
248
+ nội dung viết tay đứng trước khối NoDeskAI trong agent-config (nếu có).
249
+ File nào không có metadata (agent-config viết tay không qua NoDeskAI,
250
+ hoặc file từ bản NoDeskAI cũ trước khi có sync) thì bỏ qua, không lỗi
251
+ cứng cả lệnh.
252
+ """
253
+ project_dir = Path(args.path).resolve()
254
+
255
+ if not project_dir.exists():
256
+ print(f"Lỗi: đường dẫn không tồn tại: {project_dir}")
257
+ sys.exit(1)
258
+
259
+ files_to_check = detect_installed_files(project_dir)
260
+
261
+ if not files_to_check:
262
+ print(
263
+ "Lỗi: không tìm thấy NODESKAI.md hay agent-config nào trong project này. "
264
+ "Chạy 'nodeskai init' trước khi dùng 'sync'."
265
+ )
266
+ sys.exit(1)
267
+
268
+ updated = [] # (filename, old_version)
269
+ up_to_date = [] # (filename, version)
270
+ skipped = [] # filename không có metadata
271
+
272
+ for path in files_to_check:
273
+ content = path.read_text(encoding="utf-8")
274
+ match = METADATA_PATTERN.search(content)
275
+
276
+ if match is None:
277
+ skipped.append(path.name)
278
+ continue
279
+
280
+ flags_str, old_version = match.group(1), match.group(2)
281
+ strict, fast, product_context = string_to_flags(flags_str)
282
+
283
+ # Giữ nguyên phần nội dung đứng trước khối NoDeskAI (preamble viết
284
+ # tay, nếu có) - chỉ build lại phần từ vị trí metadata trở đi.
285
+ preamble = content[: match.start()]
286
+ new_content = preamble + build_skill_content(strict, fast, product_context)
287
+
288
+ if new_content == content:
289
+ up_to_date.append((path.name, old_version))
290
+ else:
291
+ path.write_text(new_content, encoding="utf-8")
292
+ updated.append((path.name, old_version))
293
+
294
+ if not updated and not up_to_date:
295
+ print(
296
+ "Lỗi: không file nào trong project có dòng metadata NoDeskAI "
297
+ "(flags/version) — có thể được tạo bởi bản NoDeskAI cũ hơn trước "
298
+ "khi có lệnh 'sync', hoặc dòng metadata bị sửa/xoá thủ công.\n"
299
+ "Cách xử lý: chạy lại 'nodeskai init' với đúng các flag mong muốn "
300
+ "(--strict/--fast/--product-context) để thêm metadata, sau đó "
301
+ "'sync' sẽ dùng được từ lần sau."
302
+ )
303
+ sys.exit(1)
304
+
305
+ for filename, old_version in updated:
306
+ if old_version == __version__:
307
+ print(f"[OK] Đã cập nhật {filename} (cùng version {__version__}, nội dung skill đã thay đổi)")
308
+ else:
309
+ print(f"[OK] Đã cập nhật {filename} từ version {old_version} lên {__version__}")
310
+
311
+ for filename, version in up_to_date:
312
+ print(f"[OK] {filename} đã ở bản mới nhất (version {version}).")
313
+
314
+ for filename in skipped:
315
+ print(f"[SKIP] {filename} không có metadata NoDeskAI, bỏ qua (có thể là file viết tay không qua NoDeskAI).")
316
+
317
+
318
+ # ============================================================
319
+ # Lệnh `audit`
320
+ # ============================================================
321
+
322
+ def check_bloat(path: Path, lines: list) -> list:
323
+ """Trả về danh sách cảnh báo nếu file vượt ngưỡng số dòng hợp lý."""
324
+ findings = []
325
+ line_count = len(lines)
326
+ if line_count > BLOAT_LINE_THRESHOLD:
327
+ findings.append(
328
+ f"[BLOAT] {path.name}: {line_count} dòng, vượt ngưỡng {BLOAT_LINE_THRESHOLD} dòng "
329
+ f"— rule quan trọng có nguy cơ bị chôn vùi trong nhiễu, nên rà soát và cắt bớt."
330
+ )
331
+ return findings
332
+
333
+
334
+ def check_duplicates(path: Path, lines: list) -> list:
335
+ """
336
+ Phát hiện các dòng nội dung trùng lặp trong cùng 1 file (bỏ qua dòng
337
+ trống). Đây là dấu hiệu kiểu "thêm rule mới mỗi khi gặp lỗi mà không
338
+ dọn dẹp rule cũ" đã thấy ở CLAUDE.md gốc.
339
+ """
340
+ findings = []
341
+ seen = {}
342
+ for line_number, raw_line in enumerate(lines, start=1):
343
+ normalized = raw_line.strip().lower()
344
+ if not normalized or normalized.startswith("#") or normalized.startswith("<!--"):
345
+ continue
346
+ # Bỏ qua dòng phân cách Markdown thuần ký tự (---, ===, ***...) -
347
+ # đây không phải nội dung rule, trùng nhau là bình thường.
348
+ if normalized == normalized[0] * len(normalized) and normalized[0] in "-=*_":
349
+ continue
350
+ if normalized in seen:
351
+ findings.append(
352
+ f"[TRÙNG LẶP] {path.name}: dòng {line_number} trùng nội dung với dòng {seen[normalized]}"
353
+ )
354
+ else:
355
+ seen[normalized] = line_number
356
+ return findings
357
+
358
+
359
+ def check_malicious_patterns(path: Path, lines: list) -> list:
360
+ """Quét từng dòng theo danh sách pattern đáng ngờ đã định nghĩa sẵn."""
361
+ findings = []
362
+ for line_number, raw_line in enumerate(lines, start=1):
363
+ lowered = raw_line.lower()
364
+ for pattern, description in MALICIOUS_PATTERNS:
365
+ if pattern in lowered:
366
+ findings.append(
367
+ f'[NGUY HIỂM] {path.name}: dòng {line_number} — {description} (khớp: "{pattern}")'
368
+ )
369
+ return findings
370
+
371
+
372
+ def cmd_audit(args):
373
+ project_dir = Path(args.path).resolve()
374
+
375
+ if not project_dir.exists():
376
+ print(f"Lỗi: đường dẫn không tồn tại: {project_dir}")
377
+ sys.exit(1)
378
+
379
+ files_to_check = detect_installed_files(project_dir)
380
+
381
+ if not files_to_check:
382
+ print("Không tìm thấy NODESKAI.md hay agent config nào trong project này. Không có gì để audit.")
383
+ return
384
+
385
+ all_findings = []
386
+ for path in files_to_check:
387
+ lines = path.read_text(encoding="utf-8").splitlines()
388
+ all_findings.extend(check_bloat(path, lines))
389
+ all_findings.extend(check_duplicates(path, lines))
390
+ all_findings.extend(check_malicious_patterns(path, lines))
391
+
392
+ print(f"Đã quét {len(files_to_check)} file: {', '.join(p.name for p in files_to_check)}\n")
393
+
394
+ if not all_findings:
395
+ print("[OK] Không phát hiện vấn đề nào (bloat, trùng lặp, pattern đáng ngờ).")
396
+ return
397
+
398
+ danger_count = sum(1 for f in all_findings if f.startswith("[NGUY HIỂM]"))
399
+
400
+ for finding in all_findings:
401
+ print(finding)
402
+
403
+ print(f"\nTổng cộng: {len(all_findings)} vấn đề được phát hiện.")
404
+
405
+ if danger_count > 0:
406
+ print(f"CẢNH BÁO: {danger_count} pattern nguy hiểm được phát hiện — kiểm tra kỹ trước khi tin tưởng file này.")
407
+ sys.exit(1)
408
+
409
+
410
+ # ============================================================
411
+ # Argument parser
412
+ # ============================================================
413
+
414
+ def build_parser():
415
+ parser = argparse.ArgumentParser(
416
+ prog="nodeskai",
417
+ description="NoDeskAI - skill-pack giúp AI coding agent code kỷ luật hơn.",
418
+ )
419
+ subparsers = parser.add_subparsers(dest="command", required=True)
420
+
421
+ init_parser = subparsers.add_parser("init", help="Cài skill vào project hiện tại")
422
+ init_parser.add_argument("--path", default=".", help="Đường dẫn tới project (mặc định: thư mục hiện tại)")
423
+ init_parser.add_argument("--strict", action="store_true", help="Bật chế độ nghiêm ngặt (thêm rào chắn cho quyết định rủi ro cao)")
424
+ init_parser.add_argument("--fast", action="store_true", help="Bật chế độ nhanh (nới lỏng cho việc nhỏ hiển nhiên)")
425
+ init_parser.add_argument("--product-context", action="store_true", help="Thêm skill bối cảnh product/team")
426
+ init_parser.set_defaults(func=cmd_init)
427
+
428
+ sync_parser = subparsers.add_parser("sync", help="Cập nhật NODESKAI.md theo bản skill mới nhất của package đang cài")
429
+ sync_parser.add_argument("--path", default=".", help="Đường dẫn tới project (mặc định: thư mục hiện tại)")
430
+ sync_parser.set_defaults(func=cmd_sync)
431
+
432
+ audit_parser = subparsers.add_parser("audit", help="Kiểm tra bloat, rule trùng lặp, pattern đáng ngờ")
433
+ audit_parser.add_argument("--path", default=".", help="Đường dẫn tới project (mặc định: thư mục hiện tại)")
434
+ audit_parser.set_defaults(func=cmd_audit)
435
+
436
+ return parser
437
+
438
+
439
+ def main():
440
+ parser = build_parser()
441
+ args = parser.parse_args()
442
+ args.func(args)
443
+
444
+
445
+ if __name__ == "__main__":
446
+ main()
@@ -0,0 +1,16 @@
1
+ # NoDeskAI — Chế độ Nhanh (--fast)
2
+
3
+ Bộ quy tắc cơ bản của NoDeskAI thiên về thận trọng. Với dự án nhỏ hoặc giai
4
+ đoạn prototype, điều đó có thể làm chậm những việc hiển nhiên. Chế độ này
5
+ nới lỏng có kiểm soát:
6
+
7
+ 1. **Việc 1 dòng/hiển nhiên thì làm thẳng.** Sửa lỗi chính tả, đổi tên biến
8
+ rõ ràng, format code — không cần hỏi lại, không cần nêu giả định.
9
+
10
+ 2. **Vẫn giữ nguyên quy tắc không sửa code ngoài phạm vi** và **không tự
11
+ giả định khi yêu cầu thực sự mơ hồ** — chế độ nhanh chỉ bỏ bớt các bước
12
+ xác nhận thừa cho việc nhỏ, không bỏ 2 quy tắc nền tảng này.
13
+
14
+ 3. **Khi không chắc 1 việc có "hiển nhiên" hay không, mặc định coi là
15
+ KHÔNG hiển nhiên** và quay lại quy trình đầy đủ — tránh lạm dụng chế độ
16
+ nhanh để bỏ qua bước cần thiết.
@@ -0,0 +1,31 @@
1
+ # NoDeskAI — Quy tắc kỷ luật cho AI coding agent
2
+
3
+ Đây là file được NoDeskAI tự động cài vào project. Nếu bạn là một AI coding
4
+ agent đang đọc file này, hãy tuân theo các quy tắc sau khi làm việc trong
5
+ project này:
6
+
7
+ 1. **Không tự ý giả định rồi làm bừa.** Nếu yêu cầu của người dùng có thể
8
+ hiểu theo nhiều cách, hoặc thiếu thông tin cần thiết, hãy hỏi lại hoặc nêu
9
+ rõ giả định đang dùng — không âm thầm chọn một cách hiểu rồi code luôn.
10
+
11
+ 2. **Không phình to giải pháp.** Nếu một việc giải quyết được trong 20-50
12
+ dòng, không viết thành 200-500 dòng với class/abstraction không cần thiết.
13
+ Ưu tiên giải pháp đơn giản nhất giải quyết đúng vấn đề được yêu cầu.
14
+
15
+ 3. **Không sửa code ngoài phạm vi.** Chỉ động vào phần code liên quan trực
16
+ tiếp đến yêu cầu. Không "tiện tay" refactor, đổi style, hay sửa phần
17
+ không liên quan, kể cả khi thấy phần đó có thể cải thiện.
18
+
19
+ 4. **Môi trường resource-constrained (Termux/Android/máy yếu/mạng chậm).**
20
+ Nếu phát hiện project đang chạy trong môi trường như vậy: ưu tiên lệnh
21
+ nhẹ, tránh build/install nặng không cần thiết, tránh vòng lặp thử-sai tốn
22
+ nhiều lượt gọi API/token. Gộp các thay đổi nhỏ lại thay vì chạy nhiều lệnh
23
+ rời rạc.
24
+
25
+ 5. **Báo cáo rõ ràng.** Sau khi hoàn thành, nêu ngắn gọn đã thay đổi gì, có
26
+ phần nào chưa kiểm chứng được (ví dụ: không có môi trường để chạy thử)
27
+ thì nói rõ, không khẳng định như đã test đầy đủ.
28
+
29
+ ---
30
+ *File này do [nodeskai](https://github.com/) cài đặt. Chạy `nodeskai sync` để
31
+ cập nhật bản mới nhất.*
@@ -0,0 +1,28 @@
1
+ # NoDeskAI — Bối cảnh Product/Team
2
+
3
+ CLAUDE.md gốc (andrej-karpathy-skills) được viết cho 1 kỹ sư làm việc một
4
+ mình với code. Skill này bổ sung phần CLAUDE.md không có: buộc agent làm rõ
5
+ bối cảnh sản phẩm/team trước khi bắt tay vào code, không chỉ dừng ở mức
6
+ "hiểu đúng yêu cầu kỹ thuật".
7
+
8
+ Khi bắt đầu 1 feature hoặc thay đổi không hiển nhiên, agent PHẢI:
9
+
10
+ 1. **Nêu rõ success criteria ở cấp feature**, không chỉ ở cấp dòng lệnh.
11
+ Ví dụ: không chỉ "hàm này trả về đúng giá trị" mà còn "tính năng này coi
12
+ là xong khi nào, ai là người dùng cuối, điều kiện thất bại là gì".
13
+
14
+ 2. **Không tự chốt số liệu/metric quan trọng thay người dùng.** Nếu yêu cầu
15
+ có liên quan tới ngưỡng, giới hạn, hay tiêu chí đo lường (ví dụ: "tối ưu
16
+ tốc độ", "giảm lỗi") mà không có con số cụ thể, phải hỏi lại thay vì tự
17
+ đặt ra một con số rồi báo cáo như đã đạt được.
18
+
19
+ 3. **Ghi lại quyết định đã chốt.** Sau khi người dùng xác nhận 1 hướng đi,
20
+ tóm tắt lại quyết định đó trong 1-2 câu để tránh "không ai nhớ vì sao lại
21
+ chọn hướng này" khi xem lại sau này.
22
+
23
+ 4. **Phân biệt rõ "việc nhỏ hiển nhiên" và "quyết định ảnh hưởng lâu dài".**
24
+ Việc nhỏ (sửa lỗi chính tả, đổi tên biến) thì làm thẳng. Quyết định ảnh
25
+ hưởng kiến trúc/tính năng lâu dài thì phải nêu rõ đánh đổi trước khi làm.
26
+
27
+ ---
28
+ *Skill này là phần mở rộng riêng của NoDeskAI, không có trong CLAUDE.md gốc.*
@@ -0,0 +1,19 @@
1
+ # NoDeskAI — Chế độ Nghiêm ngặt (--strict)
2
+
3
+ Áp dụng thêm các rào chắn sau, ngoài bộ quy tắc cơ bản:
4
+
5
+ 1. **Bắt buộc viết test trước khi sửa lỗi.** Với mọi yêu cầu sửa bug, viết 1
6
+ test tái hiện lỗi trước, xác nhận test đó fail, rồi mới sửa code cho tới
7
+ khi test pass. Không sửa "theo cảm giác" rồi báo đã xong.
8
+
9
+ 2. **Bắt buộc nêu phương án rollback.** Với thay đổi ảnh hưởng nhiều file
10
+ hoặc cấu trúc dữ liệu, nêu rõ cách hoàn tác nếu thay đổi gây lỗi, trước
11
+ khi thực hiện.
12
+
13
+ 3. **Không tự động chạy lệnh rủi ro cao.** Các lệnh như xoá thư mục, ghi đè
14
+ file cấu hình, force-push, cài đặt lớn — phải liệt kê ra và chờ xác nhận,
15
+ không tự chạy.
16
+
17
+ 4. **Tự kiểm tra lại 1 lần trước khi báo hoàn thành.** Đọc lại toàn bộ thay
18
+ đổi vừa làm như một reviewer khó tính, tìm lỗi cú pháp/logic/thiếu bước
19
+ trước khi báo cáo là đã xong.
@@ -0,0 +1,105 @@
1
+ Metadata-Version: 2.4
2
+ Name: nodeskai
3
+ Version: 0.4.0
4
+ Summary: Skill-pack giup AI coding agent code ky luat hon, xay dung hoan toan tren dien thoai.
5
+ License: MIT
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Dynamic: license-file
10
+
11
+ # NoDeskAI
12
+
13
+ *[Đọc bằng tiếng Việt](README.vi.md)*
14
+
15
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
16
+ [![Made in Vietnam](https://img.shields.io/badge/made%20in-%F0%9F%87%BB%F0%9F%87%B3%20Vietnam-red.svg)](#)
17
+ [![Built on a phone](https://img.shields.io/badge/built%20on-%F0%9F%93%B1%20a%20phone-brightgreen.svg)](#)
18
+
19
+ **Your AI coding agent keeps guessing, over-engineering, and editing code
20
+ outside the scope you asked for. NoDeskAI fixes that — in one command.**
21
+
22
+ NoDeskAI is a skill-pack for AI coding agents (Claude Code, Cursor, Codex
23
+ CLI, Windsurf...): install it once and your agent stops silently guessing
24
+ at ambiguous requests, stops bloating simple tasks into over-engineered
25
+ solutions, and stops touching code outside what you asked for. It ships
26
+ with `audit` — a built-in scanner that checks the skill/rule files you're
27
+ about to trust for bloat, duplicate rules, and prompt-injection patterns.
28
+
29
+ > 🇻🇳 **Made in Vietnam.** Every line of this project — writing, testing,
30
+ > committing, and pushing to GitHub — was done entirely on an Android
31
+ > phone through Termux. No PC, no laptop, no iPad.
32
+
33
+ ## Install
34
+
35
+ ```bash
36
+ pip install nodeskai
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ ```bash
42
+ cd your-project
43
+ nodeskai init
44
+ ```
45
+
46
+ This writes the full discipline ruleset into **all 4 agent-config files**
47
+ (`CLAUDE.md`, `.cursorrules`, `AGENTS.md`, `.windsurfrules`) — creating
48
+ whichever ones don't exist yet, and appending to any that already have
49
+ content of your own (your existing content is kept, NoDeskAI's block is
50
+ added below it). It also creates `NODESKAI.md` as the source of truth.
51
+ Every file gets a metadata line (flags + version) at the top so `sync`
52
+ knows how to update it later.
53
+
54
+ ### Optional modes
55
+
56
+ ```bash
57
+ nodeskai init --strict # extra guardrails for high-risk decisions
58
+ nodeskai init --fast # relaxed rules for obviously trivial tasks
59
+ nodeskai init --product-context # adds a product/team-context skill (missing from the original CLAUDE.md)
60
+ ```
61
+
62
+ `--strict` and `--fast` can't be combined (they're opposite modes).
63
+
64
+ ### Update when a new skill version is available
65
+
66
+ ```bash
67
+ nodeskai sync
68
+ ```
69
+
70
+ Updates **every file NoDeskAI manages** (NODESKAI.md + installed
71
+ agent-configs) to match the currently installed NoDeskAI version, keeping
72
+ each file's own flags from `init` and preserving any hand-written content
73
+ that came before the NoDeskAI block. Files with no NoDeskAI metadata
74
+ (hand-written, never run through `init`) are reported as `[SKIP]` — they
75
+ don't break the command.
76
+
77
+ ### Check installed skill/agent-config files
78
+
79
+ ```bash
80
+ nodeskai audit
81
+ ```
82
+
83
+ Scans every skill/agent-config file in the project for:
84
+ - **Bloat** — files over 150 lines, where important rules risk getting
85
+ buried.
86
+ - **Duplicate rules** — a sign of rules being added over time without ever
87
+ being cleaned up.
88
+ - **Suspicious patterns** — prompt-injection attempts, destructive
89
+ commands, data-exfiltration signs.
90
+
91
+ ## Current status
92
+
93
+ v0.4.0 — `init` writes the full skill into all 4 agent-config files at
94
+ once, `audit` is fully functional (bloat / duplicates / suspicious
95
+ patterns), `sync` updates every managed file when a new skill version is
96
+ available, keeping each file's own flags.
97
+
98
+ ## Support the project
99
+
100
+ If NoDeskAI is useful to you, you can support it through GitHub Sponsors
101
+ (link coming soon) or Ko-fi.
102
+
103
+ ## License
104
+
105
+ MIT
@@ -0,0 +1,14 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ nodeskai/__init__.py
5
+ nodeskai/cli.py
6
+ nodeskai.egg-info/PKG-INFO
7
+ nodeskai.egg-info/SOURCES.txt
8
+ nodeskai.egg-info/dependency_links.txt
9
+ nodeskai.egg-info/entry_points.txt
10
+ nodeskai.egg-info/top_level.txt
11
+ nodeskai/skills/fast-mode.md
12
+ nodeskai/skills/no-overengineering.md
13
+ nodeskai/skills/product-context.md
14
+ nodeskai/skills/strict-mode.md
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ nodeskai = nodeskai.cli:main
@@ -0,0 +1 @@
1
+ nodeskai
@@ -0,0 +1,17 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "nodeskai"
7
+ version = "0.4.0"
8
+ description = "Skill-pack giup AI coding agent code ky luat hon, xay dung hoan toan tren dien thoai."
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = { text = "MIT" }
12
+
13
+ [project.scripts]
14
+ nodeskai = "nodeskai.cli:main"
15
+
16
+ [tool.setuptools.package-data]
17
+ nodeskai = ["skills/*.md"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+