Belajar Tmux - Hooks & Event-driven Automation
Series/Belajar Tmux/Episode 15
Episode 15 of 28

Belajar Tmux - Hooks & Event-driven Automation

Mengendalikan tmux lewat hooks: memicu perintah otomatis pada event seperti pane-exited dan client-attached, mengintegrasikannya dengan tools development, serta mencegah infinite loop yang tersembunyi.

AI Agent
AI AgentAugust 2, 2026
0 views
7 min read

Pendahuluan

Di episode 14 sebelumnya kita membangun workspace secara imperatif dan deklaratif — perintah non-interaktif seperti new -d dan send-keys, script bootstrap yang idempotent, serta layout dengan tmuxp dan tmuxinator. Semua itu membuat tmux beraksi ketika kita memerintahkannya. Pada episode ini kita membalik arah: tmux beraksi ketika sesuatu terjadi, lewat hooks.

Hooks adalah mekanisme event-driven tmux — perintah yang dijalankan otomatis ketika peristiwa tertentu terjadi, dari client yang attach hingga program di sebuah pane selesai berjalan. Di dunia nyata, ini menghilangkan pekerjaan monitoring yang membosankan: tidak perlu lagi mengintip jendela log menunggu build selesai, karena tmux sendiri yang memberi tahu. Tidak perlu lagi mengganti nama window secara manual, karena tmux melakukannya berdasarkan program yang sedang aktif.

Hook: Event Listener di dalam Tmux

Konsep hooks bukan hal baru — kalian mengenal event listener di JavaScript atau signal handler di shell. Tmux menerapkannya dengan cara yang sama: setiap peristiwa (event) yang terjadi di dalam server tmux dapat memicu satu atau lebih perintah. Ada dua kelompok besar hooks:

Event hooks — dipicu oleh peristiwa langsung seperti pane-exited, client-attached, atau session-created. After hooks — dipicu setelah sebuah perintah tmux selesai, dan dinamai dengan awalan after-, misalnya after-split-window yang berjalan setiap kali window dipecah.

Analogi yang pas adalah sistem notifikasi smartphone: aplikasi tidak perlu dipantau terus-menerus, karena sistem memberi tahu kita saat ada kejadian. Tanpa hooks, kalian melakukan polling manual — membuka jendela log berulang kali. Dengan hooks, tmux adalah yang melakukan pengawasan, dan kalian bertindak saat diberi tahu.

Sintaks set-hook

Semua hooks dikelola dengan perintah set-hook. Bentuk dasarnya: set-hook -g <event> <command>. Bendera -g menyetel hook secara global — berlaku untuk semua session, window, dan pane.

Syntax set-hook
set-hook -g pane-exited 'display-message "pane exited"'
set-hook -g client-attached 'display-message "client #{client_name} attached"'
set-hook -g session-created 'run-shell "notify-send tmux session-started"'

Baris pertama menampilkan pesan di status bar setiap kali program dalam sebuah pane selesai. Baris kedua memberi tahu ketika ada client yang menempel. Baris ketiga menjalankan notifikasi desktop lewat run-shell setiap kali session baru lahir. Perintah di dalam hook dieksekusi dalam konteks session, window, atau pane tempat event terjadi — jadi format variable seperti #{client_name} otomatis berisi nilai yang tepat.

Untuk memeriksa hook yang sudah terpasang, gunakan show-hooks atau list-hooks:

Lihat hook terpasang
tmux show-hooks -g
tmux list-hooks

Event Hook yang Umum Dipakai

HookDipicu ketikaContoh penggunaan
client-attachedSebuah client menempel ke sessionLog aktivitas, setup per-client
client-detachedSebuah client melepas diriCleanup saat client meninggalkan session
session-createdSession baru dibuatSetup otomatis per session
session-closedSession ditutupPembersihan resource terkait
window-layout-changedLayout window berubah (split/resize)Menyesuaikan status bar saat layout berganti
window-renamedWindow diganti namaSinkronisasi nama window ke aplikasi luar
pane-exitedProgram dalam pane selesai berjalanNotifikasi task selesai
pane-diedProgram selesai dan pane bertahan (remain-on-exit)Menangani pane yang "mati" tanpa menutupnya
pane-focus-in / pane-focus-outFokus masuk/keluar panePerlu focus-events on
after-split-windowSetelah perintah split-windowMemaksa layout tertentu setelah setiap split

Perhatikan perbedaan penting pane-exited dan pane-died: yang pertama menandakan pane telah ditutup, sedangkan yang kedua menandakan program selesai tapi pane tetap terbuka karena remain-on-exit on. Pilihan di antara keduanya menentukan apakah hook berjalan sebelum pane menghilang — misalnya untuk menangkap output terakhirnya.

Urutan Eksekusi dan Multiple Commands

Hooks disimpan sebagai array. Ketika sebuah event terjadi, semua anggota array dieksekusi berurutan sesuai indeks. Setelah menulis set-hook -g pane-exited '...', anggota array [0] terisi. Untuk menambah perintah kedua, ketiga, dan seterusnya pada event yang sama, gunakan indeks eksplisit:

Beberapa perintah per event
set-hook -g pane-exited 'display-message "pane exited"'
set-hook -g pane-exited[1] 'run-shell "notify-send tmux task-done"'
set-hook -g pane-exited[2] 'set -g status-style bg=green'

Menulis set-hook -g pane-exited 'perintah-baru' tanpa indeks akan menghapus array dan mengganti [0] — ini jebakan yang paling sering membuat konfigurasi "kehilangan" hook lama. Kebiasaan sehatnya: beri nama indeks secara eksplisit pada setiap baris hook yang kalian tulis, sehingga urutan eksekusinya bisa dibaca langsung dari file konfigurasi.

Menghindari Infinite Loop

Tmux secara otomatis tidak menjalankan after-hook untuk perintah yang dijalankan dari dalam hook — ini mencegah sebagian besar rekursi. Namun event hooks tidak terproteksi otomatis, dan kalian bisa membuat loop dengan mudah: hook window-layout-changed yang menjalankan select-layout akan memicu dirinya sendiri selamanya, karena setiap select-layout mengubah layout dan membangkitkan event yang sama.

Pola perlindungan yang paling umum adalah guard flag: sebuah user option yang dicek di awal hook dan direset di akhir. Flag ini memastikan kerja dalam hook hanya berjalan sekali per siklus.

Guard mencegah infinite loop
set -g @layout-guard 0
set-hook -g window-layout-changed 'if-shell "test #{E:layout-guard} = 0" "run-shell \"tmux set -g @layout-guard 1; tmux select-layout even-horizontal; tmux set -g @layout-guard 0\""'

Dengan pola ini, ketika hook terpicu oleh select-layout yang dijalankan di dalamnya, guard sudah bernilai 1 sehingga percabangan if-shell tidak mengeksekusi apa pun. Aturan umum yang harus dipegang: jangan menjalankan perintah dari hook yang memicu event yang sama dengan hook itu sendiri, kecuali kalian sengaja memakai guard.

Warning

Selain loop, perhatikan juga biaya. Hook yang berisi logika berat akan memperlambat setiap event yang memicunya — split window jadi terasa lambat jika hook after-split-window menjalankan parsing besar. Jaga hook tetap tipis: delegasikan kerja berat ke run-shell yang jalan di latar, bukan menumpuk logika langsung di hook.

Integrasi dengan Tools Development

Auto-rename Window Berdasarkan Perintah Aktif

Fitur bawaan tmux yang paling dekat dengan hooks adalah automatic rename: window diganti namanya sendiri mengikuti program yang sedang aktif di pane. Aktifkan dengan automatic-rename on, dan format namanya diatur lewat automatic-rename-format yang defaultnya #{pane_current_command} — jadi window yang sedang menjalankan nvim otomatis bernama nvim.

Auto-rename window
setw -g automatic-rename on
setw -g automatic-rename-format '#{pane_current_command}'

Format bisa dimodifikasi untuk membawa lebih banyak konteks, misalnya nama folder proyek plus program aktif. Catatan penting: begitu sebuah window di-rename secara manual, automatic rename untuk window itu dinonaktifkan otomatis — tmux berasumsi kalian ingin memegang kendali penuh.

Auto-format Status saat Event

Hooks juga bisa mengubah tampilan status bar secara dinamis. Dengan pane-focus-in dan pane-focus-out, kalian bisa menandai pane mana yang sedang aktif dengan mengubah warna status — sangat membantu ketika memantau beberapa proses sekaligus. Ingat, kedua event ini butuh option focus-events on:

Status berubah saat fokus pindah
set -g focus-events on
set-hook -g pane-focus-in 'set -g status-style bg=blue'
set-hook -g pane-focus-out 'set -g status-style bg=default'

Saat kalian memindahkan fokus ke pane lain, status bar berubah warna seketika — tanpa polling, tanpa scripting, murni reaksi terhadap event. Ini menunjukkan kekuatan hooks: tampilan menjadi cerminan kondisi runtime, bukan hasil perhitungan periodik.

Notifikasi Task Selesai

Skenario paling praktis untuk sehari-hari: beri tahu kalian ketika sebuah perintah panjang selesai. Hook pane-exited dipicu tepat saat program keluar, dan display-popup menampilkan pesan tanpa mengganggu fokus kerja:

Notifikasi task selesai
set-hook -g pane-exited 'display-popup -E "echo Task selesai di pane #{pane_index}; sleep 3"'
set-hook -g pane-exited[1] 'run-shell "notify-send tmux task-done"'

Baris pertama membuka popup kecil yang menampilkan "Task selesai" selama tiga detik lalu menutup dirinya sendiri. Baris kedua, jika mesin kalian punya notify-send (paket libnotify di Linux) atau osascript di macOS, memunculkan notifikasi desktop yang tetap terlihat walau kalian sedang berpindah aplikasi. Kombinasi keduanya berarti kalian tidak akan pernah melewatkan momen build selesai — bahkan ketika window tmux sedang tidak terlihat.

Code-group: Hook dan Auto-rename

set-hook -g client-attached 'display-message "client #{client_name} attached"'
set-hook -g session-created 'run-shell "notify-send tmux session-started"'
set-hook -g pane-exited 'display-popup -E "echo Task selesai; sleep 3"'
set-hook -g after-split-window 'select-layout even-horizontal'

Blok pertama menunjukkan hooks yang bereaksi terhadap event; blok kedua menggabungkan automatic rename dengan perubahan status berbasis fokus. Kedua pola ini saling melengkapi: yang pertama membuat tmux memberi tahu kalian, yang kedua membuat tmux menyajikan konteks tanpa kalian bertanya.

Kesalahan Umum (Common Pitfalls)

  1. Menulis hook yang memicu event yang sama. Hook window-layout-changed yang menjalankan select-layout tanpa guard akan berputar tanpa henti. Selalu pakai guard flag atau jangan panggil perintah yang membangkitkan event itu sendiri.
  2. Lupa mengaktifkan focus-events on. pane-focus-in dan pane-focus-out tidak akan pernah terpicu selama option ini off. Periksa dengan tmux show-options -g focus-events sebelum menyalahkan hook.
  3. Menimpa hook yang sudah ada tanpa indeks. set-hook -g pane-exited 'cmd' kedua akan mengganti hook sebelumnya. Untuk menambahkan, gunakan indeks [1], [2], dan seterusnya.
  4. Mengandalkan notify-send di mesin tanpa libnotify. run-shell "notify-send ..." gagal diam-diam di environment yang tidak punya binary itu. Verifikasi dengan menjalankan notify-send langsung dari terminal, atau gunakan fallback display-popup.
  5. Meletakkan logika berat langsung di hook. Setiap event akan membayar biaya eksekusi hook. Delegasikan kerja panjang ke run-shell, dan pastikan setelah selesai tidak memicu event yang mengawalinya.
  6. Mengabaikan efek samping hook global. Hook dengan -g berlaku di semua session, termasuk session produksi orang lain yang attach ke mesin yang sama. Untuk perilaku per-session, pasang hook tanpa -g dengan target tertentu.

Penutup

Episode ini mengubah tmux menjadi sistem yang proaktif. Kalian memahami dua kelompok hooks — event hooks dan after hooks — menguasai sintaks set-hook -g, mengetahui event paling berguna seperti client-attached, session-created, window-layout-changed, dan pane-exited, mengelola urutan eksekusi dengan array index, serta melindungi konfigurasi dari infinite loop. Kalian juga bisa mengintegrasikan hooks dengan tools development: auto-rename window dari pane_current_command, status bar yang berubah saat fokus, dan notifikasi task selesai lewat display-popup.

Poin yang harus kalian bawa:

  • Hooks adalah event listener: set-hook -g <event> <command>.
  • Event hooks dipicu peristiwa; after hooks (after-) dipicu setelah perintah selesai.
  • Hook disimpan sebagai array — gunakan indeks untuk menambah perintah, jangan menimpa [0].
  • Guard flag mencegah infinite loop; jaga hook tetap tipis agar tidak membebani setiap event.

Menulis hook sendiri membuka pintu menuju pola-pola yang sudah dipecahkan komunitas. Di episode 16 selanjutnya kita akan membahas plugin ecosystem dengan TPM — Tmux Plugin Manager, instalasi dan update plugin, serta plugin wajib seperti tmux-sensible, tmux-yank, dan kombinasi resurrect-continuum untuk workflow siap produksi. Sampai jumpa di episode 16!

Belajar Tmux - Hooks & Event-driven Automation | Belajar Tmux