All docs
Write your first tool
Turn a Python function into a live canvas node in ten lines with lsdtools — scaffold a package, add a step, and watch it hot-load into the palette.
A node is just a decorated Python function. Here is the whole thing.
Scaffold a package#
The quickest start is a scaffold — it writes a working tool.py, an lsd_package.json, and a
README:
lsd package new my-pkg
Or write tool.py by hand#
# tool.py
from lsdtools import Tool, Table
tool = Tool("my", label="My Tool")
@tool.shape
def top(t: Table, limit: int = 10) -> Table:
"""Keep the highest-scoring rows."""
return t.sort("score", descending=True).head(limit)
tool = Tool("my")— oneToolper package, at module scope.@tool.shape— makes a transform node (my.top).t: Table— an input port (wire it from an upstream node).limit: int = 10— a parameter; it renders as a number field.
See it on the canvas#
In the desktop app, use the Package Manager's "Add local…" and pick the
folder. Your node appears in the add-node palette with a generated form. Edit tool.py and it
hot-reloads — the tight loop is: change the function, see the node update.
Run it without the desktop#
You don't even need the app to try it:
from lsdtools import Engine, Table
data = Table({"name": ["a", "b", "c"], "score": [3, 9, 5]})
result = Engine().run(top(data, limit=2))
result.output.print()
# → name:["b","c"] score:[9,5]
Next#
- Where to go next — the map of these docs.
- Go deeper on the Tool object and parameters vs ports.
Related#
Learn — The Tool object · Load steps
Examples — Your first tool
Frequently asked questions
Where does tool.py go?
Anywhere on your import path. In the desktop, use "Add local package…" to point at a folder — its steps hot-reload as you edit. For a shareable unit, scaffold a package with lsd package new.
How does a function become a node?
The @tool.load/@tool.shape/@tool.deliver decorators register the function as a node type. A Table parameter becomes an input port; every other parameter becomes a form field.