Công nghệ

Vibe coding với Claude: thả hồn theo code, đừng thả tay lái

Vibe coding — nói bằng lời rồi để AI viết code — nhanh thật, nhưng cũng lạc nhanh thật. Chín thói quen mình rút ra khi dựng lại chính trang này cùng Claude Code: cho AI bộ nhớ, bắt nó lên kế hoạch, chia nhỏ việc, đòi bằng chứng và luôn giữ tay trên phanh.

Ảnh bìa bài viết Vibe coding với Claude: thả hồn theo code, đừng thả tay lái

Đầu năm 2025, Andrej Karpathy đặt tên cho một kiểu lập trình mới: vibe coding — nói bằng lời mình muốn gì, để AI viết code, thấy chạy là được, gần như quên luôn là code có tồn tại. Nghe thì như mơ. Làm thật thì… cũng như mơ, chỉ là thỉnh thoảng thành ác mộng.

Trang bạn đang đọc được dựng lại gần như toàn bộ cùng Claude Code: chuyển từ Umbraco sang .NET 10, làm giao diện mới, trang profile, editor bài viết, cho tới lúc deploy và cài chứng chỉ SSL. Tốc độ thì khỏi bàn — có việc trước đây mất cả tuần, giờ xong trong một buổi tối. Nhưng cũng chính trong quá trình đó mình gặp đủ kiểu "toang" nho nhỏ, và nhận ra một điều: AI hiếm khi làm hỏng dự án; cách mình dùng AI mới làm hỏng dự án.

Dưới đây là chín thói quen mình rút ra. Không có gì cao siêu — phần lớn là kỷ luật của một kỹ sư bình thường, chỉ là áp lên một đồng nghiệp gõ phím nhanh gấp trăm lần mình.

Trước hết: ai cầm lái?

Hai thẻ so sánh vai trò: bạn là thuyền trưởng chọn đích đến, duyệt kế hoạch, đòi bằng chứng; Claude là hoa tiêu đọc code, đề xuất kế hoạch, viết code, báo cáo
Bạn chọn hướng và chịu trách nhiệm; Claude chèo. Hai bên trao đổi bằng yêu cầu rõ ràng và bằng chứng.

Hình dung Claude là một hoa tiêu cực giỏi: đọc hải đồ nhanh, chèo khoẻ, không biết mệt. Nhưng hoa tiêu này có ba điểm yếu cố hữu: không nhớ hải trình hôm qua (mỗi phiên làm việc bắt đầu trắng trơn), không biết những gì bạn không nói ra, và đôi khi tự tin hơn mức nên có.

Vì vậy hãy chia vai cho rõ ngay từ đầu. Bạn chọn đích đến, duyệt lộ trình, kiểm tra kết quả và giữ chìa khoá những thứ không quay lại được. Claude lo phần chèo. Chín thói quen bên dưới đều xoay quanh một ý: giữ bánh lái trong tay mình.

1. Cho AI một tấm hải đồ: CLAUDE.md

Chồng tài liệu CLAUDE.md, ai-rules.md, coding-convention.md, pitfalls.md, known-issues.md được nạp vào Claude ở mỗi phiên mới
Thứ gì quan trọng thì phải nằm trong repo — AI quên, file thì không.

Claude Code tự đọc file CLAUDE.md ở gốc repo mỗi khi bắt đầu một phiên. Lệnh /init tạo sẵn bản đầu tiên cho bạn. Đây là nơi ghi những điều mà một người mới vào dự án cần biết ngay ngày đầu: chạy lệnh gì để build, để test; điều gì tuyệt đối không được làm; tài liệu chi tiết nằm ở đâu. Muốn kéo thêm file khác vào, dùng cú pháp @đường/dẫn. CLAUDE.md của chính trang này, rút gọn:

# CLAUDE.md
Website cá nhân hungcd.com — .NET 10 + Blazor, EF Core + PostgreSQL.

## Lệnh
- Build: dotnet build HungCd.slnx
- Xem trước deploy, không đụng server: bash deploy/deploy.sh --dry-run

## Quy tắc làm việc
@docs/conventions/ai-rules.md

Hai điều mình học được. Một: giữ nó ngắn — tài liệu chính thức khuyên dưới khoảng 200 dòng; dòng nào bỏ đi mà AI không làm sai hơn thì xoá. Hai: cập nhật nó như cập nhật code. Mỗi lần AI làm sai một việc mà một câu dặn có thể ngăn được, câu dặn đó thuộc về CLAUDE.md hoặc một file nó trỏ tới.

2. Việc lớn: kế hoạch trước, code sau

Việc nhỏ và rõ — đổi một dòng chữ, sửa một lỗi chính tả — cứ để Claude làm luôn. Còn việc chạm nhiều file, đổi database, thêm thư viện thì bắt nó lên kế hoạch trước. Trong Claude Code, bấm Shift+Tab cho tới khi thanh trạng thái báo plan mode: Claude chỉ đọc code và đề xuất, chưa sửa gì. Bạn đọc kế hoạch, gạch bớt chỗ thừa, hỏi lại chỗ mơ hồ, rồi mới cho làm.

Ở repo này mình ghi hẳn thành luật: thay đổi nào đụng hơn ba file, đụng schema, xác thực hay script deploy thì phải trình kế hoạch và chờ duyệt. Khi làm editor HTML cho chính trang này, bước lên kế hoạch đã lôi ra một chi tiết suýt bị bỏ qua: bài soạn bằng HTML sẽ không tìm kiếm được, vì trigger tìm kiếm chỉ đọc cột Markdown. Phát hiện ở bước kế hoạch thì sửa mất năm phút; phát hiện sau khi lên production thì mất nguyên một buổi.

3. Viết yêu cầu như viết ticket cho người giỏi nhưng mới vào

So sánh hai cách yêu cầu: câu mơ hồ 'sửa giúp cái editor bị lỗi' và câu rõ ràng có triệu chứng, cách tái hiện, phạm vi và tiêu chí xong
Bốn thứ nên có trong mọi yêu cầu: triệu chứng, cách tái hiện, phạm vi, tiêu chí xong.

Claude giỏi, nhưng nó không đọc được suy nghĩ. Một yêu cầu tốt có bốn phần:

  • Triệu chứng — thấy gì, ở màn hình nào, khác với mong đợi ra sao.
  • Cách tái hiện — làm gì thì lỗi xuất hiện. Nếu chưa biết, yêu cầu Claude tái hiện trước khi sửa.
  • Phạm vi — được đụng vào đâu, không được đụng vào đâu.
  • Tiêu chí xong — kiểm bằng cách nào thì coi là xong.

Lỗi con trỏ nhảy khi gõ tiếng Việt trong editor của trang này là ví dụ điển hình. Câu "sửa giúp cái editor" sẽ nhận về một bản sửa đoán mò. Còn khi yêu cầu tái hiện trước, Claude viết một đoạn script giả lập đúng cách Unikey gõ Telex — xoá ký tự vừa gõ rồi chèn chữ có dấu, liền nhau trong vài mili giây — và thấy lỗi xảy ra ngay cả khi không có độ trễ mạng. Nguyên nhân nằm ở cách nối dữ liệu của một ô nhập trong Blazor; bản sửa gói gọn trong một file, và chính script đó xác nhận lỗi đã hết.

4. Một vòng, một mục tiêu nhỏ

Vòng lặp sáu bước: mô tả rõ, lên kế hoạch, làm một bước nhỏ, kiểm chứng, đọc diff, commit và ghi bài học
Mỗi vòng chỉ nhắm một mục tiêu. Diff nhỏ thì đọc được, sai thì lùi được.

Đừng giao cả con voi. Chia việc thành những bước mà diff của mỗi bước đọc hết được trong năm phút, làm xong bước nào thì kiểm, đọc, commit bước đó. Một phiên dài trộn năm việc khác nhau là công thức cho nhầm lẫn: ngữ cảnh càng dài, AI càng dễ lẫn chi tiết của việc này sang việc kia.

Vài phím nên thuộc:

  • Esc — dừng Claude ngay khi thấy nó đi sai hướng, đừng đợi nó làm xong mới sửa.
  • Esc Esc hoặc /rewind — quay lại một điểm trước đó trong cuộc trò chuyện, kèm hoặc không kèm khôi phục code.
  • /clear — xoá ngữ cảnh khi chuyển sang một việc không liên quan. Tài liệu chính thức còn khuyên: đã sửa hướng hai lần cho cùng một vấn đề mà vẫn sai thì /clear rồi viết lại yêu cầu từ đầu — thường nhanh hơn là cố kéo một cuộc trò chuyện đã rối.

5. Đòi bằng chứng, đừng nhận lời hứa

AI báo đã tạo mật khẩu admin, kính lúp phóng to cho thấy ký tự ẩn \r ở cuối mật khẩu, màn hình đăng nhập báo sai mật khẩu
Chuyện có thật: mật khẩu "đúng" nhưng không ai gõ được, vì có một ký tự vô hình ở cuối.

Câu đáng nhớ nhất trong hướng dẫn chính thức của Claude Code là: hãy cho Claude một cách để tự kiểm tra công việc của nó — test, build, linter, ảnh chụp màn hình. Không có cách kiểm thì bạn chính là bước kiểm.

Khi deploy trang này lần đầu, Claude sinh mật khẩu admin bằng openssl, băm, ghi lên server rồi báo thành công. Mọi thứ trông đều đúng. Chỉ đến khi đăng nhập thử mới thấy báo sai mật khẩu. Nguyên nhân: trên Git Bash, openssl trả về \r\n ở cuối dòng, lệnh chỉ cắt \n, nên thứ được băm là "mật khẩu + một ký tự \r vô hình" — thứ không bàn phím nào gõ ra được. Từ đó mọi việc có đầu ra quan trọng đều kèm một bước kiểm như người dùng thật: đăng nhập thử, mở trang thử, gõ thử.

Trang này chưa có test tự động, nên mình yêu cầu Claude tự mở trình duyệt chạy ngầm, chụp màn hình cả máy tính lẫn điện thoại sau mỗi thay đổi giao diện, và xem ảnh trước khi báo xong. Và luôn đòi một bản báo cáo trung thực: đã kiểm gì, chưa kiểm gì. Một câu "chưa thử trên điện thoại" có giá trị hơn mười câu "đã hoàn thành".

6. Đọc diff như review PR của người khác

Code chạy được chưa chắc là code đúng, và code đúng chưa chắc là code mình muốn giữ. Đừng nhận dòng nào mình không hiểu — hỏi thẳng "tại sao lại viết thế này?", "có cách nào đơn giản hơn không?". Claude giải thích rất tốt khi được hỏi, và nhiều khi chính lúc giải thích nó tự phát hiện ra chỗ chưa ổn.

Một thứ cần soi kỹ là sửa lan: AI rất hay "tiện tay" sửa luôn chỗ bên cạnh, đổi tên biến cho "đẹp", hay hiện đại hoá đoạn code không liên quan. Mỗi thay đổi ngoài phạm vi là một thứ nữa bạn phải review và một rủi ro nữa không ai yêu cầu. Repo này có luật: thấy chỗ khác cần sửa thì ghi vào danh sách vấn đề đã biết, không tự sửa kèm.

7. Rào chắn: đèn xanh, đèn vàng, đèn đỏ

Ba cột đèn giao thông: đèn xanh cứ làm, đèn vàng trình kế hoạch chờ duyệt, đèn đỏ chỉ làm khi được bảo rõ như deploy, commit, xoá dữ liệu
Phân loại việc theo mức "có quay lại được không", rồi ghi thành luật.

Phần lớn rủi ro không nằm ở code sai — code sai thì sửa được. Rủi ro nằm ở những thao tác không quay lại được: deploy, xoá dữ liệu, đẩy secret lên git, restart một dịch vụ dùng chung. Server của trang này chạy chung với bốn site khác; một lệnh restart nginx là cả năm site cùng gián đoạn. Vì vậy những việc đó chỉ được làm khi chính mình yêu cầu rõ trong lượt đó.

Có một điểm hay bị nhầm: luật trong CLAUDE.md là lời dặn — AI đọc và thường làm theo, nhưng không có gì bảo đảm. Muốn có rào chắn thật thì dùng cơ chế quyền của Claude Code. Trong .claude/settings.json, bạn cho phép sẵn những lệnh an toàn để khỏi phải bấm duyệt mỗi lần, và chặn hẳn những lệnh nguy hiểm:

{
  "permissions": {
    "allow": ["Bash(dotnet build *)", "Bash(git status)", "Bash(git diff *)"],
    "deny": ["Bash(git push *)", "Bash(ssh *)", "Read(./.env)"]
  }
}

Quy tắc chặn có hiệu lực cả khi bật chế độ bỏ qua hỏi quyền. Còn những việc lần nào cũng phải xảy ra — chạy formatter sau mỗi lần sửa file chẳng hạn — thì giao cho hook, vì hook chạy chắc chắn, không phụ thuộc vào việc AI có nhớ lời dặn hay không.

8. Git là phao cứu sinh

Làm trên nhánh riêng, commit nhỏ sau mỗi vòng, và tự mình quyết định khi nào commit, khi nào push. Commit message do AI viết thì được — thường còn viết kỹ hơn người — nhưng hãy đọc trước khi chấp nhận.

Claude Code có checkpoint: Esc Esc hoặc /rewind lùi được các thay đổi file mà Claude đã sửa. Nhưng checkpoint không theo dõi những thay đổi qua lệnh shell như rm, mv, và tài liệu chính thức nói thẳng: checkpoint không thay thế được version control. Git vẫn là tấm lưới cuối cùng.

9. Biến sai lầm thành luật

Mỗi lỗi khó hiểu mất hơn nửa tiếng để tìm ra, repo này ghi lại một mục "bẫy" theo mẫu: triệu chứng, nguyên nhân, cách làm đúng. Ký tự \r trong mật khẩu là bẫy P-28; con trỏ nhảy khi gõ tiếng Việt là P-29; Git Bash tự đổi tham số trông giống đường dẫn khi chạy curl là P-26. Phiên sau Claude đọc lại những file này, nên không vấp lại đúng hòn đá cũ.

Một sai lầm mắc lần đầu là bài học. Mắc lần hai là do mình lười ghi lại.

Khi nào nên tự cầm bút?

  • Khi chưa hiểu bài toán. Nếu bạn không review được thứ AI viết, đừng để nó viết. Học trước, giao sau.
  • Ở phần nhạy cảm: xác thực, thanh toán, dữ liệu người dùng. Vẫn dùng AI được, nhưng review kỹ gấp đôi và tự viết test cho các tình huống xấu.
  • Khi muốn học. Tự gõ một lần, hiểu sâu hơn đọc mười lần code AI viết.
  • Khi đã biết chính xác chỗ cần sửa. Sửa một dòng nhanh hơn giải thích cho AI dòng nào cần sửa.

Checklist một phút trước khi bấm Enter

  • Đã nói rõ triệu chứng, phạm vi và thế nào là xong chưa?
  • Việc này có đủ lớn để cần kế hoạch trước không?
  • Claude có cách tự kiểm không — build, test, chạy thử, chụp màn hình?
  • Có thao tác nào không quay lại được không? Ai sẽ bấm nút đó?
  • Xong rồi: đã đọc diff, đã commit, đã ghi lại bài học chưa?

Vibe coding không sai. Sai là vibe mà không có hải đồ. Cứ để Claude chèo — nhanh, khoẻ, không than mệt — miễn là bánh lái vẫn trong tay bạn, và ở cuối mỗi hải trình luôn có một ngọn hải đăng tên là bằng chứng.

Muốn đọc thêm, hướng dẫn chính thức Best practices for Claude Code của Anthropic rất đáng dành nửa tiếng. Còn bạn có thói quen nào khác khi làm việc với AI? Để lại bình luận nhé — mình đọc hết.

Bình luận (0)

Chưa có bình luận nào. Mở hàng nhé!

Để lại bình luận

Không cần đăng nhập. Bình luận hiển thị sau khi được duyệt.