Revisiting AI Agents
It's been six months, how much could have changed?
Well, I'm back. AI has gotten better at coding since I last posted in September. Like, markedly better. Like scarily better. Like it's no longer a question of if AI can write an app from scratch, but more of why on Earth are we even bothering to type things with our human hands anymore?

[prompt: A pair of realistic looking unbroken hands]
As a human with hands (currently unbroken at time of writing), this concerns me. News like Block getting rid of 40% of their workforce because of AI really concerns unemployed me. It feels like those in the tech industry who don't start trying to ride the AI wave are going to be crushed by it. So, uh, guess it's time to grab my surfboard and start paddling. ππΌββοΈ
The Initial Problem Statement
I have my AIPackingList app and I'm going to maintain the same boundaries as before - me no write code. My goal at the end of this is to implement a new feature that should require some restructuring of the existing code.
One big change between this and the last two segments is that I'll be utilizing Claude from Anthropic instead of Gemini from Google. The main motivation for this change is my husband offering to pay for the Pro version of Claude so I can really explore the depths of this AI rabbit hole without having to worry about immediately running out of tokens (please don't explain the concept of shared finances to me, it's a joke). I used Claude to rewrite the website that this post is hosted on and it went really well, so I am optimistic about this experiment.
Claude currently has a beta plugin for Android Studio / Jetbrains that appears to pretty much be a wrapper around its Claude Code terminal offering. I installed this, but ended up just using Claude Code in the terminal as they seemed functionally similar.
To begin with, I turned on Claude Code's "Plan Mode", which essentially turns the assistant into a read-only assessment mode, where you can consult it about a given codebase or ask it to develop a multi-step plan where you can then edit individual steps.
This was my initial prompt, which describes the new feature to add to the packing list app - templatization!
I want to add the ability to create a new list from a template. I'd like the app to have several templates available for packing lists for different vacations (ski trip, beach trip, weekend away, etc). The user should be able to add or remove items from these templates and save them for future use. These templates should be separate than the actual lists, which the user can add items to without altering whatever template it was based on.
Read the full AI response
β 2 Explore agents finished (ctrl+o to expand)
ββ Explore UI screens and navigation Β· 11 tool uses Β· 14.4k tokens
β βΏ Β Done
ββ Explore ViewModel and data persistence Β· 6 tool uses Β· 13.7k tokens
βΏ Β DoneReady to code?
Here is Claude's plan: βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ Plan: Packing List Templates
Context
Users want to create packing lists from pre-defined templates (ski trip, beach trip, etc.) rather than always starting from scratch. Templates are a separate concept from lists β editing a template does not affect lists that were created from it, and creating a list from a template copies the items rather than linking to them. Users can also edit templates (add/remove items, rename) and create their own templates.
Data Model Changes
New file: TemplateItem.kt
@Serializabledata class TemplateItem(val id: Int, val text: String)New file: PackingListTemplate.kt
@Serializabledata class PackingListTemplate(val id: Int,val name: String,val items: List<TemplateItem> = emptyList()> )Modify UserPreferences.kt β add to data class:
val templates: List<PackingListTemplate> = emptyList()(No ID counter needed β use max+1 approach consistent with addNewPackingList())Navigation Changes
Modify Screen.kt β add two new screens to the sealed class and update Saver:
object TemplatesScreen : Screen()- data class TemplateDetailScreen(val templateId: Int) : Screen()Add TYPE_TEMPLATES and TYPE_TEMPLATE_DETAIL constants and handle them in the Saver save/restore lambdas, following the existing TYPE_ITEMS pattern exactly.
ViewModel Changes (PackingListViewModel.kt)
Add a companion object with hardcoded default templates:
companion object {
val DEFAULT_TEMPLATES = listOf(
PackingListTemplate(id = 1, name = "Beach Trip", items = listOf(...)),
PackingListTemplate(id = 2, name = "Ski Trip", items = listOf(...)),
PackingListTemplate(id = 3, name = "Weekend Away", items = listOf(...)),
PackingListTemplate(id = 4, name = "City Break", items = listOf(...)),
)
}Add init block to seed defaults on first launch:
init {
viewModelScope.launch {
dataStore.updateData { prefs ->
if (prefs.templates.isEmpty()) prefs.copy(templates = DEFAULT_TEMPLATES) else
prefs
}
}
}New functions:
- addNewTemplate() β max id + 1, default name, empty items
- renameTemplate(templateId: Int, newName: String)
- updateItemsForTemplate(templateId: Int, items: List<TemplateItem>)
- deleteTemplate(templateId: Int)
- createListFromTemplate(templateId: Int) β finds template, copies items as SelectableItem (id preserved, isSelected = false), creates new PackingList via same logic as addNewListAndUpdateIds, returns new list id via callback or StateFlow event
- generateNewTemplateItemId(template: PackingListTemplate): Int β same max+1 pattern as generateNewItemId
For createListFromTemplate, since the ViewModel can't return a value from a launch block, use a SharedFlow<Int> named newListCreatedEvent that emits the new list's ID. PackingListApp collects this in a LaunchedEffect and navigates to ItemsScreen.
New UI Files
TemplatesScreen.kt β mirrors AllPackingListsScreen:
- TopAppBar titled "Templates" with back navigation
- FAB to add a new blank template
- LazyColumn of TemplateCard items
- Empty state message
TemplateCard.kt β mirrors PackingListCard:
- Displays template name (editable in-place with Edit/Done/Cancel)
- Shows item count ("X items")
- Tap β navigate to TemplateDetailScreen
- "Use" OutlinedButton on card β calls onUseTemplate(templateId)
TemplateDetailScreen.kt β mirrors SelectableListScreen but simpler:
- No checkboxes, no sorting, no isSelected state
- Editable title in TopAppBar
- LazyColumn of TemplateItemRow items (text + delete button)
- NewItemInputRow at bottom (reuse existing component)
- Back button
TemplateItemRow.kt β simple row with item text and a delete icon, no checkbox
MainActivity.kt Changes
In PackingListApp:
- Collect viewModel.newListCreatedEvent in a LaunchedEffect to navigate to ItemsScreen after template-based creation
- Add handlers: onNavigateToTemplates, onAddNewTemplate, onRenameTemplate, onDeleteTemplate, onUseTemplate, onUpdateTemplateItems
- Expand the when (screen) block to handle TemplatesScreen and TemplateDetailScreen
- Add BackHandler for both new screens
AllPackingListsScreen.kt Changes
Add a "Templates" IconButton (using Icons.Filled.List or similar) to the TopAppBar actions, with an onNavigateToTemplates: () -> Unit parameter. The existing FAB is unchanged.
Verification
- Run unit tests: ./gradlew test β existing tests should still pass
- Add unit tests for new ViewModel functions in PackingListViewModelTest.kt:
- Default templates are seeded when templates list is empty
- addNewTemplate adds a template
- renameTemplate renames correctly
- updateItemsForTemplate updates only the target template
- deleteTemplate removes the template
- createListFromTemplate creates a list with copied items and emits the new list ID
- Manual test flow:
- Tap Templates icon β see 4 built-in templates
- Tap a template β edit its items, rename it
- Tap "Use" on a template β new list created with copied items, navigated to item screen
- Verify editing the new list does not change the template
- Add a custom template via FAB βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Claude has written up a plan and is ready to execute. Would you like to proceed?
β― 1. Yes, clear context (21% used) and auto-accept edits
- Yes, auto-accept edits
- Yes, manually approve edits
- Type here to tell Claude what to change
I love plan mode, at least just based on this initial usage. I can dig into the technical details or just skim them and accept edits to the code. This is very similar to shepherding a smart junior engineer - letting them run with it, but still checking that they're on the right track. I also love that it is just going to write unit tests without any additional prompting.
My only question now is can I change the default "auto-accept edits" prompt to "just send it".

Anyway, I let it spin for a bit and eventually it spit out the following:
β Build successful, no warnings. Here's a summary of everything that was implemented:
New files:
- TemplateItem.kt β data class for template items (id + text, no checked state)
- PackingListTemplate.kt β data class for templates
- TemplateItemRow.kt β simple item row with delete button, no checkbox
- TemplateCard.kt β card with in-place rename, item count, and "Use this template" button
- TemplatesScreen.kt β list of all templates with FAB to add new ones
- TemplateDetailScreen.kt β edit a template's name and items
Modified files:
- UserPreferences.kt β added templates field
- Screen.kt β added TemplatesScreen and TemplateDetailScreen screens + Saver support
- PackingListViewModel.kt β added init block to seed 4 default templates (Beach Trip, Ski Trip, Weekend Away, City Break), newListCreatedEvent SharedFlow, and 6 new template functions
- AllPackingListsScreen.kt β added Templates icon button in the top app bar
- MainActivity.kt β wired up all new screens and handlers
UX flow: Tap the list icon in the top bar β browse/edit templates β tap "Use this template" to create a new list with copied items β navigated directly to the new list. The original template is untouched.
β» Cooked for 7m 17s
This is like... really good. It took care of the templating use cases and copying everything and... like the only thing I would want to add (maybe) is being able to delete a template? But honestly it took what would have taken me a bit to implement and verify and I probably would have missed a use case and just did it in 7m 17s. And you can turn on auto-accept so you can truly, truly let AI yolo you an app.
I kind of don't know where to go from here. This is the basic functionality I wanted when I set out with this app idea in my head. It's just... done - I just spoke a feature into existence in less time than it takes me to walk to a coffee shop and get a latte.
Cue the Existential Dread
Writing this conclusion has involved a lot of moodily staring out the window into the glum Seattle "spring". I set out in July asking if my job was obsolete as a tongue-in-cheek joke, and now I'm asking that as a serious question.
It's insane how well this technology has progressed from September, when I struggled to get agentic AI to write unit tests - let alone making reasonable code, making and verifying a plan, executing, test writing, and doing all that with minimal input from myself, a human-in-the-loop. I don't even have to copy/paste anything, besides the original prompt. And $20/month is significantly cheaper than my previous salary. It's hard to come out of this experiment and feel good about the future of humans in software engineering.
Granted, there's a lot more that goes into engineering than just typing a prompt into a terminal, especially when dealing with significantly large and complicated systems that hold more private data than a packing list. But for this example it was significantly easier to just make an AI do it than to contribute anything of note myself. I'd also argue that the spark of creativity - the idea to write the app is still firmly in the court of the human entity. But does that just make us all PMs to the robot underlings?
I don't know. My cat was pretty happy with it though, as he could sit in my lap and I could use my hands to pet him for seven minutes instead of typing for hours. I'd feel a lot better about it if I could earn money for taking care of my cat versus writing and designing code.

I think at this point this initial series of experiments can be called complete. I'm still going to be working on this, as this is still really only scratching the surface of AI in software engineering. But I think the question of "can AI code well enough to write features" has been answered.
Yes. Yes, it can.