Automatic decisions from history

CommitMind reads your commit history and proposes which commits represent architectural decisions worth recording. You review the proposals; accepted ones become first-class entries in your project's decision log.

How it works

When you connect a GitHub repo to CommitMind, three things happen automatically:

  1. Backfill — past commits and their summaries flow into the project's memory. (Already shipped; this is what populates the timeline.)
  2. Classification — for each commit, an LLM reads the message + diff and answers "is this an architectural decision?" with a confidence score and a draft title, rationale, and alternatives. Positive matches become candidates.
  3. Review — candidates appear in the dashboard's AI Decision Candidates section. You promote (with edits if you want) or dismiss each one.

The chain runs without user action — connect the repo and walk away; come back to a populated candidate list.

What counts as a "decision"

The classifier is conservative on purpose. It looks for:

It explicitly skips: bug fixes, typo fixes, dependency bumps, mechanical refactors, and routine feature additions. False positives are worse than false negatives — they waste reviewer time. When in doubt, the classifier says "no".

The classifier

We use OpenAI's gpt-4o-mini via the Vercel AI Gateway. The model returns structured JSON:

{
  "is_decision": true,
  "confidence": 0.82,
  "title": "Use Postgres advisory locks for the extraction worker",
  "rationale": "Avoids a separate lock table and keeps the worker stateless.",
  "alternatives": ["Redis SETNX", "dedicated locks table"]
}

JSON mode means the response always parses cleanly.

You can swap the model via DECISION_EXTRACTION_MODEL if you self-host (see the CLI reference for environment variables). Default is openai/gpt-4o-mini because it's the cheapest classifier with reliable structured output. Other tested options: anthropic/claude-haiku-4-5 (~3-4× the cost, marginally better at nuanced code reasoning) and anthropic/claude-sonnet-4-6 (~10× cost; overkill for a binary classifier).

Pricing tiers

| Tier | Commits analyzed / month | Notes | | --- | --- | --- | | Free | 100 | Default for every new org. | | Pro | 5,000 | Enough for most active monorepos. | | Enterprise | Unlimited | Set manually for now. |

Quotas are per-org, not per-project, so creating a second project in the same org doesn't double your budget. The counter resets on the first day of each calendar month (UTC).

Failures don't charge quota. GitHub timeouts, LLM transport failures, and per-commit timeouts skip the commit without billing it. You only pay for successful classifications, regardless of whether the result was positive.

See the pricing page for current plan details.

Reviewing candidates

In the dashboard, every project with active candidates gets an AI Decision Candidates section. Each candidate shows:

Re-running

When new commits flow in (via the post-commit hook or webhook), the system doesn't auto-re-run the classifier. Click Analyze N more commits above the candidates list. Quota gates apply.

If a job hits the quota limit mid-run, it completes with status done_partial — the analyzed prefix becomes candidates; you can either upgrade your tier and re-run for the rest, or wait until next month's quota resets.

What's not analyzed

Privacy

Commit messages plus the patches of changed files are sent to your configured LLM provider (Vercel AI Gateway, defaulting to OpenAI). The Vercel AI Gateway has zero data retention by default. Files outside the changeset are never read.

If you self-host CommitMind with a different AI_GATEWAY_API_KEY or model, you control where the data goes.

Self-hosting and disabling

Decision extraction requires AI_GATEWAY_API_KEY to be set on the API server's environment. When unset, the classifier silently disables — the rest of CommitMind still runs (timeline, search, manual decisions). The /analyze-decisions endpoint returns 503 service_unavailable and the auto-trigger from backfill is skipped.

To turn it back on: set the key, restart the worker.

Next steps