Guisu (归宿, pronounced "gwee-soo") — A haven for your dotfiles, inspired by the Chinese phrase meaning "home" or "destination". Just as 归宿 represents a place of belonging, Guisu provides a safe harbor for managing your configuration files across all your machines.
Early Development Notice: Guisu is currently in early development (pre-1.0). APIs and features are subject to change. Production use is not recommended yet.
Guisu is a Rust-based dotfile manager inspired by chezmoi, designed to help you manage your configuration files (dotfiles) across multiple machines with:
- Blazing Fast: Rust native binary with parallel processing
- Secure by Default: Built-in age encryption without external dependencies
- Template-Based: Powerful Jinja2-like templates via minijinja
- Type-Safe: Leverages Rust's type system to prevent runtime errors
- Smart State Tracking: Persistent state management using redb
- Interactive Conflict Resolution: Beautiful TUI for handling conflicts
- Cross-Platform: Works on macOS, Linux, and Windows
| Feature | Guisu | Chezmoi | Advantage |
|---|---|---|---|
| Performance | Native Rust | Go (with cgo) | 2-5x faster |
| Binary Size | ~3-5 MB | ~20 MB | 4x smaller |
| Encryption | Built-in only (age crate) | Built-in or external age | Simpler, no config needed |
| Git | Built-in only (git2) | Built-in or external git | Simpler, no config needed |
| Database | redb (pure Rust) | BoltDB (cgo) | Simpler build |
| Type Safety | Compile-time path types | Runtime checks | Fewer bugs |
| Templates | minijinja (Jinja2) | Go text/template | More familiar |
From source (requires Rust toolchain):
git clone https://github.com/PaulYuuu/guisu.git
cd guisu
cargo install --path crates/cliBinary releases: Coming soon
# Clone your dotfiles repository
guisu init username
# Or use full URL
guisu init https://github.com/username/dotfiles.git# Create a new dotfiles repository
guisu init# Add a file
guisu add ~/.bashrc
# Add with encryption
guisu add --encrypt ~/.ssh/id_rsa
# Add entire directory
guisu add ~/.config/nvim# Apply all changes
guisu apply
# Interactive mode (resolve conflicts manually)
guisu apply --interactive
# Dry run (preview changes)
guisu apply --dry-run# Show managed files status
guisu status
# Show differences
guisu diff
# Preview rendered content
guisu cat ~/.bashrc# Edit source file (transparently handles encryption)
guisu edit ~/.bashrc
# Opens in your configured editor# Pull latest changes and apply
guisu update
# Pull without applying
guisu update --no-apply# Show basic status and validate configuration
guisu info
# Show detailed information (build info, versions, public keys, configuration)
guisu info --all
# Output in JSON format
guisu info --json
guisu info --all --json# Show all variables (system, guisu, and user-defined)
guisu variables
# Show only builtin variables (system + guisu)
guisu variables --builtin
# Show only user-defined variables
guisu variables --user
# Output in JSON format
guisu variables --jsonGuisu manages files through three distinct states:
Source State Target State Destination State
(Repository) (After Processing) (Actual Files)
↓ ↓ ↓
.bashrc.j2 → .bashrc (rendered) → ~/.bashrc
key.txt.age → key.txt (decrypted) → ~/key.txt
Persistent State (redb database) tracks what was last applied to detect external changes.
Guisu uses filename extensions to encode file attributes. Source and destination filenames are the same, except for special extensions:
# Template files (rendered with Jinja2)
.bashrc.j2 → ~/.bashrc (rendered)
# Encrypted files (age encryption)
private_key.age → private_key (decrypted)
# Combined: template + encryption
.bashrc.j2.age → ~/.bashrc (decrypted, then rendered)
# Regular files (no transformation)
.bashrc → ~/.bashrc
.ssh/config → ~/.ssh/config
scripts/deploy.sh → scripts/deploy.shGuisu uses minijinja (Jinja2-compatible) for templates:
# ~/.local/share/guisu/.bashrc.j2
# Platform-specific configuration
{% if os == "darwin" %}
export HOMEBREW_PREFIX="/opt/homebrew"
alias ls="gls --color=auto"
{% elif os == "linux" %}
alias ls="ls --color=auto"
{% endif %}
# User variables
export EDITOR="{{ editor }}"
export EMAIL="{{ email }}"
# Secrets from Bitwarden
export GITHUB_TOKEN="{{ bitwarden("GitHub").login.password }}"
# Or use bitwardenFields for custom fields
export API_KEY="{{ bitwardenFields("GitHub", "APIKey") }}"Create .guisu.toml in your dotfiles repository:
[general]
color = true
progress = true
editor = "nvim"
[age]
identity = "~/.config/guisu/key.txt"
derive = true # Derive public key from identity for encryption
[bitwarden]
provider = "rbw" # or "bw"
[variables]
email = "user@example.com"
editor = "nvim"
[ignore]
# Files/directories to exclude from guisu management (not a .gitignore replacement)
global = [".git", ".DS_Store"]
darwin = ["Thumbs.db"]
linux = ["*~"]# Generate age identity
guisu age generate -o ~/.config/guisu/key.txt
# Add encrypted file
guisu add --encrypt ~/.ssh/id_rsa
# Edit encrypted file (automatic decryption)
guisu edit ~/.ssh/id_rsaOrganize variables in .guisu/variables/ directory:
.guisu/variables/
├── user.toml # Global user variables
├── visual.toml # UI/appearance settings
├── darwin/
│ ├── git.toml # macOS-specific git config
│ └── terminal.toml # macOS-specific terminal
└── linux/
├── git.toml # Linux-specific git config
└── terminal.toml # Linux-specific terminal
When local files differ from your dotfiles:
guisu apply --interactiveBeautiful TUI shows:
- Side-by-side diff
- Three-way comparison (Source, Target, Destination, Database)
- Options: Overwrite, Skip, View Diff, Preview
- File management (files, directories, symlinks)
- Template processing (minijinja, ~30 functions)
- Age encryption (file + inline)
- Git integration (clone, pull, push)
- Interactive conflict resolution (TUI)
- Persistent state tracking (redb)
- Parallel processing (rayon)
- Platform-specific configuration
- Bitwarden integration (bw, rbw, bws)
Critical:
- Script execution system (
run_before_*,run_after_*,run_once_*,run_onchange_*) - External resources (
.chezmoiexternalequivalent) - Modify file type (
modify_*prefix) - Create-only files (
create_*prefix)
High Priority:
- Limited password manager support (only Bitwarden; missing 1Password, LastPass, Pass, Vault, etc.)
- Limited template functions (~30 vs 200+ in chezmoi)
Medium Priority:
- Missing commands:
doctor,unmanaged,re-add,archive,verify,merge
See ROADMAP.md for detailed development plan.
- Architecture Overview - System architecture and design
- Container Architecture - Crate structure
- Component Design - Internal components
- Data Flow - Processing pipeline
- Contributing Guide - How to contribute
- Roadmap - Feature roadmap
Guisu is in early development and welcomes contributions! Please see CONTRIBUTING.md for:
- Development setup
- Code structure
- Testing guidelines
- Pull request process
Guisu is heavily inspired by chezmoi, with the goal of providing similar functionality in a Rust-native package.
MIT License - see LICENSE for details.