Skip to main content

Shell Integration

Hooks, Completions, and PATH Management

This guide covers OMG's shell integration features including the shell hook, completions, and ultra-fast shell functions.


ðŸŽŊ Overview​

OMG provides deep shell integration that:

  1. Automatically updates PATH when you change directories
  2. Detects version files and activates the correct runtime
  3. Provides instant completions for all commands
  4. Exposes ultra-fast functions for shell prompts

🔧 Shell Hook Installation​

What the Hook Does​

The shell hook:

  • Runs on every directory change (cd)
  • Runs on every prompt (to catch pushd, popd, etc.)
  • Detects version files (.nvmrc, .python-version, etc.)
  • Prepends correct runtime bin directories to PATH
  • Provides fast package count functions

Installation by Shell​

Zsh​

Add to ~/.zshrc:

eval "$(omg hook zsh)"

Reload:

source ~/.zshrc
# or
exec zsh

Bash​

Add to ~/.bashrc:

eval "$(omg hook bash)"

Reload:

source ~/.bashrc
# or
exec bash

Fish​

Add to ~/.config/fish/config.fish:

omg hook fish | source

Reload:

source ~/.config/fish/config.fish
# or
exec fish

Verifying Installation​

# Test hook output
omg hook zsh

# Check if hook is active
type _omg_hook

# Test version detection
cd /path/to/project/with/.nvmrc
echo $PATH | grep omg

📝 How Version Detection Works​

Detection Order​

When you enter a directory, OMG checks for version files in this order:

  1. Current directory
  2. Parent directories (walking up to filesystem root)
  3. Global default (~/.local/share/omg/versions/<runtime>/current)

Supported Version Files​

FileRuntimePriority
.node-versionNode.js1 (highest)
.nvmrcNode.js2
.bun-versionBun1
.python-versionPython1
.ruby-versionRuby1
.go-versionGo1
go.modGo2
.java-versionJava1
rust-toolchain.tomlRust1
rust-toolchainRust2
.tool-versionsMultiple3
.mise.tomlMultiple3
.mise.local.tomlMultiple2
mise.tomlMultiple4
package.jsonNode/Bun4 (engines/volta)

Version File Formats​

Simple Version Files​

.nvmrc, .python-version, .go-version, etc.:

20.10.0

Or with v prefix:

v20.10.0

Or aliases (Node.js):

lts/*
lts/hydrogen

rust-toolchain.toml​

[toolchain]
channel = "stable" # or "nightly" or "1.75.0"
components = ["rustfmt", "clippy"]
targets = ["wasm32-unknown-unknown"]
profile = "minimal"

Or simple rust-toolchain file:

stable

.tool-versions (asdf format)​

node 20.10.0
python 3.12.0
rust stable
go 1.21.0

.mise.toml​

[tools]
node = "20.10.0"
python = "3.12.0"
rust = "stable"
deno = "1.40.0"

[tools.node]
version = "20"

[tools.python]
version = "3.12"

package.json​

{
"engines": {
"node": ">=18 &lt;21",
"bun": ">=1.0"
},
"volta": {
"node": "20.10.0",
"bun": "1.0.25"
}
}

Priority: engines > volta


🚀 Ultra-Fast Shell Functions​

The hook provides cached package count functions for shell prompts.

Cached Functions (Sub-Microsecond)​

These read from a cached status file updated by the daemon:

FunctionReturns
omg-ecExplicit package count
omg-tcTotal package count
omg-ocOrphan count
omg-ucUpdates count

Fresh Functions (~1ms)​

These read the status file directly:

FunctionReturns
omg-explicit-countExplicit package count
omg-total-countTotal package count
omg-orphan-countOrphan count
omg-updates-countUpdates count

Using in Prompts​

Zsh Prompt​

# In ~/.zshrc
PROMPT='[ðŸ“Ķ $(omg-ec)] %~$ '

# Or with colors
PROMPT='%F{cyan}[$(omg-ec) pkgs]%f %~$ '

# Full example with git
PROMPT='%F{green}%n@%m%f %F{blue}%~%f $(git_prompt_info)[ðŸ“Ķ $(omg-ec)]$ '

Bash Prompt​

# In ~/.bashrc
export PS1='[\w] $(omg-ec) pkgs$ '

# With colors
export PS1='\[\e[36m\][$(omg-ec) pkgs]\[\e[0m\] \w$ '

Fish Prompt​

# In ~/.config/fish/functions/fish_prompt.fish
function fish_prompt
echo -n (omg-ec)" pkgs "
set_color blue
echo -n (prompt_pwd)
set_color normal
echo '$ '
end

Performance Comparison​

MethodLatencyUse Case
omg-ec (cached)<1ΞsPrompts
omg-explicit-count (fresh)~1msScripts
omg explicit --count~1.2msCommands
pacman -Qq | wc -l~14msFallback

ðŸ”Ī Shell Completions​

Installation​

Zsh​

# Create completions directory
mkdir -p ~/.zsh/completions

# Generate completions
omg completions zsh > ~/.zsh/completions/_omg

# Add to fpath in ~/.zshrc (if not already)
fpath=(~/.zsh/completions $fpath)
autoload -Uz compinit && compinit

# Rebuild completion cache
rm ~/.zcompdump
compinit

Bash​

# System-wide
sudo omg completions bash > /etc/bash_completion.d/omg

# Or user-only
omg completions bash > ~/.local/share/bash-completion/completions/omg

# Source immediately
source /etc/bash_completion.d/omg

Fish​

# User completions
omg completions fish > ~/.config/fish/completions/omg.fish

# System-wide
sudo omg completions fish > /usr/share/fish/vendor_completions.d/omg.fish

Completion Features​

OMG provides intelligent completions for:

  • Commands: All subcommands with descriptions
  • Package names: From daemon cache (80k+ AUR packages)
  • Runtime versions: Installed and available versions
  • Options: All flags with descriptions

Fuzzy Matching​

OMG uses Nucleo for ultra-fast fuzzy matching:

omg i frfx<TAB>
# Completes to: firefox

🔄 Hook Behavior Deep Dive​

Zsh Hook Internals​

The Zsh hook uses precmd and chpwd functions:

_omg_hook() {
trap -- '' SIGINT
eval "$(omg hook-env -s zsh)"
trap - SIGINT
}

typeset -ag precmd_functions
if [[ -z "${precmd_functions[(r)_omg_hook]+1}" ]]; then
precmd_functions=(_omg_hook ${precmd_functions[@]})
fi

typeset -ag chpwd_functions
if [[ -z "${chpwd_functions[(r)_omg_hook]+1}" ]]; then
chpwd_functions=(_omg_hook ${chpwd_functions[@]})
fi

Bash Hook Internals​

Bash uses PROMPT_COMMAND:

_omg_hook() {
local previous_exit_status=$?
trap -- '' SIGINT
eval "$(omg hook-env -s bash)"
trap - SIGINT
return $previous_exit_status
}

if [[ ! "${PROMPT_COMMAND:-}" =~ _omg_hook ]]; then
PROMPT_COMMAND="_omg_hook${PROMPT_COMMAND:+;$PROMPT_COMMAND}"
fi

Fish Hook Internals​

Fish uses event handlers:

function _omg_hook --on-variable PWD --on-event fish_prompt
omg hook-env -s fish | source
end

Cache Refresh​

The hook includes automatic cache refresh every 60 seconds:

_omg_refresh_cache() {
local f="${XDG_RUNTIME_DIR:-/tmp}/omg.status"
[[ -f "$f" ]] || return
local now=$EPOCHSECONDS
(( now - _OMG_CACHE_TIME < 60 )) && return
_OMG_CACHE_TIME=$now
local data=$(od -An -j8 -N16 -tu4 "$f" 2>/dev/null)
read _OMG_TOTAL _OMG_EXPLICIT _OMG_ORPHANS _OMG_UPDATES <<< "$data"
}

🛠ïļ Manual PATH Management​

If you prefer manual control over PATH:

Without Hook​

# Manually add runtime paths
export PATH="$HOME/.local/share/omg/versions/node/current/bin:$PATH"
export PATH="$HOME/.local/share/omg/versions/python/current/bin:$PATH"
export PATH="$HOME/.local/share/omg/versions/go/current/bin:$PATH"
export PATH="$HOME/.local/share/omg/versions/rust/current/bin:$PATH"

Project-Specific​

# Add to project's .envrc (if using direnv)
export PATH="$HOME/.local/share/omg/versions/node/20.10.0/bin:$PATH"

Check Active Versions​

# See what's in PATH
echo $PATH | tr ':' '\n' | grep omg

# Check symlinks
ls -la ~/.local/share/omg/versions/node/current

⚙ïļ Configuration Options​

Shims vs Hooks​

OMG offers two PATH management methods:

  • Faster runtime switching
  • PATH modified on directory change
  • Works with all terminals

Shims​

  • Better IDE compatibility
  • Wrapper scripts for each binary
  • Slightly slower execution

Enable shims in ~/.config/omg/config.toml:

shims_enabled = true

Generate shims:

omg shim generate

Runtime Backend​

Control runtime resolution:

# In ~/.config/omg/config.toml
runtime_backend = "native-then-mise"

Options:

  • native — Only OMG's built-in managers
  • mise — Only mise
  • native-then-mise — Native first, mise fallback (default)

🔍 Troubleshooting​

Hook Not Running​

# 1. Check hook is in shell config
grep "omg hook" ~/.zshrc

# 2. Verify hook works
omg hook zsh | head -20

# 3. Check function exists
type _omg_hook

# 4. Force reload
exec zsh

Wrong Version Active​

# 1. Check version files
ls -la .nvmrc .python-version .tool-versions

# 2. Check what OMG detects
omg which node

# 3. Check PATH order
echo $PATH | tr ':' '\n' | head -10
# OMG paths should be first

# 4. Force switch
omg use node 20.10.0

Slow Directory Changes​

# 1. Ensure daemon is running
omg status

# 2. Check hook-env timing
time omg hook-env -s zsh
# Should be under 10ms

# 3. If slow, the daemon may be down
omg daemon

Completions Not Working​

# Zsh
rm ~/.zcompdump
omg completions zsh > ~/.zsh/completions/_omg
compinit

# Check fpath
echo $fpath | tr ' ' '\n' | grep completions

📊 Performance Tips​

1. Keep Daemon Running​

# Start daemon on login
echo "omg daemon &" >> ~/.zprofile

# Or use systemd
systemctl --user enable omgd

2. Use Cached Functions in Prompts​

# Fast (cached)
PROMPT='$(omg-ec) pkgs$ '

# Avoid (hits binary each time)
PROMPT='$(omg explicit --count) pkgs$ '

3. Minimize Version Files​

Only place version files in project roots, not deeply nested directories.

4. Combine with Starship/Powerlevel10k​

These prompt themes have built-in version display. Combine with OMG:

# OMG handles PATH, Starship handles display
eval "$(omg hook zsh)"
eval "$(starship init zsh)"

📚 See Also​