Documentation Index
Fetch the complete documentation index at: https://docs.synheart.ai/llms.txt
Use this file to discover all available pages before exploring further.
synheart-cli is the developer command-line interface for the Synheart platform. Use it to:
- Authenticate with
platform.synheart.aiand download runtime artifacts. - Generate local mock wearable streams for app development and QA.
- Run local platform endpoints for consent and ingest testing.
- Receive HSI exports from a Synheart mobile client over your local network.
For installation, see Install the CLI. For the full onboarding flow (account, auth, runtime), see Setup overview.
Developer Workflows
SDK Artifact Install
Authenticate, install SDK artifacts, and lock/sync exact versions across machines.
Local App Testing
Generate mock Whoop/Garmin payloads and optional HSI output over WebSocket/SSE/UDP.
Offline Platform
Run local consent+ingest endpoints and receive HSI exports from mobile apps.
Command Groups
| Group | Commands | Purpose |
|---|---|---|
| Authentication | login, logout, whoami, auth status, auth refresh | Account + token management |
| SDK artifacts | install, sync, env | Deterministic artifact installation per project |
| Runtime | runtime current, runtime upgrade | Inspect / refresh the runtime pinned in this project |
| Mock simulation | mock start, mock record, mock replay, mock list-scenarios, mock describe | Local sensor stream generation and replay |
| Local services | local, receiver | Offline platform testing and mobile export intake |
| Diagnostics | doctor, version, env | Environment validation, identity, runtime metadata |
| Knowledge | explain | In-binary primers for Synheart concepts (HSI, HRV, recovery, wear, consent, …) |
| Project config | config show, config path | Inspect the resolved project configuration from .synheart/config.yaml |
| AI integration | mcp serve | Expose CLI verbs as MCP tools for Claude Code, Cursor, Claude Desktop |
| Self-update | update, update --check, update --rollback | Check, apply, or roll back a CLI release |
Authenticate
synheart login opens a browser to the platform login page and stores
an access token at ~/.synheart/credentials. All other commands that
hit the network (install, sync, mock scenario sync) require an
active session; commands that only touch the local machine
(mock start, local, receiver, version, doctor) do not.
synheart whoami decodes the locally-cached JWT — no network call —
and prints the email, org, and plan tier carried by the access token.
synheart auth refresh forces a rotation if you need to re-pull
server-side claims that changed (plan upgrade, org switch).
If a network command fails with one of the auth error codes, synheart auth status walks the storage chain — file path, keyring availability, token expiry — and tells you which step failed. Same JSON shape (--format json) is exposed as the synheart_auth_status MCP tool.
| Code | Meaning | Recovery |
|---|---|---|
SH-AUTH-001 | Not logged in | synheart login |
SH-AUTH-003 | Credentials file unreadable | synheart auth status to see the path / permissions |
SH-AUTH-004 | Keyring access failed | Unlock the OS keyring; retry |
SH-AUTH-009 | Refresh token expired or invalid | synheart login (the stored token is dead; retrying won’t help) |
SH-AUTH-010 | Refresh failed transiently | Retry once; if it persists, escalate to auth status |
Runtime artifact workflow
Use this flow to bootstrap or update the Synheart Runtime native binary in your app repo. The CLI manages the runtime artifact only — the SDK packages themselves are installed through the host platform’s package manager (pub.dev, Maven Central, Swift Package Manager).Install a specific channel or version
Runtime variants
The runtime ships in three variants tied to plan entitlement:| Package | Variant | Who gets it |
|---|---|---|
synheart-core-runtime-edge | edge | Default for free / pro plans |
synheart-core-runtime-stable | stable | Locked-down builds for production deployments |
synheart-core-runtime-lab | lab | Research / experimental builds |
--variant, the registry picks the variant your plan
entitles. Pass --variant edge|stable|lab to override (subject to
entitlement — the server rejects requests for variants you don’t have
access to with a typed error).
synheart.lock so sync always pulls the
same one.
Inspect or refresh the pinned runtime
runtime upgrade is install runtime plus “keep the variant from the
lockfile” — useful when you just want to bump the version without
changing edge/stable/lab. Returns SH-RT-NOLOCK if there’s no
lockfile to upgrade from.
synheart.lock
synheart install writes a synheart.lock next to your project root.
The lockfile pins the exact runtime version, channel, and per-platform
artifact hashes that were resolved. Commit it.
synheart sync reads the lockfile and reinstalls byte-for-byte — no
new resolution happens. Run synheart sync in CI so every build pulls
the same runtime your developers built against.
Where runtime artifacts land
| Project type | Path |
|---|---|
| Flutter (iOS) | ios/Frameworks/SynheartRuntime.xcframework/ |
| Flutter (Android) | android/src/main/jniLibs/<abi>/libsynheart_runtime.so |
| Swift Package | .build/synheart/SynheartRuntime.xcframework/ |
| Kotlin / JVM | build/synheart/jniLibs/<abi>/ |
| Standalone | ~/.synheart/install/runtime/<version>/<platform>/ |
synheart install auto-detects project type by walking up from the
current directory looking for pubspec.yaml, Package.swift, or
build.gradle.kts. Override with --project-type if needed.
Mock simulation
synheart mock generates synthetic vendor streams locally so you can
develop and QA your app without a real wearable. The CLI streams raw
vendor-formatted JSON (the same shape WHOOP / Garmin webhooks emit);
HSI transformation happens inside the SDK runtime in your app, not in
the CLI.
- WebSocket:
ws://127.0.0.1:8787 - SSE:
http://127.0.0.1:8788/events - UDP:
127.0.0.1:8789
Record and replay
Capture a live mock stream to disk and replay it deterministically later — useful for regression tests that need a fixed stream.record and replay accept the same transport flags as start
(--port, --host, --web).
Scenario inspection
baseline, workout,
recovery_high, stress_event). describe prints the metadata —
duration, signal envelope, expected event mix — so test authors can
pick the right profile.
Local platform server
synheart local mirrors the cloud’s consent + ingest endpoints on
127.0.0.1. Use it for offline app development — your SDK can post
ingests, fetch consent tokens, and exercise the full cloud flow
without burning real platform quota or needing network.
Defaults:
| Setting | Default |
|---|---|
| Port | 8083 |
| API key | mock-dev-api-key-2026 |
| HMAC secret | mock-dev-hmac-secret-2026 |
| Consent profiles | loaded from data/profiles.json |
| Persisted ingests | ~/.synheart/local/ingested/ |
--https mode generates a local CA, trusts it in the OS keychain,
adds a 127.0.0.1 <domain> entry to /etc/hosts, and serves the
mock platform behind that domain — so your SDK can hit
https://api.synheart.example exactly as it would hit the production
host. Run synheart local cleanup --remove-certs to reverse the OS
changes.
The --web flag runs a small status dashboard on a separate port
showing connected SDK clients, queued ingests, and recent consent
grants.
HSI export receiver
synheart receiver accepts HSI exports from a Synheart mobile
client. Use it when you want to debug a real on-device session by
replaying it on your laptop — the client packages a session as one
or more HSI snapshots and posts them to the receiver over the local
network.
Mock stream — full flag reference
synheart mock record and synheart mock replay accept the same
flags plus --in (replay input file), --speed (real-time multiplier),
and --loop (restart on EOF).
Diagnostics
synheart doctor reports environment, scenario data, auth status, and
network bind state inline as ok / warn / error. It exits 0 even
when something’s missing — specific commands (synheart mock,
synheart install) surface their own typed errors when they actually
need a missing piece. Pass --port <n> to check a non-default port.
synheart env prints local paths, plus three identity blocks when
they’re available. All sources are local — no network calls:
| Block | Source | Shows when |
|---|---|---|
Auth | locally-decoded JWT | logged in |
Runtime | synheart.lock | project has a pinned runtime |
iOS / Android | Runner.xcodeproj/project.pbxproj and app/build.gradle{,.kts} | the project ships an iOS or Android app |
synheart version prints just the version by default. Pass --build
when you need build metadata (commit hash, build date, OS/arch) for a
support ticket. JSON output (--format json) always includes the
full set.
Learn the platform
synheart explain ships in-binary primers for every unfamiliar concept the CLI exposes (HSI, HRV, recovery, wear, consent, mock, local, receiver, update). Each primer includes a few example commands and a list of related topics.
The primers are also exposed as the synheart_explain MCP tool, so AI agents (Claude Code, Cursor) can ground themselves on Synheart concepts without leaving the chat.
Project configuration
Every command honors a project-level config at.synheart/config.yaml — discovered by walking up from the current directory. Resolution precedence (highest wins):
- Explicit CLI flag (e.g.
--port 9000) - Environment variable
- Project config (
.synheart/config.yaml) - Hardcoded default
.synheart/ directory in your repo and the data-plane commands — synheart doctor, synheart mock start, synheart mock record, synheart mock replay, synheart local, synheart receiver — pick up their port/scenario/vendor from the matching section automatically. Other commands (auth, install, sync, explain, mcp, update) ignore project config because they don’t have a per-project shape.
AI agent integration (MCP)
synheart mcp serve exposes seven read-only verbs as MCP tools so agents (Claude Code, Cursor, Claude Desktop) can call them directly:
| Tool | Wraps |
|---|---|
synheart_explain | concept primer text |
synheart_doctor | environment diagnostic |
synheart_config_show | resolved project config |
synheart_auth_status | auth state diagnostic |
synheart_whoami | current logged-in user |
synheart_list_scenarios | available mock scenarios |
synheart_version | CLI version + build info |
- Claude Code
- Cursor / Claude Desktop
- “What can you tell me about HSI?” → calls
synheart_explainwithtopic: hsi - “Run synheart doctor and tell me if anything’s broken.” → calls
synheart_doctor, summarizes - “What scenarios can I run with mock data?” → calls
synheart_list_scenarios
Self-update
https://dist.synheart.ai/synheart-cli/latest/manifest.json, downloads the matching archive for your platform, verifies its SHA-256 against the manifest, and atomically swaps the new binary into place. The previous binary is archived at ~/.synheart/bin/synheart.prev, so synheart update --rollback reverts in one step.
Self-update is refused when the binary appears to be managed by a package manager (Homebrew, apt, Chocolatey, go install) — those installs should upgrade through their package manager, not through synheart update. Pass --force to override if you know what you’re doing.
The installer scripts remain the supported recovery path for fresh installs and for clients on a release that pre-dates self-update:
- macOS / Linux:
curl -fsSL https://synheart.sh/install | sh - Windows (PowerShell):
iwr -useb https://synheart.sh/install.ps1 | iex
SYNHEART_NO_UPDATE_CHECK=1— explicit opt-outCI=true— auto-suppressed in build environments--format json— never pollutes machine outputsynheart mcp serveandsynheart completion— auto-quieted (protocol / setup contexts)
SH-UPD-APPLY (download/verify/swap failed; the existing binary is left untouched) or SH-UPD-CHECK (manifest fetch failed). Both retry safely.
CI/CD
For deterministic builds, install the runtime once, commit the lockfile, andsync in CI:
synheart login --token (non-interactive) with a CI service-
account token. Tokens are scoped per project and per environment;
rotate via the platform dashboard.
Global flags
These persistent flags work on every command:--format text|json— output format. JSON output is schema-stable (snake_case fields, RFC 3339 timestamps); the CLI synthesizes a JSON error body witherror_codeon every command failure so scripts can branch on it.--quiet/--verbose— suppress or expand log output.--verbosealso reveals the underlying cause on typed errors.--no-color— disable ANSI colors. TheNO_COLORenv var is also honored (https://no-color.org).
Error codes
When a command fails, the CLI returns a typed error like:SH-<DOMAIN>-<NUMBER>. Domains in active use today: AUTH, WEAR, HSI, CONS, ING, CFG, NET, INST, RT (runtime lifecycle), UPD (self-update). Codes are stable identifiers — search them in your shell history, link them in support tickets, branch on them in scripts (error_code field in JSON output). Renames or reassignments would be a breaking change.
Environment variables
| Variable | Purpose |
|---|---|
SYNHEART_API_URL | Override the API gateway base URL (auth + registry). |
SYNHEART_DIST_URL | Override the distribution CDN base URL. |
SYNHEART_INSTALL_DIR | Override the CLI install directory used by the installer scripts. |
SYNHEART_UPDATE_MANIFEST_URL | Override the release manifest URL used by synheart update (testing/staging). |
SYNHEART_NO_UPDATE_CHECK | Set to 1 to suppress the passive update notification. |
SYNHEART_SCENARIOS_DIR | Override the directory mock looks in for scenario YAML files. |
NO_COLOR | Any non-empty value disables ANSI color output (industry standard). |
CI | When set to anything truthy, suppresses the passive update notification automatically. |
Troubleshooting
Install/sync requires login
Install/sync requires login
Run
synheart login first. Artifact commands require a valid
access token. If you keep getting kicked back to login, your
token may have expired — synheart logout then synheart login
again.Mock stream port already in use
Mock stream port already in use
Use
--port with synheart mock start or check availability
with synheart doctor --port 8787. Port 8787 (WS), 8788 (SSE),
and 8789 (UDP) are the defaults; bumping --port shifts all
three together (--port N → WS=N, SSE=N+1, UDP=N+2).Need reproducible SDK versions in CI
Need reproducible SDK versions in CI
Commit
synheart.lock and run synheart sync in CI to install
pinned artifacts. Add synheart sync --check to catch lockfile
drift on PRs before the runtime version changes silently.`--platform flutter` returns no artifacts
`--platform flutter` returns no artifacts
The
flutter value is currently a no-op — runtime artifacts are
published per native target. Use --platform android or
--platform ios.`synheart local --https` fails to write to /etc/hosts
`synheart local --https` fails to write to /etc/hosts
--https mode needs sudo to add the 127.0.0.1 <domain> entry
and to trust the generated CA. Either run with sudo, or use
plain HTTP (synheart local, no --https) for development —
the SDK accepts both.Receiver pairing QR doesn't scan from Life
Receiver pairing QR doesn't scan from Life
Make sure the receiver and the Life app are on the same Wi-Fi
network and the receiver’s port (default 8788) isn’t blocked by
your firewall.
synheart doctor --port 8788 confirms binding.`SYNHEART_API_URL` not picked up
`SYNHEART_API_URL` not picked up
The CLI re-reads environment variables on every invocation, but
a stale
synheart.lock can pin the install URL. Delete
synheart.lock and re-run synheart install.