Pluck any git repo from any forge — auto-detect, auto-install, done!
Project description
Pluck git repos from any forge — auto-detect, auto-install, done!
- Quick Start
- How It Works
- Features
- Commands
- Flags
- Installation
- Configuration
- Project Structure
- Development
🚀 Quick Start
# 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.
🔄 How It Works
┌─────────────────┐ ┌──────────────┐ ┌─────────────────┐ ┌──────────────┐
│ Any git URL │────▶│ Clone to │────▶│ Detect Method │────▶│ Install │
│ (any forge) │ │ Temp Dir │ │ (Auto-detect) │ │ (8 methods) │
└─────────────────┘ └──────────────┘ └─────────────────┘ └──────────────┘
│
┌─────────────────┐ ┌──────────────┐ │
│ Post-Install │◀────│ Register │◀───────────────────────────────┘
│ Hook (opt) │ │ App │
└─────────────────┘ └──────────────┘
│
▼
┌─────────────────┐
│ Summary + │
│ Cleanup │
└─────────────────┘
Install Methods
| 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 |
✨ Features
Installation
- 🔗 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
Management
- 📋 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
Configuration
- 📁 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
🌐 Supported Forges
| 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.
📖 Commands
| 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 |
🏷️ Flags
| 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 |
📥 Installation
From Source
# 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/project
Via pip
pip install pluck-cli
Via Docker
docker build -t pluck .
docker run pluck install https://gitlab.com/user/project
⚙️ Configuration
Default Paths
| 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 |
User Config File
{
"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"]'
Post-Install Hooks
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
🖱️ Browser Integration
Pluck includes a right-click context menu integration. Install a repo from any forge without leaving your browser.
Quick Setup
# 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.
No Extension? Use the Bookmarklet
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.
How It Works
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.
📁 Project Structure
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
🛠️ Development
# 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 install
Test Coverage
111 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)
📄 License
This project is licensed under the MIT License — see the LICENSE file for details.
🤝 Contributing
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
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
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 pluck_cli-0.3.2.tar.gz.
File metadata
- Download URL: pluck_cli-0.3.2.tar.gz
- Upload date:
- Size: 34.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c724882c177e753209f72bd95f5b9a37b5a756e0540fc145b3aff8015967242b
|
|
| MD5 |
d82e68f9c63d92c02115a6301e3701e0
|
|
| BLAKE2b-256 |
b76f579da9bda9601ee6bd9c3fc26ef2addc4effc681cbe2aad11bec115d1ca1
|
File details
Details for the file pluck_cli-0.3.2-py3-none-any.whl.
File metadata
- Download URL: pluck_cli-0.3.2-py3-none-any.whl
- Upload date:
- Size: 24.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b871da9b9adf76118423b520a4a30c75f008b1fcc5faa0b28f979d0efa3e4b13
|
|
| MD5 |
4eabee49bca18a59ee67994699a41634
|
|
| BLAKE2b-256 |
4424e275619da5c966071e4b0bb26a123084b29697c016454be59f09a143318b
|