# Hooks ใน Claude Code 2026: ตั้งค่าทีละขั้นตอนพร้อมตัวอย่าง 7 รายการที่พร้อมใช้

> 7 hooks พร้อมใช้สำหรับ .claude/settings.json คัดลอกและวางได้ทันที: การป้องกัน .env, prettier, การ force-push ไปยัง main, em dash และเซิร์ฟเวอร์ dev มี handler 4 ประเภทและ event 31 รายการ

Source: https://ailoot.ai/blog/th/claude-code-hooks/
Canonical: https://ailoot.ai/blog/th/claude-code-hooks/
Language: th
Publisher: Ailoot (https://ailoot.ai/)
Translation: guide-121
Revision: sha256-e49e0b4e2581f7a2043879cd55bafdb0dca97ceb4bd87c8feb3f8ed604ad8fe0


Hooks ใน Claude Code คือคำสั่ง shell การเรียก HTTP หรือการตรวจสอบด้วย LLM สั้น ๆ ที่ทำงานโดยอัตโนมัติก่อนหรือหลังการกระทำของ Claude Hooks เพิ่มการตรวจเฉพาะ tool events จัดรูปแบบหลังแก้ และใส่บริบทตอนเริ่มเซสชัน PreToolUse ที่ตรง matcher ปฏิเสธคำขอนั้นได้ แต่ตัวอย่าง regex เป็นตัวช่วยกันพลาด ไม่ใช่ขอบเขตปลอดภัยครอบคลุมทุกเส้นทางไฟล์หรือ Git ต่อไปนี้เป็นรายละเอียดของ handler 4 ประเภท, event ตลอดวงจรการทำงาน 31 รายการ, แบบทดสอบว่า “กฎควรอยู่ใน hook เมื่อใด”, hooks พร้อมคัดลอกไปใช้ 7 รายการสำหรับ `.claude/settings.json` และข้อผิดพลาด 3 ข้อที่ฉันเคยเจอด้วยตัวเอง



[เอกสาร Ailoot: API, คีย์ และการตั้งค่า](https://ailoot.ai/docs/).

## Hooks ใน Claude Code คืออะไร?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Key takeaways">

ประเด็นสำคัญ

Hook คือคำสั่ง shell การเรียก HTTP พรอมป์ต์ LLM สั้น ๆ หรือ subagent ที่ Claude Code เรียกใช้เพื่อตอบสนองต่อ event เฉพาะในวงจรการทำงาน ต่างจากคำสั่งใน `CLAUDE.md` ซึ่งโมเดลอาจเพิกเฉยหรือลืมได้ hook จะทำงานเหมือนเดิมทุกครั้ง เพราะมันคือโค้ด ไม่ใช่คำแนะนำ

</div>

ตลอดครึ่งปี ฉันเก็บกฎ “ห้ามแก้ไข `.env` โดยตรง” ไว้ใน `CLAUDE.md` Claude ละเมิดกฎนี้เดือนละครั้ง ไม่ใช่เพราะเจตนาร้าย แต่เพียงลืมไปเมื่อเซสชันยาวนาน ครั้งหนึ่งมีโทเค็นเกินมาใน `.env`; อีกครั้งหนึ่งตัวแปรชื่อซ้ำไปเขียนทับตัวแปรที่ใช้งานอยู่

เมื่อเครื่องมือแก้โดยตรงที่ตรง matcher ส่ง path `.env` hook ที่ตั้งจะปฏิเสธคำขอนั้น แต่ Bash redirection สคริปต์ MCP และเส้นทางอื่นต้องมีการควบคุมแยก ตัวอย่างนี้ไม่ได้ทำให้ไฟล์เปลี่ยนไม่ได้

<figure>
<blockquote>
<p>Hooks คือคำสั่ง shell, HTTP endpoint หรือพรอมป์ต์ LLM ที่คุณกำหนด แล้วให้ทำงานโดยอัตโนมัติ ณ จุดต่าง ๆ ในวงจรการทำงานของ Claude Code</p>
</blockquote>
<figcaption>— Anthropic, https://code.claude.com/docs/en/hooks</figcaption>
</figure>

กล่าวอีกอย่างคือ hook เป็นคำสั่งของคุณที่ Claude Code เรียกใช้เมื่อเกิด event บางอย่าง การแก้ไขไฟล์ การเปิด Bash การเริ่มเซสชัน หรือการทำงานของ subagent เสร็จ ล้วนเป็น event ที่คุณผูก hook เข้าด้วยได้

เหตุใดเรื่องนี้จึงสำคัญสำหรับคนเขียนโค้ดแบบ vibe coding:

- ป้องกันไฟล์ที่มีข้อมูลลับจากการแก้ไขโดยไม่ตั้งใจ
- เรียก prettier/eslint โดยอัตโนมัติหลังสร้างโค้ดทุกครั้ง
- บล็อก `git push --force` ไปยัง main หากไม่ได้รับอนุญาตอย่างชัดเจน
- ใส่บริบทล่าสุดเมื่อเริ่มแต่ละเซสชัน
- บันทึกการกระทำของ Claude เพื่อการตรวจสอบ

CLAUDE.md จัดการบริบท ส่วน hooks จัดการ **การกระทำ** นี่เป็นคนละเรื่องกัน และการสับสนระหว่างสองอย่างนี้เป็นข้อผิดพลาดหลักของมือใหม่

## Hooks ต่างจาก CLAUDE.md และ skills อย่างไร?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Key takeaways">

ประเด็นสำคัญ

`CLAUDE.md` คือข้อความที่โมเดลอ่านเมื่อเริ่มเซสชันและพยายามทำตาม Hook คือคำสั่ง shell ที่กระบวนการ Claude Code เรียกใช้เมื่อตอบสนองต่อ event โดยไม่ขึ้นกับโมเดล ส่วน skill คือชุดคำสั่งที่มีชื่อ ซึ่ง Claude เรียกใช้ด้วยเครื่องมือ Skill ได้เหมือนฟังก์ชัน ทั้งสามอย่างเหมาะกับงานคนละประเภท

</div>

เอกสารของ Anthropic อธิบายความแตกต่างระหว่าง `CLAUDE.md` กับ hooks ไว้อย่างชัดเจน:

<figure>
<blockquote>
<p>เนื้อหา CLAUDE.md จะถูกส่งมาเป็นข้อความจากผู้ใช้หลัง system prompt ไม่ได้เป็นส่วนหนึ่งของ system prompt Claude อ่านและพยายามทำตาม แต่ไม่มีการรับประกันว่าจะปฏิบัติตามอย่างเคร่งครัด</p>
</blockquote>
<figcaption>— Anthropic, เอกสารเกี่ยวกับ memory, https://code.claude.com/docs/en/memory</figcaption>
</figure>

กล่าวอีกอย่างคือ เนื้อหาใน `CLAUDE.md` ส่งถึง Claude ในฐานะข้อความแรกจากผู้ใช้ ไม่ใช่คำสั่งระบบ โมเดลจะอ่านและพยายามทำตาม แต่ไม่มีหลักประกัน โดยเฉพาะช่วงท้ายของเซสชันยาว ๆ เมื่อบริบทเพิ่มขึ้นและคำสั่งเก่าถูกดันออกไป

Hook ทำงานต่างออกไป มันอยู่ใน `settings.json` ไม่ขึ้นกับโมเดล และกระบวนการ Claude Code จะเรียกใช้เมื่อเกิด event เฉพาะ เช่น `PreToolUse`, `PostToolUse`, `SessionStart` และอื่น ๆ คำสั่งจะทำงานก่อน Claude ได้รับผลลัพธ์ และสามารถบล็อกการกระทำจริง ๆ (exit 2) หรือแก้ไขไฟล์หลังการแก้ไข (exit 0)

เปรียบเทียบ:

| คุณสมบัติ | CLAUDE.md | Hook | Skill |
|----|----|----|----|
| อยู่ที่ไหน | `CLAUDE.md` ในรูทโปรเจกต์ | `.claude/settings.json` | โฟลเดอร์ `.claude/skills/` |
| ใครเป็นผู้เรียกใช้ | โมเดลอ่านเป็นส่วนหนึ่งของข้อความผู้ใช้ | กระบวนการ Claude Code เมื่อเกิด event | โมเดลผ่านเครื่องมือ Skill |
| รับประกันการทำงานหรือไม่ | ไม่ (พยายามอย่างดีที่สุด) | command hook ที่ตั้งและ matcher ตรงรันโค้ด แต่ความล้มเหลวกับ exit ขึ้นกับ event | ผ่านการเรียกโมเดล (มีการอนุญาต แต่ไม่ใช่ระดับ shell) |
| ใช้ทำอะไร | บริบทโปรเจกต์ น้ำเสียง รูปแบบ การกำหนดเส้นทาง | ข้อจำกัด การจัดรูปแบบ การตรวจสอบไฟล์เฉพาะ | ขั้นตอนซับซ้อนหลายขั้นที่มีพารามิเตอร์ |
| ทำงานเมื่อใด | ทุกข้อความของโมเดลในเซสชัน | เมื่อเกิด event ในวงจรการทำงาน | เมื่อโมเดลเรียกใช้ |
| บล็อกการกระทำได้หรือไม่ | ไม่ได้ | ได้ (exit 2) | ไม่ได้ |

เทมเพลต `CLAUDE.md` ฉบับเต็มและกฎ 6 ข้อสำหรับไฟล์ที่ดูแลต่อเนื่องอยู่ในคู่มือ [วิธีกำหนดค่า CLAUDE.md ในปี 2026: เทมเพลตพร้อมใช้และกฎ 6 ข้อ](https://ailoot.ai/blog/th/claude-md-template/) ดูข้อมูลเกี่ยวกับ skills ในฐานะความสามารถที่มีชื่อได้ที่ [Claude Code Skills: วิธีสร้างคลังของคุณเอง](https://ailoot.ai/blog/th/claude-code-skills-library/)

Hook เป็นระดับต่ำสุด: ไม่มีโมเดล ไม่มีการตีความ มีแค่ shell

Hooks เป็นหนึ่งในเครื่องมือด้าน [context engineering](https://ailoot.ai/blog/th/context-engineering/) ควบคู่กับ Plan Mode และ /compact



## Hook 4 ประเภท: Command, HTTP, Prompt, Agent — ควรเลือกแบบไหน?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Key takeaways">

ประเด็นสำคัญ

Claude Code มี handler 4 ประเภท Command คือสคริปต์ shell และเป็นประเภทที่พบบ่อยที่สุด HTTP ส่งคำขอ POST ไปยัง URL ของคุณ เหมาะสำหรับทีมและการผสานระบบ Prompt เรียก Haiku สั้น ๆ เพื่อตรวจสอบความหมาย Agent สร้าง subagent ที่เข้าถึงเครื่องมือได้เพื่อการตรวจสอบเชิงลึก มือใหม่ต้องใช้ Command และ Prompt ซึ่งครอบคลุมงาน 90%

</div>

| ประเภท | ทำอะไร | ควรเลือกใช้เมื่อใด | ความซับซ้อน |
|----|----|----|----|
| **Command** | เรียกคำสั่ง shell รับ JSON ผ่าน stdin และตอบกลับด้วย exit code และ stdout | 90% ของกรณี: ตรวจสอบ path, จัดรูปแบบ, grep เนื้อหา, lsof, การทำงานกับ git | ต่ำ |
| **HTTP** | ส่งคำขอ POST ไปยัง URL ของคุณพร้อม JSON body และรับ JSON ตอบกลับ | เมื่อกฎเป็นของทีมหรือ CI: การตรวจสอบจากส่วนกลาง แดชบอร์ดสถานะที่ใช้ร่วมกัน การตรวจสอบจากระยะไกล | ปานกลาง (ต้องมีเซิร์ฟเวอร์) |
| **Prompt** | ส่งพรอมป์ต์สั้น ๆ ไปยัง Haiku (ตามค่าเริ่มต้น) แล้วรับ yes/no เพื่อประเมินเชิงความหมาย | เมื่อ grep ไม่พอ: “ประเมินว่าข้อความนี้ฟังดูเป็นภาษาบริษัทหรือไม่” | ต่ำ |
| **Agent** | สร้าง subagent ที่เข้าถึง Read/Grep/Glob ได้ เพื่อทำการตรวจสอบหลายขั้นตอน | การตรวจสอบที่หนักหน่วง: “ค้นหาไฟล์ที่เปลี่ยนทั้งหมดและตรวจว่ามีการทดสอบที่เกี่ยวข้องหรือไม่” | สูง |

ข้อผิดพลาดที่พบบ่อยที่สุดคือพยายามใช้ Command ทำสิ่งที่ต้องใช้ Prompt ตัวอย่างเช่น “ห้ามใช้ em dash ในไฟล์ `.md`” เป็นงาน grep จึงเหมาะกับ Command แต่ “ห้ามเขียนด้วยน้ำเสียงแบบบริษัท” เป็นเรื่องเชิงความหมาย จึงต้องใช้ Prompt

หากเพิ่งเริ่มต้น ให้ใช้ Command Hooks พร้อมใช้ทั้ง 7 รายการด้านล่างเป็น Command ทั้งหมด ส่วน HTTP/Prompt/Agent ค่อยใช้เมื่อพร้อม

## settings.json อยู่ที่ไหน และมี config 4 ระดับอะไรบ้าง?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Key takeaways">

ประเด็นสำคัญ

Claude Code ค้นหาการตั้งค่าจาก 4 ตำแหน่ง ได้แก่ ระดับองค์กร (ติดตั้งผ่าน MDM), ระดับผู้ใช้ (`~/.claude/settings.json`), ระดับโปรเจกต์ (`.claude/settings.json` ในรูท repository) และระดับ local (`.claude/settings.local.json` ซึ่งไม่อยู่ใน git) ไฟล์ทั้ง 4 จะถูกรวมกันเมื่อเริ่มเซสชัน โดยระดับที่อยู่ล่างกว่าจะมีสิทธิ์เหนือกว่า

</div>

| ระดับ | Path | มีผลเมื่อใด | อยู่ใน git หรือไม่ |
|----|----|----|----|
| องค์กร | `/Library/Application Support/ClaudeCode/settings.json` (Mac), `/etc/claude-code/settings.json` (Linux) | ใช้กับทั้งทีมผ่าน MDM | ไม่ |
| ผู้ใช้ | `~/.claude/settings.json` | ทุกโปรเจกต์ของผู้ใช้คนเดียว | ไม่ |
| โปรเจกต์ | `.claude/settings.json` ในรูท repository | โปรเจกต์นี้ สำหรับทั้งทีม | **ใช่** |
| Local | `.claude/settings.local.json` | เฉพาะโปรเจกต์นี้และผู้ใช้คนนี้ | **ไม่** (อยู่ใน `.gitignore`) |

ฉันเก็บ hooks ทั้ง 7 รายการที่อธิบายไว้ด้านล่างใน `.claude/settings.json` ระดับ **โปรเจกต์** จึงถูกรวมโดยอัตโนมัติเมื่อ clone repository และ Claude ใช้กฎเดียวกันในหน้าต่างใหม่ ส่วน hooks ทดลองส่วนตัวจะเก็บไว้ใน `.claude/settings.local.json` เพื่อไม่ให้รบกวนทีม

ไฟล์ทั้ง 4 จะถูกรวมเมื่อเริ่มเซสชัน หากกฎขัดแย้งกัน ระดับที่อยู่ล่างกว่าจะมีสิทธิ์เหนือกว่า (local เหนือ project และ project เหนือ user)

**วิธีสร้าง hook แรกที่เร็วที่สุด** คือใช้เมนูโต้ตอบ `/hooks` ใน Claude Code เลือก event จากรายการ เลือก matcher (เช่น `Bash` หรือ `Edit`) แล้ววางคำสั่ง Claude Code จะเขียน JSON ที่ถูกต้องลงใน `settings.json` ให้

## Event ในวงจรการทำงาน 31 รายการ: มือใหม่ควรใช้รายการใดบ้าง?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Key takeaways">

ประเด็นสำคัญ

ปัจจุบัน Claude Code มี event ตลอดวงจรการทำงาน 31 รายการ แบ่งเป็น 3 ความถี่ ได้แก่ ครั้งเดียวต่อเซสชัน (`SessionStart`/`SessionEnd`), ครั้งเดียวต่อเทิร์น (`UserPromptSubmit`/`Stop`) และทุกครั้งที่เรียกใช้เครื่องมือ (`PreToolUse`/`PostToolUse`) มือใหม่ต้องใช้ 4 event จากทั้งหมด 31 รายการ: `PreToolUse` สำหรับข้อจำกัด, `PostToolUse` สำหรับการแก้ไขอัตโนมัติ, `SessionStart` สำหรับบริบท และ `Stop` สำหรับการตรวจสอบขั้นสุดท้าย

</div>

<figure>
<blockquote>
<p>Event เกิดขึ้นในสามความถี่: ครั้งเดียวต่อเซสชัน (SessionStart, SessionEnd), ครั้งเดียวต่อเทิร์น (UserPromptSubmit, Stop, StopFailure) และทุกครั้งที่เรียกใช้เครื่องมือภายใน agentic loop (PreToolUse, PostToolUse)</p>
</blockquote>
<figcaption>— Anthropic, เอกสารอ้างอิง hooks, https://code.claude.com/docs/en/hooks</figcaption>
</figure>

ควรทำความเข้าใจความถี่ทั้งสามแบบเพื่อไม่ให้สับสน:

1.  **ครั้งเดียวต่อเซสชัน** - `SessionStart`, `SessionEnd`, `Setup` ทำงานครั้งเดียวเมื่อเปิดและปิด Claude Code ใช้เริ่มต้นบริบทและล้างไฟล์ชั่วคราว
2.  **ครั้งเดียวต่อเทิร์น** - `UserPromptSubmit`, `UserPromptExpansion`, `Stop`, `StopFailure` ทำงานเมื่อมีข้อความจากคุณแต่ละครั้งและเมื่อโมเดลหยุดแต่ละครั้ง ใช้บันทึกบทสนทนาและตรวจสอบผลลัพธ์สุดท้าย
3.  **ทุกครั้งที่เรียกใช้เครื่องมือ** - `PreToolUse`, `PostToolUse`, `PostToolUseFailure`, `PermissionRequest`, `PermissionDenied`, `PostToolBatch`, `SubagentStart`, `SubagentStop` ทำงานทุกครั้งที่แก้ไขไฟล์ เปิด Bash อ่าน หรือค้นหา นี่คือชั้นที่ทำงานถี่ที่สุด ซึ่งเป็นที่อยู่ของข้อจำกัด การจัดรูปแบบ และการตรวจสอบ

รายการ event ทั้ง 31 รายการยังรวม event แบบ asynchronous/reactive ด้วย ได้แก่ `TeammateIdle`, `PreCompact`, `PostCompact`, `Elicitation`, `ElicitationResult`, `InstructionsLoaded`, `ConfigChange`, `CwdChanged`, `FileChanged`, `WorktreeCreate`, `WorktreeRemove`, `Notification` รายการเหล่านี้ใช้กับกรณีขั้นสูง ข้ามไปก่อนได้

## แบบทดสอบ 5 คำถาม: กฎควรอยู่ใน hook หรือคงไว้ใน CLAUDE.md?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Key takeaways">

ประเด็นสำคัญ

ถ้ากฎเกี่ยวกับการกระทำ (ไม่ใช่บริบท) เกี่ยวข้องกับความปลอดภัย/เงิน/ข้อมูล ตรวจสอบได้ด้วย grep/regex แก้ไขผลเสียได้ยาก และ Claude เคยละเมิดกฎนี้อย่างน้อยหนึ่งครั้ง กฎนั้นควรอยู่ใน hook หากคำตอบ “ใช่” น้อยกว่า 3 ข้อจาก 5 ข้อ ให้คงไว้ใน `CLAUDE.md` ฉันทดสอบกับเนื้อหา 80 บรรทัดของตัวเอง แล้วกฎ 5 ข้อถูกย้ายไป hooks

</div>

สำหรับฉัน วิธีนี้ทำงานเหมือนกฎหมาย ไม่ใช่คำแนะนำ ฉันย่อการตัดสินใจระหว่าง `CLAUDE.md` กับ hook ให้เหลือแบบทดสอบง่าย ๆ 5 ข้อ ถ้าตอบ “ใช่” อย่างน้อย 3 ข้อ กฎนั้นจะไปอยู่ใน hook ถ้าน้อยกว่า 3 ข้อ ก็อยู่ในข้อความต่อไป

**แบบทดสอบ “กฎควรอยู่ใน hook เมื่อใด”:**

1.  กฎนี้เกี่ยวกับการกระทำมากกว่าบริบทหรือไม่? (“ห้ามเรียก `rm -rf`” เป็นเรื่องการกระทำ; “ฉันมีโปรเจกต์ TypeScript” เป็นบริบท)
2.  กฎนี้เกี่ยวกับความปลอดภัย เงิน หรือข้อมูลหรือไม่? (“ห้ามแตะ `.env`”, “ห้ามเผยแพร่คีย์”)
3.  ตรวจสอบได้ด้วย grep, regex หรือ exit code ของคำสั่ง shell หรือไม่? (“หลังแก้ `.md` ให้ตรวจว่าไม่มี em dash”)
4.  หากละเมิดกฎแล้ว ผลที่ตามมาจะแก้ไขได้ยากหรือไม่? (“force push ไปยัง main” แก้ไขได้ยาก; “ลืมใส่จุดท้ายประโยค” แก้ได้ง่าย)
5.  คุณเคยเห็น Claude ลืมกฎนี้อย่างน้อยหนึ่งครั้งแล้วหรือไม่?

**ตัวอย่าง: “ห้ามใช้ em dash ให้ใช้ hyphen เท่านั้น”** เกี่ยวกับการกระทำไหม? ใช่ ความปลอดภัยไหม? ไม่ ตรวจด้วย grep ได้ไหม? ได้ แก้ไขยากไหม? ไม่ เคยเห็นว่าละเมิดไหม? เคย **3 จาก 5: ใส่ไว้ใน hook**

**ตัวอย่างที่ตรงกันข้าม: “ฉันมี vibe coders ไม่ใช่ developers ให้เขียนโดยไม่ใช้คำสแลง”** เกี่ยวกับการกระทำไหม? เป็นบริบทมากกว่า ความปลอดภัยไหม? ไม่ ตรวจด้วย regex ได้ไหม? ยากเกินไป แก้ไขยากไหม? ไม่ เคยเห็นว่าละเมิดไหม? เคย **1 จาก 5: คงไว้ใน `CLAUDE.md`**

กฎของฉัน 5 ข้อผ่านแบบทดสอบ จึงย้ายไปไว้ใน hooks ส่วนอีก 75% ยังคงอยู่ในไฟล์ข้อความ

## Hooks 7 รายการพร้อมคัดลอกไปใช้

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Key takeaways">

ประเด็นสำคัญ

ด้านล่างคือ hooks พร้อมใช้ 7 รายการสำหรับ `.claude/settings.json`: บล็อกการแก้ไข `.env`, เรียก prettier โดยอัตโนมัติ, ป้องกัน force-push ไปยัง main, ตรวจหา em dash, เคลียร์พอร์ตก่อน `npm run dev`, auto-commit หลังทดสอบสำเร็จ และใส่บริบทล่าสุดเมื่อเริ่มเซสชัน คัดลอกแต่ละรายการลงไฟล์ แล้วเริ่ม Claude Code ใหม่ ก็ใช้งานได้เลย

</div>

Hooks ทั้ง 7 รายการเก็บไว้ในไฟล์ `.claude/settings.json` ไฟล์เดียวที่รูทโปรเจกต์ แต่ละรายการประกอบด้วยประเภท event, ตัวกรองเครื่องมือ (matcher) และคำสั่ง shell exit code 2 ปฏิเสธ PreToolUse ที่ตรงก่อนรัน แต่ใน PostToolUse การกระทำเกิดแล้ว hook ให้ feedback และย้อนการกระทำไม่ได้

<figure>
<blockquote>
<p>สำหรับ event ของ hook ส่วนใหญ่ มีเพียง exit code 2 เท่านั้นที่บล็อกการกระทำ Claude Code ถือว่า exit code 1 เป็นข้อผิดพลาดที่ไม่บล็อก และดำเนินการต่อ แม้ตามธรรมเนียม Unix ค่า 1 จะหมายถึงความล้มเหลวก็ตาม</p>
</blockquote>
<figcaption>— Anthropic, เอกสารอ้างอิง hooks, https://code.claude.com/docs/en/hooks</figcaption>
</figure>

`exit 0` หมายถึงสำเร็จ `exit 1` หมายถึงเกิดข้อผิดพลาด แต่ Claude ทำต่อ (นี่คือ anti-pattern แรกด้านล่าง) `exit 2` มีผลตาม event บล็อก PreToolUse ได้ แต่ PostToolUse รายงาน feedback ของสิ่งที่ทำแล้วเท่านั้น

### Hook 1. กันการแก้ `.env` โดยตรง (PreToolUse, exit 2)

บล็อกความพยายามแก้ไขโดยตรงกับไฟล์ใดก็ตามที่ตรงกับ `.env`, `.env.local`, `.env.production` และอื่น ๆ

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(jq -r '.tool_input.file_path // empty'); [ -z \"$FILE\" ] && exit 0; echo \"$FILE\" | grep -qE '(^|/)\\.env(\\.|$)' && { echo 'Do not edit `.env` directly. Tell me which variable to add, and I’ll open the file myself.' >&2; exit 2; } || exit 0"
          }
        ]
      }
    ]
  }
}
```

**การทำงาน:** ก่อน `Edit`/`Write`/`MultiEdit` ทุกครั้ง hook จะดึง path ของไฟล์ ตรวจด้วย grep ว่าตรงกับรูปแบบ `.env` หรือไม่ และถ้าตรงก็ส่ง exit 2 พร้อมข้อความ Claude เห็น stderr และบอกฉันว่า “ฉันพยายามแก้ `.env` แต่ hook บล็อกไว้ บอกฉันว่าต้องเพิ่มตัวแปรใด”

### Hook 2. เรียก prettier โดยอัตโนมัติหลังแก้โค้ดทุกครั้ง (PostToolUse, exit 0)

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(jq -r '.tool_input.file_path // empty'); [ -z \"$FILE\" ] && exit 0; echo \"$FILE\" | grep -qE '\\.(ts|tsx|js|jsx|json)$' && npx prettier --write \"$FILE\" 2>/dev/null & exit 0"
          }
        ]
      }
    ]
  }
}
```

**การทำงาน:** หลัง `Edit`/`Write` ทุกครั้ง hook จะดึง path และถ้านามสกุลเป็น `.ts`/`.tsx`/`.js`/`.jsx`/`.json` ก็เรียก prettier ทำงานเบื้องหลังด้วย `&` โดยจะจบด้วย exit 0 เสมอ เพราะเป็นการจัดรูปแบบ ไม่ใช่ข้อจำกัด หาก prettier ล้มเหลวก็ไม่เป็นไร ไฟล์ยังคงสภาพเดิม

ความแตกต่างระหว่าง hook 1 และ hook 2 เป็นเรื่องพื้นฐาน: PreToolUse + exit 2 คือการบล็อกอย่างเด็ดขาด **ก่อน** ทำงาน ส่วน PostToolUse + exit 0 คือการแก้ไขแบบไม่เข้มงวด **หลัง** ทำงาน ทั้งสองแบบมีไว้สำหรับงานคนละประเภท

### Hook 3. บล็อก `git push --force` ไปยัง branch main (PreToolUse, exit 2)

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "CMD=$(jq -r '.tool_input.command // empty'); [ -z \"$CMD\" ] && exit 0; echo \"$CMD\" | grep -qE 'git[[:space:]]+push' && echo \"$CMD\" | grep -qE '(\\-\\-force|\\-\\-force-with-lease|[[:space:]]-f([[:space:]]|$))' && echo \"$CMD\" | grep -qE '([[:space:]/:])main([[:space:]/:]|$)' && { echo 'Force push to main is forbidden. Create a new branch or ask me to do it manually.' >&2; exit 2; } || exit 0"
          }
        ]
      }
    ]
  }
}
```

**การทำงาน:** ทุกครั้งที่เปิด Bash จะตรวจว่าคำสั่งมี `push`, มี `--force`/`--force-with-lease`/`-f` และกล่าวถึง `main` หรือไม่ หากตรงครบทั้งสามเงื่อนไข ก็จะบล็อกพร้อมข้อความที่ชัดเจน

เมื่อก่อนฉันเขียนกฎนี้ด้วยตัวพิมพ์ใหญ่ทั้งหมดไว้ใน `CLAUDE.md` Claude ก็ยังละเมิดประมาณทุกสองสัปดาห์ ตอนที่ฉันขอให้ “force push เพื่อยกเลิก commit ที่ทำพลาด” hook จับรูปคำสั่งตรงที่แสดง แต่ aliases สคริปต์ branch ปลายทางโดยนัย หรือ Git client อื่นข้าม string check ได้ ต้องบังคับป้องกัน main บน remote และจำกัด credentials ของเอเจนต์

### Hook 4. บล็อก em dash ในไฟล์ข้อความ (PostToolUse, exit 2)

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write|MultiEdit",
        "hooks": [
          {
            "type": "command",
            "command": "FILE=$(jq -r '.tool_input.file_path // empty'); [ -z \"$FILE\" ] && exit 0; echo \"$FILE\" | grep -qE '\\.(md|mdx|tsx?)$' && grep -q $'\\xe2\\x80\\x94' \"$FILE\" && { echo \"File $FILE contains an em dash (U+2014). Replace it with a regular hyphen (U+002D).\" >&2; exit 2; } || exit 0"
          }
        ]
      }
    ]
  }
}
```

**การทำงาน:** PostToolUse ที่คืน exit 2 รายงานการตรวจหลังแก้ไม่ผ่านแก่ Claude ไม่ย้อนหรือป้องกันการเขียนที่เกิดแล้ว หาก Claude แก้ไฟล์แล้วทิ้ง em dash ไว้ hook จะไม่ผ่าน Claude ได้รับผลตอบกลับและลองอีกครั้ง หลังผ่านไป 2–3 เซสชัน Claude จะเลิกใส่อักขระนี้โดยสิ้นเชิง

โปรดสังเกตว่า grep ค้นหาอักขระ em dash (U+2014) โดยเฉพาะผ่าน `$'\xe2\x80\x94'` ซึ่งเป็นสัญกรณ์ Bash สำหรับเขียนอักขระนี้เป็นไบต์ UTF-8 หากเขียน `grep -q '-'` เฉย ๆ ก็จะจับ hyphen ปกติด้วยและทำงานกับทุกไฟล์ อักขระที่มองไม่เห็นทำให้ตรรกะทั้งหมดเสียหาย

### Hook 5. เคลียร์พอร์ต 3000 ก่อน `npm run dev` (PreToolUse, exit 0)

```json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "CMD=$(jq -r '.tool_input.command // empty'); [ -z \"$CMD\" ] && exit 0; echo \"$CMD\" | grep -qE '(npm|pnpm|yarn)[[:space:]]+run[[:space:]]+dev' && { lsof -ti:3000 | xargs -r kill -9 2>/dev/null; echo 'Port 3000 freed before launch' >&2; }; exit 0"
          }
        ]
      }
    ]
  }
}
```

**การทำงาน:** ก่อน `npm run dev` (หรือ `pnpm`/`yarn`) ทุกครั้ง จะฆ่ากระบวนการที่ใช้พอร์ต 3000 และจบด้วย exit 0 เสมอ เพราะเป็นการเตรียมการ ไม่ใช่ข้อจำกัด วิธีนี้ช่วยป้องกันปัญหาที่ Claude เห็นว่า “พอร์ตถูกใช้งานอยู่” แล้วคิดว่าโค้ดมีปัญหาจึงเริ่มแก้ ทั้งที่จริงเซิร์ฟเวอร์เก่ายังค้างอยู่

### Hook 6. auto-commit หลังการทดสอบสำเร็จ (PostToolUse, exit 0)

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": "INPUT=$(cat); CMD=$(printf '%s' \"$INPUT\" | jq -r '.tool_input.command // empty') || exit 1; EXIT=$(printf '%s' \"$INPUT\" | jq -r '.tool_response.exit_code // empty') || exit 1; case \"$CMD\" in 'npm test'|'pnpm test'|'yarn test') ;; *) exit 0 ;; esac; [ \"$EXIT\" = \"0\" ] || exit 0; git diff --cached --quiet || { echo 'Existing staged changes: review manually' >&2; exit 0; }; git add -- src/orders.ts tests/orders.test.ts || exit 1; git diff --cached --quiet && exit 0; git commit -m 'tests: checkpoint after successful run'"
          }
        ]
      }
    ]
  }
}
```

**การทำงาน:** อ่าน JSON จาก stdin ครั้งเดียว รับเฉพาะคำสั่ง test ธรรมดาที่ระบุตรง ทำต่อเฉพาะ `tool_response.exit_code` มีค่าเป็นศูนย์ชัด หากรุ่นติดตั้งไม่ส่งฟิลด์นี้ให้ข้าม commit แทนเดาว่าสำเร็จ แทน `src/orders.ts` กับ `tests/orders.test.ts` ด้วยไฟล์ตรงที่งานรับผิดชอบ หากมี staged changes เดิมจะหยุดสูตรไม่รวมงานอื่น add ล้มต้องหยุด diff ว่างไม่สร้าง commit และยังเปิด commit hooks ปกติ ทดสอบ input สำเร็จ ล้มเหลว และไม่มีผลแบบ offline ก่อนเปิด

รูปแบบที่ควรหลีกเลี่ยงคือเพิ่ม `git commit --no-verify` ทุก Edit ต้องคง commit checks หาก check เรียกอัตโนมัตินี้ซ้ำวน ให้จำกัด trigger หรือออกแบบ check ใหม่ ไม่ข้ามการตรวจเป็นค่าเริ่มต้น ตรวจ staged diff กับขอบเขตงานก่อนเปิด auto-commit

### Hook 7. ใส่บริบทล่าสุดเมื่อเริ่มเซสชัน (SessionStart พร้อม additionalContext)

```json
{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "*",
        "hooks": [
          {
            "type": "command",
            "command": "BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo 'no-branch'); STATUS=$(git status --short 2>/dev/null | head -10); echo \"{\\\"additionalContext\\\":\\\"Current branch: $BRANCH. Uncommitted changes:\\n$STATUS\\\"}\""
          }
        ]
      }
    ]
  }
}
```

**การทำงาน:** เมื่อเริ่มเซสชัน จะรวบรวม branch Git ปัจจุบันและรายการการเปลี่ยนแปลงที่ยังไม่ได้ commit จากนั้นส่ง JSON ที่มีฟิลด์ `additionalContext` Claude Code จะใส่ข้อความนี้ใน system message แรก ทำให้ Claude รู้ตั้งแต่ต้นว่ากำลังอยู่ที่ไหนและมีงานอะไรจากเซสชันก่อนค้างอยู่

<figure>
<blockquote>
<p>ใช้ additionalContext สำหรับข้อมูลที่ Claude ควรรู้เกี่ยวกับสถานะปัจจุบันของสภาพแวดล้อมหรือการดำเนินการที่เพิ่งเสร็จสิ้น: สถานะสภาพแวดล้อม (branch ปัจจุบัน เป้าหมายการ deploy feature flag ที่ใช้งานอยู่), กฎโปรเจกต์แบบมีเงื่อนไข (คำสั่งทดสอบใดใช้กับไฟล์ที่เพิ่งแก้), ข้อมูลภายนอก (issue ที่เปิดอยู่และมอบหมายให้คุณ ผล CI ล่าสุด)</p>
</blockquote>
<figcaption>— Anthropic, เอกสารอ้างอิง hooks, https://code.claude.com/docs/en/hooks</figcaption>
</figure>

ส่วนขยายของ hook นี้: ดึง commit ล่าสุดและคำอธิบาย สถานะ GitHub Actions sprint ที่กำลังทำใน Linear/Jira และ issue ที่เปิดอยู่ของ repository ปัจจุบัน

## ข้อผิดพลาดจาก hooks 3 ข้อที่คนส่วนใหญ่เจอ

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Key takeaways">

ประเด็นสำคัญ

ข้อผิดพลาดแรก: hook ที่ออกด้วย exit 1 ผ่านไปอย่างเงียบ ๆ และ Claude เพิกเฉยต่อข้อผิดพลาด ข้อที่สอง: งานหนักใน hook จะถูกยุติเมื่อครบ timeout 60 วินาที ข้อที่สาม: hook เห็นเฉพาะ environment variable จาก `~/.zshrc` ไม่ใช่ `.env` ของโปรเจกต์ แก้แต่ละข้อได้ด้วยบรรทัดเดียว แต่ถ้าไม่รู้ข้อผิดพลาดเหล่านี้ อาจดูเหมือนว่า “hooks ใช้ไม่ได้”

</div>

### ข้อผิดพลาด 1. Hook ที่ออกด้วย exit 1 ผ่านไปอย่างเงียบ ๆ

ข้อนี้อันตรายที่สุด เป็นเวลาหนึ่งสัปดาห์ที่ฉันคิดว่าตัวป้องกัน `.env` ทำงาน แต่ปรากฏว่าใน hook ฉันใช้ `jq -r '.tool_input.file_path'` โดยไม่ได้ตรวจ null เมื่อ `tool_input` ว่าง jq ออกด้วย code 1 Claude มอง exit 1 ว่า “hook error, ทำต่อ” การกระทำจึงเกิดขึ้น ฉันไม่เข้าใจว่าทำไมยังมีการแตะ `.env` จนกระทั่งรัน hook ด้วยตนเองใน terminal โดยป้อน input ว่างและพบสาเหตุ

**วิธีแก้มีเพียงกฎเดียว:** เริ่ม hook ทุกตัวด้วยการตรวจ null และจบด้วย `|| exit 0` หากเกิด exit ที่ไม่คาดคิด ก็จะออกอย่าง “ปลอดภัย” แทนที่จะผ่านไปอย่างเงียบ ๆ

```bash
# Safe start and end template:
FILE=$(jq -r '.tool_input.file_path // empty')
[ -z "$FILE" ] && exit 0
# ... your logic ...
exit 0   # or || exit 0 on one line
```

### ข้อผิดพลาด 2. Hooks ที่ช้าจะถูกยุติเมื่อหมดเวลา

ฉันเคยมี hook ที่รัน `eslint --fix` กับทั้งไฟล์หลัง Edit ไฟล์ขนาดใหญ่ (1000+ บรรทัด) ใช้เวลาประมวลผล 8–10 วินาที ค่าเริ่มต้น timeout ของ hook ใน Claude Code คือ 60 วินาที ฉันจึงคิดว่ายังอยู่ในขีดจำกัด แต่เมื่อมีการ Edit หลายครั้งภายในหนึ่งนาที hooks จะสะสมและรอในคิว บางรายการก็ถูกข้ามไป ฉันรู้ตัวเมื่อ log แสดงข้อความ “hook timed out”

**วิธีแก้:** หาก hook ต้องทำงานหนัก ให้ทำงานเบื้องหลัง `eslint --fix "$FILE" &` โดยไม่รอผลลัพธ์ จากนั้น hook จะคืน exit 0 ภายในไม่กี่มิลลิวินาที ขณะที่งานจริงยังทำงานอยู่เบื้องหลัง

```bash
# Heavy operation in background:
npx eslint --fix "$FILE" &
exit 0
```

### ข้อผิดพลาด 3. Hook มองไม่เห็น environment variable ของโปรเจกต์

ฉันคิดว่า `process.env` จะใช้ได้ใน hook เช่นเดียวกับแอป Node.js แต่ไม่ใช่ Hook ทำงานใน shell ที่กระบวนการหลักของ Claude Code เรียกขึ้นมา และมองเห็นเฉพาะสิ่งที่อยู่ใน `~/.zshrc` หรือ `~/.bashrc` รวมถึงสิ่งที่ Claude Code ส่งผ่านให้อย่างชัดเจน หาก hook ของคุณต้องใช้ `OPENAI_API_KEY` จาก `.env` คุณต้องอ่าน `.env` ด้วยตนเอง

**วิธีแก้:** อ่าน `.env` อย่างชัดเจนในคำสั่ง hook

```bash
# Passing project env into hook:
cd "$PWD" && source .env && curl -H "Authorization: Bearer $OPENAI_API_KEY" ...
# Or with dotenv:
dotenv -e .env -- node my-validator.js
```

ปัญหานี้ลำบากเป็นพิเศษใน monorepo ซึ่งแต่ละแพ็กเกจมีไฟล์ `.env` ของตัวเอง แก้โดยส่ง `PWD` ผ่านมาและเรียก `cd "$PWD"` อย่างชัดเจนตั้งแต่ต้นคำสั่ง

## ทดสอบ hooks ก่อน commit อย่างไร?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Key takeaways">

ประเด็นสำคัญ

Hook เป็นคำสั่ง shell คุณเรียกใช้ด้วยตนเองใน terminal โดยป้อน stdin จำลอง ตรวจ exit code และ stderr ได้ก่อนที่ Claude Code จะเรียกใช้ วิธีนี้ช่วยประหยัดเวลาหลายชั่วโมงในการแก้ปัญหา และป้องกัน hooks ที่บล็อกการทำงานของตัวเอง

</div>

**สถานการณ์ทดสอบพื้นฐาน** นำคำสั่ง hook จาก JSON เปิด terminal แล้วป้อน JSON ที่ Claude Code จะส่งให้:

```bash
# Test hook 1 (protect .env):
echo '{"tool_input":{"file_path":".env"}}' | bash -c '
FILE=$(jq -r ".tool_input.file_path // empty")
[ -z "$FILE" ] && exit 0
echo "$FILE" | grep -qE "(^|/)\.env(\.|$)" && {
  echo "BLOCKED" >&2
  exit 2
} || exit 0
'
echo "Exit code: $?"
```

ควรเห็น `BLOCKED` ใน stderr และ `Exit code: 2` หากได้ exit 0 แสดงว่า regex ใช้ไม่ได้ ให้แก้ grep

**สถานการณ์ที่ควรตรวจสอบ:**

1.  **กรณีปกติ** - ไฟล์ควรถูกบล็อก: `.env` สำหรับ hook 1, `git push --force main` สำหรับ hook 3
2.  **กรณีเชิงลบ** - ไฟล์ไม่ควรถูกบล็อก: `README.md` สำหรับ hook 1, `git push origin feature-branch` สำหรับ hook 3
3.  **กรณีขอบ** - input ว่าง ค่า null อักขระที่ไม่คาดคิด hook ควรคืน exit 0 หรือไม่ก็ล้มเหลวพร้อมข้อผิดพลาดที่ชัดเจน ห้ามผ่านไปอย่างเงียบ ๆ

**ตำแหน่งเก็บ hooks ทดลอง** อย่าใส่ใน `.claude/settings.json` ให้ใส่ใน `.claude/settings.local.json` (ไม่อยู่ใน git) วาง hooks ใหม่ไว้ใต้ `PostToolUse` โดยใช้ `echo` แทนการกระทำจริง ตรวจว่าทำงานหรือไม่ แล้วค่อยย้ายไปยัง `settings.json` สำหรับใช้งานจริง

```json
// Experiment in settings.local.json - writes to /tmp/hook-debug.log:
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          {
            "type": "command",
            "command": "echo \"[hook fired] $(date) $(jq -r '.tool_input.file_path // \"?\"')\" >> /tmp/hook-debug.log"
          }
        ]
      }
    ]
  }
}
```

หลังแก้ไข 5–10 ครั้งใน Claude Code ให้เปิด `/tmp/hook-debug.log` เพื่อดูว่าไฟล์ใดเรียก hook หากไฟล์ว่าง แสดงว่า matcher ไม่ตรง ให้แก้ regex

## ต่อไปทำอะไร?

<div class="aside" data-semantic="key-takeaway" role="note" aria-label="Key takeaways">

ประเด็นสำคัญ

เริ่มจาก hooks ของ PostToolUse ที่ออกด้วย exit 0 ซึ่งปลอดภัยที่สุดและไม่บล็อกอะไร หลังผ่านไปหนึ่งสัปดาห์ ให้เพิ่ม hook PreToolUse ตัวแรกที่ใช้ exit 2 เพื่อป้องกัน `.env` หรือป้องกัน force-push หลังผ่านไปสองสัปดาห์ `CLAUDE.md` จะลดจากข้อตกลง 200 บรรทัดเหลือคำอธิบายบริบทสั้น ๆ 50–80 บรรทัด โดยย้ายการตรวจ event ที่เลือกไป hooks และบังคับขอบเขตสิทธิ์จริงแยกด้วย permissions, sandboxing และ remote protections

</div>

5 ขั้นตอนสำหรับสัปดาห์ที่จะถึงนี้:

1.  **ค้นหาใน `CLAUDE.md`** ด้วยคำอย่าง “never,” “forbidden,” “always” และ “must” กฎเหล่านี้เป็นตัวเลือกสำหรับ hook หากเป็นคำสั่ง ไฟล์ข้อความจะบังคับใช้ไม่ได้
2.  **เริ่มด้วย PostToolUse + exit 0** ซึ่งปลอดภัยที่สุด: ทำการเปลี่ยนแปลงแต่ไม่บล็อกอะไร Prettier (hook 2), ปิดเซิร์ฟเวอร์ dev (hook 5), auto-commit หลังทดสอบ (hook 6)
3.  **เมื่อมั่นใจแล้วเท่านั้น จึงเพิ่ม PreToolUse + exit 2 ตัวแรก** เช่น ป้องกัน `.env` (hook 1) หรือป้องกัน force-push (hook 3) นี่เป็นการบล็อกแบบเด็ดขาด และข้อผิดพลาดในคำสั่ง grep อาจบล็อกคุณเองได้
4.  **ทดสอบ hooks ด้วยตนเองก่อน commit** (ดูหัวข้อด้านบน) วิธีนี้ช่วยประหยัดเวลาหลายชั่วโมงในการแก้ปัญหา
5.  **เก็บ hooks ทดลองไว้ใน `settings.local.json`** เพิ่ม hooks ใหม่ที่นั่นโดยใช้ `echo` แทนการกระทำจริง

เมื่อตั้งค่า hooks แล้ว ขั้นตอนถัดไปในชุดคู่มือคือ [วิธีย้อนการเปลี่ยนแปลงใน Claude Code](https://ailoot.ai/blog/th/claude-code-undo-changes/) เผื่อ hook ปล่อยให้มีสิ่งอันตรายผ่านไป หากต้องการให้ Claude จดจำโครงสร้างโปรเจกต์ระหว่างเซสชัน ให้สร้าง [Second Brain ใน Claude Code](https://ailoot.ai/blog/th/claude-code-second-brain/) (โฟลเดอร์ `business/` + ฐานความรู้ที่เชื่อมโยงกัน) และหากต้องการตั้งชื่อ skills ของโปรเจกต์เพื่อให้เรียกใช้ซ้ำได้ ดูที่ [Claude Code Skills](https://ailoot.ai/blog/th/claude-code-skills-library/)

<div class="section" role="doc-bibliography" aria-label="Sources">

### แหล่งข้อมูล

- [เอกสารอ้างอิง Claude Code Hooks - เอกสารทางการของ Anthropic](https://code.claude.com/docs/en/hooks)
- [เอกสาร Claude Code Memory - เกี่ยวกับ CLAUDE.md และ system prompt](https://code.claude.com/docs/en/memory)
- [ทำเวิร์กโฟลว์ให้เป็นอัตโนมัติด้วย hooks - คู่มือทางการของ Anthropic พร้อมตัวอย่าง](https://code.claude.com/docs/en/hooks-guide)

</div>





หากต้องการเข้าถึง neural network ผ่าน Ailoot ลองดู [Ailoot](https://ailoot.ai/).

## คำถามที่พบบ่อย

### ทำไม hook ต้องอ่าน JSON input เพียงครั้งเดียว?

stdin เป็นสตรีม jq ตัวแรกอ่านจนหมดทำให้ตัวถัดไปพบ EOF ต้องเก็บ input ครั้งเดียวแล้วดึง command กับผลจากค่าที่เก็บ หากไม่มีผลหรือไม่ทราบให้ถือว่ายังไม่ยืนยันและข้าม auto-commit

### regex hooks ตัวอย่างสร้างขอบเขตความปลอดภัยหรือไม่?

ไม่สร้าง ตรวจเฉพาะ event กับรูปคำสั่งที่รู้จัก shell redirection, aliases, scripts, MCP หรือทางเขียนอื่นอาจข้ามได้ ขีดจำกัดจริงต้องใช้ credentials จำกัด สิทธิ์ไฟล์ sandbox และ branch protection


## Ailoot · บริษัทและพอร์ตโฟลิโอโครงการของบริษัท

Ailoot อาศัยประสบการณ์การดำเนินงานที่สั่งสม ฐานลูกค้าขนาดใหญ่ บริการที่เสถียร และการติดตาม KPI อย่างต่อเนื่อง

บริษัทและพอร์ตโฟลิโอโครงการของบริษัท: ลูกค้าหลายล้านราย; ยอดขายระดับหลายพันล้านต่อเดือน.

Ailoot นำประสบการณ์การดำเนินงานนี้มาใช้เพื่อให้เข้าถึงฟังก์ชัน AI ผ่าน API ในผลิตภัณฑ์ของลูกค้า เอเจนต์ แอปพลิเคชัน และระบบอัตโนมัติ
