JavaScript has npm, Ruby has Gems, Python has pip and now Shell has bpkg!
bpkg is a lightweight bash package manager. It takes care of fetching the shell scripts, installing them appropriately, setting the execution permission and more.
You can install shell scripts globally (on ${PREFIX:-/usr/local/bin}) or use them on a per-project basis (on ${BPKG_DEPS:-./deps/}), as a lazy-man "copy and paste".
You can install bpkg from three distinct ways:
Our install script is the simplest way. It takes care of everything for you, placing bpkg and related scripts on /usr/local/bin.
You can install bpkg with the get.bpkg.sh endpoint:
curl -Lo - get.bpkg.sh | bashOr optionally paste the following on your shell and you're good to go:
curl -Lo- "https://raw.githubusercontent.com/bpkg/bpkg/master/setup.sh" | bashor by tag/version
curl -Lo- "https://raw.githubusercontent.com/bpkg/bpkg/1.0.15/setup.sh" | bashclib is a package manager for C projects. If you already have it, installing bpkg is a simple matter of:
clib install bpkg/bpkgTo directly install bpkg from its source code you have to clone its repository and run the setup.sh script:
git clone https://github.com/bpkg/bpkg.git
cd bpkg
./setup.sh # Will install bpkg in $HOME/.local/bin
sudo ./setup.sh # Will install bpkg in /usr/local/bin.
PREFIX=/my/custom/directory ./setup.sh # Will install bpkg in a custom directory.You use bpkg by simply sending commands, pretty much like npm or pip.
Packages can either be global (on ${PREFIX:-/usr/local/bin} if installed as root or
${PREFIX:-$HOME/.local/bin} otherwize) or local (under ${BPKG_DEPS:-./deps}).
For example, here's a global install for the current user of the term package:
bpkg install term -g
termAnd the same package as a local install:
bpkg install term
./deps/term/term.shAfter a local install the term.sh script is copied as term to the deps/bin directory, you can add this directory to the PATH with
export PATH=$PATH:/path_to_bkpg/deps/binAs a bonus, you can specify a specific version:
bpkg install jwerle/suggest.sh@0.0.1 -gNote: to do that the packages must be tagged releases on the repository.
You can also install packages without a bpkg.json (or package.json).
As long as there is a Makefile in the repository it will try to invoke make install as long as the -g or --global flags are set when invoking bpkg install.
For example you could install git-standup with an omitted bpkg.json (or package.json) because of the Makefile and the install target found in it.
bpkg install stephenmathieson/git-standup -g
warn: bpkg.json doesn`t exist
warn: package.json doesn`t exist
warn: Trying `make install'...
info: install: `make install'
cp -f git-standup /usr/local/binYou can install a packages dependencies with the bpkg getdeps command. These will recursively install in deps/ sub-folders to resolve all dependencies.
Note: There is no protection against circular dependencies, so be careful!
You can run a package script with bpkg run which will install your
package globally and execute it as a command
After installing a package, you can obtain info from it using bpkg.
Supposing you're on the root of a package directory, the following commands show that package metadata:
# Asking for single information
bpkg package name
"bpkg"
bpkg package version
"0.0.5"
# Dumping all the metadata
bpkg package
["name"] "bpkg"
["version"] "0.0.5"
["description"] "Lightweight bash package manager"
["global"] true
["install"] "make install"Here we lay down some info on the structure of a package.
Every package must have a file called bpkg.json (for backward-compatibility
package.json can also be used); it specifies package metadata on the JSON format.
Here's an example of a well-formed bpkg.json:
{
"name": "term",
"version": "0.0.1",
"description": "Terminal utility functions",
"scripts": [ "term.sh" ],
"install": "make install"
}All fields are mandatory except when noted. Here's a detailed explanation on all fields:
The name attribute is required as it is used to tell bpkg where to put it in the deps/ directory in you project.
"name": "my-script"The version attribute is not required but can be useful. It should correspond to the version that is associated with the installed package.
"version": "0.0.1"A human readable description of what the package offers for functionality.
"description": "This script makes monkeys jump out of your keyboard"Indicates that the package is only intended to be install as a script. This allows the omission of the -g or --global flag during installation.
"global": "true"Shell script used to invoke in the install script. This is required if the global attribute is set to true or if the -g or --global flags are provided.
"install": "make install"This is an array of scripts that will be installed into a project.
"scripts": ["script.sh"]This is an array of files that will be installed into a project.
"files": ["bar.txt", "foo.txt"]This is a hash of dependencies. The keys are the package names, and the values are the version specifiers. If you want the latest code use 'master' in the version specifier. Otherwise, use a tagged release identifier. This works the same as bpkg install's package/version specifiers.
"dependencies": {
"term": "0.0.1"
}These are guidelines that we strongly encourage developers to follow.
It's nice to have a bash package that can be used in the terminal and also be invoked as a command line function. To achieve this the exporting of your functionality should follow this pattern:
if [[ ${BASH_SOURCE[0]} != "$0" ]]; then
export -f my_script
else
my_script "${@}"
exit $?
fiThis allows a user to source your script or invoke as a script.
# Running as a script
./my_script.sh some args --blah
# Sourcing the script
source my_script.sh
my_script some more args --blahbpkg wouldn't be where it is today without the help of its authors, contributors, and sponsors:
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]
This project exists thanks to all the people who contribute. [Contribute].
Thank you to all our backers! 🙏 [Become a backer]
bpkg is released under the MIT license.
See file LICENSE for a more detailed description of its terms.