An Emacs package that provides integration with the ticket (tk) command-line ticket tracking tool. It offers a transient command menu for common ticket operations and an interactive tree-based browser for navigating tickets and their dependencies.
- Transient menu — a single entry point (
ticket-transient) for creating, listing, and closing tickets. - Ticket browser — a read-only buffer (
*tickets*) that renders tickets as a collapsible dependency tree, sorted by priority with dependency-aware tie-breaking for equal-priority siblings and roots. - Inline priority editing — raise or lower ticket priority directly from the browser without opening the file.
- Filter modes — show only open/in-progress tickets or all tickets including closed ones.
- Ticket view minor mode — auto-activates on
.tickets/*.mdfiles and exposes commands for editing status, type, dependencies, and parent without leaving the buffer. - Evil mode support — keybindings are also registered in Evil's motion state.
- Emacs 28 or later (uses
transient, which is built-in since Emacs 29; on Emacs 28, install it from MELPA). - The
tkcommand-line tool installed and available on yourPATHastk.
(package-vc-install "https://github.com/jmmv/ticket.el")(use-package ticket
:vc (:url "https://github.com/jmmv/ticket.el" :rev :newest))(straight-use-package
'(ticket :host github :repo "jmmv/ticket.el" :files ("ticket.el")))Clone the repository and add its directory to load-path:
(add-to-list 'load-path "/path/to/ticket.el")
(require 'ticket);;; In ~/.doom.d/packages.el
(package! ticket
:recipe (:host github :repo "jmmv/ticket.el" :files ("ticket.el")))
;;; In ~/.doom.d/config.el
(use-package! ticket
:config
(map! :leader :desc "Ticket" "k" #'ticket-transient))ticket.el exposes two user-facing variables:
ticket-executablecontrols the path to thetkbinary. It defaults totkon the systemPATH.ticket-browser-restore-on-ticket-closecontrols whether killing a ticket buffer opened from*tickets*returns that window to the browser. Defaults tot.
Example overrides:
(setq ticket-executable "/path/to/tk")
(setq ticket-browser-restore-on-ticket-close nil)Bind ticket-transient to a convenient key. Example using the built-in
keymap-global-set:
(keymap-global-set "C-c t" #'ticket-transient)Invoke ticket-transient (or whatever key you bound it to) to open the menu:
| Key | Action |
|---|---|
c |
Create a new ticket |
b |
Browse tickets |
C |
Close a ticket (completing-read) |
Inside the *tickets* browser buffer:
| Key | Action |
|---|---|
RET |
Open the ticket file at point |
TAB |
Expand current node; press again to expand all |
S-TAB |
Collapse all except current; press again to collapse current |
g |
Refresh — reload tickets from disk |
a |
Toggle filter: all tickets / open and in-progress only |
< |
Increase priority of ticket at point (P0 = highest) |
> |
Decrease priority of ticket at point |
c |
Close selected ticket |
o |
Reopen selected ticket |
d |
Add dependency to selected ticket |
p |
Set parent for selected ticket |
? |
Open browser action/help menu |
q |
Quit the browser window |
The browser action/help menu (?) exposes the same tree navigation, filtering,
and priority shortcuts, plus edit actions for the selected ticket:
- Close / reopen.
- Add dependency (opens selection mode in the browser).
- Set parent (opens selection mode in the browser).
ticket-view-mode is a minor mode that activates automatically whenever you
open a file matching .tickets/*.md. It is indicated by the Ticket lighter
in the mode line.
The mode adds commands to manipulate the ticket's fields without leaving the buffer:
- Status — close or reopen the ticket (delegates to
tk; the buffer is reloaded automatically). - Type — switch between
taskandepicby editing the frontmatter field in place. - Dependency — open the ticket browser in selection mode; press
RETon any ticket to record it as a dependency, orqto cancel. - Parent — open the browser in selection mode; press
RETto set the chosen ticket as the parent (written directly to the frontmatter).
| Key | Action |
|---|---|
C-c k o |
Open ticket at point |
C-c k s d |
Add dependency |
C-c k s p |
Set parent |
C-c k s s c |
Close ticket |
C-c k s s o |
Reopen ticket |
C-c k s t t |
Set type to task |
C-c k s t e |
Set type to epic |
When ticket-view-mode is active the transient menu (ticket-transient, bound
to SPC k in the Doom example) gains a "Current ticket" section:
| Key | Action |
|---|---|
o |
Open ticket at point |
s d |
Add dependency |
s p |
Set parent |
s s c |
Close |
s s o |
Reopen |
s t t |
Set type: task |
s t e |
Set type: epic |
The "Current ticket" section is absent when ticket-view-mode is not active
(i.e., in non-ticket buffers), so SPC k continues to work unchanged
everywhere else. In the *tickets* browser, use ? for the browser-specific
menu.
When ticket-view-set-dep or ticket-view-set-parent opens the browser, the
status bar shows Select … (RET to confirm, q to cancel). Pressing RET on
a ticket calls the appropriate action and returns focus to the source ticket
buffer. Pressing q closes the browser without making any changes.
Tickets are Markdown files stored under a .tickets/ directory at the project
root. Each file has a YAML frontmatter block followed by a Markdown body:
---
id: abc123
status: open
priority: 2
type: task
parent: xyz789
---
# Ticket title
Description goes here.Fields recognized by ticket.el:
| Field | Values | Notes |
|---|---|---|
id |
string | Unique ticket identifier |
status |
open, in_progress, closed |
Default: open |
priority |
integer (0 = highest) | Default: 2 |
type |
task, bug, … |
Default: task |
parent |
another ticket id |
Optional; used for tree layout |
In the browser, each ticket is shown as:
<indent><symbol> <id> [P<n>] [<type>] <title>
▶— collapsed node with children▼— expanded node with children•— leaf node (no children)- Tickets are sorted by priority first; for equal-priority root/sibling groups, dependencies are shown before dependents when possible.
- In-progress tickets are highlighted with the
warningface. - Closed tickets are rendered with the
shadowface.
Run the ERT test suite in batch mode:
emacs -Q --batch -L . -l test-ticket.el -f ert-run-tests-batch-and-exit