Forge your shell configuration from modular pieces with dependency resolution
Project description
gzh-cli-shellforge
Forge your shell configuration from modular pieces with dependency resolution
A build tool that transforms modular shell scripts into a unified .zshrc/.bashrc with automatic dependency ordering and OS-specific filtering.
What it does
- Reads shell modules from your config directory
- Resolves dependencies automatically
- Filters by OS (Mac/Linux)
- Generates optimized
.zshrc/.bashrc - Validates configuration integrity
- Automatic backup and version control (new in v0.2.0)
Problem
Managing shell configurations across multiple machines and operating systems is challenging:
- Manual concatenation is error-prone
- Dependency ordering is hard to maintain
- OS-specific logic scattered everywhere
- No validation before deployment
Solution
Shellforge uses a declarative manifest to define your shell modules and their dependencies, then builds the final configuration file with correct ordering and OS filtering.
Installation
# With uv (recommended)
uv pip install shellforge
# Or with pip
pip install shellforge
Quick Start
Option A: Auto-generate from existing shellrc (Recommended)
If you have an existing shell configuration in init.d/, rc_pre.d/, rc_post.d/ structure:
# 1. Auto-generate manifest from existing config
shellforge init -c ~/devenv/config/shellrc -o manifest.yaml
# 2. Review and edit the generated manifest
vim manifest.yaml
# 3. Validate
shellforge validate -c ~/devenv/config/shellrc -m manifest.yaml
# 4. Build
shellforge build -c ~/devenv/config/shellrc -m manifest.yaml --auto-output
Option B: Manual manifest creation
# manifest.yaml
modules:
- name: brew-path
file: init.d/brew.sh
requires: []
os: [Mac]
description: Homebrew PATH initialization
- name: conda
file: rc_pre.d/conda.sh
requires: [brew-path]
os: [Mac, Linux]
description: Conda environment
Then build:
shellforge build \
--config-dir ~/devenv/config/shellrc \
--manifest manifest.yaml \
--output ~/.zshrc
New in v0.2.0: Deployment with Backup
Deploy with automatic backup and version control:
shellforge build \
-c shellforge-modules/modules \
-m shellforge-modules/manifest.yaml \
--auto-output \
--deploy
This will:
- Build to
tmp/shellforge-build/first - Create timestamped snapshot in
~/.backup/shellforge/snapshots/ - Commit to git in
~/.backup/shellforge/ - Deploy to actual location (e.g.,
~/.zshrc)
Dual Protection:
- Git history for full version control
- Timestamped snapshots for quick rollback
Restore from Backup
Rollback to a previous version:
# List available snapshots
shellforge restore -t ~/.zshrc --list
# Restore interactively (shows recent snapshots)
shellforge restore -t ~/.zshrc
# Restore specific snapshot
shellforge restore -t ~/.zshrc -s ~/.backup/shellforge/snapshots/zshrc/2025-11-23_10-29-15
Cleanup Old Snapshots
Manage snapshot retention:
# Keep only last 10 snapshots
shellforge clean-snapshots -t ~/.zshrc --keep-count 10
# Keep snapshots from last 30 days
shellforge clean-snapshots -t ~/.zshrc --keep-days 30
# Preview what would be deleted
shellforge clean-snapshots -t ~/.zshrc --keep-count 10 --dry-run
See Deployment Guide for details.
Self-Documenting CLI (v0.3.0+)
Shellforge provides contextual guidance to help you navigate workflows without constantly consulting documentation:
Quick Start Guide
Run shellforge --help to see common workflows organized by use case:
- First-time setup: Migrate existing config or start from scratch
- Daily workflow: Validate → Build → Diff → Deploy cycle
- Recovery: Restore from backups
Smart Statistics
Commands show helpful statistics after execution:
$ shellforge validate -c modules -m manifest.yaml
✓ Validation passed
📊 Validation Statistics:
• Total modules: 27
• Mac modules: 27
• Linux modules: 22
• Total dependencies: 18
💡 Next steps:
Preview: shellforge build -c modules -m manifest.yaml --dry-run
Compare: shellforge diff -c modules -m manifest.yaml --auto-detect-existing
Next Steps Suggestions
Each command suggests what to do next based on the operation result:
- After
validate: Suggests preview, compare, or deploy - After
build: Suggests compare or deploy (context-aware) - After
diff: Suggests deploy or backup strategies
Verbose Mode for Details
Use -v or --verbose flag for detailed information:
# See dependency resolution details
shellforge validate -c modules -m manifest.yaml -v
# See module load order during build
shellforge build -c modules -m manifest.yaml -o output.zsh -v
# See detailed change analysis
shellforge diff -c modules -m manifest.yaml --auto-detect-existing -v
Error-Specific Help
Errors include specific troubleshooting steps:
$ shellforge validate -c wrong -m manifest.yaml
✗ Validation failed:
• Circular dependency detected: asdf-core -> nvm -> asdf-core
💡 Fix circular dependency:
Edit manifest.yaml and review the 'requires' fields
Remove one dependency from the circular chain
Common error scenarios covered:
- Circular dependencies: Shows which dependencies to review
- Missing files: Guides path verification
- YAML syntax errors: Links to example manifests
- Permission errors: Provides chmod examples
Usage
Init
Generate manifest from existing shell configuration:
# Auto-generate manifest from existing shellrc directory
shellforge init -c config/shellrc -o manifest.yaml
# Preview without writing file
shellforge init -c config/shellrc --dry-run
# Custom output location
shellforge init -c ~/dotfiles/shellrc -o ~/dotfiles/manifest.yaml
What it does:
- Scans
init.d/,rc_pre.d/,rc_post.d/directories - Auto-detects module dependencies:
$MACHINEusage → depends onos-detectionbrewcommands → depends onbrew-path- Module-specific (e.g.,
asdf-flutter→asdf-core)
- Detects OS support from
case $MACHINEstatements - Extracts descriptions from comments or generates defaults
- Generates YAML manifest with helpful category comments
Example output:
# Shellforge Manifest
# Auto-generated from existing shell configuration
modules:
# System Initialization (init.d)
- name: os-detection
file: init.d/00_check_os.sh
requires: []
os: [Mac, Linux]
description: Detect operating system and set MACHINE variable
# Pre-RC Configuration (rc_pre.d)
- name: conda
file: rc_pre.d/conda.sh
requires: [os-detection, brew-path]
os: [Mac, Linux]
description: Conda environment initialization
Build
Generate shell configuration file:
# Auto-detect OS and use recommended output file
shellforge build -c config/shellrc -m manifest.yaml --auto-output
# Specify OS, shell, and session type
shellforge build -c config/shellrc -m manifest.yaml \
--os macos --shell zsh --session interactive \
--auto-output
# Manual output file
shellforge build -c config/shellrc -m manifest.yaml -o ~/.zshrc
# Build for different session types
# Login shell (.zprofile for zsh, .bash_profile for bash)
shellforge build -c config/shellrc -m manifest.yaml \
--session login --auto-output
# Interactive shell (.zshrc for zsh, .bashrc for bash)
shellforge build -c config/shellrc -m manifest.yaml \
--session interactive --auto-output
# Always sourced (.zshenv for zsh)
shellforge build -c config/shellrc -m manifest.yaml \
--shell zsh --session always --auto-output
# Fish shell (always use --session always for fish)
shellforge build -c config/shellrc -m manifest.yaml \
--shell fish --session always --auto-output
# Dry run (preview output)
shellforge build -c config/shellrc -m manifest.yaml --auto-output --dry-run
# Verbose output
shellforge build -c config/shellrc -m manifest.yaml --auto-output -v
Template
Generate new modules from common patterns:
# List available templates
shellforge template list
# Generate PATH module
shellforge template generate path my-custom-bin \
-f path_dir=/opt/myapp/bin \
-f description="My custom application binaries"
# Generate environment variable
shellforge template generate env EDITOR \
-f var_name=EDITOR \
-f var_value=vim \
-f description="Set default editor"
# Generate aliases
shellforge template generate alias git-shortcuts \
-f description="Git command shortcuts" \
-f aliases="alias gs='git status'
alias gp='git push'
alias gl='git pull'"
# Generate tool initialization with dependencies
shellforge template generate tool-init nvm \
-f tool_name=nvm \
-f tool_command=nvm \
-f init_command='eval "$(nvm init -)"' \
-f description="Node Version Manager" \
-r brew-path
# Interactive mode (prompts for all fields)
shellforge template generate env MY_VAR -i
# Generate in specific directory
shellforge template generate path custom-bin \
-c ~/dotfiles/shellrc \
-f path_dir=/usr/local/mybin \
-f description="Custom binaries"
Available templates:
path- Add directory to PATH (init.d/)env- Set environment variable (rc_pre.d/)alias- Define shell aliases (rc_post.d/)conditional-source- Source file if it exists (rc_pre.d/)tool-init- Initialize development tool (rc_pre.d/)os-specific- OS-specific configuration (rc_pre.d/)
Info
Show shell configuration file information:
# macOS zsh interactive shell
shellforge info --os macos --shell zsh --session interactive
# Ubuntu bash login shell
shellforge info --os ubuntu --shell bash --session login
# Arch zsh (always sourced)
shellforge info --os arch --shell zsh --session always
# Fish shell (all platforms, session type is always 'always')
shellforge info --os macos --shell fish --session always
shellforge info --os ubuntu --shell fish --session always
Validate
Check manifest and module files:
shellforge validate -c config/shellrc -m manifest.yaml
Migrate
Convert traditional RC file to shellforge structure:
# Migrate existing .zshrc to shellforge modules
shellforge migrate -s ~/.zshrc -t config/shellrc
# Preview migration without writing files
shellforge migrate -s ~/.zshrc -t config/shellrc --dry-run
# Migrate without backup
shellforge migrate -s ~/.zshrc -t config/shellrc --no-backup
# Migrate without auto-generating manifest
shellforge migrate -s ~/.zshrc -t config/shellrc --no-manifest
What it does:
- Analyzes your existing RC file and identifies logical sections
- Automatically categorizes sections into init.d/, rc_pre.d/, or rc_post.d/
- Creates modular shell scripts for each section
- Creates backup of original file (default)
- Auto-generates manifest.yaml (default)
Example workflow:
# 1. Migrate existing .zshrc
shellforge migrate -s ~/.zshrc -t ~/dotfiles/shellrc
# 2. Review migrated modules
ls ~/dotfiles/shellrc/*/
# 3. Validate
shellforge validate -c ~/dotfiles/shellrc -m ~/dotfiles/shellrc/manifest.yaml
# 4. Build and test
shellforge build -c ~/dotfiles/shellrc -m ~/dotfiles/shellrc/manifest.yaml --auto-output --dry-run
Diff
Compare generated configuration with existing RC file:
# Auto-detect existing RC file based on OS/shell
shellforge diff -c config/shellrc -m manifest.yaml --auto-detect-existing
# Compare with specific file
shellforge diff -c config/shellrc -m manifest.yaml -e ~/.zshrc
# Show detailed unified diff
shellforge diff -c config/shellrc -m manifest.yaml \
--auto-detect-existing --format unified
# Context diff format
shellforge diff -c config/shellrc -m manifest.yaml \
--auto-detect-existing --format context
# Summary only (default)
shellforge diff -c config/shellrc -m manifest.yaml \
--auto-detect-existing --format summary
Output formats:
summary: Statistics about differences (default)unified: Standard unified diff formatcontext: Context diff format
List Modules
Show modules in load order:
# Current OS
shellforge list-modules -c config/shellrc -m manifest.yaml
# Specific OS
shellforge list-modules -c config/shellrc -m manifest.yaml --os Linux
Manifest Format
modules:
- name: module-name # Unique identifier
file: path/to/module.sh # Relative to config-dir
requires: [dep1, dep2] # Dependencies (optional)
os: [Mac, Linux] # Supported OS (optional)
description: What it does # Description (optional)
Example Manifest
See examples/manifest.yaml for a complete example.
Project Structure
your-dotfiles/
├── config/
│ └── shellrc/
│ ├── init.d/
│ │ ├── 00-os-detection.sh
│ │ └── 05-brew-path.sh
│ ├── rc_pre.d/
│ │ ├── conda.sh
│ │ └── nvm.sh
│ └── rc_post.d/
│ └── aliases.sh
└── manifest.yaml
Features
Shell Configuration Metadata
Shellforge includes comprehensive metadata about shell configuration files for different operating systems and session types.
Supported Operating Systems:
- macOS
- Ubuntu
- Debian
- Arch Linux
- Manjaro Linux
Supported Shells:
- Zsh (~69% market share) - Default on macOS
- Bash (~17% market share) - Most widely available
- Fish (~6% market share) - Modern, user-friendly shell
Session Types:
login: Login shells (TTY, SSH, Terminal.app on macOS) - bash/zshinteractive: Interactive non-login shells (most terminal emulators) - bash/zshalways: Always sourced - zsh (via .zshenv) and fish (all invocations)gui: GUI desktop environment startup
Note on Fish Shell:
Fish does not distinguish between login/non-login or interactive/non-interactive shells.
All fish shells load the same configuration files, so use --session always for fish.
The metadata includes:
- Which files are loaded in which order
- System-wide vs user-specific files
- File alternatives (e.g., .bash_profile OR .bash_login OR .profile)
- Recommended build targets for each environment
Use shellforge info to explore the metadata for your environment.
Automatic Dependency Resolution
Shellforge builds a dependency graph and uses topological sorting to ensure modules are loaded in the correct order.
modules:
- name: gcloud
requires: [brew-path] # Will be loaded after brew-path
- name: brew-path
requires: [] # Loaded first
OS Filtering
Only include modules for the target OS:
modules:
- name: brew-path
os: [Mac] # Only on macOS
- name: pacman-setup
os: [Linux] # Only on Linux
- name: common-aliases
os: [Mac, Linux] # Both
Circular Dependency Detection
Shellforge detects and reports circular dependencies:
$ shellforge validate -c config -m manifest.yaml
✗ Validation failed:
- Circular dependency detected: 'module-a' -> 'module-b' -> 'module-a'
Development
Setup
# Clone repository
git clone git@github.com:Gizzahub/gzh-cli-shellforge.git
cd gzh-cli-shellforge
# Quick setup (creates venv and installs dependencies)
make dev-setup
# Or manual installation
uv pip install -e ".[dev]"
Available Make Commands
make help # Show all available commands
# Installation
make install # Install in development mode
make install-system # Install system-wide
make install-dev # Install with dev dependencies
# Testing
make test # Run all tests
make test-coverage # Run tests with coverage report
# Code Quality
make lint # Check code style (no changes)
make lint-fix # Auto-fix lint issues
make lint-strict-fix # Strict lint with auto-fix
# Build
make build # Build package
make clean # Clean build artifacts
Run Tests
make test
# or directly
uv run pytest -v
Lint
make lint-fix
# or directly
uv run ruff check . --fix
uv run ruff format .
Integration with Chezmoi
You can use Shellforge with Chezmoi for multi-machine dotfile management:
# Build config
shellforge build -c config/shellrc -m manifest.yaml -o ~/.zshrc
# Add to Chezmoi
chezmoi add ~/.zshrc
# Apply to other machines
chezmoi apply
License
MIT
Contributing
Contributions welcome! Please open an issue or PR.
Documentation
- Testing Guide - Manual testing guide with sample data
- Deployment Guide - Comprehensive guide for backup and deployment features
- Examples - Example configurations and manifests
Related Projects
Part of gzh-cli Series
Other tools in the gzh-cli series:
gzh-cli-shellforge- This project- More coming soon...
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file gz_shellforge-0.3.2.tar.gz.
File metadata
- Download URL: gz_shellforge-0.3.2.tar.gz
- Upload date:
- Size: 108.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52937ae8843cdd99d30c11ed54f340ed7fa9ae31eb2cedc6c3750fb1b277366d
|
|
| MD5 |
a707ae7e7a55d6ec8edc5e4013995c55
|
|
| BLAKE2b-256 |
f2b7db46ac56f60015a8d56244051cbca8128d543f478a162c895b52fe8d5f04
|
File details
Details for the file gz_shellforge-0.3.2-py3-none-any.whl.
File metadata
- Download URL: gz_shellforge-0.3.2-py3-none-any.whl
- Upload date:
- Size: 35.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
77b3a15efccb69c99a5a6b904a19f18cc6e13e152c63f2f35aa8addda377a9a4
|
|
| MD5 |
e16c65f44af3a167c659997474eb92f7
|
|
| BLAKE2b-256 |
ee9e5e8eb8336d37b1a6025ef7b8387792c5f9370e1da73f793a8f32595cf52f
|