Use Xantly with Raycast (AI extensions)
Raycast AI itself is hosted, but open-source extensions that call LLMs via the Node SDK can route through Xantly. Works for both extension users and authors.
Raycast is a macOS-native launcher with a rich AI extension ecosystem. Raycast AI itself (the built-in chat) is hosted on Raycast's infra and doesn't currently support custom base URLs. But Raycast extensions that call LLMs via the Node SDK can route through Xantly, which unlocks any open-source extension that uses openai, @anthropic-ai/sdk, or the ai SDK.
Two audiences
- You use Raycast extensions that hit OpenAI/Anthropic APIs: set the env vars below and extensions will pick up Xantly automatically.
- You build Raycast extensions: use the OpenAI SDK with Xantly's base URL directly.
Prerequisites
- Raycast installed on macOS
- A Xantly API key, create one
- (Extension users) An extension that uses a standard LLM SDK and reads env vars
Setup, as a Raycast extension user
Most Raycast extensions read OPENAI_API_KEY (sometimes OPENAI_API_BASE) from the environment. Set them in your shell:
export OPENAI_API_BASE=https://api.xantly.com/v1
export OPENAI_API_KEY=xantly_sk_...
Then restart Raycast (or reload the extension). The extension's OpenAI calls will now route through Xantly.
macOS launchers don't inherit shell env vars by default. Use launchctl setenv or create ~/Library/LaunchAgents/xantly.plist to export them globally:
launchctl setenv OPENAI_API_BASE https://api.xantly.com/v1
launchctl setenv OPENAI_API_KEY xantly_sk_...
(This persists across reboots if you add it to a LaunchAgent plist.)
Setup, as an extension author
In your package.json:
{
"dependencies": {
"@raycast/api": "^1.70.0",
"openai": "^4.0.0"
}
}
In your extension source:
import { getPreferenceValues } from '@raycast/api'
import OpenAI from 'openai'
interface Preferences {
apiKey: string
baseURL: string
model: string
}
const prefs = getPreferenceValues<Preferences>()
const client = new OpenAI({
baseURL: prefs.baseURL || 'https://api.xantly.com/v1',
apiKey: prefs.apiKey,
})
const resp = await client.chat.completions.create({
model: prefs.model || 'xantly/auto-value',
messages: [{ role: 'user', content: 'Hello from Raycast' }],
})
And in your package.json preferences schema:
"preferences": [
{
"name": "baseURL",
"type": "textfield",
"required": false,
"title": "Base URL",
"description": "LLM API base URL (Xantly default)",
"default": "https://api.xantly.com/v1"
},
{
"name": "apiKey",
"type": "password",
"required": true,
"title": "API Key",
"description": "Xantly or OpenAI key"
},
{
"name": "model",
"type": "dropdown",
"required": true,
"title": "Model",
"default": "xantly/auto-value",
"data": [
{ "title": "Xantly Auto Quality", "value": "xantly/auto-quality" },
{ "title": "Xantly Auto Value", "value": "xantly/auto-value" },
{ "title": "Xantly Auto Speed", "value": "xantly/auto-speed" },
{ "title": "Claude Sonnet 4.6", "value": "anthropic/claude-sonnet-4.6" },
{ "title": "GPT-5.4", "value": "openai/gpt-5.4" }
]
}
]
Popular Raycast extensions that work with Xantly
- Ray AI community forks, open-source, reads env vars.
- AI Assistant extensions, any that bundle the
openaiSDK. - Prompt library extensions: often read
OPENAI_API_KEYdirectly. - Custom snippets with AI rewriting: Xantly works here too.
The pattern: if the extension lets you paste an OpenAI API key and optionally a base URL, Xantly works.
Model choice
| Model ID | When |
|---|---|
xantly/auto-speed | Raycast extensions, you want sub-second responses for launcher UX. |
xantly/auto-value | Balanced quality/speed. |
xantly/auto-quality | For heavy-weight extensions (summarization, writing help). |
groq/llama-3.3-70b | Fastest inference for short completions. |
Default to speed tier, Raycast is a launcher; users want snap-response.
Verify
Run any Raycast AI extension (summarize clipboard, chat assistant, etc.) and check your Xantly dashboard, the call should log with cost + model + cache status.
What you get
- Every Raycast extension that uses OpenAI. Works transparently once env vars are set.
- Cache hits on repeat prompts. Launcher workflows (same "summarize X" prompt all day) hit cache instantly.
- Waterfall fallback. Extension doesn't crash on provider outages.
- Cost per Raycast command. Tag API keys per-extension (create a Xantly key named
raycast-quicknote, etc.) for fine-grained cost tracking.
Gotchas
Raycast AI built-in is not Xantly-compatible. The chat panel in Raycast Pro uses Raycast's hosted AI. Custom base URL isn't supported for the built-in, only for extensions.
Extension env var discovery. Some extensions use env vars, some require preferences, some hardcode. Check the extension's README.
Extension authors: respect user's own key. If the user already has OPENAI_API_KEY set for their direct OpenAI usage, don't clobber it. Read your own XANTLY_API_KEY pref or fall back to env.
launchctl setenv scope. Applies to future apps launched. Restart Raycast after setting.
Next steps
- OpenAI SDK (TypeScript), the SDK Raycast extensions typically use.
- Cost-Optimized Routing, keep launcher-cadence usage cheap.
- Bring Your Own Key, use your own OpenAI credits through Xantly.
- Vercel AI SDK, alternative TS SDK popular for extensions.