Claude Code tiap hari tanpa drama: garis approval dan sandbox
Batas allow/ask/deny, kapan pakai plan/acceptEdits/auto, soal dangerously-skip-permissions, dan posisi sandbox dari sisi praktik.
“Toh dialog konfirmasi selalu muncul, jadi harusnya aman-aman saja.”
Waktu baru mulai pakai, saya berpikir begitu. Setiap kali Claude Code mau melakukan sesuatu, muncul konfirmasi. Saya baca, saya tekan OK. Rasanya saya sudah mengemudi dengan hati-hati.
Dua minggu kemudian saya menyadari sesuatu dan langsung pucat: jari saya menekan Enter secara refleks, tanpa membaca isi konfirmasinya. Begitu sebuah aksi jadi “alur biasa”, saya berhenti memeriksanya. git push, tulis ke API eksternal, semuanya saya loloskan tanpa lihat isinya. Tidak ada kecelakaan cuma karena saya beruntung.
Dialog approval bukan barang yang makin banyak makin aman. Terlalu banyak, orang berhenti membaca. Terlalu sedikit, aksi yang tidak bisa dibatalkan ikut lolos. Hari ini saya fokus ke “garis pemisah” ini, bukan ke detail file konfigurasi, tapi ke bagaimana memutuskannya setiap hari.
Poin penting
- Approval bukan soal “stop semua” atau “loloskan semua”. Sumbunya: kerja yang reversible dibuat cepat, kerja yang irreversible sengaja dibuat lambat. Garisnya ditarik dari bisa-tidaknya di-
undo. - Permission mode (
default/acceptEdits/plan/auto/dontAsk/bypassPermissions) diganti sesuai fase kerja. Eksplorasi pakaiplan, perbaikan sambil review pakaiacceptEdits. --dangerously-skip-permissions(aliasbypassPermissions) bukan untuk dipakai harian. Gantinya pakai modeautoatau sandbox.- Sandbox mempersempit “jangkauan” yang bisa disentuh Bash, di level OS. Jalan di macOS / Linux / WSL2, dan tidak jalan di Windows native.
- Di tim, “letak garis approval” jangan diserahkan ke semangat orang per orang. Kunci secara fisik lewat aturan deny dan hook.
Format penulisan file konfigurasinya sendiri saya bahas di artikel saudaranya, referensi pengaturan izin Claude Code, dan resep menggabungkan CLAUDE.md dengan izin ada di resep CLAUDE.md x izin. Artikel ini murni soal keputusan operasional “di mana harus berhenti”.
Tarik garis approval dari “bisa dibatalkan atau tidak”
Kalau ragu menarik garis, sebelum menimbang besar-kecilnya risiko teknis, tanyakan satu hal ini dulu pada diri sendiri.
“Ini, lima menit lagi masih bisa saya batalkan?”
Membaca file, grep, melihat diff, menjalankan npm run build. Berapa kali pun diulang masih bisa diulang. Paling buruk pun bisa kembali dengan git checkout. Karena itu saya ingin ini berputar cepat. Sebaliknya git push, deploy produksi, kirim email, tulis ke DB eksternal, begitu ditekan dunia di luar ikut berubah. Tidak bisa dibatalkan. Karena itu sengaja saya buat lambat.
Pembagian tiga tingkat yang sering saya pakai seperti ini.
| Aksi | Keputusan | Alasan |
|---|---|---|
| Baca, grep, diff, build, test, lint | allow | Reversible. Tidak mau memperlambatnya |
| Edit kode di branch | ask atau acceptEdits | Tergantung kematangan repo |
| push, deploy, publish, kirim email, tulis API eksternal | ask | Berdampak ke dunia luar. Tidak bisa dibatalkan |
Baca .env, rm -rf, git reset --hard, curl | sh | deny | Kerugiannya terlalu besar saat kena |
Yang paling bikin bingung di sini adalah “edit”. Edit itu tidak selalu berbahaya. Untuk repo pribadi yang test-nya lengkap, memutar edit dengan cepat pun tidak menakutkan. Yang justru menakutkan adalah membiarkan edit liar di repo yang dekat produksi dan test-nya lemah. Jadi tolok ukurnya bukan “boleh edit atau tidak”, melainkan setelah edit, diverifikasi dengan apa. Kalau perintah verifikasi sudah rapi, edit boleh dibuat cepat. Kalau belum rapi, biarkan tetap di ask.
Deny justru aman dipasang lebar-lebar “untuk jaga-jaga”. Baca .env dan perintah destruktif sebaiknya ditutup sejak awal, dengan asumsi hari untuk menaikkannya ke allow tidak akan pernah datang. Instruksi tipe “lewati permissions, secepat mungkin” seperti yang saya angkat di kumpulan prompt berbahaya adalah aksi yang sengaja merusak batas ini. Kalau sudah masuk deny, apa pun yang dikatakan dari sisi prompt, intinya tetap dihentikan oleh aplikasinya.
Ganti permission mode sesuai fase
Kalau allow/ask/deny adalah pengaturan “apa” yang dihentikan, maka permission mode adalah pilihan gigi “sekarang seberapa banyak yang dihentikan”. Dengan Shift+Tab kamu bisa berganti default -> acceptEdits -> plan. Dokumentasi resmi permission modes merangkum semua mode, tapi yang perlu diingat untuk operasi adalah pasangan berikut.
| Mode | Jangkauan yang jalan tanpa konfirmasi | Cocok untuk situasi ini |
|---|---|---|
default | Hanya baca | Repo pertama kali, kerja yang ingin pelan-pelan |
plan | Hanya baca (tidak edit, cuma menyusun rencana) | Ingin paham codebase dulu baru bergerak |
acceptEdits | Baca + edit di dalam folder kerja | Memperbaiki sambil review sendiri |
auto | Hampir semua (di belakang ada classifier cek keamanan) | Kerja panjang, ingin kurangi lelah konfirmasi |
dontAsk | Hanya yang sudah di-allow sebelumnya | CI atau skrip di lingkungan tertutup |
bypassPermissions | Semua (tanpa cek) | Hanya di dalam container/VM terisolasi |
Cara saya membaginya sederhana. Pintu masuk pekerjaan baru selalu plan. Suruh Claude membaca dulu, keluarkan rencana langkahnya, pastikan arahnya cocok, baru gerakkan. Setelah arah mantap, turunkan ke acceptEdits dan suruh edit sekaligus, lalu lihat hasilnya terkumpul lewat git diff. Daripada menyetujui baris demi baris, membaca semuanya sekaligus di akhir justru bikin saya lebih fokus membacanya. Ini soal menjadikan “pasti dilihat di akhir” sebagai mekanisme, sejalan dengan ide “letakkan penjaga gerbang pada mesin” yang saya tulis di harness engineering.
Satu catatan penting. Di mode mana pun selain bypassPermissions, tulis ke protected paths tidak akan disetujui otomatis. Tempat seperti .git, .claude, .bashrc, .npmrc, yang kalau rusak akan mematikan repo atau konfigurasinya sendiri. Walau kamu lagi enak mengedit dengan acceptEdits, khusus di sini konfirmasi tetap masuk. Anggap ini bukan gangguan, tapi jaring pengaman terakhir.
Selesaikan tanpa --dangerously-skip-permissions
Untuk menyelesaikan keluhan “konfirmasinya kebanyakan, ribet”, banyak orang menjangkau --dangerously-skip-permissions (alias mode bypassPermissions). Sesuai namanya, ini flag yang mematikan semua cek.
Kalau kamu pakai ini sebagai kebiasaan di dialog harian, itu bukan lagi “agent yang diawasi”. Cuma kebetulan belum kena celaka. Dokumentasi resmi pun menulis tegas mode ini “hanya di dalam container/VM terisolasi”, dan selain kasus terburuk seperti rm -rf / atau rm -rf ~, tidak ada prompt apa pun yang keluar. Pertahanan terhadap prompt injection juga nol.
Tapi perasaan “ribet” itu sendiri benar. Karena itu yang harus dibasmi adalah jumlah konfirmasi, bukan jaring pengamannya. Ada dua alternatif.
Pertama, mode auto. Ini menghapus konfirmasi, tapi model classifier lain mengawasi tiap aksi di belakang dan memblokir aksi berbahaya seperti curl | bash, deploy produksi, push langsung ke main, atau force push. Kalau di tengah percakapan kamu bilang “jangan push”, itu pun bekerja sebagai sinyal blokir sementara. Konfirmasi berkurang, tapi aksi berbahaya tetap berhenti. Beda dengan bypassPermissions. Hanya saja mode auto masih research preview, jadi bukan alat untuk melewati review aksi sensitif secara total, melainkan untuk dipakai pada “kerja yang arahnya bisa dipercaya”.
Kedua, sandbox. Saya jelaskan di bab berikutnya.
Kalau ingin mengurangi konfirmasi, mulai dari acceptEdits atau auto, kalau masih kurang baru sandbox. bypassPermissions cukup dianggap khusus container. Kalau berpikir dengan urutan ini, alasan untuk repot-repot melepas seluruh jaring pengaman jadi nyaris tidak ada.
Sandbox mengikat “jangkauan yang bisa disentuh” di level OS
Kalau approval adalah mekanisme yang menanyakan “boleh tidak melakukan aksi ini”, maka sandbox adalah mekanisme yang mempersempit jangkauan file dan jaringan yang bisa disentuh Bash itu sendiri, di level OS. Approval itu “cek sebelum eksekusi”, sandbox itu “tembok saat eksekusi”. Lapisannya berbeda.
Yang bikin ini ampuh adalah karena ia menambal kelemahan approval. Approval menilai dengan melihat string perintah, jadi tidak akan sadar kalau npm run build diam-diam melakukan hal di luar dugaan. Tapi dengan sandbox, perintah itu secara default cuma boleh menulis di dalam folder kerja. Walau ia tidak berperilaku sesuai namanya, OS menghentikannya secara fisik.
Jalankan /sandbox maka panel pengaturan terbuka dan kamu bisa memilih dua mode.
- auto-allow: di dalam sandbox, Bash dieksekusi tanpa konfirmasi (aman karena jangkauannya terkurung). Hanya aksi yang keluar dari jangkauan yang kembali ke approval biasa.
- regular permissions: bahkan di dalam sandbox, approval tetap keluar seperti biasa. Kontrolnya kuat tapi konfirmasinya banyak.
Artinya ini pas untuk orang yang “ingin kurangi konfirmasi, tapi takut kalau apa pun bisa dieksekusi”. Karena dijaga lewat jangkauan, kamu tidak perlu ditanya satu per satu.
Tapi ada batasan penting. Sandbox hanya jalan di macOS / Linux / WSL2, dan tidak jalan di Windows native. Pengguna Windows perlu menjalankan Claude Code di dalam WSL2. Kalau tidak bisa pakai WSL, atau memang pakai di Windows polos, jangan berharap pada sandbox, dan buat pembagian allow/ask/deny lebih ketat. Khususnya deploy, publish, dan urusan secret condongkan ke ask. Ini titik kompromi yang realistis di Windows.
Pengaturan sandbox bentuknya seperti ini. Hanya untuk tool yang butuh menulis di luar folder kerja (contoh: kubectl yang menyentuh ~/.kube), kita buka lubang secara eksplisit.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"sandbox": {
"enabled": true,
"failIfUnavailable": false,
"filesystem": {
"allowWrite": ["~/.kube", "/tmp/build"],
"denyRead": ["~/.aws", "~/.ssh"]
}
}
}
failIfUnavailable: false adalah pengaturan “kalau di lingkungan yang tidak punya sandbox, cukup keluarkan peringatan lalu jatuh ke eksekusi biasa”. Sebaliknya kalau di organisasi sandbox dijadikan wajib, set ke true supaya peluncurannya sendiri dihentikan. Yang diam-diam penting juga denyRead. Default sandbox itu bisa membaca hampir semua file, jadi secret seperti ~/.aws atau ~/.ssh lebih tenang kalau ditutup eksplisit.
Titik awal pengaturan untuk “operasi harian”
Kalau semua keputusan di atas dijadikan satu file, titik awal operasi harian cukup sebanyak ini. Makna detail formatnya (beda Bash(npm run build) dengan Bash(npm*) dan sebagainya) saya serahkan ke referensi pengaturan izin.
{
"$schema": "https://json.schemastore.org/claude-code-settings.json",
"permissions": {
"defaultMode": "plan",
"allow": [
"Read",
"Grep",
"Glob",
"Bash(npm run build)",
"Bash(npm run test)",
"Bash(npm run lint)"
],
"ask": [
"Bash(git push *)",
"Bash(npx wrangler pages deploy *)",
"Bash(node scripts/outreach-send-mails.mjs --send)",
"WebFetch(domain:api.gumroad.com)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Bash(rm -rf *)",
"Bash(git reset --hard *)",
"Bash(curl * | sh)"
]
},
"sandbox": {
"enabled": true,
"failIfUnavailable": false
}
}
Yang dilakukan cuma tiga. Baca dan verifikasi diputar cepat. Aksi yang berdampak ke luar pasti dihentikan. Yang jelas berbahaya dilarang sejak awal. defaultMode: "plan" saya pasang karena saya ingin memulai sesi baru dari “baca dulu lalu rencana”. Sisanya tinggal naik ke acceptEdits lewat Shift+Tab sambil bekerja.
Edit (Edit / Write) sengaja tidak saya tulis di allow maupun ask. Karena saya mau mengontrolnya dari sisi mode (acceptEdits). Kalau edit diikat di rule dan mode sekaligus, jadi tidak jelas mana yang berlaku. Bagi peran begini: edit lewat mode, efek samping eksternal lewat rule, kepala jadi lebih tertata.
Di tim, kunci “letak garis approval” secara fisik
Sampai sini cerita soal individu. Begitu jadi tim, muncul satu masalah lagi: garis pemisahnya jadi beda-beda tergantung orang. Ada yang hati-hati, ada juga yang mau memutar semua dengan bypassPermissions. Kalau bergantung pada semangat dan akal sehat, operasi orang yang paling longgar yang jadi garis efektif tim.
Karena itu, tempat yang ingin dihentikan jangan diserahkan ke penilaian orang, tapi dikunci secara fisik. Tiga contoh konkret.
1. Hentikan masuknya secret sebelum commit. Lewat hook PreToolUse, sebelum git add cek secara mesin apakah .env ter-stage. Sebelum orang sadar “wah, ini harusnya tidak ikut”, commit-nya sudah berhenti.
2. Paksa build sebelum deploy. Jangan percaya “rasanya build lokal sudah lewat”. Sebelum perintah deploy, lewat hook pasti jalankan npm run build.
3. Putar verifikasi otomatis setelah edit. Setelah Edit / Write, alirkan npm run test. Karena verifikasi jalan bahkan untuk perbaikan tipis, kamu tidak akan maju dalam keadaan rusak.
Konfigurasi minimalnya kira-kira sebanyak ini. Hook bukan makin banyak makin bagus; kira-kira satu hook penghenti dan satu hook verifikasi justru bikin operasi tidak mudah rusak.
{
"hooks": {
"PreToolUse": [
{
"matcher": "Bash(git add*)",
"hooks": [{
"type": "command",
"command": "git diff --cached --name-only | grep -E '^\\.env' && echo 'Blocked: .env staged' && exit 1 || exit 0"
}]
},
{
"matcher": "Bash(npx wrangler pages deploy*)",
"hooks": [{
"type": "command",
"command": "npm run build"
}]
}
],
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [{
"type": "command",
"command": "npm run test || true"
}]
}
]
}
}
Kalau di Windows, bagian grep tinggal diganti findstr atau skrip Node kecil, sudah jalan. Yang penting bukan perintahnya itu sendiri, tapi tiga bentuk ini: “berhenti sebelum commit / build sebelum deploy / verifikasi setelah edit”. Kalau mau mengikat di level organisasi, ada juga cara men-disable bypassPermissions lewat managed settings dan menjadikan sandbox wajib. Begitu ukurannya sebesar tim, merancang sekalian aturan operasinya lewat halaman konsultasi justru paling cepat.
Contoh kegagalan yang sering terjadi
Ketiganya benar-benar pernah dialami saya atau orang di sekitar saya.
Puas setelah menaruh semua di ask
Hari pertama kelihatan aman. Tapi seminggu kemudian kamu mulai menekan OK tanpa membaca isi konfirmasinya. Ini lebih bahaya daripada keadaan deny yang lemah. Karena yang tersisa cuma ilusi “merasa sudah memeriksa”. Sebelum menderetkan ask, mantapkan deny dulu.
--dangerously-skip-permissions jadi kebiasaan mulut
Sekali mencicipi “wah ini cepat”, susah balik. Tapi itu cuma melepas pengawasan. Kalau konfirmasi terasa ribet, pakai mode auto atau auto-allow sandbox. Tidak ada satu pun alasan untuk melepas seluruh jaring pengaman.
Salah mengira build sukses sama dengan release sukses
Ini sering muncul baik di operasi konten maupun development. Build lokal sudah lewat, tapi URL publik masih lama, satu bahasa belum ke-update, CTA berantakan di mobile. Approval dan sandbox tidak bisa mencegah kegagalan ini. Yang dibutuhkan adalah pemeriksaan setelah publish. Saya berkali-kali “merasa sudah merilis” gara-gara ini.
Pertanyaan umum
T. Mode auto dengan auto-allow sandbox, apa bedanya?
J. Cara menjaganya beda. Mode auto memakai model classifier untuk menilai “apakah aksi ini berbahaya” lalu memblokirnya. Auto-allow sandbox mengamankan dengan mengikat “jangkauan yang bisa disentuh” lewat OS, bukan isi aksinya. Yang pertama menjaga lewat penilaian, yang kedua menjaga lewat jangkauan. Keduanya bisa dikombinasikan.
T. Apakah sandbox bisa dipakai di Windows? J. Di Windows native tidak bisa. Kalau Claude Code dijalankan di dalam WSL2, baru bisa. Kalau pakai di Windows polos, jangan bergantung pada sandbox, condongkan deploy, publish, dan urusan secret ke ask, lalu buat deny lebih ketat.
T. Mode plan dengan mode acceptEdits, bagaimana cara membaginya?
J. plan itu “cuma baca, tidak edit”, untuk fase memahami codebase dan menyusun langkah. acceptEdits itu “loloskan edit di dalam folder kerja tanpa konfirmasi”, untuk fase memperbaiki sekaligus setelah arahnya mantap. Saya mulai dari plan, kalau sudah sepakat baru turun ke acceptEdits.
T. Kalau aksi yang sudah masuk deny ternyata benar-benar perlu dieksekusi sekali saja? J. Deny dipaksakan oleh aplikasi Claude Code, jadi tidak bisa dilonggarkan lewat prompt (justru itu nilai deny). Kalau benar-benar perlu, lepas dari settings di tempat itu lalu eksekusi, selesai dikembalikan lagi. Repotnya “sengaja melepas sementara” itu sendiri yang jadi rem untuk aksi berbahaya.
T. Hook dan permission, perannya tidak tumpang tindih? J. Tidak. Permission mengontrol “boleh tidak mengeksekusi aksi ini”, hook mengontrol “apa yang pasti dijalankan sebelum dan sesudah eksekusi”. Cek deterministik seperti menghentikan masuknya secret atau build sebelum deploy adalah tugas hook.
Hasil setelah saya coba sendiri
Cara berpikir ini saya pasang ulang apa adanya ke daily automation situs ini. Yang paling berubah bukan kualitas output AI-nya sendiri, melainkan jadi jelasnya “di titik mana manusia berhenti”.
Dulu operasinya kabur, cuma “memajukan satu hal”, kadang run selesai setelah cuma sedikit memperbaiki artikel lama. Sekarang alurnya terpaku: susun langkah di plan -> edit di acceptEdits -> build lewat hook sebelum deploy -> cek mobile semua bahasa setelah publish. Sejak berhenti pakai bypassPermissions dan beralih ke acceptEdits + sandbox, rasa deg-degan “kok tiba-tiba sudah melakukan sesuatu ke luar” itu hilang.
Daripada menyerahkan semua ke AI yang pintar, letakkan satu tarikan napas tepat sebelum aksi yang tidak bisa dibatalkan. Kelihatannya memutar, tapi yang bisa diputar dengan tenang setiap hari justru cara ini. Coba mulai dengan menaruh cheatsheet gratis di samping kamu, lalu isi daftar deny-mu sendiri baris demi baris.
PDF gratis: cheatsheet Claude Code
Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.
Kami menjaga datamu dan tidak mengirim spam.
Tentang penulis
Masa
Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.
Artikel terkait
Cara Menulis Instruksi agar Claude Code Hanya Mengubah Satu File
Dari kegagalan 'bikin lebih bagus' yang mengubah 40 baris: template brief Claude Code yang menyatukan scope, verifikasi, dan rollback.
Pulih dari permission denial Claude Code tanpa melemahkan guardrail
Ubah command Claude Code yang ditolak menjadi recovery prompt dengan alasan, alternatif aman, proof command, dan kriteria retry.
Claude Code Harness Smoke Test: loop bukti 15 menit sebelum mempercayai agen
Pemeriksaan Claude Code untuk scope, area terlarang, command bukti, URL publik, dan CTA pendapatan.