Metadata-Version: 2.4
Name: toolery
Version: 0.0.3
Summary: A searchable, self-maintaining catalog over any corpus of tools, skills, agents, and components.
Project-URL: Homepage, https://github.com/thorwhalen/toolery
Project-URL: Repository, https://github.com/thorwhalen/toolery
Project-URL: Issues, https://github.com/thorwhalen/toolery/issues
Author: Thor Whalen
License-Expression: MIT
License-File: LICENSE
Keywords: agents,catalog,discovery,mcp,retrieval,search,skills,tools
Requires-Python: >=3.10
Requires-Dist: argh>=0.31
Provides-Extra: dev
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Requires-Dist: ruff>=0.1.0; extra == 'dev'
Provides-Extra: docs
Requires-Dist: sphinx-rtd-theme>=1.0; extra == 'docs'
Requires-Dist: sphinx>=6.0; extra == 'docs'
Description-Content-Type: text/markdown

# toolery

A searchable, self-maintaining catalog over any corpus of tools, skills, agents, and components.

Point `toolery` at a collection of heterogeneous assets — Claude skills, agent specs,
MCP tools, docs, or packages — and get **one** searchable catalog: ask *"what do I
already have for X?"* and get a ranked answer, not fifty schemas.

```
pip install toolery
```

## Quick start

Search a folder of notes/docs from the command line:

```bash
toolery search "dedupe a csv" ~/my/notes
```

Or from Python — the simplest thing that works, with zero configuration:

```python
import toolery

cat = toolery.catalog("~/my/notes")        # harvest a folder of markdown
for card, score in cat.search("parse pdf"):
    print(score, card.name, card.source_uri)
```

Out of the box the search is a fast, dependency-free lexical scorer, so nothing to
install, no models, no API keys.

## Any corpus, any asset kind

A catalog is built from **sources**. A source is a folder, a built-in *harvester*, or
bare cards:

```python
import toolery

cat = toolery.catalog(
    toolery.skills("~/.claude/skills"),     # Claude Agent Skills (SKILL.md)
    "~/my/notes",                           # a folder of docs
    [toolery.Card("grep", "tool", "grep", "search text with patterns")],
)
cat.search("find text in files")
cat.by_kind("skill")
cat.kinds                                   # {'skill': 42, 'doc': 118, 'tool': 1}
```

Everything is projected onto one uniform record, the `Card`
(`id, kind, name, description, tags, source_uri, content_ref`). Supporting a new
asset kind (agent specs, MCP tool schemas, packages) is just another generator that
yields `Card`s — nothing else changes.

## Bring your own search

`catalog(...)` and `Catalog(...)` accept a `search_backend` — any callable
`(query, cards, *, limit) -> [(card, score), ...]`. The default,
`toolery.lexical_search`, needs no dependencies. A semantic backend built on the
[`ir`](https://github.com/thorwhalen/ir) retrieval substrate drops into the same seam
(planned), so you can start lexical and upgrade to embeddings without changing your code.

```python
from toolery import Catalog, lexical_search

cat = Catalog(cards, search_backend=lexical_search)   # or your own backend
```

## Status

Early (`0.x`). The lexical core, the `Card`/harvester/catalog model, and the CLI are
in place; an `ir`-backed semantic backend and more built-in harvesters (agents, MCP
tools, packages) are next.
