Open Source

Fork With Provenance

Fork With Provenance

Codex became Codewith, Yazi became Open Yasa, Zellij became Open Mosaic — three forks, one paper trail each, and a rule for when a fork has earned the right to exist.

Forking is not stealing. Forking without provenance is.

I have forked three pieces of software that matter to how I work every day: OpenAI's Codex became Codewith, Yazi became Open Yasa, Zellij became Open Mosaic. All three keep the upstream license, credit the original authors in the README's second line, and ship a document that states exactly what changed. None of them pretend to be original work. That is the whole discipline, and it is smaller than people think and easier to skip than people admit.

Codewith is the biggest of the three, and the story behind it is not idealism, it is friction. I wanted multi-provider routing in my daily coding CLI — the ability to point the same harness at Claude, GLM, DeepSeek, Qwen, or Minimax depending on the task — and I could not get that upstream through a pull request. Codex is Codex. So I forked it instead of waiting.

The fork went through two names before it settled. It started as a straight Codex checkout in April, got renamed takumi for a few weeks while I figured out what it actually was, and became Codewith in June once the shape was clear: a multi-provider harness with a gateway layer sitting above the providers, not just a rebrand of somebody else's CLI. The README states the lineage in line two — a modified derivative of OpenAI's Codex, with a formal disclaimer that it is not associated with, sponsored by, or endorsed by OpenAI. A NOTICE file, third-party license files, a THIRD_PARTY_NOTICES.md, and the original LICENSE all ship alongside it. None of that is decorative. It is the paper trail that lets a stranger verify the claim instead of taking my word for it.

The takumi-to-Codewith rename was not a find-and-replace. It ran as a fleet workflow: spawn agents across every reference to the old name, preserve legacy fallback paths only where existing installs needed wire compatibility, run regression tests plus every CI-equivalent check available, run the secret scan, commit with conventional messages and explicit pathspecs, push to both remotes, then report the exact root causes of anything still red. It was scoped at 24 agents first, then scaled down to 6 once the surface area was clearer. Renaming a fork exhaustively, so no dangling reference to the old name lies to a future contributor, is part of the same provenance discipline as the NOTICE file — a fork that half-remembers its own name is a fork nobody can audit.

The document that matters most is MODIFICATIONS.md. It is not a changelog — it is a running account of exactly what diverges from upstream: branding, package names, local state paths, authentication profiles, provider configuration. Anyone auditing the fork can open one file and see the delta instead of diffing two codebases by hand. Writing that document is the tax you pay for forking. It is a small tax. Most forks never pay it, which is exactly why most forks cannot be trusted at a glance.

A fork earns its existence by going where upstream will not, or cannot. Codewith did not stop at multi-provider routing. It grew multi-profile subscription authentication with a usage-heartbeat daemon that auto-switches profiles the moment one hits a rate limit — I run well over a dozen subscription profiles across my machines, treated as a schedulable compute fleet, which is not a feature OpenAI has any reason to ship. Then a native primitives ladder no upstream Codex has: task, goal, chain of goals, goal plan, and workflow sitting above all of it, plus native scheduled loops. Then cross-session agent-to-agent mailboxes, so one agent can message another agent in a completely different session instead of only the sub-agents it personally spawned. Then a full native macOS app, built to pixel parity with the reference Codex app, with its own bugs and its own fixes — stopping an app-server fork bomb, surfacing failed turns, flushing the header under `ignoresSafeArea`. None of that was ever going to land in Codex. That is what the fork is for.

Sandboxing tells the same story in miniature. Codewith runs Seatbelt on macOS, Landlock plus bubblewrap on Linux, and a private-desktop sandbox on Windows — three different operating-system primitives, hardened independently, because a coding agent with shell access is a different threat model on each platform and upstream's defaults were not built around a fork that dispatches sixteen agents across five machines.

Forking also beats rewriting for a reason that has nothing to do with ideology. The Rust core underneath Codewith is still literally named codex-rs in the repository, and it represents work I did not have to redo: terminal rendering, streaming, process management, patch application, all of it hardened by another team over years, inherited for the cost of a git clone. The fork spends its own effort exclusively on the parts that make it different — the gateway, the subscription fleet, the mailbox — instead of re-discovering bugs Codex's own maintainers already found and fixed.

Owning a fork means owning bugs upstream never had, because the surface area you added is yours alone. After the rename, the app started reporting that 'the gpt-5.5 model requires a newer version of Codex' — the renamed binary was still announcing itself with old version metadata, so the provider-side check rejected it. Distribution had its own round: ENOENT errors extracting tarballs across the fork's own dependency packages, and bubblewrap user-namespace failures on some Linux hosts. None of that is glamorous. It is the actual cost of forking honestly — you inherit the plumbing along with the feature, and you fix the plumbing yourself instead of filing it upstream and waiting.

Running the fork like a real open-source project is its own discipline, separate from the legal paperwork. PR triage on hasna/codewith runs as a loop, working through dependabot bumps and TUI features and context-overflow recovery patches in numbered batches — one session triaged PRs 39 through 64 in a single pass, each one getting an adversarial review before merge. The changelog got built retroactively, on purpose, specifically so there would be a record of everything that happened since the fork point. A fork that cannot account for its own history has already lost the thing that made forking honest in the first place.

I liked Yazi before I ever forked it. Months earlier I was recommending it in public as the file manager to pair with a terminal-heavy agent workflow — good split panes, good defaults, nothing missing. That is the healthiest starting point for a fork: you fork tools you already trust and already use daily, not tools you are hoping will become useful once you have rewritten half of them.

Open Yasa is the smaller, cleaner example, because the divergence is narrower and easier to see whole. When I forked Yazi, the fork added exactly one thing: a machine-aware entry layer. Start it and you get a machine chooser; pick a remote machine and you browse it over sftp, with routes resolved live from my own machines package instead of a static config file. The README says the fork intentionally stays close to upstream Yazi. The MIT license and the original authorship are untouched. If you already know Yazi, you already know 95 percent of Open Yasa — which is exactly the point. The fork should be legible to anyone who has used the thing it came from.

Open Mosaic does to Zellij what Yasa does to Yazi, at a slightly larger scope, because a terminal multiplexer touches more surface than a file manager. It adds structured session and pane discovery, prompt delivery receipts, prompt queues, agent metadata, pane observation, and audit records — the plumbing an agentic terminal workspace needs that a human-first multiplexer never had a reason to build. The honest part is in its own status notes: some internals still use Zellij-derived names, stated plainly, because renaming them would break upstream sync for no benefit to anyone. That sentence is worth more than a hundred lines of legal boilerplate. It tells a contributor exactly where the seams are instead of hiding them under a fresh coat of branding.

Compare any of this to the other kind of "open" I see floated casually: decompiling a minified npm package because an AI makes taking it apart trivial now, then shipping the result with no attribution and no license trail. That is not forking. It produces working code and zero provenance — no way for anyone downstream to know what came from where, what license applies to which lines, or what the original authors intended. It optimizes for the same afternoon and sabotages every afternoon after it. A real fork is slower to set up and faster to trust for the rest of its life.

Provenance also protects the fork itself, not just the people evaluating it. A NOTICE file and a formal non-affiliation disclaimer are the difference between a documented derivative and an unlicensed clone the moment anyone with standing decides to look closely. I would rather spend an afternoon writing MODIFICATIONS.md than spend a month explaining after the fact why a rebrand looked like it was trying to hide where the code came from.

The test I actually apply before forking anything is simple: can I get this upstream instead? If yes, file the issue, send the PR, wait. If the answer is genuinely no — the maintainers have a different scope, a different business model, a different set of users than the one I'm building for — then fork, and pay the provenance tax on day one, not when someone asks. NOTICE file first. LICENSE preserved first. A MODIFICATIONS.md that starts empty and grows with every commit, not one written retroactively from memory six months in.

None of the three forks are static museum pieces frozen at the moment of divergence. Codewith keeps pulling from Codex where it makes sense and diverging harder where it doesn't. Yasa and Mosaic still sync upstream on purpose, because staying close to a healthy upstream is a feature, not a compromise — it means security patches and bug fixes upstream still reach you, and it means the fork's actual contribution stays legible instead of buried under an unrelated refactor.

A fork that earns its existence stops being described by what it forked from. Nobody asks me anymore whether Codewith is "basically Codex" once they've used the gateway layer, the subscription fleet, or the mailbox between two agents in different sessions. It is its own thing now, with a documented birth certificate. That is the outcome you are actually forking for — not a rebrand, a second life for software that would have stayed frozen if you had waited for permission.

Fork respectfully. Say so loudly. Keep the receipts even when nobody is checking. Especially when nobody is checking. That is the entire discipline, and it fits on one line because it is supposed to.

← Back to the articles

Newsletter

What we shipped, what broke,
and what we learned