Skip to content

Contributing & Project Status

In a nutshell

OVOS is built from many small, independent repositories rather than one monolith. This page is a map for anyone who wants to send in a fix: how a change actually gets from your laptop into a released package, where the code lives, how "does this actually follow the spec" gets checked, and where to ask if you get stuck.

Fixing a bug in a core repo itself, rather than a skill or plugin? See Development Environment for cloning, an editable install, running the service you're changing, and reloading your changes while you work.

How a change reaches a release

Every OVOS repository publishes through the same shared pipeline, described in full on the gh-automations page:

  1. Branch: fork the repo on GitHub, clone your fork, and cut a feature branch from dev, never from master and never directly on dev. Name the branch after its conventional-commit type: fix/<topic>, feat/<topic>, or docs/<topic>. The PR title (not the branch name) must also carry the conventional-commit prefix (fix:, feat:, …) — a per-repo labeller reads the title to apply the label that decides the version bump on merge. See Version bump rules.
  2. Pull request into dev: opening a PR against dev triggers the shared OVOS PR Checks: build/install/test, license and dependency scanning, plugin-manifest detection (for plugin repos), coverage, and a version-bump preview. These checks post their results as a single comment on the PR. A PR merges once they pass.
  3. Merge to dev: a merged PR triggers an automatic alpha release to PyPI, so the change is installable (as a pre-release) right away.
  4. Promotion to stable: periodically, a release PR rolls accumulated dev changes into master. Merging it tags and publishes the stable release.

See Release Flow and Workflow Reference for the full mechanics, including how versions are bumped from conventional-commit prefixes.

Finding the code

OVOS is split across many small repositories: one per plugin, one per core service, one per skill. The OVOS Repository Index is the map of every public repository in the project. The Plugin Ecosystem page is the narrower view of installable plugins by category (STT, TTS, wake word, and so on). Start there rather than guessing a repo name.

How "spec-correct" is checked

Core subsystems (the messagebus, the audio pipeline, OCP, and others) are backed by written architecture specs. See the spec index. Conformance to those specs isn't just asserted in prose. ovos-test-harness is an executable conformance suite that exercises a running OVOS instance against the spec's observable behavior. See Specs & Tooling for how the specs, the harness, and the message-spec definitions fit together.

The harness also runs a mixed-version back-compat matrix: two package sets alive at once (a skill container and a core in separate venvs, talking through a real ovos-messagebus), covering old/new version boundaries and cells pinned to the live release channels' constraints files. Heavier tiers run on a schedule rather than blocking every PR. If your change touches a wire surface (bus topics, session fields, registration payloads), expect it to land as a matrix cell — see ovos-test-harness for the full grid and what each cell pins.

Testing your change locally

The shared OVOS PR Checks above catch a broken change, but waiting for CI to tell you is the slow way to find out. Run the same kind of check locally first:

  • Skills and plugins: use ovoscope, the official end-to-end test tool. It runs a small in-process pretend assistant, so you can confirm a request is understood and answered correctly without real hardware or a full install. Every official OVOS skill must pass ovoscope E2E tests, so writing one for your change also writes the test the PR check will run.
  • Core repositories (ovos-core, ovos-bus-client, ovos-utils, and the other libraries under the repository index): run that repo's own pytest suite from a checkout before opening the PR: uv pip install -e ".[test]" (or the extra the repo's pyproject.toml names for tests), then pytest. See Development Environment for the full local setup.

Either way, the goal is the same. Catch a failure on your own machine, where you can iterate on it in seconds, instead of finding out from a CI comment minutes later.

Writing a skill or plugin

If you're contributing a new ability rather than a core fix, start with Your first skill for the step-by-step tutorial, or Anatomy of a Skill for the reference structure. For plugins (a new STT engine, TTS voice, wake word, and so on), browse the Plugin Ecosystem page for the category you're extending, and use an existing plugin in that category as a template. The plugin base classes referenced throughout this manual (for example, the TTS plugin template) are the contract your plugin's entry point needs to satisfy.

Contributing to language support

Want to help a language rather than fix code? Translating skill text is a separate path from adding parser/STT/TTS support: see Contributing Translations for translation work, and Adding a New Language for the full path to full language support.

Where to ask

See Skill Dev FAQ for answers to the questions that come up most, and Troubleshooting for what to include when you ask for help (a log excerpt or ovos-busmon export for the stage where things went wrong).


Read next: gh-automations Overview Related: Skill Dev F.A.Q. · Your First Skill · Plugin Ecosystem · Troubleshooting & Debugging