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:
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:
Checking Migration Status
See what was imported and what was skipped:
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
# 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
.zshrcare 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 withdialect = "zsh"
A standalone generated config is not exposed in 0.6.x. Add Hash-specific customizations below the marker in ~/.hashrc.
What Gets Imported
| Feature | Bash | Zsh | Notes |
|---|---|---|---|
| Aliases | ✓ | ✓ | Converted to functions (see note below) |
| Environment variables | ✓ | ✓ | export statements |
| Functions | ✓ | ✓ | POSIX-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:
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:
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:
| Feature | Reason | Hash Alternative |
|---|---|---|
bindkey | zsh-specific key bindings | Keybindings config |
setopt | zsh shell options | Hash config options |
compdef / zstyle | zsh completion system | Hash completion |
autoload | zsh function autoloading | Define functions directly |
| precmd hooks | zsh-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
sourceandevalcommands 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.