Git frontend CGI script for Gemini
Merge branch 'cache' and add dep declaration
Fix _generate_header calls
Fix source code URl in index



You can also use your local clone with git send-email.

#git.gmi - git frontend CGI script


At this point (i.e. 6a98cf0: View commit) I consider git.gmi feature-complete, tagged v0.4.0. Unless necessary, no new features will be integrated into git.gmi, including new views and new functional paths (/commit, /ref, etc). From now on, over an indefinite period, changes will mainly be enhancements and optimizations.

#Front Matter

You may find it strange how I wrote a CGI script when there are so many amazing things available, and you're right. Git.gmi isn't meant to be a CGI script; it had to be one. The only Gemini server library I know in Python, Jetforce, is licensed under the Floodgap "Free" Software License, which is free software but well, free as in beer. I find absolutely no reason to allow proprietization but prohibit monetization, which is the exact opposite from the GPL - unfortunately the license of choice by the pygit2 devs. So here we are, locked in restrictions of both fundamental dependencies that don't get along with each other. I once comtemplated violating FFSL, before coming up with this workaround, i.e. CGI. Git.gmi is licensed under GPLv2 eventually.

The CGI script, cgi.py, prints output to stdout as response to the user, the one thing I'm uncomfortable with because it disables the One True Debugger. As an extra workaround, I just used raise Exception('debug message') everywhere (but deleted all of them before committing, ofc).

It's in the MVP stage, with the ability to view summary, trees, blobs, and commit log in a primitive way. There is a test instance at gemini://fkfd.me/git/cgi.py/.



  • relatively new version of Python (3.8.3 personally)
  • pygit2 (pip install pygit2)
  • hurry.filesize (pip install hurry.filesize)
  • dateutil (pip install python-dateutil)
  • a gemini server capable of serving CGI

You need to edit the shebang of git-gmi/cgi:

# change this:
# to the path to your python executable as a shebang
import gateway

also stuff in const.py:

GIT_CATALOG = "/home/fakefred/p/gemini/repos/" # dir where your repos are placed
CGI_PATH = "/git/cgi/" # path after the host part of URL that invokes the CGI script
# for example, gemini://fkfd.me/git/cgi/ is the entrance URL, hence /git/cgi/
GIT_GMI_SITE_TITLE = "git.gmi demo instance" # whatever you want
# ...

Let's suppose you put your Gemini static files in /path/to/gemini/. Clone git.gmi to /path/to/git.gmi/. Then, symlink the git-gmi subdir to /path/to/gemini/git/.

$ cd /path/to
$ git clone https://git.sr.ht/~fkfd/git.gmi
$ ln -s /path/to/git.gmi/git-gmi gemini/git`
$ ls gemini/git # this is your cgi-bin dir
cgi  const.py  gateway.py  git.py

Then, if you use Jetforce, run:

$ jetforce --dir /path/to/gemini --cgi-dir git [other arguments]

Access your instance at gemini://your-domain-or-ip/git/cgi/. Don't forget the trailing slash, because jetforce is not capable of telling git.gmi its existence, potentially messing up relative links.

#Licensing's a Bitch

hurry.filesize is licensed under ZPL-2.0. I'm obligated, on ZPL-2.0's terms, to include it. I am once again asking begging you to use permissive licenses like a normal human being.


The mailing list is ~fkfd/gemini@lists.sr.ht. Send patches (git-send-email) and feedback to the list.