---
title: Move a flat application to grouped services
description: Preview an optional source-only move, apply validated edits, and restore a guarded recovery receipt.
pagination: false
sidebar:
  icon: folder-input
---

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.

1. ## Preview before applying

    Run from the application root with installed dependencies:

    ```sh
    bun run relkit migrate layout
    bun run relkit --json migrate layout
    ```

    Preview 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.

2. ## 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.

    ```sh
    bun run relkit migrate layout --write
    ```

    Write 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:

```sh
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:

```sh
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.

{/* Generated by apps/docs/scripts/generate.ts. Do not edit. */}

**Reference and source**

- [`@relkit/services` API](/docs/api/services)
- [`@relkit/functions` API](/docs/api/functions)

- [`packages/cli/tests/migration/layout.probe.ts`](https://github.com/rel-kit/relkit/blob/main/packages/cli/tests/migration/layout.probe.ts)
