Email in and out, two-way issue mirroring with GitHub and GitLab, SSRF-guarded webhooks, a built-in MCP server, SCIM provisioning, Jira import that carries comments and work logs, and configuration transfer that never deletes anything.
Three directions of travel: data coming in, data going out, and a one-time move.
Five inbound provider types and five outbound sender types — named exactly, so you can check against your own stack before you talk to us.
Anyone can poll a mailbox. The difficulty is everything that happens after the message arrives.
Outbound configuration resolves down a three-level ladder — organisation → tenant → platform — and the lowest appropriate configuration wins. A tenant can set a house default that an individual organisation overrides for its own branding, without either of them having to know the platform settings.
Every secret is encrypted per field: SMTP password, API key, OAuth client secret and tokens. There is a connection test and a test send at every level, plus a view showing which configuration is actually in effect — the question that otherwise takes an afternoon to answer.
Name, address, provider, enabled flag, JSON configuration, poll interval (five minutes by default), whether to store the original .eml, whether to extract attachments, the reply-handling mode, and default ticket type, priority and assignee. Plus last poll, last error and an error count.
A mailbox is scoped to an organisation or to a single project. OAuth uses a three-legged flow with a provider-and-connection mismatch guard, per-organisation client credentials held encrypted, and pre-expiry token refresh — so the mailbox does not go quiet at 3am because a token lapsed.
ALWAYS_NEW_TICKET creates a ticket every time. MATCH_BY_SUBJECT finds a ticket key with a regex, resolved only within that mailbox's own organisation — and including retired project keys, so a thread that started before a project was re-keyed still lands on the right ticket. MATCH_BY_THREAD uses the thread id, In-Reply-To and References.
Processing is deduped by message id, then creates a ticket or appends a comment, finds or creates a customer account from the sender, initialises SLA on new tickets, adds the customer as a watcher and sends the confirmation after commit.
An auto-response detector skips out-of-office replies, bounces and DSNs, mailing-list confirmations and other automation. Without it, a support queue and a vacation responder will happily talk to each other all weekend.
A reply parser strips quoted chains: >-prefixed quoting, Outlook's -----Original Message-----, the Gmail and Apple Mail "On [date], [name] wrote:" form, Thunderbird, and forwarded blocks. Customers reply on top of the whole thread; the ticket should not accumulate it.
Seven providers: Trakr's own INTEGRATED git server, Forgejo, Gitea, GitHub including Enterprise, GitLab self-hosted or SaaS, Codeberg and Gogs.
INBOUND makes the remote the source of truth — the shape you want while migrating onto Trakr, with the forge still authoritative. OUTBOUND makes Trakr the source of truth, which is what you switch to when migrating off a forge. BOTH is a true mirror, and the default.
The three directions are one setting, so a migration is a change of direction rather than a rebuild of the integration.
Each of the three can be turned on or off on its own. Open-status and closed-status mapping is configurable, there is a default ticket type for issues arriving from the remote, and mirrored writes are attributed to an account you nominate.
Label mapping works by name, case-insensitively, creating labels on demand on either side. Explicit rows handle names that genuinely differ — kind/bug against bug — and mapping a remote label to an empty local name blocks it from crossing at all, which is how you keep a forge's internal triage labels out of your tracker.
POLL on a per-mirror interval, fifteen minutes by default, cursor-based so the remote is asked only for what changed. WEBHOOK on issues and issue_comment events, HMAC-verified, with GitLab's token header supported. MANUAL for a "sync now". IMPORT for a full backfill that adopts existing issues.
And TICKET_EVENT, a Trakr-side change pushed outward — dispatched after commit and executed asynchronously, so a slow or unreachable forge never slows down a user's save and never rolls one back.
Write to the remote, the remote fires a webhook, the webhook writes back locally, which fires an outbound sync. Left alone, this runs forever.
Trakr breaks it in two different ways because issues and comments have different shapes. Issues carry a lastSyncedHash over the local field set — summary, description, open or closed, label names — so an echo that changes nothing meaningful is dropped. Comments, being append-only, use per-comment origin link rows instead: a comment that came from the remote is known to have come from the remote.
Outbound, sanitised HTML becomes Markdown: headings, paragraphs, emphasis, lists, links, images, code, quotes and tables, with anything else degrading gracefully to text. Inbound, Markdown becomes HTML and is then re-sanitised.
Because the mirror writes with a single bot token, every mirrored item carries a fenced trakr:meta block naming the real author and the ticket key and URL. Otherwise a year of migrated discussion ends up attributed to a service account.
A single repository can be mirrored by several projects at once — the monorepo split — with each project verifying its own webhook secret. One repo, several trackers, no shared secret.
Each issue gets one short transaction rather than one long transaction per run, paging is capped at 40 × 100, and run history — status, trigger, issues pulled and pushed, comments pulled and pushed, skipped count, error, who ran it and timings — is kept for thirty days and pruned nightly. The mirror token is deliberately separate from the coding token: it only needs issues scope. Disconnecting a mirror keeps everything.
Push, pull, and provision.
Named precisely. There is no Trello, Asana or GitHub importer, and we would rather you know that now than discover it during a migration window.
Available both as a five-step wizard page and as an in-list modal — source, preview with per-row checkboxes, live progress.
Export a bundle from an organisation or a project, preview importing it elsewhere, then apply.
A drag-and-drop routing board where organisations are columns and projects are cards. Reorganisations happen; the tracker should survive them.
Three operations: MOVE_TO_TENANT, MERGE and SPLIT. Between them they cover the acquisition, the consolidation and the demerger — the three events that otherwise turn a tracker into an archive nobody can use.
Every restructuring starts as a dry-run preview. It computes the whole plan — what moves, what is reused, what collides — and writes nothing. Only then do you apply.
People are handled per user with an explicit decision: MOVE, STAY or LINK. Nobody is moved by inference.
Configuration matched by name is reused at the destination and everything else is cloned, with ticket pointers — statuses, types, priorities, incident flags — re-pointed to the objects that now apply.
Collisions are detected and resolved in place rather than aborting the whole operation and leaving you to guess which of four hundred names was the problem.
Projects are re-keyed where they must be, with a free-key suggestion offered. Crucially, every retired key is preserved, so old links keep working — and email threads keep matching, because MATCH_BY_SUBJECT resolves retired keys too.
The whole operation is audited: the operation itself, its status, source and target, the plan JSON, the result JSON, any error, and the actor. A failure is written in its own transaction, so the record of what went wrong survives the rollback of what went wrong.
Five inbound provider types: Microsoft 365 over the Graph API, Google over the Gmail API, generic IMAP through Jakarta Mail, Zoho, and Outboundly. There is no POP3 support. Each mailbox carries its own poll interval, defaulting to five minutes, plus settings for storing the original .eml, extracting attachments, reply handling, and the default ticket type, priority and assignee. A mailbox can be scoped to an organisation or to a single project.
Each mailbox chooses one of three reply-handling modes. ALWAYS_NEW_TICKET creates a ticket every time. MATCH_BY_SUBJECT looks for a ticket key with a regex, resolved only within that mailbox's own organisation and including retired project keys so old threads still land correctly. MATCH_BY_THREAD uses the thread id, In-Reply-To and References headers. Processing is deduped by message id, and an auto-response detector skips out-of-office replies, bounces and mailing-list confirmations.
Yes. A mirror runs INBOUND with the remote as the source of truth, OUTBOUND with Trakr as the source of truth, or BOTH, which is the default. Comments, labels and state each toggle independently, and label mapping works by name, case-insensitively, with explicit rows for names that genuinely differ. Echoes are broken by a content hash over the local field set for issues and by per-comment origin rows for comments, so a two-way mirror does not loop.
Trakr imports from CSV, Jira XML and Jira CSV. The Jira XML path streams an RSS/XML backup with StAX and brings across items along with their comments and work logs, with DTD and external entities disabled to close XXE and billion-laughs attacks. Field mappings are auto-detected with configurable overrides, thirteen date formats are accepted, and external users are mapped to Trakr users with suggestions before you preview the rows and pick which ones to import.
No. Configuration transfer covers twelve sections and offers three modes — SKIP_EXISTING, REPLACE and RENAME — and nothing is ever deleted, even under REPLACE. Matching is by name, case-insensitively, and REPLACE preserves identifiers so existing tickets keep pointing at the object they already referenced. Preview and apply share one code path, but preview writes nothing and notifies nobody.
Yes. Restructuring supports MOVE_TO_TENANT, MERGE and SPLIT from a drag-and-drop board, with a dry-run preview that writes nothing before you apply. Projects are re-keyed with a free-key suggestion, and every retired key is preserved so old links and email threads still resolve. Collisions are detected and resolved in place, and per-user decisions of MOVE, STAY or LINK determine who follows the project.
Jira XML with comments and work logs, a two-way forge mirror while you transition, and a configuration transfer that never deletes anything.