Helmet

v0.3.1

Manage your Helmet library accounts (Helsinki capital region) from an AI agent — renew loans, place and cancel holds, view fines, and search the catalog acro...

1· 111·1 current·1 all-time
Security Scan
VirusTotalVirusTotal
Benign
View report →
OpenClawOpenClaw
Benign
high confidence
Purpose & Capability
Name/description match the requirements and behavior: the skill invokes a 'helmet' CLI, offers account/hold/renew/fines/search actions, and declares the same CLI in its install spec. The declared config path (~/.config/helmet/config.json) and session cache are appropriate for a local library-account client.
Instruction Scope
SKILL.md instructs only to run the 'helmet' CLI with --json, perform login once per card, and use profile flags. It does not direct the agent to read unrelated system files or transmit data to unexpected endpoints. It does document reading/writing local config and session cookies (expected for this use).
Install Mechanism
Installation is via an npm package (@helmet-ai/helmet) which is a common, expected mechanism for providing the 'helmet' binary. Installing npm packages runs publisher code on the machine during install — normal but a moderate risk compared with no-install skills. No suspicious download URLs or extract-from-unknown-host steps are present.
Credentials
The skill requests no environment variables and only a local config path. It stores card numbers and PINs in ~/.config/helmet/config.json and session cookies under ~/.config/helmet/sessions. This is proportionate to the stated functionality, but these are sensitive credentials — their presence is expected but worth considering before installing.
Persistence & Privilege
The skill is not always-enabled and does not request elevated platform privileges. It does allow the agent to call the CLI (the platform default allows autonomous invocation); combined with stored credentials, that means the agent could perform account actions (renewals, holds) if permitted—this is consistent with the skill's purpose.
Assessment
This skill appears to be what it says: a CLI client for Helmet (Helsinki libraries). Before installing, verify you trust the npm package publisher (@helmet-ai) — npm packages execute code at install time. The CLI will store library card numbers and PINs in ~/.config/helmet/config.json and session cookies under ~/.config/helmet/sessions (permissions claimed as 0600). If you keep multiple family profiles, the agent can query all of them (and perform non-destructive fan-out) so consider limiting stored profiles or requiring manual confirmation for destructive actions. As a precaution: run 'helmet login' interactively first to create the config, inspect the config file permissions, and consider whether you want the agent to act autonomously with those stored credentials.

Like a lobster shell, security has layers — review code before you run it.

Runtime requirements

Binshelmet

Install

Install Helmet CLI (npm)
Bins: helmet
npm i -g @helmet-ai/helmet
latestvk979m7718pxaxrzgst5v9j336x8503gk
111downloads
1stars
5versions
Updated 2d ago
v0.3.1
MIT-0

Helmet Library Skill

Access the Helmet library system (Helsinki Metropolitan Area libraries) from an AI agent. Query loans, renew books, check holds and fines — for one account or many family accounts at once, via the helmet CLI with --json output.

What you can ask your agent

  • "Is anything overdue for me or the kids at the library?"
  • "Renew everything that's due this week."
  • "How many holds do I have, and which are ready for pickup?"
  • "Place a hold on Dog Man Scarlet Shedder."
  • "Cancel my hold on the Finnish language audiobook."
  • "Do I owe any fines right now?"
  • "Search the Helmet catalog for 'Tove Jansson'."

Quick Start

# Install
npm install -g @helmet-ai/helmet

# First-time login — run once per library card (saves credentials locally)
helmet login

# Full account overview (single account)
helmet summary --json

# Family overview (all saved profiles)
helmet summary --all-profiles --json

Preflight (recommended before bulk queries)

helmet status --json
helmet status --all-profiles --json

Verifies each saved profile's session is live. Exit code 0 means authenticated; 2 means the user needs to run helmet login. Run this once at the start of a multi-step task to avoid partial failures halfway through.

Profiles

The CLI stores one or more library accounts as profiles. Use these when acting for a user or a family:

  • One profile saved — commands run against it by default.
  • Multiple profiles saved — commands run against the last-used profile unless you pass --profile or --all-profiles.

Profile selection flags

FlagPurpose
--profile <selector>Target one profile. Selector is any of: display name (Alice), unique display-name prefix (al), card number, or full id (helmet|<card>).
--all-profilesFan out across every saved profile. Works on summary and loans list. Mutually exclusive with --profile.

--all-profiles is not supported on loans renew, holds place, holds cancel (all destructive — always target one profile), search (unauthenticated), or login.

Fan-out JSON shape

--all-profiles --json wraps output in a per-profile array. Each row is independent: one profile failing does not block others.

[
  {"profile": {"id": "helmet|...", "displayName": "Alice"}, "ok": true,  "data": { /* same shape as single-profile --json */ }},
  {"profile": {"id": "helmet|...", "displayName": "Bob"},   "ok": false, "error": "AuthenticationError: ...", "errorCode": "AUTH_REQUIRED"}
]

Exit code is 0 if at least one profile succeeded, 1 if all failed. When reporting partial failures to the user, key on errorCode (stable) rather than the free-form error string (which embeds the raw exception message).

helmet profiles list --json

Enumerate saved profiles. Returns id, displayName, cardNumber, and lastUsedAt for each.

helmet profiles rename <selector> <new-name> / helmet profiles remove <selector>

Local-only management of saved profiles (no Helmet API calls).

Session cache

Each profile's authenticated cookie jar is persisted at ~/.config/helmet/sessions/<id>.json (mode 0600). The first command per profile walks the full Finna login handshake (~2.7s); subsequent commands skip straight to the data request (~1.3s). Stale cookies are handled transparently — if Finna redirects to the login page, the session auto-re-authenticates using the stored PIN. You do not need to manage the cache explicitly; it is cleared automatically on helmet login, helmet profiles remove, or an unrecoverable AuthenticationError.

Commands

All commands accept --json for machine-readable output. Always use --json when calling from an agent.

helmet summary --json

Returns a complete account snapshot: loans (with overdue/due-soon flags), holds (with pickup-ready status), and fines. Start here — one call gives you everything needed for triage. Add --profile <selector> for a specific person or --all-profiles for a whole family.

helmet loans list --json

List checked-out items with title, author, due date, due status (ok, due, overdue), and whether renewable. Supports --profile and --all-profiles.

helmet loans renew <id> --json

Renew a specific loan by its ID. Returns success/failure with new due date or error code. Requires --profile <selector> when multiple profiles exist (the CLI will not auto-pick a profile for destructive operations).

helmet loans renew --all --json

Renew every renewable item on one profile. Same profile-targeting rule as above — pass --profile <selector> explicitly.

helmet holds list --json

List current holds. helmet holds (no subcommand) is an alias. Each row has shape:

{
  "id": "12345678",
  "title": "Sample Book Title",
  "author": "Last, First",
  "pickupLocation": "Sample Branch",
  "queuePosition": null,
  "pickupDeadline": "15.1.2026",
  "createdDate": "1.1.2026",
  "shelfLocation": "A 000",
  "status": "available_for_pickup",
  "cancelable": true,
  "fetchedAt": "2026-01-01T12:00:00.000Z"
}

Field meanings:

  • status: "pending" (in queue) / "in_transit" (on its way to the pickup branch) / "available_for_pickup" (arrived — the user must go collect it).
  • pickupDeadline (Finnish "nouto viimeistään"): the date the hold will be cancelled and passed to the next patron if uncollected. Only populated when status === "available_for_pickup"null otherwise. Date is in Finnish format D.M.YYYY. If the user misses this date, Helmet charges a no-pickup fee and may suspend borrowing for a period — agents should surface this date prominently in reminders.
  • shelfLocation (Finnish "Varaushylly"): the exact shelf code inside the branch where the arrived hold is waiting (e.g. A 000). Only populated for arrived holds. Include it in pickup reminders so the user can walk straight to the shelf.
  • createdDate (Finnish "Luotu"): when the hold was placed. Informational, not actionable.
  • queuePosition: for pending holds, the user's position in the reservation queue (null once the hold is in transit or arrived).

helmet holds place <record-id> [--comment <text>] --json

Place a title-level hold on a Helmet catalog record. The record-id comes from helmet search (e.g. helmet.2613471). The CLI uses the default pickup location preselected by Helmet in the hold form. The --comment field is used only for bookmobile pickup stops. Returns { success, message }; on success, message is typically "Varauspyyntö onnistui.". Requires --profile <selector> when multiple profiles exist — the CLI will not auto-pick a profile for a destructive/state-changing operation.

helmet holds cancel <hold-id> --json

Cancel an active hold. The hold-id is the id field from helmet holds list --json. Returns { success, message }; on success, message is typically "1 varaus(ta) poistettu.". Same profile-targeting rule as place — pass --profile <selector> explicitly.

helmet fines --json

List individual fines and total amount owed.

helmet search <query> --json

Search the Helmet catalog. Unauthenticated — --profile has no effect and --all-profiles is rejected.

helmet status [--json] [--all-profiles]

Lightweight preflight: reports whether the selected profile (or all profiles) has a live authenticated session. Exit code 0 if authenticated, 2 if helmet login is needed. With --json:

{
  "version": "0.3.0",
  "profile": {"id": "helmet|...", "displayName": "Alice"},
  "authenticated": true,
  "checkedAt": "2026-04-14T12:34:56Z"
}

On --all-profiles, emits {version, checkedAt, profiles: [...]} where each row carries authenticated: bool and, on failure, errorCode: "AUTH_REQUIRED". Run this before multi-step tasks.

helmet version / helmet --version / helmet -V

Print the CLI version (e.g. 0.3.0). No auth, no network. Useful when an agent needs to record which helmet build produced a report.

Handling authentication errors

When the stored session expires, the PIN has changed, or Finna invalidates the session for any reason, helmet exits with code 2 and (with --json) emits:

{
  "ok": false,
  "errorCode": "AUTH_REQUIRED",
  "errorName": "AuthenticationError",
  "message": "Helmet session expired and re-authentication failed — run `helmet login` to refresh credentials.",
  "recovery": "Run `helmet login` to refresh your library credentials."
}

On --all-profiles, one row may fail with errorCode: "AUTH_REQUIRED" while others succeed. Report the affected person by displayName and continue with the rest.

Agent recovery procedure

  1. Detect — check the exit code (2 = auth) or the errorCode: "AUTH_REQUIRED" field in the JSON output.
  2. Report — tell the user which profile(s) need re-authentication, referring to them by displayName (not card number).
  3. Do NOT run helmet login yourself. It is interactive and prompts for a PIN that only the user knows. Ask the user to run helmet login locally.
  4. Retry the original command after the user confirms they've re-logged in. The CLI's stale session cache is cleared automatically when auth fails, so the retry will attempt a fresh login.
  5. Do NOT loop. If the retry still returns AUTH_REQUIRED, stop and ask the user — do not keep retrying. The most likely cause is a changed PIN that the stored credential no longer matches, which only a fresh helmet login can fix.

Triage Guidance

When reporting to the user, prioritize items by actionability:

PriorityConditionAction
URGENTOverdue items (dueStatus: "overdue")Renew immediately or alert user
URGENTFines > 0 EURAlert user — fines block borrowing
URGENTReady-for-pickup hold whose pickupDeadline is today, tomorrow, or in the pastAlert user to collect today — missing the deadline cancels the hold and charges a no-pickup fee
HIGHLoans due within 3 days (dueStatus: "due" or in loansDueSoon)Renew if possible, otherwise warn
HIGHReady-for-pickup hold (status: "available_for_pickup") with pickupDeadline within 7 daysRemind user to pick up. Always cite the exact deadline date and the shelfLocation so they can go straight to the shelf at pickupLocation.
MEDIUMLoans due within 7 daysMention in summary
LOWHolds with queue position ≤ 2Mention — pickup may come soon

Formatting hold reminders for users

When surfacing a ready-for-pickup hold, prefer a line like:

"Pick up Sample Book Title at Sample Branch (shelf A 000) by 15.1.2026 — otherwise the hold is cancelled and a no-pickup fee applies."

Always include: title, pickupLocation, shelfLocation (when present), and pickupDeadline. Dates are already in Finnish D.M.YYYY format — keep them as-is; do not reformat to ISO unless the user is clearly a developer consuming JSON.

Recommended workflow (single person)

  1. Run helmet summary --json (or with --profile <name>).
  2. Check for URGENT items first — auto-renew overdue loans if renewable.
  3. Surface HIGH items prominently.
  4. Mention MEDIUM/LOW items briefly.
  5. If renewals fail, include the error code in your report.

Recommended workflow (family)

  1. Run helmet summary --all-profiles --json — one call covers everyone.
  2. Flatten rows where ok: true. For each ok: false row, mention the person's name and that their data could not be fetched (don't abort the whole report).
  3. Group findings by urgency first, by person second — one overdue book across any family member is more actionable than "here is Alice's summary, here is Bob's summary".
  4. For renewals, issue one helmet loans renew --all --profile <name> per person that has renewable overdue loans. Never fan out renew.
  5. Prefer referring to people by displayName in user-facing output; keep id for internal routing.

Scripts

The wrapper script at scripts/helmet-cli.sh can be used as a fallback when the helmet binary is not on PATH:

bash skills/helmet/scripts/helmet-cli.sh summary --all-profiles --json

Troubleshooting

Empty holds / loans / fines arrays with no error — this was a bug in helmet ≤ 0.1.1 where an expired session was parsed as "no data" instead of raising an auth error. Upgrade to 0.2.0+:

npm install -g @helmet-ai/helmet@latest
helmet --version   # must be ≥ 0.2.0

If you still see empty results after upgrading, run helmet status --json — if it reports authenticated: false, the user needs to run helmet login. Real empty results (no holds, no loans) after 0.2.0 are legitimate; only pre-0.2.0 masked auth failures as empty.

Comments

Loading comments...