Skip to content

About

Helper tool to build toolpacks for ToolHub out of bunch ToolSpec compliant files. Written with AI

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

ToolPack Builder

Build ToolHub-compatible .toolpack bundles from Python tools that implement the TWYLT contract.

ToolPack Builder is intentionally independent from both projects:

  • TWYLT defines how a Python tool describes and launches itself.
  • ToolPack Builder discovers TWYLT tools and assembles a pack.
  • ToolHub imports and runs the resulting .toolpack.

Current release: 0.4.1. The generated format is TOOLHUB_PACK version 1.

Quick start

CLI

Create an environment and install the project:

python3 -m venv .venv
. .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -e .

Scan a source tree:

toolpack-builder scan ./tools

Build a pack:

toolpack-builder build ./tools \
  --category-name my-tools \
  --output dist/my-tools.toolpack

GUI

Install the optional GUI dependency:

python -m pip install -e '.[gui]'
toolpack-builder-gui

The CustomTkinter GUI provides source and output selection, include/exclude patterns, category configuration, separate Scan and Build operations, progress reporting, scan results, and a raw ToolPack viewer.

On Debian/Ubuntu, Tk may need to be installed separately:

sudo apt install python3-tk

How it works

A build consists of two distinct stages.

1. Scan

ToolPack Builder recursively discovers candidate files and probes each candidate with:

INPUT_DESCRIBE=json_spec

TWYLT is the source of truth for tool metadata. The builder obtains the tool name, description, requirements, input schema, output schema, and examples through this public introspection contract rather than importing TWYLT internals.

If a tool declares dependencies that are required to complete introspection, the builder installs them into an isolated temporary --target directory and retries the probe. Identical requirement sets share one temporary installation during a scan. These dependencies are not installed into ToolHub or into the builder's active Python environment.

2. Build

Only successfully probed tools are converted into ToolHub entries. The ToolHub tool name comes from the TWYLT name, not from the source filename.

Duplicate or empty TWYLT names are build errors.

The generated bootstrap is equivalent to:

from pathlib import Path
from twylt.bootstrap import run_tool_file

run_tool_file(Path("/absolute/path/to/the/discovered/tool.py"))

Runtime requirements contain twylt>=1.0.0 plus the requirements declared by the tool.

Discovery rules

The default include pattern is:

**/*.py

Additional exclusions can be supplied repeatedly:

toolpack-builder scan ./tools \
  --glob '**/*_tool.py' \
  --exclude '**/generated/**' \
  --exclude '**/examples/**'

Include and exclude patterns use the same path-glob rules:

  • * matches within one path component.
  • ** spans any number of directories, including zero.
  • hidden files are always ignored;
  • everything below a hidden directory is always ignored.

For example, .venv/, .git/, .cache/, nested hidden directories, and hidden Python files do not need explicit exclusions.

The CLI additionally excludes run.py, test_*.py, tests/, and __pycache__/ by default.

Categories

The CLI can place generated tools below a root category:

toolpack-builder build ./tools \
  --category-name filesystem \
  --output dist/filesystem.toolpack

The GUI supports two category strategies:

Single category places all discovered tools under one configured category.

From directory structure maps directories relative to the scan root to nested ToolHub categories. The filename does not determine the tool name; the TWYLT name still does.

Important runtime assumptions

Source files are referenced by absolute path

The current pack format generated by ToolPack Builder does not vendor the Python source into the .toolpack.

ToolHub executes a small bootstrap that points to the original discovered tool by absolute path. Therefore the source tree must still exist at the same path on the machine where ToolHub runs the tool.

A future packaging mode may make packs self-contained, but 0.4.x deliberately uses source references.

ToolHub needs a Python runner

Generated entries request:

runnerType = python_local
runnerName = Python

If the ToolHub installation does not already provide that runner, create one equivalent to:

{
  "codeFileName": "run.py",
  "depFileName": "requirements.txt",
  "installCmd": "python -m pip install -r requirements.txt",
  "runCmd": "python run.py"
}

The runner identity can be changed with --runner-type and --runner-name.

CLI reference

The two primary commands are:

toolpack-builder scan ROOT [options]
toolpack-builder build ROOT --output FILE [options]

Common options include:

--glob PATTERN
--exclude PATTERN
--python PYTHON
--probe-timeout SECONDS
--runner-type TYPE
--runner-name NAME
--json

Build additionally supports:

--category-name NAME
--timeout-ms MILLISECONDS

Use the built-in help for the authoritative option list:

toolpack-builder --help
toolpack-builder scan --help
toolpack-builder build --help

Exit status

Code Meaning
0 Command completed without failed candidates
1 Scan/build completed, but at least one candidate failed
2 Builder or configuration failure

A build may still write a .toolpack when individual candidates fail. Successfully probed TWYLT tools are retained while the non-zero exit status remains useful for CI.

Machine-readable output and debugging

Command results can be emitted as JSON:

toolpack-builder scan ./tools --json

Framework errors can also be emitted as JSON, and tracebacks can be enabled:

toolpack-builder --error-format json build ...
toolpack-builder --debug build ...

Equivalent environment variables are available:

TOOLPACK_BUILDER_ERROR_FORMAT=json
TOOLPACK_BUILDER_DEBUG=1

GUI state

GUI project parameters are persisted between launches. Scan results are deliberately not persisted, because the source tree may have changed while the application was closed.

On Linux, configuration is stored below:

$XDG_CONFIG_HOME/toolpack-builder

or, when XDG_CONFIG_HOME is not set:

~/.config/toolpack-builder

The corresponding platform configuration directory is used on other operating systems.

Changing scan-relevant parameters after a scan marks the current results as stale and disables Build until another scan is completed.

Development and verification

Install test dependencies and run the normal offline suite:

python -m pip install -e '.[test]'
pytest
python scripts/verify_package.py

The generated ToolHub payload is validated before writing and is covered by JSON round-trip tests.

An opt-in integration test exercises a real TWYLT checkout:

TWYLT_REPO=/path/to/twylt \
pytest -q tests/integration/test_twylt_100.py

The normal test suite remains offline and reproducible.

Architectural decisions are recorded in docs/adr/. Regression tests are cumulative: bug fixes should add coverage rather than replace existing tests. Release history is maintained in CHANGELOG.md.

Project status

ToolPack Builder currently targets:

  • TWYLT >=1.0.0;
  • TWYLT protocol 1.8-compatible introspection;
  • ToolHub TOOLHUB_PACK version 1;
  • Python >=3.10.

The project is licensed under the MIT License.

About

Helper tool to build toolpacks for ToolHub out of bunch ToolSpec compliant files. Written with AI

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages