{"id":50385267,"url":"https://github.com/workos/workos-migrations","last_synced_at":"2026-05-30T15:00:27.317Z","repository":{"id":353667562,"uuid":"1022354293","full_name":"workos/workos-migrations","owner":"workos","description":null,"archived":false,"fork":false,"pushed_at":"2026-05-25T14:16:34.000Z","size":967,"stargazers_count":0,"open_issues_count":17,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-25T16:20:04.339Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/workos.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-18T22:52:13.000Z","updated_at":"2026-05-25T14:16:31.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/workos/workos-migrations","commit_stats":null,"previous_names":["workos/workos-migrations"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/workos/workos-migrations","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workos%2Fworkos-migrations","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workos%2Fworkos-migrations/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workos%2Fworkos-migrations/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workos%2Fworkos-migrations/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/workos","download_url":"https://codeload.github.com/workos/workos-migrations/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/workos%2Fworkos-migrations/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33655441,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-29T02:00:06.066Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-05-30T15:00:18.173Z","updated_at":"2026-05-30T15:00:27.285Z","avatar_url":"https://github.com/workos.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# WorkOS Migrations\n\nA CLI tool for migrating users from identity providers into WorkOS. Supports Auth0, Clerk, Firebase Auth, and custom CSV imports with password hashes, organization memberships, roles, and TOTP MFA factors.\n\n## Quick Start\n\nThe fastest way to get started is with the interactive wizard:\n\n```bash\nexport WORKOS_SECRET_KEY=sk_...\n\nnpx @workos/migrations wizard\n```\n\nThe wizard walks you through provider selection, export/transform, validation, and import step by step.\n\n## Installation\n\nRun directly with `npx` (no install needed):\n\n```bash\nnpx @workos/migrations \u003ccommand\u003e\n```\n\nOr via the [WorkOS CLI](https://github.com/workos/cli):\n\n```bash\nnpx workos migrations \u003ccommand\u003e\n```\n\nOr install globally:\n\n```bash\nnpm install -g @workos/migrations\nworkos-migrate \u003ccommand\u003e\n```\n\n## Commands\n\n| Command                     | Description                                                                   |\n| --------------------------- | ----------------------------------------------------------------------------- |\n| `wizard`                    | Interactive step-by-step migration wizard                                     |\n| `export-auth0`              | Export users from Auth0 via Management API                                    |\n| `export-cognito`            | Export users + SSO connections from AWS Cognito                               |\n| `export-template`           | Export a blank CSV template (users, saml_connections, oidc_connections, etc.) |\n| `merge-passwords`           | Merge Auth0 password hashes into the export CSV                               |\n| `transform-clerk`           | Transform a Clerk CSV export to WorkOS format                                 |\n| `transform-firebase`        | Transform a Firebase Auth JSON export to WorkOS format                        |\n| `validate`                  | Validate a CSV file before import                                             |\n| `import`                    | Import users from CSV into WorkOS                                             |\n| `import-package`            | Import a migration package directory into WorkOS                              |\n| `generate-package-template` | Generate an empty migration package skeleton                                  |\n| `validate-package`          | Validate a migration package against the contract                             |\n| `analyze`                   | Analyze import errors and generate retry CSV                                  |\n| `enroll-totp`               | Enroll TOTP MFA factors for imported users                                    |\n| `process-role-definitions`  | Create roles and assign permissions in WorkOS                                 |\n\nRun `npx @workos/migrations \u003ccommand\u003e --help` for full option details on any command.\n\n## Prerequisites\n\n- Node.js 22.11+\n- A WorkOS Secret Key (`WORKOS_SECRET_KEY` environment variable)\n\n## CSV Format\n\nThe import CSV uses these columns:\n\n| Column               | Required | Description                                         |\n| -------------------- | -------- | --------------------------------------------------- |\n| `email`              | Yes      | User email address                                  |\n| `first_name`         | No       | First name                                          |\n| `last_name`          | No       | Last name                                           |\n| `email_verified`     | No       | `true` or `false`                                   |\n| `password_hash`      | No       | Password hash value                                 |\n| `password_hash_type` | No       | `bcrypt`, `firebase-scrypt`, `ssha`, `md5`          |\n| `external_id`        | No       | External identifier from source system              |\n| `metadata`           | No       | JSON string of custom metadata                      |\n| `org_id`             | No       | WorkOS organization ID                              |\n| `org_external_id`    | No       | External org identifier (looked up or auto-created) |\n| `org_name`           | No       | Organization name (used with auto-creation)         |\n| `role_slugs`         | No       | Comma-separated role slugs for org membership       |\n\nThe export and transform commands produce CSVs in this format automatically.\n\n---\n\n## Migrating from Auth0\n\nAuth0 is a parity-complete migration source. The end-to-end flow is:\n\n1. Run `export-auth0 --package` to produce a [migration package](docs/migration-package.md) with users, organizations, memberships, roles, SSO handoff files, warnings, and the upload-compatible projection. For very large tenants, `--engine bulk-job` is available; see step 3b.\n2. Optionally run `merge-passwords --package \u003cdir\u003e` to merge the Auth0 password export into the package. Unsupported hash algorithms are skipped with warnings instead of failing the merge.\n3. Run `import-package \u003cdir\u003e` to push organizations, users, memberships, roles, and TOTP factors into WorkOS in one shot. SSO connections are surfaced as **handoff-only**; see [`docs/auth0-sso-handoff.md`](docs/auth0-sso-handoff.md).\n\n### 1. Set up Auth0 credentials\n\nCreate a Machine-to-Machine application in Auth0, authorize it for the Management API, and grant these scopes:\n\n- `read:users`\n- `read:user_idp_tokens`\n- `read:organizations`\n- `read:organization_members`\n- `read:organization_member_roles`\n- `read:roles`\n- `read:connections`\n- `read:connections_options`\n\n`read:connections_options` is required for complete SAML/OIDC handoff exports because Auth0 stores\nconnection configuration inside the `options` object. If this scope is missing, later package phases\nwill warn and omit fields that cannot be read.\n\n### 2. Export users\n\n```bash\nworkos-migrate export-auth0 \\\n  --domain my-tenant.us.auth0.com \\\n  --client-id \u003cM2M_CLIENT_ID\u003e \\\n  --client-secret \u003cM2M_CLIENT_SECRET\u003e \\\n  --output auth0-export.csv\n```\n\nTo write a migration package with users, organizations, memberships, warnings, and skipped-user\nsidecars:\n\n```bash\nworkos-migrate export-auth0 \\\n  --domain my-tenant.us.auth0.com \\\n  --client-id \u003cM2M_CLIENT_ID\u003e \\\n  --client-secret \u003cM2M_CLIENT_SECRET\u003e \\\n  --package \\\n  --output-dir ./migration-auth0\n```\n\nPackage mode also writes `workos_upload/users.csv`, `workos_upload/organizations.csv`, and\n`workos_upload/organization_memberships.csv` using the narrower WorkOS upload templates. SSO\nconnection files remain under `sso/` as handoff artifacts.\n\nTo include the Auth0 role catalog and per-org role assignments alongside users, organizations, and\nmemberships:\n\n```bash\nworkos-migrate export-auth0 \\\n  --domain my-tenant.us.auth0.com \\\n  --client-id \u003cM2M_CLIENT_ID\u003e \\\n  --client-secret \u003cM2M_CLIENT_SECRET\u003e \\\n  --package \\\n  --entities users,organizations,memberships,roles \\\n  --output-dir ./migration-auth0\n```\n\nThis writes `role_definitions.csv` and `user_role_assignments.csv` and merges the matched\n`role_slugs` into `users.csv` and `organization_memberships.csv`. The\n[`process-role-definitions`](#post-import-totp-and-roles) command can then create the roles in\nWorkOS and assign them to memberships. Note that the `--use-metadata` flow cannot fetch per-org\nassignments from Auth0, so it writes the role catalog only and emits a warning.\n\nTo write only SSO handoff files:\n\n```bash\nworkos-migrate export-auth0 \\\n  --domain my-tenant.us.auth0.com \\\n  --client-id \u003cM2M_CLIENT_ID\u003e \\\n  --client-secret \u003cM2M_CLIENT_SECRET\u003e \\\n  --package \\\n  --entities sso \\\n  --output-dir ./migration-auth0-sso\n```\n\nOptions:\n\n- `--orgs \u003cids...\u003e` - Filter to specific Auth0 organization IDs\n- `--entities \u003centities\u003e` - Comma-separated package entities to export (`users,organizations,memberships,roles,sso`)\n- `--rate-limit \u003cn\u003e` - API requests per second (default: 50)\n- `--use-metadata` - Use `user_metadata` for org discovery instead of the Organizations API\n- `--include-federated-users` - Include federated/JIT users in package mode (skipped by default)\n- `--include-secrets` - Include SSO connection secrets in package handoff files (redacted by default)\n- `--job-id \u003cid\u003e` - Enable export checkpointing for large tenants\n- `--resume [jobId]` - Resume a previously checkpointed export\n\nThe export maps Auth0 fields to WorkOS CSV format, including `email_verified`, `external_id`, and custom metadata.\nAuth0 package SSO export is handoff-only: it inspects Auth0 enterprise strategies for SAML/OIDC configuration and emits only connections with enough reliable handoff data. Database, passwordless, social, generic OAuth, non-SAML/OIDC enterprise, and incomplete connections are skipped with warnings.\n\nFor a callback proxy reference implementation during Auth0 enterprise-connection cutover, see [`proxy-sample-auth0`](proxy-sample-auth0/README.md). The repo also includes [`proxy-sample-cognito`](proxy-sample-cognito/README.md) for Cognito migrations.\n\n### 3. Merge password hashes (optional)\n\nAuth0 does not include password hashes in the Management API export. You need to request a password export from Auth0 support, which provides an NDJSON file. Once you have it, the CLI supports both legacy single-CSV merging and package-aware merging:\n\n```bash\n# Single CSV (legacy)\nworkos-migrate merge-passwords \\\n  --csv auth0-export.csv \\\n  --passwords auth0-passwords.ndjson \\\n  --output auth0-with-passwords.csv\n\n# Migration package — updates users.csv, workos_upload/users.csv, and the manifest\nworkos-migrate merge-passwords \\\n  --package ./migration-auth0 \\\n  --passwords auth0-passwords.ndjson\n```\n\nPackage mode warns and omits credentials for users whose hash algorithm is not supported by WorkOS imports (anything other than `bcrypt` or `md5`). Users without a matching hash are left without a password and will need to reset on first login.\n\n### 3b. Bulk export engine for very large tenants\n\nFor tenants where the Management API per-user fetch is too slow, package mode can use Auth0's `users-exports` job engine instead. This engine returns users without organization membership, so you'll typically run it alongside a Management API run that captured org/membership data, or follow up with a CSV-driven membership reconciliation.\n\n```bash\nworkos-migrate export-auth0 \\\n  --domain my-tenant.us.auth0.com \\\n  --client-id \u003cM2M_CLIENT_ID\u003e \\\n  --client-secret \u003cM2M_CLIENT_SECRET\u003e \\\n  --package \\\n  --engine bulk-job \\\n  --output-dir ./migration-auth0-bulk\n```\n\nA `bulk_export_no_org_membership` warning is recorded in the package and bulk mode does not populate `organizations.csv`, `organization_memberships.csv`, or per-org role assignments.\n\n### 4. Validate, import, and post-import\n\nContinue to [Validation](#validation), [Import](#importing-users), and [Post-Import](#post-import-totp-and-roles) below.\n\n---\n\n## Migrating from Clerk\n\n### 1. Export from Clerk\n\nExport your users from the Clerk Dashboard as a CSV file. The export includes columns like `id`, `first_name`, `last_name`, `primary_email_address`, `password_digest`, `password_hasher`, etc.\n\n### 2. Transform to a migration package (recommended)\n\n```bash\nworkos-migrate transform-clerk \\\n  --input clerk-export.csv \\\n  --package \\\n  --output-dir ./migration-clerk \\\n  --org-mapping orgs.csv \\\n  --role-mapping roles.csv\n```\n\nPackage mode writes the canonical layout (`users.csv`, `organizations.csv`,\n`organization_memberships.csv`, `role_definitions.csv`, `user_role_assignments.csv`,\n`workos_upload/`, manifest, warnings, skipped users) so the result can be fed\nstraight into `import-package`. Unsupported password hashers are recorded as\nwarnings instead of failing the export.\n\nThe legacy single-CSV mode is still available for back-compat:\n\n```bash\nworkos-migrate transform-clerk \\\n  --input clerk-export.csv \\\n  --output clerk-transformed.csv\n```\n\nOptions:\n\n- `--package` - Write a migration package instead of a single CSV.\n- `--output-dir \u003cdir\u003e` - Required when `--package` is set.\n- `--org-mapping \u003cpath\u003e` - CSV mapping Clerk user IDs to organizations (`clerk_user_id,org_external_id,org_name`)\n- `--role-mapping \u003cpath\u003e` - CSV mapping Clerk user IDs to roles (`clerk_user_id,role_slug`)\n- `--source-tenant \u003cname\u003e` - Optional tenant identifier recorded in the manifest.\n\nThe transformer handles:\n\n- Field mapping (Clerk columns to WorkOS columns)\n- bcrypt password passthrough (other hash types like argon2 are dropped with a warning since WorkOS does not support them)\n- Username, phone number, and TOTP secret preservation in metadata\n- Organization and role sidecar merging into the output CSV (or package)\n\n### 3. Validate, import, and post-import\n\nContinue to [Validation](#validation), [Import](#importing-users), and [Post-Import](#post-import-totp-and-roles) below.\n\n---\n\n## Migrating from Firebase Auth\n\nThe recommended path is `transform-firebase --package`, which writes a [migration package](docs/migration-package.md) ready for `import-package`. The legacy `--output \u003ccsv\u003e` mode still ships for back-compat.\n\n### 1. Export from Firebase\n\nExport your users from the Firebase Console or using the Firebase CLI (`firebase auth:export`). This produces a JSON file with a `users` array.\n\n### 2. Get password hash parameters\n\nIf you want to migrate passwords, get the hash parameters from Firebase Console \u003e Authentication \u003e Users \u003e Password Hash Parameters. You need the signer key, salt separator, rounds, and memory cost.\n\n### 3. Transform to WorkOS format\n\nMigration package (recommended):\n\n```bash\nworkos-migrate transform-firebase \\\n  --input firebase-export.json \\\n  --package \\\n  --output-dir ./migration-firebase \\\n  --signer-key \u003cBASE64_KEY\u003e \\\n  --salt-separator \u003cBASE64_SEP\u003e \\\n  --rounds 8 \\\n  --memory-cost 14 \\\n  --org-mapping orgs.csv\n```\n\nLegacy single CSV (still supported):\n\n```bash\nworkos-migrate transform-firebase \\\n  --input firebase-export.json \\\n  --output firebase-transformed.csv \\\n  --signer-key \u003cBASE64_KEY\u003e \\\n  --salt-separator \u003cBASE64_SEP\u003e \\\n  --rounds 8 \\\n  --memory-cost 14\n```\n\nOptions:\n\n- `--package` - Write a migration package instead of a single CSV.\n- `--output-dir \u003cdir\u003e` - Required when `--package` is set.\n- `--source-tenant \u003cname\u003e` - Optional tenant identifier recorded in the manifest.\n- `--name-split \u003cstrategy\u003e` - How to split `displayName` into first/last: `first-space` (default), `last-space`, or `first-name-only`\n- `--include-disabled` - Include disabled users (excluded by default)\n- `--skip-passwords` - Skip password hash encoding\n- `--org-mapping \u003cpath\u003e` - CSV mapping Firebase UIDs to organizations (`firebase_uid,org_external_id,org_name`)\n- `--role-mapping \u003cpath\u003e` - CSV mapping Firebase UIDs to roles (`firebase_uid,role_slug`)\n\nThe transformer handles:\n\n- Firebase scrypt to PHC format encoding (`$firebase-scrypt$hash=...`)\n- `displayName` splitting into `first_name` and `last_name`\n- Phone number, custom claims, and Firebase UID preservation in metadata\n- Skipping users without an email address\n\n### 4. Validate, import, and post-import\n\nContinue to [Validation](#validation), [Import](#importing-users), and [Post-Import](#post-import-totp-and-roles) below.\n\n---\n\n## Migrating from AWS Cognito\n\n### 1. Set up AWS credentials\n\nConfigure your AWS credentials using one of the standard methods:\n\n- Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`)\n- AWS credentials file (`~/.aws/credentials`)\n- IAM role (when running on EC2/ECS/Lambda)\n\nThe Cognito exporter requires these IAM permissions:\n\n- `cognito-idp:ListUserPools`\n- `cognito-idp:ListIdentityProviders`\n- `cognito-idp:DescribeIdentityProvider`\n- `cognito-idp:ListUsers`\n\n### 2. Export users and connections\n\nThe recommended path is to write a [migration package](docs/migration-package.md) that the\n`import-package` orchestrator can consume in a single step:\n\n```bash\nworkos-migrate export-cognito \\\n  --region us-east-1 \\\n  --user-pool-ids us-east-1_ABC123,us-east-1_DEF456 \\\n  --package \\\n  --output-dir ./migration-cognito \\\n  --entities users,organizations,memberships,sso\n```\n\nPackage mode writes the canonical layout: `users.csv`, `organizations.csv`,\n`organization_memberships.csv`, the `sso/` handoff CSVs, and the `workos_upload/` projection.\nBy default each Cognito user pool maps to one WorkOS organization; pass\n`--org-strategy connection` for one org per identity provider (memberships then become\nheader-only) or `--org-strategy none` to skip organization rows entirely.\n\nThe legacy loose-CSV mode is still available for backward compatibility:\n\n```bash\nworkos-migrate export-cognito \\\n  --region us-east-1 \\\n  --user-pool-ids us-east-1_ABC123,us-east-1_DEF456\n```\n\nOptions:\n\n- `--package` - Write a migration package (recommended). Without this flag, loose CSVs are written.\n- `--entities \u003clist\u003e` - Loose mode: `connections,users`. Package mode: `users,organizations,memberships,sso`.\n- `--org-strategy \u003cstrategy\u003e` - Package mode only: `user-pool` (default), `connection`, or `none`.\n- `--output-dir \u003cdir\u003e` - Output directory for CSV files (default: current directory)\n- `--saml-custom-entity-id-template \u003curl\u003e` - Template for SAML custom Entity ID (default: `urn:amazon:cognito:sp:{user_pool_id}`)\n- `--saml-custom-acs-url-template \u003curl\u003e` - Template for SAML custom ACS URL (placeholders: `{provider_name}`, `{user_pool_id}`, `{region}`)\n- `--oidc-custom-redirect-uri-template \u003curl\u003e` - Template for OIDC custom redirect URI\n- `--skip-external-provider-users` - Skip Cognito users whose `userStatus=EXTERNAL_PROVIDER` (default in package mode; opt-in in loose mode).\n\nLoose mode produces:\n\n- `workos_saml_connections.csv` - SAML SSO connections\n- `workos_oidc_connections.csv` - OIDC SSO connections\n- `custom_attribute_mappings.csv` - Supplementary attribute mappings\n- `workos_users.csv` - Users in WorkOS import format\n\n**Note:** Cognito does not expose password hashes via its API. The `password_hash` column will be blank for all users. Affected users will need to reset their password post-migration or rely on SSO + JIT provisioning via the migration proxy.\n\n### 3. Migration proxy (optional)\n\nFor a seamless cutover where existing IdP configurations continue to work, see the reference proxy implementation in [`proxy-sample-cognito/`](./proxy-sample-cognito/). This Lambda handler routes per-tenant traffic between Cognito and WorkOS during the migration window.\n\n### 4. Validate and import users\n\nContinue to [Validation](#validation), [Import](#importing-users), and [Post-Import](#post-import-totp-and-roles) below.\n\n---\n\n## Custom CSV\n\nIf you already have a CSV in WorkOS format (see [CSV Format](#csv-format) above), skip straight to validation:\n\n```bash\nworkos-migrate validate --csv my-users.csv\nworkos-migrate import --csv my-users.csv\n```\n\n### CSV migration package (manual provider path)\n\nFor unsupported providers, you can hand-build a [migration package](docs/migration-package.md) and run it through the same `import-package` orchestrator the dedicated providers use:\n\n```bash\n# Scaffold an empty package skeleton\nworkos-migrate generate-package-template --output-dir ./migration-csv\n\n# Populate users.csv (and optionally organizations.csv, organization_memberships.csv,\n# role_definitions.csv, user_role_assignments.csv) with the canonical headers from\n# docs/migration-package.md.\n\n# Validate the package against the contract\nworkos-migrate validate-package ./migration-csv\n\n# Run it through the importer (or --plan / --dry-run first)\nworkos-migrate import-package ./migration-csv\n```\n\n`validate-package` checks the manifest schema, every canonical CSV header, every required file, manifest count consistency, and JSONL parseability. It's safe to run repeatedly — exit 0 means the package is ready for `import-package`.\n\n---\n\n## Validation\n\nValidate your CSV before importing to catch problems early:\n\n```bash\nworkos-migrate validate --csv users.csv\n```\n\nThe validator checks:\n\n- Required fields (`email` is present and non-empty)\n- Email format\n- Duplicate emails\n- Password hash format (valid bcrypt or firebase-scrypt structure)\n- Organization reference consistency\n\n### Auto-fix\n\nThe `--auto-fix` flag corrects common issues automatically:\n\n```bash\nworkos-migrate validate --csv users.csv --auto-fix --output users-fixed.csv\n```\n\nAuto-fix handles whitespace trimming, email lowercasing, and empty field cleanup.\n\n---\n\n## Importing Users\n\n### Basic import\n\n```bash\nworkos-migrate import --csv users.csv\n```\n\n### Organization modes\n\n**User only** (no org membership):\n\n```bash\nworkos-migrate import --csv users.csv\n```\n\n**Single org** (all users into one organization):\n\n```bash\nworkos-migrate import --csv users.csv --org-id org_01ABC\n```\n\n**Multi-org** (org per row, from CSV columns):\n\n```bash\nworkos-migrate import --csv users.csv --create-org-if-missing\n```\n\nIn multi-org mode, the importer reads `org_id`, `org_external_id`, or `org_name` from each row. Organizations are cached in memory to avoid repeated API lookups. If `--create-org-if-missing` is set, organizations referenced by name or external ID that don't exist in WorkOS are created automatically.\n\n### Performance options\n\n```bash\nworkos-migrate import \\\n  --csv users.csv \\\n  --concurrency 20 \\\n  --rate-limit 50 \\\n  --workers 4 \\\n  --chunk-size 5000 \\\n  --job-id my-migration\n```\n\n- `--concurrency \u003cn\u003e` - Parallel API requests per worker (default: 10)\n- `--rate-limit \u003cn\u003e` - Max requests per second across all workers (default: 50)\n- `--workers \u003cn\u003e` - Worker threads for CPU distribution (default: 1, requires `--job-id`)\n- `--chunk-size \u003cn\u003e` - Rows per checkpoint chunk (default: 1000)\n\n### Checkpoint and resume\n\nFor large migrations, use `--job-id` to enable checkpointing. If the process crashes or is interrupted, resume from where it left off:\n\n```bash\n# Start with checkpointing\nworkos-migrate import --csv users.csv --job-id my-migration\n\n# Resume after interruption\nworkos-migrate import --csv users.csv --resume my-migration\n```\n\nCheckpoint state is stored in `.workos-checkpoints/\u003cjob-id\u003e/`.\n\n### Dry run\n\nPreview what the import would do without making any API calls:\n\n```bash\nworkos-migrate import --csv users.csv --dry-run\n```\n\n### Error output\n\nImport errors are written to a JSONL file (default: `errors.jsonl`). Each line contains the email, error type, HTTP status, and message for a single failure.\n\n---\n\n## Error Analysis\n\nAfter an import, analyze errors to understand what went wrong and generate a retry CSV:\n\n```bash\nworkos-migrate analyze \\\n  --errors errors.jsonl \\\n  --retry-csv retry.csv \\\n  --original-csv users.csv\n```\n\nThe analyzer groups errors by pattern, classifies them as retryable or non-retryable, and suggests fixes. The retry CSV contains only the rows that failed with retryable errors, so you can re-import just those users.\n\n---\n\n## Importing a migration package\n\nMigration packages produced by `export-auth0 --package` (and other providers as they move onto the package contract) can be imported in one step with `import-package`:\n\n```bash\n# Plan only — print what would happen and exit\nworkos-migrate import-package ./migration-auth0 --plan\n\n# Dry run — validate the package and write workos_import_summary.json with status=planned\nworkos-migrate import-package ./migration-auth0 --dry-run\n\n# Live import\nworkos-migrate import-package ./migration-auth0\n```\n\nThe orchestrator runs entities in this order:\n\n1. Organizations (resolved or created during user import via `--create-org-if-missing` semantics).\n2. Users + memberships (`runImport` on `users.csv`).\n3. Role definitions (`process-role-definitions` on `role_definitions.csv`).\n4. User-role assignments (per-org slices of `user_role_assignments.csv`).\n5. TOTP enrollment (`enroll-totp` on `totp_secrets.csv`).\n6. SSO connections — surfaced as **handoff-only**. The orchestrator never creates WorkOS SSO connections automatically. See `sso/handoff_notes.md` in the package for next steps.\n\nEvery run writes `workos_import_summary.json` (or `--summary \u003cpath\u003e`) with per-entity status, totals, succeeded/failed counts, and warnings. Per-row errors land in `workos_import_errors.jsonl` (or `--errors \u003cpath\u003e`).\n\n---\n\n## Post-Import: TOTP and Roles\n\n### TOTP MFA enrollment\n\nIf your source system has TOTP secrets (e.g., from Auth0 or Clerk), you can enroll them in WorkOS after import:\n\n```bash\nworkos-migrate enroll-totp \\\n  --input totp-secrets.csv \\\n  --totp-issuer \"MyApp\"\n```\n\nThe input file can be CSV (`email,totp_secret`) or NDJSON (one JSON object per line with `email` and `totp_secret` or `mfa_factors` fields). Format is auto-detected from the file extension.\n\nOptions:\n\n- `--format \u003ccsv|ndjson\u003e` - Override auto-detection\n- `--concurrency \u003cn\u003e` - Parallel requests (default: 5)\n- `--rate-limit \u003cn\u003e` - Requests per second (default: 10)\n- `--totp-issuer \u003cname\u003e` - Issuer shown in authenticator apps\n- `--dry-run` - Validate without enrolling\n\n### Role definitions and assignment\n\nCreate roles and permissions in WorkOS from a CSV, then assign them to users:\n\n```bash\n# Create roles and permissions\nworkos-migrate process-role-definitions \\\n  --definitions role-definitions.csv\n\n# Create roles and assign to users\nworkos-migrate process-role-definitions \\\n  --definitions role-definitions.csv \\\n  --user-mapping user-roles.csv \\\n  --org-id org_01ABC\n```\n\n**Role definitions CSV** (`role_slug,role_name,role_type,permissions[,org_id]`):\n\n```csv\nrole_slug,role_name,role_type,permissions\nadmin,Administrator,environment,\"read,write,delete\"\nviewer,Viewer,environment,read\norg-admin,Org Admin,organization,\"read,write\",org_01ABC\n```\n\n**User-role mapping CSV** (`email,role_slug`):\n\n```csv\nemail,role_slug\nalice@example.com,admin\nbob@example.com,viewer\n```\n\n---\n\n## Development\n\n```bash\nnpm install\nnpm run build\nnpm run dev         # Run with tsx (no build step)\nnpm run lint\nnpm run typecheck\nnpm test            # 120 tests across 10 suites\n```\n\n## Contributing\n\nSee [CONTRIBUTING.md](./CONTRIBUTING.md) for development setup and guidelines. Security issues should be reported privately as described in [SECURITY.md](./SECURITY.md).\n\n## License\n\nMIT. See [LICENSE](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkos%2Fworkos-migrations","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fworkos%2Fworkos-migrations","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fworkos%2Fworkos-migrations/lists"}