Stop forgetting to tweet about your code wins.
diff2tweet feeds your recent git commits and diffs to an LLM and generates a tweet draft. Run it after you push, review the candidates, and move on.
pip install diff2tweetFor Anthropic or Gemini providers, install the extras you need:
pip install 'diff2tweet[anthropic]' # Claude
pip install 'diff2tweet[gemini]' # Gemini
pip install 'diff2tweet[all-providers]' # everythingVerify the install:
diff2tweet --help1. Add your API key
Create a .env file in your repo root (or export the variable):
OPENAI_API_KEY=sk-...
# ANTHROPIC_API_KEY=sk-ant-...
# GEMINI_API_KEY=...
All three providers are supported. Based on testing with gpt-5.1, claude-sonnet-4-6, and gemini-2.5-flash-lite-preview, Claude produced the best output quality. OpenAI was solid. Gemini struggled with context grounding. Your mileage may vary by model.
2. Add a config file
Create diff2tweet.yaml in your repo root. Minimal config:
provider: openai
model: gpt-4o
project_name: your-project
project_summary: One sentence about what your project does.
project_audience: Who you're building for.
project_stage: prototype # prototype | beta | launched
project_tone: technical # technical | founder | casualA full annotated example is at diff2tweet.yaml in the repo.
From anywhere inside your git repo:
diff2tweetThe tool will:
- Find your
diff2tweet.yamland.envat the repo root - Pull your recent committed changes since the last run
- Generate tweet candidates
- Save the result to
.diff2tweet/
No new commits since the last run
If you run diff2tweet without making new commits since the last run, it will tell you and ask whether to fall back to the configured lookback_commits window anyway:
No new commits since the last run.
Generate a tweet using the last 5 commit(s) anyway? [y/N]:
First run / not enough commits
On first run (no prior run log), diff2tweet looks back lookback_commits commits. If the repo has fewer commits than that, it tells you and asks whether to proceed with what's available:
Only 2 commit(s) available, but lookback_commits is set to 5.
Use the last 2 commit(s) to generate a tweet anyway? [y/N]:
Skipping prompts with --force
Pass --force to skip both of the above prompts — useful in CI or scripts:
diff2tweet --forceDrop a NOTES.md in your repo root to give the LLM extra context that wouldn't be visible in commits — what you're working toward, anything worth emphasizing, framing you want it to use. Gets included automatically.
| Key | Default | Description |
|---|---|---|
provider |
openai |
openai, anthropic, or gemini |
model |
— | Model name for the selected provider (required) |
project_name |
"" |
Project name for prompt context |
project_summary |
"" |
What the project does |
project_audience |
"" |
Who it's for |
project_stage |
prototype |
prototype, beta, or launched |
project_tone |
technical |
technical, founder, or casual |
project_key_terms |
[] |
Domain vocabulary to inform framing |
num_candidates |
1 |
Number of tweet drafts to generate |
character_limit |
280 |
Max tweet length |
lookback_commits |
5 |
Commits to include on first run |
commit_subject_min_chars |
20 |
Min chars for a commit subject to be included |
readme_max_chars |
0 |
Max README.md chars to include as context |
forced_hashtags |
[] |
Hashtags always included when they fit |
custom_instructions |
"" |
Extra guidance appended to the prompt |
context_max_chars |
12000 |
Max characters of context sent to the LLM |
max_doc_diff_sections |
3 |
Max documentation diff sections to include |
max_doc_section_chars |
1000 |
Max chars per individual doc diff section |
diff_ignore_patterns |
(list) | Glob patterns to exclude from diff context |
output_folder |
.diff2tweet |
Where logs and drafts are saved |
Each run writes a markdown artifact to .diff2tweet/runs/ with the tweet candidates. Runs are also logged to .diff2tweet/run_log.jsonl so subsequent runs only pick up new commits.
Add .diff2tweet/ to your .gitignore, or commit it if you want a record of your tweet history.
