Cross-platform CLI to sync scattered local dev configs and portable Codex state to a private Git repo, with qoder<->codex AI config translation.
Project description
asura-sync
Cross-platform CLI to sync scattered local dev configs and portable local state to a private Git repo, with qoder↔codex AI config translation.
跨平台配置同步工具——将散落在本机各处的 SSH、Docker、npm、gitconfig、AI skill/MCP、Codex 本地状态等用户级配置统一同步到私有 Git 仓库,支持 三方对账(本地/仓库/基线)和 AI 配置平级翻译(qoder↔codex)。
Features
- 7 个同步模块:SSH、Docker、npm/yarn、gitconfig、AI skills、AI MCP、Codex 本地状态
- 三方对账引擎:引入"上次同步基线"作为第三参照点,内容 sha256 比较,绝不依赖 mtime
- AI 配置翻译:canonical 中立格式为仓库唯一权威源,qoder/codex 平级双向翻译,确定性规则 + 四道工程兜底
- 增量同步:仅处理有变化的项,支持
--dry-run预览 - 冲突安全:冲突项自动备份本地与仓库两份内容 + 上报,支持
--prefer local|cloud决策 - SSH 权限保持:私钥回写本机后自动恢复 600 权限(Windows 跳过)
- 安全默认值:默认剔除 Docker
auths、Codexauth.json等登录凭据,可显式--include-secrets - Codex 状态同步:同步 Codex 配置、规则、会话索引与 SQLite 主库快照,排除缓存、临时文件、生成图片、skills/MCP 重复源
Installation
pip install asura-sync
Or install from source:
git clone <this-repo>
cd asura-sync
pip install -e .
Quick Start
1. Initialize
asura-sync init --repo git@github.com:your/asura-sync-repo.git
2. Push local configs to repo
asura-sync push # push all modules
asura-sync push --only ssh,skills # push specific modules
asura-sync push --only skills --dry-run # preview only
3. Pull configs from repo
asura-sync pull # pull all modules
asura-sync pull --only ssh # pull SSH only
4. Two-way sync (default)
asura-sync sync # auto-detect push/pull per item
asura-sync sync --prefer local # resolve conflicts in favor of local
asura-sync sync --prefer cloud # resolve conflicts in favor of cloud
5. Check status
asura-sync status # show reconciliation results
asura-sync status --only ssh,skills # filter by module
CLI Reference
| Command | Description |
|---|---|
init --repo <url> |
Initialize local working copy (clone or init + remote) |
sync |
Two-way sync with three-way reconciliation |
push |
One-way: local → repo → git push |
pull |
One-way: git pull → repo → local |
status |
Show per-item reconciliation status |
Common Options
| Option | Description |
|---|---|
--only <modules> |
Comma-separated module list: ssh,docker,npm,git,skills,mcp |
--dry-run |
Preview actions without executing |
-v, --verbose |
Verbose output |
--prefer local|cloud |
Conflict resolution direction (sync only) |
--exclude-secrets |
Strip Docker auths, Codex auth files, and similar credentials (default) |
--include-secrets |
Allow secret files/fields to be synced; use only with an encrypted private repo |
--from <tool> |
Specify authoritative AI tool when collecting (qoder or codex) |
Modules
| Module | Source | Repo Path | Notes |
|---|---|---|---|
ssh |
~/.ssh/ |
ssh/ |
Keys, config, known_hosts; chmod 600 on private keys |
docker |
~/.docker/ |
docker/ |
daemon.json + config.json; --exclude-secrets strips auths |
npm |
~/.npmrc etc. |
npm/ |
.npmrc / .yarnrc / .yarnrc.yml |
git |
~/.gitconfig |
gitconfig/ |
Global git config + ignore file |
skills |
~/.qoder/skills/ etc. |
ai/skills/ |
SKILL.md standard, fan-out to all detected tools |
mcp |
Tool MCP files | ai/mcp/ |
Canonical JSON, translated to codex TOML / qoder JSON |
codex |
~/.codex/ |
codex/ |
Portable Codex state; excludes auth, cache, temp, generated images, skills and MCP duplicate data |
Codex State Sync
The codex module syncs portable local Codex state under ~/.codex, including config fields outside [mcp_servers], rules, session indexes, shell snapshots and SQLite/database files. SQLite and .db files are copied through the SQLite backup API where possible, so a live local database can be snapshotted safely.
To avoid duplicating canonical modules or leaking volatile data, it skips skills/, [mcp_servers] inside config.toml, plugin caches, vendor imports, temp folders, generated images, WAL/SHM files, logs and auth files by default. The existing skills and mcp modules remain the authoritative sync path for Codex skills and MCP servers.
Three-Way Reconciliation
Problem: configs are scattered across ~/.ssh, ~/.qoder/skills, ~/.codex, etc. Git can't see these external source files, so git version alone can't tell which side is newer.
Solution: Introduce a sync baseline (base) as the third reference point. Compare three content hashes per item:
| Condition | Decision |
|---|---|
| local==base && repo==base | No change → skip |
| local!=base && repo==base | Local only → push |
| local==base && repo!=base | Cloud only → pull |
| Both changed, local==repo | Converged → update base |
| Both changed, local!=repo | Conflict → backup + report |
Never relies on mtime — always uses content sha256 as the authority.
AI Config Translation
- Canonical as authority: Git repo stores one neutral canonical format; qoder and codex are equal peers
- Skills: Same SKILL.md standard, fan-out by copying to each tool's skills root directory
- MCP: Canonical
servers.json→ codex TOML[mcp_servers.*]/ qoder JSONmcpServers - Four safeguards: unknown field passthrough, round-trip idempotency check, versioned field map, graceful degradation
Architecture
asura-sync/
├── pyproject.toml
├── config_sync/
│ ├── cli.py # argparse subcommands
│ ├── syncer.py # Three-way reconciliation engine
│ ├── manifest.py # Module registry
│ ├── state.py # Sync baseline (sha256 per item)
│ ├── gitrepo.py # Git subprocess wrapper
│ ├── logger.py # Console + file logging
│ ├── toolpaths.py # TOOL_TARGETS path table
│ ├── modules/
│ │ ├── base.py # SyncModule + FileSyncModule
│ │ ├── ssh.py # SSH module
│ │ ├── docker.py # Docker module
│ │ ├── npm.py # npm/yarn module
│ │ ├── gitcfg.py # gitconfig module
│ │ ├── ai.py # AiSkillsModule + AiMcpModule
│ │ └── codex.py # Portable Codex local state module
│ └── adapters/
│ ├── canonical.py # Neutral canonical format
│ ├── collectors.py # Tool → canonical
│ ├── translators.py # Canonical → tool format
│ └── _toml.py # TOML read/write compat
└── tests/
└── test_core.py # Core unit tests
Development
# Install in dev mode
pip install -e ".[dev]"
# Run tests
python -m pytest
Requirements
- Python 3.9+
- Git installed and available in PATH
- Runtime dependencies: tomli (Python < 3.11), tomli-w
- Dev dependencies: pytest
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file asura_sync-0.1.4.tar.gz.
File metadata
- Download URL: asura_sync-0.1.4.tar.gz
- Upload date:
- Size: 29.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
df4dc72e5de8340772d09fac95bf184ace9298a322bd62344713e2cdd7abe652
|
|
| MD5 |
0adcc7705868a0599ee0d1eecd2cbf91
|
|
| BLAKE2b-256 |
c341160105b8518239e6ed360cde3cb651003b91c4f947dfebec0f9649244e00
|
File details
Details for the file asura_sync-0.1.4-py3-none-any.whl.
File metadata
- Download URL: asura_sync-0.1.4-py3-none-any.whl
- Upload date:
- Size: 33.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4e92904a0c4640c681c7ce55e5f54ae7e8f5e40c802f1c7b30339ebfaf53874e
|
|
| MD5 |
825de93358ead2c285864dfb6758d1ec
|
|
| BLAKE2b-256 |
b5980ddd9be70297ed5b98398443e614b4f419b6f6930f57808df193358422ec
|