Sometimes you start coding something and you don’t yet realize if it will be a project worth sharing on github. We don’t always think about this as we begin coding. This is a write up on how to deal with the time you code something up, and then – after awhile – you realize you want to share it. This method, also works for creating fresh new repos that you haven’t started coding yet.

Of course the normal practice is to create a github repo from the browser and then follow the code to git init it.

Thats all fine and nice, but its time consuming to open up the browser and create the github repo. Luckily, we can do it using the github api.

First you need to get a github API key. Then using curl you can send a command to github to create your repo for you. There are many settings you can tweak. Specifically for us we want the basic; public repo without any commits or files (no README.md files).

Step 1 – Create API Token

First you have to create an authentication token – personal token:

  • Login to github.com on your browser
  • Go to Settings -> Developer settings -> Create Personal Access Token
  • Hit Generate button
  • In the note textbox, write its purpose. ex: “creating repos from command line
  • Then give it proper access in the scopes:
    • Check on everything in the repo section
    • Check on gist
  • That is it. When you submit this info, it will give you an access token (long alphanumeric string)
  • Save that access token string. We will be using it in our curl commands. This token is the equivalent of providing a username and password (so don’t lose it and dont share it)

Step 2 – Command Line

After you get your key you can now use it in the shell. For example’s sake we use abc123 as the key (your key will have more characters).

Here is how it will look like in your workflow:

  • First, create directory and code some stuff
  • Realize you are making a repo
  • git init the repo. That only saves it locally
  • Make a commit
  • Now create the github repo using curl command. Note we set auto_init to false (by default its true) so that it doesn’t create a first commit with a template README.md file. Also, we make it a public repo, so we set private to true.
    • Change abc123 to your authorization token alphanumeric value
    • Change REPONAME to your repo name. Only use these chars alphabet, number, dot, underscore and minux: A-Za-z0-9_. -.
curl -H "Authorization: token abc123" https://api.github.com/user/repos -d '{"name":"REPONAME","auto_init": false, "private": false}'
  • Then set the git origin, which is the remote repository server and repo. Make sure to use the https://github.com/USERNAME/REPONAME.git link; If you use wrong link remove with git remote remove origin. This link is seen in the curl output (look for “clone_url“)
    • Change USERNAME to your github username and REPONAME to your reponame
git remote add origin https://github.com/USERNAME/REPONAME.git
  • set the branch (master or main) to upstream and push
git push --set-upstream origin master

More Info:

  • More information on github api. Such as more options to pass in the json string with the -d argument to affect the type of repo that gets created: https://developer.github.com/v3/repos/#create-a-repository-for-the-authenticated-user
  • The simplest form of this call curl -H "Authorization: token abc123" https://api.github.com/user/repos -d '{"name":"REPONAME"}' would create a repo that has an initial commit. However, for a fluid work process we don’t want that, so we add the option auto_init: false (if not provided; this option is set to true). Also we set private to false, so that we get a public repo.
  • Previously, you could use the api without a token using your username and password; that has been deprecated out as its unsafe. the commands looked like this: curl -u user:pass https://api.github.com/user/repos -d '{"name":"REPONAME"}'

Making an alias for easier use

It might be annoying to always type those long commands. So you can write an alias and stick it in your .bashrc or .bashprofile. However, that alias is really long. I prefer to create an environment function – it’s a bash function that can be called from the shell; it’s just a regular bash function that was created in the shell instead of in a script.

Here is what I have in my bashrc/bashprofile:

# --- CREATE PUBLIC GIT REPO ALIAS AND FUNCTION --- #

# Comment the ALIAS you don't need. Only keep one alias and the function.

# ALIAS 1 - place auth token into GITHUB_API_KEY var
unalias CreateGitRepo 2> /dev/null; alias CreateGitRepo="GITHUB_API_KEY=abc123 create-git-repo-function"

# ALIAS 2 - place auth token into ~/.github-api-key file (1 line file)
unalias CreateGitRepo 2> /dev/null; alias CreateGitRepo="GITHUB_API_KEY=$(cat ~/.github-api-key | head -1) create-git-repo-function"

# FUNCTION
unset -f create-git-repo-function 2> /dev/null || unfunction create-git-repo-function 2> /dev/null;
create-git-repo-function () ( 
	[ -z $1 ] && { echo -e "ERROR: missing repo name.\nexample 1: # GITHUB_API_KEY=abc123 create-git-repo-function \nexample 2: # CreateGitRepo "; exit 1; }
    [ -z $GITHUB_API_KEY ] && { echo -e "ERROR: GITHUB_API_KEY environment variable not set.\nSet it with your github token.\nex: # export GITHUB_API_KEY=abc123"; }
    # GITHUB_API_KEY is environment variable
    OUT=$(curl -H "Authorization: token $GITHUB_API_KEY" https://api.github.com/user/repos -d '{"name":"'"$1"'","auto_init": false, "private": false}')
    CLONE_URL=$(echo "$OUT" | grep -o '"clone_url"[^:"]*:[^:"]*"[^"]*"' | cut -f4 -d'"')
    echo "$OUT"
    [ -z $CLONE_URL ] && ( echo "- clone_url not detected; perhaps api failed. investigate.";
    ) || (
    echo "- If you already init your directory and made a commit. You can push it with:";
    echo "git remote add origin $CLONE_URL";
    echo "git push --set-upstream origin master"; ); exit 0; )

Don’t forget to comment out whichever alias function you don’t want to use (ALIAS 1 or ALIAS 2). I personally use ALIAS 1 as I don’t like having extra files).

For ALIAS 1, don’t forget to put the Auth Token in the variable, thus replacing abc123.

For ALIAS 2, don’t forget to create file ~/.github-api-key with your key: echo "abc123" > ~/.github-api-key

If you just created the script don’t forget to source your .bashrc or .bashprofile (or whichever file you put the script in): source ~/.bashrc

Using the Alias / Function on the Go

Now finally you can use like this – just an example (you can use it other ways – like you can start with the CreateGitRepo command):

  • Create a directory Project1:
    mkdir Project1
  • Change into the dir:
    cd Project1
  • Code some stuff up:
    echo "somecode" > wow.js
  • Initialize the local git repo in the current dir:
    git init
  • Stage the current files (wow.js):
    git add .
  • Commit the staged to the local repo with a descriptive comment:
    git commit -m "wow.js has been created"
  • Now create the empty public remote repo (in otherwords create the repo on github):
    CreateGitRepo Project1
  • This will show you a lot of lines output if all worked correct.
  • So far the repo has been created but the code has not been pushed to it yet. the final 2 lines of CreateGitRepo command help you with the final 2 commands to set origin and push the code to github. for this example those 2 commands would look like this:
# git remote add origin https://github.com/bhbmaster/REPONAME.git
# git push --set-upstream origin master

Create Private Git Repo

After using this function a bit, I realized having a private repo creator is just as useful. Here is the same alias and function made for private. The alias and function have an extra suffix to differentiate them. Copy and paste into your .bashrc or .zshrc.

# --- CREATE PRIVATE GIT REPO ALIAS AND FUNCTION --- #

# Comment the ALIAS you don't need. Only keep one alias and the function.

# ALIAS 1 - place auth token into GITHUB_API_KEY var
unalias CreateGitRepoPr 2> /dev/null; alias CreateGitRepoPr="GITHUB_API_KEY=abc123 create-git-repo-function-pr"

# ALIAS 2 - place auth token into ~/.github-api-key file (1 line file)
unalias CreateGitRepoPr 2> /dev/null; alias CreateGitRepoPr="GITHUB_API_KEY=$(cat ~/.github-api-key | head -1) create-git-repo-function-pr"

# FUNCTION
unset -f create-git-repo-function-pr 2> /dev/null || unfunction create-git-repo-function-pr 2> /dev/null;
create-git-repo-function-pr () ( 
	[ -z $1 ] && { echo -e "ERROR: missing repo name.\nexample 1: # GITHUB_API_KEY=abc123 create-git-repo-function-pr \nexample 2: # CreateGitRepo "; exit 1; }
    [ -z $GITHUB_API_KEY ] && { echo -e "ERROR: GITHUB_API_KEY environment variable not set.\nSet it with your github token.\nex: # export GITHUB_API_KEY=abc123"; }
    # GITHUB_API_KEY is environment variable
    OUT=$(curl -H "Authorization: token $GITHUB_API_KEY" https://api.github.com/user/repos -d '{"name":"'"$1"'","auto_init": false, "private": true}')
    CLONE_URL=$(echo "$OUT" | grep -o '"clone_url"[^:"]*:[^:"]*"[^"]*"' | cut -f4 -d'"')
    echo "$OUT"
    [ -z $CLONE_URL ] && ( echo "- clone_url not detected; perhaps api failed. investigate.";
    ) || (
    echo "- If you already init your directory and made a commit. You can push it with:";
    echo "git remote add origin $CLONE_URL";
    echo "git push --set-upstream origin master"; ); exit 0; )

Final Thoughts

All of these commands create a public repo. You can modify that by setting private to true (change "private": false to "private": true). If you want you can even create your own function for that.

The end

2 thoughts on “Create Github Repo On The Go From The Shell – Github API

  1. The UI for Issues on GitHub aims to provide ‘just enough’ workflow while staying out of your way. With the GitHub Issues API, you can pull data out or create issues from other tools to create a workflow that works for your team.

  2. @Amruth-Smaragdine I tried to create a repo using Microsoft Windows command line I got the same JSON error like you mentioned (see the attached image). I tried with

Leave a Reply

Your email address will not be published. Required fields are marked *