Move a flat application to grouped services
Preview an optional source-only move, apply validated edits, and restore a guarded recovery receipt.
Move to the grouped src/services/<name>/service.ts layout when it helps organize an existing application. New applications use
src/services/<name>/service.ts; relkit add preserves an existing app’s detected layout.
Migration is optional and does not change service APIs, logical IDs, provider profiles, or task versions.
Preview before applying
Run from the application root with installed dependencies:
bun run relkit migrate layout
bun run relkit --json migrate layoutPreview inventories complete service roots, including helpers and assets, and reports exact moves, syntax-aware rewrites, conflicts, and manual-action references. It leaves source, lockfiles, generated output, database migration history, credentials, runtime state, and observability unchanged. An already grouped app has no moves.
Static imports, re-exports, type-only imports, and literal dynamic imports use the effective TypeScript configuration and resolved target. Supported literal paths in tests, Drizzle configuration, package/operational scripts, code-generation configuration, Markdown code spans/links, and local agent guidance are planned explicitly. Comments and unrelated data strings remain intact. Ambiguous prose, interpolated paths, and computed affected references require manual review before write.
Apply a checked candidate
Stop this application’s development session and external watchers. Resolve occupied destinations, mixed/duplicate/nested service boundaries, case collisions, symlinks, and touched tracked changes. Unrelated dirty files and inventoried untracked service contents remain preserved.
bun run relkit migrate layout --writeWrite uses separate owned staging directories with the installed dependency identity. Baseline and candidate must pass check and typecheck; logical graph and offline deployment comparisons must retain IDs, ownership, contracts, exposure, policies, bindings, and resources before publication. Missing validation is a refusal, not a compatibility pass. The operation does not install packages, run SQL migrations or seeds, acquire providers, provision cloud infrastructure, or edit global skills.
Publication is coordinated across files. The restricted local receipt retains before/after bytes,
permissions, and created-directory ownership for interruption or crash recovery; it does not promise
cross-file atomicity. Keep the returned .relkit/migrations/<id>/receipt.json private. Failure recovery
restores only matching transaction-owned states and preserves later edits.
Roll back with the exact receipt
Use the path returned by the write result:
bun run relkit migrate layout --rollback .relkit/migrations/RECEIPT_ID/receipt.json
Rollback rejects foreign, redirected, tampered, or permissive receipts. Later edits and occupied original locations are conflicts; it refuses to overwrite them. Inspect a retained recovery-required receipt and resolve its reported conflict before retrying. Never delete runtime state or migration history to force a rollback.
After migration or restoration, prepare a fresh development cohort:
bun run check
bun run typecheck
bun run relkit dev --prepare
bun run dev
Verify actual public responses and authorization before accepting the new cohort. Graph/build hashes and source links can change; that physical provenance is distinct from the stable logical contracts. Accepted jobs and agent threads can remain pinned to immutable older executable cohorts, so retain their owned artifacts and test native recovery before claiming source-move continuity. Stable IDs alone do not prove a provider can resume incompatible or unavailable historical executables.
CLI statuses are 0 for successful preview/write/no-op/rollback, 1 for operational refusal,
2 for usage errors, and 130 for migration cancellation. JSON stdout contains one secret-safe result;
diagnostic logging uses stderr.