git-ew
Git Email Workflow - A GitHub-like web interface for email-based git workflows
Overview
git-ew provides a GitHub-style web interface for email-based git workflows. It organizes emails into threads, handles infinite nesting, and allows posting comments via plain-text emails.
Features
- GitHub-like interface for viewing threads and patches
- Email integration (maildir, mbox, public archives)
- Threaded discussions with infinite nesting support
- Automatic patch detection and display
- Plain-text email replies with proper headers
- Thread flattening for long linear chains
- SQLite backend with async FastAPI
Installation
pip install git-ew
With uv:
uv tool install git-ew
Getting Started
Quick Demo
Try git-ew with sample data:
git-ew init
python scripts/create_sample_data.py
git-ew serve
Open http://127.0.0.1:8000 to view sample threads.
Setup
Initialize the database:
git-ew init
Use the interactive setup wizard:
git-ew config
Or configure manually:
import asyncio
from git_ew._internal.database import Database
from git_ew._internal.models import EmailSource
import json
async def setup():
db = Database()
await db.init_db()
# Configure SMTP for sending emails
await db.set_config("email_config", {
"smtp_host": "smtp.gmail.com",
"smtp_port": 587,
"from_email": "you@example.com",
"from_name": "Your Name",
"username": "you@example.com",
"password": "your-app-password", # Use app password for Gmail
"use_tls": True
})
# Add email source - Maildir
async with db.session() as session:
source = EmailSource(
name="my-inbox",
source_type="maildir",
config=json.dumps({"path": "/path/to/maildir"}),
enabled=True
)
session.add(source)
# Or add email source - Mbox
async with db.session() as session:
source = EmailSource(
name="mailing-list",
source_type="mbox",
config=json.dumps({"path": "/path/to/archive.mbox"}),
enabled=True
)
session.add(source)
asyncio.run(setup())
Usage
Start the server:
git-ew serve # Default: http://127.0.0.1:8000
git-ew serve --host 0.0.0.0 # Listen on all interfaces
git-ew serve --port 3000 # Custom port
git-ew serve --reload # Auto-reload (development)
Access the web interface and click "Sync Emails" to fetch messages from configured sources.
Configuration Details
Email Sources
Maildir (local mail folders):
{"path": "/home/user/.mail/INBOX"}
Mbox (archive files):
{"path": "/path/to/mailing-list.mbox"}
Public Inbox (coming soon):
{"url": "https://example.org/archive/"}
SMTP Providers
Gmail: Enable 2FA and generate an app password
Outlook/Office365: Use regular or app-specific password
Custom SMTP: Any server supporting STARTTLS
Fastmail: Use a Fastmail app password with mail access enabled. Configure SMTP as
smtp.fastmail.com on port 587 with TLS, and configure an IMAP source using
imap.fastmail.com on port 993 with the folders INBOX and Sent.
To download and ingest zsh-workers archives into the database:
git-ew ingest zsh-workers --since 2026-03-18
Command Line
git-ew init # Initialize database
git-ew serve # Start web server
git-ew sync # Sync emails from sources
How It Works
Email Fetching
git-ew can fetch emails from various sources:
- Maildir: Local maildir folders
- Mbox: Mbox archive files
- Public Archives: Public-inbox archives (coming soon)
Thread Organization
Emails are organized into threads based on their Message-ID, In-Reply-To, and References headers. The system:
- Groups related emails into threads
- Builds a tree structure with infinite nesting support
- Detects linear chains (single replies) and marks them for flattening
- Renders threads with proper indentation and visual hierarchy
Sending Emails
When you post a comment through the web interface:
- The comment is sent as a plain-text email (no HTML)
- Proper email headers are set (
In-Reply-To,References) - The email is stored in the local database
- Email threading is maintained correctly
Patch Detection
git-ew automatically detects patches in emails by looking for:
- Git diff format (
diff --git) - Unified diff format (
---and+++) [PATCH]in the subject line
Patches are displayed with syntax highlighting and can be viewed/hidden.
Architecture
git-ew/
├── models.py # SQLAlchemy database models
├── database.py # Database operations
├── email_parser.py # Email parsing utilities
├── email_fetcher.py # Fetch emails from various sources
├── email_sender.py # Send emails via SMTP
├── thread_utils.py # Thread organization and flattening
├── app.py # FastAPI application
├── cli.py # Command-line interface
├── templates/ # Jinja2 HTML templates
│ ├── base.html
│ ├── index.html
│ └── thread.html
└── static/ # CSS and JavaScript
├── css/style.css
└── js/main.js
API Endpoints
GET /- List threadsGET /thread/{id}- View thread detailsPOST /api/thread/{id}/comment- Post a comment (sends email)POST /api/thread/{id}- Update thread (e.g., close/reopen)POST /api/sync- Sync emails from sourcesGET /api/threads- Get threads as JSONGET /api/thread/{id}- Get thread details as JSON
Sponsors
Metadata
Release files for git-ew 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| git_ew-0.1.0.tar.gz | 68.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| git_ew-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 122.8 kB
Release files / git_ew-0.1.0.tar.gz
| Download URL | git_ew-0.1.0.tar.gz |
|---|---|
| Size | 68.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4cccf398246f66b77c876e740ef01c2c584485d475d3e77df0ae2d39da2ada02
|
|
BLAKE2b-256 checksum How to use checksums |
6b7bb4d9ac17505ccd1d61488f9494bd535d254161eb88563c3868bc7a86a403
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|
Release files / git_ew-0.1.0-py3-none-any.whl
| Download URL | git_ew-0.1.0-py3-none-any.whl |
|---|---|
| Size | 54.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6f3c59bd7ac9e1519335fb1856baf7763bc350ffd307cab3162846a6638a41bf
|
|
BLAKE2b-256 checksum How to use checksums |
b2d40029c5069049cc780b571cf43a24fda1449382f9fcbc24f10de11beee689
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.8
|