gitdone

السجل الرسمي أدوات المطورين

Read-only project status: strict and weighted completion, each claim held to git.

التثبيت

أضف هذا إلى إعدادات MCP في عميلك (Claude Desktop: claude_desktop_config.json، وCursor: ‏.cursor/mcp.json، ويستخدم VS Code وغيره الصيغة نفسها «mcpServers»).

PYPI package gitdone
Claude Code
claude mcp add gitdone -- uvx gitdone==0.3.0 mcp
إعداد JSON (Claude Desktop وCursor وVS Code)
{
    "mcpServers": {
        "gitdone": {
            "command": "uvx",
            "args": [
                "gitdone==0.3.0",
                "mcp"
            ]
        }
    }
}

التوثيق

مأخوذ من ملف README للمشروع على GitHub ويُحدَّث أسبوعيًا. تفتح الروابط على GitHub.

المحتويات
  1. GitDone
  2. Try it
  3. What it writes
  4. What happens
  5. What you get
  6. What installs, and when it runs
  7. Commands
  8. The method, in one paragraph
  9. How it compares
  10. FAQ
  11. This repository tracks itself
  12. Contributing
  13. License

GitDone

CI · PyPI · MIT license

Your agent says it shipped. Git decides.

One markdown table of what must exist for a project to be done, with every row held to git. A row is Live only when a commit on the default branch or a merged pull request says so. A commit that would make the numbers lie is refused, and a claim stops holding the day its commit is reverted.

No account, no server, no model calls, no dependencies. The files live in your repository and stay readable without the tool.

Try it

pipx install gitdone

Then, in your repository:

gitdone init --from-checklist TODO.md --hook --ci   # or: --rows "Sign-in, Search, Export"
gitdone shipped 1 <commit>                          # refused unless that commit is on your default branch, pushed if you have a remote
git add .gitdone.json status-table.md STATUS.md .github && git commit -m "Track status"   # the gate runs here

--ci adds the GitHub Action, which is the gate no flag can skip. The hook is a courtesy that lives in this clone, so another clone runs gitdone install-hook once.

To try it with nothing installed, put uvx in front of each command: uvx gitdone init --rows "A, B".

Using a coding agent? In Claude Code: /plugin marketplace add ArtJack/gitdone, then /plugin install gitdone@gitdone. Cursor, Codex and others: npx skills add ArtJack/gitdone. The details.

What it writes

FileWhat it isWho edits it
status-table.mdThe table: one row per capability, one status eachYou, or shipped, mark, add, remove
STATUS.mdThe view: the numbers, what is left, what is live and whyNobody: it is generated
.gitdone.jsonThe plan: the title, the repository, the kinds and their weightsYou, rarely

A row is one of four kinds. Live: a commit, pull request or tag on the default branch says so. Built, not live: on a branch that exists. Partial: a note says what exists. Not built. Strict counts Live rows, which is what an outside reviewer would count. Weighted also credits the others, at weights you can read and argue with in the plan.

STATUS.md after the session below:

kiosk: 4 rows

  • Strict: 1 of 4 live · █████░░░░░░░░░░░░░░░ 25%
  • Weighted: █████░░░░░░░░░░░░░░░ 25%
  • Built, not live: 0 · partial: 0 · not built: 3
DomainRowsLiveBuiltPartialNot builtStrictWeighted
1. Scope4100325%25%███░░░░░░░░░

What is left: 3 of 4 rows

#NameStatusNote
2SearchNot built
3ExportNot built
4ReportsNot built

Live: 1 of 4 rows

#NameEvidence
1Sign-in(Live 2026-03-04: 660d81a; was Not built)

Tracked with gitdone: every Live row names its evidence, and git holds it to that.

What happens

# Four things must exist for this to be done.
$ gitdone init --rows "Sign-in, Search, Export, Reports" --hook
wrote .gitdone.json, status-table.md (4 rows) and STATUS.md
All: strict 0% (0/4), weighted 0% · next: row 1 (Sign-in)

# The agent says sign-in shipped, and names a commit from its spike branch.
$ gitdone shipped 1 705af2a
refused, nothing changed: commit 705af2a is not on main
Still on a branch? Record it with: gitdone mark 1 built --branch NAME

# The commit that really landed:
$ gitdone shipped 1 660d81a
row 1: Not built → Live (verified: commit 660d81a is on main)
All: strict 25% (1/4), weighted 25% · next: row 2 (Search)
to commit: git add status-table.md STATUS.md

# Someone types Live into the table by hand, with nothing behind it.
$ git add -A && git commit -m 'Search is live'
FAIL row 2 names no commit, pull request or tag; run `gitdone shipped 2 <commit>`
result: FAIL in --strict, evidence is missing or partly disproved

# Later, sign-in is reverted on main. The claim stops holding.
$ gitdone check
FAIL row 1 (Live): commit 660d81a was reverted on main by 3f6610b
  what is true now? gitdone mark 1 <kind> <words>, or shipped 1 <the new commit>
result: FAIL, 1 contradicted or inconsistent

# Your agent says it shipped. Git decides.

Every line above is real output, with the longer commands trimmed: docs/demo/record.py runs it, and a test keeps this copy true.

A checklist's checked items are Live only if what they name holds. The rest start as Partial, with the reason beside them, so the first number you see is already true. --from-issues does the same from GitHub issues.

What you get

  • Why. A task tracker tells you what to do next. It cannot tell you how far along you are, because a closed task is only someone's word. This answers the other question, with a number that traces to commits, and it says what it could not verify.
  • A gate that reads what the commit will contain. The local hook judges git's index, not your disk, and stays out of every commit that does not touch the tracker. Sixty claims in a repository of a thousand commits take about 0.2 seconds.
  • Claims that can stop holding. Each run checks each row again. A reverted commit, through git revert or GitHub's button, turns its row into a failure until someone says what is true now, and the headline says so.
  • A burn-up chart from your git history, from the table's first commit on, with the scope line visible when it grows, and no forecast. No percentage is a date.
  • A badge, kept with the view by init --badge or badge --keep, so it needs no CI:
  • A comment on every pull request that moves a row, with findings on the table's lines in the diff. The Action needs no key and no install.
  • report: the evidence row by row, as Markdown, for a client or a manager who will never open the repository.
  • portfolio: every tracked project under a folder, on one page.
  • Agents held to it. A skill, an AGENTS.md section, a Claude Code plugin and a read-only MCP server: coding agents.

The chart and the badge here belong to Bramble Kiosk, a fictional sample.

What installs, and when it runs

Measured from the code, and SECURITY.md has the rest.

DependenciesNone: Python 3.9 or newer and its standard library
Processes it startsgit. gh or glab, only for a row that names a pull request or merge request, and never with --offline
Files it writesThe table, the view and the badge (shipped, mark, add, remove, render --write), what init creates, the workflow (install-ci), what you pass to --out. Reading commands write nothing
Git hooksOnly with install-hook or init --hook. In .git/hooks, never committed, and it refuses to replace a hook it did not write
NetworkNone of its own
Telemetry, model callsNone
Claude Code pluginOne SessionStart hook that prints a line and can never stop a session, two skills, no agent

Commands

CommandWhat it does
gitdoneWhere the project stands, what is next, and whether the gate holds. Also status, opener
initStart a tracker: --rows, --from-checklist FILE, --from-issues [LABEL], --hook, --ci, --agents, --badge
shipped <row> <evidence>Move a row to Live, or refuse. Evidence is a commit id, PR #12, MR !12 or tag v1.2. --allow-unverified takes a claim nothing here could ever check, and the note says so
mark <row> <kind> [note]Move a row short of Live, held to that kind's rule. --branch NAME
add <name>, remove <row>Change the scope and keep the counts true. --domain, --new-domain, --kind, --note
rowsList rows. --open, --kind, --domain
checkThe gate. Plain, it fails only on a proven contradiction. --strict, what the hook and the Action run, fails on anything not checked. --offline, --if-staged. Rules and exit codes
week [since]What moved since a date, a span or a commit, from the table's git history
render, countsPrint the view or the counts table. render --write writes the view; counts --write updates a counts table you pasted into the table
chartThe burn-up: --out FILE for an SVG, --csv, --json, --group
badgeThe numbers as a badge: --svg FILE, --endpoint FILE, --keep, --label
reportThe evidence behind the numbers, row by row. --out, --offline
portfolio [folder...]Every tracked project under a folder. --out
doctorEverything the tracker needs here, on one screen. --offline
whereWhich plan this folder resolves to
install-hook, install-ci, install-agents, install-skillThe local gate (--lenient only warns about missing evidence), the GitHub Action, the AGENTS.md section, a project-level skill
ci, mcpWhat the Action runs, and read-only tools over stdio

--json works on gitdone, status, check, week, where, rows, report, doctor, chart and portfolio: the shapes.

The method, in one paragraph

The table is the one place a status changes, and only on a release or a reviewed branch, never because work started. The view is generated from it, and nobody edits it by hand. Rows are capabilities a stranger could check, not tasks, so the table is also your definition of done, reviewed like code. The whole method is a page, and it works without the tool. For more depth: the status table, the plan file, evidence and the gate.

How it compares

These tools are good at other jobs, and most pair well with this one.

The question it answers"Done" meansIs the claim checked against git?
gitdoneHow far along is this scope, provably?A commit on the default branch or a merged PR says soYes: at commit time, in the PR, and again after a revert
Task trackers for agents (beads, Backlog.md, Taskmaster)What should the agent do next?Someone closed the taskNo
Spec tools (spec-kit, OpenSpec)What are we building?The tasks under the spec got tickedNo
Issue boards (GitHub Projects, Linear)Who is doing what?The issue is closedA linked PR can close it; nothing checks it stayed merged
Claim checkers (agent-claimcheck)Did this agent do what it just said?The session's trace supports itAt claim time, for one claim, with no view of the project
VerdictIs what shipped any good?A QA verdict with evidenceYes, about quality. The sibling of this tool, and a plan can show its record

FAQ

What gets past the gate? The hook is a courtesy and CI is the gate: --no-verify, a rebase or a cherry-pick skip the hook, and the Action judges what arrived. A real commit cited for the wrong row passes, and a reviewer sees that on one line of the diff. A pull request can edit the gate's own rules, and the Action says so out loud. The rules, and what the gate cannot tell.

A commit was reverted and the number did not drop? The number is what the table says, and only a person moves a row. The gate fails, and the headline says so, until someone says what is true now. Then the number moves, in a commit with their name on it. The view and the badge change the same way.

Can a row just be deleted? Yes: scope is a person's decision, in a diff with their name on it. week and the Action's comment say which rows left, the chart's top line moves, and rows_total in the plan makes it a deliberate edit.

Two branches moved rows, and the table conflicts? Resolve status-table.md as you would any file, then gitdone render --write. The gate names a conflict marker it finds. The view is generated, so either side will do.

Does it read my code? No. A status is a person's claim, and the engine holds the claim to its evidence. It proves a commit is on the default branch, not that the commit holds the feature. The claim and its commit sit on one line of the table's diff, where a reviewer sees them.

Why no forecast? A line through past progress describes the past. Scope grows, and the chart shows that.

We squash-merge. Cite the squash commit, or the pull request. A branch's old tip is not on the default branch.

A monorepo? One tracker per package: the nearest .gitdone.json wins. repo can also point elsewhere, so a tracker may live apart from the code it measures.

GitLab? MR !12 is verified through glab. So far that path is tested against a stub of glab, not a real GitLab; a report from one is welcome.

Windows? The suite passes there in CI, on the oldest and the newest Python. The tests that need a POSIX shell are left out, so the hooks, which are sh and which Git for Windows runs, are the less proven part.

No git at all? It still renders and counts, and every claim stays unproven until there is a repository.

Do I need the plugin? No. The engine stands alone. Everything else is a thin layer over the same commands.

This repository tracks itself

STATUS.md is this project's own view, under its own gate, with this roadmap as its scope. The rows that are Live name the commits that made them so. Its burn-up, published by the Action on every push:

Contributing

CONTRIBUTING.md. The reports that matter most: a claim the gate accepted and should not have, or refused and should not have.

License

MIT.

GitDone is an independent project, not affiliated with or endorsed by the Git Project. Git is a trademark of Software Freedom Conservancy.

الأسئلة الشائعة

ما هو gitdone؟

Read-only project status: strict and weighted completion, each claim held to git.

كيف أثبّت gitdone؟

يعمل على جهازك. في Claude Code: claude mcp add gitdone -- uvx gitdone==0.3.0 mcp. وفي العملاء الآخرين، الصق إعداد JSON من هذه الصفحة في إعدادات MCP الخاصة بهم.

هل يحتاج gitdone إلى مفتاح API؟

لا يذكر إدراجه في السجل أي مفتاح أو سر إلزامي. قد تتطلب بعض الميزات حسابًا لدى الخدمة التي يتصل بها.

هل gitdone مفتوح المصدر؟

نعم. شيفرته متاحة على GitHub بترخيص MIT.

من يصون gitdone؟

ينشره ArtJack. يدرجه AI.tn لكنه لا يصونه ولا يوصي به.

من سجل MCP الرسمي. الإدراج ليس توصية: راجع شيفرة الخادم وصلاحياته قبل منحه الوصول إلى بياناتك.