{"id":13431078,"url":"https://github.com/tonerdo/dotnet-env","last_synced_at":"2025-05-14T04:00:26.850Z","repository":{"id":41086355,"uuid":"61912169","full_name":"tonerdo/dotnet-env","owner":"tonerdo","description":"A .NET library to load environment variables from .env files","archived":false,"fork":false,"pushed_at":"2025-03-25T23:24:32.000Z","size":276,"stargazers_count":487,"open_issues_count":1,"forks_count":51,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-05-10T03:56:23.219Z","etag":null,"topics":["csharp","dotnet","dotnet-core","env","environment-variables"],"latest_commit_sha":null,"homepage":"","language":"C#","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/tonerdo.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2016-06-24T21:00:09.000Z","updated_at":"2025-05-07T15:49:08.000Z","dependencies_parsed_at":"2024-01-05T20:52:34.090Z","dependency_job_id":"c11c9875-1ee3-40ec-9049-e9216bf8399c","html_url":"https://github.com/tonerdo/dotnet-env","commit_stats":{"total_commits":97,"total_committers":15,"mean_commits":6.466666666666667,"dds":0.6494845360824743,"last_synced_commit":"3dbee19770951a75785d398d02d7eed92261d0fe"},"previous_names":[],"tags_count":16,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonerdo%2Fdotnet-env","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonerdo%2Fdotnet-env/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonerdo%2Fdotnet-env/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tonerdo%2Fdotnet-env/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tonerdo","download_url":"https://codeload.github.com/tonerdo/dotnet-env/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254067072,"owners_count":22009072,"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":["csharp","dotnet","dotnet-core","env","environment-variables"],"created_at":"2024-07-31T02:01:00.325Z","updated_at":"2025-05-14T04:00:26.820Z","avatar_url":"https://github.com/tonerdo.png","language":"C#","funding_links":[],"categories":["Frameworks, Libraries and Tools","框架, 库和工具","dotnet","csharp"],"sub_categories":["Misc","大杂烩"],"readme":"[![Windows build status](https://ci.appveyor.com/api/projects/status/github/rogusdev/dotnet-env?branch=master\u0026svg=true)](https://ci.appveyor.com/project/rogusdev/dotnet-env)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n[![NuGet version](https://badge.fury.io/nu/DotNetEnv.svg)](https://www.nuget.org/packages/DotNetEnv)\n# dotnet-env\n\nA .NET library to load environment variables from .env files. Supports .NET Core and .NET Framework (4.6+).\n\n## Installation\n\nAvailable on [NuGet](https://www.nuget.org/packages/DotNetEnv/)\n\nVisual Studio:\n\n```powershell\nPM\u003e Install-Package DotNetEnv\n```\n\n.NET Core CLI:\n\n```bash\ndotnet add package DotNetEnv\n```\n\n## Usage\n\n### Load env file\n\n`Load()` will automatically look for a `.env` file in the current directory by default,\n  or any higher parent/ancestor directory if given the option flag via TraversePath()\n```csharp\nDotNetEnv.Env.Load();\nDotNetEnv.Env.TraversePath().Load();\n```\n\nOr you can specify the path directly to the `.env` file,\n and as above, with `TraversePath()`, it will start looking there\n and then look in higher dirs from there if not found.\n```csharp\nDotNetEnv.Env.Load(\"./path/to/.env\");\n```\n\nIt's also possible to load the (text) file as a `Stream` or `string` or multiple files in sequence\n\n```csharp\nusing (var stream = File.OpenRead(\"./path/to/.env\"))\n{\n    DotNetEnv.Env.Load(stream);\n}\n\nDotNetEnv.Env.LoadContents(\"OK=GOOD\\nTEST=\\\"more stuff\\\"\");\n\n// will use values in later files over values in earlier files\n// NOTE: NoClobber will reverse this, it will use the first value encountered!\nDotNetEnv.Env.LoadMulti(new[] {\n    \".env\",\n    \".env2\",\n});\n```\n\n### Accessing environment variables\n\nThe variables in the `.env` can then be accessed through the `System.Environment` class\n\n```csharp\nSystem.Environment.GetEnvironmentVariable(\"IP\");\n```\n\nOr through one of the helper methods:\n\n```csharp\nDotNetEnv.Env.GetString(\"A_STRING\");\nDotNetEnv.Env.GetBool(\"A_BOOL\");\nDotNetEnv.Env.GetInt(\"AN_INT\");\nDotNetEnv.Env.GetDouble(\"A_DOUBLE\");\n```\n\nThe helper methods also have an optional second argument which specifies what value to return if the variable is not found:\n\n```csharp\nDotNetEnv.Env.GetString(\"THIS_DOES_NOT_EXIST\", \"Variable not found\");\n```\n\n### Additional arguments\n\nYou can also pass a `LoadOptions` object arg to all `DotNetEnv.Env.Load` variants to affect the Load/Parse behavior:\n\n```csharp\nnew DotNetEnv.LoadOptions(\n    setEnvVars: true,\n    clobberExistingVars: true,\n    onlyExactPath: true\n)\n```\n\nHowever the recommended approach is with a fluent syntax for turning flags off such as:\n\n```csharp\nDotNetEnv.Env.NoEnvVars().NoClobber().TraversePath().Load();\n```\n\nAll parameters default to true, which means:\n\n1. `setEnvVars`, first arg: `true` in order to actually update env vars.\n Setting it `false` allows consumers of this library to process the .env file\n but use it for things other than updating env vars, as a generic configuration file.\n The Load methods all return an `IEnumerable\u003cKeyValuePair\u003cstring,string\u003e\u003e` for this, but\n there is an extension method `ToDotEnvDictionary()` to get a dict with the last value for each key.\n\n```env\nKEY=value\n```\n\n```csharp\nvar kvps = DotNetEnv.Env.Load(\n    options: new DotNetEnv.Env.LoadOptions(\n        setEnvVars: false\n    )\n)\n\n// or the recommended, cleaner (fluent) approach:\nvar dict = DotNetEnv.Env.NoEnvVars().Load().ToDotEnvDictionary();\n\n// not \"value\" from the .env file\nnull == System.Environment.GetEnvironmentVariable(\"KEY\")\n\"KEY\" == kvps.First().Key\n\"value\" == kvps.First().Value\n```\n\nWith `CreateDictionaryOption` you can change behavior of `ToDotEnvDictionary` to take either the First value or to throw on duplicates. With the `TakeFirst` options you can simulate `NoClobber`-behavior.\n\n2. `clobberExistingVars`, second arg: `true` to always set env vars,\n `false` would leave existing env vars alone.\n\n```env\nKEY=value\n```\n\n```csharp\nSystem.Environment.SetEnvironmentVariable(\"KEY\", \"really important value, don't overwrite\");\nDotNetEnv.Env.Load(\n    options: new DotNetEnv.Env.LoadOptions(\n        clobberExistingVars: false\n    )\n)\n\n// or the recommended, cleaner (fluent) approach:\nDotNetEnv.Env.NoClobber().Load();\n\n// not \"value\" from the .env file\n\"really important value, don't overwrite\" == System.Environment.GetEnvironmentVariable(\"KEY\")\n```\n\n3. `exactPathOnly`, third arg: `true` to require .env to be\n in the current directory if not specified, or to match the exact path passed in,\n `false` would traverse the parent directories above the current or given path\n to find the nearest `.env` file or whatever name was passed in.\n This option only applies to Env.Load that takes a string path.\n\nSee `DotNetEnvTraverse.Tests` for examples.\n\n```csharp\n// the recommended, cleaner (fluent) approach:\nDotNetEnv.Env.TraversePath().Load();\n```\n\n### Using .NET Configuration provider\n\nIntegrating with the usual ConfigurationBuilder used in .NET is simple!\n\n```csharp\nvar configuration = new ConfigurationBuilder()\n    .AddDotNetEnv(\".env\", LoadOptions.TraversePath()) // Simply add the DotNetEnv configuration source!\n    .Build();\n```\n\nThe configuration provider will map `__` as `:` to allow sections!\n\n## .env file structure\n\nAll lines must be valid assignments or empty lines (with optional comments).\n\nA minimal valid assignment looks like:\n```sh\nKEY=value\n```\n\nThere can optionally be one of a few export or equivalent keywords at the beginning\n and there can be a comment at the end, values can be quoted to include whitespace,\n and interpolated references can be included (unquoted values as well as double quoted,\n with optional braces in both cases -- but often more useful in unquoted), like:\n```sh\nexport KEY=\"extra $ENVVAR value\" # comment\nset KEY2=extra${ENVVAR}value # comment\n```\n\nBraced interpolation allows for default, required, and alternative values:\n```sh\n# value of ENVVAR if set, otherwise default\nKEY1=${ENVVAR:-default} \nKEY2=${ENVVAR-default} \n\n# value of ENVVAR if set and non-empty, otherwise exit with error\nKEY1=${ENVVAR:?error}\nKEY2=${ENVVAR?error}\n\n# value of alternate if ENVVAR is set, otherwise empty ''\nKEY1=${ENVVAR:+alternative}\nKEY2=${ENVVAR+alternative}\n```\n\nInterpolation can also be nested:\n- `${VARIABLE:-${FOO}}`\n- `${VARIABLE?$FOO}`\n- `${VARIABLE:-${FOO:-default}}`\n\n\u003e **Note on colon syntax**\n\u003e Typically, using the colon syntax before a default value, error, or alternative value indicates\n\u003e  that the interpolated variable is allowed to be empty. [`netstandard2.0` does not support this](https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/9.0/empty-env-variable),\n\u003e  and treats empty environment variables as unset. This library currently does not support the \n\u003e  \"if set and non-empty\" behaviour, but the syntax itself is supported.\n\nThe options for the export keyword are:\n\n    export  # bash\n    set     # windows cmd\n    SET     # windows cmd\n    set -x  # fish\n\nThis allows the `.env` file itself to be `source`-d like `. .env`\n to load the env vars into a terminal session directly.\n\nThe options for quoting values are:\n\n1. `\"\"` double: can have everything: interpolated variables, plus whitespace, escaped chars, and byte code chars\n1. `''` single: can have whitespace, but no interpolation, no escaped chars, no byte code chars -- notably not even escaped single quotes inside -- single quoted values are for when you want truly raw values\n1. unquoted: can have interpolated variables, but only inline whitespace, and no quote chars, no escaped chars, nor byte code chars\n\nAs these are the options bash recognizes. However, while bash does have\n special meaning for each of these, in this library, they are all the same,\n other than that you do not need to escape single quote chars inside\n a double quoted value, nor double quotes inside single quotes.\n\nAs a special note: if a value is unquoted, it can still include a `#` char,\n which might look like it is starting a comment, like:\n```sh\nKEY=value#notcomment #actualcomment\n```\n\nThis is how bash works as well:\n```sh\nexport TEST=value#notcomment #actualcomment\nenv | grep TEST\n# TEST=value#notcomment\n```\n\nHowever, unlike bash, a `#` directly after the `=` will be recognized as a comment:\n```sh\nKEY=#yesacomment\n```\n\nThis is because whitespaces between `=` and the value are allowed by this library, which is not allowed in bash. This prevents confusion between `KEY=#comment` and `KEY= #comment`, which is expected to give the same result when leading whitespaces before the value are allowed.\n\nAlso unlike bash, inline whitespace is allowed so you can do:\n```\nKEY=value#notcomment more\twords here # yes comment\n\n\"value#notcomment more\twords here\" == System.Environment.GetEnvironmentVariable(\"KEY\")\n```\n\nYou can also declare unicode chars as byte codes in double quoted values:\n\n    UTF8 btes: \"\\xF0\\x9F\\x9A\\x80\" # rocket 🚀\n    UTF16 bytes: \"\\uae\" # registered ®\n    UTF32 bytes: \"\\U1F680\" # rocket 🚀\n\nCapitalization on the hex chars is irrelevant, and leading zeroes are optional.\n\nAnd standard escaped chars like `\\t`, `\\\\``, `\\n`, etc are also recognized\n -- though quoted strings can also be multi line, e.g.:\n\n```sh\nKEY=\"value\nand more\"\nOTHER='#not_comment\nline2'\n```\n\nLoaded gives:\n```csharp\n\"value\\nand more\" == System.Environment.GetEnvironmentVariable(\"KEY\")\n\"#not_comment\\nline2\" == System.Environment.GetEnvironmentVariable(\"OTHER\")\n```\n\nYou can also include whitespace before and after the equals sign in assignments,\n between the name/identifier, and the value, quoted or unquoted.\n Note that the pre/trailing and post/leading whitespace will be ignored.\n If you want leading whitepace on your values, quote them with whitespace.\n```sh\nWHITE_BOTH = value\nWHITE_QUOTED=\" value \"\n```\n\nLoaded gives:\n```csharp\n\"value\" == System.Environment.GetEnvironmentVariable(\"WHITE_BOTH\")\n\" value \" == System.Environment.GetEnvironmentVariable(\"WHITE_QUOTED\")\n```\n\nNote that bash env vars do not allow white space pre or post equals,\n so this is a convenience feature that will break sourcing .env files.\n But then, not all of this is 100% compatible anyway, and that's ok.\n\nNote that other .env parsing libraries also might have slightly different rules\n -- no consistent rules have arisen industry wide yet.\n\n## A Note about Production and the Purpose of This Library\n\nYou should not be using a .env file in production.  The purpose of this library is to enable easy local development.\n\nYour dev team should have a .env with localdev testing credentials/etc stored in some secure storage -- 1pass/lastpass or s3 bucket or something like that.\n\nThen every developer gets a copy of that file as part of onboarding that they save into their project dir that uses DotNetEnv to get env vars for configuration.\n\nWhen the application is deployed into production, actual env vars should be used, not a static .env file!\n\nThis does mean that env vars, and thus this library, are only useful for load time configuration -- not anything that changes during the lifetime of an application's run.\n(You should load env var values during startup or on first access and not look them up more than once during the application's lifetime.)\n\nAdmittedly, this is best practices advice, and if you want to use .env files in production, that's up to you.  But at least I have told you so. :)\n\n## Issue Reporting\n\nIf you have found a bug or if you have a feature request, please report them at this repository issues section.\n\n## Contributing\n\nRun `dotnet test` to run all tests.\n\nOr some more specific test examples:\n\n    dotnet test --filter \"FullyQualifiedName~DotNetEnv.Tests.EnvTests.BadSyntaxTest\"\n    dotnet test --filter \"FullyQualifiedName~DotNetEnv.Tests.ParserTests.ParseAssignment\"\n\n`src/DotNetEnvEnv/Env.cs` is the entry point for all behavior.\n\n`src/DotNetEnvEnv/Parsers.cs` defines all the [Superpower](https://github.com/datalust/superpower) parsers.\n\nThe `DotNetEnvTraverse.Tests` project tests loading `.env` files in parent (or higher) directories from the executable.\n\nOpen a PR on Github if you have some changes, or an issue if you want to discuss some proposed changes before creating a PR for them.\n\n## License\n\nThis project is licensed under the MIT license. See the [LICENSE](LICENSE) file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftonerdo%2Fdotnet-env","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftonerdo%2Fdotnet-env","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftonerdo%2Fdotnet-env/lists"}