cat blog/.md
Tìm hiểu folder .claude: cấu trúc và cấu hình Claude Code
Lần đầu mở một project có dùng Claude Code, mình nhìn vào folder .claude/ và hoang mang: có agents/, skills/, hooks/, hai file settings.json và settings.local.json, một worktrees/ rỗng. Không có tài liệu nào ở chỗ dễ thấy giải thích cái nào nên commit, cái nào nên cho vào .gitignore, cái nào dùng chung, cái nào cá nhân. Sau vài lần tự mày mò và gây phiền cho team (commit nhầm cấu hình cá nhân, ghi đè cấu hình chung của team), mình ngồi xuống đọc kỹ và tự viết ghi chú. Bài này là ghi chú đó, chỉnh lại cho ai cũng dùng được.
Hai vị trí: global và project
Claude Code đọc cấu hình từ hai cấp:
- Global:
~/.claude/— thuộc về user, không commit, chứa cấu hình cá nhân và runtime state. - Project:
{repo}/.claude/— thuộc về project, commit được, dùng chung với team.
Khi có xung đột, cấu hình ở project sẽ override cấu hình global. Cách hoạt động giống Git config (~/.gitconfig vs {repo}/.git/config), hoặc ESLint (~/.eslintrc vs file trong project).
Nguyên tắc đơn giản mình tự đặt: cái gì team cần cùng tuân theo thì nằm ở project, cái gì của riêng mình thì nằm ở global hoặc file .local.
Folder ~/.claude/ — global
Folder này Claude Code tự tạo ra khi bạn cài CLI. ls qua sẽ thấy nhiều thứ:
~/.claude/
├── settings.json # config cá nhân (model default, theme...)
├── projects/ # lịch sử conversation theo từng project
├── sessions/ # session đang mở
├── todos/ # todo list của mỗi session
├── plans/ # plan do agent tạo ra
├── skills/ # skill cá nhân (dùng ở mọi project)
├── plugins/ # plugin cài từ marketplace
├── file-history/ # snapshot file Claude đã edit
├── shell-snapshots/ # state shell khi agent chạy Bash
├── telemetry/ # data usage
├── backups/ # backup định kỳ
└── history.jsonl # history lệnh đã gõ
Đa phần là runtime state — đừng đụng vào. Thứ bạn thực sự nên quan tâm chỉ có ba:
settings.json — cấu hình cá nhân. Ví dụ theme, model mặc định, danh sách công cụ tin cậy riêng (ví dụ bạn muốn cho phép Bash(docker compose:*) ở mọi project mà không cần khai lại từng project một).
skills/ — skill cá nhân dùng được ở mọi project. Mình để đây: /commit, /review-pr, /explain-diff. Cấu trúc đã nói kỹ trong bài cấu trúc SKILL.md.
projects/ — mỗi project bạn từng mở có một folder con chứa lịch sử trò chuyện. Đường dẫn được mã hóa: /Users/kyro/work/my-app → -Users-kyro-work-my-app. Biết quy tắc này có ích khi bạn muốn mở lại cuộc trò chuyện cũ.
Phần còn lại (file-history/, shell-snapshots/, telemetry/) là dữ liệu phụ trợ. Không commit, không sửa tay. Muốn dọn bớt dung lượng? Xóa backups/ cũ là đủ.
Folder {project}/.claude/ — project
Đây mới là nơi đáng đầu tư. Cấu trúc điển hình:
.claude/
├── settings.json # config team dùng chung (commit)
├── settings.local.json # override cá nhân (gitignore)
├── agents/ # subagent của project (commit)
├── skills/ # skill của project (commit)
├── hooks/ # hook script (commit)
└── worktrees/ # worktree metadata (gitignore)
settings.json. Config team dùng chung. Ví dụ từ project mình:
{
"permissions": {
"allow": [
"Bash(docker compose:*)",
"Bash(npx nuxi:*)",
"mcp__playwright__browser_navigate"
]
},
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": "bash .claude/hooks/check-claude-md.sh"
}
]
}
]
},
"enabledPlugins": {
"github@claude-plugins-official": true
}
}
Ba thứ chính:
permissions.allow: cấp phép trước một số công cụ cho project này. Ai trong team cũng dùng Docker, nên cho phép sẵnBash(docker compose:*)để đỡ phải xác nhận mỗi lần.hooks: script chạy tự động theo sự kiện. Ở đây mình cóPostToolUse— sau mỗi lần agent Edit/Write file, hệ thống sẽ chạycheck-claude-md.shđể nhắc cập nhật fileCLAUDE.mdtương ứng.enabledPlugins: plugin bật cho project này.
settings.local.json. Cấu hình cá nhân override lên cấu hình chung, bắt buộc cho vào .gitignore. Đây là nơi bạn thêm quyền tạm thời, cho phép công cụ riêng, đặt khác đồng đội mà không phiền ai. Định dạng giống settings.json, các giá trị trùng sẽ override.
.gitignore tối thiểu:
.claude/settings.local.json
.claude/worktrees/
.claude/.DS_Store
agents/. Subagent — một dạng agent con mà main agent giao việc cho. Mỗi subagent là một folder có file Markdown mô tả vai trò. Project mình có: docker-ops, migration-writer, schema-sync, security-auditor, test-writer, api-contract-designer… Khi main agent gặp việc phù hợp, nó giao cho subagent chuyên biệt thay vì tự làm. Tách việc rõ, ngữ cảnh của main agent không bị ngập. Cách thiết kế AGENT.md, chọn model, thu hẹp danh sách công cụ, và những bẫy hay gặp mình đã mổ xẻ trong bài subagent Claude Code.
skills/. Giống skill global nhưng chỉ áp dụng trong project này. Project mình có /create-pr, /commit (override skill mặc định bằng quy ước của team), /dev-flow, /qa-tester…
hooks/. Shell script chạy theo sự kiện. Ví dụ check-claude-md.sh của mình kiểm tra sau mỗi lần Edit/Write xem có cần cập nhật phần nào trong CLAUDE.md không, in cảnh báo nếu có. Hook là cách tốt nhất để bắt buộc tuân theo quy ước mà không phụ thuộc vào việc agent “nhớ” quy tắc. Các sự kiện chính (PreToolUse, PostToolUse, UserPromptSubmit…), định dạng JSON đầu vào, và vài tình huống thực dụng mình đã đi kỹ ở bài hooks trong Claude Code.
worktrees/. Metadata của Git worktree do Claude Code tạo khi dùng chế độ isolation: worktree. Runtime state, cho vào .gitignore.
File CLAUDE.md — nơi ghi kiến thức về codebase
Không nằm trong folder .claude/ nhưng thuộc cùng hệ sinh thái này. CLAUDE.md là file Markdown đặt ở thư mục gốc của repo (và có thể đặt thêm ở subfolder), tự động được nạp vào ngữ cảnh mỗi khi Claude Code làm việc với file trong thư mục đó.
Nội dung nên có:
- Công nghệ và quy ước đang dùng (Python 3.12, kiến trúc layered của FastAPI…)
- Cấu trúc thư mục và trách nhiệm từng module
- Những pattern quan trọng (đặt tên, xử lý lỗi, ghi log)
- Lệnh dev thường dùng (
docker compose up, chạy test, migrate) - Những thứ đã thống nhất nhưng không tự suy ra được từ code (chế độ của PgBouncer, vị trí định nghĩa event schema…)
Monorepo thì mỗi service/app có CLAUDE.md riêng, cộng thêm CLAUDE.md chung ở thư mục gốc. Claude Code tự merge theo scope — bạn đang làm file trong backend/identity/ thì cả CLAUDE.md gốc lẫn backend/identity/CLAUDE.md đều được nạp vào.
Mẹo cá nhân: viết CLAUDE.md như viết tài liệu hướng dẫn cho thành viên mới. Viết xong tự đọc lại, hỏi “nếu quên sạch project này thì đọc doc này có đủ để làm được task đầu tiên không?”.
Cái gì commit, cái gì không
Checklist mình dùng:
Commit:
.claude/settings.json.claude/agents/,.claude/skills/,.claude/hooks/- Mọi
CLAUDE.mdở root và subfolder
Gitignore:
.claude/settings.local.json.claude/worktrees/.claude/.DS_Store- Không bao giờ commit cái gì từ
~/.claude/
Bẫy dễ dính:
- Commit
settings.local.jsonchứa quyền quá rộng → đồng đội bỗng dưng được cấp sẵn những quyền mà bạn tự duyệt cho riêng mình. - Viết hook gọi công cụ chỉ cài trên máy bạn (
brew install xxx) → máy đồng đội chạy hook lỗi. - Nhét secret vào
CLAUDE.md— nhớ file này được Claude Code đọc mỗi session, và cũng được commit lên repo. Secret lộ như thường.
Tổ chức cho team
Sau vài tháng, đây là bố cục mình thấy hợp lý:
CLAUDE.mdở thư mục gốc mô tả tổng quan, link sang tài liệu chi tiết.- Mỗi service/app có
CLAUDE.mdriêng kèm architecture index (file/module quan trọng, pattern). .claude/settings.jsonquy định quyền và hook cơ bản cho cả team..claude/skills/chứa slash command theo quy trình team:/commit,/create-pr,/dev-flow..claude/agents/chứa subagent chuyên môn hóa:migration-writer,security-auditor..claude/hooks/check-claude-md.shvà các hook khác để nhắc cập nhật tài liệu.
Setup này ngốn khoảng nửa ngày ban đầu. Đổi lại, mỗi dev mới clone về là agent đã “hiểu” project — không phải giải thích lại từ đầu mỗi session, không phải copy-paste quy ước từ Notion. Thời gian onboarding thành viên mới từ 2 tuần xuống còn 3-4 ngày. Đó là khoản đầu tư có lợi nhất mình thấy từ việc dùng công cụ AI năm nay.
cat comments.log