ข้ามไปยังเนื้อหา
KoishiAI
EN
← กลับไปหน้าสารบัญ
บทที่ 9 / 12 · 5 กันยายน 2569

สั่งงานอัตโนมัติ — headless, ตารางเวลา, ลิงก์ และ CI

ให้ Claude Code ทำงานตอนคุณไม่ได้พิมพ์ ตั้งแต่ claude -p ในสคริปต์ ตารางเวลาสามแบบที่ต่างกันจริง ลิงก์ claude-cli:// ในคู่มือรับมือเหตุ ไปจนถึง GitHub Actions และ Agent SDK

คู่มือชุดนี้ลิขสิทธิ์ All Rights Reserved — อ่านได้ฟรี แต่คัดลอก/เผยแพร่ซ้ำต้องขออนุญาต

บทที่ 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 (ค่าตั้งต้น)ข้อความล้วน
jsonJSON ที่มี result, session ID และ metadata รวมถึง total_cost_usd
stream-jsonJSON บรรทัดต่อบรรทัดแบบสตรีมสด

บังคับรูปร่างของคำตอบได้ด้วย --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 dontAskCI ที่ล็อกแน่น ปฏิเสธทุกอย่างที่ไม่อยู่ในกฎ 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 ระหว่างรอรอบถัดไป

กับดักที่ต้องรู้สามข้อ

  1. หมดอายุ 7 วัน งานที่ทำซ้ำจะยิงครั้งสุดท้ายแล้วลบตัวเองทิ้งเมื่อครบ 7 วันนับจากสร้าง นี่คือเพดานกันไม่ให้ loop ที่ลืมไว้รันตลอดกาล ถ้าต้องการนานกว่านั้นให้ใช้ Routines หรือ Desktop scheduled task
  2. มี jitter งานที่ทำซ้ำอาจยิงช้ากว่าเวลาที่ตั้งได้ถึง 30 นาที (หรือครึ่งหนึ่งของช่วง สำหรับงานที่ถี่กว่ารายชั่วโมง) เพื่อไม่ให้ทุก session ยิง API พร้อมกัน ถ้าเวลาสำคัญ ให้เลี่ยงนาที :00 และ :30 เช่นใช้ 3 9 * * * แทน 0 9 * * *
  3. ไม่มีการยิงชดเชย ถ้าเวลาที่ตั้งผ่านไปตอน 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 พาธที่มี .. และอักขระควบคุมล่องหนถูกปฏิเสธ
reposlug แบบ 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” แล้ว

ภาษาแพ็กเกจ
Pythonclaude-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 เลือกอย่างไร

ถ้าโจทย์คือใช้
เรียกครั้งเดียวจากสคริปต์หรือ Makefileclaude -p --bare
เฝ้าดูอะไรบางอย่างระหว่างที่นั่งทำงานอยู่/loop
งานประจำที่ต้องเดินแม้ปิดคอมRoutines (/schedule)
งานประจำที่ต้องใช้ไฟล์ในเครื่องDesktop scheduled task
ผูกกับ PR หรือ pushGitHub Actions
ปุ่มเดียวในคู่มือรับมือเหตุลิงก์ claude-cli://
แอปที่ต้องคุมทีละข้อความAgent SDK

คำศัพท์ประจำบท

คำความหมาย
Headless / -pรันแบบไม่โต้ตอบ อ่าน stdin เขียน stdout
--bareข้ามการโหลด hook/skill/MCP/CLAUDE.md เพื่อให้ผลเหมือนกันทุกเครื่อง
Jitterการเลื่อนเวลายิงงานตามตารางเพื่อกระจายภาระ
Routineงานตามตารางที่รันบนคลาวด์ ไม่ต้องเปิดเครื่อง
Deep linkURL claude-cli:// ที่เปิด session พร้อมพรอมต์เติมไว้