Skills

Skills are modular capability packs that teach lsbot how to use external tools. Each skill is a directory containing a SKILL.md file — a markdown document with YAML frontmatter that declares requirements, metadata, and instructions.

Quick Start

# List all discovered skills
lsbot skills

# See what's ready vs missing
lsbot skills check

# Get details on a specific skill
lsbot skills info github

# Disable / enable a skill
lsbot skills disable weather
lsbot skills enable weather

CLI Reference

lsbot skills / lsbot skills list

List all discovered skills with their eligibility status.

lsbot skills list [flags]
FlagDescription
--eligibleShow only ready-to-use skills
-v, --verboseShow missing requirements column
--jsonOutput as JSON

Example:

$ lsbot skills list -v

Skills (6/8 ready)

  Status       Skill            Description                          Source      Missing
  ✗ missing    🔐 1password     Set up and use 1Password CLI (op)... bundled     bins: op
  ✓ ready      🎮 discord       Use when you need to control Disc... bundled
  ✓ ready      🐙 github        Interact with GitHub using the g... bundled
  ✗ missing    💎 obsidian       Work with Obsidian vaults (plain... bundled     bins: obsidian-cli
  ✓ ready      👀 peekaboo      Capture and automate macOS UI wit... bundled
  ✓ ready      💬 slack          Use when you need to control Slac... bundled
  ✓ ready      🧵 tmux          Remote-control tmux sessions for... bundled
  ✓ ready      🌤️ weather       Get current weather and forecasts... bundled

lsbot skills info <name>

Show detailed information for a single skill — description, source path, requirements with per-item status, and install hints.

$ lsbot skills info 1password

🔐 1password ✗ Missing requirements

Set up and use 1Password CLI (op). Use when installing the CLI,
enabling desktop app integration, signing in, or reading/injecting secrets.

Details:
  Source:   bundled
  Path:     ~/Projects/lsbot/bundled-skills/1password/SKILL.md
  Homepage: https://developer.1password.com/docs/cli/get-started/

Requirements:
  Binaries:  ✗ op

Install options:
  → Install 1Password CLI (brew)

lsbot skills check

Summary view — counts by status, lists ready skills and what's missing.

$ lsbot skills check

Skills Status Check

Total:                  8
✓ Eligible:             6
⏸ Disabled:             0
✗ Missing requirements: 2

Ready to use:
  🎮 discord
  🐙 github
  👀 peekaboo
  💬 slack
  🧵 tmux
  🌤️ weather

Missing requirements:
  🔐 1password (bins: op)
  💎 obsidian (bins: obsidian-cli)

lsbot skills enable <name>

Re-enable a previously disabled skill. Removes the name from skills.disabled in bot.yaml.

lsbot skills disable <name>

Disable a skill. Adds the name to skills.disabled in bot.yaml. The skill remains on disk but is excluded from eligibility checks.

JSON Output

All read commands support --json for scripting:

lsbot skills list --json
lsbot skills info github --json
lsbot skills check --json

Skill Discovery

Skills are loaded from three directories in precedence order. When two directories contain a skill with the same name, the higher-precedence source wins.

PriorityLocationDescription
1 (lowest)<binary>/../skills/ or ./bundled-skills/Bundled skills shipped with the binary
2~/.lingti/skills/User-installed (managed) skills
3 (highest)./skills/Project-specific (workspace) skills

The bundled directory is resolved automatically:

  1. $LINGTI_BUNDLED_SKILLS_DIR environment variable (if set)
  2. <executable-dir>/../skills/
  3. <executable-dir>/skills/
  4. ./bundled-skills/ (development mode)

Additional directories can be configured in bot.yaml:

skills:
  extra_dirs:
    - /path/to/shared/skills
    - /another/team/skills

Creating a Skill

1. Create the directory

mkdir -p ~/.lingti/skills/my-tool

2. Write SKILL.md

---
name: my-tool
description: "Short description shown in skills list."
homepage: https://example.com/my-tool
metadata:
  emoji: "🔧"
  os: ["darwin", "linux"]
  requires:
    bins: ["my-tool"]
    env: ["MY_TOOL_API_KEY"]
  install:
    - id: brew
      kind: brew
      formula: example/tap/my-tool
      label: "Install my-tool (brew)"
    - id: npm
      kind: npm
      package: my-tool
      label: "Install my-tool (npm)"
---

# My Tool

Instructions for the AI agent on how to use my-tool...

## Common Commands

\`\`\`bash
my-tool list
my-tool create --name "example"
\`\`\`

## Tips

- Always use `--json` flag for parseable output.
- Use `MY_TOOL_API_KEY` for authentication.

3. Verify

lsbot skills info my-tool

SKILL.md Format

A SKILL.md file has two parts:

  1. YAML frontmatter (between --- delimiters) — machine-readable metadata
  2. Markdown body — instructions for the AI agent

Frontmatter Fields

FieldTypeRequiredDescription
namestringyesUnique skill identifier
descriptionstringyesShort description (shown in list, truncated to ~36 chars)
homepagestringnoURL to documentation or project page

Metadata Fields

Nested under metadata: in the frontmatter.

FieldTypeDefaultDescription
emojistring📦Emoji shown next to skill name
os[]string(all)Allowed operating systems: darwin, linux, windows
alwaysboolfalseSkip all gating — always mark as eligible
requires.bins[]string[]Required binaries — all must exist in PATH
requires.any_bins[]string[]At least one must exist in PATH
requires.env[]string[]Required environment variables — all must be set
install[]InstallSpec[]How to install missing requirements

InstallSpec Fields

Each entry in the install array:

FieldTypeDescription
idstringUnique identifier for this install method
kindstringPackage manager: brew, apt, go, npm, download
formulastringHomebrew formula (for kind: brew)
packagestringPackage name (for kind: apt or kind: npm)
modulestringGo module path (for kind: go)
urlstringDownload URL (for kind: download)
labelstringHuman-readable label shown in skills info
bins[]stringBinaries this method installs

OpenClaw Compatibility

Skills from the OpenClaw project work out of the box. The parser automatically handles OpenClaw's nested metadata format:

metadata: {"openclaw": {"emoji": "🐙", "requires": {"bins": ["gh"]}}}

This is equivalent to the flat format:

metadata:
  emoji: "🐙"
  requires:
    bins: ["gh"]

Eligibility Gating

When a skill is discovered, it goes through a series of gates to determine if it's eligible (ready to use):

1. Not disabled?         → Check skills.disabled in bot.yaml
2. OS matches?           → Check metadata.os against runtime OS
3. Always flag?          → If metadata.always=true, skip remaining gates
4. All bins exist?       → exec.LookPath for each in requires.bins
5. Any bin exists?       → At least one from requires.any_bins
6. All env vars set?     → os.Getenv for each in requires.env

A skill that fails any gate is marked as missing (with details of what's missing). A skill explicitly listed in skills.disabled is marked as disabled.

Configuration

Skills configuration lives in bot.yaml under the skills key:

# bot.yaml
skills:
  # Skills to exclude from eligibility (by name)
  disabled:
    - obsidian
    - 1password

  # Additional directories to scan for skills
  extra_dirs:
    - /Users/shared/team-skills
    - ~/my-extra-skills

Config file location:

  • macOS: ~/Library/Preferences/Lingti/bot.yaml
  • Linux: ~/.config/lingti/bot.yaml
  • Other: ~/.lingti/bot.yaml

Directory Layout

~/.lingti/skills/                  # Managed skills (user-installed)
├── my-custom-skill/
│   └── SKILL.md
└── another-skill/
    └── SKILL.md

<project>/skills/                  # Workspace skills (project-specific)
└── project-tool/
    └── SKILL.md

<binary>/../skills/                # Bundled skills (shipped with binary)
├── github/
│   └── SKILL.md
├── peekaboo/
│   └── SKILL.md
├── tmux/
│   └── SKILL.md
└── weather/
    └── SKILL.md

Bundled Skills

Lingti-bot ships with 8 bundled skills:

SkillEmojiRequiresDescription
1password🔐op1Password CLI for secrets management
discord🎮Discord bot control and moderation
github🐙ghGitHub CLI for issues, PRs, CI, and API queries
obsidian💎obsidian-cliWork with Obsidian vaults
peekaboo👀peekaboomacOS UI automation (screenshots, clicks, typing)
slack💬Slack workspace control
tmux🧵tmuxRemote-control tmux sessions for interactive CLIs
weather🌤️curlWeather forecasts via wttr.in and Open-Meteo

Examples

Override a bundled skill

Create a skill with the same name in ~/.lingti/skills/ to override the bundled version:

mkdir -p ~/.lingti/skills/github
cat > ~/.lingti/skills/github/SKILL.md << 'EOF'
---
name: github
description: "Custom GitHub workflow with team conventions."
metadata:
  emoji: "🐙"
  requires:
    bins: ["gh"]
---

# GitHub (Custom)

Always use `--repo myorg/myrepo` by default...
EOF

The managed version takes precedence over the bundled one.

Project-specific skill

Add a skill that only applies to the current project:

mkdir -p ./skills/deploy
cat > ./skills/deploy/SKILL.md << 'EOF'
---
name: deploy
description: "Deploy this project to production."
metadata:
  emoji: "🚀"
  requires:
    bins: ["kubectl", "helm"]
    env: ["KUBECONFIG"]
---

# Deploy

Use helm to deploy to the staging cluster...
EOF

Skill that requires an API key

---
name: openai
description: "OpenAI API integration."
metadata:
  emoji: "🤖"
  requires:
    env: ["OPENAI_API_KEY"]
---

If OPENAI_API_KEY is not set, the skill shows as missing with a clear indication of what's needed.