Skip to content

Configuration

Asterios Raptis edited this page Mar 27, 2026 · 2 revisions

Configuration

PluginForge uses a YAML-based configuration system with three layers:

  1. App Config - Global application settings
  2. Plugin Config - Per-plugin settings
  3. i18n - Multilingual strings

Missing config files are never an error - they produce empty defaults.

App Config

Path: config/app.yaml

app:
  name: "MyApp"
  version: "1.0.0"
  description: "My application"
  default_language: "de"

plugins:
  entry_point_group: "myapp.plugins"
  enabled:
    - "export"
    - "analytics"
  disabled:
    - "experimental"

Fields

Field Description
app.name Application name
app.version Application version
app.default_language Default language for i18n (default: "en")
plugins.entry_point_group Entry point group for plugin discovery
plugins.enabled List of enabled plugin names (if set, only these are loaded)
plugins.disabled List of disabled plugin names (always takes precedence)

Enable/Disable Logic

  • If enabled is set, only listed plugins are loaded
  • disabled always takes precedence over enabled
  • If neither is set, all discovered plugins are loaded

Reloading Config

Config is loaded once at startup. To reload at runtime:

pm.reload_config()  # reloads app.yaml and clears i18n cache

Active plugins are not affected. For a full restart: deactivate_all() + discover_plugins().

Plugin Config

Path: config/plugins/{plugin_name}.yaml

Each plugin can have its own config file. The contents are passed to plugin.init() and available via plugin.config.

# config/plugins/export.yaml
formats:
  - epub
  - pdf
pandoc_path: "/usr/bin/pandoc"
pdf_engine: "xelatex"

Access in the plugin:

class ExportPlugin(BasePlugin):
    name = "export"

    def activate(self) -> None:
        self.formats = self.config.get("formats", ["pdf"])
        self.pandoc = self.config.get("pandoc_path", "pandoc")

Config Schema Validation

Plugins can declare expected types for their config values:

class ExportPlugin(BasePlugin):
    name = "export"
    config_schema = {
        "pandoc_path": str,
        "toc_depth": int,
        "default_format": str,
    }

If a config value has the wrong type (e.g. toc_depth: "abc" instead of toc_depth: 2), the plugin is skipped during initialization with a clear error message in pm.get_load_errors(). Missing keys are not an error.

i18n Config

Path: config/i18n/{lang}.yaml

See i18n for details.

Config Merge Logic

App-Config (config/app.yaml)
  + Plugin-Config (config/plugins/{name}.yaml)  -> plugin.config
  + i18n (config/i18n/{lang}.yaml)              -> pm.get_text()

The app config is available on each plugin via plugin.app_config. The plugin config via plugin.config. i18n is accessed separately through PluginManager.get_text().

Security

Plugin names and language codes are validated before being used to construct file paths. Names containing path separators (/, ..) are rejected with InvalidPluginNameError. See Security for details.

API

load_yaml(path) -> dict

Load any YAML file. Returns empty dict if file is missing or invalid.

load_app_config(config_path) -> dict

Load the main app config.

load_plugin_config(config_dir, plugin_name) -> dict

Load config from {config_dir}/plugins/{plugin_name}.yaml. Validates the plugin name.

load_i18n(config_dir, lang) -> dict

Load i18n strings from {config_dir}/i18n/{lang}.yaml. Validates the language code.

Clone this wiki locally