Skip to main content

Dotfile manager with git-powered branching

Project description

dot-man

Dotfile manager with git-powered branching

CI PyPI version PyPI downloads Python License: MIT Code style: black Ruff Checked with mypy Coverage PRs Welcome


Switch your entire development environment in one command.

Install · Quick Start · Commands · Config · Docs


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

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

Advanced

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

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

Installation

From PyPI (recommended)

pip install dotman-git

Shell completions are installed automatically on first run.

With pipx (isolated)

pipx install dotman-git

From source

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

Verify

dot-man --version

Quick Start

# 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)

# 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)

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

# 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

[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:

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:

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

Development

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 and DEVELOPMENT.md for full guides.


Roadmap

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

See docs/roadmap.md for the full roadmap.


Contributing

Pull requests are welcome. Please read CONTRIBUTING.md first.

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


License

MIT © Bishoy Ehab & ZVAXEROWS

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

dotman_git-1.1.1.tar.gz (195.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dotman_git-1.1.1-py3-none-any.whl (158.3 kB view details)

Uploaded Python 3

File details

Details for the file dotman_git-1.1.1.tar.gz.

File metadata

  • Download URL: dotman_git-1.1.1.tar.gz
  • Upload date:
  • Size: 195.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dotman_git-1.1.1.tar.gz
Algorithm Hash digest
SHA256 3a9250e82494384794fc762c63c10d7d8b180100ce15840c294b0e3824898883
MD5 e003e51b4bd6df4424d9bbb3ca514bf6
BLAKE2b-256 630da925fed70f073709a090fd3ff1b816ac334e8c3da2156ae5da9c02fb818f

See more details on using hashes here.

Provenance

The following attestation bundles were made for dotman_git-1.1.1.tar.gz:

Publisher: publish.yml on BeshoyEhab/dot-man

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file dotman_git-1.1.1-py3-none-any.whl.

File metadata

  • Download URL: dotman_git-1.1.1-py3-none-any.whl
  • Upload date:
  • Size: 158.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for dotman_git-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 538f2cbf44c4ce041532c9c605d7926a24e1694c0e15b1439f6f93820c77fe0d
MD5 1a04113445ac3272b0b35acfb5ded03d
BLAKE2b-256 505d6e52af80241708d62f3275e8b18298e4fef896bba74ac2ead1f2d2cbe969

See more details on using hashes here.

Provenance

The following attestation bundles were made for dotman_git-1.1.1-py3-none-any.whl:

Publisher: publish.yml on BeshoyEhab/dot-man

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page