TL;DR: Use environment variables for API keys, set restrictive file permissions, and never commit your config to git.
Store API keys in environment variables instead of config files:
# macOS / Linux
export ANTHROPIC_API_KEY="sk-ant-..."
export OPENAI_API_KEY="sk-..."
export BRAVE_SEARCH_API_KEY="..."
export MUXD_HUB_TOKEN="your-hub-token"
muxd# Windows PowerShell
$env:ANTHROPIC_API_KEY = "sk-ant-..."
$env:OPENAI_API_KEY = "sk-..."
$env:BRAVE_SEARCH_API_KEY = "..."
$env:MUXD_HUB_TOKEN = "your-hub-token"
muxdWhy? Environment variables are:
- ✅ Not written to disk
- ✅ Not vulnerable to file permission mistakes
- ✅ Easy to rotate (just restart)
- ✅ Better for CI/CD and containerization
If you must use the config file, protect it:
# After setting keys via /config set
chmod 600 ~/.config/muxd/config.json
# Verify (should show rw-------)
ls -la ~/.config/muxd/config.jsonWhat does this do?
6(owner): read + write0(group): no permissions0(others): no permissions
Result: Only your user can read the file.
Add to your .gitignore:
# .gitignore
~/.config/muxd/config.json
~/.config/muxd/Or use a global gitignore:
echo "~/.config/muxd/" >> ~/.gitignore_global
git config --global core.excludesfile ~/.gitignore_globalWhy? If you accidentally commit it:
- ❌ All your API keys are in git history forever
- ❌ Anyone with repo access gets your keys
- ❌ Impossible to fully delete (git history)
If you suspect a key was leaked:
-
Revoke immediately:
- Anthropic: console.anthropic.com → API keys
- OpenAI: platform.openai.com → API keys
- Brave: asearch.brave.com → Manage API keys
-
Generate new key:
- Follow provider's instructions
-
Update muxd:
/config set anthropic.api_key <new-key> -
Restart muxd:
- Exit and restart to ensure old key is flushed from memory
# 1. Verify config directory is private
ls -ld ~/.config/muxd/
# Should show: drwx------
# 2. Verify config file is private
ls -l ~/.config/muxd/config.json
# Should show: -rw-------
# 3. Verify database is private
ls -l ~/.local/share/muxd/
# Should show: drwx------❌ INSECURE:
drwxr-xr-x ~/.config/muxd/
-rw-r--r-- ~/.config/muxd/config.json
Group and others can read your keys!
✅ SECURE:
drwx------ ~/.config/muxd/
-rw------- ~/.config/muxd/config.json
Only you can read.
If muxd shows a warning:
WARNING: ~/.config/muxd/config.json is readable by others (mode 644).
Run: chmod 600 ~/.config/muxd/config.json
Fix it:
chmod 600 ~/.config/muxd/config.json
chmod 700 ~/.config/muxd/
chmod 700 ~/.local/share/muxd/Problem: Other users might read your config file.
Solution:
-
Use environment variables only (recommended)
- No config file with keys = no risk
-
Encrypt your home directory (OS-level)
- Linux: LUKS, eCryptfs
- macOS: FileVault
- Windows: BitLocker
-
Use a separate user account for muxd
- Keep work completely isolated
Problem: System admins can read all files.
Solution:
- Don't store production keys on shared servers
- Use environment variables from secure CI/CD
- Run muxd in a container with secret injection
The hub auth token controls access to all connected nodes. Set it explicitly to avoid accidental rotation:
# Via environment variable (recommended for services)
MUXD_HUB_TOKEN="your-token" muxd --hub
# Via CLI flag
muxd --hub --hub-token "your-token"
# Via config
/config set hub.auth_token your-tokenThe token is also persisted in the hub database (hub.db) as a backup.
By default the hub binds to localhost. To accept connections from other machines:
muxd --hub --hub-bind 0.0.0.0Only do this on trusted networks. The hub has no TLS - use a reverse proxy (nginx, caddy) for public exposure.
The hub token grants full access to all connected nodes (sessions, files, commands):
- Treat it like an API key
- Don't share it in public channels
- Rotate it if compromised: set a new token and restart all nodes
muxd runs with your user's permissions. It can:
- ✅ Read files in your project
- ✅ Create/edit/delete files
- ✅ Run shell commands (npm, git, etc.)
- ✅ Read your
.envfiles - ❌ NOT read ~/.config/muxd/config.json (blocked)
Be careful with:
.envfiles containing secrets → muxd can read them- Sensitive source code → muxd can read it
- Bash commands → muxd can execute anything you can
Scenario: You have a .env with secrets
DATABASE_PASSWORD=secret123
API_KEY_PROD=sk-...Risk: If you ask muxd to "read .env", it will see all secrets.
Mitigation:
- Don't ask muxd to read .env directly
- Use a .env.example with placeholders:
DATABASE_PASSWORD=<your-password> API_KEY_PROD=<your-key>
- Ask muxd to work with .env.example instead
When muxd creates/edits files, it stores undo/redo checkpoints:
- Location:
.git/refs/muxd-*(git stash-like) - Stored in your project's git repo
- Contains file contents at time of change
✅ Yes, if your git repo is secure:
- Private GitHub repo → Safe
- Public GitHub repo → Anyone can see old file states
❌ Risk if repo is public:
- Secrets that were removed → Still visible in stash
- Private code that was deleted → Still visible
- Make repos private if they have secrets
- Don't remove secrets, rotate them:
- ❌ Remove secret from code, push
- ✅ Rotate secret at provider, then remove code
- Use BFG Repo-Cleaner if you accidentally leaked a secret
Immediate (5 minutes):
- Revoke the key at the provider
- Generate a new key
- Restart muxd:
muxd /exitthenmuxd
Short-term (next day):
- Check provider's logs for unauthorized usage
- Monitor your account for unusual activity
- Update other tools that use the key
Long-term:
- Add key rotation to your security checklist (quarterly)
- Use secrets manager (1Password, LastPass) to auto-rotate
- Enable MFA on provider accounts
Immediate (1 hour):
- Revoke all keys (API providers, hub token)
- Delete the commit from git history:
git filter-branch --force --index-filter \ 'git rm --cached --ignore-unmatch ~/.config/muxd/config.json' \ --prune-empty --tag-name-filter cat -- --all git push --force --all - Generate new keys
Long-term:
- Add
~/.config/muxd/to.gitignore - Set up git hooks to prevent this:
git config core.hooksPath ./hooks
Recently used keys:
grep -l "ANTHROPIC_API_KEY\|OPENAI_API_KEY" ~/.bash_history ~/.zsh_history
# Note: keys might be in command history (not ideal)Recent API usage (at provider):
- Anthropic: console.anthropic.com → Dashboard
- OpenAI: platform.openai.com → Usage
Session logs (muxd):
ls -la ~/.local/share/muxd/
# muxd.db contains all your session historyQ: Can muxd see my API keys if I use env vars? A: muxd can read them at startup (standard practice), but they're not stored to disk.
Q: Can someone on the internet access my muxd daemon?
A: By default no - it only listens on localhost. If you use --bind 0.0.0.0 or run a hub with --hub-bind 0.0.0.0, it's accessible on your network. Use token auth and trusted networks.
Q: What if my computer is stolen? A: With full disk encryption enabled: keys are safe. Without it: they can be read.
Q: Can I use muxd in a Docker container?
A: Yes. Mount config and data as volumes. Use env vars for secrets (recommended).
Q: Should I grant muxd shell access?
A: Yes, that's its purpose. But only if you trust the AI model provider.
Q: How often should I rotate API keys?
A: At minimum quarterly. More often if:
- You suspect compromise
- You accidentally exposed them
- Provider recommends it
- Anthropic API Docs: https://docs.anthropic.com
- OpenAI API Docs: https://platform.openai.com/docs
- OWASP Top 10: https://owasp.org/www-project-top-ten/
Last Updated: 2026-03-02