English | 简体中文
xenv is a local development environment manager for SDK versions, environment variables, and PATH entries. It is designed for developers who switch between projects that need different toolchains or local runtime settings.
- Discover and activate locally installed SDKs, such as Go and Node.js.
- Manage global, project-local, and shell-session environment variables.
- Manage global, project-local, and shell-session
PATHentries. - Load project state from
.xenv.tomlwhen you enter a directory through the shell integration. - Check effective SDKs and project tool requirements.
- Generate shell hooks for bash, zsh, PowerShell, and cmd/clink.
Install by Eget:
eget install inhere/xenvInstall the latest version with Go:
go install github.com/inhere/xenv/cmd/xenv@latestEnable shell integration first. This lets xenv use, xenv set, and xenv path add update the current shell instead of only printing shell script output.
Bash:
eval "$(xenv shell --type bash)"Zsh:
eval "$(xenv shell --type zsh)"PowerShell:
Invoke-Expression (&xenv shell --type pwsh)Initialize the default configuration explicitly if you want to create it before first use:
xenv config initThe default configuration file is created at:
~/.config/xenv/config.yaml
Then index locally installed SDKs and activate a version:
xenv sdk index
xenv sdk list
xenv use go:latestSave project-local settings to .xenv.toml:
xenv use -s go:1.24
xenv set -s APP_ENV local
xenv path add -s ./binInspect status and run checks:
xenv status
xenv checkGenerate shell integration scripts:
xenv shell --type bash
xenv shell --type zsh
xenv shell --type pwsh
xenv shell --type cmdInstall the hook into your shell profile:
# PowerShell
xenv shell --install -t pwsh --profile $PROFILE.CurrentUserAllHosts
# bash or zsh
xenv shell --install -t $SHELLPowerShell can also load the hook directly:
Invoke-Expression (&xenv shell --type pwsh)
# or
xenv shell --type pwsh | Out-String | Invoke-ExpressionWhen shell integration is active, xenv keeps a shell-session state file and can automatically load matching .xenv.toml files when you change directories.
Most environment-changing commands support four scopes:
| Scope | Flag | Storage | Use case |
|---|---|---|---|
| Session | none | ~/.config/xenv/session/<session_id>.json |
Temporary changes for the current hooked shell |
| Project | -s, --save, or -d |
nearest .xenv.toml |
Project-specific SDKs, env vars, and paths |
| Global | -g or --global |
~/.config/xenv/global.toml |
Defaults shared by all projects |
| System | -S or --system |
OS user environment: HKCU\Environment on Windows, the shell startup file (~/.bashrc, ~/.zshrc) xenv block on Linux/macOS |
Values that must be visible to new processes without the xenv hook |
Examples:
# Current shell session
xenv use go:latest
xenv set APP_ENV local
xenv path add ./bin
# Project .xenv.toml
xenv use -s go:1.24
xenv set -s APP_ENV local
xenv path add -s ./bin
# Global state
xenv use -g go:1.24
xenv set -g GOPROXY https://proxy.golang.org,direct
xenv path add -g ~/.local/bin
# OS user environment
xenv set -S GOPROXY https://proxy.golang.org,direct
xenv unset -S GOPROXY
xenv path add -S ~/.local/bin
xenv path remove -S ~/.local/bin-S/--system can not be combined with -g/--global or -s/--direnv. New PATH entries are prepended, so they take priority. Run xenv from a hooked shell to also update the current shell immediately.
xenv run (alias exec) builds an SDK/ENV/PATH environment from options and runs a command inside it. Nothing is written to xenv state and no shell hook is required, so it also works from editors, CI runners and GUI-launched processes.
xenv run -u go:1.24,node:22 -p ./bin -e APP_ENV=local -- go build ./...
xenv exec -u go:1.24 --cwd D:/work/proj -- go test ./...
xenv run -u go --print -- go version| Option | Description |
|---|---|
-u, --use <spec,...> |
SDK specs to activate, repeatable and comma separated (go, go:1.24, go@1.24) |
-p, --path <dir> |
Directory prepended to PATH, repeatable |
-e, --env <KEY=VALUE> |
Environment variable to set, repeatable |
-c, --cwd <dir> |
Working directory for the command |
--print |
Print the resolved environment and command without running it |
Rules:
- ENV order: inherited environment, then SDK
active_env, then--env; the last value wins. - PATH order:
--pathentries, then SDK bin directories, then the inheritedPATH; duplicate entries are dropped and new entries win. - Options of the target command must be placed after
--, otherwise they are parsed asxenv runoptions. - The exit status is the child's status,
127when the command is not found and2forxenvside errors.
xenv status: Show current state for this directory and shell, including Effective State, Session Context, and Runtime State.xenv sdk list: List local SDK inventory.xenv env list: List xenv-managed environment variable state.xenv path list: List xenv-managedPATHstate.xenv check: Check whether Effective State and project tool requirements are satisfied.
Top-level xenv list / xenv ls is not kept in v0; use xenv status for state diagnostics.
Project state is stored in .xenv.toml. The shell hook can load it automatically when you enter the project directory.
Example:
paths = [
"./bin",
"windows:C:/Program Files (x86)/NSIS",
"linux:/opt/nsis/bin",
"darwin:/opt/homebrew/bin",
]
[sdks]
go = "1.24"
node = "20"
flutter = "windows:3.27"
[envs]
APP_ENV = "local"
[tools]
rg = "*"
golangci-lint = ">=1.60,required"Sections:
paths: Project-local entries added toPATH. Prefix an entry withwindows:,linux:, ordarwin:to load it only on that OS; the prefix is stripped before adding it toPATH.sdks: SDK versions activated for the project. Prefix a version withwindows:,linux:, ordarwin:to activate it only on that OS; the prefix is stripped before version matching.envs: Environment variables loaded for the project.tools: External tool requirements checked byxenv check tools.
When source_project_scripts: true is set in config.yaml, entering a directory also sources project scripts: .xenv.sh / .xenv.ps1 and a compatible .envrc (bash/zsh) or .envrc.ps1 (pwsh) found in the directory or its parents. Keep this disabled for untrusted directories, since those files run with your shell's privileges.
Each init-direnv run records what it applied to the current shell in the XENV_APPLIED_DIRENV environment variable (a JSON record: applied .xenv.toml, added PATH entries, changed variables with their previous values, activated SDKs).
cdinto another project or out of the project: the recordedPATHentries are removed, variables are restored to their previous values (unsetwhen they were not set before), and the new directory is applied in the same shell command.cdinside the same project (including subdirectories): nothing is re-applied or reverted.-s/--direnvcommands (use -s,set -s,unset -s,path add/remove -s) update the record too, so their effect is reverted on leave.- The record lives in the shell environment only: it is per-shell, disappears with the shell, and is never written to state files.
Not reverted on leave:
source_project_scripts/.envrcside effects, since the scripts run in your current shell (keep the option off for directories you do not trust).- Changes made outside xenv (for example editing
PATHyourself), and removals that were not recorded. -g/--globaland-S/--systemchanges, which are not directory scoped.
Use xenv status --layers to inspect the current record.
SDKs are configured in config.yaml, then indexed from local installation directories.
Common commands:
xenv sdk index
xenv sdk list
xenv sdk list --all
xenv sdk show go
xenv sdk where go:1.24
xenv sdk where --bin go:1.24
xenv sdk which go:1.24Version specs can use either name:version or name@version:
xenv use go:1.24
xenv use node@20When the version is omitted, latest is used:
xenv use go
xenv use go:latest
xenv use go:stablelatest and stable both resolve to the highest installed version. Other aliases such as lts are not supported yet and fail with a message asking for an explicit version.
Activate or deactivate multiple SDKs at once:
xenv use go:1.24 node:20
xenv unuse go:1.24 node:20List environment variables managed by xenv:
xenv env
xenv env listSet and unset values:
xenv env set APP_ENV=local
xenv env set APP_ENV=local DEBUG=true
xenv env set APP_ENV local
xenv env unset APP_ENVenv set accepts one or more KEY=VALUE pairs. When exactly two arguments are given and the first one contains no =, they are read as <name> <value> (the original form).
Top-level shortcuts are also available:
xenv set APP_ENV local
xenv unset APP_ENVUse -s for project state or -g for global state:
xenv set -s APP_ENV local
xenv unset -g GOPROXYUse -S to write to the OS user environment, so new processes read the value without the xenv hook:
xenv set -S GOPROXY https://proxy.golang.org,direct
xenv unset -S GOPROXYOn Windows the value is written to HKCU\Environment; on Linux/macOS it is written to the xenv block of ~/.bashrc or ~/.zshrc. -S can not be combined with -g or -s.
List the OS user environment variables in addition to the xenv-managed state:
xenv env list -SList managed PATH entries:
xenv path
xenv path listAdd, remove, and search entries:
xenv path add ./bin
xenv path remove ./bin
xenv path search goUse -s for project state or -g for global state:
xenv path add -s ./bin
xenv path add -g ~/.local/binUse -S to add or remove an entry in the OS user PATH:
xenv path add -S ~/.local/bin
xenv path remove -S ~/.local/binThe entry is prepended, and the original value type and %VAR% references are preserved on Windows. Adding or removing a path that does not change anything fails with a message instead of writing a duplicate entry.
List the OS user PATH entries in addition to the xenv-managed state:
xenv path list -SRun all checks:
xenv checkCheck SDK availability for Effective State:
xenv check sdkCheck project tool requirements from .xenv.toml:
xenv check toolsTool requirements live under [tools]:
[tools]
rg = "*"
golangci-lint = ">=1.60,required"Default files:
~/.config/xenv/config.yaml
~/.config/xenv/global.toml
~/.config/xenv/session/<session_id>.json
~/.config/xenv/sdks.local.json
~/.config/xenv/hooks
Show the active configuration summary:
xenv configRead selected configuration values:
xenv config get bin_dir
xenv config get shell_hooks_dirEdit the configuration file with $XENV_EDITOR, $VISUAL or $EDITOR:
xenv config --editExport configuration:
xenv config export zip
xenv config export jsonConfiguration files support environment variable expansion in values, for example ${HOME} or ${XENV_SDK_ROOT}.
Example config.yaml:
bin_dir: "~/.local/bin"
eget_enable: false
eget_store_file: ""
check_tools_on_direnv: false
source_project_scripts: false
allow_up_match: 1
shell_hooks_dir: "~/.config/xenv/hooks"
global_env: {}
global_paths: []
sdks:
- name: go
alias: golang
install_dir: "${XENV_SDK_ROOT}/go{version}"
bin_dir: "bin"
active_env:
GOROOT: "{install_dir}"
- name: node
install_dir: "${XENV_SDK_ROOT}/node-v{version}"
bin_dir: "bin"SDK fields:
| Field | Description |
|---|---|
name |
SDK name used in commands, such as go |
alias |
Optional alias for display or lookup |
install_dir |
SDK installation directory template; {version} is replaced by the selected version and is used to strictly match indexed directory names; {anyword} matches one non-empty path-name segment |
bin_dir |
SDK binary directory relative to install_dir |
active_env |
Environment variables exported when the SDK is active |
other_versions |
Additional versions that should be considered by the SDK index |
| Command | Description |
|---|---|
xenv sdk index |
Scan configured SDK directories and update the local SDK index |
xenv sdk list |
List installed SDKs |
xenv sdk list --all |
List all configured SDKs, including uninstalled ones |
xenv sdk show <name> |
Show details for one SDK |
xenv sdk where [--bin] <name:version> |
Print an SDK installation or binary path |
xenv use [-g] [-s] <name:version>... |
Activate SDK versions |
xenv unuse [-g] [-s] <name:version>... |
Deactivate SDK versions |
xenv env list |
List managed environment variables, -S also lists the OS user environment |
xenv env set [-g] [-s] [-S] <KEY=VALUE>... |
Set environment variables (<name> <value> also accepted) |
xenv env unset [-g] [-s] [-S] <name...> |
Remove environment variables |
xenv path list |
List managed PATH entries, -S also lists the OS user PATH |
xenv path add [-g] [-s] [-S] <path> |
Add a PATH entry |
xenv path remove [-g] [-s] [-S] <path> |
Remove a PATH entry, --match removes every entry containing the value |
xenv path search <value> |
Search current PATH entries |
xenv run [-u spec,...] [-p dir] [-e KEY=VALUE] [-c dir] [--print] -- <cmd> [args...] |
Run a command with a one-shot environment |
xenv status |
Show Effective State for the current directory |
xenv status --layers |
Show Global State, Directory State, and Session Context layers |
xenv status --runtime |
Show Runtime State detected from PATH and SDK active env vars |
xenv check |
Run SDK and tool checks |
xenv check sdk |
Check SDK availability for Effective State |
xenv check tools |
Check project tool requirements |
xenv shell --type <shell> |
Print shell hook script |
xenv shell --install -t <shell> |
Install shell hook into a shell profile |
xenv config |
Show configuration summary |
xenv config get <name> |
Read a supported configuration value |
xenv config export <zip|json> |
Export configuration |
Aliases:
xenv sdksforxenv sdkxenv stforxenv statusxenv eforxenv envxenv pforxenv pathxenv cfgforxenv configxenv sdk refreshorxenv sdk scanforxenv sdk indexxenv sdk whichforxenv sdk wherexenv path rmorxenv path deleteforxenv path remove
Run tests:
go test ./...Build without release compression:
go build ./cmd/xenvBuild with the project Makefile:
make buildThe Makefile uses UPX for compression on supported targets, so upx must be available for those build targets.