This skill is version 2.0.4. Before first use each session, check for updates:
bash
curl -sf https://raw.githubusercontent.com/vargHQ/skills/main/varg-ai/SKILL.md | grep 'version:' | head -1
If the remote version is newer than 2.0.4, update and re-read this file:
bash
npx -y skills update
Before generating anything, check authentication and determine rendering mode.
Do NOT run interactive CLI tools (like bunx vargai init) -- they require stdin which agents cannot provide. Use the curl-based flow below instead.
bash
echo "${VARG_API_KEY:-}" && cat ~/.varg/credentials 2>/dev/null
If VARG_API_KEY is set (via env or credentials file), skip to step 2.
If neither exists, authenticate the user. Try Option A first, fall back to Option B.
Option A: User already has an API key
Ask the user if they have a VARG_API_KEY. If yes, tell them to export it in their terminal:
bash
export VARG_API_KEY=<their_key>
Important: Do NOT ask the user to paste the raw key to you. Ask them to run the export command themselves. Then skip to "Save credentials" below.
Option B: Sign up / sign in via email (OTP)
bash
curl -s -X POST https://app.varg.ai/api/auth/cli/send-otp \
-H "Content-Type: application/json" \
-d '{"email":"USER_EMAIL"}'
bash
VARG_AUTH=$(curl -s -X POST https://app.varg.ai/api/auth/cli/verify-otp \
-H "Content-Type: application/json" \
-d '{"email":"USER_EMAIL","code":"THE_6_DIGIT_CODE"}')
export VARG_API_KEY=$(echo "$VARG_AUTH" | grep -o '"api_key":"[^"]*"' | cut -d'"' -f4)
echo "Authenticated. Balance: $(echo "$VARG_AUTH" | grep -o '"balance_cents":[0-9]*' | cut -d: -f2) credits"
The response contains {"api_key":"varg_xxx","email":"...","balance_cents":0,"access_token":"..."}.
The key is now in $VARG_API_KEY -- never reference the raw value directly.
Save credentials
Once VARG_API_KEY is set (from either option), save it globally and verify. Always reference $VARG_API_KEY -- never the raw value:
bash
mkdir -p ~/.varg && echo "{\"api_key\":\"$VARG_API_KEY\",\"email\":\"USER_EMAIL\",\"created_at\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"}" > ~/.varg/credentials && chmod 600 ~/.varg/credentials
Verify the key works:
bash
curl -s -H "Authorization: Bearer $VARG_API_KEY" https://api.varg.ai/v2/billing/balance
You should get {"available": ..., "total_balance": ..., ...} (values in credits/cents). If you get 401, the key is invalid -- ask the user to double-check it.
Also add to the project .env if one exists:
bash
echo "VARG_API_KEY=$VARG_API_KEY" >> .env
Check balance and add credits
Check balance_cents from the verify-otp response, or available from the balance check above. If balance is 0 (or too low for the user's task), the user needs credits before generating anything. 1 credit = 1 cent. A typical video costs $2-5 (200-500 credits).
Available packages:
Package IDCreditsPricecredits-20002,000$20credits-50005,000$50credits-1000010,000 (recommended)$100credits-2000020,000$200credits-5000050,000$500credits-100000100,000$1,000
Ask the user which package they'd like, then:
access_token (from Option B email OTP), capture it and create a Stripe checkout session:bash
VARG_ACCESS_TOKEN=$(echo "$VARG_AUTH" | grep -o '"access_token":"[^"]*"' | cut -d'"' -f4)
curl -s -X POST https://app.varg.ai/api/billing/checkout \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $VARG_ACCESS_TOKEN" \
-H "Origin: https://app.varg.ai" \
-d '{"packageId":"PACKAGE_ID"}'
Response: {"url":"https://checkout.stripe.com/..."}
Tell the user to open that URL in their browser to complete payment. Credits are added immediately after payment.
bunffmpegModeNoNoCloud Render -- read cloud-render.mdYesNoCloud Render -- read cloud-render.mdYesYesLocal Render (recommended) -- read local-render.md
Everything you know about varg is likely outdated. Always verify against this skill and its references before writing code.
Image({...}) creates media, <Clip> composes timeline. Never write <Image prompt="..." />.Video({ prompt: { images: [img] } }) takes exactly one image. Multiple images cause errors.providerOptions: { varg: {...} }, never fal, when going through the gateway (both modes).export VARG_API_KEY=... and use $VARG_API_KEY in all subsequent commands. This prevents keys from leaking into conversation context and terminal history.bash
# Submit TSX code to the render service — returns a job: {"id": "job_xxx", "status": "queued", ...}
curl -s -X POST https://api.varg.ai/v2/render \
-H "Authorization: Bearer $VARG_API_KEY" \
-H "Content-Type: application/json" \
-d '{"code": "const img = Image({ model: varg.imageModel(\"nano_banana_pro\"), prompt: \"a cabin in mountains at sunset\", aspectRatio: \"16:9\" });\nexport default (<Render width={1920} height={1080}><Clip duration={3}>{img}</Clip></Render>);"}'
# Poll for result (repeat until "completed" or "failed"; video at output.outputs[0].url)
curl -s https://api.varg.ai/v2/jobs/JOB_ID \
-H "Authorization: Bearer $VARG_API_KEY"
Full details: cloud-render.md
tsx
/** @jsxImportSource vargai */
import { Render, Clip, Image } from "vargai/react"
import { createVarg } from "vargai/ai"
const varg = createVarg({ apiKey: process.env.VARG_API_KEY! })
const img = Image({
model: varg.imageModel("nano_banana_pro"),
prompt: "a cabin in mountains at sunset",
aspectRatio: "16:9"
})
export default (
<Render width={1920} height={1080}>
<Clip duration={3}>{img}</Clip>
</Render>
)
bash
bunx vargai render video.tsx --preview # free preview
bunx vargai render video.tsx --verbose # full render (costs credits)
Full details: local-render.md
For one-off images, videos, speech, or music without building a multi-clip template:
bash
curl -X POST https://api.varg.ai/v2/image \
-H "Authorization: Bearer $VARG_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "nano_banana_pro", "prompt": "a sunset over mountains"}'
Full API reference: gateway-api.md
Video code has two layers: media generation (function calls) and composition (JSX).
tsx
// 1. GENERATE media via function calls
const img = Image({ model: ..., prompt: "..." })
const vid = Video({ model: ..., prompt: { text: "...", images: [img] }, duration: 5 })
const voice = Speech({ model: ..., voice: "rachel", children: "Hello!" })
// 2. COMPOSE via JSX tree
export default (
<Render width={1080} height={1920}>
<Music model={...} prompt="upbeat electronic" duration={10} volume={0.3} />
<Clip duration={5}>
{vid}
<Title position="bottom">Welcome</Title>
</Clip>
<Captions src={voice} style="tiktok" withAudio />
</Render>
)
ComponentTypePurposeImage()Function callGenerate still imageVideo()Function callGenerate video (text-to-video or image-to-video)Speech()Function callText-to-speech audio<Render>JSXRoot container -- sets width, height, fps<Clip>JSXTimeline segment -- duration, transitions<Music>JSXBackground audio (always set duration!)<Captions>JSXSubtitle track from Speech<Title>JSXText overlay<Overlay>JSXPositioned layer<Split> / <Grid>JSXLayout helpers
Full props: components.md
Both modes use varg.* for all models. The only difference is imports:
Cloud RenderLocal RenderNo imports needed (globals are auto-injected)import { ... } from "vargai/react" + import { createVarg } from "vargai/ai"``varg.imageModel("nano_banana_pro")``varg.imageModel("nano_banana_pro")``varg.videoModel("kling_v3")``varg.videoModel("kling_v3")``varg.speechModel("eleven_v3")``varg.speechModel("eleven_v3")
Always use varg.*Model() with VARG_API_KEY. It handles routing, caching, billing, and works with a single key. BYOK via the API is not available in v2 — see byok.md for what works (local-render direct provider modules only).
GET https://api.varg.ai/v2/pricing (no auth). Estimate any request: POST /v2/estimate.--preview generates free placeholders to validate structure.Load these on demand based on what you need:
NeedReferenceWhen to loadRender via APIcloud-render.mdNo bun/ffmpeg, or user wants cloud renderingRender locallylocal-render.mdbun + ffmpeg availablePatterns & workflowsrecipes.mdTalking head, character consistency, slideshow, lipsyncModel selectionmodels.mdChoosing models, checking prices, duration constraintsComponent propscomponents.mdNeed detailed props for any componentBetter promptsprompting.mdUser wants cinematic / high-quality resultsREST APIgateway-api.mdSingle-asset generation or Render API detailsDebuggingcommon-errors.mdSomething failed or produced unexpected resultsFull examplestemplates.mdNeed complete copy-paste-ready templatesBYOK keysbyok.mdUsing your own provider API keys for $0 billing