A universal, scope-aware environment for AI coding agents.
llmenv is direnv for Claude Code and other AI tools. As you move between
networks, hosts, users, and projects, it detects the current context, selects
the matching configuration, materializes it into an agent-native config
directory, and points the agent at it — all from a shell hook that runs on every
prompt.
A single global agent config can't express "use the office MCP server only at
work", "load these plugins only in this repo", or "share memory across every
project tagged rust". llmenv lets you declare configuration once, attach it to
scopes via tags, and have the right slice activate automatically.
cargo install llmenvOr build from source:
git clone https://github.com/phaedrus1992/llmenv.git
cd llmenv
cargo build --release
./target/release/llmenv --helpllmenv init # write a template ~/.config/llmenv/config.yaml
eval "$(llmenv hook zsh)" # add this line to ~/.zshrc (or: llmenv hook bash)
llmenv doctor # validate config + adapter wiringEdit ~/.config/llmenv/config.yaml to add scopes and bundles, then drop a
.llmenv.yaml marker into any project directory to give that project its own
tags. The shell hook re-evaluates on every prompt, so the active environment
follows you between networks and repos.
See docs/getting-started.md for the full first-run walkthrough.
llmenv resolves your environment through a fixed pipeline:
scopes → tags → bundles → materialize → adapter emit
Scopes describe where you are (network, host, user, project); each
contributes tags to the active set; bundles, MCP servers, plugins, and
the memory backend fire on matching tags; llmenv materializes the result into
a content-hashed config directory; and an adapter renders it into an agent's
native shape and exports the env vars that point the agent at it.
When scopes of different kinds set conflicting scalar values, precedence runs network → host → user → project (project wins). See docs/concepts.md for the full pipeline, precedence rules, and the marker-based project scope.
~/.config/llmenv/config.yaml:
cache:
cache_dir: "~/.cache/llmenv"
scope:
network:
- id: office
match: { gateway_mac: "aa:bb:cc:dd:ee:ff" }
tags: [office]
host:
- id: workstation
match: { hostname: "work-mbp" }
tags: [workstation]
user:
- id: me
match: { user: "alice" }
tags: [me]
bundle:
- name: base
tags: [me]
vars:
EDITOR: "code"
- name: office-config
tags: [office]
vars:
OFFICE_PROXY: "proxy.internal"A project marker, ~/code/myapp/.llmenv.yaml:
id: myapp
name: MyApp
description: "Customer-facing API"
tags: [myapp, rust]
enable_bundles: [base] # force-enable a bundle regardless of tagsOn the office network, the office and me tags are active; inside
~/code/myapp, myapp and rust join them. The matching bundles, MCP servers,
and plugins activate automatically.
| Command | Purpose |
|---|---|
llmenv init [PATH] [--repo URL] |
Write a template config (optionally clone from a repo) |
llmenv export [--scope ID] [--tag TAG] |
Print export lines for the current scope (used by the hook) |
llmenv hook <zsh|bash> |
Print shell integration code |
llmenv status |
Show the active scopes, tags, and config status |
llmenv context |
Show the resolved environment and active scopes in detail |
llmenv scope-ls |
List configured scopes, marking active/orphaned |
llmenv tag-ls |
List tags, marking active/orphaned |
llmenv bundle-ls |
List bundles, marking active |
llmenv mcp-ls |
List selected MCP servers with resolved role and transport |
llmenv marketplace-ls |
List plugin marketplaces, marking referenced ones |
llmenv plugin-ls |
List plugins, marking those selected by the active scope |
llmenv plugin-sync |
Clone/fast-forward plugin marketplaces into the cache |
llmenv sync |
git add/commit/push the config repo to GitHub |
llmenv check-stale |
Warn if the running agent's config has drifted (SessionStart hook) |
llmenv prune [--all] [--older-than DUR] [--dry-run] |
Clean stale cache folders |
llmenv doctor [--gc] |
Validate wiring; optionally garbage-collect the cache |
Every command accepts --color <auto\|always\|never>. Run llmenv <command> --help
for full flag details. Per-command reference: docs/commands.md.
llmenv export emits these so the agent (and your shell) can see the resolved
context:
| Variable | Format | Meaning |
|---|---|---|
LLMENV_ACTIVE_SCOPES |
kind:id,kind:id,… |
Every matched scope, prefixed by kind |
LLMENV_ACTIVE_TAGS |
tag,tag,… (sorted) |
The active tag set |
LLMENV_ACTIVE_BUNDLES |
name,name,… |
Bundles that fired, in declaration order |
LLMENV_ACTIVE_PROJECT |
scope id | Deepest matched project (omitted if none) |
LLMENV_PROJECT_ROOT |
absolute path | Directory of the deepest .llmenv.yaml (omitted if none) |
LLMENV_ICM_CONTEXT |
text chunk | Active tags/bundles encoded for tag-scoped memory retrieval |
See docs/mcp.md for the LLMENV_ICM_CONTEXT contract.
llmenv emits agent-native config through pluggable adapters. The current adapter
surface targets Claude Code (CLAUDE.md, settings.json, .claude.json
mcpServers, hooks, permissions, plugins). The capability model is engine-neutral, with a
per-engine native escape hatch for keys that have no portable equivalent — see
docs/engines.md.
- Getting Started — install, shell hook, first run, first errors
- Concepts — the scope → tag → bundle → materialize → adapter pipeline
- Configuration Reference — every config block and field
- Commands — per-command reference
- Plugins — marketplaces, plugin collections,
plugin-sync - MCP & Memory — MCP servers, the ICM memory backend, env var contract
- Engines — engine capability model and per-engine escape hatches
- Troubleshooting — common failures and the commands that surface them
- Maintainers — release and tap-setup index
Install the git hooks so the same checks CI enforces run locally:
prek install --hook-type pre-commit --hook-type pre-pushcargo fmt --checkruns on every commit (fast).cargo clippy -D warnings,cargo test, andcargo deny checkrun on push (slower).
Install prek from https://github.com/j178/prek if you don't have it.
llmenv follows Semantic Versioning and a Keep a Changelog changelog. A version exists only once it is git-tagged — see CHANGELOG.md and the releases page for what has shipped.
llmenv is dual-licensed under either Apache-2.0 or
MIT, at your option (MIT OR Apache-2.0).
Binary distributions statically link third-party crates whose licenses require attribution; their notices are reproduced in THIRD-PARTY-LICENSES.md (a generated artifact). See docs/licensing.md for the attribution and compatibility policy and how to regenerate the notices.