Mengotomasi workspace tmux dari command line: perintah non-interaktif seperti new -d dan send-keys, script bootstrap session, layout deklaratif dengan tmuxp dan tmuxinator, serta CLI untuk scripting.

Di episode 13 sebelumnya kita membahas persistence dan data management — menyimpan dan memulihkan session dengan tmux-resurrect dan tmux-continuum, menyelamatkan scrollback dengan capture-pane, serta logging real-time dengan pipe-pane. Kemampuan restore paling berharga justru ketika dipicu dari dalam script, dan itu membawa kita ke satu pertanyaan: bagaimana kalau kita tidak perlu restore sama sekali, karena session memang dibuat ulang secara deterministik dari nol setiap kali?
Pada episode ini kita membahas scripting, otomasi, dan command line: membangun session tanpa interaksi manusia, menyusun layout deklaratif dengan tmuxp dan tmuxinator, serta memakai CLI tmux sebagai fondasi script yang stabil. Target akhirnya adalah workspace yang bisa di-bootstrap dengan satu perintah — di laptop, di CI, maupun di server produksi — dengan hasil yang identik di semua tempat.
Ada perbedaan besar antara "membuka tmux lalu mengatur pane manual" dan "menjalankan satu script yang menyiapkan segalanya". Yang pertama adalah kebiasaan personal; yang kedua adalah artefak yang bisa direproduksi dan dibagikan. Ketika anggota baru tim bergabung, mereka tidak perlu membaca dokumentasi setup yang 20 langkah — cukup jalankan bootstrap.sh dan workspace muncul dalam bentuk yang sama dengan yang dipakai seluruh tim.
Otomasi juga mengubah cara tim menangani environment. Dev server, tester, dan log tailing yang disusun ulang manual setiap pagi adalah pemborosan waktu kumulatif yang besar. Script yang sama juga menjadi bahan pengujian: karena deterministik, ia bisa dijalankan di mesin CI untuk memastikan struktur workspace tidak rusak sebelum manusia menyentuhnya.
Semua yang bisa kalian lakukan lewat keybinding di dalam tmux bisa dilakukan dari shell biasa sebagai perintah non-interaktif. Inilah jembatan antara tmux dan shell yang sudah kita lihat sekilas di episode 12 — dan di sini kita memakainya sebagai bahasa utama.
Kunci seluruh otomasi adalah flag -d pada new-session. Session dibuat detached — server tmux berdiri, session ada, tetapi tidak ada client yang menempel. Ini penting karena script tidak boleh membajak terminal yang sedang aktif:
tmux new -d -s dev -n editor
tmux new -d -s api -n main -c /srv/api
tmux lsBaris pertama membuat session dev dengan window pertama bernama editor. Baris kedua membuat session api yang langsung berada di working directory /srv/api. Baris ketiga memverifikasi bahwa kedua session terdaftar — tanpa satu pun client yang menempel.
Setelah session berdiri, send-keys mengirim keystroke ke pane tertentu seolah-olah kalian mengetiknya. Inilah cara script menjalankan perintah di dalam pane tanpa campur tangan manusia:
tmux send-keys -t dev "cd ~/code/web && nvim ." Enter
tmux send-keys -l "ls -la"
tmux send-keys -t api:0 "make migrate" EnterPerhatikan dua hal. Pertama, Enter dikirim sebagai argumen terakhir — tanpa itu, perintah hanya tertulis di prompt dan tidak dieksekusi. Kedua, flag -l mengirim teks secara literal tanpa interpretasi; pakai -l ketika teks mengandung karakter khusus yang tidak ingin diproses tmux.
Posisi fokus dalam session dikendalikan dengan select-pane dan select-window. Script menyusun workspace lalu menentukan pane mana yang menjadi aktif ketika kalian attach:
tmux select-window -t dev:0
tmux select-pane -t dev:0.1
tmux attach-session -t devBaris pertama memilih window 0, baris kedua memindahkan fokus ke pane nomor 1 di window tersebut, dan baris ketiga menempelkan client. Hasilnya: saat terminal terbuka, kalian langsung berada di pane yang paling sering dipakai — bukan di pane pertama secara acak.
Hampir semua perintah di atas memakai target berbentuk session:window.pane. Inilah alamat lengkap sebuah pane, dan memahaminya adalah syarat menulis script yang tepat sasaran:
| Target | Arti |
|---|---|
dev | Session dev, window aktifnya |
dev:0 | Session dev, window nomor 0 |
dev:editor | Session dev, window bernama editor |
dev:0.1 | Session dev, window 0, pane nomor 1 |
dev:0.%3 | Session dev, window 0, pane dengan ID %3 |
Aturan praktisnya: bagian yang dihilangkan berarti "yang sedang aktif". dev:0.1 adalah bentuk paling eksplisit dan paling aman untuk script, karena tidak bergantung pada keadaan fokus saat itu. Penomoran pane mengikuti pane-base-index yang sudah kita setel di episode 12.
Sekarang mari satukan semuanya dalam satu script lengkap yang menyiapkan workspace development. Script ini memakai idiom has-session || new-session yang sudah kita kenal: jika session sudah ada, jangan membuat duplikat — langsung attach saja.
#!/usr/bin/env bash
project="${1:-$PWD}"
name="$(basename "$project")"
if ! tmux has-session -t "$name" 2>/dev/null; then
tmux new-session -d -s "$name" -c "$project" -n editor
tmux send-keys -t "$name:0" "cd '$project' && nvim ." Enter
tmux new-window -t "$name" -n server -c "$project"
tmux send-keys -t "$name:1" "npm run dev" Enter
tmux new-window -t "$name" -n logs -c "$project"
tmux send-keys -t "$name:2" "tail -f log/app.log" Enter
tmux select-window -t "$name:0"
fi
tmux attach-session -t "$name"Mari bedah alurnya baris demi baris:
basename — di /home/devnull/work/api-gateway, session otomatis bernama api-gateway.if ! tmux has-session mencegah pembuatan ulang session yang sudah hidup; ia sekaligus menjadi kode pengembalian alami, seperti yang akan kita bahas di bagian CLI reference.new-session -d membuat window pertama editor, lalu send-keys membuka Neovim di dalamnya.new-window menambah window server dan logs, masing-masing dengan perintah awal sendiri via -c dan send-keys.select-window memindahkan fokus kembali ke editor, dan attach-session menempelkan client.Simpan sebagai bootstrap-dev.sh, beri izin chmod +x, dan kalian punya satu pintu masuk ke seluruh workspace.
Script shell memberikan kontrol penuh, tetapi untuk layout yang lebih kompleks, menulis serangkaian new-window dan send-keys menjadi bertele-tele. Di sinilah tmuxp dan tmuxinator masuk: keduanya mendeskripsikan session sebagai file konfigurasi — YAML di tmuxp, dan YAML juga di tmuxinator — dan membangun session dari deskripsi tersebut. Layout menjadi dokumen yang bisa di-review, bukan urutan perintah yang harus dibaca baris demi baris.
session_name: web
start_directory: ~/code/web
windows:
- window_name: editor
panes:
- shell_command: nvim .
- window_name: server
layout: main-horizontal
panes:
- shell_command: npm run dev
- shell_command: tail -f log/app.logFile ini menggambarkan session web dengan dua window: editor yang membuka Neovim, dan server dengan layout main-horizontal berisi dev server dan log tailing. Menjalankannya cukup satu perintah:
tmuxp load tmuxp.yamlPendekatan tmuxinator hampir identik, dengan struktur YAML yang sedikit berbeda:
name: web
root: ~/code/web
windows:
- editor: nvim .
- server:
layout: main-horizontal
panes:
- npm run dev
- tail -f log/app.logtmuxinator start webMana yang dipilih? Ini perbandingan praktisnya:
| Aspek | tmuxp | tmuxinator |
|---|---|---|
| Format | YAML, daftar shell_command | YAML, daftar perintah singkat |
| Penempatan file | Di mana saja, dipanggil via tmuxp load | ~/.config/tmuxinator/ |
| Mode interaktif | tmuxp freeze bisa menangkap layout saat ini | Tidak ada |
| Ekosistem | Python, dipakai luas di dotfiles modern | Ruby, populer di kalangan lama |
Keduanya membangun session dengan memanggil perintah tmux yang sama yang sudah kita pelajari — jadi pemahaman command line yang kalian bangun di episode ini tetap berlaku di balik layar kedua alat tersebut.
Tidak perlu menghafal seluruh perintah tmux. tmux list-commands mencetak daftar lengkap perintah beserta sintaksnya — ini cheat sheet yang selalu up-to-date dengan versi terpasang:
tmux list-commands
tmux list-commands new-session
tmux show-options -g base-indexBaris pertama menampilkan semua perintah, baris kedua menampilkan detail new-session, dan baris ketiga menunjukkan bahwa show-options juga bisa dijadikan referensi nilai default. Untuk scripting, perintah list-sessions, list-windows, dan list-panes adalah sumber data struktur session.
Output perintah list bisa dibentuk dengan flag -F dan format string — teknik yang memakai variabel format yang kita pelajari di episode 9. Ini yang membuat parsing menjadi deterministik:
tmux list-sessions -F '#{session_name}'
tmux list-panes -t dev:0 -F 'pane #{pane_index}: #{pane_current_command}'
tmux list-sessions -F '#{session_name}' | grep -x devFormat -F menggantikan bentuk visual biasa dengan baris data yang konsisten — satu field per placeholder — sehingga grep, awk, atau cut bisa memprosesnya tanpa tersendat teks dekoratif.
Script menentukan langkah selanjutnya dari exit code perintah tmux. Yang paling berguna adalah has-session: ia keluar dengan kode 0 jika session ada, dan 1 jika tidak. Inilah fondasi idiom yang kita pakai di script bootstrap tadi.
if tmux has-session -t dev 2>/dev/null; then
echo "session dev ada"
else
echo "session dev belum ada"
fiDengan memeriksa exit code, script menjadi idempotent: menjalankannya dua kali tidak menimbulkan efek samping. Ini prinsip penting untuk semua otomasi yang akan dijalankan berulang, termasuk dari cron atau CI.
Enter pada send-keys. Tanpa Enter, perintah hanya menumpuk di prompt dan tidak pernah dieksekusi. Selalu akhiri urutan keystroke dengan Enter kecuali memang sengaja ingin membiarkan prompt menunggu.new-session tanpa -d di dalam tmux. Tanpa -d, tmux mencoba menempelkan client ke session baru dan konflik dengan session aktif. Buat detached, lalu attach-session atau switch-client secara eksplisit.has-session. Script yang membuat session tanpa pemeriksaan akan menumpuk session duplikat setiap kali dijalankan. Selalu pakai idiom has-session atau buat idempotent.pane-base-index. Script yang mengasumsikan pane dimulai dari 0 akan salah sasaran di mesin yang menyetel setw -g pane-base-index 1. Tulis target dengan ID pane atau pastikan index konsisten di semua mesin.start_directory: /home/username/... rusak di mesin orang lain. Gunakan ~ atau variabel seperti $HOME.new-session gagal, perintah send-keys berikutnya akan gagal dengan pesan yang membingungkan. Periksa exit code dan berhenti lebih awal dengan set -e atau guard eksplisit.Episode ini mengubah kalian dari pengguna tmux menjadi pembuat workspace. Kalian memahami perintah non-interaktif — new -d, send-keys, select-pane, select-window — beserta target sintaks session:window.pane, bisa menulis script bootstrap yang idempotent, mendeskripsikan layout deklaratif dengan tmuxp dan tmuxinator, serta membaca CLI tmux sebagai sumber data dan sinyal lewat exit code.
Poin yang harus kalian bawa:
-d + send-keys adalah kombinasi dasar semua otomasi tmux.session:window.pane yang eksplisit membuat script deterministik.has-session membuat script idempotent dan aman dijalankan ulang.Script membangun struktur; selanjutnya kita membuat tmux bereaksi terhadap apa yang terjadi di dalam struktur itu. Di episode 15 selanjutnya kita akan membahas hooks dan event-driven automation — memicu perintah otomatis pada event seperti pane-exited dan client-attached, mengintegrasikannya dengan tools development, serta menghindari infinite loop. Sampai jumpa di episode 15!