In this page, the "main session" is the session driven directly by
The SDK always appends
Without
With a string list, only matching skills appear in the main model's skill listing and can be invoked through the
Plugin skills use the plugin-qualified name
The configuration above ultimately allows the listed read/search tools plus
The string-list form of
The initialization result contains the full skill list the CLI discovered in this session, unfiltered by the string-list form of
If you define custom sub-Agents via
Such
Only skill-related fields are shown; full type in SDK References. In Python, the streaming
query() (or Python's QoderSDKClient), as opposed to subagents delegated via the Agent tool. See Subagents for how the two relate.
options.skills controls the main session's skill context and the Skill tool invocation policy. With a list of strings, the SDK issues the main-session skill allowlist and compiles each entry into Skill(name) merged into the tool allowlist (allowedTools / allowed_tools); with 'all', all discovered skills may be invoked and the main-session context is not additionally filtered.
SDK Does Not Load Built-in Skills
The SDK always appends --disable-builtin-skills when launching the CLI, so sessions never get the CLI's factory built-in skills (simplify, debug, security-review, quest, batch, agent-creator, hook-config, mcp-config, skill-creator, etc.). The discovery list (TypeScript's initializationResult().skills, Python's get_server_info()['skills']) contains no source: 'built-in' entries either, and the model system prompt can't see them.
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 after explicitly enabling
user/project/localvia the setting sources option. - agent-preloaded skills: declared on
options.agents[name].skills, scoped to that sub-agent only.
Using CLI Default Policy
Without skills, the SDK injects no extra Skill allowlist and defers entirely to CLI policy. Since built-in skills are disabled, sessions without setting sources / plugins have an empty discovery list.
Enabling All Discovered Skills
skills set to 'all' lets the Skill tool invoke every skill the CLI currently discovers (sources determined by setting sources / plugins; built-ins are no longer included).
Enabling Only Specific Skills
Skill tool. Entries may be bare or plugin-qualified names. Passing an empty list [] hides and rejects every skill in the main session.
The list doesn't change CLI discovery; unlisted skills may still appear in the discovery list.
Enabling Plugin Skills
Plugin skills use the plugin-qualified name plugin:skill. For plugin loading methods, see Plugins documentation.
Merging with Explicit Tool Allowlist
Skill(review). The SDK merges and dedupes—no duplicate entries are written.
Hiding Discovered Skills
The string-list form of options.skills filters the main-session model context and restricts Skill tool calls, but doesn't change discovery results. To hide a plugin / user / project skill from the discovery list as well, use settings.skillOverrides.
'off': fully hidden—absent from the discovery list and the model system prompt, andSkilltool calls are 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 the main session's model context but doesn't filter the discovery list; to hide from the discovery list too, useskillOverrides: { name: 'off' }.
Reading Skills Discovered in the Current Session
The initialization result contains the full skill list the CLI discovered in this session, unfiltered by the string-list form of options.skills. It suits host UIs showing "discovered skills" and is not the main session's current invocable list. In Python, query() is a one-shot stream with no convenient query API—use QoderSDKClient to read it after the handshake.
A string-listskillscontrols 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 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 don't enable the same skills for the main session—the main session's tool allowlist is untouched by this change.
Options Reference
| Field (TypeScript / Python) | Description |
|---|---|
skills / skills | List restricts the main session's skill context and invocation; [] disables all; 'all' enables every discovered skill |
agents / agents | Custom agents; an agent definition can declare its own skills preload list |
allowedTools / allowed_tools | Tool allowlist; merged and deduped with Skill(...) entries compiled from skills |
settingSources / setting_sources | Decides whether the CLI scans user / project directories for skills (default empty = sandboxed) |
plugins / plugins | Loads plugins; their skills join the discovery 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
SystemMessage(subtype="init").data["skills"] is a list of skill names—not the same structure as this metadata-rich discovery list.
Best Practices
- Enable
skillsdeliberately:'all'suits development and debugging; end-user products should usually pass an explicit list. - Recreate built-in skill behavior yourself if you want it: the SDK won't inject
simplify/security-reviewinto sessions; provide your own SKILL.md within plugin or setting-sources scope. - Don't treat
skillsas a sandbox: security boundaries belong to tool allow/deny lists, the permission callback, permission modes, and sandboxing combined. - Use the discovery list for UIs:
initializationResult().skills/get_server_info()['skills']is the stable entry into CLI discovery—use it to show "discovered skills", not as the main session's invocable set. - Manage sub-Agent
skillsseparately: They are independent lists from the main session'soptions.skillsand do not override each other.
Current Limitations
--disable-slash-commandsis the CLI's switch to disable all slash-command skills at once; the SDK currently exposes no first-class option—avoid relying on non-public passthrough paths.settings.skillListingMaxDescCharsandsettings.skillListingBudgetFractionare listing-budget control fields that the SDK passes through; the current qoderclicn has not implemented listing budget control, so passing them does not raise an error but also does not change behavior.- The Python SDK does not yet provide a
client.supported_skills()convenience method; read fromget_server_info()['skills']instead (already on the backlog).