{"id":14155408,"url":"https://github.com/Shiphero/shbin","last_synced_at":"2025-08-06T01:31:16.875Z","repository":{"id":53202692,"uuid":"515287570","full_name":"Shiphero/shbin","owner":"Shiphero","description":"turns a Github repo into a pastebin","archived":false,"fork":false,"pushed_at":"2024-02-21T04:40:35.000Z","size":232,"stargazers_count":56,"open_issues_count":19,"forks_count":2,"subscribers_count":37,"default_branch":"main","last_synced_at":"2024-12-08T13:36:48.437Z","etag":null,"topics":["command-line-tool","gists","git","github","github-api","pastebin","pastebin-service"],"latest_commit_sha":null,"homepage":"","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/Shiphero.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2022-07-18T17:54:40.000Z","updated_at":"2024-11-07T06:29:57.000Z","dependencies_parsed_at":"2024-01-03T04:14:37.724Z","dependency_job_id":"12f8c7cd-fe51-49c2-8fb8-834500ce7f08","html_url":"https://github.com/Shiphero/shbin","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shiphero%2Fshbin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shiphero%2Fshbin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shiphero%2Fshbin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Shiphero%2Fshbin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Shiphero","download_url":"https://codeload.github.com/Shiphero/shbin/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228821405,"owners_count":17977166,"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":["command-line-tool","gists","git","github","github-api","pastebin","pastebin-service"],"created_at":"2024-08-17T08:03:03.192Z","updated_at":"2025-08-06T01:31:16.864Z","avatar_url":"https://github.com/Shiphero.png","language":"Python","readme":"[![tests](https://github.com/Shiphero/shbin/actions/workflows/pytest.yml/badge.svg?branch=main)](https://github.com/Shiphero/shbin/actions/workflows/pytest.yml)\n[![black](https://github.com/Shiphero/shbin/actions/workflows/black.yml/badge.svg?branch=main)](https://github.com/Shiphero/shbin/actions/workflows/black.yml)\n[![PyPI version](https://img.shields.io/pypi/v/shbin)](https://pypi.org/project/shbin/)\n[![PyPI - Downloads](https://img.shields.io/pypi/dm/shbin)](https://libraries.io/pypi/shbin)\n\n`shbin` turns a Github repo into a pastebin.\n\nIt's a tiny command-line tool we've built at\n[Shiphero](http://shiphero.com) that lets you easily upload code\nsnippets, notebooks, images or any other content to a Github repository\nthat acts as your internal pastebin, and returns the URL to share it\nwith your team. If possible, this URL is automatically copied to the\nclipboard.\n\n\u003cp align=\"center\"\u003e\n    \u003cimg width=\"90%\" src=\"https://raw.githubusercontent.com/Shiphero/shbin/main/demo/usage.svg\" /\u003e\n\u003c/p\u003e\n\n# Why?\n\nYou want to share code snippets, images, notebooks, etc. with your team,\nprobably privately. Gist is great, but it has some limitations:\n\n- The content may be secret but it is not private: if you have the url\n  you have the access (and to err is human).\n- The ownership of the shared content is in the user's namespace, not\n  the organization's. What happens if the user leaves the organization?\n- You can't find some secret content shared by a teammate if the URL is\n  lost. Only the person who created it can find it, and even that isn't\n  easy if the content doesn't have a good name and description.\n- Content organization is difficult: you can upload multiple files to\n  a gist, but you can't create folders.\n- The default gist interface does not allow you to \"paste\" an image (you\n  can paste it as part of a comment, but not as part of the gist content\n  itself). Sharing screenshots is a common use case on computers.\n\nUsing a full repository has all the advantages of Gist (rich content\nrendering like markdown or ipynb, every change is a git commit, etc.)\nwithout these limitations.\n\nThe only downside of a plain repository is that it is not as easy as\n\"paste\" the content, even when editing through the Github interface.\nBut `shbin` solves that.\n\nSound good? Give us a star and share it! \n\n[![Sparkline](https://stars.medv.io/shiphero/shbin.svg)](https://stars.medv.io/shiphero/shbin)\n\n# Usage\n\n```console\n# upload or update a file\n$ shbin demo.py\n\n# upload with a commit description\n$ shbin demo.py -m \"my cool demo script\"         \n\n# Upload any content in clipboard, discovering its format. e.g.\n# a screenshot. The name will be random but the extension will be\n# based on the format detected.\n$ shbin -x          \n\n# upload the content in the clipboard with a given filename\n$ shbin -x -f my_snippet.md \n\n# upload from stdin\n$ echo \"some content\" | shbin -\n\n# download a given file (inside the namespace)\n$ shbin dl my_snippet.md     \n\n# update the content of a file that already exists\n$ shbin my_snippet.md\n\n# from clipboard with a given name to a directory in your user directory\n$ shbin -x -f the_coolest_thing.py -d coolest_things/python\n\n# upload several files in a directory\n$ shbin *.ipynb *.csv -d notebooks/project -m \"my new work\"   \n\n# Reformat the URL to link to Github pages.\n$ shbin demo.py -p\n\n$ shbin -h   # show full options\n```\n\n# How it works\n\nIt\nuses [Github API](https://docs.github.com/en/rest/repos/contents?apiVersion=2022-11-28#create-or-update-file-contents)\nto create or update files in the given repo. So there is no need to\nhave the target repository fully cloned locally.\n\n# Install\n\nThe recommended way is to use [uv](https://docs.astral.sh/uv/)\n\n```console\nuv tool install shbin \n```\n\nTo install the latest development version from the repository:\n\n```console\nuv tool install https://github.com/Shiphero/shbin/archive/refs/heads/main.zip\n```\n\n## OSX\n\nshbin depends on\n[python-magic](https://github.com/ahupp/python-magic#osx). This can be\ninstalled as follows.\n\n- When using Homebrew:\n\n```console\nbrew install libmagic\n```\n\n- When using macports:\n\n```console\nport install file\n```\n\n# Setup\n\nTo authenticate, simply run:\n```\nshbin init\n```\n\nThis command will guide you through creating a token and and selecting a repository, \nthen store them locally so that `shbin` can use them right away.\n\nAlternatively, you can **manually** create a  [new fine-grained personal token](https://github.com/settings/personal-access-tokens/new)\non Github restricted to your \"pastebin\" repository (under your user or\nyour organization's ownership), with **read and write** permission on **Contents**:\n\n![image](https://user-images.githubusercontent.com/2355719/238758491-9d15e7e6-e4b7-43c8-a321-b65c968fc7e0.png)\n\nThen set the environment variables:\n\n  ```\n  export SHBIN_GITHUB_TOKEN=\"\u003cyour personal token\u003e\"\n  export SHBIN_REPO=\"\u003cuser_or_org\u003e/\u003crepo\u003e\"   # example \"myorg/pastebin\"   \n  ```\n\n\nBy default `shbin` assigns a top-level folder to separate the content\nuploaded by each user. This can be changed using the `SHBIN_NAMESPACE`\nenvironment variable or the `--namespace` argument from the command\nline. For example:\n\n  - `export SHBIN_NAMESPACE=\"\"`        # no namespace\n  - `export SHBIN_NAMESPACE=\"pastebin_folder\"`  # the full pastebin is inside pastebin_folder/\"\n  - `export SHBIN_NAMESPACE=\"pastebin_folder/{user}\"`   # mix of both: each user has its own subfolder\n    inside `pastebin_folder/`\n\n\u003e [!NOTE] \n\u003e To interact with the clipboard, we use the library `pyclip`. This may require some additional system\n\u003e dependencies depending your operating system. See [these notes](https://github.com/spyoungtech/pyclip#platform-specific-notesissues).\n\u003e If you want to disable the automatic copying of the URL to the clipboard\n\u003e you can set the environment variable `SHBIN_COPY_URL=false` (or \"0\" or \"no\").\n\u003e\n\u003e This is useful in some Linux distributions that use Wayland as the call via `wl-copy`\n\u003e that `pyclip` uses in such environment can be slow.\n\nNice video courtesy of [tuterm](https://github.com/veracioux/tuterm), [asciinema](https://asciinema.org/) and [svg-term-cli](https://github.com/marionebl/svg-term-cli)\n\nPRs are welcome! \n\n\n","funding_links":[],"categories":["github-api","\u003ca name=\"transfer\"\u003e\u003c/a\u003eData transfer","Python"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FShiphero%2Fshbin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FShiphero%2Fshbin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FShiphero%2Fshbin/lists"}