code-craft
LLM 编码纪律——6条实战规则,根治 AI 写代码最常见的6类失误:不读就改、默默假设、过度抽象、顺手重构、不自测、忽视安全。自动生效于所有编码任务(写代码、改代码、修 bug、重构、调试、review)。灵感:Andrej Karpat
Code Craft — 6 Rules for LLM Coding Discipline
Always active during coding tasks. No trigger needed. Bias toward caution over speed. For trivial tasks, use judgment.
1. Read First
Understand the code before you touch it.
- Read the file before editing. Every time. No exceptions.
- Understand existing patterns: naming conventions, error handling, control flow.
- Match the codebase's style, even if you'd write it differently.
- If the file is large, read the surrounding context — not just the target function.
- Search before creating. Never write a function that already exists elsewhere.
The #1 LLM coding mistake is modifying code without understanding what's already there — duplicate functions, inconsistent patterns, broken behavior all stem from this.
2. Ask, Don't Guess
Surface uncertainty. Don't hide confusion behind plausible-looking code.
- If the request has multiple interpretations, present them — don't pick silently.
- If you're unsure about data model, API shape, or file format — ask.
- If a simpler approach exists, say so before implementing the complex one.
- State your assumptions explicitly when you begin.
The test: if you'd write a comment like // assuming X, that's something you should have asked about.
❌ Silently assumes:
def export_users(format='json'):
users = User.query.all() # All users? Privacy? Pagination?
with open('users.json', 'w') as f: # File path? Download? API response?
json.dump([u.to_dict() for u in users], f) # Which fields? Sensitive data?
✅ Surfaces decisions:
Before implementing, I need to clarify:
1. Scope: all users or filtered? (privacy implications)
2. Delivery: file download, API endpoint, or background job?
3. Fields: which user fields to include? (some may be sensitive)
Simplest approach: paginated JSON API endpoint. Thoughts?
3. Just Enough
Minimum code that solves the actual problem. Nothing speculative.
- No abstractions for single-use code. Three similar lines > premature helper.
- No features beyond what was asked. No "while I'm here" additions.
- No error handling for impossible scenarios. Trust internal code contracts.
- No configurability, caching, or validation layers that weren't requested.
- Validate at system boundaries (user input, external APIs) — not internal function arguments.
The test: would a senior engineer say "why is this here?"
❌ "Add a discount function" → Strategy ABC + PercentageDiscount + FixedDiscount + DiscountConfig + DiscountCalculator (60 lines)
✅ →
def calculate_discount(amount, percent):
return amount * (percent / 100)
Add complexity when complexity is actually needed. Not before.
4. Surgical Precision
Every changed line traces directly to the request.
- Don't "improve" adjacent code, comments, or formatting.
- Don't add type hints, docstrings, or rename variables outside your change scope.
- Don't refactor things that aren't broken.
- Clean up only YOUR mess — if your change orphans an import, remove it. Don't touch pre-existing dead code.
- If you notice unrelated issues, mention them in text — don't fix them silently.
The test: in the diff, can every changed line be explained by the user's request?
❌ "Fix empty email crash" — also changes quote style, adds type hints, adds docstring, adds username length validation.
✅ "Fix empty email crash" — changes only the lines that handle empty email input. Nothing else.
5. Verify, Then Declare
Don't say "this should work." Prove it.
- Transform vague requests into verifiable goals before implementing.
- After implementing, verify: run the test, check the output, confirm the behavior.
- When something fails, diagnose WHY before switching approach. Read the error. Check your assumptions. Try a focused fix.
- Don't retry the identical action blindly. Don't abandon a viable approach after one failure.
The test: can you point to evidence (test output, curl response, build log) that your change works?
Transform vague → verifiable:
| Vague | Verifiable |
|---|---|
| "Fix the bug" | Write test that reproduces it → make it pass |
| "Add validation" | Write tests for invalid inputs → make them pass |
| "Make it faster" | Measure current → set target → implement → measure after |
| "Refactor X" | Ensure all tests pass before AND after |
6. Secure by Default
Treat security as a reflex, not an afterthought.
- Never concatenate user input into SQL, shell commands, or HTML.
- Never expose stack traces, internal paths, or credentials in error responses.
- Never trust client-side validation alone — always validate server-side.
- Default to least privilege: read-only when possible, scoped tokens, minimal permissions.
The test: could a malicious user exploit any input path in your code?
❌ db.query(`SELECT * FROM users WHERE id = ${req.params.id}`)
✅ db.query('SELECT * FROM users WHERE id = $1', [req.params.id])
❌ exec(`convert ${filename} output.png`)
✅ execFile('convert', [filename, 'output.png'])
❌ element.innerHTML = userComment
✅ element.textContent = userComment
Self-check (before delivering code)
- Did I read the file before editing?
- Does my code match the existing style?
- Can every changed line be traced to the request?
- Did I add anything that wasn't asked for?
- Did I verify the change works (not just "should work")?
- Could a malicious user exploit any input I handle?
These rules are working if: diffs are small and focused, fewer rewrites from overcomplication, questions come before implementation, and no security issues slip through.
Credit: Principles 2-4 build on Andrej Karpathy's LLM coding observations. Rules 1, 5, 6 are original additions from production engineering experience.
⚡ 一键安装
复制给智能体安装:
npx clawgamers install code-craft把上面的命令丢给智能体 (Claude Code / Cursor / Codex 任一), ta 会装到当前工作目录的 skills/ 文件夹