Metadata-Version: 2.3
Name: dotsync-ai
Version: 0.2.0
Summary: Cross-OS dev environment synchronizer with auto-encrypted dotfiles
Author: Fiqi Arifianto
License: MIT
Keywords: cross-platform,devtools,dotfiles,linux,sync,windows
Classifier: Development Status :: 3 - Alpha
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: System :: Systems Administration
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Requires-Dist: click>=8.0
Requires-Dist: cryptography>=41.0
Requires-Dist: pathspec>=0.11
Requires-Dist: pydantic>=2.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich>=13.0
Provides-Extra: dev
Requires-Dist: mypy>=1.0; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Description-Content-Type: text/markdown

# DotSync AI

> **Cross-OS Dev Environment Synchronizer** — keep your dotfiles and dev tools in sync across Linux, Windows, and macOS.

[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](pyproject.toml)
![CLI](https://img.shields.io/badge/CLI-Click+Rich-green)

---

## 📋 Table of Contents

- [Why DotSync AI?](#-why-dotsync-ai)
- [Features](#-features)
- [Installation](#-installation)
- [Quick Start](#-quick-start)
- [Sync Flow Diagrams](#-sync-flow-diagrams)
- [Command Reference](#-command-reference)
- [Advanced Usage](#-advanced-usage)
- [Configuration](#-configuration)
- [Project Structure](#-project-structure)
- [Architecture](#-architecture)
- [Use Cases](#-use-cases)
- [Roadmap](#-roadmap)
- [Contributing](#-contributing)
- [License](#-license)

---

## 🎯 Why DotSync AI?

**The problem:** You have 3 machines (work Linux, personal macOS, home Windows) and configuring each one from scratch takes hours. Your `.bashrc`, `.gitconfig`, VS Code settings, SSH config, and dev tools are scattered across different OS paths.

**DotSync AI solves this by:**

| Problem | Solution |
|---------|----------|
| Manual setup on each machine | Auto-detect tools + dotfiles, apply with one command |
| Path differences across OS | Automatic cross-OS path remapping (`~/.config` ↔ `%APPDATA%`) |
| Sensitive data in git | Fernet (AES-128) encrypted secrets storage |
| File conflicts | 3-way conflict resolution (mine / theirs / merge) |
| Selective sync | Per-tool include/exclude filters |
| No backup before changes | Automatic backup on apply |

---

## ✨ Features

### 🔍 Auto-Detection
Scans your environment and detects installed dev tools automatically:
- **Shells:** bash, zsh, fish
- **Git** — `.gitconfig`, SSH keys, global gitignore
- **VS Code** — settings, keybindings, snippets, extensions
- **Terminal** — tmux, starship, kitty, alacritty
- **Runtimes** — Node.js (`.npmrc`), Python, Docker
- And more...

### 🔄 Sync & Apply
- **Snapshot** — collect dotfiles into a structured store
- **Apply** — restore dotfiles via symlinks with automatic backup
- **Diff** — compare stored vs current filesystem state
- **Selective sync** — sync only specific tools (`-t git,vscode`)

### 🛤️ Cross-OS Path Remapping
Automatically translates paths between OS conventions:
- `~/.config/code/User/settings.json` ↔ `%APPDATA%\Code\User\settings.json`
- `~/.ssh/config` ↔ `~/.ssh/config` (same on macOS/Linux)
- Windows → Linux → macOS path normalization

### 🔒 Encrypted Secrets (Fernet AES-128)
Store sensitive data safely:
- **set** / **get** / **list** / **delete** secrets
- Fernet (AES-128-CBC) symmetric encryption
- Vault file + separate key file
- Secrets never exposed in `list` output

### 📦 Git Backend
Version-controlled dotfile storage:
- **init** — create a git repo in your store
- **push** / **pull** — sync via private git remote (GitLab, GitHub)
- Smart commit messages with machine context

### 🧠 Multi-Machine
Track environments across machines:
- **machines** — list all known machines
- **switch** — switch active context
- **snapshot --copy-files** — capture actual file contents per machine

### ⚡ Conflict Resolution
When both sides changed, choose a strategy:
- `mine` — keep your local version
- `theirs` — accept the stored version
- `merge` — let DotSync attempt auto-merge

---

## 📦 Installation

### Option 1: pip (Python)

```bash
pip install dotsync-ai
```

### Option 2: pip (from source)

```bash
git clone https://gitlab.com/fiqi/dotsync-ai.git
cd dotsync-ai
pip install .
```

### Option 3: npm (Node.js wrapper)

The npm wrapper auto-bootstraps a Python virtualenv and installs the wheel on first use.

```bash
# From local source
npm install /path/to/dotsync-ai/npm

# From npm registry (when published)
npm install dotsync-ai
```

Then use via npx:

```bash
npx dotsync --help
```

### Prerequisites
- Python 3.10+
- Git (for push/pull features)
- pip (for Python installation)

---

## 🚀 Quick Start

### 1. Initialize — scan your environment

```bash
dotsync init
```

This scans your current machine for installed dev tools and detected dotfiles. Example output:

```
╭────── 🔍 DotSync Init ──────╮
│ Scanning linux environment... │
╰──────────────────────────────╯
Detected Tools (11 found):
  git      v2.34.1
  ssh      -
  bash     v5.1.16
  vscode   v1.109.5
  node     v22.20.0
  python   v3.11.15
  docker   v27.3.1
  ... and more
```

### 2. Take a snapshot

```bash
dotsync snapshot
```

Collects all detected config files into the DotSync store (`~/.dotsync/`). Use `--copy-files` to snapshot actual file contents (not just paths).

### 3. Check status

```bash
dotsync status
```

Shows current sync state: which files are tracked, modified, or missing.

### 4. List tracked files

```bash
dotsync list
```

Shows all tracked dotfiles with their status icons:
- ✓ Synced
- ⊘ Missing from stash
- ✧ Modified
- + New file

### 5. See what's changed

```bash
# Quick diff (file list)
dotsync diff

# Detailed content diff
dotsync diff --content
```

### 6. Apply dotfiles (restore)

```bash
# Dry run first — see what would happen
dotsync apply --dry-run

# Apply with automatic backup
dotsync apply

# Force overwrite
dotsync apply --force
```

---

## 🔄 Sync Flow Diagrams

### Linux → Windows (First Time Setup)

```
🖥️ PC Linux (Source)                    ☁️ Git Private Repo                    🪟 PC Windows (Target)
━━━━━━━━━━━━━━━━━━━━                    ━━━━━━━━━━━━━━━━━━                    ━━━━━━━━━━━━━━━━━━━━━

1. pip install dotsync-ai
2. dotsync init
   ├─ Scan: 11 tools detected           ⬇
   ├─ 🔧 Set up git remote?  →  [y]
   ├─ Git remote URL?         →  git@gitlab.com:user/dotfiles.git
   └─ ✔ Git initialized + remote set
3. dotsync snapshot --copy-files
   └─ ✔ 9 dotfiles captured             ⬇
4. dotsync push
   └─ ⬆ Pushed to git ─────────────────→  gitlab.com:user/dotfiles (private)
                                                                               5. pip install dotsync-ai
                                                                               6. dotsync init
                                                                                  ├─ Scan: tools detected
                                                                                  ├─ 🔧 Set up git remote? → [n]
                                                                                  └─ (skip — will pull instead)
                                                                               7. dotsync push -r git@gitlab.com:user/dotfiles.git
                                                                                  └─ ⬇ Init + set remote
                                                                               8. dotsync pull
                                                                                  └─ ⬇ Pulled dotfiles ──────←
                                                                               9. 🛤️ Auto Path Remap:
                                                                                  ~/.config/Code → %APPDATA%\Code
                                                                                  ~/.bashrc → C:\Users\x\.bashrc
                                                                               10. dotsync apply --dry-run
                                                                                   └─ Preview changes
                                                                               11. dotsync apply
                                                                                   └─ ✅ Done! Windows configured!
```

### Windows → Linux (Reverse)

```
🪟 PC Windows (Source)                   ☁️ Git Private Repo                   🖥️ PC Linux (Target)
━━━━━━━━━━━━━━━━━━━━━                   ━━━━━━━━━━━━━━━━━━                   ━━━━━━━━━━━━━━━━━━━━

1. pip install dotsync-ai
2. dotsync init
   ├─ Scan tools
   └─ 🔧 Set up git remote? → git@gitlab.com:user/dotfiles.git
3. dotsync snapshot --copy-files
4. dotsync push ──────────────────────→  dotfiles repo
                                                                              5. pip install dotsync-ai
                                                                              6. dotsync init
                                                                              7. dotsync push -r git@gitlab.com:user/dotfiles.git
                                                                              8. dotsync pull ──────────←
                                                                              9. 🛤️ Auto remap:
                                                                                 %APPDATA%\Code → ~/.config/Code
                                                                              10. dotsync apply
                                                                                  └─ ✅ Done!
```

### Daily Sync (After First Setup)

```
🔄 Daily Workflow
━━━━━━━━━━━━━━━━━

PC A:  edit dotfiles → dotsync snapshot → dotsync push ─→ ☁️
PC B:  dotsync pull ─← ☁️ → dotsync apply
```

### ⚠️ Important Notes

**Git Repo Requirement:**
- You need **1 private git repo** (GitLab, GitHub, etc.)
- Recommended: create an empty repo first, e.g. `gitlab.com/user/dotfiles`
- `dotsync init` will prompt to set it up automatically

**Vault Key (.vault_key):**
- The encryption key for secrets is **never pushed to git**
- To sync secrets across machines, transfer `.vault_key` manually:
  - Flash drive, Signal DM, encrypted email, etc.
  - Place in `~/.dotsync/.vault_key` on the target machine

---

## 📖 Command Reference

### `dotsync init`
Initialize DotSync — scan your current environment.

```bash
dotsync init                          # Scan default home directory
dotsync init --home /home/custom      # Scan a custom home directory
```

### `dotsync snapshot`
Take a snapshot of your current dotfiles into the store.

```bash
dotsync snapshot                      # Record paths of detected dotfiles
dotsync snapshot --copy-files         # Copy actual file contents
dotsync snapshot --store /custom/path # Use custom store directory
```

### `dotsync status`
Show current sync status — tracked, modified, missing.

```bash
dotsync status
```

### `dotsync list`
List all tracked dotfiles.

```bash
dotsync list                          # Table output
dotsync list --json                   # JSON output for scripting
```

### `dotsync diff`
Compare stored dotfiles with current filesystem.

```bash
dotsync diff                          # File-level comparison
dotsync diff --content                # Unified diff of file contents
dotsync diff /path/to/snapshot        # Compare against a specific snapshot
```

### `dotsync apply`
Restore dotfiles from store to filesystem via symlinks.

```bash
dotsync apply --dry-run               # Preview changes only
dotsync apply                         # Apply with backup
dotsync apply --force                 # Overwrite existing (with backup)
dotsync apply --no-backup             # Skip backup (use with caution)
dotsync apply -t git,vscode           # Only sync git and vscode
dotsync apply -e docker               # Sync everything except docker
dotsync apply --resolve mine          # Keep my version on conflict
dotsync apply --resolve theirs        # Accept stored version on conflict
dotsync apply --resolve merge         # Auto-merge on conflict
```

### `dotsync config`
Show current DotSync configuration.

```bash
dotsync config
```

### `dotsync machines`
List all known machines that have snapshots stored.

```bash
dotsync machines
```

### `dotsync switch`
Switch the active machine context.

```bash
dotsync switch <machine-name>         # e.g. dotsync switch my-work-pc
```

### `dotsync push`
Commit and push dotfiles to git remote.

```bash
dotsync push                          # Auto-commit + push
dotsync push -r git@gitlab.com:user/dotfiles.git   # Set remote URL
dotsync push -m "Custom commit message"
```

### `dotsync pull`
Pull latest dotfiles from git remote.

```bash
dotsync pull
```

### `dotsync secret`
Manage encrypted secrets in the Fernet vault.

```bash
dotsync secret set GITHUB_TOKEN       # Store a secret (prompts for value)
dotsync secret get GITHUB_TOKEN       # Retrieve a secret
dotsync secret list                   # List all secret keys
dotsync secret delete GITHUB_TOKEN    # Remove a secret
```

---

## 🔧 Advanced Usage

### 🔐 End-to-End Sync Workflow

```bash
# Machine A (source)
dotsync init
dotsync snapshot --copy-files
dotsync secret set DOTFILES_GIT_TOKEN   # Store your git token
dotsync push -r git@gitlab.com:user/dotfiles.git

# Machine B (target, fresh install)
dotsync init                           # Detect tools on this machine
dotsync pull                           # Pull dotfiles from git
dotsync apply --dry-run                # See what will be applied
dotsync apply --resolve theirs         # Accept stored versions
```

### 🛠️ Selective Sync Examples

```bash
# Only sync dev tools, skip terminal config
dotsync apply -t git,ssh,vscode,node,python

# Exclude heavy configs
dotsync apply -e docker -e starship

# Multiple machines, different tools
dotsync switch work-linux
dotsync apply -t git,vscode,docker

dotsync switch home-mac
dotsync apply -t git,ssh,node
```

### 🔄 Cross-OS Workflow

```bash
# --- On Linux work machine ---
dotsync init
dotsync snapshot --copy-files
dotsync push

# --- On Windows home machine ---
# Paths like ~/.config/code/User/settings.json
# are automatically remapped to %APPDATA%\Code\User\settings.json
dotsync init
dotsync pull
dotsync apply --dry-run      # Verify path remapping
dotsync apply
```

### 🗑️ Cleanup

```bash
# Clean up a specific tool's files from store
dotsync apply -e <tool>      # Skip the tool on next apply

# Full reset
rm -rf ~/.dotsync
```

---

## ⚙️ Configuration

DotSync looks for config in `~/.dotsync/dotsync.yaml` (auto-created on `init`).

### Example `~/.dotsync/dotsync.yaml`

```yaml
# DotSync AI Configuration

store_path: ~/.dotsync/store
active_machine: my-laptop

# Path remapping rules (cross-OS)
pathmaps:
  linux:
    vscode_config: ~/.config/Code/User
  windows:
    vscode_config: '%APPDATA%\Code\User'
  macos:
    vscode_config: ~/Library/Application Support/Code/User

# Tool-specific settings
tools:
  git:
    enabled: true
    config_files:
      - ~/.gitconfig
  vscode:
    enabled: true
  ssh:
    enabled: true
    exclude:
      - ~/.ssh/known_hosts   # Don't sync known_hosts

# Sync behavior
sync:
  backup: true                # Always backup before overwriting
  resolve_strategy: mine      # Default conflict resolution
```

---

## 📁 Project Structure

```
dotsync-ai/
├── src/dotsync/           # Main Python package
│   ├── cli.py             # CLI entry point (Click + Rich)
│   ├── scanner.py         # Detect installed tools & dotfiles
│   ├── snapshot.py        # Collect & store dotfile snapshots
│   ├── sync.py            # Apply dotfiles to target OS
│   ├── apply.py           # Symlink-based dotfile application
│   ├── diff_engine.py     # File-level and content diff
│   ├── pathmap.py         # Cross-OS path remapping
│   ├── config.py          # Config file parsing (YAML)
│   ├── crypto.py          # Encrypt/decrypt secrets (Fernet)
│   ├── git_backend.py     # Git push/pull operations
│   ├── conflict.py        # 3-way conflict resolution
│   ├── selective.py       # Per-tool include/exclude filtering
│   ├── content_remap.py   # Path remapping inside file contents
│   ├── filter.py          # Exclude/include pattern matching
│   ├── lineending.py      # Line ending normalization
│   ├── tool_normalize.py  # Tool name normalization (cross-OS)
│   ├── list_cmd.py        # List tracked files with status
│   ├── machines.py        # Multi-machine tracking
│   ├── manifest.py        # Manifest.json store management
│   ├── status.py          # Sync status display
│   ├── models.py          # Pydantic data models
│   └── __init__.py        # Package init
├── npm/                   # npm wrapper package
│   ├── package.json       # npm package definition
│   ├── bin/
│   │   └── dotsync.js     # npm CLI entry point
│   ├── src/
│   │   ├── setup.js       # postinstall — venv + wheel setup
│   │   └── cleanup.js     # uninstall — venv cleanup
│   └── dist/              # Bundled Python wheel
│       └── dotsync_ai-*.whl
├── tests/                 # Comprehensive test suite
│   ├── test_cli.py
│   ├── test_scanner.py
│   ├── test_snapshot.py
│   ├── test_sync.py
│   ├── test_apply.py
│   ├── test_pathmap.py
│   ├── test_config.py
│   ├── test_crypto.py
│   ├── test_git_backend.py
│   ├── test_conflict.py
│   ├── test_selective.py
│   ├── test_content_remap.py
│   ├── test_filter.py
│   ├── test_lineending.py
│   ├── test_tool_normalize.py
│   ├── test_list_cmd.py
│   ├── test_machines.py
│   ├── test_manifest.py
│   ├── test_status.py
│   ├── test_dotsync.py
│   ├── test_diff_engine.py
│   └── __init__.py
├── docs/
│   └── plans/             # Development plans
├── pyproject.toml         # Python project config
├── .gitignore
├── LICENSE                # MIT License
└── README.md              # You are here
```

---

## 🏗️ Architecture

```
┌──────────────────────────────────────────────┐
│               dotsync CLI                     │
│         (Click + Rich — cli.py)               │
├──────────────────────────┬───────────────────┤
│   init / snapshot / diff │  push / pull      │
│   apply / config / list  │  secret            │
│   status / machines      │                    │
│   switch                 │                    │
├──────────┬───────────────┴───────────────────┤
│ Scanner  │  GitBackend     │  Crypto          │
│ (detect) │  (version     ) │  (Fernet AES)    │
│          │   control)      │                  │
├──────────┼────────────────┼──────────────────┤
│ Pathmap  │  Conflict      │  DiffEngine       │
│ (remap)  │  (resolve)     │  (compare)        │
├──────────┴────────────────┴──────────────────┤
│              Store (~/.dotsync/)              │
│  manifest.json  │  dotfiles/  │  secrets.enc  │
└──────────────────────────────────────────────┘
```

### Key Design Decisions

| Decision | Why |
|----------|-----|
| **Symlinks for apply** | Files stay editable in-place, store is the source of truth |
| **Fernet (AES-128)** | Battle-tested symmetric encryption from `cryptography` lib |
| **YAML config** | Human-readable, easy to edit manually |
| **Git backend** | Leverages existing git infrastructure, no custom server |
| **Pydantic models** | Type-safe data validation throughout |

---

## 💡 Use Cases

### 🖥️ Developer Machine Setup
- Fresh OS install? `dotsync pull && dotsync apply` — back to full dev setup in seconds.
- VS Code settings, git config, shell aliases — all restored instantly.

### 🏢 Multi-Workstation
- Office desktop + home laptop: keep both in sync.
- Switch machine context with `dotsync switch`.
- Different tool sets per machine (desktop has Docker, laptop doesn't).

### 🌐 Cross-Platform (Linux ↔ macOS ↔ Windows)
- One config for all three OS.
- Path remapping handles OS conventions automatically.
- Line ending normalization prevents CRLF/LF issues.

### 🔐 Secure Dotfiles in Git
- Public dotfiles repo + encrypted secrets.
- Git tokens, API keys, SSH passwords stored encrypted.
- Only you can decrypt (separate vault key).

### 👥 Team Onboarding
- New dev joins the team? Share a base config.
- Each team member customizes via selective sync.
- Standardized dev environment across the team.

---

## 🗺️ Roadmap

### v0.1 — MVP (✅ Complete)
- [x] Project setup and packaging
- [x] `dotsync init` — scan environment, detect tools
- [x] `dotsync snapshot` — collect dotfiles into store
- [x] Linux support (bash, zsh, git, ssh, vscode)
- [x] `dotsync apply` — restore via symlinks
- [x] `dotsync diff` — compare environments
- [x] `dotsync status` — sync state overview
- [x] `dotsync list` — tracked file listing
- [x] Cross-OS path remapping (Linux ↔ Windows ↔ macOS)
- [x] Git-based dotfile storage (push/pull)
- [x] Encrypted secrets (Fernet AES-128)
- [x] Multi-machine support (machines/switch)
- [x] Conflict resolution (mine/theirs/merge)
- [x] Selective sync (per-tool filtering)
- [x] Config file (YAML)
- [x] npm wrapper package
- [x] Comprehensive test suite (136+ tests)

### v0.2 — Cross-OS Polish
- [ ] `dotsync snapshot` — Windows path scanning
- [ ] `dotsync init` — macOS Homebrew detection
- [ ] npm package published to registry
- [ ] Windows Chocolatey/Scoop detection
- [ ] Shell completion scripts (bash, zsh, fish)

### v0.3 — Collaboration & CI
- [ ] GitHub/GitLab CI template for dotfile validation
- [ ] `dotsync validate` — validate config before apply
- [ ] `dotsync doctor` — diagnose common issues
- [ ] Pre-commit hook for secret scanning

### v0.4 — AI-Assisted Config
- [ ] AI-powered config optimization suggestions
- [ ] Workflow-based config profiles
- [ ] Smart conflict auto-resolution
- [ ] Config drift detection and alerts

---

## 🤝 Contributing

Contributions are welcome! Here's how to get started:

```bash
# Clone and set up
git clone https://gitlab.com/fiqi/dotsync-ai.git
cd dotsync-ai

# Install in development mode
pip install -e ".[dev]"

# Run tests
pytest

# Type check
mypy src/dotsync

# Lint
ruff check src/dotsync
```

### Guidelines
1. Fork the repository.
2. Create a feature branch: `git checkout -b feat/my-feature`.
3. Write tests for new features.
4. Ensure all tests pass and coverage doesn't drop.
5. Submit a Merge Request.

---

## 📄 License

MIT License — see [LICENSE](LICENSE) for full text.

---

<p align="center">
  <strong>Made with ❤️ for developers tired of configuring environments twice.</strong>
  <br>
  <a href="https://gitlab.com/fiqi/dotsync-ai">GitLab</a>
  ·
  <a href="https://github.com/fiqi/dotsync-ai">GitHub Mirror</a>
</p>
