Bạn đã cấu hình CLAUDE.md, viết rules, có lẽ đã nghịch hooks. Nhưng settings.json vẫn còn là file bạn chưa thực sự đọc kỹ, chỉ copy từ ví dụ đâu đó rồi để đó. Bài này mổ xẻ các field load-bearing thật sự, field nào có thể crash behavior nếu cấu hình sai, và anti-pattern phổ biến nhất liên quan đến commit secrets.
Ba file settings là ba lớp kiểm soát độc lập. Hiểu thứ tự precedence của chúng là điều kiện để debug “tại sao setting của tôi không ăn”.
Ba mức settings và thứ tự precedence
+----------------------------------------------+
| settings.local.json (per-machine, gitignored)|
| overrides |
+----------------------------------------------+
| .claude/settings.json (project, tracked) |
| overrides |
+----------------------------------------------+
| ~/.claude/settings.json (global) |
+----------------------------------------------+
| File | Phạm vi | Commit được không? |
|---|---|---|
~/.claude/settings.json | Global, mọi session trên máy này | Có (private repo riêng) |
<project>/.claude/settings.json | Project, tất cả người dùng clone | Có |
<project>/.claude/settings.local.json | Project, chỉ máy này | KHÔNG, phải gitignore |
Rule đơn giản: local > project > global. Khi cùng một key xuất hiện ở nhiều mức, local thắng. Điều này cho phép mỗi dev override project setting mà không cần sửa file được commit.
settings.local.json là nơi bạn để MCP config nhạy cảm, API key, hoặc toggle thực nghiệm mà bạn không muốn đồng nghiệp kế thừa. Add nó vào .gitignore ngay từ đầu, đừng chờ đến khi commit nhầm.
Field permissions
Đây là field quan trọng nhất cho an toàn và developer experience hàng ngày.
allow: giảm ma sát khi làm việc
"permissions": {
"allow": [
"Bash",
"Edit",
"Read",
"Write",
"WebFetch",
"WebSearch",
"Glob",
"Grep",
"Task",
"Monitor"
]
}
Mỗi entry trong allow là một pattern tool. Khi CC định gọi một tool khớp pattern trong allow, nó tự động approve mà không hỏi. Điều này tránh màn hình xác nhận liên tục khi đang làm việc.
Pattern có hai dạng:
- Tool name thuần:
"Bash"cho phép mọi bash command. - Tool name có argument:
"Bash(npm test)"chỉ cho phép lệnhnpm test, không mở rộng hơn. - Wildcard:
"WebFetch(https://docs.anthropic.com/**)"chỉ cho phép fetch từ domain đó.
Ví dụ setup an toàn cho project có test suite:
"allow": [
"Read",
"Bash(npm test)",
"Bash(npm run lint)",
"Bash(git status)",
"Bash(git diff *)"
]
Session này CC được đọc file, chạy test, chạy lint, xem git status, nhưng mọi thứ khác đều phải hỏi.
deny: hard block không override được
"deny": [
"Bash(aws s3 rm *)",
"Bash(aws s3 rb *)",
"Bash(aws s3api delete-bucket *)",
"Bash(aws s3api delete-object *)"
]
deny thắng allow trong mọi tình huống. Kể cả khi user gõ lệnh trực tiếp, kể cả khi agent chạy với bypassPermissions, lệnh match deny vẫn bị chặn.
Đây là sự khác biệt quan trọng: allow chỉ là shortcut để skip prompt. deny là hard wall, không bypass được từ trong session. Xem bài 4 để biết incident cụ thể khiến các rule deny này ra đời.
defaultMode: cấp độ mặc định cho mọi tool
"defaultMode": "default"
| Giá trị | Hành vi |
|---|---|
default | Hỏi user trước mỗi tool call không có trong allow. |
acceptEdits | Tự động approve Edit và Write, vẫn hỏi với Bash. |
bypassPermissions | Auto-approve tất cả, kể cả Bash. Cực kỳ nguy hiểm. |
plan | Chỉ cho phép tool read-only, buộc CC dùng plan mode. |
bypassPermissions trong defaultMode là anti-pattern nghiêm trọng. Nếu bạn thấy mình muốn dùng nó để “giảm popup phiền phức”, giải pháp đúng là mở rộng allow list thay vì tắt toàn bộ permission check.
Field hooks
"hooks": {
"WorktreeCreate": [
{
"hooks": [
{
"type": "command",
"command": "$HOME/.claude/hooks/worktree-create.sh",
"timeout": 30
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "$HOME/.claude/hooks/stop-notify-telegram.sh",
"timeout": 10
}
]
}
]
}
hooks là nơi bạn wire shell script vào các lifecycle event của CC. Mỗi event có thể có nhiều hook, chạy theo thứ tự khai báo.
Các event phổ biến:
| Event | Khi nào chạy |
|---|---|
SessionStart | Ngay khi session bắt đầu |
PreToolUse | Trước khi tool được gọi (có thể block tool) |
PostToolUse | Sau khi tool chạy xong |
Stop | Khi CC kết thúc một lượt (assistant done) |
SubagentStop | Khi subagent kết thúc |
WorktreeCreate | Khi tạo worktree mới |
WorktreeRemove | Khi xóa worktree |
PreCompact | Trước khi compaction xảy ra |
Field timeout (giây) là bắt buộc với mọi hook. Hook chạy quá timeout sẽ bị kill. Nếu hook là PreToolUse và bị kill, tool bị block. Chọn timeout thận trọng, đừng để hook notification làm trì hoãn mọi tool call.
Hook nhận JSON từ stdin (chứa event detail, tool name, input). Hook có thể ghi JSON ra stdout để CC đọc, ví dụ để inject thêm context hoặc block tool với message.
Xem bài 9 để đọc chi tiết về lifecycle event, stdin/stdout schema, và các pattern hook thực tế.
Field env
"env": {
"CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS": "1",
"ENABLE_PROMPT_CACHING_1H": "1",
"CLAUDE_CODE_NO_FLICKER": "1",
"CLAUDE_CODE_SUBPROCESS_ENV_SCRUB": "1",
"CLAUDE_CODE_ENABLE_AWAY_SUMMARY": "1"
}
env set biến môi trường cho mọi session khởi động từ settings file này. Chia nhóm để dễ nhớ:
Nhóm performance và cache
| Var | Tác dụng |
|---|---|
ENABLE_PROMPT_CACHING_1H=1 | Cache L1-L4 prompt với TTL 1 giờ thay vì 5 phút mặc định. Giảm latency và cost đáng kể khi làm việc liên tục. Xem bài 5. |
CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY | Số tool được chạy song song. Default 10. Tăng cho agent task nhiều file. |
BASH_DEFAULT_TIMEOUT_MS | Timeout mặc định của Bash tool (ms). Default 120000 (2 phút). |
BASH_MAX_TIMEOUT_MS | Timeout tối đa cho lệnh bash dài. Default 600000 (10 phút). |
Nhóm experimental và tính năng mới
| Var | Tác dụng |
|---|---|
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS=1 | Bật team/teammate mode, dùng được TeamCreate và SendMessage để spawn agent có tên, liên lạc qua nhau. |
CLAUDE_CODE_ENABLE_AWAY_SUMMARY=1 | Tóm tắt session khi bạn quay lại sau khi tab/terminal bị ẩn. |
CLAUDE_CODE_EFFORT_LEVEL | low, medium, high, xhigh, max, auto. Ảnh hưởng đến thinking budget. |
Nhóm telemetry và privacy
| Var | Tác dụng |
|---|---|
DISABLE_TELEMETRY=1 | Tắt toàn bộ telemetry gửi về Anthropic. |
DO_NOT_TRACK=1 | Honor header Do Not Track, tương đương. |
DISABLE_AUTOUPDATER=1 | Tắt auto-update. Dùng khi cần pin version cho CI/CD. |
CLAUDE_CODE_ENABLE_TELEMETRY=1 | Bật OpenTelemetry để export trace sang hệ thống observability của bạn. |
Nhóm debug và logging
| Var | Tác dụng |
|---|---|
CLAUDE_CODE_DEBUG_LOGS_DIR | Path đến thư mục log debug. Hữu ích khi hook hoặc tool behave unexpected. |
CLAUDE_CODE_DEBUG_LOG_LEVEL | verbose, debug, info, warn, error. |
CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1 | Scrub env vars nguy hiểm khi spawn subprocess. Bảo vệ khỏi secret leak qua process tree. |
Các field khác
model: chọn model mặc định
Không phải field model trực tiếp mà qua env var:
"env": {
"ANTHROPIC_MODEL": "claude-opus-4-7"
}
Hoặc dùng lệnh /model trong session để chọn tạm. Thay đổi qua settings.json áp dụng cho mọi session mới từ đó trở đi.
language: ngôn ngữ output
"language": "Vietnamese"
CC sẽ ưu tiên trả lời bằng ngôn ngữ này khi không có chỉ dẫn khác. Giá trị là chuỗi tên ngôn ngữ tiếng Anh: "English", "Vietnamese", "Japanese", v.v.
plugins: bật/tắt từng plugin
"enabledPlugins": {
"typescript-lsp@claude-plugins-official": true,
"hookify@claude-plugins-official": true,
"skill-creator@claude-plugins-official": true,
"security-guidance@claude-plugins-official": true,
"frontend-design@claude-plugins-official": true
}
Format: "<plugin-name>@<registry>". Giá trị true bật, false tắt. Plugin tắt sẽ không load tool, không inject context vào session. Nếu một plugin gây ra slowdown hoặc conflict tool name, set false ở đây thay vì uninstall.
Ví dụ: nếu bạn cài plugin telegram cho một mục đích rồi switch sang cơ chế khác, đặt "telegram@claude-plugins-official": false thay vì gỡ cài đặt. Dễ bật lại khi cần.
autoMemoryDirectory: redirect memory folder
"autoMemoryDirectory": "/path/to/shared/memory"
Theo mặc định CC lưu memory vào ~/.claude/projects/<workdir-hash>/memory/. Field này redirect toàn bộ auto-memory sang một path khác. Dùng để chia sẻ memory giữa nhiều project trên cùng một domain (ví dụ nhiều project cùng công ty dùng chung một memory folder).
Xem bài 12 và bài 14 để hiểu đầy đủ hơn về memory system.
Anti-pattern: commit secrets vào settings.json
Đây là lỗi phổ biến nhất liên quan đến settings.
Nếu bạn nhét ANTHROPIC_API_KEY, database URL, hay token vào env trong settings.json project rồi commit, key đó sẽ tồn tại mãi trong git history dù bạn xóa đi sau đó.
Pattern đúng:
project/
.claude/
settings.json <- commit, env không có secret
settings.local.json <- gitignored, chứa secret của máy này
.gitignore
.claude/settings.local.json
settings.local.json override settings.json cho máy bạn. Bạn đặt key ở đây, commit lên máy bạn không ảnh hưởng đến repo. Người khác clone repo sẽ không có file đó và phải tự tạo cho máy của họ.
Breadcrumb pattern: đặt file settings.local.json.example trong repo (không chứa giá trị thật) để người clone biết cần tạo file đó với các key gì.
Một settings.json tối thiểu cho project team
Đây là cấu hình tối giản an toàn để bắt đầu với project có nhiều người:
{
"permissions": {
"allow": [
"Read",
"Bash(npm test)",
"Bash(npm run lint)",
"Bash(git status)",
"Bash(git diff *)",
"Bash(git log *)"
],
"deny": [],
"defaultMode": "default"
},
"language": "English",
"enableAllProjectMcpServers": false
}
Sau đó từng dev thêm settings.local.json với những gì họ muốn override (model, allow list mở rộng hơn, MCP server riêng, v.v.).
Tóm tắt và bài tiếp theo
- Ba mức settings: global (
~/.claude/settings.json), project (.claude/settings.json), per-machine (.claude/settings.local.json). Thứ tự: local > project > global. permissions.denylà hard wall,permissions.allowchỉ là skip prompt. Deny thắng allow mọi lúc.envtrong settings.json set biến môi trường cho mọi session. Chia nhóm: cache, experimental, telemetry, debug.- Secrets không bao giờ vào
settings.jsonđược commit. Luôn dùngsettings.local.jsonvà gitignore nó. hookswire shell script vào lifecycle event. Xem bài 9 để đọc chi tiết.
Bài 11 sẽ đi vào plugin system: cách CC load plugin, format <name>@<registry>, và cách viết plugin cơ bản để thêm tool hoặc inject context.
Bài thuộc series Claude Code từ zero. Series plan tại bài giới thiệu.