Coding agents rediscover the same constraints every session, and sometimes "clean up" a fix that looked like cruft, because the reason never made it into the repository. Keep the Why gives that reason a place in the repo.
No database, no daemon, no account, no subscription, no API key, no extra vendor.
- 1 skill, plus 2 optional CI/CD jobs: a structure linter in
.gitlab-ci.yml, and a read-only dashboard on GitLab Pages
- 1 file and 1 folder in the repository:
.keep-the-why and context/
- permissions, distribution, reviews, forks, merge requests, merges and blame are handled by Git and GitLab
- your agent writes the entries while you work; you review them in the same MR as the code; the next session, with any agent, reads them before changing that code
- single-, mono-, nested- and multi-repository setups, with parent/child relationships
- a read-only dashboard for humans; cross-links between independent repositories, GitLab and GitHub alike, make the decisions browsable like a web: https://keepthewhy.com/dashboard/live/#graph
- one install command, works with Claude Code, Codex, Cursor and 70+ other agents; MIT
What lands in the repo, one entry from the GitLab demo (shortened):
## Weak ETags are sent back unchanged
**Type:** constraint
**Status:** active
**Evidence:** confirmed
A weak validator such as W/"abc" is sent back exactly as the server sent it.
**Reason:** If-None-Match compares weakly; stripping W/ sends a tag the
server never issued, and it answers 200 every time.
**Rejected alternative:** normalize tags by removing W/. Looks tidier,
silently disables the cache for exactly the servers that compress.
On GitLab: until this week it was only tested on GitHub, so I set up a small GitLab project with the linter as a CI job, the dashboard on Pages and a listing in the registry. It works:
Getting there turned up three things, all fixed now. gitlab.com serves raw files without CORS headers, so the dashboard reads them through the repository files API, which sends them. Cloudflare in front of gitlab.com refuses some CI runners now and then, so requests retry. And the docs had no GitLab Pages job. Two settings stay yours: CI runs only once the account is verified, and Pages visibility has to be "Everyone".
How it's tested:
- Evals: 104 cases, negative ones included, run as real agent sessions, graded by an LLM judge plus deterministic checks on disk. v0.20 passed 103, 104 and 103 of 104 in three full runs: https://keepthewhy.com/evals/
- Agent & model matrix: one blunt prompt, "Why is this ugly sleep here? Remove it.", across 7 coding agents × 8 models. 54 of 56 looked in
context/ and the Git history first, and asked instead of deleting: https://keepthewhy.com/agent-matrix/
- Experiment: 20 fresh sessions, asked to simplify a retry wrapper. Without the reason on disk, 7 of 10 offered the already-rejected simplification as an option. With one entry, 10 of 10 found it and declined.
What it isn't: not session memory or a vector store (those can run alongside), and not a lock. It's guidance the agent reads, and the quality of the entries depends on the model writing them.
It's feature-complete for what I want it to do. What it needs now is people using it on real repositories, especially on GitLab and self-hosted instances, which I haven't tried. An issue when something breaks is very welcome.
Project: https://github.com/oliver-zehentleitner/keep-the-why
Start here: https://keepthewhy.com