A pyenv-style environment manager for Claude Code.
Activate domain-specific skills, agents, and rules per project.
Claude Code loads all your skills, agents, and rules in every session. When working across multiple domains — Go, Kubernetes, ETF, Crypto — you end up with unrelated tools always visible. There is no native way to say "in this project, only load Go tools."
claudeenv solves that.
Each project declares its domain in a .claudeenv file. With the one-time shell setup below in place, claudeenv symlinks the matching profile's skills, agents, and rules into .claude/ — and removes the previous ones — automatically before every claude session. (Skipped that step? Run claudeenv load directly to do the same thing on demand.)
# .claudeenv
[project]
golang
[global]
programmingcd ~/DevOps/Go/payment-service
claude # loads only Go skills, agents, rules
cd ~/Finance/etf-tracker
claude # loads only ETF skills, rulesLoading only the necessary profiles has a real impact on Claude Code's behaviour and cost:
| Loaded at startup | Benefit | |
|---|---|---|
| Rules | yes — always | less context consumed, better domain focus |
| Skills | partially | cleaner list, less chance of wrong tool |
| Agents | no | UX only |
Rules are loaded into the context window at every session start. Loading irrelevant rules wastes tokens and dilutes Claude's attention. A Go project doesn't need finance rules — and with claudeenv, it won't have them.
| Audience | Use case |
|---|---|
| App developer | domain isolation — load only Go tools in Go projects, only ETF tools in finance projects |
| DevOps / infra | stage isolation — different rules for dev, test, prod environments |
| Skill author | variant comparison — A/B test skills and rules on the same codebase |
| CI/CD pipeline | reproducible context — .claudeenv committed to the repo guarantees identical Claude config on every run |
See GUIDE.md for full walkthroughs of all three scenarios.
For a complete step-by-step guide including profile setup see INSTALL.md.
macOS / Linux:
curl -fsSL https://raw.githubusercontent.com/nemethk/claudeenv/main/scripts/install.sh | bashHomebrew:
brew install nemethk/tap/claudeenvGo:
GOBIN=/usr/local/bin go install github.com/nemethk/claudeenv@latestOne-time shell setup — add to ~/.zshrc or ~/.bashrc:
eval "$(claudeenv init)"Reload your shell:
source ~/.zshrc # or ~/.bashrcSee claudeenv symlink real profiles into .claude/ — no setup beyond cloning two repos:
# profiles repo: golang + kubernetes project profiles, a "programming" global profile
git clone https://github.com/nemethk/claudeenv-demo-profiles.git ~/claudeenv-demo-profiles
# project repo — .claudeenv already declares [project] golang kubernetes / [global] programming
git clone https://github.com/nemethk/claudeenv-demo-project.git ~/claudeenv-demo-project
export CLAUDEENV_DIR_PROJECT=~/claudeenv-demo-profiles/claude-project
export CLAUDEENV_DIR_GLOBAL=~/claudeenv-demo-profiles/claude-global
cd ~/claudeenv-demo-project
claudeenv loadclaudeenv: loaded project profile "golang"
claudeenv: loaded project profile "kubernetes"
claudeenv: loaded global profile "programming"
Inspect .claude/skills/, .claude/agents/, .claude/rules/ — they're now symlinks into the cloned profiles.
Want this to happen automatically before every claude session instead of running claudeenv load by hand? Add to ~/.bashrc or ~/.zshrc:
# Claude Code - Claudeenv
eval "$(claudeenv init)"claudeenv project use golang # set project profile, writes .claudeenv
claudeenv project add kubernetes # add a second profile
claudeenv project list # list available project profiles
claudeenv project reset # remove .claudeenvclaudeenv global use finance # set global profile
claudeenv global list # list available global profiles
claudeenv global reset # remove global profileclaudeenv new <name> # scaffold a new project profile
claudeenv load # manually reload profiles
sudo claudeenv upgrade # update to latest version.claudeenv — committed to the repo, shared with the team:
[project]
golang
kubernetes
[global]
programming.claudeenv.local — gitignored, personal overrides:
# override global profile
[global]
finance
# override global profiles directory for this project
[global.dir]
~/my-personal/claudeenv/claude-global
# add to team's project profile (+ prefix required)
[project]
+etf| Rule | Behaviour |
|---|---|
[global] in local |
replaces team default |
[global.dir] in local |
overrides CLAUDEENV_DIR_GLOBAL for this project |
[project] in local |
additive only — + prefix required |
Heads up:
claudeenv project use <profile>rewrites.claudeenvfrom scratch and drops any existing[global]line — if your committed file declares a team-default global (like the example above), useclaudeenv project add <profile>to add further project profiles without losing it.
Override where profiles are stored via environment variables:
# ~/.zshrc or ~/.bashrc
export CLAUDEENV_DIR_GLOBAL=~/my-profiles/claude-global
export CLAUDEENV_DIR_PROJECT=~/work/team-profiles/claude-project| Variable | Default |
|---|---|
CLAUDEENV_DIR_GLOBAL |
~/claudeenv/claude-global |
CLAUDEENV_DIR_PROJECT |
~/claudeenv/claude-project |
Load profiles automatically when you enter a directory:
eval "$(claudeenv init --hook)"Note:
--hookgenerates zsh-specific code (add-zsh-hook chpwd). bash users should use the defaulteval "$(claudeenv init)"which wraps theclaudecommand instead.
Add to your projects:
.claudeenv.local
.claude/skills/
.claude/agents/
.claude/rules/Commit .claudeenv — it declares the domain for the team and CI.
claudeenv follows the conventions of pyenv, goenv, and direnv.
| Tool | File | Purpose |
|---|---|---|
| pyenv | .python-version |
Python version per project |
| goenv | .go-version |
Go version per project |
| claudeenv | .claudeenv |
Claude Code profile per project |
Bug fixes, new features, and documentation improvements are welcome — see CONTRIBUTING.md.