<?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: Vinay Agarwal</title>
    <description>The latest articles on DEV Community by Vinay Agarwal (@vinkaga).</description>
    <link>https://dev.to/vinkaga</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%2F3516775%2F1784ab6a-3ed2-4ad0-8dcd-76ef0637ab27.png</url>
      <title>DEV Community: Vinay Agarwal</title>
      <link>https://dev.to/vinkaga</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/vinkaga"/>
    <language>en</language>
    <item>
      <title>Stop Googling Shell Commands: A Better Way to Work with the Terminal</title>
      <dc:creator>Vinay Agarwal</dc:creator>
      <pubDate>Fri, 19 Sep 2025 20:29:44 +0000</pubDate>
      <link>https://dev.to/vinkaga/stop-googling-shell-commands-a-better-way-to-work-with-the-terminal-gh5</link>
      <guid>https://dev.to/vinkaga/stop-googling-shell-commands-a-better-way-to-work-with-the-terminal-gh5</guid>
      <description>&lt;p&gt;You’re deep in focus, trying to solve a problem. You need to parse some logs, and that means diving into the command line. You know &lt;em&gt;what&lt;/em&gt; you want to do, but you can’t quite remember the exact flags for &lt;code&gt;jq&lt;/code&gt; or the right way to chain &lt;code&gt;sort&lt;/code&gt; and &lt;code&gt;uniq&lt;/code&gt;. So you do what we all do: you break your focus, open a new browser tab, and start searching.&lt;/p&gt;

&lt;p&gt;These micro-interruptions are more costly than we realize. They shatter concentration, waste time, and add a layer of friction to what should be a straightforward task.&lt;/p&gt;

&lt;p&gt;What if you could stay in your terminal, ask for what you need in plain English, and get the correct command instantly? That’s the idea behind &lt;code&gt;$hAI&lt;/code&gt;, a shell-native AI assistant for macOS that integrates directly into your workflow.&lt;/p&gt;

&lt;p&gt;Let's walk through a real-world scenario: analyzing web server logs to figure out how much traffic is coming from bots.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Mission: How Many Bots Visit My Website?
&lt;/h3&gt;

&lt;p&gt;For this demo, we'll use a real access log file from &lt;code&gt;wikimedia.org&lt;/code&gt; in JSONL format. (You can download the exact file used in this tutorial &lt;a href="https://github.com/shai-shell/shAI/raw/refs/heads/main/examples/wikimedia_20250804T193623Z.jsonl" rel="noopener noreferrer"&gt;here&lt;/a&gt; to follow along.) Our first goal is simple: find out how many log entries were generated by bots.&lt;/p&gt;

&lt;p&gt;First, let's see what we're working with. A quick &lt;code&gt;ls&lt;/code&gt; shows us the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wikimedia_20250804T193623Z.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, we'll peek at the first line to understand the structure of the data using &lt;code&gt;head&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.jsonl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The output is a single, dense JSON line, but we can see a key field that looks promising: &lt;code&gt;"bot":true&lt;/code&gt;.&lt;br&gt;
&lt;/p&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="nl"&gt;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"/mediawiki/recentchange/1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"meta"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2958778979&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"categorize"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"DPLA bot"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nl"&gt;"bot"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&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;p&gt;Great. Now we can start counting. A simple pipeline using &lt;code&gt;cat&lt;/code&gt; and &lt;code&gt;wc -l&lt;/code&gt; will give us the total number of lines in the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.jsonl | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2055
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, we have 2,055 total entries.&lt;/p&gt;

&lt;h3&gt;
  
  
  The "Gotcha": When &lt;code&gt;jq&lt;/code&gt; Does Too Much
&lt;/h3&gt;

&lt;p&gt;To count only the bot entries, we'll use &lt;code&gt;jq&lt;/code&gt; to filter for lines where &lt;code&gt;.bot == true&lt;/code&gt; and then pipe that to &lt;code&gt;wc -l&lt;/code&gt;. This &lt;em&gt;should&lt;/em&gt; work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jq &lt;span class="s1"&gt;'select(.bot == true)'&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.jsonl | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;38468
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait. That can’t be right. How can we have over 38,000 bot entries when there are only 2,055 total lines?&lt;/p&gt;

&lt;p&gt;This is a classic command-line "gotcha." Let's investigate by looking at the output of our &lt;code&gt;jq&lt;/code&gt; command without the &lt;code&gt;wc -l&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jq &lt;span class="s1"&gt;'select(.bot == true)'&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.jsonl | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;"$schema"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/mediawiki/recentchange/1.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"meta"&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;"uri"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://commons.wikimedia.org/wiki/Category:Digital_Public_Library_of_America_files_missing_creator"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"request_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"590763a0-2419-4395-8881-e1c4113b4a28"&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;p&gt;Aha! By default, &lt;code&gt;jq&lt;/code&gt; pretty-prints the JSON output, turning each single-line entry into a multi-line, formatted object. The &lt;code&gt;wc -l&lt;/code&gt; command is counting these formatted lines, not the original log entries, which completely skews our result.&lt;/p&gt;

&lt;p&gt;This is the exact moment where focus breaks. Now we have to go search for the right &lt;code&gt;jq&lt;/code&gt; flag to disable pretty-printing.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix: Asking &lt;code&gt;$hAI&lt;/code&gt; for Help
&lt;/h3&gt;

&lt;p&gt;Instead of leaving the terminal, let's just ask &lt;code&gt;$hAI&lt;/code&gt; to fix the command for us. We'll type our request in plain English, right where we are.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;fix the jq wc command so that it doesn't expand json into multi lines&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, we press &lt;strong&gt;&lt;code&gt;Cmd+Return&lt;/code&gt;&lt;/strong&gt;. &lt;code&gt;$hAI&lt;/code&gt; analyzes our request and the previous command, and provides the solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jq &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'select(.bot == true)'&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.jsonl | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;-c&lt;/code&gt; flag is for "compact output," which is exactly what we need. Now, we can use &lt;strong&gt;&lt;code&gt;Cmd+Up Arrow&lt;/code&gt;&lt;/strong&gt; to recall the suggestion, and 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;jq &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'select(.bot == true)'&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.jsonl | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1196
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That looks much more reasonable. Out of 2,055 total entries, 1,196 were from bots. Problem solved, and we never had to leave the command line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Going Deeper: From Fixing to Assisting
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;$hAI&lt;/code&gt; is more than just a debugging tool. Now that we have the correct count, let's perform a more complex analysis. We want to find the top 5 most active bots and their hit counts.&lt;/p&gt;

&lt;p&gt;Constructing this command chain manually can be tricky. You need to filter, extract the user field, sort, count unique entries, and then sort again numerically.&lt;/p&gt;

&lt;p&gt;Or, you can just ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;find the top 5 bots with their counts&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Press &lt;strong&gt;&lt;code&gt;Cmd+Return&lt;/code&gt;&lt;/strong&gt;, and &lt;code&gt;$hAI&lt;/code&gt; generates the entire pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;jq &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'select(.bot == true) | .user'&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.jsonl | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's run it. As before, we'll use &lt;strong&gt;&lt;code&gt;Cmd+Up Arrow&lt;/code&gt;&lt;/strong&gt; to recall 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;jq &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s1"&gt;'select(.bot == true) | .user'&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.jsonl | &lt;span class="nb"&gt;sort&lt;/span&gt; | &lt;span class="nb"&gt;uniq&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt; | &lt;span class="nb"&gt;sort&lt;/span&gt; &lt;span class="nt"&gt;-rn&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-5&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; 256 "Dolabbot"
 231 "Gzen92Bot"
 150 "DPLA bot"
 119 "GeographBot"
 113 "SchlurcherBot"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Perfect. In seconds, we have a clear, accurate answer to our high-level question, generated from a command that would have taken time and trial-and-error to write manually.&lt;/p&gt;

&lt;h3&gt;
  
  
  Watch the Full Demo
&lt;/h3&gt;

&lt;p&gt;You can see this entire workflow in action in the video below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=aTX0eiVR6zQ" rel="noopener noreferrer"&gt;Analyzing Access Log Files With a Little Help From $hAI&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Your Terminal, Smarter
&lt;/h3&gt;

&lt;p&gt;This is just one example of how a shell-native AI assistant can remove friction and keep you in the flow. By learning your commands, helping fix errors, and automating complex tasks, &lt;code&gt;$hAI&lt;/code&gt; makes your terminal a more powerful and intuitive environment.&lt;/p&gt;

&lt;p&gt;If you're ready to stop context-switching and start executing, you can get started with &lt;code&gt;$hAI&lt;/code&gt; in just a few minutes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Sign up at &lt;a href="https://shai.sh" rel="noopener noreferrer"&gt;shai.sh&lt;/a&gt;&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Install the shell plugin:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://github.com/shai-shell/shAI/releases/latest/download/install.sh &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/install.sh &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; bash /tmp/install.sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Log in from your terminal:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;shai login
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Give it a try and see how much time you can save when you bring AI directly to your shell.&lt;/p&gt;

</description>
      <category>terminal</category>
      <category>productivity</category>
      <category>ai</category>
      <category>cli</category>
    </item>
  </channel>
</rss>
