Tips & Tricks

Panduan Lengkap Izin Claude Code | settings.json, Hooks, dan Allowlist Dijelaskan

Penjelasan lengkap pengaturan izin Claude Code. Pelajari penggunaan allow/deny/ask, otomatisasi dengan Hooks, settings.json per lingkungan, dan pola praktis — dengan kode yang berfungsi.

Claude Code memiliki kemampuan operasi file dan eksekusi perintah yang sangat powerful. Izin (permissions) adalah cara untuk mengontrol kekuatan tersebut dengan aman. Mari keluar dari kondisi “asal jalan” dan rancang Claude Code yang bekerja persis seperti yang Anda inginkan.

Artikel ini menjelaskan secara mendalam, dengan kode yang berfungsi, semua pengaturan di .claude/settings.json, pola implementasi Hooks, dan desain izin per lingkungan.

Gambaran Umum Izin

Izin Claude Code dikontrol pada 3 level.

LevelKunciPerilaku
IzinkanallowDieksekusi otomatis tanpa dialog konfirmasi
TanyaaskMemerlukan persetujuan pengguna setiap kali
TolakdenyTidak dapat dieksekusi sama sekali (diblokir dengan error)

Pengaturan ditulis di .claude/settings.json. Ditempatkan di root proyek memungkinkan tim berbagi melalui git; ditempatkan di ~/.claude.json menjadi pengaturan global.

Prioritas (tertinggi lebih dulu):
Proyek .claude/settings.json
    > Global ~/.claude.json
        > Default (semua adalah ask)

Struktur Dasar settings.json

{
  "permissions": {
    "allow": [
      "Read(**)",
      "Glob(**)",
      "Grep(**)",
      "Bash(npm run *)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(git push --force*)"
    ],
    "ask": [
      "Write(**)",
      "Edit(**)",
      "Bash(git commit*)"
    ]
  },
  "hooks": {
    "PreToolUse": [],
    "PostToolUse": []
  }
}

Nama Tool dan Sintaks Pola

Izin ditulis dalam format “NamaTool(pola argumen)”.

Daftar Tool Utama

Nama ToolDeskripsi
ReadMembaca file
WriteMembuat file baru
EditPerubahan parsial pada file yang ada
BashEksekusi perintah shell
GlobPencarian pola file
GrepPencarian konten
WebFetchMengambil URL
AgentMeluncurkan sub-agent

Sintaks Pola

"Read(**)"          // Izinkan membaca semua file
"Read(src/**)"      // Izinkan hanya di bawah src/
"Read(*.md)"        // Izinkan hanya file .md
"Bash(npm run *)"   // Izinkan hanya perintah yang dimulai dengan npm run
"Bash(git *)"       // Izinkan semua perintah git
"Bash(rm -rf *)"    // Tolak rm -rf

** cocok dengan semua path termasuk direktori; * cocok dengan satu segmen.

Pola Praktis

Pola 1: Pengembangan Solo (relatif permisif)

{
  "permissions": {
    "allow": [
      "Read(**)",
      "Glob(**)",
      "Grep(**)",
      "Bash(npm *)",
      "Bash(git log*)",
      "Bash(git diff*)",
      "Bash(git status*)",
      "Bash(git add*)",
      "Bash(node *)",
      "Bash(echo *)",
      "Bash(cat *)",
      "Bash(ls *)"
    ],
    "deny": [
      "Bash(rm -rf /)",
      "Bash(rm -rf ~*)",
      "Bash(git push --force *main*)",
      "Bash(git push --force *master*)"
    ],
    "ask": [
      "Write(**)",
      "Edit(**)",
      "Bash(git commit*)",
      "Bash(git push*)",
      "Bash(rm *)"
    ]
  }
}

Pola 2: Pengembangan Tim (berorientasi keamanan)

{
  "permissions": {
    "allow": [
      "Read(**)",
      "Glob(**)",
      "Grep(**)",
      "Bash(npm run lint)",
      "Bash(npm run test)",
      "Bash(npm run typecheck)",
      "Bash(git log*)",
      "Bash(git diff*)",
      "Bash(git status*)",
      "Bash(git branch*)"
    ],
    "deny": [
      "Bash(rm -rf*)",
      "Bash(git push --force*)",
      "Bash(git push -f*)",
      "Bash(git reset --hard*)",
      "Bash(git rebase *main*)",
      "Bash(git rebase *master*)",
      "Bash(DROP *)",
      "Bash(TRUNCATE *)",
      "Bash(curl * | bash)",
      "Bash(wget * | sh)"
    ],
    "ask": [
      "Write(**)",
      "Edit(**)",
      "Bash(git commit*)",
      "Bash(git push*)",
      "Bash(git add*)",
      "Bash(npm install*)",
      "Bash(*deploy*)"
    ]
  }
}

Pola 3: Lingkungan Produksi (hanya baca)

{
  "permissions": {
    "allow": [
      "Read(**)",
      "Glob(**)",
      "Grep(**)",
      "Bash(git log*)",
      "Bash(git diff*)",
      "Bash(git status*)",
      "Bash(git show*)",
      "Bash(cat *)",
      "Bash(ls *)",
      "Bash(ps *)",
      "Bash(df *)",
      "Bash(top *)"
    ],
    "deny": [
      "Write(**)",
      "Edit(**)",
      "Bash(git push*)",
      "Bash(git commit*)",
      "Bash(git reset*)",
      "Bash(rm *)",
      "Bash(mv *)",
      "Bash(*deploy*)",
      "Bash(*restart*)",
      "Bash(*kill *)"
    ],
    "ask": []
  }
}

Di produksi, ini ditentukan dengan CLAUDE_SETTINGS=.claude/settings.production.json claude.

Pola 4: Hanya Pembuatan Konten (pola yang digunakan di situs ini)

{
  "permissions": {
    "allow": [
      "Read(**)",
      "Glob(**)",
      "Grep(**)",
      "Write(site/src/content/**)",
      "Write(content/**)",
      "Edit(site/src/content/**)",
      "Edit(content/**)",
      "Bash(git log*)",
      "Bash(git diff*)",
      "Bash(git status*)",
      "Bash(node scripts/*)",
      "Bash(QIITA_TOKEN=* node scripts/qiita-publish.mjs)"
    ],
    "deny": [
      "Bash(rm -rf*)",
      "Bash(git push --force*)",
      "Edit(.env*)",
      "Read(.env*)"
    ],
    "ask": [
      "Bash(git add*)",
      "Bash(git commit*)",
      "Bash(git push*)",
      "Bash(bash scripts/deploy.sh*)"
    ]
  }
}

Kuncinya adalah membatasi penulisan ke direktori tertentu seperti dengan Write(site/src/content/**).

Hooks: Menjalankan Proses Sebelum dan Sesudah Izin

Hooks adalah mekanisme yang secara otomatis menjalankan perintah sebelum dan sesudah eksekusi tool. Dapat digunakan untuk pemeriksaan keamanan dan pemformatan otomatis.

PreToolUse: Hook Sebelum Eksekusi

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(git add*)",
        "hooks": [{
          "type": "command",
          "command": "git diff --cached --name-only | grep -E '^\\.env' && echo '🚨 Penambahan .env terdeteksi!' && exit 1 || exit 0"
        }]
      },
      {
        "matcher": "Bash(git commit*)",
        "hooks": [{
          "type": "command",
          "command": "node scripts/secret-scan.mjs"
        }]
      },
      {
        "matcher": "Bash(rm*)",
        "hooks": [{
          "type": "command",
          "command": "echo '⚠️ Perintah hapus terdeteksi. Akan dieksekusi dalam 5 detik. Ctrl+C untuk membatalkan.' && sleep 5"
        }]
      }
    ]
  }
}

Jika perintah hook mengembalikan kode keluar 1, eksekusi tool diblokir. Ini adalah poin terpenting.

PostToolUse: Hook Setelah Eksekusi

{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [{
          "type": "command",
          "command": "npx tsc --noEmit 2>&1 | head -20 || true"
        }]
      },
      {
        "matcher": "Bash(git commit*)",
        "hooks": [{
          "type": "command",
          "command": "git log --oneline -3"
        }]
      }
    ]
  }
}

PostToolUse digunakan untuk pemeriksaan pasca-eksekusi dan efek samping — misalnya, menjalankan pengecekan tipe secara otomatis setelah mengedit file atau menampilkan 3 entri log terbaru setelah commit.

Koleksi Resep Hooks Praktis

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash(npm install*)",
        "hooks": [{
          "type": "command",
          "command": "echo '📦 Menambahkan paket. Harap periksa package.json.'"
        }]
      },
      {
        "matcher": "Bash(*deploy*)",
        "hooks": [{
          "type": "command",
          "command": "read -p '🚀 Akan melakukan deploy. Lanjutkan? [y/N] ' ans && [ \"$ans\" = 'y' ] || exit 1"
        }]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write(*.ts)|Edit(*.ts)",
        "hooks": [{
          "type": "command",
          "command": "npx eslint --fix $CLAUDE_TOOL_INPUT_FILE_PATH 2>/dev/null || true"
        }]
      }
    ]
  }
}

Mode Izin: Level Izin Saat Peluncuran

Anda juga dapat menentukan mode saat meluncurkan perintah claude.

# Mode normal (mengikuti settings.json)
claude

# Otomatis menyetujui semua operasi (berbahaya! hanya untuk lingkungan terpercaya)
claude --dangerously-skip-permissions

# Lewati hanya operasi tertentu
claude --allowedTools "Read,Grep,Glob"

# Mode non-interaktif (digunakan di CI/CD)
claude -p "Jalankan tes dan laporkan hasilnya" --dangerously-skip-permissions

--dangerously-skip-permissions hanya boleh digunakan untuk otomatisasi CI/CD atau skrip otomatisasi yang sepenuhnya dipahami, dan dihindari dalam penggunaan interaktif sehari-hari.

Prioritas dan Override File Konfigurasi

Ketika beberapa file konfigurasi ada:

~/.claude.json              ← Global (dibagikan di semua proyek)
    +
.claude/settings.json       ← Proyek (dikelola git)
    +
.claude/settings.local.json ← Override pribadi (gitignore direkomendasikan)
    =
Pengaturan yang digabungkan diterapkan

Tulis pengaturan tambahan pribadi di .claude/settings.local.json dan tambahkan ke gitignore. Untuk mencegah daftar deny tim di-override oleh pengaturan pribadi, desain yang aman adalah hanya menulis aturan deny di settings.json.

# Tambahkan ke .gitignore
.claude/settings.local.json

5 Jebakan Umum

1. Salah menggunakan pola wildcard

// ❌ Ini hanya cocok dengan perintah tunggal "git"
"Bash(git)"

// ✅ Juga cocok dengan git diikuti argumen
"Bash(git *)"
"Bash(git*)"  // Juga berfungsi tanpa spasi, tapi * eksplisit lebih aman

2. Lupa bahwa deny memiliki prioritas di atas ask

// Dengan konfigurasi ini, Bash(rm -rf /tmp/test) ditangkap oleh deny dan diblokir
// Tidak pernah mencapai ask
{
  "deny": ["Bash(rm -rf*)"],
  "ask": ["Bash(rm*)"]  // ← rm -rf ditangani oleh deny
}

3. Tidak memperhatikan kode keluar hook

# Jika perintah hook PreToolUse selalu mengembalikan exit 0,
# kegagalan pemindaian tidak akan memblokir eksekusi

# ❌ Tetap lolos meski ada error
"command": "node scan.mjs"

# ✅ Kontrol kode keluar secara eksplisit
"command": "node scan.mjs || exit 1"

4. Secara tidak sengaja menambahkan settings.json ke .gitignore

Beberapa tim secara tidak sengaja menambahkan settings.json—yang ingin mereka bagikan—ke .gitignore. Pendekatan yang benar adalah konfigurasi proyek di bawah git, hanya settings.local.json di gitignore.

5. Lupa beralih konfigurasi produksi secara manual

# ❌ Bekerja di produksi dengan pengaturan sehari-hari

# ✅ Ganti pengaturan secara eksplisit sebelum pekerjaan produksi
CLAUDE_SETTINGS=.claude/settings.production.json claude

Mendaftarkan alias membuatnya lebih sulit dilupakan:

# ~/.bashrc or ~/.zshrc
alias claude-prod='CLAUDE_SETTINGS=.claude/settings.production.json claude'

Men-debug Konfigurasi

Ketika tidak jelas “mengapa perintah ini diblokir”:

# Periksa pengaturan saat ini
claude --print-settings 2>/dev/null || cat .claude/settings.json

# Periksa aturan mana yang cocok (mode verbose)
claude --verbose -p "Jalankan git push"

Ringkasan: Praktik Terbaik untuk Desain Izin

1. Mulai dengan deny
   → Daftarkan perintah yang tidak boleh pernah dieksekusi
   → rm -rf, git push --force, DROP TABLE wajib ada

2. Kemudian konfigurasikan ask
   → Operasi tulis dan deploy yang memerlukan konfirmasi

3. Allow untuk selebihnya
   → Operasi baca dan CI: allow semua untuk efisiensi

4. Otomatiskan keamanan dengan Hooks
   → Pemindaian pre-commit, pengecekan tipe otomatis setelah edit

5. Siapkan file konfigurasi spesifik lingkungan
   → settings.json (pengembangan), settings.production.json (produksi)

Dengan pengaturan izin yang tepat, Anda akan berhenti menekan tombol persetujuan secara mekanis dan dapat fokus hanya pada operasi yang benar-benar perlu ditinjau. Meluangkan 30 menit untuk desain awal akan membuat ratusan jam kerja mendatang menjadi lebih aman.

Artikel Terkait

Referensi

#claude-code #permissions #security #hooks #settings #configuration

Tingkatkan alur kerja Claude Code kamu

50 template prompt yang sudah teruji, siap copy-paste ke Claude Code sekarang juga.

Gratis

PDF Gratis: Cheatsheet Claude Code dalam 5 Menit

Cukup masukkan emailmu dan kami akan langsung mengirim cheatsheet PDF A4 satu halaman.

Kami menjaga data pribadimu dengan aman dan tidak pernah mengirim spam.

Masa

Tentang Penulis

Masa

Engineer yang aktif menggunakan Claude Code. Mengelola claudecode-lab.com, media teknologi 10 bahasa dengan lebih dari 2.000 halaman.