Onboarding AI Coding Agent ke Codebase yang Asing

Foto oleh Роман Рябенко via Wikimedia Commons (CC0)
Mulai dari perimeter, bukan dari arsitektur: entry point, command build dan test yang benar-benar jalan, konfigurasi datang dari mana, dan sistem luar apa saja yang diajak bicara. Jalankan setiap command yang diklaim proyek itu di clone yang bersih dan catat errornya persis apa adanya, karena error itulah catatan yang berharga. Setelah itu tulis temuannya ke instruction file yang di-commit seperti CLAUDE.md atau AGENTS.md supaya session berikutnya tidak perlu menurunkannya ulang.
Karena ia terbaca berwibawa sehingga langsung dipercaya. ARCHITECTURE.md hasil generate yang rapi akan di-commit, dianggap kebenaran oleh semua orang yang bergabung setelah kalian, dan lolos review karena memeriksanya dengan benar berarti mengulang seluruh eksplorasi awal. Kalau kalian tidak sanggup melakukan verification pass, membiarkan file itu kosong justru lebih jujur.
Minta ringkasannya sebagai daftar klaim, satu per baris, masing-masing membawa path file dan nomor baris yang membuktikannya. Buka sendiri setiap baris yang dikutip, atau serahkan daftarnya ke session kedua yang belum pernah melihat session pertama. Hapus klaim yang sitasinya tidak mengatakan apa yang diklaim, jangan diperhalus jadi tampaknya, karena kalimat salah yang dihaluskan tetap lolos review.
Ada empat kegagalan yang berulang: dead code digambarkan masih hidup, jalur yang sudah deprecated disebut sebagai jalur saat ini, default konfigurasi dilaporkan sebagai nilai yang sedang berjalan, dan module yang diam-diam dihindari semua orang. Sebabnya satu, yaitu agent membaca source sementara source bukan deployment. History git dan environment yang sedang jalan menyelesaikan keempatnya.
Keduanya bisa, dan pilihannya bergantung pada berapa banyak tool yang perlu membacanya. CLAUDE.md adalah file yang dimuat Claude Code saat startup dan yang dihasilkan command /init dari penelusuran codebase. AGENTS.md adalah Markdown biasa tanpa field wajib yang dibaca banyak coding agent, dan situsnya sendiri menyebut lebih dari 60.000 proyek open-source memakainya. Apa pun yang kalian pilih, tulis instruksi, bukan deskripsi.

Foto oleh Роман Рябенко via Wikimedia Commons (CC0)
Ringkasan Utama
Onboarding AI coding agent ke codebase yang asing baru berhasil kalau kalian memetakan perimeter lebih dulu — entry point, command build dan test yang benar-benar jalan, konfigurasi, batas ke sistem lain — lalu menulis temuannya ke instruction file yang di-commit, dan menghapus setiap klaim yang tidak bisa ditelusuri ke satu file dan satu baris.
Repository itu sampai ke saya cuma berupa URL Bitbucket dan satu pesan yang bilang sekarang ia jadi tanggung jawab saya. Ia jalan di production dan menagih customer betulan. README-nya berisi satu perintah clone, satu screenshot UI yang sudah tidak ada, dan bagian setup yang menyebut database engine yang sudah lama ditinggalkan service itu. Semua orang yang menulisnya sudah keluar.
Ini prosedur yang saya pakai untuk satu jam pertama dengan codebase yang tidak ditulis siapa pun di tim saya, dijalankan bersama coding agent alih-alih dengan membaca file satu per satu urut abjad. Sengaja tidak keren. Contohnya memakai Claude Code karena itu yang saya pakai, dan perilaku yang terdokumentasi saya kutip, tapi metodenya tidak bergantung pada tool tertentu. Bagian yang menopang semuanya adalah verification pass di akhir, dan itu bagian yang hampir tidak pernah dikerjakan orang.
Minta agent memahami codebase, dan yang kalian terima adalah ringkasan arsitektur. Itu output paling mahal yang bisa ia hasilkan sekaligus paling sulit kalian periksa. Habiskan satu jam pertama untuk perimeter saja: di mana proses dimulai, command apa yang diklaim proyek ini punya, konfigurasi datang dari mana, dan sistem lain apa yang ia ajak bicara. Keempatnya bisa dijawab dari manifest, import, dan nama file, jadi murah dibuat dan — ini yang lebih penting — murah dipatahkan.
# The perimeter, in the order I ask for it. Every answer is a path or a
# command, never a paragraph.
# 1. Is this repository alive, and where is the work actually happening?
git log -1 --format='%as %an %s'
git log --since='6 months ago' --name-only --pretty=format: \
| grep -v '^$' | sort | uniq -c | sort -rn | head -20
# 2. What commands does the project CLAIM to have? Claims, not facts.
jq '.scripts' package.json
ls Makefile Dockerfile docker-compose.yml .github/workflows/ 2>/dev/null
# 3. Where does configuration come from?
rg -o 'process\.env\.[A-Z0-9_]+' --no-heading | sort -u | head -40
ls .env.example .env.sample config/ 2>/dev/null
# 4. Which other systems does it touch?
rg -o 'https?://[a-z0-9.-]+' --glob '!*.lock' --no-heading \
| sort | uniq -c | sort -rn | head -20Pekerjaan perimeter punya sifat yang tidak dimiliki pekerjaan arsitektur: ia gagal dengan suara keras. Sebuah command build entah jalan atau mencetak error yang bisa langsung kalian tempel ke catatan. Satu paragraf soal layering tidak pernah salah dengan suara keras — ia salah diam-diam, enam minggu kemudian, di dalam keputusan orang lain. Mulai dari tempat yang feedback-nya langsung, dan satu jam itu terpakai untuk mengumpulkan fakta, bukan kalimat.
Blok scripts di package.json adalah dokumen sejarah. Di service yang saya warisi, sebagian script menyebut test runner yang sudah tidak ada lagi di dependencies, dan script dev-nya mengikat ke port yang sudah tidak di-publish oleh file Compose. Agent yang membaca file itu akan melaporkan semua script tersebut sebagai command proyek ini, karena memang begitu isi file-nya, dan ia tidak punya cara untuk tahu bahwa file itu kalah berdebat dengan kenyataan dua refactor yang lalu.
# Run every claimed command once, on a clean clone. The failure text is the
# note worth keeping — it is what the next person would otherwise rediscover.
$ npm ci
npm error notarget No matching version found for @internal/billing-orm
# -> private registry. Needs .npmrc with the internal token. Not in the README.
$ npm run test
> jest --runInBand
sh: jest: command not found
# -> the script is stale. Tests actually run under vitest, see vitest.config.ts
$ npm run dev
Server listening on 4000
# -> works, but only after: docker compose up db redis
# Without them it exits 0 and logs nothing, which reads like success.Jadi langkah kedua adalah eksekusi, bukan pembacaan. Minta agent menyusun daftar command-nya, lalu jalankan satu per satu di clone yang bersih, di sandbox yang kalian rela kehilangan, dan simpan output-nya. Yang kalian catat bukan npm test. Yang kalian catat adalah npm test beserta error persis yang ia cetak di clone bersih, karena error itulah catatan onboarding yang kalau tidak ditulis akan ditemukan ulang oleh tiap orang di tim, satu per satu.
Command /init di Claude Code menulis CLAUDE.md awal dengan menelusuri codebase untuk mencari build command, instruksi test, dan konvensi proyek, dan dengan CLAUDE_CODE_NEW_INIT=1 ia menjalankan alur interaktif yang menelusuri lewat subagent, mengajukan pertanyaan lanjutan, lalu menyodorkan proposal yang bisa kalian review. Keduanya tetap draft. Alur itu juga menarik rule peninggalan tool lain, di .cursor/rules, AGENTS.md, dan .windsurf/rules, dan isinya bisa sama basinya dengan README yang baru saja kalian berhenti percayai.
Onboarding menghasilkan artefak atau tidak menghasilkan apa-apa. Jendela chat ditutup di akhir hari, session berikutnya mulai dari nol, dan kalian membayar biaya eksplorasi yang sama untuk jawaban yang sedikit berbeda. Taruh temuannya di file yang dimuat agent saat startup: CLAUDE.md untuk Claude Code, atau AGENTS.md kalau kalian mau satu file yang dibaca banyak tool — formatnya Markdown biasa tanpa field wajib, dan situsnya sendiri menyebut lebih dari 60.000 proyek open-source kini memakainya.
# CLAUDE.md — written after the first hour, not before it.
# Instructions, not description. Every line names what proves it.
## Commands that actually run
- Install: npm ci (needs .npmrc with the internal registry token)
- Test: npx vitest run (the "test" script still calls jest; it is stale)
- Dev: docker compose up db redis, then npm run dev
## Entry points
- HTTP: src/server.ts -> src/routes/index.ts (one router per domain)
- Scheduled: src/jobs/cron.ts, registered at src/server.ts:41
- CLI: bin/reconcile.ts, run by hand at month end
## Boundaries
- Postgres via Knex. Migrations in db/migrations — never edit a merged one.
- Outbound: partner billing API, base URL from BILLING_BASE_URL. No retries.
## Unverified — do not trust
- src/legacy-invoicing/ appears unreachable from any entry point.
Last commit 2024-11. Confirm against the running service before deleting.Tulis instruksi, bukan deskripsi. Bahwa package API memakai Knex adalah fakta yang bisa ditemukan ulang agent dalam sepuluh detik. Bahwa migration yang sudah merge tidak boleh diedit dan harus diganti migration baru adalah aturan yang tidak bisa ia turunkan dari file mana pun — dan kalimat itulah yang layak di-commit. Panduan large codebase milik Claude Code sendiri memakai pasangan contoh persis seperti itu untuk instruction file per package, dan itu kalibrasi yang berguna soal apa yang pantas masuk ke sana.
Ini langkah yang menentukan apakah satu jam tadi ada gunanya. Di Stack Overflow Developer Survey 2025, 66% responden menyebut jawaban yang hampir benar tapi tidak benar-benar benar sebagai frustrasi terbesar mereka dengan tool AI, dan 45% bilang debugging kode hasil AI justru makan waktu lebih lama dari perkiraan. Ringkasan arsitektur adalah bentuk paling murni dari kategori itu: tidak ada isinya yang bisa dicek sekilas, dan salahnya muncul sebagai keputusan keliru berminggu-minggu kemudian, bukan sebagai test yang gagal hari ini.
Disiplin ini bekerja karena ada asimetri: path file dan nomor baris bisa dipatahkan dalam hitungan detik, sedangkan satu paragraf tidak bisa dipatahkan sama sekali. Ia juga mengubah apa yang ditulis. Ketika diminta klaim beserta sitasi, agent menghasilkan klaim yang jauh lebih sedikit, dan yang berhenti ia hasilkan justru yang dukungannya paling tipis — itu penyaringan yang kalian inginkan, terjadi saat generasi, bukan saat review.
Hasil terburuk dari satu session onboarding adalah ARCHITECTURE.md yang rapi dan percaya diri tapi tidak pernah diperiksa siapa pun. Ia di-commit, tiga orang berikutnya yang bergabung membacanya sebagai kebenaran, dan ia lolos setiap review karena memeriksanya dengan benar berarti mengulang seluruh pekerjaan awal. Ringkasan arsitektur yang tidak diverifikasi lebih buruk daripada tidak ada ringkasan sama sekali. Kalau kalian tidak sanggup melakukan verification pass-nya, jangan buat ringkasannya — file kosong itu jujur.

Ringkasan buatan agent cenderung menggambarkan cita-cita sebuah codebase, bukan apa yang benar-benar jalan di dalamnya. Abstraksinya disebut, layering-nya dijelaskan, dan penjelasan itu akan akurat andai setiap module bisa dijangkau dan setiap cabang kode pernah diambil. Ini lima pertanyaan yang saya pakai untuk tahu apakah petanya cocok dengan medannya, dan semuanya harus dijawab dengan path, bukan prosa.
Pertanyaan pertama saja biasanya sudah cukup. Ringkasan yang percaya diri bicara soal middleware, controller, dan service secara abstrak akan, ketika didesak menyebut file berurutan, entah memberi rantai yang bisa kalian ikuti atau menutupi lubang dengan frasa seperti request kemudian ditangani oleh service layer. Lubang itulah temuannya, dan ia selalu ada di bagian yang tidak pernah didokumentasikan siapa pun.
Empat kegagalan cukup sering berulang sampai sekarang saya memeriksanya satu per satu sebelum percaya apa pun di sebuah ringkasan. Keempatnya punya satu sebab yang sama: agent membaca kode, dan kode bukan benda yang sama dengan deployment.
| Yang dikatakan ringkasan | Kenapa agent mempercayainya | Yang menyelesaikannya |
|---|---|---|
| Dead code digambarkan masih hidup | Module-nya ada, export-nya rapi, dan tulisannya lumayan, jadi terbaca seperti kode yang masih dipakai | Cari siapa yang masih mengimpornya, lalu lihat tanggal commit terakhir file itu |
| Jalur yang sudah deprecated disebut sebagai jalur saat ini | Kedua jalur sama-sama ada, dan yang lama biasanya punya lebih banyak kode, komentar, dan test | Telusuri dari entry point ke dalam, bukan membaca directory dari luar |
| Default konfigurasi dilaporkan sebagai nilai yang sedang berjalan | Default-nya ada di source, sedangkan override-nya ada di deployment yang tidak ikut di repository | Baca nilainya dari environment yang sedang jalan, bukan dari file yang mendeklarasikannya |
| Module yang diam-diam dihindari semua orang | Tidak ada apa pun di source yang menandai sebuah module sebagai dihindari, dan import-nya masih terlihat penting | Urutkan file berdasarkan seberapa sering ia berubah dalam enam bulan terakhir |
Yang keempat adalah kegagalan yang tidak akan muncul dari membaca sebanyak apa pun. Kebanyakan codebase tua punya satu module yang diam-diam disepakati semua orang untuk dihindari: kode baru memanggil langsung benda yang dibungkusnya, atau menulis ulang satu potong kecil yang dibutuhkan, dan tidak ada yang menghapusnya karena menghapusnya adalah proyek, bukan task. Source bilang module itu sentral. History bilang ia sudah ditinggalkan — dan ditinggalkan adalah fakta tentang manusia, tepat di lapisan yang tidak bisa dilihat pembacaan statis.
# History answers the question reading the source cannot: what do people
# actually touch? The live surface of a codebase is rarely its directory tree.
# Most-changed files in the last six months.
git log --since='6 months ago' --name-only --pretty=format: \
| grep -v '^$' | sort | uniq -c | sort -rn | head -25
# Is anything still importing the module that reads as central?
rg -l 'legacy-invoicing' --glob '!node_modules' --glob '!*.lock'
# When was it last touched at all, and by whom?
git log -1 --format='%as %an' -- src/legacy-invoicing/index.ts
# And the one that ends the argument: is the config default the running value?
kubectl exec deploy/billing-svc -- printenv BILLING_TIMEOUT_MS
Semua di atas menghasilkan peta: di mana segala sesuatu berada, command mana yang jalan, apa bicara dengan apa. Ia tidak memberi tahu mana di antara semua itu yang menopang beban. Module yang paling perlu kalian hati-hati bukan module yang bisa dikenali dari import-nya — ia module yang perubahan kecilnya, yang jelas-jelas aman, memunculkan tiket support tiga hari kemudian, dan tidak ada bacaan jenis apa pun yang bisa menemukannya.
Studi METR 2025 adalah rem yang selalu saya ingat di titik ini. Enam belas maintainer open-source berpengalaman yang mengerjakan 246 issue di repository yang sudah mereka kenal ternyata 19% lebih lambat memakai tool AI, padahal mereka memperkirakan akan 24% lebih cepat dan bahkan sesudahnya masih yakin mereka 20% lebih cepat. Situasinya kebalikan dari tulisan ini — mereka hafal kodenya — tapi jarak antara kecepatan yang terasa dan kecepatan yang terukur persis alasan saya menulis artefaknya dan memverifikasinya, bukan memercayai kesan bahwa satu jam tadi berjalan mulus.
Jadi batas jujurnya begini: petanya layak dimiliki di hari pertama, dan ia bukan pemahaman. Pemahaman datang lewat satu jalan saja, yaitu mengubah sesuatu yang kecil, mengirimkannya, lalu melihat apa yang patah. Yang dibeli artefak onboarding adalah versi eksperimen itu yang lebih murah dan lebih aman, karena kalian sudah tahu cara menjalankan test-nya dan di mana batas-batasnya sebelum menyentuh apa pun.
Aturan yang saya bawa sekarang pendek saja. Satu jam pertama dengan repository asing menghasilkan file yang di-commit, bukan percakapan; setiap baris di file itu menyebut kode yang membuktikannya; dan apa pun yang tidak terbukti duduk di bawah judul yang mengatakan demikian. Siapa pun yang bercerita bahwa agent-nya memahami codebase yang belum pernah ia deploy sedang menggambarkan sebuah pembacaan, bukan pemahaman.
Sumber dan bacaan lanjutan