---
name: gite2e-repository-migration
description: Migrate a GitHub or GitLab repository into a same-named GitE2E repository through the GitE2E MCP endpoint. Use when importing, mirroring, or moving repository history into GitE2E, especially when history may contain files over 10 MiB, Git LFS objects, models, videos, archives, JARs, or other binary artifacts that must be rewritten and uploaded as encrypted GitE2E LFS objects.
---

# GitE2E Repository Migration

Migrate the complete repository on a trusted client. Use MCP only to create and inspect GitE2E metadata; never expose provider plaintext, credentials, repository contents, encryption keys, or decrypted LFS payloads to the GitE2E server.

## Preserve These Invariants

- Keep the GitHub or GitLab repository unchanged. Work from a disposable local mirror.
- Keep provider credentials in the trusted client's credential helper or environment. Never put credentials in a URL, MCP argument, command transcript, migration report, or committed file.
- Create the destination with exactly the source repository name unless the user explicitly requests a different name.
- Push only an encrypted Git graph and encrypted LFS payloads to GitE2E.
- Never call Gitea's `/api/v1/repos/migrate`; it clones plaintext on the server.
- Never use plain `git lfs migrate import` followed by a normal Git or LFS push. Standard Git LFS uploads plaintext payloads.
- Never bypass GitE2E encryption with `gite2e push --git-remote` or a direct `git push`.
- Treat all branches, tags, notes, and other advertised refs as migration scope. Report refs the provider does not expose.

## Preflight

1. Read the repository's `AGENTS.md` and local operator instructions.
2. Locate `git`, `git-lfs`, and `gite2e`. Read their installed help before choosing commands.
3. Verify the GitE2E MCP connection exposes `gite2e_prepare_repository_import` and that its token has repository write scope.
4. Verify the trusted `gite2e` client explicitly advertises `encrypted-lfs-migration-v1`. A version number, ordinary encrypted Git support, or standard Git LFS support is not proof.
5. Stop before creating a destination if that capability is missing. Report the missing capability and request a compatible client; do not invent an encryption format or downgrade to plaintext LFS.
6. Verify the selected GitHub or GitLab account locally with a secret-safe provider command or credential helper. Do not print tokens.
7. Confirm the source clone URL contains no username, password, token, query string, or fragment.

## Inspect the Source on the Trusted Client

1. Create a disposable workspace with restrictive permissions.
2. Clone the source as a mirror using the user's existing GitHub or GitLab authentication.
3. Fetch every advertised ref. Record the source ref names and object IDs for later comparison.
4. If the source uses Git LFS, run the provider-authenticated equivalent of `git lfs fetch --all` before disconnecting from the provider.
5. Scan every blob reachable from every ref, not only the default branch or current checkout.
6. Select an object for GitE2E LFS when either condition is true:
   - its uncompressed Git blob size exceeds the MCP policy threshold, which defaults to 10 MiB; or
   - its path matches a pattern returned in `lfs_policy.patterns`, including configured model, video, audio, archive, package, and JAR patterns.
7. Include existing source LFS payloads in the selected set. Fail if any selected or existing LFS payload cannot be downloaded.
8. Produce a secret-free preflight summary with ref count, selected object count, total selected bytes, largest object, matched policy, and any signed commits or tags whose IDs or signatures will change.

Do not copy provider credential files into the disposable workspace. Do not place plaintext payload names in logs when the repository's confidentiality policy forbids them.

## Prepare the Destination with MCP

Call `gite2e_prepare_repository_import` exactly once after preflight succeeds. Supply:

- `source_url`: the credential-free GitHub or GitLab clone URL.
- `source_account`: an optional non-secret account label.
- `owner`: the GitE2E user or organization when the authenticated user's namespace is not intended.
- `private`, `description`, and `object_format` when requested.
- `lfs_threshold_mib`: the user's threshold, or omit it for 10 MiB.

Check the result before writing repository data:

1. Require `destination_created` to be true.
2. Require `source.repository` and `repository.name` to equal the source repository name.
3. Require `push_handoff.executor` to be `trusted-client`.
4. Require `push_handoff.server_side_migration_allowed` and `push_handoff.server_push_performed` to be false.
5. Require `push_handoff.required_client_capability` to be `encrypted-lfs-migration-v1`.
6. Use only the returned destination URL. Stop if the destination is not empty or a same-named destination already existed; do not overwrite it.
7. Treat the returned `lfs_policy` as authoritative when it is stricter than the user's requested policy.

## Rewrite, Encrypt, and Push

Use only the workflow provided by the trusted client capability `encrypted-lfs-migration-v1`:

1. Rewrite all refs so every selected payload is represented by a valid Git LFS pointer and the corresponding destination LFS object contains locally produced ciphertext.
2. Preserve executable bits, symlinks, ref names, annotated tag metadata, and repository topology where the encryption format permits it.
3. Ensure `.gitattributes` coverage is deterministic for matching paths without losing existing attributes.
4. Encrypt the rewritten Git graph locally with GitE2E.
5. Upload encrypted LFS payloads through the GitE2E LFS endpoint backed by the configured S3-compatible store.
6. Push the encrypted Git graph through the GitE2E client to the MCP-returned destination.
7. Keep a local mapping needed by the supported encryption scheme. Never send plaintext object IDs, keys, or key material to MCP.

If the client offers separate plan, execute, resume, and verify phases, save its secret-free plan and resume state before upload. Do not substitute hand-written cryptography for a missing client phase.

## Verify Before Reporting Success

Require all checks below:

- Every selected object in every reachable ref is a valid LFS pointer after rewrite.
- No reachable non-LFS Git blob exceeds the configured threshold.
- Every expected destination LFS object exists and passes the client integrity check.
- Bytes stored through the destination LFS service are ciphertext, never the provider plaintext.
- A fresh encrypted clone into a second disposable directory can fetch and decrypt every migrated LFS object.
- The fresh clone has the expected branches, tags, notes, default branch, and repository content.
- Source-to-destination differences are limited to the expected encryption and LFS history rewrite.
- No credential, token, encryption key, plaintext payload, or disposable workspace was committed or uploaded accidentally.

Delete disposable plaintext workspaces after successful verification using a recoverable cleanup method when practical. Retain only the user's approved secret-free report and supported resume metadata.

## Report

State:

- source provider and credential-free repository identity;
- GitE2E destination owner/name and whether it is private;
- refs migrated and any refs unavailable from the provider;
- LFS threshold, patterns applied, objects converted, and encrypted bytes uploaded;
- fresh-clone verification result;
- expected commit/tag ID or signature changes caused by history rewriting;
- any capability, credential, provider, upload, or verification blocker.

Do not claim completion when only the MCP destination was created. Completion requires a real encrypted push, encrypted LFS upload when applicable, and a successful fresh-clone decrypt verification.
