In this guide, the “main session” is the session driven directly by
When the SDK launches the CLI it always appends
When
With a string array, only matching skills appear in the main model's skill listing and can be invoked through the
Plugin skills use plugin-qualified names. For plugin loading methods, see Plugins documentation.
The above configuration ultimately allows
The string-array form of
The initialization result contains the complete set of skills discovered by the CLI in this session and is not filtered by the string-array form of
If you define custom sub-Agents via
These
Only skill-related fields are shown here. See
query(), as opposed to a subagent delegated through the Agent tool. See Subagents for how the two session scopes relate.
options.skills controls the main session's skill context and Skill tool invocation policy. For a string array, the SDK sends a main-session skill allowlist and compiles each entry into Skill(name) before merging it with allowedTools. The 'all' value allows every discovered skill without adding a main-session context filter.
SDK Does Not Load Built-in Skills
When the SDK launches the CLI it always appends --disable-builtin-skills, so the session never sees the CLI's factory built-in skills (simplify, debug, security-review, quest, batch, agent-creator, hook-config, mcp-config, skill-creator, …). No source: 'built-in' entries appear in initializationResult().skills, and the model's system prompt does not see them either.
This is fixed SDK behavior with no opt-in; if you want the capability of a CLI built-in skill, either ship your own copy of the SKILL.md via a plugin / user dir / project dir, or run the CLI directly outside the SDK.
The session can still pick up skills contributed from these sources:
- plugin skills: loaded via
options.plugins, addressed with the plugin-qualified name (plugin:skill). - user / project skills: discovered when you opt into
user/project/localviaoptions.settingSources. - agent-preloaded skills: declared on
options.agents[name].skills, scoped to that sub-agent only.
query() once and read initializationResult().skills — don't hard-code the set.
Using CLI Default Policy
When skills is not passed, the SDK does not inject an additional Skill allowlist, leaving everything to the CLI's own policy. Because built-ins are disabled, initializationResult().skills is an empty array for a session with no settingSources / plugins.
Enabling All Discovered Skills
skills: 'all' allows the Skill tool to invoke every skill the CLI currently discovers (sources are determined by settingSources / plugins; built-ins are no longer included).
Enabling Only Specific Skills
Skill tool. Entries can use plain names or plugin-qualified names. An empty array [] hides every skill from the main session and rejects every Skill tool invocation.
This list does not change CLI discovery. Unlisted skills may still appear in initializationResult().skills.
Enabling Plugin Skills
Plugin skills use plugin-qualified names. For plugin loading methods, see Plugins documentation.
Merging with Explicit Tool Allowlist
Read, Grep, and Skill(review).
Hiding Discovered Skills
The string-array form of options.skills filters the main model's context and restricts Skill tool invocations, but it does not change the discovery result in initializationResult().skills. To also remove a plugin / user / project skill from the discovered inventory, use settings.skillOverrides.
'off': Completely hidden — not ininitializationResult().skills, not in the model system prompt, andSkilltool invocations are also rejected.- Other values:
'on'(default),'name-only'(only shows name, not description),'user-invocable-only'(invisible to model, user can still trigger via/name). - Scope of effect: every SDK-visible source (plugin, user, project, …) respects this override; CLI built-ins are already blocked by
--disable-builtin-skills, so overrides for them have nothing to act on. - Key naming rules: Plugin skills use the plugin-qualified name
plugin:skill; non-plugin skills use bare names. Both forms can be written simultaneously; matching is attempted against the fully qualified name first, then falls back to the bare name.
options.skillscan hide skills from the main model's context, but it does not filter theinitializationResult().skillsdiscovery inventory. To hide a skill from both, useskillOverrides: { name: 'off' }.
Reading Skills Discovered in the Current Session
The initialization result contains the complete set of skills discovered by the CLI in this session and is not filtered by the string-array form of options.skills. A host UI can use it as a discovered-skill inventory, not as the list currently callable by the main session.
The string-array form ofskillscontrols main-session context and tool visibility; it is not a security boundary. Unlisted skills do not appear in the model's skill listing and cannot be invoked through theSkilltool, but their files remain on disk and can still be accessed by regular file-reading tools.
Custom Agent Preloading Skills
If you define custom sub-Agents via options.agents, you can declare skills in the Agent definition. When the main session invokes the Agent tool, the sub-Agent will run with the specified skills loaded.
skills only affect that Agent's context and are not equivalent to enabling the same-named skill for the main session.
Options Reference
| Field | Type | Description |
|---|---|---|
skills | string[] | 'all' | An array restricts main-session skill context and invocation; [] disables all; 'all' enables every discovered skill |
agents | Record<string, AgentDefinition> | Custom Agents; each Agent can declare an independent skills preload list |
allowedTools | string[] | Tool allowlist; merged with Skill(...) entries compiled from skills with deduplication |
settingSources | ('user' | 'project' | 'local')[] | Controls whether the CLI scans user / project directories for skills; an empty array scans none of these sources |
plugins | PluginSpec[] | Loads plugins; skills inside contribute to the discovered set |
settings also has several skill-related fields that the SDK passes through; actual effects depend on whether the CLI version implements them:
| Field | Purpose |
|---|---|
skillOverrides | Set 'on' | 'name-only' | 'user-invocable-only' | 'off' per skill name; plugin, user, project sources all respect this override |
skillListingMaxDescChars | Character limit per description in the skill listing; the SDK passes it through and the default depends on the CLI version |
skillListingBudgetFraction | Context-window fraction reserved for the skill listing; the SDK passes it through and the default depends on the CLI version |
Return Value Reference
SDKControlInitializeResponse for the complete type.
Best Practices
- Enable
skillsas needed:skills: 'all'is ideal for development and debugging; end-user-facing products should typically pass an explicit list. - Want a CLI built-in's behavior? Ship your own copy: the SDK will not inject
simplify/security-reviewand the rest. Provide your own SKILL.md via a plugin or asettingSources-visible directory. - Don't treat
skillsas a security boundary: It only filters skill discovery and invocation. UseallowedTools,disallowedTools,canUseTool, permission mode, and isolation provided by the host environment to control access. - Use
initializationResult().skillsfor UI: This is the stable entry point for the CLI discovery pipeline and represents discovered skills, not every skill currently callable by the main session. - Manage sub-Agent
skillsseparately: They are independent lists from the main session'soptions.skillsand do not override each other.