Raycast: расширение с Claude и GPT на своём ключе
Raycast AI считает запросы по подписке, а свой ключ — по факту расхода. Собираем расширение на TypeScript, которое ходит напрямую в API мимо встроенного AI.
4 мин · · Обновлено · IDE · инструменты
Встроенный Raycast AI — это подписка с фиксированной ценой, а не оплата за фактический расход. Если нужен конкретный контроль над тем, какая модель отвечает и сколько это стоит, проще написать своё расширение, которое ходит в API напрямую по вашему ключу — Raycast это позволяет как обычное TypeScript-расширение с собственными сетевыми вызовами.
Структура расширения
raycast-zukko/
package.json
src/
ask.tsx
В package.json описываются команда и её конфигурация — Preferences, куда попадёт ключ пользователя:
{
"name": "zukko-ask",
"title": "Ask AI",
"commands": [
{ "name": "ask", "title": "Ask", "mode": "view" }
],
"preferences": [
{
"name": "apiKey",
"type": "password",
"title": "Zukko API Key",
"description": "Ключ вида fetch_...",
"required": true
},Ключ хранится в preferences с типом password — Raycast шифрует его в своём хранилище, а не держит в открытом виде в файле конфига расширения.
Команда ask.tsx
import { ActionPanel, Action, Form, getPreferenceValues, showToast, Toast } from "@raycast/api";
import { useState } from "react";
interface Prefs { apiKey: string; model: string; }
export default function Command() {
const { apiKey, model } = getPreferenceValues<Prefs>();
const [answer, setAnswer] = useState("");
async function ask(prompt: string) {
const toast = await showToast({ style: Toast.Style.Animated, title: "Спрашиваю..." });
const r = await fetch("https://api.zukko.pro/v1/chat/completions", {
method: "POST",Быстрая модель для интерфейса, которому важна скорость
Raycast — это про мгновенный отклик, поэтому по умолчанию в примере стоит лёгкая glm-5.3-flash ($0.04 за миллион токенов), а не тяжёлая модель с расширенным контекстом. Для коротких команд вроде «перефразируй», «сократи», «переведи одну строку» разница в задержке между glm-5.3-flash и, скажем, claude-opus-5-5 может быть заметна на глаз — проверьте на своих командах; для расширения, которое открывают на секунду, скорость часто важнее. Тяжёлую модель имеет смысл оставить отдельным пунктом дропдауна для случаев, когда нужна именно она — например, вопрос с картинкой (изображения читают модели Claude и GPT; у GLM vision нет) или разбор длинного фрагмента кода в контексте 1,000,000 токенов (у GLM окно 128K).
Кэш реально экономит на Raycast-паттернах использования
Расширения Raycast часто вызываются с одним и тем же промптом снова и снова — «объясни это регулярное выражение», «сократи заголовок». Заголовок X-Zukko-Cache: true в примере выше включает кэширование одинаковых запросов на срок до 7 суток: повторный вызов с полностью совпадающим телом запроса (тот же текст, та же модель, те же параметры) возвращается мгновенно и бесплатно, а в ответе будет X-Zukko-Cache: hit. Отличие хотя бы в одном символе — уже промах кэша; попадания в кэш не пишутся в /v1/usage. Для расширения с быстрым UX это ощущается как разница между «висит секунду» и «отвечает сразу».
Обработка типичных ошибок в интерфейсе Raycast
Raycast больше не прощает голого исключения — лучше сразу переводить коды ошибок в понятный toast:
if (r.status === 401) {
toast.title = "Проверьте API-ключ в настройках расширения";
} else if (r.status === 402) {
toast.title = "Баланс закончился — пополните на zukko.pro/app";
} else if (r.status === 404) {
toast.title = "Модель не найдена, проверьте имя в настройках";
} else if (r.status === 503) {
toast.title = "Модель сейчас недоступна — выберите другую в настройках";
} else if (r.status === 429) {
toast.title = "Исчерпан дневной или месячный лимит ключа (или провайдер перегружен)";
}Своего rate limit у шлюза нет: 429 от Zukko означает key_daily_limit_reached (сброс в 00:00 UTC) или key_monthly_limit_reached, прочие 429 приходят от провайдера. Выключенная модель отвечает 503 model_disabled.
Ключ можно получить и обновить в кабинете на https://zukko.pro/app/api-keys — на странице конкретного ключа заодно настраиваются его дневной/месячный лимит и список разрешённых моделей, что полезно, если расширением пользуется не только один человек, а расшарено в команде через общий ключ с урезанными правами.
Если нужна генерация изображений прямо из Raycast
Генерация изображений через Zukko сейчас временно недоступна (актуальный список моделей — GET https://api.zukko.pro/v1/models). Когда она вернётся, её стоит вынести в отдельную команду с явным предупреждением о цене: модели картинок оплачиваются за штуку, а не за токены, и смешивать их с текстовым ask не стоит.
Проверка расхода прямо из расширения
Полезно добавить вторую команду, которая просто дергает /v1/balance и показывает остаток в HUD Raycast — тогда не нужно переключаться в браузер, чтобы понять, пора ли пополнять счёт:
const r = await fetch("https://api.zukko.pro/v1/balance", {
headers: { "Authorization": `Bearer ${apiKey}` }
});
const { balance_cents } = await r.json();
await showHUD(`Баланс: $${(balance_cents / 100).toFixed(2)}`);Заголовок X-Fetch-Balance-Cents, который приходит с каждым обычным (нестриминговым) ответом на ask, тоже можно писать в локальный кэш расширения и показывать рядом с ответом — тогда видно остаток без отдельного запроса, сразу после каждого вызова модели. Учтите: несмотря на название, значение в нём в микродолларах (1 000 000 = $1), поэтому делите его на 1_000_000, а не на 100. Точный баланс в центах — поле balance_cents из /v1/balance.
Ограничение расхода на командный ключ
Если ключ в Preferences общий на всю команду, задайте на странице ключа в кабинете (https://zukko.pro/app/api-keys) дневной лимит расхода в долларах — это защитит бюджет от одного человека, который случайно зациклит вызовы через быструю модель. Список разрешённых моделей на той же странице стоит держать в синхроне с дропдауном в package.json, чтобы расширение не предлагало модели, которые ключу запрещены политикой — иначе пользователь получит 403 model_not_allowed_for_key вместо ответа.
zukko
Платите в 25×
меньше
за Claude Code & ChatGPT
Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.
Похожие статьи
- JetBrains AI Assistant не работает: причины и обходные путиAI Assistant не активируется, молчит или недоступен в отдельных файлах. Разбираем причины по документации JetBrains и подключаем свои модели через шлюз.
- DeepSeek в VS Code: подключение через Cline, Kilo Code и ContinueПодключаем DeepSeek к Cline, Kilo Code и Continue с одним ключом, выбираем между Flash и Pro и считаем, сколько стоит рабочий день с агентом в редакторе.
- Аналоги GitHub Copilot со своим API-ключом: что выбратьCline, Kilo Code, Continue и Cursor работают со своим ключом. Сравниваем, куда они встроены, как подключаются к шлюзу и как считать расход.
- Invalid API key в opencode: почему ключ не принимается и как проверитьОшибка Invalid API key в opencode почти всегда сводится к четырём причинам. Проверяем ключ отдельно от opencode и находим, где ломается цепочка.