TungDaDev's Blog

12 tính năng Claude Code mà kỹ sư nào cũng nên biết

Digital art with text claude code and vibe coding
Published on
/20 mins read/

Cách dùng Claude Code phổ biến nhất có lẽ là thế này: mở terminal, gõ yêu cầu, chờ, đọc, gõ tiếp. Dùng vậy vẫn ra việc, nhưng giống mua cái xe số rồi cả đời chạy số một.

Bài này không định liệt kê cho đủ mười hai món. Mình muốn giải thích vì sao từng tính năng tồn tại, vì khi hiểu được cái máy bên dưới vận hành ra sao thì tự khắc biết lúc nào nên dùng cái gì. Và gần như mọi tính năng ở đây đều xoay quanh một sự thật: context là tài nguyên quý nhất của agent.

Claude Code ra bản mới liên tục. Bài viết dựa trên tài liệu chính thức tại thời điểm tháng 10/2026. Gặp lệnh nào khác đi thì tra docs là chuẩn nhất.


# trước hết: vì sao context quý đến vậy

Ở bài chuyện gì xảy ra khi bạn nhấn Enter mình có kể: model không nhớ gì giữa các lượt. Mỗi lần Claude Code gọi model, nó gửi lại toàn bộ những gì model cần biết: system prompt, nội dung CLAUDE.md, định nghĩa các tool, lịch sử hội thoại, nội dung các file đã đọc, output của các lệnh đã chạy. Một phiên làm việc dài có thể chạm mức hàng trăm nghìn token ở mỗi lượt gọi.

Context đầy thì có ba cái hại. Tốn tiền và chậm, dù prompt caching đỡ được khá nhiều. Model bắt đầu "lạc" giữa mớ thông tin, quên mất lời dặn từ đầu phiên. Và khi chạm giới hạn, Claude Code phải nén (compact) hội thoại, tức là tóm tắt lại và chắc chắn sẽ mất chi tiết.

Giữ trong đầu điều này, phần lớn các tính năng bên dưới sẽ trở nên rất dễ hiểu: hoặc là cách đưa đúng thông tin vào context, hoặc là cách giữ thông tin thừa ở ngoài.


# 1. CLAUDE.md: tài liệu onboarding cho agent

Mỗi phiên, Claude Code bắt đầu với cái đầu trống trơn. Nó không biết project build bằng lệnh gì, đặt tên theo kiểu nào, thư mục nào cấm đụng. CLAUDE.md là chỗ bạn viết những điều đó, và nó được nạp vào context ở đầu mọi phiên.

Cách nạp đáng để hiểu kỹ, vì nó quyết định bạn đặt chỉ dẫn ở đâu. Claude Code đọc CLAUDE.md ở thư mục bạn mở phiên và mọi thư mục cha của nó, rồi nối tất cả lại theo thứ tự từ gốc xuống, chứ không file nào ghi đè file nào. File gần chỗ làm việc nhất nằm cuối, nên được đọc sau cùng. Ngoài ra còn có file cá nhân ở ~/.claude/CLAUDE.md áp cho mọi project, file CLAUDE.local.md cho những ghi chú riêng mà bạn không muốn commit, và ở công ty lớn thì có cả file do bộ phận IT quản lý áp cho mọi người.

CLAUDE.md nằm ở các thư mục con thì không nạp ngay. Nó chỉ được nạp khi Claude đọc hay sửa một file trong thư mục con đó. Với monorepo, đây là cách rất hay: đặt chỉ dẫn riêng của apps/web vào apps/web/CLAUDE.md, khi nào agent đụng vào frontend thì mới tốn context cho nó.

# Project: order-service
 
## Build & test
 
- Build: `./gradlew build`
- Test một class: `./gradlew test --tests "*OrderServiceTest"`
 
## Quy ước
 
- Java 21, Spring Boot 3. Dùng record cho DTO, không dùng Lombok @Data.
- Thay đổi schema phải đi qua migration Flyway trong `src/main/resources/db/migration`.
 
## Đừng đụng vào
 
- `legacy/` đang chờ xoá, không sửa và không tham chiếu tới.
 
Chi tiết về kiến trúc: @docs/architecture.md

Dòng cuối dùng cú pháp @path để nhúng thêm một file khác (lồng tối đa bốn cấp). Tiện để chia nhỏ, nhưng nhớ là file được nhúng vẫn nạp ngay từ đầu, nên không giúp tiết kiệm context. Muốn tiết kiệm thật thì dùng thư mục .claude/rules/: mỗi file một chủ đề, và có thể khai báo paths để file đó chỉ nạp khi agent làm việc với những file khớp mẫu, ví dụ quy tắc viết test chỉ nạp khi đụng vào **/*Test.java.

Gõ /init để Claude Code tự đọc repo và viết bản nháp đầu tiên. Ngoài ra nó còn tự ghi chép (auto memory) những gì học được qua các lần bạn sửa lưng nó, lưu riêng cho từng repo.

Hai lời khuyên theo docs mà mình thấy đúng. Giữ mỗi file dưới khoảng 200 dòng, vì file càng dài thì agent càng hay bỏ qua chỉ dẫn. Và nhớ rằng CLAUDE.md chỉ là lời dặn, không phải luật: thứ gì bắt buộc phải xảy ra thì dùng hooks (mục 8).


# 2. plan mode: sửa kế hoạch rẻ hơn sửa code

Với thay đổi lớn, điều tệ nhất là để agent lao vào sửa code khi nó còn hiểu sai yêu cầu. Mười phút sau bạn nhận về hai chục file sửa theo một hướng mình không muốn, và việc gỡ ra còn mất công hơn tự viết.

Plan mode chặn điều đó. Ở chế độ này agent chỉ được đọc code, tìm hiểu, chạy những lệnh an toàn, chứ không được sửa file. Tìm hiểu xong nó đưa ra một kế hoạch. Bạn đọc, góp ý, chỉnh tới khi ưng, rồi mới duyệt cho nó làm.

claude --permission-mode plan

Hoặc bấm Shift+Tab để chuyển chế độ ngay trong phiên.

Nên coi bản kế hoạch như một design doc thu nhỏ, và review nó kỹ như review design doc thật. Những câu nên tự hỏi khi đọc: nó định sửa những file nào, có file nào lạ không? Nó định viết test ở đâu? Có bước nào đụng tới migration, cấu hình production? Phát hiện sai ở bước này chỉ tốn một câu góp ý. Phát hiện sai sau khi code đã viết xong thì tốn cả buổi.


# 3. chế độ quyền: bao nhiêu tự do là vừa

Mỗi lần agent định sửa file hay chạy lệnh, câu hỏi là có cần hỏi bạn không. Claude Code có sáu chế độ cho câu hỏi đó:

chế độđược làm mà không hỏihợp với
Manual (default)Chỉ đọcCode nhạy cảm, codebase lạ
acceptEditsĐọc, sửa file, vài lệnh file cơ bản như mkdir, mv, cpĐang làm cùng và review từng thay đổi
planĐọc và lên kế hoạch, không sửaTìm hiểu trước khi thay đổi
autoMọi thứ, có một model phân loại kiểm tra an toàn chạy nềnViệc dài, đỡ phải bấm duyệt liên tục
dontAskChỉ những tool đã cho phép trước, còn lại từ chối thẳngCI, script
bypassPermissionsMọi thứ, không kiểm traChỉ trong container hay VM cô lập

Chế độ auto thú vị nhất. Thay vì bắt bạn bấm "đồng ý" cho từng lệnh, một model phân loại (classifier) đọc từng hành động và chặn những gì có vẻ nguy hiểm. Từ các bản gần đây, đây là chế độ mặc định trong terminal và VS Code. Nó giải quyết một vấn đề rất thật: khi phải bấm duyệt tới lần thứ hai mươi, người ta bắt đầu bấm theo phản xạ, và lúc đó bước duyệt chẳng còn tác dụng gì.

Quan trọng hơn chế độ là luật quyền viết trong settings.json. Luật cấm (deny) có hiệu lực ở mọi chế độ, kể cả bypassPermissions. Nên những thứ tuyệt đối không được làm, như đẩy code thẳng lên nhánh chính hay đọc file .env, hãy viết thành luật cấm thay vì trông cậy vào chế độ.


# 4. checkpoint: nút undo cho agent

Agent sửa một loạt file rồi bạn nhận ra hướng đó sai. Không cần git stash hay sửa tay. Claude Code tự lưu checkpoint trước mỗi lượt bạn gửi yêu cầu.

Bấm Esc hai lần khi ô nhập trống, hoặc gõ /rewind, để mở danh sách các lượt trước. Chọn một lượt, rồi chọn khôi phục code, khôi phục hội thoại, hay cả hai. Trong menu này còn hai tuỳ chọn ít người biết là "tóm tắt từ đây" và "tóm tắt tới đây": nén một đoạn hội thoại dài thành bản tóm tắt để giải phóng context, mà vẫn giữ nguyên những phần khác.

Có mấy giới hạn cần nhớ. Checkpoint chỉ theo dõi những thay đổi qua công cụ sửa file của Claude Code. File bị đổi bằng lệnh shell như rm, mv, hay bởi một bước build, thì không hoàn tác được. Thay đổi do subagent chạy nền thực hiện cũng thường không được khôi phục. Nên checkpoint là nút undo nhanh trong phiên, còn git vẫn là lưới an toàn thật.


# 5. quản lý context: dọn bàn cho agent

Context giống cái bàn làm việc. Bàn càng bừa thì càng dễ lạc đồ. Có ba lệnh nên thuộc.

/context cho bạn thấy context đang bị chiếm bởi những gì: system prompt, CLAUDE.md, định nghĩa tool của các MCP server, hội thoại. Chạy thử một lần, có khi bạn sẽ giật mình vì mấy MCP server cài cho vui đã ăn mất một phần context đáng kể dù chưa từng được dùng.

/compact tóm tắt hội thoại để giải phóng chỗ, và có thể kèm hướng dẫn về điều cần giữ, ví dụ /compact giữ lại thiết kế API và các quyết định đã chốt, bỏ phần debug. /clear xoá sạch để bắt đầu việc mới.

Thói quen quan trọng nhất là mỗi việc một phiên. Làm xong tính năng A thì /clear rồi mới sang tính năng B. Một phiên kéo dài cả ngày với đủ chuyện lẫn lộn là cách chắc chắn nhất để agent làm việc ngày càng tệ dần mà bạn không hiểu vì sao.


# 6. skills: đóng gói quy trình, nạp khi cần

Nếu có quy trình nào bạn hay nhờ agent làm đi làm lại (review PR theo checklist, viết release note, chuẩn bị deploy), hãy đóng thành skill: một thư mục chứa file SKILL.md, đặt trong .claude/skills/ của project hoặc ~/.claude/skills/ để dùng cho mọi project.

Điểm khác biệt lớn nhất của skill so với nhét hết vào CLAUDE.md là cách nạp. Lúc đầu phiên, chỉ có phần mô tả ngắn của mỗi skill nằm trong context. Toàn bộ nội dung chỉ được nạp khi skill thật sự được gọi, bởi bạn gõ /ten-skill hoặc bởi agent tự thấy yêu cầu khớp với mô tả. Vì vậy bạn có thể có hàng chục skill, mỗi skill dài cả trăm dòng, mà gần như không tốn context cho tới khi cần.

---
name: review-pr
description: Review pull request hiện tại theo checklist của team backend. Dùng khi được nhờ review code hoặc trước khi tạo PR.
allowed-tools: Bash(git diff *) Bash(git log *)
---
 
## Thay đổi cần review
 
!`git diff main...HEAD --stat`
 
## Checklist
 
1. Thay đổi schema có migration đi kèm không?
2. Logic mới có test không? Test có kiểm tra trường hợp lỗi không?
3. Có log nào in ra dữ liệu cá nhân không?
4. Có chỗ nào gọi service ngoài mà không có timeout không?
 
Báo cáo theo ba mức: chặn merge, nên sửa, góp ý nhỏ. Nếu không có vấn đề ở mức nào thì nói rõ là không có.

Có hai chi tiết đáng chú ý trong ví dụ. Dòng bắt đầu bằng !` là lệnh shell chạy trước khi nội dung skill được gửi cho model, nên agent nhận được luôn diff mà không phải tốn một lượt tự chạy lệnh. allowed-tools cho phép sẵn những lệnh mà skill cần, chỉ trong lượt đó. Ngoài ra skill còn có thể chạy trong một subagent riêng bằng context: fork, để toàn bộ quá trình đọc code không làm bẩn context của phiên chính.

Commit thư mục .claude/skills/ vào repo là cả team dùng chung một quy trình. Nếu bạn từng dùng custom slash command trong .claude/commands/ thì chúng giờ đã được gộp vào skill, file cũ vẫn chạy bình thường.


# 7. subagents: giao việc mà không làm bẩn context

Subagent là agent phụ chạy với context riêng, system prompt riêng và bộ quyền riêng. Lợi ích lớn nhất không phải chạy song song, mà là cô lập context. Giả sử bạn cần tìm xem một hàm được gọi ở những đâu trong codebase hai trăm nghìn dòng. Để phiên chính tự tìm thì nó đọc ba chục file và context phình lên. Giao cho subagent thì subagent đọc ba chục file đó trong context của nó, rồi chỉ trả về một đoạn kết luận ngắn.

Tự định nghĩa subagent bằng một file trong .claude/agents/:

---
name: security-reviewer
description: Review thay đổi để tìm lỗ hổng bảo mật. Dùng sau mỗi thay đổi đụng tới auth, input người dùng hoặc SQL.
tools: Read, Grep, Glob
model: sonnet
---
 
Bạn là kỹ sư bảo mật. Chỉ báo cáo lỗ hổng có thể khai thác được, kèm file:line, cách khai thác và cách sửa.
Không sửa code. Không báo cáo những vấn đề về style.

Để ý dòng tools: subagent này chỉ được đọc. Dòng model cho phép dùng model khác, rẻ hơn hay nhanh hơn, cho những việc không cần model mạnh nhất. Giới hạn quyền cho từng subagent là thói quen tốt, đúng tinh thần quyền tối thiểu ở bài threat model cho ứng dụng LLM.

Có điều đừng lạm dụng. Mỗi subagent khởi động với context trống, phải đọc lại những gì cần biết, nên với việc nhỏ thì giao đi còn chậm hơn tự làm. Subagent đáng dùng khi việc cần đọc nhiều mà chỉ cần kết luận ngắn, hoặc khi cần một góc nhìn độc lập không bị ảnh hưởng bởi hội thoại trước đó (một reviewer không biết bạn đã cãi nhau với agent ra sao thì review khách quan hơn).


# 8. hooks: những việc bắt buộc phải xảy ra

Dặn trong CLAUDE.md "nhớ chạy formatter sau khi sửa" thì agent có lúc nhớ, có lúc quên. Bản chất của lời dặn là vậy: model đọc nó, không bị ép theo. Với những việc phải luôn xảy ra, dùng hooks: lệnh shell (hoặc HTTP, hoặc một lượt hỏi model) do chính Claude Code thực thi ở những thời điểm xác định trong vòng đời của phiên.

Những sự kiện hay dùng nhất là PreToolUse (trước khi dùng một tool), PostToolUse (sau khi dùng xong), UserPromptSubmit (khi bạn gửi yêu cầu), Stop (khi agent định kết thúc lượt), và SessionStart. Hook nhận thông tin dạng JSON qua stdin, có tên tool, tham số, thư mục làm việc.

Phần quan trọng nhất cần nhớ là exit code. 0 là ổn, cho đi tiếp. 2 là chặn: với PreToolUse thì tool bị chặn, với Stop thì agent bị buộc làm tiếp, và nội dung stderr được đưa cho agent đọc như một lời giải thích. Các mã khác như 1 chỉ là lỗi không chặn, hành động vẫn diễn ra. Viết hook bảo vệ mà exit 1 thì tưởng là chặn, thật ra chẳng chặn gì.

Ví dụ đầu tiên, tự format mọi file agent vừa sửa, khai báo trong .claude/settings.json:

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "jq -r '.tool_input.file_path' | xargs npx prettier --write --ignore-unknown"
          }
        ]
      }
    ],
    "Stop": [
      {
        "hooks": [
          { "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/require-tests.sh" }
        ]
      }
    ]
  }
}

Ví dụ thứ hai mạnh hơn nhiều: hook Stop không cho agent kết thúc khi test còn đỏ. Đây là cách biến câu "nhớ chạy test trước khi báo xong" từ một lời dặn thành một luật:

#!/usr/bin/env bash
# .claude/hooks/require-tests.sh
input=$(cat)
session=$(jq -r '.session_id' <<<"$input")
counter="${TMPDIR:-/tmp}/claude-require-tests-$session"
 
if output=$(npm test --silent 2>&1); then
  rm -f "$counter"
  exit 0
fi
 
# đã chặn 2 lần mà test vẫn đỏ: cho agent dừng để báo lại, tránh vòng lặp vô tận
blocked=$(cat "$counter" 2>/dev/null || echo 0)
if [ "$blocked" -ge 2 ]; then
  rm -f "$counter"
  exit 0
fi
echo $((blocked + 1)) > "$counter"
 
echo "Test đang fail, chưa được kết thúc. Sửa cho test pass rồi hãy báo xong:" >&2
echo "$output" | tail -40 >&2
exit 2   # chặn việc kết thúc, stderr được đưa cho agent đọc

Agent báo "xong rồi" nhưng test đỏ? Hook trả về exit 2, agent đọc 40 dòng log lỗi và phải làm tiếp. Bộ đếm theo session_id là để agent không bị kẹt mãi khi test không thể sửa được: sau hai lần bị chặn, nó được dừng lại và báo tình hình cho bạn. Bản thân Claude Code cũng có lưới an toàn: input của hook Stop có trường stop_hook_active (bằng true khi agent đang chạy tiếp do bị hook chặn), và sau tám lần bị chặn liên tiếp mà agent không gọi tool nào thì Claude Code tự cho kết thúc lượt. Có điều tự đếm như trên thì bạn chủ động chọn ngưỡng dừng.

--ignore-unknown ở ví dụ format là để prettier bỏ qua những file nó không hiểu (.java, .sql...), thay vì báo lỗi sau mỗi lần agent sửa chúng.

Một ý tưởng nữa: hook PreToolUse cho Edit với điều kiện đường dẫn nằm trong db/migration/, trả về quyết định deny kèm lý do. Migration đã chạy trên production sẽ không bao giờ bị sửa, bất kể agent đang ở chế độ nào.


# 9. MCP: nối agent với công cụ của team

MCP (Model Context Protocol) là chuẩn mở để kết nối agent với công cụ bên ngoài. Qua MCP, Claude Code đọc được ticket Jira, tài liệu trên Google Drive, lỗi trên Sentry, dữ liệu trong database, thay vì bạn copy dán vào.

claude mcp add --transport http <ten-server> <url-cua-mcp-server>
claude mcp list

Tool của MCP server hiện ra với tên dạng mcp__<server>__<tool>, nên viết luật quyền hay hook cho chúng cũng theo đúng mẫu đó, ví dụ chặn mọi tool ghi của một server bằng mcp__jira__.* kết hợp với kiểm tra tên tool.

Hai điều nên nhớ. Mỗi MCP server đưa định nghĩa tool của nó vào context, nên cài càng nhiều thì context càng chật, dùng /context để xem và gỡ những server không cần. Và mô tả tool của một server lạ cũng là nội dung không tin cậy, có thể chứa lệnh ẩn. Chỉ cài server từ nguồn bạn tin. Mình có bài riêng về Model Context Protocol nếu bạn muốn hiểu bên dưới nó hoạt động thế nào.


# 10. headless: Claude Code trong script và CI

Với cờ -p, Claude Code chạy một lần, in kết quả ra rồi thoát, hợp để ghép vào script hay pipeline theo đúng tinh thần Unix:

# phân tích log
tail -200 app.log | claude -p "tóm tắt các lỗi lặp lại nhiều nhất và nguyên nhân có thể"
 
# review các file vừa đổi, lấy kết quả dạng JSON để xử lý tiếp
git diff main --name-only | claude -p "review các file này, chỉ báo vấn đề bảo mật" --output-format json
 
# chạy trong CI với quyền giới hạn chính xác
claude -p "chạy test và tóm tắt các test fail" --permission-mode dontAsk --allowedTools "Bash(npm test)" "Read"

Ví dụ cuối là cách nên dùng trong CI: chế độ dontAsk với danh sách tool được phép rõ ràng. Thứ gì ngoài danh sách bị từ chối thẳng, thay vì treo pipeline chờ một người không bao giờ tới bấm duyệt. Claude Code còn có tích hợp sẵn với GitHub Actions và GitLab CI/CD để review PR hay xử lý issue tự động.


# 11. chạy song song nhiều phiên

Một agent làm một việc thì bạn ngồi chờ. Nhiều agent làm nhiều việc song song thì bạn thành người điều phối. Claude Code có vài cách hỗ trợ: chạy agent nền và theo dõi nhiều phiên trên một màn hình, giao việc dài cho bản chạy trên web rồi kéo về terminal sau.

Nguyên tắc không đổi dù dùng cách nào: mỗi agent một working directory riêng. Hai agent cùng sửa một thư mục thì sớm muộn cũng giẫm chân nhau. Cách cơ bản và chắc chắn nhất là git worktree:

git worktree add ../shop-payment -b feat/payment-retry
git worktree add ../shop-search -b feat/search-filter
 
cd ../shop-payment && claude   # phiên 1
cd ../shop-search && claude    # phiên 2, ở terminal khác

Lưu ý nhỏ: CLAUDE.local.md bị gitignore nên chỉ tồn tại ở worktree nơi bạn tạo nó. Muốn chia sẻ ghi chú cá nhân giữa các worktree thì để chúng trong một file ở thư mục home rồi nhúng bằng @.

Từ ba phiên trở lên, việc biết phiên nào đang chờ bạn duyệt bắt đầu khó. Mình có viết về Herdr, một terminal multiplexer làm riêng cho việc trông nhiều agent cùng lúc.


# 12. lên lịch: để agent làm việc khi bạn không ngồi đó

Có những việc nên làm đều đặn: review PR mỗi sáng, phân tích CI fail mỗi đêm, rà dependency mỗi tuần. Claude Code có hai cách chính.

/loop lặp lại một yêu cầu ngay trong phiên đang mở, hợp cho canh chừng ngắn hạn kiểu "cứ 5 phút kiểm tra deploy một lần, xong thì báo". Tắt phiên là nó dừng.

Routines thì chạy trên cloud theo lịch, nên vẫn chạy khi bạn đã tắt máy. Tạo từ web, từ app desktop, hoặc gõ /schedule trong CLI. Routine còn chạy được theo sự kiện, như khi có PR mới trên GitHub.

Ghép với skill ở mục 6: lên lịch cho /review-pr chạy mỗi sáng là đến công ty đã có bản review sơ bộ chờ sẵn. Bài xây đội nhân viên AI cho team IT có thêm nhiều ý tưởng cho kiểu tự động hoá này.


# nên bắt đầu từ đâu

Nếu chỉ chọn ba thứ làm ngay tuần này: viết một CLAUDE.md gọn dưới 200 dòng cho project chính, tập thói quen dùng plan mode cho mọi thay đổi đụng từ ba file trở lên, và nhớ Esc hai lần khi agent đi sai hướng. Quen rồi thì viết hook Stop bắt chạy test, vì nó thay đổi chất lượng đầu ra nhiều hơn mọi lời dặn trong prompt. Sau đó mới tới skill, subagent và lên lịch.

Tài liệu tham khảo:


Chỉ là những ghi chép cá nhân với hy vọng mang lại chút giá trị. Nếu thấy hữu ích, đừng ngại chia sẻ cho bạn bè & đồng nghiệp nhé!

Happy coding 😎 👍🏻 🚀 🔥.