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 đầy đủ mình đang dùng (sau vài lần tổ chức lại):
.claude/
├── README.md # giải thích tổ chức folder cho team mới (commit)
├── settings.json # config team dùng chung — permissions + hooks + statusLine (commit)
├── settings.local.json # override cá nhân (gitignore)
├── statusline.sh # script render statusline ở đáy terminal (commit)
├── rules/ # quy ước cross-cutting — single source of truth (commit)
├── skills/ # capability nhỏ, auto-trigger qua description (commit)
├── commands/ # slash command user gõ thẳng — /commit, /pr... (commit)
├── agents/ # subagent persona/utility (commit)
├── agent-memory/ # bộ nhớ persistent của agent — tự build qua sessions (commit)
├── hooks/ # hook script (commit)
└── worktrees/ # worktree metadata (gitignore)
Hai folder mới nhất mình thêm vào — rules/ và agent-memory/ — là phần quan trọng nhất sau vài tháng nhưng không có trong setup mặc định.
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
rules/ (lớp single source of truth). Đây là folder mình thêm vào sau khi nhận ra skills/agents đang lặp nội dung của nhau. rules/ chứa quy ước cross-cutting: branch strategy, commit convention, PR template, security baseline, coding guide, language conventions. Skills và agents reference file trong rules/ thay vì copy-paste. Đổi rule một chỗ, mọi nơi tự cập nhật. Ví dụ rules/contributing.md, rules/coding-guide.md, rules/security-baseline.md.
skills/ (lớp capability). Procedure atomic — auto-trigger khi description match với task. Project mình có: requirements-analysis, task-planner, backend-coder, unit-testing, security-audit, code-review. Mỗi skill ~150-280 dòng, làm một việc cụ thể. Cấu trúc đã nói kỹ trong bài SKILL.md.
commands/ (lớp user entry point). Slash command user gõ thẳng — /commit, /pr, /branch, /dev-flow. Khác skill ở chỗ: command luôn user-triggered (không auto-trigger), thường là thin shim spawn agent hoặc chứa procedure ngắn. Mình tách commands khỏi skills sau khi nhận ra hai khái niệm bị trộn lẫn — slash command đơn giản dạng /commit thuộc về commands/, capability dạng unit-testing (Claude tự pick khi viết test) thuộc về skills/.
agents/ (lớp role/persona). Subagent có context riêng, tools/permissions thu hẹp. Project mình tách hai loại:
- Personas (workflow dài):
ba(Business Analyst),tl(Tech Lead, model Opus),dev,qa,cr(Code Reviewer, model Opus). - Utility (context protection):
explore(model Haiku) — quét codebase rộng và trả về tóm tắt, tránh ngập context của persona.
Cách thiết kế AGENT.md, chọn model, và spawn subagent từ subagent qua Task tool — mình mổ xẻ trong bài subagent Claude Code.
agent-memory/ (lớp persistent memory). Đây là feature mình suýt bỏ qua nhưng giá trị nhất. Mỗi agent khai báo memory: project trong YAML frontmatter → Claude Code tự load 200 dòng / 25KB đầu của .claude/agent-memory/<agent-name>/MEMORY.md vào system prompt mỗi lần spawn agent. Agent có Read/Write/Edit để tự curate file này.
Ý nghĩa: agent không phải re-scan codebase mỗi lần. explore/MEMORY.md mình seed sẵn architecture summary của các service trong monorepo → first run trả lời ngay từ memory thay vì quét hàng chục file. dev/MEMORY.md chứa các gotchas đặc thù project (vd quy ước về soft-delete, datetime timezone, exception hierarchy). Sau vài session, agent tự thêm pattern mới.
hooks/. Shell script chạy theo sự kiện. Mình có 4 hook đang chạy: block-secrets.sh (chặn đọc .env/secrets), format-on-edit.sh (auto Prettier/Ruff sau Edit/Write), inject-context.sh (đưa branch + uncommitted state vào đầu mỗi prompt), stop-summary.sh (tóm tắt trạng thái khi Claude xong turn). Các sự kiện chính, định dạng JSON đầu vào, và sample script mình đã đi kỹ ở bài hooks trong Claude Code.
statusline.sh. Script render dòng status cố định ở đáy terminal — Claude Code refresh mỗi vài giây. Ví dụ output: 📍 fe:release±2 | be:#1234±3 | mig:feature/xyz±2 | core:main±44. Mình hiển thị git state per service (multi-repo project), tô màu branch theo loại (red cho main, blue cho release, yellow cho dirty). Wire trong settings.json qua "statusLine": { "type": "command", "command": "..." }.
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/README.md.claude/rules/,.claude/skills/,.claude/commands/,.claude/agents/,.claude/hooks/.claude/agent-memory/— bộ nhớ persistent, share qua git để team cùng lợi.claude/statusline.sh- Mọi
CLAUDE.mdở root và subfolder
Gitignore:
.claude/settings.local.json.claude/agent-memory-local/— bộ nhớ scopelocalchỉ riêng máy bạn.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 — 4 lớp khái niệm rõ ràng
Sau vài tháng, mình tổ chức theo 4 lớp khái niệm — mỗi lớp có vai trò không giao nhau:
| Lớp | Vai trò | Khi nào load | Đối tượng |
|---|---|---|---|
| rules/ | Single source of truth — quy ước, conventions | Reference từ skills/agents/commands | Toàn project |
| skills/ | Atomic capability — HOW làm 1 procedure cụ thể (~150-280 dòng) | Auto-load khi description match | Main agent + persona có Skill tool |
| agents/ | Role/persona — WHO làm việc, isolated context, long workflow (~80 dòng) | Spawn qua Task tool | Subagent độc lập |
| commands/ | User entry point — slash command bạn gõ | Load vào main context khi gõ /<name> | User-triggered |
Nguyên tắc tách lớp:
- Rules không copy nội dung vào skills/agents — link bằng path
- Skills không chứa persona — chỉ procedure
- Agents không chứa procedure dài — link skills + giữ persona/gates/completion criteria
- Commands không chứa persona — thin shim spawn agent (cho persona) hoặc procedure ngắn (cho action)
Bố cục hợp lý mình đang dùng:
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/README.mdgiải thích tổ chức folder cho người mới..claude/rules/chứa quy ước cross-cutting: branch, commit, PR, security baseline, coding guide..claude/settings.jsonquy định permissions, hooks, statusLine cho cả team..claude/skills/chứa capability:requirements-analysis,task-planner,backend-coder,unit-testing….claude/commands/chứa slash command:/commit,/pr,/branch,/dev-flow..claude/agents/chứa persona (ba,tl,dev,qa,cr) + utility (explore)..claude/agent-memory/<name>/MEMORY.md— bộ nhớ persistent, seed sẵn cho explore/ba/tl/dev, để qa/cr auto-build..claude/hooks/— 4 hook (block-secrets, format-on-edit, inject-context, stop-summary) wire trong settings.json..claude/statusline.sh— render git state per service ở đáy terminal.
Setup này ngốn khoảng 1-2 ngày ban đầu, nhiều hơn lần đầu mình viết bài này. Lý do tăng: mình tách thêm rules/ và agent-memory/. Đổ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. Quan trọng hơn: agent không phải re-scan codebase mỗi session vì memory đã có sẵn architecture cache. Thời gian onboarding thành viên mới từ 2 tuần xuống còn 3-4 ngày. Đó vẫn 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