{"id":13683606,"url":"https://github.com/Shopify/shadowenv","last_synced_at":"2025-04-30T13:31:32.028Z","repository":{"id":34216081,"uuid":"164012005","full_name":"Shopify/shadowenv","owner":"Shopify","description":"reversible directory-local environment variable manipulations","archived":false,"fork":false,"pushed_at":"2024-10-29T15:33:22.000Z","size":653,"stargazers_count":394,"open_issues_count":18,"forks_count":18,"subscribers_count":387,"default_branch":"main","last_synced_at":"2024-10-30T01:05:13.595Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://shopify.github.io/shadowenv/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Shopify.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-01-03T19:04:03.000Z","updated_at":"2024-10-29T15:33:21.000Z","dependencies_parsed_at":"2024-01-08T07:58:05.323Z","dependency_job_id":"2c3dc18a-aa1a-43ec-b2a0-83f7c016596b","html_url":"https://github.com/Shopify/shadowenv","commit_stats":{"total_commits":192,"total_committers":18,"mean_commits":"10.666666666666666","dds":0.515625,"last_synced_commit":"0e9731891a65a8e50cc05935bbd72b2487f07af5"},"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2Fshadowenv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2Fshadowenv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2Fshadowenv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shopify%2Fshadowenv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Shopify","download_url":"https://codeload.github.com/Shopify/shadowenv/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224212303,"owners_count":17274387,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T13:02:18.165Z","updated_at":"2024-11-12T03:31:29.442Z","avatar_url":"https://github.com/Shopify.png","language":"Rust","funding_links":[],"categories":["Rust"],"sub_categories":[],"readme":"# Shadowenv\n\nShadowenv provides a way to perform a set of manipulations to the process environment upon entering\na directory in a shell. These manipulations are reversed when leaving the directory, and there is\nsome limited ability to make the manipulations dynamic.\n\n![shadowenv in action](https://burkelibbey.s3.amazonaws.com/shadowenv.gif)\n\nIn order to use shadowenv, add a line to your shell profile (`.zshrc`, `.bash_profile`, or\n`config.fish`) reading:\n\n```bash\neval \"$(shadowenv init bash)\" # for bash\neval \"$(shadowenv init zsh)\"  # for zsh\nshadowenv init fish | source  # for fish\n```\n\nWith this code loaded, upon entering a directory containing a `.shadowenv.d` directory,\nany `*.lisp` files in that directory will be executed and you will see \"activated shadowenv.\" in your\nshell.\n\nThe syntax for the `.shadowenv.d/*.lisp` files is [Shadowlisp](https://shopify.github.io/shadowenv/),\na minimal [Scheme-like](https://en.wikipedia.org/wiki/Scheme_(programming_language)) language.\nUnlike other tools like [direnv](https://direnv.net/), this has the interesting property of allowing\nus to do things like simulate `chruby reset` upon entry into a directory without the user having\n`chruby` installed (and undo these changes to the environment when `cd`'ing back out):\n\n```scheme\n(provide \"ruby\")\n\n(when-let ((ruby-root (env/get \"RUBY_ROOT\")))\n  (env/remove-from-pathlist \"PATH\" (path-concat ruby-root \"bin\"))\n  (when-let ((gem-root (env/get \"GEM_ROOT\")))\n    (env/remove-from-pathlist \"PATH\" (path-concat gem-root \"bin\"))\n    (env/remove-from-pathlist \"GEM_PATH\" gem-root))\n  (when-let ((gem-home (env/get \"GEM_HOME\")))\n    (env/remove-from-pathlist \"PATH\" (path-concat gem-home \"bin\"))\n    (env/remove-from-pathlist \"GEM_PATH\" gem-home)))\n```\n\nThe intention isn't really for users to write these files directly, nor to commit them to\nrepositories , but for other tool authors to generate configuration on the user's machine. Here's\nan example of a generated Shadowlisp file for activating ruby 2.7.1:\n\n```scheme\n(provide \"ruby\" \"2.7.1\")\n\n(when-let ((ruby-root (env/get \"RUBY_ROOT\")))\n (env/remove-from-pathlist \"PATH\" (path-concat ruby-root \"bin\"))\n (when-let ((gem-root (env/get \"GEM_ROOT\")))\n   (env/remove-from-pathlist \"PATH\" (path-concat gem-root \"bin\")))\n (when-let ((gem-home (env/get \"GEM_HOME\")))\n   (env/remove-from-pathlist \"PATH\" (path-concat gem-home \"bin\"))))\n\n(env/set \"GEM_PATH\" ())\n(env/set \"GEM_HOME\" ())\n(env/set \"RUBYOPT\" ())\n\n(env/set \"RUBY_ROOT\" \"/opt/rubies/2.7.1\")\n(env/prepend-to-pathlist \"PATH\" \"/opt/rubies/2.7.1/bin\")\n(env/set \"RUBY_ENGINE\" \"ruby\")\n(env/set \"RUBY_VERSION\" \"2.7.1\")\n(env/set \"GEM_ROOT\" \"/opt/rubies/2.7.1/lib/ruby/gems/2.7.0\")\n\n(when-let ((gem-root (env/get \"GEM_ROOT\")))\n  (env/prepend-to-pathlist \"GEM_PATH\" gem-root)\n  (env/prepend-to-pathlist \"PATH\" (path-concat gem-root \"bin\")))\n\n(let ((gem-home\n      (path-concat (env/get \"HOME\") \".gem\" (env/get \"RUBY_ENGINE\") (env/get \"RUBY_VERSION\"))))\n  (do\n    (env/set \"GEM_HOME\" gem-home)\n    (env/prepend-to-pathlist \"GEM_PATH\" gem-home)\n    (env/prepend-to-pathlist \"PATH\" (path-concat gem-home \"bin\"))))\n```\n\n## `.shadowenv.d`\n\nThe `.shadowenv.d` directory will generally exist at the root of your repository (in the same\ndirectory as `.git`.\n\nWe *strongly* recommend creating `gitignore`'ing everything under `.shadowenv.d` (`echo '*' \u003e .shadowenv.d/.gitignore`).\n\nA `.shadowenv.d` will contain any number of `*.lisp` files. These are evaluated in the order in which\nthe OS returns when reading the directory: generally alphabetically. We *strongly* recommend using\na prefix like `090_something.lisp` to make it easy to maintain ordering.\n\n`.shadowenv.d` will also contain a `.trust-\u003cfingerprint\u003e` file if it has been marked as trusted. (see\nthe trust section).\n\n## Language\n\nSee https://shopify.github.io/shadowenv/ for Shadowlisp documentation.\n\n## Integrations\n\nShadowenv has plugins for multiple editors and/or IDEs:\n\n* [shadowenv.vim](https://github.com/Shopify/shadowenv.vim)\n* [shadowenv.el](https://github.com/Shopify/shadowenv.el)\n* [vscode-shadowenv](https://github.com/Shopify/vscode-shadowenv)\n* [atom-shadowenv](https://github.com/Shopify/atom-shadowenv)\n* [sublime-shadowenv](https://github.com/Shopify/sublime-shadowenv)\n* [intellij-shadowenv](https://github.com/Shopify/intellij-shadowenv)\n\n## Trust\n\nIf you `cd` into a directory containing `.shadowenv.d/*.lisp` files, they will not be run and you\nwill see a message indicating so. This is for security reasons: we don't want to enable random\nstuff downloaded from the internet to modify your `PATH`, for example.\n\nYou can run `shadowenv trust` to mark a directory as trusted.\n\nTechnically, running `shadowenv trust` will create a file at `.shadowenv.d/.trust-\u003cfingerprint\u003e`,\nindicating that it's okay for `shadowenv` to run this code. The `.shadowenv.d/.trust-*` file contains\na cryptographic signature of the directory path. The key is generated the first time `shadowenv` is\nrun, and the fingerprint is an identifier for the key.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FShopify%2Fshadowenv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FShopify%2Fshadowenv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FShopify%2Fshadowenv/lists"}