git logChangelog
Commit History of Bad DecisionsChangelog
Real milestones from real repos, in the voice they deserve. The jokes are labelled.Dated milestones from my projects: releases, launches and first commits.
Uncommitted changesJokes. Never committed, so no dates.
Joke, not a real event: feat: built another thing nobody asked for
Joke, not a real event: fix: fixed the fix that broke the fix
Joke, not a real event: chore: questioning my life choices
Joke, not a real event: perf: made it fast enough that I can't blame the computer anymore
feat(ohfork): put the portfolio on a design system before it had a portfolio.
The design system, themes and typed content model landed on main, the same night as the scaffold and the brand identity.
ohfork.dev: The design system, themes and typed content model landed on main, the same night as the scaffold and the brand identity.
chore(langswitch): open-sourced, with the original author credited. Properly, this time.
LangSwitch became a public GitHub repository (MIT). Its latest commit credits CapsLangSwitcher by Gamezxz again.
LangSwitch: LangSwitch became a public GitHub repository (MIT). Its latest commit credits CapsLangSwitcher by Gamezxz again.
docs(ohfork): wrote the roadmap before writing the website. Classic.
First commit of ohfork.dev: the concept, the roadmap and the instructions for coding agents.
ohfork.dev: First commit of ohfork.dev: the concept, the roadmap and the instructions for coding agents.
feat(jit): jit now runs on schway. It's agents all the way down.
Jit gained a Schway bridge, pinned to a host release.
Jit: Jit gained a Schway bridge, pinned to a host release.
feat(jit): learned to read Telegram. Still ignores my messages.
Jit bound a Telegram owner identity, with a durable long-poll inbox.
Jit: Jit bound a Telegram owner identity, with a durable long-poll inbox.
docs(jit): started a project by writing specs for it. Growth.
First Jit commit: the discovery baseline and feature specifications. The MVP backlog followed the same night.
Jit: First Jit commit: the discovery baseline and feature specifications. The MVP backlog followed the same night.
refactor(heelflick): renamed the "Studio" so it sounds like a skateboard trick.
The ad-production studio was renamed Heelflick and got a refreshed web UI.
Heelflick: The ad-production studio was renamed Heelflick and got a refreshed web UI.
feat(heelflick): built an ad agency with zero clients.
First Heelflick commit: workflows for producing advertising videos.
Heelflick: First Heelflick commit: workflows for producing advertising videos.
release(oliv): 0.2.0 is public. Thai voice typing that spells "PostgreSQL" in English.
OLIV 0.2.0 was published as a GitHub release on the public chayapats/oliv repository.
OLIV: OLIV 0.2.0 was published as a GitHub release on the public chayapats/oliv repository.
release(schway): 1.0.0-rc.2. Still a candidate. Still running.
Schway 1.0.0-rc.2 was published to npm under the "next" dist-tag.
Schway: Schway 1.0.0-rc.2 was published to npm under the "next" dist-tag.
feat(oliv): ported to iPhone, because a Mac in your pocket is too heavy.
First commit of the native OLIV iPhone client. A minimal Thai/English keyboard was added the same day.
OLIV: First commit of the native OLIV iPhone client. A minimal Thai/English keyboard was added the same day.
feat(oliv): one server, many clients, individual keys. Look ma, a platform.
The Linux and iPhone clients both moved to the public OLIV API, with an API key per device.
OLIV: The Linux and iPhone clients both moved to the public OLIV API, with an API key per device.
release(schway): 1.0.0-rc.1, published at 1:36 a.m., like a professional.
Schway 1.0.0-rc.1 was published to npm as the "latest" dist-tag.
Schway: Schway 1.0.0-rc.1 was published to npm as the "latest" dist-tag.
release(schway): 0.6.0. Three minor versions in three days.
Schway 0.6.0 was published to npm.
Schway: Schway 0.6.0 was published to npm.
feat(schway): published to npm. Nobody asked.
First real npm publish of Schway, version 0.4.0. A 0.0.0-stage placeholder went out two minutes earlier.
Schway: First real npm publish of Schway, version 0.4.0. A 0.0.0-stage placeholder went out two minutes earlier.
feat(oliv): ported to Linux, so the Hyprland crowd can talk to their tiling WM.
The Omarchy/Hyprland port of OLIV started, and its dictation API was first deployed the same day.
OLIV: The Omarchy/Hyprland port of OLIV started, and its dictation API was first deployed the same day.
chore(schway): wrote my own coding agent, as one does.
First Schway commit. The first feature streamed headless Anthropic conversations through Schway's agent loop.
Schway: First Schway commit. The first feature streamed headless Anthropic conversations through Schway's agent loop.
fix(langswitch): macOS 27 broke Caps Lock. Fixed Caps Lock.
LangSwitch learned to read macOS 27's per-device hidutil tables, so the Caps Lock remap works again.
LangSwitch: LangSwitch learned to read macOS 27's per-device hidutil tables, so the Caps Lock remap works again.
release(jarn): v1.0.12. Last words.
J.A.R.N.'s final commit on main merged the v1.0.12 release prep. v1.0.11 had gone to PyPI earlier that day.
jarn: J.A.R.N.'s final commit on main merged the v1.0.12 release prep. v1.0.11 had gone to PyPI earlier that day.
feat(jarn)!: 1.0.0 GA candidate. The "!" was foreshadowing.
J.A.R.N. 1.0.0 was prepared as a GA candidate.
jarn: J.A.R.N. 1.0.0 was prepared as a GA candidate.
release(oliv): 0.1.11. Thai tech jargon comes back out as actual English.
OLIV 0.1.11 was released on GitHub. It got better at turning Thai-transcribed jargon back into English words.
OLIV: OLIV 0.1.11 was released on GitHub. It got better at turning Thai-transcribed jargon back into English words.
release(locked-in): v1.0.0 of a training plan I now have to follow.
Locked In reached its v1.0.0 production release.
Locked-in: Locked In reached its v1.0.0 production release.
feat(locked-in): scaffolded a running coach at 1 a.m. instead of sleeping.
First Locked In commit, at 01:07.
Locked-in: First Locked In commit, at 01:07.
feat(langswitch): someone else made Caps Lock useful. I made it show the right language.
My first LangSwitch commit: a custom input-source indicator on top of CapsLangSwitcher by Gamezxz.
LangSwitch: My first LangSwitch commit: a custom input-source indicator on top of CapsLangSwitcher by Gamezxz.
release(oliv): 0.1.0. First public build, signed and notarized.
OLIV 0.1.0 was released on GitHub, on what was then a separate releases repository.
OLIV: OLIV 0.1.0 was released on GitHub, on what was then a separate releases repository.
refactor(oliv): renamed Whispy to OLIV. The name was taken.
The product was renamed from Whispy to OLIV because of a name collision.
OLIV: The product was renamed from Whispy to OLIV because of a name collision.
feat(oliv): taught a Mac to understand Thai devs who say "deploy" in English.
First OLIV commit, back when it was called Whispy: local Thai and English push-to-talk dictation for macOS.
OLIV: First OLIV commit, back when it was called Whispy: local Thai and English push-to-talk dictation for macOS.
feat(vera): started a native app, because the web wasn't lonely enough.
Work on Vera's native mobile app began.
Vera: Work on Vera's native mobile app began.
chore(agents-irl): last commit. The desk pet sleeps now.
The ESP32-C3 port was merged: the last commit on agents-irl's main branch.
agents-irl: The ESP32-C3 port was merged: the last commit on agents-irl's main branch.
feat(jarn): v0.1.0, my first coding agent. Not my last. Unfortunately.
First J.A.R.N. commit (v0.1.0), published to PyPI the same evening.
jarn: First J.A.R.N. commit (v0.1.0), published to PyPI the same evening.
feat(agents-irl): ported the desk pet to a smaller chip. It got cuter.
The agents-irl firmware moved from a NodeMCU (ESP8266) to an ESP32-C3 SuperMini.
agents-irl: The agents-irl firmware moved from a NodeMCU (ESP8266) to an ESP32-C3 SuperMini.
feat(agents-irl): built a physical pet that panics when Claude is thinking.
First agents-irl commit: a hardware desk pet that reacts to AI coding-agent activity.
agents-irl: First agents-irl commit: a hardware desk pet that reacts to AI coding-agent activity.
feat(arsom-pos): a live view so the owner can watch the shop from anywhere.
Arsom POS got a live page where the shop owner sees the shop's current status.
Arsom POS: Arsom POS got a live page where the shop owner sees the shop's current status.
feat(arsom-pos): a POS for a massage shop. Queue fairness, now enforced by software.
First Arsom POS commit. Audit logging and staff settings followed the next morning.
Arsom POS: First Arsom POS commit. Audit logging and staff settings followed the next morning.
feat(calquest): "Initial commit: production-ready." Narrator: it was the first commit.
First CalQuest commit. Its literal message: "Initial commit: Calorie Quest production-ready".
CalQuest: First CalQuest commit. Its literal message: "Initial commit: Calorie Quest production-ready".
chore(vera): got a real domain. Commitment issues: resolved.
Vera moved to the veradating.app domain.
Vera: Vera moved to the veradating.app domain.
feat(vera): built a dating app. Three "Initial commit"s in one evening.
Vera's first commit was followed by two more "Initial commit" commits that evening.
Vera: Vera's first commit was followed by two more "Initial commit" commits that evening.
feat(cleancheck): initial commit, already v0.8.0-beta. v1.0.0 by teatime.
CleanCheck's first commit was titled "v0.8.0-beta". The version was bumped to v1.0.0 about four hours later.
CleanCheck: CleanCheck's first commit was titled "v0.8.0-beta". The version was bumped to v1.0.0 about four hours later.