ekso migrate gemini pulls projects, issues, comments, attachments, time entries, sprints, versions, and components from Countersoft Gemini into your Ekso tenant. Two commands — collect and apply. Read Migrate overview and Before you start first.
What gets imported
Because the Gemini schema and Ekso’s canonical migration schema were designed by the same team, the mapping is the cleanest of any source — most fields transfer 1:1.| Gemini concept | Ekso shape |
|---|---|
| Project | DataContainer (Code = project.code, Name = project.name) |
| Issue | DataItem |
| Comment | DataAnnotation |
| Attachment | DataFile (multipart upload) |
| Time entry | DataItem.Time[] (in the same item POST — billable flag preserved) |
| Component | ConfigLabel (prefix component:) + item Tags |
| Version (release / fix) | DataCycle |
| Sprint | DataCycle |
| Custom field | DataItem.Field[] (via --field-map) or Meta |
| Resource (watcher) | DataItem.Meta.gemini_resources[] |
| Follower (subscriber) | preserved in Meta |
| Link (parent/child, related, duplicate) | DataLink |
| User / Group | DataUser |
What does NOT get imported
- Workflow definitions / state machines. v1 imports the current status of each issue. State-transition rules don’t migrate — Ekso’s process system is a successor; redesign the workflow at migration time.
- License data. Out of scope for the data migration; that’s a sales conversation.
- Saved reports / queries. Re-author on the Ekso side.
Before you start
Pre-flight checklist on top of the general one:- A running Gemini install (v7+ recommended).
- One of:
- SQL access to the Gemini DB (recommended — fastest, most complete), or
- API access to the Gemini REST API (works behind the firewall).
gemini block to your migration.config.json:
connectionMode=sql, url/username/apiKey are ignored. If connectionMode=api, connectionString is ignored. You can configure both and switch via --connection-mode at runtime.
Env-var overrides for CI:
EKSO_MIGRATE_GEMINI_KEYoverridesgemini.apiKey.EKSO_MIGRATE_GEMINI_DB_PWDis read by the connection string when interpolated as${EKSO_MIGRATE_GEMINI_DB_PWD}.
Two modes — when to use which
| Mode | When | Pros | Cons |
|---|---|---|---|
SQL Server direct (connectionMode: "sql") | The CLI can reach the Gemini DB on TCP 1433. | Fastest. Reads attachment bytes directly from varbinary / FILESTREAM. Every column is queryable. | Many Gemini installs don’t expose SQL externally. Needs DB read credentials. |
REST API (connectionMode: "api") | The CLI can reach the Gemini web app over HTTPS. | Works through firewalls. No DB credentials. Schema-stable. | Slower for large data sets. Some internal fields aren’t exposed. |
Step 1 — list projects
--connection-mode api.
Step 2 — collect
--project for multiple. Sample run:
--connection-mode {sql,api}— override the configured mode.--no-attachments— skip downloads.--no-comments— skip comments.--exclude-closed— skip items in final-state statuses.--resume— pick up where a killed collect left off.
Step 3 — dry-run apply
Step 4 — apply for real
--resume.
Time tracking — the strongest fidelity point
Gemini has first-class time tracking, and Ekso preserves it natively. Every Gemini time entry becomes one row inDataItem.Time[] on its parent item — written in the same POST /api/item call that creates the item. No separate POST, no time-tracking applier.
The billable flag is preserved on each entry’s Meta.source_billable. After migration:
ekso time list --item <id>lists every imported entry.ekso time list --user <id>lists every entry by user, across all migrated projects.- Standard Ekso reporting (profitability, cost-center, billable hours) works on the imported data the same way it works on natively-created data.
Identity resolution for Gemini
Gemini users have email —--user-strategy match-or-create is reliable. No special handling needed.
Read Identity resolution.
Custom fields for Gemini
Gemini custom fields are accessed by name. Map them to Ekso process fields:dbo.IssueCustomFields. In API mode, they come from the issue payload. Both modes route to the same Ekso Field[] slot.
See Field mapping.
Sprints, Versions, Components
| Gemini | Ekso | Notes |
|---|---|---|
| Sprint | DataCycle | Always — no flag. |
| Version (release / fix) | DataCycle | Sprint-shaped (name + dates + member items). |
| Component | ConfigLabel (component:Backend) + DataItem.Tags | Always — no flag. |
--board <BOARD_ID> if the tenant has more than one board.
Iron rule — dual-mode dispatch
The Gemini adapter holds two repository implementations:SqlSrvGeminiRepository (T-SQL queries) and ApiGeminiRepository (HTTP client). The mode is fixed at adapter construction — once you pick SQL or API, the same mode is used for the entire run.
If you need to switch modes mid-migration (e.g. SQL for collect, API for re-collect on a different machine), run a fresh collect in the new mode. The cache files are interchangeable on apply — apply doesn’t care which mode produced the cache.
The recommended path is SQL mode whenever your network allows it — it’s faster and pulls full-fidelity data including attachment bytes directly from the DB. API mode is the firewall-friendly fallback.
Older Gemini versions
The migrator targets Gemini v7+ schemas. Older versions (v5, v6) work in API mode if your install’s API supports it. Schema drift is surfaced inMeta.gemini_unmapped_columns — the migration completes; data shape just differs slightly. v2 TODO: explicit version-aware schema modules if a customer needs first-class v5/v6 support.
Multiple Gemini installations on one SQL Server
If your SQL Server hosts multiple Gemini DBs, set the rightDatabase= in the connection string:
Self-hosted Ekso
Ekso runs self-hosted as well as SaaS. If you’ve been running Gemini on-prem and want to keep that posture, deploy Ekso to the same network and migrate locally — neither the source data nor the Ekso credentials need to leave your infrastructure.Troubleshooting Gemini-specific issues
| Symptom | Fix |
|---|---|
SQL connection refused | Network can’t reach the DB. Switch to --connection-mode api, or run from a host inside the corporate network. |
SQL credentials invalid | DB user lacks read on Gemini tables. Grant db_datareader. |
API 401 | Wrong / disabled API key. Get a fresh one from Gemini admin. |
Schema drift — unknown column | Older or newer Gemini schema than the supported set. Surfaced in Meta.gemini_unmapped_columns; migration still completes. |
Mode mismatch — SQL configured but only API access | Pass --connection-mode api at the command line. |
Why move to Ekso
Ekso is what the Gemini team would build today — same DNA, modern stack, AI native, financial intelligence built in. Self-host or SaaS. See Ekso vs Countersoft Gemini for the full upgrade story.Where to next
- Command reference — full flag surface.
- Identity resolution —
--user-strategydeep-dive. - Field mapping — Gemini custom fields.
- Troubleshooting — exit codes and recovery.