Slash commands — `/plan` `/sync-api` `/review` `/ship`
The workspace root's .claude/commands/ holds four slash commands. This note covers the operational flow of why each one was created and when it gets used.
.claude/commands/
├── plan.md # cross-directory implementation plan
├── sync-api.md # BFF ↔ mobile shared API contract consistency check
├── review.md # change review (per-directory dispatch)
└── ship.md # release gate (full build/test + consistency)
The flow sits naturally on a single line:
design → implement → contract check → review → ship
/plan (bff-dev/kmp-dev) /sync-api /review /ship
/plan <feature> — design from the BFF first
When cross-directory work comes in — e.g. "add an admin grant button that surfaces the new credit balance in the mobile user menu" — designing BFF, shared, and cmp simultaneously in a single agent's head always leaves one side underbaked. So the command forces six explicit phases:
- Impact scope (BFF route? shared DTO? cmp UI? iOS adapter?)
- Design from the BFF first — the BFF is the contract's source of truth
- Map mobile shared changes (
commonMainfirst → expect/actual only where required) - Map mobile cmp UI changes (domain calls go only through
:shared) - Verification gates (per-directory build/test +
/sync-api) - Risk check (BFF compatibility, Windows paths, signed URLs, BFF_BASE_URL env)
The command's value: details like BFF route signatures / @SerialName policy / mobile BuildConfig env vars get raised in the same slot, in the same phrasing, across every plan. The cost of asking the same item differently each time disappears.
/sync-api — BFF ↔ mobile contract consistency
The BFF's routes/DTOs and mobile shared's BffApi/DTOs aren't linked at compile time — the two directories have separate gradle builds, so when a BFF DTO changes, mobile only finds out at runtime.
/sync-api is the verification command that bridges that gap. It cross-checks five items:
- Endpoint coverage — BFF's
/api/v2/*lines up 1:1 with mobileBffApimethods - DTO field consistency —
@SerialName, types, nullability - Multipart part names — keys like
video_0/bgm_0/file/spec/config/inputIdmatch character for character - HTTP status codes — BFF
ErrorHandlingmapping ↔ mobileexpectSuccess = trueResponseExceptionhandling - Domain interface consistency —
AudioSeparationRepositoryand friends correspond logically to BFF endpoints
When to run it:
- Before merging a BFF PR (the enforcement point for the "BFF is source of truth" policy)
- Verification gate 5 in
/plan - Item 4 in
/ship
Why this is needed: after a case where mobile build passed + BFF build passed → real-device integration surfaced a runtime error like Field 'foo_id' is required, but it was missing. Gaps not caught at build time have to be hoisted into an explicit verification step.
/review — per-directory dispatch
Review itself has different angles per directory — BFF prioritizes security/efficiency/error mapping, KMP/CMP prioritizes commonMain pollution, expect/actual consistency, and JVM-only library leakage.
So /review doesn't inspect directly — it looks at the change scope and dispatches to the per-directory review skill:
vibi-bffchanges:vibi-bff/.claude/skills/review.md(4 angles + severity labels)vibi-mobilechanges: BFF checklist with KMP angles added- Changes in both: the above two + cross-API contract check (including a
/sync-apicall)
/review's value: it auto-invokes the right checklist based on directory location — a human doesn't have to judge "this PR is BFF-only, so focus on security" / "this one touches mobile too, so also expect/actual" every time.
/ship — release gate
Bundles the build command + tests + /sync-api consistency into one pass. Five phases:
vibi-bff—./gradlew test+compileKotlin+ env verificationvibi-mobile (:shared)—:shared:testDebugUnitTest+:shared:build+ iOS framework linkvibi-mobile (:cmp)—:cmp:assembleDebug+ iOS simulator build- Cross API contract —
/sync-apimismatches at 0 - Risk check —
BFF_BASE_URLproduction address, iOSInfo.plistpermissions, Android permissions, etc.
/ship itself doesn't run the builds — per the in-memory policy (operating-rules.md), gradle/xcodebuild/simctl auto-execution is disallowed. The user takes the command, a human triggers it, and Claude grades the output against the checklist.
What the commands have in common
- They all end with a checklist + output format. If the output is free-form, every run looks different and can't be compared.
- One command calls another —
/shipcalls/sync-api, and/reviewcalls/sync-apiwhen needed. The commands are small building blocks. - The "BFF is source of truth" policy is the baseline running through all of them.
Related reading
agents.md— the two subagents the commands dispatch toskills.md— the smaller unit invoked from inside commands (e.g. per-directory review skill)- Workspace
CLAUDE.md§ "Root slash commands" — the one-line catalog of the same four commands