Skip to main content
ticket-rs didn’t appear out of nowhere. It’s the result of learning from other tools, identifying pain points, and building something better.

The Problem

AI agents need long-term memory to coordinate work effectively. But existing solutions put up roadblocks:

JIRA & Linear

API tokens, rate limits, constant browser context switching.

SQLite Files

Merge conflicts, zombie daemons, background processes to fight.

Complex CLIs

Verbose output burning through AI context windows.

No Git Integration

Issues live separately from code, making versioning difficult.
We wanted something simpler. Something that lives in git with zero external dependencies. Human-readable files — Markdown and YAML — that agents can grep and edit directly. For developers, this means less context switching. You live in the terminal and IDE, not bouncing between browser tabs.

Learning from Beads

Steve Yegge’s Beads pioneered AI-native issue tracking. It got a lot right:
Git-backed storage — issues versioned with code
Tight CLI — fast, focused commands
Core insight — AI agents need structured memory to coordinate work
I used Beads for months and it was fantastic. But then friction started showing up:

The Friction Points

SQLite daemon — Clever, but led to zombie processes and merge conflicts
Monorepo challenges — Multiple .beads/ directories required workarounds
Sandboxed environments — Couldn’t fetch GitHub releases in environments like Claude Code web
Feature creep — As the project grew (sometimes changing 50k lines per day through “vibe coding”), it added features I didn’t need while missing ones I did
Beads proved the concept. Now we needed something more focused and portable.

Discovering ticket

That’s when I stumbled on wedow/ticket — a single bash script that nailed it:
“Tickets are markdown files with YAML frontmatter in .tickets/. This allows AI agents to easily search them for relevant content without dumping ten thousand character JSONL lines into their context window.”
Exactly.
  • ✅ No daemons
  • ✅ No databases
  • ✅ Just files
  • ✅ Version controlled alongside your code
This was the right architecture. Simple, elegant, and it just worked.

Why Rust?

Bash works great, but I wanted to floor it. Here’s what I wanted to add:

1. Graph Analytics

Inspired by beads_viewer, I wanted powerful graph algorithms:
  • PageRank — Surface issues that unblock the most work
  • Betweenness centrality — Identify bottleneck issues
  • Critical path analysis — Understand project timelines
These algorithms are computationally intensive. Rust gives us the performance to run them instantly.

Learn More

See how graph analytics help you prioritize work

2. Native Python Bindings

Instead of subprocess overhead (running tk via shell from Python), we can use Maturin to create native Python bindings:
from ticket_py import Ticket

# Direct function calls, no subprocess
tk = Ticket()
issues = tk.list_issues()
tk.create_issue("Add auth", priority=1)
This makes tk a library as well as a CLI.

3. Cross-Platform, Single Binary

Rust compiles to:
  • A single ~9MB executable
  • Zero runtime dependencies
  • Native performance on every platform
Compare that to:
  • Node.js requires a runtime installation
  • Python requires interpreter + dependencies
  • Bash has inconsistent behavior across platforms

4. Type Safety

Rust’s compiler catches bugs before they hit production:
// This won't compile - caught at build time
let priority: Priority = "invalid"; // ❌ Type error

// This is safe - types enforced
let priority = Priority::High; // ✅
No more runtime errors from typos or invalid data.

5. Sandboxed Environment Support

Because tk is a single binary with no dependencies, it works in restricted environments:
  • Claude Cowork/Claude Code web
  • Docker containers (minimal base images)
  • CI/CD runners (no setup required)
  • Air-gapped systems (no external downloads)
Just drop the binary and go.

The Result

ticket-rs combines the best of all these approaches:
1

Beads' Vision

Git-backed, AI-native issue tracking with structured memory
2

ticket's Simplicity

Markdown + YAML files, no daemons, no databases
3

Rust's Performance

Blazing speed, type safety, cross-platform single binary
4

Graph Analytics

PageRank, critical path, betweenness centrality for smart prioritization

Design Decisions

Why Markdown + YAML?

Human-readable and machine-friendly. AI agents can grep, developers can diff, git can merge.
---
status: open
priority: 1
deps: [tk-abc123]
---

# Add authentication

Implement OAuth2 flow.
This is vastly better than:
  • JSON blobs (verbose, not human-friendly)
  • Binary databases (can’t grep or diff)
  • External APIs (requires network, credentials, rate limits)

Why Local-First?

Your project’s issues should travel with your code. When you git clone, you get:
  • ✅ Source code
  • ✅ Issue history
  • ✅ Dependency graph
  • ✅ Complete context
No API calls. No external services. Full offline capability.

Why Zero Daemons?

Background processes create problems:
  • Zombie processes that need manual cleanup
  • Port conflicts
  • Resource consumption when idle
  • Startup/shutdown complexity
tk is stateless: run the command, get results, done. No lingering processes.

Evolution Timeline

1

2025 Q4

Used Beads, hit friction points with SQLite daemon and monorepos
2

2025 Q4

Discovered wedow/ticket, validated the markdown + YAML approach
3

2025 Q4

Started ticket-rs prototype in Rust, added graph analytics
4

2025 Q4

Added GitHub/Linear sync, MCP server, Python bindings
5

2026 Q1

Production-ready release, Claude Code integration, comprehensive docs

What’s Next?

ticket-rs is production-ready, but the journey continues:

More Integrations

GitLab, Azure DevOps, Jira, Asana

Advanced Analytics

Velocity tracking, burndown charts, time estimates

Team Features

Assignees, mentions, notifications

AI Enhancements

Auto-triage, smart estimates, dependency suggestions

Next Steps