{"id":22300346,"url":"https://github.com/dropseed/barrel","last_synced_at":"2025-07-29T02:31:43.248Z","repository":{"id":42681698,"uuid":"429240599","full_name":"dropseed/barrel","owner":"dropseed","description":"Python command line tools that are easy to install, repo-isolated, and update themselves.","archived":false,"fork":false,"pushed_at":"2022-03-28T18:47:29.000Z","size":60,"stargazers_count":3,"open_issues_count":2,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-30T14:55:30.626Z","etag":null,"topics":["cli","command-line","pip","python","python3","virtualenv"],"latest_commit_sha":null,"homepage":"https://barrel.dev/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dropseed.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-11-18T00:12:24.000Z","updated_at":"2023-11-26T07:32:38.000Z","dependencies_parsed_at":"2022-09-26T20:02:00.058Z","dependency_job_id":null,"html_url":"https://github.com/dropseed/barrel","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dropseed%2Fbarrel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dropseed%2Fbarrel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dropseed%2Fbarrel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dropseed%2Fbarrel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dropseed","download_url":"https://codeload.github.com/dropseed/barrel/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227971951,"owners_count":17849421,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cli","command-line","pip","python","python3","virtualenv"],"created_at":"2024-12-03T18:10:35.589Z","updated_at":"2024-12-03T18:10:36.381Z","avatar_url":"https://github.com/dropseed.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Barrel\n\n\u003cimg src=\"https://user-images.githubusercontent.com/649496/144511332-90651fbb-826c-4776-9bce-05586b1a1d02.png\" width=\"100\" height=\"100\" align=\"right\" /\u003e\n\n**Python command line tools that are easy to install, repo-isolated, and update themselves.**\n\nUsers install your package with:\n\n```console\n$ curl -sSL https://barrel.dev/install.py | python3 - \u003cpypi_package_name\u003e\n```\n\nAnd update it with:\n\n```console\n$ \u003ccli_name\u003e update\n```\n\n- [Overview](#overview)\n- [What Barrel is](#what-barrel-is)\n- [How Barrel works](#how-barrel-works)\n- [Barrel for package authors](#barrel-for-package-authors)\n- [What Barrel doesn't do](#what-barrel-doesnt-do)\n- [Alternatives](#alternatives)\n\n## Overview\n\nPython can be a great language for writing command line tools,\nbut your users shouldn't have to be Python experts to use them.\n\nFor tools that are *globally* installed,\npeople tend to do things like `pip install --user \u003cpackage\u003e`,\n[write a custom installation script](https://github.com/python-poetry/poetry/blob/cbbd92ceb5938a43a1f4666cdaf9599c74650442/get-poetry.py),\nor install and use a wrapper like [pipx](https://github.com/pypa/pipx/).\n\nThis works when you intend to use the same version of the CLI no matter what you're working on.\nBut there are other things like static site generators and automation tools that should be installed specifically into a user's *repository*.\nThe version installed needs to be isolated and pinned,\nso you can use the same tools on multiple repos/projects without worrying about update conflicts and forcing them all to use the same version.\n\nThere are obviously ways to deal with this today (see [alternatives](#alternatives)),\nbut they all require a certain amount of Python-ecosystem knowledge that your users may not have.\nEspecially if your CLI is written in Python,\nbut the user doesn't actually use Python when interacting with it.\n\n## What Barrel is\n\nBarrel is an installation script,\nembeddable package,\nand set of conventions for installing an isolated and versioned command line tool into a repo.\nAs a bonus, Barrel makes it easy for you to have a self-updating CLI.\n\nThe goal is to *simplify* the process (especially for non-Pythonistas) and provide a developer experience that doesn't suck.\nIt does this by being a lightweight wrapper around standard, known conventions that can be used as a \"one-liner\".\n\nUsing well-known conventions like `requirements.txt` also allows standard CI/CD workflows and other services/tools to \"just work\",\nwithout knowing or caring about Barrel itself.\nThis makes it automatically compatible with hosting services like Netlify,\nand dependency management automation like Dependabot.\n\n## How Barrel works\n\nThe initial install of a command line tools is done with a script.\nA curl -\u003e Python command is the easiest way to do this,\nand doesn't require *any* additional dependencies besides Python 3 (which your CLI requires anyway).\n\n```console\n$ curl -sSL https://barrel.dev/install.py | python3 - \u003cpypi_package_name\u003e\n```\n\nThis will create a virtual environment at `.venv` and `requirements.txt` file.\nThe `.venv` should be in `.gitignore` but the `requirements.txt` should be committed.\nThe install script will help point out these details for people that aren't familiar with them.\n\nThe `requirements.txt` file will look something like this and effectively [\"pins\"](https://www.python.org/dev/peps/pep-0440/#version-matching) the version in use until an update is made:\n\n```txt\n# This file is managed automatically by \u003cpackage\u003e\n\u003cpackage\u003e==2.3.0\n```\n\nOnce installed, updates can be done two ways.\n\n1) Barrel is integrated into the package/CLI itself, providing a command like `\u003cpackage\u003e update`.\nThis is the most user-friendly way to do it,\nsince they already have your CLI installed and don't have to remember or save the curl command.\n2) But if you don't include Barrel in your package,\nyou can always run the curl command again to update the package (using the `--reinstall` option).\n\nThe only caveat at this point is that `.venv/bin/` needs to be in the user's `PATH`,\nor they need to use `./.venv/bin/\u003cpackage\u003e` directly.\nThe install script will help point this out and how it can be done (ex. `export PATH=\"./.venv/bin:$PATH\"`).\n\n## Barrel for package authors\n\nTo use Barrel for the installation process,\nyou just need a published package that is your CLI.\n\nYou can copy [install.py](https://github.com/dropseed/barrel/blob/master/barrel/install.py) to your own repo or site,\nbut the we always keep an up-to-date hosted version at https://barrel.dev/install.py.\n\nYour documentation should tell users how to use the curl command (including your package name as the argument).\n\n```console\n$ curl -sSL https://barrel.dev/install.py | python3 - \u003cpypi_package_name\u003e\n```\n\nYou *should* add \"barrel\" as a dependency in your package and provide a self-updating experience.\nTo do this, you just need to call the `update` function with the name of your package.\nYou can add it to your CLI like this example using [click](https://github.com/pallets/click):\n\n```python\nimport barrel\n\n\n@click.command()\ndef update():\n    \"\"\"Update your version of combine\"\"\"\n    barrel.update(\"combine\")\n```\n\nIf you don't add \"barrel\" as a dependency,\nthen you'll need to tell users to run the curl command again to update with the `--reinstall` option.\n\n```console\n$ curl -sSL https://barrel.dev/install.py | python3 - \u003cpypi_package_name\u003e --reinstall\n```\n\nThings to know:\n\n- Barrel supports Python 3 only\n- Barrel expects your package to be the only direct dependency the user needs to install (i.e. their `requirements.txt` will only end up with your package in it -- [nothing else](#freeze-all-dependency-requirements))\n- Barrel expects your package to have an entrypoint (by default this should be the same as the package name)\n\n## What Barrel doesn't do\n\nThe primary goal of Barrel is to *simplify* the dependency installation/update process for people.\nSo it shouldn't come as a surprise that certain features you know from full-fledged dependency managers are intentionally missing.\n\n### Freeze *all* dependency requirements\n\nThe `requirements.txt` won't include all of the pinned versions of indirect/transitive dependencies.\nWhile that would help with the predictability of an install,\nthose details don't (and arguably *shouldn't*) matter to most people and can cause a lot of noise in automated dependency update tools.\n\nIf you're authoring a package that uses Barrel,\nyou should take extra care to specify the ranges of your dependencies that you know *work*,\nand put a CI process in place to regularly test a fresh install just like your users would get.\n\n### Lock to a specific Python version\n\nBarrel won't save the Python version it used during the install,\nand it won't force everyone on the repo to use the same Python version.\n\nManaging multiple Python versions is not for everyone.\nThere are tools and ways to do it,\nbut it can get complicated fast.\n\nBarrel only works with Python 3 since [Python 2 was sunset in 2020](https://www.python.org/doc/sunset-python-2/).\nThis makes it easier.\n\nSimilar to the point on frozen requirements,\nit should be the package authors responsiblity to define the range of Python3 versions you support and to make sure they work.\n[Use a matrix in your CI tests to stay on top of it.](https://github.com/dropseed/barrel/blob/fae14a440e503ee67ec81da053a47c2ec8439ecb/.github/workflows/test.yml#L8-L15)\n\n## Alternatives\n\n### pip by itself\n\nBarrel is a wrapper around standard pip processes and conventions,\nso you can obviously do the same thing with pip directly.\nThe problem is, there are a series of steps that people either have to already know or have scripted.\nThere are a lot of decisions to make along the way and you can easily lose people just by having an overly complicated install process for someone who isn't familiar with Python.\n\nBarrel essentially does these steps for a new install:\n\n```console\n$ python3 -m venv .venv\n$ ./.venv/bin/pip install \u003cpackage\u003e\n$ ./.venv/bin/pip freeze | grep \u003cpackage\u003e \u003e requirements.txt\n```\n\nThese steps for a fresh install of an existing repo:\n\n```console\n$ python3 -m venv .venv\n$ ./.venv/bin/pip install -r requirements.txt\n```\n\nAnd these steps for update:\n\n```console\n$ ./.venv/bin/pip install -U \u003cpackage\u003e\n$ ./.venv/bin/pip freeze | grep \u003cpackage\u003e \u003e requirements.txt\n```\n\nBarrel makes the install step (new or existing) a curl one-liner,\nand the update step as simple as `\u003cpackage\u003e update`.\n\n### pipx\n\nOn the surface, [pipx](https://github.com/pypa/pipx/) is pretty similar in goals.\nThe difference is that pipx is aimed at tools that are installed *globally* on a user's machine.\nThis is not exactly what you want if your package needs to be versioned to a specific user's repo.\n\nIf you try to use a globally installed command across multiple repos,\nyou run into problems when a new version of the command is released and new features are added/removed that aren't compatible with *all* of your repos (build command changed syntax, YAML config settings changed, etc.).\nThe only solution you have is to update all of them at once,\nwhich can be a pretty unpleasant experience depending on the changes required.\n\n### poetry, pipenv, etc.\n\nIn a lot of ways, Barrel is intended to be a simpler alternative to these.\nBoth [Poetry](https://github.com/python-poetry/poetry) and [Pipenv](https://github.com/pypa/pipenv) can be used for installing a specific version of a Python package into a repo.\nBut they come with a lot of other baggage that you simply don't need for a single-dependency repo.\n\nBoth require you to install the tool itself first (which is a process of its own),\nand can force other decisions like locking to a specific Python version,\nnew commands to learn,\nand extra headaches if poetry/pipenv themselves break!\nWhich does happen (surprisinglyg frequently in the case of Pipenv) and can require a lot of difficult troubleshooting.\nBarrel largely avoids this by doing basic `pip` commands and `requirements.txt` flows that are unlikely to have any problems.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdropseed%2Fbarrel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdropseed%2Fbarrel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdropseed%2Fbarrel/lists"}