Skip to main content

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

Project description

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

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

pluck_cli-0.3.2.tar.gz (34.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

pluck_cli-0.3.2-py3-none-any.whl (24.2 kB view details)

Uploaded Python 3

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

Hashes for pluck_cli-0.3.2.tar.gz
Algorithm Hash digest
SHA256 c724882c177e753209f72bd95f5b9a37b5a756e0540fc145b3aff8015967242b
MD5 d82e68f9c63d92c02115a6301e3701e0
BLAKE2b-256 b76f579da9bda9601ee6bd9c3fc26ef2addc4effc681cbe2aad11bec115d1ca1

See more details on using hashes here.

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

Hashes for pluck_cli-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b871da9b9adf76118423b520a4a30c75f008b1fcc5faa0b28f979d0efa3e4b13
MD5 4eabee49bca18a59ee67994699a41634
BLAKE2b-256 4424e275619da5c966071e4b0bb26a123084b29697c016454be59f09a143318b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page