Skip to content

Instantly share code, notes, and snippets.

@laughingman7743
Last active July 4, 2026 02:12
Show Gist options
  • Select an option

  • Save laughingman7743/e033a9296f8e962ffb9ab60247a28e5a to your computer and use it in GitHub Desktop.

Select an option

Save laughingman7743/e033a9296f8e962ffb9ab60247a28e5a to your computer and use it in GitHub Desktop.
macOS terminal & window-management dotfiles - Ghostty, tmux, yabai, skhd (HackGen Console NF, TokyoNight, Emacs-like keybinds)
# This is the configuration file for Ghostty.
#
# This template file has been automatically created at the following
# path since Ghostty couldn't find any existing config files on your system:
#
# /Users/{USER_NAME}/Library/Application Support/com.mitchellh.ghostty/config
#
# The template does not set any default options, since Ghostty ships
# with sensible defaults for all options. Users should only need to set
# options that they want to change from the default.
#
# Run `ghostty +show-config --default --docs` to view a list of
# all available config options and their default values.
#
# Additionally, each config option is also explained in detail
# on Ghostty's website, at https://ghostty.org/docs/config.
#
# Ghostty can reload the configuration while running by using the menu
# options or the bound key (default: Command + Shift + comma on macOS and
# Control + Shift + comma on other platforms). Not all config options can be
# reloaded while running; some only apply to new windows and others may require
# a full restart to take effect.
# Config syntax crash course
# ==========================
# # The config file consists of simple key-value pairs,
# # separated by equals signs.
# font-family = Iosevka
# window-padding-x = 2
#
# # Spacing around the equals sign does not matter.
# # All of these are identical:
# key=value
# key= value
# key =value
# key = value
#
# # Any line beginning with a # is a comment. It's not possible to put
# # a comment after a config option, since it would be interpreted as a
# # part of the value. For example, this will have a value of "#123abc":
# background = #123abc
#
# # Empty values are used to reset config keys to default.
# key =
#
# # Some config options have unique syntaxes for their value,
# # which is explained in the docs for that config option.
# # Just for example:
# resize-overlay-duration = 4s 200ms
# Appearance
theme = TokyoNight
font-family = "HackGen Console NF"
font-size = 15
adjust-cell-height = 20%
window-padding-x = 10
window-padding-y = 10
window-padding-balance = true
# Translucent background with blur (macOS only)
background-opacity = 0.80
background-blur = 30
# Dim inactive splits so the focused pane stands out
unfocused-split-opacity = 0.7
# Hide the cursor while typing
mouse-hide-while-typing = true
# Make rendered text slightly thicker for better readability
font-thicken = true
# Treat the Option key as Alt so shells receive M-b / M-f / M-d etc.
macos-option-as-alt = true
# Increase scrollback buffer to ~100MB (default is 10MB)
scrollback-limit = 100000000
# Skip confirmation dialog when closing a surface
confirm-close-surface = false
# New splits / windows inherit the current working directory
window-inherit-working-directory = true
# Auto-detect and enable shell integration features (cd history, prompt marks, ...)
shell-integration = detect
# Selection automatically goes to the system clipboard
copy-on-select = clipboard
clipboard-read = allow
clipboard-write = allow
# Strip trailing whitespace from pasted text
# (prevents accidental command execution from copy-pasted text with a trailing newline)
clipboard-trim-trailing-spaces = true
# ----- Quick Terminal: drop-down terminal toggled by Cmd+Shift+T -----
quick-terminal-position = right
quick-terminal-screen = main
quick-terminal-animation-duration = 0.3
keybind = cmd+shift+t=toggle_quick_terminal
# Open the config file in $VISUAL / $EDITOR (Cmd+, is reserved by macOS menu)
keybind = cmd+shift+e=text:ghostty\x20+edit-config\x0d
# Close the current split / tab with the macOS-standard shortcut
keybind = cmd+w=close_surface
# Remap Cmd+T to new_window (native tabs conflict with yabai's tiling)
keybind = cmd+t=new_window
# ----- Emacs-like window split keybinds (C-x prefix) -----
# C-x 2 / 3 / 0 / o : split, close, switch (matches Emacs window commands)
keybind = ctrl+x>2=new_split:down
keybind = ctrl+x>3=new_split:right
keybind = ctrl+x>0=close_surface
keybind = ctrl+x>o=goto_split:next
# Equalize all split sizes (C-x =)
keybind = ctrl+x>equal=equalize_splits
# Font size adjustment (C-x C-= / C-x C-- / C-x C-0)
keybind = ctrl+x>ctrl+equal=increase_font_size:1
keybind = ctrl+x>ctrl+minus=decrease_font_size:1
keybind = ctrl+x>ctrl+0=reset_font_size
#!/usr/bin/env bash
# Pick a URL from captured pane text with fzf, then open it.
# Usage: fzf-url.sh <file>
# The <file> is produced by `tmux capture-pane` + `save-buffer` in the keybind
# (see `bind u` in tmux.conf), which reliably targets the active pane.
set -euo pipefail
file="${1:?usage: fzf-url.sh <file>}"
[ -f "$file" ] || exit 0
url=$(grep -oE '(https?|ftp|file)://[A-Za-z0-9._~:/?#@!$&()*+,;=%-]+' "$file" \
| sed -E 's/[].,);]+$//' \
| awk '!seen[$0]++' \
| fzf --reverse --no-sort --prompt='open url> ') || { rm -f "$file"; exit 0; }
rm -f "$file"
[ -n "${url:-}" ] && open "$url"
onboarding = false
# herdr configuration — ~/.config/herdr/config.toml
# ============================================================================
# tmux からの移行用設定。既存の ~/.config/tmux/tmux.conf のキーバインドを踏襲。
#
# prefix = Ctrl-t (旧 screen `escape ^Tt` 由来。tmux 側と同じ)
#
# 用語対応: workspace ≈ tmux session
# tab ≈ tmux window
# pane ≈ tmux pane
#
# デフォルト設定の全項目は `herdr --default-config` で確認可能。
# 反映は `herdr server reload-config`(起動中)または prefix+r(下で定義)。
# ============================================================================
[theme]
name = "tokyo-night" # tmux status の TokyoNight 配色に合わせる
[terminal]
# tmux の split-window -c "#{pane_current_path}" 相当。新ペイン/タブは元のCWDを継承。
new_cwd = "follow"
[ui]
# tmux の `c`(new-window)と同じく、名前入力プロンプトなしで即タブ作成。
prompt_new_tab_name = false
# バックグラウンド workspace のエージェントが done / 入力待ち(blocked) になった時の通知。
[ui.toast]
# off=無効 / herdr=アプリ内トースト / terminal=端末(Ghostty)経由のデスクトップ通知 /
# system=macOS 通知センターに直接。herdr 外の別アプリ作業中も気づきたいなら "system" か "terminal"。
delivery = "herdr"
[keys]
prefix = "ctrl+t" # tmux: set -g prefix C-t
# ---- Tab(= tmux window)--------------------------------------------------
new_tab = "prefix+c" # tmux: c new-window
next_tab = "prefix+n" # tmux: n next-window
previous_tab = "prefix+p" # tmux: p previous-window
rename_tab = "prefix+comma" # tmux: , rename-window
close_tab = "prefix+ampersand" # tmux: & kill-window
switch_tab = "prefix+1..9" # tmux: 1-9 select-window
# ---- Pane(= tmux pane)---------------------------------------------------
split_vertical = "prefix+|" # tmux: | split-window -h(左右に分割)
split_horizontal = "prefix+minus" # tmux: - split-window -v(上下に分割)
cycle_pane_next = "prefix+o" # tmux: o 次のペインへフォーカス
focus_pane_left = "prefix+h" # tmux(region/resize): h
focus_pane_down = "prefix+j" # j
focus_pane_up = "prefix+k" # k
focus_pane_right = "prefix+l" # l
close_pane = "prefix+x" # tmux(region): 0 kill-pane 相当
zoom = "prefix+z" # tmux 標準の pane zoom
resize_mode = "prefix+shift+r"# tmux(region): ^ 相当(hjkl/矢印でリサイズ、q/Escで抜ける)
# ---- Workspace(= tmux session)------------------------------------------
detach = "prefix+d" # tmux: d detach-client
workspace_picker = "prefix+s" # tmux: s session 一覧(NAVIGATE オーバーレイ)
new_workspace = "prefix+shift+n"# 新規セッション(C-t N)
rename_workspace = "prefix+shift+w"# tmux: $ 相当($ は直接割当が不安定なため shift+w に)
previous_workspace = "prefix+<" # C-t < 前の workspace へ順送り(| と同じくリテラル指定)
next_workspace = "prefix+>" # C-t > 次の workspace へ順送り
# 番号ジャンプ(switch_workspace = "prefix+shift+1..9")は shift+7=& が close_tab(C-t &)と
# 衝突するため未設定。番号で飛びたい場合は要相談(close_tab の移設が必要)。
# ---- その他 ---------------------------------------------------------------
edit_scrollback = "prefix+[" # tmux: [ copy-mode 相当(スクロールバック閲覧)
reload_config = "prefix+r" # tmux: r source-file(設定リロード)
toggle_sidebar = "prefix+b" # サイドバー = session/window 一覧ビュー
# ---- デフォルトとの衝突回避(tmux 側の割当を優先したため退避)-------------
settings = "prefix+shift+s" # 既定 prefix+s → workspace_picker と衝突するため退避
open_notification_target = "prefix+shift+o" # 既定 prefix+o → cycle_pane_next と衝突するため退避
# ---- カスタムコマンド例 ---------------------------------------------------
# tmux の C-t u(fzf URL ピッカー)に相当。herdr は tmux の capture-pane とは
# 仕組みが異なるため、URL 抽出は専用スクリプト化が必要。まずは一例として lazygit:
# [[keys.command]]
# key = "prefix+g"
# type = "pane" # 一時ペインで実行し、終了で閉じる
# command = "lazygit"
[experimental]
# 日本語IME対策(macOS): prefix モード中は一時的にASCII配列へ切替え、
# IME が有効でも prefix コマンド(c / n / | など)を確実に受理する。
switch_ascii_input_source_in_prefix = true
# skhd config for yabai window management.
#
# Modifier choice notes:
# - We avoid `alt -` (Option) alone because Ghostty has `macos-option-as-alt = true`,
# which makes Option act as Meta in the shell (M-b / M-f / M-d for word jumping).
# - We avoid `cmd + alt` because it collides with macOS shortcuts like
# Cmd+Alt+H (Hide Others), Cmd+Alt+M (Minimize), etc.
# - The main modifier is `ctrl + alt`. The third tier (resize) uses `cmd + ctrl + alt`.
# ===== Focus another window (vim-style hjkl) =====
ctrl + alt - h : yabai -m window --focus west
ctrl + alt - j : yabai -m window --focus south
ctrl + alt - k : yabai -m window --focus north
ctrl + alt - l : yabai -m window --focus east
# ===== Swap window position with neighbor =====
shift + ctrl + alt - h : yabai -m window --swap west
shift + ctrl + alt - j : yabai -m window --swap south
shift + ctrl + alt - k : yabai -m window --swap north
shift + ctrl + alt - l : yabai -m window --swap east
# ===== Resize the focused window (40px steps) =====
# The `||` fallback handles edge windows: if pulling left fails (no left edge),
# push the right edge instead, so the same key works regardless of position.
cmd + ctrl + alt - h : yabai -m window --resize left:-40:0 || yabai -m window --resize right:-40:0
cmd + ctrl + alt - l : yabai -m window --resize right:40:0 || yabai -m window --resize left:40:0
cmd + ctrl + alt - j : yabai -m window --resize bottom:0:40 || yabai -m window --resize top:0:40
cmd + ctrl + alt - k : yabai -m window --resize top:0:-40 || yabai -m window --resize bottom:0:-40
# ===== Layout / window state toggles =====
ctrl + alt - e : yabai -m window --toggle split # flip split direction (horizontal <-> vertical)
ctrl + alt - r : yabai -m space --rotate 90 # rotate the entire space 90 degrees
ctrl + alt - b : yabai -m space --balance # equalize all window sizes in the space
ctrl + alt - f : yabai -m window --toggle zoom-fullscreen # zoom focused window to fill the space
ctrl + alt - d : yabai -m window --toggle zoom-parent # zoom focused window to fill its parent container
ctrl + alt - t : yabai -m window --toggle float \
; yabai -m window --grid 4:4:1:1:2:2 # toggle floating and center on screen
# ===== Switch to space (desktop) =====
ctrl + alt - 1 : yabai -m space --focus 1
ctrl + alt - 2 : yabai -m space --focus 2
ctrl + alt - 3 : yabai -m space --focus 3
ctrl + alt - 4 : yabai -m space --focus 4
ctrl + alt - x : yabai -m space --focus recent
# ===== Send focused window to another space (and follow) =====
shift + ctrl + alt - 1 : yabai -m window --space 1; yabai -m space --focus 1
shift + ctrl + alt - 2 : yabai -m window --space 2; yabai -m space --focus 2
shift + ctrl + alt - 3 : yabai -m window --space 3; yabai -m space --focus 3
shift + ctrl + alt - 4 : yabai -m window --space 4; yabai -m space --focus 4
# ===== Switch focus between displays =====
ctrl + alt - n : yabai -m display --focus next
ctrl + alt - p : yabai -m display --focus prev
# ===== Restart yabai (handy after editing yabairc) =====
cmd + ctrl + alt - r : yabai --restart-service
# ~/.config/tmux/tmux.conf
# ============================================================================
# screen-level simplicity + Ghostty-oriented + Emacs-flavored
#
# Two-layer prefix design:
# C-x = Ghostty layer (terminal splits/tabs; configured on the Ghostty side)
# C-t = tmux layer (sessions/windows/panes; this file)
# Different prefixes, so they never clash and coexist at all times.
# Switch layers simply by which prefix you press.
# ============================================================================
# ---- prefix: inherit the old .screenrc `escape ^Tt` --------------------
unbind C-b
set -g prefix C-t
bind C-t send-prefix # C-t C-t sends a literal C-t
# ---- Basics ---------------------------------------------------------------
set -g mouse on # wheel to scroll, click to select pane/window
set -g history-limit 50000 # scrollback
set -sg escape-time 0 # remove ESC/meta-key delay (matters for Emacs/vi)
set -g base-index 1 # window numbering starts at 1
setw -g pane-base-index 1
set -g renumber-windows on # renumber windows when one is closed
set -g focus-events on
set -g set-clipboard on # system clipboard via Ghostty OSC52
setw -g mode-keys emacs # copy-mode uses Emacs keys
set -g status-keys emacs # command-line editing uses Emacs keys
set -g detach-on-destroy off # on session destroy, switch to another (don't exit)
# ---- truecolor (Ghostty) --------------------------------------------------
set -g default-terminal "tmux-256color"
set -as terminal-features ",xterm-ghostty:RGB"
# ---- Extended keys: forward Shift+Enter etc. to apps (e.g. Claude Code) ---
set -s extended-keys on
set -as terminal-features ",xterm-ghostty:extkeys"
# ---- Window operations (screen / tmux standard) ---------------------------
bind c new-window -c "#{pane_current_path}"
bind w choose-tree -Zw # window list
bind , command-prompt -I "#W" "rename-window '%%'"
bind & kill-window
bind n next-window
bind p previous-window
# C-t <1-9> selects a window - left as the tmux default
# ---- Direct pane shortcuts (split in one step) ----------------------------
bind | split-window -h -c "#{pane_current_path}" # split right
bind - split-window -v -c "#{pane_current_path}" # split down
bind o select-pane -t :.+ # go to next pane
# ---- REGION submenu (faithful port of the old .screenrc `bind -c REGION`) --
# Press C-t x, then 2/3/1/0/o/^
bind x switch-client -T region
bind -T region 2 split-window -v -c "#{pane_current_path}" # split (down)
bind -T region 3 split-window -h -c "#{pane_current_path}" # split (right)
bind -T region 1 kill-pane -a # only (kill other panes)
bind -T region 0 kill-pane # remove (this pane)
bind -T region o select-pane -t :.+ # focus (next pane)
bind -T region x select-pane -t :.+ # repeat x to keep focusing
# ^ enters resize mode (hjkl / arrows resize repeatedly; q or Escape to exit)
bind -T region ^ switch-client -T resize
bind -T resize h resize-pane -L 3 \; switch-client -T resize
bind -T resize j resize-pane -D 3 \; switch-client -T resize
bind -T resize k resize-pane -U 3 \; switch-client -T resize
bind -T resize l resize-pane -R 3 \; switch-client -T resize
bind -T resize Left resize-pane -L 3 \; switch-client -T resize
bind -T resize Down resize-pane -D 3 \; switch-client -T resize
bind -T resize Up resize-pane -U 3 \; switch-client -T resize
bind -T resize Right resize-pane -R 3 \; switch-client -T resize
bind -T resize = select-layout tiled \; switch-client -T resize # even out layout
bind -T resize q switch-client -T root
bind -T resize Escape switch-client -T root
# ---- Session persistence (the main goal for Claude Code) ------------------
bind d detach-client
bind s choose-tree -Zs # session list
bind '$' command-prompt -I "#S" "rename-session '%%'"
# ---- copy-mode / misc -----------------------------------------------------
bind '[' copy-mode
bind ']' paste-buffer
bind r source-file ~/.config/tmux/tmux.conf \; display-message "tmux.conf reloaded"
# C-t u : pick a URL from the current pane with fzf (in a popup) and open it.
# capture-pane targets the active pane natively, then the popup runs fzf on it.
bind u capture-pane -J -S -3000 \; save-buffer /tmp/tmux-fzf-url.txt \; delete-buffer \; display-popup -E -w 70% -h 50% "$HOME/.config/tmux/scripts/fzf-url.sh /tmp/tmux-fzf-url.txt"
# ============================================================================
# Status line (subtle TokyoNight-ish palette; mirrors screen's bottom line)
# Left: session name + window list / Right: prefix indicator + date-time
# ============================================================================
set -g status on
set -g status-interval 5
set -g status-justify left
set -g status-style "bg=#1a1b26,fg=#c0caf5"
set -g status-left "#[bg=#7aa2f7,fg=#1a1b26,bold] #S #[bg=#1a1b26,fg=#7aa2f7]"
set -g status-left-length 30
set -g status-right "#[fg=#f7768e]#{?client_prefix,● PREFIX ,}#[fg=#7aa2f7]%Y-%m-%d #[fg=#c0caf5]%H:%M "
set -g status-right-length 40
setw -g window-status-format "#[fg=#565f89] #I #W "
setw -g window-status-current-format "#[bg=#283457,fg=#7aa2f7,bold] #I #W "
setw -g window-status-separator ""
set -g pane-border-style "fg=#283457"
set -g pane-active-border-style "fg=#7aa2f7"
set -g message-style "bg=#7aa2f7,fg=#1a1b26"
set -g mode-style "bg=#283457,fg=#c0caf5"
#!/usr/bin/env sh
# Scripting addition (requires partial SIP disable).
# Uncomment to load on startup; sudoers must allow yabai --load-sa without password.
#
# sudo yabai --load-sa
# yabai -m signal --add event=dock_did_restart action="sudo yabai --load-sa"
# ===== Focus / mouse behavior =====
yabai -m config mouse_follows_focus off
yabai -m config focus_follows_mouse off
# ===== Window appearance =====
yabai -m config window_origin_display default
yabai -m config window_placement second_child
yabai -m config window_topmost off
yabai -m config window_shadow on
# Dim inactive windows to make the focused one stand out
yabai -m config window_opacity on
yabai -m config window_opacity_duration 0.0
yabai -m config active_window_opacity 1.0
yabai -m config normal_window_opacity 0.85
# Window borders disabled (use opacity for focus indication)
yabai -m config window_border off
yabai -m config insert_feedback_color 0xffd75f5f
# ===== Tiling behavior =====
yabai -m config layout bsp
yabai -m config split_ratio 0.50
yabai -m config auto_balance off
# ===== Mouse drag (Fn + drag = move, Fn + right-drag = resize) =====
yabai -m config mouse_modifier fn
yabai -m config mouse_action1 move
yabai -m config mouse_action2 resize
yabai -m config mouse_drop_action swap
# ===== Padding / gaps =====
yabai -m config top_padding 8
yabai -m config bottom_padding 8
yabai -m config left_padding 8
yabai -m config right_padding 8
yabai -m config window_gap 8
# ===== App rules: float (skip tiling) for apps that don't tile well =====
yabai -m rule --add app="^System Settings$" manage=off
yabai -m rule --add app="^System Preferences$" manage=off
yabai -m rule --add app="^System Information$" manage=off
yabai -m rule --add app="^Calculator$" manage=off
yabai -m rule --add app="^Activity Monitor$" manage=off
yabai -m rule --add app="^Installer$" manage=off
yabai -m rule --add app="^1Password$" manage=off
yabai -m rule --add app="^Finder$" title="(Copy|Bin|Info|Connect|Settings|移動)" manage=off
echo "yabai configuration loaded.."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment