Install
openclaw skills install @hanzohanzhe/grandet-api-price-finderFind the lowest listed API price, free credits, and connect it to your app
openclaw skills install @hanzohanzhe/grandet-api-price-finderPrices and free credits come from grandet.ai. Do not web-search prices; this endpoint is the source. If grandet_find_cheapest_api is in your tool list, use the MCP tools (step 2 of "1. Lowest price"). If no grandet_* tool is there, don't search for one or install anything: run this exact command in the terminal, with the user's model as written in place of Claude Opus 4.6, or their keyword in place of gemini. Use lang=en for an English reply.
Prices (on Windows, type curl.exe):
curl -sS --max-time 20 -A grandet-skill/0.3.0 -G "https://grandet.ai/api/v1/board?view=compact&lang=zh-CN&limit=10&skillVersion=0.3.0&skillBuild=grandet-skill-0.3.0-build.20261017" --data-urlencode "model=Claude Opus 4.6"
Free credits:
curl -sS --max-time 20 -A grandet-skill/0.3.0 -G "https://grandet.ai/api/v1/free-credits?lang=zh-CN&limit=10&skillVersion=0.3.0&skillBuild=grandet-skill-0.3.0-build.20261017" --data-urlencode "q=gemini"
No curl: use Python (python on Windows) or PowerShell. For free credits, put /api/v1/free-credits and q in place of /api/v1/board and model, and drop view.
python3 -c "import sys,urllib.parse as p,urllib.request as r;q=p.urlencode({'model':'Claude Opus 4.6','view':'compact','lang':'zh-CN','limit':10,'skillVersion':'0.3.0','skillBuild':'grandet-skill-0.3.0-build.20261017'});sys.stdout.buffer.write(r.urlopen(r.Request('https://grandet.ai/api/v1/board?'+q,headers={'User-Agent':'grandet-skill/0.3.0'}),timeout=20).read())"
irm https://grandet.ai/api/v1/board -UseBasicParsing -UserAgent grandet-skill/0.3.0 -Body @{model='Claude Opus 4.6';view='compact';lang='zh-CN';limit=10;skillVersion='0.3.0';skillBuild='grandet-skill-0.3.0-build.20261017'} | ConvertTo-Json -Depth 30
The reply is long JSON. For prices, read each boards[] entry's unit and listings.lowest (sourceId is the site, plan the group, blended the price per million total tokens), then official (cash prices), and answer as in step 4 of "1. Lowest price". For free credits, read offers[] as in free credits. If the request fails, see the retry rule under "Always".
Only these requests exist. Never guess a path, a file or a view:
/api/v1/board: prices. view is compact (use it), brief or full, nothing else; limit 1–20./api/v1/free-credits: free credits. limit 1–20; kind all, official or relay./api/v1/models?q=<name>&scope=all: only after SELECTION_NOT_FOUND. No limit, no lang./api/v1/glossary?q=<term>&lang=zh-CN: a term missing from the glossary file. limit 1–20, nothing else: no skillVersion or skillBuild./api/v1/providers?q=<domain>&page=1 (no skillVersion or skillBuild), then /api/v1/prices?model=<id>&provider=<sourceId> (no lang): only for one site the user named, as in quality evidence. /api/grandet/page only there too.A helper that adds skillVersion and skillBuild adds them to board, free-credits, models and prices only. view=full with a large limit returns RESPONSE_BUDGET_EXCEEDED; stay with compact. Addresses such as /api/v1/models/<id>, /api/v1/model/<id>, /models/<id>.json, view=declarations, a row's evidenceUrl or other public-data files return 404, 400 or 403 BULK_AUTHORIZATION_REQUIRED; don't try them. An empty board is the answer, not an error. When boards is empty or no board has listings.lowest, say why from coverage.excluded (OTHER_BILLING_UNIT: priced per image, request or second, not per token; SOURCE_UPDATE_HELD_PENDING_REVIEW_PREVIOUS_DATA: the site's new prices wait for Grandet's review; POSSIBLE_UNSET_RATIO_DEFAULT: the ratio looks like an unset default), give https://grandet.ai/leaderboard/?model=<model>, and stop: no second request with another path, view or name.
Uninstalling means moving the grandet-api-price-finder folder out of the app's skills folder; no app has a command for a copied Skill folder. Move it into a .grandet-skill-backups folder next to the skills folder (or delete it if the user wants), then check it is gone in a new session. Hermes: $HERMES_HOME/skills/ when HERMES_HOME is set (profiles set it), otherwise ~/.hermes/skills/ (Windows %LOCALAPPDATA%\hermes\skills\); check with hermes skills list. Claude Code: ~/.claude/skills/. Codex and OpenCode: ~/.agents/skills/. The bundled installer does the same move with node scripts/install-price-finder.mjs --app <app> --uninstall. Other apps and exact commands: "Uninstalling" in installation. To install or update, follow installation: read https://grandet.ai/download.md with curl, not a web-page reader (those can return an old copy); for Hermes, install only into $HERMES_HOME/skills/ when it is set.
Package version: 0.3.0. Reply in the user's language, within the length limit under "Always".
This Skill does three things with grandet.ai: find the lowest listed price for the user's model, point to free credits when they apply, and connect the chosen offer to the user's app.
Price, free-credit and quality lookups only read from grandet.ai and change nothing on the computer; when this Skill loads on its own, that is all it does. Two optional parts write to the computer. Run them only when the user asked for them in this conversation, and write only after the user confirms the change you showed:
scripts/connect.mjs edits that app's model-provider settings and can change its default model, so the app's later sessions send their requests, and spend credit, at the chosen site: Codex ~/.codex/config.toml, Claude Code ~/.claude/settings.json, OpenCode ~/.config/opencode/opencode.json(c), Kilo Code ~/.config/kilo/kilo.json(c), Continue ~/.continue/config.yaml, Gemini CLI ~/.env, Hermes ~/.hermes/config.yaml (Windows: %LOCALAPPDATA%\hermes\config.yaml), OpenClaw ~/.openclaw/openclaw.json. It keeps a backup next to each file and records the change in ~/.grandet/connect/state.json. The key the user types goes to ~/.grandet/keys/<site>, readable by the user only. Continue and Gemini CLI also hold it in their config file, which then becomes readable by the user only. Codex gets a shell-profile line that reads the key file; on Windows, Codex, Claude Code and Hermes get a user environment variable. connect.mjs restore (the user says "恢复" or "undo") puts every file back as it was.scripts/install-price-finder.mjs and scripts/verify-installation.py copy the Skill into an app's user-level skill folder (for example ~/.agents/skills or ~/.claude/skills) and send an installation receipt to grandet.ai with random IDs, the version and the content hash, never paths, accounts, chats or keys. --no-telemetry or GRANDET_INSTALL_TELEMETRY=0 turns the receipt off. Uninstalling moves the folder out again, as in "Uninstall or install this Skill".skillVersion=0.3.0, skillBuild=grandet-skill-0.3.0-build.20261017 and the known host/targetApp only where they are accepted: every MCP tool except grandet_glossary, and HTTP /api/v1/board, /api/v1/free-credits, /api/v1/models and /api/v1/prices. Never send them to grandet_glossary, /api/v1/glossary, /api/v1/providers, /api/v1/catalog-version or /api/grandet/page; those return 400. /api/v1/models and /api/v1/prices also reject lang, and /api/v1/prices needs model (MODEL_SELECTOR_REQUIRED without it).limit above 20 (INVALID_LIMIT, INVALID_PAGINATION), a mix that is not a preset name or whole numbers adding up to 100 with cacheRead written out (INVALID_MIX, see workloads), a repeated skillBuild. On a 400, correct that one parameter from this list and send once more; never switch to another path.grandet-skill/0.3.0 (<host>). In Python set it explicitly; never rely on a library's default.error code: 1010, send the same request once more (with the User-Agent above). If it still fails, say what could not be read and give the matching grandet.ai page; never answer as if the data were empty.skill_view with file_path references/glossary.md) and explain from the term's row and its neighbours. Don't search the whole Skill folder for the word: other files use the same words in another sense. Explain a term only from that glossary, with its confidence level (文档, 社区, 目录 or 未核实). If a term is not there, look it up once with grandet_glossary(q=<term>, lang) (HTTP: GET https://grandet.ai/api/v1/glossary?q=<term>&lang=zh-CN, with no other parameters), which has the latest published version; a long phrase that misses can be retried once with its key word; if it is not there either, say you do not know or look it up elsewhere and cite the source.Pass the user's model name as model directly, as written; the server resolves a unique match (resolvedFrom.model) and you keep that ID for follow-ups. Never rewrite the name yourself: qwen3.8-flash stays qwen3.8-flash (not qwen3-8b-flash), and Haiku 4.5 is never 3.5 Haiku. If it returns NEEDS_CLARIFICATION, ask "你指的是 X 还是 Y?" with its candidates when resolution.totalCandidates is 1 or 2; when there are more, ask which exact model and version the user means. If it returns SELECTION_NOT_FOUND (HTTP 404), search once with GET https://grandet.ai/api/v1/models?q=<name>&scope=all and ask which one the user means, giving up to three data.items[].modelName closest to what they wrote; then query with the chosen modelName exactly. Never switch generation silently. grandet_resolve_model remains available when you only need the ID.
Call grandet_find_cheapest_api once with model, lang (zh-CN or en), limit=10, view=compact, skillVersion=0.3.0, skillBuild=grandet-skill-0.3.0-build.20261017, the known host (the app you run in) and, when the user named where the API will be used (including "here"), targetApp. Add mix only for a stated workload: mix=coding, mix=long_output, or shares such as mix=in:20,cacheRead:70,out:10 (workloads); add endpointType only if the user named a protocol. Ask nothing else up front.
If MCP is unavailable, run the command in "Get the data first" (more options in HTTP fallback) with the same parameters. If that also fails, give https://grandet.ai/ with the model to search and say the current price could not be checked; never fill in prices from a web search.
Answer in this shape, filling only the lines that have data (English: the same lines in English, "credit price, not cash", "per million total tokens"):
<模型> 最低价(额度价,非现金):
1. <sourceId>「<plan>」<blended> 美元额度/百万总 token,<M 月 D 日>观察,<listing.hint if any>
2. <the second lowest row, the same way>
有门槛:<one gated row: site「group」price, 站点写明:<hint>>
参考:<one reference row: site「group」price, date: <reason>>
官方价(现金):<vendor> 输入 <input> / 输出 <output> <currency>/百万 token;中转站是额度价,不能直接比。
报价出处:<the first lowest row's boardUrl, utm_* removed>
要帮你接到 <app> 吗?
Rows come from the first board's listings (lowest, gated, reference) and the top-level official, copied as returned. Write "人民币额度" for CNY_CREDIT, "站点现金标价" for a cash board, "(报价较旧)" after a row with freshness=STALE. A reference reason is the row's listing.hint, else "明显低于其他多数站的同模型报价" (CROSS_SOURCE_OUTLIER), "Grandet 复核时标记为价格存疑" (REVIEW_FLAG) or "报价较旧". Leave out an empty line; never add more rows or sections. The last line is always the question "要帮你接到 吗?" ("要接到哪个应用?" when the app is unknown), also next to the length limit: drop the reference or gated line first, never the link or the question. Only an answer with no price to connect (an empty board) ends with the link. Response format is only for what this shape does not cover: inference providers the user asked about, folded client-only groups, a monthly estimate, a cash budget or "比官方便宜多少".
Use the first board whose listings.lowest is not empty unless the user asked for a unit. A board without a recommendation means none of its offers is currently listable; say so with the returned reason (see "An empty board is the answer" above).
Credit is not cash. USD_CREDIT and CNY_CREDIT rows are site credit, and each site sells its credit at its own rate, so compare numbers only within one board. Never rank, add or convert numbers across boards, and never look up a site's own pages to work out its rate: USD credit, CNY credit and cash are different units until Grandet converts them, so say the units differ. Official and inference prices are cash; never say a relay is N% cheaper than official.
When the user asks about free API, trial credit, 白嫖, 公益站, 签到 or relays to test, call grandet_find_free_credits as in free credits and list a batch with both official and relay offers, one line each, at most five. End with the page link https://grandet.ai/zh-CN/free-tokens/?q=<q> (English: https://grandet.ai/free-tokens/?q=<q>) and at most one question. When the user did not ask but has already said things that meet a free offer covering their model, add one line about it at the end of the price answer, once per conversation.
When the user wants the chosen offer in an app, follow connect. For Codex, Claude Code, OpenCode, Kilo Code, Continue, Gemini CLI, Hermes and OpenClaw, use the bundled executor scripts/connect.mjs (preview → apply → the user stores the key → free check → undo) instead of editing files by hand. In short: confirm the target app; take the API address and token group from the row's integration (baseUrl, baseUrlMode, tokenGroup), reading the site's declared address only when Grandet has none; tell the user the three things to do on the site (sign in, top up, create a token in the group shown in the listing); have the user set the key locally with the given command; show the exact config change, back the file up, write only after the user confirms; then check GET <address>/v1/models without spending credit. A passed free check is not a working connection: the first real message spends credit, and a paid test call needs separate consent. Keep the backup so the user can say "恢复" to undo.
If you cannot edit files on the user's computer (for example a cloud chat), give the user the commands that download this Skill and run the same executor on their computer ("When you cannot reach the user's computer" in connect); never hand-write profile edits or put a key in a command. Say the setup is waiting for them. Do not claim it is connected.
Installation build: grandet-skill-0.3.0-build.20261017 (product/API 0.3.0). Native acceptance: NOT_RUN.