<?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: kuangren chu</title>
    <description>The latest articles on DEV Community by kuangren chu (@kuangren_chu_0ca6da848be4).</description>
    <link>https://dev.to/kuangren_chu_0ca6da848be4</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3444787%2Fb172302e-3c68-4d53-88c0-1a33836e4b2a.jpg</url>
      <title>DEV Community: kuangren chu</title>
      <link>https://dev.to/kuangren_chu_0ca6da848be4</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kuangren_chu_0ca6da848be4"/>
    <language>en</language>
    <item>
      <title>A declarative CLI framework in Rust</title>
      <dc:creator>kuangren chu</dc:creator>
      <pubDate>Sat, 18 Apr 2026 02:41:01 +0000</pubDate>
      <link>https://dev.to/kuangren_chu_0ca6da848be4/a-declarative-cli-framework-in-rust-d8i</link>
      <guid>https://dev.to/kuangren_chu_0ca6da848be4/a-declarative-cli-framework-in-rust-d8i</guid>
      <description>&lt;p&gt;I built a declarative CLI framework in Rust (define your CLI in TOML)&lt;/p&gt;




&lt;p&gt;Most Rust CLI tools are built with libraries like &lt;code&gt;clap&lt;/code&gt;. They’re powerful—but also verbose.&lt;/p&gt;

&lt;p&gt;After building a few internal tools, I kept running into the same problem:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Too much boilerplate for simple commands&lt;/li&gt;
&lt;li&gt;Repeating argument parsing logic&lt;/li&gt;
&lt;li&gt;Hard to manage growing CLI complexity&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So I built &lt;strong&gt;tkucli&lt;/strong&gt; — a &lt;strong&gt;declarative CLI framework for Rust&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 The idea
&lt;/h2&gt;

&lt;p&gt;Instead of writing Rust code to define commands, you describe your CLI in a &lt;code&gt;TOML&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;You define:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;commands&lt;/li&gt;
&lt;li&gt;arguments&lt;/li&gt;
&lt;li&gt;workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;…and the framework handles execution.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ Example
&lt;/h2&gt;

&lt;p&gt;Define a command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[app]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt;           &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"vm-cli"&lt;/span&gt;
&lt;span class="py"&gt;version&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1.0"&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"A Tkucli-powered CLI"&lt;/span&gt;
&lt;span class="py"&gt;default_output&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"table"&lt;/span&gt;

&lt;span class="nn"&gt;[tui]&lt;/span&gt;
&lt;span class="py"&gt;enabled&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="py"&gt;theme&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"dark"&lt;/span&gt;

&lt;span class="nn"&gt;[[resource]]&lt;/span&gt;
&lt;span class="py"&gt;name&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"vm"&lt;/span&gt;
&lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"VM resource — replace with your own"&lt;/span&gt;

  &lt;span class="nn"&gt;[[resource.operation]]&lt;/span&gt;
  &lt;span class="py"&gt;verb&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"create"&lt;/span&gt;
  &lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"create a vm"&lt;/span&gt;
  &lt;span class="py"&gt;args&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;required&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nn"&gt;[[resource.operation]]&lt;/span&gt;
  &lt;span class="py"&gt;verb&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"list"&lt;/span&gt;
  &lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"List all examples"&lt;/span&gt;
  &lt;span class="py"&gt;flags&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;short&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"u32"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;default&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"20"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;help&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Max results"&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nn"&gt;[[resource.operation]]&lt;/span&gt;
  &lt;span class="py"&gt;verb&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"get"&lt;/span&gt;
  &lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Get a vm by name"&lt;/span&gt;
  &lt;span class="py"&gt;args&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;required&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="nn"&gt;[[resource.operation]]&lt;/span&gt;
  &lt;span class="py"&gt;verb&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"delete"&lt;/span&gt;
  &lt;span class="py"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Get a vm by name"&lt;/span&gt;
  &lt;span class="py"&gt;args&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;{&lt;/span&gt; &lt;span class="py"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;required&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;tkucli vm-cli vm create &lt;span class="nt"&gt;--name&lt;/span&gt; first-vm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🚀 Why I built this
&lt;/h2&gt;

&lt;p&gt;I wanted something that feels like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Infrastructure-as-Code&lt;/strong&gt;, but for CLI&lt;/li&gt;
&lt;li&gt;Easy to extend (TUI, workflows, automation)&lt;/li&gt;
&lt;li&gt;Great for internal tools / DevOps / homelabs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔄 How it compares
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;clap&lt;/code&gt; → full control, but code-heavy&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;bash&lt;/code&gt; → quick, but messy at scale&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;tkucli&lt;/strong&gt; → structured, declarative, fast to build&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧩 Use cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Wrapping tools like Ansible / Terraform&lt;/li&gt;
&lt;li&gt;Internal developer platforms&lt;/li&gt;
&lt;li&gt;Automation CLIs&lt;/li&gt;
&lt;li&gt;Homelab management&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  ⚠️ What it’s NOT
&lt;/h2&gt;

&lt;p&gt;This isn’t trying to replace low-level CLI frameworks.&lt;/p&gt;

&lt;p&gt;If you need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;very custom parsing&lt;/li&gt;
&lt;li&gt;maximum performance
→ use &lt;code&gt;clap&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 What I’m exploring next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Built-in TUI support (ratatui-style)&lt;/li&gt;
&lt;li&gt;Better workflow composition&lt;/li&gt;
&lt;li&gt;Git-backed CLI configs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🙌 Looking for feedback
&lt;/h2&gt;

&lt;p&gt;I’m trying to answer a simple question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;What if building a CLI felt like writing a config, not a program?&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Curious if this resonates with others building tools in Rust.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does this solve a real pain for you?&lt;/li&gt;
&lt;li&gt;Would you use something like this?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Happy to share repo / details if there’s interest.&lt;/p&gt;

</description>
      <category>cli</category>
      <category>rust</category>
      <category>showdev</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
