Table of Contents
Introduction
If you work on both personal and work projects, you’ve probably run into the situation where you need to switch your GitHub CLI (gh) account depending on which project you’re in. An issue gets filed under the wrong account, or a PR is opened as the wrong user.
gh auth switch solves this, but remembering to run it every time you change directories gets old fast.
This post shows how to combine the GH_TOKEN environment variable with zsh’s chpwd hook so that your GitHub CLI account switches automatically the moment you enter a directory.
The Problem with gh auth switch
gh lets you switch the active account with:
gh auth switch --user <account-name>
The problem is that this changes global state. Switch accounts in terminal tab A and it affects tab B as well. When you have multiple projects open at once, it’s easy to lose track of which account is currently active.
Using the GH_TOKEN Environment Variable
When GH_TOKEN is set, gh uses that token instead of whichever account is stored in its config.
export GH_TOKEN=ghp_xxxxxxxxxxxx
gh pr list # runs as the GH_TOKEN account
Environment variables are isolated per shell session. Terminal tab A and tab B can each hold a different GH_TOKEN, so there’s no global state conflict like with gh auth switch.
If you’re already logged in to an account with gh, you can retrieve its token without creating a new one:
gh auth token --user <personal-account>
gh auth token --user <work-account>
Auto-switching with the chpwd Hook
zsh’s chpwd hook runs a function every time the working directory changes. Register one with add-zsh-hook chpwd and it fires automatically on every cd.
Put the GH_TOKEN switching logic there and your account changes as soon as you enter a directory.
Full Configuration
Add the following to ~/.zshrc:
# GitHub CLI — auto-switch GH_TOKEN by directory
# ~/personal/* → personal account
# everywhere else → work account
_GH_TOKEN_PERSONAL=$(gh auth token --user <personal-account> 2>/dev/null)
_GH_TOKEN_WORK=$(gh auth token --user <work-account> 2>/dev/null)
_gh_pick_account() {
case "$PWD/" in
"$HOME/personal/"*)
export GH_TOKEN="$_GH_TOKEN_PERSONAL" ;;
*)
export GH_TOKEN="$_GH_TOKEN_WORK" ;;
esac
}
add-zsh-hook chpwd _gh_pick_account
_gh_pick_account
gh() {
local label
case "$PWD/" in
"$HOME/personal/"*) label="personal" ;;
*) label="work" ;;
esac
print -P "%F{cyan}▶ GitHub account: %B${label}%b%f"
command gh "$@"
}
Apply it:
source ~/.zshrc
How It Works
1. Token caching at shell startup
_GH_TOKEN_PERSONAL=$(gh auth token --user <personal-account> 2>/dev/null)
_GH_TOKEN_WORK=$(gh auth token --user <work-account> 2>/dev/null)
gh auth token adds a small delay on each call. Caching the tokens in variables at startup means directory changes are instant — no extra latency.
2. chpwd hook swaps GH_TOKEN
_gh_pick_account() {
case "$PWD/" in
"$HOME/personal/"*)
export GH_TOKEN="$_GH_TOKEN_PERSONAL" ;;
*)
export GH_TOKEN="$_GH_TOKEN_WORK" ;;
esac
}
add-zsh-hook chpwd _gh_pick_account
_gh_pick_account # also apply to the current directory on shell startup
Directories under $HOME/personal/ get the personal token; everything else gets the work token. The bare _gh_pick_account call at the end ensures the correct token is set as soon as a new terminal opens.
Showing the Active Account with a gh Wrapper
When accounts switch automatically it’s easy to forget which one is active. Wrapping the gh command to print the current account before every invocation prevents mistakes.
gh() {
local label
case "$PWD/" in
"$HOME/personal/"*) label="personal" ;;
*) label="work" ;;
esac
print -P "%F{cyan}▶ GitHub account: %B${label}%b%f"
command gh "$@"
}
Every gh call now shows:
▶ GitHub account: personal
Summary
| Approach | Per-session isolation | Auto-switch | Extra tool |
|---|---|---|---|
gh auth switch | X (global state) | X | X |
direnv + GH_TOKEN | O | O | Required |
chpwd + GH_TOKEN | O | O | X |
The chpwd + GH_TOKEN combination needs no extra tools and switches accounts automatically just by changing directories. The same pattern works for any other CLI tool that supports token-based authentication via an environment variable.
Was my blog helpful? Please leave a comment at the bottom. it will be a great help to me!
App promotion
Deku.Deku created the applications with Flutter.If you have interested, please try to download them for free.