สั่งงานอัตโนมัติ — headless, ตารางเวลา, ลิงก์ และ CI
ให้ Claude Code ทำงานตอนคุณไม่ได้พิมพ์ ตั้งแต่ claude -p ในสคริปต์ ตารางเวลาสามแบบที่ต่างกันจริง ลิงก์ claude-cli:// ในคู่มือรับมือเหตุ ไปจนถึง GitHub Actions และ Agent SDK
บทที่ 9 | สั่งงานอัตโนมัติ กลุ่มเป้าหมาย: คนที่อยากให้ Claude Code ทำงานโดยไม่มีใครนั่งพิมพ์อยู่
9.1 headless — เรียกจากสคริปต์ด้วย claude -p
ใส่ -p (หรือ --print) เพื่อรันแบบไม่โต้ตอบ
claude -p "หาและแก้บั๊กใน auth.py" --allowedTools "Read,Edit,Bash"
มันอ่าน stdin ได้ ดังนั้นต่อท่อได้เหมือนคำสั่ง Unix ทั่วไป
cat build-error.txt | claude -p 'อธิบายสาเหตุรากของ build error นี้แบบกระชับ' > output.txt
stdin ที่ต่อท่อเข้ามาจำกัดที่ 10MB ถ้าเกิน Claude Code จะออกพร้อม error และสถานะไม่เป็นศูนย์ ข้อมูลใหญ่กว่านั้นให้เขียนลงไฟล์แล้วอ้างพาธในพรอมต์แทน
--bare คือธงที่คนใช้ CI ควรรู้ที่สุด
claude --bare -p "สรุป README.md" --allowedTools "Read"
มันข้ามการค้นหาอัตโนมัติของ hooks, skills, คำสั่งกำหนดเอง, subagents, plugins, MCP servers, auto memory และ CLAUDE.md ประโยชน์คือ ได้ผลเหมือนกันทุกเครื่อง hook ที่อยู่ใน ~/.claude ของเพื่อนร่วมทีม หรือ MCP server ใน .mcp.json ของโปรเจกต์ จะไม่ถูกรัน เพราะโหมดนี้ไม่อ่านมันเลย
กลับกัน นี่คือคำเตือนความปลอดภัยที่สำคัญ ถ้าไม่ใส่ --bare เซสชัน -p จะรัน hook ใน .claude/settings.json ของโปรเจกต์และต่อ MCP server ใน .mcp.json แม้ในโฟลเดอร์ที่คุณไม่เคยกด trust เพราะโหมด -p ไม่แสดงกล่อง trust และไม่ถามอนุมัติรายเซิร์ฟเวอร์
ในโหมด --bare Claude Code ไม่อ่าน OAuth credential และไม่แตะ keychain ต้องตั้ง ANTHROPIC_API_KEY เอง
เอกสารระบุว่า
--bareจะกลายเป็นค่าตั้งต้นของ-pในรุ่นถัดไป เขียนสคริปต์วันนี้ให้เผื่อไว้
รูปแบบผลลัพธ์
| ค่า | ได้อะไร |
|---|---|
text (ค่าตั้งต้น) | ข้อความล้วน |
json | JSON ที่มี result, session ID และ metadata รวมถึง total_cost_usd |
stream-json | JSON บรรทัดต่อบรรทัดแบบสตรีมสด |
บังคับรูปร่างของคำตอบได้ด้วย --json-schema ผลจะไปอยู่ในฟิลด์ structured_output
claude -p "ดึงชื่อฟังก์ชันหลักจาก auth.py" \
--output-format json \
--json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}'
โหมดสิทธิ์ในโหมด -p จุดนี้สำคัญและเปลี่ยนจากที่หลายคนเข้าใจ โหมดตั้งต้นของ -p คือ Manual ทุกแพ็กเกจ ต้องระบุเองว่าจะใช้โหมดไหน
| โหมด | เหมาะกับ |
|---|---|
--permission-mode auto | ให้ classifier ตรวจทานแทนคุณ |
--permission-mode dontAsk | CI ที่ล็อกแน่น ปฏิเสธทุกอย่างที่ไม่อยู่ในกฎ allow |
--permission-mode acceptEdits | ให้เขียนไฟล์ได้โดยไม่ถาม |
และถ้าไม่มีใครอยู่ตอบกล่องขออนุญาตเลย
claude -p "อัปเดต dependency pins แล้วรันเทสต์" --permission-mode auto --permission-prompts none
เขียน allow rule ให้แม่น ช่องว่างก่อน * มีความหมาย
claude -p "ดู staged changes แล้ว commit ให้เหมาะสม" \
--allowedTools "Bash(git diff *),Bash(git log *),Bash(git status *),Bash(git commit *)"
Bash(git diff *) อนุญาตคำสั่งที่ขึ้นต้นด้วย git diff ส่วน Bash(git diff*) ที่ไม่มีช่องว่าง จะเผลอครอบ git diff-index ไปด้วย
การต่อบทสนทนา
session_id=$(claude -p "เริ่มรีวิว" --output-format json | jq -r '.session_id')
claude -p "รีวิวต่อ" --resume "$session_id"
สถานะขาออก เอกสารระบุว่า Claude Code ออกด้วยรหัส 0 เมื่อสำเร็จ และรหัสที่ไม่ใช่ศูนย์เมื่อล้มเหลว สคริปต์แตกกิ่งจากตรงนี้ได้ กรณีพิเศษที่ระบุไว้ชัดคือ ถ้าหยุดด้วย SIGTERM จะออกด้วยรหัส 143 และเทิร์นที่ค้างอยู่จะไม่ถูกบันทึกผลลัพธ์ ถ้าอยากให้จบเทิร์นให้ส่ง SIGINT แทน
9.2 ตารางเวลา — สามแบบที่ไม่เหมือนกัน
นี่คือจุดที่คนเลือกผิดบ่อยที่สุด เพราะทั้งสามอย่างฟังดูเหมือนกัน
| Routines (คลาวด์) | Desktop scheduled task | /loop | |
|---|---|---|---|
| รันที่ | คลาวด์ | เครื่องคุณ | เครื่องคุณ |
| ต้องเปิดเครื่องไหม | ไม่ | ต้อง | ต้อง |
| ต้องเปิด session ค้างไหม | ไม่ | ไม่ | ต้อง |
| อยู่รอดหลังรีสตาร์ต | ได้ | ได้ | กลับมาเมื่อ --resume ถ้ายังไม่หมดอายุ |
| เข้าถึงไฟล์ในเครื่อง | ไม่ได้ (clone ใหม่) | ได้ | ได้ |
| กล่องขออนุญาต | ไม่มี รันเอง | ตั้งได้ต่องาน | สืบทอดจาก session |
| ช่วงถี่ที่สุด | 1 ชั่วโมง | 1 นาที | 1 นาที |
/loop — เร็วที่สุดสำหรับงานเฝ้าดูระหว่าง session
/loop 5m เช็กว่า deploy เสร็จหรือยัง แล้วบอกผลด้วย
รูปแบบมีสามอย่าง
| ให้อะไร | เกิดอะไร |
|---|---|
| ทั้งช่วงเวลาและพรอมต์ | รันตามตารางตายตัว |
| พรอมต์อย่างเดียว | Claude เลือกช่วงเองแต่ละรอบ ระหว่าง 1 นาทีถึง 1 ชั่วโมง ตามที่มันสังเกตเห็น |
ไม่ให้อะไรเลย (/loop) | รันพรอมต์ดูแลรักษาที่ติดมาในตัว หรือไฟล์ loop.md ของคุณถ้ามี |
หน่วยที่รองรับคือ s m h d วินาทีถูกปัดขึ้นเป็นนาทีเพราะ cron ละเอียดสุดที่ 1 นาที และช่วงที่หารไม่ลงตัวอย่าง 7m หรือ 90m จะถูกปัดไปค่าที่ลงตัวแล้ว Claude จะบอกว่าเลือกอะไร
หยุด loop ที่ Claude กำหนดจังหวะเองด้วยการกด Esc ระหว่างรอรอบถัดไป
กับดักที่ต้องรู้สามข้อ
- หมดอายุ 7 วัน งานที่ทำซ้ำจะยิงครั้งสุดท้ายแล้วลบตัวเองทิ้งเมื่อครบ 7 วันนับจากสร้าง นี่คือเพดานกันไม่ให้ loop ที่ลืมไว้รันตลอดกาล ถ้าต้องการนานกว่านั้นให้ใช้ Routines หรือ Desktop scheduled task
- มี jitter งานที่ทำซ้ำอาจยิงช้ากว่าเวลาที่ตั้งได้ถึง 30 นาที (หรือครึ่งหนึ่งของช่วง สำหรับงานที่ถี่กว่ารายชั่วโมง) เพื่อไม่ให้ทุก session ยิง API พร้อมกัน ถ้าเวลาสำคัญ ให้เลี่ยงนาที
:00และ:30เช่นใช้3 9 * * *แทน0 9 * * * - ไม่มีการยิงชดเชย ถ้าเวลาที่ตั้งผ่านไปตอน Claude กำลังยุ่ง มันจะยิงครั้งเดียวเมื่อว่าง ไม่ใช่ยิงย้อนทุกรอบที่พลาด
เขียนพรอมต์ตั้งต้นของตัวเองด้วย loop.md
| พาธ | ขอบเขต |
|---|---|
.claude/loop.md | ระดับโปรเจกต์ ชนะเมื่อมีทั้งสองไฟล์ |
~/.claude/loop.md | ระดับผู้ใช้ ใช้กับโปรเจกต์ที่ไม่มีของตัวเอง |
แก้ไฟล์นี้มีผลในรอบถัดไปทันที ปรับได้ระหว่าง loop กำลังทำงาน เนื้อหาเกิน 25,000 ไบต์จะถูกตัด
เครื่องมือเบื้องหลัง คือ CronCreate CronList และ CronDelete รับ cron 5 ช่องมาตรฐาน นาที ชั่วโมง วันที่ เดือน วันในสัปดาห์ แต่ละ session เก็บได้ไม่เกิน 50 งาน และ ไวยากรณ์ขยายอย่าง L W ? หรือชื่อย่ออย่าง MON ใช้ไม่ได้
เวลาทั้งหมดตีความตามเขตเวลาเครื่องคุณ ไม่ใช่ UTC ปิดทั้งระบบได้ด้วย CLAUDE_CODE_DISABLE_CRON=1
Routines — ตารางเวลาที่ไม่ต้องเปิดเครื่อง
พิมพ์ /schedule ในเซสชันไหนก็ได้เพื่อสร้างแบบคุยกัน มี /schedule list และ /schedule update ด้วย มันรันบนโครงสร้างพื้นฐานที่ Anthropic ดูแล ช่วงถี่ที่สุดคือ 1 ชั่วโมง และต้องมีบัญชี claude.ai (ดูตารางแพ็กเกจในบทที่ 8)
9.3 ลิงก์ claude-cli:// — เปิด session จากคลิกเดียว
รูปแบบคือ claude-cli://open ตามด้วยพารามิเตอร์
| พารามิเตอร์ | ความหมาย |
|---|---|
q | ข้อความที่จะเติมในช่องพรอมต์ ต้อง URL-encode ใช้ %0A สำหรับขึ้นบรรทัดใหม่ สูงสุด 5,000 ตัวอักษร |
cwd | พาธเต็มของไดเรกทอรีทำงาน พาธ UNC พาธที่มี .. และอักขระควบคุมล่องหนถูกปฏิเสธ |
repo | slug แบบ owner/name ของ GitHub Claude Code จะหา clone ในเครื่องที่มันเคยเห็น ถ้าไม่เจอจะเปิดที่โฮมไดเรกทอรีแทน |
ถ้าใส่ทั้ง cwd และ repo cwd ชนะเสมอ และ repo ถูกเมิน แม้พาธนั้นจะไม่มีอยู่จริง
ตัวอย่างในคู่มือรับมือเหตุ
## อัตรา 5xx สูงผิดปกติที่ web-gateway
1. รับเรื่องใน PagerDuty
2. [เปิด Claude Code ใน repo ของ gateway](claude-cli://open?repo=acme/web-gateway&q=5xx%20rate%20is%20elevated%20on%20web-gateway.)
3. โพสต์สิ่งที่พบเบื้องต้นใน #incident
เปิดจาก shell ได้ด้วย
# macOS
open "claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
# Linux
xdg-open "claude-cli://open?repo=acme/payments&q=review%20open%20PRs"
บน Windows PowerShell ใช้ Start-Process "claude-cli://open?..." ส่วนใน cmd.exe ต้องใส่ชื่อหน้าต่างว่างก่อน คือ start "" "claude-cli://open?..."
ความปลอดภัย ลิงก์ไม่รันอะไรเอง มันแค่เลือกไดเรกทอรีและเติมข้อความในช่องพรอมต์ ไม่มีอะไรถึงโมเดลจนกว่าคุณจะกด Enter จะมีบรรทัดเตือน Prompt from an external link ค้างอยู่ใต้ช่องพรอมต์ และถ้าพรอมต์ยาวเกิน 1,000 ตัวอักษรจะบอกจำนวนตัวอักษรพร้อมเตือนให้เลื่อนอ่านให้ครบ เพราะพรอมต์ยาวดันคำสั่งพ้นจอได้
กับดักที่เจอบ่อย
- คลิกแล้วไม่เกิดอะไร ตัวจัดการยังไม่ถูกลงทะเบียน มันลงทะเบียนตอนคุณ ส่งพรอมต์แรกของ session แบบโต้ตอบ ไม่ใช่ตอนเปิด session
- GitHub ตัดลิงก์ทิ้ง README, issue, PR และ wiki ของ GitHub อนุญาตแต่
http/httpsลิงก์แบบนี้จะเหลือแต่ข้อความ วิธีแก้คือใส่ลิงก์ไว้ในบล็อกโค้ดให้คนคัดลอกไปวางเอง - เปิดที่โฮมแทน repo เพราะ
repoหา clone ที่ Claude Code เคยเห็นเท่านั้น ให้รันclaudeใน clone นั้นสักครั้ง หรือเปลี่ยนไปใช้cwd
ปิดการลงทะเบียนได้ด้วย disableDeepLinkRegistration เป็น "disable" ใน settings.json
9.4 CI — GitHub Actions
ติดตั้งเร็วที่สุดคือพิมพ์ /install-github-app ใน Claude Code มันจะติดตั้ง GitHub App เพิ่ม secret และเตรียม PR ของ workflow ให้
หรือเขียน workflow เอง
name: Claude Code
on:
issue_comment:
types: [created]
jobs:
claude:
if: contains(github.event.comment.body, '@claude')
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
issues: write
id-token: write
steps:
- uses: actions/checkout@v6
- uses: anthropics/claude-code-action@v1
with:
anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
ใส่ธง CLI ผ่าน claude_args ได้ เช่น --model, --allowedTools, --max-turns
9.5 Agent SDK
ถ้าต้องการควบคุมมากกว่าที่ CLI ให้ ใช้แพ็กเกจโดยตรง ชื่อเดิม “Claude Code SDK” เปลี่ยนเป็น “Agent SDK” แล้ว
| ภาษา | แพ็กเกจ |
|---|---|
| Python | claude-agent-sdk |
| TypeScript | @anthropic-ai/claude-agent-sdk |
from claude_agent_sdk import query, ClaudeAgentOptions
async for message in query(
prompt="พรอมต์ของคุณ",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Glob"],
permission_mode="acceptEdits",
),
):
...
9.6 เลือกอย่างไร
| ถ้าโจทย์คือ | ใช้ |
|---|---|
| เรียกครั้งเดียวจากสคริปต์หรือ Makefile | claude -p --bare |
| เฝ้าดูอะไรบางอย่างระหว่างที่นั่งทำงานอยู่ | /loop |
| งานประจำที่ต้องเดินแม้ปิดคอม | Routines (/schedule) |
| งานประจำที่ต้องใช้ไฟล์ในเครื่อง | Desktop scheduled task |
| ผูกกับ PR หรือ push | GitHub Actions |
| ปุ่มเดียวในคู่มือรับมือเหตุ | ลิงก์ claude-cli:// |
| แอปที่ต้องคุมทีละข้อความ | Agent SDK |
คำศัพท์ประจำบท
| คำ | ความหมาย |
|---|---|
Headless / -p | รันแบบไม่โต้ตอบ อ่าน stdin เขียน stdout |
--bare | ข้ามการโหลด hook/skill/MCP/CLAUDE.md เพื่อให้ผลเหมือนกันทุกเครื่อง |
| Jitter | การเลื่อนเวลายิงงานตามตารางเพื่อกระจายภาระ |
| Routine | งานตามตารางที่รันบนคลาวด์ ไม่ต้องเปิดเครื่อง |
| Deep link | URL claude-cli:// ที่เปิด session พร้อมพรอมต์เติมไว้ |