Skip to content

Instantly share code, notes, and snippets.

@aserper
Created September 19, 2025 17:54
Show Gist options
  • Select an option

  • Save aserper/24350ba2a89b7801bcff272b8ddf89a1 to your computer and use it in GitHub Desktop.

Select an option

Save aserper/24350ba2a89b7801bcff272b8ddf89a1 to your computer and use it in GitHub Desktop.
local wezterm = require("wezterm")
local act = wezterm.action
local mux = wezterm.mux
local config = wezterm.config_builder()
-- Session Management Plugin
local workspace_switcher = wezterm.plugin.require("https://github.com/MLFlexer/smart_workspace_switcher.wezterm")
workspace_switcher.zoxide_path = "/usr/bin/zoxide"
-- Font configuration (exactly matching ghostty config)
config.font = wezterm.font("CaskaydiaMono Nerd Font")
config.font_size = 12
config.harfbuzz_features = { "liga", "calt" }
config.font_rules = {
{
intensity = "Bold",
font = wezterm.font("CaskaydiaMono Nerd Font", { weight = "Bold" }),
},
{
italic = true,
font = wezterm.font("CaskaydiaMono Nerd Font", { style = "Italic" }),
},
{
intensity = "Bold",
italic = true,
font = wezterm.font("CaskaydiaMono Nerd Font", { weight = "Bold", style = "Italic" }),
},
}
config.cell_width = 1.0
config.line_height = 1.1
config.adjust_window_size_when_changing_font_size = false
-- Font rendering to match ghostty (enhanced)
config.freetype_load_target = "Light"
config.freetype_render_target = "HorizontalLcd"
config.freetype_load_flags = "NO_HINTING"
-- Disable custom rendering that might interfere
config.custom_block_glyphs = false
config.use_cap_height_to_scale_fallback_fonts = false
-- Window configuration
config.window_padding = {
left = 14,
right = 14,
top = 14,
bottom = 14,
}
config.window_decorations = "NONE"
config.enable_wayland = false
config.window_background_opacity = 0.98
config.text_background_opacity = 1.0
-- Focus follows mouse (from Ghostty)
config.pane_focus_follows_mouse = true
-- Background blur and visual effects
config.macos_window_background_blur = 20
config.window_background_gradient = {
orientation = "Vertical",
colors = {
"#1a1b26",
"#16161e",
},
}
-- Cursor configuration
config.default_cursor_style = "BlinkingUnderline"
config.cursor_blink_rate = 1000
config.cursor_blink_ease_in = "Constant"
config.cursor_blink_ease_out = "Constant"
-- Tokyo Night theme colors
config.colors = {
foreground = "#a9b1d6",
background = "#1a1b26",
cursor_bg = "#a9b1d6",
cursor_fg = "#1a1b26",
cursor_border = "#a9b1d6",
selection_fg = "#1a1b26",
selection_bg = "#7aa2f7",
scrollbar_thumb = "#444b6a",
split = "#32344a",
ansi = {
"#32344a", -- black
"#f7768e", -- red
"#9ece6a", -- green
"#e0af68", -- yellow
"#7aa2f7", -- blue
"#ad8ee6", -- magenta
"#449dab", -- cyan
"#787c99", -- white
},
brights = {
"#444b6a", -- bright black
"#ff7a93", -- bright red
"#b9f27c", -- bright green
"#ff9e64", -- bright yellow
"#7da6ff", -- bright blue
"#bb9af7", -- bright magenta
"#0db9d7", -- bright cyan
"#acb0d0", -- bright white
},
}
-- Enhanced tab bar configuration (blog post style)
config.enable_tab_bar = true
config.use_fancy_tab_bar = false
config.tab_bar_at_bottom = false
config.hide_tab_bar_if_only_one_tab = false
config.show_new_tab_button_in_tab_bar = false
config.tab_max_width = 32
-- Custom tab styling
config.colors.tab_bar = {
background = "#1a1b26",
active_tab = {
bg_color = "#7aa2f7",
fg_color = "#1a1b26",
intensity = "Bold",
},
inactive_tab = {
bg_color = "#32344a",
fg_color = "#787c99",
},
inactive_tab_hover = {
bg_color = "#444b6a",
fg_color = "#a9b1d6",
},
new_tab = {
bg_color = "#32344a",
fg_color = "#787c99",
},
new_tab_hover = {
bg_color = "#444b6a",
fg_color = "#a9b1d6",
},
}
-- Scrollback and scrolling enhancements
config.scrollback_lines = 10000
config.enable_scroll_bar = true
config.mouse_wheel_scrolls_tabs = false
-- Default shell command to ensure prompt loads properly
config.default_prog = { "/bin/bash", "-l", "-c", "exec bash" }
-- Keybindings
config.keys = {
-- Fullscreen toggle
{ key = "F11", action = wezterm.action.ToggleFullScreen },
-- Tab management
{ key = "t", mods = "CTRL|SHIFT", action = wezterm.action.SpawnTab("CurrentPaneDomain") },
{ key = "q", mods = "CTRL|SHIFT", action = wezterm.action.CloseCurrentTab({ confirm = true }) },
{ key = "RightArrow", mods = "CTRL|SHIFT", action = wezterm.action.ActivateTabRelative(1) },
{ key = "LeftArrow", mods = "CTRL|SHIFT", action = wezterm.action.ActivateTabRelative(-1) },
-- Workspace management
{ key = "s", mods = "CTRL|SHIFT", action = workspace_switcher.switch_workspace() },
{ key = "w", mods = "CTRL|SHIFT", action = act.ShowLauncherArgs({ flags = "FUZZY|WORKSPACES" }) },
{ key = "LeftBracket", mods = "CTRL|SHIFT", action = act.SwitchWorkspaceRelative(-1) },
{ key = "RightBracket", mods = "CTRL|SHIFT", action = act.SwitchWorkspaceRelative(1) },
{ key = "d", mods = "CTRL|SHIFT", action = act.SwitchToWorkspace({ name = "default" }) },
-- Direct tab switching with Alt+Ctrl+number
{ key = "1", mods = "ALT|CTRL", action = wezterm.action.ActivateTab(0) },
{ key = "2", mods = "ALT|CTRL", action = wezterm.action.ActivateTab(1) },
{ key = "3", mods = "ALT|CTRL", action = wezterm.action.ActivateTab(2) },
{ key = "4", mods = "ALT|CTRL", action = wezterm.action.ActivateTab(3) },
{ key = "5", mods = "ALT|CTRL", action = wezterm.action.ActivateTab(4) },
{ key = "6", mods = "ALT|CTRL", action = wezterm.action.ActivateTab(5) },
{ key = "7", mods = "ALT|CTRL", action = wezterm.action.ActivateTab(6) },
{ key = "8", mods = "ALT|CTRL", action = wezterm.action.ActivateTab(7) },
{ key = "9", mods = "ALT|CTRL", action = wezterm.action.ActivateTab(8) },
-- Tmux-style pane splitting (prefix key approach)
{
key = "a",
mods = "CTRL",
action = wezterm.action.ActivateKeyTable({
name = "tmux_mode",
one_shot = true,
timeout_milliseconds = 1000,
}),
},
-- Pane navigation
{ key = "h", mods = "CTRL|SHIFT", action = wezterm.action.ActivatePaneDirection("Left") },
{ key = "l", mods = "CTRL|SHIFT", action = wezterm.action.ActivatePaneDirection("Right") },
{ key = "k", mods = "CTRL|SHIFT", action = wezterm.action.ActivatePaneDirection("Up") },
{ key = "j", mods = "CTRL|SHIFT", action = wezterm.action.ActivatePaneDirection("Down") },
-- Search functionality
{ key = "f", mods = "CTRL|SHIFT", action = wezterm.action.Search({ CaseInSensitiveString = "" }) },
-- Command palette
{ key = "p", mods = "CTRL|SHIFT", action = wezterm.action.ActivateCommandPalette },
-- Copy/paste enhancements with popup notification
{
key = "c",
mods = "CTRL|SHIFT",
action = wezterm.action.Multiple({
wezterm.action.CopyTo("Clipboard"),
wezterm.action.EmitEvent("show-copy-notification"),
}),
},
{ key = "v", mods = "CTRL|SHIFT", action = wezterm.action.PasteFrom("Clipboard") },
-- Scrolling shortcuts
{ key = "PageUp", mods = "SHIFT", action = wezterm.action.ScrollByPage(-1) },
{ key = "PageDown", mods = "SHIFT", action = wezterm.action.ScrollByPage(1) },
{ key = "Home", mods = "SHIFT", action = wezterm.action.ScrollToTop },
{ key = "End", mods = "SHIFT", action = wezterm.action.ScrollToBottom },
-- Window management
{ key = "z", mods = "CTRL|SHIFT", action = wezterm.action.TogglePaneZoomState },
{ key = "=", mods = "CTRL", action = wezterm.action.IncreaseFontSize },
{ key = "-", mods = "CTRL", action = wezterm.action.DecreaseFontSize },
{ key = "0", mods = "CTRL", action = wezterm.action.ResetFontSize },
-- Pane resizing
{ key = "LeftArrow", mods = "CTRL|ALT", action = wezterm.action.AdjustPaneSize({ "Left", 5 }) },
{ key = "RightArrow", mods = "CTRL|ALT", action = wezterm.action.AdjustPaneSize({ "Right", 5 }) },
{ key = "UpArrow", mods = "CTRL|ALT", action = wezterm.action.AdjustPaneSize({ "Up", 5 }) },
{ key = "DownArrow", mods = "CTRL|ALT", action = wezterm.action.AdjustPaneSize({ "Down", 5 }) },
}
-- Performance optimizations
config.front_end = "OpenGL"
-- Enhanced visual effects
config.inactive_pane_hsb = {
saturation = 0.9,
brightness = 0.85,
}
-- Selection and copy behavior
config.selection_word_boundary = " \t\n{}[]()\"'`"
config.bypass_mouse_reporting_modifiers = "SHIFT"
-- Visual bell instead of audio (subtle)
config.audible_bell = "Disabled"
config.visual_bell = {
fade_in_function = "EaseIn",
fade_in_duration_ms = 75,
fade_out_function = "EaseOut",
fade_out_duration_ms = 75,
}
config.colors.visual_bell = "#444b6a"
-- Oh-my-tmux style key table (prefix mode: Ctrl+A)
config.key_tables = {
tmux_mode = {
-- Split panes (simple keys)
{ key = "v", action = wezterm.action.SplitHorizontal({ domain = "CurrentPaneDomain" }) }, -- vertical split (pane to right)
{ key = "h", action = wezterm.action.SplitVertical({ domain = "CurrentPaneDomain" }) }, -- horizontal split (pane below)
-- Oh-my-tmux additional split bindings
{ key = "-", action = wezterm.action.SplitVertical({ domain = "CurrentPaneDomain" }) }, -- split horizontally (pane below)
{ key = "_", action = wezterm.action.SplitHorizontal({ domain = "CurrentPaneDomain" }) }, -- split vertically (pane right)
-- Pane navigation (using arrow keys to avoid conflict with split)
{ key = "LeftArrow", action = wezterm.action.ActivatePaneDirection("Left") },
{ key = "DownArrow", action = wezterm.action.ActivatePaneDirection("Down") },
{ key = "UpArrow", action = wezterm.action.ActivatePaneDirection("Up") },
{ key = "RightArrow", action = wezterm.action.ActivatePaneDirection("Right") },
-- Pane resizing (oh-my-tmux style)
{ key = "H", action = wezterm.action.AdjustPaneSize({ "Left", 2 }) },
{ key = "J", action = wezterm.action.AdjustPaneSize({ "Down", 2 }) },
{ key = "K", action = wezterm.action.AdjustPaneSize({ "Up", 2 }) },
{ key = "L", action = wezterm.action.AdjustPaneSize({ "Right", 2 }) },
-- Pane swapping (oh-my-tmux style)
{ key = ">", action = wezterm.action.RotatePanes("Clockwise") },
{ key = "<", action = wezterm.action.RotatePanes("CounterClockwise") },
-- Maximize current pane (oh-my-tmux +)
{ key = "+", action = wezterm.action.TogglePaneZoomState },
-- Window navigation (oh-my-tmux style)
{ key = "h", mods = "CTRL", action = wezterm.action.ActivateTabRelative(-1) },
{ key = "l", mods = "CTRL", action = wezterm.action.ActivateTabRelative(1) },
{ key = "Tab", action = wezterm.action.ActivateLastTab },
-- Session/window management
{ key = "c", mods = "CTRL", action = wezterm.action.SpawnTab("CurrentPaneDomain") }, -- new session (closest to new tab)
{ key = "c", action = wezterm.action.SpawnTab("CurrentPaneDomain") }, -- new window (tab)
-- Config reload (oh-my-tmux 'r')
{ key = "r", action = wezterm.action.ReloadConfiguration },
-- Clear screen and history (oh-my-tmux Ctrl+l)
{
key = "l",
mods = "CTRL",
action = wezterm.action.Multiple({
wezterm.action.SendKey({ key = "l", mods = "CTRL" }),
wezterm.action.ClearScrollback("ScrollbackAndViewport"),
}),
},
-- Close current pane
{ key = "x", action = wezterm.action.CloseCurrentPane({ confirm = true }) },
-- Pane management
{ key = "z", action = wezterm.action.TogglePaneZoomState }, -- toggle zoom (duplicate of +)
{ key = "o", action = wezterm.action.ActivatePaneByIndex(0) }, -- cycle through panes
{ key = "q", action = wezterm.action.PaneSelect }, -- show pane numbers
{ key = "{", action = wezterm.action.RotatePanes("CounterClockwise") }, -- move pane left
{ key = "}", action = wezterm.action.RotatePanes("Clockwise") }, -- move pane right
{ key = "!", action = wezterm.action.SpawnTab("CurrentPaneDomain") }, -- break pane into new tab
{ key = ";", action = wezterm.action.ActivateLastTab }, -- go to last active (using tab as closest equivalent)
-- Exit tmux mode
{ key = "Escape", action = "PopKeyTable" },
{ key = "a", mods = "CTRL", action = "PopKeyTable" }, -- double Ctrl+A to exit
},
}
-- Custom tab title formatting (from blog post)
local function get_current_working_dir(tab)
local current_dir = tab.active_pane and tab.active_pane.current_working_dir or { file_path = "" }
local HOME_DIR = string.format("file://%s", os.getenv("HOME"))
return current_dir.file_path == HOME_DIR and "~" or string.gsub(current_dir.file_path, "(.*[/\\])(.*)", "%2")
end
wezterm.on("format-tab-title", function(tab, tabs, panes, config, hover, max_width)
local has_unseen_output = false
if not tab.is_active then
for _, pane in ipairs(tab.panes) do
if pane.has_unseen_output then
has_unseen_output = true
break
end
end
end
-- Get the window title (what applications set dynamically)
local window_title = tab.active_pane.title or ""
-- Get current working directory
local cwd = get_current_working_dir(tab)
-- Format: [1] app_title (directory) or [1] directory if no title
local title
if window_title and window_title ~= "" and window_title ~= cwd then
title = string.format(" [%s] %s (%s) ", tab.tab_index + 1, window_title, cwd)
else
title = string.format(" [%s] %s ", tab.tab_index + 1, cwd)
end
if has_unseen_output then
return {
{ Foreground = { Color = "#bb9af7" } }, -- Tokyo Night purple for unseen output
{ Text = title },
}
end
return {
{ Text = title },
}
end)
-- Startup workspace configuration
wezterm.on("gui-startup", function(cmd)
-- Create a default workspace with the home directory
local home_path = wezterm.home_dir
local tab, pane, window = mux.spawn_window({
workspace = "default",
cwd = home_path,
})
mux.set_active_workspace("default")
end)
-- Copy notification popup (simple and clean)
local copy_notification_visible = false
wezterm.on("show-copy-notification", function(window, pane)
copy_notification_visible = true
-- Clear notification after 1 second
wezterm.time.call_after(1.0, function()
copy_notification_visible = false
end)
end)
-- Status handling for notifications, tmux mode, and workspace display
wezterm.on("update-right-status", function(window, pane)
local key_table = window:active_key_table()
if copy_notification_visible then
window:set_right_status(wezterm.format({
{ Background = { Color = "#32344a" } },
{ Foreground = { Color = "#a9b1d6" } },
{ Text = " ✓ COPIED " },
}))
elseif key_table == "tmux_mode" then
window:set_right_status(wezterm.format({
{ Background = { Color = "#e0af68" } },
{ Foreground = { Color = "#1a1b26" } },
{ Text = " TMUX MODE " },
}))
else
-- Show current workspace name (including default)
local workspace_name = window:active_workspace()
if workspace_name then
window:set_right_status(wezterm.format({
{ Background = { Color = "#7aa2f7" } },
{ Foreground = { Color = "#1a1b26" } },
{ Text = " " .. workspace_name .. " " },
}))
else
window:set_right_status("")
end
end
end)
return config
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment