Documentation
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.
DevSyncPlugin base class.Plugin Structure
Each plugin lives in its own directory with three required files:
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.
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:
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
| Method | Purpose | Returns |
|---|---|---|
| get_metadata() | Declare plugin name, version, author, category, and supported platforms | PluginMetadata |
| detect() | Check whether the tool is installed on this machine | bool |
| 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.
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
Categories
Use one of the standard categories in your manifest so your plugin appears in the right section of the gallery:
Testing
Place tests in a tests/ directory inside your plugin folder. Run them with pytest:
pytest plugins/my-tool/
Publishing
To share your plugin with the community, submit a pull request to the official plugins repository.