<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
<channel>
<title>tcm blog</title>
<link>https://tcm.codes/blog/</link>
<atom:link href="https://tcm.codes/blog/rss.xml" rel="self" type="application/rss+xml"/>
<description>Writing about tcm: Unison's content-addressed codebase model, for plain TypeScript.</description>
<language>en</language>
<lastBuildDate>Sat, 07 Nov 2026 00:00:00 GMT</lastBuildDate>
<item>
<title>Introducing tcm</title>
<link>https://tcm.codes/blog/introducing-tcm.html</link>
<guid isPermaLink="true">https://tcm.codes/blog/introducing-tcm.html</guid>
<pubDate>Sat, 07 Nov 2026 00:00:00 GMT</pubDate>
<dc:creator>Andrew Lisowski</dc:creator>
<description>&lt;p&gt;tcm is a new way to store TypeScript. Instead of a folder of text files, your code lives in a &lt;strong&gt;codebase&lt;/strong&gt;: a
database of code. Each function, type and constant is stored on its own, under the hash of its code. Names are kept
apart from the code, as labels that point at those hashes.&lt;/p&gt;
&lt;p&gt;Writing code doesn&amp;#39;t change. You write ordinary TypeScript in a scratch file, in the editor you already use. Once it
typechecks, you add it to the codebase, which stores each definition in it. There&amp;#39;s no new language: Node runs the
stored code directly.&lt;/p&gt;
&lt;p&gt;Keeping names apart from code makes everyday edits simpler. A rename moves a label, so no code is edited and nothing
breaks. Changing a definition doesn&amp;#39;t leave the code that uses it behind, either. tcm checks each place that uses it
against the new version. The ones that still typecheck move to it, and the rest go on a todo list, with the reason.&lt;/p&gt;
&lt;h2 id=&quot;where-it-comes-from&quot;&gt;Where it comes from&lt;/h2&gt;
&lt;p&gt;Most of the model is &lt;a href=&quot;https://www.unison-lang.org&quot;&gt;Unison&lt;/a&gt;&amp;#39;s. Unison is a language built around storing code by its
hash, and it showed what that makes possible: free renames, changes that carry through, scratch files that show
values as you write, search by type, and history that knows a rename from an edit. tcm brings that model to
TypeScript, and keeps the compiler, packages and editors people already use.&lt;/p&gt;
&lt;p&gt;Sharing works as it does on &lt;a href=&quot;https://share.unison-lang.org&quot;&gt;Unison Share&lt;/a&gt;. Codebases are pushed and pulled by hash,
and a contribution is a branch, reviewed as a diff of definitions rather than lines of text.&lt;/p&gt;
&lt;h2 id=&quot;your-code-as-a-graph&quot;&gt;Your code as a graph&lt;/h2&gt;
&lt;p&gt;Each definition is stored with the hashes of what it uses, so a codebase is an exact graph of your code. A folder of
files is a rough version of that graph: import one function from a file, and you depend on the whole file. With the
exact graph, tcm knows what any change reaches, and much of what it does follows from that.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Tests run once.&lt;/strong&gt; A test&amp;#39;s result is kept with the hashes it reached. Only the tests a change reaches run again,
and results travel with the code when you push and pull.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Apps ship only what they use.&lt;/strong&gt; An app is bundled from what it reaches, so there&amp;#39;s no dead code to remove.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Code runs where it belongs.&lt;/strong&gt; Whether a definition runs on the server or in the browser is worked out from what
it uses. Browser code calls a server function by importing it, with no routes or fetch calls. React server
components work the same way, with no &lt;code&gt;&amp;quot;use client&amp;quot;&lt;/code&gt; or &lt;code&gt;&amp;quot;use server&amp;quot;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deploys don&amp;#39;t break open tabs.&lt;/strong&gt; Calls from the browser to the server go by hash, and earlier builds stay
served, so a tab keeps calling the code it loaded.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://tcm.codes/docs/claims.html&quot;&gt;What goes away&lt;/a&gt; goes through each of these, and where it stops.&lt;/p&gt;
&lt;h2 id=&quot;try-it&quot;&gt;Try it&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://tcm.codes/docs/getting-started.html&quot;&gt;Install tcm&lt;/a&gt; and take the &lt;a href=&quot;https://tcm.codes/docs/tutorial-codebase.html&quot;&gt;tutorial&lt;/a&gt;, or browse
&lt;a href=&quot;https://tcm.codes/forge/&quot;&gt;tcm&amp;#39;s own code&lt;/a&gt;. tcm is developed in a codebase of its own, and its docs and this blog are pages in it.&lt;/p&gt;
</description>
</item>
<item>
<title>Why Files</title>
<link>https://tcm.codes/blog/why-files.html</link>
<guid isPermaLink="true">https://tcm.codes/blog/why-files.html</guid>
<pubDate>Sat, 07 Nov 2026 00:00:00 GMT</pubDate>
<dc:creator>Andrew Lisowski</dc:creator>
<description>&lt;p&gt;The core idea behind tcm is that there are no files: your code is stored in a database (called a codebase).
But that raises the question: why do we store code in files at all?&lt;/p&gt;
&lt;p&gt;Well, the answer is kind of obvious: that&amp;#39;s just how computers work!
But that&amp;#39;s not the full story. Files are there because we put them there.
Files help us define something, organize similar things into groups, and then group those further into folders.
Seems necessary? Maybe not.&lt;/p&gt;
&lt;h2 id=&quot;the-downsides-of-files-for-code&quot;&gt;The downsides of files for code&lt;/h2&gt;
&lt;p&gt;So files and folders are (seemingly) good for organizing our code, but what baggage comes with them?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Placement comes with constraints&lt;/strong&gt; - Putting a bit of code in a package seems simple, right? Not really. That package might only work on the server, so code the client needs can&amp;#39;t go there. If you want that code on both the server and the client, you have to set up a third package to hold the shared code. You&amp;#39;ll also have to make sure that package stays isomorphic, or else your bundle might blow up or your server might crash.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Files need managing&lt;/strong&gt; - Is a value really used? We can try to rely on our tools, but cruft accumulates. Is the file too long? Too short? Too spread out? You need to decide ahead of time how much or how little should go where. That might make sense in the moment, but not as a project evolves.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Folders&lt;/strong&gt; - And once you have files, which folder do you put them in? Oh, that changed? Now countless files have to change. Just like with files, we have to anticipate the ideal structure, then suffer later when it inevitably turns out to be slightly the wrong shape.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&amp;#39;s a whole lotta problems that aren&amp;#39;t code!
Files and folders are littered with hurdles that have nothing to do with shipping code, just with organizing it to appease the beast.&lt;/p&gt;
&lt;h2 id=&quot;knowledge-bases&quot;&gt;Knowledge bases&lt;/h2&gt;
&lt;p&gt;An interesting thing about knowledge bases is that the less organization, the better!
Folders and organization are choices, and those choices mean constant maintenance and having to categorize things.
If you free yourself from that, and instead keep a single flat folder of files that organizes itself through the connections between them, you start to do a lot less work.&lt;/p&gt;
&lt;p&gt;Another concept found in knowledge bases is &amp;quot;evergreen notes&amp;quot;.
These notes are bite-sized concepts that you link together to form a web of thoughts and knowledge.
With this, you don&amp;#39;t repeat yourself much, but you have very detailed context embedded in the thoughts.&lt;/p&gt;
&lt;p&gt;Could we apply these principles to code?&lt;/p&gt;
&lt;h2 id=&quot;a-graph-of-values&quot;&gt;A graph of values&lt;/h2&gt;
&lt;p&gt;When you add code to your codebase, each value (types, constants, functions, classes) is stored as a row in a database.
If you follow their imports, you get a big graph of how all the code in your program connects.&lt;/p&gt;
&lt;p&gt;You can think of it just like a knowledge base.
Instead of a directory of files with relative links to each other, it&amp;#39;s a graph of bite-sized values.&lt;/p&gt;
&lt;p&gt;Apps, packages and scripts become subsections of the graph, picked out into whatever output format we want.
Need a package?
It materializes with the things you need, and none of the things you don&amp;#39;t.
Because we work in values, we don&amp;#39;t have to worry that an array lives in a server package: we just need the value.&lt;/p&gt;
&lt;p&gt;Suddenly, all the problems of files are gone! (There are, of course, many new problems caused by this.)
We didn&amp;#39;t need to anticipate the needs of the future with how we structured our code&amp;#39;s files.
Instead, our code can transform to meet the demands of the moment.&lt;/p&gt;
&lt;p&gt;Working on a feature? Pull all the relevant values into one file, or as many as you want.
The code can meet your needs right there, no planning needed.&lt;/p&gt;
&lt;h2 id=&quot;files-are-human&quot;&gt;Files are human&lt;/h2&gt;
&lt;p&gt;Files are ultimately a tool for humans.
Managing code the way tcm does, in a codebase, is a very different way of working.
It&amp;#39;s a bit easier to remember where a file is.
After working in a codebase for a while, you get to know the lay of the land: you remember where that function is stored, like a mark on a map.&lt;/p&gt;
&lt;p&gt;But that topology comes with constraints, and with our code as a graph, we can work around many of them.&lt;/p&gt;
</description>
</item>
</channel>
</rss>
