<?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: Nathaniel Ady</title>
    <description>The latest articles on DEV Community by Nathaniel Ady (@nathaniel_ady_7755ccc80df).</description>
    <link>https://dev.to/nathaniel_ady_7755ccc80df</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%2F3865811%2F1b8aca03-8bcb-4dd1-989d-a5c6c09fe4d4.png</url>
      <title>DEV Community: Nathaniel Ady</title>
      <link>https://dev.to/nathaniel_ady_7755ccc80df</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nathaniel_ady_7755ccc80df"/>
    <language>en</language>
    <item>
      <title>lazy-alias: my shell history writes my aliases, with a 1.5B model on my CPU</title>
      <dc:creator>Nathaniel Ady</dc:creator>
      <pubDate>Mon, 26 Oct 2026 03:21:07 +0000</pubDate>
      <link>https://dev.to/nathaniel_ady_7755ccc80df/lazy-alias-my-shell-history-writes-my-aliases-with-a-15b-model-on-my-cpu-33b5</link>
      <guid>https://dev.to/nathaniel_ady_7755ccc80df/lazy-alias-my-shell-history-writes-my-aliases-with-a-15b-model-on-my-cpu-33b5</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the Hacktoberfest Open-Source AI Challenge, Week 3: Slow and Steady.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;lazy-alias&lt;/strong&gt; reads your bash history, finds the 2-3 step command sequences you keep&lt;br&gt;
retyping, and asks a small open-weight model running on your CPU to name each one as a shell&lt;br&gt;
function. Nothing is written until you approve it. Weeks later, when you've forgotten what you&lt;br&gt;
called it, &lt;code&gt;lazy-alias find "restart the containers"&lt;/code&gt; gets it back by meaning, not just by keyword.&lt;/p&gt;

&lt;p&gt;It's built for the laziest possible workflow: you don't have to notice your own habits. Your&lt;br&gt;
history already did.&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;Demo transcript (no video): real output of &lt;code&gt;./demo.sh&lt;/code&gt;, shown below.&lt;/p&gt;

&lt;p&gt;Real output from &lt;code&gt;./demo.sh&lt;/code&gt; (synthetic seeded history, see The Lazy Payoff):&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="o"&gt;==&lt;/span&gt; lazy-alias ingest
ingested 932 commands into TimescaleDB
&lt;span class="o"&gt;==&lt;/span&gt; lazy-alias suggest &lt;span class="nt"&gt;--yes&lt;/span&gt;

&lt;span class="c"&gt;# typed 38 times on 21 days: git add -A &amp;amp;&amp;amp; git commit -m wip &amp;amp;&amp;amp; git push&lt;/span&gt;
&lt;span class="c"&gt;# Pushes changes to the remote repository after adding and committing them.&lt;/span&gt;
git_commit_push&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  git add &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  git commit &lt;span class="nt"&gt;-m&lt;/span&gt; wip &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  git push
&lt;span class="o"&gt;}&lt;/span&gt;
...
&lt;span class="o"&gt;==&lt;/span&gt; lazy-alias find &lt;span class="s1"&gt;'restart the containers'&lt;/span&gt;
keyword: &lt;span class="o"&gt;[]&lt;/span&gt;
vector:  &lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="s1"&gt;'compose_operations'&lt;/span&gt;, &lt;span class="s1"&gt;'use_context_web'&lt;/span&gt;, &lt;span class="s1"&gt;'api_test_setup'&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
best &lt;span class="o"&gt;(&lt;/span&gt;RRF&lt;span class="o"&gt;)&lt;/span&gt;:
compose_operations&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  docker compose down &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  docker compose up &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--build&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  docker compose logs &lt;span class="nt"&gt;-f&lt;/span&gt; api
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/CyberScryb/lazy-alias" rel="noopener noreferrer"&gt;https://github.com/CyberScryb/lazy-alias&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Python, about 220 lines: &lt;code&gt;history.py&lt;/code&gt; (parse), &lt;code&gt;db.py&lt;/code&gt; (TimescaleDB + pgvector SQL),&lt;br&gt;
&lt;code&gt;naming.py&lt;/code&gt; (Qwen via llama.cpp), &lt;code&gt;search.py&lt;/code&gt; (rank fusion), &lt;code&gt;cli.py&lt;/code&gt;. MIT licensed, 3 unit tests.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Storage: TimescaleDB.&lt;/strong&gt; History is loaded into a &lt;code&gt;commands&lt;/code&gt; hypertable. Sessions split on&lt;br&gt;
30-minute gaps. &lt;code&gt;demo.sh&lt;/code&gt; starts a throwaway, user-owned Postgres cluster in &lt;code&gt;./.pgdata&lt;/code&gt; on a&lt;br&gt;
private socket, so it never touches the system Postgres config.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mining habits in SQL.&lt;/strong&gt; Window functions (&lt;code&gt;lead()&lt;/code&gt; over each session) pair every command with&lt;br&gt;
the next one or two, as long as they're at most 5 minutes apart. Grouping by the sequence gives a&lt;br&gt;
count, and &lt;code&gt;count(DISTINCT time_bucket('1 day', ts))&lt;/code&gt; tells a daily habit apart from one&lt;br&gt;
afternoon of repetition. Two-step sequences already contained in a three-step one are dropped.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Naming with an open model.&lt;/strong&gt; Qwen2.5-1.5B-Instruct (q4_k_m GGUF, about 1 GB) runs through&lt;br&gt;
llama.cpp on CPU at temperature 0. It returns JSON with a name and a one-line description; the&lt;br&gt;
name is sanitized into a valid, unique shell identifier. You approve each function with &lt;code&gt;y&lt;/code&gt;.&lt;br&gt;
I could swap models in one line (&lt;code&gt;LAZY_ALIAS_MODEL&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Finding forgotten functions: hybrid search.&lt;/strong&gt; Each approved function is stored with a&lt;br&gt;
&lt;code&gt;tsvector&lt;/code&gt; and a 384-dim all-MiniLM-L6-v2 embedding in a pgvector column. &lt;code&gt;find&lt;/code&gt; runs a keyword&lt;br&gt;
query (&lt;code&gt;to_tsquery&lt;/code&gt;, ranked by &lt;code&gt;ts_rank&lt;/code&gt;) and a cosine-distance query (&lt;code&gt;&amp;lt;=&amp;gt;&lt;/code&gt;), then merges them&lt;br&gt;
with reciprocal-rank fusion. "docker logs" hits by keyword; "restart the containers" shares no&lt;br&gt;
words with the function, so the vector side finds it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;Your shell history is one of the most private files on your machine: hostnames, paths,&lt;br&gt;
sometimes tokens pasted by mistake. A tool that reads it should never ship it to an API.&lt;br&gt;
Open-weight models small enough for a laptop CPU, plus an open-source database with vector&lt;br&gt;
search built in, make that possible. Everything here is inspectable, runs offline once the models&lt;br&gt;
are downloaded, and costs nothing per call. Open licenses (Apache-2.0 models, open-source&lt;br&gt;
Postgres extensions, MIT code) mean anyone can fork it for zsh, fish, or their own team.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Lazy Payoff
&lt;/h2&gt;

&lt;p&gt;On the demo history, lazy-alias found four habits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;cd ~/proj/api &amp;amp;&amp;amp; source .venv/bin/activate &amp;amp;&amp;amp; pytest -q&lt;/code&gt;: 44 times on 19 days&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;git add -A &amp;amp;&amp;amp; git commit -m wip &amp;amp;&amp;amp; git push&lt;/code&gt;: 38 times on 21 days&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl config use-context staging &amp;amp;&amp;amp; kubectl get pods -n web&lt;/code&gt;: 36 times on 19 days&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker compose down &amp;amp;&amp;amp; up -d --build &amp;amp;&amp;amp; logs -f api&lt;/code&gt;: 29 times on 17 days&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That's 147 multi-step retypes that become one word each.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt; these numbers come from a synthetic, seeded 30-day history generated by&lt;br&gt;
&lt;code&gt;seed_history.py&lt;/code&gt;, not from anyone's real shell. They show what the tool does, not a measured&lt;br&gt;
productivity gain. Run it on your own history to see yours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Overall&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Tiger Data:&lt;/strong&gt; TimescaleDB stores the history as a hypertable and
&lt;code&gt;time_bucket&lt;/code&gt; separates daily habits from one-off bursts. pgvector stores the embeddings, and
&lt;code&gt;find&lt;/code&gt; runs &lt;strong&gt;hybrid keyword + vector search&lt;/strong&gt; (tsvector + pgvector, fused with RRF), which is
exactly what the category prompt asks for.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  My Agent Session
&lt;/h2&gt;

&lt;p&gt;An AI coding agent built this with me. It wrote the code, set up the local TimescaleDB +&lt;br&gt;
pgvector cluster, ran the tests and the demo, and drafted this post. The demo output above is&lt;br&gt;
pasted from its real run (&lt;code&gt;demo_run.txt&lt;/code&gt; in the repo). I don't have a session-replay embed to share.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Assistance
&lt;/h2&gt;

&lt;p&gt;I built this with help from an AI coding agent, which wrote much of the code and this draft.&lt;br&gt;
An AI agent ran everything on its machine and drafted this post; I approved it for publishing.&lt;br&gt;
Every output shown above comes from a real run of &lt;code&gt;./demo.sh&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credits
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;TimescaleDB (Tiger Data) and pgvector&lt;/li&gt;
&lt;li&gt;Qwen2.5-1.5B-Instruct (Apache-2.0), Qwen team&lt;/li&gt;
&lt;li&gt;all-MiniLM-L6-v2 (Apache-2.0), via fastembed&lt;/li&gt;
&lt;li&gt;llama.cpp and llama-cpp-python; psycopg&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>I stopped pasting JSON into random websites — 9 free dev utilities that don't want your email</title>
      <dc:creator>Nathaniel Ady</dc:creator>
      <pubDate>Wed, 14 Oct 2026 20:19:49 +0000</pubDate>
      <link>https://dev.to/nathaniel_ady_7755ccc80df/i-stopped-pasting-json-into-random-websites-9-free-dev-utilities-that-dont-want-your-email-263g</link>
      <guid>https://dev.to/nathaniel_ady_7755ccc80df/i-stopped-pasting-json-into-random-websites-9-free-dev-utilities-that-dont-want-your-email-263g</guid>
      <description>&lt;p&gt;I have a confession: for years my debugging workflow included pasting API responses, tokens, and log snippets into whatever formatter or decoder site Google threw at me. No adblock regrets can undo the times I decoded a JWT on a site that had twelve popups.&lt;/p&gt;

&lt;p&gt;I built a small set of free browser tools for exactly this reason, so I want to be upfront: yes, these are my tools. But the point of this post stands even if you never click the links — stop handing your data to sites you wouldn't trust with your coffee order.&lt;/p&gt;

&lt;p&gt;What I wanted was simple: paste, get the answer, leave. No account. No email. No "upgrade to format the rest of your file." Here's the kit I keep open in a tab group:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;JSON formatter/validator&lt;/strong&gt; — paste it, it's formatted and validated. Also converts JSON to CSV when the analyst asks for a spreadsheet.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Regex tester&lt;/strong&gt; — live highlighting while you build the pattern, so you stop guessing and start shipping.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Base64 encoder/decoder&lt;/strong&gt; — no mystery, does the thing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;JWT decoder&lt;/strong&gt; — see the payload and header instantly. This is the one that made me stop pasting tokens into random decoders.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cron expression builder&lt;/strong&gt; — human-readable schedule next to the expression so "0 3 * * 1" stops being a quiz question.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Epoch converter&lt;/strong&gt; — timestamps both directions, plus the human dates.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Markdown to HTML&lt;/strong&gt; — for when the CMS wants raw HTML and you think in markdown.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Text diff&lt;/strong&gt; — two files, instant diff, no repo needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subnet calculator&lt;/strong&gt; — CIDR math without the whiteboard.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of them ask for an account. There's no signup wall, no freemium tier, no "create a free account to continue." You paste, you get the answer, you leave. That was the whole design goal.&lt;/p&gt;

&lt;p&gt;My rules for trusting a utility site now, in case you're evaluating others:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It should work before asking who you are. If the first screen is a signup form, it's not a tool, it's a funnel.&lt;/li&gt;
&lt;li&gt;Everything should run in your browser for things like formatting and decoding. If a "JSON formatter" needs a server round-trip, ask yourself why.&lt;/li&gt;
&lt;li&gt;It should not have seventeen ad trackers firing before the tool even loads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The links, since you'll ask: the full set is at &lt;a href="https://cyberscryb.com/tools/" rel="noopener noreferrer"&gt;https://cyberscryb.com/tools/&lt;/a&gt; — JSON formatter is &lt;a href="https://cyberscryb.com/tools/json-formatter/" rel="noopener noreferrer"&gt;https://cyberscryb.com/tools/json-formatter/&lt;/a&gt;, regex tester &lt;a href="https://cyberscryb.com/tools/regex-tester/" rel="noopener noreferrer"&gt;https://cyberscryb.com/tools/regex-tester/&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What tools are in your tab group? I'm always collecting good ones — the ones I trust enough to not ask for anything.&lt;/p&gt;




&lt;p&gt;Nate Ady — founder of CyberScryb. I build free AI tools and dev utilities, no signup, no paywall.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tools</category>
      <category>productivity</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
