<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Paul</title>
    <description>The latest articles on DEV Community by Paul (@jane_lee_ecafb4b88ef2eff0).</description>
    <link>https://dev.to/jane_lee_ecafb4b88ef2eff0</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3527049%2F7c15ef55-e4a2-4791-9354-60112535486c.png</url>
      <title>DEV Community: Paul</title>
      <link>https://dev.to/jane_lee_ecafb4b88ef2eff0</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jane_lee_ecafb4b88ef2eff0"/>
    <language>en</language>
    <item>
      <title>A Fig That Works Anywhere — FaiTerm</title>
      <dc:creator>Paul</dc:creator>
      <pubDate>Thu, 01 Oct 2026 15:03:12 +0000</pubDate>
      <link>https://dev.to/jane_lee_ecafb4b88ef2eff0/a-fig-that-works-anywhere-faiterm-47d8</link>
      <guid>https://dev.to/jane_lee_ecafb4b88ef2eff0/a-fig-that-works-anywhere-faiterm-47d8</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqn0sb80mf439l27vsnhh.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqn0sb80mf439l27vsnhh.jpg" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Do any of these sound familiar?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do I get Fig on Windows?&lt;/li&gt;
&lt;li&gt;When will Fig's command suggestions ever land on Linux?&lt;/li&gt;
&lt;li&gt;Can Fig's completion also use my command history?&lt;/li&gt;
&lt;li&gt;If I work over SSH, how do I get Fig-style completion without installing anything on the remote machine?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Preface
&lt;/h2&gt;

&lt;p&gt;If you spend a lot of time on the command line, you already know the pain: too many commands, too many flags, and no completion worth the name. What you want is something like the candidate list from an input method editor — except for shell commands. That thing was Fig — &lt;a href="https://app.fig.io" rel="noopener noreferrer"&gt;https://app.fig.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But Fig only ever shipped a Mac version. Nobody else got to experience that kind of command-line completion. Fig did open-source its completion data, though: &lt;a href="https://github.com/withfig/autocomplete" rel="noopener noreferrer"&gt;https://github.com/withfig/autocomplete&lt;/a&gt; — a pile of JavaScript that describes how commands should be suggested.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftc571stwafrywoc14jbo.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftc571stwafrywoc14jbo.gif" alt=" " width="662" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Fig: The Best Terminal Completion There Ever Was
&lt;/h2&gt;

&lt;p&gt;Fig has since been acquired by Amazon and renamed &lt;code&gt;Amazon Q&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once you had it installed and enabled, you'd type &lt;code&gt;git&lt;/code&gt; in iTerm2 and a dropdown would appear at the right of your cursor — &lt;code&gt;add&lt;/code&gt;, &lt;code&gt;commit&lt;/code&gt;, &lt;code&gt;push&lt;/code&gt;, &lt;code&gt;rebase&lt;/code&gt;… each with an icon and a one-line description. Keep typing &lt;code&gt;git checkout&lt;/code&gt; and it wouldn't list filenames; it would list the branches that actually exist in your repo. Type &lt;code&gt;npm run&lt;/code&gt; and it would list the real scripts from your &lt;code&gt;package.json&lt;/code&gt;. Type &lt;code&gt;docker&lt;/code&gt; and it would list the containers and images actually on your machine.&lt;/p&gt;

&lt;p&gt;That was Fig's entire ambition: &lt;strong&gt;give the terminal you already use an IDE-style completion experience.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  What Fig got right
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. It didn't build another terminal.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This was Fig's smartest move. Every other approach at the time either forced you onto a brand-new terminal emulator (Warp, Tabby) or left you stuck with the weak completion of the day. Fig chose to piggyback instead — it supported macOS Terminal, &lt;a href="https://iterm2.com" rel="noopener noreferrer"&gt;iTerm2&lt;/a&gt;, &lt;a href="https://tabby.sh" rel="noopener noreferrer"&gt;Tabby&lt;/a&gt;, &lt;a href="https://hyper.is" rel="noopener noreferrer"&gt;Hyper&lt;/a&gt;, &lt;a href="https://sw.kovidgoyal.net/kitty" rel="noopener noreferrer"&gt;Kitty&lt;/a&gt;, &lt;a href="https://wezfurlong.org/wezterm/" rel="noopener noreferrer"&gt;WezTerm&lt;/a&gt;, &lt;a href="https://alacritty.org/" rel="noopener noreferrer"&gt;Alacritty&lt;/a&gt;, and even the embedded terminals in VS Code, the JetBrains IDEs, and Android Studio. You changed nothing. You installed an app.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Completion quality came from human-written declarative specs, not guesswork.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This was Fig's real moat. It didn't try to guess what should follow &lt;code&gt;git checkout&lt;/code&gt;. It defined a &lt;strong&gt;completion spec&lt;/strong&gt; — a declarative schema describing a CLI's &lt;code&gt;subcommands&lt;/code&gt;, &lt;code&gt;options&lt;/code&gt;, and &lt;code&gt;args&lt;/code&gt;. The &lt;a href="https://github.com/withfig/autocomplete" rel="noopener noreferrer"&gt;withfig/autocomplete&lt;/a&gt; repo held specs like that for hundreds of popular CLIs, maintained by &lt;strong&gt;400+ contributors&lt;/strong&gt;. That data was Fig's single most valuable asset, and the part it open-sourced under the MIT license.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Fig's Limitations
&lt;/h2&gt;

&lt;p&gt;Fig proved that "declarative specs + a GUI dropdown" was the right direction. But the way it built that direction locked it in.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. It only supported macOS
&lt;/h3&gt;

&lt;p&gt;This wasn't "macOS only for now" — from 2021 until the day it shut down, &lt;strong&gt;Windows and Linux stayed officially "in progress."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The reason:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It depended on the &lt;strong&gt;Accessibility API&lt;/strong&gt;, which is macOS-specific. Windows and Linux have no equivalent, and "where is the cursor on screen" is simply an unsolvable problem there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The community pushed for Linux support from day one. The team opened &lt;a href="https://github.com/aws/q-command-line-discussions/discussions/14" rel="noopener noreferrer"&gt;discussion #14 (Linux)&lt;/a&gt; and &lt;a href="https://github.com/aws/q-command-line-discussions/discussions/15" rel="noopener noreferrer"&gt;discussion #15 (Windows)&lt;/a&gt;. Neither shipped before the Fig name disappeared.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Recommendations were mostly static
&lt;/h3&gt;

&lt;p&gt;Most of what Fig suggested was fixed. There was a dynamic portion too — branch names for &lt;code&gt;git&lt;/code&gt;, directory candidates for &lt;code&gt;cd&lt;/code&gt; — but that was about the extent of it.&lt;/p&gt;

&lt;p&gt;If you've used fish, you know its history-based command suggestions are a fantastic feature. Or zsh with zsh-autosuggestions, which gives you something similar.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Specs were TypeScript code
&lt;/h3&gt;

&lt;p&gt;This is the limitation that made Fig's assets &lt;strong&gt;genuinely unreusable by any other language.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Fig's specs were &lt;code&gt;.ts&lt;/code&gt; files. They could contain callbacks like &lt;code&gt;custom&lt;/code&gt;, &lt;code&gt;postProcess&lt;/code&gt;, and &lt;code&gt;generateSpec&lt;/code&gt; — real executable code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// The shape of a Fig spec (illustrative)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;spec&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Fig&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Spec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;git&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;subcommands&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkout&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;branch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;generators&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;git&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;branch&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;--no-color&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="na"&gt;postProcess&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;})),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Data and logic were mixed together, and that data &lt;strong&gt;had to run inside Node before it could be evaluated.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So when a Go, Rust, or Dart project said "I want Fig's completion too," what it faced wasn't "read a JSON file" — it was "re-translate the function logic across hundreds of TS files."&lt;/p&gt;

&lt;p&gt;So I forked it and started this project.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. autocomplete (Dart): Rebuilding Fig's Most Valuable Part as a Portable Engine
&lt;/h2&gt;

&lt;p&gt;Repo: &lt;strong&gt;&lt;a href="https://github.com/littlewrite/autocomplete" rel="noopener noreferrer"&gt;github.com/littlewrite/autocomplete&lt;/a&gt;&lt;/strong&gt; (a fork of &lt;code&gt;withfig/autocomplete&lt;/code&gt;; the new code lives in &lt;code&gt;dart/&lt;/code&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  3.1 The assets I inherited
&lt;/h3&gt;

&lt;p&gt;Measured against Fig's repo:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;Count&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Logical commands&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1463&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Alias entries&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;736&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Physical JSON documents&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;1464&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Coverage&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;git&lt;/code&gt;, &lt;code&gt;docker&lt;/code&gt;, &lt;code&gt;kubectl&lt;/code&gt;, &lt;code&gt;npm&lt;/code&gt;, &lt;code&gt;cargo&lt;/code&gt;, &lt;code&gt;brew&lt;/code&gt;, &lt;code&gt;terraform&lt;/code&gt;, &lt;code&gt;aws&lt;/code&gt;, &lt;code&gt;az&lt;/code&gt;, &lt;code&gt;gcloud&lt;/code&gt;, &lt;code&gt;flutter&lt;/code&gt;, &lt;code&gt;codex&lt;/code&gt;, &lt;code&gt;claude&lt;/code&gt; …&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Most of that repo is object definitions — spec definitions. A small fraction is dynamic code, i.e. spec generators: &lt;code&gt;git&lt;/code&gt; branches and &lt;code&gt;cd&lt;/code&gt; directory candidates, for instance, are produced by executing code.&lt;/p&gt;

&lt;h3&gt;
  
  
  3.2 The rewrite: a JSON-first architecture
&lt;/h3&gt;

&lt;p&gt;Since most of autocomplete is TypeScript object definitions, they can be converted into JSON files and deserialized back into objects at use time. That means Java can read it — and so can Go, Rust, and Python. All of them can read the same JSON and deserialize it into spec objects that just work. The dynamic functions are only a small part, and they're straightforward to convert.&lt;/p&gt;

&lt;p&gt;This is the fork's biggest design improvement:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static data → pure JSON&lt;/strong&gt;: command names, descriptions, &lt;code&gt;options&lt;/code&gt;, &lt;code&gt;subcommands&lt;/code&gt;, &lt;code&gt;args&lt;/code&gt;, &lt;code&gt;template&lt;/code&gt;, &lt;code&gt;loadSpec&lt;/code&gt; links, and the command and &lt;code&gt;splitOn&lt;/code&gt; of &lt;code&gt;script&lt;/code&gt; generators — all of it lives in JSON.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic behavior → stable handler ID references&lt;/strong&gt;: wherever code needs to run, the JSON keeps only a reference:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"branch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"generators"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"script"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"git"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"branch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"--no-color"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postProcess"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"handler"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git.branches"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;There is no executable code in the JSON.&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Improvements Over Fig
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Feature 1: JSON abstraction — one dataset, N languages
&lt;/h3&gt;

&lt;p&gt;Once specs become JSON, a completion spec stops being "some TypeScript code" and becomes &lt;strong&gt;a language-agnostic data contract&lt;/strong&gt;. Three things define it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;A JSON Schema&lt;/strong&gt; (&lt;code&gt;schema/completion-spec.schema.json&lt;/code&gt;) — what the data looks like;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A physical layout convention&lt;/strong&gt; — flat commands at &lt;code&gt;&amp;lt;first-letter&amp;gt;/&amp;lt;command&amp;gt;.json&lt;/code&gt;, namespaced commands at &lt;code&gt;&amp;lt;first-letter&amp;gt;/&amp;lt;namespace&amp;gt;/.../command.json&lt;/code&gt;, with &lt;code&gt;index.json&lt;/code&gt; mapping logical names to files only;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A handler contract&lt;/strong&gt; — &lt;code&gt;{"handler": id, "version": n}&lt;/code&gt;, where the field's position determines the callback signature (&lt;code&gt;custom&lt;/code&gt; / &lt;code&gt;postProcess&lt;/code&gt; / &lt;code&gt;trigger&lt;/code&gt; / &lt;code&gt;generateSpec&lt;/code&gt; / &lt;code&gt;alias&lt;/code&gt; / &lt;code&gt;script&lt;/code&gt; each have an explicit Dart signature).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That makes extensibility remarkably clean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Switching languages&lt;/strong&gt;: any language with a JSON parser — Go, Rust, Java, Kotlin, Swift, C#, JS — can implement its own handler registry and &lt;strong&gt;reuse the exact same JSON catalog without changing a single byte&lt;/strong&gt;. Dart is simply the first implementation that works end to end, not the only one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A handler ID is a versioned API boundary&lt;/strong&gt;: the &lt;code&gt;version&lt;/code&gt; field makes semantic changes traceable. If the semantics don't change, old documents keep working; if they do, you bump the version and old and new implementations can coexist.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data updates require recompiling no host at all&lt;/strong&gt;: adding a command to the catalog means adding a JSON file, not editing code in any language.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Reusing Fig's specs in another language would have meant "re-translating the logic" — fully translating several thousand files into the target language, an enormous amount of work. By defining the spec as JSON, that work disappears entirely. What's left is the dynamic functions, and they're only a small fraction, so porting them is far quicker.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feature 2: A genuinely platform-independent runtime (pure Dart, no Flutter dependency)
&lt;/h3&gt;

&lt;p&gt;The package's &lt;code&gt;lib/&lt;/code&gt; contains &lt;strong&gt;no &lt;code&gt;dart:io&lt;/code&gt;&lt;/strong&gt; and &lt;strong&gt;does not depend on Flutter&lt;/strong&gt;. It asks the host for exactly two injection points:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="c1"&gt;// 1. Where does the data come from — a function that returns a string&lt;/span&gt;
&lt;span class="kd"&gt;typedef&lt;/span&gt; &lt;span class="n"&gt;JsonAssetReader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="kt"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;relativePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// 2. The completion environment — directories, processes, environment variables&lt;/span&gt;
&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompleteAdapter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Feature 3: The adapter abstraction — the completion environment itself is replaceable
&lt;/h3&gt;

&lt;p&gt;For Fig, the completion environment &lt;em&gt;was&lt;/em&gt; the local machine. This project abstracts it into an interface:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight dart"&gt;&lt;code&gt;&lt;span class="kd"&gt;abstract&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CompleteAdapter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="n"&gt;getEnv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;resolveCwd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Shell&lt;/span&gt; &lt;span class="n"&gt;shell&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;FileSystemEntry&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;listDirectory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;Future&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;ProcessRunResult&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;runProcess&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;String&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;command&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So completion can work in three completely different worlds:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Adapter&lt;/th&gt;
&lt;th&gt;Scenario&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Local (&lt;code&gt;dart:io&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;The local shell&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SSH / SFTP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;A remote server: directory listings go over remote SFTP, and a generator's &lt;code&gt;script&lt;/code&gt; is executed &lt;strong&gt;on the remote host&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Noop&lt;/td&gt;
&lt;td&gt;Disconnected / unknown host — &lt;strong&gt;never silently falls back to the local filesystem&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Add to that a &lt;code&gt;Shell&lt;/code&gt; enum covering &lt;code&gt;bash&lt;/code&gt; / &lt;code&gt;zsh&lt;/code&gt; / &lt;code&gt;fish&lt;/code&gt; / &lt;code&gt;pwsh&lt;/code&gt; / &lt;code&gt;powershell&lt;/code&gt; / &lt;code&gt;cmd&lt;/code&gt; / &lt;code&gt;xonsh&lt;/code&gt; / &lt;code&gt;nushell&lt;/code&gt;, plus a per-session &lt;code&gt;pathSeparator&lt;/code&gt; (only native Windows consoles use &lt;code&gt;\&lt;/code&gt;; WSL / Git Bash / macOS / Linux / remote Unix all use &lt;code&gt;/&lt;/code&gt;) — &lt;strong&gt;cross-platform isn't a slogan here, it's semantics nailed down one at a time.&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Yes: you can use it from Dart on any platform, any OS — even the Web.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Feature 4: Streaming completion — static results immediately, slow ones later
&lt;/h3&gt;

&lt;p&gt;Completion splits into static and dynamic. With streaming completion, the user gets the static suggestions right away, and as soon as the dynamic code finishes executing, those results keep filling into the list. The whole thing just feels faster.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Static&lt;/strong&gt;: the subcommands, options, and args hardcoded in the spec. They're sitting in the local JSON; they come back in microseconds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic&lt;/strong&gt;: anything that requires actually running a process. &lt;code&gt;git branch&lt;/code&gt;, &lt;code&gt;docker ps&lt;/code&gt;, &lt;code&gt;kubectl get pods&lt;/code&gt;, directory listings…&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fig's approach was &lt;strong&gt;compute everything, then show it all at once.&lt;/strong&gt; What the user experienced: type, wait, and only once everything had been generated did the full list of suggestions appear. Over SSH, where you're at the mercy of the network, that experience is nothing short of disastrous.&lt;/p&gt;

&lt;p&gt;autocomplete provides &lt;code&gt;SuggestionRequestMode.staticThenFinal&lt;/code&gt;, which splits a single computation into &lt;strong&gt;progressive frames&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Frame&lt;/th&gt;
&lt;th&gt;Contents&lt;/th&gt;
&lt;th&gt;Arrives&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;staticPartial&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The subcommands / options / args from the spec&lt;/td&gt;
&lt;td&gt;Immediately&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;staticPartial&lt;/code&gt; (second frame)&lt;/td&gt;
&lt;td&gt;New subcommands produced by &lt;code&gt;generateSpec&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Once generated&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sourcePartial&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The result of one dynamic source (&lt;strong&gt;one frame per source&lt;/strong&gt;)&lt;/td&gt;
&lt;td&gt;As each generator finishes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;finalResult&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The authoritative, complete result&lt;/td&gt;
&lt;td&gt;Once everything is done&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Which means the experience becomes: &lt;strong&gt;by the time you've finished typing, suggestions are already in front of you; while you're reading and choosing, the rest keep filling in.&lt;/strong&gt; Not "wait for every command to finish computing before anything appears."&lt;/p&gt;

&lt;h2&gt;
  
  
  5. FaiTerm: A Cross-Platform Command-Completion Terminal
&lt;/h2&gt;

&lt;p&gt;FaiTerm is a terminal GUI built with Flutter. Command completion is built in — no extra configuration needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.1 Why build a terminal
&lt;/h3&gt;

&lt;p&gt;Because I want to use it on Windows and Linux — and on Android and mobile devices too.&lt;/p&gt;

&lt;p&gt;Tools like Fig &lt;strong&gt;piggyback on someone else's terminal&lt;/strong&gt;, so they have to obtain two things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The cursor's on-screen coordinates&lt;/strong&gt; — only available through macOS's Accessibility API; Windows and Linux have no equivalent.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;What you're currently typing&lt;/strong&gt; — only available by inserting a pseudo-terminal passthrough layer between the terminal and the shell.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Those two constraints mean it can never cross platforms.&lt;/p&gt;

&lt;p&gt;So flip it around: what if the terminal &lt;em&gt;is&lt;/em&gt; mine?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Where's the cursor? &lt;strong&gt;I render it — of course I know.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;What are you typing? &lt;strong&gt;I receive the keystrokes, and I maintain the edit buffer.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;What's the shell, and what's the current directory? &lt;strong&gt;I spawned the PTY — I know.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Otherwise you're stuck depending on the &lt;code&gt;Accessibility API&lt;/code&gt;, a pseudo-terminal passthrough layer, and system accessibility permissions — and cross-platform becomes extraordinarily hard.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.2 Command history suggestions
&lt;/h3&gt;

&lt;p&gt;On top of autocomplete's dynamic suggestions, FaiTerm also suggests commands based on your history. Compared to zsh-autosuggestions, FaiTerm's history completion gives you &lt;strong&gt;multiple choices at once.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I use that plugin myself, and most of the time it's excellent. But there's one annoyance: when two commands are very similar, unless you type something that differentiates them, you can't bring up the other suggestion. That's the pain point I ran into after using the zsh plugin for a long time.&lt;/p&gt;

&lt;h3&gt;
  
  
  5.3 What FaiTerm can do today
&lt;/h3&gt;

&lt;p&gt;Beyond completion, it's a terminal you can genuinely live in.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Capability&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;Multi-tab terminal&lt;/td&gt;
&lt;td&gt;Native Pty; local and remote share one interaction model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Command completion&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;spec + history + notes + AI, merged into one list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multi-protocol connections&lt;/td&gt;
&lt;td&gt;SSH / SFTP / Telnet / FTP / serial, unified into a single connection list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SFTP file management&lt;/td&gt;
&lt;td&gt;Dual-pane, drag and drop, transfer queue&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI chat and Agent&lt;/td&gt;
&lt;td&gt;Can bind to a terminal and execute automatically; dangerous-command blocking + approval modes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Knowledge base + RAG&lt;/td&gt;
&lt;td&gt;Notes are searchable; &lt;code&gt;#&lt;/code&gt; completes straight into the command line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Command history&lt;/td&gt;
&lt;td&gt;Stored in SQLite, searchable, filterable by window / host&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Themes&lt;/td&gt;
&lt;td&gt;600+ terminal color schemes, light/dark paired, following the app's appearance&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-platform&lt;/td&gt;
&lt;td&gt;macOS / Linux / Windows / Android / iOS / HarmonyOS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  6. Try It Out
&lt;/h2&gt;

&lt;h3&gt;
  
  
  FaiTerm
&lt;/h3&gt;

&lt;p&gt;Website: &lt;strong&gt;&lt;a href="https://www.faiterm.com" rel="noopener noreferrer"&gt;https://www.faiterm.com&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Current version: &lt;strong&gt;v1.0.9&lt;/strong&gt;. Download directly:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Artifacts&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;dmg (Apple Silicon / Intel / universal), pkg&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows&lt;/td&gt;
&lt;td&gt;exe, msix (x64 / arm64)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;AppImage, deb, rpm, zip&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Install it and it just works — no Fig to install first, no accessibility permissions to grant, no background service to run separately.&lt;/p&gt;

&lt;p&gt;Bug reports, complaints, and feature requests are all welcome:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/littlewrite/FaTerm" rel="noopener noreferrer"&gt;https://github.com/littlewrite/FaTerm&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;For the Chinese-speaking community, there's also a QQ group: &lt;strong&gt;1028280069&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  autocomplete (Dart)
&lt;/h3&gt;

&lt;p&gt;If you're not here for FaiTerm but want to &lt;strong&gt;wire a completion engine into your own project&lt;/strong&gt;, just use the package directly:&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/littlewrite/autocomplete" rel="noopener noreferrer"&gt;https://github.com/littlewrite/autocomplete&lt;/a&gt; — package docs are in &lt;code&gt;dart/README.md&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;dependencies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;autocomplete&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;git&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;git@github.com:littlewrite/autocomplete.git&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dart&lt;/span&gt;
      &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;feat_dart_v2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It does not depend on Flutter. It runs on the CLI, on desktop, on mobile, and on the Web — all you have to provide is "a function that reads a string" and "a completion environment."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you work in Go / Rust / Java / Kotlin / Swift / C# / JS, you're especially welcome to come run this JSON catalog.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's exactly the problem JSON-first set out to solve: the spec data doesn't need rewriting, you just implement the handler contract. Dart is the first implementation to work end to end, not the only one.&lt;/p&gt;

&lt;p&gt;Equally welcome is help with &lt;strong&gt;the completion specs themselves&lt;/strong&gt; — is a CLI you use every day incompletely covered, or missing entirely? Come open a PR; adding one JSON file is all it takes.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Closing
&lt;/h2&gt;

&lt;p&gt;A huge thank you to Fig and to the other developers who contributed to the community — &lt;strong&gt;the declarative completion spec&lt;/strong&gt;, withfig/autocomplete.&lt;/p&gt;

&lt;p&gt;autocomplete-dart builds on that: it takes the &lt;strong&gt;most valuable part&lt;/strong&gt; Fig left behind — that spec asset — and rebuilds it from "code that can only run inside Node" into "a data contract any language and any platform can read." JSON for the data; an abstracted adapter so the completion environment itself is replaceable.&lt;/p&gt;

&lt;p&gt;Fig's story ended on macOS.&lt;br&gt;
This story continues in FaiTerm, no longer bound to any single platform.&lt;/p&gt;




&lt;h2&gt;
  
  
  Appendix: Key Links
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;FaiTerm website: &lt;a href="https://www.faiterm.com" rel="noopener noreferrer"&gt;https://www.faiterm.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/littlewrite/autocomplete" rel="noopener noreferrer"&gt;github.com/littlewrite/autocomplete&lt;/a&gt; — the JSON-first Dart implementation (MIT)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/withfig/autocomplete" rel="noopener noreferrer"&gt;withfig/autocomplete&lt;/a&gt; — Fig's spec repo (now Amazon Q Developer CLI, MIT)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://techcrunch.com/2023/08/29/amazon-fig-command-line-terminal-generative-ai/" rel="noopener noreferrer"&gt;Amazon acquires Fig (TechCrunch, 2023-08-29)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/microsoft/inshellisense/issues/258" rel="noopener noreferrer"&gt;inshellisense #258: Fig is sunsetting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kiro.dev/docs/cli/migrating-from-q/" rel="noopener noreferrer"&gt;Kiro CLI: Upgrading from Amazon Q Developer CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Design docs: &lt;code&gt;docs/v3-json-first-architecture.md&lt;/code&gt;, &lt;code&gt;docs/json-driven-specs.md&lt;/code&gt;, &lt;code&gt;docs/json-spec-generation-rules.md&lt;/code&gt;, &lt;code&gt;docs/remote-spec-distribution.md&lt;/code&gt; (all in the &lt;code&gt;autocomplete&lt;/code&gt; repo)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>fig</category>
      <category>terminal</category>
      <category>autocomplete</category>
    </item>
    <item>
      <title>Cursor vs Trae vs Kiro vs GitHub Copilot: My Honest 2-Year Review of 4 AI IDEs</title>
      <dc:creator>Paul</dc:creator>
      <pubDate>Mon, 16 Mar 2026 01:51:20 +0000</pubDate>
      <link>https://dev.to/jane_lee_ecafb4b88ef2eff0/cursor-vs-trae-vs-kiro-vs-github-copilot-my-honest-2-year-review-of-4-ai-ides-29of</link>
      <guid>https://dev.to/jane_lee_ecafb4b88ef2eff0/cursor-vs-trae-vs-kiro-vs-github-copilot-my-honest-2-year-review-of-4-ai-ides-29of</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7h2wgq138m0c65ap7641.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7h2wgq138m0c65ap7641.png" alt=" "&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Two Years, Four Mainstream AI IDEs, and Honest Paid-Subscriber Feedback — Not an Ad, Just a Real-World Pitfall Guide
&lt;/h1&gt;

&lt;p&gt;This article is about my real experience with four tools: &lt;strong&gt;Cursor, Trae, Kiro, and GitHub Copilot&lt;/strong&gt;. I’ll walk through how I got into each one, what feels great in day-to-day use, and where each one breaks down. If you’re deciding which IDE to use next—or you’re already unhappy with your current setup—I hope this hard-earned experience helps.&lt;/p&gt;

&lt;p&gt;That said, tools are always personal. What works for me may not work for you. If your experience is different, or you think I missed a better setup, feel free to challenge me—discussion is exactly how we all get better.&lt;/p&gt;

&lt;h2&gt;
  
  
  I: My AI Coding Journey
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;GitHub Copilot: From “Old-School Typing” to “Tab-Driven Coding”&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;When people talk about AI coding, Copilot is hard to ignore. In 2023, when it moved from preview into mainstream use, I was an early adopter. It felt &lt;strong&gt;revolutionary&lt;/strong&gt; at the time: type a few characters and it can complete an entire line, paragraph, or function. I jumped from “manual typing” to “trust the Tab key” almost overnight.&lt;/p&gt;

&lt;p&gt;I’m a heavy JetBrains user, and VS Code never felt like home to me. Copilot’s strength is that it works across environments: not only VS Code, but also an &lt;strong&gt;official IntelliJ IDEA plugin&lt;/strong&gt;. That gave my existing workflow a smooth AI upgrade. In 2023–2024, “IDEA interaction + Copilot completion quality” was my productivity sweet spot. I paid for it for two straight years, and it became foundational to my workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Completion tip:&lt;/strong&gt; Copilot pushed me to write clearer comments. The clearer I described intent in natural language, the better its completions became. That also improved my code readability.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Cursor: Shifting from Manual to Automatic&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Cursor represented a new paradigm: not just completion, but conversation-driven development.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Talk to me,
Code for me.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When this capability first appeared, it was a shock to the industry. While Copilot was still optimizing Tab completion, Cursor was already handling higher-level reasoning and generating large code blocks from natural language prompts.&lt;/p&gt;

&lt;p&gt;I started using Cursor in 2024. At that time there was no IDEA plugin, so I had to work in VS Code, which took some adjustment. My prompting skills were also weak at the beginning, so it didn’t click immediately. But after adapting to the workflow, I hit a second major productivity jump.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Kiro: Following the Leader, with Growing Pains&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Because Cursor could be unstable in some network environments, I looked for a backup. That’s when I found &lt;strong&gt;Kiro&lt;/strong&gt;. It started as Amazon Q and later became a standalone AI IDE. As an early user, I had a long free period, and when Cursor failed, Kiro often saved me.&lt;/p&gt;

&lt;p&gt;Kiro is also VS Code-based, so onboarding was easy after using Cursor. The purple theme grew on me too. As an AWS product, it appears feature-complete: code completion, chat coding, diagnostics, and more.&lt;/p&gt;

&lt;p&gt;But “has features” and “feels good to use” are very different things. Kiro has had more &lt;strong&gt;basic product bugs&lt;/strong&gt; than any AI IDE I’ve used. I’m not talking about model hallucinations; I mean UI and interaction bugs in the product itself. That’s especially frustrating when expectations are high for a company known for infrastructure reliability.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Trae: A Late Entrant with Strong Engineering Discipline&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;I had seen Trae ads for a long time, but only started using it deeply in &lt;strong&gt;early 2026&lt;/strong&gt;. I use the international version and subscribed with a local Visa card. By then, I was fully comfortable with VS Code-like IDEs.&lt;/p&gt;

&lt;p&gt;My first impression: Trae is extremely polished in fundamentals. The UI is clean, response is fast, and localization is excellent. There are reports that the team rewrote major VS Code internals in Rust. True or not, large projects feel very smooth. After months of use, I can say this: touching so much low-level architecture while staying this stable is genuinely impressive. (Yes, this is also a subtle shot at Kiro 😏)&lt;/p&gt;

&lt;p&gt;Of course, I’ve used Trae for less time than the others, so my view may evolve.&lt;/p&gt;

&lt;h1&gt;
  
  
  Chapter II: Deep Comparison — The Devil Is in the Details
&lt;/h1&gt;

&lt;p&gt;Enough background. Here’s a direct breakdown of strengths and weaknesses from daily, high-intensity use.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;GitHub Copilot: The Best Tab Experience&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Positioning &amp;amp; price:&lt;/strong&gt; &lt;strong&gt;$10/month&lt;/strong&gt;. Its biggest advantage is ecosystem reach. You can use it in VS Code, the IntelliJ suite, Vim, and Neovim.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Subscribe once, tab everywhere
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Core strengths:&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Completion quality:&lt;/strong&gt; Years of iteration still make its line/block completion speed and accuracy top-tier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ecosystem fit:&lt;/strong&gt; Deep GitHub integration gives it strong context awareness for repos, style, and team habits. In JetBrains, it still feels best-in-class.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core weakness (Agent mode):&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Slow/inaccurate context retrieval:&lt;/strong&gt; It often misses the right files unless you repeatedly guide it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Whole-file rewrite behavior:&lt;/strong&gt; This is my biggest pain point. Instead of focused edits, it tends to regenerate full files, which causes:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Unwanted formatting/style churn:&lt;/strong&gt; comments, spelling, and style get changed even when not requested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Higher breakage risk:&lt;/strong&gt; full-file rewrites raise the chance of introducing regressions.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bottom line:&lt;/strong&gt; Copilot is an elite “Tab accelerator.” But if you want an autonomous project-aware partner for complex tasks, it can feel behind newer AI IDE workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Kiro: Backed by a Giant&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Positioning &amp;amp; price:&lt;/strong&gt; &lt;strong&gt;$20/month (1000 points)&lt;/strong&gt; at entry level. No free fallback model after points run out, so AI functions stop hard.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core strengths:&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Claude-based intelligence:&lt;/strong&gt; Good reasoning and instruction following for most engineering tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Spec-driven mindset:&lt;/strong&gt; Useful for teams that prioritize strict, document-first workflows.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core weaknesses (frustrating details):&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Visible product bugs:&lt;/strong&gt; From completion edge cases to UI glitches.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Painful file reference UX:&lt;/strong&gt; In chat, you often have to manually type file names. In large projects with similar names, this is a productivity killer.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fragile image handling:&lt;/strong&gt; The model may not support images, but the IDE allows image content. Accidentally pasting rich text with images can break the session.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Long-context slowdown:&lt;/strong&gt; It starts strong, then degrades into very slow “one-line edit, one-step think” behavior in late-stage refinements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expensive token economy:&lt;/strong&gt; $20/1000 points can disappear quickly on long-context tasks. Several full-time users around me report ~$40/month as the practical minimum.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;What Kiro taught me:&lt;/strong&gt; Control context aggressively. Split weakly related tasks into separate sessions. Precisely scope files with @ references instead of relying on broad retrieval.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Trae: An Elegant Swiss-Army Knife&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Positioning &amp;amp; price:&lt;/strong&gt; &lt;strong&gt;$10/month&lt;/strong&gt; entry plan with excellent value.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core strengths:&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Excellent fundamentals:&lt;/strong&gt; UI, performance, stability, and localization are consistently strong.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Efficient workflow design:&lt;/strong&gt; Its agent tends to follow:
&lt;code&gt;Find rules -&amp;gt; Retrieve code -&amp;gt; Read context -&amp;gt; Think -&amp;gt; Edit -&amp;gt; Check -&amp;gt; Fix -&amp;gt; Summarize&lt;/code&gt;
It uses retrieval and proactive context compression, which helps reduce token waste.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong Chinese/local adaptation:&lt;/strong&gt; Especially useful for Chinese-language workflows and local ecosystems.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Core weaknesses (trade-offs of its philosophy):&lt;/strong&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Overkill for tiny tasks:&lt;/strong&gt; The full process can feel heavy for simple edits or translations.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code-first bias:&lt;/strong&gt; Outside coding tasks, it may ask for project structure before proceeding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Session concurrency limits:&lt;/strong&gt; Compared with some competitors, parallel multi-chat workflows feel more constrained.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;“Prepare first” tendency:&lt;/strong&gt; Even with precise instructions and file targeting, it may still perform extra retrieval before acting.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;My take on Trae:&lt;/strong&gt; Polished, powerful, and methodical. Great for substantial tasks; less ideal for lots of micro-edits.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Cursor: The Gold-Standard All-Rounder&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Positioning &amp;amp; price:&lt;/strong&gt; &lt;strong&gt;$20/month&lt;/strong&gt; (with more flexible plans now).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why it still feels best overall:&lt;/strong&gt; Most pain points from other tools are either absent or better handled.

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Project-level understanding:&lt;/strong&gt; Strong repository awareness without constant manual file tagging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fast and focused edits:&lt;/strong&gt; Usually edits targeted blocks instead of rewriting full files.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reliable baseline experience:&lt;/strong&gt; Fewer product-level bugs in day-to-day use.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexible model fallback:&lt;/strong&gt; Auto mode can bridge gaps when premium quotas are exhausted.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smooth interaction model:&lt;/strong&gt; Chat, edit, and file operations feel tightly integrated.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Biggest drawback:&lt;/strong&gt; In mainland China, reliable access to top overseas models (like Claude) usually requires a stable proxy/VPN setup.&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  III: Summary &amp;amp; Selection Guide — Find Your Coding Partner
&lt;/h1&gt;

&lt;p&gt;So which one should you choose?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;GitHub Copilot: Your Tab Booster&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Developers who want AI enhancement inside their existing IDE workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-liner:&lt;/strong&gt; If you want stronger coding flow without changing your toolchain, Copilot’s cross-IDE plugin ecosystem is hard to beat.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Cursor: Your General-Purpose AI Coding Partner&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Developers ready to embrace conversation-first coding and able to handle connectivity requirements.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Kiro: Your Process-Heavy Contractor&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Teams that are deeply tied to AWS and strongly prefer spec-driven, documentation-first delivery.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Trae: Your Automated Workshop Lead&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; China-based developers, especially those on local stacks, who care about cost-efficiency and structured automation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;One-liner:&lt;/strong&gt; Excellent fundamentals, strong localization, and highly automated flow.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I welcome discussion—and disagreement.&lt;/p&gt;

&lt;h1&gt;
  
  
  Extra Notes (Detailed Comparison)
&lt;/h1&gt;

&lt;p&gt;Here’s the short practical version from real usage:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Copilot&lt;/strong&gt; is still the best pure Tab completion experience, especially if you use multiple IDEs.&lt;/li&gt;
&lt;li&gt;Its Agent mode is weaker: context lookup can miss, and full-file rewrites often create noisy diffs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kiro&lt;/strong&gt; can solve real tasks with Claude-class reasoning, but UX issues and point-based billing can make long sessions expensive.&lt;/li&gt;
&lt;li&gt;Kiro taught me to aggressively manage context and explicitly scope files to save tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trae&lt;/strong&gt; is very strong on product quality and token efficiency, but can feel heavy for tiny, non-coding tasks.&lt;/li&gt;
&lt;li&gt;For larger tasks, Trae’s structured flow is reliable and cost-effective.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cursor</category>
      <category>kiro</category>
      <category>githubcopilot</category>
    </item>
    <item>
      <title>How to visualize dependencies in Golang</title>
      <dc:creator>Paul</dc:creator>
      <pubDate>Wed, 24 Sep 2025 14:06:10 +0000</pubDate>
      <link>https://dev.to/jane_lee_ecafb4b88ef2eff0/how-to-visualize-dependencies-in-golang-3205</link>
      <guid>https://dev.to/jane_lee_ecafb4b88ef2eff0/how-to-visualize-dependencies-in-golang-3205</guid>
      <description>&lt;h1&gt;
  
  
  Background
&lt;/h1&gt;

&lt;p&gt;I encountered an issue while building a &lt;code&gt;golang&lt;/code&gt; project recently. Even though I specified the version of a dependency package, the version number was automatically upgraded during the build process. I didn't understand why at the time. Later, I learned about the &lt;code&gt;go mod graph&lt;/code&gt; command, which lists all dependencies. I tried it, but it wasn't intuitive at all; I still had to copy the output into a text editor to search for information.&lt;/p&gt;

&lt;p&gt;So, I searched online for related tools.&lt;/p&gt;

&lt;h1&gt;
  
  
  Other Tools
&lt;/h1&gt;

&lt;p&gt;Search terms: Go Module dependency visualization&lt;/p&gt;

&lt;p&gt;There are many tools available online. Most solutions use &lt;code&gt;graphviz&lt;/code&gt;, &lt;code&gt;echarts&lt;/code&gt;, or generate images. I tried a few.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;graphviz&lt;/code&gt; is a powerful tool, but it requires separate installation. The generated SVG files aren't very readable either, especially when there are many dependent packages. For example, look at this one:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3whwftd9rqf9wl1d86h.webp" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3whwftd9rqf9wl1d86h.webp" alt=" " width="800" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, I turned to echarts.&lt;/p&gt;

&lt;p&gt;Wow, it looks quite nice! The mouse hover feedback is good, and the color scheme is vibrant.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxu8rqqff212k8jecezog.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxu8rqqff212k8jecezog.gif" alt=" " width="600" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The echarts solution is beautiful, but not practical. With SVG I could at least search for package names; with this echart version, the package names aren't displayed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  My Solution
&lt;/h1&gt;

&lt;p&gt;Alright, enough complaining. The problem still needs solving. Today, I'm introducing a visualization tool for &lt;code&gt;go mod graph&lt;/code&gt; — &lt;a href="https://github.com/PaulXu-cn/go-mod-graph-chart" rel="noopener noreferrer"&gt;gmchart&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  gmchart
&lt;/h1&gt;

&lt;p&gt;github: &lt;a href="https://github.com/PaulXu-cn/go-mod-graph-chart" rel="noopener noreferrer"&gt;https://github.com/PaulXu-cn/go-mod-graph-chart&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Installation
&lt;/h1&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/PaulXu-cn/go-mod-graph-chart/gmchart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check if the installation was successful like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gmchart &lt;span class="nt"&gt;--help&lt;/span&gt;

Usage of ~&lt;span class="se"&gt;\g&lt;/span&gt;o&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="se"&gt;\g&lt;/span&gt;mchart:
  &lt;span class="nt"&gt;-debug&lt;/span&gt; int
        is debug model
  &lt;span class="nt"&gt;-keep&lt;/span&gt; int
        start http server not &lt;span class="nb"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;Navigate to your Golang project directory and run the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;go mod graph | gmchart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;This should automatically open your browser. If it doesn't, open it manually.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Visit &lt;a href="http://127.0.0.1:60306" rel="noopener noreferrer"&gt;http://127.0.0.1:60306&lt;/a&gt; to see the result.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh27r9rcvi0joqt6d9uaf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh27r9rcvi0joqt6d9uaf.gif" alt=" " width="720" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it renders the dependencies into a dependency tree. You can see which layer a particular package is introduced in, which is very intuitive. The webpage contains an SVG, making it easy to find a specific package—just use &lt;code&gt;Ctrl+F&lt;/code&gt; to search.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;p&gt;After searching for so long, why wasn't there a suitable tool?&lt;/p&gt;

&lt;p&gt;I thought about it. &lt;strong&gt;Visualization&lt;/strong&gt; is a front-end specialty. Front-end developers don't typically use &lt;code&gt;Golang&lt;/code&gt;. Those who do are rare, and among those, even fewer are interested in the &lt;code&gt;go mod graph&lt;/code&gt; functionality. So, it fell to us back-end developers to create this tool.&lt;/p&gt;

&lt;p&gt;Sigh~&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative Solutions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/poloxue/modv" rel="noopener noreferrer"&gt;https://github.com/poloxue/modv&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ofabry/go-callvis" rel="noopener noreferrer"&gt;https://github.com/ofabry/go-callvis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/ios122/graph-go" rel="noopener noreferrer"&gt;https://github.com/ios122/graph-go&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
    </item>
  </channel>
</rss>
