Skip to content

Configuration Reference

Complete reference for ~/.config/skilltap/config.toml -- all options, defaults, and policy composition rules.

File Location

~/.config/skilltap/config.toml

Created with defaults on first run. Edit manually, use skilltap config for the interactive wizard, or use skilltap config get/skilltap config set for scripted access.

State is tracked separately in ~/.config/skilltap/state.json (machine-managed, do not edit). Pre-v2.1 used installed.json + plugins.json; those are now read-fallback only for unmigrated users.


[defaults]

Default settings for install and link commands.

OptionTypeDefaultDescription
scope"global" | "project" | """"Default install scope. Empty string means prompt every time.
alsoarray of strings[]Agent-specific directories to auto-symlink on every install. Values: "claude-code", "cursor", "codex", "gemini", "windsurf"
yesbooleanfalseAuto-accept prompts. Auto-selects all skills and auto-accepts clean installs. Security warnings still require confirmation. Scope still prompts unless scope is also set.

Example

toml
[defaults]
scope = "global"
also = ["claude-code", "cursor"]
yes = false

Interaction Between scope and yes

yesscopeBehavior
false""Prompt: skill selection, scope, install confirm
false"global"Prompt: skill selection, install confirm (scope set)
true""Auto-select skills, still prompt: scope, auto-install if clean
true"global"Auto-select, scope=global, auto-install if clean
true"project"Auto-select, scope=project, auto-install if clean

CLI flags always override config: --project overrides scope, --yes overrides yes.


[security]

Shared security scanning settings plus per-mode (human/agent) configuration. Configure via skilltap config security (interactive wizard or flags).

Shared Settings

OptionTypeDefaultDescription
agent_clistring""Agent CLI for semantic scanning. Values: "claude", "gemini", "codex", "opencode", "ollama", or an absolute path. Empty = prompt on first use.
thresholdinteger 0-105Risk threshold for semantic scan. Chunks scoring at or above this value are flagged.
max_sizeinteger (bytes)51200Max total skill directory size before warning. Default is 50 KB.
ollama_modelstring""Model name when using the Ollama adapter. Required when agent_cli = "ollama".

Per-Mode Settings: [security.human] / [security.agent]

OptionTypeHuman DefaultAgent DefaultDescription
scan"static" | "semantic" | "off""static""static"Scan mode.
on_warn"prompt" | "fail" | "allow""prompt""fail"What to do when warnings are found. "allow" logs but proceeds.
require_scanbooleanfalsetrueWhen true, blocks --skip-scan.

Trust Tier Overrides: [[security.overrides]]

Override security per source. Named tap overrides take priority over source-type overrides.

OptionTypeDescription
matchstringTap name or source type (tap, git, npm, local)
kind"tap" | "source"What match refers to
preset"none" | "relaxed" | "standard" | "strict"Security preset to apply

Presets

PresetScanOn WarnRequire Scan
noneoffallowfalse
relaxedstaticallowfalse
standardstaticpromptfalse
strictsemanticfailtrue

Example

toml
[security]
agent_cli = "claude"
threshold = 5
max_size = 51200

[security.human]
scan = "semantic"
on_warn = "fail"
require_scan = true

[security.agent]
scan = "static"
on_warn = "fail"
require_scan = true

[[security.overrides]]
match = "my-company-tap"
kind = "tap"
preset = "none"

Supported Agents

ValueBinaryInvocation
"claude"claudeclaude --print -p '<prompt>' --tools "" --output-format json
"gemini"geminiecho '<prompt>' | gemini --non-interactive
"codex"codexcodex --prompt '<prompt>' --no-tools
"opencode"opencodeopencode --prompt '<prompt>'
"ollama"ollamaollama run <model> '<prompt>' (requires ollama_model)
Absolute pathanyecho '<prompt>' | /path/to/binary

All agents are invoked without tool access -- they can only produce text output, never execute commands or read files during the scan.


[agent-mode]

Agent mode settings. When enabled, all skilltap commands become non-interactive. Three ways to enter agent mode (highest precedence first):

  1. Per-invocation flag: skilltap install foo --agent
  2. Environment variable: SKILLTAP_AGENT=1 skilltap install foo
  3. Persistent config: skilltap config agent-mode (interactive wizard, sets enabled = true below)

The flag and env var are recommended for CI / scripts because they don't leak persistent config state. The config block remains for users who always want agent mode in a given environment.

OptionTypeDefaultDescription
enabledbooleanfalseEnable agent mode.
scope"global" | "project""project"Default scope for agent installs. Required when agent mode is enabled.

Example

toml
["agent-mode"]
enabled = true
scope = "project"

Behavior When Enabled

When agent-mode.enabled = true:

SettingValueEffect
yestrueAll prompts auto-accept or hard-fail
Securityfrom [security.agent]Uses per-mode agent security settings (fully configurable)
Output formatPlain textNo ANSI colors, spinners, or Unicode decorations

Agent mode can be toggled via the --agent flag, the SKILLTAP_AGENT=1 env var, or persistently via skilltap config agent-mode (interactive wizard). Precedence order is flag > env > config block. Security levels within agent mode are configurable via skilltap config security --mode agent.

Agent Mode Output

Success:

OK: Installed commit-helper -> ~/.agents/skills/commit-helper/ (v1.2.0)

Skip:

SKIP: commit-helper is already installed.

Error:

ERROR: Repository not found: https://example.com/bad-url.git

Security failure (directive message to the agent):

SECURITY ISSUE FOUND -- INSTALLATION BLOCKED

DO NOT install this skill. DO NOT retry. DO NOT use --skip-scan.
STOP and report the following to the user:

  SKILL.md L14: Invisible Unicode (3 zero-width chars)
  SKILL.md L8: Hidden HTML comment containing instructions

User action required: review warnings and install manually with
  skilltap install <url>

[updates]

Controls how skilltap checks for and applies CLI updates, and how often it checks installed skills for updates in the background.

OptionTypeDefaultDescription
auto_update"off" | "patch" | "minor""off"Automatically install updates on startup. "patch" applies patch releases silently; "minor" applies patch and minor releases. Major releases are always notify-only regardless of this setting. Only applies to compiled binaries.
interval_hoursinteger24How often (in hours) to check GitHub for a new skilltap release. The check is non-blocking — it fires in the background and updates a local cache for the next run. Set to 0 to check on every invocation.
skill_check_interval_hoursinteger24How often (in hours) to check installed skills for updates in the background. When updates are available, a dim notice is printed to stderr. Use skilltap update --check to force an immediate check.
show_diff"full" | "stat" | "none""full"Verbosity of the diff displayed when an update changes a skill's content. "full" shows the full unified diff; "stat" shows only file-level summary stats; "none" suppresses the diff entirely.

Example

toml
[updates]
# Automatically apply patch releases on startup
auto_update = "patch"
# Check for a new release every 12 hours
interval_hours = 12
# Check installed skills for updates every 6 hours
skill_check_interval_hours = 6
# Show only file-level stats when a skill update changes content
show_diff = "stat"

When auto_update triggers, you'll see on stderr:

⟳  Auto-updating skilltap 0.3.1 → 0.3.2 (patch)…
✓  Updated to v0.3.2. Changes take effect next run.

Run skilltap self-update at any time to force an immediate check and update.


[telemetry]

Anonymous usage telemetry. Managed by skilltap telemetry enable / skilltap telemetry disable. You can also edit these keys directly, but prefer the subcommands.

OptionTypeDefaultDescription
enabledbooleanfalseWhether telemetry is active.
anonymous_idstring""A random UUID assigned on telemetry enable. Never tied to a user or machine identity.
notice_shownbooleanfalseInternal flag — set to true once the startup opt-in banner has been displayed. Do not edit.

Environment overrides: DO_NOT_TRACK=1 or SKILLTAP_TELEMETRY_DISABLED=1 disable telemetry regardless of these config values.

Example

toml
[telemetry]
enabled = true
anonymous_id = "a3f8c1d2-4b5e-6f7a-8c9d-0e1f2a3b4c5d"

[registry]

Controls which skill registries are searched when running skilltap find <query>.

OptionTypeDefaultDescription
enabledarray of strings["skills.sh"]Which registries to search, in order. Built-in: "skills.sh". Set to [] to disable all registry search.
sourcesarray of tables[]Custom registry definitions. Each entry needs name and url.
allow_npmbooleantrue(Deprecated) Use enabled = [] to disable registries instead.

Custom Registries

Any URL implementing the skills.sh search API can be added as a custom registry:

GET {url}/api/search?q={query}&limit={n}
→ { "skills": [{ "id": string, "name": string, "description": string, "source": string, "installs": number }] }

The source field in each result must be a valid skilltap install ref (e.g. owner/repo for GitHub sources, a full git URL, or npm:package).

Example

toml
[registry]
# Search skills.sh and a company registry
enabled = ["skills.sh", "acme"]

# Custom registry definition
[[registry.sources]]
name = "acme"
url = "https://skills.acme.com"

To disable all registry search (taps only):

toml
[registry]
enabled = []

verbose

Top-level boolean. Controls whether install step details (fetched, scan clean) are logged during skilltap install and skilltap tap install.

OptionTypeDefaultDescription
verbosebooleantrueShow step-by-step install progress. Set to false to suppress. Can also be overridden per-invocation with --quiet.

Example

toml
# Suppress step details during install (show only success/error lines)
verbose = false

builtin_tap

Top-level boolean. Controls whether the built-in skilltap-skills tap (a curated catalog maintained by the project) is enabled.

OptionTypeDefaultDescription
builtin_tapbooleantrueWhen true, the built-in tap is auto-cloned and searchable via skilltap find. Set to false to opt out — useful for fully air-gapped or corp-only setups where you only want your own taps to appear.

Example

toml
# Disable the built-in skilltap-skills tap
builtin_tap = false

default_git_host

Top-level string. The git host used to resolve owner/repo shorthand into a full URL.

OptionTypeDefaultDescription
default_git_hoststring"https://github.com"Base URL for owner/repo shorthand. For example, with default_git_host = "https://gitea.example.com", skilltap install nathan/commit-helper resolves to https://gitea.example.com/nathan/commit-helper.

Example

toml
# Resolve owner/repo shorthand against an internal Gitea
default_git_host = "https://gitea.corp.example.com"

[[taps]]

Tap definitions. Managed by skilltap tap add and skilltap tap remove. Each entry is a TOML array table.

FieldTypeDefaultDescription
namestringLocal name for the tap
urlstringGit URL of the tap repo
type"git""git"Tap type. v2.0 supports git only — pre-v2.0 also accepted "http" for live API registries; those entries are now silently filtered with a warning, and skilltap migrate flags them for manual conversion.

v2.0 — HTTP tap removal

type = "http", auth_token, and auth_env were removed in v2.0. Self-host a private git repo (Gitea, GitLab, bare HTTP repo) for non-public distribution; git authentication via SSH keys or credential helpers covers the auth use case.

Example

toml
[[taps]]
name = "home"
url = "https://gitea.example.com/nathan/my-skills-tap"

[[taps]]
name = "community"
url = "https://github.com/someone/awesome-skills-tap"

Git taps are cloned to ~/.config/skilltap/taps/{name}/.


Full Example

A complete config.toml with all options:

toml
# Default settings for install commands
[defaults]
# Default install scope. "" = prompt, "global" or "project" = skip prompt.
scope = "global"
# Auto-symlink to these agent directories on every install.
also = ["claude-code", "cursor"]
# Auto-accept clean installs (security warnings still prompt).
yes = false

# Security settings — per-mode with trust overrides
# Configure via: skilltap config security
[security]
agent_cli = ""
threshold = 5
max_size = 51200
ollama_model = ""

[security.human]
scan = "static"
on_warn = "prompt"
require_scan = false

[security.agent]
scan = "static"
on_warn = "fail"
require_scan = true

# Trust overrides — per-tap or per-source-type presets
# [[security.overrides]]
# match = "my-company-tap"
# kind = "tap"
# preset = "none"

# Agent mode -- for when skilltap is invoked by AI agents.
# Toggle with: skilltap config agent-mode
["agent-mode"]
enabled = false
scope = "project"

# CLI update settings
[updates]
auto_update = "patch"
interval_hours = 24

# Skill registry search settings
[registry]
# Which registries to query with 'skilltap find'. Set to [] to disable.
enabled = ["skills.sh"]

# Telemetry (managed via `skilltap telemetry enable/disable`)
[telemetry]
enabled = false

# Show step details during install (fetched, scan clean). Set false to silence.
verbose = true

# Tap definitions
[[taps]]
name = "home"
url = "https://gitea.example.com/nathan/my-skills-tap"

Policy Composition Rules

Per-mode config options and CLI flags compose together. The active mode ([security.human] or [security.agent]) is selected based on whether agent mode is enabled. Trust tier overrides replace mode defaults when a matching tap or source type is configured.

Flag Overrides

Config (active mode)CLI FlagResult
on_warn = "prompt"--strictstrict (flag wins)
on_warn = "fail"(none)strict (config wins)
on_warn = "fail"--no-strictprompt (flag overrides)
require_scan = true--skip-scanERROR (config blocks)
scan = "semantic"(none)Layer 1 + Layer 2
scan = "static"--semanticLayer 1 + Layer 2 (flag adds)
scan = "off"--semanticLayer 2 only
yes = false--yesyes (flag wins)
scope = "global"--projectproject (flag overrides)

Agent Mode Behavior

When agent-mode.enabled = true:

  • yes = true (all prompts auto-accept or hard-fail)
  • Security uses [security.agent] settings (fully configurable)
  • Output is plain text (no ANSI, spinners, or Unicode)

Agent mode can be toggled per-invocation with --agent, per-shell with SKILLTAP_AGENT=1, or persistently with skilltap config agent-mode. Security levels within agent mode are configurable via skilltap config security --mode agent.

Trust Tier Override Resolution

Override priority: named tap match > source type match > mode default. CLI flags still override on top of trust tier settings.

Worked Example: Power User

scan / on_warn / require_scan live in the per-mode blocks ([security.human] for interactive use, [security.agent] for --agent / CI). The shared [security] block holds keys common to both modes (agent_cli, threshold, max_size, ollama_model).

toml
[defaults]
also = ["claude-code", "cursor"]
yes = true
scope = "global"

[security.human]
scan = "semantic"
on_warn = "fail"
require_scan = true

[security.agent]
scan = "semantic"
on_warn = "fail"
require_scan = true

[security]
agent_cli = "claude"
threshold = 3
max_size = 102400

With this config:

bash
skilltap install <url>
# -> auto-select all skills (yes = true)
# -> scope = global (no prompt)
# -> symlinks to claude-code + cursor
# -> Layer 1 + Layer 2 scan (security.human.scan = semantic)
# -> abort on any warning (security.human.on_warn = fail)
# -> --skip-scan blocked (security.human.require_scan = true)
# -> claude used for semantic scan (security.agent_cli)
# -> flag chunks scoring >= 3 (security.threshold)

skilltap install <url> --no-strict
# -> same as above but warnings prompt instead of abort

skilltap install <url> --skip-scan
# -> ERROR: Security scanning is required by config

skilltap install <url> --project
# -> --project overrides scope for this invocation

Worked Example: Agent Mode

toml
[defaults]
also = ["claude-code"]

[security.human]
scan = "static"

[security.agent]
scan = "static"
on_warn = "fail"           # default for agent mode anyway
require_scan = true        # default for agent mode anyway

[security]
agent_cli = "claude"

[agent-mode]
enabled = true
scope = "project"

With this config:

bash
skilltap install <url>
# -> auto-select all (forced)
# -> scope = project (from agent-mode.scope)
# -> symlinks to claude-code (from defaults.also)
# -> Layer 1 scan
# -> any warning = SECURITY ISSUE FOUND directive + exit 1
# -> --skip-scan blocked (forced)
# -> plain text output, no colors