<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Prashant's Blog]]></title><description><![CDATA[Prashant's Blog]]></description><link>https://blog.prashantkoirala.info.np</link><generator>RSS for Node</generator><lastBuildDate>Mon, 11 May 2026 02:43:44 GMT</lastBuildDate><atom:link href="https://blog.prashantkoirala.info.np/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Why TypeScript became the language of AI apps]]></title><description><![CDATA[A few years ago, TypeScript was mostly described as a safer JavaScript.
That description was true, but too small.
In 2026, TypeScript is no longer just the language people use to make React code less ]]></description><link>https://blog.prashantkoirala.info.np/why-typescript-became-the-language-of-ai-apps</link><guid isPermaLink="true">https://blog.prashantkoirala.info.np/why-typescript-became-the-language-of-ai-apps</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[AI]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[webdev]]></category><category><![CDATA[Software Engineering]]></category><category><![CDATA[fullstackdevelopment]]></category><dc:creator><![CDATA[Prashant Koirala]]></dc:creator><pubDate>Sun, 10 May 2026 13:30:05 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/df3d2dc6-a489-4868-8a66-968f7cf6427c.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>A few years ago, TypeScript was mostly described as a safer JavaScript.</p>
<p>That description was true, but too small.</p>
<p>In 2026, TypeScript is no longer just the language people use to make React code less painful. It has become one of the main languages for building AI applications: chat interfaces, agents, tool calling systems, model gateways, browser AI features, workflow automation, internal copilots, and full stack products that sit between users and large language models.</p>
<p>The shift did not happen because TypeScript suddenly became a machine learning language. Python still owns the research side of AI. It is still the language of notebooks, training pipelines, PyTorch, data science, and experimentation.</p>
<p>TypeScript won a different part of the stack.</p>
<p>It became the language of <strong>AI product engineering</strong>.</p>
<p>That distinction matters. Most AI apps are not just models. They are user interfaces, API routes, streaming responses, auth systems, billing, databases, vector search, tool calls, background jobs, and observability. They are software products wrapped around probabilistic systems.</p>
<p>That is exactly where TypeScript is strongest.</p>
<h2><strong>The short version</strong></h2>
<p>TypeScript became the language of the AI app era because it sits at the intersection of five forces:</p>
<table>
<thead>
<tr>
<th><strong>Force</strong></th>
<th><strong>Why it matters</strong></th>
</tr>
</thead>
<tbody><tr>
<td>AI moved into apps</td>
<td>Developers need to connect models to real products</td>
</tr>
<tr>
<td>The web is the main interface</td>
<td>Most AI tools are delivered through browsers</td>
</tr>
<tr>
<td>SDKs became TypeScript first</td>
<td>OpenAI, Anthropic, Vercel, LangChain, and others support strong TypeScript workflows</td>
</tr>
<tr>
<td>AI outputs are messy</td>
<td>Types, schemas, and validation help tame unpredictable responses</td>
</tr>
<tr>
<td>Teams need speed with guardrails</td>
<td>TypeScript lets small teams move fast without losing structure</td>
</tr>
</tbody></table>
<p>TypeScript is not the best language for training models.</p>
<p>It is becoming the best language for shipping AI features to users.</p>
<h2><strong>AI apps are not just model calls</strong></h2>
<p>The simplest AI demo looks like this.</p>
<pre><code class="language-typescript">const response = await model.generate("Write a summary of this document")
console.log(response.text)
</code></pre>
<p>That is fine for a demo.</p>
<p>A real AI product looks very different.</p>
<p>It needs to handle:</p>
<ul>
<li><p>User sessions</p>
</li>
<li><p>Permissions</p>
</li>
<li><p>Streaming responses</p>
</li>
<li><p>File uploads</p>
</li>
<li><p>Tool calls</p>
</li>
<li><p>Prompt templates</p>
</li>
<li><p>Model routing</p>
</li>
<li><p>Structured outputs</p>
</li>
<li><p>Retries and timeouts</p>
</li>
<li><p>Token usage</p>
</li>
<li><p>Rate limits</p>
</li>
<li><p>Database writes</p>
</li>
<li><p>Background jobs</p>
</li>
<li><p>Error reporting</p>
</li>
<li><p>Safety checks</p>
</li>
<li><p>Human approval</p>
</li>
<li><p>Observability</p>
</li>
</ul>
<p>That is not a model problem. That is an application engineering problem.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/fe228bf5-662e-4043-9373-e6a4872f73f6.png" alt="" style="display:block;margin:0 auto" />

<p>This is the first reason TypeScript became so important.</p>
<p>AI applications live close to the product surface. They need frontend code, backend code, serverless functions, API handlers, form state, database clients, and deployment platforms. TypeScript can cover all of that without switching languages.</p>
<p>A team can write the chat UI, the streaming endpoint, the tool definitions, the validation schemas, and the database access layer in one language.</p>
<p>That is a big deal when AI product cycles are measured in days.</p>
<h2><strong>The data points in the trend</strong></h2>
<p>The trend is visible in developer data and ecosystem behavior.</p>
<p>GitHub's Octoverse 2025 report described AI, agents, and typed languages as driving one of the biggest shifts in software development in more than a decade. GitHub also reported that TypeScript reached the number one position on the platform in that report cycle.</p>
<p>Stack Overflow's 2025 Developer Survey shows how fast AI became normal developer tooling. It reports that 84 percent of respondents are using or planning to use AI tools in their development process, up from 76 percent the previous year. It also reports that 51 percent of professional developers use AI tools daily.</p>
<p>The State of JavaScript 2024 survey showed another important pattern: 67 percent of respondents said they write more TypeScript than JavaScript, and the largest single group said they only write TypeScript.</p>
<p>These are not isolated numbers. They point to the same direction.</p>
<p>Developers are using AI more. They are also using typed JavaScript more. The overlap is where modern AI app development is happening.</p>
<img src="https://commons.wikimedia.org/wiki/Special:Redirect/file/Typescript_logo_2020.svg" alt="TypeScript logo" style="display:block;margin:0 auto" />

<p>The more interesting evidence is in the tools people use.</p>
<p>Vercel's AI SDK describes itself as a TypeScript toolkit for building AI powered applications and agents with React, Next.js, Vue, Svelte, Node.js, and more. The official OpenAI TypeScript and JavaScript SDK provides server side access to the OpenAI API. Anthropic provides an official TypeScript SDK for the Claude API. LangChain.js provides JavaScript and TypeScript tools for agents, models, embeddings, vector stores, and workflows.</p>
<p>The center of gravity for AI app development is not only in Python notebooks anymore.</p>
<p>It is also in TypeScript repositories.</p>
<h2><strong>Why TypeScript fits AI product work</strong></h2>
<p>TypeScript works well for AI apps because AI apps are full of boundaries.</p>
<p>There is a boundary between the user and the app. Another between the app and the model. Another between model output and trusted application state. Another between tools and real systems. Another between frontend state and backend data.</p>
<p>Every boundary is a place where things can break.</p>
<p>TypeScript gives developers a way to describe those boundaries.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/8da39988-35ac-49a0-af62-ba7dbb1291fc.png" alt="" style="display:block;margin:0 auto" />

<p>That does not make AI deterministic. It does not magically stop hallucinations. It does not replace testing.</p>
<p>But it does reduce the number of ordinary software mistakes around the model.</p>
<p>For example:</p>
<ul>
<li><p>A tool call should have a known input shape.</p>
</li>
<li><p>A model response should be parsed before it touches business logic.</p>
</li>
<li><p>A database write should not accept random model text as a trusted object.</p>
</li>
<li><p>A UI component should know whether a message is streaming, complete, failed, or waiting for approval.</p>
</li>
<li><p>A workflow should know which tools are read only and which tools can change real data.</p>
</li>
</ul>
<p>TypeScript helps teams express those rules in code.</p>
<p>It is not about type theory. It is about not shipping chaos.</p>
<h2><strong>The AI stack moved closer to the web</strong></h2>
<p>Most people experience AI through web apps.</p>
<p>ChatGPT, Claude, Gemini, Perplexity, Cursor, v0, Replit, Notion AI, Linear integrations, customer support copilots, internal knowledge assistants, and dashboard copilots all have a strong web surface.</p>
<p>That matters because the web already had a dominant language family: JavaScript and TypeScript.</p>
<p>The AI app stack often looks like this:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/b1053a73-0ac7-4b3c-8a06-d2e8c23cb4aa.png" alt="" style="display:block;margin:0 auto" />

<p>In this architecture, TypeScript is not a side language. It is the glue.</p>
<p>It powers the interface. It powers the server route. It defines the tool input. It validates the output. It talks to the database. It streams tokens back to the browser.</p>
<p>This full stack continuity is the biggest practical advantage.</p>
<p>A Python backend can absolutely power an AI product. Many great AI products use Python. But if the frontend is TypeScript, the API client is generated into TypeScript, the validation schemas are needed in the browser, and the deployment target is serverless JavaScript, the pressure to keep more logic in TypeScript grows quickly.</p>
<p>That is why many teams end up with this split:</p>
<table>
<thead>
<tr>
<th><strong>Layer</strong></th>
<th><strong>Common language</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Model research</td>
<td>Python</td>
</tr>
<tr>
<td>Data science</td>
<td>Python</td>
</tr>
<tr>
<td>Training and fine tuning</td>
<td>Python</td>
</tr>
<tr>
<td>Product UI</td>
<td>TypeScript</td>
</tr>
<tr>
<td>API routes</td>
<td>TypeScript or Python</td>
</tr>
<tr>
<td>Agents inside web products</td>
<td>TypeScript</td>
</tr>
<tr>
<td>Tool calling and integrations</td>
<td>TypeScript</td>
</tr>
<tr>
<td>Internal dashboards</td>
<td>TypeScript</td>
</tr>
<tr>
<td>Browser AI</td>
<td>TypeScript</td>
</tr>
</tbody></table>
<p>Python is still the lab.</p>
<p>TypeScript is increasingly the product floor.</p>
<h2><strong>Streaming made the frontend matter again</strong></h2>
<p>AI apps are not like traditional request response apps.</p>
<p>When a user asks a model a question, the response may take seconds. If the app waits for the whole response before showing anything, it feels slow.</p>
<p>That is why streaming became a core part of AI UX.</p>
<p>Instead of this:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/03efa1c7-5b04-40cc-9367-6c41b01e417d.png" alt="" style="display:block;margin:0 auto" />

<p>Modern AI apps often do this:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/608e5495-458b-46a0-80ef-c2614fe90b8d.png" alt="" style="display:block;margin:0 auto" />

<p>This made frontend engineering more important, not less.</p>
<p>The app needs to render partial messages. It needs to handle cancelled requests. It needs to recover from broken streams. It needs to show tool calls in progress. It needs to keep the conversation state consistent.</p>
<p>TypeScript fits this because it already owns the browser side of the problem.</p>
<p>A simple AI message type might look like this:</p>
<pre><code class="language-typescript">type MessageStatus = "submitted" | "streaming" | "complete" | "failed"

type ChatMessage = {
  id: string
  role: "user" | "assistant" | "tool"
  content: string
  status: MessageStatus
  createdAt: string
  tokenCount?: number
}
</code></pre>
<p>That small type is not fancy. But in a real app, it prevents a lot of confusion.</p>
<p>Is the message still streaming? Did it fail? Was it produced by a user, assistant, or tool? Can the user retry it? Should it count toward billing?</p>
<p>Good AI UX depends on clean state.</p>
<p>TypeScript is good at clean state.</p>
<h2><strong>Structured output changed the game</strong></h2>
<p>Early AI apps often treated model output as plain text.</p>
<p>That works for chat. It does not work as well when the model needs to feed another part of the app.</p>
<p>For example, imagine asking a model to classify a support ticket.</p>
<p>Bad version:</p>
<pre><code class="language-plaintext">This ticket is probably urgent and seems related to billing.
</code></pre>
<p>Useful version:</p>
<pre><code class="language-json">{
  "priority": "high",
  "category": "billing",
  "needsHumanReview": true
}
</code></pre>
<p>The second version can drive software. It can route a ticket, update a dashboard, trigger an approval flow, or create a task.</p>
<p>This is why structured outputs became so important.</p>
<p>OpenAI's Structured Outputs feature is designed to make model responses follow a supplied JSON Schema. Zod gives TypeScript developers a runtime schema validation library that also produces TypeScript types. The Vercel AI SDK supports schema based generation patterns. Together, these tools match the way AI apps are built.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/a1e3bf87-6bc8-4e35-8138-aa4980c772d6.png" alt="" style="display:block;margin:0 auto" />

<p>Here is the idea in TypeScript:</p>
<pre><code class="language-typescript">import { z } from "zod"

const TicketClassification = z.object({
  priority: z.enum(["low", "medium", "high"]),
  category: z.enum(["billing", "bug", "feature", "other"]),
  needsHumanReview: z.boolean(),
  summary: z.string().min(1)
})

type TicketClassification = z.infer&lt;typeof TicketClassification&gt;

function handleClassification(raw: unknown) {
  const result = TicketClassification.parse(raw)

  if (result.needsHumanReview) {
    return createHumanReviewTask(result)
  }

  return routeTicket(result)
}
</code></pre>
<p>The important part is not the syntax.</p>
<p>The important part is the mindset.</p>
<p>Model output is untrusted until it is parsed. Once it passes validation, the rest of the app can treat it as a known shape.</p>
<p>That is exactly how professional AI apps should work.</p>
<h2><strong>Tool calling needs types</strong></h2>
<p>Agents are not just chatbots.</p>
<p>An agent can choose tools, call APIs, inspect results, and continue working. That makes tool definitions one of the most important parts of an AI system.</p>
<p>A badly designed tool is dangerous.</p>
<p>It may be too broad. It may accept vague parameters. It may allow destructive actions without approval. It may return too much data. It may make it easy for the model to do the wrong thing.</p>
<p>TypeScript helps because tool contracts can be written clearly.</p>
<pre><code class="language-typescript">const createIssueTool = {
  name: "create_issue",
  description: "Create a GitHub issue after the user has approved the title and body.",
  inputSchema: z.object({
    repo: z.string(),
    title: z.string().min(5),
    body: z.string().min(10),
    labels: z.array(z.string()).default([])
  })
}
</code></pre>
<p>That schema does several things.</p>
<p>It tells the model what the tool expects. It tells the runtime how to validate input. It gives the developer a type to use in code. It documents the boundary between language and action.</p>
<p>This is where TypeScript becomes more than a developer convenience.</p>
<p>It becomes part of the safety model.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/0da75515-0d88-43e5-a9d9-d31b3205e249.png" alt="" style="display:block;margin:0 auto" />

<p>A real AI app should not let a model call arbitrary functions with arbitrary JSON.</p>
<p>Every tool should have a name, a description, a schema, a permission level, and a logging path.</p>
<p>TypeScript makes that style natural.</p>
<h2><strong>The SDK ecosystem moved fast</strong></h2>
<p>TypeScript's AI rise is also about timing.</p>
<p>When the AI app boom started, the web ecosystem was already mature. Developers already had:</p>
<ul>
<li><p>React</p>
</li>
<li><p>Next.js</p>
</li>
<li><p>Node.js</p>
</li>
<li><p>npm</p>
</li>
<li><p>Vite</p>
</li>
<li><p>tRPC</p>
</li>
<li><p>Prisma</p>
</li>
<li><p>Drizzle</p>
</li>
<li><p>Zod</p>
</li>
<li><p>Playwright</p>
</li>
<li><p>Vitest</p>
</li>
<li><p>Tailwind CSS</p>
</li>
<li><p>Serverless platforms</p>
</li>
<li><p>Edge runtimes</p>
</li>
<li><p>Component libraries</p>
</li>
</ul>
<p>Then AI SDKs arrived directly inside that ecosystem.</p>
<p>The Vercel AI SDK is provider agnostic and built for TypeScript app development. OpenAI maintains an official TypeScript and JavaScript library. Anthropic maintains an official TypeScript SDK. LangChain.js and LangGraph.js support agent and workflow development in JavaScript and TypeScript. The OpenAI Agents SDK for TypeScript targets agentic applications in JavaScript and TypeScript.</p>
<p>That means a developer can build a useful AI product without leaving the TypeScript world.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/388b5f82-0282-4529-a730-d99bd7239bc5.png" alt="" style="display:block;margin:0 auto" />

<p>This matters because the best language is not always the one with the best syntax.</p>
<p>Often, it is the one with the shortest path from idea to production.</p>
<p>For AI apps, TypeScript has that path.</p>
<h2><strong>TypeScript is useful when the model is wrong</strong></h2>
<p>AI systems fail in strange ways.</p>
<p>A normal function usually fails because of a bug, a bad input, or an unavailable dependency.</p>
<p>A model can fail because it misunderstood the prompt, invented a field, ignored an instruction, mixed two tools, returned a half valid object, or gave a confident answer that looks correct but is not.</p>
<p>Types do not solve those problems.</p>
<p>But they help contain them.</p>
<p>Think of TypeScript as guardrails around a messy center.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/71b26a34-5fb4-4fd2-869d-9a3a77c1713a.png" alt="" style="display:block;margin:0 auto" />

<p>The model can still be wrong. But the app should know what shape the wrongness is allowed to take.</p>
<p>For example, if a model classifies a transaction, it should not be allowed to invent a new transaction status that the rest of the system does not understand.</p>
<pre><code class="language-typescript">type TransactionRisk = "safe" | "review" | "blocked"
</code></pre>
<p>If the model returns <code>maybe_suspicious</code>, the app should reject it or map it through an explicit fallback path.</p>
<p>This sounds boring.</p>
<p>It is boring.</p>
<p>That is the point.</p>
<p>Reliable AI apps are built from boring constraints around powerful models.</p>
<h2><strong>The frontend is now part of the AI system</strong></h2>
<p>In older backend systems, frontend code was often treated as a display layer.</p>
<p>In AI apps, the frontend is more involved.</p>
<p>It may need to:</p>
<ul>
<li><p>Show streaming text</p>
</li>
<li><p>Show tool call progress</p>
</li>
<li><p>Let users approve or reject actions</p>
</li>
<li><p>Render citations</p>
</li>
<li><p>Display confidence levels</p>
</li>
<li><p>Compare model outputs</p>
</li>
<li><p>Let users edit prompts or instructions</p>
</li>
<li><p>Handle voice input</p>
</li>
<li><p>Handle file uploads</p>
</li>
<li><p>Show partial results from long running workflows</p>
</li>
<li><p>Warn users when the model is uncertain</p>
</li>
</ul>
<p>The UI is not just showing the answer. It is managing the human model interaction.</p>
<p>That makes TypeScript valuable because frontend mistakes can become product mistakes.</p>
<p>A user should not accidentally approve a tool call because state was stale. A citation should not point to the wrong document because array indexes shifted. A retry should not create duplicate tasks because the client lost track of request IDs.</p>
<p>Here is a simple type for a tool approval flow:</p>
<pre><code class="language-typescript">type ToolApproval = {
  id: string
  toolName: string
  risk: "low" | "medium" | "high"
  proposedInput: unknown
  status: "pending" | "approved" | "rejected" | "expired"
  requestedAt: string
  approvedBy?: string
}
</code></pre>
<p>That type is small, but it forces the app to ask useful questions.</p>
<p>Is this tool call pending? Who approved it? Did it expire? Is it high risk? What exactly is being approved?</p>
<p>When an AI app can act on the real world, the UI becomes a control surface.</p>
<p>Control surfaces need strong state models.</p>
<h2><strong>Agent frameworks need application discipline</strong></h2>
<p>Agent demos are easy.</p>
<p>Production agents are hard.</p>
<p>A production agent needs more than a loop that calls a model until it finishes. It needs stop conditions, tool limits, memory rules, retries, traces, permission checks, evaluation sets, and fallback behavior.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/0554cc79-b6af-471c-81f1-0cf371e0c6d8.png" alt="" style="display:block;margin:0 auto" />

<p>TypeScript is a good fit here because agent systems are mostly orchestration.</p>
<p>They coordinate tools. They pass structured data. They maintain state. They call APIs. They update UIs. They emit logs.</p>
<p>This is normal software engineering, just with a model in the middle.</p>
<p>That is why the phrase "AI engineer" can be misleading. For many product teams, the AI engineer is not training a model. They are building reliable software around a model.</p>
<p>TypeScript is excellent for that kind of work.</p>
<h2><strong>The type system helps teams share intent</strong></h2>
<p>TypeScript's value grows with team size.</p>
<p>In a solo prototype, types may feel optional. In a team building an AI product, they become communication.</p>
<p>A type tells another developer:</p>
<ul>
<li><p>What this function expects</p>
</li>
<li><p>What this API returns</p>
</li>
<li><p>What states are possible</p>
</li>
<li><p>What fields are optional</p>
</li>
<li><p>What tool calls are allowed</p>
</li>
<li><p>What errors should be handled</p>
</li>
</ul>
<p>That is especially useful in AI apps because the domain changes fast.</p>
<p>Prompts change. Models change. Providers change. Product behavior changes. New tools get added. Old tools get retired. Workflows get split. Safety rules get stricter.</p>
<p>Types give the codebase a map.</p>
<p>For example:</p>
<pre><code class="language-plaintext">type ModelProvider = "openai" | "anthropic" | "google" | "local"

type ModelRoute = {
  provider: ModelProvider
  model: string
  purpose: "chat" | "classification" | "embedding" | "tool_use"
  maxTokens: number
  fallback?: ModelRoute
}
</code></pre>
<p>This makes model routing explicit.</p>
<p>That is much better than scattering model names across random files.</p>
<p>AI apps need this kind of clarity because model behavior is already uncertain. The surrounding software should not also be uncertain.</p>
<h2><strong>TypeScript and Python are not enemies</strong></h2>
<p>It is tempting to frame this as TypeScript versus Python.</p>
<p>That is the wrong framing.</p>
<p>Python and TypeScript are solving different problems in the AI era.</p>
<table>
<thead>
<tr>
<th><strong>Workload</strong></th>
<th><strong>Python strength</strong></th>
<th><strong>TypeScript strength</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Research notebooks</td>
<td>Excellent</td>
<td>Weak</td>
</tr>
<tr>
<td>Model training</td>
<td>Excellent</td>
<td>Weak</td>
</tr>
<tr>
<td>Data pipelines</td>
<td>Strong</td>
<td>Moderate</td>
</tr>
<tr>
<td>Backend APIs</td>
<td>Strong</td>
<td>Strong</td>
</tr>
<tr>
<td>Web UI</td>
<td>Weak</td>
<td>Excellent</td>
</tr>
<tr>
<td>Streaming chat</td>
<td>Moderate</td>
<td>Excellent</td>
</tr>
<tr>
<td>Agent product UX</td>
<td>Moderate</td>
<td>Excellent</td>
</tr>
<tr>
<td>Tool integrations</td>
<td>Strong</td>
<td>Strong</td>
</tr>
<tr>
<td>Browser AI</td>
<td>Weak</td>
<td>Excellent</td>
</tr>
<tr>
<td>Full stack product</td>
<td>Moderate</td>
<td>Excellent</td>
</tr>
</tbody></table>
<p>Python is still the default for building models and experimenting with AI techniques.</p>
<p>TypeScript is becoming the default for turning model capabilities into products.</p>
<p>Many serious teams will use both.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/34a92434-a00b-4d97-ae1f-213bf44356e2.png" alt="" style="display:block;margin:0 auto" />

<p>The best architecture is often hybrid.</p>
<p>Use Python where the AI ecosystem is strongest. Use TypeScript where product engineering is strongest. Keep the boundary clean.</p>
<h2><strong>The browser AI wave favors TypeScript</strong></h2>
<p>Another reason TypeScript matters is that some AI is moving closer to the user.</p>
<p>WebGPU, WebAssembly, ONNX Runtime Web, Transformers.js, WebLLM, and emerging browser AI APIs are making it more realistic to run smaller models or AI features locally in the browser.</p>
<p>That does not mean every app will run a large model on device. It means some AI features can happen without a round trip to a cloud model.</p>
<p>Examples include:</p>
<ul>
<li><p>Local embeddings</p>
</li>
<li><p>Small text classifiers</p>
</li>
<li><p>Offline summarization</p>
</li>
<li><p>Privacy sensitive processing</p>
</li>
<li><p>Image preprocessing</p>
</li>
<li><p>On device autocomplete</p>
</li>
<li><p>Hybrid cloud and local workflows</p>
</li>
</ul>
<p>When AI runs in the browser, TypeScript becomes even more central.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/a82ea4cf-8a2c-43e7-bb5c-d7a0de2e052b.png" alt="" style="display:block;margin:0 auto" />

<p>This is not replacing cloud AI.</p>
<p>It is expanding the AI runtime surface. Some logic stays in the cloud. Some moves to the edge. Some moves into the browser. TypeScript is one of the few languages that can sit naturally across all of those places.</p>
<h2><strong>Why runtimes matter</strong></h2>
<p>The old JavaScript world was mostly browser plus Node.js.</p>
<p>The new TypeScript world has more runtime options:</p>
<table>
<thead>
<tr>
<th><strong>Runtime</strong></th>
<th><strong>Why it matters for AI apps</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Node.js</td>
<td>Mature ecosystem, broad SDK support, production familiarity</td>
</tr>
<tr>
<td>Deno</td>
<td>Secure runtime model, built in TypeScript support, web standards focus</td>
</tr>
<tr>
<td>Bun</td>
<td>Fast startup, integrated tooling, TypeScript and JSX support out of the box</td>
</tr>
<tr>
<td>Edge runtimes</td>
<td>Low latency API routes, streaming, global deployment</td>
</tr>
<tr>
<td>Browser</td>
<td>Local AI, UI state, WebGPU, WebAssembly</td>
</tr>
</tbody></table>
<p>Deno says it can run JavaScript and TypeScript with no additional tools or configuration. Bun describes itself as an all in one toolkit for JavaScript and TypeScript apps. Edge platforms often support TypeScript based workflows because the web platform is already the common denominator.</p>
<p>This gives AI product teams flexibility.</p>
<p>A small team can start with a Next.js app. They can add an AI SDK route. They can stream responses. They can move some routes to the edge. They can add background jobs. They can later split out Python services if needed.</p>
<p>TypeScript does not force the whole system into one runtime.</p>
<p>It gives teams a shared language across many runtimes.</p>
<h2><strong>The hidden reason TypeScript works so well with AI tools</strong></h2>
<p>AI coding assistants are better when the codebase gives them structure.</p>
<p>Types are structure.</p>
<p>A TypeScript codebase gives an AI coding tool more hints than a loosely structured JavaScript codebase. Function signatures, interfaces, discriminated unions, schema definitions, and generated API types all give the assistant a clearer target.</p>
<p>That does not mean AI generated TypeScript is always correct.</p>
<p>It is not.</p>
<p>But typed code makes mistakes easier to catch.</p>
<p>If an AI assistant invents a property that does not exist, the compiler can flag it. If it passes the wrong object shape to a function, TypeScript can complain. If it forgets a union case, strict checking can help expose it.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/2ac8c241-7d1a-49dc-b460-2cade79d7b7c.png" alt="" style="display:block;margin:0 auto" />

<p>This is one reason typed languages are gaining more attention in the agentic coding era.</p>
<p>AI tools can generate code quickly. Type systems help teams reject some bad code quickly.</p>
<p>That combination is powerful.</p>
<h2><strong>Where TypeScript is weak</strong></h2>
<p>A good argument should include the limits.</p>
<p>TypeScript is not the answer to every AI problem.</p>
<p>It has real weaknesses.</p>
<p>First, TypeScript types disappear at runtime. The compiler checks your code before it runs, but external data still needs runtime validation. This is why tools like Zod matter.</p>
<p>Second, the AI research ecosystem is still much stronger in Python. If you need custom model training, deep learning research, or heavy numerical work, TypeScript is not the natural choice.</p>
<p>Third, JavaScript package supply chain risk is real. npm is huge, fast moving, and sometimes messy. AI app teams should be careful with dependencies, lockfiles, package provenance, and CI permissions.</p>
<p>Fourth, full stack TypeScript can become too clever. Teams sometimes over abstract simple systems with complex types, generated clients, and framework specific patterns. TypeScript should make the system clearer, not more theatrical.</p>
<p>Fifth, serverless TypeScript can hide infrastructure problems. Cold starts, memory limits, long running jobs, queue behavior, and streaming timeouts still matter.</p>
<p>TypeScript is a strong product language.</p>
<p>It is not magic.</p>
<h2><strong>A practical TypeScript architecture for AI apps</strong></h2>
<p>A solid TypeScript AI app usually has clear layers.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/8507a765-d9e6-4179-8ba3-0723a4a558f9.png" alt="" style="display:block;margin:0 auto" />

<p>The key is separation.</p>
<p>Do not let model calls spread everywhere. Put them behind a model gateway. Do not let tools run without schemas. Put tool execution behind a runtime. Do not let the UI guess what is happening. Give it typed states.</p>
<p>A clean project might look like this:</p>
<pre><code class="language-plaintext">src/
  app/
    chat/
      page.tsx
    api/
      chat/
        route.ts
  ai/
    models.ts
    prompts.ts
    gateway.ts
    streaming.ts
  tools/
    index.ts
    github.ts
    database.ts
    approval.ts
  schemas/
    messages.ts
    tool-inputs.ts
    model-outputs.ts
  server/
    auth.ts
    rate-limit.ts
    logging.ts
  db/
    schema.ts
    queries.ts
  evals/
    ticket-classification.eval.ts
    tool-safety.eval.ts
</code></pre>
<p>The exact folders do not matter.</p>
<p>The boundaries do.</p>
<h2><strong>Patterns that work well</strong></h2>
<p>Here are patterns that make TypeScript AI apps easier to maintain.</p>
<h3><strong>Keep prompts close to types</strong></h3>
<p>A prompt should not be a mysterious string in the middle of a route handler.</p>
<p>If a prompt asks for a specific output, keep the schema nearby.</p>
<pre><code class="language-typescript">const SummarySchema = z.object({
  title: z.string(),
  bullets: z.array(z.string()).min(3).max(7),
  confidence: z.number().min(0).max(1)
})
</code></pre>
<p>The prompt and schema should evolve together.</p>
<h3><strong>Treat model output as unknown</strong></h3>
<p>This is one of the most important rules.</p>
<pre><code class="language-typescript">function parseModelOutput(output: unknown) {
  return SummarySchema.parse(output)
}
</code></pre>
<p>Do not trust model output because it looks like JSON.</p>
<p>Parse it.</p>
<h3><strong>Use discriminated unions for workflow state</strong></h3>
<p>AI workflows have many states. Make them explicit.</p>
<pre><code class="language-typescript">type RunState =
  | { status: "queued"; runId: string }
  | { status: "running"; runId: string; currentStep: string }
  | { status: "waiting_for_approval"; runId: string; approvalId: string }
  | { status: "completed"; runId: string; resultId: string }
  | { status: "failed"; runId: string; error: string }
</code></pre>
<p>This helps both the UI and the backend.</p>
<h3><strong>Separate read tools from write tools</strong></h3>
<p>A read tool and a write tool should not feel the same.</p>
<pre><code class="language-typescript">type ToolRisk = "read" | "low_write" | "high_write"
</code></pre>
<p>Then enforce different controls.</p>
<p>Read tools may only need logging. High risk write tools may need approval.</p>
<h3><strong>Build a provider neutral model layer</strong></h3>
<p>Do not scatter provider calls everywhere.</p>
<pre><code class="language-typescript">type GenerateTextInput = {
  purpose: "chat" | "summary" | "classification"
  messages: Array&lt;{ role: "system" | "user" | "assistant"; content: string }&gt;
  temperature?: number
}
</code></pre>
<p>A model gateway lets you switch providers, add fallbacks, and track cost more easily.</p>
<h3><strong>Log the boring details</strong></h3>
<p>For every model call, log:</p>
<ul>
<li><p>Model name</p>
</li>
<li><p>Provider</p>
</li>
<li><p>Purpose</p>
</li>
<li><p>Latency</p>
</li>
<li><p>Token usage</p>
</li>
<li><p>User or service ID</p>
</li>
<li><p>Tool calls requested</p>
</li>
<li><p>Tool calls approved</p>
</li>
<li><p>Error type</p>
</li>
</ul>
<p>This data becomes priceless when something breaks.</p>
<h2><strong>Patterns that usually age badly</strong></h2>
<p>Some patterns feel fast at first and painful later.</p>
<table>
<thead>
<tr>
<th><strong>Pattern</strong></th>
<th><strong>Why it hurts later</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Raw string prompts everywhere</td>
<td>Hard to test, version, or debug</td>
</tr>
<tr>
<td>No output validation</td>
<td>Model mistakes leak into app logic</td>
</tr>
<tr>
<td>One giant agent tool</td>
<td>Too broad and hard to secure</td>
</tr>
<tr>
<td>Provider calls in UI components</td>
<td>Hard to control secrets and permissions</td>
</tr>
<tr>
<td>No streaming state model</td>
<td>UI bugs and duplicate messages</td>
</tr>
<tr>
<td>No evaluation tests</td>
<td>Regressions go unnoticed</td>
</tr>
<tr>
<td>No audit logs</td>
<td>You cannot explain what the agent did</td>
</tr>
<tr>
<td>Shared admin token for tools</td>
<td>One bug can become a serious incident</td>
</tr>
</tbody></table>
<p>The fix is not heavy enterprise architecture.</p>
<p>The fix is simple structure from the start.</p>
<h2><strong>What this means for developers</strong></h2>
<p>For frontend developers, this is an opportunity.</p>
<p>The AI app era needs people who understand interfaces, state, user flows, latency, accessibility, and product quality. That is frontend work, but with new primitives.</p>
<p>For backend developers, TypeScript is becoming harder to ignore.</p>
<p>AI product backends often live near the web layer. They stream responses, manage tools, handle auth, and coordinate providers. TypeScript is a practical fit for that work.</p>
<p>For Python developers, this is not a threat.</p>
<p>It is a collaboration point. The model and data layer may stay in Python. The product and orchestration layer may move through TypeScript. The clean boundary between them is where good systems are built.</p>
<p>For teams, the message is simple.</p>
<p>Do not choose TypeScript because it is fashionable. Choose it when your AI work is mostly product engineering: UI, tools, agents, APIs, workflows, and structured model output.</p>
<p>That is where TypeScript shines.</p>
<h2><strong>The future is typed, streamed, and full stack</strong></h2>
<p>The first wave of AI apps was about calling a model.</p>
<p>The next wave is about building systems around models.</p>
<p>Those systems need interfaces. They need schemas. They need tool contracts. They need human approval flows. They need streaming UX. They need observability. They need deployment paths that small teams can manage.</p>
<p>TypeScript is popular in the AI app era because it gives developers a practical way to build all of that in one ecosystem.</p>
<p>It is not replacing Python.</p>
<p>It is not replacing model research.</p>
<p>It is becoming the language many teams reach for when they want to turn AI into a real product.</p>
<p>That is the important shift.</p>
<p>The AI era did not just create a need for better models. It created a need for better product infrastructure around models.</p>
<p>TypeScript happened to be standing exactly where that infrastructure needed to be built.</p>
<h2><strong>References</strong></h2>
<ul>
<li><p>GitHub Octoverse 2025: <a href="https://octoverse.github.com/">https://octoverse.github.com/</a></p>
</li>
<li><p>GitHub blog on Octoverse 2025 and TypeScript: <a href="https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/">https://github.blog/news-insights/octoverse/octoverse-a-new-developer-joins-github-every-second-as-ai-leads-typescript-to-1/</a></p>
</li>
<li><p>Stack Overflow Developer Survey 2025 AI section: <a href="https://survey.stackoverflow.co/2025/ai">https://survey.stackoverflow.co/2025/ai</a></p>
</li>
<li><p>Stack Overflow Developer Survey 2025 technology section: <a href="https://survey.stackoverflow.co/2025/technology">https://survey.stackoverflow.co/2025/technology</a></p>
</li>
<li><p>State of JavaScript 2024 usage data: <a href="https://2024.stateofjs.com/en-US/usage/">https://2024.stateofjs.com/en-US/usage/</a></p>
</li>
<li><p>Vercel AI SDK documentation: <a href="https://ai-sdk.dev/docs/introduction">https://ai-sdk.dev/docs/introduction</a></p>
</li>
<li><p>Vercel AI SDK repository: <a href="https://github.com/vercel/ai">https://github.com/vercel/ai</a></p>
</li>
<li><p>OpenAI TypeScript and JavaScript SDK docs: <a href="https://developers.openai.com/api/reference/typescript/">https://developers.openai.com/api/reference/typescript/</a></p>
</li>
<li><p>OpenAI SDKs and libraries: <a href="https://developers.openai.com/api/docs/libraries">https://developers.openai.com/api/docs/libraries</a></p>
</li>
<li><p>OpenAI Structured Outputs guide: <a href="https://developers.openai.com/api/docs/guides/structured-outputs">https://developers.openai.com/api/docs/guides/structured-outputs</a></p>
</li>
<li><p>Anthropic TypeScript SDK docs: <a href="https://platform.claude.com/docs/en/api/client-sdks">https://platform.claude.com/docs/en/api/client-sdks</a></p>
</li>
<li><p>Anthropic TypeScript SDK repository: <a href="https://github.com/anthropics/anthropic-sdk-typescript">https://github.com/anthropics/anthropic-sdk-typescript</a></p>
</li>
<li><p>LangChain.js agents documentation: <a href="https://docs.langchain.com/oss/javascript/langchain/agents">https://docs.langchain.com/oss/javascript/langchain/agents</a></p>
</li>
<li><p>LangChain.js reference: <a href="https://reference.langchain.com/javascript/langchain">https://reference.langchain.com/javascript/langchain</a></p>
</li>
<li><p>OpenAI Agents SDK for TypeScript: <a href="https://openai.github.io/openai-agents-js/">https://openai.github.io/openai-agents-js/</a></p>
</li>
<li><p>Zod documentation: <a href="https://zod.dev/">https://zod.dev/</a></p>
</li>
<li><p>TypeScript 5.9 announcement: <a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-9/">https://devblogs.microsoft.com/typescript/announcing-typescript-5-9/</a></p>
</li>
<li><p>Bun TypeScript runtime docs: <a href="https://bun.com/docs/runtime/typescript">https://bun.com/docs/runtime/typescript</a></p>
</li>
<li><p>Deno runtime docs: <a href="https://docs.deno.com/runtime/">https://docs.deno.com/runtime/</a></p>
</li>
<li><p>TypeScript logo on Wikimedia Commons: <a href="https://commons.wikimedia.org/wiki/File:Typescript_logo_2020.svg">https://commons.wikimedia.org/wiki/File:Typescript_logo_2020.svg</a></p>
</li>
<li><p>Cover image from Unsplash: <a href="https://unsplash.com/s/photos/laptop-code">https://unsplash.com/s/photos/laptop-code</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[AI changed the software supply chain]]></title><description><![CDATA[Most developers still think of security as something that happens inside their own code.
That used to be a useful mental model. You wrote code, tested it, scanned it, shipped it, and patched it when a]]></description><link>https://blog.prashantkoirala.info.np/ai-changed-the-software-supply-chain</link><guid isPermaLink="true">https://blog.prashantkoirala.info.np/ai-changed-the-software-supply-chain</guid><category><![CDATA[software-supply-chain]]></category><category><![CDATA[Security]]></category><category><![CDATA[DevSecOps]]></category><category><![CDATA[Open Source]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Prashant Koirala]]></dc:creator><pubDate>Wed, 06 May 2026 01:57:11 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/672d7b4a-3f80-40b8-8ec1-507821c540ee.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most developers still think of security as something that happens inside their own code.</p>
<p>That used to be a useful mental model. You wrote code, tested it, scanned it, shipped it, and patched it when a vulnerability appeared. The boundary was clear enough. Your repository was your responsibility. Everything outside it was a dependency, a vendor, or an infrastructure problem.</p>
<p>That model is breaking.</p>
<p>Modern software is not written from scratch. It is assembled. A small web app can pull hundreds or thousands of transitive packages. A backend service can depend on base images, GitHub Actions, build scripts, cloud roles, code generators, secrets, registries, container layers, Terraform modules, model APIs, and now AI-generated code.</p>
<p>The supply chain is no longer a line from developer to production. It is a graph.</p>
<p>AI makes that graph bigger. It helps developers write code faster, but it also changes where code comes from, who reviews it, how dependencies are chosen, and how quickly risky changes move through the pipeline. AI agents can open pull requests, add packages, write workflows, call tools, and sometimes touch production systems. That is powerful. It is also dangerous when the pipeline was built for a slower world.</p>
<p>This article is a detailed look at the new software supply chain problem. It is written for developers, platform engineers, security engineers, and technical founders who want to understand what changed and what to do about it.</p>
<h2><strong>What changed</strong></h2>
<p>A few years ago, supply chain security felt like a topic for large companies, government vendors, and security teams. Then SolarWinds, Log4Shell, dependency confusion, package hijacking, CI leaks, and registry attacks made the lesson obvious.</p>
<p>You can write secure code and still ship compromised software.</p>
<p>That is the core idea. The attacker does not need to find a bug in your application if they can change what your application is built from.</p>
<p>A modern release is made from many parts:</p>
<ul>
<li><p>Your source code</p>
</li>
<li><p>Open source dependencies</p>
</li>
<li><p>Transitive dependencies</p>
</li>
<li><p>Package manager behavior</p>
</li>
<li><p>Lockfiles</p>
</li>
<li><p>Build scripts</p>
</li>
<li><p>CI/CD workflows</p>
</li>
<li><p>Secrets and tokens</p>
</li>
<li><p>Container base images</p>
</li>
<li><p>Infrastructure modules</p>
</li>
<li><p>Artifact registries</p>
</li>
<li><p>Deployment permissions</p>
</li>
<li><p>Generated code</p>
</li>
<li><p>AI-written changes</p>
</li>
<li><p>Third-party actions and plugins</p>
</li>
</ul>
<p>Every one of these can become the weak point.</p>
<p>The OWASP Top 10 for Large Language Model Applications lists supply chain vulnerabilities as a core LLM risk. OWASP also calls out prompt injection, insecure output handling, sensitive information disclosure, and insecure plugin design. Those are not separate from software supply chain security. They are becoming part of it.</p>
<p>Here is the simple version.</p>
<p>Before AI, the main question was:</p>
<blockquote>
<p>Can I trust this package, build, artifact, and deployment pipeline?</p>
</blockquote>
<p>Now we also have to ask:</p>
<blockquote>
<p>Can I trust how this code was suggested, generated, reviewed, approved, and connected to tools?</p>
</blockquote>
<p>That extra layer matters.</p>
<p>GitHub's 2025 Octoverse report says AI, agents, and typed languages are driving one of the biggest shifts in software development in more than a decade. That is not just a productivity story. It is a security story too. More code is being created faster, with more automation around it, and with more tools acting on behalf of developers.</p>
<p>Speed is useful. Blind speed is not.</p>
<h3><strong>The old model</strong></h3>
<p>The old model looked roughly like this.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/8a9f839f-f537-4e7c-9b0d-4b9073208a20.png" alt="" style="display:block;margin:0 auto" />

<p>It was never truly this simple, but many teams still reason this way.</p>
<p>The problem is that the real model now looks closer to this.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/935f0f06-b4d9-42fc-8acb-90a53897f45c.png" alt="" style="display:block;margin:0 auto" />

<p>There are more paths into the release. There are more identities. There are more machines making changes.</p>
<p>The attack surface has moved from "the code" to "the system that creates the code."</p>
<h3><strong>Why attackers like the supply chain</strong></h3>
<p>Supply chain attacks scale.</p>
<p>If an attacker compromises one small application, they get one target. If they compromise a package, a build action, a maintainer token, or a popular library, they get every downstream project that trusts it.</p>
<p>That is the appeal.</p>
<p>A single compromised package can reach:</p>
<ul>
<li><p>Developer laptops</p>
</li>
<li><p>CI runners</p>
</li>
<li><p>Internal repositories</p>
</li>
<li><p>Cloud credentials</p>
</li>
<li><p>Production deployment systems</p>
</li>
<li><p>Customer applications</p>
</li>
<li><p>Other packages maintained by the same account</p>
</li>
</ul>
<p>This is why package ecosystems are so attractive. The trust is already there. Developers install packages quickly. CI systems pull dependencies automatically. Build scripts run with high access. Many teams still use long-lived tokens.</p>
<p>The attacker does not need to knock on the front door. They can become part of the build.</p>
<h2><strong>Where attacks happen now</strong></h2>
<p>Supply chain security is easier to understand when you separate the attack paths. Most incidents are not magic. They follow patterns.</p>
<p>The modern software supply chain has several weak spots.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/8f34f5fe-ae84-42d0-910a-43aa34e0ee0e.png" alt="" style="display:block;margin:0 auto" />

<h3><strong>Package maintainers</strong></h3>
<p>Open source maintainers hold a lot of power. Many popular packages are maintained by one person, a small team, or a tired group of volunteers.</p>
<p>If an attacker gets a maintainer account, they may be able to publish a malicious version of a package. That version can then flow into real applications.</p>
<p>Common paths include:</p>
<ul>
<li><p>Phishing maintainers</p>
</li>
<li><p>Stealing npm, PyPI, or GitHub tokens</p>
</li>
<li><p>Taking over abandoned packages</p>
</li>
<li><p>Social engineering a maintainer</p>
</li>
<li><p>Getting added as a co-maintainer</p>
</li>
<li><p>Compromising a maintainer's laptop</p>
</li>
<li><p>Publishing a lookalike package</p>
</li>
</ul>
<p>This is not theoretical.</p>
<p>In 2025, the Shai-Hulud npm campaign showed how bad this can get. Unit 42 described it as a self-replicating worm that compromised npm packages and targeted developer credentials. The campaign looked for secrets such as npm tokens, GitHub personal access tokens, and cloud keys, then used stolen npm tokens to modify other packages maintained by the same developer. Unit 42 also assessed with moderate confidence that an LLM helped generate part of the malicious script, based on comments and emojis in the code.</p>
<p>That detail matters.</p>
<p>It means attackers are not just attacking AI systems. They may be using AI to scale attacks against traditional package ecosystems.</p>
<p>The Cyber Security Agency of Singapore also warned that Shai-Hulud used a self-propagating payload. Their advisory said the campaign began with the compromise of <code>@ctrl/tinycolor</code> and that researchers had identified more than 180 compromised npm packages during the attack window.</p>
<h3><strong>Package install scripts</strong></h3>
<p>Package install scripts are one of the scariest parts of the ecosystem.</p>
<p>In npm, packages can run lifecycle scripts during install. These scripts are useful for legitimate build steps. They are also useful for attackers because they execute when a developer or CI system installs dependencies.</p>
<p>That changes the risk.</p>
<p>A malicious package does not always need to be imported by your application. It may only need to be installed.</p>
<p>Here is the basic flow.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/4f03187a-4cfa-459a-a91b-0a83e2c6e5ba.png" alt="" style="display:block;margin:0 auto" />

<p>This is why CI dependency installation is a high risk moment.</p>
<p>A build runner often has access to:</p>
<ul>
<li><p>GitHub tokens</p>
</li>
<li><p>Cloud deployment credentials</p>
</li>
<li><p>npm or PyPI publish tokens</p>
</li>
<li><p>Docker registry credentials</p>
</li>
<li><p>Private package registry tokens</p>
</li>
<li><p>Signing keys</p>
</li>
<li><p>Environment variables</p>
</li>
<li><p>Internal network access</p>
</li>
</ul>
<p>If a dependency install script can read those, the build server becomes a treasure chest.</p>
<h3><strong>CI/CD workflows</strong></h3>
<p>CI/CD is where trust becomes action.</p>
<p>Your CI pipeline can test code, build containers, publish packages, deploy infrastructure, rotate versions, sign artifacts, and push to production. That means a compromised CI workflow can do real damage.</p>
<p>Common CI/CD risks include:</p>
<ul>
<li><p>Overpowered default tokens</p>
</li>
<li><p>Long-lived cloud secrets</p>
</li>
<li><p>Pull request workflows that expose secrets</p>
</li>
<li><p>Unpinned third-party actions</p>
</li>
<li><p>Actions pinned only by tag instead of commit SHA</p>
</li>
<li><p>Workflow injection through user-controlled input</p>
</li>
<li><p>Build scripts that run untrusted code</p>
</li>
<li><p>Self-hosted runners with broad network access</p>
</li>
<li><p>Missing separation between build and deploy jobs</p>
</li>
</ul>
<p>GitHub's own Actions security docs tell teams to use least privilege for credentials. Their OIDC docs also explain that GitHub Actions workflows can use OIDC tokens instead of stored long-lived cloud secrets.</p>
<p>That is a major improvement.</p>
<p>A long-lived cloud key in CI is a standing target. An OIDC token is short-lived and tied to a workflow identity. It is not a silver bullet, but it reduces the blast radius when something leaks.</p>
<h3><strong>Dependency confusion and typosquatting</strong></h3>
<p>Dependency confusion happens when internal package names overlap with public package names. If your package manager resolves the public version first, an attacker can publish a package with the same name and wait for your build to download it.</p>
<p>Typosquatting is simpler. The attacker publishes a package with a name that looks like a real one.</p>
<p>Examples of the pattern:</p>
<table>
<thead>
<tr>
<th><strong>Real package</strong></th>
<th><strong>Malicious style</strong></th>
</tr>
</thead>
<tbody><tr>
<td><code>requests</code></td>
<td><code>requestss</code></td>
</tr>
<tr>
<td><code>react-dom</code></td>
<td><code>reactdom</code></td>
</tr>
<tr>
<td><code>lodash</code></td>
<td><code>lodashts</code></td>
</tr>
<tr>
<td><code>company-internal-auth</code></td>
<td>Public package with same internal name</td>
</tr>
</tbody></table>
<p>Package managers have improved. Teams have also learned. But these attacks still work because developers move fast and package names are easy to misread.</p>
<p>AI can make this worse.</p>
<p>When a coding assistant suggests a package name that looks plausible, a developer may trust it. The package might be real. It might be abandoned. It might be malicious. It might not exist, which creates another problem: attackers can publish the suggested package later and wait for people to install it.</p>
<p>That is not science fiction. It is a natural side effect of generated code meeting public registries.</p>
<h3><strong>Container images</strong></h3>
<p>Dependencies are not only application packages.</p>
<p>A container image includes:</p>
<ul>
<li><p>Operating system packages</p>
</li>
<li><p>Language runtimes</p>
</li>
<li><p>Shell tools</p>
</li>
<li><p>System libraries</p>
</li>
<li><p>Certificates</p>
</li>
<li><p>Package manager caches</p>
</li>
<li><p>Build layers</p>
</li>
<li><p>Application artifacts</p>
</li>
</ul>
<p>If your base image is stale or untrusted, your application inherits that risk.</p>
<p>The same is true for container build steps. A Dockerfile can download scripts from the internet, install packages without pinning versions, and copy secrets into layers by mistake.</p>
<p>A bad image can pass code review because the risky part is not in application code. It is in the build environment.</p>
<h3><strong>Infrastructure as code</strong></h3>
<p>Terraform modules, Helm charts, Kubernetes manifests, and GitOps configs are part of the supply chain.</p>
<p>An attacker who changes infrastructure code may be able to:</p>
<ul>
<li><p>Open a storage bucket</p>
</li>
<li><p>Add a public ingress</p>
</li>
<li><p>Create an admin role</p>
</li>
<li><p>Disable logging</p>
</li>
<li><p>Expose a secret</p>
</li>
<li><p>Change an image tag</p>
</li>
<li><p>Route traffic to a malicious endpoint</p>
</li>
<li><p>Add a privileged sidecar</p>
</li>
</ul>
<p>AI agents can now edit infrastructure code too. That makes review even more important.</p>
<p>A generated Terraform change can look clean while quietly widening permissions. A generated Kubernetes manifest can work in staging while adding a risky security context. A generated GitHub Actions workflow can pass tests while exposing secrets to a pull request.</p>
<p>The risk is not that AI is evil.</p>
<p>The risk is that AI is confident, fast, and often unaware of your security boundaries.</p>
<h2><strong>The AI layer changes risk</strong></h2>
<p>AI-generated code is not automatically bad. Most of the time, it is just code.</p>
<p>That is exactly why it needs the same checks as human code.</p>
<p>The problem is not that AI writes insecure code every time. The problem is that AI changes the economics of code creation. It lowers the cost of generating code, glue, scripts, tests, configs, and workflows. That means more changes enter the system.</p>
<p>More changes need better gates.</p>
<img src="https://images.unsplash.com/photo-1555949963-aa79dcee981c?auto=format&amp;fit=crop&amp;w=1600&amp;q=80" alt="Software engineering and automation workspace" style="display:block;margin:0 auto" />

<h3><strong>AI creates code without provenance</strong></h3>
<p>Open source has a visible history. You can inspect commits, authors, reviews, releases, tags, issues, and maintainers.</p>
<p>AI-generated code is different.</p>
<p>The model gives you an answer. You may not know which examples influenced it. You may not know whether the pattern came from old code, vulnerable code, deprecated docs, or a Stack Overflow answer from ten years ago. You may not know whether the license risk is clean.</p>
<p>That does not mean you should never use AI-generated code. It means you should not treat generated code as magically original or safe.</p>
<p>A useful rule:</p>
<blockquote>
<p>AI-generated code should be treated like a pull request from a fast junior developer who had access to the entire internet but no context about your production risk.</p>
</blockquote>
<p>That sounds harsh. It is also fair.</p>
<p>The code might be good. It still needs review.</p>
<h3><strong>AI chooses dependencies</strong></h3>
<p>A lot of supply chain risk enters through dependency choice.</p>
<p>When an AI assistant suggests a package, it may optimize for convenience. It may not check:</p>
<ul>
<li><p>Maintenance activity</p>
</li>
<li><p>Known vulnerabilities</p>
</li>
<li><p>Package ownership</p>
</li>
<li><p>Download source</p>
</li>
<li><p>License</p>
</li>
<li><p>Typosquatting risk</p>
</li>
<li><p>Whether the package exists</p>
</li>
<li><p>Whether the package is still recommended</p>
</li>
<li><p>Whether the package runs install scripts</p>
</li>
<li><p>Whether a built-in API would be enough</p>
</li>
</ul>
<p>That is a real problem.</p>
<p>A human developer might ask for "a package to parse JWTs" or "a library for PDF extraction." The assistant may produce a working answer with a dependency. If the developer copies it, the supply chain changed.</p>
<p>One dependency can pull many more.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/0129dfd8-95bc-4563-8d23-46ad3cdd67ef.png" alt="" style="display:block;margin:0 auto" />

<p>The package suggestion is not a small detail. It is a design decision.</p>
<h3><strong>AI writes build and deployment scripts</strong></h3>
<p>Build scripts are dangerous because they run in privileged places.</p>
<p>A coding agent may create:</p>
<ul>
<li><p>GitHub Actions workflows</p>
</li>
<li><p>Dockerfiles</p>
</li>
<li><p>Bash scripts</p>
</li>
<li><p>Terraform plans</p>
</li>
<li><p>Helm charts</p>
</li>
<li><p>Release scripts</p>
</li>
<li><p>Package publishing scripts</p>
</li>
<li><p>Database migration scripts</p>
</li>
</ul>
<p>These files often receive less careful review than application code. That is backwards.</p>
<p>A one-line workflow change can expose secrets. A Dockerfile can leak credentials into layers. A Terraform policy can grant broad access. A release script can publish the wrong artifact.</p>
<p>AI-generated infrastructure code deserves extra review, not less.</p>
<h3><strong>AI agents can take actions</strong></h3>
<p>The next step is not AI autocomplete. It is agents.</p>
<p>Agents can plan, call tools, read files, edit code, run commands, create pull requests, and sometimes deploy. That connects AI behavior to real systems.</p>
<p>OWASP's LLM risk list includes insecure plugin design and excessive agency. These risks fit agentic development tools very well. If a model can act through tools, the tool boundary becomes part of your supply chain.</p>
<p>The risk looks like this.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/97b1add5-bcbd-4b76-b7e8-2095d09acd15.png" alt="" style="display:block;margin:0 auto" />

<p>A prompt injection in an issue or README can influence the agent. If the agent has write access and poor tool limits, that influence can become a real change.</p>
<p>This is why AI supply chain security is not only about scanning generated code. It is about controlling what agents can do.</p>
<h3><strong>AI helps attackers too</strong></h3>
<p>Defenders use AI. Attackers use it as well.</p>
<p>AI can help attackers:</p>
<ul>
<li><p>Generate phishing emails for maintainers</p>
</li>
<li><p>Write package descriptions</p>
</li>
<li><p>Create convincing fake documentation</p>
</li>
<li><p>Generate malware variants</p>
</li>
<li><p>Analyze public repositories for secrets</p>
</li>
<li><p>Find weak CI workflows</p>
</li>
<li><p>Create typo packages at scale</p>
</li>
<li><p>Translate attacks across ecosystems</p>
</li>
<li><p>Write exploit glue faster</p>
</li>
</ul>
<p>The Unit 42 Shai-Hulud analysis is a useful signal because it links a large npm supply chain campaign with suspected LLM assistance in the malicious script. The important point is not whether the whole attack was AI-driven. The point is that AI reduces the cost of attacker work.</p>
<p>That changes the defender's job.</p>
<p>Manual review alone cannot keep up with automated attack paths. You need automated guardrails too.</p>
<h2><strong>What a hardened pipeline looks like</strong></h2>
<p>A secure supply chain is not one tool. It is a set of controls that reinforce each other.</p>
<p>The goal is not to make attacks impossible. That is not realistic. The goal is to make risky changes visible, hard to land, hard to exploit, and easy to roll back.</p>
<p>A hardened pipeline answers five questions:</p>
<ol>
<li><p>What code changed?</p>
</li>
<li><p>Who or what changed it?</p>
</li>
<li><p>What dependencies entered the build?</p>
</li>
<li><p>What artifact was produced?</p>
</li>
<li><p>Can we prove that production is running the artifact we reviewed?</p>
</li>
</ol>
<p>Here is the shape.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/fd92b804-2423-4364-a10a-2cad1f1353e1.png" alt="" style="display:block;margin:0 auto" />

<h3><strong>Dependency control</strong></h3>
<p>The first layer is dependency control.</p>
<p>You should know when dependencies change. You should know why they changed. You should know whether the change adds risky behavior.</p>
<p>Practical controls:</p>
<ul>
<li><p>Use lockfiles.</p>
</li>
<li><p>Review dependency diffs in pull requests.</p>
</li>
<li><p>Block known malicious packages.</p>
</li>
<li><p>Use private registries or proxy registries for internal packages.</p>
</li>
<li><p>Prefer direct dependencies with healthy maintenance.</p>
</li>
<li><p>Remove unused dependencies.</p>
</li>
<li><p>Avoid packages that run install scripts unless you need them.</p>
</li>
<li><p>Pin versions for application dependencies.</p>
</li>
<li><p>Pin GitHub Actions to commit SHAs for high risk workflows.</p>
</li>
<li><p>Use package manager settings that reduce script execution in CI where possible.</p>
</li>
</ul>
<p>A dependency review should not only ask "does it have a CVE?"</p>
<p>It should ask:</p>
<ul>
<li><p>Who maintains it?</p>
</li>
<li><p>How often is it updated?</p>
</li>
<li><p>Does it have many transitive dependencies?</p>
</li>
<li><p>Does it execute install scripts?</p>
</li>
<li><p>Does it request network access during install?</p>
</li>
<li><p>Is it replacing a small function we could write ourselves?</p>
</li>
<li><p>Is it a package suggested by AI without verification?</p>
</li>
<li><p>Is the license acceptable?</p>
</li>
<li><p>Is this package allowed in our organization?</p>
</li>
</ul>
<p>Some teams create an "approved dependency path." That does not mean every package needs a week-long security review. It means the pipeline treats new packages differently from routine code changes.</p>
<p>That is smart.</p>
<h3><strong>Secret control</strong></h3>
<p>Secrets are the fuel of supply chain attacks.</p>
<p>A compromised package is bad. A compromised package with access to CI secrets is much worse.</p>
<p>Start with the obvious:</p>
<ul>
<li><p>Do not commit secrets.</p>
</li>
<li><p>Scan repositories for secrets.</p>
</li>
<li><p>Scan pull requests for secrets.</p>
</li>
<li><p>Rotate secrets quickly when exposed.</p>
</li>
<li><p>Remove long-lived credentials from CI where possible.</p>
</li>
<li><p>Use OIDC for cloud access from CI.</p>
</li>
<li><p>Scope tokens to the minimum required permissions.</p>
</li>
<li><p>Separate build credentials from deploy credentials.</p>
</li>
<li><p>Do not expose production secrets to pull request workflows.</p>
</li>
<li><p>Keep self-hosted runners isolated.</p>
</li>
</ul>
<p>GitHub's docs recommend least privilege for workflow secrets. Their OIDC documentation explains how Actions can authenticate to cloud providers without storing long-lived secrets in GitHub.</p>
<p>This is one of the best upgrades a team can make.</p>
<p>A short-lived token tied to a workflow is not perfect, but it is much safer than a cloud key that sits in a secret store for years.</p>
<h3><strong>Build isolation</strong></h3>
<p>A build should be clean, repeatable, and isolated.</p>
<p>That means:</p>
<ul>
<li><p>Build on controlled infrastructure.</p>
</li>
<li><p>Avoid building release artifacts on developer laptops.</p>
</li>
<li><p>Keep build runners patched.</p>
</li>
<li><p>Use ephemeral runners for sensitive builds.</p>
</li>
<li><p>Limit network access where possible.</p>
</li>
<li><p>Keep deploy credentials out of build jobs.</p>
</li>
<li><p>Separate test jobs from release jobs.</p>
</li>
<li><p>Do not let untrusted pull requests access secrets.</p>
</li>
<li><p>Do not reuse dirty workspaces for release builds.</p>
</li>
</ul>
<p>The build environment is part of the artifact. If the build runner is compromised, the output can be compromised even when the source code is clean.</p>
<p>This is where SLSA becomes useful.</p>
<p>SLSA, short for Supply-chain Levels for Software Artifacts, is a framework from OpenSSF. The SLSA site describes it as a checklist of standards and controls to prevent tampering, improve integrity, and secure packages and infrastructure.</p>
<p>That framing is helpful because SLSA is not a single product. It is a maturity path.</p>
<p>At a high level:</p>
<table>
<thead>
<tr>
<th><strong>Control area</strong></th>
<th><strong>What it protects</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Source integrity</td>
<td>The code being built is the code that was reviewed</td>
</tr>
<tr>
<td>Build integrity</td>
<td>The build process was not quietly changed</td>
</tr>
<tr>
<td>Provenance</td>
<td>The artifact can be traced to source and build steps</td>
</tr>
<tr>
<td>Isolation</td>
<td>Attackers cannot easily tamper with the build</td>
</tr>
<tr>
<td>Verification</td>
<td>Consumers can check that artifacts match policy</td>
</tr>
</tbody></table>
<p>You do not need to reach the highest maturity level on day one. Even basic provenance is useful because it gives incident responders a way to answer hard questions.</p>
<p>Where did this artifact come from? Which commit produced it? Which workflow built it? Which builder ran it? Was it signed? Was it altered after the build?</p>
<p>Without provenance, you are guessing.</p>
<h3><strong>SBOMs</strong></h3>
<p>A <strong>Software Bill of Materials</strong>, or <strong>SBOM</strong>, is an inventory of software components.</p>
<p>Think of it as an ingredient list for software. It does not make the software safe by itself. It tells you what is inside, so you can respond when something inside becomes risky.</p>
<p>CISA published updated draft guidance for SBOM minimum elements in 2025. CISA describes SBOMs as a software transparency tool that helps manage software risk more effectively.</p>
<p>A useful SBOM should answer:</p>
<ul>
<li><p>What components are included?</p>
</li>
<li><p>What versions are included?</p>
</li>
<li><p>Which packages are direct dependencies?</p>
</li>
<li><p>Which are transitive dependencies?</p>
</li>
<li><p>What licenses apply?</p>
</li>
<li><p>What package manager or ecosystem do they come from?</p>
</li>
<li><p>What hashes identify the components?</p>
</li>
<li><p>Which tool generated the SBOM?</p>
</li>
<li><p>When was it generated?</p>
</li>
<li><p>Which artifact does it describe?</p>
</li>
</ul>
<p>SBOMs are most useful when they are generated during the build and attached to the artifact. A manually created SBOM gets stale fast.</p>
<p>SBOMs also need monitoring.</p>
<p>If a new vulnerability appears in a dependency, you should be able to ask:</p>
<blockquote>
<p>Which services include this component?</p>
</blockquote>
<p>That is the operational value.</p>
<h3><strong>Signing and verification</strong></h3>
<p>Signing turns trust into something machines can check.</p>
<p>Sigstore is one of the most important projects in this space. The Sigstore project describes itself as a collection of open source tools that improve software supply chain security. Cosign, one of its tools, supports signing container images and other artifacts, including keyless signing.</p>
<p>The idea is simple.</p>
<p>Build an artifact. Sign it. Store the signature. Verify the signature before deployment.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/4731788a-51ec-4ef9-b293-b71bb6099a39.png" alt="" style="display:block;margin:0 auto" />

<p>This gives you a strong rule:</p>
<blockquote>
<p>Production should run only artifacts that were built by approved systems, from approved repositories, under approved workflows.</p>
</blockquote>
<p>That is much better than trusting anyone who can push an image tag.</p>
<p>Tags are mutable. Signatures and provenance give you better proof.</p>
<h3><strong>CI/CD hardening</strong></h3>
<p>CI/CD deserves its own checklist because it is often the highest value target.</p>
<p>For GitHub Actions, strong defaults include:</p>
<pre><code class="language-yaml">permissions:
  contents: read
</code></pre>
<p>Then grant more permissions only where needed.</p>
<p>For cloud deployment, prefer OIDC instead of stored keys. For third-party actions, pin sensitive workflows to commit SHAs. For pull requests from forks, never expose secrets. For self-hosted runners, treat public pull request execution as risky.</p>
<p>A safer GitHub Actions pattern looks like this.</p>
<pre><code class="language-yaml">name: build

on:
  pull_request:
  push:
    branches: [main]

permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Install dependencies without running scripts
        run: npm ci --ignore-scripts

      - name: Run tests
        run: npm test
</code></pre>
<p>For release workflows, use separate permissions.</p>
<pre><code class="language-yaml">name: release

on:
  push:
    tags:
      - "v*"

permissions:
  contents: read
  id-token: write
  packages: write

jobs:
  release:
    runs-on: ubuntu-latest
    environment: production

    steps:
      - uses: actions/checkout@v4

      - name: Build
        run: npm ci --ignore-scripts &amp;&amp; npm run build

      - name: Authenticate with cloud using OIDC
        run: echo "Use cloud provider login action here"

      - name: Publish signed artifact
        run: echo "Build, sign, and publish"
</code></pre>
<p>This is not a complete workflow. It shows the shape.</p>
<p>The build job does not need deployment power. The release job gets only what it needs. Production requires an environment boundary. OIDC replaces static cloud keys.</p>
<h3><strong>AI guardrails</strong></h3>
<p>AI-generated changes need guardrails that match how AI works.</p>
<p>A practical policy might say:</p>
<ul>
<li><p>AI can draft code, but a human must own the change.</p>
</li>
<li><p>AI can suggest dependencies, but dependency additions require review.</p>
</li>
<li><p>AI cannot modify release workflows without CODEOWNERS approval.</p>
</li>
<li><p>AI cannot create or rotate production secrets.</p>
</li>
<li><p>AI cannot deploy to production directly.</p>
</li>
<li><p>AI-generated infrastructure changes require plan review.</p>
</li>
<li><p>Agent tool access must be scoped by task.</p>
</li>
<li><p>Agent actions must be logged.</p>
</li>
<li><p>Prompt context from external systems must be treated as untrusted.</p>
</li>
</ul>
<p>This is not anti-AI. It is normal engineering.</p>
<p>You would not give a new contractor unrestricted production access on their first day. You should not give an agent that access either.</p>
<h3><strong>Policy as code</strong></h3>
<p>Manual review is not enough.</p>
<p>Use policy as code to stop common mistakes before merge. Tools vary by stack, but the idea is the same.</p>
<p>Examples of policies:</p>
<ul>
<li><p>Block public S3 buckets unless explicitly approved.</p>
</li>
<li><p>Block Kubernetes privileged containers.</p>
</li>
<li><p>Require pinned base images.</p>
</li>
<li><p>Require signed container images.</p>
</li>
<li><p>Require SBOMs for production artifacts.</p>
</li>
<li><p>Require CODEOWNERS review for workflow changes.</p>
</li>
<li><p>Block new dependencies with known critical vulnerabilities.</p>
</li>
<li><p>Block deploy jobs without OIDC.</p>
</li>
<li><p>Block containers running as root.</p>
</li>
<li><p>Block Terraform changes that grant wildcard admin access.</p>
</li>
</ul>
<p>The value is consistency.</p>
<p>A tired reviewer can miss a risky permission. A policy check should not.</p>
<h2><strong>A practical roadmap</strong></h2>
<p>The hard part about supply chain security is not knowing what good looks like. The hard part is making progress without stopping engineering work.</p>
<p>You do not need to do everything at once.</p>
<p>Here is a roadmap that works for small teams and can grow with larger ones.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/1d8290c5-7475-47e5-809a-e90186bdd97e.png" alt="" style="display:block;margin:0 auto" />

<h3><strong>Phase one: know what you ship</strong></h3>
<p>Start with visibility.</p>
<p>If you do not know what you ship, you cannot secure it.</p>
<p>Do this first:</p>
<ul>
<li><p>Turn on dependency alerts.</p>
</li>
<li><p>Generate SBOMs for release artifacts.</p>
</li>
<li><p>Store SBOMs with builds.</p>
</li>
<li><p>Track direct and transitive dependencies.</p>
</li>
<li><p>Identify production repositories.</p>
</li>
<li><p>Identify who can publish packages.</p>
</li>
<li><p>Identify who can deploy.</p>
</li>
<li><p>Inventory CI secrets.</p>
</li>
<li><p>Inventory third-party GitHub Actions.</p>
</li>
<li><p>Find self-hosted runners.</p>
</li>
<li><p>Map which services use which base images.</p>
</li>
</ul>
<p>This phase is not glamorous. It is useful.</p>
<p>The output should be a basic map.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/eaa84d6b-2db7-408a-bdd2-d7dc40ced619.png" alt="" style="display:block;margin:0 auto" />

<p>Do not skip this.</p>
<p>Most supply chain incidents become worse because teams do not know where the affected package is used, which token leaked, or which build produced the artifact.</p>
<h3><strong>Phase two: reduce easy risk</strong></h3>
<p>Next, remove obvious dangerous defaults.</p>
<p>Focus on the things attackers love:</p>
<ul>
<li><p>Long-lived cloud keys in CI</p>
</li>
<li><p>Broad GitHub tokens</p>
</li>
<li><p>Unpinned deployment workflows</p>
</li>
<li><p>Secrets exposed to pull requests</p>
</li>
<li><p>Unreviewed workflow changes</p>
</li>
<li><p>Overly broad package publish rights</p>
</li>
<li><p>Unused dependencies</p>
</li>
<li><p>Old base images</p>
</li>
<li><p>Install scripts running in CI without need</p>
</li>
</ul>
<p>Quick wins:</p>
<table>
<thead>
<tr>
<th><strong>Risk</strong></th>
<th><strong>Safer move</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Long-lived cloud keys</td>
<td>Use OIDC</td>
</tr>
<tr>
<td>Broad CI token permissions</td>
<td>Set least privilege permissions</td>
</tr>
<tr>
<td>Unreviewed workflow changes</td>
<td>Add CODEOWNERS</td>
</tr>
<tr>
<td>Unknown dependencies</td>
<td>Add dependency review</td>
</tr>
<tr>
<td>Secret leaks</td>
<td>Add secret scanning and rotation playbooks</td>
</tr>
<tr>
<td>Unsigned artifacts</td>
<td>Sign release artifacts</td>
</tr>
<tr>
<td>Mutable image tags</td>
<td>Deploy by digest</td>
</tr>
<tr>
<td>AI adding packages freely</td>
<td>Require review for dependency changes</td>
</tr>
</tbody></table>
<p>You will not fix everything. That is fine.</p>
<p>Fix the paths that lead to production first.</p>
<h3><strong>Phase three: protect the build</strong></h3>
<p>After visibility and quick wins, focus on build integrity.</p>
<p>A strong build process should be:</p>
<ul>
<li><p>Automated</p>
</li>
<li><p>Isolated</p>
</li>
<li><p>Repeatable</p>
</li>
<li><p>Provenanced</p>
</li>
<li><p>Signed</p>
</li>
<li><p>Verifiable</p>
</li>
</ul>
<p>That means release artifacts should come from CI, not laptops. The build should generate provenance and an SBOM. The artifact should be signed. Deployment should verify policy before running it.</p>
<p>A healthy release chain looks like this.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/56f53355-1c29-4191-ad2c-bf5b57cd455d.png" alt="" style="display:block;margin:0 auto" />

<p>The key idea is traceability.</p>
<p>If someone asks, "Why is this running in production?" you should have a better answer than "because the tag says latest."</p>
<h3><strong>Phase four: govern AI-generated code</strong></h3>
<p>AI governance should be boring.</p>
<p>That is good.</p>
<p>Start with a written policy that developers can actually follow.</p>
<p>A practical policy might be:</p>
<ol>
<li><p>AI-generated code is allowed.</p>
</li>
<li><p>The human who submits the pull request owns the code.</p>
</li>
<li><p>New dependencies suggested by AI require dependency review.</p>
</li>
<li><p>Security-sensitive files require CODEOWNERS review.</p>
</li>
<li><p>AI tools cannot receive secrets.</p>
</li>
<li><p>AI agents cannot deploy without explicit approval.</p>
</li>
<li><p>Generated code must pass the same tests and scans as human code.</p>
</li>
<li><p>Agent actions must be logged when they touch repositories or tools.</p>
</li>
</ol>
<p>Then make the pipeline enforce parts of it.</p>
<p>Add CODEOWNERS for:</p>
<ul>
<li><p><code>.github/workflows/*</code></p>
</li>
<li><p><code>Dockerfile</code></p>
</li>
<li><p><code>docker-compose.yml</code></p>
</li>
<li><p><code>terraform/**</code></p>
</li>
<li><p><code>helm/**</code></p>
</li>
<li><p><code>k8s/**</code></p>
</li>
<li><p><code>package.json</code></p>
</li>
<li><p><code>package-lock.json</code></p>
</li>
<li><p><code>pyproject.toml</code></p>
</li>
<li><p><code>requirements.txt</code></p>
</li>
<li><p><code>go.mod</code></p>
</li>
<li><p><code>Cargo.toml</code></p>
</li>
</ul>
<p>This does not block AI. It puts review where risk enters.</p>
<h3><strong>Phase five: prepare for incidents</strong></h3>
<p>You will still have incidents.</p>
<p>The question is how fast you can respond.</p>
<p>For supply chain incidents, every team should know how to:</p>
<ul>
<li><p>Find where a package is used.</p>
</li>
<li><p>Remove or pin a package version.</p>
</li>
<li><p>Rebuild affected artifacts.</p>
</li>
<li><p>Rotate leaked tokens.</p>
</li>
<li><p>Disable compromised workflows.</p>
</li>
<li><p>Revoke package publish tokens.</p>
</li>
<li><p>Audit recent releases.</p>
</li>
<li><p>Search logs for suspicious CI behavior.</p>
</li>
<li><p>Check which artifacts reached production.</p>
</li>
<li><p>Notify customers if required.</p>
</li>
</ul>
<p>Write the playbook before you need it.</p>
<p>A simple incident flow:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/3968cffd-3434-46d7-9eb5-c92ffee10b69.png" alt="" style="display:block;margin:0 auto" />

<p>The teams that handle supply chain incidents well are not always the teams with the most tools. They are the teams with the clearest ownership and the fastest path from alert to rebuild.</p>
<h3><strong>What this means for developers</strong></h3>
<p>This whole topic can sound like a security team problem.</p>
<p>It is not.</p>
<p>Developers make supply chain decisions every day.</p>
<p>You make one when you install a package. You make one when you copy a GitHub Actions snippet. You make one when you accept an AI-generated dependency. You make one when you add a Docker base image. You make one when you approve a pull request that changes a workflow.</p>
<p>That does not mean every developer must become a security engineer.</p>
<p>It means every developer should learn a few instincts:</p>
<ul>
<li><p>Fewer dependencies are easier to defend.</p>
</li>
<li><p>Lockfiles matter.</p>
</li>
<li><p>Build scripts deserve review.</p>
</li>
<li><p>CI secrets are production risk.</p>
</li>
<li><p>AI-generated code still needs ownership.</p>
</li>
<li><p>Package install is code execution.</p>
</li>
<li><p>A signed artifact is better than a trusted tag.</p>
</li>
<li><p>SBOMs help you answer questions during an incident.</p>
</li>
<li><p>Provenance tells you where software came from.</p>
</li>
<li><p>Fast code without traceability becomes expensive later.</p>
</li>
</ul>
<p>The future of software supply chain security is not one big scanner. It is a culture where code, dependencies, builds, artifacts, and AI agents are all treated as part of the same system.</p>
<p>That is the shift.</p>
<p>AI did not create the software supply chain problem. Open source scale, automation, and cloud delivery already did that.</p>
<p>AI made the problem faster.</p>
<p>So the answer is not to stop using AI. The answer is to build pipelines that can handle speed without losing trust.</p>
<p>The best teams will use AI to write faster, test faster, review better, and detect risk earlier. They will also put hard boundaries around credentials, builds, artifacts, and production changes.</p>
<p>That is where professional software engineering is going.</p>
<p>Not less process. Better process.</p>
<p>Not less trust. Verifiable trust.</p>
<h2><strong>Practical checklist</strong></h2>
<p>Use this as a starting point for your own project.</p>
<table>
<thead>
<tr>
<th><strong>Area</strong></th>
<th><strong>Minimum useful control</strong></th>
</tr>
</thead>
<tbody><tr>
<td>Dependencies</td>
<td>Lockfiles, dependency review, remove unused packages</td>
</tr>
<tr>
<td>AI-generated code</td>
<td>Human owner, normal tests, dependency review</td>
</tr>
<tr>
<td>CI secrets</td>
<td>Least privilege, OIDC, no secrets for untrusted PRs</td>
</tr>
<tr>
<td>Workflows</td>
<td>CODEOWNERS, pinned actions, limited permissions</td>
</tr>
<tr>
<td>Builds</td>
<td>Clean CI builds, no release artifacts from laptops</td>
</tr>
<tr>
<td>Artifacts</td>
<td>Signed images, deploy by digest, registry access controls</td>
</tr>
<tr>
<td>SBOM</td>
<td>Generate during build and store with artifacts</td>
</tr>
<tr>
<td>Provenance</td>
<td>Attach build provenance to release artifacts</td>
</tr>
<tr>
<td>Containers</td>
<td>Pin base images, scan images, rebuild often</td>
</tr>
<tr>
<td>Infrastructure</td>
<td>Policy checks for risky permissions</td>
</tr>
<tr>
<td>Incidents</td>
<td>Token rotation and rebuild playbooks</td>
</tr>
</tbody></table>
<p>The point is not perfection.</p>
<p>The point is reducing blind trust.</p>
<h2><strong>References</strong></h2>
<ul>
<li><p><a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/">OWASP Top 10 for Large Language Model Applications</a></p>
</li>
<li><p><a href="https://octoverse.github.com/">GitHub Octoverse 2025</a></p>
</li>
<li><p><a href="https://unit42.paloaltonetworks.com/npm-supply-chain-attack/">Unit 42 analysis of the Shai-Hulud npm campaign</a></p>
</li>
<li><p><a href="https://www.csa.gov.sg/alerts-and-advisories/alerts/al-2025-093/">Cyber Security Agency of Singapore advisory on Shai-Hulud</a></p>
</li>
<li><p><a href="https://access.redhat.com/security/supply-chain-attacks-NPM-packages">Red Hat summary of multiple npm supply chain attacks</a></p>
</li>
<li><p><a href="https://slsa.dev/">SLSA framework</a></p>
</li>
<li><p><a href="https://www.sigstore.dev/">Sigstore</a></p>
</li>
<li><p><a href="https://docs.sigstore.dev/cosign/signing/overview/">Cosign signing overview</a></p>
</li>
<li><p><a href="https://github.com/ossf/scorecard">OpenSSF Scorecard</a></p>
</li>
<li><p><a href="https://docs.github.com/en/actions/reference/security/secure-use">GitHub Actions secure use reference</a></p>
</li>
<li><p><a href="https://docs.github.com/en/actions/concepts/security/openid-connect">GitHub Actions OIDC documentation</a></p>
</li>
<li><p><a href="https://www.cisa.gov/sbom">CISA SBOM page</a></p>
</li>
<li><p><a href="https://www.cisa.gov/resources-tools/resources/2025-minimum-elements-software-bill-materials-sbom">CISA 2025 minimum elements for SBOM</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[Local first AI is coming back
]]></title><description><![CDATA[AI on the web has mostly meant one thing: send user input to an API, wait for a cloud model, then render the answer.
That model is not going away. Large frontier models still need serious compute. But]]></description><link>https://blog.prashantkoirala.info.np/local-first-ai-is-coming-back</link><guid isPermaLink="true">https://blog.prashantkoirala.info.np/local-first-ai-is-coming-back</guid><category><![CDATA[AI]]></category><category><![CDATA[webdev]]></category><category><![CDATA[JavaScript]]></category><category><![CDATA[Machine Learning]]></category><category><![CDATA[webgpu]]></category><dc:creator><![CDATA[Prashant Koirala]]></dc:creator><pubDate>Sun, 03 May 2026 14:32:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/214e35e9-8ce4-4b2f-ab6d-c7ca0c230bde.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AI on the web has mostly meant one thing: send user input to an API, wait for a cloud model, then render the answer.</p>
<p>That model is not going away. Large frontier models still need serious compute. But another path is getting more practical: run smaller AI models directly on the user's device, inside the browser.</p>
<p>This is <strong>local first AI</strong>. It is not a replacement for every cloud AI feature. It is a different design choice. It can be faster, cheaper, more private, and better offline when the task is small enough to fit on the client.</p>
<p>The timing matters. WebGPU gives browsers access to modern GPU compute. WebAssembly keeps CPU fallback fast and portable. ONNX Runtime Web, Transformers.js, WebLLM, WebNN, and Chrome's built in AI APIs are making browser AI feel less like a demo and more like a real app architecture.</p>
<h2><strong>Why local first AI is back</strong></h2>
<p>The first wave of AI apps was cloud first for a good reason. Big models were too large for normal devices, browser APIs were not ready, and JavaScript ML tooling felt limited.</p>
<p>That is changing.</p>
<p>Modern browsers now have better access to device hardware. <a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API">MDN describes WebGPU</a> as a browser API for high performance graphics and general purpose GPU computation. The same GPU path that helps render complex visuals can also help run machine learning workloads.</p>
<p>Frameworks are catching up too. <a href="https://webllm.mlc.ai/docs/">WebLLM</a> runs large language models in the browser with WebGPU acceleration. <a href="https://huggingface.co/docs/transformers.js/index">Transformers.js</a> lets developers run transformer models directly in the browser with no server. <a href="https://onnxruntime.ai/docs/tutorials/web/">ONNX Runtime Web</a> lets web apps run machine learning models through JavaScript APIs.</p>
<p>This is the shift:</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/ebea2aba-bd3b-4d5c-9864-c336c3244f75.png" alt="" style="display:block;margin:0 auto" />

<p>The new question is not, "Can the browser run AI?" It can.</p>
<p>The better question is, "Which AI tasks should run locally, and which still belong in the cloud?"</p>
<h2><strong>What runs inside the browser</strong></h2>
<p>Local AI does not mean the same thing in every app. A browser can run AI in several ways, depending on the task and the user's device.</p>
<table>
<thead>
<tr>
<th><strong>Layer</strong></th>
<th><strong>What it does</strong></th>
<th><strong>Why it matters</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>JavaScript</strong></td>
<td>App logic and model orchestration</td>
<td>Keeps the developer experience familiar</td>
</tr>
<tr>
<td><strong>WebAssembly</strong></td>
<td>Fast CPU execution and fallback</td>
<td>Works across many devices</td>
</tr>
<tr>
<td><strong>WebGPU</strong></td>
<td>GPU acceleration</td>
<td>Speeds up heavy parallel work</td>
</tr>
<tr>
<td><strong>WebNN</strong></td>
<td>Hardware neutral neural network API</td>
<td>Lets browsers target GPUs, CPUs, and NPUs</td>
</tr>
<tr>
<td><strong>Built in browser AI</strong></td>
<td>Browser provided models</td>
<td>Reduces setup for supported tasks</td>
</tr>
</tbody></table>
<img src="https://images.unsplash.com/photo-1555066931-4365d14bab8c?auto=format&amp;fit=crop&amp;w=1600&amp;q=80" alt="Code on a laptop" style="display:block;margin:0 auto" />

<p>The most practical browser AI tasks today are not giant reasoning agents. They are smaller, focused features:</p>
<ul>
<li><p>Summarizing a short document</p>
</li>
<li><p>Classifying text</p>
</li>
<li><p>Detecting sentiment</p>
</li>
<li><p>Translating simple content</p>
</li>
<li><p>Running semantic search over local notes</p>
</li>
<li><p>Extracting labels from images</p>
</li>
<li><p>Helping users rewrite text</p>
</li>
<li><p>Creating embeddings for private data</p>
</li>
</ul>
<p><a href="https://developer.chrome.com/docs/ai/prompt-api">Chrome's Prompt API</a> lets developers send natural language requests to Gemini Nano in the browser. Chrome's broader <a href="https://developer.chrome.com/docs/ai/built-in">built in AI docs</a> also describe APIs for tasks like summarizing, writing, rewriting, and translation.</p>
<p>The W3C is moving in the same direction. The <a href="https://www.w3.org/TR/webnn/">Web Neural Network API</a> defines a hardware neutral abstraction for machine learning in browsers. The W3C Web Machine Learning Working Group says its mission is to develop APIs for efficient ML inference in the browser.</p>
<p>That is important. Local AI will not be one library. It will be a stack.</p>
<h2><strong>Why developers should care</strong></h2>
<p>The obvious benefit is privacy.</p>
<p>If a user asks your app to summarize private notes, classify local files, or search personal data, sending everything to a server may feel wrong. Local AI lets you keep sensitive data on the device for the right tasks.</p>
<p>But privacy is only one part of the story.</p>
<p>Local AI also changes cost. Cloud inference can get expensive when every small action becomes an API call. A rewrite button, a smart search box, or a local classifier might be used hundreds of times per session. Moving small tasks to the client can reduce backend load.</p>
<p>It also improves latency. A local model can respond without a round trip to a server. That matters for UI features where the user expects instant feedback.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/ea24beb6-78f9-4641-a16e-d67b49160f13.png" alt="" style="display:block;margin:0 auto" />

<p>The best design is often hybrid.</p>
<p>Use local AI for fast, private, repeated tasks. Use cloud AI for complex reasoning, huge context windows, heavy generation, or tasks that need the best available model.</p>
<table>
<thead>
<tr>
<th><strong>Use local AI when</strong></th>
<th><strong>Use cloud AI when</strong></th>
</tr>
</thead>
<tbody><tr>
<td>The data is private</td>
<td>The model needs broad world knowledge</td>
</tr>
<tr>
<td>The task is small</td>
<td>The task needs deep reasoning</td>
</tr>
<tr>
<td>Low latency matters</td>
<td>Quality matters more than speed</td>
</tr>
<tr>
<td>Offline support matters</td>
<td>The model is too large for the device</td>
</tr>
<tr>
<td>Cost per action matters</td>
<td>You need centralized monitoring</td>
</tr>
</tbody></table>
<p>The point is not to pick one side forever. The point is to route each task to the right place.</p>
<h2><strong>The stack is getting real</strong></h2>
<p>A few years ago, browser AI felt like a science project. Now the pieces are easier to name.</p>
<p><strong>WebGPU</strong> gives web apps a modern compute path. ONNX Runtime's WebGPU documentation describes WebGPU as a browser standard for general purpose GPU compute and graphics, designed around modern APIs like D3D12, Vulkan, and Metal.</p>
<p><strong>WebAssembly</strong> still matters because not every device has a strong GPU path. It gives browser AI a portable CPU fallback. ONNX Runtime Web supports WebAssembly, WebGPU, WebGL, and WebNN backends, depending on the use case.</p>
<p><strong>Transformers.js</strong> gives JavaScript developers a familiar way to run models from the Hugging Face ecosystem. Hugging Face announced Transformers.js v4 in February 2026 with a rewritten WebGPU runtime and broader model support.</p>
<p><strong>WebLLM</strong> focuses on in browser LLM inference. Its docs describe it as a high performance engine for running LLMs in browsers with WebGPU acceleration.</p>
<p><strong>WebNN</strong> points toward a future where browser ML can target GPUs, CPUs, and dedicated AI hardware without every developer writing device specific code.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/201bac5a-a275-412d-bb1c-d3ff06eef8fa.png" alt="" style="display:block;margin:0 auto" />

<p>This is why the browser is becoming an AI runtime.</p>
<p>Not because it can run the biggest model. Because it can run useful models close to the user.</p>
<h2><strong>What can go wrong</strong></h2>
<p>Local AI has real limits.</p>
<p>First, model size matters. Users do not want to download a huge model just to try a web app. Chrome's built in AI docs tell developers to inform users when a model is downloading and when it is ready. That detail sounds small, but it affects trust.</p>
<p>Second, devices vary. A powerful laptop with a good GPU is not the same as an older phone. Your app needs fallback paths.</p>
<p>Third, browser support is still uneven. WebGPU is more mature than before, but you still need feature detection and graceful fallback. WebNN is still an emerging standard, even though the direction is clear.</p>
<p>Fourth, local models are smaller. They may be good enough for summarization, classification, embeddings, and rewriting. They may not be good enough for deep research, legal review, medical decisions, or high stakes reasoning.</p>
<p>A good local AI feature should be honest.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/2db6c741-f3bf-4b84-9b2f-d08d6cf87ad6.png" alt="" style="display:block;margin:0 auto" />

<p>The safest pattern is simple.</p>
<ul>
<li><p>Detect device support.</p>
</li>
<li><p>Keep local tasks narrow.</p>
</li>
<li><p>Show model download state.</p>
</li>
<li><p>Let users choose cloud fallback.</p>
</li>
<li><p>Avoid pretending a small local model is smarter than it is.</p>
</li>
</ul>
<p>Local first AI should feel calm, not magical.</p>
<h2><strong>Where this is heading</strong></h2>
<p>The web keeps absorbing things that used to require native apps.</p>
<p>First it took documents. Then chat. Then video editing, design tools, IDEs, games, and real time collaboration. AI is next.</p>
<p>The browser will not replace every cloud model. That is not the interesting claim.</p>
<p>The interesting claim is smaller: many everyday AI features do not need to leave the device.</p>
<p>A writing helper can rewrite a sentence locally. A note app can search private notes locally. A browser extension can summarize a page locally. A design tool can classify assets locally. A support tool can detect intent locally before sending only the needed context to a server.</p>
<p>That makes apps feel faster. It lowers costs. It protects user data. It also gives developers a new architectural choice.</p>
<p>Cloud AI gave us powerful models. Local first AI gives us better product boundaries.</p>
<p>The next great AI web app may not be the one that calls the largest model for everything. It may be the one that knows when not to call the cloud at all.</p>
<h2><strong>References</strong></h2>
<ul>
<li><p><a href="https://developer.mozilla.org/en-US/docs/Web/API/WebGPU_API">MDN WebGPU API</a></p>
</li>
<li><p><a href="https://developer.chrome.com/docs/ai/built-in">Chrome built in AI docs</a></p>
</li>
<li><p><a href="https://developer.chrome.com/docs/ai/prompt-api">Chrome Prompt API</a></p>
</li>
<li><p><a href="https://webllm.mlc.ai/docs/">WebLLM documentation</a></p>
</li>
<li><p><a href="https://huggingface.co/docs/transformers.js/index">Transformers.js documentation</a></p>
</li>
<li><p><a href="https://huggingface.co/blog/transformersjs-v4">Transformers.js v4 announcement</a></p>
</li>
<li><p><a href="https://onnxruntime.ai/docs/tutorials/web/">ONNX Runtime Web docs</a></p>
</li>
<li><p><a href="https://onnxruntime.ai/docs/tutorials/web/ep-webgpu.html">ONNX Runtime WebGPU docs</a></p>
</li>
<li><p><a href="https://www.w3.org/TR/webnn/">W3C Web Neural Network API</a></p>
</li>
<li><p><a href="https://www.w3.org/2025/03/webmachinelearning-charter.html">W3C Web Machine Learning Working Group Charter</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[MCP beyond the hype]]></title><description><![CDATA[AI agents are useful only when they can reach the world outside the chat box. They need files, calendars, databases, APIs, code repositories, search tools, and sometimes internal company systems.
That]]></description><link>https://blog.prashantkoirala.info.np/mcp-beyond-the-hype</link><guid isPermaLink="true">https://blog.prashantkoirala.info.np/mcp-beyond-the-hype</guid><category><![CDATA[AI]]></category><category><![CDATA[mcp]]></category><category><![CDATA[llm]]></category><category><![CDATA[Security]]></category><category><![CDATA[developers]]></category><dc:creator><![CDATA[Prashant Koirala]]></dc:creator><pubDate>Fri, 01 May 2026 16:09:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/f929ed37-12c7-49c2-bb0c-3ad128845ab2.jpg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>AI agents are useful only when they can reach the world outside the chat box. They need files, calendars, databases, APIs, code repositories, search tools, and sometimes internal company systems.</p>
<p>That is where <strong>Model Context Protocol</strong>, or <strong>MCP</strong>, becomes interesting.</p>
<p>MCP is an open standard for connecting AI applications to external systems. The <a href="https://modelcontextprotocol.io/docs/getting-started/intro">official MCP documentation</a> describes it as a way for apps like Claude or ChatGPT to connect to data sources, tools, and workflows through a shared protocol. OpenAI's Agents SDK uses the same simple analogy: MCP is like a USB-C port for AI apps.</p>
<p>That analogy is helpful, but it hides the serious part.</p>
<p>A USB-C port can charge your laptop. It can also connect a device you do not trust. MCP has the same shape. It can make agents more useful, but it also creates a new security boundary where language models can request real actions.</p>
<img src="https://images.unsplash.com/photo-1746286720965-cccf57e56c68?auto=format&amp;fit=crop&amp;fm=jpg&amp;q=80&amp;w=1600" alt="AI code editor on a laptop" style="display:block;margin:0 auto" />

<p><em>Image credit:</em> <a href="https://unsplash.com/photos/laptop-displays-the-ai-code-editor-website-wjFOjA2zXy8"><em>Aerps.com on Unsplash</em></a></p>
<h2>Why MCP exists</h2>
<p>Before MCP, every AI app had to build its own integration layer.</p>
<p>If your assistant needed GitHub, Slack, Notion, Postgres, and Google Drive, you wrote custom connectors for each one. Then another AI app had to do the same thing again. The result was a messy grid of integrations.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/5c99e132-b02a-4a94-9295-0d9936ac0f9d.png" alt="" style="display:block;margin:0 auto" />

<p>MCP tries to replace that pattern with a common protocol.</p>
<p>Instead of each app writing its own custom connector, a tool provider can expose an <strong>MCP server</strong>. Any MCP compatible client can connect to it. That does not remove all integration work, but it changes where the work happens.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/ae3c110e-ea98-48df-b274-ee0f604d1414.png" alt="" style="display:block;margin:0 auto" />

<p>Anthropic introduced MCP in 2024 as an open standard for secure two way connections between AI tools and data sources. GitHub also describes MCP as a standard way to connect AI models to different data sources and tools, including GitHub Copilot integrations.</p>
<p>That timing matters.</p>
<p>AI tools are moving from autocomplete to action. They are no longer just writing text. They are reading repositories, creating pull requests, querying data, scheduling meetings, and calling APIs.</p>
<p>MCP is one of the clearest attempts to standardize that shift.</p>
<h2>How the architecture works</h2>
<p>MCP uses three main roles.</p>
<table>
<thead>
<tr>
<th>Role</th>
<th>What it means</th>
<th>Example</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Host</strong></td>
<td>The app the user interacts with</td>
<td>Claude Desktop, an IDE, an agent app</td>
</tr>
<tr>
<td><strong>Client</strong></td>
<td>The protocol component inside the host</td>
<td>One MCP client per server connection</td>
</tr>
<tr>
<td><strong>Server</strong></td>
<td>The external system connector</td>
<td>GitHub server, database server, file server</td>
</tr>
</tbody></table>
<p>The <a href="https://modelcontextprotocol.io/docs/learn/architecture">MCP architecture docs</a> explain that a host creates MCP clients, and each client keeps a dedicated connection to a server. This is important. The host is the product you use. The client is the protocol piece. The server is the bridge to an external system.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/2d0a5019-6e9c-4af4-96d6-30b09515be2d.png" alt="" style="display:block;margin:0 auto" />

<p>MCP servers usually expose three kinds of capabilities.</p>
<table>
<thead>
<tr>
<th>Capability</th>
<th>What it does</th>
<th>Simple example</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Resources</strong></td>
<td>Provide readable context</td>
<td>Read a file, fetch a database schema</td>
</tr>
<tr>
<td><strong>Tools</strong></td>
<td>Perform actions</td>
<td>Create an issue, run a query, call an API</td>
</tr>
<tr>
<td><strong>Prompts</strong></td>
<td>Provide reusable workflows</td>
<td>Summarize a repo, prepare a release note</td>
</tr>
</tbody></table>
<p>A resource is usually read focused. A tool can change something. A prompt is a reusable instruction pattern.</p>
<p>That difference matters for safety.</p>
<p>Reading a database schema is not the same as running a migration. Listing GitHub issues is not the same as closing one. A serious MCP setup should treat these capabilities differently.</p>
<p>Here is a simple request flow.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/71157824-c14f-4938-8406-fe7bdd167f06.png" alt="" style="display:block;margin:0 auto" />

<p>The model does not magically get access to everything. Access depends on the server, the client, the user approval flow, and the permissions granted to that connection.</p>
<p>That is the part teams need to design carefully.</p>
<h2>Why security is the real story</h2>
<p>MCP makes AI agents more useful by giving them better context and tools. It also gives attackers a bigger surface area.</p>
<p>The <a href="https://modelcontextprotocol.io/specification/2025-11-25">MCP specification</a> is direct about this. It says the protocol enables powerful capabilities through arbitrary data access and code execution paths. That is not a small warning.</p>
<p>A normal API client follows code you wrote. An AI agent follows a mix of system instructions, user requests, retrieved content, tool descriptions, and model output. That makes trust harder.</p>
<p><a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/">OWASP's LLM Top 10</a> lists prompt injection as a major LLM application risk. It also warns about insecure output handling, plugin design, supply chain risk, and excessive agency. Those risks map closely to MCP systems because MCP gives models a path to tools.</p>
<p>The tricky part is that prompt injection can come from places that look harmless.</p>
<p>A malicious instruction can hide inside:</p>
<ul>
<li><p>A GitHub issue</p>
</li>
<li><p>A README file</p>
</li>
<li><p>A support ticket</p>
</li>
<li><p>A calendar invite</p>
</li>
<li><p>A web page</p>
</li>
<li><p>A database row</p>
</li>
<li><p>A document shared with the agent</p>
</li>
</ul>
<p>The agent may read that content as context, then treat part of it like an instruction.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/b3505e43-b962-4c77-a7c3-c208741a3b51.png" alt="" style="display:block;margin:0 auto" />

<p>This is why MCP security cannot be just an API key problem.</p>
<p>API keys answer one question: is this connection allowed? They do not answer a harder question: should the agent perform this specific action, at this specific time, based on this specific context?</p>
<p>That is the core risk.</p>
<p>MCP turns LLM security from a chat problem into a systems problem.</p>
<img src="https://upload.wikimedia.org/wikipedia/commons/9/9d/Security_keyboard.jpg" alt="Security keypad" style="display:block;margin:0 auto" />

<p><em>Image credit:</em> <a href="https://commons.wikimedia.org/wiki/File:Security_keyboard.jpg"><em>Security keyboard on Wikimedia Commons</em></a></p>
<h2>A safer production pattern</h2>
<p>A safer MCP setup starts with a boring rule: do not give the agent more power than it needs.</p>
<p>That sounds obvious. It is also where many systems fail.</p>
<p>The best pattern is to put a policy layer between the AI host and sensitive MCP servers. That layer should handle approval, logging, rate limits, and tool restrictions.</p>
<img src="https://cdn.hashnode.com/uploads/covers/6818fe7787817224e50ba1ae/7b0af8a6-0ee3-4a95-a294-f33e2eeda59e.png" alt="" style="display:block;margin:0 auto" />

<p>A production MCP design should separate low risk and high risk actions.</p>
<table>
<thead>
<tr>
<th>Action type</th>
<th>Example</th>
<th>Suggested control</th>
</tr>
</thead>
<tbody><tr>
<td>Read only</td>
<td>List issues, read docs</td>
<td>Allow with logging</td>
</tr>
<tr>
<td>Low risk write</td>
<td>Draft a comment</td>
<td>Require user review</td>
</tr>
<tr>
<td>High risk write</td>
<td>Merge PR, delete record</td>
<td>Require explicit approval</td>
</tr>
<tr>
<td>Sensitive access</td>
<td>Query customer data</td>
<td>Limit scope and log every call</td>
</tr>
<tr>
<td>Code execution</td>
<td>Run shell command</td>
<td>Avoid by default, sandbox if needed</td>
</tr>
</tbody></table>
<p>A few rules help a lot.</p>
<ul>
<li><p>Start with read only servers.</p>
</li>
<li><p>Use short lived credentials where possible.</p>
</li>
<li><p>Prefer scoped tokens over broad tokens.</p>
</li>
<li><p>Keep tool descriptions clear and narrow.</p>
</li>
<li><p>Log every tool call and response status.</p>
</li>
<li><p>Add human approval for writes.</p>
</li>
<li><p>Treat retrieved text as untrusted input.</p>
</li>
<li><p>Do not let one tool silently feed secrets into another tool.</p>
</li>
</ul>
<p>The last point is easy to miss.</p>
<p>The danger is not always one tool. It is tool composition. A file reader plus a network sender can become a data leak. A database query tool plus a ticket updater can expose private data in a public issue.</p>
<p>Good MCP design is mostly about boundaries.</p>
<img src="https://upload.wikimedia.org/wikipedia/commons/1/11/PDC_server_room.jpg" alt="Server room with network infrastructure" style="display:block;margin:0 auto" />

<p><em>Image credit:</em> <a href="https://commons.wikimedia.org/wiki/File:PDC_server_room.jpg"><em>PDC server room on Wikimedia Commons</em></a></p>
<h2>What developers should build next</h2>
<p>MCP is not magic. It is plumbing.</p>
<p>Good plumbing matters because it decides what can flow, where it can flow, and what happens when something breaks. That is why MCP is worth learning now.</p>
<p>The useful question is not, "Should every app support MCP?" The better question is, "Where would a standard tool interface remove custom glue without creating too much risk?"</p>
<p>MCP fits well when:</p>
<ul>
<li><p>Your agent needs to read from many systems.</p>
</li>
<li><p>You want one connector to work across many AI clients.</p>
</li>
<li><p>You are building internal developer tools.</p>
</li>
<li><p>You need controlled access to company context.</p>
</li>
<li><p>You can define clear tool permissions.</p>
</li>
</ul>
<p>MCP is a poor fit when:</p>
<ul>
<li><p>You cannot audit tool calls.</p>
</li>
<li><p>The agent needs broad write access from day one.</p>
</li>
<li><p>The data is highly sensitive and poorly classified.</p>
</li>
<li><p>You have no approval flow for risky actions.</p>
</li>
<li><p>You are treating the model as a trusted decision maker.</p>
</li>
</ul>
<p>My practical recommendation is simple.</p>
<p>Start with a small internal MCP server. Give it read only access. Connect it to something useful, like documentation, issue search, or service metadata. Watch how people use it. Then add write actions one by one, with approvals and logs.</p>
<p>That path is slower than a demo.</p>
<p>It is also how you avoid turning a useful agent into a confused intern with production credentials.</p>
<p>MCP is probably going to matter because it gives AI apps a shared way to connect to the world. But the winners will not be the teams with the most tools. They will be the teams with the clearest boundaries.</p>
<h2>Sources</h2>
<ul>
<li><p><a href="https://modelcontextprotocol.io/docs/getting-started/intro">MCP introduction</a></p>
</li>
<li><p><a href="https://modelcontextprotocol.io/docs/learn/architecture">MCP architecture overview</a></p>
</li>
<li><p><a href="https://modelcontextprotocol.io/specification/2025-11-25">MCP specification</a></p>
</li>
<li><p><a href="https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization">MCP authorization specification</a></p>
</li>
<li><p><a href="https://www.anthropic.com/news/model-context-protocol">Anthropic MCP announcement</a></p>
</li>
<li><p><a href="https://openai.github.io/openai-agents-python/mcp/">OpenAI Agents SDK MCP docs</a></p>
</li>
<li><p><a href="https://docs.github.com/en/copilot/concepts/context/mcp">GitHub Copilot MCP docs</a></p>
</li>
<li><p><a href="https://owasp.org/www-project-top-10-for-large-language-model-applications/">OWASP Top 10 for LLM applications</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[The Future of Coding: AI, Automation, and the Evolving Developer Landscape]]></title><description><![CDATA[The world of coding stands at a pivotal moment. Artificial intelligence is no longer some far-off idea. It is reshaping software development right now, changing how code gets written, who does the writing, and what it even means to be a developer. To...]]></description><link>https://blog.prashantkoirala.info.np/the-future-of-coding-ai-automation-and-the-evolving-developer-landscape</link><guid isPermaLink="true">https://blog.prashantkoirala.info.np/the-future-of-coding-ai-automation-and-the-evolving-developer-landscape</guid><category><![CDATA[#ai-tools]]></category><category><![CDATA[coding]]></category><category><![CDATA[programing]]></category><category><![CDATA[Artificial Intelligence]]></category><category><![CDATA[gemini]]></category><category><![CDATA[chatgpt]]></category><category><![CDATA[futureoftech]]></category><category><![CDATA[vibe coding]]></category><dc:creator><![CDATA[Prashant Koirala]]></dc:creator><pubDate>Thu, 08 May 2025 19:20:07 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/0Jk1QCGMz5o/upload/1c18be9fb184349f9208f113f9cb4840.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>The world of coding stands at a pivotal moment. Artificial intelligence is no longer some far-off idea. It is reshaping software development right now, changing how code gets written, who does the writing, and what it even means to be a developer. Tools like GitHub Copilot and autonomous agents such as Devin are leading the charge. At the same time, the job market pulses with both promise and unease. Demand for AI experts surges, while traditional programming positions grapple with upheaval.</p>
<h2 id="heading-the-ai-surge-in-coding-a-snapshot-of-2025">The AI Surge in Coding: A Snapshot of 2025</h2>
<p>Artificial intelligence has shifted from hype to a fundamental part of software development. Tools such as GitHub Copilot, Cursor, and Claude 3.7 Sonnet have become everyday essentials for developers. They churn out code snippets, propose fixes, and even sketch full functions. Back in 2023, a Stack Overflow survey showed that 70 percent of developers turned to AI tools at least once a week. By 2025, that figure has almost certainly climbed as these tools grow more refined.</p>
<p>The bigger shift comes from AI agents that do more than just help. Consider Devin, created by Cognition. It grabbed headlines in 2024 for tackling complete coding projects, from finishing freelance jobs on Upwork to patching bugs in massive codebases. The first version of Devin had trouble with intricate work, but the 2025 release of Devin 2.0 brings improvements like crafting project outlines, answering code queries with references, and building documentation sites. Cognition's new pay-as-you-go model makes it easier for more people to try, a sign of their belief in its potential.</p>
<p>Then there is "vibe coding," a phrase that captures a fresh way of working where developers guide AI rather than type every detail. A Forbes piece noted that a quarter of the startups in Y Combinator's 2025 batch have codebases that are at least 85 percent AI-generated. This evolution questions the old image of developers as meticulous artisans and spotlights the skills that will matter going forward.</p>
<p>The market for generative AI coding assistants stood at 25.9 million dollars in 2024. Projections put it at 97.9 million by 2030, with a compound annual growth rate of 24.8 percent. This rapid expansion mirrors the rising intricacy of software projects and the push for faster development cycles.</p>
<h2 id="heading-navigating-the-job-market-growth-amid-turmoil">Navigating the Job Market: Growth Amid Turmoil</h2>
<p>In 2025, the coding job scene tells two stories. AI-focused positions are exploding in demand, while conventional programming jobs stir up worries.</p>
<h3 id="heading-the-explosion-in-ai-and-machine-learning-positions">The Explosion in AI and Machine Learning Positions</h3>
<p>The World Economic Forum predicted in 2024 that global need for AI and machine learning experts would jump 40 percent in the coming years. Data from early 2025 backs that up. A Jobright analysis of 80,000 job openings at U.S. AI startups pinpointed machine learning engineers as the hottest role, with over 2,000 spots available. Senior roles in this field command salaries from 172,880 to 209,640 dollars a year, underscoring the high value placed on these abilities.</p>
<p>At NVIDIA's GTC event in March 2025, speakers stressed the importance of developers who weave AI into their routines. Discussions highlighted how even those without deep technical backgrounds can use AI to code, while seasoned pros are blending in skills from fields like the liberal arts to infuse projects with a human element. This points to a future where blending technical know-how with creativity sets people apart.</p>
<h3 id="heading-pressures-on-traditional-programming-roles">Pressures on Traditional Programming Roles</h3>
<p>Meanwhile, classic programming jobs face headwinds. A Fortune report from March 2025 revealed that U.S. employment for computer programmers has dropped to levels not seen since 1980, tying into the ascent of generative AI like ChatGPT. The Washington Post listed programming among the top 10 jobs hit hardest, as AI speeds up routine tasks and might cut the need for entry-level coders.</p>
<p>Industry voices are raising concerns. In March 2025, Anthropic's CEO Dario Amodei forecasted that AI could handle 90 percent of code in six months and almost all of it within a year. Social media posts from figures like Sumanth Raman echo this, suggesting that basic coding jobs could disappear by year's end as AI produces code more swiftly and accurately. Mark Zuckerberg stated that Meta's Llama initiatives aim for fully AI-written code in the next 12 to 18 months.</p>
<p>Not all views align on the extent of this change. A 2024 Danish study showed AI chatbots had little effect on wages or jobs in 11 fields, including software development. Bill Gates recognizes AI's influence but insists humans will stay vital for oversight and inventive thinking.</p>
<h2 id="heading-ai-coding-tools-from-assistants-to-automated-modes">AI Coding Tools: From Assistants to Automated Modes</h2>
<p>The pace of innovation in AI coding tools is staggering in 2025. Here is a look at the main contenders and directions.</p>
<h3 id="heading-github-copilot-and-its-rivals">GitHub Copilot and Its Rivals</h3>
<p>GitHub Copilot, backed by OpenAI, holds a strong position. Microsoft reports that up to 30 percent of its code this year comes from AI. Still, challengers are gaining ground. Cursor stands out for its intuitive design, with developers saying it edges out Copilot in certain areas. Claude 3.7 Sonnet, Windsurf, and Replit bring unique strengths like planning code and spotting errors.</p>
<h3 id="heading-devin-and-self-running-agents">Devin and Self-Running Agents</h3>
<p>Devin positions itself as the first true AI software engineer, capable of managing projects from start to finish, including deployment. Early iterations faltered on tough challenges, but the 2025 version bolsters its reliability in coding and docs. Social media buzz from 2024 praised its threat to sites like Upwork.</p>
<h3 id="heading-zencoders-coffee-mode">Zencoder's Coffee Mode</h3>
<p>Launched by Zencoder, founded by former Wrike leader Andrew Filev, Coffee Mode arrived in April 2025. It lets developers press a button to have AI generate unit tests. Working with tools like Visual Studio Code, JetBrains IDEs, JIRA, and GitHub, Zencoder tops benchmarks and slips into current processes. This move toward simple automation is reshaping how we think about efficiency.</p>
<h3 id="heading-emerging-platforms">Emerging Platforms</h3>
<p>Fresh developments include whispers of Apple and Anthropic teaming up for an AI coding system, alongside Amazon's push into code generation. These efforts show big tech's heavy investment in AI-powered building.</p>
<h2 id="heading-the-emergence-of-multi-agent-collaboration-platforms">The Emergence of Multi-Agent Collaboration Platforms</h2>
<p>Multi-agent collaboration platforms, or MCPs, represent a budding trend. They combine AI agents to tackle multifaceted jobs. A social media post described one MCP that lets agents code, pull from APIs, and manage real-world duties, labeling it transformative. These setups free developers from drudgery, allowing focus on big-picture design and fresh ideas.</p>
<p>MCPs hold special promise for businesses. As one observer noted online, companies crave AI coding solutions, fueling rivalry. Cursor leads for now, but acquisitions like OpenAI's Windsurf and integrated packages add pressure. MCPs might overhaul team dynamics, casting developers as directors who guide AI rather than code everything themselves.</p>
<h2 id="heading-hurdles-and-debates">Hurdles and Debates</h2>
<p>The ascent of AI in coding brings complications. Here are the main points fueling discussions in 2025.</p>
<h3 id="heading-fears-of-job-loss">Fears of Job Loss</h3>
<p>The International Monetary Fund figures that 60 percent of jobs in developed economies face AI exposure, with half at risk of harm. Goldman Sachs estimates 300 million global positions could shift, with coding high on the list. While AI might spawn roles like ethicists or prompt specialists, the shift could prove tough for beginners.</p>
<h3 id="heading-risks-of-depending-too-much-on-ai">Risks of Depending Too Much on AI</h3>
<p>Seasoned coders fret that tools like Copilot or Devin might stunt growth for newcomers. A 2025 article quoted skeptics who say fresh developers miss core knowledge when they rely heavily on AI. For instance, Cursor once declined to produce code, urging a user to build the logic on their own to foster independence.</p>
<h3 id="heading-questions-around-ownership">Questions Around Ownership</h3>
<p>Code from AI sparks debates on rights and laws. Who claims ownership of output from Devin or Copilot? Growing oversight on intellectual property is influencing the field, pushing firms to define terms clearly.</p>
<h3 id="heading-issues-with-bias-and-dependability">Issues with Bias and Dependability</h3>
<p>AI tools for coding have flaws. A 2025 review found that while options like Grok err on small things, they are advancing fast. Yet, biases in data or invented errors, known as hallucinations, worry users, particularly in essential systems.</p>
<h2 id="heading-essential-skills-for-tomorrows-developers">Essential Skills for Tomorrow's Developers</h2>
<p>With AI claiming routine work, the developer's job is evolving. Here is what will count.</p>
<ul>
<li><strong>Guiding AI</strong>: Mastery of directing and prompting tools will be key. NVIDIA's event stressed embedding AI in daily tasks.</li>
<li><strong>Interpersonal Abilities</strong>: Creativity, clear communication, and solving problems will set stars apart. AI handles code, but people grasp nuance and user wants.</li>
<li><strong>Niche Expertise</strong>: Areas like security, blockchain, or AI ethics will thrive as AI covers basics.</li>
<li><strong>Ongoing Education</strong>: Tools change monthly, so keeping current through resources like NVIDIA's institute or online groups is vital.</li>
</ul>
<h2 id="heading-looking-forward-hope-or-worry">Looking Forward: Hope or Worry?</h2>
<p>Coding's future excites and unnerves. AI opens doors, letting non-experts code and speeding breakthroughs. A quarter of Y Combinator startups with mostly AI code proves this. But threats of unemployment and fading skills, especially for starters, cast shadows.</p>
<p>Experts vary in outlook. Pew Research shows AI pros more upbeat than the public on job effects, seeing gains in speed and new paths. Others, like Ray Dalio, caution that harnessing AI's strength while preserving human input is key to dodging economic shakes.</p>
<p>For developers, adaptation is non-negotiable. Partnering with AI, via features like Zencoder's Coffee Mode or MCPs, will define winners. As Anthropic's Dario Amodei put it, telling folks to skip learning code ranks as terrible advice. The craft may transform, but its essence persists.</p>
<h2 id="heading-final-thoughts-welcome-the-shift">Final Thoughts: Welcome the Shift</h2>
<p>In 2025, coding thrives in an AI-fueled world. Innovations like Devin, Copilot, and Zencoder redefine building software, while MCPs and business tools suggest developers will lead rather than labor over lines. The job landscape mixes highs and lows, booming for AI whizzes but testing for traditionalists. One certainty: thriving means adapting, learning, and harnessing AI.</p>
]]></content:encoded></item><item><title><![CDATA[Boost Your Workflow: An Inside Look at My Time-Tested Dotfiles Setup]]></title><description><![CDATA[As a developer, nothing beats the feeling of a finely tuned workspace, where every tool, shortcut, and visual detail feels like a natural extension of your thought process. Setting up that perfect environment, though, is rarely straightforward. It’s ...]]></description><link>https://blog.prashantkoirala.info.np/boost-your-workflow-an-inside-look-at-my-time-tested-dotfiles-setup</link><guid isPermaLink="true">https://blog.prashantkoirala.info.np/boost-your-workflow-an-inside-look-at-my-time-tested-dotfiles-setup</guid><category><![CDATA[yabai]]></category><category><![CDATA[customization]]></category><category><![CDATA[vim]]></category><category><![CDATA[dotfiles]]></category><category><![CDATA[neovim]]></category><category><![CDATA[aerospace]]></category><category><![CDATA[workflow]]></category><category><![CDATA[10xDeveloper]]></category><dc:creator><![CDATA[Prashant Koirala]]></dc:creator><pubDate>Mon, 05 May 2025 19:31:49 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/DuHKoV44prg/upload/fde5aa343649b3b4afc2eab2680e0c02.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a developer, nothing beats the feeling of a finely tuned workspace, where every tool, shortcut, and visual detail feels like a natural extension of your thought process. Setting up that perfect environment, though, is rarely straightforward. It’s a journey of trial and error, late-night tweaks, and the occasional frustration of a forgotten keybinding or a lost script that made everything just right. Like many of you, I’ve spent countless hours wrestling with new machine setups, trying to recreate the magic of a workflow that hums along effortlessly. That’s why I’ve poured years into building and refining my dotfiles repository, a living snapshot of how I work, available at <a target="_blank" href="https://github.com/prashantkoirala465/Config-Files">github.com/prashantkoirala465/Config-Files</a>.</p>
<p>In this post, I’m opening the hood on my dotfiles setup, sharing not just the configs themselves but the stories, decisions, and hard-earned lessons behind them. This isn’t a surface-level overview; it’s a detailed exploration of every file, folder, and choice that shapes my daily coding life. Whether you’re a newcomer starting your own dotfiles journey, a veteran developer curious about fresh tools, or simply someone who loves geeking out over configurations, I hope you’ll find something valuable here. Expect in-depth breakdowns, practical code snippets, personal anecdotes, comparisons to other approaches, and actionable tips to craft a setup that works for you. Let’s dive in.</p>
<h2 id="heading-why-dotfiles-matter">Why Dotfiles Matter</h2>
<p>Dotfiles, those unassuming configuration files tucked away with their telltale <code>.</code> prefix, are the quiet architects of a developer’s environment. They dictate everything from how your shell prompt looks to the behavior of your editor’s keybindings. For me, dotfiles are more than just settings; they’re a reflection of my approach to coding: prioritize efficiency, embrace modularity, and always keep refining.</p>
<h3 id="heading-my-dotfiles-origin-story">My Dotfiles Origin Story</h3>
<p>My dotfiles journey began out of necessity. Early in my career, setting up a new MacBook or Linux machine was a slog. I’d spend hours piecing together my ideal Neovim setup or tweaking an Alacritty theme to reduce eye strain, only to realize I couldn’t replicate it later. Switching jobs or hardware meant starting from scratch, and I’d inevitably forget some critical tweak. Frustrated, I decided to centralize my configurations in a Git repository with a few clear goals:</p>
<ul>
<li><strong>Consistency</strong>: Make my environment feel identical whether I’m on my MacBook, Arch Linux desktop, or a remote server.</li>
<li><strong>Speed</strong>: Cut setup time from hours to minutes with a single <code>git clone</code> and a setup script.</li>
<li><strong>Shareability</strong>: Open-source my configs to learn from others and give back to the community.</li>
<li><strong>Control</strong>: Customize every tool to fit my workflow like a glove.</li>
</ul>
<h3 id="heading-the-broader-dotfiles-landscape">The Broader Dotfiles Landscape</h3>
<p>Dotfiles are a universal practice, but every developer’s approach is unique. Some keep things lean with just a <code>.bashrc</code> or <code>.vimrc</code>, prioritizing portability. Others, like Zach Holman or Mathias Bynens, build intricate setups with custom scripts and integrations for tools like <code>tmux</code> or <code>iTerm2</code>. Then there are the aesthetic enthusiasts who craft visually stunning terminal and editor themes. My setup blends all three: it’s functional, performant, and easy on the eyes, drawing inspiration from communities like <a target="_blank" href="https://dotfiles.github.io/">DotFiles</a>.</p>
<h3 id="heading-what-youll-take-away">What You’ll Take Away</h3>
<p>By the end of this post, you’ll not only see what my dotfiles do but understand why I made each choice. I’ll break down my reasoning, compare my approach to alternatives, and share tips to help you build a setup that feels uniquely yours. Let’s start with the foundation: how my repository is organized.</p>
<h2 id="heading-repository-structure-built-for-clarity-and-flexibility">Repository Structure: Built for Clarity and Flexibility</h2>
<p>My dotfiles live at <a target="_blank" href="https://github.com/prashantkoirala465/Config-Files">github.com/prashantkoirala465/Config-Files</a>, designed to be modular, intuitive, and easy to maintain. Here’s the structure:</p>
<pre><code>Config-Files/
├── aerospace/
│   └── aerospace.toml
├── alacritty/
│   └── alacritty.yml
├── karabiner/
│   └── karabiner.json
├── nvim/
│   ├── init.lua
│   └── lua/
├── wezterm/
│   └── wezterm.lua
├── yabai/
│   └── yabairc
├── zed/
│   └── settings.json
├── LICENSE
└── README.md
</code></pre><h3 id="heading-why-this-layout">Why This Layout?</h3>
<p>Each tool gets its own dedicated folder, keeping things organized and making it easy to swap components. If I decide to switch from Alacritty to Kitty, for example, I can update just the <code>alacritty/</code> folder without touching the rest. The <code>README.md</code> walks you through setup steps, and the MIT <code>LICENSE</code> ensures others can freely use or adapt my work.</p>
<h3 id="heading-how-others-organize-dotfiles">How Others Organize Dotfiles</h3>
<p>Some developers use a “bare” Git repository, tracking files directly in their home directory (<code>~/.git</code>). Others rely on tools like <a target="_blank" href="https://www.gnu.org/software/stow/">Stow</a> to manage symlinks. I opted for a directory-based approach because it’s simple and pairs well with my setup script, which handles symlinking to the home directory automatically.</p>
<h3 id="heading-tips-for-your-repository">Tips for Your Repository</h3>
<ul>
<li><strong>Document Clearly</strong>: A detailed <code>README</code> with setup instructions is non-negotiable.</li>
<li><strong>Use Submodules</strong>: For external plugins, Git submodules keep everything in sync.</li>
<li><strong>Commit Often</strong>: Regular backups prevent losing your tweaks.</li>
<li><strong>Test Fresh</strong>: Periodically try your setup on a clean virtual machine to ensure it works seamlessly.</li>
</ul>
<h2 id="heading-window-management-taming-the-chaos-with-aerospace">Window Management: Taming the Chaos with Aerospace</h2>
<p>For someone juggling multiple projects—coding, debugging, writing—a good window manager is essential. My workflow thrives on keyboard-driven organization, and for years, I relied on <a target="_blank" href="https://github.com/koekeishiya/yabai">Yabai</a>, a tiling window manager for macOS. Its ability to snap windows into grids or stacks transformed how I multitasked. My <code>yabairc</code> was tuned for simplicity and speed:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/usr/bin/env sh</span>

yabai -m config layout bsp
yabai -m config window_gap 12
yabai -m config top_padding 10
yabai -m config bottom_padding 10
yabai -m config left_padding 10
yabai -m config right_padding 10
yabai -m config window_border on
yabai -m config window_border_width 4
yabai -m config active_window_border_color 0xff5e81ac

<span class="hljs-comment"># Keybindings</span>
yabai -m signal --add event=window_focused action=<span class="hljs-string">"yabai -m window --focus recent"</span>
yabai -m config mouse_follows_focus off
yabai -m config focus_follows_mouse off
</code></pre>
<p>This gave me a clean, tiled layout with subtle borders to highlight active windows. But as macOS tightened security with each update, Yabai required more manual tweaks to keep its scripting features running smoothly.</p>
<h3 id="heading-enter-aerospace">Enter Aerospace</h3>
<p>In 2024, I switched to <a target="_blank" href="https://github.com/koekeishiya/aerospace">Aerospace</a>, a polished alternative that builds on Yabai’s strengths. Its TOML-based configuration is more readable than Yabai’s shell scripts, and it feels smoother out of the box. Here’s a snippet from my <code>aerospace.toml</code>:</p>
<pre><code class="lang-toml"><span class="hljs-comment"># Gaps and padding</span>
<span class="hljs-attr">gaps.inner</span> = <span class="hljs-number">18</span>
<span class="hljs-attr">gaps.outer</span> = <span class="hljs-number">20</span>
<span class="hljs-attr">screen-padding</span> = <span class="hljs-number">20</span>

<span class="hljs-comment"># Window appearance</span>
<span class="hljs-attr">border.width</span> = <span class="hljs-number">4</span>
<span class="hljs-attr">border.color.normal</span> = <span class="hljs-string">'#5e81ac'</span>
<span class="hljs-attr">border.color.focused</span> = <span class="hljs-string">'#88c0d0'</span>

<span class="hljs-comment"># Layout</span>
<span class="hljs-attr">default-workspace-layout</span> = <span class="hljs-string">'stacking'</span>

<span class="hljs-comment"># Keybindings</span>
<span class="hljs-attr">bind</span> = [
  { key = <span class="hljs-string">'Return'</span>, mods = [<span class="hljs-string">'Mod4'</span>], command = <span class="hljs-string">'exec alacritty'</span> },
  { key = <span class="hljs-string">'h'</span>, mods = [<span class="hljs-string">'Mod4'</span>], command = <span class="hljs-string">'focus left'</span> },
  { key = <span class="hljs-string">'l'</span>, mods = [<span class="hljs-string">'Mod4'</span>], command = <span class="hljs-string">'focus right'</span> },
  { key = <span class="hljs-string">'j'</span>, mods = [<span class="hljs-string">'Mod4'</span>], command = <span class="hljs-string">'focus down'</span> },
  { key = <span class="hljs-string">'k'</span>, mods = [<span class="hljs-string">'Mod4'</span>], command = <span class="hljs-string">'focus up'</span> },
  { key = <span class="hljs-string">'Shift+h'</span>, mods = [<span class="hljs-string">'Mod4'</span>], command = <span class="hljs-string">'move left'</span> },
  { key = <span class="hljs-string">'Shift+l'</span>, mods = [<span class="hljs-string">'Mod4'</span>], command = <span class="hljs-string">'move right'</span> },
]
</code></pre>
<p>Aerospace’s stacking layout suits my preference for vertically organized windows, especially when editing multiple files in Neovim or Zed. The 18px gaps and 20px padding create a spacious workspace, and the Nordic-inspired colors add a subtle, professional touch.</p>
<h3 id="heading-comparing-approaches">Comparing Approaches</h3>
<p>Many macOS users lean on native tools like Mission Control or apps like <a target="_blank" href="https://rectangleapp.com/">Rectangle</a>. Linux developers often favor <code>i3</code> or <code>sway</code>. Aerospace strikes a balance, offering tiling automation with enough flexibility for manual tweaks, making it ideal for developers who value both structure and control.</p>
<h3 id="heading-window-management-tips">Window Management Tips</h3>
<ul>
<li><strong>Try Different Layouts</strong>: Experiment with binary space partitioning versus stacking to find your flow.</li>
<li><strong>Optimize Keybindings</strong>: Use intuitive shortcuts, like Vim-inspired <code>h/j/k/l</code>, for navigation.</li>
<li><strong>Test Multi-Monitor</strong>: Make sure your config works across displays.</li>
<li><strong>Document Choices</strong>: Note why you picked specific gaps or layouts for future tweaks.</li>
</ul>
<h2 id="heading-terminal-emulators-where-commands-come-to-life">Terminal Emulators: Where Commands Come to Life</h2>
<p>The terminal is my control hub, whether I’m running scripts, managing Git, or connecting to a server. I need speed, reliability, and a touch of style. I rely on two emulators: <a target="_blank" href="https://github.com/alacritty/alacritty">Alacritty</a> for its performance and <a target="_blank" href="https://wezfurlong.org/wezterm/">WezTerm</a> for its advanced features.</p>
<h3 id="heading-alacritty-built-for-speed">Alacritty: Built for Speed</h3>
<p>Alacritty’s GPU acceleration makes it one of the fastest terminals out there. My <code>alacritty.yml</code> prioritizes clarity and minimalism:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">window:</span>
  <span class="hljs-attr">padding:</span>
    <span class="hljs-attr">x:</span> <span class="hljs-number">10</span>
    <span class="hljs-attr">y:</span> <span class="hljs-number">10</span>
  <span class="hljs-attr">opacity:</span> <span class="hljs-number">0.95</span>

<span class="hljs-attr">font:</span>
  <span class="hljs-attr">normal:</span>
    <span class="hljs-attr">family:</span> <span class="hljs-string">"Fira Code"</span>
    <span class="hljs-attr">style:</span> <span class="hljs-string">"Regular"</span>
  <span class="hljs-attr">bold:</span>
    <span class="hljs-attr">style:</span> <span class="hljs-string">"Bold"</span>
  <span class="hljs-attr">size:</span> <span class="hljs-number">12.0</span>

<span class="hljs-attr">colors:</span>
  <span class="hljs-attr">primary:</span>
    <span class="hljs-attr">background:</span> <span class="hljs-string">'#1e1e2e'</span>
    <span class="hljs-attr">foreground:</span> <span class="hljs-string">'#cdd6f4'</span>
  <span class="hljs-attr">cursor:</span>
    <span class="hljs-attr">text:</span> <span class="hljs-string">'#1e1e2e'</span>
    <span class="hljs-attr">cursor:</span> <span class="hljs-string">'#f5e0dc'</span>
  <span class="hljs-attr">normal:</span>
    <span class="hljs-attr">black:</span> <span class="hljs-string">'#45475a'</span>
    <span class="hljs-attr">red:</span> <span class="hljs-string">'#f38ba8'</span>
    <span class="hljs-attr">green:</span> <span class="hljs-string">'#a6e3a1'</span>
    <span class="hljs-attr">yellow:</span> <span class="hljs-string">'#f9e2af'</span>
    <span class="hljs-attr">blue:</span> <span class="hljs-string">'#89b4fa'</span>
    <span class="hljs-attr">magenta:</span> <span class="hljs-string">'#f5c2e7'</span>
    <span class="hljs-attr">cyan:</span> <span class="hljs-string">'#94e2d5'</span>
    <span class="hljs-attr">white:</span> <span class="hljs-string">'#bac2de'</span>
</code></pre>
<p>The <code>Fira Code</code> font with ligatures makes code easy to read, while the Catppuccin Mocha theme offers a high-contrast, soothing palette. A slight opacity adds a modern feel without compromising legibility.</p>
<h3 id="heading-wezterm-the-feature-packed-alternative">WezTerm: The Feature-Packed Alternative</h3>
<p>WezTerm excels for complex workflows, with Lua-based scripting and features like tabs and multiplexing that rival <code>tmux</code>. My <code>wezterm.lua</code> balances aesthetics and functionality:</p>
<pre><code class="lang-lua">local wezterm = require 'wezterm'
local config = wezterm.config_builder()

config.font = wezterm.font('MesloLGS Nerd Font Mono', { weight = 'Bold' })
config.font_size = 14
config.enable_tab_bar = false
config.window_decorations = 'RESIZE'
config.window_background_opacity = 0.8
config.macos_window_background_blur = 10

config.colors = {
  foreground = '#CBE0F0',
  background = '#011423',
  cursor_bg = '#47FF9C',
  cursor_border = '#47FF9C',
  cursor_fg = '#011423',
  selection_bg = '#033259',
  selection_fg = '#CBE0F0',
  ansi = { '#214969', '#E52E2E', '#44FFB1', '#FFE073', '#0FC5ED', '#a277ff', '#24EAF7', '#24EAF7' },
  brights = { '#214969', '#E52E2E', '#44FFB1', '#FFE073', '#A277FF', '#a277ff', '#24EAF7', '#24EAF7' },
}

return config
</code></pre>
<p>The bold <code>MesloLGS Nerd Font Mono</code> and vibrant colors make WezTerm ideal for long coding sessions, with background blur and opacity creating an immersive experience.</p>
<h3 id="heading-alacritty-vs-wezterm">Alacritty vs. WezTerm</h3>
<ul>
<li><strong>Alacritty</strong>: Perfect for lightweight tasks like SSH or quick scripts.</li>
<li><strong>WezTerm</strong>: Shines for managing multiple projects with tabs or custom Lua scripts.</li>
</ul>
<h3 id="heading-terminal-trends">Terminal Trends</h3>
<p>Some developers prefer <code>iTerm2</code> for macOS integration or <code>Kitty</code> for its image protocol. Minimalists might use macOS’s default Terminal or <code>xterm</code> on Linux. My dual setup lets me switch based on the task, offering flexibility over a single-tool commitment.</p>
<h3 id="heading-terminal-tips">Terminal Tips</h3>
<ul>
<li><strong>Pick a Great Font</strong>: Nerd Fonts like <code>Fira Code</code> or <code>MesloLGS</code> support icons and ligatures.</li>
<li><strong>Choose Comfortable Colors</strong>: Themes like Catppuccin reduce eye strain.</li>
<li><strong>Automate Setup</strong>: Script your terminal installation and config deployment.</li>
<li><strong>Master Your Tool</strong>: Explore Alacritty’s YAML or WezTerm’s Lua docs for hidden gems.</li>
</ul>
<h2 id="heading-editors-where-code-meets-creativity">Editors: Where Code Meets Creativity</h2>
<p>My editors are where I spend most of my time, so they need to be fast, flexible, and intuitive. I primarily use <a target="_blank" href="https://neovim.io/">Neovim</a>, with <a target="_blank" href="https://zed.dev/">Zed</a> as a secondary option for specific tasks.</p>
<h3 id="heading-neovim-my-coding-sanctuary">Neovim: My Coding Sanctuary</h3>
<p>Neovim’s speed and extensibility make it my go-to editor. My <code>init.lua</code> uses <a target="_blank" href="https://github.com/folke/lazy.nvim">Lazy.nvim</a> for plugin management, tailored for a modern, streamlined workflow:</p>
<pre><code class="lang-lua">-- init.lua
vim.g.mapleader = ' '
vim.g.maplocalleader = ' '

require('lazy').setup({
  { 'nvim-treesitter/nvim-treesitter', build = ':TSUpdate' },
  { 'neovim/nvim-lspconfig' },
  { 'hrsh7th/nvim-cmp', dependencies = { 'hrsh7th/cmp-nvim-lsp' } },
  { 'catppuccin/nvim', name = 'catppuccin' },
  { 'nvim-telescope/telescope.nvim', dependencies = { 'nvim-lua/plenary.nvim' } },
})

-- Theme
vim.cmd.colorscheme 'catppuccin-mocha'

-- Treesitter
require('nvim-treesitter.configs').setup {
  ensure_installed = { 'lua', 'python', 'javascript', 'typescript' },
  highlight = { enable = true },
  incremental_selection = { enable = true },
}

-- LSP
local lspconfig = require('lspconfig')
lspconfig.pyright.setup {}
lspconfig.tsserver.setup {}

-- CMP (Autocompletion)
local cmp = require('cmp')
cmp.setup {
  mapping = {
    ['&lt;C-n&gt;'] = cmp.mapping.select_next_item(),
    ['&lt;C-p&gt;'] = cmp.mapping.select_prev_item(),
    ['&lt;CR&gt;'] = cmp.mapping.confirm({ select = true }),
  },
  sources = {
    { name = 'nvim_lsp' },
    { name = 'buffer' },
  },
}

-- Keybindings
vim.keymap.set('n', '&lt;leader&gt;ff', '&lt;cmd&gt;Telescope find_files&lt;CR&gt;', { desc = 'Find Files' })
vim.keymap.set('n', '&lt;leader&gt;fg', '&lt;cmd&gt;Telescope live_grep&lt;CR&gt;', { desc = 'Live Grep' })
</code></pre>
<p>This includes:</p>
<ul>
<li><strong>Treesitter</strong> for syntax highlighting and navigation.</li>
<li><strong>LSP</strong> for Python (<code>pyright</code>) and JavaScript/TypeScript (<code>tsserver</code>).</li>
<li><strong>CMP</strong> for autocompletion.</li>
<li><strong>Telescope</strong> for fuzzy finding.</li>
<li><strong>Catppuccin Mocha</strong> for a consistent theme.</li>
</ul>
<p>I opted for a custom config over distributions like NvChad to keep things lean and tailored.</p>
<h3 id="heading-zed-a-modern-complement">Zed: A Modern Complement</h3>
<p>Zed is a lightweight, collaborative editor I use for pair programming or quick edits. My <code>settings.json</code> keeps it simple:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"theme"</span>: <span class="hljs-string">"Catppuccin Mocha"</span>,
  <span class="hljs-attr">"font_size"</span>: <span class="hljs-number">14</span>,
  <span class="hljs-attr">"font_family"</span>: <span class="hljs-string">"Fira Code"</span>,
  <span class="hljs-attr">"buffer_font_weight"</span>: <span class="hljs-string">"Regular"</span>,
  <span class="hljs-attr">"tab_bar"</span>: { <span class="hljs-attr">"show"</span>: <span class="hljs-literal">false</span> },
  <span class="hljs-attr">"keymap"</span>: [
    {
      <span class="hljs-attr">"context"</span>: <span class="hljs-string">"Editor"</span>,
      <span class="hljs-attr">"bindings"</span>: {
        <span class="hljs-attr">"ctrl-w h"</span>: <span class="hljs-string">"pane:ActivatePrev"</span>,
        <span class="hljs-attr">"ctrl-w l"</span>: <span class="hljs-string">"pane:ActivateNext"</span>
      }
    }
  ]
}
</code></pre>
<p>Zed’s speed and collaboration features make it a great backup, especially for React and TypeScript projects.</p>
<h3 id="heading-neovim-vs-zed">Neovim vs. Zed</h3>
<ul>
<li><strong>Neovim</strong>: Unrivaled for customization and terminal workflows.</li>
<li><strong>Zed</strong>: Excels in GUI-based editing and team collaboration.</li>
</ul>
<h3 id="heading-editor-preferences">Editor Preferences</h3>
<p>Many developers use VS Code for its plugins or JetBrains IDEs for robust projects. Vim enthusiasts might stick with vanilla Vim or LunarVim. My hybrid setup leverages Neovim’s power and Zed’s simplicity.</p>
<h3 id="heading-editor-tips">Editor Tips</h3>
<ul>
<li><strong>Build Gradually</strong>: Add plugins one at a time to avoid config overload.</li>
<li><strong>Master Shortcuts</strong>: Learn your editor’s keybindings to work faster.</li>
<li><strong>Sync Settings</strong>: Use Git to keep configs consistent across devices.</li>
<li><strong>Try New Tools</strong>: Experiment with editors like Zed or Helix to broaden your toolkit.</li>
</ul>
<h2 id="heading-keyboard-customization-unlocking-efficiency-with-karabiner">Keyboard Customization: Unlocking Efficiency with Karabiner</h2>
<p><a target="_blank" href="https://karabiner-elements.pqrs.org/">Karabiner-Elements</a> transforms my MacBook’s keyboard into a productivity powerhouse. My favorite tweak maps <code>Caps Lock</code> to a Hyper Key (Cmd + Ctrl + Option + Shift) for endless shortcut possibilities:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"title"</span>: <span class="hljs-string">"Caps Lock to Hyper Key"</span>,
  <span class="hljs-attr">"rules"</span>: [
    {
      <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Caps Lock to Hyper"</span>,
      <span class="hljs-attr">"manipulators"</span>: [
        {
          <span class="hljs-attr">"from"</span>: {
            <span class="hljs-attr">"key_code"</span>: <span class="hljs-string">"caps_lock"</span>,
            <span class="hljs-attr">"modifiers"</span>: { <span class="hljs-attr">"optional"</span>: [<span class="hljs-string">"any"</span>] }
          },
          <span class="hljs-attr">"to"</span>: [
            {
              <span class="hljs-attr">"key_code"</span>: <span class="hljs-string">"left_control"</span>,
              <span class="hljs-attr">"modifiers"</span>: [<span class="hljs-string">"left_command"</span>, <span class="hljs-string">"left_option"</span>, <span class="hljs-string">"left_shift"</span>]
            }
          ],
          <span class="hljs-attr">"type"</span>: <span class="hljs-string">"basic"</span>
        }
      ]
    },
    {
      <span class="hljs-attr">"description"</span>: <span class="hljs-string">"Hyper + t to open Alacritty"</span>,
      <span class="hljs-attr">"manipulators"</span>: [
        {
          <span class="hljs-attr">"from"</span>: {
            <span class="hljs-attr">"key_code"</span>: <span class="hljs-string">"t"</span>,
            <span class="hljs-attr">"modifiers"</span>: { <span class="hljs-attr">"mandatory"</span>: [<span class="hljs-string">"left_control"</span>, <span class="hljs-string">"left_command"</span>, <span class="hljs-string">"left_option"</span>, <span class="hljs-string">"left_shift"</span>] }
          },
          <span class="hljs-attr">"to"</span>: [
            { <span class="hljs-attr">"shell_command"</span>: <span class="hljs-string">"open -a Alacritty"</span> }
          ],
          <span class="hljs-attr">"type"</span>: <span class="hljs-string">"basic"</span>
        }
      ]
    }
  ]
}
</code></pre>
<p>This lets me launch apps or scripts with a single key combo, saving countless keystrokes.</p>
<h3 id="heading-why-karabiner">Why Karabiner?</h3>
<p>Karabiner’s flexibility is unmatched on macOS, where keyboard customization is otherwise limited. It pairs perfectly with Aerospace’s bindings for a seamless workflow.</p>
<h3 id="heading-keyboard-customization-trends">Keyboard Customization Trends</h3>
<p>Linux users might use <code>xmodmap</code> or <code>setxkbmap</code>, while Windows developers lean on AutoHotkey. Some prefer hardware solutions like QMK keyboards. Karabiner offers a sweet spot for macOS users.</p>
<h3 id="heading-keyboard-tips">Keyboard Tips</h3>
<ul>
<li><strong>Start Small</strong>: Remap one key to build familiarity.</li>
<li><strong>Keep a Cheat Sheet</strong>: Document your mappings for reference.</li>
<li><strong>Test Thoroughly</strong>: Ensure remaps don’t conflict with existing shortcuts.</li>
<li><strong>Share Your Setup</strong>: Publish your rules to inspire others.</li>
</ul>
<h2 id="heading-my-development-philosophy">My Development Philosophy</h2>
<p>My dotfiles reflect how I approach coding:</p>
<ul>
<li><strong>Modularity</strong>: Separate configs for each tool simplify maintenance.</li>
<li><strong>Performance</strong>: Fast tools like Alacritty and Neovim keep me in flow.</li>
<li><strong>Aesthetics</strong>: Cohesive themes reduce visual clutter.</li>
<li><strong>Simplicity</strong>: Avoid unnecessary plugins to stay focused.</li>
<li><strong>Iteration</strong>: Constantly refine based on new tools or workflows.</li>
</ul>
<p>This mindset comes from years of experimenting, failing, and learning—whether switching from Yabai to Aerospace or adding Zed to my toolkit.</p>
<h2 id="heading-practical-tips-for-your-dotfiles">Practical Tips for Your Dotfiles</h2>
<p>Here’s what I’ve learned over the years:</p>
<ol>
<li><strong>Automate Setup</strong>: Create a <code>setup.sh</code> script to handle symlinking and dependencies.</li>
<li><strong>Version Everything</strong>: Use Git to track and revert changes.</li>
<li><strong>Steal Ideas</strong>: Browse GitHub for inspiration from other developers’ dotfiles.</li>
<li><strong>Stay Lean</strong>: Only include configs you actively use.</li>
<li><strong>Test Across Systems</strong>: Ensure compatibility with macOS, Linux, or WSL.</li>
</ol>
<h2 id="heading-resources-to-explore">Resources to Explore</h2>
<ul>
<li><a target="_blank" href="https://github.com/koekeishiya/aerospace">Aerospace Docs</a></li>
<li><a target="_blank" href="https://neovim.io/doc/">Neovim Docs</a></li>
<li><a target="_blank" href="https://github.com/alacritty/alacritty/blob/master/README.md">Alacritty Guide</a></li>
<li><a target="_blank" href="https://wezfurlong.org/wezterm/">WezTerm Docs</a></li>
<li><a target="_blank" href="https://karabiner-elements.pqrs.org/docs/">Karabiner-Elements Docs</a></li>
<li><a target="_blank" href="https://zed.dev/docs">Zed Docs</a></li>
<li><a target="_blank" href="https://dotfiles.github.io/">DotFiles Community</a></li>
</ul>
<h2 id="heading-wrapping-up-make-your-dotfiles-your-own">Wrapping Up: Make Your Dotfiles Your Own</h2>
<p>My dotfiles are more than code; they’re a story of my growth as a developer, from my first <code>.bashrc</code> to my current Aerospace and Neovim setups. Each tweak reflects a problem solved or a lesson learned. Sharing them isn’t about bragging—it’s about sparking ideas and encouraging you to take charge of your tools.</p>
<p>I hope this deep dive into my <a target="_blank" href="https://github.com/prashantkoirala465/Config-Files">Config-Files repository</a> has inspired you, whether it’s to fork my repo, try a new config, or share your own dotfiles story. Drop me a message or comment with your thoughts, and let’s keep the conversation going.</p>
<p>Thanks for reading, and happy coding!</p>
]]></content:encoded></item></channel></rss>