Hôm qua tôi bảo Claude Code “refactor auth module to use JWT with refresh tokens”, AI phân tích 8 files liên quan, generate middleware, repository, và test suite trong 15 phút. Việc thường mất tôi cả buổi sáng.

Rồi thực tế ập đến: đây là production app với Stripe secret keys trong .env, AWS credentials trong docker-compose.yml, proprietary pricing algorithms trong src/services/pricing/, và hardcoded database passwords nằm rải rác. Tôi muốn năng suất của Claude Code, nhưng không thể giao toàn bộ secrets cho một AI.

Cách thận trọng nhất tôi thử đầu tiên — tạo demo project sạch, copy code qua lại bằng tay — an toàn nhưng giết năng suất. Ngược lại với lý do tôi dùng Claude Code. Vài tháng sau, tôi đã thử qua 4 chiến lược khác nhau, mỗi cái có trade-off riêng. Đây là toàn bộ chúng, xếp hạng theo bảo mật, tốc độ, và độ bền hàng ngày.


Claude Code thực sự “thấy” gì

Trước khi đi vào chiến lược, clarify một điều: Claude Code không tự động scan toàn bộ project của bạn. Nó request permission để đọc file, bạn approve hoặc deny. Có thể tin tưởng được — nếu bạn deny access đến .env, nó không đọc.

Nhưng rủi ro thật nằm ở đây: khi Claude Code cần hiểu kiến trúc hoặc debug lỗi phức tạp, nó request đọc file gần code nhạy cảm. Ranh giới giữa “vô hại” và “chứa secret” không luôn rõ ràng.

Ví dụ thực tế:

# Files AN TOÀN cho Claude Code đọc:
src/services/payment.service.ts # TypeScript interface
app/api/users/route.ts # Next.js API route
lib/repositories/user_repo.dart # Flutter repository
Sources/Services/UserService.swift # iOS service protocol
# Files CHỨA SECRETS — nguy hiểm:
.env # DATABASE_URL, API keys
.env.local # Development overrides
docker-compose.yml # DB passwords, service tokens
src/config/stripe.ts # Hardcoded keys
google-services.json # Android Firebase
GoogleService-Info.plist # iOS Firebase
credentials.json # GCP service account

Code interface vô hại vs config chứa secrets:

// src/services/payment.service.ts — interface vô hại ✅
export interface PaymentService {
charge(amount: number, currency: string): Promise<PaymentResult>;
refund(transactionId: string): Promise<void>;
}
// src/config/stripe.ts — chứa secret ❌
export const stripeConfig = {
publishableKey: "pk_live_...", // OK để public
secretKey: process.env.STRIPE_SECRET_KEY, // OK nếu đọc từ .env
webhookSecret: "whsec_live_abc123...", // hardcoded! nguy hiểm
};

Khi Claude Code thấy error trong payment flow, nó muốn đọc cả hai file. Bạn có chắc luôn bắt được lúc approve hay không?

Đây là lý do tôi thử các chiến lược ngăn chặn vật lý thay vì chỉ dựa vào approve từng file.


Chiến lược 1: Demo Project — Copy bằng “cơm”

Cách hoạt động: Tạo project trắng, copy file cần sửa sang đó, để Claude Code xử lý, rồi copy output ngược lại project thật.

Project thật Demo project sạch
↓ copy ↓
File A (có secret) File A (xóa secret)
↓ ↓
(không chạm) Claude Code edit
↓ copy ngược ↓
File A (merge bằng tay) File A (output)

Trải nghiệm thực tế: Đây là cách đầu tiên tôi thử. An toàn tuyệt đối — Claude Code không bao giờ thấy project thật. Nhưng overhead quá khủng khiếp. Một task “add rate limiting to API endpoints” trở thành:

  1. Copy routes/api.ts, middleware/rateLimit.ts, config/redis.ts sang demo project (2 phút)
  2. Xóa import từ proprietary modules, fake Redis config (5 phút)
  3. Chạy Claude Code, output OK (3 phút)
  4. Copy output ngược, merge conflict bằng tay (10 phút)
  5. Fix import, dependencies, compile errors (15 phút)

Một task 5 phút trở thành 35 phút. Overhead tệ nhưng chưa phải tệ nhất — chất lượng output tệ hơn. Demo project không có đầy đủ context: không có database schemas, không có shared types, không có existing middleware stack. Claude Code generate code hoàn toàn đúng về syntax nhưng sai về architecture vì nó không thấy cách phần còn lại của app hoạt động.

Tiêu chíĐánh giá
Bảo mật⭐⭐⭐⭐⭐ — Hoàn toàn cô lập
Tốc độ⭐ — Overhead 6-7x
Chất lượng output⭐⭐ — Context nghèo nàn
Bền vững hàng ngày⭐ — Quá tốn thời gian

Phù hợp khi: Một lần fix quick bug trên code cực nhạy cảm và không bao giờ lặp lại.


Chiến lược 2: Duplicate Project + Git Patch

Cách hoạt động: Clone project thật, xóa secrets, thêm fake config, làm việc với Claude Code ở đó, sync thay đổi về project thật bằng git patch.

Terminal window
# One-time setup
git clone project.git project-claude
cd project-claude
# Script tự động xóa secrets
./scripts/remove-secrets.sh

Script cleanup universal (remove-secrets.sh):

#!/bin/bash
# Remove all sensitive files
rm -f .env .env.local .env.production
rm -f docker-compose.prod.yml
rm -f credentials.json service-account.json
find . -name "google-services.json" -delete
find . -name "GoogleService-Info.plist" -delete
find . -name "*.keystore" -delete
find . -name "*.jks" -delete
find . -name "*.pem" -delete
find . -name "*.p12" -delete
# Add dummy configs
echo "DATABASE_URL=postgres://user:pass@localhost:5432/mydb" > .env
echo "STRIPE_SECRET_KEY=sk_test_DUMMY_DO_NOT_USE" >> .env
echo "AWS_ACCESS_KEY_ID=DUMMY" >> .env
echo "OPENAI_API_KEY=sk-test-FAKE" >> .env
git add -A && git commit -m "Sanitize for Claude Code"

Daily workflow:

Terminal window
# Làm việc trong project-claude
cd ~/projects/project-claude
# ... Claude Code edit files ...
git diff main > changes.patch
# Apply vào project thật
cd ~/projects/project
git apply changes.patch

Trải nghiệm thực tế: Đây là cải thiện lớn. Tôi có full context — toàn bộ API routes, database models, middleware stack, shared utilities. Claude Code thấy đủ để generate code follow đúng patterns của app. Secrets bị remove vật lý ở workspace khác, nên không có cách nào Claude Code đọc được.

Sync bằng patch hiệu quả hơn copy thủ công 10 lần. Nhưng vẫn có ma sát: mỗi khi project thật nhận update từ team, tôi phải pull ở cả hai workspace và đảm bảo sanitization vẫn đúng. Nếu ai đó thêm secret mới (ví dụ thêm Twilio API key), tôi phải nhớ update script cleanup.

Sau một tháng, tôi có script automation hoàn chỉnh để sync và sanitize. Hoạt động tốt nhưng vẫn phải quản lý hai workspace, hai git states.

Tiêu chíĐánh giá
Bảo mật⭐⭐⭐⭐⭐ — Cô lập vật lý
Tốc độ⭐⭐⭐⭐ — Chỉ overhead nhẹ
Chất lượng output⭐⭐⭐⭐ — Gần đầy đủ context
Bền vững hàng ngày⭐⭐⭐ — Cần automation

Phù hợp khi: Bạn có thời gian setup script automation và cần bảo mật chắc chắn. Cân bằng tốt.


Chiến lược 3: .claudeignore trên Project thật

Cách hoạt động: Làm việc trực tiếp trên project thật, dùng .claudeignore để chặn Claude Code đọc file nhạy cảm. Zero overhead.

Terminal window
# .claudeignore — Universal secrets protection
# Environment variables
.env*
*.env
# Cloud credentials
credentials.json
service-account.json
*.pem
*.key
*.p12
# Mobile platform configs
google-services.json
GoogleService-Info.plist
local.properties
# Keystores & certificates
*.keystore
*.jks
*.pfx
# Infrastructure configs
docker-compose.prod.yml
kubernetes/secrets.yaml
**/vault/**
**/secrets/**
# Proprietary business logic
src/**/trading/**
src/**/pricing-engine/**
src/**/recommendation-algorithm/**
# Build artifacts & dependencies
node_modules/
dist/
build/
.next/
__pycache__/
target/
vendor/

Trải nghiệm thực tế: Nhanh nhất, output tốt nhất, overhead bằng không. Khi bạn cần fix bug, bạn chỉ cần nói với Claude Code. Nó thấy đầy đủ context — architecture, dependencies, patterns — nhưng bị chặn không đọc secrets.

Nhưng tôi phải thành thật về e ngại của mình: đây là ranh giới phần mềm, không phải vật lý. Files vẫn nằm trên ổ đĩa. Tôi tin Anthropic, nhưng tôi không thể verify 100% rằng .claudeignore không bao giờ bị bypass — do bug, do misconfiguration, hoặc do edge case tôi chưa nghĩ ra.

Ví dụ: nếu một file không trong .claudeignore import constants từ file bị ignore, và Claude Code cần hiểu constant đó để fix bug, điều gì sẽ xảy ra? Nó có request đọc file được import không? Tôi không chắc.

Vì vậy tôi dùng chiến lược này cho project cá nhân hoặc side project không có secrets nghiêm trọng. Với production app có real payment keys và production database URLs, tôi chưa yên tâm 100%.

Tiêu chíĐánh giá
Bảo mật⭐⭐⭐ — Tin tưởng implementation
Tốc độ⭐⭐⭐⭐⭐ — Zero overhead
Chất lượng output⭐⭐⭐⭐⭐ — Đầy đủ context
Bền vững hàng ngày⭐⭐⭐⭐⭐ — Workflow tự nhiên

Phù hợp khi: Bạn chấp nhận ranh giới phần mềm. Hoặc project không chứa secrets cực nhạy cảm. Hoặc chính sách công ty cho phép.


Chiến lược 4: Git Worktree + Clean Branch

Cách hoạt động: Dùng git worktree tạo working directory thứ hai trên branch sạch không có secrets. Cùng một repo, hai folders. Bảo mật vật lý + sync hiệu quả.

Terminal window
# One-time setup
cd ~/projects/my-app
git worktree add ../my-app-claude clean-branch
# Ở clean-branch:
cd ~/projects/my-app-claude
./scripts/remove-secrets.sh
git add -A && git commit -m "Sanitize: remove all secrets"
# Daily workflow
cd ~/projects/my-app-claude # Worktree sạch
# ... Claude Code edit ...
git add -A && git commit -m "Add email verification flow"
# Sync về main
cd ~/projects/my-app # Project thật
git cherry-pick <commit-hash> # Chọn commits muốn apply
# Hoặc test trước khi merge
npm test # Verify trong project thật
# pytest # Python
# go test ./... # Go
# ./gradlew test # Android/Java
# swift test # iOS

Trải nghiệm thực tế: Đây là giải pháp thanh lịch mà ít developer biết. Git worktree cho phép checkout hai branches của cùng một repo vào hai folders khác nhau. Không phải clone, không phải duplicate — cùng một .git, hai working directories.

Setup: tôi tạo branch claude-clean, xóa tất cả secrets, commit fake configs. Branch này không bao giờ merge vào main. Mỗi khi làm việc với Claude Code, tôi checkout worktree vào folder riêng:

Terminal window
~/projects/
my-app/ main branch (có secrets)
my-app-claude/ claude-clean branch (không secrets)

Khi Claude Code xong, tôi cherry-pick commit từ claude-clean vào main. Git đủ thông minh để apply code changes mà không apply secret deletions. Nếu có conflict ở secret files, tôi chỉ cần skip.

Ưu điểm lớn: bảo mật vật lý giống Chiến lược 2, nhưng không phải quản lý hai repos. Sync dễ dàng hơn nhiều vì cùng git history. Tôi thậm chí có thể rebase claude-clean lên main thường xuyên để giữ nó updated.

Nhược điểm: cần thành thạo git. Nếu chưa quen cherry-pick, rebase, hoặc worktree, learning curve hơi dốc.

Tiêu chíĐánh giá
Bảo mật⭐⭐⭐⭐⭐ — Cô lập vật lý
Tốc độ⭐⭐⭐⭐ — Cherry-pick rất nhanh
Chất lượng output⭐⭐⭐⭐⭐ — Đầy đủ context
Bền vững hàng ngày⭐⭐⭐⭐ — Khi đã quen git

Phù hợp khi: Bạn comfortable với git worktree. Muốn bảo mật vật lý mà vẫn workflow gần như tự nhiên.


So sánh nhanh

Chiến lượcBảo mậtTốc độContextSetupBest for
Demo projectCao nhấtChậm nhấtNghèoDễOne-off tasks
Duplicate + patchCaoTốtĐầy đủTrung bìnhAutomation-friendly workflow
.claudeignoreTrung bìnhNhanh nhấtĐầy đủDễ nhấtProjects không quá nhạy cảm
Git worktreeCaoTốtĐầy đủCần hiểu gitProduction apps + git fluent

Files cần bảo vệ theo platform

File / PatternPlatformsLý do
.env, .env.*Tất cảAPI keys, DB URLs, secrets
docker-compose.prod.ymlBackend, fullstackProduction passwords
credentials.jsonGCP (all platforms)Service account keys
google-services.jsonAndroidFirebase config với API keys
GoogleService-Info.plistiOSFirebase config cho iOS
*.keystore, *.jksAndroid, JavaApp signing keys
*.pem, *.p12, *.pfxiOS, SSL, certificatesPrivate keys
secrets.yamlKubernetesInfrastructure secrets
local.propertiesAndroidSDK paths, signing configs
xcconfig filesiOSBuild settings với tokens

Đề xuất — Chọn theo mức độ chấp nhận rủi ro

  • Bạn paranoid về security: Git worktree (#4) hoặc Duplicate + patch (#2)
  • Bạn cần năng suất tối đa: .claudeignore (#3) — nhưng audit .claudeignore thường xuyên
  • Bạn chưa quen git worktree: Duplicate + patch (#2) + viết script automation
  • Chỉ cần dùng Claude Code một lần: Demo project (#1) OK, đừng mong workflow lâu dài

Bonus: CLAUDE_CONTEXT.md cho phép Claude Code biết những gì nó KHÔNG được thấy

Dù dùng chiến lược nào, tôi recommend thêm file CLAUDE_CONTEXT.md hoặc CLAUDE.md nói rõ những gì bị ẩn và cách truy cập đúng.

Next.js / TypeScript Example:

CLAUDE_CONTEXT.md
## Tech Stack
- Next.js 14 + TypeScript + Prisma + PostgreSQL
- Stripe for payments
- AWS S3 for file storage
## Secrets (hidden from Claude Code)
- `.env.local` contains:
- DATABASE_URL (Postgres connection)
- STRIPE_SECRET_KEY
- AWS_ACCESS_KEY_ID & AWS_SECRET_ACCESS_KEY
- NEXTAUTH_SECRET
## How to reference secrets in code
- Always use `process.env.VARIABLE_NAME`
- NEVER hardcode keys
- NEVER commit .env files
- For client-side: prefix with `NEXT_PUBLIC_` (but avoid secrets there)
## Example:
```typescript
// ✅ Correct
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
apiVersion: '2023-10-16',
});
// ❌ Wrong
const stripe = new Stripe('sk_live_abc123...', {
apiVersion: '2023-10-16',
});
CLAUDE_CONTEXT.md
### Python / FastAPI Example:
```markdown
## Tech Stack
- FastAPI + SQLAlchemy + PostgreSQL
- Redis for caching
- AWS for infrastructure
## Secrets (hidden from Claude Code)
- `.env` loaded by python-dotenv
- Contains: DATABASE_URL, REDIS_URL, AWS credentials, API keys
## How to reference secrets
- All secrets accessed via `settings.py` Pydantic BaseSettings
- NEVER hardcode secrets
- Use `settings.DATABASE_URL` not direct os.getenv()
## Example:
```python
# ✅ Correct
from app.config import settings
engine = create_engine(settings.DATABASE_URL)
# ❌ Wrong
engine = create_engine("postgresql://user:password@localhost/db")
CLAUDE_CONTEXT.md
### Mobile (KMP / React Native) Example:
```markdown
## Tech Stack
- Kotlin Multiplatform (KMP) shared code
- Android: Jetpack Compose
- iOS: SwiftUI
## Secrets (hidden from Claude Code)
- Android: `local.properties` (API keys, SDK paths)
- iOS: `Config.xcconfig` files
- Shared: `gradle.properties` for signing
## How to reference secrets
- Android: Use BuildConfig constants
- iOS: Use Info.plist or xcconfig variables
- NEVER commit keystore files or signing certificates
## Example:
```kotlin
// ✅ Correct (Android)
val apiKey = BuildConfig.API_KEY
// ❌ Wrong
val apiKey = "sk-abc123xyz"
Điều này giúp Claude Code generate code đúng cấu trúc — nó biết phải dùng `process.env.STRIPE_SECRET_KEY` hoặc `BuildConfig.API_KEY` thay vì hardcode, dù không thấy file chứa key.
---
## Kết luận
Hành trình của tôi: bắt đầu với Demo project (quá chậm), chuyển sang Duplicate + patch (tốt hơn nhiều), thử `.claudeignore` (nhanh nhất nhưng lo ngại bảo mật), cuối cùng settle ở Git worktree (cân bằng tốt nhất cho workflow của tôi).
Bạn không cần theo đúng con đường đó. Chọn chiến lược fit với risk tolerance và git comfort level của bạn. Điều quan trọng nhất: đừng bỏ qua bảo mật vì năng suất. Claude Code là force multiplier, nhưng chỉ khi bạn dùng nó trên nền tảng an toàn.
Dù chọn cách nào, thêm `CLAUDE_CONTEXT.md`. Nó giúp AI hiểu những gì nó không thấy.
---
*Muốn đi sâu hơn? [Khóa học Claude Code Mastery](/) cover tất cả — bao gồm module bảo mật hoàn chỉnh (Phase 2) với bài tập thực hành. Phases 1-3 hoàn toàn miễn phí.*
*Nhận [Claude Code Cheat Sheet miễn phí](/products) — 50+ commands trong một file PDF — khi đăng ký newsletter.*