Skills
Vis can discover and load the skills you (or other AI coding harnesses)
leave on disk — no vis-specific format required. This is a built-in
compatibility layer, the foundation-harness foundation module (ships in core,
always available). It is the sibling of the shell layer's POSIX compatibility, but for the
skill markdown that Claude Code, pi, opencode, and the
agents standard already define.
Skills are exposed through a model-facing verb, skill(name), and a
user-facing invocation, /<name> [task] (see
Context files & prompts).
What a skill is
A skill is a directory containing a SKILL.md file with YAML-ish ---
frontmatter plus a body of instructions, alongside any bundled resource files
(scripts, templates, reference docs):
my-skill/
├── SKILL.md # required: frontmatter + instructions
├── scripts/
│ └── process.sh
└── references/
└── guide.md
---
name: my-skill
description: What this skill does and WHEN to use it. Be specific.
---
# My Skill
## Usage
Run `scripts/process.sh <input>` to …
Only name and description are read from the frontmatter. A missing name
falls back to the skill's directory name; a missing description is fine but
makes the skill harder for the model to pick. The parser is a minimal,
dependency-free reader — a folded (multi-line) description is joined into one
line.
Progressive disclosure
Skills are progressive, so they cost almost nothing until used:
- The system prompt lists every skill as
name — description(descriptions clipped to ~180 chars). This is the only always-present cost. - When a task matches, the model calls
skill("name"), which loads the fullSKILL.mdbody plus the absolute paths of every bundled resource. - The model reads those resource paths with its normal file tools and follows the instructions.
The first activation returns the full SKILL.md body. While that exact body
remains on the provider-visible tape, another skill("name") call returns only
a compact already-active receipt. The original tool call and result are left
byte-for-byte in their append-only position, so deduplication does not rewrite
the cached prefix.
The activation index is rebuilt from the post-fold provider wire, not inferred
from the mere existence of a database row. If a legacy fold removed the body,
if a new user turn no longer replays that tool result, or if the file's digest
changed, the next call returns the full body exactly once and establishes a new
live activation. session_fold excludes a currently active skill iteration
from broad fold targets; other selected iterations still compact normally.
Where skills come from
Vis scans a fixed, ordered registry of source roots. Precedence is source order, first-name-wins: vis' own project-local skills win, then other harnesses' project dirs, then their user dirs, then plugin caches.
| Precedence | Tool | Location | Scope |
|---|---|---|---|
| 1 | vis | .vis/skills |
project / dir-local |
| 2 | Claude Code | .claude/skills |
project |
| 3 | Claude Code | ~/.claude/skills |
user |
| 4 | Claude Code | ~/.claude/plugins/cache/**/skills |
installed plugins |
| 5 | pi | .pi/skills |
project |
| 6 | pi | ~/.pi/agent/skills |
user |
| 7 | agents standard | .agents/skills |
project + ancestors up to the git root |
| 8 | agents standard | ~/.agents/skills |
user |
| 9 | opencode | .opencode/skill |
project |
| 10 | opencode | ~/.config/opencode/skill |
user |
Project-relative roots (.vis/skills, .claude/skills, …) resolve against the
active workspace root (the directory the session works in), so a skill
checked into a repo travels with it. The .agents/skills root additionally
walks the workspace root's ancestor directories up to the git repo root
(nearest wins) — in a monorepo, repo-level skills apply inside every
subproject. The scan is defensive: missing directories are simply skipped and
it never throws.
Discovery is live: the source roots are stat-checked on each access and
re-scanned when a SKILL.md (or agent file) appears, changes, or disappears —
a skill added mid-session shows up without a restart.
Project-local .vis/skills
Drop a skill dir straight into your repo under .vis/skills/<name>/SKILL.md and
it takes precedence over anything with the same name from a global or
other-harness location — the natural place for skills specific to one project.
Availability
Skill discovery, the prompt catalog, and skill(name) are built in and always
available. There is no skills feature toggle.
Invoking a skill yourself
The model picks skills from the prompt listing on its own, but you can force
one: every skill is also a prompt template named <name>, so typing
/setup-pre-commit for husky in any channel loads that skill's full
SKILL.md directly into that user message and runs your task with it. Details in
Context files & prompts.
Using skills from other harnesses
Because discovery already scans Claude Code, pi, the agents standard, and
opencode roots, skills you authored for any of those tools are reused as-is —
there is nothing vis-specific to add. To make a skill vis-first, put it under
.vis/skills/ (project) so it wins on precedence.
