วิธีแชร์ Agent Skills ข้าม Repository ไม่ให้โค้ดเพี้ยน
เลิกคัดลอกไฟล์ Agent Skills ไปไว้หลายโปรเจกต์จนเกิดปัญหาโค้ดไม่ตรงกัน เปลี่ยนมาใช้วิธีจัดการแบบ Dependency ด้วยการระบุเวอร์ชันผ่าน Tag และทำ Smoke Test เพื่อควบคุมคุณภาพ
วิธีการแชร์ทักษะของ Agent ข้าม Repository
หากต้องการแชร์ทักษะของ Agent ข้าม Repository ให้หยุดการคัดลอกไฟล์และเปลี่ยนมาใช้วิธีการอ้างอิงแทน โดยให้เก็บทักษะทั้งหมดไว้ใน Repository เดียว ทำการติด Tag และให้แต่ละโปรเจกต์ระบุเวอร์ชันผ่าน Tag นั้น จากนั้นให้เพิ่ม smoke test สำหรับแต่ละทักษะ และตรวจสอบการอัปเดตเวอร์ชันทุกครั้งเช่นเดียวกับการตรวจสอบการอัปเดต Dependency
กระบวนการนี้ประกอบด้วย 4 ส่วน ได้แก่ แหล่งข้อมูลหลักที่ใช้ร่วมกัน, การระบุเวอร์ชันที่แน่นอนในแต่ละ Repository, การทำ smoke test สำหรับแต่ละทักษะ และขั้นตอนการตรวจสอบ เนื้อหาด้านล่างนี้จะอธิบายถึงเหตุผลที่ต้องมีแต่ละส่วน สิ่งที่เครื่องมือที่เปิดตัวในปี 2026 จะเข้ามาช่วยจัดการ และวิธีการสร้างระบบทั้งหมดนี้บน Git remote ที่คุณโฮสต์เองโดยไม่ต้องพึ่งพาบริการภายนอก
ทักษะของ Agent คือโฟลเดอร์ที่เก็บไฟล์ SKILL.md รวมถึงสคริปต์และไฟล์อ้างอิงที่จำเป็น หากหน่วยข้อมูลนี้เป็นสิ่งใหม่ โปรดอ่าน ทักษะของ Agent คืออะไรและ SKILL.md ทำงานอย่างไร ก่อน หน้าเว็บนี้จะเน้นไปที่ห่วงโซ่อุปทาน (supply chain) ที่เกี่ยวข้องกับหน่วยข้อมูลดังกล่าว
แหล่งที่อยู่ของทักษะและเหตุผลที่การแบ่งปันเป็นเรื่องยาก
Claude Code โหลดทักษะจากสามแหล่ง และ เอกสารประกอบเกี่ยวกับทักษะ ได้ระบุพาธของแต่ละแหล่งไว้ดังนี้
~/.claude/skills/<skill-name>/SKILL.mdเป็นระดับส่วนบุคคล โดยจะโหลดเข้าสู่ทุกโปรเจกต์ของคุณและไม่มีผลกับผู้อื่น.claude/skills/<skill-name>/SKILL.mdเป็นระดับโปรเจกต์ โดยจะโหลดสำหรับทุกคนที่ checkout รีโพสิทอรีนั้น<plugin>/skills/<skill-name>/SKILL.mdมาพร้อมกับปลั๊กอิน โดยจะโหลดในทุกที่ที่ปลั๊กอินนั้นถูกเปิดใช้งาน
แหล่งที่สองมีประโยชน์ที่สุดสำหรับทีม เนื่องจากมีการ commit ไว้และทุกคนที่ clone รีโพสิทอรีจะได้รับทักษะนั้นไป แต่นั่นก็เป็นจุดเริ่มต้นของปัญหาเช่นกัน ทักษะที่อยู่ใน .claude/skills/ จะผูกติดอยู่กับรีโพสิทอรีเดียว หากคุณมีแปดรีโพสิทอรี ทักษะนั้นก็จะถูกคัดลอกไปแปดครั้ง
ส่วน frontmatter ไม่ได้ช่วยในเรื่องนี้ สเปกของ Agent Skills อนุญาตให้ใช้คีย์ได้หกรายการ และพาธการแจกจ่ายที่บังคับใช้สเปกนี้จะแสดงรายการคีย์ออกมาเมื่อคุณใช้คีย์อื่น:
Unexpected key(s) in SKILL.md frontmatter: argument-hint. Allowed properties are: allowed-tools, compatibility, description, license, metadata, nameสังเกตสิ่งที่ขาดหายไป: ไม่มีคีย์ version อยู่เลย ไม่มีข้อมูลใดภายในไฟล์ที่บันทึกว่าสำเนาชุดใดใหม่กว่ากัน ซึ่งเป็นเรื่องสมเหตุสมผลเนื่องจากทักษะเป็นเอกสารมากกว่าที่จะเป็นแพ็กเกจ แต่นั่นหมายความว่าการทำ versioning จะต้องมาจากเลเยอร์ที่อยู่รอบไฟล์นั้น และเลเยอร์ดังกล่าวคือหน้าที่ของคุณ
ปัญหาที่หนึ่ง: สำเนาแปดชุดที่ค่อยๆ แตกต่างกัน
การคัดลอกและวางใช้งานได้ดีในวันแรก แต่จะล้มเหลวในวันที่หกสิบ มีคนแก้ไขคำสั่งที่ผิดพลาดใน repo payments แต่ไม่ได้แตะต้องอีกเจ็ดชุดที่เหลือ อีกคนหนึ่งเพิ่มกฎเกี่ยวกับการแบ่งหน้าใน orders ตอนนี้ชื่อทักษะเดียวกันให้ผลลัพธ์การรีวิวที่ต่างกันสองแบบ ขึ้นอยู่กับว่า agent เริ่มต้นทำงานในไดเรกทอรีใด และไม่มีนักพัฒนาคนไหนทราบเรื่องนี้
ความล้มเหลวนี้เงียบเชียบเพราะไม่มีสถานะข้อผิดพลาดเกิดขึ้น ทักษะคือข้อความ คำสั่งที่ล้าสมัยจะสร้างคำตอบที่มั่นใจแต่ผิดพลาด ซึ่งเป็นความผิดพลาดที่มีราคาแพง ไม่มีสิ่งใดใน agent ที่คอยเปรียบเทียบสำเนาของคุณกับของผู้อื่น ดังนั้นสัญญาณเดียวที่จะพบคือการที่มีคนสังเกตเห็นว่า repo สองแห่งให้ข้อมูลไม่ตรงกัน
ปัญหาที่สอง: ไม่มีการระบุเวอร์ชันที่แน่นอน
แม้ว่าทีมจะเก็บทักษะไว้ในที่เดียวกัน แต่วิธีการแบ่งปันที่ใช้กันทั่วไปคือการคัดลอกไฟล์ ไม่ว่าจะเป็นสคริปต์ติดตั้ง, บรรทัดคำสั่ง curl ในเอกสารแนะนำพนักงานใหม่ หรือ shell alias ที่ใช้ซิงค์โฟลเดอร์ วิธีการเหล่านี้ล้วนติดตั้งสิ่งที่อยู่ที่ส่วนหัวของ branch ในขณะนั้นทั้งสิ้น
นั่นหมายความว่านักพัฒนาสองคนที่ทำงานบน commit เดียวกันของแอปพลิเคชันเดียวกัน อาจกำลังรันคำสั่งที่แตกต่างกัน เพราะพวกเขาทำการซิงค์ในวันที่ต่างกัน นอกจากนี้ยังหมายความว่าคุณไม่สามารถตอบคำถามสำคัญที่เกิดขึ้นหลังจากรัน agent แล้วเกิดข้อผิดพลาดได้ว่า: ทักษะเวอร์ชันใดที่สร้างผลลัพธ์นี้ขึ้นมา? หากไม่มีการบันทึก revision ไว้ การรันนั้นจะไม่สามารถทำซ้ำได้ ส่งผลให้รายงานข้อผิดพลาดไม่สามารถนำไปดำเนินการแก้ไขต่อได้
ปัญหาที่สาม: ไม่มีใครทราบว่าทักษะยังคงทำงานได้ตามปกติ
ทักษะ (skill) ไม่มีคอมไพเลอร์ เนื่องจากเป็นชุดคำสั่งที่มุ่งเน้นไปยังโมเดล ทักษะจึงอาจหยุดทำงานได้อย่างถูกต้องแม้ว่าไฟล์จะยังคงเหมือนเดิมทุกไบต์ก็ตาม การอัปเกรดโมเดลอาจส่งผลต่อความแม่นยำในการปฏิบัติตามคำสั่งที่ยาว เครื่องมือบรรทัดคำสั่งที่ทักษะเรียกใช้อาจมีการเปลี่ยนชื่อ flag หรือ URL ในไฟล์อ้างอิงอาจเริ่มส่งค่า 404 กลับมา ทำให้เอเจนต์ทำงานโดยอ้างอิงจากหน้าแสดงข้อผิดพลาดแทน
ในกรณีเหล่านี้ไม่มีสิ่งใดล้มเหลวอย่างชัดเจน เอเจนต์ยังคงให้คำตอบได้ตามปกติ เพียงแต่คำตอบนั้นมีคุณภาพแย่ลงกว่าเดือนที่ผ่านมา ซึ่งเป็นสิ่งที่สังเกตได้ยากหากพิจารณาเพียงทีละ pull request
สิ่งที่เครื่องมือที่เปิดตัวในปี 2026 เข้ามาแก้ไข
ขณะนี้มีคำตอบหลายรูปแบบปรากฏขึ้นมา ซึ่งยังมีความเห็นไม่ตรงกันว่าควรเก็บเวอร์ชันไว้ที่ใด
Lockfiles. เครื่องมือบรรทัดคำสั่ง skills จาก Vercel Labs (vercel-labs/skills, สัญญาอนุญาต MIT, เวอร์ชัน 1.5.22 ณ วันที่ 5 สิงหาคม 2026) ทำหน้าที่ติดตั้งทักษะ (skills) จาก git repository ลงในไดเรกทอรีที่เอเจนต์ของคุณกำหนด โดยเครื่องมือนี้รองรับรูปแบบโครงสร้างของเอเจนต์มากกว่า 70 รายการ npx skills add <repo> ใช้สำหรับติดตั้ง, npx skills update ใช้สำหรับอัปเกรด และ npx skills list ใช้สำหรับแสดงรายการที่คุณมีอยู่ บันทึกสิ่งที่ติดตั้งจะถูกเก็บไว้ต่อผู้ใช้หนึ่งคนแทนที่จะเก็บต่อหนึ่ง repository ทั้งนี้มีคำร้องขอที่เปิดค้างไว้ในโปรเจกต์ดังกล่าว (issue 283) ซึ่งต้องการคำสั่ง skills install เพื่อติดตั้งทักษะทั้งหมดที่ติดตามอยู่ใน lock file ใหม่ เพื่อให้เครื่องที่สองมีชุดทักษะที่เหมือนกัน โปรดอ่านคำร้องขอนั้นเสมือนเป็นรายงานสถานะ แนวคิดเรื่อง lockfile นั้นได้ข้อสรุปแล้ว แต่ส่วนที่ทำงานแยกตามโปรเจกต์นั้นยังอยู่ในระหว่างการพัฒนา
Specs และการทดสอบ. SkillSpec มองในมุมที่ต่างออกไป โดยมองว่า SKILL.md เป็นสัญญาที่ต้องตรวจสอบแทนที่จะเป็นข้อความที่ต้องเชื่อถือ โดยมีเป้าหมายที่ระบุไว้คือการทำให้ทักษะ "ติดตามได้ ทดสอบได้ และพิสูจน์ได้" skillspec doctor <path> จะรายงานจุดที่เอเจนต์มีแนวโน้มจะทำหลุดจากหัวข้อสนทนา skillspec boundary map <path> จะรายงานสิ่งที่ทักษะนั้นเข้าถึงได้ และ skillspec boundary assess <path> จะจัดลำดับความเสี่ยงจากสิ่งที่พบ เครื่องมือนี้เป็น Rust crate ที่ใช้สัญญาอนุญาตแบบคู่ (MIT หรือ Apache 2.0) ที่เวอร์ชัน 0.2.2 ณ วันที่ 29 กรกฎาคม 2026 ควรติดตั้งเวอร์ชันที่ระบุไว้แทนที่จะเป็นเวอร์ชันล่าสุด:
cargo install skillspec --version 0.2.2 --locked
skillspec --version--locked จะทำการ build โดยใช้เวอร์ชันของ dependency ตามที่ crate นั้นถูกเผยแพร่ เพื่อไม่ให้การ build เปลี่ยนแปลงไปจากเดิม skillspec --version ควรแสดงผลเป็น 0.2.2 หากได้ตัวเลขอื่น แสดงว่ามี binary เวอร์ชันเก่าที่อยู่ใน PATH ของคุณทำงานแทรกขึ้นมา
แนวปฏิบัติในการทำ Vendor. Google ได้อธิบายวิธีการสร้างทักษะใน google/skills ผ่านบทความเรื่อง วิธีการสร้าง ทดสอบ และขยายขนาดทักษะของเอเจนต์ หากตัดเรื่องการขยายขนาดออกไป กลไกที่เหลือก็คือการทำ continuous integration (CI) ตามปกติ ทักษะทุกอย่างต้องผ่านการตรวจสอบด้วย linter สำหรับ metadata ใน frontmatter, จำนวนบรรทัด, โครงสร้างไดเรกทอรี และการตั้งชื่อก่อนที่จะทำการ merge นอกจากนี้ยังมีตัวตรวจสอบลิงก์ที่จะทำให้การ build ล้มเหลวหากพบ URL ที่ส่งค่า 404 ซึ่งช่วยตรวจจับลิงก์ที่เอเจนต์สร้างขึ้นมาเอง ผู้เขียนต้องจัดเตรียมชุดคำสั่งประเมินผล (evaluation prompt suite) และเกณฑ์การให้คะแนนควบคู่ไปกับทักษะนั้น จากนั้นงานประเมินผลตามกำหนดการจะรันทุกสัปดาห์กับคลังทักษะทั้งหมดเพื่อตรวจจับปัญหาที่เกิดขึ้นใหม่ (regression) และทักษะทุกรายการจะมีเจ้าของที่ระบุชื่อไว้ ซึ่งคาดหวังว่าจะต้องเข้ามาแก้ไขเมื่อคุณภาพของทักษะลดลง
รูปแบบที่อยู่ภายใต้คำตอบทั้งสามประการ
คุณไม่จำเป็นต้องเลือกเพียงข้อใดข้อหนึ่ง ทั้งสามข้อมีโครงสร้างพื้นฐานร่วมกัน และ git แบบมาตรฐานก็มอบทุกสิ่งที่จำเป็นให้แก่คุณ
- แหล่งข้อมูลเดียวที่เชื่อถือได้ (One source of truth): ทักษะหนึ่งอย่างควรมีที่เก็บเพียงแห่งเดียว และทุก repository จะอ้างอิงไปยังที่เก็บนั้นแทนการเก็บสำเนาไว้เอง
- การระบุเวอร์ชันที่แน่นอนต่อ repository: แต่ละโปรเจกต์จะบันทึก revision ที่ใช้งานจริงไว้ ดังนั้นการอัปเกรดจึงเป็นเพียงการ commit ในโปรเจกต์นั้นๆ ซึ่งมีผู้เขียนและวันที่ระบุชัดเจน
- การทดสอบเบื้องต้นต่อหนึ่งทักษะ (Smoke test): มีการตรวจสอบที่รันได้จริงหนึ่งรายการเพื่อพิสูจน์ว่าทักษะนั้นยังคงให้ผลลัพธ์ตามที่คาดหวัง
- เส้นทางการตรวจสอบ (Review path): การเปลี่ยนแปลงทักษะที่ใช้ร่วมกันจะต้องผ่านการตรวจสอบ และผู้ใช้งานทุกคนจะเห็นความแตกต่าง (diff) ก่อนที่จะนำไปใช้
นั่นคือรูปแบบของ dependency เนื่องจากทักษะต่างๆ กลายเป็นสิ่งที่ถูกนำมาใช้ร่วมกันเร็วกว่าที่เครื่องมือสนับสนุนจะพัฒนาตามทัน ดังนั้นการใช้เครื่องมือที่คุณไว้วางใจอยู่แล้วจึงเป็นทางเลือกที่ปลอดภัยที่สุด
โครงสร้างสำหรับทีมขนาดเล็กบน Git remote ที่โฮสต์เอง
ที่เก็บข้อมูล (repository) หนึ่งแห่งจะทำหน้าที่เก็บทักษะความรู้ โดยไม่มีข้อมูลอื่นปะปนอยู่ภายใน ประวัติการแก้ไขจึงทำหน้าที่เป็นบันทึกการเปลี่ยนแปลง (changelog) ของคำแนะนำต่างๆ ไปในตัว
agent-skills/
skills/
api-review/
SKILL.md
release-notes/
SKILL.md
tests/
api-review.sh
release-notes.sh
CHANGELOG.mdการปล่อยซอฟต์แวร์ (releases) ให้ใช้การทำ tags โดยแนะนำให้ใช้ annotated tags เนื่องจากสามารถระบุข้อความและวันที่ได้ ให้เขียนข้อความอธิบายถึงเหตุผลที่ผู้ใช้งานควรทำการอัปเดตเวอร์ชันนั้นๆ:
git tag -a v1.4.0 -m "api-review: require pagination on list endpoints"
git push origin v1.4.0หาก remote ของคุณคือ Gitea, Forgejo, GitLab หรือเป็น bare repository ที่ใช้งานผ่าน SSH บน VPS ของคุณเอง เนื้อหาหลังจากนี้จะไม่มีการเปลี่ยนแปลงใดๆ ทุกอย่างในที่นี้คือการทำงานของ git ร่วมกับการใช้ symlink
การตรึงเวอร์ชันด้วย git submodule
Submodule จะบันทึก commit ที่เจาะจงของ repository อื่นไว้ภายใน repository ของคุณ บันทึกนั้นคือการตรึงเวอร์ชัน (pin) ในแต่ละโปรเจกต์ที่นำไปใช้งาน:
git submodule add https://git.example.com/team/agent-skills.git vendor/agent-skills
git -C vendor/agent-skills fetch --tags
git -C vendor/agent-skills checkout v1.4.0
mkdir -p .claude/skills
ln -s ../../vendor/agent-skills/skills/api-review .claude/skills/api-review
git add .gitmodules vendor/agent-skills .claude/skills/api-review
git commit -m "Pin shared agent skills to v1.4.0"Symlink คือส่วนที่ทำให้กระบวนการนี้ทำงานได้ รายการ skill ในระดับโปรเจกต์อาจเป็น symlink ที่ชี้ไปยังไดเรกทอรีอื่นบนดิสก์ ซึ่ง Claude Code จะติดตาม symlink นั้นไปและอ่าน SKILL.md จากเป้าหมาย ดังนั้น skill จะถูกโหลดในฐานะ skill ของโปรเจกต์ปกติ ในขณะที่ข้อมูลจริงจะอยู่ใน submodule ณ commit ที่คุณเลือกไว้
ตรวจสอบการตรึงเวอร์ชัน:
git submodule statusบรรทัดที่สมบูรณ์จะขึ้นต้นด้วยช่องว่าง ตามด้วย commit, path และ tag ล่าสุด:
4d1a7c2f0b93e5a1c8d6f2b40e7a95c3d1f8b602 vendor/agent-skills (v1.4.0)หากขึ้นต้นด้วย - หมายความว่า submodule ยังไม่ถูก initialised ทำให้ .claude/skills/api-review ไม่ชี้ไปยังที่ใดและ skill จะไม่ถูกโหลดโดยไม่มีการแจ้งเตือน แก้ไขปัญหานี้ด้วย git submodule update --init หากขึ้นต้นด้วย + หมายความว่า commit ที่ checkout อยู่แตกต่างจากที่บันทึกไว้ ซึ่งหมายความว่านักพัฒนารายนั้นกำลังรันคำสั่งที่ไม่มีใครใช้ การ clone ใหม่จำเป็นต้องใช้ git clone --recurse-submodules และบรรทัดนี้ควรอยู่ใน README เพราะการ clone ปกติจะทำให้ vendor/agent-skills ว่างเปล่าและไม่แสดงข้อผิดพลาดใดๆ
การอัปเกรดเป็นสิ่งที่ต้องทำโดยเจตนา ซึ่งเป็นหัวใจสำคัญของเรื่องนี้:
git -C vendor/agent-skills fetch --tags
git -C vendor/agent-skills diff v1.4.0 v1.5.0 -- skills/
git -C vendor/agent-skills checkout v1.5.0
git add vendor/agent-skills
git commit -m "Bump shared agent skills to v1.5.0"บรรทัด diff คือเส้นทางการตรวจสอบ (review path) ซึ่งแสดงการเปลี่ยนแปลงแบบเดียวกับที่ repository อื่นๆ ที่ใช้งานจะได้รับ และสามารถรวมไว้ใน pull request ได้
การตรึงเวอร์ชันด้วย Marketplace ของปลั๊กอินแทน
หากคุณไม่ต้องการให้ผู้พัฒนาทุกคนต้องเรียนรู้วิธีใช้ submodules ระบบปลั๊กอินของ Claude Code สามารถจัดการการแจกจ่ายให้คุณได้ และยังทำงานร่วมกับ remote ที่คุณโฮสต์เองได้ด้วย ให้วางแคตตาล็อกไว้ที่ .claude-plugin/marketplace.json ใน repository ของ skills:
{
"name": "acme-agents",
"owner": { "name": "Platform team", "email": "platform@example.com" },
"plugins": [
{
"name": "team-skills",
"description": "Shared review and release skills",
"version": "1.4.0",
"source": {
"source": "url",
"url": "https://git.example.com/team/agent-skills.git",
"ref": "v1.4.0",
"sha": "4d1a7c2f0b93e5a1c8d6f2b40e7a95c3d1f8b602"
}
}
]
}ในการนี้จะมีแหล่งที่มาสองแห่งที่เกี่ยวข้อง และข้อผิดพลาดที่พบบ่อยคือการสับสนระหว่างแหล่งที่มาทั้งสอง แหล่งที่มาของ marketplace ซึ่งหมายถึงตำแหน่งที่ดึงแคตตาล็อกมานั้น รองรับเฉพาะ ref สำหรับ branch หรือ tag เท่านั้น และไม่รองรับ sha ส่วนแหล่งที่มาของปลั๊กอินภายในแคตตาล็อกรองรับทั้งสองอย่าง และเมื่อมีการตั้งค่าทั้งคู่ sha จะถือเป็นค่าที่ใช้ในการตรึงเวอร์ชัน ดังนั้นการตรึงด้วย exact-commit จึงต้องระบุไว้ในรายการของแคตตาล็อก
จากนั้น repository ที่เรียกใช้งานแต่ละแห่งจะประกาศ marketplace ไว้ในไฟล์ .claude/settings.json ที่ถูก commit ไว้:
{
"extraKnownMarketplaces": {
"acme-agents": {
"source": {
"source": "url",
"url": "https://git.example.com/team/agent-skills.git",
"ref": "v1.4.0"
}
}
},
"enabledPlugins": {
"team-skills@acme-agents": true
}
}เพื่อนร่วมทีมที่เชื่อถือโฟลเดอร์โปรเจกต์จะได้รับแจ้งให้ติดตั้ง marketplace และปลั๊กอินจะถูกเปิดใช้งานให้โดยอัตโนมัติโดยไม่ต้องอาศัยหน้า wiki เพื่อบอกวิธีการติดตั้ง จากนั้น skills จะตอบสนองต่อ /team-skills:api-review เนื่องจาก skill ของปลั๊กอินจะถูกจัดกลุ่มตามชื่อปลั๊กอินและไม่สามารถทับซ้อนกับ skill ของโปรเจกต์ที่มีชื่อเดียวกันได้ หลังจากที่คุณ push tag ใหม่ ผู้ใช้งานสามารถรีเฟรชด้วย /plugin marketplace update acme-agents จากนั้นให้รัน /reload-plugins หากสรุปการติดตั้งแจ้งให้ดำเนินการดังกล่าว
การเขียน smoke test สำหรับหนึ่งทักษะ
Smoke test คือการรันสคริปต์ผ่าน agent โดยใช้ fixture ที่มีข้อผิดพลาดที่ทราบแน่ชัดร่วมกับการตรวจสอบ (assertion) หนึ่งรายการ Claude Code ทำงานแบบ non-interactive ด้วย -p และทักษะที่เรียกใช้โดยผู้ใช้จะทำงานในโหมดนี้: ให้ใส่ /skill-name ลงในสตริงของ prompt แล้วระบบจะขยายค่าดังกล่าวก่อนการรันจะเริ่มขึ้น
#!/usr/bin/env bash
set -euo pipefail
claude -p "/api-review Read fixtures/orders-api.md and list the rule ids it breaks." \
--allowedTools "Read" \
--output-format json \
--json-schema '{"type":"object","properties":{"rule_ids":{"type":"array","items":{"type":"string"}}},"required":["rule_ids"]}' \
| jq -e '.structured_output.rule_ids | index("pagination-required")' > /dev/nullfixtures/orders-api.md เป็นไฟล์ขนาดสั้นที่มีข้อผิดพลาดที่ตั้งใจใส่ไว้หนึ่งจุด การตรวจสอบคือทักษะต้องระบุชื่อไฟล์นั้น jq -e จะ exit ด้วยสถานะ non-zero เมื่อตัวกรองสร้าง null ดังนั้นหากทักษะหยุดตรวจพบข้อผิดพลาดที่ใส่ไว้ สคริปต์จะล้มเหลว claude จะ exit ด้วยสถานะ non-zero เมื่อการรันล้มเหลว และ set -euo pipefail จะเปลี่ยนความล้มเหลวทั้งสองกรณีให้กลายเป็นการทดสอบที่ล้มเหลว
โมเดลจะปรับเปลี่ยนคำตอบระหว่างการรันแต่ละครั้ง ดังนั้นห้ามตรวจสอบ (assert) ทั้งประโยค ให้ตรวจสอบที่ตัวระบุ (identifier) ที่ทักษะควรจะแสดงออกมา หรือตรวจสอบที่ฟิลด์ของ schema ที่คุณร้องขอ และรักษาขนาดของ fixture ให้เล็กเพื่อให้การรันมีค่าใช้จ่ายต่ำ
ใน CI ให้เพิ่ม --bare หากไม่มีตัวเลือกนี้ claude -p จะโหลด context เดียวกับที่เซสชันแบบโต้ตอบใช้งาน ซึ่งรวมถึง hooks, plugins และ CLAUDE.md จากเครื่องที่รันอยู่ ดังนั้นการตั้งค่าส่วนตัวของเพื่อนร่วมทีมอาจส่งผลต่อผลลัพธ์ได้ โหมด bare จะข้ามการค้นหาอัตโนมัติทั้งหมด ซึ่งหมายความว่าจะข้ามทักษะที่คุณกำลังทดสอบด้วย ดังนั้นให้โหลดทักษะดังกล่าวอย่างชัดเจน โหมด bare จะไม่อ่านข้อมูลการเข้าสู่ระบบสมาชิกของคุณด้วย ดังนั้นให้ตั้งค่า ANTHROPIC_API_KEY ใน environment ไว้ก่อน:
claude --bare -p "/team-skills:api-review Read fixtures/orders-api.md and list the rule ids it breaks." \
--plugin-dir vendor/agent-skills \
--allowedTools "Read" \
--output-format jsonด้วย --output-format stream-json เหตุการณ์แรกของการรันจะรายงานว่ามีปลั๊กอินใดบ้างที่โหลดขึ้นมา และจะแสดงอาร์เรย์ plugin_errors สำหรับปลั๊กอินที่ไม่สามารถโหลดได้ ให้ทำให้งาน CI ล้มเหลวหาก plugin_errors ไม่ว่างเปล่า วิธีนี้จะช่วยตรวจจับกรณีที่การระบุเวอร์ชัน (pin) ชี้ไปยัง revision ที่ไม่มีอยู่แล้ว ซึ่งหากไม่ตรวจสอบ จุดนี้จะปรากฏเป็น agent ที่เพิกเฉยต่อกฎระเบียบของคุณอย่างเงียบๆ
ทักษะที่แชร์กันคือชุดคำสั่งที่ทำงานได้จริง
มีคุณสมบัติสองประการที่ทำให้สิ่งนี้เป็นจริง และทั้งสองประการมีความสำคัญเมื่อไฟล์มาจากทีมอื่น
ประการแรก SKILL.md สามารถรันคำสั่งเชลล์ก่อนที่โมเดลจะอ่านเนื้อหาใดๆ บรรทัดลักษณะนี้ในเนื้อหาคือการประมวลผลล่วงหน้า:
- Current branch: !`git rev-parse --abbrev-ref HEAD`คำสั่งจะทำงานบนเครื่องที่โหลดทักษะ และผลลัพธ์จะเข้ามาแทนที่ตัวยึดตำแหน่งในข้อความที่โมเดลได้รับ บล็อกที่เปิดด้วย backtick สามตัวตามด้วย ! จะรันคำสั่งหลายรายการในลักษณะเดียวกัน ไม่มีใครอนุมัติสิ่งเหล่านี้ในขณะรันไทม์ การอ่านทักษะที่แชร์กันจึงหมายถึงการอ่านคำสั่งที่ถูกแทนที่เหล่านั้นด้วย
ประการที่สอง frontmatter สามารถอนุมัติเครื่องมือล่วงหน้าได้ allowed-tools จะอนุญาตให้ใช้เครื่องมือที่ระบุโดยไม่ต้องแสดงข้อความขออนุญาตสำหรับการโต้ตอบที่เรียกใช้ทักษะนั้น สำหรับทักษะของโปรเจกต์ การอนุญาตจะมีผลเมื่อมีคนยอมรับกล่องโต้ตอบความเชื่อมั่นของ workspace สำหรับโฟลเดอร์นั้น เอกสารประกอบของ Claude Code ระบุผลลัพธ์ไว้อย่างชัดเจน: ให้ตรวจสอบทักษะของโปรเจกต์ก่อนที่จะเชื่อถือ repository เพราะทักษะสามารถอนุญาตให้ตัวเองเข้าถึงเครื่องมือในวงกว้างได้
ดังนั้น ให้จัดการการอัปเดตทักษะเหมือนกับการอัปเดต dependency ให้ระบุเวอร์ชันด้วย commit ที่แน่นอนทุกครั้งที่กลไกอนุญาต เพราะ tag สามารถถูกย้ายได้และ branch ก็มีการเปลี่ยนแปลงโดยนิยาม สำหรับเครื่องที่ถูกจำกัดสิทธิ์ "disableSkillShellExecution": true ในการตั้งค่าจะแทนที่การแทนที่คำสั่งทั้งหมดด้วยข้อความตัวอักษร [shell command execution disabled by policy] แทนที่จะรันคำสั่งนั้น และหากใช้ผ่านการตั้งค่าที่มีการจัดการ ผู้ใช้จะไม่สามารถยกเลิกได้ ทักษะที่มาพร้อมกับระบบหรือทักษะที่มีการจัดการจะได้รับการยกเว้นจากการตั้งค่านี้
ความระมัดระวังเดียวกันนี้ใช้กับสิ่งที่ทักษะอ่าน ทักษะที่รัน env หรือเปิดไฟล์ config จะดึงข้อมูลใดๆ ที่พบเข้าสู่บริบทของโมเดล ซึ่งเป็นความล้มเหลวที่ครอบคลุมอยู่ใน การเก็บความลับให้พ้นจากเอเจนต์ที่คุณรัน ทักษะที่ดึงหน้าเว็บหรือรัน query คือการเปิดเผยข้อมูลในลักษณะเดียวกันที่ชี้ออกไปภายนอก เนื่องจากข้อความที่ดึงมาจะปรากฏในบริบทเหมือนกับคำสั่งที่คุณเขียนไว้ทุกประการ ซึ่งเป็นขอบเขตที่ควรศึกษาข้อมูลก่อนที่คุณจะ ชี้เอเจนต์ไปยังอินสแตนซ์ SearXNG ของคุณเองเพื่อค้นหาเว็บ
สิ่งที่ควรตรวจสอบเมื่อมีการปรับเวอร์ชัน
- ผลต่าง (diff) ของเนื้อหา
SKILL.mdทุกส่วน เนื่องจากข้อความดังกล่าวคือคำสั่งที่เอเจนต์ของคุณจะปฏิบัติตาม - การแทนที่คำสั่ง (command substitution) ทุกรายการ เนื่องจากคำสั่งเหล่านี้จะทำงานบนเครื่องของคุณเมื่อโหลดทักษะ (skill) นั้น
- การเปลี่ยนแปลงใดๆ ใน
allowed-toolsเนื่องจากบรรทัดดังกล่าวเป็นการให้สิทธิ์การเข้าถึงเครื่องมือโดยไม่ต้องแจ้งเตือน - การทดสอบที่อยู่เบื้องหลังแท็ก (tag) หากที่เก็บข้อมูลส่วนกลางมีการรัน smoke test ใน CI แท็กที่คุณอ้างอิงควรมีสถานะการรันที่ผ่าน (green run)
ผู้ตรวจสอบที่ไม่สามารถอ่านผลต่างทั้งหมดได้ภายใน 10 นาที แสดงว่าทักษะดังกล่าวมีขนาดใหญ่เกินไป ควรแยกส่วนประกอบออก ข้อโต้แย้งเดียวกันนี้ใช้กับเอกสารในที่เก็บข้อมูลที่เอเจนต์ของคุณอ่าน: ให้เก็บกฎถาวรไว้ในไฟล์ที่อธิบายไว้ใน การแยกไฟล์ AGENTS.md และ HUMAN.md และเก็บเหตุผลเชิงสถาปัตยกรรมไว้ใน ไฟล์ DESIGN.md ที่เขียนสำหรับเอเจนต์ โดยให้ทักษะคงไว้เป็นขั้นตอนการทำงานที่เฉพาะเจาะจงเท่านั้น
เมื่อการเปลี่ยนแปลงของโมเดลหรือเครื่องมือทำให้ทักษะใช้งานไม่ได้
มีหลายสิ่งที่เปลี่ยนแปลงอยู่เบื้องหลังทักษะโดยไม่มีใครเข้าไปแก้ไข การอัปเกรดโมเดลส่งผลต่อความน่าเชื่อถือในการปฏิบัติตามคำสั่งที่ยาวเหยียด ดังนั้นทักษะที่เคยพึ่งพาความสามารถของโมเดลในการทำตามขั้นตอนที่ 9 อาจไม่สามารถทำได้อีกต่อไป เครื่องมือบรรทัดคำสั่งมีการเปลี่ยนชื่อ flag ทำให้เอเจนต์รันด้วย flag เก่า อ่านข้อผิดพลาดที่เกิดขึ้น แล้วพยายามแก้ไขปัญหาเฉพาะหน้า URL ที่อ้างอิงเริ่มส่งค่า 404 กลับมา หรือตัวควบคุมเอเจนต์ (agent harness) เปลี่ยนวิธีการเลือกทักษะ ทำให้ description ที่เคยถูกเลือกใช้งานกลับไม่ถูกเลือกอีกต่อไป
นี่คือเหตุผลที่การทดสอบแบบ smoke test มีความสำคัญอย่างยิ่งในโครงสร้างนี้ ให้รันการทดสอบของแต่ละทักษะตามกำหนดเวลาและทุกครั้งที่มีการ push โค้ด Google รันงานประเมินผลรายสัปดาห์กับคลังทักษะทั้งหมดด้วยเหตุผลนี้ และการตั้ง cron job รายสัปดาห์บน VPS ขนาดเล็กก็เพียงพอสำหรับทีมที่มีทักษะประมาณ 10 รายการ นี่เป็นวิธีเดียวที่คุณจะทราบถึงปัญหาที่เกิดขึ้นก่อนที่นักพัฒนาจะพบ
ความสามารถในการพกพา (portability) ก็มีส่วนช่วยเช่นกัน ข้อกำหนด Agent Skills จำกัดส่วน frontmatter ไว้ที่ 6 คีย์ ดังนั้นทักษะที่เขียนตามข้อกำหนดนั้นจะสามารถโหลดใช้งานในเครื่องมืออื่นนอกเหนือจากเครื่องมือที่คุณเขียนขึ้นมาเพื่อมันได้ ในขณะที่คีย์เฉพาะของตัวควบคุม (harness-specific key) ที่คุณเพิ่มเข้าไปนั้นเปรียบเสมือนการเดิมพันกับผู้ให้บริการรายใดรายหนึ่ง การเขียนทักษะให้รองรับการเปลี่ยนโมเดลเป็นทักษะเฉพาะทาง ซึ่งครอบคลุมอยู่ใน การทำให้ทักษะทำงานได้บนทุกโมเดล
FAQ
ฉันจะแชร์ทักษะของ agent หนึ่งรายการข้ามหลาย repository ได้อย่างไร
ให้เก็บทักษะไว้ใน git repository แยกต่างหาก ทำการ tag release ในนั้น และให้แต่ละโปรเจกต์ที่นำไปใช้ระบุอ้างอิงถึง tag แทนการคัดลอกไฟล์ วิธีการที่ใช้งานได้มีสองรูปแบบ: git submodule จะบันทึก commit ที่เจาะจงไว้ และการทำ symlink จาก .claude/skills/<name> เข้าไปยัง submodule จะทำให้มันโหลดเป็นทักษะปกติของโปรเจกต์ ส่วน plugin marketplace จะทำงานในลักษณะเดียวกันผ่าน /plugin โดยมีการระบุเวอร์ชันที่ต้องการไว้ใน .claude/settings.json ของ repository ที่นำไปใช้ ทั้งสองวิธีจะบันทึกเวอร์ชันไว้ในประวัติของ git ทำให้คุณสามารถตรวจสอบได้ว่าชุดคำสั่งใดที่ใช้ในการรัน agent ครั้งนั้นๆ
ฉันสามารถล็อกเวอร์ชัน (pin) ของทักษะ agent ให้เป็นเวอร์ชันที่เจาะจงได้หรือไม่
ไม่สามารถทำได้จากภายใน SKILL.md เนื่องจาก frontmatter ดังกล่าวไม่มีคีย์ version การล็อกเวอร์ชันต้องทำจากเลเยอร์ที่ครอบไฟล์นั้นอยู่ โดยธรรมชาติแล้ว git submodule จะล็อกที่ commit ที่เจาะจง สำหรับใน Claude Code plugin marketplace แหล่งที่มาของ plugin จะรองรับ ref สำหรับ branch หรือ tag และ sha สำหรับ commit ที่เจาะจง โดยที่ sha จะมีความสำคัญสูงสุดหากระบุไว้ทั้งคู่ ส่วนแหล่งที่มาของ marketplace เองจะรองรับเฉพาะ ref เท่านั้น ควรเลือกใช้การล็อกที่ commit เพราะ tag สามารถถูกย้ายได้หลังจากที่คุณตรวจสอบไปแล้ว
การทดสอบ smoke test ของทักษะควรตรวจสอบอะไรบ้าง
ให้ตรวจสอบสิ่งที่เสถียร ให้รันการทดสอบทักษะแบบ non-interactive กับ fixture ที่มีข้อผิดพลาดที่ทราบแน่ชัด จากนั้นตรวจสอบว่ามีตัวระบุที่เฉพาะเจาะจงปรากฏในผลลัพธ์หรือไม่ เช่น rule id ที่ทักษะควรจะรายงานออกมา การร้องขอผลลัพธ์แบบ structured output ด้วย --output-format json และ --json-schema จะช่วยให้การตรวจสอบแม่นยำ และ jq -e จะทำให้สคริปต์ล้มเหลวหากไม่พบค่าดังกล่าว ห้ามตรวจสอบจากประโยคเต็ม เพราะโมเดลอาจเรียบเรียงคำตอบใหม่ในแต่ละครั้งที่รัน
การติดตั้งทักษะที่แชร์มาจาก repository ของทีมอื่นมีความปลอดภัยหรือไม่
ให้ถือว่าทักษะดังกล่าวเป็น code dependency เนื่องจากมันคือชุดคำสั่งที่สามารถรันได้ SKILL.md สามารถรัน shell command ในขณะโหลดผ่านรูปแบบ command substitution ของ ! และฟิลด์ allowed-tools ใน frontmatter สามารถอนุมัติเครื่องมือล่วงหน้าโดยไม่ต้องรอการยืนยันจากผู้ใช้ ให้ตรวจสอบ diff ทุกครั้งที่มีการอัปเดตเวอร์ชัน ล็อกไว้ที่ commit ที่เจาะจงแทนการใช้ branch และเลือกใช้แหล่งที่มาที่ทีมของคุณควบคุมเอง สำหรับเครื่องที่ถูกจัดการอยู่ การตั้งค่า "disableSkillShellExecution": true จะช่วยหยุดการทำงานของ command substitution ทั้งหมด
ทักษะที่แชร์จะทำงานใน agent อื่นที่ไม่ใช่ Claude Code ได้หรือไม่
ขึ้นอยู่กับว่าคุณใช้ frontmatter ใด ข้อกำหนด Agent Skills กำหนดคีย์ไว้ 6 รายการ ได้แก่ name, description, license, compatibility, metadata และ allowed-tools ทักษะที่จำกัดอยู่เพียงคีย์เหล่านี้จะสามารถโหลดข้ามเครื่องมือที่รองรับข้อกำหนดนี้ได้ และยังสามารถโหลดใน Claude Code ได้โดยไม่ต้องแก้ไข คีย์เฉพาะของแต่ละระบบและฟีเจอร์ในส่วนเนื้อหาที่นอกเหนือจากข้อกำหนดจะถูกละเว้นหรือปฏิเสธการทำงานในระบบอื่น ดังนั้นควรหลีกเลี่ยงการใช้สิ่งเหล่านี้ในทักษะที่คุณต้องการแชร์ในวงกว้าง