Bỏ qua để đến nội dung

Best practices

Claude Code là một môi trường code agentic. Khác với chatbot chỉ trả lời rồi chờ, Claude Code đọc file, chạy lệnh, sửa code và tự làm việc qua vấn đề trong lúc bạn quan sát, điều hướng - hoặc rời đi hoàn toàn.

Điều này đổi cách bạn làm việc: thay vì tự viết code rồi nhờ Claude review, bạn mô tả điều mình muốn và Claude tự tìm cách xây. Nhưng quyền tự chủ đó cũng đi kèm một đường cong học tập.

Claude dừng khi công việc trông như đã xong. Không có phép kiểm tra nào, “trông như xong” là tín hiệu duy nhất nó có - và bạn trở thành vòng lặp kiểm chứng: mọi lỗi phải chờ bạn phát hiện. Đưa cho nó thứ trả về pass/fail, vòng lặp tự khép lại: Claude làm việc → chạy kiểm tra → đọc kết quả → sửa → lặp lại đến khi pass.

Phép kiểm tra là bất cứ thứ gì trả về tín hiệu Claude đọc được: bộ test, exit code của build, linter, script so output với fixture, hay ảnh chụp trình duyệt đối chiếu với thiết kế.

Cách làm Trước Sau
Cung cấp tiêu chí kiểm chứng “viết hàm kiểm tra email hợp lệ” “viết hàm validateEmail. Test case ví dụ: user@example.com → true, invalid → false, user@.com → false. Chạy test sau khi viết xong”
Kiểm chứng thay đổi UI bằng mắt “làm dashboard đẹp hơn” “[dán screenshot] triển khai thiết kế này. Chụp ảnh kết quả, so với ảnh gốc, liệt kê khác biệt rồi sửa”
Trị nguyên nhân gốc, không trị triệu chứng “build đang lỗi” “build lỗi với thông báo: [dán lỗi]. Sửa và xác nhận build thành công. Trị nguyên nhân gốc, đừng chỉ chặn lỗi đi”

Có phép kiểm tra rồi, chọn mức “siết” khi Claude muốn dừng:

  • Trong một prompt - yêu cầu Claude chạy kiểm tra và lặp ngay trong cùng tin nhắn (như bảng trên). Dùng được ngay hôm nay, cho mọi tác vụ.
  • Xuyên suốt phiên - đặt phép kiểm tra thành điều kiện /goal; một bộ đánh giá riêng kiểm lại sau mỗi lượt và Claude làm tiếp đến khi điều kiện đúng.
  • Như một cổng chặn tất định - Stop hook chạy script kiểm tra của bạn và chặn lượt kết thúc đến khi pass.
  • Bằng ý kiến thứ hai - một subagent kiểm chứng để một model mới thử phản biện kết quả, để agent làm việc không phải là agent tự cho điểm mình.

Hãy yêu cầu Claude trình bằng chứng thay vì tuyên bố thành công: output test, lệnh đã chạy và kết quả trả về, hoặc ảnh chụp. Đọc bằng chứng nhanh hơn tự chạy lại - và dùng được cả với những phiên bạn không ngồi xem.

Để Claude nhảy thẳng vào code dễ tạo ra thứ giải quyết sai vấn đề. Dùng plan mode để tách khám phá khỏi thực thi. Quy trình bốn bước:

  1. Khám phá - vào plan mode. Claude đọc file và trả lời câu hỏi, không sửa gì.
    đọc /src/auth và hiểu cách chúng ta xử lý session và login.
    xem cả cách quản lý biến môi trường cho secret.
  2. Lên kế hoạch - yêu cầu một kế hoạch triển khai chi tiết.
    tôi muốn thêm Google OAuth. Cần sửa những file nào?
    Luồng session ra sao? Hãy lập kế hoạch.
    Nhấn Ctrl+G để mở kế hoạch trong editor và tự sửa trước khi Claude tiếp tục.
  3. Triển khai - thoát plan mode, để Claude code và tự đối chiếu với kế hoạch.
    triển khai luồng OAuth theo kế hoạch của bạn. Viết test cho callback handler,
    chạy bộ test và sửa các lỗi nếu có.
  4. Commit - commit với message mô tả rõ và mở PR

Claude suy luận được ý định, nhưng không đọc được suy nghĩ của bạn. Hãy trỏ tới file cụ thể, nêu ràng buộc, và chỉ ra pattern mẫu.

Cách làm Trước Sau
Khoanh phạm vi - nói rõ file nào, tình huống nào, cách test “thêm test cho foo.py” “viết test cho foo.py, bao trường hợp user đã đăng xuất. Không dùng mock.”
Trỏ tới nguồn - chỉ Claude đến nơi có câu trả lời “sao API của ExecutionFactory kỳ vậy?” “đọc git history của ExecutionFactory và tóm tắt xem API của nó hình thành thế nào”
Tham chiếu pattern có sẵn “thêm một calendar widget” “xem các widget hiện có ở trang home để hiểu pattern - HotDogWidget.php là ví dụ tốt. Theo pattern đó làm một calendar widget cho phép chọn tháng và phân trang năm. Không thêm thư viện ngoài những cái đã dùng trong codebase.”
Mô tả triệu chứng - kèm nơi nghi ngờ và định nghĩa “đã sửa” “sửa bug login” “user báo login lỗi sau khi session timeout. Kiểm tra luồng auth trong src/auth/, đặc biệt phần refresh token. Viết một test fail tái hiện lỗi, rồi sửa”

Prompt mơ hồ vẫn có chỗ dùng: khi bạn đang khám phá và chấp nhận điều chỉnh dần. Câu như "bạn sẽ cải thiện gì trong file này?" có thể lộ ra những thứ bạn chưa nghĩ tới.

  • Tham chiếu file bằng @ thay vì mô tả code nằm ở đâu - Claude đọc file trước khi trả lời.
  • Dán ảnh trực tiếp - copy/paste hoặc kéo-thả vào ô nhập.
  • Đưa URL tài liệu, API reference. Dùng /permissions để allowlist các domain hay dùng.
  • Pipe dữ liệu vào: cat error.log | claude.
  • Để Claude tự lấy ngữ cảnh - bảo nó tự tìm bằng lệnh Bash, MCP tool, hoặc đọc file.

Xem chi tiết ở Bộ nhớ với CLAUDE.md. Điểm quan trọng nhất: giữ ngắn. Với mỗi dòng, hãy tự hỏi “bỏ dòng này đi thì Claude có mắc lỗi không?” - nếu không, cắt. File CLAUDE.md phình to khiến Claude bỏ qua chính những chỉ dẫn bạn cần nhất.

✅ Nên có ❌ Không nên có
Lệnh Bash mà Claude không thể tự đoán Bất cứ thứ gì Claude tự đọc code là biết
Quy tắc code style khác với mặc định Quy ước ngôn ngữ tiêu chuẩn Claude đã biết
Cách chạy test, test runner ưu tiên Tài liệu API chi tiết (hãy link tới docs)
Quy tắc repo (đặt tên branch, quy ước PR) Thông tin thay đổi thường xuyên
Quyết định kiến trúc riêng của dự án Giải thích dài dòng, tutorial
Điểm “lạ” của môi trường dev (biến env bắt buộc) Mô tả từng file trong codebase
Các bẫy thường gặp, hành vi không hiển nhiên Lời khuyên sáo rỗng kiểu “viết code sạch”

Nếu Claude liên tục làm điều bạn không muốn dù đã có quy tắc - khả năng cao file quá dài và quy tắc bị lạc mất. Nếu Claude hỏi bạn điều mà CLAUDE.md đã trả lời - chắc là câu chữ chưa rõ. Hãy đối xử với CLAUDE.md như code: review khi có vấn đề, tỉa định kỳ, và kiểm chứng thay đổi bằng cách quan sát xem hành vi Claude có thật sự đổi.

Mặc định Claude Code xin phép trước mọi hành động có thể thay đổi hệ thống. An toàn, nhưng mệt - đến lần duyệt thứ mười thì bạn không còn review nữa, chỉ bấm cho xong. Ba cách giảm gián đoạn:

  • Auto mode - một model phân loại riêng xem trước từng lệnh và chỉ chặn thứ trông rủi ro (leo thang phạm vi, hạ tầng lạ, hành động bị nội dung độc hại điều khiển).
  • Allowlist quyền - cho phép sẵn các tool bạn biết là an toàn, ví dụ npm run lint, git commit.
  • Sandbox - cô lập ở mức OS, giới hạn truy cập filesystem và mạng, để Claude làm tự do hơn trong ranh giới đã định.

Xem Lệnh & chế độ quyền hạnCấu hình.

CLI tool là cách tiết kiệm ngữ cảnh nhất để tương tác với dịch vụ ngoài. Dùng GitHub thì cài gh - Claude biết dùng nó để tạo issue, mở PR, đọc comment. Không có gh, Claude vẫn gọi được GitHub API nhưng request không xác thực thường bị rate limit.

Claude cũng học CLI mới rất nhanh: dùng 'foo-cli-tool --help' để tìm hiểu công cụ foo, rồi dùng nó giải quyết A, B, C.

  • MCP server - cho Claude đọc issue tracker, truy vấn database, lấy thiết kế Figma. Kết nối bằng claude mcp add, ví dụ claude mcp add --transport http notion https://mcp.notion.com/mcp.
  • Hooks - dùng cho việc phải xảy ra mỗi lần, không ngoại lệ. Khác CLAUDE.md (mang tính khuyến nghị), hooks là tất định. Claude tự viết hook được: “viết một hook chạy eslint sau mỗi lần sửa file”.
  • Skill - đóng gói kiến thức domain và quy trình lặp lại vào .claude/skills/, nạp theo yêu cầu chứ không phình mọi hội thoại.
  • Subagent - trợ lý chuyên biệt trong ngữ cảnh riêng, với bộ tool riêng.

Chạy /plugin để duyệt marketplace. Plugin đóng gói skill, hook, subagent, và MCP server thành một gói cài sẵn từ cộng đồng hoặc từ Anthropic, không cần tự cấu hình. Nếu bạn làm việc với ngôn ngữ có kiểu tĩnh, cài thêm một code intelligence plugin để Claude điều hướng theo symbol chính xác và tự phát hiện lỗi type sau khi sửa.

Hỏi về codebase như hỏi một senior engineer

Phần tiêu đề “Hỏi về codebase như hỏi một senior engineer”

Khi mới vào một codebase, dùng Claude Code để học và khám phá. Cứ hỏi đúng những gì bạn sẽ hỏi một đồng nghiệp:

  • Logging hoạt động thế nào?
  • Làm sao tạo một API endpoint mới?
  • async move { ... } ở dòng 134 của foo.rs làm gì?
  • CustomerOnboardingFlowImpl xử lý những edge case nào?
  • Sao đoạn này gọi foo() mà không gọi bar() ở dòng 333?

Không cần prompt đặc biệt gì cả. Đây là cách onboarding hiệu quả: rút ngắn thời gian làm quen và giảm tải cho các engineer khác.

Với tính năng lớn, hãy để Claude phỏng vấn bạn trước. Bắt đầu bằng một prompt tối giản:

Tôi muốn xây [mô tả ngắn]. Hãy phỏng vấn tôi thật chi tiết bằng tool AskUserQuestion.
Hỏi về cách triển khai kỹ thuật, UI/UX, edge case, những điểm đáng lo và các đánh đổi.
Đừng hỏi những câu hiển nhiên - hãy đào vào những phần khó mà tôi có thể chưa nghĩ tới.
Cứ phỏng vấn đến khi đã bao hết mọi thứ, rồi viết một spec đầy đủ vào SPEC.md.

Xong spec, hãy mở phiên mới để thực thi: ngữ cảnh sạch, tập trung hoàn toàn vào triển khai, và bạn đã có spec viết ra để đối chiếu. Spec hữu ích nhất là spec tự chứa: nêu tên file và interface liên quan, nói rõ cái gì ngoài phạm vi, và kết thúc bằng một bước kiểm chứng end-to-end chứng minh tính năng chạy được.

Hội thoại được lưu bền và có thể quay ngược - hãy lợi dụng điều đó. Xem thêm Quản lý phiên làm việc.

Kết quả tốt nhất đến từ vòng phản hồi chặt. Sửa hướng ngay khi bạn thấy Claude đi lệch:

  • Esc - dừng Claude giữa hành động. Ngữ cảnh được giữ, bạn chuyển hướng được.
  • Esc hai lần hoặc /rewind - mở menu tua lại, phục hồi hội thoại và code về trạng thái trước.
  • "undo that" - bảo Claude hoàn tác thay đổi của nó.
  • /clear - reset ngữ cảnh giữa các tác vụ không liên quan.

Quản lý ngữ cảnh một cách quyết liệt

Phần tiêu đề “Quản lý ngữ cảnh một cách quyết liệt”
  • /clear thường xuyên giữa các tác vụ.
  • Khi auto compaction kích hoạt, Claude tóm tắt phần quan trọng nhất (pattern code, trạng thái file, quyết định chính).
  • Muốn kiểm soát hơn: /compact <chỉ dẫn>, ví dụ /compact tập trung vào các thay đổi API.
  • Chỉ nén một phần hội thoại: Esc + Esc hoặc /rewind, chọn một checkpoint rồi chọn Summarize from here (nén từ điểm đó về sau) hoặc Summarize up to here (nén phần trước, giữ nguyên phần gần đây).
  • Tuỳ biến hành vi compaction bằng chỉ dẫn trong CLAUDE.md, ví dụ “Khi compact, luôn giữ đầy đủ danh sách file đã sửa và các lệnh test”.
  • Câu hỏi nhanh không cần lưu vào ngữ cảnh: dùng /btw - câu trả lời hiện trong overlay và không bao giờ vào lịch sử hội thoại.

Vì ngữ cảnh là ràng buộc cốt lõi, subagent là một trong những công cụ mạnh nhất. Khi Claude nghiên cứu codebase nó đọc rất nhiều file - tất cả đều ngốn ngữ cảnh của bạn. Subagent chạy trong ngữ cảnh riêng và chỉ báo về bản tóm tắt:

Dùng subagent để tìm hiểu hệ thống auth của chúng ta xử lý refresh token thế nào,
và xem đã có utility OAuth nào có thể tái dùng chưa.

Cũng dùng được để kiểm chứng sau khi Claude triển khai: dùng một subagent review đoạn code này xem có edge case nào không.

Mỗi prompt bạn gửi tạo một checkpoint. Claude tự snapshot file trước mỗi thay đổi. Nhấn Esc hai lần hoặc /rewind để mở menu: phục hồi chỉ hội thoại, chỉ code, cả hai, hoặc tóm tắt từ một tin nhắn.

Nhờ vậy bạn không cần tính toán cẩn thận từng bước - cứ bảo Claude thử một hướng mạo hiểm, không được thì tua lại và thử cách khác. Checkpoint được lưu cùng hội thoại nên bạn tắt terminal, resume sau, vẫn tua lại được.

Terminal window
# Truy vấn một lần
claude -p "Dự án này làm gì?"
# Output có cấu trúc cho script
claude -p "Liệt kê mọi API endpoint" --output-format json
# Streaming để xử lý thời gian thực
claude -p "Phân tích file log này" --output-format stream-json --verbose

Lệnh đầu in text thuần. json trả một object JSON có field result. stream-json in một object JSON mỗi dòng, bắt đầu bằng một event init. Lần chạy vẫn tạo phiên resume được, trừ khi bạn truyền --no-session-persistence.

Chọn cách phù hợp với mức độ bạn muốn tự phối hợp:

  • Worktree - nhiều phiên CLI trên các checkout git cô lập, không đụng nhau.
  • Desktop app - quản lý nhiều phiên cục bộ bằng giao diện, mỗi phiên một worktree.
  • Claude Code on the web - chạy phiên trên hạ tầng cloud của Anthropic, mỗi phiên một VM cô lập.
  • Agent teams - tự động phối hợp nhiều phiên với task dùng chung, nhắn tin và một team lead.

Ngoài chuyện song song hoá, nhiều phiên còn mở ra các quy trình tập trung vào chất lượng: ngữ cảnh mới review code tốt hơn vì Claude không bị thiên vị với code chính nó vừa viết. Ví dụ pattern Writer/Reviewer:

Phiên A (Writer) Phiên B (Reviewer)
Triển khai rate limiter cho các API endpoint
Review phần rate limiter ở @src/middleware/rateLimiter.ts. Tìm edge case, race condition, và tính nhất quán với các middleware pattern hiện có.
Đây là phản hồi review: [output phiên B]. Xử lý các vấn đề này.

Làm tương tự với test: một Claude viết test, một Claude khác viết code để pass.

Với migration hoặc phân tích lớn, phân phối việc ra nhiều lần gọi claude -p song song:

  1. Sinh danh sách việc - liệt kê tất cả file Python cần migrate.
  2. Viết script lặp qua danh sách:
    Terminal window
    for file in $(cat files.txt); do
    claude -p "Migrate $file từ React sang Vue. Trả về OK hoặc FAIL." \
    --allowedTools "Edit,Bash(git commit *)"
    done
  3. Thử trên vài file trước, rồi chạy toàn bộ - tinh chỉnh prompt dựa trên những gì sai ở 2-3 file đầu. Cờ --allowedTools giới hạn những gì Claude được làm, rất quan trọng khi chạy không có người ngồi canh.

Cũng nhúng được vào pipeline xử lý dữ liệu có sẵn: claude -p "<prompt>" --output-format json | lệnh_của_bạn. Dùng --verbose khi phát triển, tắt đi khi lên production.

Muốn chạy không gián đoạn nhưng vẫn có kiểm tra an toàn chạy nền, dùng auto mode: một model phân loại riêng xem trước từng lệnh, chặn hành động leo thang phạm vi, nhắm vào hạ tầng lạ, hay có dấu hiệu bị nội dung độc hại điều khiển - trong khi vẫn để việc thường ngày chạy tiếp không cần hỏi.

Terminal window
claude --permission-mode auto -p "sửa hết lỗi lint"

Khi classifier liên tục chặn hành động trong một lần chạy không tương tác (-p), Claude Code không dừng lượt chạy - nó tiếp tục làm việc trong giới hạn được cho phép thay vì treo lại chờ xác nhận.

Claude chạy không giám sát càng lâu, một lượt kiểm tra độc lập trước khi coi việc là xong càng quan trọng. Một reviewer chạy trong ngữ cảnh subagent mới chỉ thấy diff và tiêu chí bạn đưa - không thấy chuỗi suy luận đã tạo ra thay đổi đó - nên nó đánh giá kết quả một cách độc lập.

Muốn kiểm tra tính đúng đắn, chạy skill /code-review có sẵn. Muốn đối chiếu diff với kế hoạch, tự viết prompt review - nêu rõ việc cần kiểm, kế hoạch để đối chiếu, và cái gì được tính là phát hiện:

Dùng subagent review diff của rate limiter đối chiếu với PLAN.md. Kiểm xem
mọi yêu cầu đã được triển khai, các edge case đã liệt kê đều có test, và
không có gì ngoài phạm vi tác vụ bị thay đổi. Báo cáo các thiếu sót,
không báo cáo ý kiến về style.
  • Phiên “bồn rửa bát” - bắt đầu một việc, hỏi sang chuyện không liên quan, rồi quay lại việc đầu. Ngữ cảnh đầy thông tin vô ích. → Sửa: /clear giữa các tác vụ không liên quan.
  • Sửa đi sửa lại - Claude làm sai, bạn sửa, vẫn sai, sửa nữa. Ngữ cảnh nhiễm các hướng thất bại. → Sửa: sau hai lần sửa không thành, /clear và viết prompt ban đầu tốt hơn, gộp những gì bạn vừa học.
  • CLAUDE.md quá chi tiết - file quá dài, Claude bỏ qua một nửa vì quy tắc quan trọng lạc trong tiếng ồn. → Sửa: tỉa mạnh tay. Nếu Claude vốn đã làm đúng mà không cần chỉ dẫn - xoá, hoặc chuyển thành hook.
  • Khoảng trống tin-mà-không-kiểm - Claude tạo ra thứ trông hợp lý nhưng không xử lý edge case. → Sửa: luôn cung cấp phép kiểm chứng (test, script, ảnh chụp). Không kiểm chứng được thì đừng ship.
  • Khám phá vô tận - bạn bảo Claude “điều tra” mà không khoanh phạm vi; nó đọc hàng trăm file và làm đầy ngữ cảnh. → Sửa: khoanh phạm vi hẹp, hoặc dùng subagent để việc khám phá không ngốn ngữ cảnh chính.

Các pattern trong trang này không phải luật bất biến - chúng là điểm khởi đầu thường hiệu quả, nhưng không tối ưu cho mọi tình huống.

Đôi khi bạn nên để ngữ cảnh tích tụ, vì bạn đang đào sâu vào một vấn đề phức tạp và lịch sử đó có giá trị. Đôi khi nên bỏ qua việc lập kế hoạch và để Claude tự mò, vì tác vụ mang tính thăm dò. Đôi khi một prompt mơ hồ lại đúng, vì bạn muốn xem Claude hiểu vấn đề thế nào trước khi ràng buộc nó.

Hãy để ý điều gì hiệu quả. Khi Claude cho ra kết quả tốt, nhìn lại xem bạn đã làm gì: cấu trúc prompt, ngữ cảnh bạn cung cấp, chế độ bạn đang dùng. Khi Claude gặp khó, hỏi tại sao - ngữ cảnh quá nhiễu? Prompt quá mơ hồ? Tác vụ quá lớn cho một lượt?