Skip to main content

toolrack

toolrack is the dispatcher engine behind a user-owned scripts repository. It reads a registry of script paths, loads YAML sidecars beside those scripts, and builds a typed Click CLI at runtime.

If you want the starter repository that uses this engine, see toolrack-template.

PyPI Unit tests

Animated toolrack walkthrough: register, discover, and run scripts

Quickstart

git clone https://github.com/anfit/toolrack-template my-tools
cd my-tools
python setup_toolrack.py   # venv, installs toolrack-cli from PyPI, wrappers, PATH, completion

The engine is published on PyPI as toolrack-cli; the command it installs is toolrack. To work on the engine itself, clone this repo and pass --toolrack ../toolrack to the setup script for an editable install.

Open a new shell, then add a script and its sidecar:

# scripts/hello/greet.py
import sys
print(f"Hello, {sys.argv[1]}!")
# scripts/hello/greet.yml
description: Print a greeting.
args:
  - name: name
    positional: true
    required: true
    help: Who to greet.
my-tools core register scripts/hello/greet.py
my-tools hello greet Alice        # -> Hello, Alice!
my-tools hello <TAB>              # completes commands, options and choices

Why This Exists

AI has made it dramatically easier to write small, useful scripts. That is the good news. The follow-up news is that once you have twenty of them, "somewhere in a folder" stops being a system.

toolrack is for that moment.

The basic idea is simple:

  • AI is very good at helping you produce small scripts quickly.
  • A growing script library still needs structure, discoverability, and sane UX.
  • AI also benefits from compartmentalization: small scripts with narrow scope are easier to write, review, test, and replace.
  • AI work is non-deterministic by nature, so every stable, tested, deterministic thing you can hand off to automation is one less task balanced on your pet clanker's back.

This project is not trying to turn your script repo into a framework empire. It is trying to help your collection of tiny automations stay tidy, callable, and pleasant to use after the novelty phase.

Showcase

The intended flow looks like this:

  1. Create a scripts repository with a clear layout. There is a starter repo for that: toolrack-template.
  2. Add small scripts under folders that match their area of work: github/, jira/, db/, images/, deploy/, and so on.
  3. Put a sidecar next to each script so the command has typed arguments, help, and completion.
  4. Plug toolrack into that repo so the whole thing becomes one coherent CLI.

The result is one command on your PATH, available from PowerShell, Git Bash, or Cygwin, with shared help and completion instead of a growing folklore of "I think that one is in a repo called maybe-tools-old?"

Example:

my-tools github list-prs --state open --limit 20
my-tools jira show ISSUE-123
my-tools db query --env prod --file scripts/db/slow_report.sql

That is the main payoff: when you want to make a new script, it is not trapped in "that project you did two years ago". It lives next to two similar scripts in the folder dedicated to that area, where both humans and models can find the pattern immediately.

Which also makes the AI prompt much nicer:

Hey AI, make me one like this, but mauve.

Testing Your Tools

Installing toolrack-cli also gives your test suite a pytest plugin. It runs the real CLI in a subprocess against a repository, so tests cover what users run: sidecar parsing, argument mapping, exit codes and the script itself. Python, Bash and SQL scripts are all supported.

Check the whole repo in CI. core validate is read-only and exits non-zero on a missing script or sidecar, an invalid sidecar, a bad aliases.cfg, or two scripts that map to the same command. Unregistered sidecar pairs and a stale cache are warnings; --strict makes them failures.

my core validate --strict

Or from pytest, against your real repo (toolrack_project) or a throwaway one (toolrack_repo):

def test_repo_is_valid(toolrack_project):
    toolrack_project.validate(strict=True)   # AssertionError lists every problem

def test_python_tool(toolrack_repo):
    toolrack_repo.add_script(
        "greet/hello.py",
        "import sys\nprint('hi', sys.argv[2])\n",
        {"description": "Say hi.", "args": [{"name": "name", "required": True}]},
    )
    assert toolrack_repo.run("greet", "hello", "--name", "Ada").check().stdout == "hi Ada\n"

def test_bash_tool(toolrack_repo, toolrack_require_bash):      # skips without bash
    toolrack_repo.add_script("ops/fail.sh", "exit 3\n", {"description": "Fails."})
    assert toolrack_repo.run("ops", "fail").returncode == 3

def test_sql_tool(toolrack_repo, toolrack_require_posix):      # no database needed
    psql = toolrack_repo.stub_executable("psql", record_env=("PGDATABASE",))
    script = toolrack_repo.add_script("db/ping.sql", "SELECT 1;", {"description": "Ping."})
    toolrack_repo.run("db", "ping", env={"PGDATABASE": "dev"}).check()
    assert psql.calls()[0]["argv"] == ["-f", str(script)]

SQL scripts run as psql -f <file>, so stub_executable puts a recording fake psql first on PATH instead of needing a database. It works on POSIX hosts only. ToolrackRepo is in toolrack.testing if you prefer to use it without the fixtures.

Migrating From a Checked-Out toolrack

If you installed the engine editable from a clone (pip install -e path/to/toolrack, distribution name toolrack), switch your scripts repo to the PyPI release:

python3 ./sync_toolrack.py                              # refresh setup_toolrack.py
python3 ./setup_toolrack.py --yes --force --cli-name <your-command>

Setup removes the old editable install, installs toolrack-cli, rewrites the wrappers, and regenerates completion. Full steps, plus the manual route, are in the toolrack-template README.

Deployment Model

toolrack is meant to be installed into a scripts repository's virtualenv (pip install toolrack-cli) and launched through a repo-local wrapper in bin/. The PyPI distribution is toolrack-cli; the package and command are toolrack.

The wrapper is responsible for:

  • choosing the visible command name
  • setting TOOLRACK_REPO_ROOT
  • setting TOOLRACK_SCRIPTS_ROOT
  • setting TOOLRACK_REGISTRY_FILE or TOOLRACK_REGISTRY_BASENAME
  • invoking python -m toolrack from the repo's virtualenv

Defaults:

  • CLI name: inferred from the wrapper filename, else toolrack
  • registry basename: .toolrack
  • repo discovery also accepts legacy .attic during walk-up

Core Commands

toolrack provides a small management surface under core:

  • core register <script_path>: add one script to the registry
  • core auto-register: scan scripts/ for sidecar-backed scripts
  • core unregister <script_path>: remove one script from the registry
  • core reregister: validate every registered script and sidecar
  • core refresh-cache: rebuild the cached command metadata next to .toolrack
  • core list: show registry entries and sidecar status
  • core install-completion <shell>: print shell completion source

Scripts Repo Contract

A scripts repository normally contains:

  • scripts/: runnable .py, .sh, .bash, or .sql files
  • .toolrack: registry of enabled scripts
  • .toolrack.cache.json: cached command metadata used for faster startup and completion
  • aliases.cfg: optional group aliases, stored next to .toolrack
  • bin/: wrappers that export the toolrack environment variables

aliases.cfg lets you shorten first-level or nested group paths without renaming folders. For example:

[groups]
environments = env
refactoring = refactor

That turns your-tools environments get-status into your-tools env get-status.

Sidecars live next to scripts as <script>.yml. See SIDECAR_SPEC.md.

For a starter repository layout, use toolrack-template.

Shell completion

Completion is answered from .toolrack.cache.json without importing Click, so stays fast; anything the fast path does not model exactly falls back to Click. core install-completion bash prints a script that calls the Python interpreter directly and falls back to the wrapper if that interpreter moves.

Development

python -m pip install -e ".[dev]"
python -m pytest
python -m pytest -m integration -s

Metadata

Release files for toolrack-cli 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for toolrack-cli 0.2.0
File Size Uploaded Provenance Actions
toolrack_cli-0.2.0.tar.gz 42.9 kB With provenance Details for toolrack_cli-0.2.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for toolrack-cli 0.2.0
File Interpreter ABI Platform Actions
toolrack_cli-0.2.0-py3-none-any.whl Python 3 none any Details for toolrack_cli-0.2.0-py3-none-any.whl

Total release size: 70.7 kB

Release files / toolrack_cli-0.2.0.tar.gz

Download URL toolrack_cli-0.2.0.tar.gz
Size 42.9 kB
Tags Source
SHA-256 checksum
How to use checksums
64ecff123b568bd8b8ef3cfabd6749c376650fb7dc0e20ba24adf45822667af1
BLAKE2b-256 checksum
How to use checksums
3b7de20498367d1c1e3c9a2b9a73d197cc50f3ef98373bd83d567662446367b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

Release files / toolrack_cli-0.2.0-py3-none-any.whl

Download URL toolrack_cli-0.2.0-py3-none-any.whl
Size 27.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8a6e375e3db008e459759c19bbd4ee8955e9afff5293ee99b6a4891f473ebea4
BLAKE2b-256 checksum
How to use checksums
5c81b8306a3552cdb068e6d1632c2edd7539210fdb7a5f6c94084ba0dc03a5f4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

Security for toolrack-cli 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for toolrack_cli-0.2.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 4, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page