<?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: Ramu Narasinga</title>
    <description>The latest articles on DEV Community by Ramu Narasinga (@ramunarasinga-11).</description>
    <link>https://dev.to/ramunarasinga-11</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%2F392818%2Fcc9dbd66-5cc2-4591-8c1c-6c650a374161.jpeg</url>
      <title>DEV Community: Ramu Narasinga</title>
      <link>https://dev.to/ramunarasinga-11</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ramunarasinga-11"/>
    <language>en</language>
    <item>
      <title>`acquireLock` function in claude-context codebase.</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Thu, 02 Jul 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/acquirelock-function-in-claude-context-codebase-39io</link>
      <guid>https://dev.to/ramunarasinga-11/acquirelock-function-in-claude-context-codebase-39io</guid>
      <description>&lt;p&gt;In this article, we review &lt;code&gt;acquireLock&lt;/code&gt; function in claude-context codebase. You will learn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is claude-context?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;acquireLock&lt;/code&gt; function explained.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2F7surk1jnbg859fgezms0.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%2F7surk1jnbg859fgezms0.png" width="800" height="631"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is claude-context?
&lt;/h2&gt;

&lt;p&gt;Make entire codebase the context for any coding agent using claude-context. Claude Context is an MCP plugin that adds semantic code search to Claude Code and other AI coding agents, giving them deep context from your entire codebase.&lt;/p&gt;

&lt;p&gt;🧠 Your Entire Codebase as Context: Claude Context uses semantic search to find all relevant code from millions of lines. No multi-round discovery needed. It brings results straight into the Claude’s context.&lt;/p&gt;

&lt;p&gt;💰 Cost-Effective for Large Codebases: Instead of loading entire directories into Claude for every request, which can be very expensive, Claude Context efficiently stores your codebase in a vector database and only uses related code in context to keep your costs manageable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;p&gt;Use the command line interface to add the Claude Context MCP server:&lt;br&gt;
&lt;/p&gt;

&lt;p&gt;```plaintextclaude mcp add claude-context \&lt;br&gt;
  -e OPENAI_API_KEY=sk-your-openai-api-key \&lt;br&gt;
  -e MILVUS_ADDRESS=your-zilliz-cloud-public-endpoint \&lt;br&gt;
  -e MILVUS_TOKEN=your-zilliz-cloud-api-key \&lt;br&gt;
  -- npx @zilliz/claude-context-mcp@latest&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;


### Why I chose to write about acquireLock?

As I was reading thru the claude-context source code, I came across the concepts like saving snapshot. Saving where? I asked this question and looked into the function implementation.

Below is a code snippet from [handler.ts,](https://github.com/zilliztech/claude-context/blob/master/packages/mcp/src/handlers.ts#L324) showing how the saveCodebaseSnapshot is invoked.



```javascript
// Check if already indexing
if (this.snapshotManager.getIndexingCodebases().includes(absolutePath)) {
    if (forceReindex) {
        console.log(`[FORCE-REINDEX] Clearing stale indexing state for '${absolutePath}'`);
        this.snapshotManager.removeCodebaseCompletely(absolutePath);
        this.snapshotManager.saveCodebaseSnapshot();
    } else {
        return {
            content: [{
                type: "text",
                text: `Codebase '${absolutePath}' is already being indexed in the background. Please wait for completion.`
            }],
            isError: true
        };
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  saveCodebaseSnapshot
&lt;/h3&gt;

&lt;p&gt;Below is the code snippet picked from the &lt;a href="https://github.com/zilliztech/claude-context/blob/master/packages/mcp/src/snapshot.ts#L603" rel="noopener noreferrer"&gt;snapshot.ts&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kr"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;saveCodebaseSnapshot&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[SNAPSHOT-DEBUG] Saving codebase snapshot to:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snapshotFilePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locked&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;acquireLock&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;locked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;warn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[SNAPSHOT-DEBUG] Failed to acquire lock, saving without lock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Ensure directory exists&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;snapshotDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snapshotFilePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;existsSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snapshotDir&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;snapshotDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
          &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[SNAPSHOT-DEBUG] Created snapshot directory:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;snapshotDir&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I mean, snapshot is written to your local file system. Claude-Context uses file system to keep track of codebase indexing, is what I figured looking at some of the files and the way file-system was used.&lt;/p&gt;

&lt;p&gt;Since we now understand what led to finding this acquireLock function, let’s take a look at this function, &lt;code&gt;acquireLock&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;acquireLock&lt;/code&gt; function explained.
&lt;/h2&gt;

&lt;p&gt;acquireLock is defined in &lt;a href="https://github.com/zilliztech/claude-context/blob/master/packages/mcp/src/snapshot.ts#L555" rel="noopener noreferrer"&gt;claude-context/packages/mcp/snapshot.ts at L555&lt;/a&gt; as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kr"&gt;private&lt;/span&gt; &lt;span class="nf"&gt;acquireLock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;maxRetries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;retryInterval&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lockPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;snapshotFilePath&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.lock&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;maxRetries&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lockPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Check for stale lock (&amp;gt; 10 seconds old)&lt;/span&gt;
            &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;statSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lockPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mtimeMs&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rmdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lockPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                    &lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// retry after removing stale lock&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* lock was removed by another process */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="c1"&gt;// Busy wait and retry&lt;/span&gt;
            &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;waitUntil&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;retryInterval&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;waitUntil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* busy wait */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It creates a lock file using the snapshotFilePath with .lock extension and then returns true. &lt;code&gt;mkdirsync&lt;/code&gt; synchronously creates a directory. Returns undefined, or if recursive is true, the first directory path created. This is the synchronous version of mkdir.&lt;/p&gt;

&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/zilliztech/claude-context/blob/master/packages/mcp/src/snapshot.ts#L555" rel="noopener noreferrer"&gt;zilliztech/claude-context/packages/mcp/src/snapshot.ts#L555&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/zilliztech/claude-context/blob/master/packages/mcp/src/snapshot.ts#L603" rel="noopener noreferrer"&gt;zilliztech/claude-context/packages/mcp/src/snapshot.ts#L603&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>opensource</category>
      <category>codebase</category>
      <category>context</category>
      <category>claude</category>
    </item>
    <item>
      <title>Hunk, terminal diffs for humans and agents.</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Wed, 24 Jun 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/hunk-terminal-diffs-for-humans-and-agents-3kab</link>
      <guid>https://dev.to/ramunarasinga-11/hunk-terminal-diffs-for-humans-and-agents-3kab</guid>
      <description>&lt;p&gt;In this article, we review what a hunk library is. You will learn: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is Hunk?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Modem&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2F1vzeshgv3cf93pju4mjh.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%2F1vzeshgv3cf93pju4mjh.png" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Hunk??
&lt;/h2&gt;

&lt;p&gt;Hunk is a review-first terminal diff viewer for agent-authored changesets, built on &lt;a href="https://github.com/anomalyco/opentui" rel="noopener noreferrer"&gt;OpenTUI &lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/@pierre/diffs" rel="noopener noreferrer"&gt;Pierre diffs.&lt;/a&gt;. &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%2Ff7eyflyl8o9hm779z7ag.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%2Ff7eyflyl8o9hm779z7ag.png" width="800" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;multi-file review stream with sidebar navigation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;inline AI and agent annotations beside the code&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;split, stack, and responsive auto layouts&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;watch mode for auto-reloading file and Git-backed reviews&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;keyboard, mouse, pager, and Git difftool support&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Quick start
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;hunk           # show help
hunk --version # print the installed version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Working with Git
&lt;/h3&gt;

&lt;p&gt;Hunk mirrors Git’s diff-style commands, but opens the changeset in a review UI instead of plain text.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;hunk&lt;/span&gt; &lt;span class="nx"&gt;diff&lt;/span&gt;                      &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;review&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt; &lt;span class="nx"&gt;repo&lt;/span&gt; &lt;span class="nx"&gt;changes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;including&lt;/span&gt; &lt;span class="nx"&gt;untracked&lt;/span&gt; &lt;span class="nx"&gt;files&lt;/span&gt;
&lt;span class="nx"&gt;hunk&lt;/span&gt; &lt;span class="nx"&gt;diff&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;watch&lt;/span&gt;              &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;auto&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;reload&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;working&lt;/span&gt; &lt;span class="nx"&gt;tree&lt;/span&gt; &lt;span class="nx"&gt;changes&lt;/span&gt;
&lt;span class="nx"&gt;hunk&lt;/span&gt; &lt;span class="nx"&gt;show&lt;/span&gt;                      &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;review&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;latest&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt;
&lt;span class="nx"&gt;hunk&lt;/span&gt; &lt;span class="nx"&gt;show&lt;/span&gt; &lt;span class="nx"&gt;HEAD&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;               &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;review&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;earlier&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Working with agents
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Open Hunk in another terminal with hunk diff or hunk show.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Tell your agent to add the skill file returned by hunk skill path.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ask your agent to use the skill against the live Hunk session.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A good generic prompt is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Load the Hunk skill and use it for this review. Run `hunk skill path` to get the skill path.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Learn more about &lt;a href="https://www.hunk.dev/" rel="noopener noreferrer"&gt;hunk.dev/.&lt;/a&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Modem
&lt;/h2&gt;

&lt;p&gt;Hunk is an opensource library authored by Modem. Modem captures every piece of customer feedback your team gets — from Slack, Linear, GitHub, Intercom, and PostHog — and triages it automatically so engineers spend less time PMing and more time shipping.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build what’s actually important
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Every bug report, every feature request, automatically clustered and prioritized&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Unified company &amp;amp; user profiles to understand who matters and who can wait&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Spot emerging trends before they become fires&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Act on problems you didn’t know you had
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Get alerted to user concerns as they happen, not days later&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create detailed tickets automatically or straight from chat&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Delegate tasks to coding agents with the context they need to be successful&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Learn more about &lt;a href="https://modem.dev/" rel="noopener noreferrer"&gt;Modem.&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/modem-dev/hunk" rel="noopener noreferrer"&gt;github.com/modem-dev/hunk&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.hunk.dev/" rel="noopener noreferrer"&gt;hunk.dev/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://modem.dev/" rel="noopener noreferrer"&gt;modem.dev/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>hunk</category>
      <category>modem</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>`undici.setGlobalDispatcher` function in pi-coding-agent package.</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Thu, 18 Jun 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/undicisetglobaldispatcher-function-in-pi-coding-agent-package-3cl7</link>
      <guid>https://dev.to/ramunarasinga-11/undicisetglobaldispatcher-function-in-pi-coding-agent-package-3cl7</guid>
      <description>&lt;p&gt;In this article, we review undici.setGlobalDispatcher function in &lt;a href="https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/http-dispatcher.ts#L54C2-L54C28" rel="noopener noreferrer"&gt;earendil-works/pi/packages/coding-agent.&lt;/a&gt; You will learn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is pi-coding-agent?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;What is Undici?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;setGlobalDispatcher method in pi-coding-agent&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2Fpax0p73pn747fp5dodfh.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%2Fpax0p73pn747fp5dodfh.png" width="800" height="595"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is pi-coding-agent?
&lt;/h2&gt;

&lt;p&gt;Pi is a minimal agent harness. Adapt Pi to your workflows, not the other way around. Customize Pi with &lt;a href="https://github.com/earendil-works/pi/tree/main/packages/coding-agent#extensions" rel="noopener noreferrer"&gt;extensions&lt;/a&gt;, &lt;a href="https://github.com/earendil-works/pi/tree/main/packages/coding-agent#skills" rel="noopener noreferrer"&gt;skills&lt;/a&gt;, &lt;a href="https://github.com/earendil-works/pi/tree/main/packages/coding-agent#prompt-templates" rel="noopener noreferrer"&gt;prompt templates&lt;/a&gt; and &lt;a href="https://github.com/earendil-works/pi/tree/main/packages/coding-agent#themes" rel="noopener noreferrer"&gt;themes&lt;/a&gt;. Bundle them as &lt;a href="https://pi.dev/packages" rel="noopener noreferrer"&gt;Pi packages&lt;/a&gt; and share via npm or git.&lt;/p&gt;

&lt;p&gt;Pi ships with powerful defaults but skips features like sub-agents and plan mode. Ask Pi to build what you want, or install a package that does it your way.&lt;/p&gt;

&lt;p&gt;Four modes: interactive, print/JSON, &lt;a href="https://github.com/earendil-works/pi/tree/main/packages/coding-agent#programmatic-usage" rel="noopener noreferrer"&gt;RPC, and SDK.&lt;/a&gt;. See &lt;a href="https://github.com/OpenClaw/OpenClaw" rel="noopener noreferrer"&gt;OpenClaw&lt;/a&gt; for a real-world integration.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Learn more about &lt;a href="https://pi.dev/" rel="noopener noreferrer"&gt;pi-coding-agent.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What is&amp;nbsp;Undici?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/undici" rel="noopener noreferrer"&gt;Undici&lt;/a&gt; is a fast, modern HTTP/1.1 and HTTP/2 client written from scratch for Node.js. Maintained by the Node.js core team, it serves as the underlying engine that powers Node's built-in fetch global API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Use the Standalone Package?
&lt;/h3&gt;

&lt;p&gt;While Node.js embeds a version of Undici internally, installing it explicitly from the undici npm page gives you distinct advantages: [ &lt;a href="https://www.npmjs.com/package/undici?activeTab=versions" rel="noopener noreferrer"&gt;1&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/undici" rel="noopener noreferrer"&gt;2&lt;/a&gt;. ]&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Advanced Features: Access specialized clients like ProxyAgent, Socks5Agent, and MockAgent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maximum Performance: Use the low-level undici.request function for faster request handling than standard fetch.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Connection Pooling: Configure and optimize connection limits and keep-alive behaviors manually.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HTTP Pipelining: Enable concurrent request pipelining over a single connection.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Latest Updates: Receive bug fixes, performance updates, and security patches without waiting for a full Node.js runtime upgrade. [ &lt;a href="https://undici.nodejs.org/" rel="noopener noreferrer"&gt;1&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/undici/v/4.0.0-rc.4" rel="noopener noreferrer"&gt;2&lt;/a&gt;, &lt;a href="https://github.com/nodejs/undici/discussions/2371" rel="noopener noreferrer"&gt;3&lt;/a&gt;, &lt;a href="https://www.npmjs.com/package/undici" rel="noopener noreferrer"&gt;4&lt;/a&gt;, &lt;a href="https://blog.platformatic.dev/http-fundamentals-understanding-undici-and-its-working-mechanism" rel="noopener noreferrer"&gt;5&lt;/a&gt;. ]&lt;/p&gt;&lt;/li&gt;
&lt;/ul&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%2F0lqxcpjr7euileo5rn34.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%2F0lqxcpjr7euileo5rn34.png" width="799" height="485"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Learn more about &lt;a href="https://www.npmjs.com/package/undici" rel="noopener noreferrer"&gt;Undici&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  setGlobalDispatcher method in pi-coding-agent
&lt;/h2&gt;

&lt;p&gt;well, to understand why this method used in pi-coding-agent, we need to first check the official docs for this.&lt;/p&gt;

&lt;h3&gt;
  
  
  undici.setGlobalDispatcher(dispatcher)
&lt;/h3&gt;

&lt;p&gt;Sets the global dispatcher used by Common API Methods. Global dispatcher is shared among compatible undici modules, including undici that is bundled internally with node.js.&lt;/p&gt;

&lt;p&gt;Undici stores this dispatcher under Symbol.for('undici.globalDispatcher.2').&lt;/p&gt;

&lt;p&gt;setGlobalDispatcher() also mirrors the configured dispatcher to Symbol.for('undici.globalDispatcher.1') using Dispatcher1Wrapper, so Node.js built-in fetch can keep using the legacy handler contract while Undici uses the new handler API.&lt;/p&gt;

&lt;p&gt;Below is an example I picked from the Undici module docs&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setGlobalDispatcher&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;undici&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Use undici.request for maximum performance&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Or use undici.fetch with custom configuration&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Agent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;keepAliveTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nf"&gt;setGlobalDispatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://api.example.com/data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way, you can set your custom configuration and dispatch globally so the fetch uses the configuration dispatched. With this info, let's take a closer look at pi-coding-agent's usage.&lt;/p&gt;

&lt;p&gt;The below code snippet is picked from &lt;a href="https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/http-dispatcher.ts#L54C2-L54C28" rel="noopener noreferrer"&gt;pi/packages/coding-agent/src/core/http-dispatcher.ts.&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;configureHttpDispatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timeoutMs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_HTTP_IDLE_TIMEOUT_MS&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;normalizedTimeoutMs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;parseHttpIdleTimeoutMs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timeoutMs&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;normalizedTimeoutMs&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Invalid HTTP idle timeout: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timeoutMs&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="nx"&gt;undici&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setGlobalDispatcher&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;undici&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;EnvHttpProxyAgent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
   &lt;span class="na"&gt;allowH2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;bodyTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;normalizedTimeoutMs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;headersTimeout&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;normalizedTimeoutMs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
 &lt;span class="p"&gt;);&lt;/span&gt;
 &lt;span class="c1"&gt;// Keep fetch and the dispatcher on the same undici implementation. Node 26.0's&lt;/span&gt;
 &lt;span class="c1"&gt;// bundled fetch can otherwise consume compressed responses through npm undici's&lt;/span&gt;
 &lt;span class="c1"&gt;// dispatcher without decompressing them, causing response.json() failures.&lt;/span&gt;
 &lt;span class="c1"&gt;// If a caller replaced fetch after module load, preserve that deliberate override.&lt;/span&gt;
 &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shouldInstallGlobals&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;installedGlobalFetch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
   &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;originalGlobalFetch&lt;/span&gt;
   &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;installedGlobalFetch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;shouldInstallGlobals&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;undici&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="p"&gt;?.();&lt;/span&gt;
  &lt;span class="nx"&gt;installedGlobalFetch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;globalThis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Just like what we learnt, there is a custom configuration applied and dispatched:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;new undici.EnvHttpProxyAgent({
   allowH2: false,
   bodyTimeout: normalizedTimeoutMs,
   headersTimeout: normalizedTimeoutMs,
}),
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and this comment explains why this was configured this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Keep fetch and the dispatcher on the same undici implementation. Node 26.0's
// bundled fetch can otherwise consume compressed responses through npm undici's
// dispatcher without decompressing them, causing response.json() failures.
// If a caller replaced fetch after module load, preserve that deliberate override.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/earendil-works/pi/blob/main/packages/coding-agent/src/core/http-dispatcher.ts#L54C2-L54C28" rel="noopener noreferrer"&gt;earendil-works/pi/packages/coding-agent/src/core/http-dispatcher.ts#L54C2-L54C28&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://pi.dev/" rel="noopener noreferrer"&gt;pi.dev/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.npmjs.com/package/undici" rel="noopener noreferrer"&gt;npmjs.com/package/undici&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>pi</category>
      <category>ai</category>
      <category>opensource</category>
      <category>undici</category>
    </item>
    <item>
      <title>How to build a custom Claude plugin?</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Thu, 18 Jun 2026 15:00:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/how-to-build-a-custom-claude-plugin-5621</link>
      <guid>https://dev.to/ramunarasinga-11/how-to-build-a-custom-claude-plugin-5621</guid>
      <description>&lt;p&gt;In this article, you will learn how to build a custom Claude plugin. We will look at the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is a Claude plugin?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Build a simple Claude plugin.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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%2F37pief5796rhzzfmyt42.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%2F37pief5796rhzzfmyt42.png" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is a Claude plugin?
&lt;/h2&gt;

&lt;p&gt;You can create custom plugins to extend Claude Code with skills, agents, hooks, and MCP servers. Plugins let you extend Claude Code with custom functionality that can be shared across projects and teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  When to use a plugin?
&lt;/h3&gt;

&lt;p&gt;You can use a plugin when you want to share directories containing skills, agents, hooks etc., with teammates, things that are reusable across projects.&lt;/p&gt;

&lt;p&gt;There is a also a standalone configuration, defined in .claude folder and this can be specific to a project, can include personal workflows or for quick experiments.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Learn more about &lt;a href="https://code.claude.com/docs/en/plugins#when-to-use-plugins-vs-standalone-configuration" rel="noopener noreferrer"&gt;when to use a plugin vs standalone configuration.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s build a simple plugin following the &lt;a href="https://code.claude.com/docs/en/plugins#quickstart" rel="noopener noreferrer"&gt;official docs quick start guide.&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build a simple Claude plugin
&lt;/h2&gt;

&lt;p&gt;There are 5 steps involved to create your first plugin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create the plugin directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mkdir&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This folder can contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Skills&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agents or hooks&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;optionally, a .claude-plugin/plugin.json manifest&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Create the plugin manifest.
&lt;/h3&gt;

&lt;p&gt;You will define the metadata such as name, description, and version of your plugin. In plugin manager, this info is used by Claude Code to display your plugin.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// run this first&lt;/span&gt;
&lt;span class="nx"&gt;mkdir&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;claude&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then add this to &lt;code&gt;my-first-plugin/.claude-plugin/plugin.json&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my-first-plugin&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;description&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A greeting plugin to learn the basics&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;version&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1.0.0&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;author&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Your Name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Learn more about the &lt;a href="https://code.claude.com/docs/en/plugins-reference#plugin-manifest-schema" rel="noopener noreferrer"&gt;manifest schema.&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Add a skill
&lt;/h3&gt;

&lt;p&gt;Skills are added in the skills/ directory. Folder name becomes the skill name. First, create the skills directory in your plugin folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;mkdir&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;my&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;first&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;plugin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;skills&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;helloaxios&lt;/span&gt; &lt;span class="nx"&gt;zustand&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then create the SKILL.md file in &lt;code&gt;my-first-plugin/skills/hello/&lt;/code&gt; folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
description: "Greet the user with a friendly message"
disable-model-invocation: true
---

Greet the user warmly and ask how you can help them today.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test your plugin
&lt;/h3&gt;

&lt;p&gt;You need to load your plugin by running the below command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;claude --plugin-dir ./my-first-plugin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the Claude Code starts, you can try your new skill by running the below command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/my-first-plugin:hello
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll see Claude respond with a greeting. Run /help to see your skill listed under the plugin namespace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a skill argument
&lt;/h3&gt;

&lt;p&gt;You can pass user input as an argument to your skill to make it dynamic. &lt;code&gt;$ARGUMENTS&lt;/code&gt; placeholder captures any text user provides after the skill name.&lt;/p&gt;

&lt;p&gt;Update your SKILL.md to use this $ARGUMENTS variable in your file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
description: Greet the user with a personalized message
---

# Hello Skill

Greet the user named "$ARGUMENTS" warmly and ask how you can help them today. Make the greeting personal and encouraging.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, it is important that you run /reload-plugins to pick up changes and then you can run your skill as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/my-first-plugin:hello Ram
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude will greet you by name.&lt;/p&gt;

&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://code.claude.com/docs/en/plugins" rel="noopener noreferrer"&gt;code.claude.com/docs/en/plugins&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://code.claude.com/docs/en/plugins#quickstart" rel="noopener noreferrer"&gt;code.claude.com/docs/en/plugins#quickstart&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://code.claude.com/docs/en/plugins-reference#plugin-manifest-schema" rel="noopener noreferrer"&gt;code.claude.com/docs/en/plugins-reference#plugin-manifest-schema&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>claude</category>
      <category>pluggin</category>
      <category>opensource</category>
      <category>skills</category>
    </item>
    <item>
      <title>How to build a coding agent — Part 1.1</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Wed, 17 Jun 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/how-to-build-a-coding-agent-part-11-4mel</link>
      <guid>https://dev.to/ramunarasinga-11/how-to-build-a-coding-agent-part-11-4mel</guid>
      <description>&lt;p&gt;In this tutorial series, we build a coding agent that you can assign tasks on GitHub. In this part 1.1, we do the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Set up React + Vite frontend&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Set up Python FastAPI backend&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Design and implement database schema&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create basic API endpoints for agents&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;I mentioned the AI prompts used to implement tasks.&lt;/p&gt;
&lt;/blockquote&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.amazonaws.com%2Fuploads%2Farticles%2Feqbkqmp2f43zga8xebl0.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.amazonaws.com%2Fuploads%2Farticles%2Feqbkqmp2f43zga8xebl0.png" width="800" height="480"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up React + Vite frontend
&lt;/h2&gt;

&lt;p&gt;For this demo, I used React + Vite to create a frontend project. Run the below command to create a react-ts project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;vite&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;latest&lt;/span&gt; &lt;span class="nx"&gt;frontend&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="nx"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install the dependencies required:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;tanstack&lt;/span&gt;&lt;span class="sr"&gt;/react-query @tanstack/&lt;/span&gt;&lt;span class="nx"&gt;react&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;devtools&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="nx"&gt;zustand&lt;/span&gt;
&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.amazonaws.com%2Fuploads%2Farticles%2Fpir56vzj1e961clq13ws.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.amazonaws.com%2Fuploads%2Farticles%2Fpir56vzj1e961clq13ws.png" width="799" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up Python FastAPI backend
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Create a folder named backed
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;cd into it
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd backend
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;setup virtual env
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;python3 -m venv venv
source venv/bin/activate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Install requirements
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pip install fastapi uvicorn sqlalchemy psycopg2-binary pydantic websockets python-dotenv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Design and implement database schema
&lt;/h3&gt;

&lt;p&gt;Let’s use Supabase for this tutorial. You will need to create an account on Supabase. Run the below script in your Supabase SQL Editor.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="nx"&gt;Users&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;
&lt;span class="nx"&gt;CREATE&lt;/span&gt; &lt;span class="nx"&gt;TABLE&lt;/span&gt; &lt;span class="nf"&gt;users &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt; &lt;span class="nx"&gt;PRIMARY&lt;/span&gt; &lt;span class="nx"&gt;KEY&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="nf"&gt;gen_random_uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="nc"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;UNIQUE&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;created_at&lt;/span&gt; &lt;span class="nx"&gt;TIMESTAMP&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="nc"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="nx"&gt;Agents&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;  
&lt;span class="nx"&gt;CREATE&lt;/span&gt; &lt;span class="nx"&gt;TABLE&lt;/span&gt; &lt;span class="nf"&gt;agents &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt; &lt;span class="nx"&gt;PRIMARY&lt;/span&gt; &lt;span class="nx"&gt;KEY&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="nf"&gt;gen_random_uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="nc"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="nc"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="nx"&gt;claude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;codex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;etc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;instructions&lt;/span&gt; &lt;span class="nx"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;runtime_id&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;created_at&lt;/span&gt; &lt;span class="nx"&gt;TIMESTAMP&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="nc"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="nx"&gt;Issues&lt;/span&gt; &lt;span class="nf"&gt;table &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;GitHub&lt;/span&gt; &lt;span class="nx"&gt;issues&lt;/span&gt; &lt;span class="nx"&gt;synced&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;CREATE&lt;/span&gt; &lt;span class="nx"&gt;TABLE&lt;/span&gt; &lt;span class="nf"&gt;issues &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt; &lt;span class="nx"&gt;PRIMARY&lt;/span&gt; &lt;span class="nx"&gt;KEY&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="nf"&gt;gen_random_uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;github_issue_id&lt;/span&gt; &lt;span class="nx"&gt;INTEGER&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;title&lt;/span&gt; &lt;span class="nx"&gt;TEXT&lt;/span&gt; &lt;span class="nx"&gt;NOT&lt;/span&gt; &lt;span class="nx"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="nx"&gt;TEXT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="nc"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;backlog&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;assignee_id&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt; &lt;span class="nx"&gt;REFERENCES&lt;/span&gt; &lt;span class="nf"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;created_at&lt;/span&gt; &lt;span class="nx"&gt;TIMESTAMP&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="nc"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="nx"&gt;Agent&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt; &lt;span class="nx"&gt;queue&lt;/span&gt;
&lt;span class="nx"&gt;CREATE&lt;/span&gt; &lt;span class="nx"&gt;TABLE&lt;/span&gt; &lt;span class="nf"&gt;agent_task_queue &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt; &lt;span class="nx"&gt;PRIMARY&lt;/span&gt; &lt;span class="nx"&gt;KEY&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="nf"&gt;gen_random_uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;issue_id&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt; &lt;span class="nx"&gt;REFERENCES&lt;/span&gt; &lt;span class="nf"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;agent_id&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt; &lt;span class="nx"&gt;REFERENCES&lt;/span&gt; &lt;span class="nf"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="nc"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;queued&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="nx"&gt;queued&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatched&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;running&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;completed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;failed&lt;/span&gt;
    &lt;span class="nx"&gt;priority&lt;/span&gt; &lt;span class="nx"&gt;INTEGER&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;created_at&lt;/span&gt; &lt;span class="nx"&gt;TIMESTAMP&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="nc"&gt;NOW&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="o"&gt;--&lt;/span&gt; &lt;span class="nx"&gt;Runtimes&lt;/span&gt; &lt;span class="nx"&gt;table&lt;/span&gt;
&lt;span class="nx"&gt;CREATE&lt;/span&gt; &lt;span class="nx"&gt;TABLE&lt;/span&gt; &lt;span class="nf"&gt;agent_runtimes &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="nx"&gt;UUID&lt;/span&gt; &lt;span class="nx"&gt;PRIMARY&lt;/span&gt; &lt;span class="nx"&gt;KEY&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="nf"&gt;gen_random_uuid&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="nc"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="nc"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="nc"&gt;VARCHAR&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;last_heartbeat&lt;/span&gt; &lt;span class="nx"&gt;TIMESTAMP&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is what you see after a successful run.&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.amazonaws.com%2Fuploads%2Farticles%2Fizeodes3evnsqv4v28n2.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.amazonaws.com%2Fuploads%2Farticles%2Fizeodes3evnsqv4v28n2.png" width="800" height="474"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;are these tables enough to create an agent? may be. Our goal is to setup minimal configuration to create an agent and run the agent in the background, inspired by the Multica’s architecture. You can learn more about  &lt;a href="https://deepwiki.com/multica-ai/multica" rel="noopener noreferrer"&gt;Multica’s architecture on Deepwiki.&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create basic API endpoints for agents
&lt;/h3&gt;

&lt;p&gt;Let’s get started with backend files. To setup basic API endpoints, you need to create the following files:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;main.py&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create main.py in the backend folder and the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;fastapi&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;fastapi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cors&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;CORSMiddleware&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;FastAPI&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add_middleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;CORSMiddleware&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;allow_origins&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:5173&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;allow_methods&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;allow_headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Database&lt;/span&gt; &lt;span class="nx"&gt;models&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;websocket&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/agents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;agents&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;issues&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/issues&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;issues&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include_router&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/tasks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tasks&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;routes/agents.py&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create &lt;code&gt;routes&lt;/code&gt; folder and add a file named &lt;code&gt;agents.py&lt;/code&gt; in the routes folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;fastapi&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HTTPException&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;pydantic&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;BaseModel&lt;/span&gt;
&lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;get_db&lt;/span&gt;

&lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;APIRouter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AgentCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;
    &lt;span class="nx"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;  &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;claude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;codex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;etc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="nx"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AgentCreate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Create&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Return&lt;/span&gt; &lt;span class="nx"&gt;created&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;
    &lt;span class="nx"&gt;pass&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;list_agents&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Return&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;agents&lt;/span&gt;
    &lt;span class="nx"&gt;pass&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/{agent_id}&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_agent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;agent_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Return&lt;/span&gt; &lt;span class="nx"&gt;specific&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;
    &lt;span class="nx"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;routes/issues.py&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create a file named issues.py and add the below code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IssueCreate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;BaseModel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="nx"&gt;github_issue_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;int&lt;/span&gt;
    &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;create_issue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;issue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IssueCreate&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Create&lt;/span&gt; &lt;span class="nx"&gt;issue&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;database&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Optionally&lt;/span&gt; &lt;span class="nx"&gt;sync&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;GitHub&lt;/span&gt; &lt;span class="nx"&gt;API&lt;/span&gt;
    &lt;span class="nx"&gt;pass&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/{issue_id}/assign&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;assign_issue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;issue_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;agent_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Assign&lt;/span&gt; &lt;span class="nx"&gt;issue&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Enqueue&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;This&lt;/span&gt; &lt;span class="nx"&gt;triggers&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;agent&lt;/span&gt; &lt;span class="nx"&gt;execution&lt;/span&gt; &lt;span class="nx"&gt;flow&lt;/span&gt;
    &lt;span class="nx"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;routes/tasks.py&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Create a file named tasks.py and add the following code&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/claim&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;claim_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;runtime_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Daemon&lt;/span&gt; &lt;span class="nx"&gt;calls&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;claim&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt; &lt;span class="nx"&gt;available&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Use&lt;/span&gt; &lt;span class="nx"&gt;FOR&lt;/span&gt; &lt;span class="nx"&gt;UPDATE&lt;/span&gt; &lt;span class="nx"&gt;SKIP&lt;/span&gt; &lt;span class="nx"&gt;LOCKED&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;concurrent&lt;/span&gt; &lt;span class="nx"&gt;safety&lt;/span&gt;
    &lt;span class="nx"&gt;pass&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/{task_id}/start&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;start_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Mark&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;running&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Broadcast&lt;/span&gt; &lt;span class="nx"&gt;via&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt;
    &lt;span class="nx"&gt;pass&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/{task_id}/complete&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;complete_task&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;task_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;dict&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Mark&lt;/span&gt; &lt;span class="nx"&gt;task&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;completed&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;Update&lt;/span&gt; &lt;span class="nx"&gt;issue&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;needed&lt;/span&gt;
    &lt;span class="nx"&gt;pass&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;coding-agent is open source and available at &lt;a href="https://github.com/thinkthroo/coding-agent" rel="noopener noreferrer"&gt;thinkthroo/coding-agent&lt;/a&gt; &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://supabase.com/" rel="noopener noreferrer"&gt;supabase.com&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://deepwiki.com/multica-ai/multica" rel="noopener noreferrer"&gt;deepwiki.com/multica-ai/multica&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>opensource</category>
      <category>aicodingagent</category>
      <category>multica</category>
      <category>react</category>
    </item>
    <item>
      <title>How to build a coding agent - Part 1.0</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Wed, 03 Jun 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/how-to-build-a-coding-agent-part-10-1a4e</link>
      <guid>https://dev.to/ramunarasinga-11/how-to-build-a-coding-agent-part-10-1a4e</guid>
      <description>&lt;p&gt;In this tutorial series, we build a coding agent that you can assign tasks on GitHub. In this part 1.0, we discuss:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Plan&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Architecture&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Table of content&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;This tutorial series is inspired by &lt;a href="https://github.com/multica-ai/multica" rel="noopener noreferrer"&gt;Multica&lt;/a&gt;, an open-source managed agents platform.&lt;/p&gt;
&lt;/blockquote&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.amazonaws.com%2Fuploads%2Farticles%2Fzfxgw7m6calpjrj6r0r0.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.amazonaws.com%2Fuploads%2Farticles%2Fzfxgw7m6calpjrj6r0r0.png" width="800" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The plan
&lt;/h2&gt;

&lt;p&gt;I noticed Multica repository has been trending on GitHub. With Multica, you can assign your GitHub issues to an agent you create via Multica platform and it picks up the work, writes code, report blockers, and update statuses autonomously.&lt;/p&gt;

&lt;p&gt;Well, may you could just vibe code this entire Multica clone, but the reason I wrote this series is because I wanted to understand how Multica creates agents, how an issue can be assigend to an agent, how to executes in the background, underlying system architecture.&lt;/p&gt;

&lt;p&gt;We use &lt;a href="https://deepwiki.com/multica-ai/multica" rel="noopener noreferrer"&gt;DeepWiki to understand the Multica's codebase architecture&lt;/a&gt; apply those principles in the project we build.&lt;/p&gt;

&lt;p&gt;Multica uses Go in the backend, we will implement this in Python. Architecture and the concepts will be same, just that we use a different programming language. The goal is not to copy the exact way of Multica's architecture but rather take inspiration and implement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;Let's just reiterate the tech stack:&lt;/p&gt;

&lt;p&gt;Frontend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;React + Vite&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;TanStack Query&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Backend:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FastAPI (Python)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Goal:
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Create an Agent via the UI&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Save this Agent info in the database&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Assign a task on Github to this agent&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Daemon implementation to complete the assigned task.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While we implement the above goals, we study the Multica's architecture and replicate the patterns in our project, frameworks may vary, but the principles would not change.&lt;/p&gt;

&lt;h2&gt;
  
  
  Table of content
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Part 1: Foundation and setup&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 2: Agent Creation System&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 3: GitHub Integration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 4: Task Assignment System&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 5: Agent Execution Layer&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 6: Real-time updates&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 7: Task Completion and GitHub Sync&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Part 8: Advanced features&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/multica-ai/multica" rel="noopener noreferrer"&gt;github.com/multica-ai/multica&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://deepwiki.com/multica-ai/multica" rel="noopener noreferrer"&gt;deepwiki.com/multica-ai/multica&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>opensource</category>
      <category>multica</category>
      <category>codingagent</category>
      <category>architecture</category>
    </item>
    <item>
      <title>gitrelease.mjs file in Nango codebase.</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Tue, 02 Jun 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/gitreleasemjs-file-in-nango-codebase-72c</link>
      <guid>https://dev.to/ramunarasinga-11/gitreleasemjs-file-in-nango-codebase-72c</guid>
      <description>&lt;p&gt;In this article, we review gitrelease.mjs file in Nango codebase. You will learn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;gitrelease.mjs file&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;publish workflow&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2Fumg7u8doqgpo2vfj8uq9.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.amazonaws.com%2Fuploads%2Farticles%2Fumg7u8doqgpo2vfj8uq9.png" width="800" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  gitrelease.mjs file
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/NangoHQ/nango/blob/603e24657e3dc21d506795ec313cab1840af0a9e/scripts/gitrelease.mjs" rel="noopener noreferrer"&gt;gitrelease.mjs&lt;/a&gt;. is defined in the scripts folder and is defined as shown below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cp"&gt;#!/usr/bin/env zx
&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;echo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;zx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GITHUB_TOKEN&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;branch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;master&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextTag&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`v&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextVersion&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="s2"&gt;`Publishing &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextVersion&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; on branch &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;branch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git config --global user.email "contact@nango.dev"`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git config --global user.name "Release Bot"`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;tagExists&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git tag -l &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextTag&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tagExists&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="s2"&gt;`Tag &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextTag&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; already exists`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;releaseMessage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`chore(release): &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextVersion&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="s2"&gt;`Checkout out branch`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git fetch origin &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;branch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git switch &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;branch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="s2"&gt;`Generating changelog`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`npx git-cliff -o CHANGELOG.md -t &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextTag&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="s2"&gt;`Adding file`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git add -A package.json package-lock.json packages/**/package.json CHANGELOG.md packages/**/lib/version.ts`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="s2"&gt;`Creating commit`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git commit --allow-empty --author="Release Bot &amp;lt;contact@nango.dev&amp;gt;" -m &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;releaseMessage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; `&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="s2"&gt;`Creating tag`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git tag -a &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextTag&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; HEAD -m &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;releaseMessage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="s2"&gt;`Pushing`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Rebase on latest to handle commits that landed on ${branch} during publish&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git fetch origin &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;branch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git rebase origin/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;branch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Push branch and tag separately - tag intentionally points to the pre-rebase commit&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git push origin HEAD:refs/heads/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;branch&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`git push origin &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;nextTag&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="s2"&gt;`Commit pushed, publishing release...`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Push GitHub release&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;releaseNotes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`npx git-cliff --latest --strip header footer`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;releaseData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nextTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tag_name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nextTag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;releaseNotes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="s2"&gt;`curl --silent --fail --show-error -H "Authorization: Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;" -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/NangoHQ/nango/releases -d &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;releaseData&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;releaseData&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;echo&lt;/span&gt;&lt;span class="s2"&gt;`✅ Done`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can follow the echo statements to understand what is happening in the code:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Check out branch&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generating changelog&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Adding file&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating commit&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Creating tag&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Pushing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Commit pushed, publishing release.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wrote a separate article about &lt;a href="https://git-cliff.org/docs/" rel="noopener noreferrer"&gt;what git-cliff is.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  publish workflow
&lt;/h2&gt;

&lt;p&gt;It is a common practice to define scripts and run them in the GitHub workflows. &lt;a href="https://github.com/NangoHQ/nango/blob/603e24657e3dc21d506795ec313cab1840af0a9e/.github/workflows/publish.yaml#L54" rel="noopener noreferrer"&gt;nango/.github/workflows/publish.yaml&lt;/a&gt; is defined as below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[Release]&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;NPM&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;publish'&lt;/span&gt;
&lt;span class="na"&gt;run-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;[Release]&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;NPM&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;publish&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;inputs.version&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}'&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;workflow_dispatch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;inputs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;string&lt;/span&gt;
                &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Version&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;to&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;publish'&lt;/span&gt;
                &lt;span class="na"&gt;required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
                &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;0.0.0'&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
    &lt;span class="na"&gt;id-token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;npm-publish&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;if&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;github.ref == 'refs/heads/master'&lt;/span&gt;
        &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/create-github-app-token@v2&lt;/span&gt;
              &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;create_github_app_token&lt;/span&gt;
              &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;app-id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GH_APP_PUSHER_ID }}&lt;/span&gt;
                  &lt;span class="na"&gt;private-key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GH_APP_PUSHER_PRIVATE_KEY }}&lt;/span&gt;

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
              &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.create_github_app_token.outputs.token }}&lt;/span&gt;
                  &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-node@v4&lt;/span&gt;
              &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;cache&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;npm'&lt;/span&gt;
                  &lt;span class="na"&gt;node-version-file&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.nvmrc'&lt;/span&gt;
                  &lt;span class="na"&gt;registry-url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;https://registry.npmjs.org'&lt;/span&gt;

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Update npm to latest&lt;/span&gt;
              &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install -g npm@11.5.1&lt;/span&gt;

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Install dependencies&lt;/span&gt;
              &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm ci&lt;/span&gt;

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish npm packages&lt;/span&gt;
              &lt;span class="na"&gt;shell&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bash&lt;/span&gt;
              &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
                  &lt;span class="s"&gt;npx zx ./scripts/publish.mjs --version="${{ inputs.version }}"&lt;/span&gt;

            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Publish release&lt;/span&gt;
              &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
                  &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.create_github_app_token.outputs.token }}&lt;/span&gt;
              &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
                  &lt;span class="s"&gt;npx zx ./scripts/gitrelease.mjs "${{ inputs.version }}" "${{ github.head_ref || github.ref_name }}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the run: section, you will see that this script is invoked using the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx zx ./scripts/gitrelease.mjs &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="p"&gt;{ inputs.version &lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;}"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="p"&gt;{ github.head_ref || github.ref_name &lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;}"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/NangoHQ/nango/blob/603e24657e3dc21d506795ec313cab1840af0a9e/scripts/gitrelease.mjs" rel="noopener noreferrer"&gt;nango/scripts/gitrelease.mjs&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/NangoHQ/nango/blob/603e24657e3dc21d506795ec313cab1840af0a9e/.github/workflows/publish.yaml#L54" rel="noopener noreferrer"&gt;nango/.github/workflows/publish.yaml#L54&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://git-cliff.org/docs/" rel="noopener noreferrer"&gt;git-cliff.org/docs/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>gitcliff</category>
      <category>nango</category>
      <category>opensource</category>
      <category>workflow</category>
    </item>
    <item>
      <title>git-cliff, a changelog generator.</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Mon, 01 Jun 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/git-cliff-a-changelog-generator-22ci</link>
      <guid>https://dev.to/ramunarasinga-11/git-cliff-a-changelog-generator-22ci</guid>
      <description>&lt;p&gt;In this article, we review git-cliff. You will learn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is git-cliff?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;git-cliff usage in Nango&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2Fwhq3n3fmwdn03so6het2.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.amazonaws.com%2Fuploads%2Farticles%2Fwhq3n3fmwdn03so6het2.png" width="799" height="499"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is git-cliff?
&lt;/h2&gt;

&lt;p&gt;git-cliff is a highly customizable Changelog Generator that follows Conventional Commit specifications.&lt;/p&gt;

&lt;h3&gt;
  
  
  High customizable
&lt;/h3&gt;

&lt;p&gt;git-cliff uses regex-powered custom parsers and the changelog can be customized easily with a configuration file to match the desired format.&lt;/p&gt;

&lt;h3&gt;
  
  
  Conventional Commits
&lt;/h3&gt;

&lt;p&gt;git-cliff can generate changelog files for any Git repository that follows the conventional commits specification.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easy Integration
&lt;/h3&gt;

&lt;p&gt;git-cliff can be easily integrated with your Rust/Python/Node.js project as a command-line tool and also can be used as a library for Rust projects.&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.amazonaws.com%2Fuploads%2Farticles%2Fzufe2tnti0pqh02dxhtz.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.amazonaws.com%2Fuploads%2Farticles%2Fzufe2tnti0pqh02dxhtz.png" width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick start
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Install git-cliff
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cargo&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cliff&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Initialise git-cliff:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;cliff&lt;/span&gt; &lt;span class="p"&gt;--&lt;/span&gt;&lt;span class="k"&gt;init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Edit the default &lt;a href="https://gitcliff.org/docs/configuration/" rel="noopener noreferrer"&gt;Configuration&lt;/a&gt;.                                           (cliff.toml) as you like. Check out the&lt;br&gt;&lt;br&gt;
&lt;a href="https://git-cliff.org/docs/templating/examples/" rel="noopener noreferrer"&gt;example&lt;/a&gt;.  for different templates.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Generate a changelog
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;git&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cliff&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="nx"&gt;CHANGELOG&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;md&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  git-cliff usage in Nango
&lt;/h2&gt;

&lt;p&gt;I found the &lt;a href="https://github.com/NangoHQ/nango/blob/master/cliff.toml" rel="noopener noreferrer"&gt;cliff.toml file in Nango codebase&lt;/a&gt;. It is defined as shown below.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cliff&lt;/span&gt; &lt;span class="o"&gt;~&lt;/span&gt; &lt;span class="nx"&gt;configuration&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//git-cliff.org/docs/configuration&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;changelog&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;changelog&lt;/span&gt; &lt;span class="nx"&gt;header&lt;/span&gt;
&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"""&lt;/span&gt;&lt;span class="s2"&gt;
# Changelog&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;
All notable changes to this project will be documented in this file.&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;
&lt;/span&gt;&lt;span class="dl"&gt;"""&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;changelog&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//keats.github.io/tera/docs/#introduction&lt;/span&gt;
&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"""&lt;/span&gt;&lt;span class="s2"&gt;
{% if version -%}
    ## [{{ version }}] - {{ timestamp | date(format=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="nx"&gt;Y&lt;/span&gt;&lt;span class="o"&gt;-%&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="o"&gt;-%&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;) }}
{% else -%}
    ## [Unreleased]
{% endif -%}
{% for group, commits in commits | group_by(attribute=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="nx"&gt;group&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;) %}
    ### {{ group | upper_first }}
    {% for commit in commits %}
        - {% if commit.scope %}*({{ commit.scope }})* {% endif %}&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
           {{ commit.message | upper_first }}&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
           {% if commit.github.username %} by @{{ commit.github.username }}{%- endif -%}
    {% endfor %}
{% endfor %}&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;
&lt;/span&gt;&lt;span class="dl"&gt;"""&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;changelog&lt;/span&gt; &lt;span class="nx"&gt;footer&lt;/span&gt;
&lt;span class="nx"&gt;footer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"""&lt;/span&gt;&lt;span class="s2"&gt;
{% for release in releases -%}
    {% if release.version -%}
        {% if release.previous.version -%}
            [{{ release.version }}]: &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
                https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
                    /compare/{{ release.previous.version }}..{{ release.version }}
        {% endif -%}
    {% else -%}
        [unreleased]: https://github.com/{{ remote.github.owner }}/{{ remote.github.repo }}&lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;&lt;span class="s2"&gt;
            /compare/{{ release.previous.version }}..HEAD
    {% endif -%}
{% endfor %}
&amp;lt;!-- generated by git-cliff --&amp;gt;
&lt;/span&gt;&lt;span class="dl"&gt;"""&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;remove&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;leading&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;trailing&lt;/span&gt; &lt;span class="nx"&gt;whitespace&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;templates&lt;/span&gt;
&lt;span class="nx"&gt;trim&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;git&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;parse&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;commits&lt;/span&gt; &lt;span class="nx"&gt;based&lt;/span&gt; &lt;span class="nx"&gt;on&lt;/span&gt; &lt;span class="nx"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="c1"&gt;//www.conventionalcommits.org&lt;/span&gt;
&lt;span class="nx"&gt;conventional_commits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;commits&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;conventional&lt;/span&gt;
&lt;span class="nx"&gt;filter_unconventional&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;an&lt;/span&gt; &lt;span class="nx"&gt;individual&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt;
&lt;span class="nx"&gt;split_commits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;parsing&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;grouping&lt;/span&gt; &lt;span class="nx"&gt;commits&lt;/span&gt;
&lt;span class="nx"&gt;commit_parsers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^feat&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Added&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^.*: add&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Added&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^test&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fixed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^fix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fixed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^.*: fix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Fixed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^chore.release.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;skip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;^.*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;group&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Changed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;protect&lt;/span&gt; &lt;span class="nx"&gt;breaking&lt;/span&gt; &lt;span class="nx"&gt;changes&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="nx"&gt;being&lt;/span&gt; &lt;span class="nx"&gt;skipped&lt;/span&gt; &lt;span class="nx"&gt;due&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;matching&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;skipping&lt;/span&gt; &lt;span class="nx"&gt;commit_parser&lt;/span&gt;
&lt;span class="nx"&gt;protect_breaking_commits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;filter&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;commits&lt;/span&gt; &lt;span class="nx"&gt;that&lt;/span&gt; &lt;span class="nx"&gt;are&lt;/span&gt; &lt;span class="nx"&gt;not&lt;/span&gt; &lt;span class="nx"&gt;matched&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="nx"&gt;commit&lt;/span&gt; &lt;span class="nx"&gt;parsers&lt;/span&gt;
&lt;span class="nx"&gt;filter_commits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;matching&lt;/span&gt; &lt;span class="nx"&gt;git&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;
&lt;span class="nx"&gt;tag_pattern&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;v[0-9].*&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;skipping&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;
&lt;span class="nx"&gt;skip_tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;regex&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;ignoring&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt;
&lt;span class="nx"&gt;ignore_tags&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;sort&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;tags&lt;/span&gt; &lt;span class="nx"&gt;topologically&lt;/span&gt;
&lt;span class="nx"&gt;topo_order&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt; &lt;span class="nx"&gt;sort&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="nx"&gt;commits&lt;/span&gt; &lt;span class="nx"&gt;inside&lt;/span&gt; &lt;span class="nx"&gt;sections&lt;/span&gt; &lt;span class="nx"&gt;by&lt;/span&gt; &lt;span class="nx"&gt;oldest&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;newest&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt;
&lt;span class="nx"&gt;sort_commits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;oldest&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can find the generated Nango's changelog at &lt;a href="https://github.com/NangoHQ/nango/blob/master/CHANGELOG.md" rel="noopener noreferrer"&gt;CHANGELOG.md.&lt;/a&gt;&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.amazonaws.com%2Fuploads%2Farticles%2Fzduji6qt2giirdp5n5v8.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.amazonaws.com%2Fuploads%2Farticles%2Fzduji6qt2giirdp5n5v8.png" width="800" height="563"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://git-cliff.org/" rel="noopener noreferrer"&gt;git-cliff.org/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://git-cliff.org/docs/" rel="noopener noreferrer"&gt;git-cliff.org/docs/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/NangoHQ/nango/blob/master/cliff.toml" rel="noopener noreferrer"&gt;nango/cliff.toml&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/NangoHQ/nango/blob/master/CHANGELOG.md" rel="noopener noreferrer"&gt;nango/CHANGELOG.md&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>gitcliff</category>
      <category>changelog</category>
      <category>nango</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Build product integrations with AI using Nango.</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Thu, 28 May 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/build-product-integrations-with-ai-using-nango-1b2h</link>
      <guid>https://dev.to/ramunarasinga-11/build-product-integrations-with-ai-using-nango-1b2h</guid>
      <description>&lt;p&gt;In this article, we review Nango. You will learn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is Nango?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;How it works?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Use cases.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2Fguupj32hiwejgtgh3s1i.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.amazonaws.com%2Fuploads%2Farticles%2Fguupj32hiwejgtgh3s1i.png" width="799" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Nango?
&lt;/h2&gt;

&lt;p&gt;Nango is an open-source platform for building product integrations. It supports &lt;a href="https://nango.dev/docs/integrations/overview" rel="noopener noreferrer"&gt;800+ APIs&lt;/a&gt;. and works with any backend language, AI coding tool, and agent SDK.&lt;/p&gt;

&lt;p&gt;You write integration logic as TypeScript functions, or let AI generate them for you, and deploy to Nango's production runtime. Nango handles auth, execution, scaling, and observability.&lt;/p&gt;

&lt;p&gt;Used in production by Replit, Ramp, Mercor, and hundreds more.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Learn more about &lt;a href="https://github.com/NangoHQ/nango#what-is-nango" rel="noopener noreferrer"&gt;Nango&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  How it works?
&lt;/h2&gt;

&lt;p&gt;Nango gives you three primitives that cover every integration pattern:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Auth
&lt;/h3&gt;

&lt;p&gt;Managed OAuth, API keys, and token refresh for 800+ APIs. Embed a white-label auth flow in your app. Nango handles credentials, token storage, and multi-tenant connection management.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Embed auth in your frontend&lt;/span&gt;
&lt;span class="nx"&gt;nango&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;openConnectUI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;onEvent&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="cm"&gt;/* handle completion */&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Proxy
&lt;/h3&gt;

&lt;p&gt;Make authenticated API requests on behalf of your users. Send requests through Nango's proxy: it resolves the provider, injects credentials, handles retries and rate limits, and returns the response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Nango&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@nangohq/node&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nango&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Nango&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;secretKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;NANGO-SECRET-KEY&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// Make an authenticated request to any API&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;nango&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/v3/contacts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;providerConfigKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;INTEGRATION-ID&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;connectionId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;CONNECTION-ID&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Functions
&lt;/h3&gt;

&lt;p&gt;Write integration logic as TypeScript functions and deploy to Nango. Functions execute on a production runtime with built-in API access, retries, storage, and observability.&lt;/p&gt;

&lt;p&gt;Use the AI builder to generate them from a description of your use case.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nango&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Nango&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nango&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;nango&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;endpoint&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`/repos/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/issues`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I copied this above info from the&lt;a href="https://github.com/NangoHQ/nango#how-it-works" rel="noopener noreferrer"&gt;Nango README.&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Usecases.
&lt;/h2&gt;

&lt;p&gt;I found these following in the Nango docs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nango.dev/docs/getting-started/use-cases/tool-calling" rel="noopener noreferrer"&gt;Tool calling for AI agents&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nango.dev/docs/getting-started/use-cases/syncs" rel="noopener noreferrer"&gt;Sync external API datants&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nango.dev/docs/getting-started/use-cases/actions" rel="noopener noreferrer"&gt;Run external API operations&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nango.dev/docs/getting-started/use-cases/webhooks-from-external-apis" rel="noopener noreferrer"&gt;Process external webhooks&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nango.dev/docs/getting-started/use-cases/unified-apis" rel="noopener noreferrer"&gt;Build a unified API&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nango.dev/docs/getting-started/use-cases/customer-configuration" rel="noopener noreferrer"&gt;Customize per customer&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nango.dev/docs/getting-started/use-cases/implement-event-handler" rel="noopener noreferrer"&gt;Connection lifecycle events&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nango.dev/docs/getting-started/use-cases/sample-app" rel="noopener noreferrer"&gt;Sample app&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;Check out the &lt;a href="https://nango.dev/docs/getting-started/use-cases/tool-calling" rel="noopener noreferrer"&gt;Nango documentation.&lt;/a&gt;. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/NangoHQ/nango" rel="noopener noreferrer"&gt;github.com/NangoHQ/nango&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nango.dev/" rel="noopener noreferrer"&gt;nango.dev&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://nango.dev/docs/getting-started/use-cases/syncs" rel="noopener noreferrer"&gt;nango.dev/docs/getting-started/use-cases/syncs&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>nango</category>
      <category>opensource</category>
      <category>integrations</category>
      <category>agents</category>
    </item>
    <item>
      <title>DeepWiki, AI documentation you can talk to, for every repo</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Wed, 27 May 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/deepwiki-ai-documentation-you-can-talk-to-for-every-repo-ep1</link>
      <guid>https://dev.to/ramunarasinga-11/deepwiki-ai-documentation-you-can-talk-to-for-every-repo-ep1</guid>
      <description>&lt;p&gt;In this article, we review DeepWiki. You will learn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; What is DeepWiki?&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2Fdj3mgz2urt7nidoz3dzj.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.amazonaws.com%2Fuploads%2Farticles%2Fdj3mgz2urt7nidoz3dzj.png" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is DeepWiki?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://deepwiki.com/" rel="noopener noreferrer"&gt;DeepWiki&lt;/a&gt;.  helps you understand any public repository. You can add a repository using the shown below image.&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.amazonaws.com%2Fuploads%2Farticles%2F9pwc8ddsso946j7heliv.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.amazonaws.com%2Fuploads%2Farticles%2F9pwc8ddsso946j7heliv.png" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  VSCode Example:
&lt;/h3&gt;

&lt;p&gt;I found this wiki docs for the VSCode codebase &lt;a href="https://deepwiki.com/microsoft/vscode" rel="noopener noreferrer"&gt;https://deepwiki.com/microsoft/vscode&lt;/a&gt;.&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.amazonaws.com%2Fuploads%2Farticles%2F1l7dxpcd8d63v7stp8vc.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.amazonaws.com%2Fuploads%2Farticles%2F1l7dxpcd8d63v7stp8vc.png" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is quite powerful, helps you understand any codebase. You can use this to learn the codebase architecture, understand patterns, best practices.&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.amazonaws.com%2Fuploads%2Farticles%2F9s7rihu2xnpwlq9i81hd.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.amazonaws.com%2Fuploads%2Farticles%2F9s7rihu2xnpwlq9i81hd.png" width="800" height="479"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I indexed my own open source project, &lt;a href="https://github.com/AsyncFuncAI/deepwiki-open" rel="noopener noreferrer"&gt;thinkthroo&lt;/a&gt;. It says the indexing process takes anywhere between 2–10 minutes&lt;/p&gt;

&lt;p&gt;I found this open source alternative of deepwiki — &lt;a href="https://github.com/AsyncFuncAI/deepwiki-open" rel="noopener noreferrer"&gt;https://github.com/AsyncFuncAI/deepwiki-open&lt;/a&gt;. &lt;/p&gt;

&lt;h3&gt;
  
  
  Deepwiki-open
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/AsyncFuncAI/deepwiki-open" rel="noopener noreferrer"&gt;AsyncFuncAI/deepwiki-open&lt;/a&gt;. provides the following features:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Analyze the code structure&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Generate comprehensive documentation&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Create visual diagrams to explain how everything works&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Organize it all into an easy-to-navigate wiki&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;DeepWiki is powered by &lt;a href="https://devin.ai/" rel="noopener noreferrer"&gt; Devin, AI software engineer&lt;/a&gt;. For the private repositories, DeepWiki lets you index using Devin.&lt;/p&gt;

&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://deepwiki.com/" rel="noopener noreferrer"&gt;deepwiki.com/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/ramu-narasinga/thinkthroo" rel="noopener noreferrer"&gt;github.com/ramu-narasinga/thinkthroo&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/AsyncFuncAI/deepwiki-open" rel="noopener noreferrer"&gt;github.com/AsyncFuncAI/deepwiki-open&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://grok-wiki.com/" rel="noopener noreferrer"&gt;grok-wiki.com/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://devin.ai/" rel="noopener noreferrer"&gt;devin.ai/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>deepwiki</category>
      <category>opensource</category>
      <category>codebase</category>
      <category>vscode</category>
    </item>
    <item>
      <title>Here is how you can render HTML-based videos using AI coding agent.</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Thu, 21 May 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/here-is-how-you-can-render-html-based-videos-using-ai-coding-agent-1pl2</link>
      <guid>https://dev.to/ramunarasinga-11/here-is-how-you-can-render-html-based-videos-using-ai-coding-agent-1pl2</guid>
      <description>&lt;p&gt;In this article, we review HyperFrames. You will learn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is HyperFrames?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;HyperFrames vs Remotion&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2Fl2f84ee8vwkysipia31d.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.amazonaws.com%2Fuploads%2Farticles%2Fl2f84ee8vwkysipia31d.png" width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is HyperFrames?
&lt;/h2&gt;

&lt;p&gt;Hyperframes is an open-source video rendering framework that lets you create, preview, and render HTML-based video compositions - with first-class support for AI agents.&lt;/p&gt;

&lt;h3&gt;
  
  
  Getting Started
&lt;/h3&gt;

&lt;p&gt;You want to install the HyperFrames skills:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npx&lt;/span&gt; &lt;span class="nx"&gt;skills&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="nx"&gt;heygen&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;hyperframes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then, define your prompt. Below is an example prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;Using&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;hyperframes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;create&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;second&lt;/span&gt; &lt;span class="nx"&gt;product&lt;/span&gt; &lt;span class="nx"&gt;intro&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;fade&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;background&lt;/span&gt; &lt;span class="nx"&gt;video&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;and&lt;/span&gt; &lt;span class="nx"&gt;background&lt;/span&gt; &lt;span class="nx"&gt;music&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hyperframes also provides to create a project manually.&lt;/p&gt;

&lt;p&gt;npx hyperframes init my-video&lt;br&gt;
cd my-video&lt;br&gt;
npx hyperframes preview      # preview in browser (live reload)&lt;br&gt;
npx hyperframes render       # render to MP4&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I highly recommend reading the &lt;a href="https://github.com/heygen-com/hyperframes" rel="noopener noreferrer"&gt;HyperFrames README.&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  HyperFrames vs Remotion
&lt;/h2&gt;

&lt;p&gt;Hyperframes is inspired by &lt;a href="https://www.remotion.dev/" rel="noopener noreferrer"&gt;Remotion&lt;/a&gt;.- we used Remotion at HeyGen in production, learned a ton from it, and kept attribution comments in the source for the patterns it pioneered (Chrome launch flags, image2pipe → FFmpeg streaming, frame buffering). Both tools drive headless Chrome and both are deterministic. They differ on one decision: what the primary author writes. Remotion's bet is React components; Hyperframes' bet is HTML.&lt;/p&gt;

&lt;p&gt;I copied this info from the README.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.remotion.dev/" rel="noopener noreferrer"&gt;Remotion&lt;/a&gt;.also has a feature -&lt;a href="https://www.remotion.dev/docs/ai/coding-agents" rel="noopener noreferrer"&gt;Prompt a video.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also did write an article about how &lt;a href="https://medium.com/@ramu.narasinga_61050/use-degit-to-download-a-template-in-your-cli-tool-6d2b628ac933" rel="noopener noreferrer"&gt;Remotion uses Degit to download template.&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/heygen-com/hyperframes" rel="noopener noreferrer"&gt;github.com/heygen-com/hyperframes&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.remotion.dev/docs/ai/coding-agents" rel="noopener noreferrer"&gt;remotion.dev/docs/ai/coding-agents&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.remotion.dev/" rel="noopener noreferrer"&gt;remotion.dev/&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.remotion.dev/docs/ai/coding-agents" rel="noopener noreferrer"&gt;remotion.dev/docs/ai/coding-agents&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>opensource</category>
      <category>hyperframes</category>
      <category>videos</category>
      <category>remotion</category>
    </item>
    <item>
      <title>attw script in CopilotKit codebase.</title>
      <dc:creator>Ramu Narasinga</dc:creator>
      <pubDate>Thu, 14 May 2026 15:30:00 +0000</pubDate>
      <link>https://dev.to/ramunarasinga-11/attw-script-in-copilotkit-codebase-4h5h</link>
      <guid>https://dev.to/ramunarasinga-11/attw-script-in-copilotkit-codebase-4h5h</guid>
      <description>&lt;p&gt;In this article, we review attw script in CopilotKit codebase. You will learn:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;What is attw?&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;attw script in CopilotKit&lt;/p&gt;&lt;/li&gt;
&lt;/ol&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.amazonaws.com%2Fuploads%2Farticles%2Fev9br41fjut5a6emxnba.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.amazonaws.com%2Fuploads%2Farticles%2Fev9br41fjut5a6emxnba.png" width="800" height="714"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is attw?
&lt;/h2&gt;

&lt;p&gt;attw is a CLI for &lt;a href="https://arethetypeswrong.github.io/" rel="noopener noreferrer"&gt;arethetypeswrong.github.io.&lt;/a&gt;.This project attempts to analyze npm package contents for issues with their TypeScript types, particularly ESM-related module resolution issues. The following kinds of problems can be detected in the node10, node16, and bundler module resolution modes:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/NoResolution.md" rel="noopener noreferrer"&gt;💀 Resolution failed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/UntypedResolution.md" rel="noopener noreferrer"&gt;❌ No types&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseCJS.md" rel="noopener noreferrer"&gt;🎭 Masquerading as CJS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseESM.md" rel="noopener noreferrer"&gt;👺 Masquerading as ESM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/CJSResolvesToESM.md" rel="noopener noreferrer"&gt;⚠️ ESM (dynamic import only)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FallbackCondition.md" rel="noopener noreferrer"&gt;🐛 Used fallback condition&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/CJSOnlyExportsDefault.md" rel="noopener noreferrer"&gt;🤨 CJS default export&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/FalseExportDefault.md" rel="noopener noreferrer"&gt;❗️ Incorrect default export&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/MissingExportEquals.md" rel="noopener noreferrer"&gt;❓ Missing export =&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/UnexpectedModuleSyntax.md" rel="noopener noreferrer"&gt;🚭 Unexpected module syntax&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/InternalResolutionError.md" rel="noopener noreferrer"&gt;🥴 Internal resolution error&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/arethetypeswrong/arethetypeswrong.github.io/blob/main/docs/problems/NamedExports.md" rel="noopener noreferrer"&gt;🕵️‍♂️ Named exports&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Below is a check I ran on my npm package, thinkthroo and these were the issues found&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.amazonaws.com%2Fuploads%2Farticles%2Fzyrix4qolrfq9o6bwh8i.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.amazonaws.com%2Fuploads%2Farticles%2Fzyrix4qolrfq9o6bwh8i.png" width="800" height="608"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  attw script in CopilotKit
&lt;/h2&gt;

&lt;p&gt;Since now that we understand what attw does, let’s review how CopilotKit uses this in the package.json script.&lt;/p&gt;

&lt;p&gt;I the &lt;a href="https://github.com/CopilotKit/CopilotKit/blob/main/packages/agentcore-runner/package.json#L27" rel="noopener noreferrer"&gt;CopilotKit/packages/agentcore-runner/package.json,&lt;/a&gt;. you will find the below code nsippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scripts&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;attw&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;attw --pack . --profile node16&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This has two arguments/options/flags passed.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pack&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Specify a directory to run npm pack in (instead of specifying a tarball filename), analyze the resulting tarball, and delete it afterwards.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;attw&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;pack&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;profile&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Profiles select a set of resolution modes to require/ignore. All are evaluated but failures outside of those required are ignored.&lt;/p&gt;

&lt;p&gt;The available profiles are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;strict - requires all resolutions&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;node16 - ignores node10 resolution failures&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;esm-only - ignores CJS resolution failures&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the CLI: --profile&lt;/p&gt;

&lt;p&gt;The script in CopilotKit ignores the node10 resolution failures.&lt;/p&gt;

&lt;h2&gt;
  
  
  About me:
&lt;/h2&gt;

&lt;p&gt;Hey, my name is &lt;a href="https://www.ramunarasinga.com/" rel="noopener noreferrer"&gt;ramunarasinga&lt;/a&gt;. Email: &lt;a href="mailto:ramu.narasinga@gmail.com"&gt;ramunarasinga@gmail.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tired of AI slop?&lt;/p&gt;

&lt;p&gt;I spent 3+ years studying OSS codebases and wrote 350+ articles on what makes them production-grade. I built&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;An &lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;open source tool that reviews your PR.&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://app.thinkthroo.com/skills-library" rel="noopener noreferrer"&gt;Codebase architecture skills,&lt;/a&gt; inspired by best OSS projects.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://thinkthroo.com/" rel="noopener noreferrer"&gt;Get started for free — thinkthroo.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  References:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.npmjs.com/package/@arethetypeswrong/cli" rel="noopener noreferrer"&gt;package/@arethetypeswrong/cli&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/CopilotKit/CopilotKit/blob/main/packages/agentcore-runner/package.json#L27" rel="noopener noreferrer"&gt;CopilotKit/packages/agentcore-runner/package.json#L27&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://arethetypeswrong.github.io/" rel="noopener noreferrer"&gt;arethetypeswrong.github.io&lt;/a&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>attw</category>
      <category>opensource</category>
      <category>copilotkit</category>
      <category>npm</category>
    </item>
  </channel>
</rss>
