obi
Command-line client for the Obitrain API — one generic, scriptable interface to every endpoint, for interactive use and automation.
Instead of wrapping each endpoint in its own subcommand, obi gives you three primitives:
obi auth— authenticate once, stay authenticatedobi api— call any endpoint (method, query, body, headers)obi schema— discover endpoints, parameters and payload shapes offline
Install
uv tool install obitrain # exposes the `obi` binary
uvx --from obitrain obi --help
User quickstart
obi auth login
obi auth login prints a short code (like QX2F-LX4T). Enter it in the Obitrain mobile app under
Account → Link a device, and the CLI receives its own API token — no password typed in the
terminal, and it works for Google/Apple accounts too. The token is long-lived and revocable from
the app at any time.
Then call anything:
obi api /v1/user # your profile
obi api /v1/training/sessions -q limit=5 # last sessions
obi api /v1/user -X PATCH -d '{"lang": "fr"}' # update a field
obi api /v1/training/session -d @session.json # body from a file (implies POST)
Continue with the user quickstart or see the full documentation.
Authentication
| Command | Purpose |
|---|---|
obi auth login |
Device-code login: approve in the app, token stored in the active profile |
obi auth set <token> |
Store a token generated from your Account page |
obi auth status / whoami |
Inspect the active profile / authenticated user |
obi auth token |
Print the token, for scripting |
obi auth clear |
Remove stored credentials |
- Profiles —
--profile work(orOBI_PROFILE) keeps separate accounts; credentials are stored per profile with0600permissions.obi auth profileslists them. - Ephemeral tokens —
OBI_TOKEN/--tokenauthenticate a single invocation without writing anything to disk; ideal for CI. - Base URL — defaults to
https://api.obitrain.com; override with--base-urlorOBI_BASE_URL.
Calling the API
obi api <path> [-X METHOD] [-q k=v ...] [-d BODY|@file|@-] [-H k:v ...] [-o json|pretty|raw|yaml] [-n]
-dimpliesPOSTunless-Xsays otherwise;@fileand@-(stdin) are supported.-n/--dry-runprints the fully resolved request (token redacted) without sending it.- Response bodies always go to stdout; diagnostics go to stderr as one-line JSON.
- Output is human-friendly by default (syntax-highlighted on a TTY) and plain JSON whenever
output is piped or an agent environment is detected;
--json(or-o json|raw|yaml) forces a format explicitly.
Exit codes
| Code | Meaning |
|---|---|
0 |
Success — parse stdout |
1 |
Usage error |
4 |
Authentication required or failed |
5 |
Network error (connection, DNS, timeout) |
6 |
Server error (5xx) |
7 |
Client error (4xx) |
130 |
Cancelled (Ctrl-C) |
Discovering the API
The OpenAPI spec is bundled with the package — discovery works offline:
obi schema tags # tags with operation counts
obi schema list --grep session # find operations
obi schema show /v1/training/sessions -X GET # params, body & response schemas, inlined models
obi schema show /v1/stats/activity/weekly # concrete paths resolve to their {template}
Agent quickstart
obi was also designed for reliable use by AI agents. The machine-facing contract includes:
-
Self-documenting binary —
obi quickstartprints the full agent guide (discovery → auth → calls → error repair) to stdout;obi --help-jsongives the machine-readable command tree. No repo or web access needed. -
Deterministic output — bodies on stdout, one-line JSON diagnostics on stderr, exit codes above. Pass
--jsonto force plain JSON; in practice you already get it, since output falls back to JSON when an agent environment is detected (CLAUDECODE,CURSOR_AGENT,GITHUB_COPILOT,AMAZON_Q,OBI_AGENT_MODE, …), whenNO_COLORis set, or when stdout is not a TTY. -
Errors carry their own fix —
404/405/422diagnostics include ahintfield built from the bundled spec:$ obi api /v1/stats/activity/weekly {"error": "http_error", "status": 422, "method": "GET", "path": "/v1/stats/activity/weekly", "hint": "required params: range_type (path, enum: daily|weekly|monthly), from_date (query, date), to_date (query, date); see `obi schema show '/v1/stats/activity/{range_type}'`"} $ obi api /v1/stats/activity/weekly -q from_date=2026-01-01 -q to_date=2026-06-01 # repaired
The recommended loop: obi schema list --grep … → obi schema show <path> → obi api … -n
(optional dry-run) → obi api … → on exit 7, read hint and retry.
Works with coding agents. Any agent that can run a shell can drive obi — give it a token via
OBI_TOKEN and tell it to run obi quickstart. Claude Code is auto-detected (CLAUDECODE); for
OpenAI Codex (AGENTS.md) and Mistral Vibe, set OBI_AGENT_MODE=1 to force JSON:
OBI_TOKEN="<api token>" claude # auto-detected
OBI_AGENT_MODE=1 OBI_TOKEN="<api token>" codex exec "use obi to fetch /v1/user"
OBI_AGENT_MODE=1 OBI_TOKEN="<api token>" vibe -p "use obi to fetch /v1/user" --enabled-tools "bash*"
See the agent quickstart for the complete workflow, including per-tool setup.
Development
uv sync --all-groups
uv run ruff check src tests && uv run ruff format --check src tests
uv run pyright
uv run pytest
Generated models
src/obitrain/api/models.py holds TypedDicts generated from static/openapi.json (the vendored
OpenAPI 3.1 spec). Regenerate after updating the spec:
sh bin/codegen.sh
git diff --exit-code src/obitrain/api/models.py # CI fails if these drift
To refresh the spec from upstream, replace static/openapi.json and rerun codegen.
Docs
uv run --group docs zensical serve # live preview
uv run --group docs zensical build # static site -> ./site
Full docs: https://obitrain.github.io/obi/.
Metadata
Release files for obitrain 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| obitrain-0.2.1.tar.gz | 49.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| obitrain-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 103.8 kB
Release files / obitrain-0.2.1.tar.gz
| Download URL | obitrain-0.2.1.tar.gz |
|---|---|
| Size | 49.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c06e28aadb7c90fe58f9e571479b9925520f13f8b209013299fd030b7e01a20a
|
|
BLAKE2b-256 checksum How to use checksums |
286f16c55c613d08504d894e5f0db096190fead4e08306074b21b9cd98167684
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / obitrain-0.2.1-py3-none-any.whl
| Download URL | obitrain-0.2.1-py3-none-any.whl |
|---|---|
| Size | 54.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1892e2b7ae0ae50f2e195ca99c62b47e4e2196e96b3f2c7f3b68f4380a5e4f4a
|
|
BLAKE2b-256 checksum How to use checksums |
68aa3cdb6c6322db789e19f1f4fad48e6108f88cec48eaf1e780e2d5adbe61b4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|