{"id":17786680,"url":"https://github.com/ypares/envil","last_synced_at":"2025-07-03T06:04:57.067Z","repository":{"id":257862307,"uuid":"866530681","full_name":"YPares/envil","owner":"YPares","description":"envil forges Nix flakes and manages stacked environments","archived":false,"fork":false,"pushed_at":"2025-04-25T23:38:25.000Z","size":2275,"stargazers_count":19,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-29T07:11:33.133Z","etag":null,"topics":["nix","nix-flakes","nu","nushell"],"latest_commit_sha":null,"homepage":"","language":"Nushell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/YPares.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-10-02T12:35:52.000Z","updated_at":"2025-05-14T07:34:56.000Z","dependencies_parsed_at":"2025-04-01T08:35:23.783Z","dependency_job_id":"4249343b-2387-4938-9700-4eafd5b68f4e","html_url":"https://github.com/YPares/envil","commit_stats":{"total_commits":88,"total_committers":3,"mean_commits":"29.333333333333332","dds":"0.26136363636363635","last_synced_commit":"540b8f649b8a1b3a53c81a2cdb4fc1227fee051c"},"previous_names":["ypares/envil"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/YPares/envil","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YPares%2Fenvil","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YPares%2Fenvil/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YPares%2Fenvil/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YPares%2Fenvil/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/YPares","download_url":"https://codeload.github.com/YPares/envil/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/YPares%2Fenvil/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263271502,"owners_count":23440396,"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":["nix","nix-flakes","nu","nushell"],"created_at":"2024-10-27T10:04:22.490Z","updated_at":"2025-07-03T06:04:57.051Z","avatar_url":"https://github.com/YPares.png","language":"Nushell","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![built with garnix](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fgarnix.io%2Fapi%2Fbadges%2FYPares%2Fenvil%3Fbranch%3Dmaster)](https://garnix.io/repo/YPares/envil)\n\n# envil\n\n\u003cimg src=\"./assets/logo.png\" width=\"250\"/\u003e\n\n`envil` is a tool to:\n\n- describe a set of environments (\"toolkits\") that contain executables you regularly want to access and hide rapidly (see for instance [here](./examples/statedir/envil-state.yaml)),\n- install and switch on/off such environments globally in an environment stack, or conversely:\n- start a subshell with a specific set of environments locally activated.\n\n`envil` does so by using [Nix](https://nixos.org), and by inspecting or creating _Nix flakes_ on the fly.\nIn the Nix ecosystem, a _flake_ is a file that describes a set of programs (the flake _outputs_) for various possible systems,\nand how to download and build those programs and their dependencies (the flake _inputs_). Nix can then install those programs in an isolated store,\nie. without risking potential conflicts with pre-existing tools on your system. Nix being a simple yet generic and powerful programming language,\nsome seemingly simple use cases (such as listing a fixed set of pre-existing packages in a flake and installing them) may _appear_ more complex\nto tackle than they need to.\n\n`envil` targets some of those simple Nix use cases. It aims at providing people who are not regular Nix users a quick way to start with custom,\nisolated \u0026 reproducible (ie. \"rebuildable identically elsewhere\") environments, one of the major reasons to use Nix.\n\nIt is important to note that `envil` is **not** a tool to:\n\n- install and manage Nix for you,\n- write complicated Nix logic for you.\n\nIf you already know and use Nix, `envil` builds upon Nix profiles, to enable you and incite you to be selective about what you put in your `PATH`, to\nquickly switch between environments, and to start shells to avoid situations where you end up with two different versions\nof the same tool in your `PATH`, or things like two different `python` installations but each one configured with its own libraries,\nleaving you unable to select which one you want.\n\n`envil` has been developped with cooperation between Nix-users and non Nix-users in mind, notably in development teams where some people would\nwant to introduce Nix to provision their local development environment(s) without too much friction.\nThis is why `envil` introduces a simple and versionable yaml environment description, but also directly supports any flake as a package source,\nand also why it operates by outputting regular Nix flakes that are locked and versionable too.\n\n![Demo GIF](./assets/demo.gif)\n\n## Setup\n\nTo install `envil`, first you need to [install Nix](https://determinate.systems/nix/). Then just do:\n\n```sh\nnix profile install github:YPares/envil#envil\n```\n\nto have `envil` available in your `PATH`. Alternatively, you can run `nix run github:YPares/envil` everytime you want to use `envil`.\n\nFinally, add `$HOME/.envil/current/bin` to your `PATH`. This is the directory in which envil will manage a Nix profile for you,\nby swapping in and out the binaries of your current environment(s).\n\nNote: if you are using Linux, it's better to set your `PATH` in your `$HOME/.pam_environment` or `$HOME/.profile` so other programs than your terminal can see the updated `PATH`.\nDon't forget to log out and back in after.\n\n## Usage\n\n`envil` manages environments as a _stack_. That means several envs can be activated at the same time. The main commands\nare `envil push` and `envil pop` to add or remove envs from the stack, and `envil show` to view the stack's current state.\n\nThe second important concept is the notion of _statedir_. That is some directory that contains a configuration file that\ndescribes the desired _state_ of your environments. This file can be one of the following two:\n\n- either an `envil-state.yaml` (\"yaml statedir\"): `envil` will generate a flake for each environment inside the statedir\n  (in the `flakes` subfolder). Each env has its own flake, so envs are locked separately.\n- or a `flake.nix` (\"flake statedir\"): `envil` will look at the attributes exported under `packages.\u003ccurrent_system\u003e` and\n  consider each one to be an environment. All the envs are in the same flake, so envs are locked together.\n\nTherefore any regular Nix flake is directly usable as a statedir, and in such case `envil` will use it as is, in a readonly\nfashion, so it's up to you to write it and update its lockfile as you see fit. This allows to use remote flakes too (e.g. from Github)\nwithout having to pre-clone them locally. On the other hand, _yaml_ statedirs must be local, writeable directories.\n\nNote that if a statedir contains both files, `envil` will use the `flake.nix` and ignore the `envil-state.yaml`.\n\nMost `envil` subcommands take a `-d` argument to select which statedir to operate with (regardless of whether it is a yaml or flake statedir),\nand register it as the _current_ statedir so you don't have to repeat it everytime.\n\nIf the folder given to `-d` does not exist or is empty, `envil` will create it with a default `envil-state.yaml` that you can then edit.\n\nEach environment present in your stack can come from a different statedir, thus allowing decomposition. You can for instance\nhave your own personal statedir for tools only you use, install tools from public flakes on Github, and then have another statedir that is part of a git project\nand used by all the developers of that project. Nix `flake.lock` files ensure that all teammembers will use the exact same version\nof the same tools, and Nixpkgs `buildEnv` function will make sure you do not have conflicts (different executables with the same name) in your stack.\n\nRun `envil -h` to see all the commands available. For instance, if you clone that repository and `cd` into your local clone,\nyou can run the following:\n\n- `envil shell -d examples/statedir`: show all the envs defined in the example statedir (`-d`) and select some of them.\n  Then open those envs in a subshell. Register `examples/statedir` as the current statedir\n- `envil switch -d examples/statedir`: select several environments in the statedir, and then replace the whole stack with them.\n  Register `examples/statedir` as the current statedir.\n- `envil push`: select an env from the current statedir (no `-d` was given) to add to the top of the env stack.\n  Globally add to your `PATH` the executables it contains\n- `envil pop`: remove the last env added to the stack\n- `envil toggle`: toggle on/off some environments in the stack (same effect than push/pop, but it's easier to reactivate them afterwards)\n- `envil show` (or just `envil`): show the current statedir, the envs in the stack, the bins in the PATH, and the envs\n  activated in the current subshell (if any). The source (statedir of origin) of each environment is also indicated, with a flake URL if the\n  statedir is a Nix flake, and a regular absolute path if it is a yaml statedir\n- `envil update`: update the flake.lock files for some environments in the current statedir. This is only for yaml statedirs.\n  This is the command to use if you want to generate the flakes for a yaml statedir ahead of time, without activating any env\n- `envil switch -r`: reload the current stack (for instance if you used `envil update` previously)\n\nSubshells started by `envil` export the `$SHELL_ENV` environment variable. You can use it in your shell prompt (eg. `PS1` for `bash`) so it shows\nwhich env(s) is (are) activated in the subshell. For instance if you use `bash`, add the following to your `.bashrc`:\n\n```bash\nif [[ -n \"$SHELL_ENV\" || \"$SHLVL\" \u003e 1 ]]; then\n    shell_env_bit='\\e[0;33m[$SHELL_ENV($SHLVL)]\\e[0m'\nfi\n\nPS1=\"${shell_env_bit}...the rest of your prompt...\"\n```\n\n(`$SHLVL` is a standard `bash` environment variable telling you how many levels of subshells you are currently in)\n\n## Updating `envil`\n\nRun `nix profile upgrade envil --refresh` to update `envil` to the latest version.\n\n## Pushing your current stack to a binary cache\n\nIf you use `cachix` and if you set up a cache on \u003chttps://www.cachix.org\u003e, run:\n\n```sh\ncachix push \u003ccache_name\u003e $HOME/.envil/current\n```\n\nAnybody who runs `cachix use \u003ccache_name\u003e` and switches to the same env(s) than you will benefit from the binary cache.\n\nIf you are using an [external store](https://nix.dev/manual/nix/2.25/store/types/) as a binary cache, you can use `nix copy`:\n\n```sh\nnix copy $HOME/.envil/current --to \"\u003ccache_url\u003e\"\n```\n\n## Notes about versioning and workflow\n\nIn each statedir containing an `envil-state.yaml`, `envil` will generate a `flakes` folder, itself containing a `flake.nix` and `flake.lock` for each env.\nThese are meant to be added to your version control system, so that any person using these envs too will have the exact\nsame tool versions you do.\n\nConversely, the contents of your `$HOME/.envil` are _not_ meant to be versioned. They represent the state of your _own_ stack,\nwhich is meant to be transient. If you often end up activating the exact same set of envs, you can declare a new env\nin your statedir that will _extend_ from them, ie. merging them all together, to make things more convenient.\nStatedirs can also _include_ one another to create envs that extend from envs from different statedirs.\n\nYou have two possible workflows with `envil`:\n\n- Decomposition: smaller and separated envs, with frequent use of `envil push` and `pop`\n- Composition: bigger environments that _extend_ one another, with frequent use of `envil switch`\n\n## Related tools \u0026 philosophy\n\n`envil` is related to [`niv`](https://github.com/nmattia/niv), [`devenv`](https://devenv.sh/), [`devbox`](https://www.jetify.com/docs/devbox/),\n[`flox`](https://flox.dev/), [`flakey-profile`](https://github.com/lf-/flakey-profile) and\n[`home-manager`](https://github.com/nix-community/home-manager) but with a focus on:\n\n- usability by people who do not write or write little Nix code;\n- compatibility with existing Nix tools, and no disruption of your existing Nix installation and configuration;\n- reusable and composable environments, meaning that:\n  - any env can extend (or import, include, whatever you prefer) other envs,\n  - statedirs can be imported and included into one another,\n  - you can have several environments activated at the same time;\n- production of regular and (as much as possible) idiomatic Nix flakes that do not require `--impure`.\n\nAlso, `envil` strongly encourages decomposition. If you write Nix code, then writing small \u0026 local Nix flakes to\nthen reuse them in `envil` envs is perfectly encouraged. `envil` will not write complicated Nix logic for you,\njust the classic boilerplate needed to define a top-level flake with some `pkgs.buildEnv` calls.\n\nContrary to `nix profile`, `envil` will not do anything to track versions of environments via a history.\nGiven it represents its configuration as a simple yaml file or as flakes, versioning can just be done with `git`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fypares%2Fenvil","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fypares%2Fenvil","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fypares%2Fenvil/lists"}