blevene/aenv/aenv

Claude Code and agent skill by blevene/aenv

Trust tier 3
  • community
  • ext:[{"type":"hook","description":"Pre/post lifecycle hooks"}]
Source check pending

Checking that the SKILL.md file is still in the repository.

Use when the user wants to set up, switch between, or manage `aenv` namespaces — named bundles of CLAUDE.md, skills, MCP entries, and other AI-coding-harness config — in a project OR globally across `$HOME`. Triggers include `aenv …` mentioned directly, "switch namespace/profile", "activate/deactivate", "create/snapshot a namespace", "install a skill (from GitHub)", "auto-activate on cd", "what namespace am I using"; and for the global scope: "swap my global/user-level config (`~/.claude`, `~/.codex`)", "use a different Claude Code setup globally", "onboard a config repo like claude-ctrl", "swap back to my old setup". Don't use for secrets, Python venv, or Claude Code plugin marketplace ops.

Install

npx vskill@latest install blevene/aenv/aenv

Semi-extensibleMentions customization, but needs skill-specific knowledge. Read the extensible skills standard

SKILL.md

aenv

aenv is a CLI that manages named bundles of AI-coding-harness configuration (CLAUDE.md, .cursorrules, .mcp.json, skills, agents, etc.) — pin a project to a namespace, activate it, and the bundle materializes into the project as symlinks. Deactivate restores the project to its pre-activation state byte-for-byte.

Mental model in three sentences

Namespaces live at ~/.aenv/envs/<name>/ and own a manifest (aenv.toml) plus the actual files. A project gets pinned to a namespace via a one-line .aenv file at its root; aenv activate reads the pin, walks the extends chain, and materializes the resolved bundle. State lives in .aenv-state/state.json and the displaced originals (if any) sit in .aenv-state/backup/<timestamp>/ until aenv deactivate puts them back.

Two scopes: project vs global

aenv works at two scopes, and the verb prefix tells them apart:

  • Project scope (aenv <verb>) — materializes a namespace's project files into a pinned project directory (the section above). State under <project>/.aenv-state/.
  • Global scope (aenv global <verb>) — materializes a namespace's user-scope files (declared as user_files) into $HOME (~/.claude/, ~/.codex/, …). One global activation lives per user; activating another swaps it in a single transaction. State at ~/.aenv/global-state.json, displaced originals stashed under ~/.aenv/global-stash/<ts>/. This is how you swap your whole Claude Code / Codex setup. See the Global profiles section below.

User request → command map

User wants…Run this
Set up a new namespace from scratchaenv create <name> --adapter claude-code (also creates an empty CLAUDE.md; user edits it)
Build on top of an existing namespaceaenv create <name> --extends <parent> (composition; child overrides win section-by-section)
Capture a hand-shaped project as a reusable namespaceaenv snapshot <name> from inside the project
Pin + activate in a projectaenv use <name> then aenv activate. (Avoid aenv activate <name> without use first — it activates without writing a .aenv pin, leaving the project in a half-state where aenv status works but no future invocation knows what namespace was intended.)
Switch active namespace in a projectaenv deactivate && aenv use <other> && aenv activate
Restore project to pre-aenv stateaenv deactivate (then aenv unpin if they want the .aenv pin file gone too)
Add a skill they wrote themselvesaenv skill new <skill-name> --ns <namespace>
Install a skill from a public GitHub repoaenv skill import git+<url> --ns <ns> --pin <ref> [--path <subdir>] — see "Pin selection" below
Install MANY skills from a monorepo at onceaenv skill import-all git+<url> --ns <ns> --base <dir> --pin <ref> [--only a,b] — clones once, imports every <base>/<subdir>/SKILL.md; malformed skills are warned + skipped, re-runs are idempotent
Copy non-skill content (agents, commands, reference docs) from a repoaenv vendor git+<url> --ns <ns> --pin <ref> --path <subtree> --as <dest> — copies into the namespace tree, declares it under the adapter's files, records [[vendored]] provenance. --force to overwrite, re-run to refresh + report drift
Remove a skillaenv skill remove <skill-name> --ns <ns>
Reclaim cache space (orphaned skill clones)aenv cache prune
See what's active in the current projectaenv status
See where a managed file came fromaenv which <project-relative-path>
Show the resolution chain + parameters + policiesaenv status (text) or aenv status --json (structured)
Compare two namespacesaenv diff <ns_a> <ns_b>
Detect drift between project and active namespaceaenv diff (no args; runs against active)
Bump a pinned skill refedit ~/.aenv/envs/<ns>/aenv.toml, change ref = line, then re-activate in any project using the namespace
Auto-activate on cd between projects`aenv init-shell <bash\zsh\fish>` printed once into the user's rc file

Pin selection (for aenv skill import --pin <ref>)

When the user wants to import a skill, ask which form of pin they want (or pick a default and tell them):

  • Tag (v1.0, v2.39.0) — when the source repo has releases. Semantic; reads cleanly. Find via repo's Releases tab.
  • Commit SHA (40-char hex) — when there are no tags, or for absolute immutability. Find via repo's Commits view; the URL ends with the full SHA.
  • Branch name (main) — only when the user actually wants to track that branch's head at the moment of import. aenv freezes the resolved SHA either way; re-import to follow main later.

--pin is optional. Without it, aenv re-resolves to the default branch HEAD on every activation. Always pin for anything reproducible.

Global profiles (aenv global — user scope)

Swapping the user-level config that every Claude Code / Codex session reads. aenv global use is the one-command front door.

User wants…Run this
Onboard a config repo (e.g. claude-ctrl) and turn it on`aenv global use <git-url\local-path> — imports it as a namespace (if not already present) **and** activates it, in one command. --as <name> to name it; --pin <ref>` for a git ref
Switch to an already-installed global profileaenv global use <name>
Swap back to the profile you were just onaenv global use - (toggles to the previous)
Swap back to your original pre-aenv setupaenv global use baseline (auto-captured on the first-ever global activation)
Author a global profile from scratchaenv global new <name> (scaffolds an editable ~/.aenv/envs/<name>/user/.claude/CLAUDE.md + manifest), then aenv global use <name>. Add --shared to scaffold it as dual-scope (shared_files) from the start.
Add a skill to a global profileaenv skill import git+<url> --ns <name> --scope user [--path <subdir>] [--pin <ref>] (or aenv skill new <skill> --ns <name> --scope user). `--scope user` is required for global profiles — without it the skill is project-scope and won't materialize on aenv global use. User-scope skills land in ~/.claude/skills/<skill>/.
Add an arbitrary file to a global profile (settings.json, RTK.md, statusline/, …)No CLI command — edit by hand: place the content at ~/.aenv/envs/<name>/user/<rel-path> (mirroring its $HOME target, e.g. user/.claude/RTK.md), then add <rel-path> to the manifest's [adapters.<adapter>] user_files (a trailing / declares a whole directory), then aenv global use <name>. user_files is not capped by the adapter.
Capture the current ~/.claude/ as a reusable namespaceaenv global snapshot <name> [--include <path>…] [--shared] (--shared declares the captured content as shared_files so it serves project scope too)
Import a source without activating itaenv global import <source> [<name>] [--pin <ref>] [--shared] (--shared → dual-scope shared_files)
What global profile is active / what it managesaenv global status (--json for structured)
Which namespace owns ~/.claude/<file>aenv global which <path> (--json adds content_hash)
List global (user-scope) namespacesaenv global list
Check a namespace's policies / clean orphan stashesaenv global doctor [<ns>] [--fix] (--fix deletes orphan stash dirs)
Turn off the global profile (restore $HOME)aenv global deactivate (add --force only if a broken on_deactivate hook blocks it)
Run the whole sequence non-interactively (CI)append --yes to use/activate

Deprecated: aenv global activate <ns> still works but prints a deprecation notice — prefer aenv global use <ns> (a superset that also imports sources and records a swap-back point).

Unified scope flags (equivalent to the `aenv global` tree): the project verbs accept --global to act on user scope without switching command trees — aenv create <ns> --global (= global new), aenv activate <ns> --global [--yes] [--no-baseline], aenv deactivate --global [--force]. Either spelling is fine; aenv global … is not going away. Guards: --global can't be combined with a --project <path> override, --yes/--no-baseline/--force are global-only, and --prune is project-only.

One copy serving both scopes (`shared_files`): to reuse one profile's content both globally and inside a project without storing it twice, declare those paths under shared_files in the adapter block instead of user_files — e.g. [adapters.claude-code] shared_files = [".claude/CLAUDE.md", ".claude/agents/"]. Content is stored once under ~/.aenv/envs/<ns>/user/; aenv activate <ns> --global materializes it into $HOME, and aenv use <ns> + aenv activate (project) materializes the same bytes into the repo, with role-tagged files remapped to each scope's layout (.claude/CLAUDE.md → repo-root CLAUDE.md in a project). Emit shared_files directly at creation/capture time with the opt-in --shared flag on aenv create <ns> --global --shared, aenv global new --shared, aenv global snapshot --shared, or aenv global import --shared (default is unchanged — user_files; on create, --shared requires --global). Or migrate an existing global-only profile by renaming its user_files key to shared_files (no files move). files/user_files still mean project-only / user-only. Heads-up: declaring the same project destination via both files and a shared_files remap makes aenv activate print a collision warning — keep one declaration per path.

Global gotchas — surface these proactively

  • One activation per user. aenv global use <b> while <a> is active deactivates <a> and activates <b> atomically; on failure <a> is restored. There's no "both at once."
  • First activation auto-captures `baseline`. Your pre-aenv ~/ surface is saved as the baseline namespace so you always have a return point (aenv global use baseline / use -). --no-baseline opts out. An empty $HOME captures nothing.
  • Running sessions keep their config until restart. aenv swaps files on disk; a live Claude Code / Codex process read its config at launch. Tell the user to quit and relaunch the harness for a swap to take effect — aenv prints this caveat on every activation.
  • Lifecycle hooks are opt-in, never inferred. A namespace runs a setup script on activation only if it declares [lifecycle] on_activate in its manifest or a source repo's aenv-namespace.toml. aenv does NOT auto-run a repo's install.sh (those are self-installers that fight aenv). First run prompts for approval (SHA-pinned at ~/.aenv/envs/<ns>/.approved); --yes skips the prompt.
  • Recovery / lockout. If an activated namespace's hooks lock you out of a Claude Code session (e.g. a settings.json hook calls a missing runtime), open a non-Claude shell and run aenv global deactivate --force, or aenv-rescue (a standalone binary that restores $HOME from global-state.json via direct fs ops, never running lifecycle scripts).

Gotchas — surface these proactively

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 90 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
2
7-day trend score
5

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Extension points

  • hookPre/post lifecycle hooks

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/blevene/aenv/aenv/badge)](https://verified-skill.com/skills/blevene/aenv/aenv)

Something wrong with this skill or its page? Tell us.