Metadata-Version: 2.4
Name: asura-sync
Version: 0.1.4
Summary: Cross-platform CLI to sync scattered local dev configs and portable Codex state to a private Git repo, with qoder<->codex AI config translation.
Author-email: asura <asura@zen-game.cn>
License-Expression: MIT
Project-URL: Homepage, https://gitee.com/lhbasura/asura-sync
Project-URL: Repository, https://gitee.com/lhbasura/asura-sync
Project-URL: Issues, https://gitee.com/lhbasura/asura-sync/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: tomli>=2.0; python_version < "3.11"
Requires-Dist: tomli-w>=1.0
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"

# 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`、Codex `auth.json` 等登录凭据，可显式 `--include-secrets`
- **Codex 状态同步**：同步 Codex 配置、规则、会话索引与 SQLite 主库快照，排除缓存、临时文件、生成图片、skills/MCP 重复源

## Installation

```bash
pip install asura-sync
```

Or install from source:

```bash
git clone <this-repo>
cd asura-sync
pip install -e .
```

## Quick Start

### 1. Initialize

```bash
asura-sync init --repo git@github.com:your/asura-sync-repo.git
```

### 2. Push local configs to repo

```bash
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

```bash
asura-sync pull                        # pull all modules
asura-sync pull --only ssh             # pull SSH only
```

### 4. Two-way sync (default)

```bash
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

```bash
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 JSON `mcpServers`
- **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

```bash
# 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
