Moderne and Anthropic, better together: Building a Claude Skill to help author OpenRewrite recipes

Bryan Friedman and Scott Jungling
|
November 13, 2025
Contents

Key Takeaways

At Moderne, we’re exploring how far AI can go toward becoming an expert OpenRewrite recipe author, capable of writing structured, testable, working recipes in the most idiomatic and maintainable way possible.

Writing OpenRewrite recipes turns out to be a great use case for generative AI. When they can be declarative, recipes are highly composable. When they need to be imperative, they’re deeply structured, built around known patterns like visitors and templates. And because every recipe can be backed by before-and-after tests, they’re easily testable, keeping AI as honest as possible. But as we discovered in our first attempts to write an OpenRewrite recipe with Claude Code, even the best models still need coaching.

It left us wondering: how much better could Claude be at writing OpenRewrite recipes if we had a way to teach it the right way to do things once, and reuse that knowledge across every session? 

It turns out, there is a way. Anthropic recently introduced Claude Skills. Skills are reusable pieces of knowledge—text instructions, scripts, or reference files—that can be pulled in as needed. 

Where AI falters in recipe writing

Even though OpenRewrite recipes are structured and testable, and we’ve seen that Claude can generate working versions, getting the model to actually produce high-quality, idiomatic output isn’t so straightforward. We saw that Claude Code didn’t follow all of our best practices, and it wasn’t aware of things like scanning recipes or language directives in tests. It also struggled with knowing when to use declarative YAML versus imperative Java. 

Anthropic offers a few ways to “teach” Claude:

  • Prompt with specific direction (like “be more idiomatic with OpenRewrite recipes”)
  • Include a CLAUDE.md file with a repo
  • Create subagents
  • Build plugins and slash commands
  • Use Claude Skills for reusable guidance

We’d already been using CLAUDE.md pretty regularly, but it’s typically tied to individual repositories, so it didn’t scale as well for cross-project use. We also tried building a recipe-authoring subagent, but that didn’t work as well as we’d hoped. Overloaded terms like “trait” confused Claude, and it continued to repeat the same common mistakes that humans do when first learning to build recipes, like forgetting to use preconditions or trying to directly mutate the LST

Claude Skills looked like a better fit. Instead of repeating instructions every session or per repo, we could encode our conventions once and reuse them everywhere.

Claude Skills and progressive disclosure

What makes Claude Skills especially interesting is how they use progressive disclosure. 

Despite good documentation and lots of examples, it can still be a lot for any model to hold in context. And that lack of retained knowledge often looked to be the source of the limitations we were running into. On top of that, we had found Opus 4.1 to be the best model for recipe authoring, but with Opus now marked as “legacy”, it’s nearly impossible to use without quickly hitting memory and context limits. 

But with progressive disclosure, Claude reads only what it needs, when it needs it, instead of trying to cram everything into a prompt, meaning it can manage context much more efficiently. A Skill is just a bundle of text instructions, optionally supported by things like scripts and reference templates, that get loaded contextually as the task unfolds.

Skills are also easy to maintain. Because it’s just text, the Skill can live alongside your codebase and documentation. You can version it, improve it, and share it across teams. For us, that meant we could start small and iterate, just like we do with recipes!

The most Claude way to write a Claude Skill

In a very meta moment, we used Claude’s own “Create Skill” skill to help us get started writing an OpenRewrite recipe-writing skill. It gave us a structure, and we filled in the rest using guidance from the OpenRewrite docs, especially around when and how different types of recipes should be used.

That meant including information like:

  • Recipe types and when to use them (YAML, Refaster, imperative, scanning)
  • Examples and templates for each type
  • How to use common constructs like JavaTemplate, JavaIsoVisitor, and preconditions
  • Useful tips and safe patterns (e.g. use with methods instead of mutation)
  • What to test and testing conventions like using the //language=java directive

We tested the skill as we built it, refining the instructions whenever Claude misunderstood or ignored them.

Although Claude Skills are meant to be “model-invoked” (used automatically based on the prompt and the skill’s description), we found it more reliable to invoke it explicitly. So we bundled the skill into a plugin, and exposed it through a slash command: /create-recipe. That let us reliably trigger the right behavior, and made the plugin easy to share and install.

As one final step before publishing the skill, we ran it through superpowers-marketplace, a tool to analyze Claude Skills and generate suggestions for improvement. Some we followed, some we didn’t, but it helped to refine the description, structure, and a few of the Markdown sections.

Teaching Claude what already exists

The biggest issue we ran into (even before we had the skill actually) was Claude reinventing recipes that already existed. We called this out in the original blog post, and the problem continued even after adding clearer instructions.

We tried to address it by urging Claude to prefer declarative YAML recipes when possible and reuse existing building blocks. But Claude didn’t have enough visibility into what was already available. The Moderne CLI can easily export a list of recipes as a CSV, but OpenRewrite now has some 5,000+ recipes across dozens of categories, which is way too much for Claude’s context window, and too noisy to be useful anyway.

Our first attempt to solve this was to create a short reference list of 25–50 common OpenRewrite primitives. That helped in some cases, but ultimately wasn’t comprehensive enough.

So we went meta again and asked Claude’s skill-creating skill to help us curate a bigger list but still follow the progressive disclosure principle. We had it break the larger list into smaller categorized CSV files for each category (e.g. primitives, Java, Spring, YAML/config, etc.)

Due to context limits (a common theme here), it ended up actually writing some Python scripts to help it parse and organize the full catalog and create the categorized lists. We reviewed and fine-tuned the output together, eventually landing on a draft that seemed to strike a good balance. The lists looked broad enough to be helpful, but still narrow enough to be usable in context.

The skill directs Claude to consult the curated CSVs first when trying to build a declarative recipe. This small addition did seem to make a difference, unlocking a much more composable, context-aware workflow.

What’s next for the skill 

Of course, work like this is never really done. As we learn more about what works and where the gaps still are, we’ll continue refining the skill just like we do our recipes and docs. In fact, we decided to keep the Claude Skill in the same repo as our documentation so we can maintain and evolve it over time using the same workflows.

Here are a few areas we’re thinking of exploring next:

Expand and refine the curated lists

The categorized recipe CSVs seemed to be useful, but they’re just a starting point. We can continue to tune them for coverage and clarity, and add relevant recipes as new ones are released. We’re also exploring adding more information than just name and description to the CSVs, like specific details about recipe options.

Breaking up dense reference files

Early on, we thought about feeding Claude an llms.txt file, a giant export of our docs specifically intended for language models. But of course, it was too big to be useful, quickly exceeding Claude’s context limits. But it may be worth exploring how we could convert key documentation into smaller, topic-based Markdown files that Claude can selectively load as needed. This might allow us to not have to maintain separate Markdown files for the skill as well as our regular documentation.

Language-specific skills

As OpenRewrite expands into new ecosystems, we’ve begun developing a recipe-writing skill for JavaScript and TypeScript too. With full LST support now available for those languages, we’re applying many of the same patterns that worked for Java to front-end and Node.js code.

Filling in model gaps

Another benefit we’ve started thinking about is how skills can help fill in missing information. Since these models do have training cutoff dates (typically a 6 month lag or so), they don’t yet have new information released since then as part of their base knowledge. This skill gives us a way to patch in that missing information without having to wait for a new model version release to catch up.

One skill, many benefits

Claude Code is already a powerful tool for writing OpenRewrite recipes. But when paired with a well-crafted skill, it becomes even more effective.

This is how to build repeatable workflows for humans and AI alike. It turns out that what’s helpful for AI is also helpful for people: clear structure, reusable patterns, fast feedback, and just the right amount of information consumed as needed.

The skill isn’t just a shortcut, it’s a way to encode and scale what we’ve already learned.

Try the OpenRewrite recipe writing skill yourself

In accordance with our Privacy Policy, you may be contacted about Moderne or related products and services. You may unsubscribe from these communications at any time.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting.

Want to learn more about writing OpenRewrite recipes? Sign up for our next OpenRewrite authoring training course.