External platforms attribute every comment, worklog, and item to a user. Ekso has to record those authors faithfully or the audit trail breaks. This page explains the three strategies, when to use which, and how to clean up afterwards.Documentation Index
Fetch the complete documentation index at: https://ekso.dev/llms.txt
Use this file to discover all available pages before exploring further.
The three strategies
Pass one ofmatch-or-create / match-only / migration-bot to apply --user-strategy:
| Strategy | What it does | Side effects |
|---|---|---|
match-or-create (default) | For each source user, look for an Ekso user with the same email. If one exists, reuse it. If not, mint a new user (random password, no invite email sent). | Tenant gains new users. Original authoring fidelity preserved. |
match-only | Match by email. Source users with no Ekso match fall back to --fallback-user. | No new users created. Authoring on items where no match was found rolls up to the fallback user. |
migration-bot | Force every author to --fallback-user. | No matching, no creation. All comments and items appear authored by one user. |
How matching works
The CLI matches by email address, case-insensitive. The match check is a singleGET /api/user against your Ekso tenant per unique source-user-email; the result is cached in the migration’s IdMap so the same email isn’t matched twice.
There is no fuzzy matching, no display-name fallback. Two source users with the same email get treated as the same Ekso user (which is usually what you want — the same person used both Jira and DevOps). Two source users with no email get treated separately.
The match runs once per unique email at the start of apply. If a source user is created on the source platform mid-migration (rare), they show up as “no match” and follow the strategy’s fallback path.
How match-or-create mints users
When the strategy is match-or-create and a source user has no Ekso match, the CLI calls POST /api/user with:
email= the source user’s emailname= the source user’s display nameactive=true- A random password generated server-side
inviteOnCreate=false— no welcome email is sent
inviteOnCreate=false path lets you mint the users now, then run a deliberate communication later.
The minted users have a random password they don’t know. Send them through the password-reset flow (or your SSO setup) when you’re ready for them to actually sign in.
When to use which
Default tomatch-or-create unless you have a reason not to. It preserves authorship without spamming users.
match-only when you specifically don’t want to mint users:
- You’re piloting the migration on a sandbox tenant and don’t want test users polluting your production directory.
- Your tenant uses SSO and you provision users centrally — the migrator shouldn’t create them.
- You only need a subset of authoring fidelity preserved (the matched ones).
user_migration_admin. The original source-user identity is preserved in the item’s Meta so you can audit later.
Use migration-bot when authoring fidelity doesn’t matter:
- The source platform’s users aren’t real people (synthetic test tenant).
- You’re consolidating archival data and don’t care who wrote what.
- You want one user to “own” everything for permission simplicity.
user_migration_bot. The original source-user identity is still preserved in Meta.
Source-specific quirks
| Source | Behaviour |
|---|---|
| Jira | Atlassian users have email; match-or-create is reliable. |
| Linear | Linear users always have email; match-or-create is reliable. |
| Azure DevOps | Service identities ([Project]\Project Collection Build Service, etc.) are filtered out at collect time — they’re not real users and won’t appear as authors. |
| Zendesk | End-users (customers) and agents (staff) are imported. End-users get tagged migrated-from:zendesk-enduser; agents get migrated-from:zendesk-agent. Anonymous end-users (no email) follow --user-strategy rules. |
| Gemini | All Gemini users have email; match-or-create is reliable. |
Anonymous users
If a source user has no email at all (some Zendesk end-users, some legacy DevOps accounts):match-or-create: minted with a placeholder email like<source-id>@anon.<source>.local. Filterable later by tag.match-only: rolls up to--fallback-user.migration-bot: rolls up to--fallback-user.
Tagging migrated users
Every user the CLI mints (or matches) is stamped with a tag of the formmigrated-from:<source> so you can filter, audit, or bulk-update them after the fact. Examples:
migrated-from:jira— minted from a Jira migrationmigrated-from:linearmigrated-from:zendesk-enduser,migrated-from:zendesk-agentmigrated-from:devopsmigrated-from:gemini
ekso user list --tag migrated-from:jira or directly in the Ekso admin UI.
Post-migration cleanup
After apply succeeds:- Audit the user list.
ekso user list --tag migrated-from:<source>shows every user touched by the migration. - Send password resets to users you actually want to onboard. Skip the rest — they’re filed for audit-trail purposes and don’t need to sign in.
- Remove placeholder-email users if you don’t need them. Their original source identity is preserved in their profile metadata for audit.
- Rotate the
--fallback-usercredentials. If you usedmigration-bot, that account briefly held a lot of authority. Rotate it or disable it.
What’s preserved on items
Even when authoring rolls up to a fallback user, the original source identity is preserved on each item, comment, and time entry inMeta. Example:
migration-bot run preserves enough information to reconstruct authorship later if you change strategies.
Where to next
- Command reference — full flag surface.
- Field mapping —
migration.fields.yamlshape. - Troubleshooting — recovering from a partial apply.