SpyBara
Go Premium

plugins/mods/events.md 2026-10-01 23:59 UTC to 2026-10-02 07:00 UTC

This page contains 83 additions and 56 deletions.

2026
Thu 1 23:59 Fri 2 07:00

Bereaksi terhadap peristiwa dengan mod

Tangani peristiwa Claude Code dari mod: amati, tulis ulang, atau jawab panggilan alat, prompt, dan giliran, saring peristiwa mana yang ditangani hook, dan rencanakan untuk mod lain.

Hook adalah penanganan peristiwa: fungsi yang dijalankan Claude Code ketika peristiwa bernama terjadi. Claude Code mengeluarkan peristiwa di setiap titik di mana ia akan bertindak, seperti ketika menjalankan alat, mengirimkan prompt, mengirim permintaan ke model, atau memulai atau mengakhiri sesi. Hook Anda berjalan sebelum Claude Code bertindak, sehingga dapat mengamati peristiwa, menulis ulangnya, atau menjawabnya sebagai pengganti Claude Code. Anda mendaftarkan hook dengan on(eventName, handler).

Bangun mod pertama Anda sebelum Anda mulai di sini. Untuk setiap peristiwa dan bidangnya yang tepat, lihat referensi atau baca tipe untuk build Anda.

Bagaimana hook menangani peristiwa

Hook duduk di antara peristiwa dan apa yang akan dilakukan Claude Code tentangnya, sehingga dapat mengamati peristiwa, menulis ulangnya, atau menjawabnya sendiri. Hook menerima tiga argumen: mods API sebagai $, peristiwa sebagai e, dan penanganan berikutnya sebagai next. Penanganan untuk peristiwa membentuk rantai middleware. next(e) memanggil penanganan berikutnya, yang merupakan hook mod lain atau, di akhir rantai, perilaku Claude Code sendiri, dan diselesaikan dengan hasilnya. Apa yang dilakukan hook Anda dengan next menentukan mana dari ketiga hal itu yang dilakukannya.

Amati peristiwa

Untuk mengamati peristiwa tanpa mengubahnya, lakukan pekerjaan Anda dan kembalikan next(e). Hook ini mencatat setiap alat yang akan digunakan Claude:

on('tool.call', async ($, e, next) => {
  // Berjalan sebelum alat dijalankan
  $.ui.log('Claude is about to use ' + e.tool)
  // Teruskan peristiwa tanpa perubahan
  return next(e)
})

Sebelum setiap alat dijalankan, baris redup seperti ● my-mod: Claude is about to use Bash muncul dalam transkrip, di mana my-mod adalah nama plugin Anda. Alat berjalan seperti yang akan terjadi tanpa mod.

Untuk bertindak setelah peristiwa, await next(e), lakukan pekerjaan Anda, dan kembalikan hasilnya. Hook ini mencatat setiap alat setelah dijalankan:

on('tool.call', async ($, e, next) => {
  // Biarkan alat berjalan, dan tunggu hasilnya
  const result = await next(e)
  // Berjalan setelah alat selesai
  $.ui.log(e.tool + ' finished')
  // Berikan hasil kembali tanpa perubahan
  return result
})

Baris sekarang muncul setelah setiap alat selesai. Claude membaca hasil yang sama dengan cara apa pun, karena hook mengembalikan apa yang diselesaikan next(e).

Tulis ulang peristiwa

Untuk mengubah apa yang Claude Code bertindak, seperti teks prompt, panggil next dengan salinan peristiwa yang dimodifikasi. Peristiwa itu sendiri tidak dapat diubah: peristiwa itu dibekukan di setiap kedalaman, dan penugasan ke bidang melempar. Hook ini memangkas setiap prompt sebelum dikirim:

on('prompt.submit', async ($, e, next) => {
  // Teruskan salinan peristiwa dengan teksnya diubah
  return next({ ...e, text: e.text.trim() })
})

Penanganan berikutnya dan Claude Code menerima prompt yang dipangkas dan tidak pernah melihat yang asli. Anda juga dapat mengubah hasilnya: await next(e), kemudian kembalikan salinan hasil dengan bidang yang diganti.

Jawab peristiwa

Untuk menangani peristiwa sendiri, kembalikan hasil tanpa memanggil next. Itu memotong rantai, sehingga mod berikutnya dan perilaku Claude Code sendiri tidak berjalan. Hook ini menolak setiap perintah Bash:

on('tool.call', { tool: 'Bash' }, async () => {
  // Tidak ada panggilan ke next, jadi perintah tidak pernah dijalankan
  return { deny: 'Bash is turned off in this project. Use the file tools.' }
})

Ketika Claude mencoba perintah Bash, perintah tidak berjalan, dan Claude membaca teks deny sebagai hasil alat. Setiap peristiwa memiliki bentuk hasil sendiri, yang referensi peristiwa daftarkan.

Saring peristiwa mana yang ditangani hook

Untuk menjalankan hook hanya untuk beberapa peristiwa, teruskan filter sebagai argumen kedua ke on. Claude Code memanggil filter sebagai matcher. Ini adalah objek yang bidangnya dibandingkan dengan peristiwa, dan hook hanya berjalan ketika setiap bidang cocok. Bidang dapat berupa nilai, array nilai yang diizinkan, atau ekspresi reguler.

Setiap baris dalam contoh ini mendaftarkan fungsi yang sama, hook, untuk set panggilan alat yang lebih sempit:

// String cocok dengan satu nilai: hanya panggilan Bash
on('tool.call', { tool: 'Bash' }, hook)
// Array cocok dengan nilai apa pun di dalamnya: panggilan Edit dan Write
on('tool.call', { tool: ['Edit', 'Write'] }, hook)
// Ekspresi reguler cocok dengan pola: setiap alat dari satu server MCP
on('tool.call', { tool: /^mcp__github__/ }, hook)

hook berjalan sekali untuk panggilan Bash, Edit, atau Write, dan sekali untuk panggilan ke alat yang namanya dimulai dengan mcp__github__. Panggilan ke alat lain apa pun, seperti Read, tidak cocok dengan ketiga hal itu, jadi hook tidak berjalan untuk itu.

Nama peristiwa dapat berupa wildcard. 'classic.*' cocok dengan setiap peristiwa hook pengaturan. '*' cocok dengan setiap peristiwa kecuali peristiwa telemetri, yang memerlukan namanya sendiri dan filter { to: 'collector' }.

Daftarkan setiap peristiwa sekali per matcher. Jika Anda memanggil on dua kali untuk session.start tanpa matcher, modul gagal dimuat dengan on("session.start") is registered twice without a matcher. Masukkan semua yang dilakukan mod Anda saat memulai sesi dalam satu hook.

Hook apa yang dilakukan Claude

Tangani peristiwa ini untuk melihat atau mengubah panggilan tool, prompt, atau giliran saat terjadi. Untuk setiap peristiwa dan apa yang dapat dikembalikan hook, lihat referensi peristiwa.

Lindungi atau ubah panggilan tool

Hook tool.call melihat setiap tool yang akan digunakan Claude, sehingga dapat menolak panggilan, mengubah argumennya, atau membiarkannya lewat. tool.call diaktifkan ketika Claude Code akan menjalankan tool, termasuk panggilan yang dibuat subagent dan panggilan ke tool MCP. e.tool adalah nama tool dan argumen tool adalah bidang e, seperti e.command untuk Bash. Ketika Anda memanggil next(e), Claude Code menjalankan pemeriksaan izin dan kemudian tool tersebut.

Hook ini menolak perintah Bash yang melakukan force-push, dan memberi tahu Claude alasannya:

// The matcher limits the hook to Bash calls, so e.command is the shell command
on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
  if (/git push .*--force/.test(e.command)) {
    // Returning without calling next answers the event, so the command never runs
    return { deny: 'Force pushes are not allowed in this repository. Push to a new branch instead.' }
  }
  // Every other command goes on to the permission check and then to Bash
  return next(e)
})

Ketika Claude mencoba git push --force, perintah tidak berjalan dan tidak ada permintaan izin yang muncul, karena hook tidak pernah memanggil next. Claude membaca teks deny sebagai hasil tool, jadi tulislah sebagai instruksi yang dapat ditindaklanjuti Claude. Setiap perintah Bash lain berjalan seperti yang akan terjadi tanpa mod.

Untuk bertindak setelah tool berjalan, await next(e), lakukan pekerjaan Anda, dan kembalikan apa yang diberikan next. Hook ini mencatat setiap file .mdx yang diubah Claude, dengan $.ui.log, yang menambahkan baris redup ke transkrip yang tidak dibaca Claude:

on('tool.call', { tool: ['Edit', 'Write'] }, async ($, e, next) => {
  // Wait for the permission check and the tool, and keep what they produced
  const result = await next(e)
  // A refused call comes back as { deny }, and a failed one has isError set
  const changed = !result.deny && !result.isError
  if (changed && e.file_path.endsWith('.mdx')) $.ui.log('Claude changed ' + e.file_path)
  // Return the result as it came, so Claude reads what the tool returned
  return result
})

Setelah Claude mengedit atau menulis file .mdx, baris redup dalam transkrip menyebutkan nama file tersebut. Tidak ada yang dicatat untuk jenis file lain, atau untuk panggilan yang ditolak atau gagal. Pandangan Claude tentang panggilan tidak berubah, karena hook mengembalikan hasil yang diterimanya.

Untuk mengubah panggilan, teruskan argumen yang diubah ke next. Untuk mencoba ulang panggilan, panggil next(e) lagi: hook yang melihat isError pada hasil pertama dapat menjalankan tool untuk kedua kalinya dan mengembalikan hasil tersebut. Untuk menjawab panggilan sendiri, kembalikan objek dengan bidang result, seperti { result: 'Skipped by my-mod' }, tanpa memanggil next. Ketika Anda melakukan itu, tidak ada permintaan izin yang muncul dan tool tidak berjalan, jadi hasil yang Anda kembalikan adalah satu-satunya yang diketahui Claude tentang apa yang terjadi.

Hook dalam pengaturan terkelola organisasi Anda berjalan sebelum hook tool.call mod mana pun, dan blokir dari salah satunya bersifat final.

Tahan panggilan tool sampai pengguna memutuskan

Hook dapat menjeda panggilan tool dan menanyakan kepada pengguna apa yang harus dilakukan sebelum melanjutkan. Hook tool.call dapat melakukan await sebelum memanggil next atau mengembalikan nilai, dan panggilan tool tetap tertunda sampai saat itu. Untuk mengajukan pertanyaan kepada pengguna, panggil $.ui.ask. Ini menampilkan pertanyaan Anda di atas daftar bernomor opsi Anda, dalam dialog yang digunakan Claude untuk menanyakan sesuatu kepada Anda, dan diselesaikan dengan label yang dipilih pengguna. Setelah opsi Anda, dialog menambahkan baris untuk mengetik jawaban berbeda dan baris Chat about this.

Pola RISKY dalam contoh ini cocok dengan rm -r, rm -rf, git reset --hard, dan git push dengan --force, dan melewatkan penulisan lain seperti git push -f. Modul ini bertanya sebelum menjalankan perintah Bash yang cocok dengan pola tersebut:

const RISKY = /\brm\s+-rf?\b|\bgit\s+reset\s+--hard\b|\bgit\s+push\b.*--force/

export function register(on) {
  on('tool.call', { tool: 'Bash' }, async ($, e, next) => {
    // Let every other command through without a question
    if (!RISKY.test(e.command)) return next(e)
    // Start from the safe answer, so a question nobody answers refuses the command
    let answer = 'Refuse'
    try {
      // The tool call waits here until the user picks one of the two labels
      answer = await $.ui.ask('Run this command? ' + e.command, ['Run it', 'Refuse'])
    } catch {
      // The user dismissed the question, or this is a claude -p run with nobody to ask
    }
    if (answer !== 'Run it') {
      // Answer without calling next, so the command doesn't run
      return { deny: 'The user declined this command. Ask before trying a different approach.' }
    }
    return next(e)
  })
}

Ketika Claude mencoba perintah seperti rm -rf build, pertanyaan muncul dengan perintah tersebut di dalamnya, dan perintah menunggu jawaban:

  • Pengguna memilih Run it: hook memanggil next(e), dan pemeriksaan izin biasa tetap berjalan setelahnya
  • Pengguna memilih Refuse: perintah tidak berjalan, dan Claude membaca teks deny
  • Pengguna mengetik jawaban: $.ui.ask diselesaikan dengan teks yang diketik. Hook membandingkannya dengan Run it, jadi teks lain apa pun menolak perintah.
  • Tidak ada yang menjawab: $.ui.ask menolak ketika pengguna menutup pertanyaan atau memilih Chat about this, dan dalam eksekusi claude -p, sehingga blok catch membiarkan jawaban tetap Refuse

Pertahankan penantian di dalam panggilan API mods seperti $.ui.ask, karena waktu tersebut tidak dihitung terhadap batas waktu hook. Waktu yang dihabiskan untuk menunggu promise Anda sendiri tetap dihitung. Claude Code melewati hook yang melampaui batas waktu, sehingga perintah yang ditahan akan berjalan.

Setujui atau tolak panggilan tool sebelum pengguna ditanya

Untuk memutuskan apakah panggilan tool boleh berjalan, tangani tool.check, peristiwa tempat Claude Code membuat keputusan tersebut. Peristiwa ini diaktifkan setelah aturan izin dan hook pengaturan telah memutuskan, dan next(e) diselesaikan dengan keputusan mereka: allow, ask, atau deny. Hook Anda mengembalikan keputusan tersebut atau keputusan yang berbeda. e.input berisi argumen tool, seperti command untuk Bash.

Untuk perintah atau path yang tetap, gunakan aturan izin seperti Bash(npm test), yang tidak memerlukan kode. Tangani tool.check ketika keputusan bergantung pada apa yang berlaku pada saat itu, seperti branch Git saat ini atau nilai yang dicatat oleh hook lain.

Hook ini menolak git push saat branch saat ini adalah main:

on('tool.check', { tool: 'Bash' }, async ($, e, next) => {
  // What the permission rules and settings hooks decided: 'allow', 'ask', or 'deny'
  const decided = await next(e)
  if (!e.input.command.includes('git push')) return decided
  const branch = await $.process.run(['git', 'branch', '--show-current'])
  if (branch.stdout.trim() !== 'main') return decided
  return { decision: 'deny', reason: 'Push from a branch other than main' }
})

Di main, hook mengembalikan deny, bahkan ketika suatu aturan mengizinkan git push. Di branch lain, dan untuk perintah lain, panggilan mendapatkan keputusan yang akan didapatnya tanpa mod.

Hook mencocokkan teks perintah, jadi perlakukan sebagai pengingat untuk Claude. Untuk memblokir push ke main bagi semua orang, lindungi branch tersebut di host Git Anda.

Hook dapat mengembalikan allow, ask, atau deny, sehingga juga dapat menyetujui panggilan yang diblokir oleh hook PreToolUse di luar pengaturan terkelola. Perluas izin dengan hook mencantumkan keputusan mana yang tetap berlaku atas mod.

Tulis ulang atau tambahkan ke prompt

Hook prompt.submit melihat setiap prompt sebelum giliran dimulai, sehingga dapat menulis ulang teks atau menambahkan sesuatu padanya. e.text adalah apa yang diketik.

Untuk melakukan ini Kembalikan ini
Tulis ulang prompt. Pesan dalam transkrip menampilkan teks baru. next({ ...e, text: newText })
Tambahkan teks yang hanya dibaca Claude, setelah prompt next({ ...e, context: [...(e.context ?? []), extraText] })
Hentikan prompt agar tidak dikirim { drop: 'the reason' }

Hook ini menambahkan nama branch saat ini untuk Claude setiap kali prompt menyebutkan pull request:

on('prompt.submit', async ($, e, next) => {
  // Pass on a prompt that doesn't mention a pull request as it is
  if (!/\bPR\b|pull request/i.test(e.text)) return next(e)
  const git = await $.process.run(['git', 'branch', '--show-current'])
  // Outside a git repository the command fails, so there's no branch to add
  if (git.exitCode !== 0) return next(e)
  // Keep any context an earlier hook added, and add one more line for Claude
  return next({ ...e, context: [...(e.context ?? []), 'Current branch: ' + git.stdout.trim()] })
})

Ketika Anda mengirim prompt seperti open a PR for this change, pesan Anda terlihat sama dalam transkrip, dan Claude juga membaca baris seperti Current branch: feature/auth setelahnya. Prompt yang tidak menyebutkan pull request diteruskan tanpa perubahan, dan git tidak berjalan.

Peristiwa lain mencakup sisa apa yang dibaca Claude: prompt.section untuk setiap bagian system prompt, prompt.context untuk konteks yang dikirim dengan pesan pertama, dan skill.prompt untuk teks skill. Teks dari hook ini yang berubah antar permintaan membatalkan cache prompt.

Ikuti giliran

Giliran adalah semua yang dilakukan Claude sebagai jawaban atas satu prompt. Tangani turn.start, turn.step, dan turn.complete untuk mengikutinya:

Peristiwa Kapan diaktifkan Apa yang dapat dilakukan hook
turn.start Giliran dimulai Amati. e.turnId mengidentifikasi giliran dalam dua peristiwa lainnya.
turn.step Claude Code akan mengirim satu permintaan ke model. Giliran dengan panggilan tool memiliki beberapa permintaan. e.agentId ditetapkan untuk permintaan subagent. Baca penggunaan token setiap permintaan, kirimkan ke model berbeda dengan next({ ...e, model }), atau jawab tanpa memanggil model
turn.complete Giliran berakhir, termasuk giliran yang diinterupsi pengguna, di mana e.isAborted adalah true. e.answer adalah teks final Claude, e.durationMs berapa lama waktu yang dibutuhkan, dan e.usage total token giliran. Giliran subagent mengaktifkannya dengan e.agentId ditetapkan. Amati, atau kembalikan objek dengan bidang text, seperti { text: 'Done in 12 seconds' }, untuk menampilkan baris di bawah jawaban

Tulis hook turn.step sebagai generator asinkron, karena peristiwa ini mengalirkan data secara streaming. yield* next(e) meneruskan respons saat dialirkan dan menghasilkan hasil akhir. Hook ini mencatat berapa banyak dari setiap permintaan yang dilayani Claude API dari cache prompt:

// function* makes the hook a generator, which can pass the response on piece by piece
on('turn.step', async function* ($, e, next) {
  // Send the request, forward each piece as it arrives, and keep the finished result
  const result = yield* next(e)
  // Skip a result that reports no token counts
  if (result.usage) {
    $.ui.log('cache read ' + result.usage.cache_read_input_tokens + ' · wrote ' + result.usage.cache_creation_input_tokens)
  }
  // Return the result unchanged, so the turn continues as usual
  return result
})

Respons Claude dialirkan ke layar seperti yang terjadi tanpa mod. Setelah setiap permintaan selesai, baris redup dalam transkrip memberikan jumlah token yang dibaca dari cache dan jumlah yang ditulis ke dalamnya. Giliran dengan panggilan tool memiliki beberapa permintaan, sehingga menambahkan beberapa baris.

result.usage menyimpan hitungan token yang dilaporkan Claude API untuk permintaan, ditambah model yang menjawab: input_tokens, output_tokens, cache_read_input_tokens, dan cache_creation_input_tokens. Hook juga berjalan untuk permintaan subagent, jadi periksa e.agentId ketika Anda hanya menginginkan percakapan utama.

Tangani peristiwa hook pengaturan

Hook pengaturan adalah hook perintah, HTTP, prompt, dan agent yang Anda konfigurasi dalam file pengaturan. Setiap peristiwa hook pengaturan, seperti Stop, SessionEnd, atau PostToolUse, juga merupakan peristiwa bernama classic. diikuti dengan nama peristiwa hook pengaturan tersebut, seperti classic.Stop. e adalah JSON yang diterima hook pengaturan di stdin, termasuk transcript_path.

Hook ini menggunakan Stop, yang diaktifkan ketika Claude selesai merespons, untuk mencatat lokasi penyimpanan transkrip sesi:

on('classic.Stop', async ($, e, next) => {
  // e has the same fields a Stop hook in a settings file reads from stdin
  $.ui.log('Transcript saved at ' + e.transcript_path)
  // Pass the event on, so Stop hooks in your settings files still run
  return next(e)
})

Setiap kali Claude selesai merespons, baris redup dalam transkrip memberikan path file transkrip. Hook mengembalikan next(e), sehingga hook hanya mengamati peristiwa dan tidak mengubah apa pun tentang cara giliran berakhir.

Jalankan bersama mod lain

Beberapa mod dapat menangani peristiwa yang sama, dan salah satu dari mereka dapat gagal. Jika mod Anda memblokir panggilan tool, periksa posisinya dalam rantai dan apa yang terjadi ketika hooknya gagal.

Urutan mod berjalan

Hook pada peristiwa yang sama membentuk satu rantai middleware. Setiap next mod memanggil hook mod berikutnya, dan next terakhir mencapai perilaku Claude Code sendiri. Mod pertama adalah terluar: melihat peristiwa sebelum yang lain dan hasil setelah mereka, dan menentukan apakah yang lain berjalan sama sekali. Mod yang lebih baru tidak dapat menghentikan yang lebih awal dari melihat peristiwa.

Claude Code mengurutkan rantai berdasarkan tempat asal setiap mod:

  1. Guard bawaan sec-default@builtin, mod yang dibangun ke dalam Claude Code yang /plugin daftarkan sebagai cc-plugin-sec-default, di mana dimuat, mod yang organisasi Anda daftarkan dalam prependPlugins, dan kemudian mod lain apa pun yang dihitung sebagai organisasi Anda dan tidak dalam appendPlugins
  2. Mod yang Anda instal
  3. Mod yang organisasi Anda daftarkan dalam appendPlugins
  4. Mod bawaan lain yang dibangun ke dalam Claude Code

Di antara mod yang Anda instal, mod berjalan sebelum mod yang didaftarkan di bawah dependencies dalam manifestnya. Dalam satu modul, hook berjalan dalam urutan register yang disebut on.

Di mana hook pengaturan berjalan dalam urutan

Hook PreToolUse yang dikonfigurasi dalam file pengaturan juga berjalan selama panggilan alat, pada titik tetap dalam rantai mod:

  • Hook PreToolUse dari pengaturan terkelola: berjalan sebelum hook tool.call mod pertama, dan blok dari salah satu dari mereka adalah final, jadi tidak ada mod yang melihat panggilan.
  • Hook PreToolUse dari setiap file pengaturan lain dan dari hooks/hooks.json plugin: berjalan setelah mod terakhir memanggil next, sebagai bagian dari perilaku Claude Code sendiri. Mod yang menjawab tool.call tanpa memanggil next mencegah mereka berjalan, dan mod yang memanggil next melihat keputusan mereka dalam hasil yang dikembalikan.

tool.check diaktifkan setelah hook tersebut dan aturan izin telah memutuskan, sehingga hook pada peristiwa tersebut dapat menyetujui panggilan yang diblokir hook di grup kedua.

Tangani hook yang gagal

Hook yang gagal tidak merusak sesi, dan Anda dapat memutuskan apa yang terjadi sebagai gantinya. Ketika hook tanpa penanganan .catch melempar, habis waktu, atau mengembalikan hasil bentuk yang salah, apa yang terjadi selanjutnya tergantung pada apakah telah memanggil next:

  • Gagal sebelum memanggil next: Claude Code melewatinya, dan penanganan berikutnya berjalan sebagai gantinya
  • Gagal setelah next diselesaikan: hasil itu berdiri, dan tidak ada yang berjalan kedua kalinya

Satu baris menamai mod, peristiwa, dan alasan, seperti my-mod: tool.call hook skipped: threw Error: boom. Tempat Anda membacanya tergantung pada sesi, seperti Cari tahu mengapa mod tidak melakukan apa pun daftarkan. Hook ui.render yang gambarnya tidak divalidasi dilaporkan berbeda, seperti Bangun pohon dari elemen menjelaskan.

Untuk membuat hook yang memblokir panggilan gagal tertutup, tambahkan penanganan kesalahan .catch yang menjawab sebagai gantinya. Di sini, guard adalah fungsi hook Anda:

// on mengembalikan pendaftaran, dan .catch melampirkan penanganan ke hook itu saja
on('tool.call', { tool: 'Bash' }, guard).catch(async ($, e, next) => {
  // next.error.kind adalah 'throw' atau 'timeout', yang mengatakan bagaimana guard gagal
  return { deny: 'The command guard failed, so this command was not run: ' + next.error.kind }
})

Sementara guard bekerja, penanganan tidak pernah berjalan. Ketika guard melempar atau habis waktu pada panggilan Bash, Claude Code memanggil penanganan dengan peristiwa yang sama. Penanganan mengembalikan { deny }, jadi perintah tidak berjalan, dan Claude membaca teks dengan throw atau timeout di akhir. Tanpa penanganan, Claude Code akan melewati guard dan menjalankan perintah. Penanganan memiliki batas waktu sendiri yang lebih singkat.

Langkah berikutnya

  • Gunakan mods API: tambahkan perintah dan alat, panggil model, dan jalankan pekerjaan pada timer
  • Gambar di antarmuka: tampilkan apa yang dikumpulkan hook Anda dalam panel atau di atas prompt
  • Uji mod: naikkan salah satu peristiwa ini dari tes
  • Referensi mods: setiap peristiwa, setiap metode mods API, dan batasnya