All docs
Docs/ Examples/ Example: your first tool
Examples

Example: your first tool

A complete, runnable package with one load step and one shape step — the smallest tool that shows up on the LSD canvas. Copy, run, and adapt.

TL;DRA full tool.py with a load step (emit rows) and a shape step (keep the top N). Run it directly in Python, or place it in a manifest-backed Local package, link the source folder and activate it in Desktop's Project Packages settings.

The smallest real tool: one node that makes data, one that transforms it. Run the two Python blocks below in your authoring environment. To put the nodes on the Desktop canvas, use the Local package workflow: place this tool.py in the scaffold's code module, link the manifest-backed folder from the source-development CLI, then enable it in Settings → Project Packages. Restart Desktop after editing a linked Local package.

Opening a .lsd file does not load neighboring Python. For a project-only experiment, save the code as steps.py beside the project and use the visible Enable project code… control to review it. Run Once uses an immutable snapshot; Trust Folder & Enable Live Development permits subsequent saved edits to reload. That choice belongs to the human using Desktop.

The code#

Python
# tool.py
from lsdtools import Tool, Table

tool = Tool("hello", label="Hello")


@tool.load
def numbers(count: int = 5) -> Table:
    """Emit a table of the first `count` integers and their squares."""
    xs = list(range(count))
    return Table({"n": xs, "square": [x * x for x in xs]})


@tool.shape
def top(t: Table, limit: int = 3) -> Table:
    """Keep the `limit` rows with the largest square."""
    return t.sort("square", descending=True).head(limit)

What each line does#

  • tool = Tool("hello") — one Tool per package, created at module scope. Its name namespaces the nodes (hello.numbers, hello.top).
  • @tool.load — makes a node that produces data. count: int = 5 has a default, so it is an optional parameter and renders as a number field.
  • Table({...}) — builds a Table from a dict of columns.
  • @tool.shape — makes a transform node. t: Table is an input port (wire it from the load node); limit: int is another parameter.
  • Every function returns a step, never data at import time — LSD runs it when the node runs.

Run it in Python#

You don't need the desktop to try it — wire the steps and run with an Engine:

Python
from lsdtools import Engine

n = numbers(count=6)
result = Engine().run(top(n, limit=3))
result.output.print()
# → n:[5,4,3] square:[25,16,9]

top(n, ...) wires the shape node's input port to the load node n. Engine().run(...) executes the chain and caches each step; result.output is the final Table.

Try changing it#

  • Add a @tool.deliver node that calls t.write_csv("out.csv").
  • Give numbers a Source parameter to load a real file instead — see File loader.
  • Add a second output with outputs=["evens", "odds"] — see Multi-output.

LearnLoad steps · Shape steps · Develop a package

APITool · Table · Engine

By LSD Team · Last updated Sep 09, 2026 Ask a question View as Markdown
Type to search every doc, guide, and tutorial.
↑↓ navigate openesc close