gitaiflow
Maintained by: [DjangoPlay](https://djangoplay.org)
A standalone OpenID Connect (OIDC) identity microservice, built with FastAPI, plus a small Django client for services that need to talk to it.
Generate an AI change summary from your git diff -- as a single, timestamped JSON file that's ready to use as a commit title/body, pipe into a commit-msg hook, or feed to another tool/agent.
Works with any AI provider: a free Google Gemini API key, a fully local Ollama model, or any OpenAI-compatible endpoint (OpenAI, Groq, DeepSeek, OpenRouter, vLLM, LM Studio, ...). One config, one output format, no vendor lock-in.
$ gitaiflow --path mailer/ --print-commit
mailer: add retry backoff for failed sends
- Added exponential backoff retry logic in retry.py
- tasks.py now retries send_mail up to 3 times on failure
- No changes to public function signatures
Install
pip install gitaiflow
Configure an AI provider (required)
gitaiflow needs an AI model configured -- it will not run without one. Pick whichever fits:
1. Gemini (free tier, cloud, default)
export AI_PROVIDER=gemini
export AI_API_KEY=<your-key> # https://aistudio.google.com/apikey
2. Ollama (local, no API key, no cost)
export AI_PROVIDER=ollama
export AI_MODEL=llama3.2:3b # must match `ollama list` exactly
3. Any OpenAI-compatible provider (OpenAI, OpenRouter, Groq, self-hosted, ...)
export AI_PROVIDER=custom
export AI_BASE_URL=<endpoint>
export AI_API_KEY=<key>
export AI_MODEL=<model>
Any of these can also live in a .gitaiflow.env file in your repo
root instead of real environment variables (same KEY=value format).
If nothing is configured, gitaiflow fails fast with these same
instructions rather than partway through a run.
Full config reference:
| Variable | Default | Notes |
|---|---|---|
AI_PROVIDER |
gemini |
gemini | ollama | openai | custom |
AI_BASE_URL |
provider default | override for any provider |
AI_API_KEY |
(none) | required for gemini/openai/custom; not needed for ollama |
AI_MODEL |
provider default | e.g. gemini-flash-lite-latest, llama3.2:3b, gpt-4.1-mini |
AI_TEMPERATURE |
0.2 |
|
AI_MAX_TOKENS |
1024 |
|
AI_REQUEST_TIMEOUT |
60 |
seconds |
Usage
gitaiflow --path mailer/ # summarize a directory
gitaiflow --path users/views/logout.py # summarize a single file
gitaiflow --path . --skip migrations tests # skip paths
gitaiflow --path . --remote upstream --base-branch develop
gitaiflow --path . -o artifacts/ # custom output root
gitaiflow --path . --markdown # also write a .md view
gitaiflow --path . --print-commit # print title+body to stdout
--print-commit is meant to be piped straight into git:
gitaiflow --path . --print-commit > /tmp/msg.txt && git commit -F /tmp/msg.txt
Output
Every run writes one JSON file to change-summary/json/<target>-<timestamp>.json:
{
"generated_at": "2026-08-19T14:32:07+05:30",
"target": "mailer",
"target_type": "directory",
"repository": "paystream",
"branch": "feature/mailer-retry",
"base": "origin/main",
"author": { "name": "Merc", "email": "merc@example.com" },
"change_window": {
"first_change_at": "2026-08-18 09:12:03",
"last_change_at": "2026-08-19 14:30:11"
},
"files_changed": [
{ "path": "mailer/tasks.py", "status": "modified" },
{ "path": "mailer/retry.py", "status": "added" }
],
"model": { "provider": "gemini", "name": "gemini-flash-lite-latest" },
"commit": {
"title": "mailer: add retry backoff for failed sends",
"body": "- Added exponential backoff retry logic in retry.py\n- tasks.py now retries send_mail up to 3 times on failure\n- No changes to public function signatures"
},
"summary": "(same content as commit.body)"
}
author, branch, base, change_window, and files_changed come
straight from git -- never from the model -- so they're accurate even
if the AI call fails or hallucinates. commit.title / commit.body
are the only model-generated fields, and they're the ones designed to
be commit-ready as-is.
--markdown renders a second, human-facing view from the same JSON
into change-summary/markdown/ -- the JSON is always the source of
truth.
Local usage log
Every run appends one line to ~/.gitaiflow/usage.jsonl -- timestamp,
repo name, target type, model used, estimated token counts, duration,
success. This file never leaves your machine. It exists so you
can see your own usage and, optionally, set soft daily limits:
export GITAIFLOW_MAX_RUNS_PER_DAY=20
export GITAIFLOW_MAX_TOKENS_PER_DAY=50000
When set, gitaiflow prints a warning once you've crossed the threshold for the day. This is a courtesy guardrail against accidentally running up a cloud-model bill, not enforcement -- it's a local file, and any user can clear it.
Repository layout
telemetry_server/ lives inside this same repo, at the root, next to
the gitaiflow/ package -- it is not a separate project and not
something copied by hand onto the server. This matters because
production deployment relies on git pull bringing it along
automatically (see telemetry_server/DEPLOY.md).
gitaiflow/ (repo root)
├── gitaiflow/ <- the PyPI package (this is what `pip install gitaiflow` installs)
│ ├── config/
│ ├── services/
│ ├── prompts/
│ └── generate_summary.py <- CLI entry point
├── telemetry_server/ <- standalone Flask receiver, deployed separately to
│ │ app.djangoplay.org -- see telemetry_server/DEPLOY.md
│ ├── app.py
│ ├── requirements.txt
│ ├── gitaiflow-telemetry.service
│ ├── nginx-conf.d-gitaiflow-telemetry-ratelimit.conf
│ ├── nginx-location-snippet.conf
│ └── DEPLOY.md
├── .gitlab-ci.yml
├── .gitlab/ci/
│ ├── pypi-release.yml <- test -> build -> version-check -> publish (manual, main only)
│ ├── github-mirror.yml <- mirrors main to GitHub on every push
│ └── deploy-telemetry.yml <- deploys telemetry_server/ to production (manual, main only)
├── .github/workflows/gitlab-mirror.yml
├── pyproject.toml
└── README.md <- this file
Two independent things ship from this one repo: the gitaiflow PyPI
package (what end users pip install), and the telemetry receiver
(a small internal service you run, not part of the package). They
share a repo and a CI pipeline but nothing else at runtime.
Telemetry (opt-in, off by default)
gitaiflow does not phone home by default. If you explicitly set:
export GITAIFLOW_TELEMETRY=true
then each run sends exactly this, to
https://app.djangoplay.org/gitaiflow-telemetry/v1/events (the
maintainer's self-hosted receiver -- see telemetry_server/ above
and its DEPLOY.md for how it's run), and nothing else:
| Field | Example |
|---|---|
install_id |
random UUID, generated once locally |
event |
"run" |
timestamp |
2026-08-19T14:32:07Z |
gitaiflow_version |
"1.0.0" |
ai_provider |
"gemini" |
model_name |
"gemini-flash-lite-latest" |
target_type |
"file" | "directory" |
files_changed_count |
4 |
tokens_estimated_in / tokens_estimated_out |
1832 / 210 |
duration_ms |
2140 |
success |
true |
os |
"linux" |
Never sent, even with telemetry on: repository name, file paths, file contents, diff content, git author/branch, commit messages, or the AI-generated summary text. On the first telemetry-enabled run, gitaiflow prints the exact payload to stdout so this is verifiable, not just promised.
Limitations
- An AI provider is mandatory -- gitaiflow does nothing without one configured, by design (see "Configure an AI provider" above).
- Daily run/token limits are a local, deletable courtesy check, not real enforcement. There's no license/quota server behind them.
- Secret redaction (
.env,*_API_KEY,*_SECRET_KEY, etc.) is best-effort pattern matching on the diff -- always review generated summaries before sharing them outside your team. - Token/cost estimates in the usage log are a rough
len(text) / 4heuristic, not provider-accurate billing.
Roadmap (not yet built)
- Hosted model-routing backend for a future paid tier.
- Server-side license/quota enforcement.
- PR-platform integration (auto-post summaries to GitHub/GitLab).
- Diff/summary caching across runs.
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 gitaiflow-1.0.0.tar.gz.
File metadata
- Download URL: gitaiflow-1.0.0.tar.gz
- Upload date:
- Size: 29.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b5013c0766b6a8e20126d22146c849039598efe98e0306ca52c89b88d475bf57
|
|
| MD5 |
751b54501624e728d017782794f85d7f
|
|
| BLAKE2b-256 |
9f519039da6deb0dfcf7e3803426409a487c384e356abeb25da6b524778a6afd
|
File details
Details for the file gitaiflow-1.0.0-py3-none-any.whl.
File metadata
- Download URL: gitaiflow-1.0.0-py3-none-any.whl
- Upload date:
- Size: 30.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
af73d5f8b2348ba56491769822e25ea073566fc82622a4664426d11dfeff82cc
|
|
| MD5 |
b2b52acb541cdb93fa96373c34f8bb1b
|
|
| BLAKE2b-256 |
dc8aa8ab8d25e362b2cb0052ced6970112498425656a4a4804570e29191b32f3
|