> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vistazo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Skills

> Workspace-authored markdown procedures that load before the work.

A skill is a written procedure a workspace member saved — house conventions, a recurring report recipe, the way this team names things. Reading one before acting is usually cheaper than inferring it.

| Tool                                              | What it does          |                   |
| ------------------------------------------------- | --------------------- | ----------------- |
| [`list_skills`](#list_skills)                     | List skills           | Read-only         |
| [`search_skills`](#search_skills)                 | Search skills         | Read-only         |
| [`get_skill`](#get_skill)                         | Get skill             | Read-only         |
| [`save_skill`](#save_skill)                       | Save skill            | Destructive write |
| [`save_skill_version`](#save_skill_version)       | Save skill version    | Additive write    |
| [`restore_skill_version`](#restore_skill_version) | Restore skill version | Destructive write |
| [`delete_skill`](#delete_skill)                   | Delete skill          | Destructive write |
| [`set_skill_access`](#set_skill_access)           | Set skill access      | Destructive write |

## list\_skills

`Read-only`

List the workspace's SKILLS: short markdown documents the workspace's own members wrote for agents — how they diagnose a metric, their house chart conventions, which sources they trust, the recipe for a recurring report. Each row carries `id` (the handle — the only way to name a skill back to a tool), `name` (a display label that MAY repeat: two skills can legitimately share one), a one-line `description` of WHEN to use it, `updatedAt`/`updatedBy`, and `archived`. Call this EARLY: when a request sounds like a standing procedure ("the monthly board deck", "why did revenue drop"), when the user names a skill, or before planning multi-step work in a workspace you don't know — a skill encodes what this workspace knows about its own data, which you cannot infer from the dashboards. Descriptions only; read the instructions themselves with get\_skill. Each row also carries `ownerId` + `ownerName`; pass `ownerId` (a uid from list\_workspace\_members, or from a member the user attached) to list only that person's skills. Archived skills are hidden unless includeArchived:true. Lists the skills YOU may open (per-skill grants + workspace default). To find a skill BY NAME OR KEYWORD, call search\_skills instead of listing everything and filtering the names yourself — it matches names and descriptions and ranks the hits.

## search\_skills

`Read-only`

Find a workspace SKILL by name or keyword — the lookup path, as search\_dashboards is for dashboards; list\_skills is the enumeration one. Reach for this when the user names a skill or describes one ("the board-deck runbook", "our churn procedure") instead of listing every skill and matching the names yourself. Searches names and the one-line descriptions and ranks the hits; matching is keyword/substring based, so one distinctive word works best and a multi-word query ranks skills matching more of the words higher. Rows are list\_skills rows — `id`, `name`, `description`, `ownerId`/`ownerName`, `updatedAt` — and the `id` is what you pass on to get\_skill: a skill's NAME MAY REPEAT (two skills can legitimately share one), so never resolve a skill by name. RANK ORDER IS NOT IDENTITY: when several hits tie at the top score with near-identical names the response carries a `hint` saying so — confirm which one is meant (get\_skill, or ask the user) before acting on it. Returns only the skills YOU may open (per-skill grants + the workspace default; a guest needs a grant), and never archived ones. If nothing matches, the skill may live in a DIFFERENT workspace (search each from list\_workspaces before concluding it doesn't exist), or call list\_skills and match semantically yourself (workspaces are small).

## get\_skill

`Read-only`

Return one skill in full, including the markdown `body` — the instructions themselves. Identify it by `id` — from list\_skills, or the bracketed id on a line of the workspace-skills catalog. A skill's name is a label and may repeat, so the id is the only handle; never guess one from a name. Load the body BEFORE planning the work it covers and follow its procedure rather than improvising an equivalent one — it is the workspace's own answer to that task, and the caveats in it are usually the point. `editing` is present when a member has the skill open in the web editor (their name and when they last touched it), meaning the text may change under you. Pass format:'markdown' to get the skill back as a ready-to-write SKILL.md file instead of JSON — YAML frontmatter (name, description) followed by the body, byte-identical to the file the web Download button produces. That is the LOAD-INTO-MY-LOCAL-CLIENT case: write the returned text verbatim to .claude/skills/\<name>/SKILL.md (or wherever your client keeps skills) and it works there as it does here. Keep the default format:'json' for reading or editing a skill — the markdown carries only name, description and body, not the id, versions, or edit lock. Requires view access on that skill (owner, a grant, or the workspace default; guests need a grant).

## save\_skill

`Destructive write`

Create or update a workspace skill — how you REMEMBER a procedure the user asks you to keep ("always chart revenue this way", "here's how we do the weekly review"): write it as a skill instead of answering that you'll remember it. Omit `id` to create; pass the `id` from list\_skills to update in place. Write it as a runbook for a colleague who knows the tools but not this workspace: `name` short (a display label, not an identifier — a duplicate name is allowed and the id stays the handle), `description` ONE line saying when to use it (that line is the ONLY text a future agent sees before deciding whether to load the skill, so make it a trigger, not a title restatement), `body` markdown with the actual steps, max 20000 characters. Pass `expectedUpdatedAt` (the `updatedAt` you read from get\_skill) to make the write conditional — it refuses rather than overwriting if someone changed the skill in the meantime; without it, last writer wins. Refuses while another member has the skill open in the web editor, naming them. `archived: true` RETIRES a skill (it leaves list\_skills, the catalog agents read, and the in-app skill menu) without deleting it — prefer that to delete\_skill for anything that might be wanted again; `archived: false` restores one. An archived skill refuses content edits, so pass `archived: false` alongside the new text to restore and edit in a single write. Returns id, updatedAt. Creating needs full workspace membership; updating needs edit access on that skill (owner, editor grantee, or the editor default).

## save\_skill\_version

`Additive write`

Seal the skill's current name, description and body as a recorded version RIGHT NOW, instead of waiting for the automatic capture (an edit seals itself after a quiet period). Use before you rewrite someone else's skill substantially, so there is a known-good point to roll back to. Returns written:false when the current text already matches the latest version — that is success, not an error. get\_skill lists the recorded versions (rev + when + why); restore\_skill\_version rolls back to one. Requires edit access on the skill.

## restore\_skill\_version

`Destructive write`

Roll a skill's name, description and body back to a recorded version (rev from get\_skill's `versions`). Use when an edit made a skill wrong and an earlier version was known good. The current text is sealed as a version FIRST, so a restore is itself reversible — the response's `rev` is that safety version, the one to pass back here to undo the rollback (null when the current text already matched the latest version). A restore can change the skill's name back; its id never moves. Refuses while another member has the skill open in the web editor, and refuses an archived skill (restore it with save\_skill archived:false first). Requires edit access on the skill.

## delete\_skill

`Destructive write`

Delete a workspace skill permanently. There is no undo and no restore, so prefer editing it with save\_skill unless the user explicitly wants it gone. Confirm with the user only when their request does NOT identify the skill unambiguously; when the request names it, or you resolved the id from list\_skills and it matches what was asked for, that request IS the confirmation. Names may repeat, so when one name resolves to more than one id, ask which before deleting. Only the skill's OWNER (ownerId, which transfer\_ownership moves — the author until then) or a workspace admin may delete one.

## set\_skill\_access

`Destructive write`

Grant, change, or revoke access to ONE workspace skill — the write path for a skill's sharing, mirroring the web's Skill → Sharing pane. Two independent knobs, at least one required: `memberId` + `role` sets a NAMED grant ('editor' | 'viewer', or 'none' to remove that person's grant), and `workspaceDefault` sets the baseline every full member gets without one — 'none' (named people only), 'viewer' (everyone in the workspace can read it), or 'editor' (everyone can edit it, which is what a skill is born with). This is how a request\_skill\_access request is ANSWERED: grant the requester `editor`, which also clears the pending request. Who may call it: anyone with edit access on the skill (its owner, an editor grantee, or a workspace admin); it refuses an archived skill (restore it first with save\_skill archived:false). `memberId` must already be a member of this workspace (invite\_member first) and may be neither the skill's OWNER — the owner already holds every right, and ownership moves only through transfer\_ownership — nor YOURSELF: ask the owner or a workspace admin to change your own access rather than removing it by accident. A GUEST (share-by-email) can hold a grant and read the skill, but a guest's role is capped at viewer whatever is stored, so an editor grant on a guest is INERT until they are promoted to a full member. This writes the grants map and nothing else — it never touches the skill's text and never moves `updatedAt`, so it cannot collide with someone editing in the web app or invalidate an `expectedUpdatedAt` you are holding. Returns the skill's `ownerId` (never a grant — it lives outside the map) and the grants as they now stand.
