cvm
Documentation
GitHub
Concepts

Core concepts

How cvm maps onto Claude Code configuration without modifying Claude Code itself.

CLAUDE_CONFIG_DIR

Claude Code locates its config via CLAUDE_CONFIG_DIR (default ~/.claude). cvm sets that variable to ~/.cvm/envs/<name> while an environment is active or for a single run/open child process.

CVM_ENV

Process-scoped name of the active environment. Used by cvm current, cvm list, and statusline scripts.

Activation protocol

The compiled binary cannot change the parent shell. Hidden resolvers print data the hook applies:

Shell hooks additionally:

Reserved dotenv keysPATH, PS1, CLAUDE_CONFIG_DIR, and any CVM_* key in an environment .env are ignored so activation state cannot be poisoned.

Directory layout

~/.cvm/
├── bin/                  # cvm binary (install.sh)
└── envs/
    └── work/             # = CLAUDE_CONFIG_DIR when active
        ├── .env
        ├── skills/
        ├── bin/          # claude + skills shims
        ├── settings.json
        └── ...           # whatever Claude Code writes

Shims

Each env ships bin/claude and bin/skills (plus .cmd on Windows). They set CLAUDE_CONFIG_DIR/CVM_ENV from their parent directory, strip their own bin from PATH to avoid recursion, then exec the real tool. The skills shim runs npx --yes skills.

cvm.yaml surface

Export/import only touch settings.json (permissions + mcpServers), skill names, and .env keys. Credentials, history, and .env values are never read into the manifest.