Advanced / Debugging

When things go wrong, or you want to see what's happening under the hood.

Tracing

Hash has a comprehensive tracing system for debugging. Events are written to JSONL files.

Environment variables

VariableValuesDefault
HASH_TRACEeditor, agent, shell, parser, or all(disabled)
HASH_TRACE_PATHFile path for trace outputhash-trace.jsonl
HASH_TRACE_LEVELverbose, detailed, highverbose

Example: Enable tracing

export HASH_TRACE=all
export HASH_TRACE_PATH=/tmp/hash-trace.jsonl
export HASH_TRACE_LEVEL=detailed
hash

After your session, examine the trace:

cat /tmp/hash-trace.jsonl | jq .

Trace output format

Each line is a JSON object with:

  • timestamp — RFC3339Nano format
  • delta_ms — Time since last event in same subsystem
  • subsystem — Which component emitted the event
  • level — Verbosity level
  • event — Event name
  • data — Event-specific data

PTY tracing

For debugging issues with interactive commands (programs that use the terminal directly), Hash has a separate PTY tracing system.

VariableValuesDefault
HASH_PTY_TRACE1 to enable(disabled)
HASH_PTY_TRACE_PATHFile path for PTY tracehash-pty-trace.log

Example: Debug a hanging command

export HASH_PTY_TRACE=1
export HASH_PTY_TRACE_PATH=/tmp/pty-debug.log
hash

PTY traces capture:

  • I/O timestamps for stdin, stdout, PTY read/write
  • Terminal drain operations (escape sequence cleanup)
  • Stalled I/O detection
  • Process termination reasons

Login vs interactive mode

Hash follows traditional shell conventions for startup files:

ModeHow to invokeFiles sourced
Loginhash -l or via /etc/passwd/etc/profile, ~/.profile, ~/.hash_profile, then ~/.hashrc
Interactivehash (normal invocation)~/.hashrc
Non-interactivehash -c "command"init_commands only

Startup file dialect

Startup files are parsed with the configured shell.dialect (bash by default). With dialect = "zsh" you can point [shell.startup_files] at your zsh files (~/.zprofile, ~/.zshrc) and Hash sources them with experimental zsh parsing. See the Configuration Reference.

Environment markers

Hash sets these variables so scripts can detect the shell mode:

  • HASH_SHELL=1 — Always set
  • HASH_LOGIN=1 — Set in login mode
  • HASH_INTERACTIVE=1 — Set in interactive mode

Shell identity

Hash identifies itself differently from bash/zsh:

  • $0 is set to hash
  • $SHELL is set to the hash binary path (in login mode)
  • $HASH_SHELL=1 is always set as a detection marker

Builtins

Hash provides these built-in commands:

CommandDescription
cd [dir]Change directory (supports ~ expansion)
exit / quitExit the shell
historyShow recent commands
copyCopy commands or output to clipboard
statusShow system status (agent, history, etc.)
tipsShow helpful tips about Hash features
issueSubmit a GitHub issue with context
source / .Source shell setup files
setup-zoxideConfigure zoxide integration automatically
modelList or switch the agent model (ACP agents)

Compatibility no-op builtins such as bindkey, setopt, and compdef also exist so common zsh setup files can be sourced without failing.

history subcommands

history # Show recent 20 commands
history search git # Search history for "git"
history failed # Show failed commands (non-zero exit)
history sudo # Show commands run with sudo
history asked # Show agent interactions

copy subcommands

copy cmd # Copy last command
copy out # Copy last output
copy all # Copy command + output
copy cmd 2 # Copy 2nd-to-last command

issue options

!! # Quick issue for last failure
issue "title here" # Create issue with title
issue --last # Pre-fill with last command context
issue # Open editor with template

model subcommands

model # Open the interactive model picker
model Sonnet # Select directly by display name or value
model --list # Print available models; current marked with *

Available models come from the ACP agent itself, and the choice persists for the current shell session. See Agents for details.

Disabling builtins

Some tools like zoxide or eza replace standard commands. Disable builtins only when an external tool must replace a builtin command (for example, alias cd="z"):

config.toml
[shell]
disable_builtins = ["cd"] # Example: when using alias cd="z"

For complete setup guides including directory change hooks, see Integrations.