Skip to content

mabo-du/pluck

Repository files navigation

pluck
Pluck git repos from any forge — auto-detect, auto-install, done!

Platform: Linux | macOS Python 3.8+ License: MIT Zero dependencies 111 passing tests 11 forges supported PyPI: pluck-cli Code style: ruff GitLab CI


🚀 Quick Start

pluck chasing repos

# 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

pluck stalking a repo

┌─────────────────┐     ┌──────────────┐     ┌─────────────────┐     ┌──────────────┐
│  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--shallow for faster downloads
  • 🏷️ Branch/tag support--ref to install specific versions
  • 🎯 Force method--method to override auto-detection
  • ⏱️ Timeout & retry--timeout and --retries for 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--dir to override default install location
  • ⚙️ User config — Persistent settings via config file
  • 🎨 JSON output--json for machine-readable output
  • 🚫 No colors--no-color for clean terminal output
  • 🔇 Non-interactive--yes for scripting
  • 🐳 Docker support — Containerized installation
  • 📖 Man pageman pluck for offline docs
  • 🔧 Post-install hooks — Custom scripts after each install

🌐 Supported Forges

All the 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 stalking repos in your browser

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

About

Paste git URL, auto-detect install method, auto-install, done!

Resources

License

Contributing

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors