mind-cli 0.10.0

A manager for agent tooling (skills, agents, rules, tools) that melds arbitrary git repos and links items into your agent directories.
# Resource and helper tooling

Status: done. Some agent libraries ship helper tooling -- shell or Python
scripts, or a compiled binary -- that their skills and agents invoke at runtime.
This document specifies how a source ships that tooling, how `mind` installs it
(including an optional build step for compiled tooling), and how an item
references it by a stable, namespace-safe path.

## Overview

A skill or agent often calls a helper script it ships next to itself
(`skills/voice/resources/mine-commits.sh`) or a shared helper used by several
items (`resources/detect-project.sh`). Copying the files is already handled --
`learn` copies a skill's whole directory -- so the unsolved parts are two others:

- **Reference.** The item must name the tooling's installed path. A hardcoded
  `~/.claude/skills/voice/resources/...` breaks the moment a prefix renames the
  item to `jk:voice`, and is ambiguous when more than one agent home is
  configured (which home?). This is the same fragility `{{ns:name}}` already
  fixes for sibling *names* (namespacing.md), one level down: a path, not a name.

- **Standalone and compiled tooling.** A helper shared across items is neither a
  skill, an agent, nor a rule, so no kind installs and tracks it. And compiled
  tooling must be built, with the output landing somewhere stable to reference.

`mind` answers these with: a `tool` item kind (a store-only installable that
exists to be referenced), path-reference tokens (`{{self}}`, `{{tools:name}}`,
`{{path:ref}}`, expanded at install like `{{ns:}}`), and an optional per-item
build hook (install-hooks.md, HOOK-70..73) for tooling that must be compiled.
Tokens expand to the store path (`~/.mind/store/...`), which is single and
home-independent, so a reference resolves the same regardless of how many agent
homes are configured or what prefix is in force.

The rest of this document states the rules normatively.

## The `tool` kind

- `TOOL-1` `tool` is a fourth item kind alongside skill, agent, and rule. By
  convention, every immediate subdirectory of a `tools/` directory (under each
  scan root) is a tool; the whole directory is the item. Unlike a skill
  (`skills/<name>/SKILL.md`), a tool needs no anchor file: a bare `tools/<name>/`
  directory is a tool, and its contents are the final tool state as installed (no
  build is implied). An authoritative `mind.toml` overrides convention scanning
  as for any kind (discovery.md).
- `TOOL-2` A tool's metadata comes from an optional `TOOL.md` in its directory:
  frontmatter `description`, `bin`, and `build`. A `mind.toml` `[[items]]` entry
  overrides those fields. With neither a `TOOL.md` nor a `mind.toml` entry, a tool
  has no description and `bin`/`build` come only from convention (TOOL-5).
- `TOOL-3` A tool installs to the store (`~/.mind/store/tool/<effective_name>/`)
  like any item, but by default is NOT linked into any agent home: it carries no
  symlink and the Claude harness does not discover it. Its manifest entry records
  the store path with an empty `links` set. `forget` removes the store copy;
  `recall` reports it installed. A tool is reached only by reference (TOOL-10..12).
- `TOOL-4` A tool MAY declare an explicit `link` (`mind.toml` `[[items]].link`)
  to also surface it under each agent home, for the rare tool that should be
  discoverable in place; absent a `link`, a tool is store-only (TOOL-3).
- `TOOL-5` A tool's entrypoint -- what `{{tools:name}}` resolves to -- is the
  `bin` resolved in order: an explicit `mind.toml` `[[items]].bin`, else `TOOL.md`
  frontmatter `bin:`, else the convention default `<name>` (a file named after
  the tool at the tool dir root, e.g. `tools/shard-plan/shard-plan`) when that
  file is present in the source. A tool that nothing invokes as an executable
  need not resolve a `bin`.
- `TOOL-6` Namespacing applies to tools as to any kind: a prefix gives the
  effective name `<prefix>-<name>`, and a tool's stable identity is
  `(source, kind, bare_name)` (namespacing.md), so a prefix change is a rename
  matched on identity by `evolve`/`introspect` (lifecycle.md).
- `TOOL-7` `mind.toml` accepts `kind = "tool"` wherever a kind is named
  (`[[items]]`, and `[discover].tools` globs, which match the tool DIRECTORY
  rather than an anchor file). The `bin` and `build` item fields are valid only on
  a tool; on any other kind they are a `mind.toml` schema error.

## Path-reference tokens

An item references tooling by a token that expands, at install, to the tooling's
store path. Expansion runs in the same staging pass that expands `{{ns:}}`
(namespacing.md), so a bad reference fails before the live install is touched and
the recorded content hash is of the source (token) form.

- `TOOL-10` `{{self}}` in an item's text expands to that item's own store
  directory (a path under the store root, `~/.mind/store` honoring `MIND_HOME`,
  rendered with a leading `~` per TOOL-16). It is available in every kind, so a
  skill addresses its own bundled resources as `{{self}}/resources/<script>`
  without hardcoding its installed name.
- `TOOL-11` `{{path:ref}}` expands to a sibling item's store directory, for
  reaching non-entrypoint files in a tool (`{{path:tool:x}}/lib/helper.sh`).
  `ref` is a sibling's bare name, optionally kind-qualified
  (`{{path:tool:detect}}`, `{{path:skill:review}}`). An unqualified `ref`
  matching items of more than one kind is an error (`BadReference`); a `ref`
  matching no sibling is an error (`BadReference`), as for `{{ns:}}` (NS-12).
- `TOOL-12` `{{tools:name}}` expands to a sibling tool's entrypoint: the tool's
  store directory joined with its resolved `bin` (TOOL-5). The plural `tools:` is
  distinct from the `tool:` kind-qualifier used in `{{path:}}`. A `name` that is
  not a sibling tool, or a tool with no resolvable `bin`, is an error
  (`BadReference`).
- `TOOL-13` Path tokens expand in the staging copy during the transactional
  install, alongside `{{ns:}}` (NS-11). The recorded content hash is of the token
  (source) form, not the expanded copy, so drift detection compares source with
  source (NS-13). Both prefixed and unprefixed installs expand tokens (NS-14): a
  store path is prefix-aware via the referent's effective name.
- `TOOL-14` Path tokens expand in every text file of every item kind, including
  tool directories and a skill's bundled scripts (so a bundled `pr.py` may
  contain `{{tools:shard-plan}}`), matching the scan breadth of `{{ns:}}`
  (NS-20). Token edge cases mirror `{{ns:}}` (NS-15): inner whitespace is trimmed
  (`{{ path:x }}`); an unterminated token (no closing `}}`) is left verbatim;
  non-UTF-8 files are not scanned; text with no `{{` token is copied unchanged.
- `TOOL-15` Path tokens resolve within the source only (sibling scope), as
  `{{ns:}}` does, so tool-to-tool and bundled-script-to-tool references resolve
  when both items ship in the same source. Cross-source tooling references are out
  of scope: ship a tool in the same source as the items that use it.
- `TOOL-16` A path token renders the store root with a leading `~` when the store
  lies under the user's home directory (the default `~/.mind/store`): the home
  prefix is written as a literal `~`, not spelled out absolutely. This keeps the
  expansion matchable by a Claude `settings.json` permission glob, which uses
  tilde syntax (`Bash(~/.mind/store/**)`) that an absolute path would not match.
  When the store root is not under home (a `MIND_HOME` pointing elsewhere) or the
  home directory cannot be determined, the token expands to the absolute path.

Because every token expands under `~/.mind/store`, an item's invocations of its
tooling share one stable path prefix regardless of agent home or prefix, so a
permission allowlist can target that prefix (a `Bash(~/.mind/store/**)` rule,
matched by the `~` rendering of TOOL-16) rather than chase per-item installed
paths.

## Build hooks for compiled tooling

Tooling that must be compiled or fetched before it runs uses a build step. The
expected default is the maintainer's project-level build (a Makefile or build
script) run via a source-level install hook (install-hooks.md, HOOK-50) at meld,
which produces the artifacts in the working tree; the tool directory is then
copied as the final state at `learn` (TOOL-1), no per-tool config needed. A tool
that wants its own isolated, rollback-safe build instead declares a per-item
`build` (install-hooks.md, HOOK-70..73), run in staging before the store swap;
`{{tools:name}}` (TOOL-12) then resolves to the built artifact.

## Relationship to existing mechanisms

- A skill's bundled helpers install as part of the skill directory: the whole
  directory is the item, copied and linked into each agent home as one symlink, so
  every file under it comes along. They may live anywhere within it (`resources/`
  is a convention, not a requirement); `{{self}}` is what makes them addressable
  under a prefix. Siloing a helper with the single skill that uses it is a
  supported choice, distinct from the `tool` kind, which is for tooling
  deliberately shared across items or shipped on its own. `review` may note a
  helper duplicated across items as a `tool` candidate, but treats keeping the
  per-item copy as equally valid (CLI-144).
- The executable bit on scripts is preserved by the copy into the store (the
  install copies file permissions), so a `+x` helper stays executable without a
  hook.