# Skills Generation Enable AI agents to use the DevOps AI Toolkit CLI and access server prompts as native skills. ## What Are Skills? Skills are agent capabilities that make AI coding assistants (Claude Code, Cursor, Windsurf) aware of available tools and workflows. The CLI can generate skills from server capabilities. ## What Gets Generated Skills generation serves two purposes: ### 1. CLI Awareness (Routing Skill) Creates a `dot-ai` routing skill that makes agents aware of the CLI: - Triggers on Kubernetes and DevOps operations - Directs agents to use CLI instead of MCP - Teaches agents to use `dot-ai --help` for command discovery - Lower token overhead than MCP protocol ### 2. Server Prompts (Prompt Skills) Exposes server prompts as native agent skills: - Each server prompt becomes an agent skill (e.g., `dot-ai-projectSetup`, `dot-ai-query`) - Users can invoke them as native skills in their agent - Prefixed with `dot-ai-` to avoid naming conflicts - Skills can include supporting files (shell scripts, templates, manifests) alongside `SKILL.md` ## Supported Agents - **Claude Code** — `.claude/skills/` - **Cursor** — `.cursor/skills/` - **Windsurf** — `.windsurf/skills/` Note: Cursor also auto-discovers skills from `.claude/skills/`, so Claude Code skills work in Cursor without duplication. ## Generate Skills The server caches skills for performance (default: 24 hours). Use `--pull-latest` to force the server to pull the latest from the git repository before generating: ```bash dot-ai skills generate --agent claude-code --pull-latest ``` **For Claude Code:** ```bash dot-ai skills generate --agent claude-code ``` **For Cursor:** ```bash dot-ai skills generate --agent cursor ``` **For Windsurf:** ```bash dot-ai skills generate --agent windsurf ``` **Custom path (unsupported agents):** ```bash dot-ai skills generate --path ./custom/skills/ ``` ## Custom-Only Mode By default, `skills generate` creates skills for both MCP tools (query, recommend, remediate, etc.) and custom prompts (troubleshoot-pod, explain-resource, etc.). Use `--custom-only` to skip MCP tool skills and generate only custom prompt skills: ```bash dot-ai skills generate --agent claude-code --custom-only ``` Persist it so all future generations respect it: ```bash dot-ai config set skills.custom_only true dot-ai skills generate --agent claude-code # Clear it dot-ai config reset skills.custom_only ``` `--custom-only` follows the standard 4-tier precedence (see [Filter Precedence](#filter-precedence) below) and can be combined with `--include`/`--exclude` to further filter within the custom skills. ## Filtering Skills By default, `skills generate` creates skills for all tools and prompts from the server. You can filter which skills are generated using include/exclude regex patterns. ### One-Time Filtering with Flags ```bash # Generate only query and recommend skills dot-ai skills generate --agent claude-code --include "query|recommend" # Generate all except management skills dot-ai skills generate --agent claude-code --exclude "manage.*" # Combine: include all, then exclude specific ones dot-ai skills generate --agent claude-code --include ".*" --exclude "manage.*" ``` ### Persistent Filtering with Config Set filters once so all future generations respect them: ```bash # Persist an include filter dot-ai config set skills.include "query|recommend|remediate" # All future generates use the filter dot-ai skills generate --agent claude-code # One-time override to generate everything dot-ai skills generate --agent claude-code --include ".*" # Persist an exclude filter dot-ai config set skills.exclude "debug-.*|experimental-.*" # Clear persistent filters dot-ai config reset skills.include dot-ai config reset skills.exclude ``` ### Filter Precedence Filters follow the standard 4-tier precedence: 1. `--include` / `--exclude` / `--custom-only` flags (highest priority) 2. `DOT_AI_SKILLS_INCLUDE` / `DOT_AI_SKILLS_EXCLUDE` / `DOT_AI_SKILLS_CUSTOM_ONLY` environment variables 3. `settings.json` → `skills_include` / `skills_exclude` / `skills_custom_only` 4. Default: empty (no filtering — generate all skills) ### Filter Logic - Patterns are regular expressions matched against skill names (without the `dot-ai-` prefix) - If `--custom-only` is set, MCP tool skills are skipped entirely - If `--include` is set, only skills matching the pattern are kept - If `--exclude` is set, skills matching the pattern are removed - If both are set, include is applied first, then exclude - `--include`/`--exclude` filters apply to both tool skills and prompt skills (or just prompt skills when `--custom-only` is active) ## Auto-Update with SessionStart Hook For Claude Code, you can install a hook that automatically regenerates skills at the start of every session: ```bash dot-ai skills generate --agent claude-code --install-hook ``` This adds a `SessionStart` hook to `.claude/settings.json` that runs `dot-ai skills generate --agent claude-code` on session startup. The hook captures the flags you pass — `--custom-only`, `--include`, `--exclude`, `--repo`, `--repo-path`, `--repo-branch`, and the CLI-side source flags `--repo-fetch`, `--repo-dir` / `--source-label`, and `--no-cache` — so each firing reproduces the same source. ```bash dot-ai skills generate --agent claude-code --install-hook --custom-only --exclude "debug-.*" # Hook command: dot-ai skills generate --agent claude-code --custom-only --exclude 'debug-.*' ``` Secrets and opt-ins are **never** written to `settings.json` — they are read from the environment each time the hook fires, so they must be set per session for the hook to behave the same: - A `--repo` or `--repo-fetch` URL is stored **credential-scrubbed** (a `user:token@…` URL lands as the bare URL), and `DOT_AI_GIT_TOKEN` is read from the environment. - A `--repo-dir` hook does **not** embed `DOT_AI_ALLOW_REPO_DIR` — a committed `settings.json` must not let a clone side-load skills without consent. The opt-in must be set in the environment for the hook to fire (mirroring `DOT_AI_GIT_TOKEN`). The hook is idempotent — running the command again with the same flags won't create duplicates. Re-running with different flags replaces the existing hook. It merges with any existing settings. See [Which Source Flag?](#which-source-flag) for the flag details. To compose skills from multiple repos, install one hook per source: ```bash dot-ai skills generate --agent claude-code --install-hook # env-var repo dot-ai skills generate --agent claude-code --install-hook --repo https://github.com/orgA/skills # org-wide dot-ai skills generate --agent claude-code --install-hook --repo https://gitlab.corp/team/skills # team-private ``` Each invocation of `--install-hook` writes one hook scoped to its source. See [Composing Skills From Multiple Repositories](#composing-skills-from-multiple-repositories) for the full model. ### Global (User-Level) Install with `--global` By default the hook lands in the **project-local** `.claude/settings.json` and skills in `./.claude/skills`, so the catalog is available only in that one project. Add `--global` (requires `--agent claude-code`) to target the **user-level** `~/.claude` layout instead, so the shared catalog is available in **every** project you open: - The `SessionStart` hook is written to `~/.claude/settings.json` (resolved via your home directory), not `./.claude/settings.json`. - Without `--path`, skills default to `~/.claude/skills` (the shared "global catalog") instead of `./.claude/skills`. - It lifts the `--install-hook` / `--path` restriction (which still applies in project mode), so a global hook can pair with a custom output directory. Team onboarding becomes a single, idempotent command: ```bash dot-ai skills generate --agent claude-code --install-hook --global # Skills generated successfully in /home/you/.claude/skills # SessionStart hook installed in /home/you/.claude/settings.json ``` Or, to land the skills in a custom home-level directory: ```bash dot-ai skills generate --agent claude-code --path ~/.claude/commands --install-hook --global ``` `--global` composes with every source flag (`--repo`, `--repo-fetch`, `--repo-dir`): the named source is round-tripped into the stored command and the hook lands in `~/.claude/settings.json`. Note that only **one** dot-ai `SessionStart` hook is kept at a time — running `--install-hook` again (for the same or a different source) **replaces** the existing dot-ai hook rather than adding a second one, so a later install wins. (The generated skill *files* are still source-scoped and accumulate across per-source runs — see [Composing Skills From Multiple Repositories](#composing-skills-from-multiple-repositories) — but the auto-refresh hook installed by `--install-hook` tracks a single source.) Installing a global hook merges with — and preserves — any unrelated content already in `~/.claude/settings.json`, and re-running is idempotent. `--global` is **round-tripped** into the stored hook command (`… --global`), so every session-start regenerates to the same place. It embeds the `--global` *flag*, not the resolved `~/.claude/skills` path, so the hook re-resolves against `$HOME` at each firing and stays portable if you sync your dotfiles to a machine with a different home. (A custom `--path` is stored as the absolute path the shell already expanded.) > **`--global` without `--install-hook`** is also valid — it is the "write to the > global catalog" mode: `dot-ai skills generate --agent claude-code --global` > generates skills into `~/.claude/skills` (no hook installed). > **Bonus — opencode discovery.** `~/.claude/skills` is not Claude-Code-only: > **opencode natively discovers skills from `~/.claude/skills/*/SKILL.md`** > (alongside `~/.config/opencode/skills/` and `~/.agents/skills/`) and ignores > unknown frontmatter fields, so the `source:` tag is harmless and the > `dot-ai-*` names satisfy its naming rule. A single `--global` install therefore > lights up **both** Claude Code and opencode for skill *discovery*, with zero > opencode-specific work. (Auto-refresh on opencode startup is a separate > follow-up — opencode has no `settings.json` `SessionStart` hook.) ## Updating Skills Re-running the command updates the `dot-ai-*` skills owned by the current source: ```bash dot-ai skills generate --agent claude-code ``` Each generated skill carries a `source:` field in its YAML frontmatter recording which repo it came from (`built-in` for the server's configured default, or the repo URL passed via `--repo`). On every run, the CLI only wipes-and-replaces skills tagged with the *current* source — skills from other sources are left in place. This is what lets you compose skills from multiple repos via multiple invocations (see [Composing Skills From Multiple Repositories](#composing-skills-from-multiple-repositories)). ## Composing Skills From Multiple Repositories The `--repo ` flag overrides the server's configured default prompts repo for one invocation: ```bash dot-ai skills generate --agent claude-code --repo https://github.com/orgA/skills ``` Each invocation is **self-contained and source-scoped** — it fetches from a single repo, tags every generated skill with that repo's source identifier, and only manages files from that source. Composition across multiple sources is achieved by running the command multiple times — typically as one agent hook per source: ```bash # Hook A: server's configured default repo (env-var DOT_AI_USER_PROMPTS_REPO on the server) dot-ai skills generate --agent claude-code # Hook B: explicit org-wide repo dot-ai skills generate --agent claude-code --repo https://github.com/orgA/skills # Hook C: a self-hosted team-private repo, with its own credentials in DOT_AI_GIT_TOKEN DOT_AI_GIT_TOKEN=$TEAM_TOKEN dot-ai skills generate --agent claude-code --repo https://gitlab.corp/team/skills ``` Each hook owns its slice. The hook is the scoping unit: each one points at one source and carries that source's subdirectory, branch, and credential. ### Which Source Flag? By default the **server** fetches every skill source: with no flag it clones its own configured repo; with `--repo ` it clones the override you name. That is the right model whenever the server can both **reach** and **authenticate** to the source. Two flags — `--repo-fetch` and `--repo-dir` — instead have the **CLI host** read the source and upload it for the server to render, for the cases server-side fetch can't cover: | Your source is… | Use | Who fetches | |---|---|---| | The server's configured default repo | *(no source flag)* | Server | | Any repo the server can reach with a **static credential** (public, or private + a token) | `--repo ` (+ `DOT_AI_GIT_TOKEN` for private) | Server | | A repo only the **CLI host** can reach/authenticate — SSO/OIDC/device-attested VPNs, or a hardened cluster with no egress and no static token | `--repo-fetch ` | CLI host | | Work-in-progress skills on local disk with no remote at all | `--repo-dir --source-label