When you need a clean slate — testing, debugging, or isolating a project — each major AI coding CLI lets you override its config directory via an environment variable:
# Claude Code
CLAUDE_CONFIG_DIR=/tmp/claude-clean claude
# GitHub Copilot CLI
COPILOT_HOME=/tmp/copilot-clean copilot
# OpenAI Codex CLI
CODEX_HOME=/tmp/codex-clean codex
These replace the entire config directory (~/.claude/, ~/.copilot/, ~/.codex/), so existing sessions, permissions, and plugins won't carry over. Copy the default directory contents if you need to preserve anything.
Copilot also has a separate COPILOT_CACHE_HOME for marketplace cache and update packages — setting COPILOT_HOME alone won't relocate those.
In the HTTP era, virtual hosting was trivial: one IP serves many domains, the Host header tells them apart. HTTPS breaks this because TLS handshake happens before any HTTP header — the server must pick a certificate before knowing which domain the client wants.
SNI — the standard fix
Server Name Indication is a TLS extension where the client sends the target hostname during handshake. All modern clients support it. Nginx uses it automatically — just define separate server blocks:
server {
listen 443 ssl;
server_name a.com;
ssl_certificate /etc/ssl/a.com.crt;
ssl_certificate_key /etc/ssl/a.com.key;
}
server {
listen 443 ssl;
server_name b.com;
ssl_certificate /etc/ssl/b.com.crt;
ssl_certificate_key /etc/ssl/b.com.key;
}
Each domain gets its own certificate. Nginx routes based on SNI. Zero extra config needed.
When you'd rather use one certificate
For a handful of related domains, a SAN certificate (Subject Alternative Name) covers multiple names in one cert:
server {
listen 443 ssl;
server_name a.com b.com c.com;
ssl_certificate /etc/ssl/multi.crt;
ssl_certificate_key /etc/ssl/multi.key;
}
Let's Encrypt makes this painless:
certbot --nginx -d a.com -d b.com -d c.com
For lots of subdomains (*.example.com), a wildcard certificate is the way to go.
SNI + Let's Encrypt covers 99% of real-world setups — free and automatic.
I Wrote a git alias using [[ ... ]] and =~. Works fine in my interactive bash. Run the alias and it explodes:
$ git co master
... Syntax error: "(" unexpected (expecting "then")
First instinct: "but I have bash installed":
$ ls -l /bin/bash
-rwxr-xr-x 1 root root 1298416 ... /bin/bash
$ /bin/bash --version
GNU bash, version 5.2.37(1)-release ...
Doesn't matter. A git alias starting with ! is hardcoded to run under /bin/sh — it doesn't read $SHELL, doesn't care what your login shell is. On Debian/Ubuntu /bin/sh -> dash, and dash doesn't understand [[, =~, == or other bash extensions:
$ ls -l /bin/sh
lrwxrwxrwx 1 root root 4 ... /bin/sh -> dash
$ echo '[[ "a" == a* ]]' | /bin/sh
/bin/sh: 1: [[: not found
The source is run-command.c::prepare_shell_cmd() in git itself — it literally calls sh -c.
Two fixes:
Wrap in bash -c explicitly (minimal change, but the nested quoting inside an alias gets ugly fast):
co = "!bash -c 'f() { ...bash syntax... }; f \"$@\"' _"
Rewrite as POSIX sh (preferred). Common substitutions:
[[ "$x" == -* ]] → case "$x" in -*) ... ;; esac
[[ "$x" =~ ^HEAD~ ]] → case "$x" in HEAD~*) ... ;; esac
[[ "$a" == "$b" ]] → [ "$a" = "$b" ]
[[ -f foo ]] → [ -f foo ] (already POSIX, no reason to use [[)
Lesson: write git aliases as if dash is the only shell on the planet. Don't reach for [[ because it feels nicer — either wrap with bash -c or just use case.
Use CLAUDE_CONFIG_DIR to point Claude Code at a different config directory — credentials, settings, sessions all go there instead of ~/.claude.
mkdir -p ~/.claude-work
CLAUDE_CONFIG_DIR=$HOME/.claude-work claude
Set up aliases in your shell config for quick switching:
alias claude-work='CLAUDE_CONFIG_DIR=$HOME/.claude-work claude'
First launch in the new directory triggers the login flow — that's how you get account isolation. Both instances can run simultaneously without interference.
Share session history between instances
CLAUDE_CONFIG_DIR is all-or-nothing — no built-in way to share just sessions. Symlink the projects/ directory back to the original to get shared session history with separate settings:
mkdir -p ~/.claude-work
cp ~/.claude/settings.json ~/.claude-work/settings.json
ln -s ~/.claude/projects ~/.claude-work/projects
This gives you independent config/credentials but a unified session list. New sessions written by either instance appear in both (bidirectional). No read-only option exists — if you need isolation, don't symlink.
If curl throws SSL certificate problem: unable to get local issuer certificate every time in WSL, it's usually a stale CA bundle — especially common on corporate networks running SSL inspection (Zscaler, etc.).
First, refresh the bundle:
sudo apt-get update && sudo apt-get install -y ca-certificates
sudo update-ca-certificates
That fixes most cases. If not, try a full reinstall:
sudo apt-get install --reinstall ca-certificates
sudo update-ca-certificates --fresh
On corporate networks, you likely need your company's root CA certs. You probably already have them somewhere in your Windows filesystem (.crt or .cer files). Copy them all into the trusted store:
sudo cp /c/Certificates/*.crt /usr/local/share/ca-certificates/
sudo cp /c/Certificates/*.cer /usr/local/share/ca-certificates/
sudo update-ca-certificates
Skip .pfx files — those contain private keys and are a different format.
If you don't have the certs handy, export them from Windows:
# PowerShell — list all root certs, look for your company name
Get-ChildItem Cert:\LocalMachine\Root | Select-Object Subject, Issuer | Sort-Object Subject
Or use certmgr.msc (Win+R → certmgr.msc) → Trusted Root Certification Authorities → find your company's cert → right-click → Export → Base-64 encoded X.509.
Test with curl https://google.com after each step.