Skip to main content

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

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

Note: Development and CI run on GitLab; this GitHub repo is a mirror.


🚀 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 page — man 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 (GitLab is canonical - see note above; this repo is a mirror)
git clone https://gitlab.com/mabodu/pluck.git
cd pluck

# Install via pip
pip install -e .

# Or run directly
./src/pluck.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/
│   ├── pluck.py                # Main application (~2400 lines)
│   └── gh_install.py           # Backward-compat alias (imports pluck)
├── tests/
│   └── test_pluck.py           # Test suite (132 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 (kept for backward compat)
├── .github/
│   └── workflows/
│       └── release.yml        # Build wheel + binaries, publish to PyPI + GitHub Releases
├── 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

132 tests passing across 31 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)
├── TestParseArgsMissingFlagValue (6 tests) — regression: flags with missing values
├── TestRegistryAtomicWrite (5 tests) — regression: atomic writes + locking across all registry ops
├── TestInstallPythonSymlink (2 tests) — regression: symlink bug + directory-guard
├── TestSafeTarMembers (2 tests) — regression: CVE-2007-4559 + backslash bypass
├── TestProtocolHandlerUrlParsing (4 tests) — regression: multi-param URL parsing
├── TestReleaseInstallFallback (1 test) — regression: --release fallback to clone
└── TestInstallMakeFallback (1 test) — regression: uncaught CalledProcessError on make failure

📄 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

Metadata

Release files for pluck-cli 0.6.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pluck-cli 0.6.0
File Size Uploaded Provenance
pluck_cli-0.6.0.tar.gz 45.1 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pluck-cli 0.6.0
File Interpreter ABI Platform
pluck_cli-0.6.0-py3-none-any.whl Python 3 none any Details

Total release size: 75.3 kB

Release files / pluck_cli-0.6.0.tar.gz

Download URL pluck_cli-0.6.0.tar.gz
Size 45.1 kB
Tags Source
SHA-256 checksum
How to use checksums
2dcc8f713c81174ce85b5beac76573fe8ef9a1fa38199eec38e3d06b7982f4b1
BLAKE2b-256 checksum
How to use checksums
92dcbb826d0af228a6270cc51a633c89ed8daa80a190e1aecc09edfcf1c58de4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.

Transparency log

Release files / pluck_cli-0.6.0-py3-none-any.whl

Download URL pluck_cli-0.6.0-py3-none-any.whl
Size 30.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
874f46c78f29902a0d475c0b8af21eea988095b1ceda325ee15ade67d92fdba2
BLAKE2b-256 checksum
How to use checksums
9d96d78e7a8d860223552916d99049b26ea4458ccf4e2217a1cbb0ac88cfddf9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.

Transparency log

Security for pluck-cli 0.6.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pluck_cli-0.6.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 4, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page