Inspect and Generate
tuff list
Section titled “tuff list”Show installed capabilities with scope, drift status, and path:
tuff listFilters
Section titled “Filters”# By scopetuff list --scope projecttuff list --scope global
# By capability typetuff list --type skilltuff list --type tool
# Combine filterstuff list --scope global --type toolStatus values
Section titled “Status values”| Status | Meaning |
|---|---|
clean |
Installed content matches recorded hash |
modified |
Installed content has local changes |
missing |
Installed file no longer exists |
tuff list uses terminal colors when supported: clean is green, modified is amber, and missing is red.
tuff list --json prints the same rows as an array, one object per capability per agent, with the keys id, type, version, version_scheme, scope, target, status, and path. An empty inventory prints [].
version_scheme is one of:
semver: a release chosen by tagdeclared: a version the source wrote for itselfsha: a pinned commit
The type, target, and status keys are spelled the same as in tuff check --json, so one script can read both.
tuff list --json | jq '.[] | select(.status != "clean") | .id'tuff status
Section titled “tuff status”Show per-primitive detail including scope, drift, and override warnings:
tuff statusExample output:
python-uv-default project clean [overrides global: won't receive global updates]commit-hygiene global cleanscan-tool project cleantuff generate
Section titled “tuff generate”Generate derived Tuff artifacts from tracked project state:
# Agent-facing capability indextuff generate index -a open-agentstuff generate index -a claude
# Custom index pathtuff generate index -a open-agents --output docs/CAPABILITIES.md
# Human-readable project reporttuff generate reporttuff generate report --output docs/tuff-report.mdtuff generate index writes the default index for the selected agent:
| Agent | Default output |
|---|---|
open-agents |
.agents/CAPABILITIES.md |
claude |
.claude/CAPABILITIES.md |
The generated index is intended for agent context. Point AGENTS.md,
CLAUDE.md, or equivalent agent instructions at the generated
CAPABILITIES.md file when you want the agent to see a compact inventory of
tracked capabilities.
tuff generate report writes tuff-report.md by default.
The report includes installed capabilities, agents, source type, emitted paths,
and clean/modified/missing status summaries.
Generated files are derived output. The source of truth is
tuff.lock tracking state.
tuff outdated
Section titled “tuff outdated”Show all installed capabilities and whether upstream updates are available. Read-only; never modifies files.
tuff outdatedExample output:
find-skills skill open-agents 2adcfe5 def5678 outdatedsecurity-review tool claude abc1234 2adcfe5 outdatedrust-implement skill open-agents 1.2.0 1.4.0 outdated (minor)csv-workbench skill open-agents 1.0.0 — not checkedcrm-skill skill open-agents 1.0.0 1.0.0 repointedStatus values
Section titled “Status values”| Status | Meaning |
|---|---|
up to date |
Nothing newer is available |
outdated |
A newer commit or release exists. For releases, it carries the claimed size of the change: major, minor, or patch |
repointed |
The installed tag or pack version now names different content than when you installed it |
tag missing |
The installed tag no longer exists upstream |
not checked |
Tuff has nowhere to check, so LATEST reads — |
repointed and tag missing win over outdated, because they change what the version you have means. LATEST still shows the newest release. Your install is unaffected either way: the lockfile pins the commit or digest, not the tag.
Git capabilities that follow a commit
Section titled “Git capabilities that follow a commit”For a git capability installed without @, the row compares commits: HEAD moved or it did not.
- If the source declares no version,
CURRENTandLATESTshow the 7-character commit SHA. - If it declares one,
CURRENTshows it as1.2.0 (declared)andLATESTthe version the source declares now, with the claimed size of the change when both parse. - If the commit moved but the declared version did not, the row still reads
outdatedwithLATESTequal toCURRENT.
The check costs one ls-remote and no clone. The one exception is a source that declares a version and whose commit moved: then Tuff clones to read the version it declares now.
That same listing shows whether the repository publishes releases. When it does, a note under the table suggests the tuff update <id>@<requirement> that pins the newest one. This is where Tuff tells you release tags exist: tuff add without an @ never lists them, so an untagged install costs no extra round trip.
Git capabilities installed at a release
Section titled “Git capabilities installed at a release”For a capability installed at a release, CURRENT and LATEST are release versions.
outdatedcarries the size of the change the version numbers claim:major,minor, orpatch. That is the author’s claim, not what the content shows;tuff diff <id> --upstreamshows the content.LATESTis the newest release the repository has, whether or not your recorded requirement allows it. So an exact pin can readoutdatedwhiletuff updatereports it up to date.tuff update <id>@<requirement>lifts the pin.- Tuff also checks the installed tag still names the commit recorded at install. This costs nothing extra, since the one
ls-remotealready lists every tag with its commit.
Pack capabilities
Section titled “Pack capabilities”For a capability installed with tuff add pack --reference,
CURRENT and LATEST compare the pack’s published versions (the numbers
you passed to tuff pack build --version), since the pack is what is actually being checked.
- The installed tag is resolved and its digest compared with the one recorded at install, which is how
repointedandtag missingare found. - This costs one small manifest fetch per pack per run, not per member, and no artifact is downloaded.
- Only tags that parse as semver are compared; anything else is excluded rather than guessed at.
1.9.0is correctly treated as older than1.10.0(plain string comparison would get this backwards). - Pass
--plain-httpor--ca-filefor a self-hosted registry, matchingtuff pack push/pull.
Anything Tuff cannot check, such as a pack installed without --reference or a
local capability with no source at all, reports not checked rather than a guessed up to date.
tuff outdated --json prints the rows as an array with the keys id, type, target, version_scheme, current, latest, and status.
- Where the table shows
—,latestisnull, so a script tests for absence rather than for a dash. - The size of a release change is a separate
changekey;statusstaysoutdated. - Every git row carries
latest_release. On release-pinned rows it is the same value aslatest.
tuff outdated --json | jq '.[] | select(.status == "outdated" or .status == "repointed")'tuff policy matrix
Section titled “tuff policy matrix”Print, for every agent, how each kind of policy rule is enforced: one row per effect (deny, ask) and subject (command, read, edit, mcp), with its coverage and the mechanism the rule compiles to. It needs no project. --json prints one object per agent with its rules.
tuff policy matrixEach row names what the rule compiles to, a native permission rule or the tuff policy evaluate hook, and the notes give the caveat for each partial or unsupported row. Open Agents’ rows read unsupported. tuff add of a policy prints the caveat for each partially enforced rule and is refused for any selected agent that would not enforce one of its rules.
tuff policy evaluate
Section titled “tuff policy evaluate”Answer an agent’s hook for an installed policy. The agent runs it before a tool call and passes the call as JSON on standard input; it prints the answer in that agent’s format and exits 0. tuff add registers it where a policy needs it, so it is not meant to be run by hand. See The policy hook.
tuff policy evaluate --harness <agent> --policy <policy id>| Flag | Description |
|---|---|
--harness <id> |
The agent running the hook: claude, codex, or cursor |
--policy <id> |
The installed policy to evaluate |