Skip to main content

The agent-native CLI framework for Python

Project description

Tooli

The agent-native CLI framework for Python.

Tooli turns typed Python functions into command-line tools that work for both humans and AI agents: rich output in a terminal, strict structured output in automation, and self-describing schemas for tool calling and orchestration.

The name comes from "tool" + "CLI" = "tooli".

Why Tooli?

AI agents invoke lots of local commands, but typical CLIs are optimized for humans:

  • Huge, unstructured stdout that burns context windows
  • Opaque errors that don't suggest a fix
  • Fragile pipelines that mix logs with machine output
  • Undocumented flags that agents hallucinate

Tooli is built to be machine-consumable by default while still feeling great for humans.

Install

pip install tooli

Optional extras:

pip install "tooli[mcp]"   # MCP server support
pip install "tooli[api]"   # HTTP API + OpenAPI export (experimental)

Quick Start

Create file_tools.py:

from __future__ import annotations

from pathlib import Path
from typing import Annotated

from tooli import Argument, Option, Tooli
from tooli.annotations import Idempotent, ReadOnly

app = Tooli(name="file-tools", description="File utilities", version="4.1.0")


@app.command(annotations=ReadOnly | Idempotent, paginated=True, list_processing=True)
def find_files(
    pattern: Annotated[str, Argument(help="Glob to match")],
    root: Annotated[Path, Option(help="Root directory")] = Path("."),
) -> list[dict[str, str]]:
    return [{"path": str(p)} for p in root.rglob(pattern)]


if __name__ == "__main__":
    app()

Run it:

python file_tools.py find-files "*.py" --root .
python file_tools.py find-files "*.py" --root . --output json
python file_tools.py find-files --schema

Structured Output (JSON / JSONL)

Tooli supports dual-mode output:

  • Human mode: pretty output when attached to a TTY
  • Agent mode: strict envelopes when using --output json or --output jsonl

JSON envelope shape:

{
  "ok": true,
  "result": {"...": "..."},
  "meta": {
    "tool": "file-tools.find-files",
    "version": "2.0.0",
    "duration_ms": 12,
    "annotations": {"readOnlyHint": true, "idempotentHint": true}
  }
}

Structured Errors With Recovery Hints

When a command fails, Tooli emits a structured error with an actionable suggestion:

{
  "ok": false,
  "error": {
    "code": "E1004",
    "category": "input",
    "message": "Exact search string was not found in source.",
    "suggestion": {
      "action": "adjust search text",
      "fix": "Double-check exact spacing/newlines. Did you mean: \"...\"?"
    },
    "is_retryable": true
  }
}

Schemas, Docs, and Agent Bootstrap

Tooli can generate tool schemas and agent-facing docs directly from type hints and metadata:

python file_tools.py find-files --schema
python file_tools.py generate-skill > SKILL.md
python file_tools.py generate-skill --target claude-code > SKILL.md
python file_tools.py find-files --agent-bootstrap > SKILL.md
python file_tools.py docs llms
python file_tools.py docs man

v4 generates task-oriented SKILL.md with "When to use" guidance, recovery playbooks, composition patterns, and target-specific formatting (generic, Claude, Claude Code).

Run as an MCP server (one tool per command):

python file_tools.py mcp serve --transport stdio
python file_tools.py mcp serve --transport http --host 127.0.0.1 --port 8080
python file_tools.py mcp serve --transport sse --host 127.0.0.1 --port 8080

Universal Input (files / URLs / stdin)

Use StdinOr[T] to accept a file path, a URL, or piped stdin with one parameter.

from pathlib import Path
from typing import Annotated

from tooli import Argument, StdinOr, Tooli

app = Tooli(name="log-tools")


@app.command()
def head(
    source: Annotated[StdinOr[str], Argument(help="Path, URL, or '-' for stdin")],
) -> dict[str, int]:
    return {"bytes": len(source)}  # `source` resolves to the content

Built-In Guardrails

Tooli provides primitives for safer automation:

  • ReadOnly, Idempotent, Destructive, OpenWorld annotations on commands
  • --dry-run planning support via @dry_run_support + record_dry_action(...)
  • SecretInput[T] with automatic redaction in outputs and errors
  • Cursor pagination (--limit, --cursor, --fields, --filter) for list-shaped results

Example Apps (agent pain points)

The GitHub repo includes sample apps under examples/ that target common agent failure modes:

  • code-lens: token-efficient symbol outlines from Python ASTs (avoid dumping whole files)
  • safe-patch: self-healing file edits with dry-run plans and recovery hints
  • log-sift: pipeline-friendly log extraction with strict JSON/JSONL output
  • sqlite-probe: read-only SQLite exploration with pagination and guardrails

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tooli-6.1.0.tar.gz (161.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tooli-6.1.0-py3-none-any.whl (126.7 kB view details)

Uploaded Python 3

File details

Details for the file tooli-6.1.0.tar.gz.

File metadata

  • Download URL: tooli-6.1.0.tar.gz
  • Upload date:
  • Size: 161.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for tooli-6.1.0.tar.gz
Algorithm Hash digest
SHA256 0e60dad9d0a46e0c1d4165227244cc6f998a9950e8a9bc32bab5c1f0877a57f6
MD5 35b9eb1ab7008370a540e4cb02457587
BLAKE2b-256 af8ea419ff8377819a8a3617790f9291214306d0f0caccb1300d430e87ed45d5

See more details on using hashes here.

Provenance

The following attestation bundles were made for tooli-6.1.0.tar.gz:

Publisher: publish.yml on weisberg/tooli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tooli-6.1.0-py3-none-any.whl.

File metadata

  • Download URL: tooli-6.1.0-py3-none-any.whl
  • Upload date:
  • Size: 126.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for tooli-6.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 559ef446db756dee1a189a6d86536646bf885d2240a350403de63e98b2947507
MD5 bc48c7d17817e649f5a27968dc2b9e5f
BLAKE2b-256 997cc8d46462d9ccca9ba3a7a4e7aad1c1541065dcb0db4baa71ff4c65b7c311

See more details on using hashes here.

Provenance

The following attestation bundles were made for tooli-6.1.0-py3-none-any.whl:

Publisher: publish.yml on weisberg/tooli

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page