gitstate
GitHub Part of Vulos
local · on your machine GitHub + GitLab MIT / Apache-2.0

Your git already knows.
Stop typing it twice.

gitstate reads your repositories and derives project state, effort, contribution and classification — no tickets to groom, no story points to invent, no stand-up to reconstruct. It runs as a desktop app on your machine: a Rust core, one SQLite file, no account, no server.

Runs offline · scans a local repo with zero network calls · v0.1 — built in the open

gitstate — local daemon · 127.0.0.1:7473
The gitstate dashboard: commit, merged-PR, cycle-time and contributor stat cards over a cycle-time trend chart, a contribution heatmap and a top-contributor list, all derived from git.
0 tickets updated by hand derived from git no account · no server
Scan a repo in one command GitHub & GitLab, via your own login Everything in one SQLite file Nothing to breach, nothing to subpoena
01Derived, not entered

The ticket was always a side effect of the commit.

Every tracker next to git — Jira, Linear, ClickUp, ZenHub — asks a human to re-type what the repository already recorded. That makes it wrong by construction: stale the moment attention moves, and gamed the moment it's a target. gitstate reads the other side.

The usual waymanual
GS-418 · status field
Someone remembers to drag the card to In Progress. Two days later nobody moves it to Done.
Estimate
5 points — argued for in a room, never checked against the diff.
Friday timesheet
Hours reconstructed from memory, rounded to the nearest half day.
cost: everyone's attention, forever
gitstatederived
source
commit 8f2ac1d · 3 files
+ 84 − 31 src/ingest/retry.rs
PR #47 merged · 2 reviews
state
PR merged ⇒ Done. Open PR ⇒ in progress. Nobody had to say so.
effort
difficulty 8 — judged from the shape of the change, with the rationale attached and the method (LLM or heuristic) shown.
cost: nothing — you already wrote the commit

The rule that constrains every feature: if it would force a human to invent a number, it doesn't ship. Where git genuinely can't see something — design work, a customer call, an outage handled in Slack — gitstate marks the gap instead of guessing at it.

02What it derives

Every screen, one source of truth.

Delivery health, contribution texture, classification and working sets — computed from commits, pull requests, issues and reviews. The desktop app and the headless daemon serve the same UI over the same JSON API.

Eng Health: cycle-time p50, change-failure rate, merge frequency and deploy-proxy cards, a bus-factor ownership panel, review coverage and quality signals.
DORA, without a survey Cycle time p50/p90 measured from open to merge, a change-failure proxy, merge frequency, bus factor, review coverage and test-touch — read off the ledger, not a survey, with every proxy labelled as one.
6dimensions Contribution is texture — shipped, review, effort, quality, ownership, durability — never one number.
0servers to trust No hosted service, no org account, no telemetry. Egress only to endpoints you configured.
Board

A board nobody drags

Open, in progress, merged, done — every card is a PR, issue or review gitstate already parsed. It is read-only on purpose: a column you can drag is a column that can lie.

1SQLite file Your whole ledger. Copy it, back it up, delete it — no export request required.
Agent-native

Agents counted honestly

Claude Code, Dependabot and friends are first-class identities. Every contribution carries an agent_pct, so autonomous work is visible rather than quietly folded into a human's row — in the demo dataset the refactor agent's rows read 95% agent, and say so.

Classify: work items labelled against the signed taxonomy with confidence, method and rationale shown, plus a difficulty score per item and a correction dropdown.
Classification that stays on your box Point it at your own llmux or any OpenAI-compatible endpoint — or run the deterministic heuristic offline. Corrections train this machine only.
Import: Jira and Linear credential forms using your own personal API token, with an offline CSV/JSON export path as an alternative.
Bring the history you already have Jira and Linear import with your personal token, called from your machine — or fully offline from a CSV/JSON export. Imported issues become ordinary work items.
03Measure work, not workers

Any ranking is an artefact of the weights you chose.

So gitstate hands you the weights. Contribution is six normalised, git-grounded dimensions, computed within the repo cohort so reviewers, mentors and maintainers are never zeroed. Drag a slider and watch the "leaderboard" rearrange itself — that is the argument against having one.

Weights
demo-org/ledger-core · six-dimension texturedemo data
shipped review effort quality ownership durability

Real numbers from the bundled synthetic dataset (gitstate seed --demo), recomputed here exactly as the app does it: composite = weighted mean of the six dimensions. Shipped counts merged PRs and closed issues · review counts work done on others' changes · effort sums judged diff-difficulty · quality inverts reverts and SZZ-linked bug introductions · ownership is the area of the tree you hold · durability is surviving lines ÷ authored lines, from git blame.

04Every surface

The whole app, captured against the demo dataset.

Nothing here is a mockup: each shot is the real desktop UI running against gitstate seed --demo — a fake org with pseudonymous contributors, never anyone's real history.

05Local-first by construction

There is no server side to breach.

gitstate used to be a multi-tenant SaaS: a Postgres database holding every team's git activity behind a login. That honeypot is gone. What replaced it is a Rust core, a local daemon bound to 127.0.0.1, and a single SQLite file you own.

your machine
your git reposgit2 · walk · diff · blame
gh / glab CLIPRs · issues · reviews
local LLMoptional · your endpoint
rust core gitstate derive project state judge effort · classify six-dimension contribution
desktop appTauri 2 shell
CLI + daemon127.0.0.1:7473
one SQLite fileyour whole ledger
another machinecontexts + categories only
A plain scan of a local repository makes zero network calls. The only endpoints in the picture are ones you configured: your forge, and optionally your own LLM. Between machines, the single dashed edge carries saved working sets and labels — never your code, diffs or commits.

No central anything

No hosted service, no org accounts, no billing cloud, no telemetry, no crash reporter. The daemon binds to loopback. Uninstalling is deleting a binary and a file.

Signed data, not a service

Peers agree on what feature.api means because the category tree ships as an ed25519-signed, versioned, content-addressed file — verified against a pinned key and failing closed to your local categories if the signature doesn't check out.

Peer-to-peer, not pooled

Saved contexts and categories converge as CRDT operations — last-writer-wins scalars, add-wins sets, tombstoned deletes — merged machine to machine. Your commits, diffs and code never leave the box.

What is deliberately not built: cross-population features — trending, "others tagged this", "similar repos" — need a view of strangers you will never meet. They stay a dormant, optional seam, and there is no anti-sybil tier and no pooled fine-tuning to go with them. The rule: only "needs a view of strangers" would belong to a coordinator; everything a git tool is actually for is local and peer-to-peer.

06CLI & headless daemon

The same core, without a window.

Every derivation the app shows is a command, and the daemon that backs the desktop shell is the same binary you can leave running on a server or a spare box. Real output, captured from the demo dataset.

derive
$ gitstate repo add ~/code/atlas-api
added 5d6fe96b-8686-9274-0165-97fbab4325e4  demo-org/atlas-api

$ gitstate repo scan 5d6fe96b --no-forge   # git only, no network
scanned demo-org/atlas-api  commits=2999  contributors=10  work_items=400

$ gitstate state 5d6fe96b
repo         5d6fe96b-8686-9274-0165-97fbab4325e4
head         d42d4868a7691cfdbfbfdb0f32664f85c5a066ad
prs          open=4 merged=40 draft=2
issues       open=7 closed=21
flow         in_progress=4 done=61
cycle time   p50=8.0 p90=17.6 (hours)
change fail  0.2
warning:     synthetic demo data — not derived from real git/forge history
contribution + taxonomy
$ gitstate contributions 5d6fe96b
contributor                      ship    rev    eff   qual    own    dur    comp agent%
Ada Kestrel                        67     43     69     55     77     93    67.3     0%
Mateo Ruiz                         32     47     54     79     72     66    58.3     0%
Sana Torres                        34     36     49     62     75     93    58.2     0%
Femi Osei                          19     85     91     56     12     36    49.8     0%

$ gitstate taxonomy show
schema   gitstate.taxonomy/v1
version  1.0.0
id       b52f6ed714c642c4a0fb3d536bee006bffe7c341…
pubkey   3b6a27bcceb6a42d62a3a8d02a6f0d7365321577…
categories:
  feature.api      API / interface  (feature)
  bugfix           Bug fix
  refactor         Refactor

$ gitstate serve          # same UI, no desktop shell
gitstate serve: http://127.0.0.1:7473
07Quick start

One Cargo workspace. No Docker, no database server.

gitstate builds from source today — a Rust toolchain, plus Node for the desktop shell. Packaged installers land with the first tagged release.

build & run
# 1 — build the core, the CLI and the daemon
git clone https://github.com/vul-os/gitstate
cd gitstate
cargo build --workspace

# 2 — try it against synthetic data, no repo required
cargo run -p gitstate-cli -- seed --demo
cargo run -p gitstate-cli -- serve      # http://127.0.0.1:7473

# 3 — or point it at something real
gitstate repo add ~/code/my-project
gitstate repo scan <repo_id>            # --no-forge = offline
gitstate state <repo_id>

# 4 — the desktop app (boots the daemon in-process)
cd apps/desktop && npm install && npm run tauri dev
  1. 1
    Bring your own forge login gitstate shells out to the gh / glab you're already logged into, or takes a token from the environment. It never asks you to create an account with anyone — including us.
  2. 2
    Classification is opt-in Point VULOS_LLMUX_URL or OPENAI_BASE_URL at any OpenAI-compatible endpoint — your own llmux, a local model, whatever you run. Leave it unset and a deterministic heuristic takes over; everything still works, offline.
  3. 3
    P2P sync is a separate build A bare cargo build never pulls a network stack: gitstate-sync is excluded from the default workspace and lives behind the sync-dmtap feature. Opt in only if you want contexts to travel.
  4. 4
    Know where your data is gitstate data path prints the directory and the database file. That file is the whole product state — back it up, move it, or delete it.
08Straight answers

The questions worth asking.

How can it know the state without me updating anything?
Because the states that matter already exist in the ledger. A merged PR is done. An open PR with commits on it is in progress. A closed issue with no linked change is closed-not-shipped, and gitstate says so. Cycle time is the measured interval between first commit and merge — not an estimate anyone defended in a meeting.
Is the effort score just an LLM guessing?
The model reads the shape of the change — files touched, surface area, the kind of code moved — and returns a Fibonacci-ish difficulty with a written rationale and a confidence, both shown in the UI. Every estimate is labelled with the method that produced it (llm_judged or heuristic), so you always know which you're looking at. With no endpoint configured, the deterministic heuristic runs instead and the labels say so.
What about work that never touches git?
gitstate flags it rather than inventing it. Design reviews, incident calls and customer conversations leave no commit, and no amount of modelling will conjure one. What it will not do is silently score a person lower for work it cannot see — which is precisely why contribution is six dimensions of texture instead of a single number that reads as a verdict.
Does anything leave my machine?
Only what you configure. Scanning a local repository makes zero network calls. Pulling PRs and issues talks to your forge with your credential. Classification talks to the LLM endpoint you set, and to nothing if you set none. There is no telemetry, no crash reporting, and no gitstate-operated service anywhere in the picture — see the threat model.
Can a team use it together?
Two ways, both without a hub. Everyone can point their own copy at the same repositories and derive the same state independently — the git history is the shared source. And saved contexts (a working set of repos, PRs, tags and notes) plus your category tree sync peer-to-peer as CRDT operations, converging device to device with no authority in the middle. What does not travel is your code, your diffs or your commits.
Is this finished?
No — it's v0.1 and built in the open. The Rust core, the daemon, the CLI, the desktop shell and every screen shown above work today; the P2P sync crate is behind a feature flag; packaged installers and a few ported analytics domains are still landing. The repository's roadmap and progress log are honest about which is which.
What's the licence, and the catch?
MIT OR Apache-2.0, at your option — the same as every sibling project in the Vulos suite. There is no open-core split, no enterprise tier and no telemetry-for-free trade: the earlier AGPL licence and the commercial ee/ tier were both removed when the product stopped being a multi-tenant service. There is nothing to upsell you, because there is nothing hosted to sell.

Git is the real ledger.

Stop typing it twice — and keep it on your own machine.

Part of Vulos

Vulos is a family of open, self-hostable apps built on the same principle: the software runs where you are, not where a vendor is. gitstate is fully standalone — it never requires Vulos infrastructure — and when siblings like Diwan or slip/scan are around, it shares contexts with them peer-to-peer. No hub, no account, no coupling.

Explore Vulos →