<?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: Sabahattin Kalkan</title>
    <description>The latest articles on DEV Community by Sabahattin Kalkan (@sabahattink).</description>
    <link>https://dev.to/sabahattink</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%2F3826551%2F6103b15a-e64a-4726-a44c-39f049f899a5.jpeg</url>
      <title>DEV Community: Sabahattin Kalkan</title>
      <link>https://dev.to/sabahattink</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sabahattink"/>
    <language>en</language>
    <item>
      <title>How I Automated My Obsidian Vault with Claude — It Now Works the Night Shift</title>
      <dc:creator>Sabahattin Kalkan</dc:creator>
      <pubDate>Thu, 28 May 2026 20:21:28 +0000</pubDate>
      <link>https://dev.to/sabahattink/how-i-automated-my-obsidian-vault-with-claude-it-now-works-the-night-shift-3gjl</link>
      <guid>https://dev.to/sabahattink/how-i-automated-my-obsidian-vault-with-claude-it-now-works-the-night-shift-3gjl</guid>
      <description>&lt;h2&gt;
  
  
  I was drowning in my own notes
&lt;/h2&gt;

&lt;p&gt;For about two years, I lived inside Obsidian. Daily notes, fleeting thoughts, meeting takeaways, half-formed ideas at 2am, voice memos I'd transcribe by hand. My vault had over 3,000 notes.&lt;/p&gt;

&lt;p&gt;And I remembered almost none of it.&lt;/p&gt;

&lt;p&gt;Every morning I'd open my laptop and stare at yesterday's daily note, trying to reconstruct where I was. The vault was full — full of captures that were never synthesized, tasks that were never carried forward, ideas that died in a folder called &lt;code&gt;_inbox&lt;/code&gt;. I was doing the work of a knowledge worker but getting none of the compounding returns. Notes went in. Nothing came out.&lt;/p&gt;

&lt;p&gt;What made it worse: I knew I was supposed to do the synthesis. Review your notes. Write a morning brief. Connect the dots. But after a full day of work, the last thing I wanted to do was sit down and play editor. So I didn't. And the vault stayed a graveyard.&lt;/p&gt;




&lt;h2&gt;
  
  
  The real problem isn't note-taking
&lt;/h2&gt;

&lt;p&gt;Here's what I eventually figured out: I wasn't failing at note-taking. I was failing at synthesis — and I was expecting myself to do it at the worst possible time.&lt;/p&gt;

&lt;p&gt;Synthesis requires cognitive distance. You need to look at what you captured with fresh eyes. The problem is that "fresh eyes" happen in the morning, and the synthesis work needs to happen after the day is over. That's a structural mismatch, and no productivity system fixes it because it's not a productivity problem.&lt;/p&gt;

&lt;p&gt;It's a timing problem. And timing problems are exactly what automation solves.&lt;/p&gt;

&lt;p&gt;The thought that changed everything: Claude doesn't get tired at 11pm. It doesn't need cognitive distance — it can read the whole day in one pass and pull out what matters. So I built vault-os to hand that job off.&lt;/p&gt;




&lt;h2&gt;
  
  
  What vault-os actually does
&lt;/h2&gt;

&lt;p&gt;vault-os has two main jobs: capture anything, anywhere, and synthesize everything while you sleep.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Capture via Telegram bot.&lt;/strong&gt; I wanted to send notes from my phone without opening Obsidian. The bot uses tag-based routing — anything you send gets sorted into the right section of your daily note automatically. &lt;code&gt;#idea&lt;/code&gt; goes into Content Ideas. &lt;code&gt;#signal&lt;/code&gt; goes into Research Signals. &lt;code&gt;#link&lt;/code&gt; or a bare URL goes into Links to Process. Plain text goes to Captures. Voice messages get transcribed locally and then routed the same way.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Nightly agent at 23:00.&lt;/strong&gt; A PowerShell script runs 12 phases: it reads your day, runs Claude over your captures, synthesizes patterns, writes an evening review, prepares your morning brief, and carries forward any unfinished tasks. By the time you wake up, your daily note for the new day already has context loaded.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Morning digest API.&lt;/strong&gt; A REST endpoint serves the morning brief so you can display it anywhere — a home screen widget, a terminal script, a Raycast extension, whatever fits your setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture: the two components
&lt;/h2&gt;

&lt;h3&gt;
  
  
  server.js — Node.js + Express + Telegraf
&lt;/h3&gt;

&lt;p&gt;The server handles Telegram and the REST API. The core of it is a routing function that decides where each message goes in your daily note:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;routeMessage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^#&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;idea|fikir&lt;/span&gt;&lt;span class="se"&gt;)\b&lt;/span&gt;&lt;span class="sr"&gt;/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;## Content Ideas&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^#&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;signal|research|sinyal&lt;/span&gt;&lt;span class="se"&gt;)\b&lt;/span&gt;&lt;span class="sr"&gt;/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;## Research Signals&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/^#link&lt;/span&gt;&lt;span class="se"&gt;\b&lt;/span&gt;&lt;span class="sr"&gt;/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="sr"&gt;/^https&lt;/span&gt;&lt;span class="se"&gt;?&lt;/span&gt;&lt;span class="sr"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\/\/&lt;/span&gt;&lt;span class="sr"&gt;/i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;## Links to Process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;## Captures&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Simple regex matching. I added Turkish/Azerbaijani aliases (&lt;code&gt;fikir&lt;/code&gt;, &lt;code&gt;sinyal&lt;/code&gt;) because I switch languages mid-thought constantly. You can extend this to whatever tags your brain uses.&lt;/p&gt;

&lt;p&gt;Multi-line messages are handled per-line — if you paste a block of text with five ideas, each line gets routed independently. This matters more than it sounds; it means you can dump a brain dump into Telegram and it lands sorted.&lt;/p&gt;

&lt;p&gt;The voice pipeline runs: OGG (Telegram's format) → ffmpeg converts to 16kHz mono WAV → whisper-cli transcribes → text goes through the same routing function. The whole thing is synchronous on my machine and takes about 4 seconds for a 30-second voice memo.&lt;/p&gt;

&lt;p&gt;REST endpoints are minimal: &lt;code&gt;GET /morning-brief&lt;/code&gt; returns the prepared brief as JSON, &lt;code&gt;POST /capture&lt;/code&gt; lets other tools push content directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  nightly-agent.ps1 — PowerShell, 12 phases
&lt;/h3&gt;

&lt;p&gt;I wrote this in PowerShell because it runs as a Windows Task Scheduler job and I didn't want a dependency on a running Node process. The phases are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FAZ 1-2:&lt;/strong&gt; Environment check, date setup, locate today's note&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FAZ 3 (Claude Think):&lt;/strong&gt; Read all captured content, run a synthesis prompt, extract key themes, identify what was actually important vs. noise&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FAZ 4-5:&lt;/strong&gt; Task extraction, carry-forward logic for incomplete items&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FAZ 6 (Morning Brief):&lt;/strong&gt; Write tomorrow's opening section — not a summary of yesterday, but a launch pad for tomorrow. What's the one thing that matters. What task deserves first attention. What idea is worth developing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FAZ 7-10:&lt;/strong&gt; Link processing, research signal digestion, content angle extraction&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FAZ 11 (Evening Review):&lt;/strong&gt; Appended to today's note — a short human-readable synthesis of the day that you can read before sleep&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FAZ 12:&lt;/strong&gt; Cleanup, log rotation, error reporting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The Claude API calls follow a consistent pattern: write the prompt to a temp file, call &lt;code&gt;claude --print&lt;/code&gt; with &lt;code&gt;--max-turns 1&lt;/code&gt;, capture stdout, clean up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$prompt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-FilePath&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tmpFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Encoding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;UTF8&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$result&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;claude&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--print&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--max-turns&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tmpFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="bp"&gt;$null&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Remove-Item&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$tmpFile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ErrorAction&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;SilentlyContinue&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use &lt;code&gt;--max-turns 1&lt;/code&gt; everywhere in the nightly agent because I don't want back-and-forth — I want one focused output per phase. This also keeps costs predictable. A full nightly run on a moderately active day costs me about $0.04.&lt;/p&gt;




&lt;h2&gt;
  
  
  What a daily note actually looks like
&lt;/h2&gt;

&lt;p&gt;The daily note template has fixed sections that the automation respects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# 2026-05-29&lt;/span&gt;

&lt;span class="gu"&gt;## Morning Brief&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- written by nightly agent from previous night --&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Captures&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- plain Telegram messages land here --&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Content Ideas&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- #idea tags land here --&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Research Signals&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- #signal tags land here --&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Links to Process&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- #link tags and bare URLs land here --&amp;gt;&lt;/span&gt;

&lt;span class="gu"&gt;## Evening Review&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- written by nightly agent at 23:00 --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During the day, you're just sending messages. The structure fills itself in. The Morning Brief is already there when you open Obsidian. The Evening Review appears after the agent runs. You never touch the note directly unless you want to.&lt;/p&gt;

&lt;p&gt;This matters for adoption: if the automation requires you to maintain the structure, you'll break it within two weeks. The structure has to be robust enough to survive a messy day where you just dump text into Telegram without thinking.&lt;/p&gt;




&lt;h2&gt;
  
  
  Voice capture and why local matters
&lt;/h2&gt;

&lt;p&gt;I almost used OpenAI Whisper API for transcription. It's easier to set up and the accuracy is excellent. I switched to whisper.cpp for one reason: the content of voice notes.&lt;/p&gt;

&lt;p&gt;When you're thinking out loud into your phone, you're not performing. You're rough-drafting decisions, processing frustrations, working through half-formed ideas that you wouldn't put in a document. That content is genuinely private — not in a paranoid way, but in the way that a sketchbook is private. It's your unedited thinking.&lt;/p&gt;

&lt;p&gt;Sending that audio to an API means it transits servers you don't control. Running whisper.cpp locally means the audio never leaves your machine. The model is a file on disk (&lt;code&gt;ggml-small.bin&lt;/code&gt;, 466MB), the process runs in a subprocess, and nothing goes over the network.&lt;/p&gt;

&lt;p&gt;Accuracy with &lt;code&gt;small&lt;/code&gt; is good enough for most voice notes — I get the occasional mishearing on proper nouns and mixed-language sentences, but the meaning survives. If you mostly dictate in a single language, &lt;code&gt;small&lt;/code&gt; is the right tradeoff. &lt;code&gt;medium&lt;/code&gt; (1.5GB) is noticeably better for multilingual.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I wake up to
&lt;/h2&gt;

&lt;p&gt;Here's what the Morning Brief section looks like on a real morning:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;## Morning Brief

Carry-forward: Finish the vault-os README (started yesterday, left at setup section).

Yesterday's thread: Three captures around API cost optimization clustered
with a research signal on context caching. Worth developing.

Content angle ready: "Local-first AI tools" — #idea from Tuesday still
unaddressed, now has supporting signals from two separate sources.

Today's open question: The routing logic handles single-line captures well
but breaks on multi-paragraph pastes. Worth fixing or acceptable?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The brief is not a summary. It's a launch pad. There's a difference: a summary tells you what happened, a launch pad tells you where to start.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;Prerequisites: Node.js 18+, PowerShell 7+, Claude CLI authenticated, ffmpeg on PATH, whisper.cpp compiled.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/sabahattink/vault-os
&lt;span class="nb"&gt;cd &lt;/span&gt;vault-os
./setup.sh
&lt;span class="c"&gt;# Edit .env: VAULT_PATH, TELEGRAM_BOT_TOKEN, ANTHROPIC_API_KEY&lt;/span&gt;
node dashboard/server.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the nightly agent, register &lt;code&gt;scripts/nightly-agent.ps1&lt;/code&gt; as a Windows Task Scheduler job at 23:00:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;pwsh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-File&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;scripts/install-scheduler.ps1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  What's next
&lt;/h2&gt;

&lt;p&gt;I'm building this in public. Three things on the roadmap I actually need:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Decision intelligence endpoint.&lt;/strong&gt; Extract decisions from a date range — not summaries, but actual choices made and the reasoning captured around them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Weekly synthesis agent.&lt;/strong&gt; Look across seven days of evening reviews and find the thread — what was I actually working on this week vs. what I said I was working on.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mobile shortcut integration.&lt;/strong&gt; An iOS Shortcut that records audio and POSTs directly to the capture endpoint, bypassing Telegram entirely for voice-only workflows.&lt;/p&gt;




&lt;p&gt;If you use Obsidian and your vault isn't working for you — not because you're bad at it, but because synthesis is genuinely hard to sustain — vault-os might be worth trying.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub:&lt;/strong&gt; &lt;a href="https://github.com/sabahattink/vault-os" rel="noopener noreferrer"&gt;github.com/sabahattink/vault-os&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Star it if it looks useful. Issues and PRs welcome.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Tags: obsidian, productivity, ai, opensource&lt;/em&gt;&lt;/p&gt;

</description>
      <category>obsidian</category>
      <category>productivity</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I built a permission-first CLAUDE.md + agent stack for Claude Code (free, MIT)</title>
      <dc:creator>Sabahattin Kalkan</dc:creator>
      <pubDate>Thu, 14 May 2026 21:01:45 +0000</pubDate>
      <link>https://dev.to/sabahattink/i-built-a-permission-first-claudemd-agent-stack-for-claude-code-free-mit-4ep6</link>
      <guid>https://dev.to/sabahattink/i-built-a-permission-first-claudemd-agent-stack-for-claude-code-free-mit-4ep6</guid>
      <description>&lt;p&gt;I've been using Claude Code daily for months. And I kept hitting the same wall:&lt;/p&gt;

&lt;p&gt;The agent would just &lt;strong&gt;start doing things&lt;/strong&gt;. No plan. No approval. Just... acting.&lt;/p&gt;

&lt;p&gt;It deleted files I didn't want deleted. It refactored things I didn't ask it to refactor. It made "helpful" assumptions that broke my architecture.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;Full Stack HQ&lt;/strong&gt; — a configuration kit that enforces a permission-first workflow. Here's what I learned.&lt;/p&gt;




&lt;h2&gt;
  
  
  The core problem with AI coding agents
&lt;/h2&gt;

&lt;p&gt;Most people configure their AI agent once (or never) and just... let it go. The result is an agent that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Makes assumptions about what you want&lt;/li&gt;
&lt;li&gt;Takes irreversible actions without asking&lt;/li&gt;
&lt;li&gt;Mixes planning and execution in the same step&lt;/li&gt;
&lt;li&gt;Has no consistent code style or architectural awareness&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent is powerful but unpredictable. That's the worst combination in software development.&lt;/p&gt;




&lt;h2&gt;
  
  
  The solution: permission-first workflow
&lt;/h2&gt;

&lt;p&gt;Nothing happens without your explicit approval. The agent plans, shows you what it intends to do, and &lt;strong&gt;waits&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;You:    "Add user authentication with JWT"

Agent:  Here's my plan:
        Phase 1: Create auth module + JWT strategy
        Phase 2: Add guards to protected routes  
        Phase 3: Implement refresh token rotation

        [APPROVAL NEEDED] Should I proceed with Phase 1?

You:    PLAN APPROVED

Agent:  [implements Phase 1 only, then stops and reports]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The only valid approval keywords:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PLAN APPROVED
IMPLEMENTATION APPROVED
PROCEED
DO IT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Anything else — the agent waits. No exceptions.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's inside Full Stack HQ
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Count&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;CLAUDE.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Global rules for Claude Code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;GEMINI.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Global rules for Google Antigravity IDE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Agents&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Specialist AI personas&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Skills&lt;/td&gt;
&lt;td&gt;28&lt;/td&gt;
&lt;td&gt;Domain-specific knowledge modules&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workflows&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Slash command procedures&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  10 Specialist Agents
&lt;/h3&gt;

&lt;p&gt;Instead of one generic agent trying to do everything, you get domain experts:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Agent&lt;/th&gt;
&lt;th&gt;What it handles&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;frontend-specialist&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;React, Next.js, Tailwind&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;backend-specialist&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;NestJS, Node.js, APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;database-specialist&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prisma, PostgreSQL, migrations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;architect&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;System design, trade-offs, ADRs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;code-reviewer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Quality, patterns, best practices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;test-engineer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Vitest, Jest, Playwright&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;security-auditor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Auth, OWASP, input validation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;performance-optimizer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bundle, queries, rendering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;devops-engineer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Docker, CI/CD&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;documentation-writer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;READMEs, technical writing&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Calling them is simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use the database-specialist to design a user schema with soft deletes.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  28 Skills
&lt;/h3&gt;

&lt;p&gt;Deep knowledge modules for the tools you actually use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt;: &lt;code&gt;nextjs-app-router&lt;/code&gt;, &lt;code&gt;react-best-practices&lt;/code&gt;, &lt;code&gt;ui-ux-pro-max&lt;/code&gt;, &lt;code&gt;frontend-design&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend&lt;/strong&gt;: &lt;code&gt;nestjs-patterns&lt;/code&gt;, &lt;code&gt;prisma-workflow&lt;/code&gt;, &lt;code&gt;software-architecture&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing&lt;/strong&gt;: &lt;code&gt;test-driven-development&lt;/code&gt;, &lt;code&gt;systematic-debugging&lt;/code&gt;, &lt;code&gt;webapp-testing&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Meta&lt;/strong&gt;: &lt;code&gt;brainstorming&lt;/code&gt;, &lt;code&gt;prompt-engineering&lt;/code&gt;, &lt;code&gt;skill-creator&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  10 Workflows (Slash Commands)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plan       → phased breakdown with approval checkpoints
/brainstorm → explore architecture options
/debug      → systematic root-cause analysis
/create     → implement an approved plan
/enhance    → improve existing code quality
/test       → generate or fix tests
/orchestrate → coordinate multiple agents
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Install in 30 seconds
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Mac/Linux:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-fsSL&lt;/span&gt; https://raw.githubusercontent.com/sabahattink/antigravity-fullstack-hq/main/install.sh | bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows (PowerShell):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;irm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;https://raw.githubusercontent.com/sabahattink/antigravity-fullstack-hq/main/install.ps1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Options:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./install.sh &lt;span class="nt"&gt;--only-claude&lt;/span&gt;        &lt;span class="c"&gt;# Claude Code only&lt;/span&gt;
./install.sh &lt;span class="nt"&gt;--only-antigravity&lt;/span&gt;   &lt;span class="c"&gt;# Antigravity only&lt;/span&gt;
./install.sh &lt;span class="nt"&gt;--force&lt;/span&gt;              &lt;span class="c"&gt;# Overwrite existing configs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The script detects which IDEs you have installed and configures them automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  What gets installed where
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;~/.claude/
├── CLAUDE.md          ← global rules (Claude Code)
├── agents/            ← 10 specialist agents
└── skills/            ← 28 skill modules

~/.gemini/
├── GEMINI.md          ← global rules (Antigravity)
└── antigravity/
    ├── agents/
    ├── skills/
    └── workflows/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The CLAUDE.md philosophy
&lt;/h2&gt;

&lt;p&gt;The rules file enforces several things I found critical in practice:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Separation of planning and execution&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The agent never does both in the same step. First it plans, you approve, then it executes. This alone eliminates 80% of unwanted surprises.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Role-based reasoning&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before acting, the agent asks: "Who is the right specialist for this?" A database schema question goes to the database specialist, not the frontend agent pretending to know Prisma.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Explicit code style&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No semicolons. Single quotes. 2-space indentation. Arrow functions. Named exports. These aren't suggestions — they're enforced rules the agent follows on every file, every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Security checklist&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before every commit: no hardcoded secrets, all inputs validated, no unbounded queries, rate limiting on public endpoints. The agent checks these automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why it works
&lt;/h2&gt;

&lt;p&gt;The mental model I was missing: &lt;strong&gt;AI agents should behave like senior engineers, not interns with root access.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Senior engineers don't start typing when you describe a problem. They think, propose a plan, get sign-off, then execute — one reversible step at a time.&lt;/p&gt;

&lt;p&gt;Full Stack HQ enforces this discipline by default.&lt;/p&gt;




&lt;h2&gt;
  
  
  Repo
&lt;/h2&gt;

&lt;p&gt;⭐ &lt;a href="https://github.com/sabahattink/antigravity-fullstack-hq" rel="noopener noreferrer"&gt;github.com/sabahattink/antigravity-fullstack-hq&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MIT license. Open to PRs — especially new agents and skills.&lt;/p&gt;

&lt;p&gt;What does your current CLAUDE.md look like? I'd love to see what rules others have found valuable.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claudecode</category>
      <category>devtools</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Building MailTest: An Open Source Email Deliverability Debugger</title>
      <dc:creator>Sabahattin Kalkan</dc:creator>
      <pubDate>Mon, 13 Apr 2026 03:53:52 +0000</pubDate>
      <link>https://dev.to/sabahattink/building-mailtest-an-open-source-email-deliverability-debugger-17hn</link>
      <guid>https://dev.to/sabahattink/building-mailtest-an-open-source-email-deliverability-debugger-17hn</guid>
      <description>&lt;h1&gt;
  
  
  Building MailTest: An Open Source Email Deliverability Debugger
&lt;/h1&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;[Story about client's 50K emails going to spam]&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Existing Tools Fall Short
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Expensive ($100+/month)&lt;/li&gt;
&lt;li&gt;No explanations&lt;/li&gt;
&lt;li&gt;SaaS lock-in&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;[Demo GIF/screenshots]&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Architecture
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Backend
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;NestJS + Fastify (why not Express)&lt;/li&gt;
&lt;li&gt;BullMQ for async jobs&lt;/li&gt;
&lt;li&gt;RS256 JWT (why not HS256)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Frontend
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Next.js 15 App Router&lt;/li&gt;
&lt;li&gt;Radix UI primitives&lt;/li&gt;
&lt;li&gt;Real-time updates with SSE&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Infrastructure
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Docker Compose&lt;/li&gt;
&lt;li&gt;PostgreSQL 16&lt;/li&gt;
&lt;li&gt;Redis 7&lt;/li&gt;
&lt;li&gt;Paddle billing&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Interesting Challenges
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;IMAP Polling:&lt;/strong&gt; How to catch emails reliably&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scoring Algorithm:&lt;/strong&gt; Weighted checks (SPF 15%, DKIM 20%, etc.)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PDF Generation:&lt;/strong&gt; Server-side with Puppeteer&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;[Show interesting parts]&lt;/p&gt;

&lt;h2&gt;
  
  
  What's Next
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;More integrations&lt;/li&gt;
&lt;li&gt;Auto-fix features&lt;/li&gt;
&lt;li&gt;API monetization&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Try It
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://mailtest.scuton.com" rel="noopener noreferrer"&gt;https://mailtest.scuton.com&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Discussion
&lt;/h2&gt;

&lt;p&gt;What features would you want in a deliverability tool?&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>saas</category>
      <category>node</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>I built a CLI that diagnoses your code before you ship</title>
      <dc:creator>Sabahattin Kalkan</dc:creator>
      <pubDate>Sat, 28 Mar 2026 10:45:57 +0000</pubDate>
      <link>https://dev.to/sabahattink/title-i-built-a-cli-that-diagnoses-your-code-before-you-ship-tags-nestjs-typescript-opensource-2208</link>
      <guid>https://dev.to/sabahattink/title-i-built-a-cli-that-diagnoses-your-code-before-you-ship-tags-nestjs-typescript-opensource-2208</guid>
      <description>&lt;p&gt;I built a CLI that diagnoses your code before you ship&lt;br&gt;
Every NestJS project I've worked on had the same problems:&lt;/p&gt;

&lt;p&gt;POST endpoints without auth guards&lt;br&gt;
Hardcoded API keys in source code&lt;br&gt;
.env not in .gitignore&lt;br&gt;
Zero tests&lt;br&gt;
No Swagger documentation&lt;/p&gt;

&lt;p&gt;I was tired of catching these manually in code reviews. So I built codediag.&lt;br&gt;
What it does&lt;br&gt;
bashnpx codediag scan .&lt;br&gt;
One command. It auto-detects your stack and runs 5 analyzers:&lt;br&gt;
  codediag — Diagnostic Report&lt;/p&gt;

&lt;p&gt;Project:  my-nestjs-app&lt;br&gt;
  Stack:    nestjs + typescript + prisma&lt;br&gt;
  Score:    B+ (87/100)&lt;/p&gt;

&lt;p&gt;API Health        ███████████████░░░░░  78&lt;br&gt;
  Security          ██████████████████░░  92&lt;br&gt;
  Dependencies      ██████████████████░░  91&lt;br&gt;
  Testing           ████████████████░░░░  82&lt;br&gt;
  Structure         █████████████████░░░  88&lt;br&gt;
The 5 Analyzers&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;API Health (NestJS)
This is the differentiator. codediag uses ts-morph to do real AST analysis of your NestJS decorators — not regex pattern matching.
It discovers every endpoint from &lt;a class="mentioned-user" href="https://dev.to/get"&gt;@get&lt;/a&gt;(), &lt;a class="mentioned-user" href="https://dev.to/post"&gt;@post&lt;/a&gt;(), @Put(), @Delete(), @Patch() decorators and checks:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Auth guards: Does this endpoint have @UseGuards()? Especially important for mutating endpoints.&lt;br&gt;
DTO validation: Is the &lt;a class="mentioned-user" href="https://dev.to/body"&gt;@body&lt;/a&gt;() parameter typed with a DTO class?&lt;br&gt;
Swagger docs: Are @ApiOperation() and @ApiResponse() present?&lt;br&gt;
Return types: Is there an explicit return type annotation?&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Security
The stuff that ends up on HackerNews for the wrong reasons:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hardcoded secrets (API keys, Stripe keys, AWS keys, GitHub tokens)&lt;br&gt;
.env in .gitignore&lt;br&gt;
Helmet middleware for HTTP security headers&lt;br&gt;
CORS wildcard (origin: '*') detection&lt;br&gt;
Rate limiting package installed&lt;br&gt;
Password hashing library present&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Dependencies
Your node_modules is a supply chain. codediag treats it like one:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;npm audit vulnerabilities&lt;br&gt;
Lock file existence&lt;br&gt;
Deprecated packages&lt;br&gt;
Engine specification&lt;br&gt;
Essential scripts&lt;/p&gt;

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

&lt;p&gt;Test file existence and count&lt;br&gt;
Framework detection (Jest, Vitest, Mocha, Ava)&lt;br&gt;
Test-to-source file ratio&lt;br&gt;
E2E test directory&lt;br&gt;
Coverage threshold configuration&lt;/p&gt;

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

&lt;p&gt;README quality&lt;br&gt;
Linter configuration (ESLint or Biome)&lt;br&gt;
Formatter configuration (Prettier)&lt;br&gt;
TypeScript strict mode&lt;br&gt;
NestJS module organization&lt;br&gt;
.env.example presence&lt;/p&gt;

&lt;p&gt;Scoring&lt;br&gt;
Each analyzer scores 0-100. The total is a weighted average:&lt;br&gt;
AnalyzerWeightAPI Health25%Security30%Dependencies20%Testing15%Structure10%&lt;br&gt;
Security gets the highest weight because shipping vulnerable code is the worst bug.&lt;br&gt;
CI/CD&lt;br&gt;
One line in your GitHub Actions:&lt;br&gt;
yaml- run: npx codediag scan . --ci --threshold 80&lt;br&gt;
Exits with code 1 if the score drops below your threshold.&lt;br&gt;
What's next&lt;/p&gt;

&lt;p&gt;Next.js analyzer&lt;br&gt;
Express route analyzer&lt;br&gt;
Web dashboard with trend tracking&lt;br&gt;
AI-powered fix suggestions&lt;br&gt;
VS Code extension&lt;/p&gt;

&lt;p&gt;Try it&lt;br&gt;
bashnpx codediag scan .&lt;br&gt;
Zero config. MIT licensed. 33KB bundled.&lt;/p&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/scuton-technology/codediag" rel="noopener noreferrer"&gt;https://github.com/scuton-technology/codediag&lt;/a&gt;&lt;br&gt;
npm: &lt;a href="https://www.npmjs.com/package/codediag" rel="noopener noreferrer"&gt;https://www.npmjs.com/package/codediag&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear what checks you'd want added. Drop a comment or open an issue!&lt;/p&gt;

</description>
      <category>nestjs</category>
      <category>typescript</category>
      <category>opensource</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Stop switching to GitHub.com for standup — I built a CLI for that</title>
      <dc:creator>Sabahattin Kalkan</dc:creator>
      <pubDate>Tue, 17 Mar 2026 09:30:29 +0000</pubDate>
      <link>https://dev.to/sabahattink/stop-switching-to-githubcom-for-standup-i-built-a-cli-for-that-3llk</link>
      <guid>https://dev.to/sabahattink/stop-switching-to-githubcom-for-standup-i-built-a-cli-for-that-3llk</guid>
      <description>&lt;p&gt;Every morning it's the same routine.&lt;/p&gt;

&lt;p&gt;Open GitHub. Filter by author. Scroll through commits. Switch repos. Try&lt;br&gt;
to remember what you did yesterday. Piece together a standup from five&lt;br&gt;
different tabs.&lt;/p&gt;

&lt;p&gt;Or worse — you're juggling three different repos, two orgs, and a&lt;br&gt;
contractor's fork, and the GitHub web UI has no idea you want to see all&lt;br&gt;
of it at once.&lt;/p&gt;

&lt;p&gt;I built &lt;strong&gt;gpulse&lt;/strong&gt; to fix this.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;gpulse is a CLI toolkit that brings the GitHub insights you actually need&lt;br&gt;
into your terminal. Six focused commands, zero browser required.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @sabahattinkalkan/gpulse
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ghp_your_token_here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;gpulse standup&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;What did you actually do since yesterday?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpulse standup           &lt;span class="c"&gt;# last 24 hours, all repos&lt;/span&gt;
gpulse standup &lt;span class="nt"&gt;-d&lt;/span&gt; 3      &lt;span class="c"&gt;# last 3 days&lt;/span&gt;
gpulse standup &lt;span class="nt"&gt;-u&lt;/span&gt; alice  &lt;span class="c"&gt;# another user's activity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output:&lt;br&gt;
Standup for &lt;a class="mentioned-user" href="https://dev.to/sabahattinkalkan"&gt;@sabahattinkalkan&lt;/a&gt;&lt;br&gt;
Since Mar 15, 2026 12:00 AM&lt;br&gt;
Commits&lt;br&gt;
a1b2c3d feat: add user authentication (org/app)&lt;br&gt;
d4e5f6a fix: resolve memory leak in worker (org/api)&lt;br&gt;
Pull Requests&lt;/p&gt;
&lt;h1&gt;
  
  
  42 Add OAuth2 support (org/app)
&lt;/h1&gt;

&lt;p&gt;Reviews&lt;/p&gt;
&lt;h1&gt;
  
  
  41 Refactor database layer (org/api)
&lt;/h1&gt;

&lt;p&gt;──────────────────────────────────────────&lt;br&gt;
Summary: 2 commits, 2 PRs, 1 review&lt;/p&gt;

&lt;p&gt;This is what I actually read out at standup. Copy, paste, done.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;code&gt;gpulse health&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Repo health score (A–F). Checks README, LICENSE, CI, stale issues.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpulse health vercel/next.js
&lt;span class="c"&gt;# Score: 90/100 (A)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;gpulse review&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;PR dashboard — review requests, assigned PRs, your open PRs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpulse review
&lt;span class="c"&gt;# Review Requested (2)&lt;/span&gt;
&lt;span class="c"&gt;#   #87 Add rate limiting middleware (org/api)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;gpulse changelog&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Auto-generate changelog from git tags using Conventional Commits.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpulse changelog &lt;span class="nt"&gt;-o&lt;/span&gt; CHANGELOG.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;code&gt;gpulse digest&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Weekly repo digest — commits, issues, merged PRs, contributors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gpulse digest &lt;span class="nt"&gt;-d&lt;/span&gt; 7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why terminal?
&lt;/h2&gt;

&lt;p&gt;Context switching kills flow. gpulse keeps you in the terminal where&lt;br&gt;
you're already working. Also useful in SSH sessions and CI scripts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @sabahattinkalkan/gpulse
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ghp_...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No config files. No YAML. Just the token and go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/scuton-technology/ghx" rel="noopener noreferrer"&gt;https://github.com/scuton-technology/ghx&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;npm&lt;/strong&gt;: &lt;code&gt;npm install -g @sabahattinkalkan/gpulse&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MIT licensed. What would you add to a GitHub CLI toolkit? Drop it in the comments.&lt;/p&gt;

</description>
      <category>github</category>
      <category>cli</category>
      <category>productivity</category>
      <category>opensource</category>
    </item>
    <item>
      <title>I built a self-hosted LLM proxy that supports 12 providers (Claude, GPT-4o, Gemini, Ollama...)</title>
      <dc:creator>Sabahattin Kalkan</dc:creator>
      <pubDate>Mon, 16 Mar 2026 10:18:50 +0000</pubDate>
      <link>https://dev.to/sabahattink/i-built-a-self-hosted-llm-proxy-that-supports-12-providers-claude-gpt-4o-gemini-ollama-3ej1</link>
      <guid>https://dev.to/sabahattink/i-built-a-self-hosted-llm-proxy-that-supports-12-providers-claude-gpt-4o-gemini-ollama-3ej1</guid>
      <description>&lt;p&gt;Every time a new LLM comes out, someone on your team adds a new SDK,&lt;br&gt;
a new API key in .env, and a new set of error handling logic. Repeat&lt;br&gt;
for OpenAI, Anthropic, Gemini, Groq, Mistral, Ollama...&lt;/p&gt;

&lt;p&gt;I got tired of this. So I built &lt;strong&gt;llm-gateway&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;llm-gateway is a single Go binary that sits between your app and every&lt;br&gt;
LLM provider. Your code sends one request format (OpenAI-compatible),&lt;br&gt;
and the gateway routes it to the right provider based on the model name.&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="c"&gt;# One endpoint for all providers&lt;/span&gt;
curl http://localhost:8080/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"model": "claude-sonnet-4-20250514", "messages": [{"role": "user", "content": "hello"}]}'&lt;/span&gt;

&lt;span class="c"&gt;# Switch provider by changing the model name — zero code changes&lt;/span&gt;
curl http://localhost:8080/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"model": "gpt-4o", "messages": [...]}'&lt;/span&gt;

&lt;span class="c"&gt;# Local model — no API key needed&lt;/span&gt;
curl http://localhost:8080/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"model": "llama3.2", "messages": [...]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Model routing is automatic:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;claude-*&lt;/code&gt; → Anthropic&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gpt-*&lt;/code&gt;, &lt;code&gt;o1&lt;/code&gt;, &lt;code&gt;o3&lt;/code&gt; → OpenAI
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gemini-*&lt;/code&gt; → Google&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;llama*&lt;/code&gt; → Ollama or Groq&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;mistral-*&lt;/code&gt; → Mistral&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;grok-*&lt;/code&gt; → xAI&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sonar-*&lt;/code&gt; → Perplexity&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;command-*&lt;/code&gt; → Cohere&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Install in 30 seconds
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 &lt;span class="nt"&gt;-v&lt;/span&gt; gateway-data:/data scutontech/llm-gateway
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Open &lt;code&gt;http://localhost:8080/admin&lt;/code&gt; → set your admin password → add API&lt;br&gt;
keys from the Settings page. No .env files, no YAML editing.&lt;/p&gt;
&lt;h2&gt;
  
  
  Admin dashboard
&lt;/h2&gt;

&lt;p&gt;The gateway ships with a full admin dashboard:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time stats&lt;/strong&gt; — requests, tokens, latency, error rate, estimated cost&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Provider breakdown&lt;/strong&gt; — which providers you're actually using&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost analytics&lt;/strong&gt; — daily/monthly spend by model, with CSV export&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Request log&lt;/strong&gt; — last 50 requests with model, provider, tokens, cost, latency&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dark mode&lt;/strong&gt; — because of course&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Streaming support
&lt;/h2&gt;

&lt;p&gt;SSE streaming works for all providers. The gateway normalizes&lt;br&gt;
Anthropic's stream format to OpenAI's SSE format transparently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:8080/v1/chat/completions &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"model": "claude-sonnet-4-20250514", "stream": true, "messages": [...]}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Supported providers
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Provider&lt;/th&gt;
&lt;th&gt;Models&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Anthropic&lt;/td&gt;
&lt;td&gt;claude-opus-4, claude-sonnet-4, claude-haiku-4&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;OpenAI&lt;/td&gt;
&lt;td&gt;gpt-4o, gpt-4o-mini, o1, o3-mini&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Google&lt;/td&gt;
&lt;td&gt;gemini-2.0-flash, gemini-1.5-pro&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Groq&lt;/td&gt;
&lt;td&gt;llama-3.3-70b, mixtral-8x7b&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mistral&lt;/td&gt;
&lt;td&gt;mistral-large, codestral&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cohere&lt;/td&gt;
&lt;td&gt;command-r-plus, command-r&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;xAI&lt;/td&gt;
&lt;td&gt;grok-2, grok-2-mini&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Perplexity&lt;/td&gt;
&lt;td&gt;sonar-large, sonar-small&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Together AI&lt;/td&gt;
&lt;td&gt;50+ open source models&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ollama&lt;/td&gt;
&lt;td&gt;any local model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;LM Studio&lt;/td&gt;
&lt;td&gt;any local model&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vLLM&lt;/td&gt;
&lt;td&gt;any hosted model&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Why Go?
&lt;/h2&gt;

&lt;p&gt;~15MB binary. Under 100ms cold start. ~20MB memory at idle.&lt;br&gt;
Drop it on a $5 VPS and forget about it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/scuton-technology/llm-gateway" rel="noopener noreferrer"&gt;https://github.com/scuton-technology/llm-gateway&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Docker&lt;/strong&gt;: &lt;code&gt;docker pull scutontech/llm-gateway&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MIT licensed. PRs welcome.&lt;/p&gt;

</description>
      <category>llm</category>
      <category>ai</category>
      <category>opensource</category>
      <category>go</category>
    </item>
    <item>
      <title>Stop writing bad commit messages — I built a free AI CLI for that</title>
      <dc:creator>Sabahattin Kalkan</dc:creator>
      <pubDate>Mon, 16 Mar 2026 07:09:21 +0000</pubDate>
      <link>https://dev.to/sabahattink/stop-writing-bad-commit-messages-i-built-a-free-ai-cli-for-that-2g22</link>
      <guid>https://dev.to/sabahattink/stop-writing-bad-commit-messages-i-built-a-free-ai-cli-for-that-2g22</guid>
      <description>&lt;p&gt;We've all done it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"fix"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"wip"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"asdfgh"&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"changes"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You're deep in flow, you just want to save progress, and writing a meaningful commit message feels like a speed bump. So you write something meaningless and move on.&lt;/p&gt;

&lt;p&gt;The problem? Three months later, you (or your teammate) is trying to understand &lt;em&gt;why&lt;/em&gt; a change was made. The git log is full of "fix" and "update" and tells you nothing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution: let AI read the diff
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;ai-commit&lt;/strong&gt; — a CLI that reads your staged &lt;code&gt;git diff&lt;/code&gt; and generates 3 &lt;a href="https://www.conventionalcommits.org/" rel="noopener noreferrer"&gt;Conventional Commit&lt;/a&gt; suggestions for you to pick from.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; @scuton/ai-commit
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then just:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git add &lt;span class="nb"&gt;.&lt;/span&gt;
aic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You get something like:&lt;br&gt;
? Pick a commit message:&lt;br&gt;
❯ feat(auth): add JWT refresh token rotation&lt;br&gt;
feat(auth): implement rotating refresh token with replay protection&lt;br&gt;
chore(auth): update token lifecycle and Redis TTL strategy&lt;br&gt;
✎ Write my own&lt;br&gt;
✗ Cancel&lt;/p&gt;

&lt;p&gt;Pick one, hit enter, done. The whole thing takes 3 seconds.&lt;/p&gt;
&lt;h2&gt;
  
  
  Free option: Ollama (no API key needed)
&lt;/h2&gt;

&lt;p&gt;This is the part I'm most excited about. You can run it completely free using &lt;a href="https://ollama.ai" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; — a local LLM runner.&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="c"&gt;# Install Ollama and pull a model&lt;/span&gt;
ollama pull llama3.2

&lt;span class="c"&gt;# Use ai-commit with Ollama&lt;/span&gt;
aic &lt;span class="nt"&gt;-p&lt;/span&gt; ollama
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No API key. No cost per commit. Everything stays on your machine.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supports Claude and GPT-4o too
&lt;/h2&gt;

&lt;p&gt;If you prefer cloud models:&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="c"&gt;# Claude (best quality)&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;ANTHROPIC_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-ant-...
aic

&lt;span class="c"&gt;# GPT-4o&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;OPENAI_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sk-...
aic &lt;span class="nt"&gt;-p&lt;/span&gt; openai
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Cost is around $0.001 per commit with cloud models — basically free.&lt;/p&gt;

&lt;h2&gt;
  
  
  Install as a git hook
&lt;/h2&gt;

&lt;p&gt;If you want it to run automatically on every &lt;code&gt;git commit&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;aic hook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remove it anytime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aic hook &lt;span class="nt"&gt;--remove&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Other useful flags
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aic &lt;span class="nt"&gt;--dry-run&lt;/span&gt;        &lt;span class="c"&gt;# Preview suggestions without committing&lt;/span&gt;
aic &lt;span class="nt"&gt;--count&lt;/span&gt; 5        &lt;span class="c"&gt;# Get 5 suggestions instead of 3&lt;/span&gt;
aic &lt;span class="nt"&gt;--lang&lt;/span&gt; &lt;span class="nb"&gt;tr&lt;/span&gt;        &lt;span class="c"&gt;# Generate in Turkish (or any language)&lt;/span&gt;
aic &lt;span class="nt"&gt;--emoji&lt;/span&gt;          &lt;span class="c"&gt;# Add emoji to commit type&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Programmatic API
&lt;/h2&gt;

&lt;p&gt;You can also use it in your own tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;generateCommitMessages&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@scuton/ai-commit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;suggestions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;generateCommitMessages&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;provider&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;anthropic&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;count&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;suggestions&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// "feat(auth): add JWT refresh token rotation"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Try it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GitHub&lt;/strong&gt;: &lt;a href="https://github.com/scuton-technology/ai-commit" rel="noopener noreferrer"&gt;https://github.com/scuton-technology/ai-commit&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;npm&lt;/strong&gt;: &lt;code&gt;npm install -g @scuton/ai-commit&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MIT licensed, open source. PRs welcome — especially for new provider integrations.&lt;/p&gt;

&lt;p&gt;Happy committing.&lt;/p&gt;

</description>
      <category>git</category>
      <category>cli</category>
      <category>ai</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
