grpc-migrate
Automates gRPC service migrations across Personio's service estate.
Installation
claude plugin install grpc-migrate@personio-claude-code-marketplace
Once installed, invoke from any repository:
/grpc-migrate
The skill immediately asks which mode to run.
What does this plugin do?
Provides a full migration playbook for replacing deprecated gRPC service calls with their new versions — behind a feature flag, with tests for both flag states, and a draft PR as output.
What you need: gh CLI authenticated, ./gradlew available in the target repo, and a data-registry version that contains the target RPC.
Three modes:
| Mode | When to use |
|---|---|
migrate | Apply the full playbook to one repository — discovers call sites, plans and applies the migration, runs lint + tests + clean build + smoke test, opens a draft PR |
update tracker | Refresh an existing tracker after a batch of PRs land — checks merged PRs, newly self-migrated repos, and resolves placeholder feature flag names from open PR diffs |
discover | Search Personio-Internal org-wide for all consumers of a deprecated service and write a migration tracker .md file |
Why would you want this?
- Deprecating a proto service used by 10+ repositories? Run
discoveronce to produce a tracker, thenmigrateeach repo in turn — the playbook handles the full cycle end to end. - Each migration is feature-flagged with tests for both the flag-off and flag-on paths. The skill audits each call site for error handling, retry logic, logging, and response mapping to make sure nothing is silently dropped.
update trackerkeeps your migration status doc current without re-running the full playbook.
Mode: migrate
With a tracker (most common)
Once you have a tracker from a discover run, point the skill to it and pick the next pending repo by number:
/grpc-migrate
→ migrate
→ company/COMPANY-GRPC-MIGRATION-TRACKER.md
→ 3 # pick repo #3 from the pending list
→ ~/dev # where your local clones live
→ 1.0.20260313093041 # data-registry version with the target RPC
→ ORG-3671 # JIRA ticket
→ no # no known breaking changes
→ WAC-5012-company-grpc-v2-migration # feature flag name
The skill reads the deprecated service(s) and target service from the tracker header — no need to type them. It then:
- Pulls the latest default branch of the target repo
- Discovers all call sites for the deprecated service(s) and identifies which methods are called
- Audits each call site for error handling, retry logic, logging, and response mapping to carry forward
- Reads the target API, determines field mask requirements, and presents a migration plan for approval
- Applies the changes behind the feature flag (tests both flag-off and flag-on paths)
- Runs
compileKotlin→test→ktlintCheck→clean build→ smoke test - Opens a draft PR with a full description: changed call sites, field mask rationale, reviewer checklist
- Updates the tracker row to
👀 In review
Without a tracker
If no tracker exists yet, provide the deprecated and target services manually:
/grpc-migrate
→ migrate
→ no # no tracker
→ workflow-platform # repo name
→ ~/dev
→ 1.0.20260313093041
→ personio.proto.entity.core.company.api.v1.CompanyService # deprecated (can be multiple)
→ personio.proto.entity.core.company.api.v1alpha1.CompanyService # second deprecated service
→ personio.proto.core_hr.company.api.v1.CompanyService # target service
→ ORG-3671
→ no
→ WAC-5012-company-grpc-v2-migration
The skill discovers which specific methods are called at each site and infers READ vs. WRITE from method names — no need to specify these.
Placeholder feature flag names
If the owning team hasn't created the cleanup ticket yet, use any placeholder:
→ PLACE-HOLD-TBD
The flag name is defined as a single const val, so renaming later is a one-line change. The PR checklist will include a reminder to create the cleanup ticket before merging.
Mode: update tracker
Refreshes a tracker without running full migrations. Run this periodically to keep the tracker current after a batch of PRs land.
/grpc-migrate
→ update tracker
→ company/COMPANY-GRPC-MIGRATION-TRACKER.md
The skill:
- Checks each
👀 In reviewPR — marks merged ones as✅ Migrated (behind flag, cleanup pending) - Checks each
⏳ Pendingrepo viagh search code— if the target stub is found alongside the deprecated stub, investigates open/merged PRs and updates the status - For any row with a placeholder feature flag, reads the open PR's diff and description to find the real
const valname and updates the tracker automatically - Rewrites the tracker and prints a summary
Sample summary
Tracker updated:
- 2 PRs marked as merged: workflow-platform, surveys-service
- 1 pending repo found to have an open PR (→ 👀 In review): attendance-service
- 1 feature flag placeholder resolved from PR diff: workflow-platform (WAC-5012-company-grpc-v2-migration)
- 11 repos still pending
- 2 rows unchanged
- ⚠️ Placeholder feature flag names not yet resolved: compensation-service (PLACE-HOLD-TBD)
Mode: discover
Searches the Personio-Internal org for all services still calling a deprecated gRPC service and writes a migration tracker.
Creating a new tracker
/grpc-migrate
→ discover
→ no # no existing tracker
→ personio.proto.entity.core.company.api.v1.CompanyService # deprecated (can be multiple)
→ personio.proto.entity.core.company.api.v1alpha1.CompanyService
→ company/COMPANY-GRPC-MIGRATION-TRACKER.md # where to save
The skill runs gh search code for CompanyServiceGrpc and CompanyServiceGrpcKt across the org, cross-checks which repos also have the target stub already (already-migrated or in-progress), and writes a fully-populated tracker:
| Repository | Deprecated RPC(s) | Target RPC | Jira | Migration PR | PR Status | Feature Flag | Flag Status |
|---|---|---|---|---|---|---|---|
| [workflow-platform](…) | `v1.CompanyService` | `core_hr.v1.CompanyService` | — | — | ⏳ Pending | — | — |
| [surveys-service](…) | `v1.CompanyService` | `core_hr.v1.CompanyService` | — | [#268](…) | 👀 In review | — | 0% rollout |
Updating an existing tracker with newly-found consumers
Point discover at an existing tracker — it skips repos already listed and appends only new ones:
/grpc-migrate
→ discover
→ company/COMPANY-GRPC-MIGRATION-TRACKER.md # existing tracker
→ personio.proto.entity.core.company.api.v1.CompanyService
Tips
- Always let the skill open PRs as drafts. Do not mark ready until the owning team has reviewed and tested.
- The skill will not touch gRPC service implementations (
@GrpcServiceclasses). Only call sites are migrated — server-side handlers are permanently excluded. - New stubs always reuse the same
@GrpcClientchannel as the deprecated stub they replace. Introducing a separate channel to the same host is wrong even if another channel happens to resolve there. - Run
update trackerafter a batch of migrations rather than re-runningdiscover— it's faster and won't duplicate rows. - Extracted shared logic: if both the flag-off and flag-on paths share response mapping or auth setup, the skill extracts it into a private helper rather than duplicating it in both branches.