Skip to main content

Reusable runtime configuration and config CLI 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
  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

AppRC supports Python 3.12 and newer.

Note

For installation and first-setup recipes, see docs/How-To-User-Guides.md.


Quickstart

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

from pathlib import Path

import apprc


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


APP_CONFIG = apprc.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

import apprc

from myapp.config import APP_CONFIG, MyAppEnv

app = typer.Typer()
apprc.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 CLI runtime options, performs runtime setup 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. Apps whose config hooks must run for config set or config edit can pass runtime_policy=.... Use config_group_name=... only when the generated group should not be named config; AppRC raises a clear error if the app already owns that command or group name. Apps that own their Typer callback and extra options can use CliRuntime as the composable middle layer: the app builds its runtime state, while AppRC owns config command mounting, skip policy, context storage, and state validation. When runtime.prepare(...) skips runtime setup, session.runtime_setup_skipped is true and session.state is None. Runtimeful generated config commands require the app callback to leave the declared state_type on ctx.obj; runtime-independent config commands use AppRC's stored context instead.

Run the capability examples from a checkout with:

python -m pip install -e examples/example_apps --no-build-isolation
python -m apprc_dev.example_apps.bootstrap --clean
set -a; source .apprc-example-storage-only/.env; set +a
apprc-storage-only config doctor
apprc-examples-run-all

They cover env_only, storage_only, app_wide_config, app_wide_storage, named storage, explicit env-file selector precedence, and the CliRuntime app-callback integration. Each .apprc-example*/ directory contains a sourceable .env plus commented app-wide, storage-local, and TOML files showing where the same files would live for a real app.

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. CLI --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.


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 runnable example CLIs in examples/example_apps. Each example is its own package, such as apprc_storage_only_example, with local config.py, cli.py, and .env.shared files so the source tree mirrors a real app integration.


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.18.0.tar.gz (165.3 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.18.0-py3-none-any.whl (185.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: apprc-0.18.0.tar.gz
  • Upload date:
  • Size: 165.3 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.18.0.tar.gz
Algorithm Hash digest
SHA256 eecf928b34ced6ec0ea100b38bfda74108d7acb7b4e303cd43892378ef09fa51
MD5 bf068b142d182ab08dcf754cd3adcf61
BLAKE2b-256 24ce32f8769628ae978cb0cc1b53fe1e9edd0a55a5ced48c3abc38d3ce592bef

See more details on using hashes here.

File details

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

File metadata

  • Download URL: apprc-0.18.0-py3-none-any.whl
  • Upload date:
  • Size: 185.5 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.18.0-py3-none-any.whl
Algorithm Hash digest
SHA256 0237bcc8dda2d664ebe91ab93186c06545f8f4e7bc0a07324a67651da4292b55
MD5 48fafd114a11b150933ca6d90653ae4e
BLAKE2b-256 70bce2f71027334f601bc9dc3c34cb321a0a3471342e2f7933ed1c830f37e0fb

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