gitit: a Haskell wiki that keeps its pages in a version control repository
A wiki using HAppS, pandoc, and git
At a glance
- What is it?
- A wiki built on Happstack and pandoc where every page is a file in a git, darcs or Mercurial repository, so edits, diffs and history come for free.
- Who is it for?
- gitit is a good fit for exactly the kind of wiki where history is a feature rather than a bolt-on, because a page edit and a commit are the same operation. The trade is the Haskell toolchain: there is no prebuilt binary in the README, and installing it means stack or cabal plus a working pandoc, which is a higher bar than most wiki users will accept.
- Can I use it commercially?
- Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
- Is it still maintained?
- Yes. The repository last received commits 36 days ago.
- What is it written in?
- Mainly Haskell, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Every page is a file, which is the entire design
The description in the README is one sentence: a wiki program written in Haskell that uses Happstack for the web server and pandoc for markup processing, with pages and uploaded files stored in a git, darcs or Mercurial repository. That last clause is the interesting one. Gitit is not a wiki with an export button. It is a wiki whose storage layer is a version control repository, and edits go through a commit.
The practical consequences are immediate. You can clone the wiki and edit pages with the command-line tools of whichever VCS you chose, and the wiki picks up the changes. You get diffs, history, blame, branches and merges for free. You also get the constraint that comes with it: two people editing the same page at once means a merge conflict, and gitit inherits whatever merge experience its users already have.
The project is GPL-2.0 licensed, has 2,277 stars and 231 forks, and the last push was 2026-08-31. Open issues sit at 206, which is a large number relative to the star count and worth reading as a signal about where a prospective user would spend their time. There are no GitHub releases at all, so version tracking happens through tags rather than published artefacts.
Installing means committing to a Haskell toolchain
The README calls the stack route the most reliable one, and the three commands are short:
git clone https://github.com/jgm/gitit
cd gitit
stack installThe alternative is a Haskell Platform installation with `cabal update` followed by `cabal install gitit`, which installs the latest released version; running `cabal install` inside a checked-out directory builds that checkout instead. Verification is `gitit --version`, and if the command is not found the README's next suggestion is to check that the cabal executable directory, usually `~/.cabal/bin`, is on the path.
Either way you need `git` in your system path, or `darcs` or `hg` if you have chosen one of the other two backends. There is a source checkout with a `Makefile` at the root that calls `cabal v2-configure` with plugins enabled and `cabal v2-build`, and a `cabal.project` alongside a `stack.yaml` for the two build paths the project supports.
This is the real adoption cost of gitit and it is worth being blunt about. A reader who wants a wiki this afternoon will not get one from these instructions. A reader who already has Haskell tooling, or who is setting up a documentation site for a project that already lives in git, is in the target audience.
Starting a server on port 5001 with three directories created for you
Running it is a single command, and the README is specific about the working directory requirement: switch to a directory where you have write access, because gitit creates three directories and two files there.
gititOn first run it creates a git repository named `wikidata` with a default front page, a `static` directory for files served as-is, a `templates` directory holding HStringTemplate templates for wiki pages, and the files `gitit-users` and `gitit.log`. It then starts a web server on port 5001, and the README tells you to open `http://localhost:5001` to confirm.
The port is changeable with `gitit -p 4000`, and `gitit -h` lists the rest of the runtime options. The absence of a configuration file is fine on a first run, which is a deliberate choice: the defaults produce a working wiki with a repository, a static directory and templates without any setup file existing on disk.
Two operational notes from the README deserve repeating. Page files are assumed to be UTF-8 encoded, including page names where the filesystem allows it, so the process needs to run under a UTF-8 locale. And because gitit writes into its working directory, running two instances against the same directory is not something the documentation suggests doing.
Per-page metadata blocks for format, categories and titles
The feature that makes gitit more than a git-backed wiki is the per-page metadata block. A page can open with a YAML document delimited by `---` and `...`, and the README gives this example:
---
format: latex+lhs
categories: haskell math
toc: no
title: Haskell and
Category Theory
...
+The value of a key can continue on following lines provided they start with a space, which is what makes the multi-line `title` above legal. The README also notes the document must be valid YAML, while warning that not every valid YAML document is a valid metadata block.
Four keys are documented. `format` overrides the configured page type for that page, accepting markdown, rst, latex, html and their `+lhs` literate variants, with capitalization ignored. `categories` takes a space or comma separated list. `toc` overrides the table-of-contents setting, accepting yes, no, true or false. `title` replaces the page name as the displayed title, which is how you get something readable instead of a slug.
This is a better answer than a global setting because it lets one wiki hold LaTeX with embedded literate Haskell next to markdown, without a separate repository for each format.
Wikilinks, plugins and the embedded library
Gitit treats a link with an empty URL as a wikilink, which gives you two spellings depending on the markup. In markdown, `[Front Page]()` links to the page named Front Page; in reStructuredText, the equivalent is a backtick-quoted `Front Page <>`_. A trailing slash targets a directory listing instead, so `[foo/bar/]()` links to the listing for that subdirectory.
The plugin system is the part that makes the wiki extensible in a way most wiki software is not. Plugins are dynamically loaded page transformations written in Haskell, described through the `Network.Gitit.Interface` module, and the repository has a `plugins/` directory to match. Because the interface is a Haskell module, a plugin is an ordinary Haskell library that happens to run inside the wiki process.
The README also advertises `Network.Gitit` as a library that makes it simple to include a gitit wiki inside any Happstack application, which is the escape hatch for people who want the wiki as a component rather than a server. Around that sit caching, site-wide and per-page Atom feeds, syntax highlighting through skylighting, and TeX math rendering through texmath.
Two cautions. The skylighting integration depends on how your pandoc was compiled, and the README's way of checking is to run `pandoc -v` and look at what the build supports. And Haskell plugins mean a plugin bug is a wiki bug, in the same process.
Configuration as generated, documented files rather than a wiki admin screen
Configuration is file-based, and the README's advice is to generate the default file and edit that rather than writing one from scratch:
gitit --print-default-config > my.confYou point gitit at it with `gitit -f my.conf`, and the option can be repeated so configuration can be split across files. The README gives the concrete reason: keeping the sensible part of a configuration outside a repository, an OAuth client secret for instance, in a file that never gets committed. Configuration layered from several files is how you keep secrets out of the wiki's history without giving up versioned settings.
The other editable pieces live on disk next to the repository. The `templates/` directory holds HStringTemplate templates, so a wiki's visual identity is changed by editing templates rather than through a theme picker. The `static/` directory holds files served directly. The root of the checkout also contains a few artifacts that show the project's history: `HCAR-gitit.tex`, which is the Haskell Conference Academic Report paper, plus `BLUETRIP-LICENSE`, `YUI-LICENSE` and a `TANGOICONS` directory, all of them there because vendored components carry their own licences.
The README itself ends by pointing at the default configuration file being documented with comments, which is the intended path for learning the option set. Beyond that, the wiki documentation for page editing is delegated to a built-in Help page rather than duplicated in the README.
Editorial conclusion
gitit is a good fit for exactly the kind of wiki where history is a feature rather than a bolt-on, because a page edit and a commit are the same operation. The trade is the Haskell toolchain: there is no prebuilt binary in the README, and installing it means stack or cabal plus a working pandoc, which is a higher bar than most wiki users will accept. If you get past that, the payoff is a wiki with real diffs, plugin hooks written in Haskell, pandoc's full range of markup formats and per-page metadata. The fastest path is `gitit --print-default-config` into a file you can edit, because the generated config is documented inline and the README only summarises it.
Frequently asked questions
What backend can gitit store its pages in?
Pages and uploaded files live in a git, darcs or Mercurial repository, chosen by which command-line tool you put on your path. The default is git, and the other two are supported by running gitit with darcs or hg available instead.
Do I need pandoc installed separately to use gitit?
Pandoc is where markup processing happens, and gitit pulls it in through the Haskell build rather than shelling out to a system install. That does mean the build needs a working Haskell toolchain, whether that is stack or a cabal-based Haskell Platform setup.
Can I edit gitit pages outside the browser?
Yes. The repository behind the wiki is an ordinary version control checkout, so you can clone it and edit page files with the standard command-line tools of your VCS, and the wiki will serve the updated content. Merges and conflicts behave the way your version control tool normally does.
How do I change a single page's markup format in gitit?
Add a metadata block at the top of the page with a `format` key. Values include markdown, rst, latex, html and their `+lhs` literate variants, and capitalization is ignored. Without the key the page uses whatever the configuration file sets as the default.
What can gitit plugins do?
Plugins are dynamically loaded page transformations written in Haskell against the `Network.Gitit.Interface` module, so they run inside the wiki process and can rewrite pages however they like. The repository ships a `plugins/` directory, and the plugin build path is enabled in the root Makefile.
Which port does gitit serve on by default?
Port 5001, and the README tells you to open `http://localhost:5001` after the first run to confirm it worked. The port is changed with `gitit -p 4000` or any other value, and `gitit -h` lists the remaining runtime options.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/jgm-gitit)