Plugin Development

Create custom plugins to extend ConfigSync for any tool

Overview

ConfigSync plugins let you add sync support for any development tool. A plugin tells ConfigSync how to detect a tool, capture its configuration, and restore it on another machine.

i
Plugins are Python packages that extend the DevSyncPlugin base class.

Plugin Structure

Each plugin lives in its own directory with three required files:

Directory layout

plugins/my-tool/

plugin.py # Plugin implementation

manifest.yaml # Metadata and configuration

README.md # Documentation

tests/ # Plugin tests

manifest.yaml

The manifest declares your plugin's metadata, supported platforms, and what it syncs.

plugins/my-tool/manifest.yaml

name: my-tool

version: 1.0.0

author: Your Name

description: Sync My Tool settings and preferences

category: editor # editor, terminal, cloud, development, system, security, browser, ai_tool

platforms:

- darwin

- linux

- windows

homepage: https://my-tool.dev

files_synced:

- config.json

- keybindings.json

Plugin Implementation

Your plugin class must extend DevSyncPlugin and implement four methods:

plugins/my-tool/plugin.py

from pathlib import Path

from typing import Dict

import json

 

from devsync.plugin_system import DevSyncPlugin, PluginMetadata

 

 

class MyToolPlugin(DevSyncPlugin):

"""Sync My Tool configuration"""

 

def get_metadata(self) -> PluginMetadata:

return PluginMetadata(

name="my-tool",

version="1.0.0",

author="Your Name",

description="Sync My Tool settings",

category="editor",

platforms=["darwin", "linux"],

)

 

def detect(self) -> bool:

"""Return True if the tool is installed"""

config_path = Path.home() / ".config/my-tool/config.json"

return config_path.exists()

 

def capture(self, crypto_manager) -> Dict:

"""Read config files and return as a dict"""

config_path = Path.home() / ".config/my-tool/config.json"

with open(config_path) as f:

return {"settings": json.load(f)}

 

def restore(self, config: Dict, crypto_manager) -> bool:

"""Write config back to disk"""

config_path = Path.home() / ".config/my-tool/config.json"

config_path.parent.mkdir(parents=True, exist_ok=True)

with open(config_path, "w") as f:

json.dump(config["settings"], f, indent=2)

return True

Method Reference

MethodPurposeReturns
get_metadata()Declare plugin name, version, author, category, and supported platformsPluginMetadata
detect()Check whether the tool is installed on this machinebool
capture(crypto_manager)Read the tool's config files and return them as a serializable dict. Use crypto_manager to encrypt sensitive values.Dict
restore(config, crypto_manager)Write config back to disk. Return True on success.bool

Encrypting Sensitive Data

If your tool stores secrets (API keys, tokens, credentials), use the crypto_manager passed to capture() and restore() to encrypt them before syncing.

Encrypting a value

def capture(self, crypto_manager) -> Dict:

token = read_token_from_config()

encrypted = crypto_manager.encrypt(token)

return {"token": encrypted}

 

def restore(self, config, crypto_manager) -> bool:

token = crypto_manager.decrypt(config["token"])

write_token_to_config(token)

return True

!
Always encrypt credentials, tokens, and API keys. Never sync secrets in plaintext.

Categories

Use one of the standard categories in your manifest so your plugin appears in the right section of the gallery:

editor
terminal
development
cloud
database
security
system
ai_tool
browser

Testing

Place tests in a tests/ directory inside your plugin folder. Run them with pytest:

Run plugin tests

pytest plugins/my-tool/

Publishing

To share your plugin with the community, submit a pull request to the official plugins repository.