Parameters & Secrets
How vskill Studio stores, resolves, and consumes credentials and parameters for skills.
Every skill detail page in Studio has a Parameters & Secrets panel. This page explains exactly where those values live on disk, how they resolve at runtime, and how integration tests declare what they need.
What this is
Some skills need credentials or parameters to run — an API key for an image generator, a bot token for Slack, a project ID for a Google Workspace integration. vskill keeps each skill's credentials in a per-skill local file so they never leak between skills and never leave your machine.
The Parameters & Secrets panel in Studio is the UI on top of that file. It shows what credentials a skill's integration tests declare as required, what values you have set, and lets you add custom ones.
Where values are stored
Each skill has its own .env.local file inside the skill
directory:
The format is plain dotenv:
GEMINI_API_KEY=abc123xyz789
SLACK_BOT_TOKEN=xoxb-1234567890-...
MY_CUSTOM_PARAM=valueThe first time you save a credential through Studio, vskill creates
.env.local and ensures it is listed in
.gitignore. Existing entries are preserved.
Resolver order
When something needs the value of GEMINI_API_KEY, vskill
walks two sources in order:
This means a value you exported in your shell takes precedence over the file. It
also means vskill never injects .env.local entries into
the global environment — they stay scoped to the resolver call.
How params show up in the panel
1. Declared via evals.json
Integration test cases declare what they need:
{
"evals": [
{
"id": 2,
"name": "integration-test",
"testType": "integration",
"requiredCredentials": ["GEMINI_API_KEY"]
}
]
}Studio scans every test case in evals.json, collects the
union of requiredCredentials, and shows each one as a row
with status ready (resolvable) or missing
(not yet set in either source).
2. Custom parameters added in the UI
Click + Add Parameter, enter a key (uppercase snake_case) and a
value, save. Studio appends it to .env.local and shows
the row alongside declared credentials. Custom params are useful for skill code
that reads its own configuration without going through an integration test
declaration.
Runtime consumption
At runtime, integration tests preflight by calling
resolveAllCredentials(names, skillDir). If anything is
missing, the run fails fast with a list of what to set and how. Skill code itself
reads from process.env first (so a shell export wins),
and falls back to a parsed read of .env.local.
// vskill internals — resolver chain
const envVal = process.env[name];
if (envVal) return { value: envVal, source: "env" };
const dotenvPath = join(skillDir, ".env.local");
if (existsSync(dotenvPath)) {
const parsed = parseDotenv(readFileSync(dotenvPath, "utf-8"));
if (parsed[name]) return { value: parsed[name], source: "dotenv" };
}vskill does not call dotenv.config() —
values from .env.local are never written into
process.env. They are read on-demand by the resolver.
Security
vskill cannot guarantee a credential is well-formed or appropriately scoped.
Treat .env.local the same way you treat any other
credential file on your machine.
Common credentials by skill type
Quick reference for popular skill types — the actual list is whatever
requiredCredentials the skill declares in its
evals.json:
Always check the skill's own SKILL.md and evals.json for
the authoritative list before setting credentials.
Related resources