
Migrate
- 16 installs
- 293 repo stars
- Updated August 4, 2026
- sap/fundamental-ngx
Helps with ai & agent building tasks.
About
migrate is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.
- migrate
- AI & Agent Building
- AI-coding skill
Migrate by the numbers
- 16 all-time installs (skills.sh)
- +3 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #11,068 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/sap/fundamental-ngx --skill migrateAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 16 |
|---|---|
| repo stars | ★ 293 |
| Last updated | August 4, 2026 |
| Repository | sap/fundamental-ngx ↗ |
What it does
Helps with ai & agent building tasks.
Files
Angular 21+ Migration: $ARGUMENTS
If $ARGUMENTS is empty, ask the user for a component path or folder before proceeding.
Phase 1: Analyze
Read all files in the target path. For each component, directive, or service, scan for migration items below. If a folder is given, process all .ts and .html files within it.
What to migrate
Inputs / Outputs / Models:
@Input()→input()orinput.required()@Input()with setter →input()+linkedSignal()(preferred) oreffect()(only for DOM side effects)@Input()+@Output()pair (e.g.value/valueChange) →model()@Output()→output()- Boolean inputs: add
{ transform: booleanAttribute } - Number inputs: add
{ transform: numberAttribute }
Host bindings:
@HostBinding('class.x')→host: { '[class.x]': 'expr()' }@HostBinding('attr.x')→host: { '[attr.x]': 'expr()' }@HostBinding('style.x')→host: { '[style.x]': 'expr()' }@HostListener('event')→host: { '(event)': 'handler($event)' }
Queries:
@ViewChild()→viewChild()orviewChild.required()@ViewChildren()→viewChildren()@ContentChild()→contentChild()@ContentChildren()→contentChildren()
Template syntax:
*ngIf→@if*ngFor→@for(requirestrackexpression)*ngSwitch/*ngSwitchCase→@switch/@case
State management:
BehaviorSubjectused for local component state →signal()BehaviorSubject+combineLatest→computed()Subject<void>used only to trigger side effects →effect()effect()that only callssignal.set()for derived state →computed()orlinkedSignal- Redundant
markForCheck()after signal updates → remove - Object/array mutation in place +
signal.set()with same ref → immutable update withsignal.update()
CSS class building:
CssClassBuilder+@applyCssClass→computed()returning class string +host: { '[class]': '_cssClass()' }
Cleanup patterns:
- Custom
DestroyedService→DestroyRef+takeUntilDestroyed() ngOnDestroyonly fordestroy$.next()→ remove entirely after migration
Decorator cleanup:
- Remove
standalone: true(default since Angular 19) - Remove
allowSignalWritesoption ineffect()(the option no longer exists)
Imports:
- Deprecated
*Moduleclasses → individual component/directive imports
Member ordering (ESLint enforced):
1. Decorated properties (any remaining @Input, @Output, @ViewChild) 2. Signal inputs/outputs (input(), output(), model()) 3. Public → Protected → Private fields 4. Constructor 5. Public → Protected → Private methods
What NOT to migrate
Do NOT convert these — they should stay as-is:
- RxJS for async operations: HTTP calls, WebSocket streams, timers, interval-based logic → keep as Observable
- BehaviorSubject with complex operators:
switchMap,debounceTime,distinctUntilChanged,combineLatestwith async sources → keep as RxJS - Plain properties with no reactive consumer: If nothing in template, host binding, computed, or effect reads it → keep as plain property, do not wrap in
signal() - Signals for internal bookkeeping: One-time flags, cached DOM measurements, counters with no reactive consumer → use plain property
Migration is optional for existing code
The migration targets are recommendations, not mandatory fixes. Present all findings but let the user decide scope. Existing @Input() / @Output() decorators are valid — only migrate them if the user wants to or if the code is being substantially reworked.
Phase 2: Present Plan
Output a structured migration plan:
## Migration Plan: [component name]
### Files affected
- path/to/component.ts
- path/to/component.html
- path/to/component.spec.ts
### Inputs / Outputs
| Current | Migration | Notes |
|---------|-----------|-------|
| `@Input() label: string` | `readonly label = input<string>('')` | |
| `@Input() disabled: boolean` | `readonly disabled = input(false, { transform: booleanAttribute })` | |
| `@Input() value` + `@Output() valueChange` | `readonly value = model<T>()` | Two-way binding |
### Host Bindings
| Current | Migration |
|---------|-----------|
| `@HostBinding('class.is-open')` | `host: { '[class.is-open]': 'isOpen()' }` |
### Template Changes
| Current | Migration |
|---------|-----------|
| `*ngIf="condition"` | `@if (condition) { ... }` |
| `*ngFor="let item of items"` | `@for (item of items; track item.id) { ... }` |
### State Management
| Current | Migration | Reason |
|---------|-----------|--------|
| `BehaviorSubject<boolean>` | `signal(false)` | Local state, no async consumers |
### Skipped (intentionally not migrated)
| Item | Reason |
|------|--------|
| `httpData$` Observable | Async HTTP stream |
### Test Updates
- [ ] Replace `component.input = value` with `fixture.componentRef.setInput('input', value)`
- [ ] Update module imports to individual components
- [ ] Verify existing tests still pass after migration
### Docs Updates
- [ ] Update examples if public API changed (input names, usage patterns)
- [ ] Ensure examples use individual imports, not deprecated modules
### Breaking Changes
- [ ] List any renamed/removed inputs or outputs
- [ ] Draft BREAKING CHANGE footer if neededStop here and wait for approval before proceeding.
Phase 3: Execute
After approval:
1. Apply all migrations from the approved plan 2. Format code: yarn format 3. Run build: nx run <library>:build 4. Run lint: nx run <library>:lint 5. Run tests: nx run <library>:test --testfile=<spec-file> --skip-nx-cache 6. Report results and any issues