Bạn đã dùng Claude Code qua CLI:
- Giải thích SDK là gì, khác gì với CLI, và khi nào dùng mỗi cái
- Viết code TypeScript/Python gọi Claude Code programmatic
- Cấu hình allowedTools và permission cho SDK
- Embed SDK vào script, CI/CD pipeline, hook (đã dùng ở Bài 4.16)
- Thiết kế 5 automation scenario dùng SDK hiệu quả
SDK là gì?
Claude Code SDK = library cho phép bạn chạy Claude Code từ code.
Available cho:
Key insight
SDK chạy cùng Claude Code bạn dùng CLI. Same tools, same capability. Chỉ khác: output là structured data bạn code xử lý thay vì in ra terminal.
- TypeScript/JavaScript: npm install @anthropic-ai/claude-code
- Python: pip install anthropic-claude-code
- CLI headless mode: claude --print "task" --output-format json
Ví dụ đơn giản: TypeScript
Setup
Code
analyze.ts:
npm install @anthropic-ai/claude-codeCode
Run
import { query } from "@anthropic-ai/claude-code";
const prompt = "Look for duplicate queries in the ./src/queries dir";
for await (const message of query({ prompt })) {
console.log(JSON.stringify(message, null, 2));
}Run
Output
Script print từng message raw — bạn thấy conversation giữa local Claude Code và LM remote:
npx tsx analyze.tsOutput
Message cuối chứa conclusion. Bạn extract, dùng trong logic tiếp theo.
{
"type": "text",
"text": "I'll analyze the queries directory..."
}
{
"type": "tool_use",
"name": "Glob",
"input": { "pattern": "src/queries/**/*.ts" }
}
{
"type": "tool_result",
"content": "src/queries/orders.ts\nsrc/queries/users.ts\n..."
}
...
{
"type": "text",
"text": "Found 2 duplicates: getPendingOrders and getPendingOrdersByStatus overlap in functionality."
}Permissions — SDK default là read-only
Khi bạn gọi SDK, Claude chạy với permission mặc định chỉ read:
Lý do: Safety. Script chạy headless, không ai đứng approve tool call. Default lớp bảo vệ.
Grant permission qua allowedTools
Grant qua settings
Trong .claude/settings.json của project:
- Read ✓
- Grep ✓
- Glob ✓
- Edit ✗
- Write ✗
- Bash ✗
for await (const message of query({
prompt: "Update all TypeScript files...",
options: {
allowedTools: ["Edit", "Write", "Bash"],
}
})) {
// ...
}Grant qua settings
SDK run trong thư mục project inherit settings đó.
MCP tools
{
"permissions": {
"allow": ["Edit", "Write"]
}
}MCP tools
Mỗi MCP tool liệt kê tên riêng.
options: {
allowedTools: [
"mcp__playwright__browser_snapshot",
"mcp__playwright__browser_click"
]
}Python SDK
Tương tự:
Giống shape, khác syntax.
from claude_code import query
async def main():
async for message in query(
prompt="Analyze security of auth module",
options={
"allowed_tools": ["Read", "Grep"],
}
):
print(message.to_dict())CLI headless mode
Nếu không muốn viết code, dùng flag --print:
Output: JSON một message — final response. Dùng trong shell script dễ.
Shell script ví dụ
claude --print "Count TS files in src/" --output-format jsonShell script ví dụ
#!/bin/bash
result=$(claude --print "List files changed in last commit" --output-format json)
echo "$result" | jq -r '.messages[-1].text'Ví dụ thực chiến 1: Git hook review
Setup
.git/hooks/pre-commit:
Flow:
Kết quả: Catch lỗi trước commit thay vì trong review. Developer feedback-loop nhanh hơn.
- Dev git commit
- Hook kick Claude review diff
- Nếu clean → auto pass
- Nếu có issue → print + ask confirm
#!/bin/bash
# Chạy Claude Code review diff trước commit
diff=$(git diff --cached)
[ -z "$diff" ] && exit 0
result=$(claude --print "Review this diff. Flag any issues. If clean, reply 'CLEAN'. Diff:
$diff
" --allowed-tools Read)
if echo "$result" | grep -q "CLEAN"; then
exit 0
else
echo "$result"
echo
read -p "Proceed with commit? (y/N) " answer
[ "$answer" = "y" ] && exit 0 || exit 1
fiVí dụ thực chiến 2: Cron job audit dependency
Setup
scripts/weekly-audit.ts:
Cron
import { query } from "@anthropic-ai/claude-code";
import fs from "fs";
async function audit() {
const report: string[] = [];
for await (const message of query({
prompt: `
Audit npm dependencies. Do the following:
1. Run 'npm outdated --json' and parse
2. For each outdated package, check changelog for breaking changes
3. Check CVE database for known vulnerabilities
4. Prioritize updates: security critical > major breaking > minor
5. Output markdown report with sections
`,
options: {
allowedTools: ["Bash", "WebFetch", "Read"],
maxTurns: 20,
}
})) {
if (message.type === 'text') report.push(message.text);
}
// Save report
const filename = `reports/audit-${new Date().toISOString().split('T')[0]}.md`;
fs.writeFileSync(filename, report.join("\n"));
console.log(`Report saved: ${filename}`);
}
audit().catch(console.error);Cron
Mỗi sáng thứ Hai 8h, có file report trong reports/.
Team workflow: Eng lead review report Monday standup, assign updates.
0 8 * * 1 cd /path/to/repo && npx tsx scripts/weekly-audit.tsVí dụ thực chiến 3: Slack bot với SDK
Setup
Server Node.js với Slack Bolt:
Use case: Team Slack, mention @claude-bot, hỏi câu hỏi về codebase, bot answer.
import { App } from "@slack/bolt";
import { query } from "@anthropic-ai/claude-code";
const app = new App({ token: process.env.SLACK_BOT_TOKEN, ... });
app.message(/@claude-bot (.*)/, async ({ message, say }) => {
const userPrompt = message.text.replace("@claude-bot", "").trim();
await say(":thinking_face: Working on it...");
let response = "";
for await (const msg of query({
prompt: userPrompt,
options: {
cwd: "/path/to/codebase",
allowedTools: ["Read", "Grep", "Glob", "WebFetch"],
maxTurns: 10,
}
})) {
if (msg.type === 'text') response += msg.text;
}
await say(response);
});
app.start(3000);Setup
User: @claude-bot why do we have 2 implementations of formatPrice?
Bot: I found 2 implementations:
1. src/utils/price.ts (older, used in API layer)
2. src/components/Price.tsx (newer, used in UI)
The newer one handles i18n, the older doesn't. Recommend
deprecating the older, migrating API layer.Ví dụ thực chiến 4: Documentation generator
Setup
scripts/gen-docs.ts:
Run:
import { query } from "@anthropic-ai/claude-code";
import fs from "fs";
const FEATURES = ["auth", "billing", "reports", "admin"];
for (const feature of FEATURES) {
console.log(`Documenting ${feature}...`);
let doc = "";
for await (const msg of query({
prompt: `
Document the ${feature} feature:
1. Read @src/features/${feature}/
2. Generate markdown with:
- Overview (2 paragraphs)
- Key files & responsibilities
- API surface (exported functions, types)
- Integration points (external services, DB tables)
- Common gotchas from code comments
`,
options: { allowedTools: ["Read", "Grep", "Glob"] }
})) {
if (msg.type === 'text') doc += msg.text;
}
fs.writeFileSync(`docs/features/${feature}.md`, doc);
}
console.log("Docs generated!");Setup
4 doc files sinh ra, consistent format, auto-update khi codebase đổi.
npx tsx scripts/gen-docs.tsVí dụ thực chiến 5: CI/CD gate
Setup
.github/workflows/ci.yml:
Use case
CI sinh báo cáo tech debt định kỳ. Team review, priority.
- name: Claude quality gate
run: |
result=$(claude --print "Scan @src/ for TODO comments older than 30 days. List them with file:line." --output-format json)
count=$(echo "$result" | jq -r '.messages[-1].text' | grep -c TODO || true)
if [ "$count" -gt 50 ]; then
echo "::warning::TODO count exceeds 50: $count"
fi
echo "$result" > quality-report.json
env:
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}Case studies theo ngành
💼 Fintech — Compliance scanner SDK
Setup: Nightly SDK job scan codebase for compliance pattern (PII leak, unauthorized API call, etc.)
🏥 Healthcare — Data flow mapper
Setup: SDK script map PHI data flow across microservices weekly.
🛠️ Platform engineering — API breaking change detector
Setup: SDK on PR → scan changes to public API interface, flag breaking.
📣 Content platform — Content moderation pipeline
Setup: SDK batch process user content generation — check voice, flag issue before publish.
🎮 Game dev — Asset metadata extractor
Setup: SDK script scan new game assets, extract metadata, generate catalog JSON for engine.
- Kết quả: Compliance reports automated, save 20 hours/week.
- Kết quả: Data flow diagram auto-updated, SOC2 audit evidence.
- Kết quả: Zero accidental breaking change shipped in 6 months.
- Kết quả: Brand voice consistency automated, 3x publishing velocity.
- Kết quả: Asset pipeline 10x faster than manual tagging.
SDK vs CLI — Decision tree
Need automation?
│
├── Chạy trong terminal, 1 lần?
│ └── CLI (claude) — interactive
│
├── Chạy trong shell script?
│ └── CLI headless (claude --print)
│
├── Chạy trong code (Node.js/Python app)?
│ └── SDK — structured output
│
├── Chạy trong CI/CD?
│ └── GitHub Action (Bài 4.11) hoặc CLI headless
│
└── Chạy trong hook của Claude Code?
└── SDK (như ví dụ Bài 4.16)Anti-patterns
❌ Grant allowedTools: ["*"] cho SDK
Rủi ro: SDK chạy không supervise có thể làm destructive action. Mất code, leak data.
Cách đúng: Minimum permission. Chỉ grant tool thực sự cần cho task.
❌ Ignore maxTurns
Không set maxTurns → SDK có thể loop vô hạn, tốn $$$.
Cách đúng: maxTurns: 10-30 cho task thường, 50-100 cho task phức tạp. Cap là bắt buộc.
❌ Không handle error của SDK
SDK throw khi API fail, quota exhausted. Không catch → script crash.
Cách đúng:
❌ Run SDK trong loop không rate limit
100 file cần process → 100 SDK call song song → API rate limit.
Cách đúng: Process sequential hoặc batch nhỏ (5-10 song song max).
❌ Hardcode API key trong code
try {
for await (const msg of query({...})) {...}
} catch (err) {
console.error("SDK failed:", err);
// fallback / retry / alert
}❌ Hardcode API key trong code
Cách đúng: Env var / secret manager, không hardcode.
process.env.ANTHROPIC_API_KEY = "sk-ant-..."; // ❌Mẹo nâng cao
Mẹo 1: Structured output với JSON mode
Khi cần response có structure cố định:
Dễ parse trong code downstream.
Mẹo 2: Session resumption
SDK hỗ trợ resume conversation:
for await (const msg of query({
prompt: `Return JSON with shape: { status: 'ok'|'fail', reason: string }
Analyze ${file} and return your analysis.`,
options: {
outputFormat: "json",
}
})) {
const parsed = JSON.parse(msg.text);
// ...
}Mẹo 2: Session resumption
Task dài nhiều step có thể phân tách.
Mẹo 3: Stream để UX responsive
Thay vì wait final, stream text real-time:
const sessionId = "abc123";
const firstRun = await query({ prompt: "Start analysis", sessionId });
// ... later ...
const continuation = await query({ prompt: "Continue where you left off", sessionId });Mẹo 3: Stream để UX responsive
Perfect cho chatbot / tool interactive.
Mẹo 4: Budget & monitoring
Instrument SDK call với cost tracking:
for await (const msg of query({...})) {
if (msg.type === 'text_delta') {
process.stdout.write(msg.text); // print as it comes
}
}Mẹo 4: Budget & monitoring
Tránh bill sốc.
let tokensUsed = 0;
for await (const msg of query({...})) {
if (msg.type === 'usage') tokensUsed += msg.tokens;
}
console.log(`Spent: $${(tokensUsed * 0.003 / 1000).toFixed(2)}`);Áp dụng ngay
Bài tập 1: Script SDK đầu tiên (20 phút)
Bước 1: Trong uigen (hoặc project của bạn):
Bước 2: Tạo scripts/explore.ts:
npm install @anthropic-ai/claude-codeBài tập 1: Script SDK đầu tiên (20 phút)
Bước 3: Run npx tsx scripts/explore.ts.
Bước 4: Ghi:
Bài tập 2 (optional, 25 phút): Automation script
Chọn task lặp thực tế trong workflow bạn:
Implement bằng SDK. Run 1 lần, verify output quality. Nếu OK → schedule cron/CI.
- Kết quả: ____________
- Tokens used: ____________
- Latency: ____________
- Generate weekly report
- Scan for tech debt
- Check documentation freshness
import { query } from "@anthropic-ai/claude-code";
for await (const msg of query({
prompt: "Analyze this codebase. Report: (1) LOC by language, (2) largest 5 files, (3) dependencies with no tests.",
options: {
allowedTools: ["Read", "Grep", "Glob", "Bash"],
maxTurns: 15,
}
})) {
if (msg.type === 'text') console.log(msg.text);
}Tóm tắt bài học
🎯 SDK = Claude Code programmatic — TypeScript/Python/CLI headless.
🎯 Default read-only — phải grant allowedTools cho write/execute.
🎯 5 automation pattern: git hook, cron job, chatbot, doc generator, CI gate.
🎯 maxTurns là mandatory — tránh loop vô hạn, chi phí kiểm soát.
🎯 SDK + hook = self-improving Claude — Claude review output Claude.
- Claude Code SDK TS docs
- Claude Code SDK Python docs
- Headless automation talk — Code w/ Claude 2025
- Bài 4.11 — GitHub Actions (SDK in CI)
- Bài 4.16 — SDK in hooks (Claude reviews Claude)