Turn change descriptions into clean, consistent commit messages that are ready to copy.
🌐 También disponible en: Español.
Commit Writer is a lightweight web app for turning informal or technical change descriptions into useful commit messages. The interface is bilingual, detects the browser language, and lets you switch manually when needed.
The app includes optional local history, style selection, scope, formality, multiple output alternatives, and a pipeline that is ready for multiple LLM providers.
| Feature | Details |
|---|---|
| Languages | Bilingual EN/ES interface with manual switch |
| Styles | Conventional, simple English, simple Spanish, formal business, gitmoji, and release notes |
| Output | Recommended commit, alternatives, explanation, and suggested SemVer |
| History | Optional SQLite-based local history |
| LLM | Compatible architecture for multiple providers |
| UX | Clipboard copy, validation, and clear feedback |
- Generate commit messages from natural language.
- Support for Conventional Commits.
- Simple, formal, gitmoji, and release-note styles.
- Browser-based interface language detection.
- Manual language switching with a dedicated toggle.
- Automatic change type inference when
automaticis used. - Optional scope.
- Formality level selection.
- 1, 3, or 5 alternatives.
- Short explanation of the chosen output.
- Conservative SemVer suggestion.
- Ready-to-copy
git commit -m "..."command. - Warnings when the description is ambiguous.
- Optional local history stored in SQLite.
- Architecture prepared for multiple LLM providers.
- Sidebar indicator showing the connected provider and model, or a clear "No API connected" notice when no API key is set.
- Python 3.11+
- Streamlit
- Pydantic
- python-dotenv
- OpenAI SDK for OpenAI-compatible providers
- SQLite for local history
flowchart LR
A[Streamlit UI] --> B[Pydantic validation]
B --> C[CommitGenerationService]
C --> D[LLMClient]
D --> E[ProviderFactory]
E --> F[DeepSeek / OpenAI-compatible]
F --> G[JSON response]
G --> H[CommitResult]
H --> I[UI + copy + history]
commit-writer/
├── app.py
├── README.md
├── README.es.md
├── requirements.txt
├── .env.example
├── models/
├── prompts/
├── services/
├── storage/
└── utils/
- Clone or download the project and enter the folder.
cd commit-writer- Create a virtual environment.
python -m venv venv- Activate the virtual environment.
macOS/Linux:
source venv/bin/activateWindows:
venv\Scripts\activate- Install dependencies.
pip install -r requirements.txt- Copy the example environment file.
cp .env.example .env- Edit
.envwith your API key and provider settings.
LLM_PROVIDER=deepseek
LLM_API_KEY=sk-your-deepseek-key
LLM_MODEL=deepseek-v4-flash
LLM_BASE_URL=https://api.deepseek.com
LLM_TEMPERATURE=0.2
LLM_TIMEOUT=30
LLM_MAX_TOKENS=1200
LLM_JSON_MODE=true
HISTORY_ENABLED=trueLLM_PROVIDER=custom_openai_compatible
LLM_API_KEY=your-api-key
LLM_MODEL=model-name
LLM_BASE_URL=https://your-provider-base-url.example/v1
LLM_TEMPERATURE=0.2
LLM_TIMEOUT=30
LLM_MAX_TOKENS=1200
LLM_JSON_MODE=true
HISTORY_ENABLED=truedeepseekopenaiopenroutertogethergroqcustom_openai_compatible
streamlit run app.pyThen open the local URL shown by Streamlit.
Configuration is read from Streamlit secrets first and falls back to environment variables, so the app runs both locally (.env) and on Streamlit Community Cloud (secrets) without code changes.
- Push the repository to GitHub. The
.envfile is gitignored and is not uploaded. - Create a new app at share.streamlit.io pointing to
app.py. - In App settings → Secrets, add your configuration in TOML format:
LLM_PROVIDER = "deepseek"
LLM_API_KEY = "sk-your-key"
LLM_MODEL = "deepseek-v4-flash"
LLM_BASE_URL = "https://api.deepseek.com"
HISTORY_ENABLED = "false"The sidebar reflects the connected provider and model; when no LLM_API_KEY is set it shows a generic "No API connected" notice.
Note: the local SQLite history is not persisted on Streamlit Community Cloud because the filesystem is ephemeral. Set
HISTORY_ENABLED = "false"to avoid confusion, or use a platform with a persistent disk.
I changed the README so downloads go to the latest release
docs(readme): redirect downloads to latest releaseI fixed a bug in the login form
fix(auth): resolve login form errorI improved the performance of the user query
perf(users): optimize user query performanceThe history is stored in SQLite at:
storage/commit_history.sqlite3
To disable it:
HISTORY_ENABLED=falseThe history stores:
- Generation date.
- Original description.
- Selected style.
- Output language.
- Selected change type.
- Scope.
- Recommended commit.
- Alternatives.
- SemVer suggestion.
- Description is required.
- Minimum length: 8 characters.
- Maximum length: 1000 characters.
- Scope cannot contain spaces.
- Alternatives can only be 1, 3, or 5.
- Change type must be one of the allowed values.
- Commit style must be one of the allowed values.
- Output language must be English or Spanish.
- The LLM response must be valid JSON.
- The response structure is validated with Pydantic.
Streamlit UI
→ CommitGenerationService
→ LLMClient
→ ProviderFactory
→ BaseLLMClient
→ DeepSeekClient or OpenAICompatibleClient
→ JSON response
→ CommitResult
→ UI
- The UI is optimized for speed.
- Local history is optional and does not block generation.
- Business logic stays out of
app.py. - Messages and responses follow the active interface language.
- Branch name generator.
- Changelog generator.
- Advanced release notes generator.
- Pull request title generator.
- Pull request description generator.
- GitHub integration.
git diffingestion.- VS Code extension.
- Public FastAPI endpoint.
- Export history.
- Project profiles.
- Custom styles.
This project is licensed under the MIT License.