Do you also hate upgrading Angular versions? Because I do. I maintain a few open-source projects, and upgrading Angular is probably my least favorite maintenance task. That's also why my frontend updates often get postponed for far too long.
But we have AI now, right? It should be able to handle this with some instructions. So I decided to create (or rather vibe-code) an Angular Update Skill for Codex.
Creating the skill
Upgrading Angular isn't just about running ng update. There are several things I normally have to take care of, so I created a prompt describing what the skill should do:
- Follow the official Angular Update Guide.
- Create a separate Git branch for the upgrade.
- Handle migrations and dependency updates.
- Validate that everything still builds and works.
- Follow the same good practices I would use when upgrading Angular manually.
(Updating NuGet packages in .NET feels so much simpler.)
Codex generated the first version of the skill, and surprisingly, it worked!
Well... locally.
First problem: npm ci
After pushing my changes to GitHub, the CI pipeline failed with:
npm ci can only install packages when your package.json and package-lock.json are in sync.
Classic "works on my machine" problem. The skill had managed to update Angular, but it hadn't properly validated that a clean installation would work. So I added another validation step: run npm ci before considering the upgrade complete. This way, the agent can catch problems with the lock file before they reach CI.
Second problem: npm publishing
Then I ran into another issue when trying to publish my Angular library to npm:
npm error code E404
npm error 404 Not Found - PUT https://registry.npmjs.org/gramli-angular-mydatepicker - Not found
At first, the error wasn't particularly helpful. After some investigation, I found that my publishing environment was using Node.js 22 with npm 10.
However, according to the npm trusted publishing documentation, trusted publishing requires:
- Node.js 22.14.0 or higher
- npm 11.5.1 or higher
So I updated the skill again to prefer the latest Node.js LTS version compatible with the target Angular version, while also making sure the npm version meets any publishing requirements.
Third problem: the skill was getting too big
After all these improvements, the skill was becoming quite large. That might not matter much with generous token limits, but I also wanted it to be usable by people working with more limited AI budgets. So I shortened the instructions, removed unnecessary repetition, and kept the important validation steps. The main skill went from 1,252 words to 701 words, with the complete bundle becoming approximately 40% shorter.
Testing it on real projects
Of course, generating a skill is one thing. Actually using it is another. So far, I've used the current version on three of my open-source projects:
- Angular 21 → 22: angular-mydatepicker PR #12
- Angular 19 → 22: FileApi PR #13
- Angular 21 → 22: AuthApi PR #113
The Angular 19 → 22 upgrade was especially interesting because it required migrations across three major versions. In the AuthApi project, the upgrade also involved replacing PrimeNG with Optimus UI because of the PrimeNG licensing changes.
All three upgrades have now been merged.
Three Projects Later
The current version works pretty well, at least on my smaller projects. It's not perfect, though. Some Angular projects are much more complicated than mine, so the skill would probably need to be adapted for them. But it already helped me upgrade three projects, and I learned a few things along the way.
The best part? I finally updated my Angular projects in just ONE WEEK instead of postponing them again. 😁
I wanted to share this with the community because it might help someone else. If you want to try the skill or improve it, you can find it here:
Top comments (60)
The
npm cifailure is the part that makes this interesting. An AI agent can migrate Angular APIs correctly and still miss the contract between the lockfile, peer dependencies, and the publishing environment.For example, in a library migrating from Angular 17 to 18, updating
@angular/coreand@angular/compiler-cliisn't enough if@angular-devkit/build-angular, the TypeScript version, and the library'speerDependenciesstill target incompatible ranges. The app may compile locally because of an existingnode_modulestree, then fail in CI with a clean install or break consumers installing the published package. I'd make the skill validate those dependency constraints, runnpm cifrom a clean checkout, build the library in production mode, and test the packed tarball in a separate Angular consumer project. That last step catches problems a successful workspace build can easily miss.Good points. Actually, that first
npm cifailure is exactly why I added clean-install validation to the skill. It creates a fresh temporary copy withoutnode_modules, so it doesn't rely on existing dependencies.I also tested it on a published Angular library with its own demo application. The skill upgraded Angular, I tested the demo, and then published the updated library.
Testing the packed package in a separate consumer project makes sense for library release validation, but I'd say that's beyond the scope of a general Angular upgrade skill. 😅
That makes sense. Testing the demo app is a much better signal than just checking whether the library builds after the upgrade. One edge case I'd still watch for is Angular's partial-Ivy compatibility and peer dependency ranges. For example, a library can work perfectly in its own demo while its published
peerDependenciesaccidentally exclude an Angular version that should be supported, or while its packaging configuration omits a secondary entry point. Those are release-contract issues rather than upgrade failures, though, so I agree they don't necessarily belong in the core skill. Keeping the upgrade workflow focused and leaving deeper package-release checks as an optional step sounds like the right boundary.Yes, I agree, thanks for the detailed feedback and suggestions.
The part I'd steal is that each fix came from a real failure. The part I'd worry about is the trim from 1,252 to 701 words.
When I've cut agent instructions down, the line that goes first is usually the one that looks redundant but was there because of one specific bad day. Something like "run npm ci before calling it done" reads like filler six weeks later.
Do you keep the three failures (lockfile drift, the npm version for trusted publishing, the big migration jump) as a checklist the skill has to pass after every edit? Otherwise the next "make it shorter" pass might quietly delete one of them.
Good question. Actually, both frontend upgrades were done using the final, shorter version of the skill:
The library upgrade, angular-mydatepicker PR #12, was done before I shortened the instructions. That was actually the project where I originally built and refined the skill based on those failures.
So the shorter version has been tested on real projects, but you're right that this doesn't guarantee every original edge case is still covered. Keeping a regression checklist for future changes is actually a good idea.
That's a better test than my worry: two real upgrades on the short version. If a third one ever breaks, the regression checklist doubles as a record of what the trim dropped, which is the part I'd most want to see. Nice PRs.
The most valuable part of this workflow is that the skill improved after each real failure. I’d take that one step further by making the validation environment reproducible: pin the Node.js and npm versions, start from a clean checkout, and run the same checks locally and in CI. Otherwise, the agent may fix the symptom in one environment without identifying the underlying version mismatch. It could also record which checks passed and which remain unverified, so “upgrade complete” means more than a successful build. That turns the skill from a migration script into a repeatable maintenance process that can be trusted across projects.
Thanks for the ideas! That's actually how I approached it. The skill prefers the latest Node.js LTS compatible with the target Angular version and project requirements, rather than pinning a specific version for every project.
It also checks the CI configuration for the npm version, runs
npm ciin a fresh temporary directory withoutnode_modules, and reports which validation steps passed or couldn't be verified.Oh, this is something I should probably send to the team maintaining the Angular component library we're forced to use! 😂 Upgrading Angular itself is already a pain in the ass, but upgrading that library is a whole new level of nightmare! I swear, sometimes I think they assume nobody ever upgrades it, because they make changes like renaming (close) to (closeDialog) between versions, only to rename it back to (close) in the next one. 😂 So yeah, let them give it a try and burn some tokens! 😁
Nice,
(close)to(closeDialog)and then back to(close)? That sounds like pure evil! 😂😂😂So what you actually need is a separate skill for upgrading that specific library?! 🤣
Exactly! 😂 Every time we upgrade that library, we joke that they're doing it on purpose, just to make sure we'll have jobs for the rest of our lives! 🤣
Great post about agent skills! You are a great developer who succeeded in updating Angular using skills. 👍 I am using my handmade skills and keep updating it to write my AI Avatar README, but it always fails even though AI Avatar is already at v25. 🤣
Haha, the struggle of keeping AI skills up to date is real! 😂🚀 Turning a repetitive Angular upgrade into a one-week achievement is genuinely impressive. It’s fascinating how the right skills can transform AI from a coding assistant into a reliable workflow partner. Now I’m curious—what do you think made the biggest difference: the skill’s instructions, the workflow, or the way you guided the agent? 🤔👏
Thanks! I'd say the workflow, especially the validation steps. Clear instructions are important, but they don't guarantee the agent will get everything right. The first version looked promising, but then
npm cifailed in CI. That's when I realized the skill needed better validation.So I think the biggest difference came from testing it on real projects, finding what failed, and improving the skill along the way.
Thanks! 😁 Haha, sounds like your README skill is giving you more trouble than my Angular upgrades! 🤣
Haha, fair enough! 🤣 At least both teach us patience and keep us humble. Thanks for the fun discussion, and best of luck with your next upgrade! 😁
Great job!
🤣🤣
🤣🤣
Of course @sylwia-lask 😅
hahahahahahahha 😂😂😂
Okay, you were right. There's definitely at least one pro here! 😂😂
@gramli Fair - and I would narrow my claim: the skill should not enforce its own pins, but it can enforce the project's declared requirement. Read engines / .nvmrc / packageManager from the repo, check the running Node/npm against it as a preflight, and fail with "this project requires Node X, you have Y". No pin injection, but the constraint is read from the project and surfaced early. That was the actual point of engine-strict: it turns an opaque E404 from trusted publishing into a named, early failure - and the version mismatch stops being a supply-chain mystery.
Ah, I see what you mean now. The skill already checks the project's Node/npm requirements, but making version mismatches an explicit preflight failure with a clear error message is a good point.
Thanks for clarifying!
The interesting part is that the upgrade itself wasn’t the hardest problem. It was catching the things that only show up outside the local environment. Adding
npm cias a validation step seems like a small change, but it can save a lot of debugging later.One validation I'd add from bitter experience with
ng update: after the migration schematics run,git diff --statalone hides which schematics actually fired. I've had a schematic silently not apply because a version gate was missed, and the diff just looked 'fine' until runtime. I now make agents record the executed migrations (a small log on the upgrade branch works) so the reviewer sees 'which codemods ran', not just the resulting diff. Pairs well with your clean-install check — one verifies the environment, the other verifies the migration actually happened.Good point. The skill already tracks migration commands and milestones during the upgrade and includes migration evidence in the final report.
But you’re right, that’s not necessarily the same as recording exactly which schematics were executed. Having that information available for PR reviews could be really useful, especially when upgrading across multiple Angular versions.
Thanks for the suggestion!
making npm ci a hard gate before the agent can say done is the best move in here. most agent upgrade failures i have seen are the agent grading its own work on a dev server that is already warm. a clean install plus a production build in a fresh container catches lockfile drift, peer dep conflicts and node version mismatches in one shot.
the 1,252 to 701 word trim tracks with what we saw too, the long instructions were mostly hedging and the validation steps were the part that survived.
did the skill ever stall on the 19 to 22 jump, or did it step one major at a time?
For the 19 → 22 upgrade, I let the agent handle the process automatically. The skill is designed to upgrade one major version at a time, completing the required migrations and validation before advancing.
I didn't manually verify each intermediate version myself, though.
one major at a time with validation between each hop is the right shape. the failure i would watch for is a schematic that silently skips on hop two while the build stays green, so hop three inherits the gap. we log which migrations actually ran per hop so a reviewer can see it.
did the 19 to 22 run leave you a per hop record, or only the final report?
Some comments may only be visible to logged-in visitors. Sign in to view all comments.