I run mutt in tmux and when I run gpg to sign or encrypt, gpg shows a blank screen where I would expect to type my passphrase. I've straced gpg and it shows that it's hanging waiting on a socket read() (presumably from gpg-agent. What's going on here?

2 Answers 2


Short answer

If you are using bash, then Chris W.’s wrapper script is the way to go. If perchance you are using zsh, then you can exploit the ~/.zshenv startup script to set GPG_TTY from there, no need for a wrapper. Since bash does not have a similar startup script (cf. Bash Startup Files), you’ll have to use the wrapper there.

export GPG_TTY=${TTY}

Some background: Interactive and non-interactive shells

The gpg-agent expects GPG_TTY to point to the tty from where it is invoked, such that it can display its passphrase prompts in a secure manner. The GnuPG manual suggests putting the following in ~/.bashrc (or similar):

export GPG_TTY

If you invoke mutt directly from your shell, this will work: GPG_TTY will be set, mutt will pick it up and pass it to gpg when it needs to.

However, when you launch mutt via tmux’s new-window command or similar constructs, there is an important difference: Before, your mutt was in a so-called interactive shell—that is, you had a shell prompt open and launched mutt from there yourself. tmux new-window launches a non-interactive shell, since your shell is only needed to launch mutt and you won‘t be able to interact with it. In this case, bath won‘t read .bash_profile or .bashrc at all, since they are designed to set up your shell for interactive use.

zsh does pretty much the same thing: .zshrc is read for interactive shells and skipped for non-interactive ones. However, in zsh, you can supply a third startup file, .zshenv, that is read for every shell, no matter whether it is interactive or not. Therefore, if you set GPG_TTY from there, it will always be available, no matter in which way mutt is started. And since $TTY is a shell builtin variable that always points to the current tty, you can avoid the overhead of spawning a tty process every time the shell comes up.


I was launching mutt by running tmux neww mutt. mutt was inheriting the environment set in tmux. This includes $GPG_TTY which is different for the new pane in which I'm running mutt (or unset if not in the tmux environment). I wrote a wrapper called gpgtty that sets $GPG_TTY correctly for new panes.

GPG_TTY=$(tty) $*

Then I launch mutt: tmux neww gpgtty mutt. gpg works correctly after that. FYI, this is all using pinentry-curses for gpg passphrase input.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .