Skip to main content

gi-ingest

Offload robotics recordings from TF cards and deliver them to GILabs.

Install

Not on PyPI yet — there is no release workflow for this package ( .github/workflows/cli-release.yml publishes gidata only). Install from a checkout:

git clone https://github.com/General-Intelligence-Labs/gilabs-data-center.git
uv tool install ./gilabs-data-center/vendor-cli    # or: pipx install ./…/vendor-cli
gi-ingest --help

Needs Python ≥ 3.11. Both commands put gi-ingest on your PATH in its own isolated environment; uv tool install --force … upgrades in place after a git pull.

Once the package is published this becomes uv tool install gi-ingest (or pipx install gi-ingest) with no path — until then that command fails with "No matching distribution found", which means it is not published, not that anything is wrong with your setup.

Then authenticate:

gi-ingest login --api-key gik_...
gi-ingest doctor      # verifies connectivity, clock skew, disk, credentials

Get your token from the vendor portal at vendor.gilabs.xyz → Upload tokens.

The three phases

They are three commands because they run on two different timescales, and fusing them turns a 30-minute attended task into an all-night one.

Phase When What it does
stage attended, minutes per card Copies cards to a local disk and verifies each copy
upload unattended, hours Pushes everything staged as one delivery, overnight
reclaim attended, next morning Wipes only the cards the server confirmed
# 1. Drain every card. Swap cards as each finishes; nothing is wiped yet.
gi-ingest stage --device umi_gripper
gi-ingest stage --watch                 # or let it auto-copy on insert

# 2. Leave this running. One delivery, resumable, safe to nohup.
gi-ingest upload --max-bandwidth 50M

# 3. Next morning, with the cards back in the reader.
gi-ingest reclaim

Why the wipe is a separate step

upload finishes hours after the cards were pulled, so it cannot wipe them — they are back in the rig. stage writes a .staged.json marker and leaves the card intact; reclaim deletes part files only for episodes the server reports as delivered, and writes a tombstone so a re-scan skips them.

Between stage and reclaim, the staging disk holds the only copy. Size it for a full collection round; gi-ingest doctor warns under 50 GiB free.

Choosing where cards are copied to

By default cards land in ~/gilabs-staging. That is rarely where you want a multi-terabyte collection round, so it is settable two ways:

# Persist it — do this once per machine.
gi-ingest config set staging-dir /Volumes/BigDisk/gilabs
gi-ingest config show

# Or override for a single run, without changing the stored setting.
gi-ingest stage --staging /Volumes/OtherDisk/gilabs

config set also accepts ledger-path, api-url and project-id. Commands that read the ledger take --ledger for a one-off override, which is how you keep two independent offload runs from sharing state on one machine.

Other commands

gi-ingest whoami          # vendor, scopes, and where you may deliver
gi-ingest destinations    # the org/project list, with ids for --project
gi-ingest doctor          # token, connectivity, disk — run before a night
gi-ingest queue           # what is staged / in flight / delivered
gi-ingest status          # deliveries and their QC verdicts
gi-ingest status --batch btch_...
gi-ingest retry           # re-queue anything that failed

How a delivery works

  1. upload opens a batch and receives AWS credentials scoped to that batch's folder alone — they cannot read or write anything else, including your own other deliveries.
  2. Files go straight to S3. Credentials expire hourly and are re-minted automatically, so a multi-hour run and a laptop that sleeps both just work.
  3. upload seals the batch with a manifest listing every episode, part, size and SHA-256. GILabs verifies every declared file is present at its declared size before ingesting anything, so a half-finished upload can never be processed as if it were complete.

Interrupted? Re-run upload. It re-uses the same open delivery and skips files already sent — a restart costs a listing, not the bytes.

Choosing a destination

Every delivery is filed against one project. With a single granted destination, or one marked default, upload needs no flag. With several and no default it will refuse to guess:

gi-ingest destinations
gi-ingest upload --project proj_abc123

Duplicates

stage asks GILabs which episodes it already has before copying, so a card a colleague already delivered costs one request instead of its bytes. If you are offline it stages anyway and the duplicate is caught server-side at seal.

Local development

uv venv && uv pip install -e ".[dev]"
uv run pytest
uv run ruff check gi_ingest

Design doc: docs/product-plans/vendor-data-ingestion.md.

Release files for gi-ingest 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for gi-ingest 0.2.0
File Size Uploaded
gi_ingest-0.2.0.tar.gz 99.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for gi-ingest 0.2.0
File Interpreter ABI Platform
gi_ingest-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 142.7 kB

Release files / gi_ingest-0.2.0.tar.gz

Download URL gi_ingest-0.2.0.tar.gz
Size 99.7 kB
Tags Source
SHA-256 checksum
How to use checksums
cc55f9da9f518a6cd7bb64ac541a01cba43f7f9f599661522934a5b1a87c2e85
BLAKE2b-256 checksum
How to use checksums
2d8ad3e7d7587f1fb0bfa68254ef72993570793fd73af12d443a71dfab05c2c4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.

Transparency log

Release files / gi_ingest-0.2.0-py3-none-any.whl

Download URL gi_ingest-0.2.0-py3-none-any.whl
Size 43.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
62622852045fdd78e74aaaa4205cc13575e8d9c952be8ae9d2b2010501e25da8
BLAKE2b-256 checksum
How to use checksums
8f15c6af95a73dfe1fb2a5ad760789e6a3ec241563d1bf80788c9d792c56c777
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Aug 20, 2026.

Transparency log

Release history Release notifications | RSS feed

0.9.0

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

This release

0.2.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page