I’ve been using coding agents daily for the past year or so, and a constant problem I’ve been trying to address is making the agent as fluent as possible with my project so it can produce results like an experienced coworker would.
I wanted the agent to know which specific components the system has and how they relate to each other, without manually pointing to files. To produce code that meets my established conventions and expectations, and to really trust it when it says “it works now”.
But most importantly, I wanted it to be familiar with my way of thinking and past decisions, so when we start a new session, it won’t feel like we are starting from scratch.
At first, I was spending a huge amount of time on a single prompt, trying to provide the agent with everything I knew and explaining my intent as I would to a coworker. It worked surprisingly well - the agent could do miracles when it had the right reasoning at the right time. But it wasn’t scalable. So I started reverse engineering what “right reasoning and understanding at the right time” really means.
The models, the harnesses, and the tools were getting better by the day. But after a few months and after I tried pretty much everything - from creating rules in the early days, to extracting artifacts from sessions and providing them back to the agent through slash commands or MCP tools, and finally to utilising skills today - the same problem kept breaking the habit: the overhead of capturing context at the exact moment you have it. You finish a session, you're tired, the context is at its peak freshness, and that's precisely when you have to stop and document something in a separate file. Nobody does it consistently. I didn't either.
So I thought the problem could be solved through automation, and I tried some hacks using Claude hooks and native Git hooks. When I introduced this in my team, it was chaos - the quality of what we were capturing went down dramatically, and it became clear that forcing the capture was making it worse, not better.
The problem wasn't the habit. It was that I was treating something that evolves as something that sits still.
Then one evening, I was looking at a branch diff, trying to reconstruct why I had made a particular decision two weeks earlier. The commit said:
Useful. But it told me nothing about why I had done it that specific way and not the more obvious one. The reasoning was gone.
And then it hit me - the commit body has always been there. Completely underutilised. I’d been trying to build a parallel tracking system for session context when the thing that already tracks sessions already existed. A branch is a session. The commit history is the progression. The only thing missing was a convention for what goes in the body.
I drafted a small internal specification doc, inspired by the Conventional Commits one, so that I can instruct the agents to follow it through a simple skill when I want it to “commit”. And it worked very well. I’ve tested it with a bunch of commits, and I was surprised by how simple it is, yet powerful. So I called this internal specification - Contextual Commits.
Here is an example of how a Contextual Commit looks:
feat(auth): implement Google OAuth provider
intent(auth): users need social login, starting with Google before GitHub and Apple
decision(oauth-library): passport.js over auth0-sdk — better multi-provider flexibility
rejected(oauth-library): auth0-sdk locks us into their session model
constraint(callback-routes): must follow /api/auth/callback/:provider pattern
learned(passport-google): requires explicit offline_access scope for refresh tokens
The commit subject is still the good, well-known Conventional Commit, and it already captures the WHAT, but the body now captures also the WHY. What you see in the body is a simple list of action lines, each supposed to capture a signal that is not available in the diff alone. It has the same structure as the conventional commits, but with different action types.
It’s been a while now since I started using it internally, and I am definitely happy with it. During that time, I also created a simple utility skill that allows you to “recall”, or search through the contextual commit history. What changed in my workflow is not much. I just have the “contextual-commit” skill installed, and I still say the same “commit” to Claude Code or whatever harness I am using to commit my changes and auto-generate a commit message. The difference is that now it automatically creates a meaningful body as well. Regarding the “recall”, I use it in a few ways manually (running it without args so it can give me the “branch brief”, or searching for specific scope or action+scope), but mainly leave it to the agent to invoke proactively when it feels that it lacks reasoning and understanding.
I shared this with a couple of friends, and they immediately wanted to give it a try. That’s why I decided to open it as an “open standard for capturing the WHY in git history” with a small reference implementation (the “contextual-commit” and “recall” skills) that could be easily installed with:
And here is the actual repository: https://github.com/berserkdisruptors/contextual-commits
Looking back at everything I struggled with, it's almost funny how none of those problems exist here. The context decay problem - where a file stays confident long after the reasoning behind it has changed - doesn't exist here, because each action line ages together with the commit it belongs to. The merge conflict race conditions I kept hitting when multiple sessions were writing to shared context files - gone, because git's append-only log was literally built for concurrent contributors. The discipline dependency, where capturing context required a separate deliberate step at the worst possible moment - gone, because the commit you were already making is now the capture. No servers, no sync protocols, no vendor lock-in, no privacy concerns about your reasoning living somewhere else. And it scales the same way git scales - which is to say, to the Linux kernel and beyond. The more I think about it, the more it feels like this was always the right place for this information. We just hadn't needed it badly enough to notice.
It’s a specification, not a tool - one that welcomes anyone who has thought about this problem to help shape something the whole ecosystem can benefit from. If more people find it useful, harnesses might adopt it natively, which would give far more consistent behavior than skills can.
No new tools. No infrastructure. Just better commits.