Migration from Bash/Zsh

Hash can load your existing shell configuration with a compatibility layer, making it easy to switch without losing your customizations.

Automatic Migration (First Run)

When you first launch Hash, it detects your previous shell and offers to load compatible settings:

Welcome to Hash!

Detected zsh config files:
~/.zprofile
~/.zshrc

Would you like to load compatible settings?

[Y] Yes, load settings
[n] No, start fresh
[?] What does this do?

(To load from a different shell later: hash migrate --from bash)

Load these settings now? [Y/n/?]:

Choosing "Yes" sources your existing config with a compatibility layer. Aliases, environment variables, and functions work automatically. Migration uses your configured shell.dialect: bash mode (the default) filters zsh-only lines, while zsh mode preserves zsh syntax where possible.

Manual Migration

You can run migration manually at any time:

hash migrate # Interactive prompt
hash migrate --from zsh # Load from ~/.zshrc
hash migrate --from bash # Load from ~/.bashrc

Checking Migration Status

See what was imported and what was skipped:

$ hash migrate status

Migration from ~/.zshrc (shell: zsh)

Imported:
23 aliases
8 environment variables
3 functions

Skipped: 14 items

Last import: 2024-01-15 10:30:00

How Loading Works

Hash does not rewrite your existing shell files. It records the detected files and sources them at startup with compatibility filtering.

Generated ~/.hashrc marker

# ~/.hashrc (created by hash migrate)
# Hash migration: shell config loaded from:
# ~/.zprofile
# ~/.zshrc
#
# Files are sourced at startup with the configured shell dialect.
# Run 'hash migrate status' to see what was skipped
#
# Add your own customizations below:

Advantages:

  • Changes to your .zshrc are automatically picked up
  • You can keep using the same config for both shells during transition
  • Unsupported shell-integration commands become no-ops at runtime
  • Full bash syntax support including [[, ==, process substitution — or zsh syntax with dialect = "zsh"

A standalone generated config is not exposed in 0.6.x. Add Hash-specific customizations below the marker in ~/.hashrc.

What Gets Imported

FeatureBashZshNotes
AliasesConverted to functions (see note below)
Environment variablesexport statements
FunctionsPOSIX-compatible syntax
PATH modifications

Note: Aliases are converted to functions

Hash converts alias definitions to shell functions internally. This ensures that complex aliases with bash syntax (like && or ||) work correctly:

# Your alias:
alias deploy='npm run build && npm run deploy'

# Hash internally converts to:
deploy() { npm run build && npm run deploy; }

This is transparent — you use the alias name normally, and it works as expected. The conversion happens because Hash parses each command independently, so traditional alias expansion isn't available. Functions provide the same functionality with full bash syntax support.

Experimental zsh dialect

New in 0.6: Hash can parse zsh syntax directly instead of filtering your config down to bash. Opt in via config.toml:

~/.config/hash/config.toml
[shell]
dialect = "zsh"

[shell.startup_files]
login = ["/etc/zprofile", "~/.zprofile", "~/.hash_profile"]
interactive = ["~/.zshrc", "~/.hashrc"]

In zsh mode, commands, source, eval, configured startup files, and migrated zsh files are parsed as zsh, so zsh-only syntax in your .zshrc is preserved where possible. Upstream zsh support in the parser is experimental and incomplete, so shell/editor integration builtins like bindkey, setopt, compdef, and zstyle still run as compatibility no-ops. If you rely on ~/.zshenv, add it to the startup lists you need; Hash has no separate "all invocations" startup bucket.

What Gets Skipped

In the default bash dialect, these zsh-specific features are filtered during migration. In zsh mode they parse, but the integration builtins remain no-ops:

FeatureReasonHash Alternative
bindkeyzsh-specific key bindingsKeybindings config
setoptzsh shell optionsHash config options
compdef / zstylezsh completion systemHash completion
autoloadzsh function autoloadingDefine functions directly
precmd hookszsh-specific

Troubleshooting

Tool-specific setup

Popular tools like zoxide, direnv, fzf, and Starship work with Hash but may need specific configuration. See the Integrations page for complete setup guides.

Bash Syntax Support

In the default dialect, Hash fully supports bash 5.x syntax, including features that are shared between bash and zsh:

  • [[ ... ]] extended test construct
  • == string comparison (inside [[ ]])
  • =~ regex matching
  • Process substitution: <(cmd) and >(cmd)
  • Arrays and associative arrays
  • source and eval commands work with bash syntax

This means your existing bash and zsh configs will work without modification. The compatibility layer handles shell-specific features automatically.

Parse errors

If you see parse errors from your rc file, it may contain syntax that's specific to zsh and not shared with bash. Run hash migrate status to see what was skipped, or try dialect = "zsh" to parse it natively.