Skip to main content

Reusable runtime configuration, config CLI, and logging helpers for Python applications.

Project description

apprc: Application Runtime Config

AppRC is for Python applications that need configuration to be explicit, inspectable, and pleasant to operate. Instead of spreading environment variables, dotenv files, setup commands, and diagnostics across unrelated code, you declare the runtime contract once and let AppRC build the surrounding workflows from that metadata.

The three strongest parts:

  • Typed config contracts: declare application settings once with EnvConfig, env_field(...), and @env_owner(...).
  • Deterministic runtime config: load layered dotenv files predictably while keeping normal runtime reads and diagnostics zero-write.
  • Generated operator UX: mount ready-made Typer config commands and open the same contract in the Textual editor.

AppRC graphical abstract

Fig. 1 - AppRC Graphical Abstract: AppRC lets developers ship one typed config contract with generated setup, diagnostics, editing, and runtime config workflows.

Note

For the full system model, see docs/Explanations.md. For exact public names and command references, see docs/References.md.


Table Of Contents

  1. apprc: Application Runtime Config
    1. Table Of Contents
  2. Installation
  3. Quickstart
  4. How AppRC Works
    1. Mental Model
    2. Capability Layers
    3. Runtime Precedence
  5. Generated Workflows
    1. Config CLI
    2. Setup And Diagnostics
    3. Optional Logging
  6. More Documentation
    1. Detailed Manual
    2. Development


Install AppRC, declare the runtime contract, and mount the generated config commands in your Typer application.


Installation

python -m pip install apprc

Install optional structured logging support when your app calls setup_logging():

python -m pip install "apprc[logging]"

AppRC supports Python 3.12 and newer.

Note

For installation and first-setup recipes, see docs/How-To-User-Guides.md. Optional logging APIs are listed in docs/References.md#optional-logging-apis.


Quickstart

Declare typed config sections with EnvConfig, @env_owner, and env_field(...):

from pathlib import Path

from apprc import AppConfigKit, EnvConfig, env_field, env_owner


@env_owner(
    key="app",
    title="App",
    env_prefix="MYAPP_",
    rc_path=("app",),
)
class MyAppEnv(EnvConfig):
    storage_root: Path = env_field(
        "STORAGE",
        editable=False,
        required=True,
        title="Storage root",
    )
    profile: str = env_field(
        "PROFILE",
        default="default",
        title="Profile",
        explanation_short="Named runtime profile.",
    )
    access_token: str = env_field(
        "ACCESS_TOKEN",
        required=True,
        secret=True,
        title="Access token",
    )


APP_CONFIG = AppConfigKit.storage_only(
    app_name="myapp",
    display_name="My App",
    config_package="myapp.config",
    envs=(MyAppEnv,),
)

Add packaged defaults in myapp/config/.env.shared:

MYAPP_PROFILE="default"

Bootstrap your app before constructing runtime config objects:

import typer

from apprc.cli import mount_config_cli

from myapp.config import APP_CONFIG, MyAppEnv

app = typer.Typer()
mount_config_cli(app, APP_CONFIG)


@app.command()
def run() -> None:
    cfg = MyAppEnv()
    typer.echo(f"profile={cfg.profile}")

mount_config_cli(...) adds the standard AppRC root options, performs runtime bootstrap for commands that need resolved config, and mounts the generated config command group. Apps with custom runtime state can pass state_type=... and state_factory=...; tests or lazy-forwarding CLIs can pass args_provider=... with tokens shaped like CliArgvProvider. Use config_group_name=... only when the generated group should not be named config. Apps with existing root callbacks can use the lower-level CliBootstrapOptions, prepare_typer_context(...), and APP_CONFIG.typer_app(...) helpers instead.

Note

For the step-by-step integration guide, see docs/How-To-User-Guides.md#2-integrate-apprc. For the exact import surface, see docs/References.md#public-interfaces.



How AppRC Works

AppRC starts from one declared contract, then uses that contract to load runtime values, inspect configuration health, write explicit setup files, and generate user-facing configuration tools.

One AppRC contract feeding many workflows
Fig. 2 - One Contract, Many Workflows: AppRC reuses the same contract metadata for runtime loading, provenance, diagnostics, generated CLI commands, and the editor.

Mental Model

AppRC has one contract and several workflows built from it.

Concept Meaning
Config field One typed setting declared with env_field(...).
Config owner A related group of fields declared by @env_owner(...).
App config kit The app-level contract that selects supported persistence layers.
Bootstrap A startup step that merges dotenv layers into this Python process.
Generated CLI A reusable Typer config command group for inspection and edits.
Editor A Textual view over the same owners, fields, and dotenv layers.

Note

For the deeper architecture behind owners, fields, capability layers, provenance, and the zero-write policy, see docs/Explanations.md#3-runtime-config-model.


Capability Layers

Choose one capability constructor:

Constructor Storage root App-wide dotenv Named storage index
AppConfigKit.env_only(...) disabled optional disabled
AppConfigKit.storage_only(...) required optional optional
AppConfigKit.app_wide_config(...) disabled default disabled
AppConfigKit.app_wide_storage(...) required default optional

AppRC-managed persistence files are explicit:

Layer Default location Created by
Packaged shared defaults package .env.shared the application package
App-wide config platform config home .env.apprc-app config app init, app-wide setup, or app-scope save
Storage config <storage-root>/.env.apprc-storage storage setup, config storage add, or storage-scope save
Named-storage index <config-home>/<app>.apprc.toml config storage add/remove

Note

For constructor arguments and capability details, see docs/References.md#capability-constructors.


Runtime Precedence

When dotenv layers are loaded, AppRC merges values in this order:

  1. packaged .env.shared
  2. app-wide .env.apprc-app, when allowed and present
  3. selected storage .env.apprc-storage, when storage is selected and present
  4. explicit --env-file values
  5. existing os.environ

With --env-file-overrides-os-environ, explicit env files move after os.environ and win over shell exports.

Storage selector resolution uses:

  1. root --storage
  2. shell env, for example MYAPP_STORAGE
  3. explicit env files, respecting --env-file-overrides-os-environ
  4. app-wide .env.apprc-app, when active
  5. packaged .env.shared

Path selectors work without a named-storage index. Bare named selectors use <app>.apprc.toml when the index exists.

Note

For the rationale behind layer order and storage selector resolution, see docs/Explanations.md#runtime-bootstrap and docs/Explanations.md#storage-selection. For exact precedence tables, see docs/References.md#runtime-precedence.



Generated Workflows

Mount the generated workflows when you want your application to expose the same contract to users, setup commands, diagnostics, and the Textual editor.


Config CLI

Mounting APP_CONFIG.typer_app(...) gives your app these commands:

myapp config paths
myapp config doctor
myapp config show
myapp config setup
myapp config set KEY VALUE --scope app
myapp config set KEY VALUE --scope storage
myapp config edit
myapp config app init
myapp config storage add NAME PATH
myapp config storage list
myapp config storage remove NAME

The command group follows the selected capabilities. For example, storage-free apps do not expose named-storage commands.

Note

For the generated command table, see docs/References.md#generated-cli-commands.


Setup And Diagnostics

Use config paths before setup to see candidate paths and declared capabilities without writing anything. Use config setup for explicit first storage setup, then use config doctor when a machine is not runnable.

myapp config paths
myapp config setup --yes --storage-root /absolute/path/to/storage
export MYAPP_STORAGE="/absolute/path/to/storage"
myapp config doctor
myapp config set access_token secret-value --scope storage
myapp run

config doctor reports a status such as env_not_set, storage_not_ready, app_config_not_ready, named_storage_not_ready, or runnable.

Important

Runtime reads and diagnostics do not create files. bootstrap, config paths, config doctor, and opening config edit are zero-write.

Note

For doctor troubleshooting, see docs/How-To-User-Guides.md#troubleshoot-config-doctor. For exact status names, see docs/References.md#doctor-statuses.


Optional Logging

AppRC also includes stdlib-compatible semantic logging helpers. The base logger API imports without structlog; setup_logging() requires the logging extra.

from apprc.logging import get_logger, setup_logging

setup_logging(level="INFO", renderer="cli")
log = get_logger(__name__)
log.success("configured", extra_struct={"profile": "default"})

Create application loggers with get_logger(name) or call install_app_logger_class() before other code creates those names with logging.getLogger(name). Existing plain stdlib logger instances cannot be safely reclassed, so get_logger(name) raises RuntimeError for those names.

Note

For logging design context, see docs/Explanations.md#optional-logging. For import names and dependency details, see docs/References.md#optional-logging-apis.



More Documentation

The README stays short. The detailed manual and maintainer workflow live in the documentation directory.


Detailed Manual

The detailed manual starts at docs/README.md.

Note

Use docs/How-To-User-Guides.md for integration recipes, docs/Explanations.md for the AppRC system model, docs/References.md for exact commands, files, and APIs, and docs/Development.md for maintainer workflow and docs rules.

The repository also ships a runnable example app in examples/apprc_example_app.


Development

.venv/bin/ruff format .
.venv/bin/ruff check .
.venv/bin/pyright
.venv/bin/pytest

Regenerate the PyPI README after editing this file:

python src/apprc_dev/packaging/pypi_readme.py

Note

For maintainer workflow, documentation rules, and verification commands, see docs/Development.md.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

apprc-0.16.3.tar.gz (169.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

apprc-0.16.3-py3-none-any.whl (185.2 kB view details)

Uploaded Python 3

File details

Details for the file apprc-0.16.3.tar.gz.

File metadata

  • Download URL: apprc-0.16.3.tar.gz
  • Upload date:
  • Size: 169.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for apprc-0.16.3.tar.gz
Algorithm Hash digest
SHA256 2a0177f17eee62619610ae94e79879735eb8af8fbe91b2e00d5dc2887dfa37b1
MD5 1b3a830de2d779cd3cf124e7fa08b55b
BLAKE2b-256 b3c61bc6d31fe4ffa5fc8897098803abfa32116f7cdb6c04f7c991739323bd3d

See more details on using hashes here.

File details

Details for the file apprc-0.16.3-py3-none-any.whl.

File metadata

  • Download URL: apprc-0.16.3-py3-none-any.whl
  • Upload date:
  • Size: 185.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Fedora Linux","version":"44","id":"","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for apprc-0.16.3-py3-none-any.whl
Algorithm Hash digest
SHA256 a48bae44ad96695d1429b247b42d12e1f4b051ca5579d725a316fe219c4f0d2c
MD5 95b7c1493e782a15d440338de12b6d32
BLAKE2b-256 ce4ef3f7aebf71496fc7c74cd4dcdbad2421420ebd01d386fcab822b1f122837

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page