Skip to content

Skill Settings

In a nutshell

"Settings" are a skill's saved preferences, such as a username, an API key, or a chosen option. They stick around even after a restart. This page shows how a skill reads and writes those values, and how it reacts when a user changes them. For an optional (legacy) settings form used by community config tools, see Skill Settings Meta. For term definitions, see the Glossary.

Settings provide per-skill persistent key-value storage backed by a JSON file. They let users configure skill behavior: changing defaults, providing API keys, or adjusting integration preferences.

Which file does what

File Holds Covered on
settings.json The runtime values a user actually set. This page.
settingsmeta.json/.yaml The UI declaration: which fields a settings UI should show. Skill Settings Meta
skill.json Packaging metadata for distribution (id, author, requirements). Skill Packaging: skill.json

Quick start

Building on the MyFirstSkill from Your First Skill, here is the smallest useful use of settings: a greeting that remembers a name the user gave it once.

ovos_skill_my_first/locale/en-us/SetName.intent, one example phrase per line:

call me {name}
my name is {name}
set my name to {name}
from ovos_workshop.skills import OVOSSkill
from ovos_workshop.decorators import intent_handler


class MyFirstSkill(OVOSSkill):

    def initialize(self):
        # a default is only applied the first time — after that, whatever
        # the user (or a previous run) stored takes over
        self.settings.setdefault("name", "friend")

    @intent_handler("Hello.intent")
    def handle_hello(self, message):
        self.speak_dialog("hello", {"name": self.settings.get("name", "friend")})

    @intent_handler("SetName.intent")
    def handle_set_name(self, message):
        name = message.data.get("name")
        if name:
            self.settings["name"] = name
            self.speak(f"Okay, I'll call you {name} from now on")

Add a {name} placeholder to hello.dialog (see Statements for the mustache syntax) and the greeting picks up the stored name automatically, even after a restart.


Storage Location

$XDG_CONFIG_HOME/<base_folder>/skills/<skill_id>/settings.json

Settings are per skill, not per user

There is one settings.json per skill_id and no built-in partitioning by user, voice, or session. "Each household member gets their own preferences" is not something the settings system can express — a skill that needs per-user preferences must key its own storage on something it can observe, such as the session_id of remote clients.

<base_folder> defaults to mycroft for backwards compatibility. A system-wide ovos.conf (or the OVOS_CONFIG_BASE_FOLDER environment variable) can rename it, commonly to OpenVoiceOS. On most Linux installs XDG_CONFIG_HOME is ~/.config, so the effective default is ~/.config/mycroft/skills/<skill_id>/settings.json.

For OVOSAbstractApplication:

$XDG_CONFIG_HOME/<base_folder>/apps/<skill_id>/settings.json

Tip

Never hardcode this path in a skill — use self.settings_path (or self.file_system for other files) so it always resolves correctly regardless of how the running system is configured.


Accessing Settings

self.settings is a JsonStorage dict-like object. Read and write it like a normal dict:

# Read with default
name = self.settings.get("username", "stranger")

# Write
self.settings["username"] = "Alice"

# Persist immediately (normally auto-saved on shutdown)
self.settings.store()

Always use .get(key, default). Never use self.settings["key"] directly. That raises KeyError if the key is absent.

Do not access self.settings in __init__(). Wait until initialize(). This ensures settings are fully loaded.

Do not replace the whole self.settings dict:

# WRONG — replaces the JsonStorage object
self.settings = {"key": "value"}

# CORRECT — update individual keys
self.settings["key"] = "value"

Default Values

Set defaults as individual key assignments in initialize(), not by replacing self.settings. Defaults are only applied if the key does not already exist in the stored settings file.

The __mycroft_skill_firstrun key is managed automatically to track first-run state.


Change Callback

Set self.settings_change_callback to a callable that is invoked whenever settings change:

def initialize(self):
    self.settings_change_callback = self.on_settings_changed
    self.on_settings_changed()  # Also apply current values immediately

def on_settings_changed(self):
    self.log.info("Settings updated!")
    self._apply_new_volume(self.settings.get("volume", 50))

File Watching

Settings changes can arrive two ways:

  1. Bus event (ovos.skills.settings_changed): emitted by ovos-core's file watcher. This is the primary mechanism in a standard setup.

  2. Local file watcher: enabled by setting monitor_own_settings: true in the skill's own settings. Useful in isolated setups, for example containers, where the skill and core do not share a filesystem.


Remote Settings

Skills can receive remote settings updates via mycroft.skills.settings.changed. Only settings for this skill (keyed by skill_id) are applied. After applying remote settings the file watcher is started if not already running.


Private Settings

Skills also have access to self.private_settings (PrivateSettings), a separate storage for data that should not be shared or synced. It is backed by a JSON file outside the standard settings path.


Web-Based Settings UI (Community)

A community-built web interface, OVOS Skill Config Tool, provides a modern UI for configuring OVOS skills.

Features:

  • Clean UI for managing skill-specific settings

  • Grouping and organization of skills

  • Dark mode support

  • Built-in Basic Authentication

Installation:

pip install ovos-skill-config-tool
ovos-skill-config-tool

Access at http://0.0.0.0:8000. Default credentials: ovos / ovos.

Customize credentials via environment variables:

export OVOS_CONFIG_USERNAME=myuser
export OVOS_CONFIG_PASSWORD=mypassword

Tips

  • Always use .get(key, default) for safe reads.

  • Use initialize() instead of __init__() for anything that depends on settings.

  • Use settings_change_callback to keep your skill reactive to user changes.

  • Use self.private_settings for sensitive data that should not leave the device.


Source code: OpenVoiceOS/ovos-workshop.


Read next: Skill Filesystem Related: Decorators · Filesystem Access · Configuration Management · Session Aware Skills