skillmirror
Reference

بِسْمِ ٱللَّهِ ٱلرَّحْمَـٰنِ ٱلرَّحِيمِ

Configuration

The pointer file and the config.yaml of the vault, every key with its rules, which setting wins, and how to keep folders out of the scan.

The configuration is split in two so that the vault is self-contained and portable:

~/.config/skillmirror/vault      one line: the path to your vault
<vault>/config.yaml              everything else

The first file belongs to a machine. The second travels with the vault, so a second computer that clones the vault only has to learn where the clone is, and it should inshallah behave the same from then on.

The pointer file

~/.config/skillmirror/vault holds one line, the absolute path of the vault. The folder follows XDG_CONFIG_HOME, so it is $XDG_CONFIG_HOME/skillmirror/vault when that variable is set. A path that is empty or not absolute is an error.

skillmirror vault init writes the file when you have no default vault yet (--use writes it even when you have one), and so does the Setup screen of the interface. You can also write it by hand:

mkdir -p ~/.config/skillmirror
echo ~/skills > ~/.config/skillmirror/vault

Which setting wins

SettingFirstThenLast
the vault--vault DIRSKILLMIRROR_VAULTthe pointer file
the scan root--root DIRSKILLMIRROR_ROOTroot: in config.yaml

An empty variable counts as unset. A relative path is made absolute from the current folder. These two are the only settings that flags and variables can change: everything else comes from config.yaml.

The variables of the old tool, anything that starts with SKILL_MANAG_, are refused with a message that names the replacement, because ignoring one could sync the wrong vault:

SKILL_MANAG_VAULT=~/skills skillmirror status
error: legacy environment variables are set: SKILL_MANAG_VAULT
hint: rename each variable: SKILL_MANAG_VAULT -> SKILLMIRROR_VAULT

skillmirror config show prints what is in force and where each value came from:

skillmirror config show
vault         ~/skills  (pointer file)
root          ~/projects  (vault config)
config file   ~/skills/config.yaml
mandatory     doc-start, coding, file-tree-optimization
targets       claude
web           off
exclude_dirs  none
exclude_paths none
profiles      websites

config path prints the path of config.yaml, for $EDITOR $(skillmirror config path). config root DIR and config web on|off change root: and web: for you, and keep the comments and the other keys.

config.yaml

~/skills/config.yaml
root: /home/you/projects
mandatory: [doc-start, coding]
exclude_dirs: [testdata]
exclude_paths:
  - /home/you/projects/archive
targets: [claude]
web: false
profiles:
  websites:
    description: Everything for a website
    groups: [Web_Skills]
    skills: [coding]
  site:
    extends: [websites]
    exclude: [astro]

Every key is optional, and a missing file is an empty config. Unknown keys are an error, not ignored, so a typo cannot silently do nothing:

error: invalid vault config ~/skills/config.yaml: error: line 12 column 1: unknown field `colour`, expected one of root, mandatory, exclude_dirs, exclude_paths, profiles, targets, web
  --> <input>:12:1
   |
10 |     skills: [coding]
11 | web: false
12 | colour: blue
   | ^ unknown field `colour`, expected one of root, mandatory, exclude_dirs, exclude_paths, profiles, targets, web

The exit code is 3.

KeyWhat it holdsRules
rootthe folder that holds your projectsnot empty; relative paths are made absolute from the current folder
mandatoryskills that push and init install everywhereplain skill names, none twice; mandatory add and remove edit it
exclude_dirsfolder names the scan skips wherever they occurbare names, no / (Skipping folders)
exclude_pathsfolders the scan skips, with everything below themabsolute, or relative to the root; each must exist
targetsother agent folders to link to .agents/skillsonly claude is known; none twice (Other agent folders)
webwhether skillmirror web may starttrue or false; off unless true (The web view)
profilesnamed selections of skills for add and initsee below

Profiles

A profile selects skills by name (skills), by vault folder (groups, paths such as Web_Skills or Web_Skills/seo), and through other profiles (extends). exclude removes names from what the profile itself selects. The keys of a profile are description, extends, groups, skills and exclude, and nothing else.

  • The name of a profile is a plain name: not empty, no /, not starting with a dot.
  • extends must name profiles that exist, and the chain must not loop.
  • A skill or group a profile names must exist in the vault. The check happens when the profile is used, and doctor runs it for every profile.
  • The order of extends never changes the result, because exclude only removes what its own profile selects.

add --profile NAME, init --profile NAME, sync --profile NAME and status --profile NAME use a profile (Start a project).

Skipping folders

The scan walks everything below the root and looks for .agents/skills. It never enters these folders, at any depth:

.git  node_modules  vendor  dist  build  out  target  .next  .nuxt
.venv  __pycache__  .tox  .pytest_cache  .cache  .turbo  .parcel-cache

You can add to that list in two ways. Test fixtures that look like projects are the usual reason: a folder testdata with its own .agents/skills would be found as a project, and a sync would write into it.

skillmirror list
coding                         ~/projects/atlas-api
doc-start                      ~/projects/atlas-api
file-tree-optimization         ~/projects/atlas-api
coding                         ~/projects/atlas-api/testdata/sample
astro                          ~/projects/docs-site
...
17 skills installed in 5 projects

By name

exclude_dirs lists folder names. A folder with one of those names is skipped wherever it occurs, with everything below it.

~/skills/config.yaml
exclude_dirs: [testdata]
skillmirror list
coding                         ~/projects/atlas-api
doc-start                      ~/projects/atlas-api
file-tree-optimization         ~/projects/atlas-api
astro                          ~/projects/docs-site
...
16 skills installed in 4 projects

An entry is a bare name. testdata/sample is not one, and the config is refused.

By path

exclude_paths lists folders by path. The path is absolute, or relative to the scan root, and everything below it is skipped:

~/skills/config.yaml
exclude_paths:
  - atlas-api/testdata
skillmirror config show
vault         ~/skills  (pointer file)
root          ~/projects  (vault config)
config file   ~/skills/config.yaml
mandatory     doc-start, coding, file-tree-optimization
targets       claude
web           off
exclude_dirs  none
exclude_paths atlas-api/testdata
profiles      websites

A path has to exist. One that matches nothing is an error, because it would exclude nothing and you would not know:

skillmirror list
error: exclude_paths entry ~/projects/atlas-api/testdta does not exist
hint: fix or remove the entry in <vault>/config.yaml; a path that matches nothing excludes nothing

The exit code is 3, and every command that scans stops with it until the entry is fixed or removed. A path that climbs above the filesystem root (/..) is refused too. doctor reports what the scan could not read.

The folder outside the vault

Besides the pointer file, skillmirror keeps one more folder of its own: the backup store that undo reads. It lives under $XDG_STATE_HOME/skillmirror/backups, which is ~/.local/state/skillmirror/backups when the variable is not set. Files and folders lists everything skillmirror reads and writes.

Coming from the old tool

The Go tool skill_Manag kept its pointer in ~/.config/skill_Manag/vault. When that file exists and the new one does not, every command stops and says what to run:

skillmirror migrate

migrate copies the pointer to the new place and leaves the old file. migrate --retire removes the old pointer afterwards, so the old tool stops finding the vault. When the two files point at different vaults, migrate refuses and tells you to decide which one is right.

On this page