Keyboard-driven terminal ticket explorer for a tree of markdown briefs.
Project description
tix
Keyboard-driven terminal ticket explorer for a tree of markdown briefs. Linear-like TUI, zero deps beyond the Python stdlib + an optional markdown pager.
LANES STATE CTX
◐ P1 teams-error-mapping active 74K
○ P0 oauth-rotation-plan open —
● audit-logs-rollout done —
Why
- The filesystem is the database. A ticket is a markdown file.
grep,git log, andlsall keep working. - No SaaS, no auth, no network. Runs entirely against a local tree.
- Linear-like keys.
j/k,/to filter,Enterto open,pto pick up into awtlane. - Pure reader. tix never writes
status:for you. If you want auto-status derivation, wire up your own preload hook (see below).
Install
pipx install tix-cli
# or, in a venv:
pip install tix-cli
Installs one console script: tix.
From source
git clone https://github.com/gitpancake/tix
cd tix
pipx install --editable .
Quickstart
mkdir -p ~/.claude/tickets/spikes
cp $(python -c 'import tix, pathlib; print(pathlib.Path(tix.__file__).parent / "templates" / "_TEMPLATE.md")') \
~/.claude/tickets/spikes/my-first-ticket.md
tix
Or point at a project tree:
tix my-project # browses ~/.claude/tickets/my-project (centralized)
# and chdirs into ~/Documents/code/my-project so
# pickup (p) runs against the right repo
TIX_CODE_DIR=~/src tix my-project # override the code-repo lookup root
TICKETS_DIR=./docs/tickets tix
For zsh users who want per-project TICKETS_DIR to follow cd, add this chpwd hook to ~/.zshrc:
autoload -U add-zsh-hook
_tix_tickets_dir() {
local root base
root=$(git rev-parse --show-toplevel 2>/dev/null) || { unset TICKETS_DIR; return; }
base=${root:t}
if [[ -d "$HOME/.claude/tickets/$base" ]]; then
export TICKETS_DIR="$HOME/.claude/tickets/$base"
else
unset TICKETS_DIR
fi
}
add-zsh-hook chpwd _tix_tickets_dir
_tix_tickets_dir
Keys
| Key | Action |
|---|---|
↑ ↓ / j k |
Move |
Ctrl-U Ctrl-D |
Half page |
g G |
Top / bottom |
Enter → l |
Open in glow (or $PAGER) |
Esc ← h |
Collapse / back |
/ |
Filter |
e |
Edit in $EDITOR |
p |
Pickup → wt <slug> |
i |
Pin status active |
d |
Pin status done |
x |
Pin status cancelled |
m |
Move ticket to area |
y |
Copy slug to clipboard |
o |
Open Linear URL (if linear: set) |
r |
Reload (re-runs preload hook if set) |
? |
Help |
q |
Quit |
Schema
A ticket is a markdown file with YAML-ish line-based frontmatter:
---
status: open
priority: P1
area: integrations
linear: PROJ-123
---
# teams-error-mapping
## Context
…
## Acceptance criteria
- [ ] …
Full contract: docs/ticket-schema.md.
- Filename is the slug.
teams-error-mapping.md, neverPROJ-123.md. - Epic = folder. A directory containing
_epic.mdis an epic; numbered children (01-foo.md,02-bar.md) are its stories. - Status vocab is pinned:
active,open,draft,done,cancelled.
Configuration
| Env | Default | Purpose |
|---|---|---|
TICKETS_DIR |
~/.claude/tickets |
Root of the ticket tree |
TIX_CODE_DIR |
~/Documents/code |
Lookup root for tix <project> — the repo it chdirs into so pickup works |
ACTIVE_LANES_FILE |
~/.claude/active-lanes.json |
Optional sidecar map: slug → {path, branch, repo, last_commit}. Read by the TUI; tix never writes it. |
LINEAR_WORKSPACE |
(unset) | Slug used to derive linear: URLs (o key) |
TIX_PRELOAD_HOOK |
(unset) | Shell command run before launch. See below. |
EDITOR |
vi |
Used by e |
PAGER |
less |
Fallback when glow is absent |
TICKETS_DIR resolves in this order: explicit env var → ~/.claude/tickets. There is no in-binary project-local autodiscovery from a bare cd. Instead, tix <project> resolves the brief tree (centralized ~/.claude/tickets/<project>/ first, then $TIX_CODE_DIR/<project>/.claude/tickets/, then ./<project>/.claude/tickets/ for legacy trees) and chdirs into the project's git repo under $TIX_CODE_DIR (default ~/Documents/code) so the pickup key (p) runs wt against the right repo. Or set TICKETS_DIR explicitly (e.g. via the chpwd hook above).
Preload hook
tix doesn't write status: — that's deliberate. If you want statuses derived from external signals (live worktrees, feature branches, merged PRs, calendar events, anything), put a script on disk and point at it:
export TIX_PRELOAD_HOOK=~/bin/my-status-sync
tix
The hook runs once before the TUI is drawn. Its stdout/stderr are discarded — curses is about to claim the screen, so the next render is the feedback, not the printed diff. The hook is best-effort: a missing or failing command never blocks launch.
The r key in the TUI re-runs the hook and reloads.
A reference implementation (filesystem + git + gh) lives in gitpancake/.dotfiles as claude/scripts/ticket-status-sync.py — it derives active from live worktrees and done from merged PRs. Copy it, fork it, replace it.
Optional integrations
wt— if awtcommand is on PATH, thepkey suspends curses, runsgit fetch && git checkout main && git merge --ff-only && wt <slug>, then resumes.glow— preferred markdown pager for ticket preview. Falls back to$PAGER(defaultless).gh— used by some preload hooks (not by tix itself).
Non-goals
- No remote sync, no auth, no web UI.
- No mouse support.
- No notifications.
- No bundled status reconciler — wire your own via
TIX_PRELOAD_HOOK.
License
MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tix_cli-0.2.0.tar.gz.
File metadata
- Download URL: tix_cli-0.2.0.tar.gz
- Upload date:
- Size: 92.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b07553eb211d11cd63a64b5b55241989a7d9e01b02b646b60df41807ce4c71b
|
|
| MD5 |
8cfd11f92d72f261bea775c43845133d
|
|
| BLAKE2b-256 |
f4ed86366cd932e6294efa1c56e3c7f11812d7aff66b4811e7aa4eaadc8bce28
|
File details
Details for the file tix_cli-0.2.0-py3-none-any.whl.
File metadata
- Download URL: tix_cli-0.2.0-py3-none-any.whl
- Upload date:
- Size: 22.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.11 {"installer":{"name":"uv","version":"0.11.11","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a0c82ea91cee2c0133966f0d476bf9ae2614c96d913590b33d2cbbf13b0fa9f5
|
|
| MD5 |
b532117c72d9f498ed7186facf12c5a3
|
|
| BLAKE2b-256 |
7561ff0a941a19add0fc51b58698309c081038a8fa628e85f056f78a13708128
|