Install¶
canair isn't on PyPI yet, so install it from a clone of the repository. You need
uv (a fast Python package/tool manager).
Install the CLI¶
git clone https://github.com/philipkocanda/canair.git
cd canair
uv tool install . # installs the `canair` command globally
canair --help # first run creates ~/.config/canair/ + a starter config.yaml
The first canair run scaffolds your user config directory and a starter
config.yaml. If you run an interactive command that needs a vehicle profile,
canair offers a first-run chooser — pick one of the bundled/discovered
profiles or create a new one. It tells you exactly where profiles live
(~/.config/canair/profiles/) and records your choice as default_profile so
later runs are non-interactive. The chooser never fires when piped/scripted, or
when you pass --profile/CANAIR_PROFILE. Next:
connect your dongle.
Try it without installing¶
To poke around without a global install, run it straight from the checkout:
uv run canair … executes the code in the current repo checkout. This is also
what you'll use if you're hacking on canair itself.
Point your writes somewhere durable¶
uv tool install bakes a frozen copy of canair — including the profiles it
ships with — into uv's tool venv, and a reinstall (canair update) replaces that
copy wholesale. So a capture or PID edit recorded against a bundled profile from
a bare canair is deleted by your next update. Decide once, up front:
# You have the clone (you just used it to install) — keep profile data in it:
canair config set profiles_dir /path/to/canair/profiles
# Or take your own copy of a bundled profile:
canair profile adopt ioniq-2017
A profile you create yourself (canair profile create, or the first-run chooser)
already lands in ~/.config/canair/profiles/ and is unaffected. canair warns at
the moment of the write if data lands in the snapshot, and canair update lists
what a reinstall would delete — but neither is a substitute for the one-time
setting above. Details: Profiles → Where your writes
land.
Staying up to date¶
canair checks GitHub once a day (in a background thread — it never blocks a command, and any network failure is silently ignored) for a newer released version. When one is available it prints a one-line notice with a link to the changelog and how to upgrade.
Upgrade with a single command — it checks out the latest release tag in your clone and reinstalls the CLI from it (keeping the git-clone install intact):
canair update # check, confirm, then checkout <tag> + uv tool install . --reinstall
canair update --check # report current/latest + changelog only, change nothing
canair update --yes # skip the confirmation prompt (automation)
Because it checks out the advertised release tag (rather than fast-forwarding
main), the installed code is exactly the released version — never unreleased
commits sitting on the branch. If the latest release tag can't be determined
(GitHub unreachable), canair update reports the offline state and makes no
changes rather than guessing a version.
If canair can't find your clone or uv (e.g. a different install method), it
prints the exact manual commands instead. To silence the automatic check, set
check_for_updates: false in your config (or export CANAIR_NO_UPDATE_CHECK=1).
The two installs can drift out of sync¶
Running uv tool install . and working in a clone means you have two
copies of canair on the machine:
- a bare
canairruns the installed snapshot (uv's tool venv), taken at the lastuv tool install; uv run canairruns the repo working tree — whatever you've currently checked out or edited.
Edit the repo (or pull new commits that bump the version) and the two drift: a
bare canair keeps reporting the old version while uv run canair reports the
new one. canair update detects this — it reports which copy is running and
warns when the installed snapshot's version differs from the source clone's
pyproject.toml (the same warning also shows up in canair status). When there
is no newer release to check out but the two have drifted, canair update offers
a reinstall-only resync — it runs uv tool install <clone> --reinstall (no
network, no tag checkout) to bring the bare canair back in line with the clone.
canair update --json includes the full install block (running_origin,
running_build, tool_version, clone_version, out_of_sync) for scripts.
The version tells you which build you're running¶
An installed release is its version — uv tool install snapshots the clone at a
release tag, so 1.15.0 identifies that code exactly. A run from a clone is not
any release; it's whatever is checked out. So when canair is running from a git
working tree it says so, naming the branch and short commit:
$ canair --version
canair 1.15.0+main.343b244 # a clone, on `main`, at commit 343b244
canair 1.15.0+main.343b244.dirty # … with uncommitted edits to tracked files
canair 1.15.0 # an installed release
The same string shows up in canair status, canair update, and — most usefully
— in every capture you record, so a suspect reading can be traced back to the
exact code that produced it. Release comparisons ignore the suffix, so a dev
checkout still gets an accurate "up to date" verdict.
Tab-completion (optional)¶
Completion covers subcommands, flags, and ECU/PID names from your active profile:
Completion hooks the literal canair command word, so it won't fire through
uv run. If you work from a checkout, activate the venv first:
Git LFS (for raw-CAN logs)¶
Large raw-CAN broadcast logs (.blf/.asc/.trc and a profile's
captures/can/) are stored with Git LFS. Install it once
so a clone fetches the real log contents instead of pointer files:
Without it the tiny bundled fixtures still work (they're plain git), but any committed large log will appear as an LFS pointer. See Broadcast frames → Storing raw-CAN logs for what is committed vs. fetched on demand.