Command-line client for the Obitrain API
Project description
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/.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file obitrain-0.2.1.tar.gz.
File metadata
- Download URL: obitrain-0.2.1.tar.gz
- Upload date:
- Size: 49.6 kB
- Tags: Source
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c06e28aadb7c90fe58f9e571479b9925520f13f8b209013299fd030b7e01a20a
|
|
| MD5 |
62492299d072c1f9e77451b21039f7de
|
|
| BLAKE2b-256 |
286f16c55c613d08504d894e5f0db096190fead4e08306074b21b9cd98167684
|
File details
Details for the file obitrain-0.2.1-py3-none-any.whl.
File metadata
- Download URL: obitrain-0.2.1-py3-none-any.whl
- Upload date:
- Size: 54.2 kB
- Tags: Python 3
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1892e2b7ae0ae50f2e195ca99c62b47e4e2196e96b3f2c7f3b68f4380a5e4f4a
|
|
| MD5 |
19c8d72a61cc75247d402c903321d177
|
|
| BLAKE2b-256 |
68aa3cdb6c6322db789e19f1f4fad48e6108f88cec48eaf1e780e2d5adbe61b4
|