shuhari

Config

init writes the machine config, and you can edit it by hand. Commands that change it keep every other line as you wrote it.

Files

WhatWhere
Machine config~/.config/shuhari/config.toml
Tool-managed clones~/.local/share/shuhari/sources/<name>

The XDG_CONFIG_HOME, XDG_DATA_HOME and XDG_STATE_HOME variables move these locations, on both macOS and Linux.

A full example

machine    = "fukiBookPro-Max"
scan_roots = []

[targets]
claude = { kind = "host", path = "~/.claude/skills" }
agents = { kind = "host", path = "~/.agents/skills" }

[sources.agent-skills]
path       = "~/Projects/agent-skills"
git        = "git@github.com:you/agent-skills.git"
skills     = ["personal/*"]
import_dir = "personal"

[sources.superpowers]
git    = "https://github.com/obra/superpowers.git"
skills = ["skills/*"]
rev    = "b55764852ac78870e65c6565fb585b6cd8b3c5c9"   # a pinned source: a full commit ID

[tags]
lang = ["agent-skills:rust-*", "agent-skills:go"]

[[install]]
skills  = ["agent-skills:rust-style", "superpowers:brainstorming"]
targets = ["claude"]

[[install]]
tags    = ["lang"]
targets = ["claude", "agents"]

[[exclude]]
skill   = "agent-skills:go"
targets = ["agents"]          # optional; omitted means every target

[local]
"~/.claude/skills/ontology-design" = { kind = "wip", review_after = 2026-11-15, note = "still changing" }
"~/.claude/skills/things"          = { kind = "machine", note = "macOS Things app" }

Top-level keys

KeyMeaning
machineThe machine name. init converts the system's display name; init --machine sets another.
scan_rootsDirectories that scan walks for project skills in .claude/skills and .agents/skills. It does not follow symlinks, and skips .git and node_modules.

[targets]

One entry per target: a name, then kind and path. The kind is host. Two targets cannot resolve to the same directory.

[sources.<name>]

KeyMeaning
pathA directory you work in. With path, the source is a working-copy source.
gitThe remote URL. With git only, the source is a tool-managed source. A working-copy source with git must have origin equal to it.
skillsA list of skill patterns. Not absolute, no ... An empty list is valid, and the source then has no skills.
revA full commit ID. It pins the source.
import_dirWhere import writes new skills. It needs path.

A source needs path, git, or both. Two entries for the same source are an error: the same source means path values that resolve to the same directory, or, without path, equal git strings.

[tags]

Each key is a tag name, and its value is a list of selectors. Use a tag in an install choice with tags = ["<name>"], or as the selector tag:<name>.

[[install]]

Each entry has skills (selectors), tags, or both, and targets. shuhari add and shuhari remove edit these entries.

[[exclude]]

Each entry names one skill as source:skill. With targets, it applies to those targets only. Without it, it applies everywhere. shuhari exclude writes these entries.

[local]

Keyed by path. Each entry has kind, wip or machine, and an optional note. A wip entry accepts review_after. shuhari keep writes these entries. A declaration covers only that path: the same skill in another target is not covered.

Configs in the 1.0 format

A config with a [catalog] table uses the shuhari 1.0 format, which release 0.2.0 writes. Every command except init and doctor stops on it with exit code 2. Run shuhari init to convert it. The conversion is part of the change list, and nothing is written before you confirm.