A minimal CLI ticket management system designed for AI agents. This is a Go port of wedow/ticket.
Play the full demo:
asciinema play https://raw.githubusercontent.com/radutopala/ticket/main/demo.cast
$ tk create "Fix login bug" -t bug -p 1 --tags auth,urgent
tic-a1b2
$ tk list
tic-a1b2 [P1][open] - Fix login bug
$ tk start a1b2
Claimed tic-a1b2 -> in_progress
$ tk add-note a1b2 "Root cause: session timeout"
Added note to tic-a1b2
$ tk close a1b2
Updated tic-a1b2 -> closedtk stores issues as markdown files with YAML frontmatter in a .tickets/ directory, enabling easy content searching without bloating context windows. Based on Unix philosophy principles, it provides:
- Dependency tracking with cycle detection
- Atomic claims to prevent race conditions
- Partial ID matching for quick access
- Git-native version control for all ticket data
brew install radutopala/tap/tkRequires Go 1.25+:
go install github.com/radutopala/ticket/cmd/tk@latestgit clone https://github.com/radutopala/ticket.git
cd ticket
make installBoth Go methods install tk to your $GOPATH/bin.
make build
./bin/tk --help- Go 1.25+ (for building)
jq(optional, for thequerycommand filtering)$EDITORenvironment variable (for theeditcommand)
Add to your project's CLAUDE.md:
This project uses `tk` for ticket management. Run `tk` to see available commands.
Workflow:
- Use `tk ready` to find tickets ready to work on
- Use `tk start <id>` to claim a ticket before working on it
- Use `tk add-note <id> "progress update"` to document progress
- Use `tk close <id>` when completeOptionally, add to .claude/settings.local.json to allow ticket commands:
{
"permissions": {
"allow": [
"Bash(tk *)"
]
}
}Add to your AGENTS.md or system prompt:
This project uses a CLI ticket system. Run `tk` for help. Key commands:
- tk ready List tickets ready to work on
- tk start <id> Claim a ticket
- tk show <id> View ticket details
- tk close <id> Mark complete
Install tk as a Claude Code plugin for the /tk skill:
# Add the marketplace
/plugin marketplace add radutopala/ticket
# Install the plugin
/plugin install tkThen use /tk to get a comprehensive command reference and workflow guide.
| Command | Description |
|---|---|
create [title] |
Create a new ticket (outputs ID) |
show <id> |
Display ticket details |
edit <id> |
Open ticket in $EDITOR |
start <id> |
Mark as in_progress |
close <id> |
Mark as closed |
reopen <id> |
Revert to open status |
status <id> <status> |
Update status (open|in_progress|closed) |
tk create "My ticket title" \
-d "Description text" \
--design "Design notes" \
--acceptance "Acceptance criteria" \
-t feature \ # bug|feature|task|epic|chore (default: task)
-p 1 \ # Priority 0-4, 0=highest (default: 2)
-a "John Doe" \ # Assignee (defaults to git user.name)
--external-ref gh-123 \# External reference (e.g., JIRA-456)
--parent tic-abc1 \ # Parent ticket ID
--tags backend,urgent # Comma-separated tags| Command | Description |
|---|---|
dep add <id> <dep-id> |
Add dependency (id depends on dep-id) |
dep remove <id> <dep-id> |
Remove dependency |
dep tree [id] |
Display dependency hierarchy |
dep tree --full |
Show full tree for all tickets |
dep check |
Identify circular dependencies |
undep <id> <dep-id> |
Alias for dep remove |
| Command | Description |
|---|---|
link <id> <id> [id...] |
Create symmetric links between tickets |
unlink <id> <target-id> |
Remove link between tickets |
| Command | Description |
|---|---|
list / ls |
List all tickets |
ready |
Open/in_progress tickets with resolved deps |
blocked |
Open/in_progress tickets with unresolved deps |
closed |
Recently closed tickets |
All list commands support filters:
--status <status>- Filter by status-a, --assignee <name>- Filter by assignee-T, --tag <tag>- Filter by tag-s, --sort <field>- Sort by field (priority|created|status|title)-r, --reverse- Reverse sort order--limit <n>- Limit results (closed command only, default: 20)
| Command | Description |
|---|---|
search <query> |
Full-text search in titles and descriptions |
stats |
Display project metrics (counts by status, type, assignee) |
Search options:
--case-sensitive- Perform case-sensitive search--status <status>- Filter results by status
Stats options:
--json- Output as JSON
| Command | Description |
|---|---|
bulk close |
Close multiple tickets |
bulk reopen |
Reopen multiple tickets |
bulk start |
Start multiple tickets |
Bulk commands support filters:
--tag <tag>- Filter by tag--status <status>- Filter by status-a, --assignee <name>- Filter by assignee--dry-run- Preview changes without applying
| Command | Description |
|---|---|
export |
Export tickets to JSON or CSV |
import <file> |
Import tickets from JSON file |
Export options:
--format <format>- Output format (json|csv, default: json)-o, --output <file>- Output file (default: stdout)
Import options:
--skip-existing- Skip tickets that already exist
| Command | Description |
|---|---|
add-note <id> [text] |
Append timestamped note (text or stdin) |
query [jq-filter] |
Export tickets as JSON, optionally filter with jq |
Tickets are stored as markdown files with YAML frontmatter:
---
id: tic-a1b2
status: open
type: task
priority: 2
assignee: John Doe
tags:
- backend
- urgent
deps:
- tic-c3d4
created: 2025-01-31T12:34:56Z
---
# Ticket Title
Description content here.
## Design
Design notes section.
## Acceptance Criteria
- [ ] Criterion 1
- [ ] Criterion 2
## Notes
### 2025-01-31T14:00:00Z
Timestamped note content.Search across ticket titles and descriptions:
tk search "authentication"
tk search "bug fix" --case-sensitive
tk search "TODO" --status=openGet an overview of your project:
tk stats
tk stats --jsonPerform batch operations with filters:
tk bulk close --tag=sprint-1
tk bulk start --assignee=agent-1
tk bulk reopen --status=closed --tag=bug --dry-runUse any unique substring of a ticket ID:
tk show 5c4 # matches tic-5c46
tk start abc # matches tic-abc1tk searches parent directories for .tickets/. Override with the TICKETS_DIR environment variable:
export TICKETS_DIR=/path/to/.ticketsOutput is automatically paged. Override with TICKET_PAGER:
export TICKET_PAGER=less
export TICKET_PAGER=cat # disable pagingThe start command uses file locking to prevent race conditions when multiple agents claim tickets concurrently.
make build # Build to bin/tk
make install # Install to $GOPATH/binmake test # Run tests with race detectionmake lint # Run golangci-lint.
├── cmd/tk/ # Main entry point
├── internal/
│ ├── cmd/ # CLI commands (Cobra)
│ ├── config/ # Configuration
│ ├── domain/ # Core data models
│ └── storage/ # File I/O operations
├── .tickets/ # Ticket storage directory
├── Makefile
└── go.mod
This is a Go port of wedow/ticket, originally a bash script. The Go implementation adds:
- Compiled binary for better performance
- Comprehensive test suite
- Atomic file operations with locking
- Structured logging
MIT