Want to take your software engineering career to the next level? Join the mailing list for career tips & advice Click here


A module for creating github issue bots

Subscribe to updates I use haunt

Statistics on haunt

Number of watchers on Github 232
Number of open issues 9
Average time to close an issue 4 months
Main language JavaScript
Average time to merge a PR 1 day
Open pull requests 7+
Closed pull requests 3+
Last commit about 8 years ago
Repo Created over 8 years ago
Repo Last Updated over 2 years ago
Size 249 KB
Homepage fat.github.com/haunt
Organization / Authorfat
Page Updated
Do you use haunt? Leave a review!
View open issues (9)
View haunt activity
View on github
Book a Mock Interview With Me (Silicon Valley Engineering Leader, 100s of interviews conducted)
Software engineers: It's time to get promoted. Starting NOW! Subscribe to my mailing list and I will equip you with tools, tips and actionable advice to grow in your career.
Evaluating haunt for your project? Score Explanation
Commits Score (?)
Issues & PR Score (?)


What is it?

Haunt helps you keep your github issues under control. It does this by allowing you to run unit tests against github issues and pull-requests, then make contextual decisions about closing, sorting, tagging, and commenting.

How it's done?

Haunt pulls all open issues/pull-requests from your repo and gathers a bunch of data about them from github's api. It then runs a series of tests (which you define). Each test is provided a special haunt object which contains all the issue data as well as an api to act directly on the issue.

Real Life Examples

I run Haunt occasionally against bootstrap's issues/pull requests to keep them in order and to keep the ticketing process sane. Initially haunt closed 48 of 54 pull requests and about 65+ issues. It also tagged a number of issues as popular (accomplished with a small before filter which checks for +1 comments).

Here's a link to an actual pull request it closed. If you look at the bottom you can see that haunt made a comment explaining why the pull request was invalid, before closing it. Closing an issue of course is optional, we're just doing this in bootstrap to weed out people who file issues and never come back.

The tests I ran against bootstrap are literally the same that are in the examples dir of this repo. The only difference is i've named them .issue-guidlines.js in bootstrap.

Where to start?

You can use haunt from the command line or programatically.


To use Haunt from the command line, install like so:

$ npm install haunt -g

This will give you a haunt command you can use from terminal.

$ haunt

Running haunt with no arguments will output some simple cli documentation.


    haunt <test-path> <github-path>


    --stub     - (-s)      stubs the github api, so that requests aren't actually made to live github data
    --user     - (-u u:p)  specify a username and password for an account to make issue changes on behalf of
    --reporter - (-r Spec) specify a mocha reporter for test output formatting. If not specified, nothing will be output.


    $ haunt .issue_guidelines.js http://github.com/twitter/bootstrap

General Help:


To run some local tests against a remote repo, you might do something like this:

$ haunt ./path/to/my/local/tests.js http://github.com/my/repo

Note: haunt will prompt you for a username and password. Alternatively, you can specify them as an option by using the --user or -u flag. We use this to authenticate against the github api. All actions performed by your tests will be made on behalf of the authenticated user.

It's also worth noting that if you don't provide a local test file, haunt will look for a remote .issue-guidelines.js file in the root of the remote repo. This might look something like:

$ haunt http://github.com/my/repo
Programatic API

You may want to use the programatic api to build out a service, or something which routinely runs to keep your issues under control at a more consistent interval (like a bot).

To use haunt programmatically, just do something like:

var haunt = require('haunt');

haunt.auth('user', 'pass');
haunt.repo('http://github.com/my/repo', callback);

// haunt.repo also can take an options object.
// This can contain things like:
// + stub     - (boolean) stubs the github api write requests
// + tests    - (object)  a haunt test object
// + reporter - (object)  a mocha test reporter type

    repo: 'http://github.com/my/repo',
    tests: myTests,
    reporter: 'Landing',
    stub: true
}, callback);

Writing Tests

All haunt tests are assumed to be synchronous.

A basic haunt test file exports a single object with the two optional properties pull-request and issue. This looks something like this:

module.exports = {
    'pull-requests' : {  },
    'issues'        : {  }

Each optional object (pull-request and issue) should include a series of tests to be ran against the specified issue type. In addition to the tests you may also specify a before and after property. Before will be executed before all tests are ran, after will be executed after all tests have ran. All methods are passed a single argument which contains an interface into a github issue or pull-request.

A simple issue test file might look like this:

var assert = require('assert');

module.exports = {

    'issues': {

        'should be prefixed with the word bug': function (issue) {

        'after': function (issue) {

            if (issue.reporter.stats.failures) {




When testing issues, your function will be passed an object with the following properties:

  • issue.created_at - the created_at time of an issue
  • issue.updated_at - the updated_at time of an issue
  • issue.milestone - the assigned milestone of an issue
  • issue.assignee - the assignee of an issue
  • issue.labels - the labels for an issue
  • issue.number - the issue number
  • issue.title - the issue title
  • issue.body - the issue description body
  • issue.user - a user object for the person who filed an issue
  • issue.user.gravatar_id - a gravatar id for the user
  • issue.user.login - a user's github handle
  • issue.user.url - the url for a user's github page
  • issue.user.avatar_url - an avatar url
  • issue.user.id - a user's id number
  • issue.id - the issue's id
  • issue.comments - an array of github comment objects
  • issue.comments[x].created_at - the created_at time for a comment
  • issue.comments[x].updated_at - the updated_at time for a comment
  • issue.comments[x].user[*] - a user object for the person posting a comment (same properties as issue user obj)
  • issue.comments[x].body - the text body of a comment
  • issue.comments[x].id - the comment id
  • issue.comments[x].url - the permalink url for a particular comment

When testing pull-requests, your function will be passed an object with the following properties (in addition to all properties provided to a normal issue as specified above):

  • issue.diff - the complete diff of a pull-request
  • issue.files - an array of the files changed in a commit
  • issue.files[*].patch - the patch for a specific file
  • issue.files[*].filename - the filename changed
  • issue.files[*].status - the status of the file (modified, deleted, etc.)
  • issue.files[*].changes - the number of changes made in a file
  • issue.files[*].deletions - the number of deletions made in a file
  • issue.files[*].comments - an array of line comments on the file
  • issue.commits - an array of git commits
  • issue.commits[*].sha - the commit sha
  • issue.commits[*].commit - a commit object
  • issue.commits[*].commit.tree - a commit tree obj
  • issue.commits[*].commit.message - the commit message
  • issue.commits[*].commit.url - permalink for a given commit
  • issue.commits[*].author - a github user object for the committing author
  • issue.commits[*].committer - a github user object for the committer
  • issue.base - an object representing the branch the pull-request is being made into
  • issue.base.label - an object representing the branch the pull-request is being made into
  • issue.base.ref - the name of the branch being referenced
  • issue.base.sha - the sha
  • issue.base.user - the github user object who own the requesting repo
  • issue.base.repo - a github repo object
  • issue.head - an object representing the branch the the pull-request is being made from
  • issue.head.label - an object representing the branch the pull-request is being made into
  • issue.head.ref - the name of the branch being referenced
  • issue.head.sha - the sha
  • issue.head.user - the github user object who own the requesting repo
  • issue.head.repo - a github repo object

Before methods will be passed an object with the same properties as an issue/pull-request.


After methods will be passed an object with the same properties as an issue/pull-request, with the addition of a mocha reporter object:

  • issue.reporter.stats - a mocha stat object
  • issue.reporter.stats.tests - the number of tests run
  • issue.reporter.stats.passes - the number of tests passed
  • issue.reporter.stats.failures - the number of tests failed
  • issue.reporter.failures - an array of failed test object
  • issue.reporter.failures[*].title - the title of the failed test

The following convenience methods are made available on all haunt objects. You can call these at any time - though I recommend you only really use them in after methods.

  • issue.tag - (accepts a tagname) tags an issue/pull-request
  • issue.close - closes an issue/pull-request
  • issue.assign - (accepts a username) assigns an issue/pull-request
  • issue.comment - (accepts a string) comments on an issue/pull-request
  • issue.files[*].comment - (accepts an comment and line number) comment on a given line number in a diff of a pull-request
  • issue.files[].comments[].reply - (accepts a string) reply to a comment in a diff on a pull request
  • issue.reportFailures - generic test failure message, which notifies a user what failed based on mocha reporter.
haunt open issues Ask a question     (View All Issues)
  • about 8 years Accidental "spamming" of bootstrap
haunt open pull requests (View All Pulls)
  • Fix a typo
  • Fix getDiff 404 if private repo
  • add support for multiple test structures
  • Launch callback at process end
  • Add http proxy support
  • Made a little more friendly and encouraging
  • Ignore runtime errors and only fail on assertion errors
haunt questions on Stackoverflow (View All Questions)
  • Is using setattr to set a simple attribute in a content-type in Plone a bad practice (I mean, is it going to haunt me in the future)?
  • Alert box goes away on cancel but comes back again to haunt?
  • Killing a process leaves zombie process to haunt me... :(
  • Will treating MKCoordinateRegion like a rectangle come back to haunt me?
haunt list of languages used
Other projects in JavaScript
Powered by Autocode - Instant Webhooks, Scripts and APIs
Autocode logo wordmark