Drive the skvm CLI on behalf of a user to profile models, AOT-compile skills, run skill-assisted tasks, run benchmarks, and manage compiled proposals. Trigge...
---
name: skvm-general
description: Drive the skvm CLI on behalf of a user to profile models, AOT-compile skills, run skill-assisted tasks, run benchmarks, and manage compiled proposals. Trigger when the user asks to "profile", "aot-compile", "bench", "run a single ad-hoc task with a skill", or asks about skvm proposals. Do NOT trigger for `jit-optimize` or when the user wants to optimize/improve a skill — use the sibling `skvm-jit` skill instead.
---
# SkVM General Usage
You are driving `skvm`, a CLI that AOT-compiles and runs LLM agent skills across heterogeneous models. Use this skill when the user wants to *use* skvm — profile a model, AOT-compile a skill, run a task with a skill, run a benchmark, or manage optimization proposals. Do **not** invent flags — every example below uses the real flag set from the installed `skvm` binary.
## Step 1: Prerequisite self-check
Split the check in two — the binary must always be present, but the API key is only required for commands that call an LLM.
**Always required** — skvm is on PATH:
```bash
skvm --help >/dev/null 2>&1 || { echo "skvm not installed — tell the user to run: curl -fsSL https://skillvm.ai/install.sh | sh"; exit 1; }
```
**Required only before LLM-calling commands** — `profile` (without `--list`), `aot-compile`, `pipeline`, `run`, `bench`, `jit-optimize`. Local filesystem commands (`profile --list`, `proposals list|show|reject`, `logs`, `clean-jit`) do **not** need the API key — run them even if the key is unset.
```bash
# Before running profile/aot-compile/run/bench/jit-optimize:
test -n "${OPENROUTER_API_KEY:-}" || { echo "OPENROUTER_API_KEY is not set — ask the user for their key"; exit 1; }
```
If a required prerequisite is missing, **stop** and tell the user what is missing. Do not install anything yourself.
## Step 2: Profile a model
A profile (TCP — Target Capability Profile) records what an LLM can do across 26 primitive capabilities. It is the input for AOT compilation and is cached so subsequent compile calls reuse it.
```bash
skvm profile --model=<id> # profile one model
skvm profile --model=<id1>,<id2> --concurrency=4 # profile several in parallel
skvm profile --model=<id> --adapter=opencode # non-default adapter
skvm profile --model=<id> --force # ignore cache, re-run
skvm profile --list # list cached profiles
```
Notes:
- Default adapter is `bare-agent`. Other valid adapters: `opencode`, `openclaw`, `hermes`, `jiuwenclaw`.
- Cache lives at `$SKVM_PROFILES_DIR` (default `.skvm/profiles/`).
- Profiling is expensive — confirm with the user before running on several models, and prefer `--concurrency` over sequential runs.
## Step 3: AOT-compile a skill
AOT compilation rewrites a skill's `SKILL.md` (and optionally bundle files) so it fits a specific target model's capability profile. The three-pass AOT compiler runs by default.
```bash
skvm aot-compile --skill=<path> --model=<id> # all three passes
skvm aot-compile --skill=<path> --model=<id> --pass=1,2,3 # explicit
skvm aot-compile --skill=<path> --model=<id> --pass=1 # only pass 1 (SCR + gap analysis)
skvm aot-compile --skill=<path> --model=<id> --dry-run # no write
skvm pipeline --skill=<path> --model=<id> # profile-if-needed → aot-compile
```
Pass semantics:
- `--pass=1` — SCR extraction, gap analysis, capability substitution/compensation
- `--pass=2` — dependency manifest + env-binding script generation
- `--pass=3` — workflow decomposition + DAG parallelism extraction
Compiled variants land under the proposals tree (`proposals/aot-compile/...`). Multiple passes can be combined in any subset: `--pass=1,3` runs passes 1 and 3, skipping 2.
## Step 4: Run a single task with a skill
For ad-hoc debugging of one skill on one task:
```bash
skvm run --task=<path/to/task.json> --model=<id> # no skill
skvm run --task=<path> --model=<id> --skill=<path/to/SKILL.md> # with skill
skvm run --task=<path> --model=<id> --adapter=opencode --verbose # explicit adapter + debug
```
Use this to reproduce a single failing task or validate a skill edit. Do **not** use it for benchmarking — use `skvm bench` instead.
## Step 5: Bench a skill
Benchmarking runs a skill across many tasks and condition variants. It can get expensive fast — always confirm with the user before running across many models or tasks, and use `--concurrency` for parallelism.
```bash
skvm bench --model=<id> # all conditions, all tasks
skvm bench --model=<id> --conditions=original,aot-compiled # baseline + compiled
skvm bench --model=<id> --conditions=jit-optimized # use latest jit-optimize best round
skvm bench --model=<id> --conditions=jit-boost --jit-runs=5 # 5 warmup runs for solidification
skvm bench --model=<id1>,<id2> --concurrency=4 # multi-model in parallel
skvm bench --model=<id> --tasks=task_01,task_02 --runs-per-task=3 # specific tasks, 3 reps each
skvm bench --model=<id> --async-judge # defer LLM-judge to post-run batch
skvm bench --resume=latest # resume an interrupted session
skvm bench --list-sessions # list past sessions
```
Valid `--conditions` strings:
- `no-skill` — run the task with no skill injected (baseline floor)
- `original` — the skill as-written (baseline ceiling)
- `aot-compiled` — full 3-pass AOT compiled variant
- `aot-compiled-p1`, `-p2`, `-p3`, `-p12`, `-p13`, `-p23` — single or partial AOT passes
- `jit-optimized` — the latest best-round variant from `skvm jit-optimize` proposals
- `jit-boost` — code-solidification runtime optimization
Bench logs land at `.skvm/log/bench/<sessionId>/`.
## Step 6: Manage jit-optimize proposals
Proposals are the artifact produced by `skvm jit-optimize` (and by the sibling `skvm-jit` skill). Each proposal contains the original skill in `round-0/`, one or more improved rounds in `round-N/`, and metadata recording which round the engine considered best.
```bash
skvm proposals list # all proposals
skvm proposals list --status=pending # only pending (not yet accepted/rejected)
skvm proposals list --skill=<name> --target-model=<id> # filter by skill + target model
skvm proposals show <id> # print metadata and per-round summary
skvm proposals accept <id> # deploy the engine-recommended best round
skvm proposals accept <id> --round=2 # override: deploy round 2 instead
skvm proposals accept <id> --target=<dir> # deploy to a non-default skill dir
skvm proposals reject <id> # mark as rejected (no deploy)
skvm proposals cancel <id> # stop a detached run still in phase=running
```
Proposal id format: `<harness>/<safe-target-model>/<skill-name>/<timestamp>`, where `<safe-target-model>` is the slugified target model id (forward slashes in the CLI id become `--`). When the user gives you an id like `bare-agent/openrouter--anthropic--claude-sonnet-4.6/calendar/20260401T120000Z`, pass it verbatim — do not reformat it.
Detached runs (`skvm jit-optimize --detach`) write an extra `run-status.json` inside the proposal directory that tracks execution phase (`running` / `done` / `failed`), separate from `meta.json.status`. `skvm proposals show` renders this header and tails the last 20 lines of `run.log` for running / failed detached runs. If the user wants to stop a detached optimization mid-run, use `cancel`; sync runs (no `--detach`) do not need `cancel`, they block until complete.
**Critical rule**: only run `skvm proposals accept` when the user has **explicitly** asked to deploy. If the user just says "check the proposals", run `list` and `show` and stop there. Accepting without confirmation overwrites the skill files in place.
## Step 7: Environment variables
| Variable | Required | Purpose |
|----------|----------|---------|
| `OPENROUTER_API_KEY` | yes | OpenRouter key used by bare-agent, profiler, compiler (when routed through OpenRouter), and jit-optimize optimizer |
| `ANTHROPIC_API_KEY` | optional | Enables the Anthropic SDK backend for the compiler and judge |
| `SKVM_DATA_DIR` | optional | Override the input dataset root (default: `./skvm-data` submodule) |
| `SKVM_CACHE` | optional | Override the runtime cache root (default: `~/.skvm`) |
| `SKVM_PROPOSALS_DIR` | optional | Override the proposals storage root (default: `~/.skvm/proposals/`) |
`OPENROUTER_API_KEY` is only required for commands that actually call an LLM. Local-only commands (`proposals list/show/reject`, `profile --list`, `logs`, `clean-jit`) run without it.
## Rules
- **Never run `bench` or `profile` across many models without explicit user confirmation** — they can cost tens of dollars per run. Always quote an expected model count back to the user before starting.
- **Never run `skvm proposals accept` unless the user explicitly asked to deploy.**
- **Prefer `--concurrency=<n>` over sequential loops** for multi-model work.
- **Do not invent flags.** If the user asks for something you don't see in this skill, run `skvm <command> --help` to check before guessing.
- **Do not install anything.** If `skvm` is missing, tell the user to run the installer; if `OPENROUTER_API_KEY` is missing, ask them for it.
- **Surface skvm's stderr progress lines** (e.g. `Installing bundled opencode…`, `Downloading profile…`) as normal output — they are not errors.
don't have the plugin yet? install it then click "run inline in claude" again.
You are driving skvm, a CLI that AOT-compiles and runs LLM agent skills across heterogeneous models. Use this skill when the user wants to use skvm , profile a model, AOT-compile a skill, run a task with a skill, run a benchmark, or manage optimization proposals. Do not invent flags. Every command below uses the real flag set from the installed skvm binary.
This skill drives the skvm CLI on behalf of users who want to profile LLM models, AOT-compile skills to fit specific model capability profiles, run single tasks with skills for debugging, run benchmarks across many tasks and models, or manage compilation proposals. Use this skill when the user explicitly asks to "profile", "aot-compile", "bench", "run a task with a skill", or interact with proposals. Do not trigger this skill for jit-optimize operations or skill improvement requests , those belong to the skvm-jit skill. This skill is appropriate only when the user is consuming or validating skvm functionality, not when they are trying to improve or optimize skills iteratively.
skvm binary: must be on PATH. Check with skvm --help >/dev/null 2>&1.
OPENROUTER_API_KEY (environment variable, required for LLM-calling commands): OpenRouter API key. Required before running profile (without --list), aot-compile, pipeline, run, bench, or any command that routes through OpenRouter. Local-only commands (profile --list, proposals list/show/reject/cancel, logs, clean-jit) do not require this. Set as export OPENROUTER_API_KEY=<your-key>.
ANTHROPIC_API_KEY (environment variable, optional): Anthropic SDK key. Enables the Anthropic backend for the compiler and LLM judge if you prefer it over OpenRouter routing.
SKVM_DATA_DIR (environment variable, optional): override the input dataset root. Defaults to ./skvm-data submodule. Set as export SKVM_DATA_DIR=<path>.
SKVM_CACHE (environment variable, optional): override the runtime cache root. Defaults to ~/.skvm. Set as export SKVM_CACHE=<path>.
SKVM_PROPOSALS_DIR (environment variable, optional): override proposals storage root. Defaults to ~/.skvm/proposals/. Set as export SKVM_PROPOSALS_DIR=<path>.
Input files (for run, aot-compile, pipeline): a valid task.json file (for run) or a SKILL.md file (for aot-compile, pipeline).
Model identifiers (for profile, aot-compile, run, bench): valid model ids supported by OpenRouter or your configured backend. Format: openrouter--vendor--model-name or vendor-specific slug.
Always check that skvm is on PATH. Only check for OPENROUTER_API_KEY before commands that call an LLM.
Always required , skvm binary on PATH:
skvm --help >/dev/null 2>&1 || { echo "skvm not installed , tell the user to run: curl -fsSL https://skillvm.ai/install.sh | sh"; exit 1; }
Required only before LLM-calling commands , profile (without --list), aot-compile, pipeline, run, bench. Local filesystem commands (profile --list, proposals list/show/reject/cancel, logs, clean-jit) do not need the API key.
# Before running profile/aot-compile/pipeline/run/bench:
test -n "${OPENROUTER_API_KEY:-}" || { echo "OPENROUTER_API_KEY is not set , ask the user for their key"; exit 1; }
Input: user request to run a skvm command.
Output: confirmation that skvm binary is installed and API key (if needed) is set, or error message with remediation. Proceed only if checks pass.
A profile (TCP, Target Capability Profile) records what an LLM can do across 26 primitive capabilities. It is the required input for AOT compilation and is cached so subsequent compile calls reuse it. Profiling is expensive (typically 5-15 dollars per model), so always confirm with the user before running on multiple models.
Commands:
skvm profile --model=<id> # profile one model
skvm profile --model=<id1>,<id2> --concurrency=4 # profile several in parallel
skvm profile --model=<id> --adapter=opencode # non-default adapter
skvm profile --model=<id> --force # ignore cache, re-run
skvm profile --list # list cached profiles (local only, no API key needed)
Adapters: default is bare-agent. Valid alternatives: opencode, openclaw, hermes, jiuwenclaw.
Cache: profiles are stored at $SKVM_PROFILES_DIR (default .skvm/profiles/).
Input: user request to profile a model or list cached profiles; model id(s); optional adapter name, force flag, or concurrency level.
Output: profiling progress lines to stderr. On success, a profile file written to cache. On failure, error message with details. List mode returns table of cached profile metadata.
AOT compilation rewrites a skill's SKILL.md (and optionally bundle files) to fit a specific target model's capability profile. The three-pass AOT compiler runs by default.
Commands:
skvm aot-compile --skill=<path> --model=<id> # all three passes
skvm aot-compile --skill=<path> --model=<id> --pass=1,2,3 # explicit pass list
skvm aot-compile --skill=<path> --model=<id> --pass=1 # only pass 1
skvm aot-compile --skill=<path> --model=<id> --dry-run # no write to disk
skvm pipeline --skill=<path> --model=<id> # auto-profile if needed, then compile
Pass semantics:
Output location: compiled variants land under the proposals tree at ~/.skvm/proposals/aot-compile/<safe-target-model>/<skill-name>/<timestamp>/. Multiple passes can be combined: --pass=1,3 runs passes 1 and 3, skipping 2.
Input: path to a SKILL.md file; target model id; optional pass specification, dry-run flag.
Output: on success, a proposals directory with round-0 containing the compiled variant, plus metadata in meta.json. On dry-run, no files written. On failure, error message with gap analysis details.
For ad-hoc debugging of one skill on one task. Use this to reproduce a failing task or validate a skill edit. Do not use this for benchmarking , use skvm bench instead.
Commands:
skvm run --task=<path/to/task.json> --model=<id> # no skill
skvm run --task=<path> --model=<id> --skill=<path/to/SKILL.md> # with skill
skvm run --task=<path> --model=<id> --adapter=opencode --verbose # explicit adapter + debug
Input: path to task.json file; target model id; optional path to SKILL.md, adapter name, verbose flag.
Output: task result object (including raw LLM response, parsed output, judge verdict if applicable). On verbose, intermediate trace logs. On failure, error message.
Benchmarking runs a skill across many tasks and condition variants. Benchmarking is expensive (often 20-100 dollars depending on model and task count) , always confirm with the user before running across many models or tasks. Use --concurrency for parallelism instead of sequential loops.
Commands:
skvm bench --model=<id> # all conditions, all tasks
skvm bench --model=<id> --conditions=original,aot-compiled # baseline + compiled
skvm bench --model=<id> --conditions=jit-optimized # use latest jit-optimize best round
skvm bench --model=<id> --conditions=jit-boost --jit-runs=5 # 5 warmup runs for solidification
skvm bench --model=<id1>,<id2> --concurrency=4 # multi-model in parallel
skvm bench --model=<id> --tasks=task_01,task_02 --runs-per-task=3 # specific tasks, 3 reps each
skvm bench --model=<id> --async-judge # defer LLM judge to post-run batch
skvm bench --resume=latest # resume an interrupted session
skvm bench --list-sessions # list past sessions
Valid --conditions strings:
no-skill , task with no skill (baseline floor)original , skill as-written (baseline ceiling)aot-compiled , full 3-pass AOT compiled variantaot-compiled-p1, -p2, -p3, -p12, -p13, -p23 , single or partial AOT passesjit-optimized , latest best-round variant from skvm jit-optimize proposalsjit-boost , code-solidification runtime optimizationLogs: bench session logs at .skvm/log/bench/<sessionId>/.
Input: target model id(s); optional condition list, task filter, runs-per-task count, concurrency level, async-judge flag, resume or list-sessions action.
Output: benchmark session object with per-condition, per-task summary statistics (success rate, latency, cost, judge score). Logs written to .skvm/log/bench/<sessionId>/. On resume, existing session picked up. On list-sessions, table of past sessions with their ids, models, task counts, and status.
Proposals are artifacts produced by skvm jit-optimize (in the sibling skvm-jit skill) or by the aot-compile command. Each proposal contains the original skill in round-0/, one or more improved rounds in round-N/, and metadata recording which round the engine considered best.
Critical rule: only run skvm proposals accept when the user has explicitly asked to deploy. If the user just says "check the proposals", run list and show and stop there. Accepting without confirmation overwrites the skill files in place.
Commands:
skvm proposals list # all proposals
skvm proposals list --status=pending # only pending (not yet accepted/rejected)
skvm proposals list --skill=<name> --target-model=<id> # filter by skill + target model
skvm proposals show <id> # print metadata and per-round summary
skvm proposals accept <id> # deploy the engine-recommended best round
skvm proposals accept <id> --round=2 # override: deploy round 2 instead
skvm proposals accept <id> --target=<dir> # deploy to a non-default skill dir
skvm proposals reject <id> # mark as rejected (no deploy)
skvm proposals cancel <id> # stop a detached run still in phase=running
Proposal id format: <harness>/<safe-target-model>/<skill-name>/<timestamp>, where <safe-target-model> is the slugified target model id (forward slashes in the CLI id become --). Pass proposal ids verbatim.
Detached runs: skvm jit-optimize --detach writes a run-status.json inside the proposal directory tracking execution phase (running / done / failed), separate from meta.json.status. skvm proposals show renders this header and tails the last 20 lines of run.log for running or failed detached runs. Use cancel to stop a detached optimization mid-run. Sync runs (no --detach) block until complete.
Input: proposal id (for show/accept/reject/cancel); optional status filter, skill/model filter, round override, target directory, list action.
Output: on list, table of proposals with id, status, skill, target model, best round, timestamp. On show, full metadata object including per-round summary and (if detached and running) last 20 log lines. On accept/reject/cancel, confirmation message. On accept, skill files overwritten in place (or at --target dir).
All environment variables are optional to run the skill, but some are required to use certain commands. Set variables as export VAR=value before running skvm.
| Variable | Required | Purpose |
|---|---|---|
OPENROUTER_API_KEY |
yes (for LLM commands) | OpenRouter key used by bare-agent, profiler, compiler, and jit-optimize optimizer |
ANTHROPIC_API_KEY |
optional | Enables Anthropic SDK backend for compiler and judge |
SKVM_DATA_DIR |
optional | Override input dataset root (default: ./skvm-data submodule) |
SKVM_CACHE |
optional | Override runtime cache root (default: ~/.skvm) |
SKVM_PROPOSALS_DIR |
optional | Override proposals storage root (default: ~/.skvm/proposals/) |
If the user asks to profile or benchmark multiple models:
--concurrency=<n> (typically 4-8) to run in parallel, not sequential loops.If the user asks to check proposals:
skvm proposals list and optionally skvm proposals show <id> for specific proposals.skvm proposals accept unless the user explicitly asks to "deploy", "accept", or "apply" the proposal.If the user asks to run a command and OPENROUTER_API_KEY is unset:
--list, proposals list/show/reject/cancel, logs, clean-jit).--list, aot-compile, pipeline, run, bench), stop and ask the user for their OpenRouter API key.If the user asks for a flag or command option you do not see in this skill:
skvm <command> --help to check the installed binary's current options.If profiling or benchmarking is interrupted (e.g., network timeout, rate limit):
skvm bench --resume=latest to pick up where it left off (only if the session id is known).If the user runs a detached jit-optimize proposal and asks about its status:
skvm proposals show <id> to fetch run-status.json and render the current phase and last 20 log lines.skvm proposals cancel <id>.If aot-compile or bench produces a dry-run output:
--dry-run, no files are written. Show the user the proposed compiled variant in stdout/stderr.--dry-run.profile , on success, profile metadata written to .skvm/profiles/<model-id>.json. On list, stdout table of cached profiles. On failure, stderr error message with details (e.g. unsupported model, API error).
aot-compile , on success, proposals directory at ~/.skvm/proposals/aot-compile/<safe-target-model>/<skill-name>/<timestamp>/ containing round-0/ with compiled SKILL.md and optionally bundle files, plus meta.json with pass results. On dry-run, compiled variant printed to stdout, no files written. On failure, stderr error message with gap analysis.
run , on success, stdout task result object with keys: task_id, model_id, raw_response, parsed_output, judge_verdict, latency_ms, cost_usd. On failure, stderr error message with stack trace.
bench , on success, stdout session object with per-condition and per-task summary stats (success_rate, latency_ms_mean/p50/p95, cost_usd, judge_score_mean). Session logs at .skvm/log/bench/<sessionId>/. Benchmark report written to .skvm/log/bench/<sessionId>/summary.json. On failure, stderr error message.
proposals list , on success, stdout table of proposals with columns: id, status, skill, target-model, best-round, timestamp. On filter, table filtered to matching rows.
proposals show , on success, stdout metadata object with proposal id, status,