<?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>DEV Community: kgaidev</title>
    <description>The latest articles on DEV Community by kgaidev (@kgaidev).</description>
    <link>https://dev.to/kgaidev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4033763%2F00179adc-fab9-4243-9857-f17ac2ae902d.png</url>
      <title>DEV Community: kgaidev</title>
      <link>https://dev.to/kgaidev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kgaidev"/>
    <language>en</language>
    <item>
      <title>Why mem0, Graphiti and Cognee don't quite solve shared decision memory for Claude Code</title>
      <dc:creator>kgaidev</dc:creator>
      <pubDate>Thu, 30 Jul 2026 17:49:49 +0000</pubDate>
      <link>https://dev.to/kgaidev/why-mem0-graphiti-and-cognee-dont-quite-solve-shared-decision-memory-for-claude-code-3g7g</link>
      <guid>https://dev.to/kgaidev/why-mem0-graphiti-and-cognee-dont-quite-solve-shared-decision-memory-for-claude-code-3g7g</guid>
      <description>&lt;p&gt;You are three months into a codebase with Claude Code. You ask it to add search. It suggests Elasticsearch. Your team evaluated Elasticsearch in the spring, rejected it on cost, and moved on. Nothing in the repo says so, the person who made that call is on another team now, and the agent has no way to know. So you relitigate it, again.&lt;/p&gt;

&lt;p&gt;This is the part of AI-assisted development that nobody's tooling is quite solving. The agent writes code fluently. What it cannot do is remember why your code is the way it is, what your team already tried, and what got ruled out. That knowledge lives in people's heads and dead chat threads, and every new session starts from zero.&lt;/p&gt;

&lt;p&gt;The obvious move is to bolt on a memory layer. There are good ones. mem0, Graphiti and Cognee are the three you will run into first. They are all worth knowing. But if what you actually want is a shared record of your team's decisions wired into your coding agent, each of them solves a related problem, not that one, and getting them to do your job means taking on their complexity. Here is the honest version of why.&lt;/p&gt;

&lt;h2&gt;
  
  
  What these tools are built for
&lt;/h2&gt;

&lt;p&gt;All three are memory layers for agents and applications. Their job is to remember facts about a user or an agent, and to track how those facts change over time. That is a real and hard problem, and they are good at it. It is just a different problem from recording the decisions a team makes while building software.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mem0&lt;/strong&gt; is the easiest to reach for. It is a vector-first memory layer, Apache-2.0, with a hosted platform and a clean Claude Code integration over MCP that captures and recalls automatically. The catch for our use case is what it stores and how. It distills text into user-scoped facts, and when a new fact contradicts an old one it reconciles them by updating or removing the old fact. For personalization that is exactly right. For decision history it is the wrong shape, because the thing you most want to keep, the reason approach A was rejected, is the thing that gets overwritten.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Graphiti&lt;/strong&gt;, from the team behind Zep, is the richest of the three and the closest in spirit to what decision memory needs. It is a graph-first framework that builds a temporal knowledge graph. When new information contradicts an old fact it does not delete the old edge, it marks it invalid and keeps the time boundaries, so you can ask what was true then and what is true now. It also lets you define your own entity and edge types. That temporal, non-destructive model is genuinely the right primitive. The cost is operational. You run a graph database (Neo4j, FalkorDB or Neptune), an LLM and an embedding pipeline, and you ingest data as structured episodes. It is powerful, and it is a lot to stand up and keep running.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cognee&lt;/strong&gt; sits in between. It is an open-source memory engine, Apache-2.0, that turns data into a knowledge graph and can run anywhere from a single Postgres instance to a full graph-plus-vector stack. It has a Claude Code plugin and supports custom ontologies. What it does not have is built-in versioning or supersession of facts, so the part where a decision replaces an earlier one, with the earlier one preserved, is something you would build yourself.&lt;/p&gt;

&lt;h2&gt;
  
  
  The two gaps for team decision knowledge
&lt;/h2&gt;

&lt;p&gt;Strip away the differences and the same two gaps show up in all three.&lt;/p&gt;

&lt;p&gt;The first is semantic. None of them models a decision as a first-class thing. There is no built-in notion of a decision, its rationale, the alternatives that were considered and rejected, or a link from a new decision to the one it supersedes. You can approximate some of this by defining a custom ontology, most cleanly in Graphiti, but you are building the model, not using one.&lt;/p&gt;

&lt;p&gt;The second is operational. These are memory layers for facts, and to make one serve a whole team you have to run a shared, multi-author backend that everyone reads and writes, with some notion of review. That means a vector store, or a graph database, or both, plus an LLM doing extraction on every write, plus the service that fronts it. For a team that wanted its decisions to stop getting relitigated, that is a real infrastructure project before the first decision is even recorded.&lt;/p&gt;

&lt;p&gt;None of this is a knock on the tools. It is what happens when you use a general memory layer for a specific job it was not designed for.&lt;/p&gt;

&lt;h2&gt;
  
  
  What decision memory actually needs
&lt;/h2&gt;

&lt;p&gt;Write down what the coding-team use case really requires and the list is short and specific:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A decision as an immutable record, not a fact that gets edited in place&lt;/li&gt;
&lt;li&gt;The rationale attached to it, so the why survives the person who made the call&lt;/li&gt;
&lt;li&gt;Supersession as a first-class link, so a reversal keeps the old decision and the reason it died&lt;/li&gt;
&lt;li&gt;Rejected approaches and dead ends kept on purpose, because "we tried X, it cost us a day, here is why we stopped" is worth more than X quietly missing&lt;/li&gt;
&lt;li&gt;A shared store the whole team and their agents read and write&lt;/li&gt;
&lt;li&gt;All of it inside the coding loop, recalled before the agent touches an area and captured as decisions are made&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is a narrower target than "remember everything about the user," and narrowing it is what lets you skip most of the machinery.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where kgai is different
&lt;/h2&gt;

&lt;p&gt;We build kgai, so treat this as the interested party's account, but the design follows directly from that list.&lt;/p&gt;

&lt;p&gt;kgai is not a general memory layer, and that is the point. It records one thing, the structural decisions your team makes while coding, as an immutable graph. Every decision carries its rationale. When a decision is reversed the new one supersedes the old one by an explicit link, and the old one stays in history with the reason it died. Dead ends are kept on purpose. Recall returns only the decisions that are currently in force, so the agent reads the current picture before it changes code, and the superseded ones stay available when you are auditing why direction changed. The first issue ever filed on our own repo was that recall was handing back superseded decisions, which taught us the hard way that keeping dead ends and serving them are two separate problems.&lt;/p&gt;

&lt;p&gt;The operational story is the part that differs most from the tools above. kgai is local-first. The store lives inside your project directory. There is no vector database, no graph server, no embedding pipeline, and no service to operate. It installs as a Claude Code plugin in two commands. Capture happens in the session and a hook at the end of the turn catches anything the model forgot to record. The graph is rebuilt deterministically from the log, so the same decisions produce the same graph on every teammate's machine. Team sync is opt-in, over an S3 bucket you own, and it is conflict-aware rather than last-writer-wins. Git-remote sync is supported too but still experimental, so S3 is the path I would lean on today. Since 1.0 you can also set one machine-wide default remote with &lt;code&gt;kg remote --global&lt;/code&gt;, so each new project syncs without per-project setup. On a store of a million decisions across thirty writers, a decision lookup answers in about a hundred milliseconds. kgai hit 1.0 in July 2026, and from that release the on-disk log format, the &lt;code&gt;kg&lt;/code&gt; CLI surface and the JSON output shapes follow semver, so a breaking change to any of them means a major version bump. It is MIT licensed.&lt;/p&gt;

&lt;p&gt;The honest tradeoff is the flip side of the scope. If you want an agent to remember arbitrary facts, conversation history, or a user's preferences across products, kgai does not do that and mem0, Graphiti and Cognee do. Use them for that. kgai is for the case where the thing you keep losing is your team's decisions, and where standing up a memory service to hold them is more than you want to run.&lt;/p&gt;

&lt;h2&gt;
  
  
  Which to reach for
&lt;/h2&gt;

&lt;p&gt;If you need general agent or personal memory over changing facts, these are strong, and Graphiti in particular has the most serious model of time and history. If you specifically want your team's decisions, their rationale, their reversals and their dead ends to survive, recalled inside Claude Code without operating a backend, that narrower shape is what kgai is built for.&lt;/p&gt;

&lt;p&gt;The plugin is open source, stable as of v1.0.0, and installs in two commands. Details, the benchmark, and what still does not work well are on &lt;a href="https://kgai.dev/?ref=medium-compare" rel="noopener noreferrer"&gt;kgai.dev&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude plugin marketplace add kgaidev/kgai
claude plugin &lt;span class="nb"&gt;install &lt;/span&gt;kgai@kgai-marketplace
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>ai</category>
      <category>claude</category>
      <category>devtools</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Storing decisions instead of memory: the design behind kgai</title>
      <dc:creator>kgaidev</dc:creator>
      <pubDate>Sat, 18 Jul 2026 21:26:56 +0000</pubDate>
      <link>https://dev.to/kgaidev/storing-decisions-instead-of-memory-the-design-behind-kgai-26dk</link>
      <guid>https://dev.to/kgaidev/storing-decisions-instead-of-memory-the-design-behind-kgai-26dk</guid>
      <description>&lt;p&gt;Coding agents have a specific failure mode on long-lived codebases. Every few sessions the agent re-proposes something the team already evaluated and rejected. It reads the code, sees a slow search query, and suggests Elasticsearch. The reason Elasticsearch was rejected months ago exists only in a chat thread, so from the agent's point of view the question was never settled.&lt;/p&gt;

&lt;p&gt;Humans on the team hit the same wall in slower motion. &lt;code&gt;git blame&lt;/code&gt; tells you who changed a line and when, the PR tells you what was merged, but neither records why the other approach lost. The reviewer who knew leaves the team, and six months later someone re-litigates the whole thing in a new PR.&lt;/p&gt;

&lt;p&gt;This post describes how kgai (&lt;a href="https://github.com/kgaidev/kgai" rel="noopener noreferrer"&gt;https://github.com/kgaidev/kgai&lt;/a&gt;, MIT) approaches that as a data problem inside the dev workflow, and which properties fall out of the design. No prior knowledge of knowledge graphs is assumed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data model: boxes and arrows
&lt;/h2&gt;

&lt;p&gt;A knowledge graph here means nothing more than a map of things and connections. The things are the parts of a codebase as you'd sketch them in a design review:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fop6hh7xrug3mk80mnqcb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fop6hh7xrug3mk80mnqcb.png" alt="Elements of a codebase connected by labeled links, with properties on the side" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Each box is an element. Elements carry properties, like &lt;code&gt;search-api.retry_policy = "idempotency-key + backoff"&lt;/code&gt;. That's the entire vocabulary: elements, links, properties. It lives in &lt;code&gt;&amp;lt;project&amp;gt;/.kgai/store&lt;/code&gt;, next to the code it describes, one store per repo.&lt;/p&gt;

&lt;p&gt;The graph itself is not the interesting part. The interesting part is where it comes from.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decisions as the source of truth
&lt;/h2&gt;

&lt;p&gt;A bank doesn't store an account balance as a number that gets edited. It stores a list of transactions, and the balance is derived by summing them. A transaction, once recorded, is never modified. Corrections are new transactions.&lt;/p&gt;

&lt;p&gt;kgai applies the same structure to a codebase's architecture. The current shape (the graph above) is the derived value. The recorded facts are decisions, captured during the session in which they were made:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ recorded "Search retries use idempotency keys + exponential backoff"
    why: fixed 3x retry double-charged a request during a provider brownout
    sets search-api.retry_policy = "idempotency-key + backoff"
    supersedes "Simple 3x retry is enough"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A decision states what changed, why, and which elements it touches. The queryable graph is computed by replaying the decision log from the beginning. Deleting the graph and replaying the log yields byte-identical results, so the log is the truth and the graph is a disposable cache.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpnufl0yo6d21dshn4zyx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fpnufl0yo6d21dshn4zyx.png" alt="An append-only decision log replayed into a derived graph" width="800" height="366"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is event sourcing, the same pattern financial systems use. Applied here, the "account" is the reasoning behind a repo.&lt;/p&gt;

&lt;p&gt;Supersession instead of edits&lt;br&gt;
A decision is never updated. A change is expressed as a new decision that supersedes the old one. The old decision remains in the log, marked superseded:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kg &lt;span class="nb"&gt;history&lt;/span&gt; &lt;span class="s2"&gt;"feature:search-api"&lt;/span&gt;
feature:search-api — 2 decisions, oldest first

  2026-05-02  Simple 3x retry is enough                                superseded
      why: provider timeouts are rare, simplest thing that works

  2026-07-16  Search retries use idempotency keys + backoff            ● current
      why: fixed 3x retry double-charged a request during a brownout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fej1plkak1re9xewmlr1z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fej1plkak1re9xewmlr1z.png" alt="A superseded decision pointing to the current one, history keeps both, context serves one" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two properties follow.&lt;/p&gt;

&lt;p&gt;Rejected paths stay recorded. When a teammate opens a PR that swaps the retry logic back to something simpler, the review comment writes itself: the graph holds the incident that killed that approach. The same applies to QA reading unexpected behavior, or to the new hire asking why the API boundary sits where it sits. The answer is one query away instead of one departed colleague away.&lt;/p&gt;

&lt;p&gt;Recall stays clean. When an agent asks what's decided about an area, it receives only the current head decisions. Superseded decisions are reachable through history but are not injected into the model's context. This matters in practice: a language model given two contradictory rationales will sometimes follow the outdated one. Serving only the current state removes that failure mode while keeping the full record.&lt;/p&gt;

&lt;h2&gt;
  
  
  Idempotence and what it means for a dev team
&lt;/h2&gt;

&lt;p&gt;An operation is idempotent when performing it twice has the same effect as performing it once. An elevator button is idempotent.&lt;/p&gt;

&lt;p&gt;In kgai a decision's identity is a hash of its content. Recording the same decision twice, from two machines, in any order, converges to a single record, because identical content produces an identical id. There is no sequence counter to coordinate and no last-writer-wins overwrite.&lt;/p&gt;

&lt;p&gt;The consequence for a team: every dev's agent appends to its own log file, and sync is a union of logs over plain git or an S3 bucket. Textual merge conflicts cannot occur, because nothing is ever edited in place. Every machine replays the combined log and arrives at the same graph deterministically. Nobody maintains a wiki, nobody merges anybody's notes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frwyhwjnrgbxo7qafadg0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Frwyhwjnrgbxo7qafadg0.png" alt="Two developers' logs synced through git or S3 into byte-identical graphs" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The only conflict that can exist is a semantic one. Two devs on two branches genuinely decided the same thing differently, say Alice put session state in Redis while Bob kept it in-process. Both decisions stand in the log and the element then has two current heads, which kg conflicts reports, typically surfacing at review time. Resolution is one more decision that supersedes both. The disagreement and its resolution both remain in history, which is occasionally more useful than the resolution itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Performance characteristics
&lt;/h2&gt;

&lt;p&gt;An append-only log grows forever, which sounds like a scaling problem. It isn't, because queries never touch the log. Reads go to the derived graph, which lives in an embedded property graph database (Kuzu) inside the project directory. Writes are file appends. Rebuilds stream the log through a bulk loader rather than applying events one at a time.&lt;/p&gt;

&lt;p&gt;Measured on stores larger than a real team produces, one million decisions across fifty thousand elements written by thirty concurrent users:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;store size&lt;/th&gt;
&lt;th&gt;everyday sync&lt;/th&gt;
&lt;th&gt;cold clone&lt;/th&gt;
&lt;th&gt;full rebuild&lt;/th&gt;
&lt;th&gt;lookup&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;20k decisions&lt;/td&gt;
&lt;td&gt;&amp;lt; 0.5 s&lt;/td&gt;
&lt;td&gt;~3 s&lt;/td&gt;
&lt;td&gt;~1.5 s&lt;/td&gt;
&lt;td&gt;~60 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100k decisions&lt;/td&gt;
&lt;td&gt;&amp;lt; 0.5 s&lt;/td&gt;
&lt;td&gt;~12 s&lt;/td&gt;
&lt;td&gt;~6 s&lt;/td&gt;
&lt;td&gt;~60 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1M decisions&lt;/td&gt;
&lt;td&gt;~2 s&lt;/td&gt;
&lt;td&gt;&amp;lt; 2 min&lt;/td&gt;
&lt;td&gt;&amp;lt; 1 min&lt;/td&gt;
&lt;td&gt;~100 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Focfyn0fgkk0l8u54h48w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Focfyn0fgkk0l8u54h48w.png" alt="Lookup latency stays flat from 20k to 1M decisions" width="800" height="297"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cold clone is the onboarding path: a new teammate pulls the full decision history and has a queryable graph in seconds on a normal-sized store. These are single-run wall-clock numbers from our harness on our hardware, not percentiles. The raw runs are archived in the repo. Query latency stays flat with history size because the graph holds only current state.&lt;/p&gt;

&lt;p&gt;The read path contains no vector search and no LLM call. Retrieval is scoped by element and path identifiers, so recall is deterministic and adds no token cost beyond the decisions themselves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capture is enforced, not requested
&lt;/h2&gt;

&lt;p&gt;Decisions enter the log during normal coding sessions. Today that's wired into Claude Code as a plugin, and the engine is a single CLI, so any agent environment that can run a command can use it. When a session that edited code ends, a hook blocks the agent until it either records the structural decision it made or explicitly states there was none. This is deterministic by design. In testing, unprompted capture by the model alone proved unreliable, so the capture step is enforced at the hook level. Trivial changes (renames, formatting, bug fixes) record nothing, which keeps the log at decision granularity rather than becoming a diary.&lt;/p&gt;

&lt;p&gt;Before modifying an area, the agent queries the graph for decisions relevant to the files it's about to touch. The Elasticsearch case from the beginning then resolves differently: the agent finds the rejection and its reasoning, and works within it. So does the next dev who asks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boundaries
&lt;/h2&gt;

&lt;p&gt;The design has edges worth knowing. Free-text search over a very large store scans the corpus (about 1.4 s at 100k decisions), an index for that is planned. A 1M-decision log is roughly 790 MB on disk. Prebuilt engine binaries exist for Linux and macOS, not Windows.&lt;/p&gt;

&lt;p&gt;Everything runs locally. Sync targets are a git remote or an S3 bucket the team owns. The engine, plugin and benchmark harness are MIT: &lt;a href="https://github.com/kgaidev/kgai" rel="noopener noreferrer"&gt;https://github.com/kgaidev/kgai&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>opensource</category>
      <category>softwaredesign</category>
    </item>
  </channel>
</rss>
