Post #7 in the Claude Code Toolkit series. Earlier posts: nf-agents, nf-dream, nf-git-workflow, nf-memory, nf-cc-sync, nf-ignore. This post is the smallest in the series, the one that fixes a .envrc file most developers paste together once and never revisit.
I keep two GitHub accounts. One for personal projects, one for client work. The gh CLI tracks both and gh auth switch moves between them. The friction shows up when a script wants a GH_TOKEN environment variable per repo.
Two failure modes:
- Hardcode the token in
.envrc. Leak waiting to happen. Even if.envrcis gitignored, the token sits in plaintext on disk, and it stops working the next time you rotate viagh auth refresh. - Hardcode the account name. Brittle. Two months later you forget which account this repo uses, run
gh auth switch, and now the wrong tokens are loading silently.
nf-direnv sets up the .envrc with the token resolved dynamically at load time, with the correct account picked once and recorded in the file. Plaintext never touches disk; rotation is automatic.
What the skill does
- Preflight check:
direnvis installed and the cwd is a git repo. Aborts with a clear message otherwise. - Lists
ghaccounts viagh auth status, asks viaAskUserQuestionwhich to use for this repo. - Reads any existing
.envrcand decides between three actions: create, append, or update-in-place. Existing exports unrelated toGH_TOKENare preserved. - Shows a Before/After/Diff preview, asks for confirmation.
- Writes
.envrcusing$(gh auth token --user <selected>)so the token resolves dynamically on every shell load. - Verifies
.envrcis in.gitignore, adds the pattern if missing. - Runs
direnv allowso the file actually loads in the current shell.
How to invoke
/nf-direnv
No arguments. The skill asks the questions it needs (which account, which action on .envrc) and reports the result.
A walkthrough
A new repo for client work. gh is authenticated with two accounts: personal-acct and work-acct.
$ cd ~/WORK/some-project
$ /nf-direnv
Preflight:
direnv: found (v2.34.0)
git repo: yes
cwd: ~/WORK/some-project
gh accounts:
1. personal-acct (active)
2. work-acct
> Which account for this repo?
> 2
.envrc plan:
Status: file does not exist, will create
Content:
export GH_TOKEN=$(gh auth token --user work-acct)
.gitignore:
Status: .envrc already ignored
Apply? Yes / No
> Yes
Wrote .envrc
Ran: direnv allow
loading ~/WORK/some-project/.envrc
export +GH_TOKEN
Two minutes from cd to a working environment. The next time you cd into this repo, direnv reloads .envrc, gh auth token --user work-acct runs, and the right token populates GH_TOKEN. If you have rotated the token in the meantime, the next reload picks up the new value automatically. No edits to .envrc needed.
Decision 1: Dynamic resolution, never a plaintext token
The first version of the skill wrote the token directly:
export GH_TOKEN=gho_AbCdEf...
That worked. It also had three failure modes:
- The file is plaintext on disk. Even gitignored, a leaked filesystem snapshot is enough.
gh auth refreshrotates the token; the file is now stale and writes start failing withBad credentials.gh auth switchto a different account does nothing for this repo because the value is baked in.
The fix is one syntax change: wrap the value in $(...) and let gh auth token --user <name> resolve it on each shell load.
export GH_TOKEN=$(gh auth token --user work-acct)
gh auth token reads the encrypted credential store (keyring on most systems). The plaintext value never lands on disk. Rotation works without editing the file. Multi-account is explicit (the --user flag pins which account this repo uses).
The general lesson generalizes to any tool with a credential CLI (aws sso login, gcloud auth print-access-token, op read, pass). If the tool can print the secret on demand, wire it through $(...) in .envrc rather than copying the value out by hand.
Decision 2: Account is per-repo, picked once
The brittle alternative is to leave the account global (“use whatever gh auth switch is set to”) and assume the developer is in the right account when they cd in. That fails the first time you forget to switch.
The skill records the account explicitly in .envrc:
export GH_TOKEN=$(gh auth token --user work-acct)
The repo’s .envrc now declares which account it expects. Switching gh globally to another account does not change which token loads for this repo. The repo is self-describing for its credential needs.
This composes with direnv’s per-directory mechanism. Different repos under the same parent (e.g. ~/WORK/personal/repo-a and ~/WORK/client/repo-b) each pick up their own account on cd, with no global state to remember.
Side benefit: the account name in .envrc makes the choice grep-able. If you wonder months later “which account does this repo use”, the answer is one line in the file.
Gotchas
.envrcstays gitignored. Even though the file contains no plaintext token, the account name is per-developer. Committing it would push your personal account name to teammates. The skill auto-adds.envrcto.gitignoreif missing and never commits.envrcitself.direnv allowis per-machine. The skill runsdirenv allowonce after writing the file. If you clone the repo on another machine, you have to rundirenv allowagain there. That isdirenv’s security model, not a skill limitation.gh auth tokenrequires login. Ifgh auth statusshows no accounts, the skill stops and tells you togh auth loginfirst.- Existing
.envrccontent is preserved. The skill never overwrites unrelated exports. If you haveNODE_ENV=developmentalready there, it stays.
What you should keep even if you never use this skill
Three patterns generalize:
- Never write plaintext tokens to
.envrc. Resolve dynamically via the tool’s credential CLI.$(gh auth token --user X)is the pattern forgh; the same shape applies toaws sso login,op read,pass,gcloud auth print-access-token, and anything else with a secret-printing command. - Per-repo account selection. Record the account in the file. Do not rely on global state being correct when someone
cds in. - Verify
.envrcis gitignored before writing. A two-line check saves a serious incident.
Get the skill
White-labeled in the claude-skills-toolkit repo alongside the rest of this series.
git clone https://github.com/llawliet11/claude-skills-toolkit.git
cp -r claude-skills-toolkit/nf-direnv ~/.claude/skills/
Folder reference: claude-skills-toolkit/nf-direnv (publishes alongside this post).
Verify in a new session: invoke /nf-direnv in any repo. The first run walks you through account selection, file preview, and direnv allow. The next time you cd into the repo, the right token is already loaded.