Tulis CLAUDE.md seperti konstitusi: larangan, aturan perilaku, keputusan default. 92 commits dalam 5 hari tanpa melenceng.
Dalam 5 hari saya mengirim 92 commit dan menempatkan sebuah produk ke produksi (github.com/defi-io/smarts). Tidak ada bencana, tidak ada rollback, tidak ada refactor besar. Bukan karena Claude jenius. Karena CLAUDE.md 565 baris yang ada di akar proyek.
Tulisan ini tentang cara menulis CLAUDE.md yang berfungsi sebagai konstitusi, dan apa yang terjadi setelahnya.
Banyak orang menulis CLAUDE.md mirip README — apa proyek ini, cara menjalankannya. Itu pemborosan.
README untuk manusia. CLAUDE.md untuk Claude. Claude memuatnya otomatis di awal setiap sesi. Artinya setiap baris yang Anda tulis di sana menjadi prasyarat bagi setiap keputusan yang Claude ambil setelahnya.
Tulis gaya README, hasilnya: Claude tahu kira-kira proyeknya apa, tahu cara menjalankan tes, tapi setiap keputusan teknis dimulai dari nol.
Tulis gaya konstitusi, hasilnya: Claude tahu jalan mana yang tertutup, konvensi mana yang wajib, ke arah mana harus default di setiap percabangan, dan kapan harus berhenti dan bertanya.
Bedanya: yang pertama akan "sekalian" memasukkan dependensi baru, menambah lapisan abstraksi, mengubah Gemfile. Yang kedua tidak.
Proyek yang sedang saya bangun bernama smarts.md — platform yang menghasilkan live docs dan server MCP untuk smart contract. CLAUDE.md-nya 565 baris, terbagi seperti ini:
1. Identitas proyek (5 baris)
2. Inti produk (definisi satu baris + perbedaan struktural vs kompetitor)
3. Tech stack (kendala keras, format YAML)
4. Daftar larangan (item ❌ eksplisit)
5. Cakupan (batas keras MVP)
6. Arsitektur (dengan diagram ASCII)
7. Struktur direktori (tanggung jawab per file)
8. Konvensi koding Ruby (dengan snippet do/don't)
9. Strategi cache (sebagai tabel)
10. Persyaratan testing
11. Detail deployment
12. Alur Git
13. Aturan penggunaan Claude Code (instruksi perilaku)
14. Milestone 90 hari
15. Prinsip inti
Tidak ada bagian yang sekadar dekorasi. Di bawah saya pilih beberapa dan jelaskan kenapa ditulis seperti itu.
Punya saya kira-kira begini:
❌ Tanpa servis TypeScript / Node.js
❌ Tanpa ethers.js / web3.js
❌ Tanpa Sidekiq (pakai Solid Queue)
❌ Tanpa React / Vue / Svelte (pakai Hotwire)
❌ Tanpa Redis (Solid Cache / Solid Queue / Solid Cable menutupi semua)
❌ Tanpa kontrak tidak terverifikasi (hanya yang terverifikasi Etherscan)
❌ Tanpa Solana / Bitcoin / Move (hanya EVM)
Ini proyek Web3. Default dunia Web3 adalah TypeScript + ethers.js + Redis + React. Saya melawan arus itu. Saya punya alasan sendiri, tapi Claude tidak tahu alasan itu. Tanpa daftar larangan, Claude akan memberi rekomendasi berdasarkan "sense umum industri" yang terpendam di data latihnya — dan hampir pasti itu adalah jalur TypeScript.
Dengan daftar larangan, Claude berhenti bertanya "tambah servis Node untuk menjalankan web3.js?". Jalan itu tertutup secara default.
Kuncinya: setiap entri harus eksplisit dan mutlak. Jangan tulis "usahakan tidak pakai TypeScript". Tulis "tanpa TypeScript". Yang kabur akan dibaca Claude sebagai bisa dinegosiasi.
Blok besar terakhir di CLAUDE.md adalah "Aturan penggunaan Claude Code":
### Saat saya bilang "mulai kerjakan X"
1. Cek dulu apakah kendala CLAUDE.md mengizinkan pendekatan ini
2. Cek apakah sudah ada implementasi terkait di kode (jangan ulangi roda)
3. Sebelum menulis kode, buat branch baru
4. Setelah implementasi selesai, jalankan tes
5. Jangan auto-commit — kalau kode sudah ditulis dan tes hijau, berhenti
dan laporkan. Tunggu sampai saya bilang "commit" secara eksplisit
### Saat saya bilang "saya punya ide"
Jangan langsung menulis kode. Pertama:
1. Konfirmasi pemahaman (parafrasekan kembali)
2. Evaluasi terhadap kendala CLAUDE.md
3. Tunjukkan masalah potensial atau alternatif yang lebih baik
4. Tunggu konfirmasi saya sebelum bertindak
### Saat menemui percabangan teknis
Saat CLAUDE.md tidak menentukan:
1. Default ke opsi yang lebih "Rails-native"
2. Default ke opsi dengan dependensi lebih sedikit
3. Default ke opsi yang membuat solo dev iterasi lebih cepat
4. Kalau ragu, berhenti dan tanya
Bagian ini sepuluh kali lebih penting daripada "pakai snake_case".
Gaya kode bisa dipelajari Claude dengan membaca kode. Tapi "kapan harus berhenti dan bertanya", "saat mendengar 'saya punya ide', parafrasekan dulu alih-alih langsung menulis kode" — ini pola perilaku. Kode saja tidak mengajarkan itu.
Baris paling penting: ke arah mana default di percabangan. Aturan tunggal itu menentukan apa yang Claude lakukan saat Anda tidak di ruangan (saat Anda hanya bilang "mulai kerjakan X" lalu pergi). Tuliskan ini dengan jelas dan Anda berani melepasnya bekerja tanpa pengawasan.
Bagian atas CLAUDE.md saya berbunyi:
Dokumen ini adalah "sumber utama" proyek. Dimuat otomatis di awal setiap sesi Claude Code. Saat mengubah keputusan teknis, ubah ini lebih dulu; kode menyusul.
Ini kontrak alur kerja. Saat saya memutuskan mengganti suatu pilihan teknis — misalnya menaikkan model AI utama dari gpt-5-mini ke gpt-5 — langkah pertama bukan menyentuh initializer. Langkah pertama adalah mengubah bagian ini di CLAUDE.md:
ai:
fast: gpt-5-mini # sebelum
fast: gpt-5 # sesudah
Setelah itu saya biarkan Claude membaca ulang CLAUDE.md dan menyamakan kode.
Kenapa? Karena kalau Anda mengubah nilai di kode tapi CLAUDE.md tertinggal, di sesi berikutnya Claude membaca CLAUDE.md melihat nilai lama dan "berbaik hati" mengembalikan kode Anda. Akar konfliknya adalah satu titik kegagalan — CLAUDE.md tertinggal. Konstitusi yang tertinggal dari realitas adalah awal dari perang saudara.
Memperlakukan CLAUDE.md sebagai konstitusi berarti: ia selalu berlari di depan kode.
smarts.md, 5 hari, 92 commit:
Umur rata-rata PR: 30 menit. Tanpa refactor besar. Tanpa "tunggu, arah itu salah, rollback".
Bukan karena Claude ajaib. Karena setiap sesinya berlari di atas rel sepanjang 565 baris. Ia tahu tidak boleh menarik TypeScript, tahu Solid Queue adalah antrian default, tahu fungsi view di-cache 60 detik, tahu setiap service harus mengimplementasikan metode kelas call, tahu harus menunggu konfirmasi saya sebelum commit.
Cabut setengah dari kendala-kendala itu, hasilnya: 30 menit setiap hari menjelaskan "kenapa kita tidak pakai X", 5 menit me-review dependensi yang dia tarik "sekalian", dan Gemfile yang perlahan runtuh.
Jangan mulai dari berkas kosong. Mulai dari keputusan paling baru yang menyakitkan.
Kalau akhir-akhir ini Claude "selalu menarik dependensi baru", tulis daftar larangan.
Kalau "ganti arsitektur sembarangan", tulis diagram arsitektur + "tambah microservice, ganti DB, dll. butuh konfirmasi".
Kalau "tidak menulis tes", tulis "yang wajib di-unit-test".
Kalau "commit terlalu agresif", tulis "tanpa auto-commit, tunggu instruksi eksplisit".
Setiap rasa sakit, satu entri. Selain itu, jangan ditulis dulu.
Tiga bulan kemudian Anda akan punya CLAUDE.md 500 baris di mana setiap baris dilatari oleh "saya tidak ingin dia melakukan ini lagi" yang konkret. Dokumen itu mengalahkan template apa pun, karena dikalibrasi tepat ke proyek Anda, alur kerja Anda, tim Anda (sekalipun cuma Anda sendiri).
Konstitusi tidak ditulis sekali jadi. Ia mengkristal dari konflik konkret, satu per satu.
Sumber: github.com/defi-io/smarts