# Hardi agents V2 — cli

Contract: 2. Revision: 2026-11-03. Status: available to active verified Hardi accounts; Free, Plus and Pro retain their native limits.

Pilot installation (Node 22.23.4 or later in the Node 22 line): first download [the archive](https://hardi.app/agents/downloads/hardi-cli-2.1.3.tgz). Copy the archive to your terminal device if needed. Do not give SSO cookies or tokens to an agent. Then run:

```sh
npm install --global './hardi-cli-2.1.3.tgz'
hardi auth login --environment live --name "My agent"
hardi context --json
hardi schema --json
hardi actions simulate --file actions.json --json
hardi actions run --file actions.json --json
```

The archive requires no Next.js app, postinstall script, telemetry or background service. Its pinned dependency is the MIT-licensed MCP SDK. The @hardi/cli name, public registry ownership and public release are not approved; this pilot archive has a restricted pilot license.

Prefer macOS Keychain, Linux Secret Service or Windows current-user DPAPI. On a headless host explicitly choose --token-store file. Directory mode 700 and file mode 600, same owner, no symlink and outside a Git repository are required. --secret-file accepts a private credential file with a private parent directory for unattended execution; a matching profile is still mandatory. It becomes the profile’s active credential source; rotation and uncertainty are persisted in that same file, without requiring an OS keychain. Logout erases it. Configuration roots isolate OS credential namespaces too; keychain profiles from candidate.1-3 must reconnect once when upgrading to candidate.4. Archive installation and private file storage are qualified on macOS, Linux and Windows with Node 22.23.4. Windows DPAPI and ACL checks pass on a real Windows runner. Linux Secret Service requires an unlocked desktop session; headless qualification uses explicit file storage. Separate --profile values distinguish agents.

Use --file - to read JSON from stdin; use --json for a single JSON stdout response. Diagnostics and pairing instructions go to stderr. Complex commands accept the shared action fields; schema lists every field and permission.

Families: auth login/status/logout; profiles list/use/remove; context, doctor, schema, docs, version, example, completion; preferences get/update; settings get/update; training history/result/record-result; performances list/tests/create/update; cycles list/create/update/delete; templates list/get/create/update/add-workout/move-workout/remove-workout/delete; program check/run/simulate/resume/status; calendars list/create; exercises list/get; workouts list/get/get-batch/results/create/update/duplicate/move/trash/restore; folders list/create/update/reorder/trash/restore; planning get/results/add/update/move/reorder/swap/copy/shift/remove; actions run/simulate/list/get/retry/undo.

Exit codes: {"success":0,"invalid_request":2,"authentication":3,"permission":4,"conflict":5,"limit":6,"unavailable":7,"outcome_unknown":8,"interrupted":130}. SIGINT returns 130; it does not prove a sent mutation was cancelled.


Offline CLI recovery: hardi actions pending --profile live --json lists retained uncertain intents without authenticating. hardi actions export writes a new private metadata-only file; --request-id selects an intent and --include-content explicitly includes its original body. --output must be in a private directory outside repositories. No OAuth credential is exported. Resolve or export pending state before logout. Command and input validation runs before remote authentication. An invalid successful token response remains uncertain; never replay an old refresh token. Native plan capacities and technical pilot limits both apply; no Hardi AI or Energy is used.

Every write permission requires actions:read so an uncertain operation can recover its original receipt. Consent adds this dependency visibly; existing grants never gain it automatically. Removing receipt access removes dependent write permissions. If CLI logout reports program_running, remote revocation is reported separately and local state remains intact: stop the active program, then rerun the displayed logout command to finish cleanup.

Template reads: hardi_get_templates pages workouts followed by annotations with one nextCursor; collect items and template.dayEntries until complete. metadataOnly with templateId returns metadata and its version without content. hardi_get_template_workout reads and paginates the saved snapshot by templateId and itemId; templates:read is required. The library source may have changed independently. CLI: templates get <template-id> --metadata-only; templates get-workout <item-id> --template <template-id>. Private coach notes and media are excluded.

canUndo is evaluated against the connection's current inverse permissions. requiredUndoScopes and missingUndoScopes explain a permission refusal; native concurrency and protected dependencies are rechecked at execution. auth logout --local-only performs no remote revocation. Profile replacement removes previous credential storage after installing the new profile. Cleanup failures are reported and their locations retained privately for a later logout; incomplete logout retains the profile.

Expanded authorizations default to no absolute expiration. Temporary 1/7/30-day grants remain available. Access tokens expire after 15 minutes; rotating refresh credentials retain a finite rolling 30-day idle lifetime, capped by any grant deadline. Existing grants keep their deadline and selected resources. More permissions, all current/future calendars or a longer deadline require native consent, never an agent command. A long idle period, revocation or a security event can require reconnection.

calendars:create creates private personal calendars through native quotas, and authorizes this connection to use its own created calendars. calendar.create accepts ref, name, timelineType (dated/fixed), durationWeeks for fixed and optional description. Later actions in the same atomic batch can use calendarRef; earlier-step receipts can supply calendarId. Creation never enables sharing. Conditional actions:undo can retract only this connection's verified calendar creation, after dependent actions are reversed and only when no later protected use exists. CLI: hardi calendars create --name 'Twelve weeks' --timeline-type fixed --weeks 12 --json. hardi calendars list is paginated; follow nextCursor with the same page size. Explicit all_personal calendar access is dynamic and excludes Teams, followed, archived and foreign calendars.

workout-results:read is separate, unchecked by default, and permits read-only native coach-visible participant results on an authorized library workout or scheduled occurrence. hardi_get_workout_results takes source, exactly its workoutId/scheduledWorkoutId, blockId, optional category/division, limit (maximum 20) and cursor. Follow the same filters and page size; changes invalidate the cursor. Native anonymization and hidden-result rules apply. No athlete auth IDs, emails, avatars or unrelated history. CLI: hardi workouts results <workout-id> --block <block-id>; hardi planning results <occurrence-id> --block <block-id>.

Candidate.9 publishes self-contained action schemas plus input/output contracts for every tool: hardi schema --action workout.update; hardi schema --tool hardi_get_workout. Every action has a validated synthetic example via hardi example <type>; substitute current real IDs and versions. UTF-8 stdin/files are bounded at 256 KiB of raw bytes. Boolean --flag=false remains false; unknown/repeated options are rejected. Ordinary commands use a lightweight identity context. Detailed usage remains available through context, auth status and doctor.
