Menghidupkan daftar item lewat aksi reload, event change yang mengikuti query, penjadwalan refresh berkala, serta pelacakan lintas reload dengan --track dan --id-nth. Ditutup dengan kendali fzf dari proses eksternal lewat server HTTP --listen dan Unix domain socket untuk keperluan automation dan tooling.

Di episode 15 kalian merangkai aksi dengan --bind — termasuk reload, yang kalian pakai untuk memperbarui daftar git add tanpa meninggalkan fzf. Episode itu memberi satu sentuhan pada daftar yang hidup. Episode 16 ini membuka semua keran: bagaimana membuat daftar fzf benar-benar hidup — berubah mengikuti query, disegarkan berkala, tetap melacak item yang sama lintas reload, dan bahkan dikendalikan oleh program lain sepenuhnya di luar fzf.
Tiga wilayah yang akan kita taklukkan. Pertama, dynamic reload: aksi reload, event change yang memicu reload saat query berubah, dan penjadwalan refresh berkala untuk daftar yang terus bergerak seperti daftar proses. Kedua, pelacakan lintas reload: opsi --track dan --id-nth sejak fzf 0.71 agar kursor tidak "meloncat" ke item lain setiap kali daftar diperbarui. Ketiga, --listen: server HTTP bawaan fzf yang memungkinkan proses eksternal mengirim aksi lewat HTTP dan Unix domain socket — pintu masuk ke automation dan tooling.
reload: Mengganti Daftar Saat JalanAksi reload(perintah) mengganti seluruh daftar item dengan output perintah yang diberikan — tanpa menutup fzf. Kursor tetap di tempat, query tetap seperti adanya, hanya daftar yang berganti. Ini analog dengan menukar baki barang di konveyor: pekerjaannya sama, isi baki yang baru.
ps -ef | fzf --bind 'ctrl-r:reload(ps -ef)'Varian reload-sync melakukan hal yang sama tetapi menunggu perintah selesai sebelum melanjutkan — penting ketika langkah berikutnya bergantung pada hasil daftar yang baru, misalnya saat --multi dan seleksi harus dipetakan ulang ke item yang baru.
Note
Perbedaan reload dan reload-sync bukan soal kecepatan, melainkan soal sinkronitas. reload berjalan asinkron: fzf meneruskan input dan terus bekerja. reload-sync memblokir sampai proses selesai. Untuk daftar yang besar atau perintah yang mahal, reload-sync membuat UI sempat "menunggu" — pilih sesuai kebutuhan, bukan secara acak.
change: Reload yang Mengikuti QueryEvent change dipicu setiap kali query berubah. Menggabungkannya dengan reload menghasilkan pola paling terkenal di ekosistem fzf: delegasi pencarian ke ripgrep. fzf tidak lagi menyaring sendiri; ia mengirim query ke rg dan menampilkan hasilnya. Karena itu fzf dimatikan dari tugas filtering dengan --disabled:
fzf --disabled --bind 'change:reload:rg -l {q} || true' \
--preview 'bat --color=always {}'Bacanya: setiap kali kalian mengetik, fzf menjalankan rg -l <query>; baris yang cocok masuk sebagai daftar baru; || true mencegah error ketika tidak ada yang cocok; dan preview membuka file terpilih dengan bat. Hasilnya, pencarian kode yang sebelumnya dibatasi ukuran daftar kini bisa menyelami seluruh repository. Ini pembeda penting: fzf tetap cepat bukan hanya karena algoritmanya, tetapi karena kalian bisa memindahkan beban ke tool yang lebih spesialis.
Tidak semua daftar menunggu interaksi. Daftar proses, log, atau status pod layak diperbarui sendiri secara berkala. Di sinilah event every(N) berperan: event yang dipicu setiap N detik, tersedia di rilis fzf 0.73 ke atas. Daftar proses yang menyegarkan diri sendiri setiap dua detik terlihat seperti htop yang bisa difilter:
fzf --header-lines 1 --track --id-nth 2 \
--bind 'start,every(2):reload-sync:ps -ef'Tip
Perhatikan dua opsi pada contoh di atas: --track --id-nth 2. Tanpa keduanya, setiap reload me-reset kursor ke item pertama — tidak nyaman saat kalian sedang membidik satu proses di tengah daftar. Dengan --id-nth 2, fzf mengidentifikasi item lewat field kedua (kolom PID pada ps -ef), lalu melacak baris yang sama di daftar yang baru. Inilah fitur yang kita bahas berikutnya.
--track dan --id-nthSebelum fzf 0.71, reload selalu dianggap "daftar baru yang tidak ada hubungannya": seleksi multi hilang dan pelacakan mati. --id-nth mengubah itu dengan mendefinisikan field identitas — field yang tidak berubah antar reload meskipun kolom lain berganti.
Bayangkan memantau daftar proses: kolom CPU dan memori berubah setiap detik, tetapi PID tidak pernah berubah. Dengan --track --id-nth 1 pada daftar yang field pertamanya PID, fzf bisa menemukan proses yang sama di daftar yang baru dan menjaga kursor tetap di sana:
fzf --track --id-nth 1
fzf --track --id-nth ..Semantik --id-nth sama seperti --nth dari episode 6: angka menunjuk field ke-N dengan pemisah default whitespace, dan .. berarti seluruh baris. Dengan --multi, item yang terpilih pun dipertahankan lintas reload-sync selama identitasnya cocok — seleksi tidak lagi lenyap begitu daftar diperbarui.
--listen: Kendalikan fzf dari LuarSekarang tiba bagian paling menarik untuk automation. Opsi --listen[=ADDR:PORT] menjalankan server HTTP di dalam fzf — sejak fzf 0.52 — yang menerima dua jenis permintaan: POST untuk mengirim aksi (persis seperti yang kalian ikat di --bind), dan GET untuk membaca keadaan program dalam bentuk JSON.
fzf --listen 6266Dari terminal lain — atau dari script, cron, atau webhook — kalian bisa mengirim aksi:
curl -XPOST localhost:6266 -d 'reload(seq 100)+change-prompt(hundred> )'
curl localhost:6266 | jq .Aksi yang dikirim bisa berantai dengan + persis seperti di --bind: reload(seq 100) mengganti daftar, change-prompt(hundred> ) mengubah prompt. Bayangkan skenario nyata: sebuah script menunggu sampai build selesai, lalu memicu reload pada fzf yang sedang menampilkan daftar artefak build — pengguna tidak perlu menekan apa pun.
$FZF_PORTMenyebut port secara manual rawan bentrok. Tanpa nomor, fzf memilih port bebas sendiri dan mengeksposnya sebagai variabel $FZF_PORT untuk proses turunannya:
fzf --listen --bind 'start:execute-silent:echo $FZF_PORT > /tmp/fzf-port'curl "localhost:$(cat /tmp/fzf-port)" -d 'preview:echo siap'Ini pola yang andal untuk tooling: fzf memilih portnya sendiri, memberitahu dunia lewat file, dan script lain menyambung tanpa menebak-nebak.
Untuk komunikasi di mesin yang sama, Unix domain socket lebih ringkas daripada TCP — tidak ada alamat jaringan, tidak ada port yang bisa di-scan, hanya sebuah path. Jika argumen --listen diakhiri .sock, fzf membuat socket di path itu (perilaku yang tersedia sejak 0.66 dan telah menjadi jalur yang stabil di seri 0.74 yang kita pakai), lalu mengekspos path-nya sebagai $FZF_SOCK:
fzf --listen /tmp/fzf.sockcurl --unix-socket /tmp/fzf.sock http -d up--listenServer HTTP yang terbuka adalah pintu — dan pintu butuh kunci. Dua mekanisme melindungi --listen:
$FZF_API_KEY — jika variabel ini disetel, semua permintaan wajib membawa header x-api-key dengan nilai yang sama.--listen hanya menerima koneksi lokal. Menerima koneksi dari jaringan membutuhkan alamat non-localhost dan API key, atau --listen-unsafe yang menonaktifkan proteksi — nama yang tepat untuk sesuatu yang memang tidak aman.export FZF_API_KEY="$(head -c 32 /dev/urandom | base64)"
fzf --listen 6266curl localhost:6266 -H "x-api-key: $FZF_API_KEY" -d 'change-query(yo)'Warning
Perluasan --listen ke jaringan adalah langkah yang harus ditolak kecuali benar-benar perlu. Aksi yang bisa dikirim ke fzf — termasuk reload dan execute — adalah kemampuan eksekusi perintah. Mengikatnya ke alamat yang bisa diakses mesin lain tanpa otentikasi yang kuat sama dengan membuka pintu belakang. Di mesin bersama, biasakan --listen dengan API key, atau gunakan Unix socket yang tidak terlihat oleh jaringan.
Kekuatan penuh --listen terlihat ketika fzf menjadi bagian dari sistem yang lebih besar, bukan aplikasi mandiri. Tiga pola yang langsung berguna:
reload) ketika file berubah — fzf menjadi panel launcher yang dikendalikan dari luar.reload dan change-prompt(sukses> ) — status build tampil di dalam fzf tanpa refresh manual.--expect di sisi pembaca tidak lagi diperlukan karena --listen memungkinkan mengirim aksi setara dari jauh.| Kesalahan | Gejala | Solusi |
|---|---|---|
change:reload tanpa --disabled | Hasil ganda: fzf dan rg sama-sama menyaring | Matikan filtering fzf dengan --disabled |
Lupa || true di reload rg | fzf menutup saat tidak ada hasil | Tambahkan || true di akhir perintah |
| Kursor meloncat tiap reload | Seleksi hilang lintas pembaruan | Pakai --track --id-nth pada field identitas |
| Port bentrok | fzf tidak bisa memulai server | Biarkan fzf memilih port dan baca $FZF_PORT |
--listen tanpa API key di mesin bersama | Siapa pun bisa mengirim aksi | Setel $FZF_API_KEY dan kirim header x-api-key |
Menganggap .sock sebagai port | Socket tidak terbentuk | Path yang diakhiri .sock = Unix socket, bukan port |
Pada episode 16 ini kalian menghidupkan fzf dari berbagai arah: reload dan reload-sync untuk mengganti daftar di tempat; event change yang menjadikan query sebagai kendali pencarian eksternal lewat ripgrep; penjadwalan refresh berkala dengan every(N); pelacakan lintas reload dengan --track dan --id-nth agar kursor dan seleksi tidak meloncat; serta --listen yang membuka fzf sebagai server HTTP dan Unix socket dengan $FZF_PORT, $FZF_SOCK, dan $FZF_API_KEY — dikendalikan penuh oleh proses eksternal.
Pesan untuk dibawa pulang: fzf bukan lagi pemain tunggal — ia komponen yang bisa dipasangi dan dikendalikan dari sistem yang lebih besar.
Semua kekuatan ini, bagaimanapun, masih bergantung pada satu pertanyaan praktis: seberapa cepat fzf mengolah daftar yang kalian berikan? Ketika daftar membengkak ke ratusan ribu atau jutaan item, semuanya kembali ke performa. Di episode 17 kita membahas performance & dataset besar: memilih algoritma dengan --algo, membatasi item, keputusan --sort, meminimalkan beban preview, hingga strategi untuk jutaan item di fzf modern yang skalanya linear antar core CPU.