Pluck git repos from any forge — auto-detect, auto-install, done!
- Quick Start
- How It Works
- Features
- Commands
- Flags
- Installation
- Configuration
- Project Structure
- Development
# Install from any git forge — one command, zero fuss
pluck install https://github.com/user/repo
pluck install https://gitlab.com/user/project
pluck install https://codeberg.org/user/repo
pluck install https://bitbucket.org/owner/repo
# That's it. Pluck detects the project type and installs it.┌─────────────────┐ ┌──────────────┐ ┌─────────────────┐ ┌──────────────┐
│ Any git URL │────▶│ Clone to │────▶│ Detect Method │────▶│ Install │
│ (any forge) │ │ Temp Dir │ │ (Auto-detect) │ │ (8 methods) │
└─────────────────┘ └──────────────┘ └─────────────────┘ └──────────────┘
│
┌─────────────────┐ ┌──────────────┐ │
│ Post-Install │◀────│ Register │◀───────────────────────────────┘
│ Hook (opt) │ │ App │
└─────────────────┘ └──────────────┘
│
▼
┌─────────────────┐
│ Summary + │
│ Cleanup │
└─────────────────┘
| Method | Detection | Action |
|---|---|---|
| 🔧 Script | install.sh |
Runs bash install.sh --yes |
| 🐍 Python | pyproject.toml, setup.py |
Creates venv, pip installs |
| 🟢 Node.js | package.json |
Copies source, runs npm install |
| 🔵 Go | go.mod, *.go |
Runs go build -o to install dir |
| 🦀 Rust | Cargo.toml |
Runs cargo build --release, copies binary |
| 📋 Makefile | Makefile |
Runs make install PREFIX=... |
| 📦 Binary | release/, bin/, *.AppImage, *.deb |
Copies to install dir |
| 📥 Download | Fallback | Copies entire directory |
- 🔗 Any git forge — Install from GitHub, GitLab, Codeberg, Bitbucket, SourceHut, Gitea, Gogs, Pagure, Forgejo, self-hosted, or any git URL
- 🔍 Auto-detection — Automatically detects project type and install method
- 📦 Batch install — Install multiple repositories in one command
- ⚡ Shallow clone —
--shallowfor faster downloads - 🏷️ Branch/tag support —
--refto install specific versions - 🎯 Force method —
--methodto override auto-detection - ⏱️ Timeout & retry —
--timeoutand--retriesfor flaky connections
- 📋 List apps — See all installed applications with disk size
- 🔄 Update apps — Re-install from original URL
- 🗑️ Uninstall — Remove apps with safety guards
- ✅ Verify — Check installed apps integrity
- 🧹 Clean — Remove orphaned registry entries
- 📊 Stats — Installation statistics and method breakdown
- 🌐 Multi-forge search — Search GitHub, GitLab, or Codeberg with
--forge - 🖱️ Browser right-click — Optional extension + protocol handler to install from any page
- 📤 Export/Import — Migrate registry between machines
- 📁 Custom directory —
--dirto override default install location - ⚙️ User config — Persistent settings via config file
- 🎨 JSON output —
--jsonfor machine-readable output - 🚫 No colors —
--no-colorfor clean terminal output - 🔇 Non-interactive —
--yesfor scripting - 🐳 Docker support — Containerized installation
- 📖 Man page —
man pluckfor offline docs - 🔧 Post-install hooks — Custom scripts after each install
| Forge | Host | Built-in | Notes |
|---|---|---|---|
| GitHub | github.com |
✅ | Full support including gists |
| GitLab | gitlab.com |
✅ | HTTPS & SSH, self-hosted instances auto-detected |
| Codeberg | codeberg.org |
✅ | Powered by Forgejo |
| Bitbucket | bitbucket.org |
✅ | Both cloud & self-hosted |
| SourceHut | git.sr.ht |
✅ | Supports ~user prefix |
| Gitea | gitea.com |
✅ | Any Gitea instance works |
| Gogs | gogs.io |
✅ | Lightweight git service |
| Pagure | pagure.io |
✅ | Fedora's git hosting |
| Forgejo | forgejo.org |
✅ | Self-hosted friendly |
| Any other hosted git | Any domain | ✅ | Parses as generic type |
| Self-hosted | Any IP/domain | ✅ | SSH & HTTPS both supported |
Any git hosting platform that follows the standard host/owner/repo URL pattern works — no plugin or config needed.
| Command | Description | Example |
|---|---|---|
install <url> |
Install from any git repo URL | pluck install https://gitlab.com/user/project |
update <name> |
Update an installed app | pluck update myapp |
info <name> |
Show app details | pluck info myapp |
list |
List installed apps | pluck list |
uninstall <name> |
Uninstall an app | pluck uninstall myapp |
remove <name> |
Alias for uninstall | pluck remove myapp |
verify |
Check apps validity | pluck verify |
clean |
Remove orphaned entries | pluck clean --force |
stats |
Show statistics | pluck stats |
doctor |
Check tool availability | pluck doctor |
config [key] [val] |
View/set config | pluck config install_dir ~/Apps |
search <query> [--forge <name>] [--all] [--output <file>] |
Search repos across forges | pluck search python installer --all --output results.txt |
pin <name> |
Pin an app to prevent updates | pluck pin myapp |
unpin <name> |
Unpin an app | pluck unpin myapp |
self-update |
Update pluck itself | pluck self-update |
cache prune |
Clear download cache | pluck cache prune |
export <file> |
Export registry | pluck export ~/backup.json |
import <file> |
Import registry | pluck import ~/backup.json |
completion <shell> |
Generate shell completion | pluck completion bash |
version |
Show version | pluck version |
help |
Show help | pluck help |
| Flag | Description |
|---|---|
--dir <path> |
Install to a custom directory |
--dry-run |
Preview without making changes |
--force |
Skip confirmation prompts |
--shallow |
Use shallow clone (--depth 1) |
--ref <ref> |
Clone a specific branch or tag |
--method <method> |
Force install method |
--yes |
Non-interactive mode (alias for --force) |
--json |
Output in JSON format (for scripting) |
--no-color |
Disable colored output |
--timeout <secs> |
Timeout for git clone in seconds |
--retries <n> |
Number of retries for failed git clone |
--jobs <n> |
Number of parallel installs (default: 1) |
--release |
Install from pre-built release assets instead of cloning |
--verbose |
Show detailed git clone output |
# Clone the repository
git clone https://gitlab.com/mabodu/pluck.git
cd pluck
# Install via pip
pip install -e .
# Or run directly
./src/gh_install.py install https://gitlab.com/user/projectpip install pluck-clidocker build -t pluck .
docker run pluck install https://gitlab.com/user/project| Constant | macOS | Linux | Description |
|---|---|---|---|
DEFAULT_INSTALL_DIR |
~/Applications |
~/.local/opt |
Where apps are installed |
APP_REGISTRY_FILE |
~/.pluck-registry.json |
~/.pluck-registry.json |
App registry |
CONFIG_FILE |
~/.config/pluck/config.json |
~/.config/pluck/config.json |
User config |
{
"install_dir": "/custom/path",
"method_priority": ["script", "python", "node", "go", "rust", "make", "binary", "download"]
}Manage via CLI:
pluck config install_dir ~/Apps
pluck config method_priority '["python","node","binary","download"]'Create ~/.config/pluck/hooks/post-install.sh to run custom scripts after each install.
Available environment variables:
$PLUCK_APP— Repository name$PLUCK_PATH— Installation path$PLUCK_METHOD— Install method used
Pluck includes a right-click context menu integration. Install a repo from any forge without leaving your browser.
# 1. Register the pluck:// protocol handler on your OS
bash scripts/install-protocol-handler.sh
# 2. Load the browser extension (Chrome/Chromium/Brave/Edge)
# Open chrome://extensions → Developer mode → Load unpacked
# Select assets/browser-extension/
# 3. Right-click any git repo link → "Install with pluck"Works with GitHub, GitLab, Codeberg, Bitbucket, SourceHut — any forge.
If you prefer not to install an extension, create a bookmark with this URL:
javascript:location.href='pluck://install?url='+encodeURIComponent(location.href)
When you're on a git repo page, click the bookmark to install it.
The protocol handler is a small shell script (scripts/pluck-protocol-handler.sh)
that receives pluck://install?url=... calls from the browser, decodes the URL,
and runs pluck install <url>. The browser extension adds the right-click menu
item that triggers this protocol call.
pluck/
├── src/
│ └── gh_install.py # Main application (~1700 lines)
├── tests/
│ └── test_gh_install.py # Test suite (111 tests)
├── assets/
│ ├── images/ # Logo and illustrations
│ └── browser-extension/ # Chrome/Chromium right-click extension
├── scripts/
│ ├── pluck-protocol-handler.sh # pluck:// URL handler
│ └── install-protocol-handler.sh # Protocol registration
├── docs/
│ └── IMPLEMENTATION.md # Implementation details
├── man/
│ ├── pluck.1 # Man page
│ └── gh-install.1 # Legacy man page
├── .github/
│ └── workflows/
│ ├── ci.yml # CI: test + lint
│ └── publish-pypi.yml # PyPI publish
├── README.md # This file
├── CHANGELOG.md # Version history
├── CONTRIBUTING.md # Developer guide
├── LICENSE # MIT License
├── Dockerfile # Container image
├── pyproject.toml # Package config
├── .pre-commit-config.yaml # Pre-commit hooks
├── .gitignore # Git ignore patterns
└── .dockerignore # Docker ignore patterns
# Install dev dependencies
pip install pytest ruff
# Run tests
python -m pytest tests/ -v
# Run linter
ruff check src/ tests/
# Install pre-commit hooks
pip install pre-commit
pre-commit install111 tests passing across 24 test classes:
├── TestParseRepoUrl (22 tests)
├── TestGistUrl (7 tests) — includes GitLab snippets
├── TestDetectInstallMethod (17 tests)
├── TestSharedPaths (2 tests)
├── TestValidMethods (2 tests)
├── TestSanitizeRepoName (4 tests)
├── TestIsExecutable (6 tests)
├── TestGetDiskSize (3 tests)
├── TestParseArgs (10 tests)
├── TestDryRun (1 test)
├── TestRegistryOperations (3 tests)
├── TestUpdateApp (2 tests)
├── TestInfoApp (2 tests)
├── TestDoctor (2 tests)
├── TestConfigCommand (2 tests)
├── TestExportImport (4 tests)
├── TestVerifyApps (3 tests)
├── TestStatsCommand (2 tests)
├── TestFormatBytes (5 tests)
├── TestExtractGlobalFlags (5 tests)
└── TestDownloadAndInstallMocked (4 tests)
This project is licensed under the MIT License — see the LICENSE file for details.
Contributions are welcome! Please read the Contributing Guide for details on our code of conduct and the process for submitting pull requests.
Made with ❤️ for non-technical users everywhere



