Skip to content

6. Keep it running

Hand both streams to the runtime with tatolab run -d, so they keep running after you close the terminals and come back after a restart.

So far each stream has lived only as long as its tatolab dev. That’s what you want while you’re editing. Once they work, you want them to keep running on their own: after you close the terminals, after you log out, after the machine restarts.

Stop both tatolab dev commands (Ctrl-C in each terminal). Then, in the motion-watcher folder:

Terminal window
tatolab run -d
Output
motion_watcher kept (project /home/you/motion-watcher)

And in the motion-log folder:

Terminal window
tatolab run -d
Output
motion_log kept (project /home/you/motion-log)

Each command returns at once, and the window stays open. The runtime has recorded both streams and now owns them. Close the terminals; they keep running, and motion-events.jsonl keeps growing.

Terminal window
tatolab streams
Output
NAME STATE NODES PROJECT
motion_watcher kept 3 /home/you/motion-watcher
motion_log kept 1 /home/you/motion-log

The motion watcher has 4 nodes if you added the tint in step 5.

A kept stream is part of the machine’s setup. The runtime records it in its state folder: the graph your stream function built, the project’s Python environment, and the exposure of its ports. Every time the runtime starts, it loads the stream again: when you log in, when the machine boots, and when the runtime restarts after a crash. Both streams come back, and motion_log’s link connects once motion_watcher is running, whichever loads first.

If a kept stream keeps taking the runtime down, the runtime stops loading it: after it’s involved in two crashes in a row, it’s marked failed, and the runtime starts every other stream without it. The same happens to a kept stream that can’t load at all, say because you deleted its .venv. tatolab streams shows why:

Output
NAME STATE NODES PROJECT
motion_watcher failed - /home/you/motion-watcher
motion_watcher failed: <the reason>. `tatolab start motion_watcher` retries it, `tatolab rm motion_watcher` forgets it.
Terminal window
tatolab logs --stream motion_watcher -f # follow its log
tatolab stop motion_watcher # stop it; it stays stopped, even across restarts
tatolab start motion_watcher # start it again (or retry a failed one)
tatolab rm motion_watcher # stop it and forget it

stop is how you pause a kept stream without losing it. rm is the only command that forgets one.

The runtime keeps the graph from the moment you ran tatolab run -d. Editing stream.py or a node afterwards doesn’t change the running stream. To pick up your changes, run it again from the project folder:

Terminal window
tatolab run -d

Running run -d again for the same project and function replaces the record with the new version.

To go back to editing with tatolab dev, remove the kept stream first. A kept stream holds its name even while it’s stopped, so stop isn’t enough:

Terminal window
tatolab rm motion_watcher
tatolab dev

When you’re done, tatolab run -d keeps the new version. Then check that motion_log is reading again: tatolab graph --stream motion_log should show its link as wired. If it isn’t, reload it with tatolab stop motion_log and tatolab start motion_log.

Running a development copy under another name, next to the kept one (tatolab dev --name motion_watcher_dev), works only if the copy doesn’t open the camera too: on Linux, only one stream at a time can open a camera.

The kept stream runs in the machine’s runtime, which the installer set up as a service: a login item on macOS, a systemd user service on Linux. On a Linux machine you reach over ssh, turn on lingering (loginctl enable-linger) so the runtime, and your stream, keep running when nobody is logged in. Deploy to a machine covers servers and other machines without a screen.

Last step: let an AI agent see and change the running streams. Let an agent watch.