[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-openrouter-spawn-ori-eval":3,"mdc--t84wz3-key":34,"related-org-openrouter-spawn-ori-eval":1913,"related-repo-openrouter-spawn-ori-eval":2056},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":24,"repoUrl":25,"updatedAt":26,"license":27,"forks":28,"topics":29,"repo":30,"sourceUrl":32,"mdContent":33},"spawn-ori-eval","run model evaluations with Ori","Spawn Ori as a subprocess to run a model eval on a pinned harness and model, then relay the results. Use when the user asks which model they should use, wants to compare or bake off models, wants to measure whether their agent or prompt does the right thing, wants to catch regressions in agent behavior, or asks how good their current model is. Applies to any codebase in any language. Do not use for plain unit tests that involve no model, and do not use to re-run an eval that already exists (run `ori eval \u003Cfile>` directly).",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"openrouter","OpenRouter","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fopenrouter.png","OpenRouterTeam",[13,17,20,23],{"name":14,"slug":15,"type":16},"Benchmarking","benchmarking","tag",{"name":18,"slug":19,"type":16},"LLM","llm",{"name":21,"slug":22,"type":16},"Evals","evals",{"name":9,"slug":8,"type":16},187,"https:\u002F\u002Fgithub.com\u002FOpenRouterTeam\u002Fskills","2026-07-30T05:53:35.99701",null,26,[],{"repoUrl":25,"stars":24,"forks":28,"topics":31,"description":27},[],"https:\u002F\u002Fgithub.com\u002FOpenRouterTeam\u002Fskills\u002Ftree\u002FHEAD\u002Fskills\u002Fspawn-ori-eval","---\nname: spawn-ori-eval\ndescription: Spawn Ori as a subprocess to run a model eval on a pinned harness and model, then relay the results. Use when the user asks which model they should use, wants to compare or bake off models, wants to measure whether their agent or prompt does the right thing, wants to catch regressions in agent behavior, or asks how good their current model is. Applies to any codebase in any language. Do not use for plain unit tests that involve no model, and do not use to re-run an eval that already exists (run `ori eval \u003Cfile>` directly).\n---\n\n# Spawn Ori Eval\n\nYou are not going to write this eval. You are going to install Ori if needed, hand the request to an Ori run, keep the user in the loop while it works, and relay what comes back.\n\nThat split is deliberate. Ori pins the harness and the model that author and grade the eval, so the bench is identical no matter which coding agent the user happens to be driving. An eval you author yourself is not reproducible, and a score change has to mean the user's agent changed, not the environment.\n\nYour job is the part Ori cannot do: you are the user's only connection to a run that is otherwise invisible. Explain what you started (section 3), carry Ori's questions to them and their answers back (section 5), and relay the result in full (section 8).\n\n## 1. Preflight\n\nRun these in order. Do not skip ahead on a failure.\n\n1. `command -v ori`\n\n   If missing: `curl -fsSL https:\u002F\u002Fopenrouter.ai\u002Flabs\u002Fori\u002Finstall.sh | sh`\n\n   It installs to `~\u002F.local\u002Fbin`, which is often not on PATH in a non-login shell. Re-check with `~\u002F.local\u002Fbin\u002Fori --version` before reporting failure.\n\n2. Auth: recommend `ori login`, which stores an Ori-scoped credential at `~\u002F.ori\u002Fcredentials.json`. Do not tell the user to export a raw `OPENROUTER_API_KEY`. If the credential is missing, STOP and hand it back to the user. `ori login` opens a browser and you cannot complete it. Tell them to run it themselves. In Claude Code, tell them to type `! ori login`.\n\n3. `command -v bun`. Ori executes `*.eval.ts` through Bun.\n\nNever print, echo, or log the contents of `credentials.json` or any other value you read out of a `.env` file or config while searching. Name the key, never the value: `OPENAI_API_KEY at .env:4`, not what it is set to.\n\n## 2. Keep the Q&A in `create-eval`, but relay it\n\n`spawn-ori-eval` does not do the scoping interview. Ori's `create-eval` skill already asks which surface to eval, what it needs to be good at, what real data to use, the cost ceiling, and the baseline model. This skill just hands that request off.\n\nDo not ask the user anything **before** spawning — not even \"what do you want to eval?\". If the request is vague or empty, spawn anyway and pass through whatever the user said verbatim; `create-eval` asks its questions inside the Ori run.\n\nThat is not a licence to stay silent for the whole run. When Ori asks a question mid-run, you MUST put it to the user and send back their answer (section 5). \"Do not ask up front\" and \"relay Ori's questions\" are both true: the interview belongs to Ori, and the user belongs to you.\n\n## 3. Say what is about to happen\n\nBefore spawning, tell the user in plain language what they just set in motion. A wall of tool calls with no explanation is the single most common complaint about this skill.\n\nCover, in your own words and without the jargon below:\n\n- **What Ori is.** A separate agent that writes and runs the eval, with its own pinned harness and model.\n- **What it will do.** Pick what to measure, write a `*.eval.ts` under `evals\u002F`, and score models against it.\n- **What it costs.** Roughly 10–30 minutes and a few dollars of credits. Say this up front, not after.\n- **What they will get.** A scored table comparing the models.\n- **That it may ask them something.** Tell them you will bring any question to them. This is what makes the interruption in section 5 feel intentional rather than random.\n- **What got installed**, if you installed it: the `ori` binary, at `~\u002F.local\u002Fbin\u002Fori`.\n\nNever use this skill's internal vocabulary in anything the user reads. \"Preflight\", \"spawn\", \"verbatim\", \"harness\", \"elicitation\", \"correlationId\", \"the result line\", \"stdout\" are for you, not them. A user who sees \"Preflight passes. Spawning Ori with your request verbatim\" has been told nothing.\n\nWhile the run is going, relay progress from the stream — picked a target, wrote the eval, running model 2 of 3 — rather than reporting that it is \"still running\". A 25-minute silence is where trust dies.\n\n## 4. Spawn it\n\n```bash\nori code -p \"\u003Ctask>\" --output jsonl --interactions forward\n# For a long prompt:\nori code --prompt-file \u002Ftmp\u002Fori-task.txt --output jsonl --interactions forward\n```\n\n- `-p` and `--prompt-file` are mutually exclusive. Positional prompts are rejected.\n- `ori code -p \"\u003Ctask>\"` runs without a TTY and exits when the prompt completes: exit code 0 on success, nonzero on failure. A plain piped run streams Ori's reply as prose. Add `--output jsonl` for the structured stream — one `{\"kind\":\"event\",\"event\":...}` line per runtime event, then a final `{\"kind\":\"result\",\"ok\":...,\"sessionId\":\"...\"}` line; Ori's reply text is the concatenated `assistant.text.delta` payloads. Prefer `--output jsonl`: it is the only stream that carries the `sessionId`.\n- `--interactions forward` is what lets you answer Ori's mid-run questions; see section 5. Without it the run declines each question itself and picks for you, so the eval measures Ori's guess rather than what the user cares about.\n- Do NOT pass `--model` or `--harness`. Overriding the pin destroys the reproducibility that is the only reason to use Ori.\n- Run from the repo root so Ori can read the real prompts.\n- One invocation. Do not loop the run once per candidate model. Comparing models is `ori eval`'s job, not yours.\n- The first `ori` run on a machine creates `~\u002F.ori\u002Fglobal` and fetches templates over the network. Expect a pause of roughly 30 seconds and do not treat it as a hang.\n\n## 5. Answer Ori's questions\n\nWith `--interactions forward`, a question Ori asks stays **pending** — the run is genuinely waiting on you. Handle it:\n\n1. **Read it off the stream.** An `elicitation.requested` event carries `payload.message`, `payload.fields[]` (each with a `name`, a `type`, and often `options`), and a `correlationId`. A `permission.requested` event carries `payload.options`. Note the field **`name`** — you need it verbatim in step 3.\n2. **Put it to the user with your own question UI** (in Claude Code, `AskUserQuestion`). Preserve Ori's options one-for-one, keep \"Other\" as free text, and translate its wording into plain language. Do not show them the raw event, the `correlationId`, or the word \"elicitation\".\n\n   **Show the message, then the picker — both, in that order.** Ori's `payload.message` often carries context the option labels cannot (for the surface question it is a markdown table of surface \u002F model today). Print that message as normal text in your reply first, then call your question UI right below it with just the short option names. The table explains; the picker collects. Collapsing the table into the option descriptions loses it, and skipping it leaves the user picking between bare labels.\n3. **Write the answer back to the run's stdin**, one JSON object per line, keyed by that `correlationId`:\n\n   ```json\n   {\"kind\":\"respond\",\"correlationId\":\"ixn-0\",\"action\":\"accept\",\"content\":{\"\u003Cfield-name>\":\"\u003Cthe user's choice>\"}}\n   ```\n\n   **The keys in `content` are the field `name`s from the request**, not a fixed schema. If `payload.fields` is `[{\"name\":\"surface\", …}]`, send `\"content\":{\"surface\":\"…\"}`. Copying a `\"value\"` from an example when the request asked for `surface` produces a well-formed line that is accepted and then maps to nothing, which is worse than not answering: the run proceeds as if the user had chosen. Read the name off the event every time.\n\n   Use `action` (`accept` \u002F `decline` \u002F `cancel`, with `content` carrying the fields on an accept) for a question form, and `optionKind` for a permission request. You send only the decision; which request it answers and which session it belongs to come from the request itself.\n\nNotes that matter:\n\n- **Answer promptly.** A forwarded question falls back to being declined after `--interaction-timeout` (default 300s), and then Ori picks for itself as before. If the user may be slow, raise it: `--interaction-timeout 900`.\n- **A malformed line is skipped**, not fatal — but the request then just sits until it times out, so get the shape right.\n- **Never invent an answer.** Forwarding exists so a human decides. If you cannot reach the user, let it time out rather than guessing on their behalf; a guessed target silently invalidates the whole eval.\n- **Never answer a permission request with a blanket allow** to keep things moving. Pass it to the user.\n- **A question in plain prose** (rather than a structured request) ends the turn instead of pending. Answer that by resuming: `ori code --session \u003CsessionId> -p \"\u003Canswer>\" --output jsonl`, chaining until the eval is written and run.\n\n## 6. The task prompt\n\nWrite this to `\u002Ftmp\u002Fori-task.txt` — the file used by the section 4 command — and fill every angle-bracket slot. If you use a different path, use it in the spawn command too; an unwritten path produces an empty prompt and Ori does nothing.\n\n```text\nUse the create-eval skill.\n\nUser request: \u003Cverbatim request>\nRepo context pointers: \u003Cpaths>. Read these first.\n\nWrite the eval to evals\u002F\u003Cfeature>\u002F\u003Cname>.eval.ts and run it with ori eval. Do\nnot create or modify anything outside the top-level evals directory.\n```\n\n## 7. Never do these\n\n- **Never spawn your own subagent to \"do an eval.\"** It produces a plausible table with no pinned bench behind it, which is worse than no answer.\n- **Never write the eval yourself.** Ori's `create-eval` skill fires automatically inside the run.\n- **Never put the eval in the repo's existing test framework.** `ori eval` discovers `*.eval.ts` only. A pytest, vitest, or Go test file silently never runs, and silence reads as passing.\n- **Never hand-roll raw API calls and present the numbers as an Ori eval.** If you measure something another way, label it clearly as such.\n- **Never name model ids or prices from memory.** They go stale between releases.\n- **Never report a winner without the production model in the table.** \"No change\" is a valid and useful result.\n- **Never answer Ori's questions on the user's behalf.** Forwarding exists so a human picks. Guessing the eval's target silently invalidates the result while looking exactly like a real answer.\n- **Never let the run go quiet.** A question waiting on you, or 25 minutes with no word, both read as a hang.\n\n## 8. After the run\n\n- The `*.eval.ts` file is the durable artifact. Tell the user to commit it.\n- Re-runs do not need a full Ori run. `ori eval evals\u002F\u003Cfeature>\u002F\u003Cname>.eval.ts` is enough and much cheaper. This is what turns a one-off answer into a guardrail.\n- Use `ori eval --report \u003Cpath>` for shareable Markdown reports.\n- Use `--baseline last|best|model:\u003Cslug>` to choose the comparison baseline; history is stored in `.ori\u002Feval\u002Fhistory.jsonl`.\n- Use `run.toCostAtMost` and `run.toFinishWithin` for cost and time bounds.\n- Use `candidateModels` with `assertModelIsLive` to validate candidate availability, and `--list --allow-no-key` to list discovered evals without an API key.\n- Offer to wire `ori eval` into CI so a worse agent fails the build.\n- Relay the full table, the ship or no-ship call, and the quoted failures. Do not summarize away the failure quotes; they are the most useful output.\n- **Close with what the run cost.** One line, three parts: Ori's own session (read `usage.costUsd` off the final `turn.succeeded` event in the jsonl stream), the eval's model calls, and the judge (both from the report's Judging table or `data.results`). The authoring session usually dwarfs the eval — say so, because it is also the part a re-run never pays again:\n\n  > This cost about $28.20 total: $27.69 for Ori's one-time authoring session, $0.46 for the eval's model calls, $0.05 for judging. Re-running the eval costs only ~$0.51.\n\n  Never invent a figure — anything the stream or report did not carry is \"unmeasured\", not $0.\n\n## 9. If something goes wrong\n\n| Symptom | Do this |\n|---|---|\n| `ori: command not found` after a successful install | Try `~\u002F.local\u002Fbin\u002Fori`. The installer's PATH edit does not apply to the current shell. |\n| Auth missing | Stop. Ask the user to run `ori login` themselves. |\n| Long silence on the first run | Template fetch, roughly 30s. Wait before retrying. |\n| Ori reports a model id as unavailable | Have it look the id up again rather than substituting one from memory. |\n| The eval file landed outside `evals\u002F` | Move it and re-run `ori eval` against the new path. |\n| Run exceeds your timeout | The process may still be running. Keep reading its stdout until the `{\"kind\":\"result\",...}` line arrives; do not re-spawn. |\n| Ori picked the eval's target itself | Its question timed out (or `--interactions forward` was missing). Re-run with the flag, and answer within `--interaction-timeout`. |\n| Your answer had no effect | Check the `correlationId` matches the request exactly, and that the line is on the run's **stdin**, not a new invocation. A resumed session starts a new turn; it cannot settle a pending request. |\n| Ori accepted the answer but acted as if nothing was chosen | The `content` keys did not match the request's field `name`s, so the accept carried no usable value. Re-read `payload.fields[].name` and use those keys verbatim. |\n| A question never arrives but the run looks stalled | Some questions land as plain prose and end the turn instead of pending. Read the final assistant text and answer by resuming the session. |\n| `--interactions` rejected as unknown | The installed `ori` predates the answer channel. `ori update`, then re-check `ori code --help`. |\n| `403 Key limit exceeded` or a 402 payment error in the stream | The user's OpenRouter key is out of credit. See below. |\n\n### When the key runs out of credit\n\nA run that dies within seconds with `403 Key limit exceeded (total limit)` or a 402 payment error is not a bug in Ori or in the eval — the OpenRouter credential behind `ori login` has hit its spend cap. Handle it as a conversation, not a failure report:\n\n1. Tell the user plainly: their OpenRouter key is out of credit, no eval was written, and this attempt spent nothing.\n2. Give them the exact `Manage it using \u003Curl>` link from the error message and ask whether they want to raise the limit or add credits.\n3. Tell them the dashboard fix is enough — the credential at `~\u002F.ori\u002Fcredentials.json` stays valid, so there is no need to run `ori login` again.\n4. When they confirm, re-run the same spawn command and continue where you left off. Do not abandon the task.\n",{"data":35,"body":36},{"name":4,"description":6},{"type":37,"children":38},"root",[39,47,53,58,63,70,75,186,215,229,246,266,271,277,282,287,381,386,391,397,514,663,669,688,1127,1132,1208,1214,1227,1237,1243,1346,1352,1523,1529,1835,1842,1862,1907],{"type":40,"tag":41,"props":42,"children":43},"element","h1",{"id":4},[44],{"type":45,"value":46},"text","Spawn Ori Eval",{"type":40,"tag":48,"props":49,"children":50},"p",{},[51],{"type":45,"value":52},"You are not going to write this eval. You are going to install Ori if needed, hand the request to an Ori run, keep the user in the loop while it works, and relay what comes back.",{"type":40,"tag":48,"props":54,"children":55},{},[56],{"type":45,"value":57},"That split is deliberate. Ori pins the harness and the model that author and grade the eval, so the bench is identical no matter which coding agent the user happens to be driving. An eval you author yourself is not reproducible, and a score change has to mean the user's agent changed, not the environment.",{"type":40,"tag":48,"props":59,"children":60},{},[61],{"type":45,"value":62},"Your job is the part Ori cannot do: you are the user's only connection to a run that is otherwise invisible. Explain what you started (section 3), carry Ori's questions to them and their answers back (section 5), and relay the result in full (section 8).",{"type":40,"tag":64,"props":65,"children":67},"h2",{"id":66},"_1-preflight",[68],{"type":45,"value":69},"1. Preflight",{"type":40,"tag":48,"props":71,"children":72},{},[73],{"type":45,"value":74},"Run these in order. Do not skip ahead on a failure.",{"type":40,"tag":76,"props":77,"children":78},"ol",{},[79,123,167],{"type":40,"tag":80,"props":81,"children":82},"li",{},[83,90,94,96,102,105,107,113,115,121],{"type":40,"tag":84,"props":85,"children":87},"code",{"className":86},[],[88],{"type":45,"value":89},"command -v ori",{"type":40,"tag":91,"props":92,"children":93},"br",{},[],{"type":45,"value":95},"If missing: ",{"type":40,"tag":84,"props":97,"children":99},{"className":98},[],[100],{"type":45,"value":101},"curl -fsSL https:\u002F\u002Fopenrouter.ai\u002Flabs\u002Fori\u002Finstall.sh | sh",{"type":40,"tag":91,"props":103,"children":104},{},[],{"type":45,"value":106},"It installs to ",{"type":40,"tag":84,"props":108,"children":110},{"className":109},[],[111],{"type":45,"value":112},"~\u002F.local\u002Fbin",{"type":45,"value":114},", which is often not on PATH in a non-login shell. Re-check with ",{"type":40,"tag":84,"props":116,"children":118},{"className":117},[],[119],{"type":45,"value":120},"~\u002F.local\u002Fbin\u002Fori --version",{"type":45,"value":122}," before reporting failure.",{"type":40,"tag":80,"props":124,"children":125},{},[126,128,134,136,142,144,150,152,157,159,165],{"type":45,"value":127},"Auth: recommend ",{"type":40,"tag":84,"props":129,"children":131},{"className":130},[],[132],{"type":45,"value":133},"ori login",{"type":45,"value":135},", which stores an Ori-scoped credential at ",{"type":40,"tag":84,"props":137,"children":139},{"className":138},[],[140],{"type":45,"value":141},"~\u002F.ori\u002Fcredentials.json",{"type":45,"value":143},". Do not tell the user to export a raw ",{"type":40,"tag":84,"props":145,"children":147},{"className":146},[],[148],{"type":45,"value":149},"OPENROUTER_API_KEY",{"type":45,"value":151},". If the credential is missing, STOP and hand it back to the user. ",{"type":40,"tag":84,"props":153,"children":155},{"className":154},[],[156],{"type":45,"value":133},{"type":45,"value":158}," opens a browser and you cannot complete it. Tell them to run it themselves. In Claude Code, tell them to type ",{"type":40,"tag":84,"props":160,"children":162},{"className":161},[],[163],{"type":45,"value":164},"! ori login",{"type":45,"value":166},".",{"type":40,"tag":80,"props":168,"children":169},{},[170,176,178,184],{"type":40,"tag":84,"props":171,"children":173},{"className":172},[],[174],{"type":45,"value":175},"command -v bun",{"type":45,"value":177},". Ori executes ",{"type":40,"tag":84,"props":179,"children":181},{"className":180},[],[182],{"type":45,"value":183},"*.eval.ts",{"type":45,"value":185}," through Bun.",{"type":40,"tag":48,"props":187,"children":188},{},[189,191,197,199,205,207,213],{"type":45,"value":190},"Never print, echo, or log the contents of ",{"type":40,"tag":84,"props":192,"children":194},{"className":193},[],[195],{"type":45,"value":196},"credentials.json",{"type":45,"value":198}," or any other value you read out of a ",{"type":40,"tag":84,"props":200,"children":202},{"className":201},[],[203],{"type":45,"value":204},".env",{"type":45,"value":206}," file or config while searching. Name the key, never the value: ",{"type":40,"tag":84,"props":208,"children":210},{"className":209},[],[211],{"type":45,"value":212},"OPENAI_API_KEY at .env:4",{"type":45,"value":214},", not what it is set to.",{"type":40,"tag":64,"props":216,"children":218},{"id":217},"_2-keep-the-qa-in-create-eval-but-relay-it",[219,221,227],{"type":45,"value":220},"2. Keep the Q&A in ",{"type":40,"tag":84,"props":222,"children":224},{"className":223},[],[225],{"type":45,"value":226},"create-eval",{"type":45,"value":228},", but relay it",{"type":40,"tag":48,"props":230,"children":231},{},[232,237,239,244],{"type":40,"tag":84,"props":233,"children":235},{"className":234},[],[236],{"type":45,"value":4},{"type":45,"value":238}," does not do the scoping interview. Ori's ",{"type":40,"tag":84,"props":240,"children":242},{"className":241},[],[243],{"type":45,"value":226},{"type":45,"value":245}," skill already asks which surface to eval, what it needs to be good at, what real data to use, the cost ceiling, and the baseline model. This skill just hands that request off.",{"type":40,"tag":48,"props":247,"children":248},{},[249,251,257,259,264],{"type":45,"value":250},"Do not ask the user anything ",{"type":40,"tag":252,"props":253,"children":254},"strong",{},[255],{"type":45,"value":256},"before",{"type":45,"value":258}," spawning — not even \"what do you want to eval?\". If the request is vague or empty, spawn anyway and pass through whatever the user said verbatim; ",{"type":40,"tag":84,"props":260,"children":262},{"className":261},[],[263],{"type":45,"value":226},{"type":45,"value":265}," asks its questions inside the Ori run.",{"type":40,"tag":48,"props":267,"children":268},{},[269],{"type":45,"value":270},"That is not a licence to stay silent for the whole run. When Ori asks a question mid-run, you MUST put it to the user and send back their answer (section 5). \"Do not ask up front\" and \"relay Ori's questions\" are both true: the interview belongs to Ori, and the user belongs to you.",{"type":40,"tag":64,"props":272,"children":274},{"id":273},"_3-say-what-is-about-to-happen",[275],{"type":45,"value":276},"3. Say what is about to happen",{"type":40,"tag":48,"props":278,"children":279},{},[280],{"type":45,"value":281},"Before spawning, tell the user in plain language what they just set in motion. A wall of tool calls with no explanation is the single most common complaint about this skill.",{"type":40,"tag":48,"props":283,"children":284},{},[285],{"type":45,"value":286},"Cover, in your own words and without the jargon below:",{"type":40,"tag":288,"props":289,"children":290},"ul",{},[291,301,326,336,346,356],{"type":40,"tag":80,"props":292,"children":293},{},[294,299],{"type":40,"tag":252,"props":295,"children":296},{},[297],{"type":45,"value":298},"What Ori is.",{"type":45,"value":300}," A separate agent that writes and runs the eval, with its own pinned harness and model.",{"type":40,"tag":80,"props":302,"children":303},{},[304,309,311,316,318,324],{"type":40,"tag":252,"props":305,"children":306},{},[307],{"type":45,"value":308},"What it will do.",{"type":45,"value":310}," Pick what to measure, write a ",{"type":40,"tag":84,"props":312,"children":314},{"className":313},[],[315],{"type":45,"value":183},{"type":45,"value":317}," under ",{"type":40,"tag":84,"props":319,"children":321},{"className":320},[],[322],{"type":45,"value":323},"evals\u002F",{"type":45,"value":325},", and score models against it.",{"type":40,"tag":80,"props":327,"children":328},{},[329,334],{"type":40,"tag":252,"props":330,"children":331},{},[332],{"type":45,"value":333},"What it costs.",{"type":45,"value":335}," Roughly 10–30 minutes and a few dollars of credits. Say this up front, not after.",{"type":40,"tag":80,"props":337,"children":338},{},[339,344],{"type":40,"tag":252,"props":340,"children":341},{},[342],{"type":45,"value":343},"What they will get.",{"type":45,"value":345}," A scored table comparing the models.",{"type":40,"tag":80,"props":347,"children":348},{},[349,354],{"type":40,"tag":252,"props":350,"children":351},{},[352],{"type":45,"value":353},"That it may ask them something.",{"type":45,"value":355}," Tell them you will bring any question to them. This is what makes the interruption in section 5 feel intentional rather than random.",{"type":40,"tag":80,"props":357,"children":358},{},[359,364,366,372,374,380],{"type":40,"tag":252,"props":360,"children":361},{},[362],{"type":45,"value":363},"What got installed",{"type":45,"value":365},", if you installed it: the ",{"type":40,"tag":84,"props":367,"children":369},{"className":368},[],[370],{"type":45,"value":371},"ori",{"type":45,"value":373}," binary, at ",{"type":40,"tag":84,"props":375,"children":377},{"className":376},[],[378],{"type":45,"value":379},"~\u002F.local\u002Fbin\u002Fori",{"type":45,"value":166},{"type":40,"tag":48,"props":382,"children":383},{},[384],{"type":45,"value":385},"Never use this skill's internal vocabulary in anything the user reads. \"Preflight\", \"spawn\", \"verbatim\", \"harness\", \"elicitation\", \"correlationId\", \"the result line\", \"stdout\" are for you, not them. A user who sees \"Preflight passes. Spawning Ori with your request verbatim\" has been told nothing.",{"type":40,"tag":48,"props":387,"children":388},{},[389],{"type":45,"value":390},"While the run is going, relay progress from the stream — picked a target, wrote the eval, running model 2 of 3 — rather than reporting that it is \"still running\". A 25-minute silence is where trust dies.",{"type":40,"tag":64,"props":392,"children":394},{"id":393},"_4-spawn-it",[395],{"type":45,"value":396},"4. Spawn it",{"type":40,"tag":398,"props":399,"children":404},"pre",{"className":400,"code":401,"language":402,"meta":403,"style":403},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","ori code -p \"\u003Ctask>\" --output jsonl --interactions forward\n# For a long prompt:\nori code --prompt-file \u002Ftmp\u002Fori-task.txt --output jsonl --interactions forward\n","bash","",[405],{"type":40,"tag":84,"props":406,"children":407},{"__ignoreMap":403},[408,466,476],{"type":40,"tag":409,"props":410,"children":413},"span",{"class":411,"line":412},"line",1,[414,419,425,430,436,441,446,451,456,461],{"type":40,"tag":409,"props":415,"children":417},{"style":416},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[418],{"type":45,"value":371},{"type":40,"tag":409,"props":420,"children":422},{"style":421},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[423],{"type":45,"value":424}," code",{"type":40,"tag":409,"props":426,"children":427},{"style":421},[428],{"type":45,"value":429}," -p",{"type":40,"tag":409,"props":431,"children":433},{"style":432},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[434],{"type":45,"value":435}," \"",{"type":40,"tag":409,"props":437,"children":438},{"style":421},[439],{"type":45,"value":440},"\u003Ctask>",{"type":40,"tag":409,"props":442,"children":443},{"style":432},[444],{"type":45,"value":445},"\"",{"type":40,"tag":409,"props":447,"children":448},{"style":421},[449],{"type":45,"value":450}," --output",{"type":40,"tag":409,"props":452,"children":453},{"style":421},[454],{"type":45,"value":455}," jsonl",{"type":40,"tag":409,"props":457,"children":458},{"style":421},[459],{"type":45,"value":460}," --interactions",{"type":40,"tag":409,"props":462,"children":463},{"style":421},[464],{"type":45,"value":465}," forward\n",{"type":40,"tag":409,"props":467,"children":469},{"class":411,"line":468},2,[470],{"type":40,"tag":409,"props":471,"children":473},{"style":472},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[474],{"type":45,"value":475},"# For a long prompt:\n",{"type":40,"tag":409,"props":477,"children":479},{"class":411,"line":478},3,[480,484,488,493,498,502,506,510],{"type":40,"tag":409,"props":481,"children":482},{"style":416},[483],{"type":45,"value":371},{"type":40,"tag":409,"props":485,"children":486},{"style":421},[487],{"type":45,"value":424},{"type":40,"tag":409,"props":489,"children":490},{"style":421},[491],{"type":45,"value":492}," --prompt-file",{"type":40,"tag":409,"props":494,"children":495},{"style":421},[496],{"type":45,"value":497}," \u002Ftmp\u002Fori-task.txt",{"type":40,"tag":409,"props":499,"children":500},{"style":421},[501],{"type":45,"value":450},{"type":40,"tag":409,"props":503,"children":504},{"style":421},[505],{"type":45,"value":455},{"type":40,"tag":409,"props":507,"children":508},{"style":421},[509],{"type":45,"value":460},{"type":40,"tag":409,"props":511,"children":512},{"style":421},[513],{"type":45,"value":465},{"type":40,"tag":288,"props":515,"children":516},{},[517,536,593,604,625,630,643],{"type":40,"tag":80,"props":518,"children":519},{},[520,526,528,534],{"type":40,"tag":84,"props":521,"children":523},{"className":522},[],[524],{"type":45,"value":525},"-p",{"type":45,"value":527}," and ",{"type":40,"tag":84,"props":529,"children":531},{"className":530},[],[532],{"type":45,"value":533},"--prompt-file",{"type":45,"value":535}," are mutually exclusive. Positional prompts are rejected.",{"type":40,"tag":80,"props":537,"children":538},{},[539,545,547,553,555,561,563,569,571,577,579,584,586,592],{"type":40,"tag":84,"props":540,"children":542},{"className":541},[],[543],{"type":45,"value":544},"ori code -p \"\u003Ctask>\"",{"type":45,"value":546}," runs without a TTY and exits when the prompt completes: exit code 0 on success, nonzero on failure. A plain piped run streams Ori's reply as prose. Add ",{"type":40,"tag":84,"props":548,"children":550},{"className":549},[],[551],{"type":45,"value":552},"--output jsonl",{"type":45,"value":554}," for the structured stream — one ",{"type":40,"tag":84,"props":556,"children":558},{"className":557},[],[559],{"type":45,"value":560},"{\"kind\":\"event\",\"event\":...}",{"type":45,"value":562}," line per runtime event, then a final ",{"type":40,"tag":84,"props":564,"children":566},{"className":565},[],[567],{"type":45,"value":568},"{\"kind\":\"result\",\"ok\":...,\"sessionId\":\"...\"}",{"type":45,"value":570}," line; Ori's reply text is the concatenated ",{"type":40,"tag":84,"props":572,"children":574},{"className":573},[],[575],{"type":45,"value":576},"assistant.text.delta",{"type":45,"value":578}," payloads. Prefer ",{"type":40,"tag":84,"props":580,"children":582},{"className":581},[],[583],{"type":45,"value":552},{"type":45,"value":585},": it is the only stream that carries the ",{"type":40,"tag":84,"props":587,"children":589},{"className":588},[],[590],{"type":45,"value":591},"sessionId",{"type":45,"value":166},{"type":40,"tag":80,"props":594,"children":595},{},[596,602],{"type":40,"tag":84,"props":597,"children":599},{"className":598},[],[600],{"type":45,"value":601},"--interactions forward",{"type":45,"value":603}," is what lets you answer Ori's mid-run questions; see section 5. Without it the run declines each question itself and picks for you, so the eval measures Ori's guess rather than what the user cares about.",{"type":40,"tag":80,"props":605,"children":606},{},[607,609,615,617,623],{"type":45,"value":608},"Do NOT pass ",{"type":40,"tag":84,"props":610,"children":612},{"className":611},[],[613],{"type":45,"value":614},"--model",{"type":45,"value":616}," or ",{"type":40,"tag":84,"props":618,"children":620},{"className":619},[],[621],{"type":45,"value":622},"--harness",{"type":45,"value":624},". Overriding the pin destroys the reproducibility that is the only reason to use Ori.",{"type":40,"tag":80,"props":626,"children":627},{},[628],{"type":45,"value":629},"Run from the repo root so Ori can read the real prompts.",{"type":40,"tag":80,"props":631,"children":632},{},[633,635,641],{"type":45,"value":634},"One invocation. Do not loop the run once per candidate model. Comparing models is ",{"type":40,"tag":84,"props":636,"children":638},{"className":637},[],[639],{"type":45,"value":640},"ori eval",{"type":45,"value":642},"'s job, not yours.",{"type":40,"tag":80,"props":644,"children":645},{},[646,648,653,655,661],{"type":45,"value":647},"The first ",{"type":40,"tag":84,"props":649,"children":651},{"className":650},[],[652],{"type":45,"value":371},{"type":45,"value":654}," run on a machine creates ",{"type":40,"tag":84,"props":656,"children":658},{"className":657},[],[659],{"type":45,"value":660},"~\u002F.ori\u002Fglobal",{"type":45,"value":662}," and fetches templates over the network. Expect a pause of roughly 30 seconds and do not treat it as a hang.",{"type":40,"tag":64,"props":664,"children":666},{"id":665},"_5-answer-oris-questions",[667],{"type":45,"value":668},"5. Answer Ori's questions",{"type":40,"tag":48,"props":670,"children":671},{},[672,674,679,681,686],{"type":45,"value":673},"With ",{"type":40,"tag":84,"props":675,"children":677},{"className":676},[],[678],{"type":45,"value":601},{"type":45,"value":680},", a question Ori asks stays ",{"type":40,"tag":252,"props":682,"children":683},{},[684],{"type":45,"value":685},"pending",{"type":45,"value":687}," — the run is genuinely waiting on you. Handle it:",{"type":40,"tag":76,"props":689,"children":690},{},[691,782,824],{"type":40,"tag":80,"props":692,"children":693},{},[694,699,701,707,709,715,717,723,725,731,733,739,741,747,749,755,757,763,764,770,772,780],{"type":40,"tag":252,"props":695,"children":696},{},[697],{"type":45,"value":698},"Read it off the stream.",{"type":45,"value":700}," An ",{"type":40,"tag":84,"props":702,"children":704},{"className":703},[],[705],{"type":45,"value":706},"elicitation.requested",{"type":45,"value":708}," event carries ",{"type":40,"tag":84,"props":710,"children":712},{"className":711},[],[713],{"type":45,"value":714},"payload.message",{"type":45,"value":716},", ",{"type":40,"tag":84,"props":718,"children":720},{"className":719},[],[721],{"type":45,"value":722},"payload.fields[]",{"type":45,"value":724}," (each with a ",{"type":40,"tag":84,"props":726,"children":728},{"className":727},[],[729],{"type":45,"value":730},"name",{"type":45,"value":732},", a ",{"type":40,"tag":84,"props":734,"children":736},{"className":735},[],[737],{"type":45,"value":738},"type",{"type":45,"value":740},", and often ",{"type":40,"tag":84,"props":742,"children":744},{"className":743},[],[745],{"type":45,"value":746},"options",{"type":45,"value":748},"), and a ",{"type":40,"tag":84,"props":750,"children":752},{"className":751},[],[753],{"type":45,"value":754},"correlationId",{"type":45,"value":756},". A ",{"type":40,"tag":84,"props":758,"children":760},{"className":759},[],[761],{"type":45,"value":762},"permission.requested",{"type":45,"value":708},{"type":40,"tag":84,"props":765,"children":767},{"className":766},[],[768],{"type":45,"value":769},"payload.options",{"type":45,"value":771},". Note the field ",{"type":40,"tag":252,"props":773,"children":774},{},[775],{"type":40,"tag":84,"props":776,"children":778},{"className":777},[],[779],{"type":45,"value":730},{"type":45,"value":781}," — you need it verbatim in step 3.",{"type":40,"tag":80,"props":783,"children":784},{},[785,790,792,798,800,805,807,810,815,817,822],{"type":40,"tag":252,"props":786,"children":787},{},[788],{"type":45,"value":789},"Put it to the user with your own question UI",{"type":45,"value":791}," (in Claude Code, ",{"type":40,"tag":84,"props":793,"children":795},{"className":794},[],[796],{"type":45,"value":797},"AskUserQuestion",{"type":45,"value":799},"). Preserve Ori's options one-for-one, keep \"Other\" as free text, and translate its wording into plain language. Do not show them the raw event, the ",{"type":40,"tag":84,"props":801,"children":803},{"className":802},[],[804],{"type":45,"value":754},{"type":45,"value":806},", or the word \"elicitation\".",{"type":40,"tag":91,"props":808,"children":809},{},[],{"type":40,"tag":252,"props":811,"children":812},{},[813],{"type":45,"value":814},"Show the message, then the picker — both, in that order.",{"type":45,"value":816}," Ori's ",{"type":40,"tag":84,"props":818,"children":820},{"className":819},[],[821],{"type":45,"value":714},{"type":45,"value":823}," often carries context the option labels cannot (for the surface question it is a markdown table of surface \u002F model today). Print that message as normal text in your reply first, then call your question UI right below it with just the short option names. The table explains; the picker collects. Collapsing the table into the option descriptions loses it, and skipping it leaves the user picking between bare labels.",{"type":40,"tag":80,"props":825,"children":826},{},[827,832,834,839,841,1014,1017,1036,1038,1044,1046,1052,1054,1060,1062,1068,1070,1076,1078,1081,1083,1088,1090,1095,1097,1103,1104,1110,1112,1117,1119,1125],{"type":40,"tag":252,"props":828,"children":829},{},[830],{"type":45,"value":831},"Write the answer back to the run's stdin",{"type":45,"value":833},", one JSON object per line, keyed by that ",{"type":40,"tag":84,"props":835,"children":837},{"className":836},[],[838],{"type":45,"value":754},{"type":45,"value":840},":",{"type":40,"tag":398,"props":842,"children":846},{"className":843,"code":844,"language":845,"meta":403,"style":403},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\"kind\":\"respond\",\"correlationId\":\"ixn-0\",\"action\":\"accept\",\"content\":{\"\u003Cfield-name>\":\"\u003Cthe user's choice>\"}}\n","json",[847],{"type":40,"tag":84,"props":848,"children":849},{"__ignoreMap":403},[850],{"type":40,"tag":409,"props":851,"children":852},{"class":411,"line":412},[853,858,862,868,872,876,880,885,889,894,898,902,906,910,914,919,923,927,931,936,940,944,948,953,957,961,965,970,974,979,983,988,992,996,1000,1005,1009],{"type":40,"tag":409,"props":854,"children":855},{"style":432},[856],{"type":45,"value":857},"{",{"type":40,"tag":409,"props":859,"children":860},{"style":432},[861],{"type":45,"value":445},{"type":40,"tag":409,"props":863,"children":865},{"style":864},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[866],{"type":45,"value":867},"kind",{"type":40,"tag":409,"props":869,"children":870},{"style":432},[871],{"type":45,"value":445},{"type":40,"tag":409,"props":873,"children":874},{"style":432},[875],{"type":45,"value":840},{"type":40,"tag":409,"props":877,"children":878},{"style":432},[879],{"type":45,"value":445},{"type":40,"tag":409,"props":881,"children":882},{"style":421},[883],{"type":45,"value":884},"respond",{"type":40,"tag":409,"props":886,"children":887},{"style":432},[888],{"type":45,"value":445},{"type":40,"tag":409,"props":890,"children":891},{"style":432},[892],{"type":45,"value":893},",",{"type":40,"tag":409,"props":895,"children":896},{"style":432},[897],{"type":45,"value":445},{"type":40,"tag":409,"props":899,"children":900},{"style":864},[901],{"type":45,"value":754},{"type":40,"tag":409,"props":903,"children":904},{"style":432},[905],{"type":45,"value":445},{"type":40,"tag":409,"props":907,"children":908},{"style":432},[909],{"type":45,"value":840},{"type":40,"tag":409,"props":911,"children":912},{"style":432},[913],{"type":45,"value":445},{"type":40,"tag":409,"props":915,"children":916},{"style":421},[917],{"type":45,"value":918},"ixn-0",{"type":40,"tag":409,"props":920,"children":921},{"style":432},[922],{"type":45,"value":445},{"type":40,"tag":409,"props":924,"children":925},{"style":432},[926],{"type":45,"value":893},{"type":40,"tag":409,"props":928,"children":929},{"style":432},[930],{"type":45,"value":445},{"type":40,"tag":409,"props":932,"children":933},{"style":864},[934],{"type":45,"value":935},"action",{"type":40,"tag":409,"props":937,"children":938},{"style":432},[939],{"type":45,"value":445},{"type":40,"tag":409,"props":941,"children":942},{"style":432},[943],{"type":45,"value":840},{"type":40,"tag":409,"props":945,"children":946},{"style":432},[947],{"type":45,"value":445},{"type":40,"tag":409,"props":949,"children":950},{"style":421},[951],{"type":45,"value":952},"accept",{"type":40,"tag":409,"props":954,"children":955},{"style":432},[956],{"type":45,"value":445},{"type":40,"tag":409,"props":958,"children":959},{"style":432},[960],{"type":45,"value":893},{"type":40,"tag":409,"props":962,"children":963},{"style":432},[964],{"type":45,"value":445},{"type":40,"tag":409,"props":966,"children":967},{"style":864},[968],{"type":45,"value":969},"content",{"type":40,"tag":409,"props":971,"children":972},{"style":432},[973],{"type":45,"value":445},{"type":40,"tag":409,"props":975,"children":976},{"style":432},[977],{"type":45,"value":978},":{",{"type":40,"tag":409,"props":980,"children":981},{"style":432},[982],{"type":45,"value":445},{"type":40,"tag":409,"props":984,"children":985},{"style":416},[986],{"type":45,"value":987},"\u003Cfield-name>",{"type":40,"tag":409,"props":989,"children":990},{"style":432},[991],{"type":45,"value":445},{"type":40,"tag":409,"props":993,"children":994},{"style":432},[995],{"type":45,"value":840},{"type":40,"tag":409,"props":997,"children":998},{"style":432},[999],{"type":45,"value":445},{"type":40,"tag":409,"props":1001,"children":1002},{"style":421},[1003],{"type":45,"value":1004},"\u003Cthe user's choice>",{"type":40,"tag":409,"props":1006,"children":1007},{"style":432},[1008],{"type":45,"value":445},{"type":40,"tag":409,"props":1010,"children":1011},{"style":432},[1012],{"type":45,"value":1013},"}}\n",{"type":40,"tag":91,"props":1015,"children":1016},{},[],{"type":40,"tag":252,"props":1018,"children":1019},{},[1020,1022,1027,1029,1034],{"type":45,"value":1021},"The keys in ",{"type":40,"tag":84,"props":1023,"children":1025},{"className":1024},[],[1026],{"type":45,"value":969},{"type":45,"value":1028}," are the field ",{"type":40,"tag":84,"props":1030,"children":1032},{"className":1031},[],[1033],{"type":45,"value":730},{"type":45,"value":1035},"s from the request",{"type":45,"value":1037},", not a fixed schema. If ",{"type":40,"tag":84,"props":1039,"children":1041},{"className":1040},[],[1042],{"type":45,"value":1043},"payload.fields",{"type":45,"value":1045}," is ",{"type":40,"tag":84,"props":1047,"children":1049},{"className":1048},[],[1050],{"type":45,"value":1051},"[{\"name\":\"surface\", …}]",{"type":45,"value":1053},", send ",{"type":40,"tag":84,"props":1055,"children":1057},{"className":1056},[],[1058],{"type":45,"value":1059},"\"content\":{\"surface\":\"…\"}",{"type":45,"value":1061},". Copying a ",{"type":40,"tag":84,"props":1063,"children":1065},{"className":1064},[],[1066],{"type":45,"value":1067},"\"value\"",{"type":45,"value":1069}," from an example when the request asked for ",{"type":40,"tag":84,"props":1071,"children":1073},{"className":1072},[],[1074],{"type":45,"value":1075},"surface",{"type":45,"value":1077}," produces a well-formed line that is accepted and then maps to nothing, which is worse than not answering: the run proceeds as if the user had chosen. Read the name off the event every time.",{"type":40,"tag":91,"props":1079,"children":1080},{},[],{"type":45,"value":1082},"Use ",{"type":40,"tag":84,"props":1084,"children":1086},{"className":1085},[],[1087],{"type":45,"value":935},{"type":45,"value":1089}," (",{"type":40,"tag":84,"props":1091,"children":1093},{"className":1092},[],[1094],{"type":45,"value":952},{"type":45,"value":1096}," \u002F ",{"type":40,"tag":84,"props":1098,"children":1100},{"className":1099},[],[1101],{"type":45,"value":1102},"decline",{"type":45,"value":1096},{"type":40,"tag":84,"props":1105,"children":1107},{"className":1106},[],[1108],{"type":45,"value":1109},"cancel",{"type":45,"value":1111},", with ",{"type":40,"tag":84,"props":1113,"children":1115},{"className":1114},[],[1116],{"type":45,"value":969},{"type":45,"value":1118}," carrying the fields on an accept) for a question form, and ",{"type":40,"tag":84,"props":1120,"children":1122},{"className":1121},[],[1123],{"type":45,"value":1124},"optionKind",{"type":45,"value":1126}," for a permission request. You send only the decision; which request it answers and which session it belongs to come from the request itself.",{"type":40,"tag":48,"props":1128,"children":1129},{},[1130],{"type":45,"value":1131},"Notes that matter:",{"type":40,"tag":288,"props":1133,"children":1134},{},[1135,1160,1170,1180,1190],{"type":40,"tag":80,"props":1136,"children":1137},{},[1138,1143,1145,1151,1153,1159],{"type":40,"tag":252,"props":1139,"children":1140},{},[1141],{"type":45,"value":1142},"Answer promptly.",{"type":45,"value":1144}," A forwarded question falls back to being declined after ",{"type":40,"tag":84,"props":1146,"children":1148},{"className":1147},[],[1149],{"type":45,"value":1150},"--interaction-timeout",{"type":45,"value":1152}," (default 300s), and then Ori picks for itself as before. If the user may be slow, raise it: ",{"type":40,"tag":84,"props":1154,"children":1156},{"className":1155},[],[1157],{"type":45,"value":1158},"--interaction-timeout 900",{"type":45,"value":166},{"type":40,"tag":80,"props":1161,"children":1162},{},[1163,1168],{"type":40,"tag":252,"props":1164,"children":1165},{},[1166],{"type":45,"value":1167},"A malformed line is skipped",{"type":45,"value":1169},", not fatal — but the request then just sits until it times out, so get the shape right.",{"type":40,"tag":80,"props":1171,"children":1172},{},[1173,1178],{"type":40,"tag":252,"props":1174,"children":1175},{},[1176],{"type":45,"value":1177},"Never invent an answer.",{"type":45,"value":1179}," Forwarding exists so a human decides. If you cannot reach the user, let it time out rather than guessing on their behalf; a guessed target silently invalidates the whole eval.",{"type":40,"tag":80,"props":1181,"children":1182},{},[1183,1188],{"type":40,"tag":252,"props":1184,"children":1185},{},[1186],{"type":45,"value":1187},"Never answer a permission request with a blanket allow",{"type":45,"value":1189}," to keep things moving. Pass it to the user.",{"type":40,"tag":80,"props":1191,"children":1192},{},[1193,1198,1200,1206],{"type":40,"tag":252,"props":1194,"children":1195},{},[1196],{"type":45,"value":1197},"A question in plain prose",{"type":45,"value":1199}," (rather than a structured request) ends the turn instead of pending. Answer that by resuming: ",{"type":40,"tag":84,"props":1201,"children":1203},{"className":1202},[],[1204],{"type":45,"value":1205},"ori code --session \u003CsessionId> -p \"\u003Canswer>\" --output jsonl",{"type":45,"value":1207},", chaining until the eval is written and run.",{"type":40,"tag":64,"props":1209,"children":1211},{"id":1210},"_6-the-task-prompt",[1212],{"type":45,"value":1213},"6. The task prompt",{"type":40,"tag":48,"props":1215,"children":1216},{},[1217,1219,1225],{"type":45,"value":1218},"Write this to ",{"type":40,"tag":84,"props":1220,"children":1222},{"className":1221},[],[1223],{"type":45,"value":1224},"\u002Ftmp\u002Fori-task.txt",{"type":45,"value":1226}," — the file used by the section 4 command — and fill every angle-bracket slot. If you use a different path, use it in the spawn command too; an unwritten path produces an empty prompt and Ori does nothing.",{"type":40,"tag":398,"props":1228,"children":1232},{"className":1229,"code":1231,"language":45,"meta":403},[1230],"language-text","Use the create-eval skill.\n\nUser request: \u003Cverbatim request>\nRepo context pointers: \u003Cpaths>. Read these first.\n\nWrite the eval to evals\u002F\u003Cfeature>\u002F\u003Cname>.eval.ts and run it with ori eval. Do\nnot create or modify anything outside the top-level evals directory.\n",[1233],{"type":40,"tag":84,"props":1234,"children":1235},{"__ignoreMap":403},[1236],{"type":45,"value":1231},{"type":40,"tag":64,"props":1238,"children":1240},{"id":1239},"_7-never-do-these",[1241],{"type":45,"value":1242},"7. Never do these",{"type":40,"tag":288,"props":1244,"children":1245},{},[1246,1256,1272,1296,1306,1316,1326,1336],{"type":40,"tag":80,"props":1247,"children":1248},{},[1249,1254],{"type":40,"tag":252,"props":1250,"children":1251},{},[1252],{"type":45,"value":1253},"Never spawn your own subagent to \"do an eval.\"",{"type":45,"value":1255}," It produces a plausible table with no pinned bench behind it, which is worse than no answer.",{"type":40,"tag":80,"props":1257,"children":1258},{},[1259,1264,1265,1270],{"type":40,"tag":252,"props":1260,"children":1261},{},[1262],{"type":45,"value":1263},"Never write the eval yourself.",{"type":45,"value":816},{"type":40,"tag":84,"props":1266,"children":1268},{"className":1267},[],[1269],{"type":45,"value":226},{"type":45,"value":1271}," skill fires automatically inside the run.",{"type":40,"tag":80,"props":1273,"children":1274},{},[1275,1280,1282,1287,1289,1294],{"type":40,"tag":252,"props":1276,"children":1277},{},[1278],{"type":45,"value":1279},"Never put the eval in the repo's existing test framework.",{"type":45,"value":1281}," ",{"type":40,"tag":84,"props":1283,"children":1285},{"className":1284},[],[1286],{"type":45,"value":640},{"type":45,"value":1288}," discovers ",{"type":40,"tag":84,"props":1290,"children":1292},{"className":1291},[],[1293],{"type":45,"value":183},{"type":45,"value":1295}," only. A pytest, vitest, or Go test file silently never runs, and silence reads as passing.",{"type":40,"tag":80,"props":1297,"children":1298},{},[1299,1304],{"type":40,"tag":252,"props":1300,"children":1301},{},[1302],{"type":45,"value":1303},"Never hand-roll raw API calls and present the numbers as an Ori eval.",{"type":45,"value":1305}," If you measure something another way, label it clearly as such.",{"type":40,"tag":80,"props":1307,"children":1308},{},[1309,1314],{"type":40,"tag":252,"props":1310,"children":1311},{},[1312],{"type":45,"value":1313},"Never name model ids or prices from memory.",{"type":45,"value":1315}," They go stale between releases.",{"type":40,"tag":80,"props":1317,"children":1318},{},[1319,1324],{"type":40,"tag":252,"props":1320,"children":1321},{},[1322],{"type":45,"value":1323},"Never report a winner without the production model in the table.",{"type":45,"value":1325}," \"No change\" is a valid and useful result.",{"type":40,"tag":80,"props":1327,"children":1328},{},[1329,1334],{"type":40,"tag":252,"props":1330,"children":1331},{},[1332],{"type":45,"value":1333},"Never answer Ori's questions on the user's behalf.",{"type":45,"value":1335}," Forwarding exists so a human picks. Guessing the eval's target silently invalidates the result while looking exactly like a real answer.",{"type":40,"tag":80,"props":1337,"children":1338},{},[1339,1344],{"type":40,"tag":252,"props":1340,"children":1341},{},[1342],{"type":45,"value":1343},"Never let the run go quiet.",{"type":45,"value":1345}," A question waiting on you, or 25 minutes with no word, both read as a hang.",{"type":40,"tag":64,"props":1347,"children":1349},{"id":1348},"_8-after-the-run",[1350],{"type":45,"value":1351},"8. After the run",{"type":40,"tag":288,"props":1353,"children":1354},{},[1355,1367,1380,1392,1411,1430,1458,1470,1475],{"type":40,"tag":80,"props":1356,"children":1357},{},[1358,1360,1365],{"type":45,"value":1359},"The ",{"type":40,"tag":84,"props":1361,"children":1363},{"className":1362},[],[1364],{"type":45,"value":183},{"type":45,"value":1366}," file is the durable artifact. Tell the user to commit it.",{"type":40,"tag":80,"props":1368,"children":1369},{},[1370,1372,1378],{"type":45,"value":1371},"Re-runs do not need a full Ori run. ",{"type":40,"tag":84,"props":1373,"children":1375},{"className":1374},[],[1376],{"type":45,"value":1377},"ori eval evals\u002F\u003Cfeature>\u002F\u003Cname>.eval.ts",{"type":45,"value":1379}," is enough and much cheaper. This is what turns a one-off answer into a guardrail.",{"type":40,"tag":80,"props":1381,"children":1382},{},[1383,1384,1390],{"type":45,"value":1082},{"type":40,"tag":84,"props":1385,"children":1387},{"className":1386},[],[1388],{"type":45,"value":1389},"ori eval --report \u003Cpath>",{"type":45,"value":1391}," for shareable Markdown reports.",{"type":40,"tag":80,"props":1393,"children":1394},{},[1395,1396,1402,1404,1410],{"type":45,"value":1082},{"type":40,"tag":84,"props":1397,"children":1399},{"className":1398},[],[1400],{"type":45,"value":1401},"--baseline last|best|model:\u003Cslug>",{"type":45,"value":1403}," to choose the comparison baseline; history is stored in ",{"type":40,"tag":84,"props":1405,"children":1407},{"className":1406},[],[1408],{"type":45,"value":1409},".ori\u002Feval\u002Fhistory.jsonl",{"type":45,"value":166},{"type":40,"tag":80,"props":1412,"children":1413},{},[1414,1415,1421,1422,1428],{"type":45,"value":1082},{"type":40,"tag":84,"props":1416,"children":1418},{"className":1417},[],[1419],{"type":45,"value":1420},"run.toCostAtMost",{"type":45,"value":527},{"type":40,"tag":84,"props":1423,"children":1425},{"className":1424},[],[1426],{"type":45,"value":1427},"run.toFinishWithin",{"type":45,"value":1429}," for cost and time bounds.",{"type":40,"tag":80,"props":1431,"children":1432},{},[1433,1434,1440,1442,1448,1450,1456],{"type":45,"value":1082},{"type":40,"tag":84,"props":1435,"children":1437},{"className":1436},[],[1438],{"type":45,"value":1439},"candidateModels",{"type":45,"value":1441}," with ",{"type":40,"tag":84,"props":1443,"children":1445},{"className":1444},[],[1446],{"type":45,"value":1447},"assertModelIsLive",{"type":45,"value":1449}," to validate candidate availability, and ",{"type":40,"tag":84,"props":1451,"children":1453},{"className":1452},[],[1454],{"type":45,"value":1455},"--list --allow-no-key",{"type":45,"value":1457}," to list discovered evals without an API key.",{"type":40,"tag":80,"props":1459,"children":1460},{},[1461,1463,1468],{"type":45,"value":1462},"Offer to wire ",{"type":40,"tag":84,"props":1464,"children":1466},{"className":1465},[],[1467],{"type":45,"value":640},{"type":45,"value":1469}," into CI so a worse agent fails the build.",{"type":40,"tag":80,"props":1471,"children":1472},{},[1473],{"type":45,"value":1474},"Relay the full table, the ship or no-ship call, and the quoted failures. Do not summarize away the failure quotes; they are the most useful output.",{"type":40,"tag":80,"props":1476,"children":1477},{},[1478,1483,1485,1491,1493,1499,1501,1507,1509,1518,1521],{"type":40,"tag":252,"props":1479,"children":1480},{},[1481],{"type":45,"value":1482},"Close with what the run cost.",{"type":45,"value":1484}," One line, three parts: Ori's own session (read ",{"type":40,"tag":84,"props":1486,"children":1488},{"className":1487},[],[1489],{"type":45,"value":1490},"usage.costUsd",{"type":45,"value":1492}," off the final ",{"type":40,"tag":84,"props":1494,"children":1496},{"className":1495},[],[1497],{"type":45,"value":1498},"turn.succeeded",{"type":45,"value":1500}," event in the jsonl stream), the eval's model calls, and the judge (both from the report's Judging table or ",{"type":40,"tag":84,"props":1502,"children":1504},{"className":1503},[],[1505],{"type":45,"value":1506},"data.results",{"type":45,"value":1508},"). The authoring session usually dwarfs the eval — say so, because it is also the part a re-run never pays again:",{"type":40,"tag":1510,"props":1511,"children":1512},"blockquote",{},[1513],{"type":40,"tag":48,"props":1514,"children":1515},{},[1516],{"type":45,"value":1517},"This cost about $28.20 total: $27.69 for Ori's one-time authoring session, $0.46 for the eval's model calls, $0.05 for judging. Re-running the eval costs only ~$0.51.",{"type":40,"tag":91,"props":1519,"children":1520},{},[],{"type":45,"value":1522},"Never invent a figure — anything the stream or report did not carry is \"unmeasured\", not $0.",{"type":40,"tag":64,"props":1524,"children":1526},{"id":1525},"_9-if-something-goes-wrong",[1527],{"type":45,"value":1528},"9. If something goes wrong",{"type":40,"tag":1530,"props":1531,"children":1532},"table",{},[1533,1552],{"type":40,"tag":1534,"props":1535,"children":1536},"thead",{},[1537],{"type":40,"tag":1538,"props":1539,"children":1540},"tr",{},[1541,1547],{"type":40,"tag":1542,"props":1543,"children":1544},"th",{},[1545],{"type":45,"value":1546},"Symptom",{"type":40,"tag":1542,"props":1548,"children":1549},{},[1550],{"type":45,"value":1551},"Do this",{"type":40,"tag":1553,"props":1554,"children":1555},"tbody",{},[1556,1583,1603,1616,1629,1654,1675,1701,1728,1762,1775,1816],{"type":40,"tag":1538,"props":1557,"children":1558},{},[1559,1571],{"type":40,"tag":1560,"props":1561,"children":1562},"td",{},[1563,1569],{"type":40,"tag":84,"props":1564,"children":1566},{"className":1565},[],[1567],{"type":45,"value":1568},"ori: command not found",{"type":45,"value":1570}," after a successful install",{"type":40,"tag":1560,"props":1572,"children":1573},{},[1574,1576,1581],{"type":45,"value":1575},"Try ",{"type":40,"tag":84,"props":1577,"children":1579},{"className":1578},[],[1580],{"type":45,"value":379},{"type":45,"value":1582},". The installer's PATH edit does not apply to the current shell.",{"type":40,"tag":1538,"props":1584,"children":1585},{},[1586,1591],{"type":40,"tag":1560,"props":1587,"children":1588},{},[1589],{"type":45,"value":1590},"Auth missing",{"type":40,"tag":1560,"props":1592,"children":1593},{},[1594,1596,1601],{"type":45,"value":1595},"Stop. Ask the user to run ",{"type":40,"tag":84,"props":1597,"children":1599},{"className":1598},[],[1600],{"type":45,"value":133},{"type":45,"value":1602}," themselves.",{"type":40,"tag":1538,"props":1604,"children":1605},{},[1606,1611],{"type":40,"tag":1560,"props":1607,"children":1608},{},[1609],{"type":45,"value":1610},"Long silence on the first run",{"type":40,"tag":1560,"props":1612,"children":1613},{},[1614],{"type":45,"value":1615},"Template fetch, roughly 30s. Wait before retrying.",{"type":40,"tag":1538,"props":1617,"children":1618},{},[1619,1624],{"type":40,"tag":1560,"props":1620,"children":1621},{},[1622],{"type":45,"value":1623},"Ori reports a model id as unavailable",{"type":40,"tag":1560,"props":1625,"children":1626},{},[1627],{"type":45,"value":1628},"Have it look the id up again rather than substituting one from memory.",{"type":40,"tag":1538,"props":1630,"children":1631},{},[1632,1642],{"type":40,"tag":1560,"props":1633,"children":1634},{},[1635,1637],{"type":45,"value":1636},"The eval file landed outside ",{"type":40,"tag":84,"props":1638,"children":1640},{"className":1639},[],[1641],{"type":45,"value":323},{"type":40,"tag":1560,"props":1643,"children":1644},{},[1645,1647,1652],{"type":45,"value":1646},"Move it and re-run ",{"type":40,"tag":84,"props":1648,"children":1650},{"className":1649},[],[1651],{"type":45,"value":640},{"type":45,"value":1653}," against the new path.",{"type":40,"tag":1538,"props":1655,"children":1656},{},[1657,1662],{"type":40,"tag":1560,"props":1658,"children":1659},{},[1660],{"type":45,"value":1661},"Run exceeds your timeout",{"type":40,"tag":1560,"props":1663,"children":1664},{},[1665,1667,1673],{"type":45,"value":1666},"The process may still be running. Keep reading its stdout until the ",{"type":40,"tag":84,"props":1668,"children":1670},{"className":1669},[],[1671],{"type":45,"value":1672},"{\"kind\":\"result\",...}",{"type":45,"value":1674}," line arrives; do not re-spawn.",{"type":40,"tag":1538,"props":1676,"children":1677},{},[1678,1683],{"type":40,"tag":1560,"props":1679,"children":1680},{},[1681],{"type":45,"value":1682},"Ori picked the eval's target itself",{"type":40,"tag":1560,"props":1684,"children":1685},{},[1686,1688,1693,1695,1700],{"type":45,"value":1687},"Its question timed out (or ",{"type":40,"tag":84,"props":1689,"children":1691},{"className":1690},[],[1692],{"type":45,"value":601},{"type":45,"value":1694}," was missing). Re-run with the flag, and answer within ",{"type":40,"tag":84,"props":1696,"children":1698},{"className":1697},[],[1699],{"type":45,"value":1150},{"type":45,"value":166},{"type":40,"tag":1538,"props":1702,"children":1703},{},[1704,1709],{"type":40,"tag":1560,"props":1705,"children":1706},{},[1707],{"type":45,"value":1708},"Your answer had no effect",{"type":40,"tag":1560,"props":1710,"children":1711},{},[1712,1714,1719,1721,1726],{"type":45,"value":1713},"Check the ",{"type":40,"tag":84,"props":1715,"children":1717},{"className":1716},[],[1718],{"type":45,"value":754},{"type":45,"value":1720}," matches the request exactly, and that the line is on the run's ",{"type":40,"tag":252,"props":1722,"children":1723},{},[1724],{"type":45,"value":1725},"stdin",{"type":45,"value":1727},", not a new invocation. A resumed session starts a new turn; it cannot settle a pending request.",{"type":40,"tag":1538,"props":1729,"children":1730},{},[1731,1736],{"type":40,"tag":1560,"props":1732,"children":1733},{},[1734],{"type":45,"value":1735},"Ori accepted the answer but acted as if nothing was chosen",{"type":40,"tag":1560,"props":1737,"children":1738},{},[1739,1740,1745,1747,1752,1754,1760],{"type":45,"value":1359},{"type":40,"tag":84,"props":1741,"children":1743},{"className":1742},[],[1744],{"type":45,"value":969},{"type":45,"value":1746}," keys did not match the request's field ",{"type":40,"tag":84,"props":1748,"children":1750},{"className":1749},[],[1751],{"type":45,"value":730},{"type":45,"value":1753},"s, so the accept carried no usable value. Re-read ",{"type":40,"tag":84,"props":1755,"children":1757},{"className":1756},[],[1758],{"type":45,"value":1759},"payload.fields[].name",{"type":45,"value":1761}," and use those keys verbatim.",{"type":40,"tag":1538,"props":1763,"children":1764},{},[1765,1770],{"type":40,"tag":1560,"props":1766,"children":1767},{},[1768],{"type":45,"value":1769},"A question never arrives but the run looks stalled",{"type":40,"tag":1560,"props":1771,"children":1772},{},[1773],{"type":45,"value":1774},"Some questions land as plain prose and end the turn instead of pending. Read the final assistant text and answer by resuming the session.",{"type":40,"tag":1538,"props":1776,"children":1777},{},[1778,1789],{"type":40,"tag":1560,"props":1779,"children":1780},{},[1781,1787],{"type":40,"tag":84,"props":1782,"children":1784},{"className":1783},[],[1785],{"type":45,"value":1786},"--interactions",{"type":45,"value":1788}," rejected as unknown",{"type":40,"tag":1560,"props":1790,"children":1791},{},[1792,1794,1799,1801,1807,1809,1815],{"type":45,"value":1793},"The installed ",{"type":40,"tag":84,"props":1795,"children":1797},{"className":1796},[],[1798],{"type":45,"value":371},{"type":45,"value":1800}," predates the answer channel. ",{"type":40,"tag":84,"props":1802,"children":1804},{"className":1803},[],[1805],{"type":45,"value":1806},"ori update",{"type":45,"value":1808},", then re-check ",{"type":40,"tag":84,"props":1810,"children":1812},{"className":1811},[],[1813],{"type":45,"value":1814},"ori code --help",{"type":45,"value":166},{"type":40,"tag":1538,"props":1817,"children":1818},{},[1819,1830],{"type":40,"tag":1560,"props":1820,"children":1821},{},[1822,1828],{"type":40,"tag":84,"props":1823,"children":1825},{"className":1824},[],[1826],{"type":45,"value":1827},"403 Key limit exceeded",{"type":45,"value":1829}," or a 402 payment error in the stream",{"type":40,"tag":1560,"props":1831,"children":1832},{},[1833],{"type":45,"value":1834},"The user's OpenRouter key is out of credit. See below.",{"type":40,"tag":1836,"props":1837,"children":1839},"h3",{"id":1838},"when-the-key-runs-out-of-credit",[1840],{"type":45,"value":1841},"When the key runs out of credit",{"type":40,"tag":48,"props":1843,"children":1844},{},[1845,1847,1853,1855,1860],{"type":45,"value":1846},"A run that dies within seconds with ",{"type":40,"tag":84,"props":1848,"children":1850},{"className":1849},[],[1851],{"type":45,"value":1852},"403 Key limit exceeded (total limit)",{"type":45,"value":1854}," or a 402 payment error is not a bug in Ori or in the eval — the OpenRouter credential behind ",{"type":40,"tag":84,"props":1856,"children":1858},{"className":1857},[],[1859],{"type":45,"value":133},{"type":45,"value":1861}," has hit its spend cap. Handle it as a conversation, not a failure report:",{"type":40,"tag":76,"props":1863,"children":1864},{},[1865,1870,1883,1902],{"type":40,"tag":80,"props":1866,"children":1867},{},[1868],{"type":45,"value":1869},"Tell the user plainly: their OpenRouter key is out of credit, no eval was written, and this attempt spent nothing.",{"type":40,"tag":80,"props":1871,"children":1872},{},[1873,1875,1881],{"type":45,"value":1874},"Give them the exact ",{"type":40,"tag":84,"props":1876,"children":1878},{"className":1877},[],[1879],{"type":45,"value":1880},"Manage it using \u003Curl>",{"type":45,"value":1882}," link from the error message and ask whether they want to raise the limit or add credits.",{"type":40,"tag":80,"props":1884,"children":1885},{},[1886,1888,1893,1895,1900],{"type":45,"value":1887},"Tell them the dashboard fix is enough — the credential at ",{"type":40,"tag":84,"props":1889,"children":1891},{"className":1890},[],[1892],{"type":45,"value":141},{"type":45,"value":1894}," stays valid, so there is no need to run ",{"type":40,"tag":84,"props":1896,"children":1898},{"className":1897},[],[1899],{"type":45,"value":133},{"type":45,"value":1901}," again.",{"type":40,"tag":80,"props":1903,"children":1904},{},[1905],{"type":45,"value":1906},"When they confirm, re-run the same spawn command and continue where you left off. Do not abandon the task.",{"type":40,"tag":1908,"props":1909,"children":1910},"style",{},[1911],{"type":45,"value":1912},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":1914,"total":2055},[1915,1932,1942,1956,1970,1981,1990,2002,2012,2021,2032,2041],{"slug":1916,"name":1916,"fn":1917,"description":1918,"org":1919,"tags":1920,"stars":24,"repoUrl":25,"updatedAt":1931},"create-agent-tui","scaffold terminal agents with OpenRouter","Scaffolds a complete agent TUI in TypeScript using @openrouter\u002Fagent — like create-react-app for terminal agents. Generates a customizable terminal interface with three input styles, four tool display modes, ASCII banners, streaming output, session persistence, and configurable tools. Use when building an agent, creating a TUI, scaffolding an agent project, or building a coding assistant.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1921,1924,1927,1928],{"name":1922,"slug":1923,"type":16},"Agents","agents",{"name":1925,"slug":1926,"type":16},"CLI","cli",{"name":9,"slug":8,"type":16},{"name":1929,"slug":1930,"type":16},"TypeScript","typescript","2026-07-14T05:38:18.849741",{"slug":1933,"name":1933,"fn":1934,"description":1935,"org":1936,"tags":1937,"stars":24,"repoUrl":25,"updatedAt":1941},"create-headless-agent","scaffold headless agents with OpenRouter","Scaffolds a headless agent in TypeScript using @openrouter\u002Fagent and Bun — for CLI tools, API servers, queue workers, and pipelines. No terminal UI. Use when building a headless agent, programmatic agent, CLI tool that uses AI, batch agent, pipeline agent, API agent, agent without a UI, or agent service.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1938,1939,1940],{"name":1922,"slug":1923,"type":16},{"name":1925,"slug":1926,"type":16},{"name":1929,"slug":1930,"type":16},"2026-07-14T05:38:30.178029",{"slug":1943,"name":1943,"fn":1944,"description":1945,"org":1946,"tags":1947,"stars":24,"repoUrl":25,"updatedAt":1955},"open-responses","implement Open Responses-compliant APIs","This skill should be used when implementing, consuming, or debugging an Open Responses-compliant API — the open standard for multi-provider LLM interoperability. Covers protocol, items, state machines, streaming events, tools, the agentic loop pattern, and extensions. Triggers on: Open Responses, open-responses, \u002Fv1\u002Fresponses endpoint, multi-provider LLM API, Open Responses compliance.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1948,1951,1954],{"name":1949,"slug":1950,"type":16},"API Development","api-development",{"name":1952,"slug":1953,"type":16},"Interoperability","interoperability",{"name":18,"slug":19,"type":16},"2026-07-14T05:38:13.153467",{"slug":1957,"name":1957,"fn":1958,"description":1959,"org":1960,"tags":1961,"stars":24,"repoUrl":25,"updatedAt":1969},"openrouter-agent-migration","migrate OpenRouter SDK to agent patterns","Migration guide from @openrouter\u002Fsdk to @openrouter\u002Fagent for callModel, tool(), stop conditions, and agent features. This skill should be used when code imports callModel, tool(), or stop conditions from @openrouter\u002Fsdk and needs to migrate to @openrouter\u002Fagent.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1962,1965,1968],{"name":1963,"slug":1964,"type":16},"Migration","migration",{"name":1966,"slug":1967,"type":16},"SDK","sdk",{"name":1929,"slug":1930,"type":16},"2026-07-14T05:38:28.914981",{"slug":1971,"name":1971,"fn":1972,"description":1973,"org":1974,"tags":1975,"stars":24,"repoUrl":25,"updatedAt":1980},"openrouter-analytics","analyze OpenRouter usage and spend","Answer natural-language questions about a user's OpenRouter usage data — spend, request volume, model breakdown, latency, token usage, and cost optimization. Use when the user asks about their API usage, billing, costs, top models, traffic patterns, or wants to optimize their OpenRouter spend.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1976,1979],{"name":1977,"slug":1978,"type":16},"Analytics","analytics",{"name":9,"slug":8,"type":16},"2026-07-30T05:30:15.098344",{"slug":1982,"name":1982,"fn":1983,"description":1984,"org":1985,"tags":1986,"stars":24,"repoUrl":25,"updatedAt":1989},"openrouter-analytics-query","execute analytics queries against OpenRouter","Construct and execute analytics queries against the OpenRouter API — full parameter reference for metrics, dimensions, filters, time ranges, ordering, and pagination. Use when building or debugging an analytics query, understanding the request\u002Fresponse shape, or handling query errors.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1987,1988],{"name":1977,"slug":1978,"type":16},{"name":1949,"slug":1950,"type":16},"2026-07-14T05:38:26.402047",{"slug":1991,"name":1991,"fn":1992,"description":1993,"org":1994,"tags":1995,"stars":24,"repoUrl":25,"updatedAt":2001},"openrouter-analytics-schema","query OpenRouter analytics schema","Discover the OpenRouter analytics schema — available metrics, dimensions, filter operators, and granularities. Use when you need to know what analytics data is queryable, what dimensions you can break down by, or how to map a user's question to the right metric\u002Fdimension combination.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[1996,1997,1998],{"name":1977,"slug":1978,"type":16},{"name":18,"slug":19,"type":16},{"name":1999,"slug":2000,"type":16},"Reporting","reporting","2026-07-14T05:38:32.721796",{"slug":2003,"name":2003,"fn":2004,"description":2005,"org":2006,"tags":2007,"stars":24,"repoUrl":25,"updatedAt":2011},"openrouter-benchmarks","query OpenRouter model benchmarks","Query OpenRouter's Benchmarks API for model benchmark rankings and scores. Use when the user asks for benchmark-backed model selection, model rankings by coding\u002Fintelligence\u002Fagentic ability, Artificial Analysis or Design Arena ELO\u002Fwin-rate results, benchmark citations, or wants to call GET \u002Fapi\u002Fv1\u002Fbenchmarks. Also use alongside openrouter-models when the user asks what model should power an app, product, workflow, or use case and benchmark evidence could inform or rule out part of the recommendation, including creative writing, editing, coding, design, agentic, or intelligence-heavy apps. Do not use for OpenRouter usage analytics, billing\u002Fspend analysis, generation metadata, provider uptime\u002Flatency, generic model pricing\u002Fcapability lookup without any selection or benchmark-relevance decision, or creating an evaluation suite for a local app.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2008,2009,2010],{"name":1977,"slug":1978,"type":16},{"name":14,"slug":15,"type":16},{"name":18,"slug":19,"type":16},"2026-07-14T05:38:27.658475",{"slug":2013,"name":2013,"fn":2014,"description":2015,"org":2016,"tags":2017,"stars":24,"repoUrl":25,"updatedAt":2020},"openrouter-generations","retrieve metadata for OpenRouter generations","Retrieve detailed metadata and stored content for individual OpenRouter generations. Use when the user wants to inspect a specific request — its cost, latency, token usage, provider routing, or the actual prompt\u002Fcompletion text — or is debugging a failed or unexpected generation.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2018,2019],{"name":18,"slug":19,"type":16},{"name":9,"slug":8,"type":16},"2026-07-14T05:38:25.132801",{"slug":2022,"name":2022,"fn":2023,"description":2024,"org":2025,"tags":2026,"stars":24,"repoUrl":25,"updatedAt":2031},"openrouter-images","generate images with OpenRouter","Generate images from text prompts and edit existing images using OpenRouter's dedicated Image API. Use when the user asks to create, generate, or make an image, picture, or illustration from a description, or wants to edit, modify, transform, or alter an existing image with a text prompt.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2027,2030],{"name":2028,"slug":2029,"type":16},"Image Generation","image-generation",{"name":9,"slug":8,"type":16},"2026-07-14T05:38:21.393411",{"slug":2033,"name":2033,"fn":2034,"description":2035,"org":2036,"tags":2037,"stars":24,"repoUrl":25,"updatedAt":2040},"openrouter-models","query OpenRouter model metadata and pricing","Query OpenRouter for available AI models, pricing, capabilities, throughput, and provider performance. Use when the user asks about available OpenRouter models, model pricing, model context lengths, model capabilities, provider latency or uptime, throughput limits, supported parameters, wants to search\u002Ffilter\u002Fcompare models, or find the fastest provider for a model.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2038,2039],{"name":18,"slug":19,"type":16},{"name":9,"slug":8,"type":16},"2026-07-14T05:38:22.650307",{"slug":2042,"name":2042,"fn":2043,"description":2044,"org":2045,"tags":2046,"stars":24,"repoUrl":25,"updatedAt":2054},"openrouter-oauth","implement OpenRouter OAuth authentication","Implement \"Sign In with OpenRouter\" using OAuth PKCE — framework-agnostic, no SDK or client registration required. Use when the user wants to add OpenRouter login, authentication, sign-in buttons, OAuth, or AI model inference API keys for browser-based apps. No client registration, no backend, no secrets required.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2047,2050,2053],{"name":2048,"slug":2049,"type":16},"Auth","auth",{"name":2051,"slug":2052,"type":16},"OAuth","oauth",{"name":9,"slug":8,"type":16},"2026-07-14T05:38:20.116308",17,{"items":2057,"total":2055},[2058,2065,2071,2077,2083,2088,2093],{"slug":1916,"name":1916,"fn":1917,"description":1918,"org":2059,"tags":2060,"stars":24,"repoUrl":25,"updatedAt":1931},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2061,2062,2063,2064],{"name":1922,"slug":1923,"type":16},{"name":1925,"slug":1926,"type":16},{"name":9,"slug":8,"type":16},{"name":1929,"slug":1930,"type":16},{"slug":1933,"name":1933,"fn":1934,"description":1935,"org":2066,"tags":2067,"stars":24,"repoUrl":25,"updatedAt":1941},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2068,2069,2070],{"name":1922,"slug":1923,"type":16},{"name":1925,"slug":1926,"type":16},{"name":1929,"slug":1930,"type":16},{"slug":1943,"name":1943,"fn":1944,"description":1945,"org":2072,"tags":2073,"stars":24,"repoUrl":25,"updatedAt":1955},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2074,2075,2076],{"name":1949,"slug":1950,"type":16},{"name":1952,"slug":1953,"type":16},{"name":18,"slug":19,"type":16},{"slug":1957,"name":1957,"fn":1958,"description":1959,"org":2078,"tags":2079,"stars":24,"repoUrl":25,"updatedAt":1969},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2080,2081,2082],{"name":1963,"slug":1964,"type":16},{"name":1966,"slug":1967,"type":16},{"name":1929,"slug":1930,"type":16},{"slug":1971,"name":1971,"fn":1972,"description":1973,"org":2084,"tags":2085,"stars":24,"repoUrl":25,"updatedAt":1980},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2086,2087],{"name":1977,"slug":1978,"type":16},{"name":9,"slug":8,"type":16},{"slug":1982,"name":1982,"fn":1983,"description":1984,"org":2089,"tags":2090,"stars":24,"repoUrl":25,"updatedAt":1989},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2091,2092],{"name":1977,"slug":1978,"type":16},{"name":1949,"slug":1950,"type":16},{"slug":1991,"name":1991,"fn":1992,"description":1993,"org":2094,"tags":2095,"stars":24,"repoUrl":25,"updatedAt":2001},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[2096,2097,2098],{"name":1977,"slug":1978,"type":16},{"name":18,"slug":19,"type":16},{"name":1999,"slug":2000,"type":16}]