GuideSeptember 1, 20267 min read

Writing Custom ConfigSync Modules

ConfigSync covers 24 tools out of the box. For everything else, add custom configs or write your own module. Here is how to extend ConfigSync for any tool.

Beyond the Built-In 24

ConfigSync ships with modules for git, zsh, bash, ssh, VS Code, Cursor, npm, Docker, AWS, and many more. But developers use hundreds of tools, and no module library will cover every one. Maybe you depend on a specific database GUI, a custom internal tool, or a niche terminal application with its own config format.

There are two ways to handle tools without built-in support: add their config files as custom configs (takes seconds), or write a full module (takes an hour but benefits everyone). Most developers never need the second option.

Quick Path: Add Config Files Directly

The fastest way to track any tool is to add its config files directly:

Adding custom tool configs
# Track a tool's settings file configsync add config ~/.config/k9s/config.yaml # Track multiple files for one tool configsync add config ~/.config/k9s/hotkeys.yaml configsync add config ~/.config/k9s/aliases.yaml configsync add config ~/.config/k9s/plugins.yaml # Track a file with secrets (auto-encrypted) configsync add config ~/.config/dbgate/connections.json # Push to sync configsync push

ConfigSync detects files containing tokens, passwords, or connection strings and encrypts them automatically. Everything else syncs as plaintext. No module needed.

When is this enough? For 90% of custom tools, adding config files directly is all you need. Write a module only when auto-detection, platform-aware paths, or extras like version tracking would genuinely help.

When to Write a Full Module

ApproachBest ForTime Investment
configsync add configPersonal tools, simple configs30 seconds
Custom modulePopular tools, complex paths, platform differences1 hour

Write a module when a tool stores configs in different locations per platform (like VS Code does), when auto-detection would help other users discover the tool, or when you want to contribute it back to the ConfigSync project.

The ModuleDef Structure

Every ConfigSync module implements the ModuleDef pattern with three core methods:

configsync-cli/devsync/modules/mytool.py
from devsync.modules.base import ModuleDef from pathlib import Path import platform class MyToolModule(ModuleDef): name = "mytool" displayName = "My Tool" description = "Syncs My Tool configuration and credentials" def detect(self) -> bool: """Return True if this tool is installed or configured.""" config_dir = self._get_config_dir() return config_dir.exists() def getFiles(self) -> list[dict]: """Return list of files to track with encryption flags.""" config_dir = self._get_config_dir() return [ {"path": str(config_dir / "settings.json"), "encrypted": False}, {"path": str(config_dir / "credentials.json"), "encrypted": True}, ] def getExtras(self) -> dict: """Return additional metadata to capture.""" return {"version": self._get_version()} def _get_config_dir(self) -> Path: """Platform-aware config directory.""" if platform.system() == "Darwin": return Path.home() / "Library/Application Support/MyTool" elif platform.system() == "Linux": return Path.home() / ".config/mytool" else: return Path.home() / "AppData/Roaming/MyTool" def _get_version(self) -> str: import subprocess try: result = subprocess.run(["mytool", "--version"], capture_output=True, text=True) return result.stdout.strip() except FileNotFoundError: return "unknown"

detect() checks if the tool exists on this machine. getFiles()returns config files with their encryption status. getExtras() captures metadata like the installed version.

Platform-Aware Path Handling

The most common reason to write a module instead of using add config is that the tool stores its configuration in different locations per operating system. macOS applications often use ~/Library/Application Support/, Linux uses~/.config/, and Windows uses AppData.

A module handles this automatically. When you push from macOS, ConfigSync captures the files from the macOS path. When you pull on Linux, the module places them at the Linux path. The developer never thinks about it.

Contributing a Module Back

If your module covers a tool that other developers use, consider contributing it:

Contributing to configsync-cli
# Fork and clone git clone https://github.com/InventiveHQ/configsync-cli.git # Create your module # devsync/modules/mytool.py (module implementation) # tests/modules/test_mytool.py (test for detect, getFiles, getExtras) # Register it in the module list # devsync/modules/__init__.py # Open a PR with: # - The module following ModuleDef pattern # - Tests covering all three methods # - A brief description of the tool and its user base

The ConfigSync CLI is open source and welcomes contributions. Every new module expands what ConfigSync can auto-detect and sync for all users.

Ready to try ConfigSync?

Sync your entire dev environment across machines in minutes. Free forever for up to 3 devices.