Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Add Custom Skills

Create your own skills to teach Zeph new capabilities. A skill is a single SKILL.md file inside a named directory.

Skill Structure

.zeph/skills/
└── my-skill/
    └── SKILL.md

SKILL.md Format

Two parts: a YAML header and a markdown body.

---
name: my-skill
description: Short description of what this skill does.
---
# My Skill

Instructions and examples go here. This content is injected verbatim
into the LLM context when the skill is matched.

Header Fields

FieldRequiredDescription
nameYesUnique identifier (1-64 chars, lowercase, hyphens allowed)
descriptionYesUsed for embedding-based matching against user queries
compatibilityNoRuntime requirements (e.g., “requires curl”)
allowed-toolsNoSpace-separated tool names this skill can use
x-requires-secretsNoComma-separated secret names the skill needs (see below)

Secret-Gated Skills

If a skill requires API credentials or tokens, declare them with x-requires-secrets:

---
name: github-api
description: GitHub API integration — search repos, create issues, review PRs.
x-requires-secrets: github-token, github-org
---

Secret names use lowercase with hyphens. They map to vault keys with the ZEPH_SECRET_ prefix:

x-requires-secrets nameVault keyEnv var injected
github-tokenZEPH_SECRET_GITHUB_TOKENGITHUB_TOKEN
github-orgZEPH_SECRET_GITHUB_ORGGITHUB_ORG

Activation gate: if any declared secret is missing from the vault, the skill is excluded from the prompt. It will not be matched or suggested until the secret is provided.

Scoped injection: when the skill is active, its secrets are injected as environment variables into shell commands the skill executes. Only the secrets declared by the active skill are exposed — not all vault secrets.

Store secrets with the vault CLI:

zeph vault set ZEPH_SECRET_GITHUB_TOKEN ghp_yourtokenhere
zeph vault set ZEPH_SECRET_GITHUB_ORG my-org

See Vault — Custom Secrets for full details.

Channel Allowlist

Restrict a skill to specific I/O channels with x-channels. When set, the skill is excluded from matching on channels not in the list:

---
name: deploy-prod
description: Production deployment via kubectl.
x-channels: cli
---

This skill only activates in CLI mode — it is invisible in Telegram or TUI. Omit x-channels to allow all channels. Multiple channels are comma-separated: x-channels: cli, tui.

Name Rules

Lowercase letters, numbers, and hyphens only. No leading, trailing, or consecutive hyphens. Must match the directory name.

Skill Resources

Add reference files alongside SKILL.md:

.zeph/skills/
└── system-info/
    ├── SKILL.md
    └── references/
        ├── linux.md
        ├── macos.md
        └── windows.md

Resources in scripts/, references/, and assets/ are loaded lazily on first skill activation (not at startup). OS-specific files (linux.md, macos.md, windows.md) are filtered by platform automatically.

Local file references in the skill body (e.g., [see config](references/config.md)) are validated at load time. Broken links and path traversal attempts (../../../etc/passwd) are rejected.

Configuration

[skills]
paths = [".zeph/skills", "/home/user/my-skills"]
max_active_skills = 5

Skills from multiple paths are scanned. If a skill with the same name appears in multiple paths, the first one found takes priority.

Testing Your Skill

  1. Place the skill directory under .zeph/skills/
  2. Start Zeph — the skill is loaded automatically
  3. Send a message that should match your skill’s description
  4. Run /skills to verify it was selected

Changes to SKILL.md are hot-reloaded without restart (500ms debounce).

Installing External Skills

Use zeph skill install to add skills from git repositories or local paths:

# From a git URL — clones the repo into ~/.config/zeph/skills/
zeph skill install https://github.com/user/zeph-skill-example.git

# From a local path — copies the skill directory
zeph skill install /path/to/my-skill

Installed skills are placed in ~/.config/zeph/skills/ and automatically discovered at startup. They start at the quarantined trust level (restricted tool access). To grant full access:

zeph skill verify my-skill        # check BLAKE3 integrity
zeph skill trust my-skill trusted  # promote trust level

In an active session, use /skill install <url|path> and /skill remove <name> — changes are hot-reloaded without restart.

See Skill Trust Levels for the full security model.

Plugin Packages

For distributing and managing multiple related skills, utilities, and configurations together, Zeph supports plugin packages. A plugin is a directory containing a plugin.toml manifest that bundles:

  • Multiple skill directories
  • MCP server entries
  • Configuration overlays (tighten-only: you can only restrict, not expand permissions)

Plugin Structure

my-plugin/
├── plugin.toml                 # Manifest file
├── skills/
│   ├── skill-one/
│   │   └── SKILL.md
│   └── skill-two/
│       └── SKILL.md
└── config/
    └── overlay.toml            # Optional config tightening rules

plugin.toml Format

[plugin]
name = "my-plugin"
version = "1.0.0"
description = "My plugin description"

# Skills bundled with this plugin (relative paths from plugin root)
[[plugin.skills]]
name = "skill-one"
path = "skills/skill-one"

[[plugin.skills]]
name = "skill-two"
path = "skills/skill-two"

# MCP servers managed by this plugin (optional)
[[plugin.mcp_servers]]
id = "my-mcp-server"
command = "python"
args = ["-m", "my_mcp_module"]

# Configuration overlay — restrictive only (default: empty)
[plugin.config_overlay]
# Union of blocked patterns:
tools.blocked_commands = ["dangerous_pattern"]

# Intersection of allowed patterns (if base is empty, stays empty):
# tools.allowed_commands = ["safe_pattern"]

# Maximum for numeric fields:
# skills.disambiguation_threshold = 0.1

Installing Plugins

Use zeph plugin add to install a plugin from a local path:

# From local directory
zeph plugin add /path/to/my-plugin

# List installed plugins
zeph plugin list

# Show the active plugin overlay (which plugins are active/skipped and why)
zeph plugin list --overlay

# Remove a plugin
zeph plugin remove my-plugin

Plugins are installed to ~/.local/share/zeph/plugins/<name>/ (XDG standard location). All bundled skills are automatically discovered and hot-reloaded without restart.

In TUI mode, use the /plugins commands:

/plugins list              # Show installed plugins
/plugins list --overlay    # Show the active plugin overlay
/plugins overlay           # Show the active plugin overlay (alias)
/plugins add <path>        # Install a plugin
/plugins remove <name>     # Remove a plugin

Plugin Integrity Check

When you install a plugin, Zeph records a sha256 digest of its .plugin.toml manifest in ~/.local/share/zeph/.plugin-integrity.toml. At startup and when hot-reloading, Zeph verifies this digest to detect if a plugin manifest has been modified outside of Zeph’s control.

If a manifest is tampered with:

  • The plugin is skipped with an “integrity mismatch” reason
  • You can see the skipped plugin and reason with zeph plugin list --overlay or /plugins overlay
  • To re-protect the plugin, reinstall it: zeph plugin remove my-plugin && zeph plugin add /path/to/my-plugin

This provides basic tampering detection. The integrity check is not cryptographically signed, and concurrent installs may race (last writer wins).

Hot-Reload Behavior

Plugin config overlays — restrictions on tool access and embedding thresholds — are applied immediately when a plugin is installed or when you reload config mid-session. However, different overlay fields hot-reload differently:

Hot-reloads live (no restart needed):

  • tools.blocked_commands — shell commands blocked by the agent are updated atomically on the next execution

Require agent restart:

  • tools.allowed_commands — restrictions on allowed paths are applied at executor setup time. Zeph emits a RESTART REQUIRED warning when you change this setting

You do not need to restart Zeph when modifying blocked_commands — the agent picks up the new blocklist immediately. If you modify allowed_commands, you must restart Zeph for the change to take effect.

Plugin Security

  • Path traversal defense: skill paths in the manifest are canonicalized and must resolve within the plugin root directory
  • Config overlay validation: only tools.blocked_commands, tools.allowed_commands, and skills.disambiguation_threshold are permitted; other keys are rejected
  • Trust escalation filter: bundled skills are assigned the Trusted trust level automatically at startup, bypassing the default quarantined level that external skills receive

See Skill Trust Levels for how trust levels control tool access.

Agent-Invocable Skills

Skills are typically matched to user queries automatically via semantic embedding. With the invoke_skill tool, the agent can explicitly fetch and execute any registered skill by name at runtime. This is useful for:

  • Skills that should only run when explicitly requested
  • Composing multiple skills in a single response
  • Overriding the default embedding-based matching

Using invoke_skill in the LLM Response

When the agent needs to reference or use a skill, it calls the invoke_skill tool:

I'll use the "git-workflow" skill to help you:
<invoke_skill>
{
  "skill_name": "git-workflow",
  "args": "--verbose"
}
</invoke_skill>

The tool returns the skill body with security-aware sanitization:

  • Blocked skills: refused with an error message
  • Trusted skills: body returned as-is
  • Quarantined skills: body wrapped with a quarantine warning

CLI Usage

Invoke skills from the command line:

zeph skill invoke git-workflow --verbose
zeph skill invoke deploy-prod --environment staging

Catalog

The agent sees an invoke_skill catalog during context assembly that lists all available skills with their names and descriptions. Use /skills in TUI or CLI to see the full registry.

Generate a Skill from a Description

Instead of writing SKILL.md manually, use /skill create with a natural language description:

/skill create "A skill that manages systemd services — start, stop, restart, status"

Zeph generates a complete SKILL.md with frontmatter, instructions, and examples. The skill is saved to your skills directory and hot-reloaded immediately. Duplicate detection prevents creating skills that overlap with existing ones.

Generated skills are scored on correctness, reusability, and specificity before being written to disk. A separate critic LLM evaluates the skill and filters out low-quality generations.

Skill Evaluation Configuration

Control how generated skills are evaluated:

[skills.evaluation]
enabled = true                    # enable external critic (default: true)
correctness_weight = 0.50         # importance of correctness (0.0-1.0)
reusability_weight = 0.25         # importance of broad applicability
specificity_weight = 0.25         # importance of precise instruction
pass_threshold = 0.60             # minimum score to accept (0.0-1.0)

When a generated skill scores below pass_threshold, it is rejected and the generation process is retried. If enabled = false, all generated skills are accepted without evaluation (fail-open).

Evaluation is disabled by default for generated skills from --init to keep initial setup fast; enable it in your config if you want quality gates on all subsequent /skill create commands.

See NL Skill Generation for details on generation from descriptions and GitHub repository mining.

Next Steps