kronan
v0.1.1
Published
Kronan CLI (cart + products + favorites + orders)
Maintainers
Readme
Krónan
CLI + API client for Krónan (Iceland).
Requirements
- Node.js 18+ (or Bun)
Install
CLI (global):
npm install -g kronanRun without installing:
npx kronan --helpLibrary:
npm install kronanQuick start (CLI)
export KRONAN_AUTH_TOKEN="..."
kronan auth set --from-env
kronan products search --query "mjolk"More help:
kronan --help
kronan auth --helpAuth (CLI)
You store the raw JWT (no prefix). The CLI adds the CognitoJWT prefix automatically when it sends requests.
Store once (recommended):
export KRONAN_AUTH_TOKEN="..."
kronan auth set --from-env
kronan auth showOne-off usage (no storage):
KRONAN_AUTH_TOKEN="..." kronan products search --query "mjolk"
kronan products search --query "mjolk" --token TOKENToken storage (override with KRONAN_CONFIG_DIR):
~/.kronan/auth-token~/.kronan/refresh-token
The CLI also loads .env from the current directory (existing environment values are not overwritten).
How to obtain a token
Method A (backend request header):
- Sign in to the Krónan web app in your browser.
- Open DevTools → Network.
- Reload the page and click a request to
https://backend.kronan.is/. - In request headers, copy the
Authorizationvalue that starts withCognitoJWT. - Paste the token (without the
CognitoJWTprefix) intoKRONAN_AUTH_TOKEN.
Method B (OAuth token response):
- In DevTools → Network, find the request to
https://auth.kronan.is/oauth2/token. - Copy
id_tokenoraccess_tokenfrom the JSON response. - Set
KRONAN_AUTH_TOKENto that raw token value.
Keep tokens private. Treat them like passwords.
Auto-refresh (optional)
export KRONAN_REFRESH_TOKEN="..."
export KRONAN_COGNITO_TOKEN_URL="https://auth.kronan.is/oauth2/token"
export KRONAN_COGNITO_CLIENT_ID="..."
kronan auth setup --from-env
kronan auth refreshAbout the client ID:
- It identifies the Krónan app in Cognito/OAuth.
- It is required for refresh, and must match the app that issued your refresh token.
- It is not a secret by itself.
- It is the same for all Krónan users (not per user or per machine).
Where to find it:
- DevTools → Network →
https://auth.kronan.is/oauth2/token(POST body hasclient_id=...). - Or
https://auth.kronan.is/oauth2/authorize?...&client_id=.... - Not the same as the Google OAuth
client_id(accounts.google.com/...).
Common CLI flows
Browse + add to cart:
kronan products search --query "mjolk"
kronan cart add --sku 100230536 --qty 1
kronan cart showCheckout (delivery):
kronan order slots --type delivery --query-json '{"chain":"kronan"}'
kronan order apply-shipping --slot-id SLOT_ID
kronan order contact --body-file contact.json
kronan order payment --body-file payment.json
kronan order finishOrders export:
kronan orders export --since 2025-01-01orders export writes a JSON snapshot and a line-level CSV to ~/.kronan/orders-last-year.json and ~/.kronan/orders-last-year-lines.csv by default.
Command reference (CLI)
Global options:
--token TOKENoverride auth token--base-url URLAPI base URL--group-id IDCustomer group id--rate-limit-ms Nminimum delay between requests--jsonprint raw JSON response
Auth:
kronan auth show [--raw]
kronan auth set --token TOKEN
kronan auth set --from-env
kronan auth set-refresh --token TOKEN
kronan auth set-refresh --from-env
kronan auth refresh
kronan auth clearProducts:
kronan products search --query TEXT [--page N] [--page-size N]
kronan products sku-list --sku SKU [--sku SKU]
kronan products all-items [--limit N]Favorites:
kronan favorites products
kronan favorites recipesCart:
kronan cart show
kronan cart add --sku SKU --qty N
kronan cart add --line SKU:QTY [--line SKU:QTY]
kronan cart set --sku SKU --qty N
kronan cart remove --sku SKU
kronan cart clearOrder:
kronan order show
kronan order slots --type delivery|pickup [--query-json JSON|--query-file PATH]
kronan order reserve-slot-token
kronan order apply-shipping --slot-id ID [--address-id N]
kronan order contact --body JSON|--body-file PATH
kronan order payment --body JSON|--body-file PATH
kronan order finish
kronan order finish-invoice --body JSON|--body-file PATHOrders:
kronan orders ongoing [--limit N] [--page-size N]
kronan orders status --token ORDER_TOKEN
kronan orders export [--since DATE] [--out PATH] [--page-size N]Stats:
kronan stats most-bought [--limit N] [--out PATH] [--page-size N]Tip: add --json to print raw JSON responses for scripting.
Environment variables (CLI)
KRONAN_AUTH_TOKEN(required for authenticated calls)KRONAN_REFRESH_TOKEN(for auth refresh)KRONAN_COGNITO_TOKEN_URL(for auth refresh)KRONAN_COGNITO_CLIENT_ID(for auth refresh)KRONAN_BASE_URL(defaults tohttps://backend.kronan.is/)KRONAN_GROUP_ID(setsCustomer-Group-Idheader)KRONAN_CHECKOUT_ID(defaults todefault)KRONAN_RATE_LIMIT_MS(minimum delay between requests, default 200)KRONAN_CONFIG_DIR(override token storage directory)
Troubleshooting
Missing auth token:
export KRONAN_AUTH_TOKEN="..."
kronan auth set --from-envExpired signature / 401:
export KRONAN_REFRESH_TOKEN="..."
export KRONAN_COGNITO_TOKEN_URL="https://auth.kronan.is/oauth2/token"
export KRONAN_COGNITO_CLIENT_ID="..."
kronan auth refreshRefresh token issues:
If refresh tokens keep failing, consider creating a separate Krónan user for your bot and sign in with Google Auth instead of Auðkenni, which can be unreliable for refresh.
Invalid date for --since (orders export):
kronan orders export --since 2025-01-01Tokens are stored at ~/.kronan/ by default (override with KRONAN_CONFIG_DIR).
JavaScript/TypeScript usage
Minimal usage:
import { KronanClient } from "kronan";
const client = new KronanClient({
authToken: process.env.KRONAN_AUTH_TOKEN,
});
const stores = await client.storesList();
console.log("stores:", stores.length);Search products:
const results = await client.productsRawSearch(
{ query: "banana", page: 1, pageSize: 5 },
{ withDetail: true },
);
console.log(results.count);Add items to the smart checkout cart:
await client.smartCheckoutsLinesCreate("default", {
lines: [{ sku: "100230536", quantity: 1 }],
});Optional auto-refresh configuration:
const client = new KronanClient({
authToken: process.env.KRONAN_AUTH_TOKEN,
refreshToken: process.env.KRONAN_REFRESH_TOKEN,
cognitoTokenUrl: process.env.KRONAN_COGNITO_TOKEN_URL,
cognitoClientId: process.env.KRONAN_COGNITO_CLIENT_ID,
onAuthTokenRefreshed: (next) => {
// Persist refreshed token if you want.
console.log("refreshed", next.slice(0, 8));
},
});The client automatically refreshes the auth token on a 401 response that indicates an expired signature.
