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:
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¶
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:
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:
-
Bus event (
ovos.skills.settings_changed): emitted byovos-core's file watcher. This is the primary mechanism in a standard setup. -
Local file watcher: enabled by setting
monitor_own_settings: truein 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:
Access at http://0.0.0.0:8000. Default credentials: ovos / ovos.
Customize credentials via environment variables:
Tips¶
-
Always use
.get(key, default)for safe reads. -
Use
initialize()instead of__init__()for anything that depends on settings. -
Use
settings_change_callbackto keep your skill reactive to user changes. -
Use
self.private_settingsfor 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