<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Development Tools on KnightLi Blog</title>
        <link>https://knightli.com/en/categories/development-tools/</link>
        <description>Recent content in Development Tools on KnightLi Blog</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>en</language>
        <lastBuildDate>Sat, 30 May 2026 14:43:56 +0800</lastBuildDate><atom:link href="https://knightli.com/en/categories/development-tools/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Obsidian vs Joplin: A Markdown Notes App Comparison Guide</title>
        <link>https://knightli.com/en/2026/05/30/obsidian-vs-joplin-note-app-comparison/</link>
        <pubDate>Sat, 30 May 2026 14:43:56 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/30/obsidian-vs-joplin-note-app-comparison/</guid>
        <description>&lt;p&gt;Obsidian and Joplin are both Markdown note-taking tools, but they suit different kinds of users.&lt;/p&gt;
&lt;p&gt;In short, Obsidian is better for deep knowledge management, backlink-based Zettelkasten workflows, and users who want heavy customization. Joplin is better for practical users who care about data privacy, need cross-platform sync, prefer traditional folder-style organization, and rely on web clipping.&lt;/p&gt;
&lt;p&gt;If you want to build a &amp;ldquo;second brain&amp;rdquo;, write long-term research notes, tinker with plugins, and use knowledge graphs, start with Obsidian. If you want a safer and more open alternative to Evernote or Youdao Cloud Notes, start with Joplin.&lt;/p&gt;
&lt;h2 id=&#34;core-differences&#34;&gt;Core Differences
&lt;/h2&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Dimension&lt;/th&gt;
          &lt;th&gt;Obsidian&lt;/th&gt;
          &lt;th&gt;Joplin&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Open-source status&lt;/td&gt;
          &lt;td&gt;Closed source, free for personal use, paid for commercial use&lt;/td&gt;
          &lt;td&gt;Fully open source, AGPL-3.0 license&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Data storage&lt;/td&gt;
          &lt;td&gt;Local &lt;code&gt;.md&lt;/code&gt; plain text files&lt;/td&gt;
          &lt;td&gt;Local database management, with note content written in Markdown&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Data control&lt;/td&gt;
          &lt;td&gt;Files live directly in local folders, making migration and backup straightforward&lt;/td&gt;
          &lt;td&gt;Managed through the app or export features, but supports encryption and sync&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Official sync&lt;/td&gt;
          &lt;td&gt;Obsidian Sync, paid&lt;/td&gt;
          &lt;td&gt;Joplin Cloud, paid&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Free sync&lt;/td&gt;
          &lt;td&gt;Requires third-party options such as iCloud, Git, Jianguoyun, Syncthing, etc.&lt;/td&gt;
          &lt;td&gt;Built-in support for sync targets such as OneDrive, Dropbox, WebDAV, and file system&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Core strengths&lt;/td&gt;
          &lt;td&gt;Backlinks, knowledge graph, plugin ecosystem, strong customization&lt;/td&gt;
          &lt;td&gt;Web clipping, end-to-end encryption, cross-platform sync, open source&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Organization style&lt;/td&gt;
          &lt;td&gt;Relationship network, backlinks, tags, folders&lt;/td&gt;
          &lt;td&gt;Notebooks, sub-notebooks, notes, tags&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Onboarding experience&lt;/td&gt;
          &lt;td&gt;Powerful, but easy to become more complex over time&lt;/td&gt;
          &lt;td&gt;Closer to traditional note apps and easier to start with&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;data-management-and-privacy&#34;&gt;Data Management and Privacy
&lt;/h2&gt;&lt;p&gt;Obsidian&amp;rsquo;s key idea is &amp;ldquo;files as data&amp;rdquo;. Your notes are ordinary &lt;code&gt;.md&lt;/code&gt; files stored directly in a local folder. Even if you stop using Obsidian in the future, you can still open those files with any text editor.&lt;/p&gt;
&lt;p&gt;This approach is intuitive, open, easy to back up, and suitable for Git-based management. The downside is that sync, attachment management, and multi-device consistency require more planning from the user.&lt;/p&gt;
&lt;p&gt;Joplin also uses Markdown syntax, but notes are managed by the app&amp;rsquo;s local database. Its advantage is a more complete application layer: notes, attachments, tags, and sync status are all handled by the app. Joplin also natively supports end-to-end encryption (E2EE), so when you sync through a third-party cloud drive, the cloud provider has a harder time reading note content directly.&lt;/p&gt;
&lt;p&gt;If you care more about &amp;ldquo;my notes are local files&amp;rdquo;, Obsidian feels more natural. If you care more about &amp;ldquo;the app helps me manage sync, encryption, and attachments&amp;rdquo;, Joplin is easier.&lt;/p&gt;
&lt;h2 id=&#34;sync-options-and-cost&#34;&gt;Sync Options and Cost
&lt;/h2&gt;&lt;p&gt;Obsidian&amp;rsquo;s official sync service is Obsidian Sync. It works well, but it is paid. If you want free sync between phone, tablet, and computer, you need to configure a third-party option such as iCloud, Git, Syncthing, Jianguoyun, or another WebDAV workflow. This is fine for people familiar with file sync, but it adds friction for beginners.&lt;/p&gt;
&lt;p&gt;Joplin&amp;rsquo;s sync leans more toward built-in capability. It supports Joplin Cloud, and it also supports OneDrive, Dropbox, WebDAV, file system sync, and other sync targets. Once an account or endpoint is configured, notes can sync across devices.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Need&lt;/th&gt;
          &lt;th&gt;Better Fit&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;You are willing to pay for official sync and want a low-friction experience&lt;/td&gt;
          &lt;td&gt;Either Obsidian Sync or Joplin Cloud works&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;You want free sync through third-party cloud storage&lt;/td&gt;
          &lt;td&gt;Joplin is more direct&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;You are familiar with Git / Syncthing / iCloud and do not mind tinkering&lt;/td&gt;
          &lt;td&gt;Obsidian also works very well&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;You want end-to-end encryption during sync&lt;/td&gt;
          &lt;td&gt;Joplin has it more built in&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;plugin-ecosystem-and-customization&#34;&gt;Plugin Ecosystem and Customization
&lt;/h2&gt;&lt;p&gt;Obsidian&amp;rsquo;s plugin ecosystem is one of its strongest parts. Through plugins, it can become a task board, flashcard tool, calendar, mind map, personal database, or even something close to a local knowledge system.&lt;/p&gt;
&lt;p&gt;Backlinks, reverse links, local graphs, and plugins like Dataview can gradually turn scattered notes into a knowledge network. For writing books, research, knowledge cards, and project material accumulation, this capability is very attractive.&lt;/p&gt;
&lt;p&gt;Joplin also supports plugins, themes, and some linking features, but its ecosystem and room for tinkering are not as rich as Obsidian&amp;rsquo;s. The upside is restraint: it is less likely to make users spend a lot of time changing themes, testing plugins, and redesigning the interface.&lt;/p&gt;
&lt;p&gt;If your goal is &amp;ldquo;deeply customize a knowledge management system&amp;rdquo;, Obsidian is stronger. If your goal is &amp;ldquo;stable note-taking, sync, and search&amp;rdquo;, Joplin is already enough.&lt;/p&gt;
&lt;h2 id=&#34;web-clipping&#34;&gt;Web Clipping
&lt;/h2&gt;&lt;p&gt;Web clipping is one of Joplin&amp;rsquo;s strengths. It provides an official Web Clipper that can save web pages, simplified article content, page screenshots, or links from the browser. For people who collect offline material, save technical articles, and organize web content, this is very practical.&lt;/p&gt;
&lt;p&gt;Obsidian&amp;rsquo;s native web clipping capability is relatively weak and usually depends on third-party browser extensions or other workflows. There are many available options, but the experience and stability depend on the plugin and the structure of each web page. Clipped content may also require manual formatting afterward.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Scenario&lt;/th&gt;
          &lt;th&gt;Better Fit&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Frequently saving web articles&lt;/td&gt;
          &lt;td&gt;Joplin&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Building an offline reference library&lt;/td&gt;
          &lt;td&gt;Joplin&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Occasionally saving web links&lt;/td&gt;
          &lt;td&gt;Both are fine&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Saving content and then heavily rewriting or linking it&lt;/td&gt;
          &lt;td&gt;Obsidian&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;organization-style-differences&#34;&gt;Organization Style Differences
&lt;/h2&gt;&lt;p&gt;Obsidian is more like a knowledge network built on top of local folders. You can organize with folders, but also with tags, backlinks, reverse links, and graphs. It is well suited to nonlinear notes and knowledge bases with complex relationships between topics.&lt;/p&gt;
&lt;p&gt;Joplin is closer to traditional note-taking software. It uses a hierarchy of notebooks, sub-notebooks, and notes, while also supporting tags. For people used to tools like Evernote, Youdao Cloud Notes, or OneNote, Joplin&amp;rsquo;s organization style feels more familiar.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Preference&lt;/th&gt;
          &lt;th&gt;Recommendation&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;You like folders + backlinks + graphs&lt;/td&gt;
          &lt;td&gt;Obsidian&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;You like notebooks + sub-notebooks + tags&lt;/td&gt;
          &lt;td&gt;Joplin&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Academic research, book writing, or Zettelkasten&lt;/td&gt;
          &lt;td&gt;Obsidian&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Reference collection, project notes, and web archiving&lt;/td&gt;
          &lt;td&gt;Joplin&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;which-one-should-you-choose&#34;&gt;Which One Should You Choose?
&lt;/h2&gt;&lt;p&gt;Choose Obsidian if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You are doing long-term research, writing a book, organizing course material, or building a personal knowledge base.&lt;/li&gt;
&lt;li&gt;You care about backlinks, reverse links, and knowledge graphs.&lt;/li&gt;
&lt;li&gt;You want to deeply customize the interface, hotkeys, plugins, and workflow.&lt;/li&gt;
&lt;li&gt;You are willing to spend time tuning sync, plugins, and file structure.&lt;/li&gt;
&lt;li&gt;You want notes to exist directly as local Markdown files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Choose Joplin if:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You want an open-source, cross-platform, sync-capable traditional notes app.&lt;/li&gt;
&lt;li&gt;You care about end-to-end encryption and data privacy.&lt;/li&gt;
&lt;li&gt;You often use web clipping to save articles.&lt;/li&gt;
&lt;li&gt;You do not want to pay for basic sync or spend time building a complex sync workflow.&lt;/li&gt;
&lt;li&gt;You are more comfortable with notebooks, sub-notebooks, and tags.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;short-conclusion&#34;&gt;Short Conclusion
&lt;/h2&gt;&lt;p&gt;Obsidian and Joplin are not a question of which one is absolutely better. They have different design goals.&lt;/p&gt;
&lt;p&gt;Obsidian is more like a highly customizable Markdown knowledge management platform. It suits people who enjoy building systems, working with backlinks, and playing with plugins. Its ceiling is high, but it can also make people enjoy building the system more than writing notes.&lt;/p&gt;
&lt;p&gt;Joplin is more like a traditional notes app that is open source, syncable, and encryptable. It suits people who want stable note-taking, web clipping, multi-device sync, and long-term preservation of material. It does not have Obsidian&amp;rsquo;s backlink ecosystem, but it is closer to a tool that lets you install it and start taking notes seriously.&lt;/p&gt;
&lt;p&gt;In one sentence: choose Obsidian if you want to build a second brain; choose Joplin if you want an open-source Evernote.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Joplin: An Offline-First Open-Source Notes App with Sync and Encryption</title>
        <link>https://knightli.com/en/2026/05/30/joplin-open-source-note-taking-app/</link>
        <pubDate>Sat, 30 May 2026 14:39:48 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/30/joplin-open-source-note-taking-app/</guid>
        <description>&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/laurent22/joplin&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Joplin&lt;/a&gt; is an open-source notes and to-do app for Windows, macOS, Linux, Android, and iOS. It is not just a lightweight memo app, but a knowledge management tool designed for storing many notes over the long term, syncing them across devices, and keeping as much control as possible in the user&amp;rsquo;s hands.&lt;/p&gt;
&lt;p&gt;Joplin notes use Markdown and support notebooks, tags, full-text search, attachments, to-dos, plugins, themes, and a browser Web Clipper. For people who want to move away from Evernote, or manage personal information in a more open format, it is a very common choice.&lt;/p&gt;
&lt;h2 id=&#34;what-problem-does-joplin-solve&#34;&gt;What Problem Does Joplin Solve?
&lt;/h2&gt;&lt;p&gt;Many note apps are convenient, but their data can easily become locked into a specific account, cloud service, or private format. Joplin takes a more open approach: it keeps complete data locally, stores note content in Markdown, and then syncs between devices through a sync target chosen by the user.&lt;/p&gt;
&lt;p&gt;It is suitable for several needs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You want to keep notes as Markdown over the long term.&lt;/li&gt;
&lt;li&gt;You want to sync notes between a computer and a phone.&lt;/li&gt;
&lt;li&gt;You want to import old Evernote notes and attachments.&lt;/li&gt;
&lt;li&gt;You want to use end-to-end encrypted sync.&lt;/li&gt;
&lt;li&gt;You want to extend the notes app with plugins and themes.&lt;/li&gt;
&lt;li&gt;You want to quickly clip web content into your own note library.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;core-features-at-a-glance&#34;&gt;Core Features at a Glance
&lt;/h2&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Feature&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Open source&lt;/td&gt;
          &lt;td&gt;Public repository, long-term maintenance, licensed under the AGPL-3.0 license&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Cross-platform&lt;/td&gt;
          &lt;td&gt;Supports Windows, macOS, Linux, Android, and iOS&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Markdown&lt;/td&gt;
          &lt;td&gt;Note bodies use Markdown, which helps with reading, migration, and long-term preservation&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Offline-first&lt;/td&gt;
          &lt;td&gt;Data is always stored locally, so notes can be viewed and edited without a network connection&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Sync&lt;/td&gt;
          &lt;td&gt;Supports multiple sync targets, including Joplin Cloud, Nextcloud, Dropbox, OneDrive, and others&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;End-to-end encryption&lt;/td&gt;
          &lt;td&gt;E2EE can be enabled during sync to reduce the risk of exposing content in cloud storage&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Import&lt;/td&gt;
          &lt;td&gt;Supports importing from Evernote and from normal Markdown files&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Extensions&lt;/td&gt;
          &lt;td&gt;Supports plugins, themes, and Web Clipper&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;what-does-offline-first-mean&#34;&gt;What Does Offline-First Mean?
&lt;/h2&gt;&lt;p&gt;The official Joplin README emphasizes that it is &amp;ldquo;offline first&amp;rdquo;. This means notes are not stored only in the cloud; they are saved on the local computer or phone. Even without a network connection, you can still open, search, and edit existing notes.&lt;/p&gt;
&lt;p&gt;This design matters a lot for a notes app. When the network is unstable, a sync service is temporarily unavailable, or an account service has problems, the complete data still exists locally. Sync keeps multiple devices consistent, but it does not make the entire experience depend on the cloud.&lt;/p&gt;
&lt;h2 id=&#34;markdown-and-import-capability&#34;&gt;Markdown and Import Capability
&lt;/h2&gt;&lt;p&gt;Joplin uses Markdown for notes, which makes it easier to migrate and back up than a fully proprietary format. Users can import normal Markdown files directly, and they can also import notes from Evernote.&lt;/p&gt;
&lt;p&gt;When importing from Evernote, Joplin tries to convert formatted content and preserve resources such as images and attachments. It also keeps metadata such as creation time, update time, and location when possible. For people with years of Evernote data, this matters much more than simply copying text.&lt;/p&gt;
&lt;p&gt;Still, no cross-app migration should be trusted as a one-click perfect process. Complex layouts, tables, attachments, internal links, and tag structures should be tested with a small sample first before migrating the full library.&lt;/p&gt;
&lt;h2 id=&#34;sync-and-encryption&#34;&gt;Sync and Encryption
&lt;/h2&gt;&lt;p&gt;Joplin supports several sync methods. Common choices include:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Sync Target&lt;/th&gt;
          &lt;th&gt;Suitable Scenario&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Joplin Cloud&lt;/td&gt;
          &lt;td&gt;You want the simplest official service&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Nextcloud&lt;/td&gt;
          &lt;td&gt;You already have a self-hosted cloud or team collaboration environment&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Dropbox&lt;/td&gt;
          &lt;td&gt;You are already used to Dropbox&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;OneDrive&lt;/td&gt;
          &lt;td&gt;You use the Microsoft ecosystem&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;File system / WebDAV, etc.&lt;/td&gt;
          &lt;td&gt;You want more control over the sync location&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Sync can be used together with end-to-end encryption. After it is enabled, note content is encrypted before being synced to the cloud, so the cloud service mostly stores encrypted data. This reduces the risk that a third-party cloud drive or sync service can expose note content.&lt;/p&gt;
&lt;p&gt;Encryption also adds management cost. Users need to keep passwords and recovery information properly; otherwise, old notes may become impossible to decrypt after changing devices or reinstalling the app.&lt;/p&gt;
&lt;h2 id=&#34;web-clipper-and-plugins&#34;&gt;Web Clipper and Plugins
&lt;/h2&gt;&lt;p&gt;Joplin also provides a browser Web Clipper for saving web pages and screenshots from browsers such as Chrome and Firefox. For people who collect reference material, clip web pages, or build research notes, this is a practical entry point.&lt;/p&gt;
&lt;p&gt;Plugins and themes make Joplin closer to an extensible platform than a fixed-function notes app. Users can expand editing, display, search, import, and export capabilities according to their own workflows.&lt;/p&gt;
&lt;h2 id=&#34;differences-from-obsidian&#34;&gt;Differences from Obsidian
&lt;/h2&gt;&lt;p&gt;Joplin and Obsidian are often compared by Markdown users, but they emphasize different things.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Dimension&lt;/th&gt;
          &lt;th&gt;Joplin&lt;/th&gt;
          &lt;th&gt;Obsidian&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Main positioning&lt;/td&gt;
          &lt;td&gt;Open-source notes and to-do app with built-in sync options and encryption&lt;/td&gt;
          &lt;td&gt;Local Markdown knowledge base focused on backlinks, plugins, and graphs&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Data organization&lt;/td&gt;
          &lt;td&gt;The app manages notebooks, tags, attachments, and database indexes&lt;/td&gt;
          &lt;td&gt;Works directly around folders and Markdown files&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Sync&lt;/td&gt;
          &lt;td&gt;Built-in sync targets and E2EE&lt;/td&gt;
          &lt;td&gt;Official sync is paid; third-party sync can also be configured manually&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Best suited for&lt;/td&gt;
          &lt;td&gt;People who want ready-to-use cross-device sync with privacy features&lt;/td&gt;
          &lt;td&gt;People who want a highly customized local file-based knowledge workflow&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If you want an &amp;ldquo;open-source Evernote + Markdown + encrypted sync&amp;rdquo; experience, Joplin is closer to that need. If you want to build a highly customized knowledge system around local Markdown files, Obsidian may feel smoother.&lt;/p&gt;
&lt;h2 id=&#34;who-is-joplin-for&#34;&gt;Who Is Joplin For?
&lt;/h2&gt;&lt;p&gt;Joplin is suitable for several types of users:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;People who want to migrate away from Evernote.&lt;/li&gt;
&lt;li&gt;Users who want to keep notes in Markdown.&lt;/li&gt;
&lt;li&gt;People who need sync across Windows, macOS, Linux, Android, and iOS.&lt;/li&gt;
&lt;li&gt;People who care about privacy and want end-to-end encryption.&lt;/li&gt;
&lt;li&gt;People who want note software that is open source, self-hostable, and easy to migrate away from over the long term.&lt;/li&gt;
&lt;li&gt;People who need web clipping and attachment management.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is not necessarily ideal for people who only want the simplest sticky-note tool. Joplin is fairly complete, and setting up sync, encryption, plugins, and imports still requires some time to understand.&lt;/p&gt;
&lt;h2 id=&#34;usage-suggestions&#34;&gt;Usage Suggestions
&lt;/h2&gt;&lt;p&gt;If you plan to try Joplin, start in this order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Create a test notebook on the desktop app first.&lt;/li&gt;
&lt;li&gt;Import a small Markdown or Evernote sample.&lt;/li&gt;
&lt;li&gt;Check whether images, attachments, tags, creation time, and formatting are normal.&lt;/li&gt;
&lt;li&gt;Then set up a sync target, such as Joplin Cloud, Nextcloud, Dropbox, or OneDrive.&lt;/li&gt;
&lt;li&gt;If you want to enable end-to-end encryption, first confirm that every device can sync and decrypt correctly.&lt;/li&gt;
&lt;li&gt;Finally, migrate the full note library.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is safer than importing years of notes in one go, and it makes it easier to discover formatting or sync problems before the formal migration.&lt;/p&gt;
&lt;h2 id=&#34;my-take&#34;&gt;My Take
&lt;/h2&gt;&lt;p&gt;Joplin&amp;rsquo;s strength is that it combines several important directions: Markdown, open source, cross-platform support, offline-first storage, sync, and end-to-end encryption. It is not just a Markdown editor, but more like a personal note system designed for long-term use.&lt;/p&gt;
&lt;p&gt;If you want note data to stay as open as possible, but do not want to assemble sync, encryption, and mobile apps entirely by yourself, Joplin is worth trying. It is especially suitable for users migrating from Evernote, caring about privacy, using multiple devices, and hoping their data can still be moved elsewhere in the future.&lt;/p&gt;
&lt;p&gt;Project link: &lt;a class=&#34;link&#34; href=&#34;https://github.com/laurent22/joplin&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;laurent22/joplin&lt;/a&gt;&lt;br&gt;
Official documentation: &lt;a class=&#34;link&#34; href=&#34;https://joplinapp.org/help/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Joplin documentation&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Jimmy: Convert Exports from Evernote, Notion, Google Keep, and More into Markdown</title>
        <link>https://knightli.com/en/2026/05/30/jimmy-note-conversion-tool-markdown/</link>
        <pubDate>Sat, 30 May 2026 11:55:56 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/30/jimmy-note-conversion-tool-markdown/</guid>
        <description>&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/marph91/jimmy&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Jimmy&lt;/a&gt; is a note conversion tool whose goal is to convert content from different note apps or document formats into Markdown. It is useful for people who want to move notes out of closed apps, import them into Obsidian or Joplin, or simply keep long-term archives as plain text.&lt;/p&gt;
&lt;p&gt;The project documentation is very direct: export or back up the original note app&amp;rsquo;s data, run &lt;code&gt;jimmy&lt;/code&gt; to convert it, then import the result into Joplin or Obsidian, or open it directly in a text editor such as VSCode.&lt;/p&gt;
&lt;h2 id=&#34;what-jimmy-solves&#34;&gt;What Jimmy Solves
&lt;/h2&gt;&lt;p&gt;Many note apps have their own export formats. When switching apps, the hardest part is often not the text itself, but images, attachments, tags, internal links, and structured metadata such as front matter.&lt;/p&gt;
&lt;p&gt;Jimmy tries to turn those exports into a more universal Markdown directory:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Convert note bodies to Markdown.&lt;/li&gt;
&lt;li&gt;Preserve images, resources, and attachments as much as possible.&lt;/li&gt;
&lt;li&gt;Preserve tags, external links, and internal note links where possible.&lt;/li&gt;
&lt;li&gt;Output Markdown + front matter.&lt;/li&gt;
&lt;li&gt;Make the result importable into Joplin, Obsidian, and similar tools, or readable directly in a text editor.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The point of this kind of tool is to reduce migration cost. Once notes become Markdown, they are no longer tightly bound to one app. Backup, search, version control, and LLM processing all become much easier.&lt;/p&gt;
&lt;h2 id=&#34;many-supported-note-apps&#34;&gt;Many Supported Note Apps
&lt;/h2&gt;&lt;p&gt;Jimmy supports a wide range of sources, including Anki, Anytype, Bear, CherryTree, ColorNote, Day One, Diaro, Drafts, Dynalist, Evernote, Google Docs, Google Keep, Joplin, Notion, Obsidian, OneNote, QOwnNotes, RedNotebook, Reflect, Roam Research, Signal, Simplenote, Standard Notes, Synology Note Station, Telegram, Tiddlywiki, Turtl, UpNote, Wordpress, Zim, Zoho Notebook, and more.&lt;/p&gt;
&lt;p&gt;Not every source has the same fidelity. In a real migration, you should still test with a small batch first and check images, attachments, tags, internal links, and date fields carefully.&lt;/p&gt;
&lt;h2 id=&#34;it-can-also-convert-regular-documents&#34;&gt;It Can Also Convert Regular Documents
&lt;/h2&gt;&lt;p&gt;Besides exports from note apps, Jimmy can also handle common document formats. The docs mention converting a single file or recursively converting an entire folder, which makes it useful for turning messy document directories into Markdown.&lt;/p&gt;
&lt;p&gt;Common supported formats include:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Type&lt;/th&gt;
          &lt;th&gt;Examples&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Office documents&lt;/td&gt;
          &lt;td&gt;DOCX, ODT, RTF&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Markup languages&lt;/td&gt;
          &lt;td&gt;Asciidoc, DocBook, Markdown, MediaWiki, reStructuredText&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Web and ebooks&lt;/td&gt;
          &lt;td&gt;HTML, MHTML, EPUB&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Data and structured files&lt;/td&gt;
          &lt;td&gt;CSV, OPML, Jupyter Notebook&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Other&lt;/td&gt;
          &lt;td&gt;PDF, EML, Fountain, txt2tags&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;If you only want to batch-convert DOCX, PDF, or HTML into Markdown, Jimmy can also work as an offline batch-processing tool.&lt;/p&gt;
&lt;h2 id=&#34;two-ways-to-use-it&#34;&gt;Two Ways to Use It
&lt;/h2&gt;&lt;p&gt;Jimmy provides both CLI and TUI interfaces.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Interface&lt;/th&gt;
          &lt;th&gt;Best For&lt;/th&gt;
          &lt;th&gt;Notes&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;CLI&lt;/td&gt;
          &lt;td&gt;Batch processing, scripts, full functionality&lt;/td&gt;
          &lt;td&gt;Suitable for converting folders, writing migration scripts, and specifying source formats&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;TUI&lt;/td&gt;
          &lt;td&gt;Interactive conversion&lt;/td&gt;
          &lt;td&gt;Suitable for manual operation; currently a beta subset of the full functionality&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The official README gives these Linux examples:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Convert with the interactive TUI&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jimmy-linux tui
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Convert a single file supported by pandoc&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jimmy-linux cli libre_office_document.odt
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Convert an entire folder&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jimmy-linux cli path/to/folder
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Convert a Google Keep export&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;jimmy-linux cli takeout-20240401T160516Z-001.zip --format google_keep
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;These commands show that Jimmy is not only for one note app. It puts &amp;ldquo;note export packages&amp;rdquo; and &amp;ldquo;regular document folders&amp;rdquo; into the same conversion workflow.&lt;/p&gt;
&lt;h2 id=&#34;main-characteristics&#34;&gt;Main Characteristics
&lt;/h2&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Feature&lt;/th&gt;
          &lt;th&gt;Description&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Offline execution&lt;/td&gt;
          &lt;td&gt;Conversion does not depend on cloud services, which is useful for private notes&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Open source&lt;/td&gt;
          &lt;td&gt;The repository uses the GPL-3.0 license&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Cross-platform&lt;/td&gt;
          &lt;td&gt;Official downloads are available for Linux, Windows, and macOS&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Standalone binary&lt;/td&gt;
          &lt;td&gt;Users do not need to install Docker, Python, or Node.js&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;No AI used&lt;/td&gt;
          &lt;td&gt;Conversion does not call AI, making results more controllable and reducing privacy concerns&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Markdown + front matter&lt;/td&gt;
          &lt;td&gt;Easy to import into note apps and later manage with Git&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&amp;ldquo;Offline&amp;rdquo; and &amp;ldquo;no AI&amp;rdquo; are especially fitting for note migration. Notes often contain private information, work materials, and old attachments. Keeping conversion local makes the risk boundary clearer.&lt;/p&gt;
&lt;h2 id=&#34;who-should-use-it&#34;&gt;Who Should Use It
&lt;/h2&gt;&lt;p&gt;Jimmy is useful for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Users migrating from Evernote, Notion, OneNote, Google Keep, and similar tools to Markdown.&lt;/li&gt;
&lt;li&gt;People importing notes into Obsidian, Joplin, or another plain-text workflow.&lt;/li&gt;
&lt;li&gt;People who want to preserve long-term materials in a format that will be easier to read in the future.&lt;/li&gt;
&lt;li&gt;People preparing notes or documents as text that LLMs can process.&lt;/li&gt;
&lt;li&gt;People who need to recursively convert folders of DOCX, PDF, HTML, ODT, and similar files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It may not be for users who expect &amp;ldquo;one-click perfect migration&amp;rdquo;. Export formats vary greatly between note apps, and complex pages, databases, embeds, and internal links may still need manual review.&lt;/p&gt;
&lt;h2 id=&#34;pre-migration-checklist&#34;&gt;Pre-Migration Checklist
&lt;/h2&gt;&lt;p&gt;Before doing a real migration, it is better to follow this order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Export a small sample from the original note app.&lt;/li&gt;
&lt;li&gt;Convert the sample with Jimmy instead of converting everything immediately.&lt;/li&gt;
&lt;li&gt;Check Markdown body text, images, attachments, tags, creation time, and internal links.&lt;/li&gt;
&lt;li&gt;Confirm that the target app, such as Obsidian or Joplin, recognizes the directory structure and front matter correctly.&lt;/li&gt;
&lt;li&gt;Convert the full export package.&lt;/li&gt;
&lt;li&gt;Keep both the original export and converted result until you have verified everything.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This is a bit slower, but it avoids discovering missing attachments, broken links, or wrong tag structure only after the migration is done.&lt;/p&gt;
&lt;h2 id=&#34;my-take&#34;&gt;My Take
&lt;/h2&gt;&lt;p&gt;Jimmy is useful because it turns note migration from &amp;ldquo;relying on one app&amp;rsquo;s importer&amp;rdquo; into &amp;ldquo;convert to universal Markdown first&amp;rdquo;. It supports many sources, and its output is general enough to help free a personal knowledge base from closed formats.&lt;/p&gt;
&lt;p&gt;If you only export one or two notes occasionally, you may not need it. But if you have years of notes, attachments, and document folders and want to move to Obsidian, Joplin, or a Git-managed Markdown workflow, Jimmy is worth trying. It is best used as a migration middle layer: first turn data into readable, backup-friendly, batch-processable text, then decide which note system should own it.&lt;/p&gt;
&lt;p&gt;Project link: &lt;a class=&#34;link&#34; href=&#34;https://github.com/marph91/jimmy&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;marph91/jimmy&lt;/a&gt;&lt;br&gt;
Documentation: &lt;a class=&#34;link&#34; href=&#34;https://marph91.github.io/jimmy/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Jimmy - Note Conversion Tool&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Google Pay and Wallet Launch Developer MCP Server: Bringing Payment Integration Into AI Assistants</title>
        <link>https://knightli.com/en/2026/05/29/google-pay-wallet-developer-mcp-server/</link>
        <pubDate>Fri, 29 May 2026 15:24:18 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/29/google-pay-wallet-developer-mcp-server/</guid>
        <description>&lt;p&gt;Google Developers has released the Google Pay and Wallet Developer MCP Server. Built for developers integrating the Google Pay API and Google Wallet API, it connects official documentation, account status, integration checks, and some business metrics to MCP-compatible AI development tools.&lt;/p&gt;
&lt;p&gt;This kind of update may not look as flashy as a model launch, but it is very practical for developers. Payment and wallet integrations are often less about whether someone can write the code and more about dense documentation, many configuration items, review requirements, and scattered error feedback. The value of an MCP Server is that it lets an AI assistant help developers troubleshoot from a position much closer to the real context.&lt;/p&gt;
&lt;h2 id=&#34;what-problem-it-solves&#34;&gt;What Problem It Solves
&lt;/h2&gt;&lt;p&gt;When developers integrate Google Pay or Google Wallet, they usually have to switch back and forth across several places:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Checking official documentation and sample code&lt;/li&gt;
&lt;li&gt;Confirming account and merchant configuration&lt;/li&gt;
&lt;li&gt;Inspecting request parameters and returned errors&lt;/li&gt;
&lt;li&gt;Verifying whether the integration meets requirements&lt;/li&gt;
&lt;li&gt;Observing call performance and key metrics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If these resources are treated only as web documentation, an AI assistant can mostly explain concepts or generate examples. After connecting to an MCP Server, the assistant can access more specific information through tools and provide suggestions that are closer to the current project state.&lt;/p&gt;
&lt;h2 id=&#34;why-mcp-fits-here&#34;&gt;Why MCP Fits Here
&lt;/h2&gt;&lt;p&gt;MCP provides standardized tool interfaces for AI applications. For developer products such as Google Pay and Wallet, it is especially well suited to tasks that combine documentation, status, and validation.&lt;/p&gt;
&lt;p&gt;For example, developers can ask an MCP-capable AI tool to help answer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Which configuration items are missing from the current integration&lt;/li&gt;
&lt;li&gt;Why a particular Google Pay request failed&lt;/li&gt;
&lt;li&gt;Which fields in a Wallet pass definition may not meet the requirements&lt;/li&gt;
&lt;li&gt;How a code sample should be adapted to the current business need&lt;/li&gt;
&lt;li&gt;Which items still need to be checked before the integration goes live&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These questions are risky if answered only from a large model&amp;rsquo;s memory. When the answer can combine official tools with current account information, it becomes much more actionable.&lt;/p&gt;
&lt;h2 id=&#34;what-it-means-for-ai-coding-workflows&#34;&gt;What It Means for AI Coding Workflows
&lt;/h2&gt;&lt;p&gt;This release also points to a trend: AI coding assistants are moving from &amp;ldquo;reading code&amp;rdquo; to &amp;ldquo;reading product systems.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;In the past, when developers asked AI to help integrate payment capabilities, they usually had to paste in documentation snippets, error logs, and code. AI could explain them, but it did not necessarily know the real state of the current integration. MCP Server pushes that capability one step forward, giving AI assistants a chance to work directly around the product integration environment.&lt;/p&gt;
&lt;p&gt;This is especially valuable in several scenarios:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A new project integrates Google Pay or Wallet for the first time.&lt;/li&gt;
&lt;li&gt;An old project migrates to a new API or configuration approach.&lt;/li&gt;
&lt;li&gt;The team performs integration checks before launch.&lt;/li&gt;
&lt;li&gt;The team needs to quickly locate issues involving error codes, review problems, or configuration mismatches.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For teams, the benefit is not just reading a few fewer pages of documentation. It is reducing the friction of &amp;ldquo;the documentation was understood correctly, but the live configuration does not match.&amp;rdquo;&lt;/p&gt;
&lt;h2 id=&#34;it-will-not-replace-developer-judgment&#34;&gt;It Will Not Replace Developer Judgment
&lt;/h2&gt;&lt;p&gt;Payment and wallet integrations involve security, compliance, and user experience requirements. MCP Server can help AI assistants find information faster, check status, and generate suggestions, but developers still need to confirm the code, security strategy, merchant configuration, and launch process.&lt;/p&gt;
&lt;p&gt;This is especially true for payment flows. A seemingly reasonable AI suggestion should not be pushed directly to production. A more reliable approach is to treat MCP tools as inspectors and navigators: they can shorten the time needed to locate a problem, but they cannot replace review, testing, or business responsibility.&lt;/p&gt;
&lt;h2 id=&#34;my-take&#34;&gt;My Take
&lt;/h2&gt;&lt;p&gt;The significance of the Google Pay and Wallet Developer MCP Server is not that there is &amp;ldquo;one more MCP example.&amp;rdquo; It is that MCP has been placed inside a real, complex, highly constrained developer scenario.&lt;/p&gt;
&lt;p&gt;If MCP only connects to documentation, its value is limited. If it can connect to account status, integration validation, metrics, and product backends, AI assistants can take on more practical development work. Google&amp;rsquo;s release shows exactly that direction.&lt;/p&gt;
&lt;p&gt;Similar capabilities are likely to appear in more cloud services, advertising platforms, payment systems, and enterprise SaaS products in the future. Developers need to adapt not just to &amp;ldquo;AI can write code,&amp;rdquo; but to &amp;ldquo;AI can participate in the entire integration process through standardized tool interfaces.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Original link: &lt;a class=&#34;link&#34; href=&#34;https://developers.googleblog.com/supercharge-your-integration-workflow-with-the-google-pay-wallet-developer-mcp-server/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Supercharge your integration workflow with the Google Pay &amp;amp; Wallet Developer MCP Server&lt;/a&gt;&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Remotion: Generate Videos Programmatically with React</title>
        <link>https://knightli.com/en/2026/05/27/remotion-react-programmatic-video-generation/</link>
        <pubDate>Wed, 27 May 2026 14:39:22 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/27/remotion-react-programmatic-video-generation/</guid>
        <description>&lt;p&gt;&lt;code&gt;remotion-dev/remotion&lt;/code&gt; is a framework for creating videos programmatically with React. It pulls video production out of traditional timeline tools and turns it into a frontend engineering problem that can be controlled with components, state, data, API, CSS, Canvas, SVG, WebGL, and algorithms.&lt;/p&gt;
&lt;p&gt;Project address: &lt;a class=&#34;link&#34; href=&#34;https://github.com/remotion-dev/remotion&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;remotion-dev/remotion&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This kind of tool fits today&amp;rsquo;s AI coding workflows very well: if an agent can generate web pages, charts, and data views, it can also keep going and generate video scripts, animation components, and renderable short films.&lt;/p&gt;
&lt;h2 id=&#34;what-problem-does-remotion-solve&#34;&gt;What Problem Does Remotion Solve
&lt;/h2&gt;&lt;p&gt;Traditional video tools are good at manual editing, but not at scale, parameterization, or automation.&lt;/p&gt;
&lt;p&gt;For example, these tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Generate a personalized annual recap video for each user&lt;/li&gt;
&lt;li&gt;Automatically generate product demo videos from a database&lt;/li&gt;
&lt;li&gt;Combine charts, code snippets, and explanatory subtitles into technical short videos&lt;/li&gt;
&lt;li&gt;Batch-generate marketing assets, social media short videos, or course clips&lt;/li&gt;
&lt;li&gt;Render videos on demand through CI/CD or backend services&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With traditional editing software, these tasks are hard to fully automate. Remotion&amp;rsquo;s approach is to write video as a React application: every frame is the result of components and data at a specific point in time.&lt;/p&gt;
&lt;h2 id=&#34;why-react&#34;&gt;Why React
&lt;/h2&gt;&lt;p&gt;The reason given in the Remotion README is straightforward: React can reuse Web technologies and component-based development.&lt;/p&gt;
&lt;p&gt;It lets you use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CSS for layout and animation&lt;/li&gt;
&lt;li&gt;SVG for vector graphics&lt;/li&gt;
&lt;li&gt;Canvas and WebGL for complex drawing&lt;/li&gt;
&lt;li&gt;JavaScript / TypeScript for variables, functions, API calls, math, and algorithms&lt;/li&gt;
&lt;li&gt;React components for reuse, composition, and fast iteration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This means frontend developers do not need to learn an entirely unfamiliar video DSL from scratch. Many existing UI pieces, charts, design systems, and data logic can be moved into video generation scenarios.&lt;/p&gt;
&lt;h2 id=&#34;quick-start&#34;&gt;Quick Start
&lt;/h2&gt;&lt;p&gt;If Node.js is already installed, the entry command given in the README is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx create-video@latest
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;After creating a project, you typically write React components to describe the scene, then let Remotion render the video frame by frame.&lt;/p&gt;
&lt;p&gt;For more complete documentation, see:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Docs: &lt;a class=&#34;link&#34; href=&#34;https://www.remotion.dev/docs&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;remotion.dev/docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;API Reference: &lt;a class=&#34;link&#34; href=&#34;https://www.remotion.dev/api&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;remotion.dev/api&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;what-scenarios-is-it-good-for&#34;&gt;What Scenarios Is It Good For
&lt;/h2&gt;&lt;p&gt;Remotion is best suited to scenarios where &amp;ldquo;video content is driven by data or code.&amp;rdquo;&lt;/p&gt;
&lt;h3 id=&#34;personalized-videos&#34;&gt;Personalized Videos
&lt;/h3&gt;&lt;p&gt;Examples include annual recaps, user achievements, order summaries, and learning reports. Each user&amp;rsquo;s data is different, but the visual structure is the same. Using React components plus data-driven rendering feels more natural than manual editing.&lt;/p&gt;
&lt;h3 id=&#34;technical-demo-videos&#34;&gt;Technical Demo Videos
&lt;/h3&gt;&lt;p&gt;If a video contains code, charts, product interfaces, step animations, and explanatory text, Remotion is well suited to organizing these elements into templates that can be rendered repeatedly.&lt;/p&gt;
&lt;h3 id=&#34;data-videos-and-chart-animations&#34;&gt;Data Videos and Chart Animations
&lt;/h3&gt;&lt;p&gt;Data visualization is already a frontend strength. Remotion lets charts appear not only on web pages, but also enter videos along a timeline.&lt;/p&gt;
&lt;h3 id=&#34;ai-generated-video-workflows&#34;&gt;AI-Generated Video Workflows
&lt;/h3&gt;&lt;p&gt;An AI agent can first generate scripts and asset structures, then generate Remotion components, and finally render the video. This is more controllable than asking a model to directly generate the final video, because the intermediate artifact is code that can be inspected, edited, versioned, and reused.&lt;/p&gt;
&lt;h2 id=&#34;why-it-matters-for-ai-coding-tools&#34;&gt;Why It Matters for AI Coding Tools
&lt;/h2&gt;&lt;p&gt;Remotion is especially interesting for AI coding tools such as Codex, Claude Code, Cursor, and Gemini CLI.&lt;/p&gt;
&lt;p&gt;The reason is that video generation is broken down into development tasks:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Generate React components.&lt;/li&gt;
&lt;li&gt;Adjust styles and layout.&lt;/li&gt;
&lt;li&gt;Connect data.&lt;/li&gt;
&lt;li&gt;Preview the scene.&lt;/li&gt;
&lt;li&gt;Modify based on feedback.&lt;/li&gt;
&lt;li&gt;Render the output.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This workflow is a very good fit for agents: every step has files, code, a preview, and clear feedback. Compared with &amp;ldquo;directly generating a video file,&amp;rdquo; code-based video is easier to review and iterate on.&lt;/p&gt;
&lt;p&gt;Combined with browser sidebars, screenshot inspection, automated rendering, and comment feedback, Remotion can become the video artifact layer inside an AI workflow.&lt;/p&gt;
&lt;h2 id=&#34;check-the-license-before-use&#34;&gt;Check the License Before Use
&lt;/h2&gt;&lt;p&gt;The Remotion README specifically notes that Remotion has a special license, and that certain company usage scenarios require a company license.&lt;/p&gt;
&lt;p&gt;So do not treat it as just another small MIT utility. License requirements may differ for personal projects, open-source projects, commercial projects, and internal enterprise tools. Before using it in company production, you should first read its LICENSE page and official licensing notes.&lt;/p&gt;
&lt;p&gt;This is important, especially when connecting Remotion to automated content generation, marketing asset generation, or internal enterprise video pipelines.&lt;/p&gt;
&lt;h2 id=&#34;my-take&#34;&gt;My Take
&lt;/h2&gt;&lt;p&gt;Remotion&amp;rsquo;s value is not just &amp;ldquo;making videos with React&amp;rdquo;; it is turning video into something programmable, reusable, and automatable.&lt;/p&gt;
&lt;p&gt;For ordinary frontend teams, it is suitable for data-driven video templates. For AI tools, it is more like a stable output target: the model does not need to generate a black-box video in one shot, but can instead generate readable, editable, renderable React code.&lt;/p&gt;
&lt;p&gt;If your content needs batch generation, personalization, updates based on data, or repeated visual adjustments by an agent, Remotion is worth putting into the toolbox. It is not a replacement for traditional editing software, but a way to connect video production to a software engineering workflow.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>CLIProxyAPI Management Center: A Visual Admin Console for CLIProxyAPI</title>
        <link>https://knightli.com/en/2026/05/24/cliproxyapi-management-center/</link>
        <pubDate>Sun, 24 May 2026 10:05:15 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/24/cliproxyapi-management-center/</guid>
        <description>&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/router-for-me/Cli-Proxy-API-Management-Center&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Cli-Proxy-API-Management-Center&lt;/a&gt; can be understood as the cockpit for CLIProxyAPI.&lt;/p&gt;
&lt;p&gt;In the previous article, &lt;a class=&#34;link&#34; href=&#34;https://github.com/router-for-me/CLIProxyAPI&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;CLIProxyAPI&lt;/a&gt; was the service that proxies Gemini CLI, Codex, Claude Code, OpenRouter, and other capabilities into unified APIs. This Management Center solves a different problem:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Once the proxy service is running, should configuration, accounts, OAuth, logs, quotas, and credentials all be managed by manually editing files and scrolling through terminals?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;It provides a web management interface so you can manage CLIProxyAPI configuration and runtime state from a browser.&lt;/p&gt;
&lt;h2 id=&#34;what-it-is&#34;&gt;What It Is
&lt;/h2&gt;&lt;p&gt;According to the project description, Cli-Proxy-API-Management-Center is an independent management frontend for CLIProxyAPI. Its core features include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual editing for CLIProxyAPI configuration.&lt;/li&gt;
&lt;li&gt;Uploading and managing authentication files such as &lt;code&gt;auth.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Viewing request logs and model response logs.&lt;/li&gt;
&lt;li&gt;Managing OAuth authentication flows.&lt;/li&gt;
&lt;li&gt;Checking Gemini CLI account quotas.&lt;/li&gt;
&lt;li&gt;Providing daily maintenance entry points for accounts, configuration, logs, and related tasks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The official repository also notes that newer versions of CLIProxyAPI already include this management interface, accessible directly through &lt;code&gt;/management.html&lt;/code&gt;. The standalone repository remains useful for people who need separate deployment or secondary development.&lt;/p&gt;
&lt;p&gt;That point matters. Most ordinary users may not need to deploy this repository separately. First check whether your CLIProxyAPI version already ships with the management page.&lt;/p&gt;
&lt;h2 id=&#34;it-manages-the-entry-point-not-the-model-call-itself&#34;&gt;It Manages the Entry Point, Not the Model Call Itself
&lt;/h2&gt;&lt;p&gt;The hard part of CLIProxyAPI is not only forwarding a request to a model.&lt;/p&gt;
&lt;p&gt;The real trouble is in things like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to put multiple Gemini, OpenAI, Claude, and Codex accounts into a pool.&lt;/li&gt;
&lt;li&gt;Which account has expired, and which account is close to its quota limit.&lt;/li&gt;
&lt;li&gt;How to import, refresh, and troubleshoot OAuth login states.&lt;/li&gt;
&lt;li&gt;How to edit configuration files without missing commas or fields.&lt;/li&gt;
&lt;li&gt;Which provider, model, and account a request actually used.&lt;/li&gt;
&lt;li&gt;Whether a failed request came from an upstream issue, a protocol issue, or local configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is where Management Center is useful: it turns daily maintenance of proxy infrastructure into visual operations.&lt;/p&gt;
&lt;p&gt;If you only run one account locally and call the API occasionally, it may not be essential. But once you start using multiple accounts, multiple models, and multiple client integrations, a backend UI becomes noticeably easier to live with.&lt;/p&gt;
&lt;h2 id=&#34;typical-use-cases&#34;&gt;Typical Use Cases
&lt;/h2&gt;&lt;p&gt;First: managing account pools.&lt;/p&gt;
&lt;p&gt;CLIProxyAPI supports multi-account rotation and load balancing, but the more accounts you have, the less suitable manual configuration-file editing becomes. The management center helps you view account state, import credentials, and troubleshoot abnormal accounts.&lt;/p&gt;
&lt;p&gt;Second: troubleshooting failed requests.&lt;/p&gt;
&lt;p&gt;When a client reports an error, you need to know whether the request reached the proxy, which provider it used, and what error came back. A log UI is much more comfortable than searching through terminal output.&lt;/p&gt;
&lt;p&gt;Third: handling OAuth.&lt;/p&gt;
&lt;p&gt;Tools such as Codex, Claude Code, and Gemini CLI often involve OAuth login state. Management Center provides OAuth-related operation entry points, reducing repeated command-line work.&lt;/p&gt;
&lt;p&gt;Fourth: internal team usage.&lt;/p&gt;
&lt;p&gt;If CLIProxyAPI becomes a shared team gateway, administrators need an interface for quickly checking configuration and state. Otherwise, every change requires logging into a server and editing files, which is inefficient and error-prone.&lt;/p&gt;
&lt;h2 id=&#34;how-it-relates-to-cliproxyapi&#34;&gt;How It Relates to CLIProxyAPI
&lt;/h2&gt;&lt;p&gt;You can think of the two pieces as separate layers:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Client / IDE / Script
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        v
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CLIProxyAPI: protocol proxy, account pool, model routing
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        v
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Gemini CLI / Codex / Claude Code / OpenRouter / upstream models
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Management Center is not in the core inference request path. It is more like an operations panel:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Browser
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  v
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Management Center: edit config, view logs, manage accounts, check quotas
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  |
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  v
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;CLIProxyAPI admin APIs / config / logs / credentials
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;So do not treat it as another model proxy. It is a tool for managing CLIProxyAPI, not a replacement for CLIProxyAPI.&lt;/p&gt;
&lt;h2 id=&#34;why-the-standalone-repository-still-matters&#34;&gt;Why the Standalone Repository Still Matters
&lt;/h2&gt;&lt;p&gt;Since CLIProxyAPI already includes &lt;code&gt;/management.html&lt;/code&gt;, why pay attention to the standalone repository?&lt;/p&gt;
&lt;p&gt;There are three main reasons.&lt;/p&gt;
&lt;p&gt;First, the standalone repository makes the management center&amp;rsquo;s boundaries easier to inspect. You can see what belongs to the frontend, and what must be provided by CLIProxyAPI backend APIs.&lt;/p&gt;
&lt;p&gt;Second, if you want secondary development, such as changing the UI, adding authentication, or integrating your own monitoring system, the standalone repository is a better entry point.&lt;/p&gt;
&lt;p&gt;Third, if your deployment environment is unusual, such as separate frontend and backend hosting, a dedicated management domain, or static assets served through an internal gateway, the standalone version is more flexible.&lt;/p&gt;
&lt;p&gt;For ordinary individual users, the built-in CLIProxyAPI version is usually enough. For teams or deep customization, the standalone repository is more meaningful.&lt;/p&gt;
&lt;h2 id=&#34;what-to-watch-during-deployment&#34;&gt;What to Watch During Deployment
&lt;/h2&gt;&lt;p&gt;The admin console touches sensitive things: accounts, OAuth, API keys, logs, request contents, and upstream quotas.&lt;/p&gt;
&lt;p&gt;So the first rule is: do not expose the management page directly to the public internet.&lt;/p&gt;
&lt;p&gt;Safer options include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Allow only local access, such as binding to &lt;code&gt;127.0.0.1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If remote access is necessary, put it behind a VPN, Tailscale, an internal jump host, or an authenticated reverse proxy.&lt;/li&gt;
&lt;li&gt;Add authentication to admin endpoints. Do not rely on &amp;ldquo;nobody knows the URL&amp;rdquo;.&lt;/li&gt;
&lt;li&gt;Avoid exposing full keys, cookies, OAuth tokens, and raw user requests in logs.&lt;/li&gt;
&lt;li&gt;In team environments, separate people who can call the API from people who can change configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many proxy-tool incidents do not come from model call failures. They come from unprotected admin endpoints, logs, and credential files.&lt;/p&gt;
&lt;h2 id=&#34;what-to-use-it-with&#34;&gt;What to Use It With
&lt;/h2&gt;&lt;p&gt;If you only deploy CLIProxyAPI, a management center already solves basic maintenance needs.&lt;/p&gt;
&lt;p&gt;If you care more about statistics and observability, you can also combine it with other tools in the CLIProxyAPI ecosystem:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CPA Usage Keeper: focused on usage syncing and SQLite storage.&lt;/li&gt;
&lt;li&gt;CLIProxyAPI Usage Dashboard: focused on local-first usage, quota, and chart views.&lt;/li&gt;
&lt;li&gt;CPA-Manager: a heavier management center for request monitoring, cost estimation, account inspection, and abnormal account cleanup suggestions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A simple way to understand the division:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Management Center handles configuration and daily maintenance.&lt;/li&gt;
&lt;li&gt;Usage Dashboard handles usage and quota visibility.&lt;/li&gt;
&lt;li&gt;CPA-Manager handles heavier operations and inspections.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Which one to use depends on your deployment size. A personal local setup does not need the whole suite.&lt;/p&gt;
&lt;h2 id=&#34;usage-suggestions&#34;&gt;Usage Suggestions
&lt;/h2&gt;&lt;p&gt;If you are just starting with CLIProxyAPI, try this order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;First get CLIProxyAPI itself running and confirm the API responds normally.&lt;/li&gt;
&lt;li&gt;Open the built-in &lt;code&gt;/management.html&lt;/code&gt; and check whether configuration and logs can be read.&lt;/li&gt;
&lt;li&gt;Import one account or one provider, and confirm the management UI reflects the state change.&lt;/li&gt;
&lt;li&gt;If you need public access, add authentication and network isolation before exposing the entry point.&lt;/li&gt;
&lt;li&gt;After the number of accounts and requests grows, add usage statistics and more complete management tools.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Do not connect every account, every provider, and every management component at once from the beginning. Proxy and account-pool projects are much easier to verify in small steps.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Cli-Proxy-API-Management-Center has a clear role: it is not a model, not a chat client, and not a new API gateway. It is the visual management layer for CLIProxyAPI.&lt;/p&gt;
&lt;p&gt;When CLIProxyAPI is just a small local tool, you can ignore it. When CLIProxyAPI starts carrying multiple accounts, multiple models, and multiple client integrations, it becomes a very useful console.&lt;/p&gt;
&lt;p&gt;The real thing to watch is the security boundary. The admin backend can modify configuration, view logs, and touch credentials. If exposed incorrectly, its risk is higher than an ordinary API calling endpoint. Keep it in a trusted network, protect it with authentication, and then enjoy the convenience of visual management.&lt;/p&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/router-for-me/Cli-Proxy-API-Management-Center&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;router-for-me/Cli-Proxy-API-Management-Center GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/router-for-me/CLIProxyAPI&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;router-for-me/CLIProxyAPI GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.router-for.me/cn/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;CLIProxyAPI official documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>CLIProxyAPI: Wrapping Codex, Claude Code, and Gemini CLI into a Unified API</title>
        <link>https://knightli.com/en/2026/05/24/cliproxyapi-cli-to-api-gateway/</link>
        <pubDate>Sun, 24 May 2026 10:03:33 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/24/cliproxyapi-cli-to-api-gateway/</guid>
        <description>&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/router-for-me/CLIProxyAPI&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;CLIProxyAPI&lt;/a&gt; is a very practical, community-engineering kind of project. It is not another large model, and it is not merely an API forwarder. Instead, it repackages a set of AI tools that are originally interactive, CLI-oriented, or OAuth-login-oriented into a unified API service.&lt;/p&gt;
&lt;p&gt;It supports Gemini CLI, OpenAI Codex, Claude Code, Amp CLI, AI Studio Build, and upstream OpenAI-compatible services. In plain terms, it tries to answer this question:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I have CLI tools, subscription accounts, and OAuth login sessions. Can I connect these capabilities to my own client, scripts, IDE, or internal services just like calling a normal API?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;CLIProxyAPI&amp;rsquo;s answer is yes: put a proxy layer in the middle and translate CLI capabilities from different sources into OpenAI-, Gemini-, Claude-, and Codex-compatible interfaces.&lt;/p&gt;
&lt;h2 id=&#34;the-real-pain-point-it-solves&#34;&gt;The Real Pain Point It Solves
&lt;/h2&gt;&lt;p&gt;Many AI coding tools are powerful, but their default usage patterns are not automation-friendly.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gemini CLI can log in with an account, but your program may prefer calling an HTTP API.&lt;/li&gt;
&lt;li&gt;Claude Code is excellent for interactive coding, but integrating it into other clients can run into protocol mismatches.&lt;/li&gt;
&lt;li&gt;Codex CLI supports OAuth login and Responses-style capabilities, but not every upper-layer tool knows how to talk to it.&lt;/li&gt;
&lt;li&gt;A team may have multiple accounts and need rotation, load balancing, unhealthy account removal, and quota visibility.&lt;/li&gt;
&lt;li&gt;You may want some tools to see only an OpenAI-style interface, while the backend is actually Gemini, Claude, or Codex.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;CLIProxyAPI is positioned as the protocol adaptation layer between these tools and your clients.&lt;/p&gt;
&lt;p&gt;It hides the complex side behind the scenes: OAuth, CLI login, multiple accounts, different protocols, and different providers. On the front side, it exposes familiar interfaces such as OpenAI Chat Completions, OpenAI Responses, Gemini, Claude Messages, and Codex-related endpoints.&lt;/p&gt;
&lt;h2 id=&#34;capability-overview&#34;&gt;Capability Overview
&lt;/h2&gt;&lt;p&gt;According to the official README and documentation, CLIProxyAPI currently focuses on:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Providing OpenAI-, Gemini-, Claude-, and Codex-compatible API endpoints for CLI models.&lt;/li&gt;
&lt;li&gt;Connecting OpenAI Codex and Claude Code through OAuth login.&lt;/li&gt;
&lt;li&gt;Supporting streaming and non-streaming responses, plus WebSocket in some scenarios.&lt;/li&gt;
&lt;li&gt;Supporting function calling, tool calling, and multimodal input.&lt;/li&gt;
&lt;li&gt;Supporting multi-account rotation and load balancing for Gemini, OpenAI, and Claude.&lt;/li&gt;
&lt;li&gt;Supporting Gemini AI Studio API keys.&lt;/li&gt;
&lt;li&gt;Supporting account pools for AI Studio Build, Gemini CLI, Claude Code, and OpenAI Codex.&lt;/li&gt;
&lt;li&gt;Connecting OpenAI-compatible upstreams through configuration, such as OpenRouter.&lt;/li&gt;
&lt;li&gt;Providing a Go SDK so the proxy capability can be embedded into your own services.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The most valuable part of this kind of project is not that it supports a few more model names. It is that it packages account login, protocol translation, and request routing into one operational layer.&lt;/p&gt;
&lt;h2 id=&#34;who-it-is-for&#34;&gt;Who It Is For
&lt;/h2&gt;&lt;p&gt;CLIProxyAPI is better suited to several groups of users.&lt;/p&gt;
&lt;p&gt;The first group is heavy AI coding users. You already use Codex, Claude Code, and Gemini CLI, but you want to connect them to Cursor, Cline, RooCode, Amp, internal scripts, or custom workflows.&lt;/p&gt;
&lt;p&gt;The second group is people with multiple account pools. For example, you may have several Gemini, OpenAI, or Claude login sessions and do not want to switch manually. You want automatic rotation, balanced usage, and quick troubleshooting when an account becomes abnormal.&lt;/p&gt;
&lt;p&gt;The third group is people building internal team gateways. The team may not want every client to separately adapt to Gemini, Claude, and Codex. Instead, it wants one middle layer that exposes a unified API.&lt;/p&gt;
&lt;p&gt;The fourth group is people who like working with protocols. You may care how Responses, Chat Completions, Claude Messages, and Gemini v1beta interfaces can be converted between one another, or you may want to switch backends from the same client.&lt;/p&gt;
&lt;p&gt;If you only ask AI a few questions occasionally, or only use the official apps for chat, the deployment and maintenance cost of CLIProxyAPI may feel heavy.&lt;/p&gt;
&lt;h2 id=&#34;how-it-differs-from-a-regular-api-proxy&#34;&gt;How It Differs from a Regular API Proxy
&lt;/h2&gt;&lt;p&gt;A typical API proxy looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Client -&amp;gt; Proxy API -&amp;gt; Upstream model API
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;CLIProxyAPI is closer to this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Client -&amp;gt; CLIProxyAPI -&amp;gt; CLI / OAuth session / account pool -&amp;gt; model service
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The difference is that it handles more than API key forwarding. It also deals with CLI tools, OAuth accounts, protocol surfaces, and model aliases.&lt;/p&gt;
&lt;p&gt;Tools such as Codex and Claude Code are not traditional &amp;ldquo;give me one API key and I can call it stably&amp;rdquo; services. CLIProxyAPI wraps their login sessions and calling logic so external clients can access them as if they were normal APIs.&lt;/p&gt;
&lt;p&gt;That is what makes it attractive, and also what makes it complex.&lt;/p&gt;
&lt;h2 id=&#34;common-misunderstandings&#34;&gt;Common Misunderstandings
&lt;/h2&gt;&lt;p&gt;First, do not assume that a unified &lt;code&gt;/v1/...&lt;/code&gt; path eliminates all protocol differences.&lt;/p&gt;
&lt;p&gt;The CLIProxyAPI documentation specifically notes that when you need the request and response shape of a certain backend type, you should prefer provider-specific paths. For example, use &lt;code&gt;/api/provider/{provider}/v1/messages&lt;/code&gt; for messages-style requests, &lt;code&gt;/api/provider/{provider}/v1beta/models/...&lt;/code&gt; for Gemini model paths, and &lt;code&gt;/api/provider/{provider}/v1/chat/completions&lt;/code&gt; for chat-completions-style requests.&lt;/p&gt;
&lt;p&gt;A unified entry point is convenient, but the semantics of different protocols do not disappear. Tool calling, streaming responses, multimodal input, and system message handling may all differ by backend.&lt;/p&gt;
&lt;p&gt;Second, a model name does not uniquely identify a backend.&lt;/p&gt;
&lt;p&gt;If multiple backends expose the same client-visible model name, the path alone may not lock the request to the backend that actually performs inference. To strictly pin a backend, use unique aliases, prefixes, or avoid exposing the same model name from multiple backends.&lt;/p&gt;
&lt;p&gt;Third, multi-account rotation is not unlimited quota.&lt;/p&gt;
&lt;p&gt;Rotation only spreads usage more evenly across the account pool. It cannot bypass the real limits of upstream services. Abnormal accounts, exhausted quota, risk controls, and expired OAuth sessions still need monitoring.&lt;/p&gt;
&lt;p&gt;Fourth, it is not a maintenance-free magic box.&lt;/p&gt;
&lt;p&gt;Once you put it into your daily workflow, you need to care about configuration, logs, upstream account status, version upgrades, client compatibility, and security boundaries.&lt;/p&gt;
&lt;h2 id=&#34;management-and-monitoring&#34;&gt;Management and Monitoring
&lt;/h2&gt;&lt;p&gt;The official README notes that since v6.10.0, CLIProxyAPI and CPAMC no longer include built-in data statistics. If you need usage statistics, you can use separate projects:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CPA Usage Keeper: syncs CLIProxyAPI data into SQLite and provides aggregation APIs and a dashboard.&lt;/li&gt;
&lt;li&gt;CLIProxyAPI Usage Dashboard: a local-first usage and quota dashboard that can show accounts, models, time windows, and remaining Codex quota.&lt;/li&gt;
&lt;li&gt;CPA-Manager: a fuller management center for request monitoring, cost estimation, account pool inspection, abnormal account location, and cleanup suggestions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This suggests that CLIProxyAPI&amp;rsquo;s core is closer to a proxy and protocol layer, not an all-in-one commercial admin backend. If a team uses it, logs, monitoring, and account pool management should be considered from the beginning.&lt;/p&gt;
&lt;h2 id=&#34;a-reasonable-way-to-try-it&#34;&gt;A Reasonable Way to Try It
&lt;/h2&gt;&lt;p&gt;If you want to test it, a safer order is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start it with the official Quick Start documentation.&lt;/li&gt;
&lt;li&gt;Connect only one provider first, such as Gemini CLI or Codex, and confirm basic requests work.&lt;/li&gt;
&lt;li&gt;Then test higher-risk capabilities such as streaming responses, tool calling, and multimodal input.&lt;/li&gt;
&lt;li&gt;Confirm which endpoint the client actually uses, and avoid mixing protocol paths.&lt;/li&gt;
&lt;li&gt;Finally add multi-account rotation, management panels, and usage statistics.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Do not connect Gemini, Codex, Claude, OpenRouter, multiple accounts, and all clients at once from the start. When something breaks, it becomes hard to tell whether the issue is authentication, protocol conversion, model naming, or the upstream account.&lt;/p&gt;
&lt;h2 id=&#34;think-through-the-security-boundary&#34;&gt;Think Through the Security Boundary
&lt;/h2&gt;&lt;p&gt;CLIProxyAPI can touch account login sessions, API keys, OAuth-related credentials, and request contents. If it only runs on your own machine, the risk is relatively manageable. If it is exposed to the public internet or a team intranet, authentication, access control, log redaction, and network isolation become mandatory.&lt;/p&gt;
&lt;p&gt;Management endpoints especially should be limited to localhost or a trusted internal network. Do not expose management interfaces directly just to save a few minutes.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;CLIProxyAPI&amp;rsquo;s value is that it gathers AI capabilities scattered across multiple CLIs, accounts, and protocols into one programmable API layer.&lt;/p&gt;
&lt;p&gt;It fits heavy AI coding users, multi-account users, and internal team gateway scenarios. It is less suitable for lightweight users who want something completely plug-and-play with no maintenance.&lt;/p&gt;
&lt;p&gt;If you are already experimenting with Codex, Claude Code, and Gemini CLI, and want to connect them to your own client or automation workflow, CLIProxyAPI is worth a serious look. Treat it as infrastructure, not as a disposable small utility.&lt;/p&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/router-for-me/CLIProxyAPI&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;router-for-me/CLIProxyAPI GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/router-for-me/CLIProxyAPI/blob/main/README_CN.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;CLIProxyAPI Chinese README&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://help.router-for.me/cn/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;CLIProxyAPI official documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Two Ways to Use DeepSeek Models with Codex: Local Gateway and OpenRouter BYOK</title>
        <link>https://knightli.com/en/2026/05/24/codex-deepseek-config-ccx-openrouter-byok/</link>
        <pubDate>Sun, 24 May 2026 09:52:55 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/24/codex-deepseek-config-ccx-openrouter-byok/</guid>
        <description>&lt;p&gt;If you want Codex to use DeepSeek, the first instinct is usually to edit &lt;code&gt;~/.codex/config.toml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek-chat&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;base_url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://api.deepseek.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;That idea can work in some older versions or in regular OpenAI SDK scenarios. But with the current Codex CLI, it can easily run into a lower-level mismatch: custom model providers in Codex use the OpenAI Responses protocol, while DeepSeek&amp;rsquo;s official API is mainly exposed through an OpenAI-compatible Chat Completions interface.&lt;/p&gt;
&lt;p&gt;My local version is currently &lt;code&gt;codex-cli 0.111.0&lt;/code&gt;. &lt;code&gt;codex --help&lt;/code&gt; shows support for configuration entry points such as &lt;code&gt;--config&lt;/code&gt;, &lt;code&gt;--model&lt;/code&gt;, and &lt;code&gt;--profile&lt;/code&gt;. The official OpenAI Codex configuration reference is also explicit: &lt;code&gt;model_providers.&amp;lt;id&amp;gt;.wire_api&lt;/code&gt; currently supports only &lt;code&gt;responses&lt;/code&gt;, and defaults to &lt;code&gt;responses&lt;/code&gt; when omitted.&lt;/p&gt;
&lt;p&gt;DeepSeek&amp;rsquo;s official docs, meanwhile, show the call path as &lt;code&gt;https://api.deepseek.com/chat/completions&lt;/code&gt;, with examples such as &lt;code&gt;client.chat.completions.create(...)&lt;/code&gt;. So the issue is not that DeepSeek cannot be called through OpenAI-style tooling. The issue is that the request semantics Codex sends are not exactly the same as what DeepSeek&amp;rsquo;s native API understands.&lt;/p&gt;
&lt;p&gt;That is why changing &lt;code&gt;base_url&lt;/code&gt; directly to &lt;code&gt;https://api.deepseek.com&lt;/code&gt; may produce symptoms such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The request path does not match, resulting in a 404 or an unexpected response format.&lt;/li&gt;
&lt;li&gt;Multi-turn conversations, tool calls, or patch generation fail during parsing.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tool_calls&lt;/code&gt; order, message structure, or streaming event format does not line up.&lt;/li&gt;
&lt;li&gt;The model seems able to answer a plain prompt, but starts failing once Codex does real work.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The steadier approach is to put a translation layer between Codex and DeepSeek. There are two common routes.&lt;/p&gt;
&lt;h2 id=&#34;method-1-bridge-deepseek-through-a-local-gateway&#34;&gt;Method 1: Bridge DeepSeek Through a Local Gateway
&lt;/h2&gt;&lt;p&gt;A local gateway should do more than simple forwarding. Its job is to convert Responses-style requests from Codex into Chat Completions-style requests that DeepSeek can handle, then convert DeepSeek&amp;rsquo;s result back into a format Codex can consume.&lt;/p&gt;
&lt;p&gt;If you use a local gateway such as ccx, the configuration idea looks roughly like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;profiles&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;deepseek-ccx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek-v4-flash&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model_provider&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ccx-bridge&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;model_providers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;ccx-bridge&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Local CCX Gateway&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;base_url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;http://localhost:3000/v1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;env_key&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DEEPSEEK_API_KEY&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then set the DeepSeek key in your terminal and start Codex with that profile:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;DEEPSEEK_API_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;your-deepseek-key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex --profile deepseek-ccx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;In PowerShell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$env:DEEPSEEK_API_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;your-deepseek-key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;codex&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-profile&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;deepseek-ccx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;There are two details to watch.&lt;/p&gt;
&lt;p&gt;First, &lt;code&gt;base_url&lt;/code&gt; should point to the gateway endpoint exposed to Codex, not the official DeepSeek address. The gateway calls DeepSeek behind the scenes.&lt;/p&gt;
&lt;p&gt;Second, the correct value for &lt;code&gt;env_key&lt;/code&gt; depends on how the gateway handles authentication. Some gateways read the official DeepSeek key directly. Others ask you to provide a local proxy key, while storing the DeepSeek key in the gateway backend. In that case, &lt;code&gt;env_key&lt;/code&gt; should be changed to whatever environment variable the gateway expects.&lt;/p&gt;
&lt;p&gt;This route is local and controllable, and it is easier to reason about latency and cost. The tradeoff is that you must confirm the gateway really supports the current Responses semantics used by Codex, rather than only acting as a basic Chat Completions proxy.&lt;/p&gt;
&lt;h2 id=&#34;method-2-use-openrouter-byok-as-an-online-bridge&#34;&gt;Method 2: Use OpenRouter BYOK as an Online Bridge
&lt;/h2&gt;&lt;p&gt;If you do not want to run a local gateway, OpenRouter BYOK is another option. BYOK means binding your own upstream provider key to OpenRouter, which then handles routing and forwarding.&lt;/p&gt;
&lt;p&gt;The most common mistake here is the environment variable. Codex is calling OpenRouter, so &lt;code&gt;env_key&lt;/code&gt; should usually be &lt;code&gt;OPENROUTER_API_KEY&lt;/code&gt;, not &lt;code&gt;DEEPSEEK_API_KEY&lt;/code&gt;. The DeepSeek key should be added in OpenRouter&amp;rsquo;s BYOK or provider key settings.&lt;/p&gt;
&lt;p&gt;Example configuration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;profiles&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;deepseek-openrouter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek/deepseek-chat&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model_provider&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;openrouter&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;model_providers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;openrouter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;OpenRouter&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;base_url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://openrouter.ai/api/v1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;env_key&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;OPENROUTER_API_KEY&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Start it like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;OPENROUTER_API_KEY&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;your-openrouter-key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex --profile deepseek-openrouter
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;PowerShell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$env:OPENROUTER_API_KEY&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;your-openrouter-key&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;codex&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-profile&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;deepseek-openrouter&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then add your DeepSeek provider key in the OpenRouter dashboard. OpenRouter&amp;rsquo;s BYOK documentation says provider keys are stored encrypted and used for routing to the corresponding provider.&lt;/p&gt;
&lt;p&gt;This route saves you from maintaining a local gateway and feels more like using a regular third-party API proxy. The downside is that an online service sits in the middle, so troubleshooting may require checking Codex, OpenRouter, and DeepSeek error messages together.&lt;/p&gt;
&lt;h2 id=&#34;should-you-keep-using-the-deepseek-chat-model-name&#34;&gt;Should You Keep Using the deepseek-chat Model Name?
&lt;/h2&gt;&lt;p&gt;In DeepSeek&amp;rsquo;s documentation as of May 2026, the recommended model names include &lt;code&gt;deepseek-v4-flash&lt;/code&gt; and &lt;code&gt;deepseek-v4-pro&lt;/code&gt;, with a note that compatibility aliases such as &lt;code&gt;deepseek-chat&lt;/code&gt; and &lt;code&gt;deepseek-reasoner&lt;/code&gt; will be deprecated after 2026-07-24.&lt;/p&gt;
&lt;p&gt;For new configurations, it is better to test:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek-v4-flash&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you are using OpenRouter, follow OpenRouter&amp;rsquo;s model naming format, for example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek/deepseek-chat&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The actual available names depend on your gateway or OpenRouter&amp;rsquo;s model page. When the model name is wrong, errors usually look like &lt;code&gt;model not found&lt;/code&gt;, 404, or the provider failing to find the matching endpoint.&lt;/p&gt;
&lt;h2 id=&#34;why-directly-setting-deepseeks-official-base_url-is-not-recommended&#34;&gt;Why Directly Setting DeepSeek&amp;rsquo;s Official base_url Is Not Recommended
&lt;/h2&gt;&lt;p&gt;You can certainly try this as an experiment:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;profiles&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;deepseek-direct&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek-v4-flash&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;model_provider&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;deepseek&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;model_providers&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;deepseek&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DeepSeek&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;base_url&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;https://api.deepseek.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;env_key&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DEEPSEEK_API_KEY&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;But this is more of a debugging experiment than a stable setup. Codex talks to custom providers through the Responses protocol, while DeepSeek&amp;rsquo;s official examples use &lt;code&gt;/chat/completions&lt;/code&gt;. If DeepSeek or Codex adds a full compatibility layer later, direct connection may become simple. Until then, a bridge layer is more reliable.&lt;/p&gt;
&lt;h2 id=&#34;what-if-codex-still-uses-openai-after-editing-the-config&#34;&gt;What If Codex Still Uses OpenAI After Editing the Config?
&lt;/h2&gt;&lt;p&gt;First, confirm the config file location. The global config should be:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;~/.codex/config.toml
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The project-level &lt;code&gt;.codex/config.toml&lt;/code&gt; is not the right place for machine-level provider settings such as &lt;code&gt;model_provider&lt;/code&gt; and &lt;code&gt;model_providers&lt;/code&gt;. The official OpenAI docs also note that project-level configuration does not override local provider and authentication fields.&lt;/p&gt;
&lt;p&gt;If Codex still asks you to log in through the web, or appears to use the default OpenAI model, log out first:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex &lt;span class=&#34;nb&#34;&gt;logout&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Some older tutorials write this as &lt;code&gt;/logout&lt;/code&gt; inside the interactive UI. With the current CLI, running &lt;code&gt;codex logout&lt;/code&gt; directly in the terminal is the more reliable option.&lt;/p&gt;
&lt;p&gt;You can also run a quick check with a temporary profile:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex --profile deepseek-ccx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Or:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codex -c &lt;span class=&#34;nv&#34;&gt;model_provider&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;ccx-bridge -c &lt;span class=&#34;nv&#34;&gt;model&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;deepseek-v4-flash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If that works, the config itself is readable. If it does not, check the profile name, TOML syntax, and whether the environment variable only exists in the current shell session.&lt;/p&gt;
&lt;h2 id=&#34;troubleshooting-checklist&#34;&gt;Troubleshooting Checklist
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;401&lt;/code&gt;: The key is wrong, or &lt;code&gt;env_key&lt;/code&gt; points to the wrong environment variable.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;404&lt;/code&gt;: &lt;code&gt;base_url&lt;/code&gt; or the model name is wrong, or a Responses request is being sent to an endpoint that only supports Chat Completions.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;tool_calls&lt;/code&gt;, patch, or streaming parse errors: the protocol bridge is likely incomplete.&lt;/li&gt;
&lt;li&gt;Still prompted to log in to OpenAI: run &lt;code&gt;codex logout&lt;/code&gt;, then confirm you are using the correct profile.&lt;/li&gt;
&lt;li&gt;PowerShell environment variable disappears in a new window: &lt;code&gt;$env:...&lt;/code&gt; only applies to the current session. Use user environment variables if you need it to persist.&lt;/li&gt;
&lt;li&gt;OpenRouter BYOK is not using your own DeepSeek key: check whether the provider key is bound in OpenRouter, whether the current OpenRouter API key is allowed to use it, and whether fallback is enabled.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Using DeepSeek with Codex is not impossible through &lt;code&gt;config.toml&lt;/code&gt;. The catch is that changing only &lt;code&gt;base_url&lt;/code&gt; is usually not enough.&lt;/p&gt;
&lt;p&gt;The two steadier routes today are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use a local gateway as a protocol bridge: Codex talks to the local gateway, and the gateway talks to DeepSeek.&lt;/li&gt;
&lt;li&gt;Use OpenRouter BYOK as an online proxy: Codex talks to OpenRouter, while the DeepSeek key is bound in the OpenRouter dashboard.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you only want a quick test, OpenRouter is easier. If you want tighter control over keys, cost, and logs, a local gateway is better for long-term tinkering.&lt;/p&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://developers.openai.com/codex/config-reference/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenAI Codex Configuration Reference&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://api-docs.deepseek.com/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;DeepSeek API Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://openrouter.ai/docs/use-cases/byok/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;OpenRouter BYOK Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>What is CodeGraph? A local code map for Claude Code, Codex, and Cursor</title>
        <link>https://knightli.com/en/2026/05/23/codegraph-local-code-knowledge-graph-ai-coding-agent/</link>
        <pubDate>Sat, 23 May 2026 21:09:46 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/23/codegraph-local-code-knowledge-graph-ai-coding-agent/</guid>
        <description>&lt;p&gt;&lt;code&gt;CodeGraph&lt;/code&gt; is a local code knowledge graph designed for AI coding tools. It indexes a project ahead of time and organizes symbol relationships, call graphs, code structure, route relationships, and related information into a queryable graph. That lets Claude Code, Codex CLI, Cursor, OpenCode, Hermes Agent, and similar tools avoid relying on grep, glob, Read, and exploratory subagents every time they need to understand a project.&lt;/p&gt;
&lt;p&gt;It solves a very practical problem: when an AI Agent works on a large codebase, much of the cost is not spent on changing code, but on finding where the relevant code lives. If every task starts with repeated searches, reads, and filtering, tokens, time, and tool calls are wasted. &lt;code&gt;CodeGraph&lt;/code&gt; tries to turn the repository into a local map first, so the agent can ask the map before deciding which files to read.&lt;/p&gt;
&lt;h2 id=&#34;what-pain-points-does-it-address&#34;&gt;What pain points does it address?
&lt;/h2&gt;&lt;p&gt;AI coding tools usually work well in small projects. There are few files, search is fast, and reading files is cheap. In larger projects, common problems appear:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The agent repeatedly calls grep, find, ls, and Read just to understand one module.&lt;/li&gt;
&lt;li&gt;Exploratory subagents read many irrelevant files, while the main task context remains unclear.&lt;/li&gt;
&lt;li&gt;Architecture questions spend too many tokens locating files.&lt;/li&gt;
&lt;li&gt;Before changing a function, it is unclear who calls it and what it calls.&lt;/li&gt;
&lt;li&gt;In web projects, URL routes and handler functions are not always obvious.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;CodeGraph&lt;/code&gt; tries to move this &amp;ldquo;find the way first&amp;rdquo; work earlier. Once the project index exists, the agent can query related symbols, callers, callees, impact scope, and code snippets directly.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation
&lt;/h2&gt;&lt;p&gt;The project provides cross-platform installation scripts and does not require users to prepare Node.js manually:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -fsSL https://raw.githubusercontent.com/colbymchenry/codegraph/main/install.sh &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;On Windows PowerShell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;irm &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;https&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;//&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;raw&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;githubusercontent&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;com&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;colbymchenry&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;codegraph&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;install&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;ps1&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;iex
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you already have a Node environment, you can use npm directly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx @colbymchenry/codegraph
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Or install it globally:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm i -g @colbymchenry/codegraph
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The installer detects and configures installed agents such as Claude Code, Cursor, Codex CLI, opencode, and Hermes Agent. It writes the relevant MCP server configuration and instruction files so those tools know when to call CodeGraph.&lt;/p&gt;
&lt;h2 id=&#34;initializing-a-project&#34;&gt;Initializing a project
&lt;/h2&gt;&lt;p&gt;After installation, build an index inside the target project:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; your-project
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codegraph init -i
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This command creates a project-level knowledge graph index. The README notes that as long as a &lt;code&gt;.codegraph/&lt;/code&gt; directory exists in the project, agents can automatically use CodeGraph tools.&lt;/p&gt;
&lt;p&gt;To stop using it, you can remove the global configuration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;codegraph uninstall
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;That removes the MCP server configuration, instructions, and permissions written by the installer. The &lt;code&gt;.codegraph/&lt;/code&gt; index in the project is not deleted automatically. To remove the project index, use &lt;code&gt;codegraph uninit&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;why-it-helps-agents&#34;&gt;Why it helps agents
&lt;/h2&gt;&lt;p&gt;Tools like Claude Code, Codex CLI, and Cursor often explore before making changes: find files, read entry points, inspect references, and follow call chains. For humans this feels like browsing a project. For models, it becomes a series of tool calls and context cost.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CodeGraph&lt;/code&gt; turns that into index queries. An agent can first use &lt;code&gt;codegraph_context&lt;/code&gt; to find relevant entry points, symbols, and snippets, then use &lt;code&gt;codegraph_explore&lt;/code&gt; or other tools to read the necessary details. The benefits are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fewer irrelevant files read.&lt;/li&gt;
&lt;li&gt;Fewer search tool calls.&lt;/li&gt;
&lt;li&gt;Faster discovery of relevant code.&lt;/li&gt;
&lt;li&gt;Clearer impact scope before edits.&lt;/li&gt;
&lt;li&gt;Easier answers to architecture questions in large repositories.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The README reports benchmark results across seven real open source repositories comparing runs with and without CodeGraph. On average, enabling CodeGraph reduced cost, tokens, latency, and tool calls. The exact numbers depend on project size, language, question type, and agent behavior, but the direction is clear: the larger the repository, the more valuable pre-indexing becomes.&lt;/p&gt;
&lt;h2 id=&#34;core-capabilities&#34;&gt;Core capabilities
&lt;/h2&gt;&lt;h3 id=&#34;1-smart-context-construction&#34;&gt;1. Smart context construction
&lt;/h3&gt;&lt;p&gt;One tool call can return entry points, related symbols, and code snippets, reducing the need for the agent to launch many exploratory tasks before filtering the results. This is useful for architecture understanding, module location, and feature entry-point analysis.&lt;/p&gt;
&lt;h3 id=&#34;2-full-text-search&#34;&gt;2. Full-text search
&lt;/h3&gt;&lt;p&gt;CodeGraph uses FTS5 for full-text search, letting it quickly search names and text across the codebase. It does not replace every grep use case, but it gives the agent a more structured first stop.&lt;/p&gt;
&lt;h3 id=&#34;3-impact-analysis&#34;&gt;3. Impact analysis
&lt;/h3&gt;&lt;p&gt;Before changing a function, class, method, or route, the agent can query callers, callees, and impact radius. This is especially useful for refactoring, bug fixing, and deleting old code, where missing upstream or downstream calls is the main risk.&lt;/p&gt;
&lt;h3 id=&#34;4-automatic-freshness&#34;&gt;4. Automatic freshness
&lt;/h3&gt;&lt;p&gt;The README says CodeGraph uses native filesystem events such as FSEvents, inotify, and ReadDirectoryChangesW, along with debounced auto-sync. In practice, the index updates as local code changes, so users do not need to rebuild it manually after every edit.&lt;/p&gt;
&lt;h3 id=&#34;5-multi-language-support&#34;&gt;5. Multi-language support
&lt;/h3&gt;&lt;p&gt;The project lists support for more than 19 languages, including TypeScript, JavaScript, Python, Go, Rust, Java, C#, PHP, Ruby, C, C++, Swift, Kotlin, Dart, Lua, Luau, Svelte, Liquid, and Pascal / Delphi.&lt;/p&gt;
&lt;p&gt;That makes it suitable for multi-language repositories and full-stack projects, not just one language.&lt;/p&gt;
&lt;h3 id=&#34;6-web-route-awareness&#34;&gt;6. Web route awareness
&lt;/h3&gt;&lt;p&gt;CodeGraph also detects route files and route declarations in many web frameworks, connecting URL patterns with handler functions. The README mentions Django, Flask, FastAPI, Express, NestJS, Laravel, Rails, Spring, Gin, Axum, ASP.NET, Vapor, React Router, SvelteKit, and others.&lt;/p&gt;
&lt;p&gt;This is practical because the real entry point of many web projects is not an obvious &lt;code&gt;main&lt;/code&gt; function, but routes, controllers, handlers, views, or resolvers. If an agent can first understand the URL-to-handler relationship, it can understand business flow much faster.&lt;/p&gt;
&lt;h2 id=&#34;local-first-design&#34;&gt;Local-first design
&lt;/h2&gt;&lt;p&gt;CodeGraph emphasizes being &lt;code&gt;100% local&lt;/code&gt;. It does not require an API key or external service. Index data is stored in a local SQLite database.&lt;/p&gt;
&lt;p&gt;For enterprise projects, private repositories, or sensitive code, this matters. The concern with AI coding tools is often not only &amp;ldquo;can they find the code?&amp;rdquo;, but &amp;ldquo;will the code structure and index be sent elsewhere?&amp;rdquo; CodeGraph is positioned as local indexing, local querying, and local service for agents.&lt;/p&gt;
&lt;p&gt;Of course, local indexing also means considering disk usage, indexing time, file watching, and project size. Very large repositories still require resources for initial indexing and later synchronization.&lt;/p&gt;
&lt;h2 id=&#34;suitable-scenarios&#34;&gt;Suitable scenarios
&lt;/h2&gt;&lt;p&gt;CodeGraph is a good fit for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Large codebases where architecture and call-chain questions are common.&lt;/li&gt;
&lt;li&gt;Teams using Claude Code, Codex CLI, Cursor, or similar agents for code understanding and edits.&lt;/li&gt;
&lt;li&gt;Reducing random file reads, broad searches, and repeated exploration by agents.&lt;/li&gt;
&lt;li&gt;Analyzing impact before code changes.&lt;/li&gt;
&lt;li&gt;Web projects with complex routing, where URL-to-handler lookup matters.&lt;/li&gt;
&lt;li&gt;Teams that want a more stable local project index for AI agents.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For a small project with a few dozen files, normal search may be enough and CodeGraph&amp;rsquo;s advantage may not be obvious. It is most valuable in medium-to-large repositories and workflows where agents do a lot of exploration.&lt;/p&gt;
&lt;h2 id=&#34;things-to-watch-out-for&#34;&gt;Things to watch out for
&lt;/h2&gt;&lt;p&gt;First, CodeGraph is not a substitute for code review or testing. It helps agents find relevant code faster, but it does not guarantee that their changes are correct.&lt;/p&gt;
&lt;p&gt;Second, index quality affects results. If a project has complex structure, lots of generated code, mixed languages, or unignored build artifacts, the index may become noisy. Before using it seriously, check &lt;code&gt;.gitignore&lt;/code&gt;, project layout, and indexing scope.&lt;/p&gt;
&lt;p&gt;Third, MCP configuration and agent instructions matter. The README also warns that CodeGraph helps only when it is queried properly. If an agent ignores it and still reads many files directly, pre-indexing becomes extra overhead.&lt;/p&gt;
&lt;p&gt;Fourth, even though it is local, permissions still matter. The installer writes agent configuration and permission lists. In team environments, review those configurations centrally.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CodeGraph&lt;/code&gt; can be understood simply: it gives AI agents a local map of the codebase. It does not make the model smarter; it helps the model get less lost.&lt;/p&gt;
&lt;p&gt;When tools like Claude Code, Codex CLI, and Cursor face large repositories, the expensive part is often exploration. CodeGraph uses pre-indexed symbol relationships, call graphs, route graphs, and full-text search to handle &amp;ldquo;where is the code?&amp;rdquo; earlier, leaving more budget for understanding and editing.&lt;/p&gt;
&lt;p&gt;If you already use AI coding tools in real projects and often see the agent read many files without finding the point, CodeGraph is worth trying. It represents an important direction for AI coding tools: not only stronger models, but better local code context for those models.&lt;/p&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GitHub project: &lt;a class=&#34;link&#34; href=&#34;https://github.com/colbymchenry/codegraph&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/colbymchenry/codegraph&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>What is oh-my-pi? An AI coding assistant that connects the terminal, IDE, and debugger</title>
        <link>https://knightli.com/en/2026/05/23/oh-my-pi-ai-coding-agent-terminal-ide-lsp-debugger/</link>
        <pubDate>Sat, 23 May 2026 19:02:20 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/23/oh-my-pi-ai-coding-agent-terminal-ide-lsp-debugger/</guid>
        <description>&lt;p&gt;&lt;code&gt;oh-my-pi&lt;/code&gt; is an AI Coding Agent for the terminal and editor. It is a fork of Mario Zechner&amp;rsquo;s &lt;code&gt;Pi&lt;/code&gt; project, extended by &lt;code&gt;can1357&lt;/code&gt;. Its goal is not just to provide a command-line chat UI, but to connect file reading, code search, structured edits, LSP, debuggers, browsers, subagents, and multiple model providers into one coding workflow.&lt;/p&gt;
&lt;p&gt;From the project README, it feels more like an AI coding tool layer than a simple assistant: you can use it interactively in the terminal, connect editors through ACP, or embed it in Node projects through the SDK. For people already using Claude Code, Codex CLI, Cline, Cursor, or other agent tools, the interesting part is that &lt;code&gt;oh-my-pi&lt;/code&gt; turns many abilities that usually live in separate tools into one built-in tool surface.&lt;/p&gt;
&lt;h2 id=&#34;what-problem-is-it-trying-to-solve&#34;&gt;What problem is it trying to solve?
&lt;/h2&gt;&lt;p&gt;For many AI coding tools, the weak point is not the model itself, but the tool interface around it. When a model wants to change code but only has rough full-file reads, fragile string replacement, and one-off shell commands, the toolchain amplifies failure.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;oh-my-pi&lt;/code&gt; tries to reduce those common points of friction:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;File reads prefer structured summaries instead of dumping whole files into context.&lt;/li&gt;
&lt;li&gt;Search, glob, find, syntax highlighting, and token counting are implemented natively where possible, reducing dependence on external commands.&lt;/li&gt;
&lt;li&gt;Code writes can use LSP so renames, references, and file moves behave more like IDE operations.&lt;/li&gt;
&lt;li&gt;Debugging can use DAP tools such as &lt;code&gt;lldb&lt;/code&gt;, &lt;code&gt;dlv&lt;/code&gt;, and &lt;code&gt;debugpy&lt;/code&gt;, instead of relying only on logs and guesses.&lt;/li&gt;
&lt;li&gt;Complex tasks can be split across subagents and returned as structured results.&lt;/li&gt;
&lt;li&gt;Edits use content anchors and previews to reduce the chance of a bad patch landing directly on disk.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These choices show that the focus is not &amp;ldquo;can the model answer?&amp;rdquo;, but &amp;ldquo;can the model reliably complete a real code change?&amp;rdquo;&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation
&lt;/h2&gt;&lt;p&gt;The project provides several installation paths. On macOS and Linux, you can use the install script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -fsSL https://omp.sh/install &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you use Bun, the README recommends installing the npm package globally:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun install -g @oh-my-pi/pi-coding-agent
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;On Windows PowerShell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;irm &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;https&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;//&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;omp&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;sh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;install&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;ps1&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;iex
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The README also mentions pinning versions with &lt;code&gt;mise&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mise use -g github:can1357/oh-my-pi
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Before installing, check the Bun version requirement. The README lists macOS, Linux, and Windows support, and requires &lt;code&gt;bun &amp;gt;= 1.3.14&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;capabilities-worth-watching&#34;&gt;Capabilities worth watching
&lt;/h2&gt;&lt;h3 id=&#34;1-tool-calling-goes-beyond-shell-commands&#34;&gt;1. Tool calling goes beyond shell commands
&lt;/h3&gt;&lt;p&gt;&lt;code&gt;oh-my-pi&lt;/code&gt; includes tools for file reads, search, writes, edits, AST edits, browser use, task splitting, debugging, and LSP. The README mentions 32 built-in tools, 13 LSP operations, and 27 DAP operations.&lt;/p&gt;
&lt;p&gt;That means the agent does not have to wrap everything as command-line output. Reference lookup can go through LSP, PRs and issues can be read through a unified file-like interface, and web pages or PDFs can be converted into Markdown with link structure intact before being passed to the model.&lt;/p&gt;
&lt;h3 id=&#34;2-lsp-integration-is-useful-for-real-codebases&#34;&gt;2. LSP integration is useful for real codebases
&lt;/h3&gt;&lt;p&gt;In large projects, renaming and moving files often breaks re-exports, aliased imports, barrel files, or cross-directory references. The &lt;code&gt;oh-my-pi&lt;/code&gt; README highlights that write paths can go through LSP. For example, file renames use &lt;code&gt;workspace/willRenameFiles&lt;/code&gt;, making edits closer to semantic IDE operations.&lt;/p&gt;
&lt;p&gt;This is useful for everyday refactoring in TypeScript, Rust, Go, Python, and similar projects, especially in cases where manual edits are possible but easy to miss.&lt;/p&gt;
&lt;h3 id=&#34;3-the-debugger-is-a-first-class-tool&#34;&gt;3. The debugger is a first-class tool
&lt;/h3&gt;&lt;p&gt;Many AI coding flows still debug by adding logs, rerunning, and reading output. &lt;code&gt;oh-my-pi&lt;/code&gt; connects DAP debuggers to the tool surface. The README gives examples with C programs using &lt;code&gt;lldb&lt;/code&gt;, Go services using &lt;code&gt;dlv&lt;/code&gt;, and Python processes using &lt;code&gt;debugpy&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That changes how an agent handles bugs: it can pause a process, inspect stack frames, read local variables, and then decide what to do next, instead of guessing from error text alone.&lt;/p&gt;
&lt;h3 id=&#34;4-hashline-editing-reduces-patch-failures&#34;&gt;4. Hashline editing reduces patch failures
&lt;/h3&gt;&lt;p&gt;The project emphasizes &lt;code&gt;Hashline&lt;/code&gt;, an editing approach based on content anchors. The goal is to let the model point to the content it wants to change instead of repeatedly emitting large diffs. This reduces edit failures caused by whitespace, stale context, or failed string matching.&lt;/p&gt;
&lt;p&gt;For agent tools, this matters a lot. Even a capable model feels clumsy if the write interface keeps failing and forcing retries.&lt;/p&gt;
&lt;h3 id=&#34;5-subagents-and-workspace-isolation&#34;&gt;5. Subagents and workspace isolation
&lt;/h3&gt;&lt;p&gt;The README introduces a &lt;code&gt;task&lt;/code&gt; subagent capability: a task can be split across isolated workers, and results are returned as structured objects. The project also includes workspace isolation logic for parallel tasks, branch exploration, and avoiding overlapping edits.&lt;/p&gt;
&lt;p&gt;This fits code review, migrations, bulk fixes, and test investigation. The value is not only speed; it is also cleaner separation between different exploration paths.&lt;/p&gt;
&lt;h3 id=&#34;6-it-can-inherit-existing-rules-and-configs&#34;&gt;6. It can inherit existing rules and configs
&lt;/h3&gt;&lt;p&gt;On first run, &lt;code&gt;oh-my-pi&lt;/code&gt; can read rules and configuration left by other tools, including &lt;code&gt;.claude&lt;/code&gt;, &lt;code&gt;.cursor&lt;/code&gt;, &lt;code&gt;.windsurf&lt;/code&gt;, &lt;code&gt;.gemini&lt;/code&gt;, &lt;code&gt;.codex&lt;/code&gt;, &lt;code&gt;.cline&lt;/code&gt;, &lt;code&gt;.github/copilot&lt;/code&gt;, and &lt;code&gt;.vscode&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;That is practical. Many teams have already written rules for several AI tools. Rewriting them for every new tool is expensive, so &lt;code&gt;oh-my-pi&lt;/code&gt; tries to reuse what is already on disk.&lt;/p&gt;
&lt;h2 id=&#34;four-entry-points&#34;&gt;Four entry points
&lt;/h2&gt;&lt;p&gt;The project provides four main ways to use it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Interactive TUI: run &lt;code&gt;omp&lt;/code&gt; directly in the terminal.&lt;/li&gt;
&lt;li&gt;One-shot command: use &lt;code&gt;omp -p&lt;/code&gt; to send a single prompt.&lt;/li&gt;
&lt;li&gt;Node SDK: embed it in a Node or TypeScript project through &lt;code&gt;@oh-my-pi/pi-coding-agent&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;RPC / ACP: connect other programs and editors through stdio or Agent Client Protocol.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This means it is not only for individual terminal users. It also leaves room for IDEs, plugins, automation platforms, and internal tools.&lt;/p&gt;
&lt;h2 id=&#34;who-should-try-it&#34;&gt;Who should try it?
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;oh-my-pi&lt;/code&gt; is a good fit for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Developers who often edit, debug, and review code in the terminal.&lt;/li&gt;
&lt;li&gt;People already using AI Coding Agents but unhappy with file reading, patching, search, or debugging reliability.&lt;/li&gt;
&lt;li&gt;Developers who want to connect an agent to an editor, RPC layer, or Node service.&lt;/li&gt;
&lt;li&gt;Users who need to switch between multiple models and providers in one tool.&lt;/li&gt;
&lt;li&gt;Tool builders interested in LSP, DAP, AST editing, and subagent workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you only want a chat-style coding assistant that works immediately, the learning curve may feel high. It is better suited to people willing to understand the toolchain and treat the agent as a configurable development environment.&lt;/p&gt;
&lt;h2 id=&#34;what-to-keep-in-mind&#34;&gt;What to keep in mind
&lt;/h2&gt;&lt;p&gt;First, &lt;code&gt;oh-my-pi&lt;/code&gt; is still a fast-moving open source project. Commits are frequent, and there are many issues and pull requests, so installation and usage may change.&lt;/p&gt;
&lt;p&gt;Second, its capabilities depend heavily on your local environment. LSP, debuggers, Bun, model-provider authentication, terminal setup, and Windows or Unix differences can all affect the experience.&lt;/p&gt;
&lt;p&gt;Third, having many built-in tools does not mean every scenario should enable everything. In practice, it is better to enable the tools needed for the task and configure rules, permissions, and workspace boundaries clearly.&lt;/p&gt;
&lt;p&gt;Fourth, an AI Agent can write code, but it can also change the wrong code. Even with previews and content-anchored edits, important projects still need version control, tests, and human review.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;The interesting part of &lt;code&gt;oh-my-pi&lt;/code&gt; is not that it is another AI terminal shell. It is that it reorganizes the tool layer that often holds AI coding back: file reading, search, editing, LSP, debugging, browser access, subagents, and SDK integration all sit inside one agent workflow.&lt;/p&gt;
&lt;p&gt;It is worth watching for people who care about AI coding infrastructure, and for developers comparing different Coding Agent approaches. The competition in AI coding tools is no longer just about model answer quality. It is also about who can connect models reliably to real codebases, real debugging workflows, and real team rules. &lt;code&gt;oh-my-pi&lt;/code&gt; is an ambitious open source attempt in that direction.&lt;/p&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GitHub project: &lt;a class=&#34;link&#34; href=&#34;https://github.com/can1357/oh-my-pi&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/can1357/oh-my-pi&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Official site: &lt;a class=&#34;link&#34; href=&#34;https://omp.sh/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://omp.sh/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;SDK documentation: &lt;a class=&#34;link&#34; href=&#34;https://omp.sh/docs/sdk&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://omp.sh/docs/sdk&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Graphify Solves Claude Code&#39;s Biggest Limitation: Turning a Codebase into an AI-Queryable Knowledge Graph</title>
        <link>https://knightli.com/en/2026/05/21/safishamsi-graphify-ai-code-knowledge-graph/</link>
        <pubDate>Thu, 21 May 2026 08:02:32 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/21/safishamsi-graphify-ai-code-knowledge-graph/</guid>
        <description>&lt;p&gt;&lt;code&gt;safishamsi/graphify&lt;/code&gt; is a knowledge graph tool for AI coding assistants. Its goal is direct: take the code, docs, SQL schemas, scripts, papers, images, video, and audio inside a project folder, turn them into a queryable knowledge graph, and stop AI assistants from relying only on &lt;code&gt;grep&lt;/code&gt;, full-file reading, or ad hoc search to understand a project.&lt;/p&gt;
&lt;p&gt;Project link: &lt;a class=&#34;link&#34; href=&#34;https://github.com/safishamsi/graphify&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;safishamsi/graphify&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;At the time of writing, the GitHub page shows about 50.2k stars and 5.4k forks, with an MIT license. The README describes it like this: type &lt;code&gt;/graphify&lt;/code&gt; inside your AI coding assistant, and it maps the entire project into a queryable knowledge graph.&lt;/p&gt;
&lt;h2 id=&#34;the-core-problem-it-solves&#34;&gt;The Core Problem It Solves
&lt;/h2&gt;&lt;p&gt;AI coding assistants are becoming stronger, but in real codebases they still frequently run into several problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They do not know how key modules connect.&lt;/li&gt;
&lt;li&gt;They read many files but do not form an overall architecture map.&lt;/li&gt;
&lt;li&gt;Search finds text, but not upstream and downstream dependencies.&lt;/li&gt;
&lt;li&gt;Code, database schemas, docs, and infrastructure configuration are scattered across different places.&lt;/li&gt;
&lt;li&gt;In team collaboration, each person may have a different mental model of the project structure.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Graphify tries to add a &amp;ldquo;memory layer&amp;rdquo; to the project. It connects code entities, documentation concepts, database tables, configuration, design notes, and cross-file relationships so the AI assistant can query the graph instead of scanning files from scratch every time.&lt;/p&gt;
&lt;h2 id=&#34;minimal-usage&#34;&gt;Minimal Usage
&lt;/h2&gt;&lt;p&gt;Graphify&amp;rsquo;s minimal workflow is simple. After installation, type this inside your AI coding assistant:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;In PowerShell, the leading &lt;code&gt;/&lt;/code&gt; is treated as a path separator, so on Windows PowerShell use:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;After running, it generates a &lt;code&gt;graphify-out/&lt;/code&gt; directory with three core files:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify-out/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── graph.html
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── GRAPH_REPORT.md
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── graph.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;These files serve different purposes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;graph.html&lt;/code&gt;: an interactive graph you can open in a browser, with clickable nodes, filters, and search.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;GRAPH_REPORT.md&lt;/code&gt;: highlights, key concepts, surprising connections, and suggested questions.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;graph.json&lt;/code&gt;: the full graph, which can be queried later without rereading all files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To generate a more readable architecture page with Mermaid call-flow diagrams, run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify &lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; callflow-html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;installation-and-platform-support&#34;&gt;Installation and Platform Support
&lt;/h2&gt;&lt;p&gt;Graphify&amp;rsquo;s PyPI package name is &lt;code&gt;graphifyy&lt;/code&gt;, with a double &lt;code&gt;y&lt;/code&gt;. The README specifically warns that other &lt;code&gt;graphify*&lt;/code&gt; packages on PyPI are not affiliated with the project, although the CLI command is still &lt;code&gt;graphify&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The recommended installation method is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv tool install graphifyy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Alternatives:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pipx install graphifyy
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install graphifyy
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then register it with your AI assistant:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The project supports many platforms, including Claude Code, Codex, OpenCode, GitHub Copilot CLI, VS Code Copilot Chat, Aider, Cursor, Gemini CLI, Kimi Code, Kiro, and Google Antigravity. Different platforms can use different install commands, for example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify install --platform codex
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify install --platform gemini
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify cursor install
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify antigravity install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Codex users also need to add this under &lt;code&gt;[features]&lt;/code&gt; in &lt;code&gt;~/.codex/config.toml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;multi_agent&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The README also notes that Codex uses &lt;code&gt;$graphify&lt;/code&gt;, not &lt;code&gt;/graphify&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;what-files-it-handles&#34;&gt;What Files It Handles
&lt;/h2&gt;&lt;p&gt;Graphify supports a wide range of input types.&lt;/p&gt;
&lt;p&gt;For code, it supports 31 languages, including Python, TypeScript, JavaScript, Go, Rust, Java, C/C++, Ruby, C#, Kotlin, Scala, PHP, Swift, Lua, Zig, PowerShell, SQL, Shell, JSON, and more.&lt;/p&gt;
&lt;p&gt;For documents, it supports:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.mdx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.qmd&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.html&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.txt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.rst&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.yaml&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.yml&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Optional dependencies extend it further:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[pdf]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[office]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[video]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[mcp]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[neo4j]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[sql]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install &lt;span class=&#34;s2&#34;&gt;&amp;#34;graphifyy[all]&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Here, &lt;code&gt;pdf&lt;/code&gt; is for PDF extraction, &lt;code&gt;office&lt;/code&gt; for &lt;code&gt;.docx&lt;/code&gt; and &lt;code&gt;.xlsx&lt;/code&gt;, &lt;code&gt;video&lt;/code&gt; for video and audio transcription, &lt;code&gt;mcp&lt;/code&gt; for an MCP stdio server, &lt;code&gt;neo4j&lt;/code&gt; for pushing to Neo4j, and &lt;code&gt;sql&lt;/code&gt; for SQL schema extraction.&lt;/p&gt;
&lt;h2 id=&#34;why-the-report-matters&#34;&gt;Why the Report Matters
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;GRAPH_REPORT.md&lt;/code&gt; is not a normal summary. It extracts relationships inside the project that are especially useful for AI assistants.&lt;/p&gt;
&lt;p&gt;The README mentions report contents such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;God nodes&lt;/code&gt;: the most-connected core concepts in the project.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Surprising connections&lt;/code&gt;: unexpected links across files or modules.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;The why&lt;/code&gt;: design rationale extracted from comments, docstrings, and design docs.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Suggested questions&lt;/code&gt;: questions the graph is particularly well suited to answer.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Confidence tags&lt;/code&gt;: relationships are labeled &lt;code&gt;EXTRACTED&lt;/code&gt;, &lt;code&gt;INFERRED&lt;/code&gt;, or &lt;code&gt;AMBIGUOUS&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is important. Normal search only tells you &amp;ldquo;where this word appears.&amp;rdquo; A graph can answer &amp;ldquo;which modules, configs, tables, and docs this concept is connected to.&amp;rdquo; For large codebases, that is closer to architecture understanding than simple full-text search.&lt;/p&gt;
&lt;h2 id=&#34;common-commands&#34;&gt;Common Commands
&lt;/h2&gt;&lt;p&gt;Common Graphify commands include:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify .
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify ./docs --update
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify . --cluster-only
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify . --no-viz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify . --wiki
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify &lt;span class=&#34;nb&#34;&gt;export&lt;/span&gt; callflow-html
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify query &lt;span class=&#34;s2&#34;&gt;&amp;#34;what connects auth to the database?&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify path &lt;span class=&#34;s2&#34;&gt;&amp;#34;UserService&amp;#34;&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;DatabasePool&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify explain &lt;span class=&#34;s2&#34;&gt;&amp;#34;RateLimiter&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;You can also add a paper or video to the graph:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify add https://arxiv.org/abs/1706.03762
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify add &amp;lt;youtube-url&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;For PR-assisted analysis:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify prs
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify prs &lt;span class=&#34;m&#34;&gt;42&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify prs --triage
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify prs --conflicts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;These commands fit code review scenarios: identify which graph communities a PR affects, whether it risks conflicts with other PRs, and which review queues deserve priority.&lt;/p&gt;
&lt;h2 id=&#34;mcp-neo4j-and-ci&#34;&gt;MCP, Neo4j, and CI
&lt;/h2&gt;&lt;p&gt;Graphify is not only an HTML graph generator. It can also expose the graph to AI assistants for repeated tool use.&lt;/p&gt;
&lt;p&gt;For example, start an MCP server:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python -m graphify.serve graphify-out/graph.json
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The MCP server provides capabilities such as &lt;code&gt;query_graph&lt;/code&gt;, &lt;code&gt;get_node&lt;/code&gt;, &lt;code&gt;get_neighbors&lt;/code&gt;, &lt;code&gt;shortest_path&lt;/code&gt;, &lt;code&gt;list_prs&lt;/code&gt;, &lt;code&gt;get_pr_impact&lt;/code&gt;, and &lt;code&gt;triage_prs&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;It also supports Neo4j export or push:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify ./raw --neo4j
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;/graphify ./raw --neo4j-push bolt://localhost:7687
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;For team collaboration, the README suggests committing &lt;code&gt;graphify-out/&lt;/code&gt; so everyone on the team starts with the same project map. You can also run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;graphify hook install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This rebuilds the graph after each git commit and sets up a merge driver so &lt;code&gt;graph.json&lt;/code&gt; does not get left with conflict markers when multiple people commit in parallel.&lt;/p&gt;
&lt;h2 id=&#34;privacy-and-cost&#34;&gt;Privacy and Cost
&lt;/h2&gt;&lt;p&gt;Graphify&amp;rsquo;s README is fairly clear about privacy boundaries.&lt;/p&gt;
&lt;p&gt;Code files are parsed locally through tree-sitter and do not trigger API calls. Video and audio can be transcribed locally with faster-whisper. Docs, PDFs, and images used for semantic extraction go through your AI assistant&amp;rsquo;s model API.&lt;/p&gt;
&lt;p&gt;For headless &lt;code&gt;graphify extract&lt;/code&gt;, you may need these environment variables:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ANTHROPIC_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GEMINI_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;GOOGLE_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;OPENAI_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;DEEPSEEK_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;MOONSHOT_API_KEY
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;OLLAMA_BASE_URL
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Local Ollama, AWS Bedrock, and Claude Code CLI can also be used as backends. The README also states that the project has no telemetry, usage tracking, or analytics.&lt;/p&gt;
&lt;p&gt;In practice, remember that local code parsing does not mean everything stays offline. When docs, PDFs, images, or cloud models are involved, you still need to consider the backend, API keys, enterprise compliance, and data boundaries.&lt;/p&gt;
&lt;h2 id=&#34;suitable-scenarios&#34;&gt;Suitable Scenarios
&lt;/h2&gt;&lt;p&gt;Graphify is suitable for several types of users:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Developers who want Claude Code, Codex, Cursor, and Gemini CLI to better understand project structure.&lt;/li&gt;
&lt;li&gt;People who need to quickly understand a large unfamiliar codebase.&lt;/li&gt;
&lt;li&gt;Teams that need to analyze code, SQL schemas, docs, and configuration together.&lt;/li&gt;
&lt;li&gt;People doing architecture review, PR review, or refactor impact analysis.&lt;/li&gt;
&lt;li&gt;Teams that want to expose project knowledge as an MCP tool for Agents.&lt;/li&gt;
&lt;li&gt;Technical leads who want to keep a &amp;ldquo;project map&amp;rdquo; for the team.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is not necessary for every project. For small scripts, one-off demos, or very simple repositories, normal search and README files may be enough. Graphify&amp;rsquo;s value shows up more clearly in projects with many modules, many docs, team collaboration, and frequent AI assistant involvement.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;Graphify matters because it moves AI coding assistants from &amp;ldquo;temporarily reading files&amp;rdquo; toward &amp;ldquo;a long-lived, queryable project knowledge graph.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;For developers, it does not replace the IDE, search, or LSP. It adds a structured memory layer for AI assistants: which modules matter, which concepts are tightly connected, which docs explain design rationale, and which communities a PR may affect. As Codex, Claude Code, Gemini CLI, Antigravity, and similar Agent tools become more common, this kind of project graph layer will become increasingly useful.&lt;/p&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/safishamsi/graphify&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;GitHub: safishamsi/graphify&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>What Is Vercel AI SDK? A Unified Toolkit for TypeScript Developers Building AI Apps</title>
        <link>https://knightli.com/en/2026/05/17/vercel-ai-sdk-typescript-agent-toolkit/</link>
        <pubDate>Sun, 17 May 2026 23:07:38 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/17/vercel-ai-sdk-typescript-agent-toolkit/</guid>
        <description>&lt;p&gt;&lt;code&gt;vercel/ai&lt;/code&gt; is the open-source AI SDK maintained by Vercel.&lt;/p&gt;
&lt;p&gt;Its positioning is clear: it gives TypeScript developers a unified toolkit for building AI applications and AI Agents. It comes from the team behind Next.js, but it is not limited to Next.js. It also supports React, Svelte, Vue, Angular, and runtimes such as Node.js.&lt;/p&gt;
&lt;p&gt;Project link: &lt;a class=&#34;link&#34; href=&#34;https://github.com/vercel/ai&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/vercel/ai&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you are building a chat app, AI writing tool, RAG application, tool-calling Agent, streaming interface, or a product that needs to connect multiple model providers behind one application, Vercel AI SDK is worth a close look.&lt;/p&gt;
&lt;h2 id=&#34;the-core-problem-it-solves&#34;&gt;The Core Problem It Solves
&lt;/h2&gt;&lt;p&gt;When building AI apps today, one of the biggest headaches is not whether you can call a model. It is that different model providers have different APIs, streaming formats, tool-calling conventions, error behavior, and frontend state-management needs.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;OpenAI has its own SDK and response formats.&lt;/li&gt;
&lt;li&gt;Anthropic has its own message structure.&lt;/li&gt;
&lt;li&gt;Google, xAI, Mistral, DeepSeek, Groq, and others all differ.&lt;/li&gt;
&lt;li&gt;Streaming output requires chunk handling.&lt;/li&gt;
&lt;li&gt;Tool calling requires structured requests initiated by the model.&lt;/li&gt;
&lt;li&gt;Chat UI also needs messages, loading states, cancellation, retry, and error display.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If every provider gets its own handwritten adapter, the project becomes complex very quickly.&lt;/p&gt;
&lt;p&gt;Vercel AI SDK tries to hide those differences behind a unified API. Developers write the app against one interface and connect different models through Providers.&lt;/p&gt;
&lt;h2 id=&#34;unified-provider-architecture&#34;&gt;Unified Provider Architecture
&lt;/h2&gt;&lt;p&gt;One key feature of Vercel AI SDK is that it is provider-agnostic. It is not tied to one model vendor.&lt;/p&gt;
&lt;p&gt;It can access OpenAI, Anthropic, Google, and other model providers through a unified API. The project README also notes that AI SDK uses Vercel AI Gateway by default, making it easier to reach multiple mainstream providers.&lt;/p&gt;
&lt;p&gt;That is useful in real engineering projects.&lt;/p&gt;
&lt;p&gt;Many AI products eventually depend on more than one model:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some tasks need strong reasoning models.&lt;/li&gt;
&lt;li&gt;Some tasks need cheap, fast models.&lt;/li&gt;
&lt;li&gt;Some tasks require multimodal models.&lt;/li&gt;
&lt;li&gt;Some tasks require long context.&lt;/li&gt;
&lt;li&gt;Some tasks require local or private deployment.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A unified provider architecture makes model switching, gray releases, cost control, and fallback strategies easier.&lt;/p&gt;
&lt;h2 id=&#34;streaming-output-is-key-to-frontend-ux&#34;&gt;Streaming Output Is Key to Frontend UX
&lt;/h2&gt;&lt;p&gt;One major UX difference between AI apps and traditional APIs is that responses can be long.&lt;/p&gt;
&lt;p&gt;If users must wait for a full answer before seeing anything, chat tools, writing tools, and coding assistants feel slow. Streaming output lets text appear gradually, so users see progress sooner.&lt;/p&gt;
&lt;p&gt;Vercel AI SDK provides fairly complete abstractions for streaming generation. Developers do not need to handle low-level event streams from scratch. They can use the SDK&amp;rsquo;s generation and streaming APIs to connect model output to frontend UI.&lt;/p&gt;
&lt;p&gt;This is especially convenient for Next.js and React applications.&lt;/p&gt;
&lt;p&gt;An AI chat interface looks simple, but in practice it must handle:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Message lists.&lt;/li&gt;
&lt;li&gt;User input.&lt;/li&gt;
&lt;li&gt;Server requests.&lt;/li&gt;
&lt;li&gt;Streaming token display.&lt;/li&gt;
&lt;li&gt;Loading states.&lt;/li&gt;
&lt;li&gt;Error states.&lt;/li&gt;
&lt;li&gt;Stopping generation.&lt;/li&gt;
&lt;li&gt;Regeneration.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These are exactly the kinds of repetitive work AI SDK tries to reduce.&lt;/p&gt;
&lt;h2 id=&#34;tool-calling-and-agent-scenarios&#34;&gt;Tool Calling and Agent Scenarios
&lt;/h2&gt;&lt;p&gt;As AI apps move from &amp;ldquo;chatting&amp;rdquo; to &amp;ldquo;doing things&amp;rdquo;, tool calling becomes increasingly important.&lt;/p&gt;
&lt;p&gt;The model may need to call external functions instead of only returning natural language:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Query a database.&lt;/li&gt;
&lt;li&gt;Search documents.&lt;/li&gt;
&lt;li&gt;Call business APIs.&lt;/li&gt;
&lt;li&gt;Read order status.&lt;/li&gt;
&lt;li&gt;Generate charts.&lt;/li&gt;
&lt;li&gt;Create calendar events.&lt;/li&gt;
&lt;li&gt;Modify project files.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Vercel AI SDK supports tool-calling capabilities, allowing developers to define tools, parameters, and execution logic, then let the model request those tools when appropriate.&lt;/p&gt;
&lt;p&gt;This is one reason it has evolved from a &amp;ldquo;chat UI SDK&amp;rdquo; into a broader toolkit for AI apps and Agents.&lt;/p&gt;
&lt;p&gt;Still, tool calling is not magic. Real projects must also handle:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Parameter validation.&lt;/li&gt;
&lt;li&gt;Permission boundaries.&lt;/li&gt;
&lt;li&gt;Tool-call logs.&lt;/li&gt;
&lt;li&gt;Idempotency.&lt;/li&gt;
&lt;li&gt;Timeouts and retries.&lt;/li&gt;
&lt;li&gt;Human confirmation.&lt;/li&gt;
&lt;li&gt;Restrictions for sensitive actions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;AI SDK can help with interfaces and flow, but developers still need to design the safety boundaries.&lt;/p&gt;
&lt;h2 id=&#34;ui-integration&#34;&gt;UI Integration
&lt;/h2&gt;&lt;p&gt;Vercel AI SDK is friendly to frontend frameworks.&lt;/p&gt;
&lt;p&gt;It provides not only core generation APIs, but also abstractions around chat, completion, message state, and streaming UI. For teams using Next.js and React, this can remove a lot of boilerplate.&lt;/p&gt;
&lt;p&gt;But it is not only for Vercel deployments.&lt;/p&gt;
&lt;p&gt;If your project is built with TypeScript, or your backend runs on Node.js, AI SDK can still serve as the model-calling and streaming layer. Whether you deploy to Vercel depends on your architecture, team habits, and infrastructure choices.&lt;/p&gt;
&lt;h2 id=&#34;skill-for-coding-agents&#34;&gt;Skill for Coding Agents
&lt;/h2&gt;&lt;p&gt;The &lt;code&gt;vercel/ai&lt;/code&gt; README includes an interesting suggestion: if you use coding agents such as Claude Code or Cursor, you can add the AI SDK skill to your repository.&lt;/p&gt;
&lt;p&gt;The example command is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npx skills add vercel/ai
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This shows that Vercel understands AI SDK users are not only human developers, but also coding agents.&lt;/p&gt;
&lt;p&gt;When an agent modifies a project that uses AI SDK, a dedicated skill in the repository can help it understand SDK conventions, common APIs, project structure, and best practices, reducing the chance of messy code changes.&lt;/p&gt;
&lt;p&gt;This direction is worth watching.&lt;/p&gt;
&lt;p&gt;In the future, open-source projects may provide not only README files and docs, but also structured skill instructions for AI coding agents. For complex SDKs, that could become a new developer-experience entry point.&lt;/p&gt;
&lt;h2 id=&#34;suitable-projects&#34;&gt;Suitable Projects
&lt;/h2&gt;&lt;p&gt;Vercel AI SDK is a good fit for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AI chat apps based on Next.js or React.&lt;/li&gt;
&lt;li&gt;Writing, Q&amp;amp;A, support, and coding assistants that need streaming output.&lt;/li&gt;
&lt;li&gt;AI products that need multiple model providers.&lt;/li&gt;
&lt;li&gt;Teams building quick RAG or document Q&amp;amp;A prototypes.&lt;/li&gt;
&lt;li&gt;Apps that need tool calling, function calling, or lightweight Agent capabilities.&lt;/li&gt;
&lt;li&gt;Teams already using TypeScript and Node.js.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is especially suitable for frontend and full-stack developers. The hard part of many AI apps is not only calling a model, but turning model output into a stable, smooth, interactive product experience.&lt;/p&gt;
&lt;h2 id=&#34;what-it-is-not-for&#34;&gt;What It Is Not For
&lt;/h2&gt;&lt;p&gt;If your project is mainly a Python backend, deep-learning training workflow, model fine-tuning system, or low-level inference service, Vercel AI SDK may not be the core tool.&lt;/p&gt;
&lt;p&gt;It is an application-layer SDK, not a model-training framework.&lt;/p&gt;
&lt;p&gt;If you need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Train your own model.&lt;/li&gt;
&lt;li&gt;Manage GPU inference clusters.&lt;/li&gt;
&lt;li&gt;Run low-level batch inference.&lt;/li&gt;
&lt;li&gt;Deeply control tokenizer behavior, KV cache, quantization, and inference engines.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Then you should look at PyTorch, vLLM, SGLang, TensorRT-LLM, llama.cpp, or cloud inference services.&lt;/p&gt;
&lt;p&gt;Vercel AI SDK is closer to the application layer that connects model capabilities to products.&lt;/p&gt;
&lt;h2 id=&#34;what-to-watch-for&#34;&gt;What to Watch For
&lt;/h2&gt;&lt;p&gt;First, do not assume a unified API means all providers are identical.&lt;/p&gt;
&lt;p&gt;Different providers still differ in capabilities, context length, tool-calling formats, streaming details, error types, and pricing. A unified SDK reduces engineering friction, but it does not erase model differences.&lt;/p&gt;
&lt;p&gt;Second, control costs.&lt;/p&gt;
&lt;p&gt;Once an AI app is online, streaming chats, retries, tool calls, RAG retrieval, and multi-model fallbacks can all increase cost. Rate limits, caching, logs, and budget monitoring are necessary.&lt;/p&gt;
&lt;p&gt;Third, handle safety boundaries.&lt;/p&gt;
&lt;p&gt;If a model can call tools, you must restrict what those tools can do. Do not let the model directly execute high-risk operations, and do not expose secrets, database write permissions, or production operations to it without controls.&lt;/p&gt;
&lt;p&gt;Fourth, keep observability.&lt;/p&gt;
&lt;p&gt;When an AI app fails, frontend errors are not enough. You need to know the user input, selected model, tool calls, response time, token usage, error type, and final output.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;vercel/ai&lt;/code&gt; is not a new model, and it is not just a chat component.&lt;/p&gt;
&lt;p&gt;It is closer to infrastructure for TypeScript AI application development: unified Providers, streaming output, tool calling, frontend state management, and Agent scenarios all live inside one open-source SDK.&lt;/p&gt;
&lt;p&gt;For teams already using Next.js, React, TypeScript, and Node.js, it can significantly reduce the engineering cost of going from &amp;ldquo;the model API runs&amp;rdquo; to &amp;ldquo;the product experience works&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;But it is not a universal layer. Model selection, permission design, cost control, logging, monitoring, and business safety still belong to the developer.&lt;/p&gt;
&lt;p&gt;If you want to build AI applications rather than train models, Vercel AI SDK is a toolkit worth trying early.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/vercel/ai&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;vercel/ai GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ai-sdk.dev/docs/introduction&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;AI SDK Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://vercel.com/blog/introducing-the-vercel-ai-sdk/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Vercel: Introducing the Vercel AI SDK&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Bun: JavaScript runtime, package manager, test runner, and bundler in one tool</title>
        <link>https://knightli.com/en/2026/05/17/bun-javascript-toolkit/</link>
        <pubDate>Sun, 17 May 2026 17:42:25 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/17/bun-javascript-toolkit/</guid>
        <description>&lt;p&gt;Bun is an open source JavaScript / TypeScript all-in-one toolchain from oven-sh.&lt;/p&gt;
&lt;p&gt;It is not just trying to be a faster Node.js replacement. It puts the runtime, package manager, script runner, test runner, and bundler behind the same &lt;code&gt;bun&lt;/code&gt; command. For frontend and Node.js developers, the appeal is simple: install fewer tools, wait less during installation and builds, and complete many common tasks with one command.&lt;/p&gt;
&lt;p&gt;Project: &lt;a class=&#34;link&#34; href=&#34;https://github.com/oven-sh/bun&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/oven-sh/bun&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&#34;bottom-line&#34;&gt;Bottom line
&lt;/h2&gt;&lt;p&gt;Bun is best for people who want to simplify the JavaScript toolchain.&lt;/p&gt;
&lt;p&gt;It can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run JavaScript, TypeScript, JSX, and TSX.&lt;/li&gt;
&lt;li&gt;Act as a Node.js-compatible runtime.&lt;/li&gt;
&lt;li&gt;Replace npm / yarn / pnpm for package management.&lt;/li&gt;
&lt;li&gt;Run scripts from &lt;code&gt;package.json&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Execute tests.&lt;/li&gt;
&lt;li&gt;Bundle frontend or backend code.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;bunx&lt;/code&gt; to run commands from npm packages.&lt;/li&gt;
&lt;li&gt;Provide built-in APIs such as &lt;code&gt;Bun.serve&lt;/code&gt;, &lt;code&gt;bun:sqlite&lt;/code&gt;, &lt;code&gt;Bun.sql&lt;/code&gt;, &lt;code&gt;Bun.redis&lt;/code&gt;, and &lt;code&gt;Bun.s3&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Its clearest value is developer experience: fast installs, fast startup, unified commands, and TypeScript / JSX that work out of the box.&lt;/p&gt;
&lt;p&gt;But Bun is not something every project should switch to immediately. Large Node.js applications, projects with many native extensions, and production services with strict stability requirements still need careful compatibility, build, test, and deployment validation.&lt;/p&gt;
&lt;h2 id=&#34;what-bun-is&#34;&gt;What Bun is
&lt;/h2&gt;&lt;p&gt;According to the official README, Bun is an all-in-one toolkit for JavaScript and TypeScript applications. It ships as a single executable named &lt;code&gt;bun&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;At its core is the Bun runtime: a fast JavaScript runtime intended as a drop-in replacement for Node.js. Bun is written in Zig, built on JavaScriptCore, and optimized for startup time and memory usage.&lt;/p&gt;
&lt;p&gt;That means you can run:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun run index.tsx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;TypeScript and JSX can run without extra setup.&lt;/p&gt;
&lt;p&gt;The same &lt;code&gt;bun&lt;/code&gt; command also includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;test runner&lt;/li&gt;
&lt;li&gt;script runner&lt;/li&gt;
&lt;li&gt;Node.js-compatible package manager&lt;/li&gt;
&lt;li&gt;bundler&lt;/li&gt;
&lt;li&gt;package runner&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Common commands include:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun run start
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun install &amp;lt;pkg&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bunx cowsay &lt;span class=&#34;s1&#34;&gt;&amp;#39;Hello, world!&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;A typical project may otherwise include &lt;code&gt;node&lt;/code&gt;, &lt;code&gt;npm&lt;/code&gt;, &lt;code&gt;pnpm&lt;/code&gt;, &lt;code&gt;tsx&lt;/code&gt;, &lt;code&gt;jest&lt;/code&gt;, &lt;code&gt;vitest&lt;/code&gt;, &lt;code&gt;webpack&lt;/code&gt;, &lt;code&gt;esbuild&lt;/code&gt;, and &lt;code&gt;ts-node&lt;/code&gt;. Bun tries to absorb many of those high-frequency paths into one tool.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation
&lt;/h2&gt;&lt;p&gt;Bun supports Linux, macOS, and Windows on x64 and arm64.&lt;/p&gt;
&lt;p&gt;The official install script is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -fsSL https://bun.com/install &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Windows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;powershell&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-c&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;irm bun.sh/install.ps1 | iex&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It can also be installed through npm:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm install -g bun
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;macOS Homebrew:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew tap oven-sh/bun
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install bun
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Docker:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker pull oven/bun
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker run --rm --init --ulimit &lt;span class=&#34;nv&#34;&gt;memlock&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;-1:-1 oven/bun
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Linux users should note the kernel requirement. The README strongly recommends Linux kernel &lt;code&gt;5.6&lt;/code&gt; or newer, with &lt;code&gt;5.1&lt;/code&gt; as the minimum.&lt;/p&gt;
&lt;p&gt;Upgrade to the latest version:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun upgrade
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Upgrade to canary:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun upgrade --canary
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Canary is usually not a good choice for production unless you are validating a new feature or investigating a specific bug.&lt;/p&gt;
&lt;h2 id=&#34;why-bun-is-fast&#34;&gt;Why Bun is fast
&lt;/h2&gt;&lt;p&gt;Bun’s speed comes from several layers.&lt;/p&gt;
&lt;p&gt;First, runtime startup is fast. Many CLI tools and development scripts are not limited by long CPU work, but by process startup, module loading, TypeScript transpilation, and dependency resolution. Bun optimizes these paths.&lt;/p&gt;
&lt;p&gt;Second, package management is fast. &lt;code&gt;bun install&lt;/code&gt; aims to replace npm / yarn / pnpm installation workflows. It uses a global cache and its own lockfile, which can noticeably reduce waiting time in dependency-heavy projects.&lt;/p&gt;
&lt;p&gt;Third, TypeScript / JSX work out of the box. Many projects only need to run a &lt;code&gt;.ts&lt;/code&gt; or &lt;code&gt;.tsx&lt;/code&gt; script. Traditional Node.js setups need &lt;code&gt;tsx&lt;/code&gt;, &lt;code&gt;ts-node&lt;/code&gt;, Babel, or a build step. Bun can run these files directly and reduces glue tooling.&lt;/p&gt;
&lt;p&gt;Fourth, built-in tools reduce process and configuration switching. Testing, scripts, bundling, and runtime execution all live in one tool.&lt;/p&gt;
&lt;p&gt;Still, “Bun is fast” does not mean every project will be faster. Real results depend on dependency types, script logic, test framework, build configuration, Node.js API usage, and CI cache strategy.&lt;/p&gt;
&lt;h2 id=&#34;package-management-replacing-npm--yarn--pnpm&#34;&gt;Package management: replacing npm / yarn / pnpm
&lt;/h2&gt;&lt;p&gt;Bun can install dependencies directly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Add a dependency:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun add react
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Add a development dependency:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun add -d typescript
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Remove a dependency:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun remove react
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Explain why a dependency exists:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun why react
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Security audit:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun audit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;When migrating from npm or pnpm, check:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Whether &lt;code&gt;bun.lock&lt;/code&gt; is committed.&lt;/li&gt;
&lt;li&gt;Whether CI uses &lt;code&gt;bun install --frozen-lockfile&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Whether private registries and &lt;code&gt;.npmrc&lt;/code&gt; are compatible.&lt;/li&gt;
&lt;li&gt;Whether workspace behavior matches expectations.&lt;/li&gt;
&lt;li&gt;Whether lifecycle scripts introduce security risk.&lt;/li&gt;
&lt;li&gt;Whether pnpm-specific monorepo behavior can migrate smoothly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Small projects can try it directly. Large monorepos should not switch everything at once; start with one package or a non-blocking CI job.&lt;/p&gt;
&lt;h2 id=&#34;running-scripts-and-typescript&#34;&gt;Running scripts and TypeScript
&lt;/h2&gt;&lt;p&gt;Bun can run scripts from &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun run start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It can also run files directly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun run index.ts
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun run index.tsx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This is useful for tool scripts such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;scripts/build.ts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scripts/seed.ts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scripts/migrate.ts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scripts/check.ts&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With Node.js, these often require a TypeScript loader or precompilation. Bun’s direct execution makes those scripts lighter.&lt;/p&gt;
&lt;p&gt;If a script depends on Node.js-specific behavior, especially loaders, ESM/CJS edges, native modules, child processes, file watching, or edge APIs, it still needs testing.&lt;/p&gt;
&lt;h2 id=&#34;test-runner&#34;&gt;Test runner
&lt;/h2&gt;&lt;p&gt;Bun includes a test runner:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It is suitable for small projects that want less Jest / Vitest configuration, and for moving some unit tests, tool tests, or library tests to a lighter runner.&lt;/p&gt;
&lt;p&gt;When migrating tests, pay attention to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;expect&lt;/code&gt; behavior.&lt;/li&gt;
&lt;li&gt;mock API differences.&lt;/li&gt;
&lt;li&gt;snapshot behavior.&lt;/li&gt;
&lt;li&gt;DOM test environment.&lt;/li&gt;
&lt;li&gt;test discovery rules.&lt;/li&gt;
&lt;li&gt;coverage output.&lt;/li&gt;
&lt;li&gt;CI reporter support.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If a project deeply depends on Jest features, such as custom matchers, complex mocks, jsdom, babel-jest, or ts-jest, migration should be gradual. Let new modules use &lt;code&gt;bun test&lt;/code&gt; while old suites remain on the existing framework.&lt;/p&gt;
&lt;h2 id=&#34;bundling-and-builds&#34;&gt;Bundling and builds
&lt;/h2&gt;&lt;p&gt;Bun also provides a bundler:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun build ./src/index.ts --outdir ./dist
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;It can be used for frontend bundles, backend scripts, CLI tools, and libraries. Bun’s docs also cover loaders, plugins, macros, CSS, HTML, HMR, minifier, and single-file executables.&lt;/p&gt;
&lt;p&gt;Good early candidates:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Small frontend tools.&lt;/li&gt;
&lt;li&gt;Node.js CLI projects.&lt;/li&gt;
&lt;li&gt;Internal scripts.&lt;/li&gt;
&lt;li&gt;Single-file services.&lt;/li&gt;
&lt;li&gt;Projects that do not depend on complex webpack loaders.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Be careful with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Complex webpack plugin chains.&lt;/li&gt;
&lt;li&gt;Large Vite plugin setups.&lt;/li&gt;
&lt;li&gt;Deep Babel transformations.&lt;/li&gt;
&lt;li&gt;Special CSS / asset pipelines.&lt;/li&gt;
&lt;li&gt;Micro-frontends and module federation.&lt;/li&gt;
&lt;li&gt;Projects with strict requirements for hashes, chunks, and compatibility.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bun’s bundler is attractive, but migrating build tools is usually riskier than changing the package manager. Validate it separately.&lt;/p&gt;
&lt;h2 id=&#34;running-http-services&#34;&gt;Running HTTP services
&lt;/h2&gt;&lt;p&gt;Bun provides &lt;code&gt;Bun.serve&lt;/code&gt; for HTTP services:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;Bun&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;serve&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;({&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;port&lt;/span&gt;: &lt;span class=&#34;kt&#34;&gt;3000&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nx&#34;&gt;fetch&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;req&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;return&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;new&lt;/span&gt; &lt;span class=&#34;nx&#34;&gt;Response&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;Hello from Bun&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;})&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This is convenient for small APIs, internal services, webhook receivers, and edge-style services. Bun also provides APIs such as WebSockets, Workers, Streams, SQLite, PostgreSQL, Redis, S3, and TCP/UDP sockets.&lt;/p&gt;
&lt;p&gt;If you already use Express, Fastify, NestJS, Next.js, Hono, Elysia, or another framework, check their Bun compatibility before rewriting anything.&lt;/p&gt;
&lt;p&gt;A practical path is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use Bun first for development scripts and package management.&lt;/li&gt;
&lt;li&gt;Then try Bun for tests.&lt;/li&gt;
&lt;li&gt;Only later evaluate whether the production runtime should move to Bun.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Runtime migration needs the most care because it directly affects production behavior.&lt;/p&gt;
&lt;h2 id=&#34;relationship-with-nodejs&#34;&gt;Relationship with Node.js
&lt;/h2&gt;&lt;p&gt;One of Bun’s goals is to be a drop-in replacement for Node.js, but compatibility is not the same as complete equivalence.&lt;/p&gt;
&lt;p&gt;The Node.js ecosystem has accumulated many subtle behaviors around:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;CJS / ESM interop.&lt;/li&gt;
&lt;li&gt;Node built-in modules.&lt;/li&gt;
&lt;li&gt;Native extensions.&lt;/li&gt;
&lt;li&gt;npm lifecycle scripts.&lt;/li&gt;
&lt;li&gt;Filesystem edge behavior.&lt;/li&gt;
&lt;li&gt;stream and Buffer details.&lt;/li&gt;
&lt;li&gt;worker / child_process.&lt;/li&gt;
&lt;li&gt;debugging and profiling.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Bun is improving compatibility quickly, but production migration should be judged by tests.&lt;/p&gt;
&lt;p&gt;Practical questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Do your tests pass under Bun?&lt;/li&gt;
&lt;li&gt;Do key dependencies support Bun?&lt;/li&gt;
&lt;li&gt;Are build artifacts equivalent?&lt;/li&gt;
&lt;li&gt;Are CI and local behavior consistent?&lt;/li&gt;
&lt;li&gt;Do you have monitoring and rollback in production?&lt;/li&gt;
&lt;li&gt;Are Docker images and deployment scripts stable?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Replacing only the package manager is lower risk. Replacing the production runtime is much higher risk.&lt;/p&gt;
&lt;h2 id=&#34;suitable-projects&#34;&gt;Suitable projects
&lt;/h2&gt;&lt;p&gt;Bun fits well for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New small JavaScript / TypeScript projects.&lt;/li&gt;
&lt;li&gt;Internal tools and scripts.&lt;/li&gt;
&lt;li&gt;CLI projects.&lt;/li&gt;
&lt;li&gt;CI jobs that need faster dependency installation.&lt;/li&gt;
&lt;li&gt;Frontend projects that want less toolchain complexity.&lt;/li&gt;
&lt;li&gt;Scripts and services where startup speed matters.&lt;/li&gt;
&lt;li&gt;Developers who want TypeScript to run out of the box.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use more caution with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Very large monorepos.&lt;/li&gt;
&lt;li&gt;Projects deeply tied to pnpm workspace behavior.&lt;/li&gt;
&lt;li&gt;Services with many Node.js native extensions.&lt;/li&gt;
&lt;li&gt;Frontend builds with highly customized pipelines.&lt;/li&gt;
&lt;li&gt;Backends that require strict production runtime consistency.&lt;/li&gt;
&lt;li&gt;Test suites deeply tied to Jest.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A conservative but practical strategy is to treat Bun as a development tool first, not as an immediate replacement for every production runtime.&lt;/p&gt;
&lt;h2 id=&#34;migration-advice&#34;&gt;Migration advice
&lt;/h2&gt;&lt;p&gt;To try Bun in an existing project:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install Bun locally.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;bun install&lt;/code&gt; and inspect dependency installation.&lt;/li&gt;
&lt;li&gt;Commit or temporarily keep &lt;code&gt;bun.lock&lt;/code&gt; to avoid lockfile confusion.&lt;/li&gt;
&lt;li&gt;Try &lt;code&gt;bun run &amp;lt;script&amp;gt;&lt;/code&gt; on common scripts.&lt;/li&gt;
&lt;li&gt;Migrate a small number of tests with &lt;code&gt;bun test&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add a non-blocking Bun job in CI.&lt;/li&gt;
&lt;li&gt;If compatibility looks good, consider changing the main install flow.&lt;/li&gt;
&lt;li&gt;Evaluate production runtime migration last.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For team projects, keep a rollback path:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Preserve the old npm / pnpm / yarn flow during migration.&lt;/li&gt;
&lt;li&gt;Run both flows in CI for a while.&lt;/li&gt;
&lt;li&gt;Do not change runtime, package manager, test framework, and bundler in the same change.&lt;/li&gt;
&lt;li&gt;Split migration into small, verifiable steps.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is slower, but it avoids mixing too many problems together.&lt;/p&gt;
&lt;h2 id=&#34;common-commands&#34;&gt;Common commands
&lt;/h2&gt;&lt;p&gt;Install:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -fsSL https://bun.com/install &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Upgrade:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun upgrade
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Install dependencies:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Add a dependency:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun add lodash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Run a script:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun run dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Run TypeScript directly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun run scripts/build.ts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Test:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun &lt;span class=&#34;nb&#34;&gt;test&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Bundle:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bun build ./src/index.ts --outdir ./dist
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Run a package command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;bunx cowsay &lt;span class=&#34;s1&#34;&gt;&amp;#39;Hello, world!&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;Bun’s value is not just “faster than Node.js.” More importantly, it pulls many scattered JavaScript / TypeScript development tools into one &lt;code&gt;bun&lt;/code&gt; command: runtime, package manager, script runner, test runner, and bundler.&lt;/p&gt;
&lt;p&gt;For new projects and internal tools, this integrated experience can be pleasant: fast installs, fast startup, less configuration, and direct TypeScript / JSX execution. For large existing projects, Bun is better introduced through low-risk areas first, such as package installation, scripts, and selected tests, before validating builds and runtime behavior.&lt;/p&gt;
&lt;p&gt;If Node.js toolchain installation speed, configuration fragments, and slow test startup often bother you, Bun is worth a serious try. But production migration still comes back to basic engineering judgment: do tests pass, are dependencies compatible, is CI stable, and do you have rollback?&lt;/p&gt;
&lt;p&gt;References:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/oven-sh/bun&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;oven-sh/bun&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://bun.com/docs&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Bun Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://bun.com/docs/installation&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Bun Installation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://bun.com/docs/runtime/nodejs-compat&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Bun Node.js compatibility&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Godot Game Development Beginner Guide: From Nodes and Scenes to Your First 2D Game</title>
        <link>https://knightli.com/en/2026/05/17/godot-game-development-beginner-guide/</link>
        <pubDate>Sun, 17 May 2026 12:37:30 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/17/godot-game-development-beginner-guide/</guid>
        <description>&lt;p&gt;Godot is an open-source game engine suitable for 2D games, independent prototypes, and medium-scale 3D projects.&lt;/p&gt;
&lt;p&gt;Its biggest strengths are that it is lightweight, open source, fast to start, and built around a clear node-and-scene model. For beginners, Godot is usually easier to approach than Unity. For independent developers, it is also easier to keep projects small and controllable.&lt;/p&gt;
&lt;p&gt;This guide keeps the path simple: understand nodes and scenes, learn basic GDScript, then build a small 2D game that connects input, physics, collision, UI, audio, and export.&lt;/p&gt;
&lt;h2 id=&#34;bottom-line&#34;&gt;Bottom line
&lt;/h2&gt;&lt;p&gt;Do not start by learning every engine feature.&lt;/p&gt;
&lt;p&gt;A better path is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start with 2D, not 3D.&lt;/li&gt;
&lt;li&gt;Understand nodes and scenes before complex architecture.&lt;/li&gt;
&lt;li&gt;Learn GDScript first, not C#.&lt;/li&gt;
&lt;li&gt;Build one small game that can start, fail, and restart.&lt;/li&gt;
&lt;li&gt;Then add animation, audio, UI, levels, and export.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Completing one tiny game teaches more than watching many unrelated tutorials.&lt;/p&gt;
&lt;h2 id=&#34;who-godot-is-good-for&#34;&gt;Who Godot is good for
&lt;/h2&gt;&lt;p&gt;Godot is a strong fit if you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;want to learn game development from zero,&lt;/li&gt;
&lt;li&gt;want to build 2D indie games,&lt;/li&gt;
&lt;li&gt;need fast gameplay prototypes,&lt;/li&gt;
&lt;li&gt;do not want a heavy commercial engine workflow,&lt;/li&gt;
&lt;li&gt;want to understand how engines organize game objects,&lt;/li&gt;
&lt;li&gt;have some Python or JavaScript experience and want an easy scripting language.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Unity and Unreal still have advantages for large commercial pipelines, asset stores, mobile monetization SDKs, or high-end 3D visuals. But for learning and making your own games, Godot is an excellent starting point.&lt;/p&gt;
&lt;h2 id=&#34;installation-and-project-creation&#34;&gt;Installation and project creation
&lt;/h2&gt;&lt;p&gt;Godot is simple to install: download it from the official website, unzip it, and run it.&lt;/p&gt;
&lt;p&gt;For the first project:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use the default renderer.&lt;/li&gt;
&lt;li&gt;Use an English project name.&lt;/li&gt;
&lt;li&gt;Avoid paths with too many spaces or non-ASCII characters.&lt;/li&gt;
&lt;li&gt;Use Git from the beginning.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A simple project name:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;first-godot-game
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Learn the editor areas first: Scene tree, FileSystem, Inspector, Script editor, and 2D / 3D viewport.&lt;/p&gt;
&lt;h2 id=&#34;core-idea-nodes-and-scenes&#34;&gt;Core idea: nodes and scenes
&lt;/h2&gt;&lt;p&gt;The two most important Godot concepts are nodes and scenes.&lt;/p&gt;
&lt;p&gt;Nodes are functional units:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Node2D&lt;/code&gt;: base 2D object.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Sprite2D&lt;/code&gt;: displays an image.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CollisionShape2D&lt;/code&gt;: collision shape.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CharacterBody2D&lt;/code&gt;: controllable character.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Camera2D&lt;/code&gt;: 2D camera.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;AudioStreamPlayer&lt;/code&gt;: audio playback.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Label&lt;/code&gt;: text display.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A scene is a reusable group of nodes. A player can be a scene, an enemy can be a scene, and a level can be a scene.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Player (CharacterBody2D)
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── Sprite2D
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── CollisionShape2D
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── Camera2D
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The player handles movement, &lt;code&gt;Sprite2D&lt;/code&gt; displays the image, &lt;code&gt;CollisionShape2D&lt;/code&gt; handles collision, and &lt;code&gt;Camera2D&lt;/code&gt; follows the player.&lt;/p&gt;
&lt;h2 id=&#34;what-to-build-first&#34;&gt;What to build first
&lt;/h2&gt;&lt;p&gt;Do not start with an RPG, open world, networking, or complex platformer.&lt;/p&gt;
&lt;p&gt;Build a tiny 2D dodging game:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The player moves up, down, left, and right.&lt;/li&gt;
&lt;li&gt;Enemies spawn from screen edges.&lt;/li&gt;
&lt;li&gt;Touching an enemy means failure.&lt;/li&gt;
&lt;li&gt;Survival time becomes score.&lt;/li&gt;
&lt;li&gt;There is a start button, game-over screen, and restart.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This small project covers movement, input, collision, spawning, UI, timers, audio, and scene reloads.&lt;/p&gt;
&lt;h2 id=&#34;player-movement&#34;&gt;Player movement
&lt;/h2&gt;&lt;p&gt;Use &lt;code&gt;CharacterBody2D&lt;/code&gt; for a controllable player.&lt;/p&gt;
&lt;p&gt;Attach a script to &lt;code&gt;Player&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-gdscript&#34; data-lang=&#34;gdscript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;extends&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;CharacterBody2D&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@export&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;speed&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;300.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;_physics_process&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;delta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;direction&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Vector2&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;ZERO&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;direction&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;x&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;get_axis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;move_left&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;move_right&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;direction&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;y&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Input&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;get_axis&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;move_up&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;move_down&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;direction&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;direction&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;normalized&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;velocity&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;direction&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;*&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;speed&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;move_and_slide&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then define input actions:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;move_left  -&amp;gt; A / Left
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;move_right -&amp;gt; D / Right
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;move_up    -&amp;gt; W / Up
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;move_down  -&amp;gt; S / Down
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Use input actions instead of hard-coded key codes. It makes keyboard, gamepad, touch, and remapping easier later.&lt;/p&gt;
&lt;h2 id=&#34;collision-and-physics&#34;&gt;Collision and physics
&lt;/h2&gt;&lt;p&gt;Common 2D nodes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CollisionShape2D&lt;/code&gt;: defines collision shape.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Area2D&lt;/code&gt;: detects overlap and triggers.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CharacterBody2D&lt;/code&gt;: player or controlled character.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;RigidBody2D&lt;/code&gt;: physics-driven object.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;StaticBody2D&lt;/code&gt;: walls, floors, fixed obstacles.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For beginners: if you control movement manually, use &lt;code&gt;CharacterBody2D&lt;/code&gt;. If you only need to detect contact, use &lt;code&gt;Area2D&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-gdscript&#34; data-lang=&#34;gdscript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;_on_body_entered&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;body&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;name&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;==&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;Player&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;        &lt;span class=&#34;nf&#34;&gt;get_tree&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;reload_current_scene&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Later, replace direct reloads with a &lt;code&gt;game_over&lt;/code&gt; signal. For the first project, getting the loop working is more important.&lt;/p&gt;
&lt;h2 id=&#34;instancing-enemies&#34;&gt;Instancing enemies
&lt;/h2&gt;&lt;p&gt;Godot scenes can be used like prefabs.&lt;/p&gt;
&lt;p&gt;If you have &lt;code&gt;Enemy.tscn&lt;/code&gt;, spawn it from the main scene:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-gdscript&#34; data-lang=&#34;gdscript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nd&#34;&gt;@export&lt;/span&gt; &lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;enemy_scene&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;PackedScene&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;spawn_enemy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;():&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;enemy&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;enemy_scene&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;instantiate&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;enemy&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;position&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Vector2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;800&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;randf_range&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;mi&#34;&gt;50&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;550&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nf&#34;&gt;add_child&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;enemy&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Add a &lt;code&gt;Timer&lt;/code&gt; to call &lt;code&gt;spawn_enemy()&lt;/code&gt; repeatedly.&lt;/p&gt;
&lt;h2 id=&#34;ui-and-score&#34;&gt;UI and score
&lt;/h2&gt;&lt;p&gt;Use &lt;code&gt;Control&lt;/code&gt; nodes for UI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;CanvasLayer&lt;/code&gt;: keeps UI fixed on screen.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Label&lt;/code&gt;: text.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Button&lt;/code&gt;: button.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Panel&lt;/code&gt;: background.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VBoxContainer&lt;/code&gt; / &lt;code&gt;HBoxContainer&lt;/code&gt;: layout.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Simple survival score:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-gdscript&#34; data-lang=&#34;gdscript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;var&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;score&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0.0&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;func&lt;/span&gt; &lt;span class=&#34;nf&#34;&gt;_process&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;delta&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;score&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;+=&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;delta&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nx&#34;&gt;$CanvasLayer/ScoreLabel&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;text&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nb&#34;&gt;str&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;kt&#34;&gt;int&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;score&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;audio-and-feedback&#34;&gt;Audio and feedback
&lt;/h2&gt;&lt;p&gt;Even simple games need feedback:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;click sounds,&lt;/li&gt;
&lt;li&gt;hit sounds,&lt;/li&gt;
&lt;li&gt;score sounds,&lt;/li&gt;
&lt;li&gt;failure sounds,&lt;/li&gt;
&lt;li&gt;screen shake or flash,&lt;/li&gt;
&lt;li&gt;button hover / pressed states.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Use &lt;code&gt;AudioStreamPlayer&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-gdscript&#34; data-lang=&#34;gdscript&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;$HitSound&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;nf&#34;&gt;play&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Functionality is only the first step. Good feedback makes the player feel the game responding.&lt;/p&gt;
&lt;h2 id=&#34;project-organization&#34;&gt;Project organization
&lt;/h2&gt;&lt;p&gt;Start with clean folders:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;res://
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── scenes/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── Main.tscn
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── Player.tscn
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── Enemy.tscn
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── scripts/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── player.gd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── enemy.gd
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;├── assets/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   ├── sprites/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;│   └── audio/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;└── ui/
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    └── GameOver.tscn
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Do not dump everything into the root directory. Small games grow faster than expected.&lt;/p&gt;
&lt;h2 id=&#34;common-beginner-mistakes&#34;&gt;Common beginner mistakes
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Choosing the wrong node type.&lt;/li&gt;
&lt;li&gt;Forgetting collision shapes.&lt;/li&gt;
&lt;li&gt;Hard-coding keyboard keys.&lt;/li&gt;
&lt;li&gt;Putting player, enemies, UI, audio, and level logic into one script.&lt;/li&gt;
&lt;li&gt;Starting with a project that is too large.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A tiny finished game is more valuable than an abandoned big idea.&lt;/p&gt;
&lt;h2 id=&#34;suggested-learning-path&#34;&gt;Suggested learning path
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Editor basics.&lt;/li&gt;
&lt;li&gt;Nodes and scenes.&lt;/li&gt;
&lt;li&gt;GDScript basics.&lt;/li&gt;
&lt;li&gt;Input actions.&lt;/li&gt;
&lt;li&gt;2D movement.&lt;/li&gt;
&lt;li&gt;Collision and &lt;code&gt;Area2D&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Timer&lt;/code&gt; and spawning.&lt;/li&gt;
&lt;li&gt;UI and score.&lt;/li&gt;
&lt;li&gt;Audio and animation.&lt;/li&gt;
&lt;li&gt;Export to desktop or web.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;godot-vs-unity&#34;&gt;Godot vs Unity
&lt;/h2&gt;&lt;p&gt;Godot is comfortable for 2D indie games, teaching projects, and personal prototypes.&lt;/p&gt;
&lt;p&gt;Unity still has stronger asset stores, commercial plugins, mobile ads, monetization SDKs, and mature team workflows.&lt;/p&gt;
&lt;p&gt;Unreal is better for high-end 3D and advanced rendering.&lt;/p&gt;
&lt;p&gt;For beginners, do not let engine choice become procrastination. The core skills are game loops, input, collision, feedback, scene organization, state management, and version control.&lt;/p&gt;
&lt;h2 id=&#34;completion-checklist&#34;&gt;Completion checklist
&lt;/h2&gt;&lt;p&gt;You have really completed the first step when your game has:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;player movement,&lt;/li&gt;
&lt;li&gt;enemies or obstacles,&lt;/li&gt;
&lt;li&gt;collision failure,&lt;/li&gt;
&lt;li&gt;score or objective,&lt;/li&gt;
&lt;li&gt;start screen,&lt;/li&gt;
&lt;li&gt;game-over screen,&lt;/li&gt;
&lt;li&gt;restart,&lt;/li&gt;
&lt;li&gt;at least two sounds,&lt;/li&gt;
&lt;li&gt;simple animation or visual feedback,&lt;/li&gt;
&lt;li&gt;an exported playable build.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;Godot&amp;rsquo;s entry point is not memorizing every feature. It is understanding how the engine organizes games: nodes form scenes, scenes form games, scripts drive behavior, signals connect events, and resources live in folders.&lt;/p&gt;
&lt;p&gt;Start with a small 2D game. Once movement, collision, UI, audio, and restart work, then learn animation trees, TileMap, saving, state machines, 3D, shaders, and export optimization.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Ghostty Docs Quick Read: Installation, Configuration, and Daily Usage Notes</title>
        <link>https://knightli.com/en/2026/05/15/ghostty-docs-install-config-usage-guide/</link>
        <pubDate>Fri, 15 May 2026 14:50:11 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/15/ghostty-docs-install-config-usage-guide/</guid>
        <description>&lt;p&gt;Ghostty is a new terminal emulator, but it is not simply &amp;ldquo;another faster terminal.&amp;rdquo; According to its official documentation, it tries to balance three goals at the same time: speed, features, and a native desktop experience. In other words, it wants GPU acceleration and solid rendering performance, while also feeling like a real local app on macOS and Linux instead of pushing every interaction into a custom-drawn interface.&lt;/p&gt;
&lt;p&gt;If you currently use iTerm2, Kitty, Alacritty, WezTerm, or the system terminal, the most interesting part of Ghostty is not one isolated feature. It is the way it combines &amp;ldquo;works out of the box&amp;rdquo; with &amp;ldquo;deeply configurable.&amp;rdquo; The default configuration is already usable, but when you want to tune it further, the docs provide complete entry points for configuration files, themes, keybindings, fonts, Shell integration, and terminal control sequences.&lt;/p&gt;
&lt;h2 id=&#34;start-with-the-positioning&#34;&gt;Start with the Positioning
&lt;/h2&gt;&lt;p&gt;Ghostty&amp;rsquo;s core positioning can be summarized in three points:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is a cross-platform terminal emulator, currently focused on macOS and Linux.&lt;/li&gt;
&lt;li&gt;It uses platform-native UI: Swift, AppKit, and SwiftUI on macOS; Zig and GTK4 on Linux.&lt;/li&gt;
&lt;li&gt;Its terminal core is &lt;code&gt;libghostty&lt;/code&gt;, and the GUI applications are built around this shared core.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This design affects daily use. Tabs, splits, error prompts, window state restoration, system shortcuts, and similar features are not merely components that &amp;ldquo;look like a desktop app.&amp;rdquo; They try to follow the interaction conventions of each operating system. The default shortcuts on macOS and Linux also differ according to platform expectations.&lt;/p&gt;
&lt;h2 id=&#34;installation-direct-on-macos-distribution-dependent-on-linux&#34;&gt;Installation: Direct on macOS, Distribution-Dependent on Linux
&lt;/h2&gt;&lt;p&gt;The official prebuilt binaries mainly target macOS. The most common installation path is to download the &lt;code&gt;.dmg&lt;/code&gt;, open it, and drag Ghostty into the Applications folder. Homebrew users can also use the community-maintained cask:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install --cask ghostty
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Linux is more fragmented. The Ghostty docs separate package managers, community binaries, and source builds for different distributions. Arch, Alpine, Gentoo, NixOS, Snap, Solus, Void, and others all have their own paths. If a distribution has no official or trusted repository, the docs lean toward building from source rather than casually installing third-party binaries.&lt;/p&gt;
&lt;p&gt;This matters especially on servers and workstations: a terminal emulator handles a large amount of input and output, clipboard data, links, SSH sessions, and local file paths. It is better to be conservative with the installation source, preferring the official macOS package, distribution repositories, or a build process whose source you can audit.&lt;/p&gt;
&lt;h2 id=&#34;configuration-do-not-rush-to-copy-a-giant-dotfiles-setup&#34;&gt;Configuration: Do Not Rush to Copy a Giant dotfiles Setup
&lt;/h2&gt;&lt;p&gt;Ghostty&amp;rsquo;s configuration philosophy is &amp;ldquo;usable with zero configuration.&amp;rdquo; The default font includes JetBrains Mono and Nerd Font support, so most users can work normally the first time they open it. The docs even suggest that if you must configure a non-subjective option to feel comfortable, it may be worth asking whether that behavior should become the default.&lt;/p&gt;
&lt;p&gt;When you do need customization, Ghostty uses a text configuration file. The current configuration file name is &lt;code&gt;config.ghostty&lt;/code&gt;, while older versions also support &lt;code&gt;config&lt;/code&gt;. Common paths include:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$XDG_CONFIG_HOME/ghostty/config.ghostty
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$XDG_CONFIG_HOME/ghostty/config
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$HOME/.config/ghostty/config.ghostty
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$HOME/.config/ghostty/config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;On macOS, Ghostty also reads:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$HOME/Library/Application Support/com.mitchellh.ghostty/config.ghostty
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;$HOME/Library/Application Support/com.mitchellh.ghostty/config
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The syntax is straightforward: &lt;code&gt;key = value&lt;/code&gt;. For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;font-family = JetBrains Mono
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;font-size = 14
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;theme = light:Rose Pine Dawn,dark:Rose Pine
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;keybind = ctrl+shift+t=new_tab
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;A practical suggestion: do not start by copying someone else&amp;rsquo;s full configuration. A steadier approach is to run it bare for a few days and change only three things at first: font family, font size, and theme. Once you actually feel friction around shortcuts, splits, windows, or Shell integration, add those settings one by one.&lt;/p&gt;
&lt;h2 id=&#34;documentation-lookup-full-configuration-reference-is-available-locally&#34;&gt;Documentation Lookup: Full Configuration Reference Is Available Locally
&lt;/h2&gt;&lt;p&gt;Ghostty has many configuration options, and the official docs collect them in the Option Reference. Besides the web page, you can query the reference locally after installation:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghostty +show-config --default --docs
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This command prints the default configuration and documentation to standard output, which is useful when piped into a pager:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghostty +show-config --default --docs &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; less
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To list available fonts:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghostty +list-fonts
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To list built-in and available themes:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghostty +list-themes
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To view default keybindings:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghostty +list-keybinds --default
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;These commands are more reliable than copying snippets from the web, because they come from the Ghostty version installed on your own machine.&lt;/p&gt;
&lt;h2 id=&#34;keybindings-treat-actions-as-the-core-concept&#34;&gt;Keybindings: Treat &amp;ldquo;Actions&amp;rdquo; as the Core Concept
&lt;/h2&gt;&lt;p&gt;Ghostty&amp;rsquo;s keybinding format is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;keybind = trigger=action
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;trigger&lt;/code&gt; is the key sequence, and &lt;code&gt;action&lt;/code&gt; is the operation Ghostty performs. Creating a new tab, closing the current surface, reloading configuration, and jumping to a prompt are all actions. The model is clear: you are not &amp;ldquo;changing a menu item&amp;rdquo;; you are binding an input sequence to an action.&lt;/p&gt;
&lt;p&gt;After changing configuration, you can reload it at runtime. The default shortcut is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Linux: &lt;code&gt;ctrl+shift+,&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;macOS: &lt;code&gt;cmd+shift+,&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Not every setting takes effect immediately. Some options only affect newly created terminals, while others require a full restart. If &amp;ldquo;the config is written but nothing changed,&amp;rdquo; check the documentation for that option before spending too much time suspecting syntax.&lt;/p&gt;
&lt;h2 id=&#34;themes-and-fonts-use-built-ins-first-then-tune&#34;&gt;Themes and Fonts: Use Built-Ins First, Then Tune
&lt;/h2&gt;&lt;p&gt;Ghostty ships with many themes and supports switching themes according to the system light or dark mode:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;theme = light:Rose Pine Dawn,dark:Rose Pine
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Themes can also come from custom files. The docs are clear here: a theme file is essentially a Ghostty configuration file and can set many options, so do not casually use themes from untrusted sources.&lt;/p&gt;
&lt;p&gt;For fonts, &lt;code&gt;font-family&lt;/code&gt; can be repeated to specify fallback fonts. This is useful in multilingual environments: the primary font can handle English and symbols, while later fonts cover Chinese, Japanese, or other characters. When you encounter display details such as emoji, bold, italic, or ligatures, look up the corresponding options in the Option Reference.&lt;/p&gt;
&lt;h2 id=&#34;shell-integration-especially-important-for-ssh-users&#34;&gt;Shell Integration: Especially Important for SSH Users
&lt;/h2&gt;&lt;p&gt;Ghostty supports automatic Shell integration injection for &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;elvish&lt;/code&gt;, &lt;code&gt;fish&lt;/code&gt;, &lt;code&gt;nushell&lt;/code&gt;, and &lt;code&gt;zsh&lt;/code&gt;. When enabled, several interactions become more natural:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;New terminals can open in the previous terminal&amp;rsquo;s working directory.&lt;/li&gt;
&lt;li&gt;Complex prompts can redraw correctly after resize instead of reflowing badly.&lt;/li&gt;
&lt;li&gt;You can jump between command outputs using prompt markers.&lt;/li&gt;
&lt;li&gt;Cursor behavior at the prompt can better match editing habits.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you do not want automatic injection, disable it in the configuration:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;shell-integration = none
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;SSH deserves extra attention. Ghostty uses &lt;code&gt;xterm-ghostty&lt;/code&gt; as &lt;code&gt;TERM&lt;/code&gt;, but many remote hosts do not yet have the corresponding terminfo. The docs provide two Shell integration features, &lt;code&gt;ssh-env&lt;/code&gt; and &lt;code&gt;ssh-terminfo&lt;/code&gt;, which are disabled by default and can be enabled as needed:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;shell-integration-features = ssh-env,ssh-terminfo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you often connect to old servers, containers, bastion hosts, or tightly managed production environments, read the official Terminfo and Shell Integration docs before enabling these features. Terminal capability negotiation looks minor, but when it goes wrong, the symptoms can be strange colors, broken shortcuts, or garbled full-screen programs.&lt;/p&gt;
&lt;h2 id=&#34;my-suggested-onboarding-order&#34;&gt;My Suggested Onboarding Order
&lt;/h2&gt;&lt;p&gt;If you only want to judge whether Ghostty fits you, try this sequence:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install it and use it for a day without writing any configuration.&lt;/li&gt;
&lt;li&gt;Adjust only &lt;code&gt;font-family&lt;/code&gt;, &lt;code&gt;font-size&lt;/code&gt;, and &lt;code&gt;theme&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;ghostty +list-keybinds --default&lt;/code&gt; to inspect default shortcuts instead of importing someone else&amp;rsquo;s shortcut table first.&lt;/li&gt;
&lt;li&gt;If you use SSH often, check remote host terminfo compatibility early.&lt;/li&gt;
&lt;li&gt;Finally, tune splits, windows, transparency, title bar, background image, and other visual or workflow preferences.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ghostty&amp;rsquo;s docs are engineering-oriented. They are better read as a configuration reference manual than as a marketing page. For most users, the real evaluation criteria are simple: does the default experience already feel comfortable, and are your daily editor, Shell, SSH, tmux, or Zellij workflows stable? If those pieces work well, Ghostty deserves a place on your long-term terminal shortlist.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Ghostty Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs/about&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;About Ghostty&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs/config&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs/config/keybind&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Custom Keybindings&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs/install/binary&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Prebuilt Ghostty Binaries and Packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://ghostty.org/docs/features/shell-integration&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Shell Integration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>How to Change the VS Code Display Language: Chinese, English, and More</title>
        <link>https://knightli.com/en/2026/05/08/vscode-switch-display-language/</link>
        <pubDate>Fri, 08 May 2026 13:18:57 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/08/vscode-switch-display-language/</guid>
        <description>&lt;p&gt;VS Code supports many display languages. The usual approach is to install the matching language pack, then choose the display language from the Command Palette. If you want to pin VS Code to a specific language, you can also edit the &lt;code&gt;locale&lt;/code&gt; value in &lt;code&gt;argv.json&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This method works not only for Simplified Chinese, but also for English, Traditional Chinese, Japanese, Korean, French, German, Spanish, and other languages.&lt;/p&gt;
&lt;h2 id=&#34;install-the-language-pack&#34;&gt;Install the Language Pack
&lt;/h2&gt;&lt;p&gt;If you want to switch to a non-English interface, you usually need to install a language pack first.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open the Extensions panel in the left sidebar, or press &lt;code&gt;Ctrl+Shift+X&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Search for the target language, such as &lt;code&gt;Chinese&lt;/code&gt;, &lt;code&gt;Japanese&lt;/code&gt;, &lt;code&gt;Korean&lt;/code&gt;, or &lt;code&gt;French&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select the matching language pack and click &lt;code&gt;Install&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Restart VS Code when prompted.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For Simplified Chinese, the common language pack is &lt;code&gt;Chinese (Simplified)&lt;/code&gt;. For Traditional Chinese, use &lt;code&gt;Chinese (Traditional)&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;change-the-language-from-the-command-palette&#34;&gt;Change the Language from the Command Palette
&lt;/h2&gt;&lt;p&gt;This is the recommended method for most users.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open the Command Palette with &lt;code&gt;Ctrl+Shift+P&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Type &lt;code&gt;Configure Display Language&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Select the &lt;code&gt;Configure Display Language&lt;/code&gt; command.&lt;/li&gt;
&lt;li&gt;Choose the language you want from the list.&lt;/li&gt;
&lt;li&gt;Restart VS Code when prompted.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;After restarting, menus, settings pages, and common prompts will use the selected language. If the target language is not listed, install its language pack from the Extensions panel first.&lt;/p&gt;
&lt;h2 id=&#34;set-the-language-manually-in-argvjson&#34;&gt;Set the Language Manually in argv.json
&lt;/h2&gt;&lt;p&gt;If switching from the Command Palette does not work, or if you want to explicitly lock VS Code to a language, you can edit the runtime arguments file directly.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open the Command Palette with &lt;code&gt;Ctrl+Shift+P&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Type and select &lt;code&gt;Preferences: Configure Runtime Arguments&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Find or add the &lt;code&gt;locale&lt;/code&gt; setting.&lt;/li&gt;
&lt;li&gt;Change its value to the target language code.&lt;/li&gt;
&lt;li&gt;Save the file and restart VS Code.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For example, switch to English:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;locale&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;en&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Switch to Simplified Chinese:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;locale&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;zh-cn&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Switch to Japanese:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;locale&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;ja&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;argv.json&lt;/code&gt; is a JSON file, so pay attention to commas and quotation marks. If the configuration is invalid, VS Code may not read the language setting correctly.&lt;/p&gt;
&lt;h2 id=&#34;common-display-language-codes&#34;&gt;Common Display Language Codes
&lt;/h2&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Display language&lt;/th&gt;
          &lt;th&gt;locale&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;English (US)&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;en&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Simplified Chinese&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;zh-cn&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Traditional Chinese&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;zh-tw&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;French&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;fr&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;German&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;de&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Italian&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;it&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Spanish&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;es&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Japanese&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;ja&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Korean&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;ko&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Russian&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;ru&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Portuguese (Brazil)&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;pt-br&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Turkish&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;tr&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Bulgarian&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;bg&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Hungarian&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;hu&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id=&#34;what-to-do-if-the-language-does-not-change&#34;&gt;What to Do If the Language Does Not Change
&lt;/h2&gt;&lt;p&gt;Check the following items in order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Confirm that the target language pack is installed.&lt;/li&gt;
&lt;li&gt;Confirm that &lt;code&gt;locale&lt;/code&gt; uses the correct language code. For example, Simplified Chinese is &lt;code&gt;zh-cn&lt;/code&gt;, not &lt;code&gt;zh-CN&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Fully close and reopen VS Code after changing the language.&lt;/li&gt;
&lt;li&gt;If you edited &lt;code&gt;argv.json&lt;/code&gt; manually, check that the JSON syntax is valid.&lt;/li&gt;
&lt;li&gt;If the configuration is messy, remove the &lt;code&gt;locale&lt;/code&gt; entry and choose the language again through &lt;code&gt;Configure Display Language&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;In most cases, &lt;code&gt;Configure Display Language&lt;/code&gt; is the simplest option. Edit &lt;code&gt;argv.json&lt;/code&gt; only when you need to force a specific language or the Command Palette switch does not take effect.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://blog.csdn.net/mighty13/article/details/114420578&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;VScode: Change the VS Code display language to Simplified Chinese and switch the VS Code display language&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>opencode, Claude Code, and Codex: What&#39;s the Difference? A Guide to Open Source AI Coding Tools</title>
        <link>https://knightli.com/en/2026/05/08/opencode-open-source-ai-coding-agent/</link>
        <pubDate>Fri, 08 May 2026 08:33:37 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/08/opencode-open-source-ai-coding-agent/</guid>
        <description>&lt;p&gt;&lt;code&gt;opencode&lt;/code&gt; is an open source AI Coding Agent from anomalyco. Its positioning is straightforward: give developers a programmable, extensible coding assistant in the terminal that can connect to multiple model providers.&lt;/p&gt;
&lt;p&gt;If you compare it with &lt;code&gt;Claude Code&lt;/code&gt; and &lt;code&gt;Codex&lt;/code&gt;, all three solve the same broad problem: bringing AI into real codebases so it can understand context, edit files, run commands, and execute tests. But their product directions are different.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;opencode&lt;/code&gt; emphasizes open source, multi-model support, and a terminal TUI. &lt;code&gt;Claude Code&lt;/code&gt; emphasizes Anthropic&amp;rsquo;s model ecosystem and local engineering collaboration. &lt;code&gt;Codex&lt;/code&gt; is OpenAI&amp;rsquo;s AI coding agent, available through the terminal, IDEs, the Codex app, and cloud tasks.&lt;/p&gt;
&lt;h2 id=&#34;who-opencode-is-for&#34;&gt;Who opencode Is For
&lt;/h2&gt;&lt;p&gt;opencode is a better fit for these kinds of developers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;People who want to complete code changes, project analysis, and engineering tasks in the terminal.&lt;/li&gt;
&lt;li&gt;People who do not want their AI Coding Agent tied to a single model provider.&lt;/li&gt;
&lt;li&gt;People who prefer open source tools and want to audit, extend, or build on top of them.&lt;/li&gt;
&lt;li&gt;People already comfortable with Neovim, TUIs, and command-line workflows.&lt;/li&gt;
&lt;li&gt;People who want to eventually drive the same coding agent remotely through a desktop app, mobile app, or other clients.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Its point is not to create another chat window, but to put AI coding capability inside the terminal and project directories developers already use.&lt;/p&gt;
&lt;h2 id=&#34;installation&#34;&gt;Installation
&lt;/h2&gt;&lt;p&gt;The official README provides several installation methods.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;20
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;21
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Direct install&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -fsSL https://opencode.ai/install &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# npm&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;npm i -g opencode-ai@latest
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;scoop install opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;choco install opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# macOS and Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install anomalyco/tap/opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Arch Linux&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo pacman -S opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;paru -S opencode-bin
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Other methods&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;mise use -g opencode
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;nix run nixpkgs#opencode
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The official README also recommends removing versions older than 0.1.x before installing to avoid problems caused by older remnants.&lt;/p&gt;
&lt;p&gt;The installation script chooses the installation directory by priority:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;$OPENCODE_INSTALL_DIR&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$XDG_BIN_DIR&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$HOME/bin&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;$HOME/.opencode/bin&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you need to specify a path, use:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;OPENCODE_INSTALL_DIR&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;/usr/local/bin curl -fsSL https://opencode.ai/install &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;XDG_BIN_DIR&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;/.local/bin curl -fsSL https://opencode.ai/install &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; bash
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;the-desktop-app-is-still-beta&#34;&gt;The Desktop App Is Still Beta
&lt;/h2&gt;&lt;p&gt;In addition to the command-line tool, opencode also provides a desktop app, currently marked as Beta. It can be downloaded from GitHub Releases or &lt;code&gt;opencode.ai/download&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The desktop app covers these platforms:&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Platform&lt;/th&gt;
          &lt;th&gt;File&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;macOS Apple Silicon&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;opencode-desktop-mac-arm64.dmg&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;macOS Intel&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;opencode-desktop-mac-x64.dmg&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Windows&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;opencode-desktop-windows-x64.exe&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Linux&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;.deb&lt;/code&gt;, &lt;code&gt;.rpm&lt;/code&gt;, or &lt;code&gt;.AppImage&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;macOS and Windows users can also install the desktop app through package managers.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# macOS&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install --cask opencode-desktop
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Windows&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;scoop bucket add extras
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;scoop install extras/opencode-desktop
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;two-built-in-agent-modes&#34;&gt;Two Built-In Agent Modes
&lt;/h2&gt;&lt;p&gt;opencode includes two built-in Agents, switchable with the &lt;code&gt;Tab&lt;/code&gt; key.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;build&lt;/code&gt; is the default mode. It has full development permissions and is suitable for editing code directly, running commands, and moving engineering tasks forward.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;plan&lt;/code&gt; is read-only mode. It is better for analyzing unfamiliar codebases, understanding project structure, and planning changes. It denies file edits by default and asks before running bash commands.&lt;/p&gt;
&lt;p&gt;opencode also includes a &lt;code&gt;general&lt;/code&gt; subagent for complex searches and multi-step tasks. Users can invoke it by typing &lt;code&gt;@general&lt;/code&gt; in a message.&lt;/p&gt;
&lt;p&gt;This design is practical: use &lt;code&gt;plan&lt;/code&gt; to understand the project before acting, then switch to &lt;code&gt;build&lt;/code&gt; when code needs to change. For large repositories, separating read and write permissions helps reduce mistakes.&lt;/p&gt;
&lt;h2 id=&#34;what-is-codex&#34;&gt;What Is Codex?
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Codex&lt;/code&gt; is OpenAI&amp;rsquo;s AI coding agent for helping developers write code, review code, fix bugs, and ship engineering tasks.&lt;/p&gt;
&lt;p&gt;Unlike a simple code completion tool, Codex is closer to an Agent that can operate on a codebase. It can pair with you in local tools, and it can also take delegated tasks in the cloud. OpenAI&amp;rsquo;s official materials describe Codex as available through multiple surfaces, including CLI, IDEs, the Codex app, and ChatGPT/Codex cloud workflows.&lt;/p&gt;
&lt;p&gt;For developers, Codex has several important traits:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It can read codebases, edit files, run commands, and execute tests.&lt;/li&gt;
&lt;li&gt;It supports multiple interfaces, including terminal, IDE, app, and cloud.&lt;/li&gt;
&lt;li&gt;It fits bug fixing, feature work, refactoring, migrations, code review, and test generation.&lt;/li&gt;
&lt;li&gt;It is more closely tied to OpenAI accounts, models, and the Codex product ecosystem.&lt;/li&gt;
&lt;li&gt;Cloud tasks are useful for running multiple well-scoped engineering tasks in parallel.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If opencode is more like an open terminal agent framework, Codex is more like a full AI coding workbench from OpenAI: local pairing, cloud delegation, and longer engineering workflows for teams.&lt;/p&gt;
&lt;h2 id=&#34;core-differences&#34;&gt;Core Differences
&lt;/h2&gt;&lt;p&gt;opencode, Claude Code, and Codex are all AI coding tools, but the choice becomes clearer if you look at these dimensions.&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Tool&lt;/th&gt;
          &lt;th&gt;Core Positioning&lt;/th&gt;
          &lt;th&gt;Main Advantages&lt;/th&gt;
          &lt;th&gt;Best Fit&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;opencode&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Open source AI Coding Agent&lt;/td&gt;
          &lt;td&gt;Open source, multi-model, TUI, client/server architecture&lt;/td&gt;
          &lt;td&gt;Developers who want an open toolchain, replaceable models, and a terminal-first workflow&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;Claude Code&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;Anthropic&amp;rsquo;s command-line coding tool&lt;/td&gt;
          &lt;td&gt;Claude model experience, code understanding, long context, engineering task collaboration&lt;/td&gt;
          &lt;td&gt;Developers already using the Claude/Anthropic ecosystem who want to work on local code tasks&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;&lt;code&gt;Codex&lt;/code&gt;&lt;/td&gt;
          &lt;td&gt;OpenAI&amp;rsquo;s AI coding agent&lt;/td&gt;
          &lt;td&gt;CLI, IDE, Codex app, cloud tasks, multi-Agent workflows&lt;/td&gt;
          &lt;td&gt;Teams already using ChatGPT/OpenAI who want both local pairing and cloud delegation&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;In short, opencode is about openness and replaceability, Claude Code is about the Claude ecosystem and local engineering agents, and Codex is about the OpenAI ecosystem and multi-surface collaboration.&lt;/p&gt;
&lt;h2 id=&#34;how-it-differs-from-claude-code&#34;&gt;How It Differs From Claude Code
&lt;/h2&gt;&lt;p&gt;opencode&amp;rsquo;s official FAQ directly compares it with Claude Code. The two are similar in capability, but the main differences are these.&lt;/p&gt;
&lt;p&gt;First, opencode is a 100% open source project, hosted on GitHub and released under the MIT license.&lt;/p&gt;
&lt;p&gt;Second, opencode is not tied to a single model provider. It recommends models provided through OpenCode Zen, but it can also work with Claude, OpenAI, Google, or local models. For developers, this means that when model cost, capability, or availability changes, you are not locked into one platform.&lt;/p&gt;
&lt;p&gt;Third, opencode includes optional LSP support. For code completion, navigation, diagnostics, and project understanding, LSP is a very important foundation.&lt;/p&gt;
&lt;p&gt;Fourth, opencode emphasizes TUI. It is built by Neovim users and the creators of terminal.shop, so the product focus is clearly on the terminal experience.&lt;/p&gt;
&lt;p&gt;Fifth, opencode uses a client/server architecture. That means opencode can run on your computer while being controlled in the future by a TUI, desktop app, mobile app, or other clients. The TUI is only one possible frontend.&lt;/p&gt;
&lt;h2 id=&#34;when-to-choose-opencode-claude-code-or-codex&#34;&gt;When to Choose opencode, Claude Code, or Codex
&lt;/h2&gt;&lt;p&gt;If you already use Claude Code or Codex, opencode does not have to replace them immediately. A better way to think about it is that opencode provides an open, model-replaceable, terminal-first option.&lt;/p&gt;
&lt;p&gt;Consider opencode first when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You want your AI coding tool to be as open source as possible.&lt;/li&gt;
&lt;li&gt;You do not want your workflow tied to one model provider.&lt;/li&gt;
&lt;li&gt;You want to test Claude, OpenAI, Google, or local models with the same tool.&lt;/li&gt;
&lt;li&gt;You like TUI workflows and do not want a desktop or web app to interrupt your main workflow.&lt;/li&gt;
&lt;li&gt;You care about the remote-control potential of a client/server architecture.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Consider Claude Code first when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You mainly use Claude models.&lt;/li&gt;
&lt;li&gt;You care about long context, code understanding, and complex engineering task collaboration.&lt;/li&gt;
&lt;li&gt;You want to keep moving edits, tests, and refactors forward in a local repository.&lt;/li&gt;
&lt;li&gt;You trust Anthropic&amp;rsquo;s default Claude Code product experience.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Consider Codex first when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You already use ChatGPT or the OpenAI account ecosystem.&lt;/li&gt;
&lt;li&gt;You want one coding agent across terminal, IDE, desktop app, and cloud tasks.&lt;/li&gt;
&lt;li&gt;You want to delegate well-scoped bug fixes, feature work, migrations, or test generation to the cloud in parallel.&lt;/li&gt;
&lt;li&gt;You need code review, background tasks, team collaboration, and multi-Agent workflows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you care more about an official end-to-end experience, default model configuration, enterprise management, and ready-made integrations, Claude Code or Codex may be easier. If you care more about control, openness, and being provider-agnostic, opencode is worth watching.&lt;/p&gt;
&lt;h2 id=&#34;things-to-note&#34;&gt;Things to Note
&lt;/h2&gt;&lt;p&gt;opencode, Claude Code, and Codex are all moving quickly. GitHub releases, installation commands, desktop app file names, model availability, and plan access can all change. Before installing or choosing a tool, check the official README, documentation, and release pages.&lt;/p&gt;
&lt;p&gt;Also, opencode&amp;rsquo;s desktop app is still marked as Beta, so it should not be treated as the default stable production tool. For everyday engineering tasks, the terminal version is still the main entry point.&lt;/p&gt;
&lt;p&gt;From a tooling trend perspective, opencode represents the open-toolchain direction for AI Coding Agents: replaceable models, replaceable clients, and an open core agent capability. Codex and Claude Code are closer to model companies turning coding agents into complete product surfaces. For developers, both directions will likely coexist for a long time.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;opencode GitHub: &lt;a class=&#34;link&#34; href=&#34;https://github.com/anomalyco/opencode&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/anomalyco/opencode&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;opencode official site: &lt;a class=&#34;link&#34; href=&#34;https://opencode.ai&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://opencode.ai&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;opencode docs: &lt;a class=&#34;link&#34; href=&#34;https://opencode.ai/docs&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://opencode.ai/docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;opencode Releases: &lt;a class=&#34;link&#34; href=&#34;https://github.com/anomalyco/opencode/releases&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/anomalyco/opencode/releases&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenAI Codex: &lt;a class=&#34;link&#34; href=&#34;https://openai.com/codex/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://openai.com/codex/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Using Codex with your ChatGPT plan: &lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/11369540-codex-in-chatgpt&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://help.openai.com/en/articles/11369540-codex-in-chatgpt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;OpenAI Codex CLI Getting Started: &lt;a class=&#34;link&#34; href=&#34;https://help.openai.com/en/articles/11096431-openai-codex-ci-getting-started&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://help.openai.com/en/articles/11096431-openai-codex-ci-getting-started&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>uv Installation Guide: Choosing Between macOS, Linux, Windows, pipx, Homebrew, and WinGet</title>
        <link>https://knightli.com/en/2026/05/07/uv-installation-guide/</link>
        <pubDate>Thu, 07 May 2026 23:23:58 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/07/uv-installation-guide/</guid>
        <description>&lt;p&gt;&lt;code&gt;uv&lt;/code&gt; is a Python toolchain manager from Astral. It can manage Python versions, virtual environments, dependencies, scripts, projects, and tools. There are many ways to install it. The official documentation provides standalone installer scripts and also supports PyPI, Homebrew, WinGet, Scoop, Docker, GitHub Releases, and Cargo.&lt;/p&gt;
&lt;p&gt;If you just want a quick installation, use the official standalone installer first. If you prefer your system package manager to maintain versions, use Homebrew, WinGet, or Scoop. If you already like installing Python tools in isolated environments, use &lt;code&gt;pipx&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;quick-choice&#34;&gt;Quick Choice
&lt;/h2&gt;&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;Scenario&lt;/th&gt;
          &lt;th&gt;Recommended method&lt;/th&gt;
          &lt;th&gt;Command&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;Quick install on macOS / Linux&lt;/td&gt;
          &lt;td&gt;Official standalone installer&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;curl -LsSf https://astral.sh/uv/install.sh | sh&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;macOS / Linux without curl&lt;/td&gt;
          &lt;td&gt;Official script + wget&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;wget -qO- https://astral.sh/uv/install.sh | sh&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Quick install on Windows&lt;/td&gt;
          &lt;td&gt;PowerShell installer&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;powershell -ExecutionPolicy ByPass -c &amp;quot;irm https://astral.sh/uv/install.ps1 | iex&amp;quot;&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Isolated Python tool install&lt;/td&gt;
          &lt;td&gt;pipx&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;pipx install uv&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Temporary or traditional Python install&lt;/td&gt;
          &lt;td&gt;pip&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;pip install uv&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;macOS package management&lt;/td&gt;
          &lt;td&gt;Homebrew&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;brew install uv&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;macOS MacPorts users&lt;/td&gt;
          &lt;td&gt;MacPorts&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;sudo port install uv&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Windows package management&lt;/td&gt;
          &lt;td&gt;WinGet&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;winget install --id=astral-sh.uv -e&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Windows Scoop users&lt;/td&gt;
          &lt;td&gt;Scoop&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;scoop install main/uv&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;Rust users&lt;/td&gt;
          &lt;td&gt;Cargo&lt;/td&gt;
          &lt;td&gt;&lt;code&gt;cargo install --locked uv&lt;/code&gt;&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The generally recommended options are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;macOS / Linux: official standalone installer;&lt;/li&gt;
&lt;li&gt;Windows: official PowerShell installer or WinGet;&lt;/li&gt;
&lt;li&gt;If you already manage Python CLI tools with &lt;code&gt;pipx&lt;/code&gt;: &lt;code&gt;pipx install uv&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;macos-and-linux-official-installer&#34;&gt;macOS and Linux: Official Installer
&lt;/h2&gt;&lt;p&gt;The most direct official method is to download the script with &lt;code&gt;curl&lt;/code&gt; and run it with &lt;code&gt;sh&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -LsSf https://astral.sh/uv/install.sh &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If the system does not have &lt;code&gt;curl&lt;/code&gt;, use &lt;code&gt;wget&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;wget -qO- https://astral.sh/uv/install.sh &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To install a specific version, put the version number in the URL. For example, the official example uses &lt;code&gt;0.11.11&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;curl -LsSf https://astral.sh/uv/0.11.11/install.sh &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sh
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This method fits most personal development environments. It is simple, cross-platform, and works best with uv&amp;rsquo;s official update mechanism.&lt;/p&gt;
&lt;p&gt;The installer puts binaries such as &lt;code&gt;uv&lt;/code&gt; and &lt;code&gt;uvx&lt;/code&gt; under the user directory, and may modify the shell profile so the commands can be used directly in the terminal. If you do not want the installer to modify PATH, check the official installer options, such as setting &lt;code&gt;UV_NO_MODIFY_PATH=1&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;windows-powershell-installer&#34;&gt;Windows: PowerShell Installer
&lt;/h2&gt;&lt;p&gt;The official Windows method is to run the installer script with PowerShell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;powershell&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-ExecutionPolicy&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ByPass&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-c&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;irm https://astral.sh/uv/install.ps1 | iex&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To install a specific version, also put the version number in the URL:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;powershell&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-ExecutionPolicy&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;ByPass&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-c&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;irm https://astral.sh/uv/0.11.11/install.ps1 | iex&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;ExecutionPolicy ByPass&lt;/code&gt; allows PowerShell to fetch and run the installer script from the internet. As a safer habit, you can inspect the script before running it:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;powershell&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-c&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;irm https://astral.sh/uv/install.ps1 | more&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you prefer Windows package managers, WinGet or Scoop may be a better first choice.&lt;/p&gt;
&lt;h2 id=&#34;installing-with-pipx&#34;&gt;Installing with pipx
&lt;/h2&gt;&lt;p&gt;The official documentation notes that uv is published to PyPI. If you install from PyPI, it is recommended to put it in an isolated environment, for example with &lt;code&gt;pipx&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pipx install uv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This is suitable if you already use &lt;code&gt;pipx&lt;/code&gt; as your Python CLI tool manager. It avoids mixing uv with your current project environment.&lt;/p&gt;
&lt;p&gt;If you do not have &lt;code&gt;pipx&lt;/code&gt;, you can also use &lt;code&gt;pip&lt;/code&gt; directly:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install uv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Note that uv provides prebuilt wheels on many platforms. If a platform does not have a matching wheel, it will build from source, which requires a Rust toolchain.&lt;/p&gt;
&lt;p&gt;My suggestion: on a personal machine, &lt;code&gt;pipx install uv&lt;/code&gt; is cleaner than &lt;code&gt;pip install uv&lt;/code&gt;; inside a project environment, do not install uv as a project dependency.&lt;/p&gt;
&lt;h2 id=&#34;homebrew-macports-winget-and-scoop&#34;&gt;Homebrew, MacPorts, WinGet, and Scoop
&lt;/h2&gt;&lt;p&gt;If you prefer system package managers, uv also supports common channels.&lt;/p&gt;
&lt;p&gt;Use Homebrew on macOS:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;brew install uv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;MacPorts users can use:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo port install uv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Use WinGet on Windows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;winget&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;install&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;-&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;-id&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;astral-sh&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;uv&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-e&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Scoop users can use:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;scoop&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;install&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;main&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;uv&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The benefit of these methods is that version maintenance is delegated to the system package manager. The downside is that update timing depends on the corresponding package source, not the uv official installer.&lt;/p&gt;
&lt;h2 id=&#34;docker-github-releases-and-cargo&#34;&gt;Docker, GitHub Releases, and Cargo
&lt;/h2&gt;&lt;p&gt;uv also provides Docker images on GitHub Container Registry:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ghcr.io/astral-sh/uv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This is suitable for CI, Dockerfiles, image builds, and temporary runtime environments. In real usage, read the official Docker integration documentation as well.&lt;/p&gt;
&lt;p&gt;If you want to download binaries manually, use GitHub Releases. Each release page usually includes binaries for supported platforms and explains how to invoke the standalone installer with a GitHub URL.&lt;/p&gt;
&lt;p&gt;Rust users can also install from crates.io:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cargo install --locked uv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This builds from source and requires a compatible Rust toolchain. Unless you specifically want to install from the Rust ecosystem, ordinary users do not need to choose Cargo first.&lt;/p&gt;
&lt;h2 id=&#34;upgrading-uv&#34;&gt;Upgrading uv
&lt;/h2&gt;&lt;p&gt;If uv was installed with the official standalone installer, use the self-update command:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv self update
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The official documentation notes that updating uv reruns the installer and may modify the shell profile. If you do not want the update to modify PATH, set:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;UV_NO_MODIFY_PATH&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you installed uv another way, use the corresponding package manager. For example, if you installed it with &lt;code&gt;pip&lt;/code&gt;, use:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;pip install --upgrade uv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Homebrew, WinGet, Scoop, and MacPorts should also use their own upgrade commands.&lt;/p&gt;
&lt;h2 id=&#34;enabling-shell-completion&#34;&gt;Enabling Shell Completion
&lt;/h2&gt;&lt;p&gt;uv supports shell completion. The official documentation recommends checking your current shell first:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$SHELL&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Bash:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;eval &amp;#34;$(uv generate-shell-completion bash)&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Zsh:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;eval &amp;#34;$(uv generate-shell-completion zsh)&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; ~/.zshrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;fish:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;uv generate-shell-completion fish | source&amp;#39;&lt;/span&gt; &amp;gt; ~/.config/fish/completions/uv.fish
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;PowerShell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(!(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Test-Path&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Path&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$PROFILE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nb&#34;&gt;New-Item&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-ItemType&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Path&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$PROFILE&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Force&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;Add-Content&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Path&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$PROFILE&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Value&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;(&amp;amp; uv generate-shell-completion powershell) | Out-String | Invoke-Expression&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you often use &lt;code&gt;uvx&lt;/code&gt;, you can enable completion for &lt;code&gt;uvx&lt;/code&gt; separately.&lt;/p&gt;
&lt;p&gt;Bash:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;eval &amp;#34;$(uvx --generate-shell-completion bash)&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; ~/.bashrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Zsh:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;eval &amp;#34;$(uvx --generate-shell-completion zsh)&amp;#34;&amp;#39;&lt;/span&gt; &amp;gt;&amp;gt; ~/.zshrc
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;fish:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;echo&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;uvx --generate-shell-completion fish | source&amp;#39;&lt;/span&gt; &amp;gt; ~/.config/fish/completions/uvx.fish
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;PowerShell:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(!(&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;Test-Path&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Path&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$PROFILE&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;))&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nb&#34;&gt;New-Item&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-ItemType&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;File&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Path&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$PROFILE&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Force&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;Add-Content&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Path&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$PROFILE&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;-Value&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;(&amp;amp; uvx --generate-shell-completion powershell) | Out-String | Invoke-Expression&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;After configuration, restart the shell or reload the corresponding configuration file.&lt;/p&gt;
&lt;h2 id=&#34;uninstalling-uv&#34;&gt;Uninstalling uv
&lt;/h2&gt;&lt;p&gt;To uninstall uv, you can first clean the cache and uv-managed data:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv cache clean
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rm -r &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;uv python dir&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rm -r &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;$(&lt;/span&gt;uv tool dir&lt;span class=&#34;k&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then delete the binaries.&lt;/p&gt;
&lt;p&gt;macOS / Linux:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;rm ~/.local/bin/uv ~/.local/bin/uvx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Windows:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;rm &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;\.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;local&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;uv&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;exe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;rm &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;\.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;local&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;uvx&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;exe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;rm &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$HOME&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;\.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;local&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;bin&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;\&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;uvw&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;exe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The official documentation also notes that before &lt;code&gt;0.5.0&lt;/code&gt;, uv installed into &lt;code&gt;~/.cargo/bin&lt;/code&gt;. If you upgraded from an earlier version, old binaries may still be there and need to be removed manually.&lt;/p&gt;
&lt;h2 id=&#34;what-to-do-after-installation&#34;&gt;What to Do After Installation
&lt;/h2&gt;&lt;p&gt;After installation, check the version first:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then start with a few common tasks:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv python install
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv venv
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uv pip install requests
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;uvx ruff --version
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;For a new project, continue with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;uv init&lt;/code&gt;: initialize a project;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uv add&lt;/code&gt;: add dependencies;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uv sync&lt;/code&gt;: sync the environment;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uv run&lt;/code&gt;: run commands inside the project environment;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;uvx&lt;/code&gt;: run Python CLI tools temporarily.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;my-recommendation&#34;&gt;My Recommendation
&lt;/h2&gt;&lt;p&gt;On a personal development machine, prefer the official standalone installer because it follows the uv official documentation most closely and supports &lt;code&gt;uv self update&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Windows users who do not want to run a remote script can use WinGet or Scoop. macOS users who prefer managing all tools with Homebrew can directly use &lt;code&gt;brew install uv&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you already manage Python CLI tools with &lt;code&gt;pipx&lt;/code&gt;, use &lt;code&gt;pipx install uv&lt;/code&gt;. But I do not recommend installing uv with &lt;code&gt;pip install uv&lt;/code&gt; inside a specific project virtual environment, because that tends to mix the toolchain with project dependencies.&lt;/p&gt;
&lt;p&gt;For CI or container builds, start with Docker and GitHub Releases, and pin versions according to your image build process.&lt;/p&gt;
&lt;h2 id=&#34;related-links&#34;&gt;Related Links
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;uv installation documentation: &lt;a class=&#34;link&#34; href=&#34;https://docs.astral.sh/uv/getting-started/installation/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://docs.astral.sh/uv/getting-started/installation/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;uv First steps: &lt;a class=&#34;link&#34; href=&#34;https://docs.astral.sh/uv/getting-started/first-steps/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://docs.astral.sh/uv/getting-started/first-steps/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;uv Docker integration: &lt;a class=&#34;link&#34; href=&#34;https://docs.astral.sh/uv/guides/integration/docker/&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://docs.astral.sh/uv/guides/integration/docker/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;uv GitHub Releases: &lt;a class=&#34;link&#34; href=&#34;https://github.com/astral-sh/uv/releases&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/astral-sh/uv/releases&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Awesome Codex Skills: A Community Catalog for Extending Codex CLI</title>
        <link>https://knightli.com/en/2026/05/07/awesome-codex-skills-composio/</link>
        <pubDate>Thu, 07 May 2026 20:19:15 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/07/awesome-codex-skills-composio/</guid>
        <description>&lt;p&gt;ComposioHQ&amp;rsquo;s &lt;a class=&#34;link&#34; href=&#34;https://github.com/ComposioHQ/awesome-codex-skills&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;awesome-codex-skills&lt;/a&gt; is a community catalog for Codex CLI skills. Its value is not another pile of prompt templates, but a way to package repeatable workflows into installable, reusable, and maintainable Skills.&lt;/p&gt;
&lt;p&gt;If you already use Codex as part of daily development, this kind of repository is immediately useful: rules, commands, reference materials, and operating steps that you used to explain again and again can be written down once, then reused whenever the matching Skill is invoked.&lt;/p&gt;
&lt;h2 id=&#34;what-this-repository-solves&#34;&gt;What This Repository Solves
&lt;/h2&gt;&lt;p&gt;Codex Skills can be understood as specialized work modes for Codex CLI. A normal prompt is good for one temporary instruction; a Skill is better for something you want to reuse over time.&lt;/p&gt;
&lt;p&gt;For example, you may often need to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;generate commit messages in a fixed format;&lt;/li&gt;
&lt;li&gt;look up a specific family of API documentation;&lt;/li&gt;
&lt;li&gt;run project-specific test and deployment commands;&lt;/li&gt;
&lt;li&gt;rewrite articles, translate docs, or organize notes according to team rules;&lt;/li&gt;
&lt;li&gt;call external tools for repetitive development tasks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Typing these instructions every time quickly becomes overhead. A Skill puts the rules into a standalone directory. The core is usually a &lt;code&gt;SKILL.md&lt;/code&gt; file, sometimes accompanied by scripts, templates, reference documents, or assets. When Codex is triggered, it reads the instructions and follows the workflow described there.&lt;/p&gt;
&lt;h2 id=&#34;how-it-differs-from-a-prompt&#34;&gt;How It Differs From a Prompt
&lt;/h2&gt;&lt;p&gt;A prompt is more like a one-off instruction: &amp;ldquo;do this task this way.&amp;rdquo; A Skill is closer to a small operating manual: &amp;ldquo;whenever this class of task appears, work in this way.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Its main advantages are:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Reusable&lt;/strong&gt;: common workflows no longer need copy-and-paste setup.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reviewable&lt;/strong&gt;: skill files are usually local Markdown files that can be opened, edited, and versioned.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Extensible&lt;/strong&gt;: complex skills can include scripts, templates, and references, not just natural language instructions.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That is why catalogs like &lt;code&gt;awesome-codex-skills&lt;/code&gt; are useful: they help you discover existing skills, then adapt them to your own workflow.&lt;/p&gt;
&lt;h2 id=&#34;installation-and-use&#34;&gt;Installation and Use
&lt;/h2&gt;&lt;p&gt;The repository provides an installation script and also supports manual installation. A typical flow is:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;git clone https://github.com/ComposioHQ/awesome-codex-skills.git
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; awesome-codex-skills
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;python install.py
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you only want to try a few skills, read the &lt;code&gt;SKILL.md&lt;/code&gt; in each skill directory first. Check what it reads, what scripts it may run, what files it may edit, and whether the defaults fit your local environment.&lt;/p&gt;
&lt;p&gt;After installation, Codex can match skills when the task calls for them, or you can name a skill explicitly. For long-term use, the most practical approach is often to install a community skill first, then rewrite the instructions around your own project conventions.&lt;/p&gt;
&lt;h2 id=&#34;which-skills-are-worth-watching&#34;&gt;Which Skills Are Worth Watching
&lt;/h2&gt;&lt;p&gt;The most valuable skills are not necessarily the ones with the flashiest names. They are the ones that reliably remove repeated work.&lt;/p&gt;
&lt;p&gt;I would first look at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Development workflow skills&lt;/strong&gt;: review, testing, commits, releases, dependency checks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation skills&lt;/strong&gt;: rewriting, translation, summarization, structured organization.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Tool integration skills&lt;/strong&gt;: connecting Codex to external services, APIs, and CLI tools.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Project convention skills&lt;/strong&gt;: encoding team rules, directory structure, naming conventions, and deployment steps.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If a skill merely wraps a single sentence prompt, it has limited value. If it can connect research, judgment, execution, verification, and output into a stable workflow, it is worth keeping.&lt;/p&gt;
&lt;h2 id=&#34;what-to-watch-out-for&#34;&gt;What to Watch Out For
&lt;/h2&gt;&lt;p&gt;Community skills are convenient, but they should not be treated as black boxes. This is especially true for Skills that include scripts. Before installing one, check:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;what &lt;code&gt;SKILL.md&lt;/code&gt; asks Codex to do;&lt;/li&gt;
&lt;li&gt;whether it includes scripts that access the network, read or write files, or call external services;&lt;/li&gt;
&lt;li&gt;whether the default paths, commands, and permissions fit your machine.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A Skill expands what Codex can do. Written well, it makes Codex feel more like a teammate who knows your project. Written carelessly, it can bring unsuitable rules into your workflow. The best pattern is not to install many skills, but to keep a small set, tune them carefully, and maintain them over time.&lt;/p&gt;
&lt;h2 id=&#34;my-take&#34;&gt;My Take
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;awesome-codex-skills&lt;/code&gt; is worth bookmarking, especially if you already use Codex CLI for real development, documentation, or automation work. It is not an official capability by itself; it is a community entry point for finding and adapting reusable workflows.&lt;/p&gt;
&lt;p&gt;For heavy users, the point of Codex Skills is not simply helping AI remember more. It is helping AI make fewer detours on repeated tasks. Writing rules as Skills turns temporary instructions into reusable working infrastructure.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Warp Open Source: From Terminal to Agentic Development Environment</title>
        <link>https://knightli.com/en/2026/05/07/warpdotdev-warp-open-source-agentic-terminal/</link>
        <pubDate>Thu, 07 May 2026 20:15:08 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/05/07/warpdotdev-warp-open-source-agentic-terminal/</guid>
        <description>&lt;p&gt;&lt;code&gt;warpdotdev/warp&lt;/code&gt; is the open-source client repository for Warp. Warp now describes itself as an &amp;ldquo;agentic development environment, born out of the terminal&amp;rdquo;: it starts from the terminal, but brings AI coding agents, codebase indexing, task management, and development workflows into one environment.&lt;/p&gt;
&lt;p&gt;This is not an ordinary open-source terminal emulator repository. It is closer to an answer to a larger question: as agents such as Claude Code, Codex, and Gemini CLI become common, should the terminal itself become a development environment for scheduling, observing, and managing agents?&lt;/p&gt;
&lt;p&gt;Warp&amp;rsquo;s answer is yes.&lt;/p&gt;
&lt;h2 id=&#34;current-state-of-the-repository&#34;&gt;Current State of the Repository
&lt;/h2&gt;&lt;p&gt;As of May 7, 2026, &lt;code&gt;warpdotdev/warp&lt;/code&gt; is a public repository. GitHub shows roughly 56k stars and 4.1k forks. The README says the Warp client code is now open source and welcomes community contributions.&lt;/p&gt;
&lt;p&gt;The main language is Rust. GitHub&amp;rsquo;s language breakdown shows Rust at over 98%, which matches Warp&amp;rsquo;s positioning: it is not a web wrapper, but a cross-platform native development tool.&lt;/p&gt;
&lt;p&gt;Several README details matter:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Warp is an agentic development environment, born out of the terminal.&lt;/li&gt;
&lt;li&gt;It can use its built-in coding agent and can also connect to external CLI agents such as Claude Code, Codex, and Gemini CLI.&lt;/li&gt;
&lt;li&gt;OpenAI is the founding sponsor of the newly open-sourced Warp repository.&lt;/li&gt;
&lt;li&gt;The agentic management workflows in the repository are powered by GPT models.&lt;/li&gt;
&lt;li&gt;Warp UI framework crates use the MIT license, while the rest of the code uses AGPL v3.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This shows that Warp&amp;rsquo;s open source move is not merely publishing a terminal. It is operating the project as an experiment ground for agent workflows.&lt;/p&gt;
&lt;h2 id=&#34;warp-is-more-than-a-terminal&#34;&gt;Warp Is More Than a Terminal
&lt;/h2&gt;&lt;p&gt;Traditional terminals mainly do three things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;start a shell;&lt;/li&gt;
&lt;li&gt;run commands;&lt;/li&gt;
&lt;li&gt;display output.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Warp&amp;rsquo;s earlier differentiation was making the terminal feel more modern: command blocks, completion, history, collaboration, UI-style interactions, and cross-platform polish. Now the focus has moved further toward organizing development around AI agents.&lt;/p&gt;
&lt;p&gt;From the README, Warp no longer only emphasizes &amp;ldquo;a better terminal.&amp;rdquo; It emphasizes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;built-in coding agents;&lt;/li&gt;
&lt;li&gt;external CLI agent support;&lt;/li&gt;
&lt;li&gt;issue triage;&lt;/li&gt;
&lt;li&gt;spec writing;&lt;/li&gt;
&lt;li&gt;PR review;&lt;/li&gt;
&lt;li&gt;contributor coordination;&lt;/li&gt;
&lt;li&gt;observable agent sessions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In other words, Warp wants to turn the terminal from &amp;ldquo;where you type commands&amp;rdquo; into &amp;ldquo;where you work with multiple agents.&amp;rdquo;&lt;/p&gt;
&lt;h2 id=&#34;oz-and-open-source-project-management&#34;&gt;Oz and Open-Source Project Management
&lt;/h2&gt;&lt;p&gt;The README mentions &lt;code&gt;Oz&lt;/code&gt; several times.&lt;/p&gt;
&lt;p&gt;Warp&amp;rsquo;s contribution overview shows thousands of Oz agents working on issue triage, specs, implementation, and PR review. This is interesting because it extends AI agents from &amp;ldquo;helping one person write code&amp;rdquo; to &amp;ldquo;helping manage open-source collaboration.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The hardest part of many open-source projects is not writing code, but maintenance:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;too many issues, not enough classification;&lt;/li&gt;
&lt;li&gt;bugs and feature requests mixed together;&lt;/li&gt;
&lt;li&gt;new contributors unsure which tasks are approachable;&lt;/li&gt;
&lt;li&gt;PR review pressure;&lt;/li&gt;
&lt;li&gt;maintainers struggling to follow every community thread.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Warp&amp;rsquo;s idea is to let agents take on part of the project management and collaboration work first. The README also mentions &lt;code&gt;Oz for OSS&lt;/code&gt;, a maintainer-facing program for bringing similar agentic open-source management workflows to other repositories.&lt;/p&gt;
&lt;p&gt;This suggests that Warp&amp;rsquo;s ambition is not only the terminal product itself, but also a new model of open-source maintenance in the AI era.&lt;/p&gt;
&lt;h2 id=&#34;repository-structure-and-tech-stack&#34;&gt;Repository Structure and Tech Stack
&lt;/h2&gt;&lt;p&gt;From the repository structure, Warp is a large Rust project.&lt;/p&gt;
&lt;p&gt;The root contains:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;app/&lt;/code&gt;: main application code.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;crates/&lt;/code&gt;: core Rust crates.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;assets/&lt;/code&gt;: resource files.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;command-signatures-v2/&lt;/code&gt;: command signature related content.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker/&lt;/code&gt;, &lt;code&gt;script/&lt;/code&gt;, &lt;code&gt;resources/&lt;/code&gt;, &lt;code&gt;specs/&lt;/code&gt;, and other engineering directories.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.claude/&lt;/code&gt;, &lt;code&gt;.warp/&lt;/code&gt;, &lt;code&gt;.agents/skills&lt;/code&gt;, and other agent-related configuration.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;WARP.md&lt;/code&gt; gives more engineering detail. It describes Warp as a Rust-based terminal emulator using an in-house UI framework called &lt;code&gt;WarpUI&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The major modules can be roughly understood as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;app/&lt;/code&gt;: terminal emulation, shell management, AI integration, Drive, authentication, settings, workspace, and sessions.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;crates/warp_core/&lt;/code&gt;: core utilities and platform abstraction.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;crates/editor/&lt;/code&gt;: text editing functionality.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;crates/warpui/&lt;/code&gt; and &lt;code&gt;crates/warpui_core/&lt;/code&gt;: the in-house UI framework.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;crates/ipc/&lt;/code&gt;: inter-process communication.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;crates/graphql/&lt;/code&gt;: GraphQL client and schema.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;WARP.md&lt;/code&gt; also mentions architectural features such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;an Entity-Handle system;&lt;/li&gt;
&lt;li&gt;a modular workspace structure;&lt;/li&gt;
&lt;li&gt;macOS, Windows, Linux, and WASM targets;&lt;/li&gt;
&lt;li&gt;AI integration, including Agent Mode, context awareness, and codebase indexing;&lt;/li&gt;
&lt;li&gt;Warp Drive cloud sync.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This complexity is closer to a full IDE than a lightweight traditional terminal.&lt;/p&gt;
&lt;h2 id=&#34;local-build-commands&#34;&gt;Local Build Commands
&lt;/h2&gt;&lt;p&gt;The README gives a concise local build flow:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./script/bootstrap
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./script/run
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;./script/presubmit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Where:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;./script/bootstrap&lt;/code&gt; performs platform-specific initialization.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;./script/run&lt;/code&gt; builds and runs Warp.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;./script/presubmit&lt;/code&gt; runs formatting, clippy, tests, and other pre-submit checks.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;code&gt;WARP.md&lt;/code&gt; also lists more detailed commands:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cargo run
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cargo bundle --bin warp
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cargo nextest run --no-fail-fast --workspace --exclude command-signatures-v2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cargo fmt
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cargo clippy --workspace --all-targets --all-features --tests -- -D warnings
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you want to contribute to Warp, &lt;code&gt;./script/presubmit&lt;/code&gt; is effectively required.&lt;/p&gt;
&lt;h2 id=&#34;contribution-flow&#34;&gt;Contribution Flow
&lt;/h2&gt;&lt;p&gt;Warp&amp;rsquo;s contribution flow is not simply &amp;ldquo;open a PR.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;The README describes a lightweight process from issue to PR:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Search existing issues first.&lt;/li&gt;
&lt;li&gt;If there is no duplicate, file a bug or feature request.&lt;/li&gt;
&lt;li&gt;Maintainers review the issue and may add readiness labels.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ready-to-spec&lt;/code&gt; means the design can be expanded into a spec.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ready-to-implement&lt;/code&gt; means the design is clear enough to start an implementation PR.&lt;/li&gt;
&lt;li&gt;Contributors can pick up labeled issues.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This process fits a large open-source project. It separates ideas, design, and implementation, reducing the risk that contributors spend time building in the wrong direction.&lt;/p&gt;
&lt;p&gt;It also fits AI agents well. An agent can organize issues, draft specs, add tests, and then move into implementation. Warp itself uses this pattern to demonstrate agentic project management.&lt;/p&gt;
&lt;h2 id=&#34;license-mit--agpl-v3&#34;&gt;License: MIT + AGPL v3
&lt;/h2&gt;&lt;p&gt;Warp uses a dual license structure.&lt;/p&gt;
&lt;p&gt;The README says:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the Warp UI framework, namely the &lt;code&gt;warpui_core&lt;/code&gt; and &lt;code&gt;warpui&lt;/code&gt; crates, uses the MIT license;&lt;/li&gt;
&lt;li&gt;the rest of the repository uses AGPL v3.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This matters. AGPL v3 has stronger open-source requirements for network services and distribution. If you are learning, researching, or contributing, it is usually straightforward. But if you want to use Warp code in a commercial product or closed-source derivative, you need to read the license carefully and consult legal advice if necessary.&lt;/p&gt;
&lt;p&gt;In short, Warp is open source, but not &amp;ldquo;take it and close-source it freely&amp;rdquo; open source.&lt;/p&gt;
&lt;h2 id=&#34;why-it-is-worth-watching&#34;&gt;Why It Is Worth Watching
&lt;/h2&gt;&lt;p&gt;First, Warp brings the terminal, agents, and project management together.&lt;/p&gt;
&lt;p&gt;Many AI coding tools are still CLI tools or editor plugins. Warp starts from the terminal entry point and tries to unify agent tasks, code execution, command output, PR workflows, and team collaboration.&lt;/p&gt;
&lt;p&gt;Second, Warp&amp;rsquo;s open-source approach is a good place to observe agent workflows.&lt;/p&gt;
&lt;p&gt;It does not only publish code. It also exposes contribution overviews, agent sessions, issue triage, and spec workflows. For anyone studying how AI can participate in open-source collaboration, the repository itself is a sample.&lt;/p&gt;
&lt;p&gt;Third, Warp is a complex Rust desktop application.&lt;/p&gt;
&lt;p&gt;If you want to study Rust GUI, terminal emulation, cross-platform apps, GraphQL clients, cloud sync, and AI integration, the repository has a lot to read. But it is not a small project, so new contributors should read the docs and issue process first.&lt;/p&gt;
&lt;p&gt;Fourth, Warp supports both a built-in agent and a &amp;ldquo;bring your own CLI agent&amp;rdquo; approach.&lt;/p&gt;
&lt;p&gt;This is realistic. Developers will not use only one agent. Claude Code, Codex, Gemini CLI, OpenCode, OpenClaw, and similar tools are likely to coexist. If Warp can become a workbench for them, it becomes more valuable than a single-purpose terminal.&lt;/p&gt;
&lt;h2 id=&#34;who-should-care&#34;&gt;Who Should Care
&lt;/h2&gt;&lt;p&gt;If you are a normal terminal user, Warp matters because the terminal may be changing from a command-line tool into an AI workbench.&lt;/p&gt;
&lt;p&gt;If you are a heavy AI coding agent user, Warp is worth watching because it tries to manage multiple agents rather than act as another chat entry point.&lt;/p&gt;
&lt;p&gt;If you maintain open-source projects, the Oz for OSS direction is worth attention. It explores agent-based issue triage, PR review, community collaboration, and contributor onboarding.&lt;/p&gt;
&lt;p&gt;If you are a Rust developer, Warp is a real large-scale desktop application worth studying for UI organization, terminal internals, cloud sync, AI integration, and cross-platform code.&lt;/p&gt;
&lt;p&gt;If you only want a terminal that can replace your current one immediately, it is better to download the stable release first, then decide whether to study the source. Building from source is more suitable for contributors and deep users.&lt;/p&gt;
&lt;h2 id=&#34;short-take&#34;&gt;Short Take
&lt;/h2&gt;&lt;p&gt;The point of Warp going open source is not merely &amp;ldquo;a modern terminal became open source.&amp;rdquo;&lt;/p&gt;
&lt;p&gt;More precisely, Warp is trying to upgrade the terminal into an agentic development environment: the terminal connects the shell, codebase, command execution, agents, issues, PRs, and collaboration flow.&lt;/p&gt;
&lt;p&gt;As AI coding agents keep growing, the entry point of the development environment may change. In the past, the IDE dominated the developer experience while the terminal ran commands. Now the terminal may become the center of agent collaboration. The Warp repository is exploring that possibility.&lt;/p&gt;
&lt;h2 id=&#34;related-links&#34;&gt;Related Links
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;GitHub repository: &lt;a class=&#34;link&#34; href=&#34;https://github.com/warpdotdev/warp&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/warpdotdev/warp&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Warp website: &lt;a class=&#34;link&#34; href=&#34;https://www.warp.dev&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://www.warp.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Warp documentation: &lt;a class=&#34;link&#34; href=&#34;https://docs.warp.dev&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://docs.warp.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Warp build overview: &lt;a class=&#34;link&#34; href=&#34;https://build.warp.dev&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://build.warp.dev&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;WARP.md: &lt;a class=&#34;link&#34; href=&#34;https://github.com/warpdotdev/warp/blob/master/WARP.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/warpdotdev/warp/blob/master/WARP.md&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;CONTRIBUTING.md: &lt;a class=&#34;link&#34; href=&#34;https://github.com/warpdotdev/warp/blob/master/CONTRIBUTING.md&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/warpdotdev/warp/blob/master/CONTRIBUTING.md&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        <item>
        <title>Getting Started with Compiling UEFI Programs: From uefi-simple to Your First .EFI</title>
        <link>https://knightli.com/en/2026/04/30/compile-uefi-program-beginner-guide/</link>
        <pubDate>Thu, 30 Apr 2026 19:53:08 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/04/30/compile-uefi-program-beginner-guide/</guid>
        <description>&lt;p&gt;Compiling your first UEFI program is not exactly effortless. Environment setup can take time, linker errors are common, and a &lt;code&gt;.EFI&lt;/code&gt; program does not have the same direct edit-and-run experience as an ordinary desktop application.&lt;/p&gt;
&lt;p&gt;This article organizes the topic from a beginner&amp;rsquo;s perspective: if you only want to compile your first UEFI program, where should you start, which concepts matter first, and which pitfalls are most likely to appear?&lt;/p&gt;
&lt;h2 id=&#34;what-is-a-uefi-program&#34;&gt;What Is a UEFI Program?
&lt;/h2&gt;&lt;p&gt;A UEFI program is usually a &lt;code&gt;.EFI&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;It is not an ordinary &lt;code&gt;.exe&lt;/code&gt; that you double-click in Windows. It is a PE/COFF executable that runs inside the UEFI firmware environment. Common use cases include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Boot managers&lt;/li&gt;
&lt;li&gt;Hardware initialization tools&lt;/li&gt;
&lt;li&gt;Firmware update tools&lt;/li&gt;
&lt;li&gt;Pre-boot diagnostic tools&lt;/li&gt;
&lt;li&gt;Custom boot flows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many functions you see early in the system boot process may be related to UEFI applications, drivers, or firmware services.&lt;/p&gt;
&lt;p&gt;For beginners, there is no need to understand full firmware development immediately. The first goal is simple: compile a &lt;code&gt;.EFI&lt;/code&gt; file that can be loaded by a UEFI Shell or emulator.&lt;/p&gt;
&lt;h2 id=&#34;why-not-start-with-edk-ii&#34;&gt;Why Not Start with EDK II?
&lt;/h2&gt;&lt;p&gt;Real UEFI development often involves EDK II.&lt;/p&gt;
&lt;p&gt;EDK II is complete and closer to real firmware engineering, but it is not very friendly for beginners:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The project structure is complex&lt;/li&gt;
&lt;li&gt;The build system has a learning curve&lt;/li&gt;
&lt;li&gt;Environment variables and toolchain setup involve many details&lt;/li&gt;
&lt;li&gt;Compiler errors are not always easy to understand&lt;/li&gt;
&lt;li&gt;It is easy to get stuck on the environment before writing any code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If the goal is simply to get a minimal UEFI program running, a lightweight example is a better starting point.&lt;/p&gt;
&lt;p&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/pbatard/uefi-simple&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;pbatard/uefi-simple&lt;/a&gt; is one such project. Its goal is straightforward: provide a simple UEFI Hello World example so you can compile a &lt;code&gt;.EFI&lt;/code&gt; file first.&lt;/p&gt;
&lt;h2 id=&#34;what-is-uefi-simple-good-for&#34;&gt;What Is &lt;code&gt;uefi-simple&lt;/code&gt; Good For?
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;uefi-simple&lt;/code&gt; is a good first stepping stone for UEFI beginners.&lt;/p&gt;
&lt;p&gt;It solves three practical problems:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It gives you a minimal compilable UEFI application structure&lt;/li&gt;
&lt;li&gt;It avoids the complexity of large firmware projects at the beginning&lt;/li&gt;
&lt;li&gt;It lets you verify that compiling, linking, and running all work&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The project supports multiple build methods, including Visual Studio 2022 and MinGW/gcc. It can also be tested with QEMU and OVMF.&lt;/p&gt;
&lt;p&gt;In other words, you do not have to repeatedly reboot a real machine for early experiments. Running the program in an emulator first is much safer.&lt;/p&gt;
&lt;h2 id=&#34;what-to-prepare-before-starting&#34;&gt;What to Prepare Before Starting
&lt;/h2&gt;&lt;p&gt;You need at least a few categories of tools.&lt;/p&gt;
&lt;p&gt;The first category is the compiler toolchain.&lt;/p&gt;
&lt;p&gt;On Windows, you can start with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Visual Studio 2022&lt;/li&gt;
&lt;li&gt;Or MinGW/gcc&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The second category is a UEFI runtime environment.&lt;/p&gt;
&lt;p&gt;There are two common options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run the &lt;code&gt;.EFI&lt;/code&gt; file in a real machine&amp;rsquo;s UEFI Shell&lt;/li&gt;
&lt;li&gt;Test it in a virtual environment with QEMU + OVMF&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The third category is an example project.&lt;/p&gt;
&lt;p&gt;Beginners should not start by writing build scripts from an empty directory. Using a minimal example such as &lt;code&gt;uefi-simple&lt;/code&gt; helps avoid many build-system problems.&lt;/p&gt;
&lt;h2 id=&#34;basic-workflow&#34;&gt;Basic Workflow
&lt;/h2&gt;&lt;p&gt;A minimal UEFI program workflow can be understood like this.&lt;/p&gt;
&lt;p&gt;First, get the example project.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;git&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;clone&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;https&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;//&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;github&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;com&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;n&#34;&gt;pbatard&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;/&lt;/span&gt;&lt;span class=&#34;nb&#34;&gt;uefi-simple&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;git&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Second, choose a build toolchain.&lt;/p&gt;
&lt;p&gt;If you use Visual Studio, build with the Visual Studio solution in the project.&lt;br&gt;
If you use MinGW/gcc, follow the Makefile or instructions provided by the project.&lt;/p&gt;
&lt;p&gt;Third, generate the &lt;code&gt;.EFI&lt;/code&gt; file.&lt;/p&gt;
&lt;p&gt;The key point here is to confirm the target architecture. A common PC is usually &lt;code&gt;x86_64&lt;/code&gt;, meaning a 64-bit UEFI environment.&lt;/p&gt;
&lt;p&gt;Fourth, put the &lt;code&gt;.EFI&lt;/code&gt; file somewhere the UEFI Shell can access.&lt;/p&gt;
&lt;p&gt;On a real machine, this usually means preparing a FAT32 partition or USB drive.&lt;br&gt;
With QEMU, you can mount a directory or disk image.&lt;/p&gt;
&lt;p&gt;Fifth, run it in the UEFI Shell.&lt;/p&gt;
&lt;p&gt;The result is usually a minimal output, such as a Hello World-style message.&lt;/p&gt;
&lt;h2 id=&#34;where-beginners-usually-get-stuck&#34;&gt;Where Beginners Usually Get Stuck
&lt;/h2&gt;&lt;p&gt;The hardest part of compiling a UEFI program is usually not the C language itself, but the environment and linking process.&lt;/p&gt;
&lt;p&gt;Common issues include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Wrong compiler architecture&lt;/li&gt;
&lt;li&gt;Wrong target format&lt;/li&gt;
&lt;li&gt;Incomplete linker parameters&lt;/li&gt;
&lt;li&gt;Missing UEFI entry point&lt;/li&gt;
&lt;li&gt;Generating an ordinary executable instead of a UEFI-loadable &lt;code&gt;.EFI&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;QEMU or OVMF not configured correctly&lt;/li&gt;
&lt;li&gt;Secure Boot on a real machine blocking an unsigned program&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Linker errors are especially easy to misread as code problems.&lt;br&gt;
In many cases, the real issue is the entry function, subsystem, target architecture, or linker script.&lt;/p&gt;
&lt;p&gt;So in the first stage, do not rush into complex logic. Make sure the original example can compile and run, then change the output little by little.&lt;/p&gt;
&lt;h2 id=&#34;why-use-qemu--ovmf-for-testing&#34;&gt;Why Use QEMU + OVMF for Testing?
&lt;/h2&gt;&lt;p&gt;Testing UEFI programs on a real machine is possible, but it is not convenient at the beginner stage.&lt;/p&gt;
&lt;p&gt;You may have to repeat this cycle:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Compile&lt;/li&gt;
&lt;li&gt;Copy to a USB drive&lt;/li&gt;
&lt;li&gt;Reboot&lt;/li&gt;
&lt;li&gt;Enter the UEFI Shell&lt;/li&gt;
&lt;li&gt;Run the program&lt;/li&gt;
&lt;li&gt;Record the error&lt;/li&gt;
&lt;li&gt;Return to the system and modify the code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That loop is slow.&lt;/p&gt;
&lt;p&gt;QEMU + OVMF lets you simulate a UEFI environment directly inside the operating system. You can verify whether a &lt;code&gt;.EFI&lt;/code&gt; file loads more quickly, and it is less likely to affect your real boot entries.&lt;/p&gt;
&lt;p&gt;Once the program basically works, testing it on a real machine is much more manageable.&lt;/p&gt;
&lt;h2 id=&#34;what-should-beginners-modify-first&#34;&gt;What Should Beginners Modify First?
&lt;/h2&gt;&lt;p&gt;If you have already compiled your first &lt;code&gt;.EFI&lt;/code&gt; with the example project, do not jump into complex features immediately.&lt;/p&gt;
&lt;p&gt;A better order is:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Change the output text first to confirm that recompilation really takes effect.&lt;/li&gt;
&lt;li&gt;Try reading simple information provided by UEFI.&lt;/li&gt;
&lt;li&gt;Understand the entry function, output protocol, and basic services.&lt;/li&gt;
&lt;li&gt;Then consider more complex features such as file systems, graphical output, or boot entry management.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This approach makes every step verifiable.&lt;br&gt;
If you change too much at once, it becomes difficult to tell whether the issue is in the code, the build process, or the runtime environment.&lt;/p&gt;
&lt;h2 id=&#34;how-is-it-different-from-an-ordinary-c-program&#34;&gt;How Is It Different from an Ordinary C Program?
&lt;/h2&gt;&lt;p&gt;Although UEFI programs can be written in C, their runtime environment is completely different from ordinary C programs.&lt;/p&gt;
&lt;p&gt;An ordinary C program usually runs inside an operating system and can rely on the standard library, file system, process model, and system calls.&lt;/p&gt;
&lt;p&gt;A UEFI program runs before the operating system boots. It relies on services provided by UEFI firmware. Many things you are used to in normal programs are not automatically available here.&lt;/p&gt;
&lt;p&gt;When writing UEFI programs, you need to adapt to several differences:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The entry function is different&lt;/li&gt;
&lt;li&gt;Output works differently&lt;/li&gt;
&lt;li&gt;Available libraries are different&lt;/li&gt;
&lt;li&gt;Memory and file access work differently&lt;/li&gt;
&lt;li&gt;Debugging works differently&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This is why starting from a minimal example is better than writing code as if it were a normal C program.&lt;/p&gt;
&lt;h2 id=&#34;a-practical-learning-path&#34;&gt;A Practical Learning Path
&lt;/h2&gt;&lt;p&gt;For beginners, a realistic path looks like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Step 1: Compile &lt;code&gt;uefi-simple&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Step 2: Run it with QEMU + OVMF&lt;/li&gt;
&lt;li&gt;Step 3: Modify the Hello World output&lt;/li&gt;
&lt;li&gt;Step 4: Understand how the UEFI Shell loads &lt;code&gt;.EFI&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Step 5: Learn the UEFI entry function and basic output protocol&lt;/li&gt;
&lt;li&gt;Step 6: Then read EDK II or more complete UEFI development material&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The point of this path is to build a working feedback loop first.&lt;/p&gt;
&lt;p&gt;Once you can generate a &lt;code&gt;.EFI&lt;/code&gt; from source and see output in a UEFI environment, you have already crossed the hardest first threshold.&lt;/p&gt;
&lt;h2 id=&#34;references&#34;&gt;References
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://github.com/pbatard/uefi-simple&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;pbatard/uefi-simple&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://zhuanlan.zhihu.com/p/643704056&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;Zhihu: UEFI program compilation material&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;final-thought&#34;&gt;Final Thought
&lt;/h2&gt;&lt;p&gt;The hard part of compiling your first UEFI program is usually not writing a bit of C code, but connecting the toolchain, link format, and runtime environment.&lt;/p&gt;
&lt;p&gt;Do not rush into complex features.&lt;br&gt;
Start with a minimal example such as &lt;code&gt;uefi-simple&lt;/code&gt;, get a runnable &lt;code&gt;.EFI&lt;/code&gt; first, and then gradually understand UEFI entry points, protocols, and build methods.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>GoAccess Latest Build-from-Source Notes: From Source Install to Real-Time HTML Reports</title>
        <link>https://knightli.com/en/2026/04/29/goaccess-build-from-source-and-latest-usage/</link>
        <pubDate>Wed, 29 Apr 2026 00:08:00 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/04/29/goaccess-build-from-source-and-latest-usage/</guid>
        <description>&lt;p&gt;This is organized for &lt;code&gt;2026-04-29&lt;/code&gt;.&lt;br&gt;
At this point, the latest stable version listed in the official README is &lt;code&gt;1.10.2&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;1-install-build-dependencies-first&#34;&gt;1. Install build dependencies first
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt-get install -y build-essential wget tar &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  libncurses-dev libmaxminddb-dev libssl-dev zlib1g-dev
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;2-download-the-latest-source-package&#34;&gt;2. Download the latest source package
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; /usr/local/src
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo wget https://tar.goaccess.io/goaccess-1.10.2.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo tar -xzvf goaccess-1.10.2.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; goaccess-1.10.2
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;3-configure-build-options&#34;&gt;3. Configure build options
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo ./configure --enable-utf8 --enable-geoip&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;mmdb --with-zlib
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If you also want TLS support for real-time HTML reports:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo ./configure --enable-utf8 --enable-geoip&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;mmdb --with-zlib --with-openssl
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;4-build-and-install&#34;&gt;4. Build and install
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo make
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo make install
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;5-verify-the-version&#34;&gt;5. Verify the version
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess --version
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;which goaccess
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;6-view-reports-directly-in-the-terminal&#34;&gt;6. View reports directly in the terminal
&lt;/h2&gt;&lt;p&gt;For common Nginx or Apache combined logs:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;If the log path is Apache:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/apache2/access.log --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;7-generate-a-static-html-report&#34;&gt;7. Generate a static HTML report
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -a &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -o /usr/share/nginx/html/goaccess-report.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;You can also write it to the current directory:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -a &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -o report.html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;8-generate-a-real-time-html-report&#34;&gt;8. Generate a real-time HTML report
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -a &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -o /usr/share/nginx/html/goaccess-report.html &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --real-time-html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To change the port:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -a &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -o /usr/share/nginx/html/goaccess-report.html &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --real-time-html &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --port&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;7891&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;To bind only to localhost:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -a &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -o /usr/share/nginx/html/goaccess-report.html &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --real-time-html &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --addr&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;127.0.0.1
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;9-follow-logs-continuously&#34;&gt;9. Follow logs continuously
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tail -f /var/log/nginx/access.log &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; goaccess --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED -
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;From the beginning of the file and keep it live:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tail -f -n +0 /var/log/nginx/access.log &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; goaccess &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -o report.html &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --real-time-html -
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;10-look-at-only-certain-requests&#34;&gt;10. Look at only certain requests
&lt;/h2&gt;&lt;p&gt;For example, only requests containing &lt;code&gt;firefox&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tail -f /var/log/nginx/access.log &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; grep -i --line-buffered &lt;span class=&#34;s1&#34;&gt;&amp;#39;firefox&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; goaccess &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED -
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;For example, only &lt;code&gt;5xx&lt;/code&gt; and &lt;code&gt;3xx&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;tail -f -n +0 /var/log/nginx/access.log &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;$9~/3[0-9]{2}|5[0-9]{2}/&amp;#39;&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; goaccess &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -o out.html -
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;11-analyze-multiple-logs-together&#34;&gt;11. Analyze multiple logs together
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log /var/log/nginx/access.log.1 --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Read compressed and uncompressed logs together:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;zcat --force /var/log/nginx/access.log* &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; goaccess --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED -
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;12-enable-multithreading&#34;&gt;12. Enable multithreading
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -o report.html &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -j &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Increase chunk size:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -o report.html &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -j &lt;span class=&#34;m&#34;&gt;4&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --chunk-size&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;8192&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;13-incremental-processing&#34;&gt;13. Incremental processing
&lt;/h2&gt;&lt;p&gt;Persist an older log first:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log.1 --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED --persist
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Then append the current log:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED --restore --persist
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Read only persisted data:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess --restore
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;14-the-set-of-commands-i-would-run-first&#34;&gt;14. The set of commands I would run first
&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;15
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;16
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;17
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;18
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;19
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt-get update
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo apt-get install -y build-essential wget tar &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  libncurses-dev libmaxminddb-dev libssl-dev zlib1g-dev
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; /usr/local/src
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo wget https://tar.goaccess.io/goaccess-1.10.2.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo tar -xzvf goaccess-1.10.2.tar.gz
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;cd&lt;/span&gt; goaccess-1.10.2
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo ./configure --enable-utf8 --enable-geoip&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;mmdb --with-zlib --with-openssl
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo make
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;sudo make install
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess --version
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;goaccess /var/log/nginx/access.log &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --log-format&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;COMBINED &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -a &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -o /usr/share/nginx/html/goaccess-report.html &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  --real-time-html
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;That is basically it.&lt;br&gt;
If your goal is clear, getting the latest source build installed and making &lt;code&gt;--log-format=COMBINED&lt;/code&gt; plus &lt;code&gt;--real-time-html&lt;/code&gt; work first is usually enough. After that, most changes are just about log paths, output files, and ports.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How to Choose an Embedded Development Environment in 2026: Keil, STM32CubeIDE, VS Code, and AI Collaboration</title>
        <link>https://knightli.com/en/2026/04/22/embedded-development-environment-keil-vscode-ai-2026/</link>
        <pubDate>Wed, 22 Apr 2026 23:05:00 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/04/22/embedded-development-environment-keil-vscode-ai-2026/</guid>
        <description>&lt;p&gt;If you still work on microcontrollers or embedded systems, you will quickly run into a very practical question: in 2026, when AI-assisted coding has become increasingly common, what development environment actually makes sense?&lt;/p&gt;
&lt;p&gt;On the surface, this looks like a comparison between several IDEs. But what it really asks is something else: do you want a tool that can simply get the project running, or a workflow that balances ecosystem compatibility, coding experience, and AI collaboration?&lt;/p&gt;
&lt;p&gt;Seen from that angle, the answer is usually not to pick one out of &lt;code&gt;Keil&lt;/code&gt;, &lt;code&gt;STM32CubeIDE&lt;/code&gt;, &lt;code&gt;VS Code&lt;/code&gt;, and &lt;code&gt;CLion&lt;/code&gt;, but to recombine the parts each one does best.&lt;/p&gt;
&lt;h2 id=&#34;first-look-at-the-main-options-and-what-each-one-really-solves&#34;&gt;First look at the main options and what each one really solves
&lt;/h2&gt;&lt;p&gt;In embedded development, the familiar names are still more or less the same:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Keil&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;STM32CubeIDE&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;VS Code&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CLion&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you go back even further, people will still mention &lt;code&gt;IAR&lt;/code&gt;. But for this discussion, what matters less is who has the oldest pedigree, and more who actually fits today&amp;rsquo;s development reality.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://knightli.com/2026/04/22/embedded-development-environment-keil-vscode-ai-2026/embedded-ide-comparison.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Comparison chart of embedded development environments&#34;
	
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;keil-strong-ecosystem-dependable-entry-point-but-clearly-outdated-editing-experience&#34;&gt;Keil: strong ecosystem, dependable entry point, but clearly outdated editing experience
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Keil&lt;/code&gt; is still hard to avoid today, and the reason is simple: it is everywhere.&lt;/p&gt;
&lt;p&gt;Whether you look at legacy company projects, online tutorials, shared examples, or older codebases, a huge amount of embedded work is still organized around &lt;code&gt;Keil&lt;/code&gt;. Its build, download, and debug workflow remains mature, and if your main goal is to get code running on a board, it is still a very short path.&lt;/p&gt;
&lt;p&gt;Its problems are just as obvious:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dated interface&lt;/li&gt;
&lt;li&gt;average editing experience&lt;/li&gt;
&lt;li&gt;not a natural home for AI-assisted coding&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So &lt;code&gt;Keil&lt;/code&gt; feels more like a project entry point and debugging foundation than an ideal editor for a 2026 coding experience.&lt;/p&gt;
&lt;h2 id=&#34;stm32cubeide-friendly-for-stm32-but-more-of-a-learning-and-quick-start-tool&#34;&gt;STM32CubeIDE: friendly for STM32, but more of a learning and quick-start tool
&lt;/h2&gt;&lt;p&gt;If you mainly live inside the &lt;code&gt;STM32&lt;/code&gt; ecosystem, &lt;code&gt;STM32CubeIDE&lt;/code&gt; is often the first environment you touch.&lt;/p&gt;
&lt;p&gt;Its strengths are straightforward:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;beginner-friendly onboarding&lt;/li&gt;
&lt;li&gt;convenient peripheral configuration and project generation&lt;/li&gt;
&lt;li&gt;a fairly complete debug chain&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For students, beginners, and early project setup, that experience is direct and good enough.&lt;/p&gt;
&lt;p&gt;But once you move into longer-running projects, heavier collaboration, and more customized workflows, its limitations become more visible. In commercial work or more complex team environments, it may not be the most comfortable primary environment.&lt;/p&gt;
&lt;p&gt;So it fits better as a quick-start and STM32-centric all-in-one tool than as a long-term primary editor.&lt;/p&gt;
&lt;h2 id=&#34;vs-code-not-really-an-ide-but-increasingly-strong-in-the-ai-era&#34;&gt;VS Code: not really an IDE, but increasingly strong in the AI era
&lt;/h2&gt;&lt;p&gt;Strictly speaking, &lt;code&gt;VS Code&lt;/code&gt; is not a traditional IDE. More accurately, it is an extensible code editor.&lt;/p&gt;
&lt;p&gt;That gives it a built-in dual nature.&lt;/p&gt;
&lt;p&gt;Its weaknesses are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it needs plugins and setup&lt;/li&gt;
&lt;li&gt;it is not beginner-friendly enough&lt;/li&gt;
&lt;li&gt;it cannot replace the full embedded IDE workflow out of the box&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But its real strengths come from the same place:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;strong extensibility&lt;/li&gt;
&lt;li&gt;a much more modern coding experience&lt;/li&gt;
&lt;li&gt;better highlighting, navigation, search, and refactoring&lt;/li&gt;
&lt;li&gt;stronger momentum around AI tools and agent workflows&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;At this stage, many developers no longer just want something that lets them write code. They want to know whether AI collaboration can fit naturally into the same environment. From that perspective, the advantage of &lt;code&gt;VS Code&lt;/code&gt; is hard to miss.&lt;/p&gt;
&lt;h2 id=&#34;clion-good-experience-but-not-central-enough-in-embedded-practice&#34;&gt;CLion: good experience, but not central enough in embedded practice
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;CLion&lt;/code&gt; often comes up because its C/C++ coding experience has long been considered solid.&lt;/p&gt;
&lt;p&gt;But for many embedded developers, the question is not whether it is good. The question is whether it is worth switching to:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;relatively fewer people use it in embedded workflows&lt;/li&gt;
&lt;li&gt;it does not connect to existing embedded project ecosystems as directly as &lt;code&gt;Keil&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;it may not offer a more practical AI-collaboration advantage than &lt;code&gt;VS Code&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So it feels more like a &amp;ldquo;theoretically good option&amp;rdquo; than the most natural center of a mainstream embedded workflow today.&lt;/p&gt;
&lt;h2 id=&#34;a-more-practical-answer-let-keil-handle-build-and-debugging-let-vs-code-handle-coding&#34;&gt;A more practical answer: let Keil handle build and debugging, let VS Code handle coding
&lt;/h2&gt;&lt;p&gt;If you break these tools apart by role, a much more pragmatic conclusion appears:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;use &lt;code&gt;Keil&lt;/code&gt; to preserve existing project compatibility, build, flashing, and debugging&lt;/li&gt;
&lt;li&gt;use &lt;code&gt;VS Code&lt;/code&gt; for everyday coding, search, navigation, and AI collaboration&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The value of this combination is that it does not try to force one tool to do everything. Instead, it puts each tool back in the role it is best at.&lt;/p&gt;
&lt;p&gt;For many embedded projects, the &lt;code&gt;Keil&lt;/code&gt; ecosystem is simply not optional. If that is true, then instead of forcing everything back into &lt;code&gt;Keil&lt;/code&gt;, it makes more sense to treat it as the backend build-and-debug entry point, while handing the real editing experience to &lt;code&gt;VS Code&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://knightli.com/2026/04/22/embedded-development-environment-keil-vscode-ai-2026/keil-vscode-ai-workflow.svg&#34;
	
	
	
	loading=&#34;lazy&#34;
	
		alt=&#34;Workflow diagram for combining Keil and VS Code&#34;
	
	
&gt;&lt;/p&gt;
&lt;h2 id=&#34;why-this-combination-makes-more-sense-in-the-ai-era&#34;&gt;Why this combination makes more sense in the AI era
&lt;/h2&gt;&lt;p&gt;Today, the dividing line between environments is no longer just whether the editor feels smooth. It is whether AI can plug into the workflow naturally.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;VS Code&lt;/code&gt; has several very practical strengths here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;more active support for AI plugins and agents&lt;/li&gt;
&lt;li&gt;a code browsing experience better suited for AI reading and modifying projects&lt;/li&gt;
&lt;li&gt;easier integration with modern plugin ecosystems&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That means some of the most painful parts of embedded development can start to be offloaded to AI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;finding functions and call chains in an existing project&lt;/li&gt;
&lt;li&gt;quickly generating initialization code&lt;/li&gt;
&lt;li&gt;adding a simple UART print&lt;/li&gt;
&lt;li&gt;explaining the structure of old projects&lt;/li&gt;
&lt;li&gt;making small, localized edits in existing files&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These tasks were never impossible before. They were just awkward. The meaning of &lt;code&gt;VS Code&lt;/code&gt; is not only that it looks better. It is that it can more naturally become the workbench for AI collaboration.&lt;/p&gt;
&lt;h2 id=&#34;the-key-patch-connect-vs-code-to-keil-projects-with-plugins&#34;&gt;The key patch: connect VS Code to Keil projects with plugins
&lt;/h2&gt;&lt;p&gt;Whether this workflow works in practice depends on one thing: can you actually connect &lt;code&gt;VS Code&lt;/code&gt; to a &lt;code&gt;Keil&lt;/code&gt; project?&lt;/p&gt;
&lt;p&gt;A very practical class of plugins does exactly that by letting &lt;code&gt;VS Code&lt;/code&gt; read &lt;code&gt;Keil&lt;/code&gt; project structure and call &lt;code&gt;Keil&lt;/code&gt; backend programs from inside the editor for tasks such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;opening a project&lt;/li&gt;
&lt;li&gt;building&lt;/li&gt;
&lt;li&gt;downloading&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That way, you do not have to constantly jump between two interfaces just to write code. You only return to &lt;code&gt;Keil&lt;/code&gt; for the heavier debugging work such as stepping, breakpoints, and register inspection.&lt;/p&gt;
&lt;p&gt;The real value of these plugins is not merely saving a few window switches. It is making the workflow continuous.&lt;/p&gt;
&lt;h2 id=&#34;do-not-overlook-the-basic-cc-plugin-setup&#34;&gt;Do not overlook the basic C/C++ plugin setup
&lt;/h2&gt;&lt;p&gt;If you want to use &lt;code&gt;VS Code&lt;/code&gt; as the main embedded editor, one basic but often ignored point is this: you must set up the core C/C++ plugin and project indexing properly.&lt;/p&gt;
&lt;p&gt;Otherwise, you will run into a series of issues that seriously hurt the experience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;jump-to-definition does not work&lt;/li&gt;
&lt;li&gt;false red underlines appear&lt;/li&gt;
&lt;li&gt;completion quality is poor&lt;/li&gt;
&lt;li&gt;header relationships become messy&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Many people assume this means &lt;code&gt;VS Code&lt;/code&gt; is not suitable for embedded work. In practice, it is often just that the indexing and plugin configuration are not connected correctly.&lt;/p&gt;
&lt;p&gt;Once that layer is configured properly, &lt;code&gt;VS Code&lt;/code&gt; can actually deliver on its strengths in reading large projects, searching symbols, and using AI to assist with targeted code changes.&lt;/p&gt;
&lt;h2 id=&#34;who-this-workflow-fits-best&#34;&gt;Who this workflow fits best
&lt;/h2&gt;&lt;p&gt;I think this combination works especially well for the following groups.&lt;/p&gt;
&lt;h3 id=&#34;1-people-who-already-have-a-large-amount-of-keil-based-projects&#34;&gt;1. People who already have a large amount of Keil-based projects
&lt;/h3&gt;&lt;p&gt;If your company projects, course materials, or historical code all revolve around &lt;code&gt;Keil&lt;/code&gt;, there is no reason to throw that ecosystem away just for the sake of looking modern. Keep &lt;code&gt;Keil&lt;/code&gt;, then add &lt;code&gt;VS Code&lt;/code&gt; as the front end. That is usually the lowest-cost transition.&lt;/p&gt;
&lt;h3 id=&#34;2-people-who-want-ai-to-help-with-embedded-coding&#34;&gt;2. People who want AI to help with embedded coding
&lt;/h3&gt;&lt;p&gt;If you already like using AI to explain functions, generate boilerplate, or make local logic changes, &lt;code&gt;VS Code&lt;/code&gt; will take on that role more naturally than traditional embedded IDEs.&lt;/p&gt;
&lt;h3 id=&#34;3-people-who-want-to-balance-learning-materials-and-real-projects&#34;&gt;3. People who want to balance learning materials and real projects
&lt;/h3&gt;&lt;p&gt;Many tutorials are still built around &lt;code&gt;Keil&lt;/code&gt;, but your own workflow does not need to stay stuck in that era. Treat &lt;code&gt;Keil&lt;/code&gt; as the compatibility layer and &lt;code&gt;VS Code&lt;/code&gt; as the productivity layer, and the balance becomes much better.&lt;/p&gt;
&lt;h2 id=&#34;closing&#34;&gt;Closing
&lt;/h2&gt;&lt;p&gt;By 2026, the key question in embedded development environments is no longer just which IDE has more features. It is which combination best fits how people actually work today.&lt;/p&gt;
&lt;p&gt;If you only want to get started quickly, &lt;code&gt;STM32CubeIDE&lt;/code&gt; still has its place. If you need to inherit a large amount of existing engineering reality, &lt;code&gt;Keil&lt;/code&gt; is still unavoidable. But if you also want to bring in a modern editing experience and AI collaboration, the more practical answer is often this:&lt;/p&gt;
&lt;p&gt;let &lt;code&gt;Keil&lt;/code&gt; handle build and debugging, and let &lt;code&gt;VS Code&lt;/code&gt; handle writing code.&lt;/p&gt;
&lt;p&gt;It may not be the only answer, but it is very likely one of the least awkward answers available today.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How to Choose Among 8 Common Config File Formats: From INI, XML, JSON, YAML, TOML to Markdown</title>
        <link>https://knightli.com/en/2026/04/22/common-config-file-formats-ini-xml-json-yaml-toml-markdown/</link>
        <pubDate>Wed, 22 Apr 2026 21:48:37 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/04/22/common-config-file-formats-ini-xml-json-yaml-toml-markdown/</guid>
        <description>&lt;p&gt;If you write code, manage servers, tweak game settings, or maintain toolchains, you almost certainly cannot avoid config files.&lt;/p&gt;
&lt;p&gt;A lot of the time, what really blows up a program is not the algorithm or the framework, but one tiny line of configuration: one missing space, one extra comma, or one value written in a way the system did not expect. Looking at common config formats side by side naturally brings us back to a few core questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Which formats are friendlier for humans to write?&lt;/li&gt;
&lt;li&gt;Which formats are friendlier for machines to parse?&lt;/li&gt;
&lt;li&gt;In the AI Agent era, will the role of config files start to change?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article is a concise attempt to organize that question.&lt;/p&gt;
&lt;h2 id=&#34;01-a-config-file-is-basically-a-negotiation-between-humans-and-machines&#34;&gt;01 A config file is basically a negotiation between humans and machines
&lt;/h2&gt;&lt;p&gt;There is one way to put it that I think is especially accurate: a config file is really a kind of behavioral contract between humans and programs.&lt;/p&gt;
&lt;p&gt;Its value is obvious. You do not need to rewrite business logic or recompile anything. By changing just a few lines of text, you can alter website behavior, application logic, deployment behavior, or even game graphics and hidden options.&lt;/p&gt;
&lt;p&gt;The problem is that this contract contains a built-in tension.&lt;/p&gt;
&lt;p&gt;From the human side, what we want is:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;something readable, writable, and structurally clear&lt;/li&gt;
&lt;li&gt;preferably with comments so we and others can understand it later&lt;/li&gt;
&lt;li&gt;as little repetition as possible, ideally with reuse and modularity&lt;/li&gt;
&lt;li&gt;and a format that does not instantly explode because of one small mistake&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But from the machine side, elegance is irrelevant. It mainly cares about two things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;parsing must be fast&lt;/li&gt;
&lt;li&gt;the rules must be strict, types must be clear, and ambiguity should be minimized&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is why config formats are always pulled between “human-friendly” and “machine-friendly.” The better a format is for human reading, the more work machines often need to parse it. The more efficient it is for machines, the easier it often is for humans to make mistakes while editing it.&lt;/p&gt;
&lt;h2 id=&#34;02-ini-simple-and-direct-but-limited&#34;&gt;02 INI: simple and direct, but limited
&lt;/h2&gt;&lt;p&gt;Let’s start with &lt;code&gt;INI&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Its strengths are extremely straightforward:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;simple structure&lt;/li&gt;
&lt;li&gt;sections plus key-value pairs that are easy to understand at a glance&lt;/li&gt;
&lt;li&gt;support for comments&lt;/li&gt;
&lt;li&gt;well suited for lightweight configuration, such as game tweaks or basic environment settings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you have ever modified older game settings or manually adjusted tool parameters, you have probably seen it.&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;INI&lt;/code&gt; also has obvious limitations. Its structure is too flat and it does not naturally represent deep nesting or arrays. On top of that, it usually lacks a strict type system, so many values are basically just strings and the program has to decide how to interpret them.&lt;/p&gt;
&lt;p&gt;That makes &lt;code&gt;INI&lt;/code&gt; feel like an old but convenient utility vehicle: great for light work, but easy to outgrow once the project gets more complex.&lt;/p&gt;
&lt;p&gt;A very typical &lt;code&gt;INI&lt;/code&gt; file might look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-ini&#34; data-lang=&#34;ini&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[server]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;127.0.0.1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;[feature]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;na&#34;&gt;enable_cache&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;=&lt;/span&gt;&lt;span class=&#34;s&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;03-xml-rigorous-and-stable-but-tiring-to-write&#34;&gt;03 XML: rigorous and stable, but tiring to write
&lt;/h2&gt;&lt;p&gt;The second major format is &lt;code&gt;XML&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;If you have maintained older Java projects or seen large configuration files full of paired closing tags, it should feel familiar.&lt;/p&gt;
&lt;p&gt;The strengths of &lt;code&gt;XML&lt;/code&gt; include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;clear hierarchical structure&lt;/li&gt;
&lt;li&gt;support for comments&lt;/li&gt;
&lt;li&gt;strict rules&lt;/li&gt;
&lt;li&gt;strong validation when paired with a schema&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That means machines can know field types, cardinality, and structural constraints before they even begin real parsing, which gives a strong sense of safety.&lt;/p&gt;
&lt;p&gt;But its cost to humans is equally classic:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;verbose tags&lt;/li&gt;
&lt;li&gt;lots of visual noise&lt;/li&gt;
&lt;li&gt;files that expand quickly&lt;/li&gt;
&lt;li&gt;and one missing closing tag can sometimes break the whole page&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is why &lt;code&gt;XML&lt;/code&gt; feels like a fully stamped formal contract. Machines like it, while humans often get tired maintaining it. Many newer projects no longer choose it first, but in older systems and strict-rule environments it still has not fully disappeared.&lt;/p&gt;
&lt;p&gt;The same config written in &lt;code&gt;XML&lt;/code&gt; might look like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-xml&#34; data-lang=&#34;xml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;config&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;server&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;host&amp;gt;&lt;/span&gt;127.0.0.1&lt;span class=&#34;nt&#34;&gt;&amp;lt;/host&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;port&amp;gt;&lt;/span&gt;8080&lt;span class=&#34;nt&#34;&gt;&amp;lt;/port&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/server&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;feature&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;lt;enable_cache&amp;gt;&lt;/span&gt;true&lt;span class=&#34;nt&#34;&gt;&amp;lt;/enable_cache&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;lt;/feature&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;04-json-dominant-for-data-exchange-awkward-for-hand-edited-config&#34;&gt;04 JSON: dominant for data exchange, awkward for hand-edited config
&lt;/h2&gt;&lt;p&gt;In modern development, &lt;code&gt;JSON&lt;/code&gt; is almost impossible to avoid.&lt;/p&gt;
&lt;p&gt;The classic judgment about &lt;code&gt;JSON&lt;/code&gt; is this: it is excellent as a data interchange format, but a little awkward as a human-maintained config format.&lt;/p&gt;
&lt;p&gt;Its advantages include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;clear object and array structures&lt;/li&gt;
&lt;li&gt;network-friendly transmission&lt;/li&gt;
&lt;li&gt;mature parsers&lt;/li&gt;
&lt;li&gt;strong fit for web APIs and frontend-backend communication&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Especially next to &lt;code&gt;XML&lt;/code&gt;, &lt;code&gt;JSON&lt;/code&gt; looks much lighter. The same structure is often shorter in &lt;code&gt;JSON&lt;/code&gt;, and much easier to send over networks.&lt;/p&gt;
&lt;p&gt;But it has one major flaw: standard &lt;code&gt;JSON&lt;/code&gt; does not support comments.&lt;/p&gt;
&lt;p&gt;Its syntax is also strict:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;keys must be in double quotes&lt;/li&gt;
&lt;li&gt;the last item cannot have a trailing comma&lt;/li&gt;
&lt;li&gt;one missing symbol can immediately break everything&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So &lt;code&gt;JSON&lt;/code&gt; is excellent for APIs and service-to-service exchange, but not always ideal for configuration that humans need to edit, explain, and revisit often.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;server&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;host&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;port&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;feature&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;enable_cache&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;05-yaml-highly-readable-but-indentation-and-implicit-typing-can-betray-you&#34;&gt;05 YAML: highly readable, but indentation and implicit typing can betray you
&lt;/h2&gt;&lt;p&gt;If you have worked with Docker, CI/CD, Kubernetes, or deployment automation, then you have almost certainly dealt with &lt;code&gt;YAML&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Its biggest appeal is how clean it looks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fewer braces and quotes&lt;/li&gt;
&lt;li&gt;indentation expresses hierarchy&lt;/li&gt;
&lt;li&gt;comments are supported&lt;/li&gt;
&lt;li&gt;anchors can be used for reuse&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So from a first-glance human perspective, &lt;code&gt;YAML&lt;/code&gt; usually feels friendlier than &lt;code&gt;JSON&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;But the problem is also exactly there. It hides a lot of complexity, and in real use it often produces two classic failure modes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;indentation hell&lt;/li&gt;
&lt;li&gt;implicit type conversion&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Indentation issues are easy to understand: one extra or missing space can break the config. Worse still, implicit type conversion means some values that look like plain strings may be interpreted automatically as booleans or some other type.&lt;/p&gt;
&lt;p&gt;That is why so many people praise how good &lt;code&gt;YAML&lt;/code&gt; looks and at the same time suffer badly from it. It is genuinely good for human readability, but machines do not parse it effortlessly, and different parser libraries may even disagree in subtle ways.&lt;/p&gt;
&lt;p&gt;The same config written in &lt;code&gt;YAML&lt;/code&gt; usually looks cleaner:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;host&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;127.0.0.1&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;port&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;m&#34;&gt;8080&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;feature&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;enable_cache&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;06-toml-a-balance-between-readability-and-determinism&#34;&gt;06 TOML: a balance between readability and determinism
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;TOML&lt;/code&gt; is often presented as a modern balanced answer.&lt;/p&gt;
&lt;p&gt;Its appeal is that it combines some of the directness of &lt;code&gt;INI&lt;/code&gt; with some of the type clarity of &lt;code&gt;JSON&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;support for comments&lt;/li&gt;
&lt;li&gt;clear structure&lt;/li&gt;
&lt;li&gt;stronger, more explicit typing&lt;/li&gt;
&lt;li&gt;more natural handling of common types such as date and time&lt;/li&gt;
&lt;li&gt;far fewer of the implicit-conversion traps common in &lt;code&gt;YAML&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It has also become increasingly common in modern toolchains, such as Python’s &lt;code&gt;pyproject.toml&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Of course it is not perfect. For deeply nested structures, &lt;code&gt;TOML&lt;/code&gt; can become verbose, and path-style writing can feel repetitive. But for small to medium project config, tool config, and package-management config, its overall experience is often very steady.&lt;/p&gt;
&lt;p&gt;If you want a format with comments, clear meaning, and low parser pain, &lt;code&gt;TOML&lt;/code&gt; is a very strong candidate.&lt;/p&gt;
&lt;p&gt;A common &lt;code&gt;TOML&lt;/code&gt; example looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-toml&#34; data-lang=&#34;toml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;server&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;host&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;127.0.0.1&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;port&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;8080&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;[&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;feature&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nx&#34;&gt;enable_cache&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;07-conf-and-apache-config-not-a-universal-format-but-a-domain-language&#34;&gt;07 &lt;code&gt;.conf&lt;/code&gt; and Apache config: not a universal format, but a domain language
&lt;/h2&gt;&lt;p&gt;One point that is worth emphasizing is that many people see &lt;code&gt;.conf&lt;/code&gt; and assume it is a single standard format. It is not.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.conf&lt;/code&gt; is just a filename suffix for “configuration.” What the contents look like depends entirely on the specific system’s own rules. In other words, &lt;code&gt;.conf&lt;/code&gt; is more like a broad category than a standard syntax.&lt;/p&gt;
&lt;p&gt;Take &lt;code&gt;Apache&lt;/code&gt; config as an example. Its style is very representative:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;part of it looks like single-line directives&lt;/li&gt;
&lt;li&gt;part of it looks like tagged blocks with scoped behavior&lt;/li&gt;
&lt;li&gt;and it fits very naturally in the domain of web servers&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Its strengths are practical for operations work, especially when expressing permissions, routing, and virtual hosts. The downside is that it serves its own ecosystem and does not have much general-purpose portability.&lt;/p&gt;
&lt;p&gt;That makes it closer to a domain-specific language: great in the system it was designed for, but not something to treat as a universal config format.&lt;/p&gt;
&lt;p&gt;For example, a minimal Apache-style config looks more like a directive list:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-apache&#34; data-lang=&#34;apache&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;Listen&lt;/span&gt; &lt;span class=&#34;m&#34;&gt;80&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;VirtualHost&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;*:80&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;ServerName&lt;/span&gt; example.com
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nb&#34;&gt;DocumentRoot&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;/var/www/html&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;&amp;lt;/VirtualHost&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;08-protocol-buffers-industrial-strength-typing-but-with-a-higher-barrier&#34;&gt;08 Protocol Buffers: industrial-strength typing, but with a higher barrier
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Protocol Buffers&lt;/code&gt; are not really “just write a config file by hand” anymore. They are closer to a formal data definition and serialization system.&lt;/p&gt;
&lt;p&gt;Their strengths are substantial:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;strong typing&lt;/li&gt;
&lt;li&gt;explicit schema&lt;/li&gt;
&lt;li&gt;good forward and backward compatibility&lt;/li&gt;
&lt;li&gt;compact binary transmission&lt;/li&gt;
&lt;li&gt;efficient machine processing&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But the costs are equally clear:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you need to define &lt;code&gt;.proto&lt;/code&gt; files first&lt;/li&gt;
&lt;li&gt;you need tools and a compilation step&lt;/li&gt;
&lt;li&gt;and the barrier is relatively high for small projects&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So they are not ideal when you just want to configure a small tool. But if you are building large systems, RPC services, distributed systems, or long-lived data protocols, they are often far more reliable than lightweight config formats.&lt;/p&gt;
&lt;p&gt;Their style is closer to “define the structure first, then generate code”:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-proto&#34; data-lang=&#34;proto&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;n&#34;&gt;syntax&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s&#34;&gt;&amp;#34;proto3&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;kd&#34;&gt;message&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;ServerConfig&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kt&#34;&gt;string&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;host&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;1&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kt&#34;&gt;int32&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;port&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;2&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;kt&#34;&gt;bool&lt;/span&gt; &lt;span class=&#34;n&#34;&gt;enable_cache&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;mi&#34;&gt;3&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;err&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;09-in-the-ai-agent-era-markdown-may-become-a-config-format-again&#34;&gt;09 In the AI Agent era, Markdown may become a config format again
&lt;/h2&gt;&lt;p&gt;The most interesting part of this discussion is putting &lt;code&gt;Markdown&lt;/code&gt; into the category of “config formats.”&lt;/p&gt;
&lt;p&gt;From a traditional programming perspective, that sounds strange, because &lt;code&gt;Markdown&lt;/code&gt; normally feels more like a documentation format. But if the target is no longer a rigid parser and instead a large language model or AI Agent, the argument actually makes sense.&lt;/p&gt;
&lt;p&gt;Why?&lt;/p&gt;
&lt;p&gt;Because traditional programs depend on strict syntax and fixed fields, while large models are much better at understanding meaning, structure, and context. For them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;headings are hierarchy&lt;/li&gt;
&lt;li&gt;lists are steps&lt;/li&gt;
&lt;li&gt;bold text is emphasis&lt;/li&gt;
&lt;li&gt;natural language itself can carry rules&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So when the target of configuration changes from “a rigid parser” to “an agent that can understand meaning,” then &lt;code&gt;Markdown&lt;/code&gt;, as a human-friendly structured text format, may actually become a more natural kind of configuration.&lt;/p&gt;
&lt;p&gt;That leads to a very important judgment: in the traditional software era, many config formats existed to make humans adapt to machines; in the AI era, machines are beginning to adapt to human expression instead.&lt;/p&gt;
&lt;p&gt;For example, task configuration for an agent might simply be written like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;14
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-markdown&#34; data-lang=&#34;markdown&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gh&#34;&gt;# Goal
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;Write a welcome email for a new user.
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## Requirements
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Friendly tone
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; No more than 150 words
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Mention the product&amp;#39;s 3 core features
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;gu&#34;&gt;## Forbidden
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Do not promise features that do not exist
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;-&lt;/span&gt; Do not use exaggerated marketing language
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;10-so-how-should-you-choose&#34;&gt;10 So how should you choose?
&lt;/h2&gt;&lt;p&gt;If we compress the whole discussion, I would group the choices roughly like this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;if you want extremely simple, lightweight, flat config: &lt;code&gt;INI&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if you want strong structure, strong validation, and legacy compatibility: &lt;code&gt;XML&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if you want network transmission and interface exchange: &lt;code&gt;JSON&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if you want high readability plus cloud-native and deployment config: &lt;code&gt;YAML&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if you want a steadier modern general-purpose config experience: &lt;code&gt;TOML&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if you want domain-specific internal rules: &lt;code&gt;.conf&lt;/code&gt; / Apache-style DSLs&lt;/li&gt;
&lt;li&gt;if you want industrial protocol design and long-term evolution: &lt;code&gt;Protocol Buffers&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;if you want natural expression and task orchestration for AI Agents: &lt;code&gt;Markdown&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So there is no single “best config file format.” It depends on who you are writing for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;humans maintaining the system&lt;/li&gt;
&lt;li&gt;machines parsing at high speed&lt;/li&gt;
&lt;li&gt;services communicating with each other&lt;/li&gt;
&lt;li&gt;or AI Agents that need to understand and execute&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;short-conclusion&#34;&gt;Short conclusion
&lt;/h2&gt;&lt;p&gt;The history of config files is, at its core, the history of humans and machines constantly renegotiating where the cost of understanding should sit.&lt;/p&gt;
&lt;p&gt;In the past, humans had to adapt to machines, so we had to memorize brackets, indentation rules, quotes, and rigid syntax. Now that large language models and agent systems are getting better at understanding natural expression, “configuration” itself is beginning to change.&lt;/p&gt;
&lt;p&gt;Perhaps in the future, many config scenarios will no longer revolve around one fixed syntax, but around structured statements of intent. Until then, formats like &lt;code&gt;JSON&lt;/code&gt;, &lt;code&gt;YAML&lt;/code&gt;, &lt;code&gt;TOML&lt;/code&gt;, &lt;code&gt;INI&lt;/code&gt;, and &lt;code&gt;XML&lt;/code&gt; will continue to coexist, each occupying the role that fits it best.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>Build Docker Images in VS Code on Windows: From Setup to Build</title>
        <link>https://knightli.com/en/2026/04/16/vscode-docker-image-build-windows/</link>
        <pubDate>Thu, 16 Apr 2026 10:20:00 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/04/16/vscode-docker-image-build-windows/</guid>
        <description>&lt;p&gt;If you want to build Docker images directly from VS Code on Windows, the workflow is straightforward. You only need three parts: prepare the environment, create a Dockerfile, then run the build.&lt;/p&gt;
&lt;h2 id=&#34;01-prerequisites&#34;&gt;01 Prerequisites
&lt;/h2&gt;&lt;p&gt;Make sure these two items are ready:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Install and run Docker Desktop.&lt;/li&gt;
&lt;li&gt;Install the official Microsoft &lt;code&gt;Docker&lt;/code&gt; extension in VS Code.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;On Windows, using the &lt;code&gt;WSL 2&lt;/code&gt; backend in Docker Desktop (&lt;code&gt;Settings &amp;gt; Resources &amp;gt; WSL Integration&lt;/code&gt;) is usually more stable and faster.&lt;/p&gt;
&lt;h2 id=&#34;02-prepare-a-dockerfile&#34;&gt;02 Prepare a Dockerfile
&lt;/h2&gt;&lt;p&gt;If your project does not have one yet, VS Code can generate it:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Open your project folder in VS Code.&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;F1&lt;/code&gt; or &lt;code&gt;Ctrl+Shift+P&lt;/code&gt; to open the Command Palette.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;Docker: Add Docker Files to Workspace&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Choose your platform (Node.js, Python, .NET, etc.) and follow the prompts.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You will typically get at least:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;.dockerignore&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This gives you a working baseline that you can refine later.&lt;/p&gt;
&lt;h2 id=&#34;03-three-ways-to-build-the-image&#34;&gt;03 Three Ways to Build the Image
&lt;/h2&gt;&lt;h3 id=&#34;method-a-right-click-dockerfile&#34;&gt;Method A: Right-click Dockerfile
&lt;/h3&gt;&lt;p&gt;In the File Explorer, right-click &lt;code&gt;Dockerfile&lt;/code&gt;, select &lt;code&gt;Build Image...&lt;/code&gt;, and enter an image tag.&lt;/p&gt;
&lt;h3 id=&#34;method-b-command-palette&#34;&gt;Method B: Command Palette
&lt;/h3&gt;&lt;p&gt;Press &lt;code&gt;F1&lt;/code&gt;, run &lt;code&gt;Docker: Build Image&lt;/code&gt;, then select context and tag.&lt;/p&gt;
&lt;h3 id=&#34;method-c-integrated-terminal&#34;&gt;Method C: Integrated Terminal
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;docker build -t your-image-name .
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;This command builds an image from the current directory context with the tag &lt;code&gt;your-image-name&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&#34;04-quick-checks-for-common-issues&#34;&gt;04 Quick Checks for Common Issues
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;Docker Desktop is not running: verify it is started.&lt;/li&gt;
&lt;li&gt;Build is very slow: check whether WSL 2 backend is enabled.&lt;/li&gt;
&lt;li&gt;Build cannot find files: ensure your terminal is at the project root and files are inside build context.&lt;/li&gt;
&lt;li&gt;Docker resources do not show in VS Code: restart VS Code and check Docker CLI (&lt;code&gt;docker version&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;Building Docker images in VS Code on Windows is mostly a setup problem. Once Docker Desktop and the VS Code Docker extension are in place, you can generate Docker files quickly and build images from either the UI or the terminal.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>CH347 Resource Guide: Drivers, Tools, and SPI Flash Programming</title>
        <link>https://knightli.com/en/2026/04/03/ch347-resources-drivers-tools/</link>
        <pubDate>Fri, 03 Apr 2026 10:00:00 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/04/03/ch347-resources-drivers-tools/</guid>
        <description>&lt;p&gt;This post summarizes the CH347 resources I use most often, with one goal: get you from setup to debugging/programming as quickly as possible.&lt;/p&gt;
&lt;p&gt;If you are new to CH347, prepare your environment in this order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check the official product page first&lt;/li&gt;
&lt;li&gt;Install the correct driver for your use case&lt;/li&gt;
&lt;li&gt;Prepare an SPI Flash tool and verify connectivity&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;official-entry&#34;&gt;Official Entry
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;CH347 product page: &lt;a class=&#34;link&#34; href=&#34;https://www.wch.cn/products/CH347.html&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://www.wch.cn/products/CH347.html&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It is best to download from the official page first, to avoid outdated or unknown-source driver packages.&lt;/p&gt;
&lt;h2 id=&#34;common-drivers&#34;&gt;Common Drivers
&lt;/h2&gt;&lt;h3 id=&#34;1-ch341parexe&#34;&gt;1) &lt;code&gt;CH341PAR.EXE&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;Purpose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;USB-to-JTAG / SPI / I2C / Parallel / GPIO interface driver&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Typical use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Multi-protocol communication and low-level interface debugging with CH347&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;2-ch343serexe&#34;&gt;2) &lt;code&gt;CH343SER.EXE&lt;/code&gt;
&lt;/h3&gt;&lt;p&gt;Purpose:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Vendor Windows driver for high-speed USB-to-Serial&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Typical use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Using CH347 mainly as a serial tool, especially at higher baud rates&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;spi-flash-programming-tool&#34;&gt;SPI Flash Programming Tool
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;AsProgrammer: &lt;a class=&#34;link&#34; href=&#34;https://github.com/nofeletru/UsbAsp-flash&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;https://github.com/nofeletru/UsbAsp-flash&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Common tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Detect SPI NOR Flash&lt;/li&gt;
&lt;li&gt;Read chip ID&lt;/li&gt;
&lt;li&gt;Back up original firmware&lt;/li&gt;
&lt;li&gt;Erase / write / verify firmware&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;recommended-workflow-to-avoid-common-mistakes&#34;&gt;Recommended Workflow (to avoid common mistakes)
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;After installing drivers, replug the device and confirm detection in Device Manager.&lt;/li&gt;
&lt;li&gt;Before first write, do one full read + backup of the original contents.&lt;/li&gt;
&lt;li&gt;Always run verify after writing. Do not rely only on a &amp;ldquo;write successful&amp;rdquo; message.&lt;/li&gt;
&lt;li&gt;If the chip is not detected, check power, voltage level, and wiring before checking software settings.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;quick-troubleshooting&#34;&gt;Quick Troubleshooting
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Device is plugged in but not visible in tools: usually driver loading issues, or a power-only USB cable.&lt;/li&gt;
&lt;li&gt;Device is detected but read/write fails: first check wiring order, shared ground, and power stability.&lt;/li&gt;
&lt;li&gt;Unstable behavior at high speed: lower read/write speed first, then increase gradually after stability is confirmed.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;CH347 is not hard to use. The key is to get four things right: driver, tool, wiring, and verification.&lt;/p&gt;
&lt;p&gt;The resources above cover most beginner and day-to-day maintenance scenarios, and should get you to a stable workflow quickly.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>FFmpeg `-map` Explained: Precisely Select Video, Audio, and Subtitle Streams</title>
        <link>https://knightli.com/en/2026/04/02/ffmpeg-map-parameter-guide/</link>
        <pubDate>Thu, 02 Apr 2026 23:14:03 +0800</pubDate>
        
        <guid>https://knightli.com/en/2026/04/02/ffmpeg-map-parameter-guide/</guid>
        <description>&lt;p&gt;In multi-audio and multi-subtitle workflows, &lt;code&gt;-map&lt;/code&gt; is one of FFmpeg&amp;rsquo;s most important and most frequently misused options.&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t explicitly specify &lt;code&gt;-map&lt;/code&gt;, FFmpeg auto-selects streams using default rules, and the output is often not what you expect. For example:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Subtitles disappear after export&lt;/li&gt;
&lt;li&gt;The wrong language track is selected&lt;/li&gt;
&lt;li&gt;Unwanted data streams are included&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This article uses common real-world scenarios to explain how &lt;code&gt;-map&lt;/code&gt; works.&lt;/p&gt;
&lt;h2 id=&#34;first-understand-what-a-stream-is&#34;&gt;First, Understand What a &amp;ldquo;Stream&amp;rdquo; Is
&lt;/h2&gt;&lt;p&gt;A container file (such as &lt;code&gt;mp4&lt;/code&gt; or &lt;code&gt;mkv&lt;/code&gt;) usually contains multiple streams, including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Video streams (&lt;code&gt;v&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Audio streams (&lt;code&gt;a&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Subtitle streams (&lt;code&gt;s&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Attachment/data streams (fonts, cover art, chapters, etc.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can inspect streams with &lt;code&gt;ffprobe&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ffprobe -hide_banner input.mkv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;basic--map-syntax&#34;&gt;Basic &lt;code&gt;-map&lt;/code&gt; Syntax
&lt;/h2&gt;&lt;p&gt;Most common pattern:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;-map input_index[:stream_type][:stream_index]
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0:v&lt;/code&gt;: all video streams from the 1st input&lt;/li&gt;
&lt;li&gt;&lt;code&gt;0:a:0&lt;/code&gt;: the 1st audio stream from the 1st input&lt;/li&gt;
&lt;li&gt;&lt;code&gt;1:s:1&lt;/code&gt;: the 2nd subtitle stream from the 2nd input&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Notes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;input_index&lt;/code&gt; starts from &lt;code&gt;0&lt;/code&gt;, based on &lt;code&gt;-i&lt;/code&gt; order&lt;/li&gt;
&lt;li&gt;&lt;code&gt;stream_index&lt;/code&gt; also starts from &lt;code&gt;0&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;practical-examples&#34;&gt;Practical Examples
&lt;/h2&gt;&lt;h3 id=&#34;1-video-from-a-audio-from-b&#34;&gt;1) Video from A, audio from B
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ffmpeg -i english.mp4 -i french.mp3 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -map 0:v:0 -map 1:a:0 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -c:v copy -c:a aac &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  french.mp4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Meaning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Use the first video stream from &lt;code&gt;english.mp4&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Use the first audio stream from &lt;code&gt;french.mp3&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Merge into &lt;code&gt;french.mp4&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;2-keep-all-streams-from-input-1-then-add-one-more-audio-track&#34;&gt;2) Keep all streams from input 1, then add one more audio track
&lt;/h3&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ffmpeg -i english.mp4 -i french.mp3 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -map &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; -map 1:a:0 &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -c copy &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  english-french.mp4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Meaning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;-map 0&lt;/code&gt; keeps all streams from the first input&lt;/li&gt;
&lt;li&gt;Then append the first audio stream from the second input&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;two-useful-advanced-tricks&#34;&gt;Two Useful Advanced Tricks
&lt;/h2&gt;&lt;h3 id=&#34;1-negative-mapping-exclude-unwanted-streams&#34;&gt;1) Negative mapping: exclude unwanted streams
&lt;/h3&gt;&lt;p&gt;For example, keep everything from input 1 but remove its second audio stream:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ffmpeg -i input.mkv -map &lt;span class=&#34;m&#34;&gt;0&lt;/span&gt; -map -0:a:1 -c copy output.mkv
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id=&#34;2-optional-mapping-dont-fail-when-a-stream-is-missing&#34;&gt;2) Optional mapping: don&amp;rsquo;t fail when a stream is missing
&lt;/h3&gt;&lt;p&gt;If some files may not have subtitles, use &lt;code&gt;?&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ffmpeg -i input.mp4 -map 0:v -map 0:a -map 0:s? -c copy output.mp4
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;code&gt;0:s?&lt;/code&gt; means: map subtitles if present; otherwise skip without error.&lt;/p&gt;
&lt;h2 id=&#34;common-pitfalls&#34;&gt;Common Pitfalls
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;Once you use &lt;code&gt;-map&lt;/code&gt;, FFmpeg stops automatic stream selection, so you must map everything you need.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-c copy&lt;/code&gt; only remuxes without transcoding. If the target container doesn&amp;rsquo;t support a codec, it still fails.&lt;/li&gt;
&lt;li&gt;With multiple inputs, index mistakes are common. Input indices are determined only by &lt;code&gt;-i&lt;/code&gt; order.&lt;/li&gt;
&lt;li&gt;For robust scripts, inspect with &lt;code&gt;ffprobe&lt;/code&gt; first, then generate &lt;code&gt;-map&lt;/code&gt; dynamically.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;The core idea of &lt;code&gt;-map&lt;/code&gt; is simple: explicitly tell FFmpeg which input to use, what stream type to pick, and which stream index to select.&lt;/p&gt;
&lt;p&gt;Once you master this, you can reliably handle complex cases like multi-audio, multi-subtitle, and cross-file stream composition.&lt;/p&gt;
</description>
        </item>
        <item>
        <title>How to Troubleshoot High VS Code CPU Usage Caused by Extensions</title>
        <link>https://knightli.com/en/2026/04/01/vscode-extension-cpu-troubleshooting/</link>
        <pubDate>Wed, 01 Apr 2026 00:00:00 +0000</pubDate>
        
        <guid>https://knightli.com/en/2026/04/01/vscode-extension-cpu-troubleshooting/</guid>
        <description>&lt;p&gt;When VS Code suddenly feels laggy, your fan spins up, and CPU usage stays high, the most common cause is usually not the editor itself, but extension conflicts or abnormal extension behavior.&lt;/p&gt;
&lt;p&gt;This guide gives you a direct, actionable workflow to identify the issue quickly.&lt;/p&gt;
&lt;h2 id=&#34;start-with-the-fastest-method-start-extension-bisect&#34;&gt;Start with the Fastest Method: Start Extension Bisect
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;Start Extension Bisect&lt;/code&gt; uses a binary search approach:
in each round, VS Code temporarily disables half of your extensions and restarts. Based on whether the issue still appears, it narrows down the suspect list quickly.&lt;/p&gt;
&lt;p&gt;Steps:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Press &lt;code&gt;Ctrl+Shift+P&lt;/code&gt; (macOS: &lt;code&gt;Cmd+Shift+P&lt;/code&gt;) to open the Command Palette.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;Start Extension Bisect&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;After each restart, check whether high CPU usage and lag are still present, then choose &lt;code&gt;Good now&lt;/code&gt; or &lt;code&gt;This is bad&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;After several rounds, VS Code will show the likely problematic extension(s).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;what-to-do-after-you-find-the-suspect&#34;&gt;What to Do After You Find the Suspect
&lt;/h2&gt;&lt;p&gt;Once you identify the extension, handle it in this order:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Update the extension to the latest version.&lt;/li&gt;
&lt;li&gt;If the issue remains, disable it for 1-2 days and observe.&lt;/li&gt;
&lt;li&gt;If alternatives exist, switch to a lighter extension.&lt;/li&gt;
&lt;li&gt;If you must keep it, review advanced settings and disable unnecessary real-time analysis, indexing, or file watching features.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;two-common-amplifiers-you-might-overlook&#34;&gt;Two Common &amp;ldquo;Amplifiers&amp;rdquo; You Might Overlook
&lt;/h2&gt;&lt;p&gt;Even if an extension is the root cause, these settings can amplify CPU load:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Search scope is too broad&lt;br&gt;
If build output, dependency folders, and logs are included in global search, extensions and indexers may stay under continuous heavy load.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;File watching includes huge folders or symlinks&lt;br&gt;
Symlinks, cache directories, and generated folders can trigger large numbers of file events and force extensions to reprocess repeatedly.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;You can trim scope in &lt;code&gt;settings.json&lt;/code&gt;, for example:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;search.exclude&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;**/node_modules&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;**/dist&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;**/build&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;nt&#34;&gt;&amp;#34;files.watcherExclude&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;**/.git/objects/**&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;**/node_modules/**&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;nt&#34;&gt;&amp;#34;**/dist/**&amp;#34;&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt; &lt;span class=&#34;kc&#34;&gt;true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id=&#34;postmortem-tip&#34;&gt;Postmortem Tip
&lt;/h2&gt;&lt;p&gt;After isolating the issue, record three things: extension name, trigger scenario, and final fix.&lt;br&gt;
That note will save time when you migrate your environment or rebuild your machine later.&lt;/p&gt;
&lt;h2 id=&#34;summary&#34;&gt;Summary
&lt;/h2&gt;&lt;p&gt;For high VS Code CPU usage, the most effective path is to use &lt;code&gt;Start Extension Bisect&lt;/code&gt; first, then tighten search and file watching scope.&lt;br&gt;
Locate first, optimize second. It is faster and more reliable than randomly disabling many extensions.&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
