Matthew J. Clemente

Using Claude Code To Update claude-cfml (For the First Time)

Sep 24, 2025
5 minutes

A couple of weeks ago I put together a CFMl wrapper for the Claude API and blogged about it. Shortly thereafter, I got an email from Anthropic that the model I used was going to be deprecated in a month or so.

Here's what it said:

We're reaching out because you recently used Claude Sonnet 3.5 v2 (claude-3-5-sonnet-20241022).

Starting October 22, 2025 at 9AM PT, Anthropic is retiring and will no longer support Claude Sonnet 3.5 v2 (claude-3-5-sonnet-20241022). You must upgrade to a newer, supported model by this date to avoid service interruption.

The email concluded with a recommendation that I use Claude Sonnet 4 🤦‍♂️

Well, I guess that should have been obvious, but I had trusted Claude Code to generate the API wrapper, and apparently it had used a pretty dated list of models, which I didn't check.

I'm actually glad this happened. The goal of this experiment was to go all-in on LLM/AI generated code and to see what would happen. The code generation capabilities are impressive, but "gotchas" like this also seem to be an inherent part of the process.

The Goal

This prompted my first update to the project - I needed it to use an updated/current list of Claude models. Because the Claude API provides an endpoint to list available models, I decided step 1 would be to add support for that endpoint to the API wrapper. Then, I could use the information returned by the API to replace the out-dated model list that Claude Code had generated.

As with the initial work on this project, I'm letting Claude Code do all of the coding.

The Prompts

Prompt 1

The Claude API has an endpoing for listing models (documented here: https://docs.claude.com/en/api/models-list). I'd like this API wrapper to support that endpoint.

Claude Code fetched the documentation that I linked to and then generated a function, listModels to return the data from the endpoint. It also added a button to test this functionality to our index.cfm.

Unfortunately, it decided that because this endpoint needed GET request, and the existing functions required POST requests, the wrapper would need separate functions for making and processing HTTP GET requests (named makeGetRequest and processGetResponse). That's a bunch of duplicate code for a different HTTP verb. Time to refactor.

Prompt 2

Ok - it's redundant to have separate functions for making GET requests and handling GET responses. All HTTP requests and responses should be abstracted and handled via the same functions, with the method just being one of the arguments, if needed.

This refactor went well, with the handling of all HTTP requests and responses, regardless of method, getting abstracted via two methods.

I hopped over the to the index.cfm testing page to see what models would get returned from the request... only to find that the form would not submit.

Prompt 3

When I try to click the button to list the models, I can't, because the message field is required.

Claude Code "fixed" this issue by removing the "required" attribute on the textarea and implementing a JavaScript check to make sure the field was filled out if the prompt was being sent to the Claude API. I don't particularly like the approach being taken on this form, but it "works", so I'm not going to spend time trying to adjust it. I was able to make the request to list available Claude models. With this information, it was time to update the wrapper.

Prompt 4

Based on the response from that endpoint, it looks like claude-3-sonnet-20240229 is no longer supported. There are also new models using Claude 3.7 and 4. Can you make sure the getModels function has an accurate and up-to-date list of models?

In this prompt, I didn't want to tell Claude Code the models it should use. I wanted to see if it could get them on its own.

In the refactor, Claude Code refactored the getModels function delegate to the the listModels function, and then fall back to a hardcoded list if the API call failed. I didn't like this approach.

Prompt 5

I think having getModels and listModels functions is confusing for folks who might want to use this wrapper. Let's just stick with listModels. No need for the fallback to hardcoded values.

This refactor in the wrapper worked smoothly. I then noticed that on the testing page, the list of models was still hardcoded.

Prompt 6

On the index page, let's just use the listModels method, rather than hardcoding there. And let's default the wrapper to claude-sonnet-4-20250514.

The approach Claude Code took for outputing the select list was... verbose. Because this page is just a playground for testing, I decided to leave it, because it works.

At this point, the goal of this update/refactor is done - our model list is up-to-date and we have a function for listing available models.

Prompt 7

Alright - can you document the changes we've made in version control, and the give the project a minor version bump?

Claude Code took a strange approach here and decided it was going to create a "version" file in the root. I decided to stop and correct it.

Prompt 7 (correction 1)

No need for a version file. Just use git tags for versioning right now.

As has been Claude Code's habit, the commit message it generated was very long. I definitely need to provide some more guidance on this in my CLAUDE.md file. For now, I just corrected it again.

Prompt 7 (correction 2)

Please make your commit message succinct. Focus on the absolute essentials of what has changed.

With this final correction, the commit message and git tags were done.

Prompt 8

Please push the tag and commit to the remote repository.

This final prompt was handled smoothly, and the project update was completed. You can see the code at this point here: claude-cfml v1.1.0.

Next Steps

On my list for future improvements is packaging the project for ForgeBox and adding automated testing with Testbox.