Claude Code

ติดอาวุธให้ Claude ตอนที่ 2: ของเสริมนอกกล่องที่ควรมี

โมเดลก็จูนแล้ว ความจำก็วางแล้ว ถึงคิวของสนุก บทสองรวม "ของเสริม" ที่คนใช้จริงเขาแอบติดกัน ตั้งแต่ต่อมือให้คุมเบราว์เซอร์ สแกนช่องโหว่ ยันสกิลที่ลดโทเคนและจัดสายพานงานทั้งเส้น

ตอนที่แล้วเราจูน "ฐาน" ของ Claude ไปแล้ว เลือกโมเดลให้พอดีงาน แล้ววางระบบความจำ Hot / Cold / learning.md ให้มันเลิกลืม คราวนี้ถึงคิวของสนุก: "ของ" ที่เอามาติดตั้งเสริมนอกกล่องกันบ้าง เพราะตัวโมเดลเก่ง ๆ อย่างเดียวยังไม่พอ คนที่ใช้ AI ได้คุ้มที่สุดมักไม่ใช่คนที่พิมพ์เก่งกว่า แต่เป็นคนที่ประกอบเครื่องมือรอบตัวมันได้ถูกจุด

ก่อนจะไปดูของ ขอปูภาพให้ตรงกันนิดนึง สองปีก่อนเราใช้ AI แบบ "สมอง + ตา + หู + ปาก" มันคิดเก่ง อ่านเก่ง คุยเก่ง แต่ไม่มี "มือ-เท้า" ให้ลงมือทำอะไรจริง ๆ ยุคนี้เปลี่ยนไป เพราะมีสิ่งที่เรียกว่า agent harness (harness อ่านว่า "ฮาร์เนส" แปลว่า "สายรัด/เครื่องพันตัว" คำเดียวกับสายรัดนิรภัยตอนปีนเขา หรือเครื่องเทียมม้าลากรถ เขายืมภาพ "โครงที่สวมเข้ากับตัว แล้วต่อของใช้งานเข้าไป" มาเรียกชั้นที่หุ้มโมเดลไว้แล้วยื่นเครื่องมือให้มันหยิบใช้) เจ้า harness นี่แหละที่ใส่มือ-เท้าให้ AI จนมันเปิดไฟล์ รันคำสั่ง ต่อ service ภายนอกได้เอง Claude Code กับ Claude Cowork ก็คือ harness คนละแบบ (รายละเอียดว่าแต่ละตัวคืออะไร บทความแรก เล่าไว้แล้ว บทความนี้จะโฟกัสที่ "แล้วเราติดอะไรเสริมมันได้บ้าง")


ของเสริมที่คนใช้จริงเขาแอบเสริมกัน

ทีนี้ถึงพระเอกของบทความ "ของเสริม" นอกกล่องที่เอามาต่อกับ Claude Code ได้ ผมคัดมา 4 ตัวที่ตอบโจทย์คนละด้าน ตั้งแต่ต่อมือให้คุมเบราว์เซอร์ ยันปรับนิสัยการตอบให้ประหยัดขึ้น

Playwright MCP: ต่อมือให้ Claude คุมเบราว์เซอร์

Playwright (อ่านว่า "เพลย์ไรต์" แปลตรงตัวว่า "นักเขียนบทละคร") คือเครื่องมือคุมเบราว์เซอร์อัตโนมัติของ Microsoft ฝั่งที่เอามาต่อกับ AI ได้มีให้เลือกสองทาง: playwright-cli (ให้ AI สั่งงานผ่านบรรทัดคำสั่ง) กับ Playwright MCP (ต่อเป็นชุดเครื่องมือให้ AI หยิบใช้เอง)

เลือกทางไหนดี

ต่างกันตรงจังหวะใช้ คนเลือก CLI เมื่ออยากประหยัด context (ไม่ต้องยัดรายการ tool ทั้งชุดเข้า context ของ AI) ส่วน MCP เหมาะกับงานโต้ตอบต่อเนื่องที่ AI ต้องจำสถานะเบราว์เซอร์ข้ามหลายจังหวะ เช่นเปิดหน้า➔กรอกฟอร์ม➔เช็คผล➔วนแก้ ซึ่งเป็นงานแบบที่เรากำลังจะทำในหัวข้อนี้พอดี บทความนี้เลยพาไปทาง MCP

MCP (Model Context Protocol) คือมาตรฐานที่ให้ Claude ต่อกับเครื่องมือภายนอกเป็นระบบ (บทความ Claude Code workflow อธิบายเรื่อง MCP ไว้ละเอียดแล้ว) พอต่อ Playwright ผ่าน MCP Claude จะได้ "มือ" ชุดใหม่ทันที เปิดหน้าเว็บ คลิก พิมพ์ กรอกฟอร์ม แคปหน้าจอ อ่าน console ได้เอง เหมาะมากเวลาให้มันทดสอบเว็บที่เพิ่งเขียน แล้วรายงานกลับว่าปุ่มไหนพัง ติดตั้งด้วยคำสั่งเดียว

ต่อ Playwright MCP เข้ากับ Claude Code
# ติดตั้งเบราว์เซอร์ก่อนหนึ่งครั้ง
npx playwright install

# ลงทะเบียน MCP server เข้ากับ Claude Code
claude mcp add playwright -s user -- npx @playwright/mcp@latest

ต่อเสร็จแล้ว วงจรการใช้ก็เหมือนมี "น้องเทสเตอร์" ในทีม: เราสั่งเป็นภาษาคน➔Claude ลงมือกดจริงในเบราว์เซอร์➔รายงานกลับ + แคปหน้าจอ➔เจอบั๊กก็แก้แล้วทดสอบซ้ำ

คุณสั่งภาษาคน "ทดสอบหน้า login ให้หน่อย" สั่งงาน Claude + Playwright MCP เลือกเรียก tool เอง: navigate · type · click screenshot · อ่าน console ลงมือ เบราว์เซอร์จริง เปิดหน้า · กรอกฟอร์ม คลิกปุ่ม · แคปหน้าจอ ผล + ภาพหน้าจอเด้งกลับมาให้เราดู ➔ เจอบั๊กก็สั่งแก้แล้ววนทดสอบใหม่
เราคุยกับ Claude เป็นภาษาคน ส่วน Playwright MCP คือ "มือ" ที่ไปกดจริงในเบราว์เซอร์ แล้วส่งผล + ภาพกลับมา

สเต็ป 1: เช็คว่าต่อติดแล้ว พิมพ์ /mcp ในเซสชัน ควรเห็น playwright อยู่ในลิสต์และสถานะเป็น connected

สเต็ป 2: สั่งงานเป็นภาษาคน ไม่ต้องบอกทีละ tool ว่า "navigate ไปหน้านี้ แล้ว click ปุ่มนี้" บอกเป้าหมายรวม ๆ แล้ว Claude จะเลือกเรียก tool เองตามลำดับ ลองสมมติว่าเราเพิ่งเขียนหน้า login แล้วอยากเช็คว่ามัน validate ถูกไหม:

พิมพ์ใน Claude Code (ตัวอย่างของเล่น: ทดสอบหน้า login)
ช่วยเปิด http://localhost:3000/login ให้หน่อย
กรอกอีเมล "test@bad" กับรหัสผ่านมั่ว ๆ แล้วกดปุ่ม "เข้าสู่ระบบ"
เช็คว่ามันขึ้นข้อความ error สีแดงไหม ถ้าไม่ขึ้นบอกด้วยว่าพังตรงไหน แล้วแคปหน้าจอมาให้ดู

สเต็ป 3: อ่านผล แล้ววนแก้ในเทิร์นเดียว Claude จะเล่าให้ฟังว่ากดอะไรไปบ้างและเจออะไร พร้อมภาพหน้าจอ ถ้ามันบอกว่า "กรอกผิดแล้วไม่ขึ้น error เลย" เราสั่งต่อได้ทันทีว่า "งั้นแก้ให้มัน validate ด้วย แล้วทดสอบซ้ำ" ครบวงจรตรวจ-แก้-ตรวจในที่เดียว

ทำไมถึงเข้าคู่กับ Claude ได้ดี

เพราะมันเปลี่ยน Claude จากคนที่ "เขียนโค้ดแล้วเดาว่าน่าจะทำงาน" เป็นคนที่ "เปิดดูของจริงแล้วยืนยัน" ได้เอง เหมือนติดตากับมือให้มันไปทดสอบเว็บแทนเรา โดยเราไม่ต้องนั่งคลิกเองทีละหน้า

Trivy: ยามเฝ้าช่องโหว่ความปลอดภัย

Trivy (อ่านว่า "ทริวี่") คือเครื่องมือสแกนความปลอดภัยแบบโอเพนซอร์สจากค่าย Aqua Security มันไล่หา ช่องโหว่ (vulnerability) ในไลบรารีที่โปรเจกต์เราใช้, การตั้งค่าที่ไม่ปลอดภัย, ไปจนถึง secret (พวก API key หรือรหัสผ่าน) ที่เผลอหลุดเข้าไปในโค้ด จุดเด่นคือเป็นไฟล์เดียวจบ ไม่ต้องตั้งฐานข้อมูลอะไรให้ยุ่งยาก สั่งทีเดียวมันโหลดฐานข้อมูลช่องโหว่มาเทียบให้เอง

ลงง่ายสุดคือผ่าน package manager ที่เครื่องมีอยู่แล้ว เลือกบรรทัดตามระบบของคุณ (หรือถ้าไม่อยากลงในเครื่อง จะรันผ่าน Docker เลยก็ได้):

ติดตั้ง Trivy
# macOS หรือ Linux: ผ่าน Homebrew
brew install trivy

# Windows: ผ่าน winget
winget install -e --id AquaSecurity.Trivy

# ไม่อยากติดตั้ง? รันผ่าน Docker ได้เลย
docker run --rm -v "$PWD:/src" aquasec/trivy fs /src

ติดตั้งเสร็จแล้ว วิธีใช้จริงเป็นวงจรสั้น ๆ: สแกน➔อ่านผล➔ให้ Claude แก้➔สแกนซ้ำจนเคลียร์

โปรเจกต์ของเรา โค้ด + ไลบรารีที่ใช้ สแกน รายงานผล • ช่องโหว่ (CVE) ในไลบรารี • secret ที่เผลอหลุด • config ที่เสี่ยง อ่านผล Claude ไล่แก้ อัป lib · ถอด secret · ปรับ config ที่เสี่ยง สแกนซ้ำจนไม่เหลือช่องโหว่ระดับ HIGH / CRITICAL
Trivy เป็นคน "ตรวจเจอ" ส่วน Claude เป็นคน "ไล่แก้" แล้ววนสแกนซ้ำจนสะอาด ได้ทั้งเครื่องสแกนมืออาชีพและช่างซ่อมในทีมเดียว

สเต็ป 1: สแกนทั้งโปรเจกต์ ชี้ Trivy ไปที่โฟลเดอร์โปรเจกต์ มันจะไล่อ่านไฟล์ล็อกของ dependency, ไฟล์ตั้งค่า และเนื้อโค้ด แล้วสรุปเป็นตาราง จัดระดับความรุนแรงตั้งแต่ LOW ไปจนถึง CRITICAL

สแกนทั้งโฟลเดอร์
trivy fs .

ตัวอย่างสิ่งที่มันฟ้องกลับมา (ของเล่น): สมมติโปรเจกต์เราใช้ lodash เวอร์ชันเก่า Trivy จะขึ้นบรรทัดประมาณว่า

ตัวอย่างผลจาก Trivy
lodash  4.17.20  →  CVE-2021-23337  [HIGH]  Prototype Pollution
                     แก้: อัปเป็น 4.17.21

สเต็ป 2: กรองเอาเฉพาะที่ต้องรีบแก้ ครั้งแรกที่สแกนมักเจอเป็นร้อยบรรทัดจนท้อ ตัดให้เหลือเฉพาะระดับอันตรายก่อน จะได้โฟกัสถูกจุด

เอาเฉพาะระดับ HIGH กับ CRITICAL
trivy fs --severity HIGH,CRITICAL .

สเต็ป 3: เซฟผลเป็นไฟล์ แล้วให้ Claude ไล่แก้ สั่ง Trivy พ่นผลเป็น JSON ลงไฟล์ แล้วบอก Claude ให้อ่านไฟล์นั้นแล้วแก้ทีละจุด วิธีนี้ดีกว่าก๊อปผลยาว ๆ ยัดใส่แชทเอง (ไม่เปลือง context ด้วย)

เซฟผลเป็นไฟล์ JSON
trivy fs -f json -o trivy-report.json .
พิมพ์ใน Claude Code
อ่าน trivy-report.json แล้วไล่แก้เฉพาะช่องโหว่ระดับ HIGH กับ CRITICAL ทีละจุด บอกด้วยว่าแต่ละจุดแก้อะไรและทำไม

สเต็ป 4: สแกนซ้ำ พอ Claude แก้เสร็จก็รัน trivy fs . ใหม่ ถ้าไม่เหลือ HIGH/CRITICAL แล้วก็ถือว่าผ่านรอบนั้น วนแบบนี้จนสะอาด

ใช้คู่กับ /security-review

Claude Code เองก็มีสกิล /security-review ในตัวสำหรับรีวิวโค้ดที่เพิ่งแก้ ใช้เสริมกันได้ Trivy เก่งเรื่องสแกน dependency/config/secret ที่ "รู้จักช่องโหว่อยู่แล้ว" ส่วน /security-review เก่งเรื่องหาช่องโหว่เชิงตรรกะในโค้ดที่เราเพิ่งเขียนเอง คนละมุมกัน จับคู่กันแล้วครอบคลุมกว่า

Caveman & Ponytail: คู่หูสายลดพลังงาน

สองตัวนี้เป็น skill แบบโอเพนซอร์สฟรี (ชุดคำสั่งเสริมนิสัยให้ agent ถ้ายังไม่รู้จักว่าสกิลคืออะไร แวะอ่าน บทความ /grill-me ได้) ที่แนวคิดฮาแต่ได้ผลจริง ทั้งคู่ตั้งใจ "ลด" คนละอย่าง ตัวหนึ่งลดคำพูด อีกตัวลดโค้ด

Caveman (อ่านว่า "เคฟแมน" แปลว่า "มนุษย์ถ้ำ") แก้ปัญหาที่ Claude ชอบตอบยาวสวยหรูเกินจำเป็น ด้วยการสั่งให้มันพูดห้วน ๆ แบบมนุษย์ถ้ำ ตัดคำเชื่อมคำขยายทิ้ง เก็บแต่เนื้อ แต่จะไม่ยุ่งกับโค้ด คำสั่ง หรือ error (ส่วนที่ห้ามเพี้ยน) ผลคือประหยัด output token เฉลี่ยราว 65% ผู้เขียนถึงกับตั้งสโลแกนว่า "why use many token when few token do trick" (จะใช้หลายโทเคนทำไม ถ้าน้อยโทเคนก็เอาอยู่) หน้าตาคำตอบก็ประมาณนี้:

คำตอบปกติ (verbose)
Great question! I've gone ahead and fixed the bug. The issue was that
the function wasn't handling the null case, so I added a guard clause
at the top. I also added a couple of tests so it won't regress in the
future. Let me know if you'd like me to walk through any part!
คำตอบแบบ Caveman (เนื้อเท่าเดิม)
Bug fixed. Was null case. Added guard + 2 tests. Done.

เนื้อความสำคัญเท่ากันเป๊ะ (แก้บั๊ก เพราะเคสค่าว่าง เพิ่ม guard + เทสต์) แต่จำนวนคำต่างกันหลายเท่า นี่แหละที่มาของการประหยัด output token ราว 65%:

คำตอบปกติ ~100% output token แบบ Caveman ~35% ตัดออก ~65% (ที่ประหยัดได้) * ลดเฉพาะ output token · input กับ reasoning เท่าเดิม
เนื้อความเท่ากัน แต่ Caveman ตัดคำฟุ่มเฟือยทิ้ง เหลือ output แค่ราว 1 ใน 3

วิธีใช้ก็ตรงไปตรงมา:

สเต็ป 1: ติดตั้ง บน Claude Code ลงเป็น plugin ได้ด้วยคำสั่งเดียว (repo ทางการ: github.com/juliusbrussee/caveman มีวิธีลงบน agent อื่นและสคริปต์ติดตั้งอัตโนมัติให้ด้วย)

ติดตั้ง Caveman บน Claude Code (รันใน terminal)
claude plugin marketplace add JuliusBrussee/caveman && claude plugin install caveman@caveman

สเต็ป 2: ใช้ได้เลยตั้งแต่ข้อความแรก Caveman วางฮุคไว้ให้ Claude ตอบห้วนอัตโนมัติ ไม่ต้องพิมพ์สั่งซ้ำทุกครั้ง แค่ถามงานตามปกติ คำตอบก็จะกระชับลงเอง (โค้ด/คำสั่ง/error ยังเต็มเหมือนเดิม)

สเต็ป 3: สลับโหมดชั่วคราว บน Claude Code การเปิด/ปิดไม่ใช่ slash command แต่พิมพ์เป็นข้อความธรรมดาในแชทได้ตอนไหนก็ได้ อยากให้กลับไปตอบเต็มก็พิมพ์ normal mode แล้วพอจะให้ห้วนอีกครั้งก็พิมพ์ talk like caveman

พิมพ์เป็นข้อความปกติในแชท (ไม่ใช่ /command)
normal mode          ← กลับไปตอบเต็มแบบปกติ
talk like caveman    ← ให้กลับมาห้วนแบบมนุษย์ถ้ำอีกครั้ง

สเต็ป 4: ดูว่าประหยัดไปเท่าไหร่ มันมีคำสั่งเสริมให้เช็คยอดที่เซฟได้และบีบไฟล์ memory ให้เล็กลง (สองตัวนี้เป็น slash command จริง)

คำสั่งเสริมของ Caveman
/caveman-stats      # นับ token ที่ประหยัดได้ แล้วโชว์บน statusline
/caveman-compress   # เขียนไฟล์ memory (เช่น CLAUDE.md) ให้กระชับลง

อ่านตัวเล็กก่อนตัดสินใจ

Caveman ลดเฉพาะ output token (คำที่ AI พ่นออกมา) เท่านั้น ส่วน input กับ reasoning token ไม่ได้ลด แถมตัวสกิลเองยังกินเพิ่ม ~1–1.5k token ต่อเทิร์นด้วย เหมาะกับคนที่คุยเยอะจน output บาน แต่ถ้าอยากได้คำอธิบายเต็ม ๆ ไว้เรียนภาษาอังกฤษจาก Claude ก็สั่งปิดหรือไม่ใช้ก็ได้

ส่วน Ponytail (อ่านว่า "โพนีเทล" แปลว่า "ผมหางม้า" ทรงที่รวบให้เรียบกระชับ เข้ากับสิ่งที่มันทำพอดี) สั่งให้ AI "คิดแบบซีเนียร์ที่ขี้เกียจที่สุดในทีม" ภายใต้คติที่ว่า "โค้ดที่ดีที่สุดคือโค้ดที่คุณไม่ต้องเขียน" ก่อนจะเขียนอะไร มันจะไล่บันไดตัดสินใจลงมาทีละขั้น แล้วหยุดที่ขั้นแรกที่พองาน

  • ไม่ต้องทำเลยได้ไหม? (หลักการ YAGNI ย่อจาก You Aren't Gonna Need It แปลว่า "เดี๋ยวก็ไม่ได้ใช้หรอก" อย่าเพิ่งสร้างเผื่อ)
  • ใช้ของที่ภาษาโปรแกรมมีให้อยู่แล้ว (stdlib) ได้ไหม?
  • ใช้ความสามารถที่แพลตฟอร์มมีในตัวได้ไหม?
  • ใช้ dependency ที่ลงไว้อยู่แล้วได้ไหม?
  • ถ้าเลี่ยงไม่ได้จริง ๆ ค่อยเขียน และเขียนให้น้อยที่สุดที่พองาน
บันไดตัดสินใจของ Ponytail · ไล่ลงจากบน หยุดขั้นแรกที่พองาน 1 ไม่ต้องทำเลยได้ไหม? (YAGNI) 2 ใช้ stdlib ของภาษาได้ไหม? 3 ใช้ของที่แพลตฟอร์มมีในตัวได้ไหม? 4 ใช้ dependency ที่ลงไว้แล้วได้ไหม? 5 เขียนเองแบบสั้นสุด (เช่น 1 บรรทัด) ← หยุด! 6 เขียนเต็ม ๆ (ทางเลือกสุดท้าย) · ไม่ต้องลงมาถึง
งานง่าย ๆ อย่าง "เช็คเลขคู่" จบตั้งแต่ขั้น 5 Ponytail คอยเบรกไม่ให้ AI เผลอลงไปเขียนเต็มแบบขั้น 6

เห็นภาพชัดสุดตอนลองงานของเล่นง่าย ๆ เช่น "เขียนฟังก์ชันเช็คว่าเลขเป็นเลขคู่ไหม" AI ที่ไม่ถูกเบรกมักเขียนเผื่อจนเกินงาน (รองรับค่าติดลบ, ทำ cache, ห่อเป็น class) ส่วน Ponytail จะหยุดที่คำตอบที่พอดี:

ไม่มี Ponytail: เขียนเผื่อเกินงาน
class NumberChecker {
  constructor(options = {}) {
    this.allowNegative = options.allowNegative ?? true;
    this.cache = new Map();
  }
  isEven(n) {
    if (this.cache.has(n)) return this.cache.get(n);
    const result = Math.abs(n) % 2 === 0;
    this.cache.set(n, result);
    return result;
  }
}
มี Ponytail: พอดีงาน
const isEven = (n) => n % 2 === 0;

ผลที่วัดได้คือโค้ดน้อยลงเฉลี่ยราว 54% ฟังดูน่าใช้ แต่รุ่นพี่ที่แนะนำมาก็เตือนไว้ตรง ๆ ว่าระวังโค้ดสั้นเกินจนกลับมาอ่านทีหลังแล้วงง ความกระชับกับความอ่านง่ายบางทีก็สวนกัน ลองแล้วชั่งเอาเองว่าพอดีตรงไหน

วิธีลง บน Claude Code ก็เป็น plugin เหมือนกัน แต่คราวนี้เป็นคำสั่ง /plugin ที่พิมพ์ในแชท ไม่ใช่ terminal คำสั่งในแชทรับได้ทีละคำสั่ง เลยต่อกันด้วย && แบบฝั่ง Caveman (ที่ติดตั้งจาก terminal) ไม่ได้ ต้องส่งสองบรรทัดแยกกัน (เพิ่ม marketplace ก่อน แล้วค่อย install) ติดตั้งแล้วปรับความเข้มได้ด้วย /ponytail lite · /ponytail full · /ponytail ultra และปิดด้วย /ponytail off repo ทางการ: github.com/DietrichGebert/ponytail

พิมพ์ใน Claude Code (ส่งทีละบรรทัด)
/plugin marketplace add DietrichGebert/ponytail
/plugin install ponytail@ponytail

เกร็ด

ปรัชญาของ Ponytail จริง ๆ แล้วใกล้เคียงกับสกิล /simplify ที่คอยไล่หาโอกาสตัดโค้ดให้เรียบง่ายขึ้น แนวคิด "อย่าเขียนถ้าไม่จำเป็น" เป็นภูมิปัญญาเก่าแก่ของสายซอฟต์แวร์ที่แค่ถูกห่อใหม่ให้ AI ทำตามได้อัตโนมัติเท่านั้นเอง


แล้วสกิลสาย grill / handoff ล่ะ?

ในโลกสกิลยังมีตัวที่ต่อยอดจากที่เราเคยเล่าไปแล้วอีก Matt Pocock (คนเดียวกับที่ทำ /grill-me และ /handoff) มีสกิลรุ่นพี่ของ grill ชื่อ grill-with-docs ที่ต่างตรงระหว่างซักมันจะทยอยจดข้อสรุปลงไฟล์เอกสารในโปรเจกต์ให้เอง (สร้างแบบ lazy คือยังไม่มีไฟล์อะไรจนกว่าจะมีศัพท์หรือการตัดสินใจตกผลึกจริง ๆ ไม่ต้องเตรียมโครงไว้ก่อน) โดยแยกเป็นเอกสารสองชนิด:

  • CONTEXT.md ที่ราก = "อภิธานศัพท์" (glossary) เก็บเฉพาะความหมายของศัพท์เฉพาะในงาน ล้วน ๆ ไม่ปนสเปคหรือรายละเอียดวิธีทำ
  • docs/adr/ = ADR (Architecture Decision Record อ่านว่า "เอดีอาร์" แปลว่า "บันทึกการตัดสินใจเชิงสถาปัตยกรรม") จดเฉพาะการตัดสินใจที่กลับตัวยากและมีการชั่งได้-เสียจริง ๆ ใส่แบบประหยัด ไม่พร่ำเพรื่อ

สกิลชุดนี้เรียกใช้เป็น slash command (พิมพ์ชื่อสกิลนำหน้าด้วย / ในแชท) อย่าง grill-with-docs ก็พิมพ์ /grill-with-docs ตามด้วยเป้าหมายกว้าง ๆ แล้วปล่อยให้มันซักกลับ พร้อมทยอยจดให้เอง:

พิมพ์ใน Claude Code
/grill-with-docs เก็บบริบทฟีเจอร์ "ระบบแจ้งเตือนอีเมล" ให้หน่อย

พอคุยกันจนศัพท์คำนึงชัด มันก็หยอดลง CONTEXT.md เป็นคำนิยามล้วน ๆ (ไม่มีสเปค ไม่มีวิธีทำ):

CONTEXT.md: อภิธานศัพท์
## follow
ผู้ใช้กด "ติดตาม" ticket ไว้ เพื่อรับรู้ความเคลื่อนไหวของ ticket นั้น

## notification
อีเมลหนึ่งฉบับที่ส่งเมื่อมีเหตุการณ์บน ticket ที่ผู้ใช้ follow อยู่

ส่วนพอเจอ "ทางแยกที่ตัดสินใจแล้วกลับยาก" มันถึงจะเปิด ADR หนึ่งใบใต้ docs/adr/ บันทึกทั้งบริบท ตัวเลือกที่เลือก และผลที่ตามมา:

docs/adr/0001-ส่งอีเมลแบบ-async.md
## บริบท
คอมเมนต์ถล่มใน ticket ยอดนิยมทำให้ต้องส่งอีเมลทีละหลายพันฉบับ

## ตัดสินใจ
ส่งผ่านคิวเบื้องหลัง (async) ไม่ผูกกับ request ของผู้ใช้

## ผลที่ตามมา
อีเมลถึงช้าได้หลักวินาที แลกกับระบบหลักไม่ค้าง ชั่งแล้วคุ้ม

ข้อดีคือพอปิดแชทนี้ไป เปิดแชทใหม่ก็แค่ชี้ให้ AI อ่าน CONTEXT.md กับ docs/adr/ ต่อได้เลย ไม่ต้องเล่าใหม่ทั้งหมด เหมือน grill-me เวอร์ชันที่ "จดเลกเชอร์" ทิ้งไว้ให้ด้วย

wayfinder: พอ "จุดหมาย" ยังพร่ามัว อย่าเพิ่งพุ่งเข้าหา

wayfinder (อ่านว่า "เวย์ไฟน์เดอร์" แปลว่า "ผู้หาเส้นทาง/คนนำทาง" มาจากคำว่า wayfinding ศาสตร์การนำทางในพื้นที่ แบบที่ชาวโพลินีเซียนแล่นเรือข้ามมหาสมุทรด้วยดาวกับคลื่นโดยไม่มีแผนที่ Matt เลยยืมภาพ "ค่อย ๆ หาทางทีละช่วง ไม่ใช่เล็งปลายทางแล้วพุ่ง" มาตั้งชื่อ) คือสกิลใหม่ล่าสุดของ Matt ที่ออกแบบมาสำหรับงานคนละสเกลกับ grill-me งานก้อนใหญ่เกินกว่าจะจบใน session เดียว และ "ปลายทางยังถูกหมอกบัง" คือยังไม่รู้ด้วยซ้ำว่าคำตอบหน้าตายังไง

ประเด็นคือ grill-me เก่งเรื่อง "ซักให้สเปกชัด" ก็จริง แต่มันถูกออกแบบมาเพื่อวิ่งไปหาคำตอบ ซึ่งใช้ได้ดีตอน scope ชัดอยู่แล้ว แต่บางงานแม้แต่ตัวเราเองก็ยังไม่รู้ว่าต้องการอะไร การรีบพุ่งเข้าหา solution เลยมีโอกาสได้คำตอบผิดมากกว่าถูก และไม่แตะ root cause จริง ๆ wayfinder เลยเปลี่ยนโจทย์จาก "รีบตอบ" เป็น "ค่อย ๆ หาเส้นทาง" ก่อน

…too big for one agent session, and wrapped in fog: the way from here to the destination isn't visible yet. Wayfinding is about finding that way, not charging at the destination.

แปลไทย งานก้อนใหญ่เกินกว่า agent ตัวเดียวจะรับไหว แถมยังถูกหมอกบัง เส้นทางจากตรงนี้ไปยังจุดหมายยังมองไม่เห็น การนำทางคือการ "หาเส้นทาง" นั้น ไม่ใช่การพุ่งเข้าใส่จุดหมาย จากไฟล์ SKILL.md ของ wayfinder

ก่อนไปต่อ ขอเกริ่นคำว่า issue tracker (อ่านว่า "อิชชู แทร็กเกอร์" แปลว่า "ระบบติดตามงาน/ปัญหา") สักนิดสำหรับคนที่ยังไม่คุ้น ให้นึกภาพกระดานงานส่วนกลางของทีม ที่ทุกงานหรือทุกบั๊กจะถูกเปิดเป็นการ์ดใบหนึ่ง เรียกกันว่า ticket (หรือที่หลายเจ้าเรียก issue card ต่อไปในบทนี้ผมจะเรียกว่า ticket) แต่ละใบมีชื่อเรื่อง คำอธิบาย สถานะ (ยังไม่ทำ / กำลังทำ / เสร็จ) และช่องให้คอมเมนต์คุยกันใต้ ticket ได้ ทุกคนในทีม (และตอนนี้รวม AI ด้วย) มองเห็นกระดานเดียวกัน เจ้าที่นิยมก็เช่น Jira, GitHub Issues, Linear หรือ Trello

วิธีทำงานของ wayfinder คือย้าย "แผนที่งาน" ออกจากหัว AI ไปไว้บนกระดานนี้ สร้างเป็น ticket แม่ (ถ้าใช้ Jira ก็คือ Epic นั่นเอง) หนึ่งใบติดป้าย wayfinder:map แล้วแตกงานย่อยเป็น ticket ลูก (child issues) ใต้แผนที่นั้น ticket มีหลายชนิด ทั้งชนิดที่ให้ไปค้นข้อมูล, ชนิดซักถาม (grilling ใช่ครับ การซักแบบ grill-me กลายเป็นแค่ "โหมดหนึ่ง" ของ wayfinder), และชนิดลองทำต้นแบบ (prototype) เพื่อทดสอบสมมติฐานก่อนลงมือจริง

งานก้อนใหญ่ ปลายทางยังถูกหมอกบัง ยังไม่รู้คำตอบหน้าตายังไง จัดแผนที่ แผนที่บน issue tracker issue แม่: wayfinder:map • ticket: ค้นข้อมูล • ticket: ซักถาม · ลองต้นแบบ ทีละใบ เส้นทางค่อย ๆ ชัด 1 ticket = 1 session ทำจบแล้วอัปเดตแผนที่ ยังไม่ชัด? หยิบ ticket ใบถัดไปใน session ใหม่ · วนจนเส้นทางโผล่พ้นหมอก
wayfinder ย้าย "แผนที่งาน" ไปไว้บน issue tracker แล้วเดินทีละ ticket จบใน session เดียว แผนที่บนบอร์ดคือความจำถาวรที่ทำหน้าที่แทนการ handoff ด้วยมือ

เคล็ดที่ทำให้มันคุม context ได้เนียนคือกติกา "หนึ่ง ticket = หนึ่ง session" ห้ามเคลียร์เกินหนึ่ง ticket ต่อรอบ พอทำ ticket จบก็อัปเดตผลลงแผนที่บนบอร์ด แล้วเปิด session ใหม่หยิบ ticket ถัดไป เท่ากับไม่ปล่อยให้ context ยาวจนเข้าโซนที่ AI เริ่มมั่ว (เรื่องนี้ต่อกับ Context Pollution ตรง ๆ) และเพราะแผนที่อยู่บนบอร์ด ไม่ใช่ในหัว และ session มันเลยทำหน้าที่แทนการ /handoff ด้วยมือไปในตัว ไม่ต้องกลัวลืมสั่ง handoff อีก

วิธีลง โหลดทั้งชุดสกิลของ Matt มาทีเดียว (เพราะ wayfinder เรียกสกิลอื่นในชุดมาใช้ต่ออีกหลายตัว) แล้วรันตัวตั้งค่าเพื่อเลือกว่าจะให้แผนที่ (ticket ทั้งหลาย) ไปอยู่ที่ไหน:

ติดตั้งชุดสกิลของ Matt Pocock (มี wayfinder รวมอยู่)
# โหลดทั้ง repo สกิลมาทีเดียว
npx skills@latest add mattpocock/skills

# แล้วตั้งค่าเลือกที่เก็บ ticket + ป้ายที่ใช้ (รันในแชท Claude Code)
/setup-matt-pocock-skills

ต้องต่อเน็ต / ต้องมี MCP ไหม? ขึ้นกับว่าเก็บ ticket ไว้ที่ไหน

คำถามที่หลายคนสงสัย: สกิลนี้ต้องต่ออินเทอร์เน็ตและต่อ issue tracker ก่อนถึงใช้ได้ใช่ไหม? คำตอบคือไม่เสมอไป มันมี 2 โหมด แล้วแต่ตอน /setup-matt-pocock-skills เราเลือกอะไร:

  • โหมดไฟล์ในเครื่อง (local files): ticket ถูกเก็บเป็นไฟล์ markdown ใน repo เอง (โฟลเดอร์ .scratch/) ไม่ต้องต่อเน็ต ไม่ต้องมี tracker ไม่ต้องมี MCP อะไรเลย เหมาะสุดตอนอยากลองเล่นหรือทำงานคนเดียว
  • โหมดต่อ tracker จริง: ticket ไปอยู่บนบอร์ดออนไลน์ อันนี้ต้องต่อเน็ต และต้องมีช่องทางให้ Claude เอื้อมไปคุยกับ tracker นั้น ซึ่งไม่จำเป็นต้องเป็น MCP เสมอ แล้วแต่เจ้า:
    • GitHub Issues: สกิลใช้ผ่าน gh (GitHub CLI) ไม่ใช่ MCP แค่ลง gh แล้วล็อกอินด้วย gh auth login ครั้งเดียว (ต้องมีบัญชี GitHub)
    • GitLab: คล้ายกัน แต่ใช้ glab (GitLab CLI) แทน
    • Jira / Linear: สกิลยังไม่มี integration สำเร็จรูป ตอน setup มันจะให้เราอธิบาย workflow ของ Jira เป็นข้อความสั้น ๆ แล้วจดไว้เฉย ๆ ถ้าอยากให้ Claude อ่าน/เขียน Jira ได้จริงต้องต่อเครื่องมือเพิ่มเอง เช่นผ่าน Atlassian MCP Server ตัวทางการ (ต่อ Jira/Confluence เข้ากับ Claude ผ่าน OAuth หรือ API token)

แปลว่าถ้าจะเริ่มลองแบบไม่ยุ่งยาก เลือกโหมดไฟล์ในเครื่องก่อนได้เลย ไม่ต้องเซ็ต tracker อะไร ค่อยขยับไป GitHub หรือ Jira ตอนอยากให้ทั้งทีมเห็นบอร์ดเดียวกันจริง ๆ

พอพิมพ์คำสั่ง /wayfinder ตามด้วยงานสักก้อนที่ยัง "งง ๆ ไม่รู้จะเริ่มตรงไหน" มันจะไม่รีบเขียนโค้ด แต่ไปเปิด ticket แม่ บนบอร์ดให้ก่อน:

พิมพ์ใน Claude Code
/wayfinder ย้ายระบบ auth ไปใช้ OAuth
ตอนนี้ยังไม่รู้ด้วยซ้ำว่าจะเริ่มตรงไหนดี

ถ้าต่อกับ Jira ไว้ สิ่งที่โผล่บนบอร์ดจะหน้าตาประมาณนี้ (ตัวอย่าง) Epic หนึ่งใบเป็นแผนที่ กับ ticket ลูกที่เป็นงานชิ้นเล็ก ๆ คนละชนิด ทั้ง research (ไปค้น), grill (ซักให้ชัด), prototype (ลองของ) พร้อมสถานะ To Do / In Progress / Done แบบที่ชาว Jira คุ้นตา:

Jira Software · Backlog ของ Epic (บอร์ดงานส่วนกลางของทีม) EPIC AUTH-11 ย้ายระบบ auth ไปใช้ OAuth 3 / 7 issue เสร็จ · กำลังหาเส้นทาง AUTH-12 research provider ที่ทีมใช้อยู่แล้วมีอะไรบ้าง DONE AUTH-13 research flow ปัจจุบันเก็บ session ยังไง DONE AUTH-14 grill ต้องรองรับ login เดิมช่วง migrate ไหม DONE AUTH-15 prototype ลองต่อ Google OAuth ใน branch ทดลอง IN PROGRESS AUTH-16 research มี endpoint ไหนผูกกับ user id เดิมบ้าง TO DO
แทนที่จะถือทั้งงานไว้ในหัว wayfinder แตกเป็น ticket เล็ก ๆ ใต้ Epic เดียวบน Jira ปิดทีละใบจนหมอกจาง สถานะ To Do / In Progress / Done บอกความคืบหน้าในตาเดียว และทั้งทีมเห็นบอร์ดเดียวกัน

แต่ละใบคืองานที่ปิดได้จบใน session เดียว พอทำ AUTH-15 เสร็จ มันก็อัปเดตสถานะบนบอร์ด (ขยับจาก In Progress เป็น Done) แล้วเราค่อยเปิดแชทใหม่หยิบ AUTH-16 ต่อ หมอกที่บังปลายทางก็จางไปทีละใบ โดยที่ไม่มี session ไหนต้องแบกทั้งงานพร้อมกัน

wayfinder แทน grill-me เลยไหม?

ในเอกสาร wayfinder Matt แนะว่าสำหรับงานที่ยังพร่ามัว ให้เอื้อมหา wayfinder เป็นตัวตั้งต้น แทนการพุ่งเข้า grill-me ทันที แต่ไม่ได้แปลว่า grill-me ตกรุ่น งานที่ scope ชัดอยู่แล้ว grill-me ยังกระชับและเหมาะกว่า แถมการ "ซัก" ก็ยังเป็นหนึ่งในโหมด ticket งานของ wayfinder เองด้วยซ้ำ พูดง่าย ๆ คืองานเล็ก-ชัด➔grill-me, งานใหญ่-พร่ามัว➔wayfinder เลือกตามขนาดหมอกที่เจอ

ต่อจิ๊กซอว์: ไปป์ไลน์เต็มจากไอเดีย➔โค้ดที่รีวิวแล้ว

ที่เล่ามา grill/wayfinder เป็นแค่ "หัวขบวน" ล่าสุด Matt ปล่อยสกิลที่เหลือมาต่อกันเป็นสายพานเดียวจบ ตั้งแต่คุยจนถึง commit ไล่เป็น 5 สเต็ป โดยแต่ละตัวส่งงานให้ตัวถัดไป:

สายพาน 5 สเต็ป · งานไหลจากบนลงล่าง ทีละทอด 1 /grill-with-docs · /wayfinder ซักให้เข้าใจงานจริง: งานเล็กใช้ grill · งานใหญ่ใช้ wayfinder 2 /to-spec สรุปบทสนทนาเป็น spec · เอกสารที่นิยาม "ปลายทาง" ของฟีเจอร์ 3 /to-tickets แตก spec เป็น ticket ย่อย + ผูกลำดับก่อน-หลัง (ใบไหนทำคู่ขนานได้ก็เห็น) 4 /implement ไล่ทำทีละ ticket แบบ TDD · เขียนเทสต์ให้ "แดง" ก่อน แล้วเขียนโค้ดให้ "เขียว" 5 /code-review ตรวจมาตรฐาน + ตรงสเปค + refactor ตรงนี้ ➔ แล้วค่อย commit
งานไหลทีละทอด /grill-with-docs·/wayfinder➔/to-spec➔/to-tickets➔/implement➔/code-review แต่ละสเต็ปคือ slash command หนึ่งคำสั่ง ที่ /implement จะทำแต่ละ ticket แบบ test-first เอง

แกะคำศัพท์: TDD คืออะไร

ในสเต็ป 4 คุณจะเห็นคำว่า TDD โผล่มา ย่อจาก Test-Driven Development อ่านว่า "ทีดีดี" แปลตรงตัวว่า "การพัฒนาที่ให้เทสต์เป็นตัวนำ" คือเขียน test (ชุดตรวจว่าโค้ดทำงานถูกไหม) ก่อน เขียนโค้ดจริง แทนที่จะเขียนโค้ดเสร็จแล้วค่อยตามไปเทสต์ที่หลัง

วงจรมาตรฐานของมันมี 3 จังหวะ: แดง (เขียนเทสต์ที่ยังไม่ผ่านไว้ก่อน มันจึงขึ้นแดง)➔เขียว (เขียนโค้ดจนเทสต์ผ่านหมด กลายเป็นเขียว)➔refactor (จัดโค้ดให้สะอาดขึ้น โดยเทสต์เดิมยังเขียวอยู่) วงจรแดง-เขียว-refactor นี้เราเคยเดินผ่านมาแล้วตอน บทความ Claude Code workflow ในหัวข้อ "ให้ tests เป็นเกณฑ์ตัดสิน"

กางดู TDD เดินจริงทีละจังหวะ (ตัวอย่างของเล่น: แปลงคะแนนเป็นเกรด)

อ่านนิยามอย่างเดียวอาจยังลอย ๆ ลองจับโจทย์เล็ก ๆ มาเดินให้ครบวงดีกว่า สมมติเราอยากได้ฟังก์ชัน gradeOf(score) ที่รับคะแนน 0–100 แล้วคืนเกรด โดยเกณฑ์คือ 90 ขึ้นไป = A · 80–89 = B · 70–79 = C · 60–69 = D · ต่ำกว่านั้น = F แบบ TDD เราจะไม่เขียนฟังก์ชันก่อน แต่เขียน "เทสต์" ที่อธิบายว่าอยากได้อะไรก่อนเสมอ

จังหวะที่ 1: แดง: เขียนเทสต์ทั้งที่ยังไม่มีฟังก์ชัน เราลงมือเขียนสิ่งที่ "อยากให้เป็น" ก่อน ทั้งที่รู้ว่ามันต้องล้มแน่ ๆ เพราะ gradeOf ยังไม่มีตัวตนด้วยซ้ำ

grade.test.ts: เขียนเทสต์ก่อน
import { gradeOf } from "./grade";

test("80 คะแนน ได้เกรด B", () => {
  expect(gradeOf(80)).toBe("B");
});

รันเทสต์ครั้งแรก มันย่อมล้ม และนี่คือ "แดง" ที่เราตั้งใจให้เกิด (ล้มเพราะยังไม่มีโค้ด ไม่ใช่ล้มเพราะโค้ดผิด):

รันเทสต์: แดง
FAIL  grade.test.ts
  x  80 คะแนน ได้เกรด B
     ReferenceError: gradeOf is not defined

จังหวะที่ 2: เขียว: เขียนโค้ดให้น้อยที่สุดที่ทำให้เทสต์ผ่าน ทีนี้ค่อยเขียนฟังก์ชันจริง เป้าหมายเดียวคือ "ทำให้มันเขียว" ไม่ต้องคิดเรื่องความสวยงามตอนนี้

grade.ts: เขียนพอให้ผ่าน
export const gradeOf = (score: number): string => {
  if (score >= 90) return "A";
  if (score >= 80) return "B";
  if (score >= 70) return "C";
  if (score >= 60) return "D";
  return "F";
};
รันซ้ำ: เขียว
PASS  grade.test.ts
  ok  80 คะแนน ได้เกรด B (2 ms)

อยากมั่นใจว่าเกณฑ์ตรงขอบไม่เพี้ยน ก็เพิ่มเทสต์เคสหินอีกสองสามอัน (ค่าตรงรอยต่อพอดี ๆ อย่าง 90 กับ 59) แล้ววนจังหวะแดง➔เขียวแบบเดิม ถ้าเผลอเขียน > แทน >= เคส 90 จะฟ้องแดงให้เห็นทันที

เพิ่มเทสต์ค่าขอบ
test("90 พอดี ได้ A ไม่ใช่ B", () => {
  expect(gradeOf(90)).toBe("A");
});
test("59 ตกเกณฑ์ ได้ F", () => {
  expect(gradeOf(59)).toBe("F");
});

จังหวะที่ 3: refactor: จัดโค้ดให้สะอาดขึ้น โดยพฤติกรรมเท่าเดิม พอเขียวครบแล้วค่อยมองย้อนว่าโค้ดรกไหม ตรงนี้ if ห้าชั้นซ้ำ ๆ พอยัดเกณฑ์ใหม่ทีก็ต้องแก้หลายบรรทัด เราเลยยกไปเป็น "ตารางเกณฑ์" ให้อ่านง่ายและต่อเติมง่ายกว่า สิ่งที่การันตีว่ารื้อแล้วไม่พังคือเทสต์ชุดเดิมที่ยังเขียวอยู่ ไม่ได้แตะเลยสักบรรทัด

grade.ts: หลัง refactor (เทสต์เดิมยังเขียว)
const SCALE: [number, string][] = [[90, "A"], [80, "B"], [70, "C"], [60, "D"], [0, "F"]];

export const gradeOf = (score: number): string =>
  SCALE.find(([min]) => score >= min)![1];
รันเทสต์ชุดเดิมอีกครั้ง: ยังเขียวหมด
PASS  grade.test.ts
  ok  80 คะแนน ได้เกรด B (1 ms)
  ok  90 พอดี ได้ A ไม่ใช่ B (1 ms)
  ok  59 ตกเกณฑ์ ได้ F (1 ms)

นี่แหละวงเต็มของ TDD: แดง (บอกความต้องการด้วยเทสต์)➔เขียว (ทำให้มันผ่าน)➔refactor (เก็บกวาดโดยมีเทสต์คุ้มหลัง) วนแบบนี้ทีละก้อนเล็ก ๆ จนงานเสร็จ

ทีนี้ลองเลื่อนกลับไปดูสายพาน 5 สเต็ปข้างบนอีกที แล้วเทียบกับวง TDD ที่เพิ่งเล่า จะเจอของแปลกอยู่อย่างนึง จังหวะ refactor (จังหวะที่ 3 ของ TDD) ไม่ได้อยู่ในสเต็ป /implement แต่ไปโผล่เป็นงานของสเต็ป /code-review (สเต็ป 5) แทน ทั้งที่ตำราบอกว่ามันควรอยู่ในวงเดียวกัน ทำไมถึงเป็นงั้น?

เฉลย: Matt จงใจแยก refactor ออกจากวง

ไม่ใช่ความบังเอิญครับ Matt เขียนกำกับไว้ในสกิล tdd เลยว่า refactor ไม่นับเป็นส่วนของวง red➔green แต่ให้ไปทำตอน code-review แทน เหตุผลคืออยากให้ session ตอน /implement โฟกัสแค่ "ทำให้มันทำงานได้ก่อน" (แดง➔เขียว) ไม่ต้องแบกเรื่องจัดโค้ดให้สวยไปพร้อมกัน แล้วค่อยไปเก็บงานเรียบร้อย (refactor) ทีเดียวตอนรีวิว session เลยสั้นและสะอาดกว่า

ทฤษฎีอ่านแล้วอาจยังลอย ๆ ลองเดินไปด้วยกันทีละสเต็ปแบบไม่รีบดีกว่า สมมติเราอยากได้ฟีเจอร์ "ปุ่ม Export รายการเป็นไฟล์ CSV" จะเห็นเลยว่าสายพานมันส่งงานต่อกันเป็นทอด ๆ ยังไง โดยเราแทบไม่ต้องสั่งอะไรซับซ้อน

ย้ำก่อนว่าทุกสเต็ปคือการพิมพ์ slash command (ชื่อสกิลนำหน้าด้วย /) ในแชท ไม่ใช่บอกเป็นภาษาคนลอย ๆ สกิลตั้งแต่ /to-spec ลงไปทำงานกับบทสนทนาที่คุยไว้ก่อนหน้า เลยพิมพ์คำสั่งเปล่า ๆ ได้เลย

สเต็ป 1: /grill-with-docs: ปล่อยให้มันซักก่อน พิมพ์คำสั่งตามด้วยเป้าหมายกว้าง ๆ แบบไม่ต้องคิดเยอะ แล้วปล่อยให้มันถามกลับ ไม่ต้องรีบตอบเองให้ครบ

พิมพ์ใน Claude Code
/grill-with-docs อยากได้ปุ่ม export รายการในตารางเป็นไฟล์ CSV
AI ซักกลับ (ตัวอย่าง)
ขอถามให้ชัดก่อน 4 ข้อ:
  1. เอาทุกแถว หรือเฉพาะแถวที่กรองอยู่บนหน้าตอนนั้น?
  2. คอลัมน์ไหนบ้างที่ต้องมีในไฟล์?
  3. หัวตาราง (header) เป็นภาษาไทยหรืออังกฤษ?
  4. ปุ่มวางตรงไหนของหน้า?

เราตอบสั้น ๆ กลับไปว่า "เฉพาะแถวที่กรองอยู่ · เอาทุกคอลัมน์ที่เห็นบนตาราง · หัวตารางภาษาไทย · วางมุมขวาบนเหนือตาราง" แค่นี้บริบทก็ครบพอจะไปต่อ

สเต็ป 2: /to-spec: ตกผลึกบทสนทนาเป็นเอกสารสั้น ๆ พอตอบครบ ก็พิมพ์ /to-spec เปล่า ๆ ให้มันสรุปสิ่งที่เพิ่งคุยกันเป็น spec หนึ่งหน้า

พิมพ์ใน Claude Code
/to-spec
spec.md ที่ได้ (ตัวอย่าง)
# Export CSV

- ปุ่ม "ดาวน์โหลด CSV" วางมุมขวาบนเหนือตาราง
- กดแล้วดาวน์โหลดไฟล์ .csv ของ **เฉพาะแถวที่กรองอยู่ตอนนั้น**
- ใส่ทุกคอลัมน์ที่แสดงบนตาราง, หัวตารางเป็นภาษาไทย
- ตัวคั่น comma, encoding UTF-8 (กันภาษาไทยเพี้ยนตอนเปิดใน Excel)

ข้อดีของการมี spec คือมันกลายเป็น "ปลายทาง" ที่ตรวจสอบได้ ทีหลังจะรู้ทันทีว่าทำครบหรือยัง

สเต็ป 3: /to-tickets: แตกเป็น ticket ย่อย พร้อมบอกลำดับ พิมพ์ /to-tickets มันจะซอย spec เป็นงานชิ้นเล็ก แล้วบอกด้วยว่าใบไหนต้องรอใบไหน ใบไหนทำคู่ขนานได้

พิมพ์ใน Claude Code
/to-tickets
EXP-1 แกนกลาง แปลง rows → ข้อความ CSV ไม่ติดใคร เริ่มได้เลย blocks · ต้องเสร็จก่อน EXP-2 is blocked by EXP-1 ปุ่ม + สั่งเบราว์เซอร์ดาวน์โหลดไฟล์ EXP-3 คู่ขนานกับ EXP-2 สถานะ loading / error ตอนกดปุ่ม คู่ขนาน
to-tickets ไม่ได้แค่ซอยงาน แต่ผูก "ลำดับ" ให้แบบ Jira เลย EXP-2 ติดป้าย is blocked by EXP-1 (ต้องรอ EXP-1), ส่วน EXP-3 วิ่งคู่ขนานกับ EXP-2 ได้ ทีมเลยเห็นทันทีว่าหยิบใบไหนทำพร้อมกันได้

สเต็ป 4: /implement: ทำทีละ ticket แบบ test-first พิมพ์ /implement แล้วตามด้วยคีย์การ์ดที่จะทำให้ชัดไปเลย เช่น /implement EXP-1 ระบุดีกว่าปล่อยเปล่า ๆ เพราะถ้าไม่บอก มันจะหยิบการ์ดถัดไปที่ยังไม่ถูกบล็อก (frontier) มาทำเอง ซึ่งเราอาจเดาไม่ถูกว่ารอบหน้ามันจะจับใบไหน พอระบุคีย์ EXP-1 มันก็เอาคีย์นั้นไปดึงรายละเอียดการ์ดบน Jira ผ่านเครื่องมือที่ต่อไว้ (เช่น Atlassian MCP) มาเอง กติกาคือเขียนเทสต์ให้ "แดง" ก่อนเสมอ แล้วค่อยเขียนโค้ดจนมันเขียว เพราะงั้นรอบแรกจะเห็นเทสต์ล้มก่อน (ตั้งใจให้ล้ม):

พิมพ์ใน Claude Code
/implement EXP-1
รันเทสต์รอบแรก: แดง (ตัวอย่าง)
FAIL  toCsv.test.ts
  x  แปลง 2 แถวเป็น CSV พร้อมหัวตาราง
     ReferenceError: toCsv is not defined

เห็น "แดง" แล้วมันถึงเขียนฟังก์ชัน toCsv จริง ๆ พอโค้ดเสร็จก็รันซ้ำ คราวนี้ต้องเขียว:

รันซ้ำหลังเขียนโค้ด: เขียว (ตัวอย่าง)
PASS  toCsv.test.ts
  ok  แปลง 2 แถวเป็น CSV พร้อมหัวตาราง (3 ms)

แล้วก็ไล่ ticket EXP-2 กับ EXP-3 ต่อด้วยจังหวะเดียวกัน (แดง➔เขียว) ทีละใบ ไม่ต้องรีบทำรวดเดียวจนเหนื่อย

แล้วสถานะบน Jira (To Do / In Progress / Done) มันขยับให้เองไหม?

คำถามที่ตามมาแน่ ๆ คือ พอ Claude หยิบการ์ดไปทำ มันเลื่อนสถานะให้เอง หรือเราต้องไปลากเองบนบอร์ด? คำตอบสั้น ๆ คือขึ้นกับว่าเรียกใช้ผ่านอะไร:

  • ผ่าน /wayfinder (โหมดแผนที่): ตัว agent จัดการให้เองตามที่สกิลเขียนกำกับไว้: claim การ์ดก่อนเริ่ม (คือ assign การ์ดให้คนที่กำลังขับแผนที่ เพื่อกัน session อื่นหยิบซ้ำ บนบอร์ดก็คือถูกจับจอง/ขยับเข้าโซนกำลังทำ) แล้วพอเสร็จก็ close การ์ดพร้อมโพสต์คอมเมนต์สรุปผล (= ปิดเป็น Done) ทำผ่านเครื่องมือที่ต่อไว้ ไม่ต้องลากเอง
  • เรียก /implement ตรง ๆ ในไปป์ไลน์: ตัวสกิลนี้โฟกัสที่ "เขียนโค้ด + เทสต์" เป็นหลัก ไม่ได้การันตีว่าจะสลับสถานะ Jira ให้ทุกครั้ง ทางที่ชัวร์คือสั่งมันตรง ๆ เช่น "ย้าย EXP-1 เป็น In Progress ตอนเริ่ม แล้วปิดเป็น Done ตอนเทสต์เขียวหมด" (ถ้าต่อ Atlassian MCP / gh ไว้ มันทำให้ได้) หรือจะไปลากเองบนบอร์ดก็ได้
  • โหมดไฟล์ในเครื่อง: ไม่มีบอร์ดให้ขยับ มันก็บันทึกสถานะเป็นข้อความในไฟล์ markdown แทน

สเต็ป 5: /code-review: ตรวจแล้วค่อยเก็บกวาด พอปิด ticket แต่ละใบ (หรือจบก้อนที่พอเป็นชิ้นเป็นอัน) ก็พิมพ์ /code-review รอบนึง ไม่ต้องรอทำครบทุก ticket ก่อน จังหวะรีวิวนี้เองที่ค่อยจับ refactor เช่นเห็นว่าโค้ด escape เครื่องหมาย comma เขียนซ้ำอยู่สองที่ ก็รวบเป็นฟังก์ชันเดียว แล้วจึง commit ปิดใบนั้น

พิมพ์ใน Claude Code
/code-review

พอไล่ครบห้าสเต็ป จะรู้สึกว่าได้ครบลูปเดียว: คิด➔คุย➔กำหนดทิศ➔แตกงาน➔ทำทีละชิ้น➔ตรวจจนปิด โดยไม่ต้องคอยจำว่า "ขั้นต่อไปสั่งอะไร" สายพานมันส่งต่อให้เอง (สกิลชุดนี้อยู่ใน repo เดียวกับ wayfinder ที่ลงไปแล้ว ไม่ต้องติดตั้งเพิ่ม)

ปิดท้ายด้วยจุดอ่อนหนึ่งของ /handoff ที่ยังเจอกันบ่อยแม้ไม่ได้ใช้ wayfinder คือบางทีพอ context ใกล้เต็มเราก็ดันลืมสั่ง handoff เอง วิธีบ้าน ๆ ที่พอถูไถได้คือหมั่นดู /context (คำสั่งดูว่า context เหลือที่ว่างเท่าไหร่) แล้วสั่ง /handoff เองก่อนจะแตะโซนอันตราย แต่ถ้าขี้เกียจคอยจ้อง เราต่อ "ของเสริม" ที่กันลืมให้ตัวเองได้เลย ซึ่งพอดีเป็นตัวอย่างสอนคราฟต์ที่ดีมาก


โบนัส: คราฟต์ของเสริมเอง: ประกอบ /context + /handoff เป็น "handoff-guard"

ของเสริมที่ "พอดีจุดเจ็บเรา" ที่สุด บ่อยครั้งคือตัวที่เราต่อเอง และมันไม่ได้ยากอย่างที่คิด เป้าหมายตรงนี้คือรวมไอเดียของ /context (ดูพื้นที่เหลือ) กับ /handoff (จดส่งไม้ต่อ) ให้กลายเป็นตัวช่วยชื่อ handoff-guard ที่กันเราลืม ทำได้ 2 ระดับ ไล่จากง่ายไปออโต้:

ระดับ 1: มัดรวมเป็น "สกิล" ที่เราพิมพ์เรียกเอง สกิลใน Claude Code จริง ๆ ก็คือโฟลเดอร์หนึ่งใบที่มีไฟล์ SKILL.md ข้างในมี 2 ส่วน: ส่วนหัว (frontmatter) บอกว่าสกิลนี้ทำอะไร/ใช้ตอนไหน กับเนื้อ markdown ที่เป็นคำสั่งให้ Claude ทำตาม ชื่อโฟลเดอร์กลายเป็นชื่อคำสั่งที่เราพิมพ์ (โฟลเดอร์ handoff-guard ก็เรียกด้วย /handoff-guard) เท่านี้ก็ได้สกิลใหม่แล้ว:

~/.claude/skills/handoff-guard/SKILL.md
---
description: ร่างไฟล์ handoff สรุปสถานะงานปัจจุบัน ใช้ตอนใกล้จบเซสชันยาว ๆ หรือก่อน context จะเต็ม/โดน compact
---

## สถานะ ณ ตอนนี้

!`git status --short`
!`git log --oneline -5`

## หน้าที่

เขียนไฟล์ HANDOFF.md ให้เซสชันถัดไปหยิบทำต่อได้ทันที ครอบ 3 หัวข้อ:
1. รอบนี้ทำอะไรเสร็จไปแล้ว (อ้างไฟล์/คอมมิตจริงจากด้านบน)
2. ค้างอะไรอยู่ และสเต็ปถัดไปคืออะไร
3. กับดัก/ข้อควรระวังที่เจอระหว่างทาง
เขียนสั้น กระชับ พอให้เปิดเซสชันใหม่แล้วไปต่อได้โดยไม่ต้องเล่าใหม่

เกร็ดที่ทำให้มันคมคือบรรทัด !`git ...` ข้างบน เครื่องหมาย ! หน้า backtick สั่งให้ Claude Code รันคำสั่ง shell นั้นก่อน แล้วเอา "ผลลัพธ์จริง" ยัดแทนที่บรรทัดนั้น ตั้งแต่ยังไม่ทันส่งให้โมเดลอ่าน (เรียกว่า dynamic context injection) สกิลเลยได้เห็นสถานะ git ของจริง ไม่ใช่เดาเอา ข้อจำกัดที่ต้องรู้: สกิลแบบนี้ไม่ได้เด้งเองตอน context เต็ม เราต้องพิมพ์ /handoff-guard เรียกเอง (หรือปล่อยให้ Claude เรียกให้เมื่อ description ตรงกับสิ่งที่เรากำลังคุย) ถ้าอยากให้ "ออโต้จริง" ต้องขยับไประดับ 2

ระดับ 2: ให้มันเด้งเองด้วย hook PreCompact ตัวที่ยิงงานให้อัตโนมัติตาม "เหตุการณ์" คือ hook (เคยเล่าไว้ในบท Claude Code workflow พร้อมตัวอย่าง settings.json แล้ว) ระดับนี้เราต่อเอง 3 สเต็ป และต้องเข้าใจก่อนว่า hook มันรันสคริปต์ ไม่ได้ "พิมพ์ /handoff" ลงในเซสชันให้ เพราะงั้นเราต้องเขียนสคริปต์ที่ทำ handoff แทนขึ้นมาเอง

สเต็ป 1: เขียนสคริปต์ วางไฟล์ shell ไว้ที่ .claude/hooks/handoff-guard.sh พอ hook ยิง Claude Code จะโยน JSON ของเซสชัน (มี transcript_path = ที่อยู่ของบทสนทนาทั้งเซสชัน, cwd, ฯลฯ) เข้ามาทาง stdin เราก็งัดค่าที่ต้องใช้ออกด้วย jq แล้วเขียนไฟล์ handoff เอง:

.claude/hooks/handoff-guard.sh
#!/usr/bin/env bash
# Claude Code ยิงสคริปต์นี้ก่อน auto-compact แล้วส่ง JSON มาทาง stdin

input=$(cat)                                     # อ่าน JSON ทั้งก้อนจาก stdin
transcript=$(echo "$input" | jq -r '.transcript_path')

{
  echo "# HANDOFF: $(date '+%Y-%m-%d %H:%M')"
  echo
  echo "## สถานะ git ล่าสุด"
  git status --short
  echo
  echo "## 5 คอมมิตล่าสุด"
  git log --oneline -5
  echo
  echo "## transcript เต็มของเซสชันนี้ (ให้ session ใหม่อ่านต่อ)"
  echo "$transcript"
} > HANDOFF.md

อันนี้เป็นเวอร์ชันเก็บ snapshot ดิบ ๆ (git + ที่อยู่ transcript) ถ้าอยากได้สรุปเป็นภาษาคน ก็ให้สคริปต์เรียก claude -p (โหมด headless ที่รัน Claude แบบไม่เปิดแชท) มาอ่าน transcript แล้วสรุปลง HANDOFF.md แทนบล็อก git ด้านบนได้เลย

สเต็ป 2: ลงทะเบียน hook ตรงนี้ตอบคำถามที่หลายคนสงสัย: ต้องเขียน JSON เองไหม? ใช่ครับ เมนู /hooks ใน Claude Code ดูได้อย่างเดียว แก้ไม่ได้ เราต้องเปิดไฟล์ .claude/settings.json ใส่บล็อกนี้เอง (หรือจะบอก Claude ให้เขียนให้ก็ได้) โดยเลือก event เป็น PreCompact จังหวะที่ Claude Code ยิงก่อนบีบอัด context (ตอน auto-compact ที่ context เกือบเต็ม) และเลือก matcher เองว่าจะให้ทำงานตอนไหน: auto = เฉพาะตอนมันบีบอัดเอง (ที่เราอยากได้), หรือ manual = ตอนเราสั่ง /compact เอง

.claude/settings.json
{
  "hooks": {
    "PreCompact": [
      {
        "matcher": "auto",
        "hooks": [
          { "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/handoff-guard.sh" }
        ]
      }
    ]
  }
}

สเต็ป 3: ทำให้สคริปต์รันได้ อย่าลืมเปิดสิทธิ์ execute ให้ไฟล์ ไม่งั้น hook จะยิงแล้วรันไม่ออก:

รันครั้งเดียวใน terminal
chmod +x .claude/hooks/handoff-guard.sh

ครบสามสเต็ปแล้ววงจรจะเดินเองทั้งหมด: context เกือบเต็ม➔Claude Code เตรียม auto-compact➔ยิง PreCompact➔รัน handoff-guard.sh➔ได้ HANDOFF.md ติดมือ ก่อนบทสนทนาจะโดนสรุปทิ้ง เปิดเซสชันใหม่ก็ชี้ให้ Claude อ่าน HANDOFF.md ต่อได้เลย ไม่มีวันลืม handoff อีก

ระวังก่อนต่ออะไรที่รันสคริปต์เอง

ทั้งสกิลที่มีบรรทัด !`...` และ hook ที่ชี้ไปสคริปต์ คือโค้ดที่จะรันแทนเราจริง ๆ เปิดไฟล์ SKILL.md / สคริปต์ .sh อ่านให้เห็นก่อนว่ามันสั่งอะไร โดยเฉพาะของที่ก๊อปมาจากคนอื่น อย่าเพิ่งวางใจเพราะชื่อฟังดูไม่มีพิษภัย

นี่แหละหัวใจของ "ของเสริมนอกกล่อง" ทั้งบท พอเข้าใจว่าสกิล (สิ่งที่เราพิมพ์เรียก) กับ hook (สิ่งที่ระบบยิงให้เอง) ต่อกันยังไง เราก็ประกอบเครื่องมือที่พอดีจุดเจ็บของตัวเองขึ้นมาได้ ไม่ต้องรอใครทำมาให้

หลักการเลือกของเสริม

ของพวกนี้มีขึ้นทุกวัน อย่าไล่ติดทุกตัวจนรก เลือกจาก "จุดเจ็บ" ของตัวเองก่อน คุมเบราว์เซอร์ไม่ได้? เอา Playwright MCP กลัวช่องโหว่หลุด? เอา Trivy บิลค่า token บานเพราะคำตอบยาว? ลอง Caveman โค้ดรกเพราะเขียนเกิน? ลอง Ponytail แก้ทีละจุดเจ็บ ไม่ใช่ลงมากองไว้เฉย ๆ


สรุปบรรทัดเดียว

ตอนแรกเราจูน "สมอง" (โมเดล) กับ "ความจำ" ให้ Claude ไปแล้ว ตอนนี้คือการต่อมือ-ต่อตา-ต่อสายพานงานให้มันครบเครื่อง แต่กุญแจไม่ใช่ "ยิ่งเยอะยิ่งดี" มันคือ เลือกของเสริมตาม "จุดเจ็บ" ของตัวเอง แล้วต่อให้ถูกจุด ไม่ใช่ลงทุกตัวมากองไว้จนรก

(บทนี้เป็นตอนจบของคู่ "ติดอาวุธให้ Claude" ถ้ายังไม่ได้อ่าน ตอนที่ 1: เลือกโมเดล + วางระบบความจำ แนะนำให้ย้อนไปจูนฐานก่อน จะได้ผลเต็มที่)


แหล่งอ้างอิง

เรียบเรียงและอธิบายใหม่ด้วยคำตัวเอง โดยตรวจสอบข้อเท็จจริงกับแหล่งปฐมภูมิด้านล่าง (ค่าตัวเลขเป็นค่าที่ผู้พัฒนาแต่ละเครื่องมือรายงานไว้)

  1. โพสต์สรุปเทคนิคใช้ Claude (agent harness, Hot/Cold memory, learning.md, การเลือกโมเดล) · Supadej Suthiphongkanasai, Facebook, สืบค้นเมื่อ 10 กรกฎาคม 2026
  2. "caveman: Claude Code skill that cuts tokens by talking like caveman" · Julius Brussee, GitHub, สืบค้นเมื่อ 10 กรกฎาคม 2026
  3. "ponytail: Makes your AI agent think like the laziest senior dev in the room" · Dietrich Gebert, GitHub, สืบค้นเมื่อ 10 กรกฎาคม 2026
  4. "Trivy: Find vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more" · Aqua Security, GitHub, สืบค้นเมื่อ 10 กรกฎาคม 2026
  5. "Playwright MCP" · Playwright Docs, Microsoft, สืบค้นเมื่อ 10 กรกฎาคม 2026
  6. "playwright-mcp: Playwright MCP server (README + การติดตั้ง)" · Microsoft, GitHub, สืบค้นเมื่อ 10 กรกฎาคม 2026
  7. "mattpocock/skills: ไปป์ไลน์ to-spec / to-tickets / implement / code-review, wayfinder, handoff, grill-with-docs" · Matt Pocock, GitHub, สืบค้นเมื่อ 10 กรกฎาคม 2026
  8. "wayfinder: SKILL.md (แผนที่งานบน issue tracker, 1 ticket = 1 session)" · Matt Pocock, GitHub, สืบค้นเมื่อ 10 กรกฎาคม 2026
  9. "tdd: SKILL.md (วง red→green, ยก refactor ไปเฟส code-review)" · Matt Pocock, GitHub, สืบค้นเมื่อ 11 กรกฎาคม 2026
  10. "grill-with-docs: เอกสารสกิล (glossary ที่ CONTEXT.md + ADR ที่ docs/adr/, สร้างแบบ lazy)" · Matt Pocock, GitHub, สืบค้นเมื่อ 11 กรกฎาคม 2026
  11. "Atlassian MCP Server: ต่อ Jira/Confluence เข้ากับ Claude ผ่าน OAuth 2.1 หรือ API token" · Atlassian, GitHub, สืบค้นเมื่อ 11 กรกฎาคม 2026
  12. "Extend Claude with skills: โครงสร้าง SKILL.md, ที่อยู่ .claude/skills/, dynamic context injection" · Claude Code Docs, Anthropic, สืบค้นเมื่อ 11 กรกฎาคม 2026
  13. "Hooks reference: event PreCompact, matcher auto/manual, รูปแบบ settings.json" · Claude Code Docs, Anthropic, สืบค้นเมื่อ 11 กรกฎาคม 2026
  14. "wayfinder สกิลใหม่ แก้ปัญหาที่ grill-me ทำไม่ได้ (Context Smart/Dump Zone)" · เพจ HSpotlight (หัวหน้าฮง), Facebook, สืบค้นเมื่อ 10 กรกฎาคม 2026