TicGit is a Git-native issue tracker. Tickets live in the repository as structured git-meta metadata instead of files on an orphan branch.
Download a pre-built binary:
curl -fsSL https://ticgit.dev/install | shOr install from source via Cargo:
cargo install ticgitThe binary is named ti.
git init
git config user.email you@example.com
git config user.name "Your Name"
ti init
ti new --title "fix the parser" --tags bug,parser --comment "fails on empty input"
ti list
ti show <ticket-id-or-prefix>Most commands accept a full UUID or any unique UUID prefix.
Create tickets:
ti new --title "add docs"
ti new --title "fix crash" --tags bug,cli --assigned you@example.com
ti new --title "investigate flaky test" --comment "seen on CI twice"List and filter:
ti list
ti list --status open
ti list --state blocked
ti list --tag bug
ti list --assigned you@example.com
ti list --order title.desc
ti list --json
ti list --markdownShow details:
ti show <id>
ti show <id> --json
ti show <id> --markdownCommands that support --json also support --markdown, which renders the same
ticket data as Markdown and includes suggested next commands for agent workflows.
TicGit publishes a stable JSON schema for agent and automation workflows at
docs/schema/v1.json. On the website, the same schema is
available at https://ticgit.dev/schema/v1.json.
--json is the stable machine interface:
- successful JSON commands write parseable JSON to stdout only
- diagnostic and error text goes to stderr
- JSON output does not include ANSI color escapes
- non-zero exit status means the command failed
- ticket ids may be full UUIDs or unique UUID prefixes
- ambiguous or missing prefixes fail with a non-zero exit status and stderr diagnostic
ti show <id> --json and JSON mutation commands emit a ticket object.
ti list --json emits an array of ticket objects. Ticket metadata appears under
.meta as an object whose values are strings.
--porcelain and --format json are not supported compatibility aliases today;
use --json for schema-stable output.
Agents can run ti help --agent for a Markdown guide, or read the website's
Markdown version at docs/index.md.
Select a current ticket:
ti checkout <id>
ti show
ti comment "follow-up note"
ti checkout --clearMutate tickets:
ti state blocked --ticket <id>
ti state closed --ticket <id>
ti state closed:wontfix --ticket <id>
ti status review --ticket <id>
ti assign you@example.com --ticket <id>
ti assign --clear --ticket <id>
ti points 3 --ticket <id>
ti milestone v1.0 --ticket <id>
ti tag --ticket <id> bug ui
ti tag --ticket <id> --remove ui
ti edit <id>
ti comment --ticket <id> "fixed in the latest patch"Lifecycle values are split into a broad status and a specific state.
Open tickets use new, assigned, in-progress, blocked, or review.
Closed tickets use resolved, wontfix, duplicate, or invalid.
New tickets start as open:new; ti state closed defaults to
closed:resolved.
Recent tickets:
ti recent
ti recent --limit 20Import open GitHub issues:
ti import gh
ti import gh --repo owner/repoSaved views are named snapshots of ticket UUIDs:
ti save-view bugs --tag bug
ti views
ti views bugs
ti list --view bugsTicGit delegates storage and transfer to git-meta-lib.
ti pull
ti push
ti syncti sync performs a pull followed by a push. If you pass --remote <name>, the
named git-meta remote is used; otherwise git-meta resolves the default metadata
remote from Git config.
All TicGit data is written on the git-meta project target under the
ticgit: namespace:
ticgit:schema-version string
ticgit:owners set
ticgit:views:<name> set of ticket UUIDs
ticgit:tickets:<uuid>:title string
ticgit:tickets:<uuid>:description string (optional)
ticgit:tickets:<uuid>:status string
ticgit:tickets:<uuid>:state string
ticgit:tickets:<uuid>:assigned string
ticgit:tickets:<uuid>:points string
ticgit:tickets:<uuid>:milestone string
ticgit:tickets:<uuid>:tags set
ticgit:tickets:<uuid>:comments list
ticgit:tickets:<uuid>:created-at string
ticgit:tickets:<uuid>:created-by string
Ticket existence is implied by the presence of fields under
ticgit:tickets:<uuid>:*; there is no separate ticket index.
The local query database is git-meta's .git/git-meta.sqlite. Exchange with
other clones happens through refs/meta/* using normal Git transfer.
The workspace has two crates:
ticgit-lib: domain model and git-meta-backedTicketStore.ticgit: theticommand-line application.
Example:
use ticgit_lib::{NewTicketOpts, TicketStore};
let store = TicketStore::discover()?;
let ticket = store.create("fix parser", NewTicketOpts::default())?;
println!("{}", ticket.id);
Ok::<(), ticgit_lib::Error>(())Run the full test suite:
cargo testRun just the library tests:
cargo test -p ticgit-libRun the CLI integration tests:
cargo test -p ticgit --test cliBuild the CLI:
cargo build -p ticgitPackage the crates before publishing:
cargo package -p ticgit-lib
cargo publish -p ticgit-lib
# After ticgit-lib 0.1.0 is available in the crates.io index:
cargo package -p ticgit
cargo publish -p ticgitThe CLI crate depends on ticgit-lib by both local path and published
version, so publish ticgit-lib first.