I'd like to share a little command-line utility I wrote for managing multi-file and multi-directory private gists on GitHub. If you're not familiar with GitHub Gist, it's basically a git-backed pastebin. One of the benefits of Gist is that it supports private gists for free, allowing you to create private repos for your code snippets. To prevent abuse, GitHub does not allow you to create gists containing subdirectories.

I like to keep my list of public GitHub repositories very tidy, so I frequently use Gists for smaller projects. Last week I wanted to share the code for the note-taking app I blogged about. I didn't want to put the code into a GitHub repo, so I decided to create a gist. Unfortunately, the project contained templates and javascript that needed to go in subdirectories. To work around Gist's subdirectory restriction I used a naming convention to indicate that these files belonged in subdirectories, e.g.:

/templates/homepage.html -> templates.homepage.html

/static/js/notes.js -> statis.js.notes.js

Then I had a lightbulb moment -- why not write a script to do all this automatically?

Jist

jist is a small ~200 line python script that makes it easy to create and manage private gists. It works by flattening sub-directories before pushing to GitHub, then re-expanding them afterwards. jist supports three primary operations: init, push and clone.

How you might use it

Let's say we have a project in a directory named app. Inside the app directory are folders containing templates, static assets, source code, and more. To create a private gist containing all these files we would simply run:

jist will flatten the files, push them to a new gist, then restore the files to their original structure. Later we make some improvements and want to update the gist. To do this, we use jist push:

$cdapp/# make some changes...$jistpush

Again, jist will flatten the files, commit and push to our private Gist, then restore the files to their original structure.

Suppose a friend wants to checkout our code. We would share the gist's ID with them and they would clone our gist using jist clone:

$jistclone<gistid>

This would clone the repo and expand the flattened files into their appropriate strucutre.

jist help

While init, push and clone are the porcelain, there are also some plumbing commands available for doing things like flattening, expanding, etc. For all the details, just run jist help.

SSH Keys

In order to create new Gists you will need to add your public SSH key to GitHub (if you haven't already). To do this navigate to the account details page (the wrench/screwdriver icon), select SSH Keys and upload your public key:

Creating a personal access token

In order to be able to create new gists from the command-line, we need to use an API token. GitHub makes this very easy to do, so I will walk you through the steps.

First log in to your github account and click the wrench/screwdriver icon to navigate to your account settings. In the account settings page, click the Applications tab on the left-hand navigation. Then select the Generate new token button:

You will come to a page where you can configure permissions for your new API token. For our purposes we only need permission to create gists, so select the Gist checkbox:

Give your new token a name and save. You will be taken to a page where you can copy your new token. Do not lose this token since this is the only time you will be able to view it:

Configuring the API token

You can pass your token into jist using command line arguments:

jist-umyusername-kthetoken<command>

Because entering these values can get very repetitive, jist will also read these values from your global git config. To add these values to your gitconfig file, run the following commands:

Thanks for your comment Sam. I have a bitbucket account but I just haven't gotten around to actually using it, even though, as you mentioned, they give you unlimited free private repos. Maybe I'll give it a try!