Belajar Tmux - Custom Script, Plugin Ringan & Status Widget
Series/Belajar Tmux/Episode 17
Episode 17 of 28

Belajar Tmux - Custom Script, Plugin Ringan & Status Widget

Membangun helper tmux sendiri lewat fungsi shell, merancang status widget ringan dengan script eksternal, memecah konfigurasi menjadi modul-modul source-file, serta menyimpan semuanya via versioning.

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

Pendahuluan

Di episode 16 sebelumnya kita membangun fondasi plugin dengan TPM — mendeklarasikan plugin, menginstall lewat prefix + I, mengupdate lewat prefix + U, dan memilih plugin wajib untuk clipboard, persistence, dan widget status. Namun ada kalanya plugin terasa seperti membeli perabot jadi: cocok untuk kebutuhan umum, tetapi kurang pas untuk kebutuhan spesifik kalian sendiri.

Pada episode ini kita membalik perspektif. Alih-alih selalu menambah plugin, kita belajar membangun sendiri: fungsi shell untuk mengotomasi tmux, status widget ringan yang ditulis dalam beberapa baris, dan struktur konfigurasi yang dipecah menjadi modul-modul agar mudah dirawat dan di-versioning. Ini adalah keterampilan yang membedakan pemakai tmux biasa dengan engineer yang benar-benar mengendalikan workflow-nya.

Seluruh contoh merujuk tmux 3.7b sebagai versi stabil terbaru. Target akhirnya sederhana: konfigurasi yang tipis, jelas, dan bisa dipindahkan ke mesin mana pun tanpa drama.

Mengapa Membangun Helper Sendiri

Sebelum menulis baris pertama, penting untuk memahami kapan plugin layak dipakai dan kapan script sendiri lebih masuk akal. Keduanya bukan musuh — keduanya adalah alat dengan trade-off berbeda.

FaktorPlugin (via TPM)Script / Fungsi Sendiri
MaintenanceIkut ekosistem, update via prefix + UDirawat sendiri oleh kalian
BiayaFolder + state per pluginSatu file kecil
KustomisasiSesuai desain penulis pluginPersis sesuai kebutuhan
PortabilitasBergantung prasyarat pluginBergantung tool yang kalian pilih
Kasus PakaiMasalah umum dengan komunitas besarKebutuhan spesifik / internal tim

Analoginya seperti memilih antara membeli alat jadi dan membuat alat sendiri di bengkel. Untuk masalah yang sudah umum — clipboard, persistence — plugin adalah keputusan tepat karena komunitas sudah menguji jutaan kali. Tetapi ketika kalian membutuhkan perintah yang hanya masuk akal di workflow tim sendiri, misalnya "buat session sesuai nama folder proyek", script 15 baris jauh lebih ringan daripada plugin yang mendukung seratus fitur yang tidak pernah kalian pakai.

Fungsi Shell untuk Otomasi Tmux

Jembatan paling alami antara tmux dan shell adalah fungsi. Fungsi shell bisa dijalankan dari mana saja, membaca environment, dan memanggil perintah tmux secara non-interaktif — persis yang kita pelajari dari sisi CLI di episode 13 dan 14.

Contoh paling berguna adalah fungsi untuk membuat session per proyek. Simpan fungsi berikut di shell config kalian, misalnya ~/.zshrc atau ~/.bashrc:

Fungsi mkt di shell config
mkt() {
  local name="${1:-$(basename "$PWD")}"
  tmux has-session -t "$name" 2>/dev/null || tmux new-session -d -s "$name"
  tmux switch-client -t "$name"
}

Mari bedah setiap baris:

  • Baris kedua menyimpan nama session. Jika kalian memanggil mkt backend, nama yang dipakai adalah backend; jika tanpa argumen, nama diambil dari basename "$PWD" — jadi di folder /home/devnull/work/api-gateway, session otomatis bernama api-gateway.
  • Baris ketiga adalah inti logikanya: tmux has-session -t "$name" memeriksa apakah session sudah ada. Jika belum (ditandai dengan ||), session baru dibuat detached dengan tmux new-session -d -s "$name".
  • Baris keempat mengalihkan client saat ini ke session tersebut dengan tmux switch-client -t "$name".

Kunci dari pola ini adalah flag -d pada new-session. Tanpa -d, tmux akan mencoba menempelkan client ke session baru secara langsung, dan di dalam tmux yang sudah berjalan itu akan membuat konflik. Membuat session detached lalu memindahkan client secara eksplisit adalah pola yang aman di kedua konteks: dari dalam tmux maupun dari shell biasa.

Tip

Pola has-session || new-session ini adalah idiom terpenting dalam otomasi tmux. Kalian akan melihatnya berulang di script tmuxp, sessionizer, dan berbagai tools lain. Begitu kalian paham idiom ini, hampir semua otomasi session terbuka di hadapan kalian.

Status Widget Ringan

Status bar tmux mendukung dua cara menampilkan data dinamis: format variable #{...} yang dievaluasi oleh server, dan komando shell #(...) yang mengeksekusi perintah. Keduanya sering tertukar, padahal perilakunya berbeda.

Format variable dievaluasi cepat karena dihitung internal server. Komando shell #() justru mem-spawn proses baru setiap kali dievaluasi — fleksibel, tetapi ada biayanya. Frekuensi evaluasi diatur oleh option status-interval.

Contoh widget paling sederhana adalah menampilkan cabang git di status bar:

Status right dengan git branch
set -g status-interval 5
set -g status-right '#[fg=green]#(git rev-parse --abbrev-ref HEAD 2>/dev/null)#[default] %H:%M'

Perhatikan penggunaan 2>/dev/null — ketika kalian berada di direktori yang bukan repo git, git rev-parse mengeluarkan error ke stderr yang bisa merusak status bar. Membuangnya membuat widget diam ketika tidak relevan.

Script Eksternal untuk Widget

Ketika satu baris #(...) mulai terlalu panjang atau membutuhkan logika, pindahkan ke script eksternal. Konvensi yang sehat adalah menaruh semua widget di satu direktori, misalnya ~/.config/tmux/widgets/.

LinuxWidget beban sistem
#!/usr/bin/env bash
if [[ -r /proc/loadavg ]]; then
  read -r load _ < /proc/loadavg
else
  load="$(uptime | awk -F'load average: ' '{print $2}' | cut -d, -f1)"
fi
echo "#[fg=yellow]load ${load}#[default]"

Script ini membaca load average dengan satu trik portabilitas: di Linux, data dibaca langsung dari /proc/loadavg; di platform tanpa file tersebut, nilainya diambil dari output uptime. Hasilnya dicetak dengan format color code yang bisa langsung dipahami status bar.

Agar dapat dieksekusi, beri izin eksekusi, lalu referensikan path-nya di konfigurasi:

Set izin dan referensi script
chmod +x ~/.config/tmux/widgets/loadavg.sh
set -g status-left-length 40
set -g status-left '#[fg=cyan]#(~/.config/tmux/widgets/loadavg.sh)#[default]'

Warning

Setiap kali status-interval habis, tmux menjalankan ulang seluruh widget #(). Logika berat seperti panggilan jaringan atau parsing file besar akan menjadi beban CPU yang tidak perlu. Jaga widget tetap tipis — tampilkan nilai, jangan melakukan kerja berat di dalamnya.

Konfigurasi Modular dengan source-file

Seiring bertambahnya keybinding, tema, plugin, dan widget, satu file ~/.tmux.conf bisa membengkak hingga ratusan baris. Di sinilah source-file berperan: perintah untuk memuat file konfigurasi lain, mirip include di bahasa pemrograman.

Pola modular memecah konfigurasi berdasarkan kepentingan:

LinuxStruktur konfigurasi modular
~/.config/tmux/
  tmux.conf
  keys.conf
  plugins.conf
  theme.conf
  widgets.conf

Pada tmux 3.7b, konfigurasi bisa disimpan di ~/.config/tmux/tmux.conf mengikuti standar XDG — tmux otomatis memakainya selama ~/.tmux.conf tidak ada. File utama kemudian cukup menjadi titik masuk yang memuat modul lain:

tmux.conf dengan source-file
set -g base-index 1
set -g mouse on
 
source-file ~/.config/tmux/keys.conf
source-file ~/.config/tmux/theme.conf
source-file ~/.config/tmux/plugins.conf
source-file ~/.config/tmux/widgets.conf

Keuntungan pemecahan ini nyata di dunia nyata: ketika satu orang mengubah tema, git diff hanya menyentuh theme.conf; ketika menambah keybinding, hanya keys.conf. Kolaborasi tim jadi lebih rapi dan konflik merge lebih mudah diselesaikan. Ingat untuk memuat ulang dengan prefix + r setiap kali salah satu modul berubah.

Tema Modular

Salah satu modul yang paling sering dipisah adalah tema, karena perubahan visual paling sering terjadi. Berikut contoh theme.conf dengan palet Catppuccin Mocha:

theme.conf
set -g status-style 'bg=#1e1e2e,fg=#cdd6f4'
set -g window-status-current-style 'fg=#89b4fa'
set -g pane-border-style 'fg=#45475a'
set -g pane-active-border-style 'fg=#89b4fa'
WarnaNilaiPeran
#1e1e2eMantleBackground status bar
#cdd6f4TextWarna teks default
#89b4faBlueWarna aksen / aktif
#45475aSurfaceBorder pane non-aktif

Karena tema hanya berisi option, memindahkannya ke file terpisah tidak mengubah perilaku sama sekali — hanya menyederhanakan perawatan. Pola yang sama berlaku untuk keys.conf dan widgets.conf.

Layout Reproducible dengan tmuxp

Di episode 14 kita sudah menyentuh tmuxp sebagai alat deklaratif untuk menyusun session. Sekarang kita pakai lebih dalam untuk melengkapi konfigurasi modular: layout yang disimpan sebagai YAML bisa dijalankan ulang kapan saja dan menghasilkan struktur yang identik.

tmuxp.yaml
session_name: web
windows:
  - window_name: editor
    panes:
      - shell_command: nvim
  - window_name: server
    panes:
      - shell_command: npm run dev

File YAML ini menggambarkan sebuah session bernama web dengan dua window: editor yang membuka nvim, dan server yang menjalankan dev server. Bandingkan dengan menulis ulang baris-baris tmux new-window dan tmux send-keys secara manual — file deklaratif jauh lebih mudah dibaca, direview, dan di-versioning.

Load layout tmuxp
tmuxp load tmuxp.yaml

Karena tmuxp hanya memakai command tmux di balik layar, layout yang sama bekerja di mesin mana pun selama tmux terpasang — ideal untuk tim yang ingin menyamakan struktur workspace.

Versioning Konfigurasi

Semua upaya di atas akan sia-sia tanpa versioning. Konfigurasi yang tidak dikelola versi akan mulai berbeda antar mesin, dan perbedaan itulah sumber bug yang paling sulit dilacak.

Pendekatan paling umum adalah menyimpan konfigurasi di repo dotfiles dan menautkannya ke lokasi yang dibaca tmux:

Symlink konfigurasi ke repo dotfiles
mkdir -p ~/dotfiles/tmux
git init ~/dotfiles
ln -s ~/dotfiles/tmux/tmux.conf ~/.tmux.conf

Dengan symlink, kalian hanya punya satu sumber kebenaran: file di dalam repo. Setiap perubahan langsung bisa di-commit, di-review, dan di-rollback. Untuk setup yang lebih rapi dengan banyak tools sekaligus, tools seperti GNU Stow bisa mengelola symlink secara otomatis — tetapi untuk satu konfigurasi tmux, ln -s sudah cukup.

Kesalahan Umum (Common Pitfalls)

  1. Lupa chmod +x pada script widget. Script yang tidak executable hanya akan menampilkan error atau tidak menghasilkan apa pun di status bar. Selalu verifikasi dengan menjalankan script langsung dari terminal sebelum menautkannya ke konfigurasi.
  2. Meletakkan logika berat di widget #(). Widget dieksekusi ulang setiap status-interval. Panggilan jaringan, loop besar, atau parsing file raksasa di dalam widget akan membuat status bar lambat dan membebani CPU.
  3. Memakai path absolut di source-file. source-file /home/user/.config/tmux/theme.conf akan rusak di mesin orang lain. Gunakan ~ atau $HOME agar konfigurasi portabel.
  4. Mengedit file modular tapi lupa reload. File yang dipecah tidak otomatis dimuat ulang. Setelah mengubah theme.conf, kalian tetap harus menekan prefix + r agar perubahan tampak.
  5. Memiliki ~/.tmux.conf dan ~/.config/tmux/tmux.conf sekaligus. Tmux memprioritaskan ~/.tmux.conf; file XDG hanya dipakai ketika file lama tidak ada. Dua file ini akan saling menutupi dan membingungkan. Pilih salah satu.
  6. Versioning tanpa symlink. Menyalin file ke repo dan mengedit dua lokasi berbeda hanya menciptakan dua sumber kebenaran. Gunakan symlink agar repo adalah satu-satunya sumber.

Penutup

Episode ini melengkapi pola pikir kalian: plugin memang hebat, tetapi kemampuan membangun sendiri adalah aset jangka panjang. Kalian kini bisa menulis fungsi shell seperti mkt() yang membuat session per proyek, merancang widget ringan dengan #() dan script eksternal, memecah konfigurasi menjadi modul source-file yang terorganisir, mendeskripsikan layout dengan tmuxp, dan menjaga semuanya tetap sinkron lewat versioning.

Poin yang harus kalian bawa:

  • Idiom has-session || new-session adalah fondasi otomasi session.
  • Widget #() fleksibel tapi harus tipis; naikkan status-interval untuk mengurangi beban.
  • Konfigurasi modular memakai source-file dan XDG, bukan menumpuk ratusan baris dalam satu file.
  • tmuxp mengubah layout menjadi deklaratif, dan symlink membuat versioning menjadi satu sumber kebenaran.

Dengan fondasi lokal yang sudah kokoh, saatnya membawa tmux ke skenario yang paling menentukan: mesin remote. Di episode 18 selanjutnya kita akan membahas remote development dan SSH workflow — bertahan dari koneksi yang terputus, memakai mosh untuk jaringan lambat, menembus jump host, dan menangani nested tmux ketika server juga menjalankan tmux. Sampai jumpa di episode 18!

Belajar Tmux - Custom Script, Plugin Ringan & Status Widget | Belajar Tmux