+
+ Runnable quickstart
+ Use a new project directory and Python 3.10.1 or newer. These shell commands use Bash on Linux or macOS.
+ 1. Install and create the configuration layout
+mkdir navconfig-demo
+cd navconfig-demo
+python3 -m venv .venv
+source .venv/bin/activate
+python -m pip install navconfig
+kardex env create --env dev
+ On Windows, activate with .venv\Scripts\Activate.ps1 in PowerShell.
+ The CLI creates env/dev/.env, etc/config.ini, logs/
+ and templates/. Existing files are preserved unless you pass --force.
+ 2. Edit env/dev/.env
+ Use these values for the demo:
+ENV=dev
+APP_NAME=NavConfig Demo
+PORT=8080
+DEBUG=true
+ALLOWED_HOSTS=localhost,127.0.0.1
+CONFIG_FILE=etc/config.ini
+VAULT_ENABLED=false
+ 3. Create app.py
+from navconfig import config
+
+app_name: str = config.get("APP_NAME", fallback="My application")
+port: int = config.getint("PORT", fallback=8000)
+debug: bool = config.getboolean("DEBUG", fallback=False)
+allowed_hosts: list[str] = config.getlist("ALLOWED_HOSTS")
+
+print(f"{app_name} on port {port}")
+print(f"Debug: {debug}")
+print(f"Allowed hosts: {', '.join(allowed_hosts)}")
+ 4. Run the application
+ Set the project root and environment before Python starts so discovery is unambiguous:
+SITE_ROOT="$PWD" ENV=dev python app.py
+ PowerShell equivalent:
+$env:SITE_ROOT = (Get-Location).Path
+$env:ENV = "dev"
+python app.py
+ Application output:
+NavConfig Demo on port 8080
+Debug: True
+Allowed hosts: localhost, 127.0.0.1
+
+
+
+ Typed values and defaults
+ Environment values normally arrive as strings. Select an accessor for the type your application needs.
+
+
+
Use the fallback= keyword. The second positional argument of get,
+ getint, getboolean and getlist is an INI section name.
+
+ getlist returns an empty list for a missing value and does not strip whitespace
+ around items. Use comma-separated values without spaces, or strip each item in your application.
+ For required values, check explicitly:
+from navconfig import config
+
+app_name: str | None = config.get("APP_NAME")
+if not app_name:
+ raise ValueError("APP_NAME must be configured")
+ Attribute access such as config.APP_NAME is also available; absent or empty values
+ raise AttributeError. It does not convert strings into integers or booleans.
+ Dictionaries
+ getdict can retrieve dictionaries already present in the configuration mapping;
+ it is not a JSON parser for .env strings. For JSON stored in an environment value,
+ parse it explicitly with Python's standard library:
+EXTRA='{"region": "eu", "retries": 3}'
+import json
+from typing import Any
+
+from navconfig import config
+
+extra: dict[str, Any] = json.loads(config.get("EXTRA", fallback="{}"))
+
+
+
+ Read an INI section
+ Add this section to etc/config.ini. The CONFIG_FILE directive in
+ your environment file selects the file; relative paths resolve from SITE_ROOT.
+[service]
+host = 127.0.0.1
+port = 9000
+enabled = true
+from navconfig import config
+
+host: str = config.get("host", section="service", fallback="localhost")
+port: int = config.getint("port", section="service", fallback=8000)
+enabled: bool = config.getboolean("enabled", section="service", fallback=False)
+service: dict[str, str] = config.section("service")
+ config.section("service") returns the section as a dictionary of strings;
+ a missing section returns {}.
+
+
+
+ Use multiple environments
+kardex env new prod
+kardex env new staging --split
+ New environments copy the shared env/.env template, or the bundled sample when
+ that template is missing. Customize env/prod/.env for production and start a new process:
+SITE_ROOT="$PWD" ENV=prod python app.py
+ ENV selects env/<name>/ at initialization. The shared
+ env/.env is a scaffold template, not an automatically inherited runtime layer.
+ Use kardex env create --env dev --split for supplementary environment files.
+ See file discovery and precedence before repeating keys across files.
+ For remote secrets, follow the HashiCorp Vault setup and migration guide.
+
+
+
+ Initialize before starting async work
+ import navconfig alone does not load configuration. Reading an exported name such as
+ config or DEBUG initializes the shared container. Select
+ SITE_ROOT and ENV before that first access.
+ Call bootstrap() when you need environment-loading side effects explicitly.
+ For async applications, initialize before starting the event loop:
+import asyncio
+
+import navconfig
+
+config = navconfig.bootstrap()
+
+
+async def main() -> None:
+ print(config.get("APP_NAME", fallback="My application"))
+
+
+if __name__ == "__main__":
+ asyncio.run(main())
+ Repeated calls return the same container. If the optional navconfig[uvloop]
+ extra is installed on a supported platform, bootstrap activates it. Without it, the current
+ asyncio event loop policy is preserved.
+
+
+
+ Define Python settings
+ Create a settings/ directory with an empty __init__.py and this
+ settings.py file:
+from navconfig import config
+
+SEND_NOTIFICATIONS: bool = config.getboolean("SEND_NOTIFICATIONS", fallback=False)
+APP_TITLE: str = config.get("APP_NAME", fallback="My application")
+ Use the derived settings elsewhere in your application:
+from navconfig.conf import APP_TITLE, SEND_NOTIFICATIONS
+
+print(APP_TITLE)
+if SEND_NOTIFICATIONS:
+ print("Notifications are enabled")
+ The settings module is optional. Importing navconfig.conf also changes the process
+ working directory to BASE_DIR.
+
+
+
+ Configure application logging
+ Enable console and rotating-file logging in the project's INI file:
+kardex log enable
+import logging
+from logging.config import dictConfig
+
+from navconfig.logging import logging_config
+
+dictConfig(logging_config)
+logger = logging.getLogger("myapp")
+logger.info("Application started")
+ See logging options for log levels, output directories and Logstash.
+
+
+
+ Troubleshooting
+ Configuration files are missing
+ Run kardex env create --env dev from the project root. Confirm the selected
+ ENV directory exists and set SITE_ROOT explicitly when using a
+ virtual environment outside your project.
+ A default value is ignored
+ Use config.get("KEY", fallback="default"). Passing the default as the second
+ argument selects an INI section instead.
+ A value differs between accessors
+ The default loader builds a merged mapping and also populates os.environ.
+ Existing process variables are preserved by default. get prefers the mapping,
+ while accessors such as getint and attribute access can read the process
+ environment directly. Keep each key in one source when consistent values are required.
+ A CLI command is unavailable
+ Activate the environment where NavConfig is installed, then run kardex --help.
+ This guide follows the repository's grouped CLI; older installations may expose different
+ commands. See the CLI migration notes.
+ Report reproducible problems in the issue tracker.
+
+