Skip to content

Speed up fish prompt and mise activation#316

Merged
djensenius merged 7 commits into
mainfrom
optimize-fish-mise-prompt
May 19, 2026
Merged

Speed up fish prompt and mise activation#316
djensenius merged 7 commits into
mainfrom
optimize-fish-mise-prompt

Conversation

@djensenius
Copy link
Copy Markdown
Owner

@djensenius djensenius commented May 19, 2026

Summary

This PR is a performance pass over interactive shell/tmux startup paths. It keeps the existing workflows and visual setup, but removes repeated work from prompt rendering, mise activation, tmux window labels, tmuxinator startup, and tmux plugin startup.

Performance results

Area Before After Savings Change
Starship right prompt ~0.9-1.2s ~19-21ms ~0.9-1.2s per prompt Custom jj modules run with sh instead of Fish and skip work outside .jj repos.
Fish startup noticeably slower from duplicate mise activation ~0.10s avoided duplicate activation Disabled Homebrew's vendor mise activate fish with MISE_FISH_AUTO_ACTIVATE=0.
Mise hook on Enter ran on every prompt no prompt hook avoids repeated prompt work Replaced default prompt hook with startup activation plus a PWD change hook.
Mise PWD env refresh repeated prompt-time work ~8-10ms only on directory changes prompt stays fast mise hook-env -s fish runs only when PWD changes.
Mise remote/tool resolution repeated GitHub/version lookups and rate-limit warnings cached for 1h avoids repeated network/version checks Enabled mise env/version caches and used gh auth token for GitHub API auth.
Starship custom jj modules Fish startup for each custom module shell + .jj guard right prompt down to ~20ms Uses cheap guard before calling jj.
Tmux contextual window label helper ~70-100ms per common pane label ~10-20ms ~50-90ms per label render Added shell fast path for common fish/nvim panes; Python fallback remains.
Tmux status refresh helpers ran every 1s every 5s fewer recurring helper processes Raised status-interval from 1 to 5.
pt / personal tmux session launcher ~7.6-7.7s via tmuxinator ~3.2s cold before async TPM ~4.4s Replaced only pt with a direct Fish function that creates the same personal session layout.
Tmux cold startup ~2.1-2.3s ~0.02-0.03s immediate return ~2.1s TPM now loads asynchronously in the background.
pt after async TPM ~3.2s cold path ~0.03s immediate return ~3.1s Direct pt launcher benefits from async TPM.

Key findings

Finding Evidence Resolution
Tmux itself was not slow Minimal tmux startup measured ~20-30ms. Full config measured ~2.1-2.3s. Focused on TPM/plugin loading rather than tmux core.
TPM was the cold-start bottleneck Removing only the TPM runner dropped startup to ~30ms. Moved TPM into a background loader.
Missing npm@latest made mise noisy/slow Mise tried GitHub npm/cli release lookups and hit rate limits when npm was missing. Kept npm = 'latest' after installing it locally and added caching/auth.
Starship right prompt was dominated by custom shell modules jj custom modules were running through Fish and costing close to a second. Switched custom module shell to sh and added .jj guards.
tmuxinator start personal was much slower than equivalent tmux commands tmuxinator start personal --no-attach measured ~7.6-7.7s; direct equivalent was much faster. Added a dedicated pt Fish function for the personal session only.

Files changed by area

Area Files Purpose
Mise caching/auth mise/config.toml Cache remote version/env data for 1h and authenticate GitHub requests via gh auth token.
Fish/mise activation fish/conf.d/00-env.fish, fish/config.fish Disable duplicate Homebrew mise auto-activation and run mise env refresh on startup/PWD change only.
Prompt speed starship.toml Make custom jj prompt modules cheaper.
Tmux status/window labels tmux/tmux.conf, scripts/tmux-contextual-window-name-fast.sh, scripts/tmux-show-outdated.sh Reduce recurring status work and speed common contextual window labels.
Personal tmux launcher fish/conf.d/21-aliases.fish, fish/functions/pt.fish Replace pt tmuxinator alias with a direct session launcher.
Async TPM tmux/tmux.conf, scripts/tmux-load-plugins.sh Load plugins in the background and show loading/failure status.
Misc user changes included bat/config, fish/completions/copilot.fish Bat theme naming and Copilot completion update.

Tmux async loading details

Tmux startup was split into two phases:

Phase Behavior
Immediate startup Tmux creates the server/session and becomes usable in ~20-30ms.
Background plugin load scripts/tmux-load-plugins.sh runs TPM, then reapplies post-tpm.conf, status-style, mouse/mode settings, and post-catppuccin.conf.
Status indicator loading plugins appears in yellow while loading; it clears on success and shows plugin load failed in red on failure.
Settle time Plugin keybinds/theme/status settled after roughly 2 seconds in testing.

Tradeoffs

Tradeoff Impact
Async TPM is eventually consistent Plugin-provided keybinds and final theme/status styling may not be available for the first second or two after a brand-new tmux server starts.
pt no longer uses tmuxinator Only the personal session hot path changed. gt and st still use tmuxinator.
Status helpers refresh less often Package/speedtest/battery-style status updates can lag by up to 5s, but this avoids rerunning helpers every second.
Mise caches for 1h Newly released remote tool versions may not appear immediately, but prompt/startup avoids repeated remote checks.

Commits

Commit Description
9630301 Speed up fish prompt and mise activation
9c216b6 Update bat theme and copilot completions
aa4642a Reduce tmux status line overhead
8d84613 Restore contextual tmux window labels
12b41ce Add fast path for tmux window labels
69fb038 Speed up personal tmux session launcher
fd32d1f Load tmux plugins asynchronously

djensenius and others added 7 commits May 18, 2026 22:22
Avoid duplicate mise fish activation and replace per-prompt mise environment updates with startup and directory-change hooks. Enable mise caching for env and remote version lookups, and make Starship jj custom modules avoid spawning fish for non-jj repositories.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use the current Catppuccin Mocha bat theme name and include none as a valid Copilot reasoning effort completion.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Lower the status refresh rate, remove a per-window contextual-name shellout from Catppuccin window labels, and suppress noisy outdated-package status stderr.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Keep the contextual window-name command in Catppuccin window labels and fix the hardcoded home path.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Use a lightweight shell wrapper for common contextual window labels and fall back to the Python helper for Copilot, Node, and complex cases.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@djensenius djensenius merged commit 43684e4 into main May 19, 2026
6 checks passed
@djensenius djensenius deleted the optimize-fish-mise-prompt branch May 19, 2026 03:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant