# bugwarrior: pulling GitHub, Jira and Trac tickets into taskwarrior

> bugwarrior is a command line utility that updates a local taskwarrior database from issue trackers, with twenty-five supported services behind one configuration format. It ships as a set of small console scripts, keeps heavyweight tracker clients in optional extras, and is licensed GPL-3.0-or-later.

**GothenburgBitFactory/bugwarrior** — Pull github, bitbucket, and trac issues into taskwarrior

- Repository: https://github.com/GothenburgBitFactory/bugwarrior
- Website: http://pypi.python.org/pypi/bugwarrior
- Stars: 822 · Forks: 225
- Language: Python
- License: GPL-3.0
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/gothenburgbitfactory-bugwarrior

## One list of work instead of one per forge

bugwarrior is a command line utility for updating your local taskwarrior database from your forge issue trackers. That is the whole idea in one sentence, and the reason it exists is that developers accumulate trackers.

A single person can have a GitHub issue for a library, a GitLab issue for a service, a Jira ticket at work and a Trac instance for something older. Each has its own inbox, its own notion of what is open, and its own idea of what a priority means. taskwarrior is the local list where the work actually lives. bugwarrior is the bridge that pulls the remote items into it.

The scale of the supported set is the first thing worth noting. The documented list runs to twenty-five remote resources: Azure DevOps, Bitbucket, Bugzilla, ClickUp, the Debian Bug Tracking System, Gerrit, Git-Bug, Github, Gitlab, Gmail, Jira, Kanboard, Logseq, Nextcloud Deck, Pagure, Phabricator, Pivotal Tracker, Linear, Redmine, Taiga, Teamwork Projects, Todoist, Trac, Trello and YouTrack.

That list is not only forges. Gmail and Todoist and Logseq are in there too, which tells you the model is really about pulling anything with a remote item list into taskwarrior rather than about bug trackers specifically.

The primary language is Python, the licence is GPL-3.0-or-later, and the project is published on PyPI. The default branch is develop, and the README states that the CI badge tracks that branch, which is a hint that develop is where the work happens.

## Console scripts for pull, vault and more

The packaging installs several entry points rather than a single binary, and the names suggest the division of labour:

```toml
[project.scripts]
bugwarrior = "bugwarrior:cli"
bugwarrior-pull = "bugwarrior:pull"
bugwarrior-vault = "bugwarrior:vault"
```

The main bugwarrior command is the full command line interface, bugwarrior-pull is the entry point aimed at a scheduled, pull oriented run, and bugwarrior-vault handles credentials. The project file also lists a fourth script, bugwarrior-uda.

Splitting pull out from the general command matters for how you would run this in production. A sync job wants one predictable, non-interactive operation that updates the local database and exits, and having a separate entry point for it means you do not have to guess which flags make the main command non-interactive. The vault entry point exists because the services it talks to need credentials, and those credentials have to come from somewhere the user controls rather than from a configuration file committed to a repository.

The documentation for all of this lives on Read the Docs, at bugwarrior.readthedocs.io, with the stable version linked from the project metadata. The repository also ships a README.rst that acts as the long description on PyPI, so the package landing page and the project page are the same document.

## Heavy tracker clients live in optional extras

The dependency list is a good description of how the tool is put together, and it is deliberately split.

```toml
dependencies = [
  "click",
  "dogpile.cache>=0.5.3",
  "jinja2>=2.7.2",
  "filelock>=3",
  "pydantic[email]>=2",
  "python-dateutil",
  "requests>=1",
```

Those are the core dependencies: click for the command line, jinja2 for templating the task text, pydantic for parsing and validating configuration, python-dateutil for date handling, requests for HTTP, dogpile.cache for caching API responses, and filelock so that two concurrent runs cannot fight over the taskwarrior database.

The tracker specific libraries are all optional extras. There is bts for the Debian tracker, bugzilla for python-bugzilla, gmail for the Google API client and OAuth libraries, ini2toml for reading legacy INI configuration, jira, kanboard, keyring for credential storage, phabricator, todoist and trac. And there is a convenient aggregate:

```toml
all = ["bugwarrior[bts,bugzilla,gmail,ini2toml,jira,kanboard,keyring,phabricator,todoist,trac]"]
```

The practical effect is that a person who only tracks issues on GitHub installs a much smaller dependency tree than someone who needs Bugzilla, Jira and Gmail all at once.

One entry in the core list is a small piece of housekeeping with an explanation attached. setuptools is listed as a runtime dependency with a comment saying it is needed at runtime because phabricator and ini2toml import pkg_resources, which is no longer bundled in virtual environments since Python 3.12, with an issue reference. That is the kind of comment that saves somebody an afternoon.

The taskwarrior side is handled by the taskw client, required at 0.8 or newer.

## Caching, locking and templating: how a sync actually behaves

Three dependencies explain most of the observable behaviour of a bugwarrior run, and they are worth understanding before you configure it.

dogpile.cache is the caching layer. Without it, every run would query every tracker for every item, which is slow and rude to the APIs. With it, a run can reuse recent responses, which matters most for the large trackers where the request count is high.

filelock is the concurrency guard. Taskwarrior's database is a local file, and two bugwarrior processes writing to it at the same time would corrupt it or lose updates. The lock makes the second process wait. If you plan to run bugwarrior from a timer and also trigger it by hand, this is the piece that keeps the two apart.

jinja2 is the templating layer, and it is what turns a tracker item into a task. The fields of a GitHub issue, a Jira ticket and a Trac ticket have different names and different shapes, and the mapping onto taskwarrior's fields is expressed as templates rather than as code. That is the mechanism behind the project's central claim, that you can hand a query string to your models, or in this case configure one mapping and get consistent tasks out of many trackers.

pydantic with the email extra is what validates that configuration. A tracker entry with a malformed field, or a missing required key, fails at configuration load time rather than halfway through a sync, which is the difference between a clear error message and a partially updated database.

## Writing per-tracker clients yourself is the alternative

The obvious alternative to bugwarrior is to skip it and use the tracker client libraries directly. Those libraries are right there in the dependency list: python-bugzilla, jira, phabricator, todoist_api_python, offtrac, python-debianbts, kanboard and the Google API client for Gmail.

The difference in approach is real. Using those clients directly means writing a small program per tracker, or one program with a branch per tracker, and each of those programs has to decide the same set of questions: which fields to pull, how to map a tracker status onto a taskwarrior status, what to do about labels and assignees, how to build a description, and how to avoid re-adding an item you already have.

bugwarrior answers those questions once, in a configuration format, and the client library per tracker becomes an implementation detail behind a uniform interface. When you add a second tracker, you write another configuration section rather than another program.

The cost of that approach is that the mapping becomes configuration rather than code, which has consequences. It is easier to change and easier to get wrong, and a subtle mistake in a template produces wrong tasks rather than an error. It is also why the project needs caching and locking: the configuration model encourages frequent, scheduled runs over one-off scripts.

The other side of the comparison is that taskwarrior itself remains the centre. bugwarrior is a database updater, not a tracker of record, and the topics attached to the repository, taskwarrior2 and taskwarrior3, show that the two supported generations of taskwarrior are both in scope.

## Version 2.x, beta status and a GPL licence

The release history shows a project that made a clean break and has been tidying up since.

Version 2.0.0 was released on 2025-11-26 and version 2.1.0 on 2026-01-11, and the version recorded in the project file is 2.1.0.post, which is the packaging convention for a post release build of 2.1.0. The repository's default branch is develop rather than master, and the build badge in the documentation points at the develop branch, so the branch names say something about how the project works: master is presumably the stable line and develop is where changes land first.

The last push to the repository was on 2026-08-27, which is inside the six month window in which the project can be described as receiving work. The project classifies itself as Development Status 4, Beta, which is the project's own assessment of where it is and is worth taking at face value: it is usable, and it is not finished.

The licence is GPL-3.0-or-later, with the licence file at the root of the repository and declared in the project metadata as GPL-3.0-or-later. For a tool that runs on your own machine against your own accounts, that is not usually a blocker. For a team that wants to bundle it into a product or a service, the copyleft terms are a question for your counsel, and that is a note on the terms rather than legal advice.

Python support is 3.11 and newer, with classifiers for 3.11 through 3.14, and the dependency set has already been adjusted for the packaging changes in Python 3.12 as the setuptools comment shows.

## Conclusion

bugwarrior suits a developer who wants one list of open work instead of one per forge, and who already lives in taskwarrior and is willing to write the configuration that maps tracker fields onto task fields. It is the wrong choice for a team whose trackers already have a good triage board, and the wrong choice if you need two-way sync with status written back to the tracker, since the documentation excerpt describes a pull into the local database. Verify three things before you commit: that the tracker you use has an optional extra or a working client behind it, that the field mapping in your configuration produces tasks you can actually work from, and that the taskwarrior version you run is one the taskw client at 0.8 or newer supports.

## FAQ

### What does bugwarrior do?

It is a command line utility that updates your local taskwarrior database from your issue trackers, so open items from several forges end up in one task list. The project is published on PyPI and its documentation is on Read the Docs.

### Which issue trackers does bugwarrior support?

The documented list covers Azure DevOps, Bitbucket, Bugzilla, ClickUp, the Debian Bug Tracking System, Gerrit, Git-Bug, Github, Gitlab, Gmail, Jira, Kanboard, Logseq, Nextcloud Deck, Pagure, Phabricator, Pivotal Tracker, Linear, Redmine, Taiga, Teamwork Projects, Todoist, Trac, Trello and YouTrack.

### Do I need to install extra packages for a tracker?

Yes, the tracker specific clients are optional extras, such as bugzilla, jira, phabricator, todoist, trac, bts, gmail and kanboard, and there is an all extra that pulls in the full set at once. The core install carries only click, jinja2, pydantic, requests, dogpile.cache, filelock, python-dateutil, setuptools and the taskw client.

### Which commands does the bugwarrior package install?

The project scripts list bugwarrior for the command line interface, bugwarrior-pull for pulling updates, bugwarrior-vault for credentials, and a further entry named bugwarrior-uda.

### Which Python versions and taskwarrior client does bugwarrior support?

The package requires Python 3.11 or newer and carries classifiers for 3.11 through 3.14. Communication with taskwarrior goes through the taskw client, which is required at version 0.8 or newer, and the repository topics name both taskwarrior2 and taskwarrior3.

### What licence is bugwarrior released under?

GPL-3.0-or-later, declared in the project metadata with the licence file at the root of the repository. The project is classified as Development Status 4, Beta, with the most recent releases being 2.0.0 in November 2025 and 2.1.0 in January 2026.

## Sources

- [GothenburgBitFactory/bugwarrior on GitHub](https://github.com/GothenburgBitFactory/bugwarrior)
- [License: GPL-3.0](https://github.com/GothenburgBitFactory/bugwarrior/blob/develop/LICENSE)
- [Project website](http://pypi.python.org/pypi/bugwarrior)
- [README](https://github.com/GothenburgBitFactory/bugwarrior/blob/develop/README.md)
- [Releases](https://github.com/GothenburgBitFactory/bugwarrior/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gothenburgbitfactory-bugwarrior
