Metadata-Version: 2.4
Name: dotman-git
Version: 1.1.1
Summary: Dotfile manager with git-powered branching
Author-email: Bishoy Ehab <beshoyehabhhmm@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/BeshoyEhab/dot-man
Project-URL: Repository, https://github.com/BeshoyEhab/dot-man
Project-URL: Documentation, https://github.com/BeshoyEhab/dot-man#readme
Project-URL: Bug Tracker, https://github.com/BeshoyEhab/dot-man/issues
Project-URL: Changelog, https://github.com/BeshoyEhab/dot-man/blob/main/CHANGELOG.md
Keywords: dotfiles,git,configuration,cli,dotfile-manager,branching
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: MacOS
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 :: System :: Systems Administration
Classifier: Topic :: Utilities
Classifier: Typing :: Typed
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: click>=8.0
Requires-Dist: cryptography>=41.0.0
Requires-Dist: gitpython>=3.1
Requires-Dist: rich>=13.0
Requires-Dist: tomli>=2.0; python_version < "3.11"
Requires-Dist: tomlkit>=0.12.0
Requires-Dist: questionary>=2.0.0
Provides-Extra: yaml
Requires-Dist: pyyaml>=6.0; extra == "yaml"
Provides-Extra: tui
Requires-Dist: textual>=0.73.0; extra == "tui"
Provides-Extra: watch
Requires-Dist: watchdog>=4.0; extra == "watch"
Provides-Extra: dev
Requires-Dist: pytest>=8.3.5; extra == "dev"
Requires-Dist: pytest-cov>=5.0.0; extra == "dev"
Requires-Dist: black>=24.8.0; extra == "dev"
Requires-Dist: mypy>=1.14.1; extra == "dev"
Requires-Dist: textual>=0.73.0; extra == "dev"
Requires-Dist: ruff>=0.4.0; extra == "dev"
Requires-Dist: pre-commit>=3.0.0; extra == "dev"
Dynamic: license-file

<div align="center">

# dot-man

**Dotfile manager with git-powered branching**

[![CI](https://github.com/BeshoyEhab/dot-man/actions/workflows/ci.yml/badge.svg)](https://github.com/BeshoyEhab/dot-man/actions/workflows/ci.yml)
[![PyPI version](https://img.shields.io/pypi/v/dotman-git?color=blue&logo=pypi&logoColor=white)](https://pypi.org/project/dotman-git/)
[![PyPI downloads](https://img.shields.io/pypi/dm/dotman-git?color=blue&logo=pypi&logoColor=white)](https://pypi.org/project/dotman-git/)
[![Python](https://img.shields.io/pypi/pyversions/dotman-git?logo=python&logoColor=white)](https://pypi.org/project/dotman-git/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![Checked with mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](https://mypy-lang.org/)
[![Coverage](https://img.shields.io/badge/coverage-61%25-yellow)](https://github.com/BeshoyEhab/dot-man)
[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/BeshoyEhab/dot-man/pulls)

---

*Switch your entire development environment in one command.*

[**Install**](#installation) · [**Quick Start**](#quick-start) · [**Commands**](#commands) · [**Config**](#configuration) · [**Docs**](docs/)

</div>

---

## What is dot-man?

dot-man stores your dotfiles in a **git repository** and uses **branches as configuration profiles**. Each branch is a complete, deployable snapshot of your environment.

```
Your Machine                  dot-man Repo               Any Machine
──────────────                ────────────               ───────────
~/.bashrc      ──── save ──►  branch: main  ── deploy ──►  ~/.bashrc
~/.config/nvim ──── save ──►  branch: work  ── deploy ──►  ~/.config/nvim
~/.gitconfig   ──── save ──►  branch: server               ~/.gitconfig
```

**Secrets are never committed.** API keys, tokens and passwords are automatically detected, encrypted locally in a vault, and replaced with hashes in the repository before any commit.

---

## Features

<table>
<tr>
<td>

**Core**
- 🌿 Git-powered branch profiles
- 🔐 Automatic secret detection & vault
- 🔄 Save → switch → deploy in one command
- ⚡ Pre/post deploy hooks with aliases
- 🏷️ Tag snapshots for fast rollback

</td>
<td>

**Advanced**
- 🔒 GPG / AGE file encryption
- 🌍 Import from chezmoi, yadm, stow
- 📤 Export to tar, zip, JSON
- 🔍 Auto-discover 30+ dotfile locations
- 🌐 YAML + TOML config support

</td>
<td>

**Developer**
- 🐚 Shell completions (bash/zsh/fish)
- 🎨 Syntax-highlighted rich diffs
- 🩺 `doctor` and `verify` diagnostics
- 📦 PyPI — `pip install dotman-git`
- 🔁 Remote sync via `dot-man sync`

</td>
</tr>
</table>

---

## Installation

### From PyPI (recommended)

```bash
pip install dotman-git
```

Shell completions are installed automatically on first run.

### With pipx (isolated)

```bash
pipx install dotman-git
```

### From source

```bash
git clone https://github.com/BeshoyEhab/dot-man.git
cd dot-man
pip install .
```

### Verify

```bash
dot-man --version
```

---

## Quick Start

```bash
# 1. Initialize — runs an interactive wizard that auto-detects your dotfiles
dot-man init

# 2. Add files manually if needed
dot-man add ~/.bashrc
dot-man add ~/.config/nvim

# 3. Create a "work" profile (branch)
dot-man navigate work
# btw it was "switch" instead of "navigate" untill Bishoy decided to change it to "navigate" for some silly reasons and push that changes so as community help us to make it "switch" again.

# 4. Edit your work-specific configs, then switch back — changes are saved automatically
dot-man navigate main

# 5. See what's changed
dot-man status
dot-man diff
```

---

## How Branching Works

Each branch is an independent configuration. Switching branches runs three phases automatically:

```
dot-man navigate work
        │
        ├─► Phase 1: Save   — copies your files into the repo and commits
        ├─► Phase 2: Switch — git checkout work
        └─► Phase 3: Deploy — copies repo files back to your home directory
```

| Branch   | Purpose                              |
|----------|--------------------------------------|
| `main`   | Personal daily driver                |
| `work`   | Office: proxy, work aliases          |
| `server` | Minimal: headless, no GUI tools      |
| `laptop` | Mobile: battery saving, HiDPI        |

---

## Commands

### Navigation

| Command | Description |
|---------|-------------|
| `dot-man navigate <target>` | Switch to branch, tag, or commit |
| `dot-man navigate work --preview` | Preview what will change |
| `dot-man navigate work --preview --diff` | Full diff before switching |
| `dot-man navigate work --no-save` | Discard local changes and switch |
| `dot-man navigate v1.0` | Jump to a tag |
| `dot-man navigate abc1234` | Checkout a specific commit |

### Files & Tracking

| Command | Description |
|---------|-------------|
| `dot-man init` | Initialize repository with setup wizard |
| `dot-man add <path>` | Track a file or directory |
| `dot-man status` | Show tracked files and their state |
| `dot-man status --secrets` | Highlight files containing secrets |
| `dot-man diff` | Show uncommitted changes |
| `dot-man diff --branch main` | Compare current branch to main |
| `dot-man diff --rich` | Syntax-highlighted diff |
| `dot-man revert <file>` | Restore file from repo |
| `dot-man revert <file> -c abc123` | Restore from specific commit |
| `dot-man watch` | Auto-save tracked files on change |
| `dot-man watch --no-commit` | Watch and save without committing |

### History & Tags

| Command | Description |
|---------|-------------|
| `dot-man log` | Show commit history |
| `dot-man log --diff` | History with diffs |
| `dot-man log --interactive` | TUI log browser |
| `dot-man show <commit>` | Full diff for a commit |
| `dot-man tag create v1.0` | Create a tag |
| `dot-man tag list` | List all tags |
| `dot-man tag switch v1.0` | Checkout a tag |
| `dot-man rollback` | Roll back to previous commit |
| `dot-man rollback -n 3` | Roll back 3 commits |
| `dot-man rollback --list` | Show available rollback points |

### Security

| Command | Description |
|---------|-------------|
| `dot-man audit` | Scan repo for secrets |
| `dot-man audit --strict` | Exit non-zero if any secrets found |
| `dot-man audit --fix` | Auto-redact detected secrets |
| `dot-man encrypt encrypt <section>` | Encrypt a section with GPG/AGE |
| `dot-man encrypt status` | Show encryption status |

### Import / Export / Discovery

| Command | Description |
|---------|-------------|
| `dot-man discover` | Auto-detect existing dotfiles |
| `dot-man discover --add` | Add detected configs automatically |
| `dot-man import chezmoi` | Import from chezmoi |
| `dot-man import yadm` | Import from yadm |
| `dot-man import stow` | Import from GNU Stow |
| `dot-man export tar backup.tar.gz` | Export to tar archive |
| `dot-man export zip dots.zip` | Export to zip |
| `dot-man export json manifest.json` | Export to JSON manifest |

### Sync & Remote

| Command | Description |
|---------|-------------|
| `dot-man sync` | Push + pull with remote |
| `dot-man sync --push-only` | Only push |
| `dot-man sync --pull-only` | Only pull |
| `dot-man remote set <url>` | Set remote URL |
| `dot-man setup` | Guided GitHub remote setup |

### Diagnostics

| Command | Description |
|---------|-------------|
| `dot-man doctor` | Run health checks |
| `dot-man verify` | Validate repo integrity |
| `dot-man backup create` | Create a manual backup |
| `dot-man backup restore <id>` | Restore from backup |

---

## Configuration

Configuration lives in `~/.config/dot-man/repo/dot-man.toml` and is tracked **per branch** — different branches can track different files.

### TOML (default)

```toml
# Simple file tracking
[bashrc]
paths = ["~/.bashrc"]
post_deploy = "shell_reload"

# Directory with exclusions
[nvim]
paths = ["~/.config/nvim"]
exclude = ["*.log", "plugin/packer_compiled.lua"]
post_deploy = "nvim_sync"

# SSH config with secret filtering
[ssh-config]
paths = ["~/.ssh/config"]
secrets_filter = true
update_strategy = "rename_old"

# Hyprland with notification on deploy
[hyprland]
paths = ["~/.config/hypr"]
post_deploy = "hyprland_reload"
```

### YAML (also supported)

```yaml
bashrc:
  paths:
    - ~/.bashrc
  post_deploy: shell_reload

nvim:
  paths:
    - ~/.config/nvim
  exclude:
    - "*.log"
  post_deploy: nvim_sync
```

### Hook Aliases

Instead of writing full shell commands, use built-in aliases:

| Alias | Runs |
|-------|------|
| `shell_reload` | `source ~/.bashrc \|\| source ~/.zshrc` |
| `nvim_sync` | `nvim --headless +PackerSync +qa` |
| `hyprland_reload` | `hyprctl reload` |
| `fish_reload` | `source ~/.config/fish/config.fish` |
| `tmux_reload` | `tmux source-file ~/.tmux.conf` |
| `kitty_reload` | `killall -SIGUSR1 kitty` |

### Update Strategies

| Strategy | Behaviour |
|----------|-----------|
| `replace` | Overwrite existing files *(default)* |
| `rename_old` | Back up existing file before overwriting |
| `ignore` | Skip if file already exists |

### Templates & Inheritance

```toml
# Define reusable templates
[templates.linux-desktop]
post_deploy = "notify-send 'Config updated'"
update_strategy = "rename_old"

# Inherit in sections
[hyprland]
paths = ["~/.config/hypr"]
inherits = ["linux-desktop"]

[waybar]
paths = ["~/.config/waybar"]
inherits = ["linux-desktop"]
```

### Environment Variable Expansion

```toml
[work-files]
paths = ["$WORK_DIR/config", "~/$USER/.config/app"]
```

---

## Secret Detection

Before any file enters the repository, dot-man scans it for secrets. Detected values are **encrypted locally** and replaced with a hash placeholder in the repo.

| Pattern | Severity | Example |
|---------|----------|---------|
| Private keys | 🔴 CRITICAL | `-----BEGIN RSA PRIVATE KEY-----` |
| AWS credentials | 🔴 CRITICAL | `AKIA...` |
| GitHub tokens | 🟠 HIGH | `ghp_xxxx` |
| API keys | 🟠 HIGH | `api_key = "sk-..."` |
| Passwords | 🟠 HIGH | `password = "hunter2"` |
| JWT tokens | 🟡 MEDIUM | `eyJ...` |

```
repo file:   api_key = "***REDACTED:e3b0c44298...***"
vault:       { encrypted: "gAAAAABk..." }   ← Fernet AES-128
system file: api_key = "sk-abc123..."       ← restored on deploy
```

Run `dot-man audit` to scan at any time. Use `dot-man audit --strict` in CI/CD pipelines.

---

## Multi-Machine Profiles

Profiles let you auto-select the right branch based on hostname:

```bash
dot-man profile create work-laptop -h work-laptop -h thinkpad
dot-man profile set-branch work-laptop work
dot-man profile detect   # auto-switches to the right profile
```

---

## Template Variables

Use `{{VARIABLE}}` placeholders in your dotfiles that get substituted on deploy:

```bash
dot-man template set EMAIL john@work.com
dot-man template set HOSTNAME work-laptop
```

Then in your `~/.gitconfig`:
```
[user]
    email = {{EMAIL}}
    name  = John Doe
```

System variables (`{{HOSTNAME}}`, `{{USER}}`, `{{SHELL}}`, etc.) are auto-populated.

---

## Project Status

| Metric | Value |
|--------|-------|
| Version | `1.1.0` |
| Python | `3.9+` |
| Platforms | Linux, macOS |
| Test Coverage | 61% |
| Commands | 30+ |
| PyPI | [`dotman-git`](https://pypi.org/project/dotman-git/) |

---

## Development

```bash
git clone https://github.com/BeshoyEhab/dot-man.git
cd dot-man
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Run full quality gate
black dot_man/ tests/
ruff check dot_man/ tests/
mypy dot_man/ --ignore-missing-imports
pytest tests/ --cov=dot_man --cov-report=term-missing
```

See [CONTRIBUTING.md](CONTRIBUTING.md) and [DEVELOPMENT.md](DEVELOPMENT.md) for full guides.

---

## Roadmap

- [ ] 80%+ test coverage
- [ ] Full documentation site (mkdocs)
- [ ] Symlink mode
- [x] `dot-man watch` — auto-sync on file change
- [x] Deploy rollback (transaction-style)
- [ ] Plugin system

See [docs/roadmap.md](docs/roadmap.md) for the full roadmap.

---

## Contributing

Pull requests are welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) first.

All contributions must pass the pre-push quality checklist: `black`, `ruff`, `mypy`, and all tests.

---

## License

[MIT](LICENSE) © [Bishoy Ehab](https://github.com/BeshoyEhab) & [ZVAXEROWS](https://github.com/ZVAXEROWS)
