Packages
fnord
0.9.40
0.9.40
0.9.39
0.9.38
0.9.37
0.9.36
0.9.35
0.9.34
0.9.33
0.9.32
0.9.31
0.9.30
0.9.29
0.9.28
0.9.27
0.9.26
0.9.25
0.9.24
0.9.23
0.9.22
0.9.21
0.9.20
0.9.19
0.9.18
0.9.17
0.9.16
0.9.15
0.9.14
0.9.13
0.9.12
0.9.11
0.9.10
0.9.9
0.9.8
0.9.7
0.9.6
0.9.5
0.9.4
0.9.3
0.9.2
0.9.1
0.9.0
0.8.99
0.8.98
0.8.97
0.8.96
0.8.95
0.8.94
0.8.93
0.8.92
0.8.91
0.8.90
0.8.89
0.8.88
0.8.87
0.8.86
0.8.85
0.8.84
0.8.83
0.8.82
0.8.81
0.8.80
0.8.79
0.8.78
0.8.77
0.8.76
0.8.75
0.8.74
0.8.73
0.8.72
0.8.71
0.8.70
0.8.69
0.8.68
0.8.67
0.8.66
0.8.65
0.8.64
0.8.63
0.8.62
0.8.61
0.8.60
0.8.59
0.8.58
0.8.57
0.8.56
0.8.55
0.8.54
0.8.53
0.8.52
0.8.51
0.8.50
0.8.49
0.8.48
0.8.47
0.8.46
0.8.45
0.8.44
0.8.43
0.8.42
0.8.41
0.8.40
0.8.39
0.8.38
0.8.37
0.8.36
0.8.35
0.8.34
0.8.33
0.8.32
0.8.31
0.8.30
0.8.29
0.8.27
0.8.26
0.8.25
0.8.24
0.8.23
0.8.22
0.8.21
0.8.20
0.8.19
0.8.18
0.8.17
0.8.16
0.8.15
0.8.14
0.8.13
0.8.12
0.8.11
0.8.1
0.8.0
0.7.24
0.7.23
0.7.22
0.7.21
0.7.20
0.7.19
0.7.18
0.7.17
0.7.16
0.7.15
0.7.14
0.7.13
0.7.12
0.7.11
0.7.10
0.7.9
0.7.8
0.7.7
0.7.6
0.7.5
0.7.3
0.7.2
0.7.1
0.7.0
0.6.9
0.6.8
0.6.7
0.6.6
0.6.5
0.6.4
0.6.3
0.6.1
0.6.0
0.5.9
0.5.8
0.5.7
0.5.6
0.5.5
0.5.4
0.5.3
0.5.2
0.5.1
0.5.0
0.4.44
0.4.43
0.4.42
0.4.41
0.4.40
0.4.39
0.4.38
0.4.37
0.4.36
0.4.35
0.4.34
0.4.33
0.4.32
0.4.30
0.4.29
0.4.28
0.4.27
0.4.26
0.4.25
0.4.24
0.4.23
0.4.22
0.4.21
0.4.20
0.4.19
0.4.18
0.4.17
0.4.16
0.4.15
0.4.14
0.4.13
0.4.12
0.4.11
0.4.10
0.4.9
0.4.8
0.4.7
0.4.6
0.4.5
0.4.4
0.4.3
0.4.2
0.4.1
0.4.0
0.3.0
0.2.0
0.1.0
AI code archaeology
Current section
Files
Jump to
Current section
Files
lib/util/env.ex
defmodule Util.Env do
@moduledoc """
Utilities for interpreting environment variables used in fnord.
Provide canonical parsing helpers so different runtime contexts treat
environment values consistently (escript, mix run, CI, etc.).
Reads consult a `Services.Globals`-scoped override before the real
environment, so a process tree can see a different value than the VM at
large (see `put_override/2`). In-VM env reads should always route through
this module rather than `System.get_env` so they honor that scoping.
"""
# Overrides live under {:env_override, var} in the :fnord Globals scope.
# :unset is the "pretend the variable is not set" sentinel: a nil override
# value cannot express that, because Globals returns the caller's default
# for a missing key and nil for an explicit nil alike.
@typep override :: binary | :unset | :no_override
@doc """
Return true when the provided environment value is considered truthy.
Recognizes the common truthy values (case-insensitive): "1", "true", and "yes".
Returns false for nil, empty strings, and other values.
"""
@spec looks_truthy?(binary) :: boolean
def looks_truthy?(env_var_name) do
case fetch_env(env_var_name) do
{:ok, v} ->
truthy_value?(v)
{:error, :not_set} ->
false
end
end
# Internal helper: interpret a raw env value (string) as truthy/falsey
@spec truthy_value?(binary) :: boolean
defp truthy_value?(val) do
val
|> String.trim()
|> String.downcase()
|> case do
"1" -> true
"true" -> true
"yes" -> true
_ -> false
end
end
@spec mcp_debug_enabled?() :: boolean
def mcp_debug_enabled? do
looks_truthy?("FNORD_DEBUG_MCP")
end
@spec cursor_rules_debug_enabled?() :: boolean
def cursor_rules_debug_enabled? do
looks_truthy?("FNORD_DEBUG_CURSOR_RULES")
end
@spec get_env(binary, any) :: any
def get_env(var, default \\ nil) do
case fetch_env(var) do
{:ok, v} -> v
{:error, :not_set} -> default
end
end
@spec fetch_env(binary) :: {:ok, binary} | {:error, :not_set}
def fetch_env(var) do
case get_override(var) do
:no_override ->
case System.get_env(var) do
nil -> {:error, :not_set}
v -> {:ok, v}
end
:unset ->
{:error, :not_set}
v when is_binary(v) ->
{:ok, v}
end
end
@doc """
Override `var` for the current `Services.Globals` scope (process tree).
Reads through this module see the override; the real environment - and
therefore subprocesses - do not. `nil` makes the variable appear unset.
This is the async-safe alternative to `put_env/2` for tests: System env is
VM-global, so a per-test put/delete races every concurrently running test,
while an override dies with the test's process tree.
"""
@spec put_override(binary, binary | nil) :: :ok
def put_override(var, nil) do
Services.Globals.put_env(:fnord, {:env_override, var}, :unset)
end
def put_override(var, value) when is_binary(value) do
Services.Globals.put_env(:fnord, {:env_override, var}, value)
end
@spec get_override(binary) :: override
defp get_override(var) do
# get_override, not get_env: env-override keys have no Application-env
# counterpart, and get_env's no-root fallback would pass the tuple key to
# Application.get_env - a runtime deprecation warning on Elixir >= 1.20
# that lands in whatever test capture happens to be active.
Services.Globals.get_override(:fnord, {:env_override, var}, :no_override)
end
@doc """
Set the environment variable to the given value.
"""
@spec put_env(binary, binary) :: :ok
def put_env(var, value) do
System.put_env(var, value)
end
@doc """
Delete the environment variable.
"""
@spec delete_env(binary) :: :ok
def delete_env(var) do
System.delete_env(var)
end
end