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 canonical reference for every ekso migrate command. Each per-source page links here for the global flag surface so the source-specific pages can stay focused on the source-specific quirks.
The four commands
Every source supports the same four verbs:
| Command | What it does |
|---|
list-* | Read-only. Enumerate the source containers (projects, teams, orgs) the configured credentials can see. Useful for verifying setup. |
collect | Pull source data into a local SQLite cache. Network: source-only. No Ekso writes. |
apply | Walk the cache and write to the Ekso REST API. Network: Ekso-only. Idempotent — re-runs skip already-applied rows. |
status | Read the most recent cache file and print row counts per table, plus IdMap progress. No network. |
The list-* verb is named per-source to match the customer’s mental model:
ekso migrate jira list-projects
ekso migrate linear list-teams
ekso migrate devops list-projects
ekso migrate zendesk list-orgs
ekso migrate gemini list-projects
Global flags (every migrate command)
These flags work on every ekso migrate <source> <verb> invocation, alongside the standard CLI flags from Configuration (--tenant, --api-key, --format, --quiet, etc.).
| Flag | Description | Default |
|---|
--config <FILE> | Path to the migration config JSON. Holds source-platform credentials. | ./migration.config.json |
--working-dir <DIR> | Where to put the SQLite cache. | ~/.ekso/migrate/ |
collect flags
| Flag | Description | Required? |
|---|
--project <KEY> / --team <KEY> / --org <ID> | Source container to collect. Per-source name. Repeat for multiple. | Required for Jira / Linear / DevOps / Gemini; optional for Zendesk (omit to collect every org). |
--no-attachments | Skip downloading binary attachments. Smaller and faster cache. | No |
--no-comments | Skip fetching comments. | No |
--exclude-closed | Filter closed items at the source-API layer (Jira, Zendesk, Gemini). | No |
--resume | Resume an interrupted collect. Skips containers already cached. | No |
--connection-mode <MODE> | (Gemini only) sql or api. Overrides gemini.connectionMode in the config. | No |
apply flags
| Flag | Description | Required? |
|---|
--process <PROCESS_ID> | Destination Ekso process. Every migrated item attaches to this process. | Yes |
--board <BOARD_ID> | Destination board. Cycles attach here. Auto-discovered when the tenant has exactly one board. | If multiple boards |
--field-map <FILE> | YAML file mapping source custom fields to Ekso process fields. See Field mapping. | No |
--user-strategy <STRATEGY> | Identity resolution: match-or-create, match-only, migration-bot. | No (default: match-or-create) |
--fallback-user <USER_ID> | User ID used by match-only and migration-bot when there’s no source match. | If using match-only or migration-bot |
--dry-run | Walk the cache and log what would happen without writing to Ekso. | No |
--resume | Skip rows that already have an ID-map entry. Picks up where a failed apply left off. | No |
--cache <FILE> | Path to a specific cache file. Default: most recent <source>-*.sqlite in the working dir. | No |
See Identity resolution for what each --user-strategy does.
status flags
status is read-only and has no source-specific flags. It reads the most recent cache file (or --cache <FILE>) and prints:
- Schema version of the cache
- Row counts per
Source* table (issues, comments, attachments, etc.)
- IdMap progress per entity kind (how many items / users / files have been applied)
- Whether the cache is fresh (collect-only) or partially / fully applied
A typical run
# 1. Verify credentials work — read-only.
ekso migrate jira list-projects --config migration.config.json --tenant acme
# 2. Collect from the source. Writes ~/.ekso/migrate/jira-2026-04-29T143205.sqlite.
ekso migrate jira collect \
--config migration.config.json \
--project ACME \
--tenant acme
# 3. Dry-run the apply. Walks the cache; no Ekso writes.
ekso migrate jira apply \
--config migration.config.json \
--process proc_engineering \
--tenant acme \
--dry-run
# 4. Apply for real. Writes to your Ekso tenant.
ekso migrate jira apply \
--config migration.config.json \
--process proc_engineering \
--tenant acme
# 5. (If anything fails) re-run with --resume. Picks up at the last successful row.
ekso migrate jira apply \
--config migration.config.json \
--process proc_engineering \
--tenant acme \
--resume
# 6. Inspect the cache after the fact.
ekso migrate jira status --config migration.config.json
Idempotency model
Every apply writes (source-id → Ekso-id) pairs into an IdMap table inside the cache. A re-run reads the IdMap before each write and skips rows that already have an Ekso ID. This means:
- Running
apply twice in a row is a no-op the second time.
- A killed
apply (Ctrl-C, network blip, machine reboot) can resume cleanly with --resume.
- Running
apply without --resume after a partial run is still safe — it just re-checks every row and skips the applied ones. --resume skips the per-row IdMap lookup for speed.
If you want to start from scratch, delete the cache file (or run a fresh collect — each collect writes a new timestamped file).
Per-cache schema versioning
Every cache file is stamped with a schema_version. If you upgrade the CLI between collect and apply and the schema version changes, apply refuses to run and tells you to re-collect. This is intentional — silent data shape mismatches are worse than an explicit “please re-collect” error.
Where to next