<?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: everwinner64</title>
    <description>The latest articles on DEV Community by everwinner64 (@everwinner64).</description>
    <link>https://dev.to/everwinner64</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%2F4112454%2F84669346-3c54-4ca0-8da5-a2233fb8dc41.jpeg</url>
      <title>DEV Community: everwinner64</title>
      <link>https://dev.to/everwinner64</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/everwinner64"/>
    <language>en</language>
    <item>
      <title>I kept leaving the terminal for little things, so I spent 6 months building a CLI for them</title>
      <dc:creator>everwinner64</dc:creator>
      <pubDate>Sun, 06 Sep 2026 18:36:29 +0000</pubDate>
      <link>https://dev.to/everwinner64/i-kept-leaving-the-terminal-for-little-things-so-i-spent-6-months-building-a-cli-for-them-4moo</link>
      <guid>https://dev.to/everwinner64/i-kept-leaving-the-terminal-for-little-things-so-i-spent-6-months-building-a-cli-for-them-4moo</guid>
      <description>&lt;p&gt;Six months ago, I started noticing a pattern in the way I work.&lt;/p&gt;

&lt;p&gt;I'd be in the middle of something in the terminal or in my IDE, then I'd need to do one tiny thing.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decode a JWT.&lt;/li&gt;
&lt;li&gt;Generate a UUID.&lt;/li&gt;
&lt;li&gt;Check when a certificate expires.&lt;/li&gt;
&lt;li&gt;Convert a timestamp.&lt;/li&gt;
&lt;li&gt;Figure out why an HTTP request is taking forever.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing very difficult. Yet I'd open a browser tab. Then another one.&lt;/p&gt;

&lt;p&gt;Sometimes I'd Google the exact &lt;code&gt;openssl&lt;/code&gt; command I used three months ago, or some command that looks like a Konami code.&lt;br&gt;
Sometimes I'd write a five-line Python script that I'd never use again. And every now and then I'd end up with 37 browser tabs open, most of them containing things I was supposed to do in 30 seconds.&lt;br&gt;
It started annoying me enough that I decided to build something for it.&lt;/p&gt;

&lt;p&gt;That's how Denev happened.&lt;/p&gt;
&lt;h2&gt;
  
  
  So what is Denev?
&lt;/h2&gt;

&lt;p&gt;Denev is a command-line toolkit for developer tasks that should be easy, but aren't. It aims to centralize solutions to these tasks under a consistent, human friendly syntax. I didn't want to remember the exact incantation for every little thing, and I didn't want to switch between 10 different tools every time I needed something.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dnv crypto &lt;span class="nb"&gt;hash&lt;/span&gt; &lt;span class="s2"&gt;"hello world"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dnv jwt inspect &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dnv cert inspect github.com &lt;span class="nt"&gt;--domain&lt;/span&gt; &lt;span class="nt"&gt;--warn-days&lt;/span&gt; 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dnv http timing example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dnv uuid generate &lt;span class="nt"&gt;--type&lt;/span&gt; V7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some command outputs:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;dnv cert inspect github.com --domain --warn-days 100&lt;/code&gt;:&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;dnv jwt inspect eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.eyJzdWIiOiJldmVyd2lubmVyNjQiLCJyb2xlIjoiYWRtaW4iLCJleHAiOjE3ODg1MzU2MzV9.&lt;/code&gt;:&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;dnv regex test "(a+)+$" "aaaaaaaaaaaaaaaaaaaaaaaaaaaa!"&lt;/code&gt;:&lt;/p&gt;

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

&lt;h2&gt;
  
  
  The boring stuff is actually the useful stuff
&lt;/h2&gt;

&lt;p&gt;One of the first things I cared about was consistency.&lt;/p&gt;

&lt;p&gt;I didn't want every command to feel like it came from a completely different CLI. So the commands follow the same general shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dnv &amp;lt;domain&amp;gt; &amp;lt;action&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And I tried to keep the same ideas across the different parts of the tool. Flags should have the same logic and meaning everywhere. Flags shouldn't be ambiguous with others, for example &lt;code&gt;-d&lt;/code&gt; and &lt;code&gt;-D&lt;/code&gt; having completely different meanings. Normal output should be readable. When I'm scripting something, I don't want a box made of Unicode characters and three lines of explanatory text. So there's &lt;code&gt;--quiet&lt;/code&gt;. Input can come from arguments or stdin. Exit codes are predictable. And there is clipboard support for the cases where I'm going to paste the result somewhere anyway.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  JWTs
&lt;/h3&gt;

&lt;p&gt;A JWT is a good example of the kind of thing that pushed me toward making this.&lt;/p&gt;

&lt;p&gt;Usually I don't need a full JWT debugger.&lt;/p&gt;

&lt;p&gt;I just want to know what's inside the token.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dnv jwt inspect &amp;lt;token&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I can see the header, payload, timestamps and relevant metadata without first opening a website and pasting a token into it. That saves maybe 20 seconds, which doesn't sound like much. But doing it ten times a week for months gets surprisingly irritating or impossible if your connection is down.&lt;/p&gt;

&lt;h3&gt;
  
  
  Certificates
&lt;/h3&gt;

&lt;p&gt;Certificates are another one.&lt;/p&gt;

&lt;p&gt;I can never remember the exact &lt;code&gt;openssl s_client&lt;/code&gt; incantation when I just want a quick answer to:&lt;br&gt;
"Is this certificate going to expire soon?"&lt;/p&gt;

&lt;p&gt;So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dnv cert inspect github.com &lt;span class="nt"&gt;--domain&lt;/span&gt; &lt;span class="nt"&gt;--warn-days&lt;/span&gt; 100
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I don't want to reconstruct the operation from memory every time.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTP timing
&lt;/h3&gt;

&lt;p&gt;I also wanted something slightly more useful than "the request took 412 ms". Sometimes you want to know where that time went.&lt;/p&gt;

&lt;p&gt;So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dnv http timing example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;gives you a breakdown of the request rather than just one number, which is much more helpful to me.&lt;/p&gt;

&lt;h2&gt;
  
  
  I also wanted it to be hard to misuse by accident
&lt;/h2&gt;

&lt;p&gt;This is probably one of the less visible parts of Denev, but it ended up being one of the things I cared about most. Some operations are technically valid but worth a warning. For example, hashing something with MD5 or SHA-1 isn't an error. But silently presenting it as if it were a good default isn't great either. Likewise, an unsigned JWT can be perfectly legitimate in some contexts, but it's something I'd rather make visible than quietly ignore. There are similar checks around things like potentially problematic regular expressions. The idea isn't to stop someone from doing something unusual. It's to avoid the CLI quietly encouraging a bad assumption. Warnings can be bypassed when you know what you're doing. I just don't want the default experience to pretend that context doesn't matter.&lt;/p&gt;

&lt;h2&gt;
  
  
  There was also a less obvious goal
&lt;/h2&gt;

&lt;p&gt;I didn't want to build a giant "developer toolbox" where every imaginable utility gets thrown into one binary. What interested me was the feeling of using one tool where I already knew how things worked.&lt;/p&gt;

&lt;p&gt;Once you learn:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dnv &amp;lt;domain&amp;gt; &amp;lt;action&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can guess your way around a lot of the CLI. That matters more to me than the number of commands it has. I'd rather have 50 commands that feel coherent than 500 commands that each require their own little lesson.&lt;/p&gt;

&lt;h2&gt;
  
  
  What six months of using it taught me
&lt;/h2&gt;

&lt;p&gt;The interesting part of building Denev wasn't implementing hashes or UUIDs. The harder part was deciding what the tool should do by default. When should a command warn? What counts as a useful default? How much information is too much? What should happen when input comes from stdin? How should different commands behave when something goes wrong?&lt;/p&gt;

&lt;p&gt;A CLI is basically a collection of small opinions. And once you use it every day, you start noticing all of them.&lt;/p&gt;

&lt;h2&gt;
  
  
  One important caveat
&lt;/h2&gt;

&lt;p&gt;The Denev CLI itself is closed-source and distributed under a custom license. The website and documentation are open. I know that's a dealbreaker for some developers, and that's completely fair. I'm mentioning it here rather than trying to hide it behind the last paragraph of a landing page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where it is now
&lt;/h2&gt;

&lt;p&gt;Denev currently runs on Linux, macOS and Windows. &lt;br&gt;
You can find the docs and examples here: &lt;a href="https://denev.pages.dev" rel="noopener noreferrer"&gt;Denev CLI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd genuinely like to know what you think.&lt;br&gt;
What would you remove? What would you change? What developer task keeps sending you out of the terminal?&lt;/p&gt;

&lt;p&gt;Note: English isn't my first language, so I used a little help to polish the grammar and phrasing of this post!&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>cli</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
