<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Ai-Development on Damian Galarza | Software Engineering &amp; AI Consulting</title><link>https://www.damiangalarza.com/tags/ai-development/</link><description>Recent posts from Damian Galarza | Software Engineering &amp; AI Consulting</description><generator>Hugo</generator><language>en-us</language><managingEditor>Damian Galarza</managingEditor><atom:link href="https://www.damiangalarza.com/tags/ai-development/feed.xml" rel="self" type="application/rss+xml"/><item><title>Claude Code Routines: Auto-Maintaining PR Evolution Numbers</title><link>https://www.damiangalarza.com/posts/2026-05-06-claude-code-routine-auto-maintain-pr-evolution-numbers/</link><pubDate>Wed, 06 May 2026 00:00:00 -0400</pubDate><author>Damian Galarza</author><guid>https://www.damiangalarza.com/posts/2026-05-06-claude-code-routine-auto-maintain-pr-evolution-numbers/</guid><description>A backend PR kept colliding with other merges on database evolution numbers. Four manual rebases later, I described the problem to Claude and let it write a routine to handle the rest.</description><content:encoded><![CDATA[<p>I had a backend PR open all week, waiting for a scheduled maintenance window before it could merge. The PR adds a single database evolution, a SQL migration that creates an index needed before the deploy.</p>
<p>Play Framework evolutions are numbered sequentially: 1, 2, 3, each a SQL file. When you add a new evolution, you take the next number. The problem is that every other PR merging to master that week was also adding evolutions. Each time one landed, it took the number mine was using.</p>
<p>Rebase. Renumber. Push. Wait. Another PR merges. Rebase again.</p>
<p>There had to be a better way.</p>
<h2 id="the-ask">The ask</h2>
<p>The fix wasn&rsquo;t complicated. Check if the evolution number on my branch conflicts with what&rsquo;s on master. If it does, renumber to the next available slot, rerun code generation, and force-push. The steps were mechanical. Doing them four times in a week was the problem. This felt like a great fit for Claude Code&rsquo;s recently released feature: <a href="https://code.claude.com/docs/en/routines">routines</a>.</p>
<p>So I described it to Claude in one sentence.</p>
<blockquote>
<p>Can you monitor this daily for breaking changes to the PR and keep it up to date with master? Resolving any issues with the evolution if the number gets taken again and updating the PR accordingly.</p></blockquote>
<p>That&rsquo;s the entire prompt. No pseudo-code. No step-by-step instructions. Just the constraint and the desired outcome.</p>
<h2 id="what-claude-generated">What Claude generated</h2>
<p>Claude wrote a <a href="https://code.claude.com/docs/en/routines">routine</a> to handle the full workflow. A routine is a saved prompt that runs on a schedule against a repository. Routines can run on Anthropic&rsquo;s cloud infrastructure or locally on your machine. I used a local routine for this one.</p>
<p>Here&rsquo;s the generated routine, sanitized and condensed. This is what Claude produced from the one-sentence ask above.</p>
<div class="highlight"><pre tabindex="0" style="color:#cdd6f4;background-color:#1e1e2e;-moz-tab-size:2;-o-tab-size:2;tab-size:2;"><code class="language-text" data-lang="text"><span style="display:flex;"><span>Monitor PR #1234 on org/repo and keep the branch in a
</span></span><span style="display:flex;"><span>mergeable state with master. The PR adds one database
</span></span><span style="display:flex;"><span>evolution. Evolution-number collisions with other PRs
</span></span><span style="display:flex;"><span>merging to master are the recurring issue.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>## Workflow
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>1. Check PR state via `gh pr view` — if not OPEN, stop.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>2. Find our evolution file by grepping for the index
</span></span><span style="display:flex;"><span>   identifier in the evolutions directory.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>3. Check for collision — does master already have a file
</span></span><span style="display:flex;"><span>   at our evolution number?
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>4. If no collision and branch is current with master,
</span></span><span style="display:flex;"><span>   stop silently. No &#34;all clear&#34; comments.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>5. If collision: capture our SQL content, find the highest
</span></span><span style="display:flex;"><span>   evolution number on master, renumber to master_max + 1,
</span></span><span style="display:flex;"><span>   reset to master, write the file at the new number.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>6. Rerun sbt evolutions and code generation. If sbt fails
</span></span><span style="display:flex;"><span>   (local Postgres not reachable), proceed but flag it.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>7. Commit, force-push with lease, update the PR body to
</span></span><span style="display:flex;"><span>   reflect the new evolution number.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>8. Post a PR comment summarizing what changed: which
</span></span><span style="display:flex;"><span>   master PR landed at the old number, the rename from
</span></span><span style="display:flex;"><span>   N.sql to M.sql, and anything needing manual follow-up.
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>## Constraints
</span></span><span style="display:flex;"><span>- Don&#39;t touch other PRs. Don&#39;t merge this one.
</span></span><span style="display:flex;"><span>- Force-push with lease is fine on this feature branch.
</span></span><span style="display:flex;"><span>- Only comment when you take action or something needs
</span></span><span style="display:flex;"><span>  manual attention.
</span></span><span style="display:flex;"><span>- Idempotent: running twice with no upstream changes
</span></span><span style="display:flex;"><span>  should do nothing the second time.
</span></span></code></pre></div><p>In short: check the PR state, find the evolution file, detect whether master already has a file at the same number, and if so, renumber to the next available slot, rerun code generation, force-push, and comment on the PR with a summary. If nothing changed, do nothing and stay quiet.</p>
<p>Two things stand out.</p>
<p>First, the constraints section. I didn&rsquo;t specify most of those. Claude inferred the boundaries from the problem description: don&rsquo;t merge, don&rsquo;t touch other PRs, be idempotent, stay quiet when there&rsquo;s nothing to do. Those are the constraints an experienced developer would set. The routine arrived with them already in place.</p>
<p>Second, the idempotency requirement. A routine that runs daily needs to be safe to run twice. Claude treated that as a given rather than something I needed to spell out.</p>
<p>The routine handled four more renumbers that week without me touching it. Each morning it checked, and on the days a collision had occurred overnight, it renumbered, pushed, and left a comment on the PR explaining what changed.</p>
<h2 id="the-mental-model">The mental model</h2>
<p>The pattern here isn&rsquo;t specific to Play evolutions or database migrations. It applies to any mechanical maintenance task on a long-lived PR. Describe the constraint, not the steps. I didn&rsquo;t write the bash commands or the git operations. I described the problem (evolution numbers collide when other PRs merge) and the desired outcome (keep my PR mergeable). Claude filled in the implementation because the steps follow directly from the constraint.</p>
<p>This is the same dynamic that makes Claude Code effective for coding tasks: the more precisely you describe what you need and why, the better the output. The difference with routines is that the automation keeps running until the PR merges.</p>
<p>If you&rsquo;re babysitting a PR this week, describe the problem. Let the agent write the automation.</p>
<hr>
<p><em>If you&rsquo;re building AI into your engineering workflows and want to move faster without the trial-and-error, <a href="/services/ai-engineering/">let&rsquo;s talk about how I can help</a>.</em></p>
<h2 id="further-reading">Further reading</h2>
<ul>
<li><a href="https://code.claude.com/docs/en/routines">Claude Code Routines documentation</a> for setup and scheduling options</li>
<li><a href="/posts/how-i-use-claude-code/">How I Use Claude Code</a> for more on integrating Claude into daily development work</li>
</ul>
]]></content:encoded></item><item><title>Getting Started with Claude Code</title><link>https://www.damiangalarza.com/videos/2025-12-29-getting-started-with-claude-code/</link><pubDate>Mon, 29 Dec 2025 18:18:03 +0000</pubDate><author>Damian Galarza</author><guid>https://www.damiangalarza.com/videos/2025-12-29-getting-started-with-claude-code/</guid><description>Learn how to set up Claude Code and start using it on your existing projects in under 15 minutes. No more vibe coding - get real AI-assisted development that</description><content:encoded><![CDATA[<p>Learn how to set up Claude Code and start using it on your existing projects in under 15 minutes. No more vibe coding - get real AI-assisted development that actually understands your codebase.</p>
<p>Claude Code is Anthropic&rsquo;s official CLI tool that lives in your terminal, reads your code, makes edits, and runs commands. In this video, I&rsquo;ll take you from zero to productive with a real project.</p>
]]></content:encoded></item></channel></rss>