<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>cli on S Anand</title>
    <link>https://www.s-anand.net/blog/tag/cli/</link>
    <description>Recent content in cli on S Anand</description>
    <generator>Hugo -- 0.164.0</generator>
    <language>en-us</language>
    <lastBuildDate>Sun, 21 Sep 2025 11:20:30 +0000</lastBuildDate>
    <atom:link href="https://www.s-anand.net/blog/tag/cli/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Voice coding is the new live coding</title>
      <link>https://www.s-anand.net/blog/voice-coding-is-the-new-live-coding/</link>
      <pubDate>Sun, 21 Sep 2025 11:18:17 +0000</pubDate>
      <guid>https://www.s-anand.net/blog/voice-coding-is-the-new-live-coding/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Voice coding is the new live coding&#34; loading=&#34;lazy&#34; src=&#34;https://www.s-anand.net/blog/assets/ChatGPT-Image-Sep-21-2025-04_46_27-PM.webp&#34;&gt;&lt;/p&gt;
&lt;p&gt;In Feb 2025 at PyConf Hyderabad, I tried a new slide format: &lt;a href=&#34;https://www.s-anand.net/blog/command-line-slideshows-in-bash/&#34;&gt;command-line slideshows in &lt;code&gt;bash&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve used this format in more talks since then:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sanand0/talks0/blob/main/2025-06-pycon-sg/llm-cli.md&#34;&gt;LLMs in the CLI&lt;/a&gt;, PyCon Singapore, Jun 2025&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sanand0/talks/blob/main/2025-07-24-pugs-agent-loop/README.md&#34;&gt;Agents in the CLI&lt;/a&gt;, Singapore Python User Group, Jul 2025&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/sanand0/talks/blob/main/2025-09-13-duckdb-is-the-new-pandas/README.md&#34;&gt;DuckDB is the new Pandas&lt;/a&gt;, PyCon India, Sep 2025&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&amp;rsquo;s my favorite format. I can demo code without breaking the presentation flow.&lt;br&gt;
It also draws interest. My setup was the &lt;a href=&#34;https://github.com/sanand0/talks/blob/main/2025-09-13-duckdb-is-the-new-pandas/README.md#qa&#34;&gt;top question in my PyCon talk&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In Sep 2025, at PyCon India, I extended the setup for voice typing. &lt;a href=&#34;https://github.com/sanand0/scripts/blob/54560718bf2f4148d9005d74ab1543de52cff6d9/talkcode.sh&#34;&gt;&lt;code&gt;talkcode.sh&lt;/code&gt;&lt;/a&gt; is a Bash pipeline that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;uses &lt;a href=&#34;https://ffmpeg.org/&#34;&gt;&lt;code&gt;ffmpeg&lt;/code&gt;&lt;/a&gt; to record mic into as 16 kHz mono, voice-optimized &lt;code&gt;.opus&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;sends audio to Gemini via &lt;a href=&#34;https://llm.datasette.io/&#34;&gt;&lt;code&gt;llm&lt;/code&gt;&lt;/a&gt; for transcription&lt;/li&gt;
&lt;li&gt;uses &lt;a href=&#34;https://en.wikipedia.org/wiki/AWK&#34;&gt;&lt;code&gt;awk&lt;/code&gt;&lt;/a&gt; to extract the code fence&lt;/li&gt;
&lt;li&gt;uses &lt;a href=&#34;https://github.com/astrand/xclip&#34;&gt;&lt;code&gt;xclip&lt;/code&gt;&lt;/a&gt; to copy the code to the clipboard&lt;/li&gt;
&lt;li&gt;uses &lt;a href=&#34;https://github.com/jordansissel/xdotool&#34;&gt;&lt;code&gt;xdotool&lt;/code&gt;&lt;/a&gt; to paste it back to the original window&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Mic only, 16 kHz mono, voice filtering, fast Opus&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;ffmpeg -hide_banner -v error &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -f pulse -i default &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -ac &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt; -ar &lt;span class=&#34;m&#34;&gt;16000&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -af &lt;span class=&#34;s2&#34;&gt;&amp;#34;highpass=f=100,lowpass=f=6000&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -c:a libopus -b:a 16k -vbr on &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -compression_level &lt;span class=&#34;m&#34;&gt;2&lt;/span&gt; -application voip -frame_duration &lt;span class=&#34;m&#34;&gt;60&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  -y &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$AUDIO&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Transcribe, extract the code fence and copy to clipboard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;llm -m gemini-2.5-flash -a &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$AUDIO&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; -s &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$SYSTEM_TEXT&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; tee /dev/tty &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; awk &lt;span class=&#34;s1&#34;&gt;&amp;#39;BEGIN{f=0} /```/{f=!f; next} f{buf=buf$0&amp;#34;\n&amp;#34;} END{print buf}&amp;#39;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; xclip -selection clipboard
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;# Bring last window to foreground and paste from clipboard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;[&lt;/span&gt; -n &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;${&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;ACTIVE_WIN&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;:-&lt;/span&gt;&lt;span class=&#34;si&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;]&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;;&lt;/span&gt; &lt;span class=&#34;k&#34;&gt;then&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  xdotool windowactivate --sync &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$ACTIVE_WIN&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  sleep 0.08
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  xdotool key --clearmodifiers ctrl+shift+v
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;During the workshop, I said, &amp;ldquo;Which (judicial) bench has the longest pending cases,&amp;rdquo; and it generated a DuckDB query that, single-shot, ran correctly on the &lt;a href=&#34;https://github.com/vanga/indian-high-court-judgments&#34;&gt;Indian High Court judgements&lt;/a&gt; dataset.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;But LLMs are slow and break the flow. Here&amp;rsquo;s how I keep the room engaged:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Dictate, don&amp;rsquo;t type.&lt;/strong&gt; Speaking is faster &lt;strong&gt;and&lt;/strong&gt; more engaging. That&amp;rsquo;s why I built this workflow.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Avoid Alt-Tab.&lt;/strong&gt; Bring the LLM &lt;strong&gt;into&lt;/strong&gt; your app. Window-switching and copy-paste break focus for you &lt;strong&gt;and&lt;/strong&gt; the audience.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Always stream output.&lt;/strong&gt; Narrate as it loads. &lt;code&gt;| tee /dev/tty&lt;/code&gt; streams while piping.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Answer questions while you wait.&lt;/strong&gt; Keep a &lt;a href=&#34;https://www.slido.com/&#34;&gt;Slido&lt;/a&gt; Q&amp;amp;A open and address the top ones while waiting for the LLM.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;a href=&#34;https://www.linkedin.com/posts/sanand0_%F0%9D%97%A9%F0%9D%97%BC%F0%9D%97%B6%F0%9D%97%B0%F0%9D%97%B2-%F0%9D%97%B0%F0%9D%97%BC%F0%9D%97%B1%F0%9D%97%B6%F0%9D%97%BB%F0%9D%97%B4-%F0%9D%97%B6%F0%9D%98%80-%F0%9D%98%81%F0%9D%97%B5%F0%9D%97%B2-%F0%9D%97%BB%F0%9D%97%B2%F0%9D%98%84-activity-7376824026595278848-PxgV&#34;&gt;LinkedIn&lt;/a&gt;&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Pipes May Be All You Need</title>
      <link>https://www.s-anand.net/blog/pipes-may-be-all-you-need/</link>
      <pubDate>Sat, 05 Jul 2025 11:49:24 +0000</pubDate>
      <guid>https://www.s-anand.net/blog/pipes-may-be-all-you-need/</guid>
      <description>&lt;p&gt;&lt;img alt=&#34;Pipes May Be All You Need&#34; loading=&#34;lazy&#34; src=&#34;https://www.s-anand.net/blog/assets/ChatGPT-Image-Jul-1-2025-05_34_17-PM.webp&#34;&gt;&lt;/p&gt;
&lt;p&gt;Switching to a Linux machine has advantages. My thinking&amp;rsquo;s moving from &lt;a href=&#34;https://en.wikipedia.org/wiki/Application_software&#34;&gt;apps&lt;/a&gt; to &lt;a href=&#34;https://en.wikipedia.org/wiki/Pipeline_(Unix)&#34;&gt;pipes&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I wanted a spaced repetition app to remind me quotes from my notes. I began by writing a prompt for Claude Code:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Write a program that I can run like &lt;code&gt;uv run recall.py --files 10 --lines 200 --model gpt-4.1-mini [PATHS...]&lt;/code&gt; that suggests points from my notes to recall. It should&lt;/p&gt;
&lt;p&gt;&lt;code&gt;--files 10&lt;/code&gt;: Pick the 10 latest files from the &lt;code&gt;PATH&lt;/code&gt;s (defaulting to &lt;code&gt;~/Dropbox/notes&lt;/code&gt;)&lt;br&gt;
&lt;code&gt;--lines 200&lt;/code&gt;: Take the top 200 lines (which usually have the latest information)&lt;br&gt;
&lt;code&gt;--model gpt-4.1-mini&lt;/code&gt;: Pass it to this model and ask it to summarize points to recall&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Then I realized that I could do this on the CLI:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;find ~/Dropbox/notes -type f -printf &lt;span class=&#34;s2&#34;&gt;&amp;#34;%T@ %p\n&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\ &lt;/span&gt;  &lt;span class=&#34;c1&#34;&gt;# Print the timestamp and file path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; sort -nr &lt;span class=&#34;se&#34;&gt;\ &lt;/span&gt;                                     &lt;span class=&#34;c1&#34;&gt;# Sort latest first&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; head -n &lt;span class=&#34;m&#34;&gt;10&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\ &lt;/span&gt;                                   &lt;span class=&#34;c1&#34;&gt;# Pick the 10 latest files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; cut -d&lt;span class=&#34;s2&#34;&gt;&amp;#34; &amp;#34;&lt;/span&gt; -f2- &lt;span class=&#34;se&#34;&gt;\ &lt;/span&gt;                               &lt;span class=&#34;c1&#34;&gt;# Drop the timestamp, just get paths&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; xargs -I &lt;span class=&#34;o&#34;&gt;{}&lt;/span&gt; head -n &lt;span class=&#34;m&#34;&gt;200&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;{}&amp;#34;&lt;/span&gt; &lt;span class=&#34;se&#34;&gt;\ &lt;/span&gt;                 &lt;span class=&#34;c1&#34;&gt;# Get the first 200 lines&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;p&#34;&gt;|&lt;/span&gt; llm -s &lt;span class=&#34;s2&#34;&gt;&amp;#34;List 3 points to remember&amp;#34;&lt;/span&gt;              &lt;span class=&#34;c1&#34;&gt;# Ask an LLM to share points to recall&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This works well!&lt;/p&gt;
</description>
    </item>
    <item>
      <title>Windows XP commands</title>
      <link>https://www.s-anand.net/blog/windows-xp-commands/</link>
      <pubDate>Tue, 11 Apr 2006 12:00:00 +0000</pubDate>
      <guid>https://www.s-anand.net/blog/windows-xp-commands/</guid>
      <description>&lt;p&gt;&lt;a href=&#34;http://www.networkclue.com/os/Windows/commands/index.aspx&#34;&gt;Windows XP commands&lt;/a&gt; for the command prompt.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&#34;comments&#34;&gt;Comments&lt;/h2&gt;
&lt;!-- wp-comments-start --&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;sathish&lt;/strong&gt; &lt;em&gt;11 Apr 2006 11:18 am&lt;/em&gt;:
this is a cool link&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- wp-comments-end --&gt;
</description>
    </item>
  </channel>
</rss>
