Agent Dev Thai Academyprinciples · patterns · architecture

Claude Code Mods มาแล้ว ไทม์ไลน์เต็มไปด้วยคลิป Tetris แต่ของจริงอยู่ในคอมเมนต์ใต้ issue

ของจริงเรื่อง Claude Code Mods อยู่ในคอมเมนต์ใต้ issue ไม่ใช่คลิป Tetris ผมลองพังเองแล้ว hook ที่พังจะถูกข้าม และถ้าไม่เปิด debug ไว้จะไม่เหลือร่องรอยอะไรเลย

Claude Code Mods เพิ่งลงจริงเมื่อ 14 กันยา ไทม์ไลน์ตอนนี้เต็มไปด้วยคลิป Tetris เล่นอยู่เหนือ prompt

แต่ของมันไม่ได้เพิ่งมา มันประกาศตั้งแต่ 3 กันยาในชื่อ Function Hooks ยอดวิวเกือบล้าน แล้วเงียบไปสิบเอ็ดวัน คนส่วนใหญ่เพิ่งมาเห็นตอนมันเปลี่ยนชื่อ

สนุกดี แต่ของที่อ่านแล้วได้กลับมาจริงไม่ได้อยู่บนไทม์ไลน์ มันอยู่ในคอมเมนต์ 183 อันใต้ issue ที่คนใช้ hook หนักที่สุดมารายงานว่าของตัวเองพังมานานแค่ไหนโดยไม่รู้ตัว

แล้วผมก็เอามาลองพังเองบนเครื่องทำงาน ผลอยู่ข้อห้า สั้น ๆ คือถ้าไม่เปิด debug ไว้ hook ที่ตายไปแล้วจะไม่ทิ้งร่องรอยอะไรเลย

คัดมาให้ห้าอันพร้อมลิงก์

หนึ่ง ตัว issue เอง

anthropics/claude-code #91870GitHub ↗

เปิดมาตั้งแต่ 3 กันยา ยังเปิดอยู่ 183 คอมเมนต์ ป้าย enhancement, area:hooks, area:plugins

อ่านตัวจริงเถอะ เทรดบนไทม์ไลน์คือคนสรุปหน้านี้ต่อกันมาอีกที

ของใหม่คือ hook เลิกเป็น shell script ที่รันตามจังหวะที่กำหนดไว้ กลายเป็นฟังก์ชันจริงที่นั่งขวางอยู่กลางทางของเกือบทุกอย่างที่ Claude Code ทำ ดู tool call ได้ บล็อกได้ เขียนทับได้ หรือส่งต่อให้ plugin ตัวถัดไป

คนเสนอเรียกมันว่า middleware ถ้าเคยเขียน Express มาก่อนจะเห็นภาพทันที

สอง ต้นทางจริงคือ @ClaudeDevs วันที่ 3 กันยา

โพสต์ของ @ClaudeDevsx.com ↗

973,845 views 3,298 likes

ตอนนั้นยังชื่อ Function Hooks มีคลิปสองอันให้ดูว่ามันทำอะไรได้ ถ้าจะอ่านอันเดียวอ่านอันนี้ ไม่ใช่โพสต์ที่ไวรัลเมื่อวาน

@bcherny มาโพสต์ "Claude Mods are landing now" วันที่ 14 กันยา ได้ 531,704 views https://x.com/bcherny/status/2099551291601248485 อันนั้นคือตอนของลง ไม่ใช่ตอนของประกาศ ห่างกันสิบเอ็ดวัน

สาม @Prathkum อธิบายว่ามันต่างจากของเดิมยังไง

โพสต์ของ @Prathkumx.com ↗

94,288 views

สรุปดี เปรียบเป็น middleware แบบ Express แล้วไล่ว่าปลดล็อกอะไรบ้าง ซ่อน secret ก่อนโมเดลอ่าน บล็อก action อันตรายได้จริงไม่ใช่แค่เขียนกฎแล้วหวัง แอดมินคุมได้ว่า plugin แตะอะไรได้บ้าง

ประโยคที่เขาพูดแล้วถูกที่สุดคือ คอมเมนต์ใต้ issue ไม่ใช่กระแส มันคือ live audit

สี่ สามอันที่ลงมือติดตั้งได้เลยวันนี้

cc-arcade https://github.com/sezaakgun/cc-arcade

เกมเก้าอัน snake, Tetris, 2048, Minesweeper, Pong, Space Invaders กับ Doom ที่ raycast เป็น half block แล้วมีสัตว์เลี้ยงที่โตตามจำนวนเทสต์ที่ผ่านกับ commit ที่เกิด วางอยู่เหนือ prompt เล่นระหว่างรอ Claude ทำงาน ไม่กิน token สักตัวเพราะ plugin ตอบทุกคลิกเอง ไม่ถามโมเดล

ที่ยกมาไม่ใช่เพราะเกม แต่เพราะมันเป็นตัวแรกที่วาด interactive surface ด้วย function hook จริง อยากรู้ว่าของใหม่ทำอะไรได้ อ่าน README อันนี้เร็วกว่าอ่านสเปก

@daniel_mac8 ทำ skill ไว้ให้สร้าง mod เอง https://x.com/daniel_mac8/status/2099850309807776222

สั่ง /claude-mod-builder แล้วให้มันสร้างให้ ไม่ต้องเริ่มจากศูนย์

@dani_avila7 ใส่ Function Hooks เข้า Claude Code Templates แล้ว https://x.com/dani_avila7/status/2097519092240384237

ขึ้น npm แล้ว ลงจาก template ได้เลย

ห้า ผมลองพังมันเองบนเครื่องทำงาน แล้วได้คำตอบที่ทั้งเทรดถามหา

คำถามที่ค้างอยู่ในคอมเมนต์คือ ถ้า hook มันพัง ของที่มันกันอยู่จะทะลุไปไหม เลยลองเองซะเลย Claude Code 2.1.273 รันแบบ headless ทั้งหมด

เขียน hook ตัวนึงกัน Write ไม่ให้เขียนไฟล์นึง ทดสอบก่อนว่ากันได้จริง กันได้ โมเดลเห็น error แล้วหยุด

แล้วก็ทำให้มันพังห้าแบบ

หนึ่ง hook โยน error ไฟล์ถูกเขียน exit 0 stderr ว่าง

สอง hook ค้างไม่ยอมคืนค่า รอครบ 10 วินาทีตาม budget แล้วไฟล์ถูกเขียน รอบนั้นใช้เวลา 19 วิ จากปกติ 9 วิ ช้าขึ้นเท่าตัวแล้วก็ยังทะลุ

สาม hook คืนค่าผิดรูป ไฟล์ถูกเขียน

สี่ hook ว่างเปล่าไม่ทำอะไร ไฟล์ถูกเขียน

ทั้งสี่แบบขึ้น log บรรทัดเดียวว่า hook failed: ... (tool.call; skipped; what is below it ran in its place)

ห้า อันนี้คือของจริง ลองใหม่โดยไม่เปิด --debug-file

ไฟล์ถูกเขียน ไม่มีร่องรอยที่ไหนเลย stderr มีแต่ warning เรื่อง permission ที่ไม่เกี่ยว ใน ~/.claude/debug/ มี symlink ชื่อ latest ชี้ไปที่ไฟล์ที่ไม่มีอยู่จริง

แปลว่าโดย default ถ้า hook ที่คุณเขียนไว้กันของอันตรายมันตาย คุณไม่มีทางรู้เลย ไม่ใช่รู้ช้า ไม่ใช่ต้องไปขุด คือไม่มีข้อมูลให้ขุด

อีกอย่างที่เจอ stream-json ไม่ยิง event ของ function hook เลย ที่เห็นใน stream เป็น hook แบบเดิมทั้งหมด แปลว่าเขียนตัวเฝ้าจากข้างนอกไม่ได้ ไม่มี CI check ไม่มี alert

และเรื่องที่ตลกที่สุดของวัน รอบแรกที่รัน ไฟล์ถูกเขียนทั้งที่ guard ควรกัน เกือบบันทึกเป็นผลการทดลองไปแล้ว ที่จริงคือ path ของ plugin ผิดเพราะ cd เข้า directory ก่อนรัน plugin เลยไม่ถูกโหลด แล้วมันบอกแค่ WARN ใน debug log ไม่ขึ้น stderr

คนที่ตั้งใจมาทดสอบว่าของมันเงียบตอนพังไหม โดนความเงียบนั้นเล่นตั้งแต่รอบแรก

อีกอย่างที่ต้องพูดให้ชัด ตอนที่ guard มันทำงานปกติ มันทำงานดีมาก ลองสั่งให้เขียนไฟล์ที่ถูกกันไว้สี่รอบ โดนปฏิเสธสี่รอบ แต่ละรอบมี tool call เดียว Write แล้วจบ ไม่มีรอบไหนที่โมเดลหนีไปใช้ bash หรือ python เขียนแทน ลองเปลี่ยนข้อความปฏิเสธให้เหลือแค่คำว่า nope ก็ยังไม่หนี

แต่อันนี้ต้องติดดาวไว้ ลองแค่สี่รอบ โมเดลเดียว และ session ลูกมันอ่าน CLAUDE.md ของผมไปด้วย ซึ่งในนั้นมีกฎเรื่องห้ามข้าม guard อยู่แล้ว โมเดลตอบมาเองว่า "ไม่ได้ลองหนีไปทาง shell เพราะมันจะข้าม guard ที่คุณตั้งไว้" เครื่องที่ไม่มีกฎแบบนี้จะเป็นยังไงยังไม่รู้ อย่าเพิ่งเชื่อว่ากันได้ร้อยเปอร์เซ็นต์

ทางแก้มีอยู่ในเอกสารแล้ว .catch() ต่อท้าย hook ได้ ใน d.ts บอกว่ามันจะทำงานตอน hook โยน error เกิน budget หรือคืนค่าผิดรูป มี next.error บอกว่าเป็น throw หรือ timeout

ตรงนี้ผมยังไม่ได้ลอง เลยไม่ยืนยันว่าใช้ได้จริง แต่ประเด็นไม่ได้อยู่ที่มันเวิร์กไหม ประเด็นคือ fail-closed เป็นของที่ต้องขอ ใครไม่ขอก็ fail-open ไปโดยไม่รู้ตัว แล้วคนส่วนใหญ่ไม่รู้ว่าต้องขอ

และเคสที่แย่ที่สุดไม่ใช่สี่แบบข้างบน มันคือ path ของ plugin ผิด เพราะ guard ไม่ได้ตาย มันไม่เคยเกิดขึ้นเลย และอันนั้นก็เงียบเหมือนกัน


ในคอมเมนต์ใต้ issue คนที่รัน hook หนักอยู่แล้วเจอของแบบเดียวกันมาก่อน อันนี้คือราคาที่จ่ายไปจริง

DareDev256 มี hook 42 ตัวบน 19 event บอกว่า 35 ตัวส่ง exit code ที่ไม่ใช่ศูนย์ไม่ได้เลย สุดท้ายต้องเขียน job อีกตัวไว้ grep log ว่าตัวแรกได้รันจริงไหม

DolphusCY เจอ hook ตายไปแปดสัปดาห์ ใช้ fd -t f -n ซึ่ง -n ไม่ใช่ flag ของ fd error ทุกรอบ เงียบทุกรอบ

ipoltorak เจอ watchdog ที่มี exit 0 อยู่ต้นสาขาที่ปกติ ทุกอย่างที่ต่อท้ายไม่เคยรันเลยหลายวัน แต่ทุก check ขึ้นเขียวหมด

Helban อันนี้น่ากลัวสุด credential ที่รั่วของเขาไม่ได้รั่วทาง result มันรั่วทาง error path เพราะ Playwright พิมพ์ argument ที่มัน timeout ออกมาด้วย รหัสผ่านที่ส่งเข้า fill เลยโผล่ในทรานสคริปต์แบบตัวเป็น ๆ

DareDev256 สรุปไว้ประโยคเดียว สำหรับ hook ที่ทำหน้าที่ redact การ fail open แย่กว่าไม่มี hook เลย

ที่ข้ามได้

โพสต์แนว "Mods มาแล้ว" ที่แปะคลิป Tetris แล้วจบ ดูจบแล้วยังไม่รู้ว่ามันต่างจาก hook เดิมตรงไหน

เทรดที่ไล่ลิสต์ว่าจะทำอะไรได้บ้างโดยยังไม่มีใครรัน เป็นลิสต์ของงานที่น่าลอง ไม่ใช่ลิสต์ของผลลัพธ์

เรื่องเถียงกันว่าใครคิดก่อน มีคนบอกว่าลอก Command Code มา https://x.com/MrAhmadAwais/status/2095745997741985867 อ่านได้ถ้าสนใจ แต่ไม่ว่าใครคิดก่อน สิ่งที่ต้องทำกับ hook ตัวเองก็เหมือนเดิม

ก้อนเดียวที่เอาไปแปะได้เลย

เปิด function hooks ใส่ ~/.claude/settings.json

{
  "env": {
    "CLAUDE_CODE_ENABLE_FUNCTION_HOOKS": "1"
  }
}

ไม่ใส่อันนี้ plugin ลงได้ปกติแต่ไม่ทำอะไรเลย

อยากลองแค่ session เดียวไม่ต้องแก้ไฟล์ CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 claude

ตัวเลขที่ควรรู้ก่อนกด

ต้อง Claude Code 2.1.269 ขึ้นไป เป็นบิลด์แรกที่ function hook วาดเหนือ prompt ได้ ตอนนี้ออกถึง 2.1.273 แล้ว

ใน claude -p hook ที่ไม่ใช่ UI ยิงปกติ ลองแล้ว session.start กับ tool.call เข้า log ครบ แต่ ui.render ลงทะเบียนได้เฉย ๆ ไม่มีอะไรถูกวาด ใครรัน automation ผ่าน -p อยู่ ดักได้ วาดไม่ได้ เดสก์ท็อปกับมือถือก็ไม่วาด

ใส่ env var อย่างเดียวอาจไม่พอ มี rollout flag อีกชั้นที่ทำให้ hooks module ไม่ถูกโหลดถึงจะตั้ง env แล้วก็ตาม ถ้าลงแล้วเงียบ เช็กว่า module โหลดจริงไหมก่อนคิดว่าเขียนผิด

ยังเป็น early access API เปลี่ยนได้ระหว่าง release

จ่อ repo เดียวก่อน อย่าเพิ่งจ่อทั้งเครื่อง