CLAUDE.md טוב אינו README — הוא לוכד את האינוריאנטים ש-Claude לא יסיק מהקוד. 6 לכתוב, 4 לוותר, 5 שאלות.
בפרויקט Pickful שלי יש מערכת חבר מושבעים קהילתית מבוזרת, תשלומי קריפטו x402, Sign-In with Ethereum, מסד נתונים מרובה, פוש בזמן אמת — הכל סטאקים שצצו בשנה-שנתיים האחרונות. Claude מספק את הפיצ'רים האלה מהר ובניקיון.
אבל תפתחו את ה-CLAUDE.md של הפרויקט ותבחינו: מערכת חבר המושבעים ו-x402 — המילים האלה לא מופיעות אפילו פעם אחת.
זה לא שכחה. תפקיד ה-CLAUDE.md מעולם לא היה "לתאר פיצ'רים". תפקידו הוא ללכוד את אותם דברים ש-Claude לעולם לא יסיק רק מקריאת הקוד.
מי שכותב CLAUDE.md בפעם הראשונה נוטה להתייחס אליו כמו ל-README — לתאר כל פיצ'ר מרכזי:
תוכן כזה Claude פותח את topic_review_service.rb / x402.rb / like_points_service.rb וקורא בדיוק רב יותר ממה שתכתבו. אלף מילים של תיאור לוגיקה עסקית עולות ל-Claude כמה מאות tokens לקרוא ישירות מהקוד — ובלי סטייה פרשנית. קוד הוא עובדה. תיאורים הם מידע יד-שנייה.
מה שבאמת מפיל את Claude הן 6 הקטגוריות הבאות.
ה-CLAUDE.md של Pickful מכיל שורות כאלה:
Propshaft (not Sprockets)
ImportMap (no JavaScript bundler)
Hotwire: Turbo Frames, Turbo Streams, Stimulus
Lexxy gem overrides ActionText:
config.lexxy.override_action_text_defaults = false
כל שורה מתנגדת לניחוש ברירת המחדל. כשרואה פרויקט Rails, ההנחות של Claude כברירת מחדל הן:
בלי השורות האלה ב-CLAUDE.md, בקשו מ-Claude להוסיף פיצ'ר JS חדש: סיכוי גבוה שיתקין Webpacker, יערוך package.json, יכתוב config של bundler — הכל שגוי, ושגוי בשקט (האפליקציה רצה, אבל pipeline הנכסים מזוהם).
השורות האלה ב-CLAUDE.md אומרות ל-Claude: אל תנחש, כבר הוחלט.
PostgreSQL with 4 separate databases:
- primary - Main application data
- cache - Solid Cache storage
- queue - Solid Queue jobs
- cable - Action Cable subscriptions
ניסוח פשוט, אבל יכול לחסוך לילה שלם. Multi-DB כברירת מחדל ב-Rails 8 היא התנהגות חדשה — Claude לא יבדוק מיוזמתו כמה DBs אתם משתמשים. מיגרציה תמימה למראה נוחתת ב-DB הלא נכון, ב-dev אין שגיאה (ארבעתם PostgreSQL, ה-schema מתבצע בכל מקום). אבל בפרודקשן טבלת ה-job של Solid Queue מסתננת לגיבוי של primary, או שמודל של primary שולח שאילתה ל-DB של cache — באגים שצצים אחרי ימים.
שתי שורות ב-CLAUDE.md נגד יום שלם של איתור באגים בפרודקשן.
/p-{slug} - Short post URLs (4-5 char alphanumeric)
/t-{slug} - Topic URLs (3-4 char alphanumeric)
/s-{code} - Short URL redirects (3-4 char alphanumeric)
/r-{referral} - Referral links
את הניתובים Claude רואה ב-routes.rb, אבל הסכמות האורך (4-5 תווים, 3-4 תווים) קבורות בלוגיקת יצירת ה-slug במודלים או בשירותים. בקשו מ-Claude סוג short link חדש — בסבירות גבוהה יפיק slug בן 6 תווים, בסגנון UUID או אך ורק ספרות — מחוץ לשפה הוויזואלית של המערכת.
המאפיין של "הסכמות" כאלה: הפרה לא מייצרת שגיאה, אבל קורא הקוד הבא ירגיש שמשהו לא מסתדר. חובה לכתוב.
VIP status at 400+ points
Posts with 15+ likes are "hot" posts
שני המספרים חיים איפשהו בקוד (User#vip?, scope Post#hot?). הבעיה: כש-Claude נוגע במשהו סמוך — מכוון תגמולי נקודות, מוסיף התראת "כמעט VIP", כותב cron שנועץ hot posts — הוא לא יישר את הספים באופן אוטומטי במקומות אחרים.
התוצאה: אתם מתגמלים משימה ב-500 נקודות אבל הטקסט אומר "אתה יכול להיות VIP" (400 מספיק); או שאתם מזינים seed data לפיצ'ר חדש עם מעט לייקים ולעולם לא חוצים את סף ה-15.
יכולות הקוד של Claude חזקות, אבל אין לו תחושה מספרית מערכתית. שימת הספים הקריטיים ב-CLAUDE.md גורמת לכל שיחה להתחיל עם הידיעה ש"400 ו-15 הם מספרים מיוחדים".
- Devise (authentication) + Pundit (authorization)
- Pundit policies in app/policies/
- Check UserPolicy, PostPolicy, etc. for permission rules
תפקידה של השורה הזו הוא ניווט, לא תיאור.
בלעדיה, כש-Claude צריך להוסיף בקרת הרשאה חדשה, שלוש אפשרויות:
unless current_user.admin? היישר בתוך ה-controllerauthorize? משלו במודלעם "Pundit policies in app/policies/" כתוב, Claude בכל פעם הולך היישר ל-app/policies/ להוסיף קובץ policy — סגנון אחיד.
שורה אחת חוסכת מ-Claude את "עבודת הבלש" בכל פעם.
Supported locales: en, zh-CN, zh-TW
Testing stack: RSpec + FactoryBot + Capybara + Shoulda Matchers
בהוספת פיצ'ר חדש, ברירות המחדל של Claude הן:
אבל הפרויקט שלכם זקוק בפועל ל:
הפרה של "אילוצים חיצוניים ברמת פרויקט" כאלה מייצרת ערמה של עבודת ניקוי בדיעבד — תרגומים להשלמה, בדיקות לשכתוב. כתיבה ב-CLAUDE.md מעגנת פעם ולתמיד את "הדברים שחייבים להתבצע בכל פעם".
חשוב באותה מידה כמו "חובה לכתוב" הוא "אל תכתוב". הקטגוריות הבאות — רואים = מוחקים:
1. תיאורי פיצ'רים
"מערכת חבר המושבעים: משתמשים יכולים לדווח על תוכן מפר, המדווח נכנס להצבעה ציבורית, חברי המושבעים נבחרים מ..."
→ Claude יפתח topic_review_service.rb ויקרא בדיוק רב יותר מכפי שכתבתם. לדחוף את זה לכל שיחה חדשה זה בזבוז טהור.
2. מה שנקרא מידית מעץ הספריות / Gemfile
"app/models/ מכיל מודלים של ActiveRecord", "משתמש ב-Rails 8", "DB הוא PostgreSQL"
→ Claude מעיף מבט בשורש הפרויקט וב-Gemfile — יודע.
3. ידע תכנות כללי
"Controllers should be thin, delegate to services", "הימנעו מ-N+1", "כתבו בדיקות לפיצ'רים העיקריים"
→ זה כבר בנתוני האימון של Claude. כתבו את זה רק אם הפרויקט שלכם חריג — לדוגמה "אנחנו בכוונה לא משתמשים בשכבת service; הלוגיקה חיה ב-controllers".
4. הקשר של המשימה הנוכחית
"כרגע אנחנו עושים refactor למערכת התשלומים; הדגש הוא..."
→ זה הקשר שיחה, לא עובדה של פרויקט. זריקה ל-CLAUDE.md מזהמת את כל השיחות האחרות.
שימו את ההוכחה "אני יכול לעשות את זה" לפני הדרשה. אחרי שכתבתי את הסעיף למעלה, העברתי את ה-CLAUDE.md של Pickful — 238 שורות — דרך 5 השאלות שלי. התוצאה: בערך חצי הוא בזבוז.
מה לחתוך (~120 שורות):
רוב בלוק פקודות הפיתוח (70 שורות → 10): bin/setup / bin/rails db:migrate / bundle exec rspec / bin/rubocop / bin/brakeman — כולן פקודות Rails סטנדרטיות, כבר בתוך אימון Claude. להשאיר רק שלוש הייחודיות לפרויקט: bin/jobs (worker של Solid Queue), bin/importmap pin (ייחודי ל-ImportMap), bin/kamal deploy.
רשימת Core Domain Models (35 שורות → למחוק לגמרי): לפרט 20 מודלים עם תפקידיהם זו דוגמה קלאסית ל-"CLAUDE.md בסגנון README" — Claude מריץ ls app/models/ או קורא קובץ מודל אחד ויודע. דחיפה לכל שיחה זה בזבוז טהור.
פריטים סטנדרטיים ב-Tech Stack (28 שורות → 8): Rails 8 / Devise / Pundit / Tailwind / pg_search — הכל קריא מיד מ-Gemfile. להשאיר רק את האנטי-אינטואיטיביים: Propshaft / ImportMap / Lexxy / x402-rails / Grover.
ידע תכנות כללי מפוזר: "Controllers should be thin", "Use app/jobs/ for async processing", מה בודקים request specs לעומת model specs — Claude עושה את זה כברירת מחדל. בזבוז tokens בלבד.
נשארות ~100 שורות: הסכמות ניתוב URL, חלוקת 4 DB, ספי VIP 400 / Hot 15, override של Lexxy, בחירות ארכיטקטורה אנטי-ברירת מחדל, שלט Pundit, רשימת locales, FactoryBot (לא fixtures).
אבל חשוב יותר: אילו invariants עדיין חסרים?
במהלך הביקורת הבנתי כמה פריטים שהייתי צריך להוסיף ולא הוספתי מעולם:
238 שורות לדחוס ל-100–120, להוסיף 5–10 שורות של invariants שפוספסו — זה קרוב יותר ל"צפיפות הנכונה" של CLAUDE.md.
זה לא טוטוריאל. זו ביקורת על הפרויקט שלי עצמי — וגם אני לא כתבתי נכון. הצורה הנכונה של CLAUDE.md היא למחוק ברציפות ולהוסיף ברציפות — כל פרויקט שמתבגר מעט אמור להיות בעל CLAUDE.md קצר יותר וצפוף יותר עם הזמן.
בכל פעם שאני רוצה להוסיף משהו ל-CLAUDE.md, אני מעביר אותו דרך ה-checklist הבא:
חוקים שעברו את כל ה-5 נשארים; אחד שלא עובר — מוחקים או משכתבים.
השימוש הנכון ב-CLAUDE.md אינו "להציג את הפרויקט", אלא לדחוס את הידע המובלע בינכם לבין ה-codebase, שאותו Claude לעולם לא ישלים מקריאת קוד — בחירות חריגות, ספים בלתי נראים, הסכמות נגד ברירות מחדל, אילוצים חיצוניים ברמת הפרויקט.
כל שורה שאתם מוסיפים צריכה לענות על שאלה: "האם זה משהו ש-Claude לא יקרא מהקוד?" לא יקרא — נשאר. יקרא — מוחקים.
CLAUDE.md כתוב כך הוא בדרך כלל יותר מחצי קצר מהטיוטה הראשונה, אבל ערכו לכל שיחה גדול לאין שיעור מאלפי מילים של תיאור פיצ'רים. והוא תמיד "עוד לא גמור" — כל פיצ'ר חדש ששולחים מאיר invariant נוסף שהיה אמור להיות בפנים, ופסקה נוספת שכעת אפשר לחתוך. למחוק ולהוסיף, למחוק ולהוסיף — זו התחזוקה היומית של CLAUDE.md.